1 /* Test file for mpfr_tanu.
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_tanu (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_tanu (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_tanu (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_tanu (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_tanu (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_tanu (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, n;
75
76 mpfr_init2 (x, 6);
77 mpfr_init2 (y, 6);
78
79 /* check n + 0.5 for n integer */
80 for (n = 0; n < 10; n++)
81 {
82 /* check 2n+0.5 for n>=0: +Inf and divide by 0 exception */
83 mpfr_set_ui (x, 4 * n + 1, MPFR_RNDN);
84 mpfr_clear_divby0 ();
85 inexact = mpfr_tanu (y, x, 4, MPFR_RNDN);
86 MPFR_ASSERTN(mpfr_inf_p (y) && mpfr_sgn (y) > 0);
87 MPFR_ASSERTN(inexact == 0);
88 MPFR_ASSERTN(mpfr_divby0_p ());
89
90 /* check 2n+1 for n>=0: -0 */
91 mpfr_set_ui (x, 4 * n + 2, MPFR_RNDN);
92 mpfr_clear_divby0 ();
93 inexact = mpfr_tanu (y, x, 4, MPFR_RNDN);
94 MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) != 0);
95 MPFR_ASSERTN(inexact == 0);
96 MPFR_ASSERTN(!mpfr_divby0_p ());
97
98 /* check 2n+1.5 for n>=0: -Inf and divide by 0 exception */
99 mpfr_set_ui (x, 4 * n + 3, MPFR_RNDN);
100 mpfr_clear_divby0 ();
101 inexact = mpfr_tanu (y, x, 4, MPFR_RNDN);
102 MPFR_ASSERTN(mpfr_inf_p (y) && mpfr_sgn (y) < 0);
103 MPFR_ASSERTN(inexact == 0);
104 MPFR_ASSERTN(mpfr_divby0_p ());
105
106 /* check 2n+2 for n>=0: +0 */
107 mpfr_set_ui (x, 4 * n + 4, MPFR_RNDN);
108 mpfr_clear_divby0 ();
109 inexact = mpfr_tanu (y, x, 4, MPFR_RNDN);
110 MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) == 0);
111 MPFR_ASSERTN(inexact == 0);
112 MPFR_ASSERTN(!mpfr_divby0_p ());
113
114 /* check -2n-0.5 for n>=0: -Inf and divide by 0 exception */
115 mpfr_set_si (x, -4 * n - 1, MPFR_RNDN);
116 mpfr_clear_divby0 ();
117 inexact = mpfr_tanu (y, x, 4, MPFR_RNDN);
118 MPFR_ASSERTN(mpfr_inf_p (y) && mpfr_sgn (y) < 0);
119 MPFR_ASSERTN(inexact == 0);
120 MPFR_ASSERTN(mpfr_divby0_p ());
121
122 /* check -2n-1 for n>=0: +0 */
123 mpfr_set_si (x, -4 * n - 2, MPFR_RNDN);
124 mpfr_clear_divby0 ();
125 inexact = mpfr_tanu (y, x, 4, MPFR_RNDN);
126 MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) == 0);
127 MPFR_ASSERTN(inexact == 0);
128 MPFR_ASSERTN(!mpfr_divby0_p ());
129
130 /* check -2n-1.5 for n>=0: +Inf and divide by 0 exception */
131 mpfr_set_si (x, -4 * n - 3, MPFR_RNDN);
132 mpfr_clear_divby0 ();
133 inexact = mpfr_tanu (y, x, 4, MPFR_RNDN);
134 MPFR_ASSERTN(mpfr_inf_p (y) && mpfr_sgn (y) > 0);
135 MPFR_ASSERTN(inexact == 0);
136 MPFR_ASSERTN(mpfr_divby0_p ());
137
138 /* check -2n-2 for n>=0: -0 */
139 mpfr_set_si (x, -4 * n - 4, MPFR_RNDN);
140 mpfr_clear_divby0 ();
141 inexact = mpfr_tanu (y, x, 4, MPFR_RNDN);
142 MPFR_ASSERTN(mpfr_zero_p (y) && mpfr_signbit (y) != 0);
143 MPFR_ASSERTN(inexact == 0);
144 MPFR_ASSERTN(!mpfr_divby0_p ());
145 }
146
147 /* check 2*pi*x/u = pi/4 thus x/u = 1/8, for example x=1 and u=8 */
148 mpfr_set_ui (x, 1, MPFR_RNDN);
149 inexact = mpfr_tanu (y, x, 8, MPFR_RNDN);
150 MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0 && inexact == 0);
151
152 /* check 2*pi*x/u = 3*pi/4 thus x/u = 3/8, for example x=3 and u=8 */
153 mpfr_set_ui (x, 3, MPFR_RNDN);
154 inexact = mpfr_tanu (y, x, 8, MPFR_RNDN);
155 MPFR_ASSERTN(mpfr_cmp_si (y, -1) == 0 && inexact == 0);
156
157 /* check 2*pi*x/u = 5*pi/4 thus x/u = 5/8, for example x=5 and u=8 */
158 mpfr_set_ui (x, 5, MPFR_RNDN);
159 inexact = mpfr_tanu (y, x, 8, MPFR_RNDN);
160 MPFR_ASSERTN(mpfr_cmp_ui (y, 1) == 0 && inexact == 0);
161
162 /* check 2*pi*x/u = 7*pi/4 thus x/u = 7/8, for example x=7 and u=8 */
163 mpfr_set_ui (x, 7, MPFR_RNDN);
164 inexact = mpfr_tanu (y, x, 8, MPFR_RNDN);
165 MPFR_ASSERTN(mpfr_cmp_si (y, -1) == 0 && inexact == 0);
166
167 mpfr_clear (x);
168 mpfr_clear (y);
169 }
170
171 static void
test_regular(void)172 test_regular (void)
173 {
174 mpfr_t x, y, z;
175 int inexact;
176
177 mpfr_init2 (x, 53);
178 mpfr_init2 (y, 53);
179 mpfr_init2 (z, 53);
180
181 mpfr_set_ui (x, 17, MPFR_RNDN);
182 inexact = mpfr_tanu (y, x, 42, MPFR_RNDN);
183 /* y should be tan(2*17*pi/42) rounded to nearest */
184 mpfr_set_str (z, "-0xa.e89b03074638p-4", 16, MPFR_RNDN);
185 MPFR_ASSERTN(mpfr_equal_p (y, z));
186 MPFR_ASSERTN(inexact > 0);
187
188 mpfr_clear (x);
189 mpfr_clear (y);
190 mpfr_clear (z);
191 }
192
193 /* Check argument reduction with large hard-coded inputs. The following
194 values were generated with gen_random(tan,10,53,100,20), where the
195 Sage code for gen_random is given in the tcosu.c file. */
196 static void
test_large(void)197 test_large (void)
198 {
199 static struct {
200 const char *x;
201 unsigned long u;
202 const char *y;
203 } t[] = {
204 { "-0x1.8f7cb49edc03p+16", 28, "0x4.c869fd8050554p-4" },
205 { "-0xe.8ede30716292p+16", 17, "-0x2.c83df69d8fdecp+4" },
206 { "-0x8.f14a73a7b4a3p+16", 4, "-0xd.be24a6d0fde98p-4" },
207 { "0xe.f82c4537b473p+16", 93, "-0x5.d0d95fdc8ffbcp+0" },
208 { "0x8.4148f00c8418p+16", 50, "0x1.e4e4aa652b2a4p-4" },
209 { "-0x6.e8b69db10e63p+16", 27, "-0x2.4f32f1977b7b2p-4" },
210 { "-0xe.a3ebf225ea2fp+16", 18, "0x6.5f7637f74517p+0" },
211 { "-0x5.580eb29168d8p+16", 92, "0x8.96418eed84e8p+0" },
212 { "0x8.13c5a1b43231p+16", 19, "0xb.2718b861b29fp-8" },
213 { "0x4.eb4e546e042dp+16", 64, "0x6.0b3ba821e4ep+0" }
214 };
215 int i;
216 mpfr_t x, y, z;
217
218 mpfr_inits2 (53, x, y, z, (mpfr_ptr) 0);
219 for (i = 0; i < numberof (t); i++)
220 {
221 mpfr_set_str (x, t[i].x, 0, MPFR_RNDN);
222 mpfr_set_str (y, t[i].y, 0, MPFR_RNDN);
223 mpfr_tanu (z, x, t[i].u, MPFR_RNDN);
224 MPFR_ASSERTN (mpfr_equal_p (y, z));
225 }
226 mpfr_clears (x, y, z, (mpfr_ptr) 0);
227 }
228
229 #define TEST_FUNCTION mpfr_tanu
230 #define ULONG_ARG2
231 #include "tgeneric.c"
232
233 static int
mpfr_tan2pi(mpfr_ptr y,mpfr_srcptr x,mpfr_rnd_t r)234 mpfr_tan2pi (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t r)
235 {
236 return mpfr_tanu (y, x, 1, r);
237 }
238
239 int
main(void)240 main (void)
241 {
242 tests_start_mpfr ();
243
244 test_singular ();
245 test_exact ();
246 test_regular ();
247 test_large ();
248
249 test_generic (MPFR_PREC_MIN, 100, 1000);
250
251 data_check ("data/tan2pi", mpfr_tan2pi, "mpfr_tan2pi");
252
253 tests_end_mpfr ();
254 return 0;
255 }
256