1 /* Test file for mpfr_sinu.
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_sinu (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_sinu (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_sinu (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_sinu (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_sinu (y, x, 1, MPFR_RNDN);
57 MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) == 0);
58 MPFR_ASSERTN(inexact == 0);
59
60 /* check x = -0 */
61 mpfr_set_zero (x, -1);
62 inexact = mpfr_sinu (y, x, 1, MPFR_RNDN);
63 MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) != 0);
64 MPFR_ASSERTN(inexact == 0);
65
66 mpfr_clear (x);
67 mpfr_clear (y);
68 }
69
70 static void
test_exact(void)71 test_exact (void)
72 {
73 mpfr_t x, y;
74 int inexact;
75
76 mpfr_init (x);
77 mpfr_init (y);
78
79 /* check 2*pi*x/u = pi/2 thus x/u = 1/4, for example x=1 and u=4 */
80 mpfr_set_ui (x, 1, MPFR_RNDN);
81 inexact = mpfr_sinu (y, x, 4, MPFR_RNDN);
82 MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0 && inexact == 0);
83
84 /* check 2*pi*x/u = pi thus x/u = 1/2, for example x=2 and u=4 */
85 mpfr_set_ui (x, 2, MPFR_RNDN);
86 inexact = mpfr_sinu (y, x, 4, MPFR_RNDN);
87 MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) == 0);
88 MPFR_ASSERTN(inexact == 0);
89
90 /* check 2*pi*x/u = 3*pi/2 thus x/u = 3/4, for example x=3 and u=4 */
91 mpfr_set_ui (x, 3, MPFR_RNDN);
92 inexact = mpfr_sinu (y, x, 4, MPFR_RNDN);
93 MPFR_ASSERTN(mpfr_cmp_si (y, -1) == 0 && inexact == 0);
94
95 /* check 2*pi*x/u = 2*pi thus x/u = 1, for example x=4 and u=4 */
96 mpfr_set_ui (x, 4, MPFR_RNDN);
97 inexact = mpfr_sinu (y, x, 4, MPFR_RNDN);
98 MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) == 0);
99 MPFR_ASSERTN(inexact == 0);
100
101 /* check x/u = 2^16, for example x=3*2^16 and u=3 */
102 mpfr_set_ui_2exp (x, 3, 16, MPFR_RNDN);
103 inexact = mpfr_sinu (y, x, 3, MPFR_RNDN);
104 MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) == 0);
105 MPFR_ASSERTN(inexact == 0);
106
107 /* check 2*pi*x/u = -pi/2 thus x/u = -1/4, for example x=-1 and u=4 */
108 mpfr_set_si (x, -1, MPFR_RNDN);
109 inexact = mpfr_sinu (y, x, 4, MPFR_RNDN);
110 MPFR_ASSERTN(mpfr_cmp_si (y, -1) == 0 && inexact == 0);
111
112 /* check 2*pi*x/u = -pi thus x/u = -1/2, for example x=-2 and u=4 */
113 mpfr_set_si (x, -2, MPFR_RNDN);
114 inexact = mpfr_sinu (y, x, 4, MPFR_RNDN);
115 MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) != 0);
116 MPFR_ASSERTN(inexact == 0);
117
118 /* check 2*pi*x/u = -3*pi/2 thus x/u = -3/4, for example x=-3 and u=4 */
119 mpfr_set_si (x, -3, MPFR_RNDN);
120 inexact = mpfr_sinu (y, x, 4, MPFR_RNDN);
121 MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0 && inexact == 0);
122
123 /* check 2*pi*x/u = -2*pi thus x/u = -1, for example x=-4 and u=4 */
124 mpfr_set_si (x, -4, MPFR_RNDN);
125 inexact = mpfr_sinu (y, x, 4, MPFR_RNDN);
126 MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) != 0);
127 MPFR_ASSERTN(inexact == 0);
128
129 /* check x/u = -2^16, for example x=-3*2^16 and u=3 */
130 mpfr_set_si_2exp (x, -3, 16, MPFR_RNDN);
131 inexact = mpfr_sinu (y, x, 3, MPFR_RNDN);
132 MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) != 0);
133 MPFR_ASSERTN(inexact == 0);
134
135 /* check 2*pi*x/u = pi/6, for example x=1 and u=12 */
136 mpfr_set_ui (x, 1, MPFR_RNDN);
137 inexact = mpfr_sinu (y, x, 12, MPFR_RNDN);
138 MPFR_ASSERTN(mpfr_cmp_ui_2exp (y, 1, -1) == 0 && inexact == 0);
139
140 /* check 2*pi*x/u = 5*pi/6, for example x=5 and u=12 */
141 mpfr_set_ui (x, 5, MPFR_RNDN);
142 inexact = mpfr_sinu (y, x, 12, MPFR_RNDN);
143 MPFR_ASSERTN(mpfr_cmp_ui_2exp (y, 1, -1) == 0 && inexact == 0);
144
145 /* check 2*pi*x/u = 7*pi/6, for example x=5 and u=12 */
146 mpfr_set_ui (x, 7, MPFR_RNDN);
147 inexact = mpfr_sinu (y, x, 12, MPFR_RNDN);
148 MPFR_ASSERTN(mpfr_cmp_si_2exp (y, -1, -1) == 0 && inexact == 0);
149
150 /* check 2*pi*x/u = 11*pi/6, for example x=5 and u=12 */
151 mpfr_set_ui (x, 11, MPFR_RNDN);
152 inexact = mpfr_sinu (y, x, 12, MPFR_RNDN);
153 MPFR_ASSERTN(mpfr_cmp_si_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_sinu (y, x, 42, MPFR_RNDN);
171 /* y should be sin(2*17*pi/42) rounded to nearest */
172 mpfr_set_str (z, "0x9.035be4a906768p-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 gen_random(sin,10,53,100,20), where the
183 Sage code for gen_random is given in the tcosu.c file. */
184 static void
test_large(void)185 test_large (void)
186 {
187 static struct {
188 const char *x;
189 unsigned long u;
190 const char *y;
191 } t[] = {
192 { "-0x4.338bcaf01cb4p+16", 37, "0xa.a85c8758c1228p-4" },
193 { "-0x6.01aa844d11acp+16", 12, "0x4.46e2cea96ee2cp-4" },
194 { "-0x7.997759de3b3dp+16", 35, "0xf.144b13bc0b008p-4" },
195 { "-0xc.74f72253bc7ep+16", 74, "-0x9.1c24e8ac6fb48p-4" },
196 { "-0x4.ea97564d3ecp+12", 93, "0x3.2d49033cc4556p-4" },
197 { "0xc.1cd85e0766ffp+16", 48, "-0xd.74b642b1c7368p-4" },
198 { "0xe.add2f0441bap+16", 82, "-0xf.fc35c5a5e1448p-4" },
199 { "0xc.8feb943a0fe5p+16", 43, "-0x5.8af3e0e11b794p-4" },
200 { "-0xd.d61b06ace6d9p+16", 55, "0xa.175c9f7e4ede8p-4" },
201 { "0xb.cf036b4e5fap+12", 46, "0x1.b7128e1975d9ap-4" },
202 /* The following case does not come from the random values.
203 Here, x mod u may need more precision than x. */
204 { "0x3.p+16", 99, "-0xb.e4a8a986c9fd03ap-5" }
205 };
206 int i;
207 mpfr_t x, y, z;
208
209 mpfr_inits2 (53, x, y, z, (mpfr_ptr) 0);
210 for (i = 0; i < numberof (t); i++)
211 {
212 mpfr_set_str (x, t[i].x, 0, MPFR_RNDN);
213 mpfr_set_str (y, t[i].y, 0, MPFR_RNDN);
214 mpfr_sinu (z, x, t[i].u, MPFR_RNDN);
215 MPFR_ASSERTN (mpfr_equal_p (y, z));
216 /* Same test after reducing the precision of x to its minimum one. */
217 mpfr_prec_round (x, mpfr_min_prec (x), MPFR_RNDN);
218 mpfr_sinu (z, x, t[i].u, MPFR_RNDN);
219 MPFR_ASSERTN (mpfr_equal_p (y, z));
220 mpfr_prec_round (x, 53, MPFR_RNDN);
221 }
222 mpfr_clears (x, y, z, (mpfr_ptr) 0);
223 }
224
225 #define TEST_FUNCTION mpfr_sinu
226 #define ULONG_ARG2
227 #include "tgeneric.c"
228
229 static int
mpfr_sin2pi(mpfr_ptr y,mpfr_srcptr x,mpfr_rnd_t r)230 mpfr_sin2pi (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t r)
231 {
232 return mpfr_sinu (y, x, 1, r);
233 }
234
235 int
main(void)236 main (void)
237 {
238 tests_start_mpfr ();
239
240 test_singular ();
241 test_exact ();
242 test_regular ();
243 test_large ();
244
245 test_generic (MPFR_PREC_MIN, 100, 1000);
246
247 data_check ("data/sin2pi", mpfr_sin2pi, "mpfr_sin2pi");
248
249 tests_end_mpfr ();
250 return 0;
251 }
252