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