xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/tcosu.c (revision ba125506a622fe649968631a56eba5d42ff57863)
1 /* Test file for mpfr_cosu.
2 
3 Copyright 2020-2023 Free Software Foundation, Inc.
4 Contributed by the AriC and Caramba projects, INRIA.
5 
6 This file is part of the GNU MPFR Library.
7 
8 The GNU MPFR Library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 The GNU MPFR Library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16 License for more details.
17 
18 You should have received a copy of the GNU Lesser General Public License
19 along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
20 https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
22 
23 #include "mpfr-test.h"
24 
25 static void
test_singular(void)26 test_singular (void)
27 {
28   mpfr_t x, y;
29   int inexact;
30 
31   mpfr_init (x);
32   mpfr_init (y);
33 
34   /* check u = 0 */
35   mpfr_set_ui (x, 17, MPFR_RNDN);
36   inexact = mpfr_cosu (y, x, 0, MPFR_RNDN);
37   MPFR_ASSERTN(mpfr_nan_p (y));
38 
39   /* check x = NaN */
40   mpfr_set_nan (x);
41   inexact = mpfr_cosu (y, x, 1, MPFR_RNDN);
42   MPFR_ASSERTN(mpfr_nan_p (y));
43 
44   /* check x = +Inf */
45   mpfr_set_inf (x, 1);
46   inexact = mpfr_cosu (y, x, 1, MPFR_RNDN);
47   MPFR_ASSERTN(mpfr_nan_p (y));
48 
49   /* check x = -Inf */
50   mpfr_set_inf (x, -1);
51   inexact = mpfr_cosu (y, x, 1, MPFR_RNDN);
52   MPFR_ASSERTN(mpfr_nan_p (y));
53 
54   /* check x = +0 */
55   mpfr_set_zero (x, 1);
56   inexact = mpfr_cosu (y, x, 1, MPFR_RNDN);
57   MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0);
58   MPFR_ASSERTN(inexact == 0);
59 
60   /* check x = -0 */
61   mpfr_set_zero (x, -1);
62   inexact = mpfr_cosu (y, x, 1, MPFR_RNDN);
63   MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0);
64   MPFR_ASSERTN(inexact == 0);
65 
66   /* check x/u = 2^16, for example x=3*2^16 and u=3 */
67   mpfr_set_ui_2exp (x, 3, 16, MPFR_RNDN);
68   inexact = mpfr_cosu (y, x, 3, MPFR_RNDN);
69   MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0);
70   MPFR_ASSERTN(inexact == 0);
71 
72   /* check x/u = -2^16, for example x=-3*2^16 and u=3 */
73   mpfr_set_si_2exp (x, -3, 16, MPFR_RNDN);
74   inexact = mpfr_cosu (y, x, 3, MPFR_RNDN);
75   MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0);
76   MPFR_ASSERTN(inexact == 0);
77 
78   mpfr_clear (x);
79   mpfr_clear (y);
80 }
81 
82 static void
test_exact(void)83 test_exact (void)
84 {
85   mpfr_t x, y;
86   int inexact;
87 
88   mpfr_init (x);
89   mpfr_init (y);
90 
91   /* check 2*pi*x/u = pi/2 thus x/u = 1/4, for example x=1 and u=4 */
92   mpfr_set_ui (x, 1, MPFR_RNDN);
93   inexact = mpfr_cosu (y, x, 4, MPFR_RNDN);
94   MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) == 0);
95   MPFR_ASSERTN(inexact == 0);
96 
97   /* check 2*pi*x/u = pi thus x/u = 1/2, for example x=2 and u=4 */
98   mpfr_set_ui (x, 2, MPFR_RNDN);
99   inexact = mpfr_cosu (y, x, 4, MPFR_RNDN);
100   MPFR_ASSERTN(mpfr_cmp_si (y, -1) == 0 && inexact == 0);
101 
102   /* check 2*pi*x/u = 3*pi/2 thus x/u = 3/4, for example x=3 and u=4 */
103   mpfr_set_ui (x, 3, MPFR_RNDN);
104   inexact = mpfr_cosu (y, x, 4, MPFR_RNDN);
105   MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) == 0);
106   MPFR_ASSERTN(inexact == 0);
107 
108   /* check 2*pi*x/u = 2*pi thus x/u = 1, for example x=4 and u=4 */
109   mpfr_set_ui (x, 4, MPFR_RNDN);
110   inexact = mpfr_cosu (y, x, 4, MPFR_RNDN);
111   MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0 && inexact == 0);
112 
113   /* check 2*pi*x/u = -pi/2 thus x/u = -1/4, for example x=-1 and u=4 */
114   mpfr_set_si (x, -1, MPFR_RNDN);
115   inexact = mpfr_cosu (y, x, 4, MPFR_RNDN);
116   MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) == 0);
117   MPFR_ASSERTN(inexact == 0);
118 
119   /* check 2*pi*x/u = -pi thus x/u = -1/2, for example x=-2 and u=4 */
120   mpfr_set_si (x, -2, MPFR_RNDN);
121   inexact = mpfr_cosu (y, x, 4, MPFR_RNDN);
122   MPFR_ASSERTN(mpfr_cmp_si (y, -1) == 0 && inexact == 0);
123 
124   /* check 2*pi*x/u = -3*pi/2 thus x/u = -3/4, for example x=-3 and u=4 */
125   mpfr_set_si (x, -3, MPFR_RNDN);
126   inexact = mpfr_cosu (y, x, 4, MPFR_RNDN);
127   MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) == 0);
128   MPFR_ASSERTN(inexact == 0);
129 
130   /* check 2*pi*x/u = -2*pi thus x/u = -1, for example x=-4 and u=4 */
131   mpfr_set_si (x, -4, MPFR_RNDN);
132   inexact = mpfr_cosu (y, x, 4, MPFR_RNDN);
133   MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0 && inexact == 0);
134 
135   /* check 2*pi*x/u = pi/3, for example x=1 and u=6 */
136   mpfr_set_ui (x, 1, MPFR_RNDN);
137   inexact = mpfr_cosu (y, x, 6, MPFR_RNDN);
138   MPFR_ASSERTN(mpfr_cmp_ui_2exp (y, 1, -1) == 0 && inexact == 0);
139 
140   /* check 2*pi*x/u = 2*pi/3, for example x=2 and u=6 */
141   mpfr_set_ui (x, 2, MPFR_RNDN);
142   inexact = mpfr_cosu (y, x, 6, MPFR_RNDN);
143   MPFR_ASSERTN(mpfr_cmp_si_2exp (y, -1, -1) == 0 && inexact == 0);
144 
145   /* check 2*pi*x/u = 4*pi/3, for example x=4 and u=6 */
146   mpfr_set_ui (x, 4, MPFR_RNDN);
147   inexact = mpfr_cosu (y, x, 6, MPFR_RNDN);
148   MPFR_ASSERTN(mpfr_cmp_si_2exp (y, -1, -1) == 0 && inexact == 0);
149 
150   /* check 2*pi*x/u = 5*pi/3, for example x=5 and u=6 */
151   mpfr_set_ui (x, 5, MPFR_RNDN);
152   inexact = mpfr_cosu (y, x, 6, MPFR_RNDN);
153   MPFR_ASSERTN(mpfr_cmp_ui_2exp (y, 1, -1) == 0 && inexact == 0);
154 
155   mpfr_clear (x);
156   mpfr_clear (y);
157 }
158 
159 static void
test_regular(void)160 test_regular (void)
161 {
162   mpfr_t x, y, z;
163   int inexact;
164 
165   mpfr_init2 (x, 53);
166   mpfr_init2 (y, 53);
167   mpfr_init2 (z, 53);
168 
169   mpfr_set_ui (x, 17, MPFR_RNDN);
170   inexact = mpfr_cosu (y, x, 42, MPFR_RNDN);
171   /* y should be cos(2*17*pi/42) rounded to nearest */
172   mpfr_set_str (z, "-0xd.38462625fd3ap-4", 16, MPFR_RNDN);
173   MPFR_ASSERTN(mpfr_equal_p (y, z));
174   MPFR_ASSERTN(inexact < 0);
175 
176   mpfr_clear (x);
177   mpfr_clear (y);
178   mpfr_clear (z);
179 }
180 
181 /* Check argument reduction with large hard-coded inputs. The following
182    values were generated with the following Sage code:
183 # generate N random tests for f, with precision p, u < U, and |x| < 2^K
184 # f might be cos (for cosu), sin (for sinu) or tan (for tanu)
185 # gen_random(cos,10,53,100,20)
186 def gen_random(f,N,p,U,K):
187    R = RealField(p)
188    for n in range(N):
189       u = ZZ.random_element(U)
190       x = R.random_element()*2^K
191       q = p
192       while true:
193          q += 10
194          RI = RealIntervalField(q)
195          y = RI(f(2*pi*x.exact_rational()/u))
196          if R(y.lower().exact_rational()) == R(y.upper().exact_rational()):
197             break
198       y = R(y.lower().exact_rational())
199       print (x.hex(), u, y.hex()) */
200 static void
test_large(void)201 test_large (void)
202 {
203   static struct {
204     const char *x;
205     unsigned long u;
206     const char *y;
207   } t[] = {
208     { "0xd.ddfeb0f4a01fp+16", 72, "0x4.8e54ce9b84d78p-4" },
209     { "-0xb.ccb63f74f9abp+16", 36, "-0xb.cce98d64941bp-4" },
210     { "0x9.8451e45ed4bap+16", 26, "-0xb.b205cfe8a13cp-4" },
211     { "-0x7.6b4c16c45445p+16", 60, "-0x7.dee04000f4934p-4" },
212     { "0x1.bb80916be884p+16", 43, "-0xc.059d9c8f1b7fp-4" },
213     { "-0x5.4d3623b69226p+16", 1, "0xa.3cb353892757p-4" },
214     { "0xd.1c59eab5a14bp+16", 58, "0x1.02978f1c99614p-4" },
215     { "-0xf.bb1f858b9949p+16", 33, "-0x3.b53e5214db138p-4" },
216     { "-0x2.9bcda761bb7p+16", 55, "-0x6.e6c08e7d92898p-4" },
217     { "-0x9.f8f40e2c50f9p+16", 73, "0x7.0e0ff5e4dccbp-4" }
218   };
219   int i;
220   mpfr_t x, y, z;
221 
222   mpfr_inits2 (53, x, y, z, (mpfr_ptr) 0);
223   for (i = 0; i < numberof (t); i++)
224     {
225       mpfr_set_str (x, t[i].x, 0, MPFR_RNDN);
226       mpfr_set_str (y, t[i].y, 0, MPFR_RNDN);
227       mpfr_cosu (z, x, t[i].u, MPFR_RNDN);
228       MPFR_ASSERTN (mpfr_equal_p (y, z));
229     }
230   mpfr_clears (x, y, z, (mpfr_ptr) 0);
231 }
232 
233 #define TEST_FUNCTION mpfr_cosu
234 #define ULONG_ARG2
235 #include "tgeneric.c"
236 
237 static int
mpfr_cos2pi(mpfr_ptr y,mpfr_srcptr x,mpfr_rnd_t r)238 mpfr_cos2pi (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t r)
239 {
240   return mpfr_cosu (y, x, 1, r);
241 }
242 
243 int
main(void)244 main (void)
245 {
246   tests_start_mpfr ();
247 
248   test_singular ();
249   test_exact ();
250   test_regular ();
251   test_large ();
252 
253   /* Note: since the value of u can be large (up to 2^64 - 1 on 64-bit
254      machines), the cos argument can be very small, yielding a special
255      case in small precision. Thus it is better to use a maximum
256      precision (second test_generic argument) that is large enough. */
257   test_generic (MPFR_PREC_MIN, 200, 1000);
258 
259   data_check ("data/cos2pi", mpfr_cos2pi, "mpfr_cos2pi");
260 
261   tests_end_mpfr ();
262   return 0;
263 }
264