1 /* ttan -- test file for mpc_tan.
2
3 Copyright (C) 2008, 2011, 2012, 2013, 2020 INRIA
4
5 This file is part of GNU MPC.
6
7 GNU MPC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU Lesser General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11
12 GNU MPC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15 more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with this program. If not, see http://www.gnu.org/licenses/ .
19 */
20
21 #include <stdlib.h>
22 #include "mpc-tests.h"
23
24 static void
pure_real_argument(void)25 pure_real_argument (void)
26 {
27 /* tan(x -i*0) = tan(x) -i*0 */
28 /* tan(x +i*0) = tan(x) +i*0 */
29 mpfr_t x;
30 mpfr_t tan_x;
31 mpc_t z;
32 mpc_t tan_z;
33
34 mpfr_init2 (x, 79);
35 mpfr_init2 (tan_x, 113);
36 mpc_init2 (z, 79);
37 mpc_init2 (tan_z, 113);
38
39 /* tan(1 +i*0) = tan(1) +i*0 */
40 mpc_set_ui_ui (z, 1, 0, MPC_RNDNN);
41 mpfr_set_ui (x, 1, MPFR_RNDN);
42 mpfr_tan (tan_x, x, MPFR_RNDN);
43 mpc_tan (tan_z, z, MPC_RNDNN);
44 if (mpfr_cmp (mpc_realref (tan_z), tan_x) != 0
45 || !mpfr_zero_p (mpc_imagref (tan_z)) || mpfr_signbit (mpc_imagref (tan_z)))
46 {
47 printf ("mpc_tan(1 + i * 0) failed\n");
48 exit (1);
49 }
50
51 /* tan(1 -i*0) = tan(1) -i*0 */
52 mpc_conj (z, z, MPC_RNDNN);
53 mpc_tan (tan_z, z, MPC_RNDNN);
54 if (mpfr_cmp (mpc_realref (tan_z), tan_x) != 0
55 || !mpfr_zero_p (mpc_imagref (tan_z)) || !mpfr_signbit (mpc_imagref (tan_z)))
56 {
57 printf ("mpc_tan(1 - i * 0) failed\n");
58 exit (1);
59 }
60
61 /* tan(Pi/2 +i*0) = +Inf +i*0 */
62 mpfr_const_pi (x, MPFR_RNDN);
63 mpfr_div_2ui (x, x, 1, MPFR_RNDN);
64 mpfr_set (mpc_realref (z), x, MPFR_RNDN);
65 mpfr_set_ui (mpc_imagref (z), 0, MPFR_RNDN);
66 mpfr_tan (tan_x, x, MPFR_RNDN);
67 mpc_tan (tan_z, z, MPC_RNDNN);
68 if (mpfr_cmp (mpc_realref (tan_z), tan_x) != 0
69 || !mpfr_zero_p (mpc_imagref (tan_z)) || mpfr_signbit (mpc_imagref (tan_z)))
70 {
71 printf ("mpc_tan(Pi/2 + i * 0) failed\n");
72 exit (1);
73 }
74
75 /* tan(Pi/2 -i*0) = +Inf -i*0 */
76 mpc_conj (z, z, MPC_RNDNN);
77 mpc_tan (tan_z, z, MPC_RNDNN);
78 if (mpfr_cmp (mpc_realref (tan_z), tan_x) != 0
79 || !mpfr_zero_p (mpc_imagref (tan_z)) || !mpfr_signbit (mpc_imagref (tan_z)))
80 {
81 printf ("mpc_tan(Pi/2 - i * 0) failed\n");
82 exit (1);
83 }
84
85 /* tan(-Pi/2 +i*0) = -Inf +i*0 */
86 mpfr_neg (x, x, MPFR_RNDN);
87 mpc_neg (z, z, MPC_RNDNN);
88 mpfr_tan (tan_x, x, MPFR_RNDN);
89 mpc_tan (tan_z, z, MPC_RNDNN);
90 if (mpfr_cmp (mpc_realref (tan_z), tan_x) != 0
91 || !mpfr_zero_p (mpc_imagref (tan_z)) || mpfr_signbit (mpc_imagref (tan_z)))
92 {
93 printf ("mpc_tan(-Pi/2 + i * 0) failed\n");
94 exit (1);
95 }
96
97 /* tan(-Pi/2 -i*0) = -Inf -i*0 */
98 mpc_conj (z, z, MPC_RNDNN);
99 mpc_tan (tan_z, z, MPC_RNDNN);
100 if (mpfr_cmp (mpc_realref (tan_z), tan_x) != 0
101 || !mpfr_zero_p (mpc_imagref (tan_z)) || !mpfr_signbit (mpc_imagref (tan_z)))
102 {
103 printf ("mpc_tan(-Pi/2 - i * 0) failed\n");
104 exit (1);
105 }
106
107 mpc_clear (tan_z);
108 mpc_clear (z);
109 mpfr_clear (tan_x);
110 mpfr_clear (x);
111 }
112
113 static void
pure_imaginary_argument(void)114 pure_imaginary_argument (void)
115 {
116 /* tan(-0 +i*y) = -0 +i*tanh(y) */
117 /* tan(+0 +i*y) = +0 +i*tanh(y) */
118 mpfr_t y;
119 mpfr_t tanh_y;
120 mpc_t z;
121 mpc_t tan_z;
122 mpfr_prec_t prec = (mpfr_prec_t) 111;
123
124 mpfr_init2 (y, 2);
125 mpfr_init2 (tanh_y, prec);
126 mpc_init2 (z, 2);
127 mpc_init2 (tan_z, prec);
128
129 /* tan(0 +i) = +0 +i*tanh(1) */
130 mpc_set_ui_ui (z, 0, 1, MPC_RNDNN);
131 mpfr_set_ui (y, 1, MPFR_RNDN);
132 mpfr_tanh (tanh_y, y, MPFR_RNDN);
133 mpc_tan (tan_z, z, MPC_RNDNN);
134 if (mpfr_cmp (mpc_imagref (tan_z), tanh_y) != 0
135 || !mpfr_zero_p (mpc_realref (tan_z)) || mpfr_signbit (mpc_realref (tan_z)))
136 {
137 mpc_t c99;
138
139 mpc_init2 (c99, prec);
140 mpfr_set_ui (mpc_realref (c99), 0, MPFR_RNDN);
141 mpfr_set (mpc_imagref (c99), tanh_y, MPFR_RNDN);
142
143 TEST_FAILED ("mpc_tan", z, tan_z, c99, MPC_RNDNN);
144 }
145
146 /* tan(0 -i) = +0 +i*tanh(-1) */
147 mpc_conj (z, z, MPC_RNDNN);
148 mpfr_neg (tanh_y, tanh_y, MPFR_RNDN);
149 mpc_tan (tan_z, z, MPC_RNDNN);
150 if (mpfr_cmp (mpc_imagref (tan_z), tanh_y) != 0
151 || !mpfr_zero_p (mpc_realref (tan_z)) || mpfr_signbit (mpc_realref (tan_z)))
152 {
153 mpc_t c99;
154
155 mpc_init2 (c99, prec);
156 mpfr_set_ui (mpc_realref (c99), 0, MPFR_RNDN);
157 mpfr_set (mpc_imagref (c99), tanh_y, MPFR_RNDN);
158
159 TEST_FAILED ("mpc_tan", z, tan_z, c99, MPC_RNDNN);
160 }
161
162 /* tan(-0 +i) = -0 +i*tanh(1) */
163 mpc_neg (z, z, MPC_RNDNN);
164 mpfr_neg (tanh_y, tanh_y, MPFR_RNDN);
165 mpc_tan (tan_z, z, MPC_RNDNN);
166 if (mpfr_cmp (mpc_imagref (tan_z), tanh_y) != 0
167 || !mpfr_zero_p (mpc_realref (tan_z)) || !mpfr_signbit (mpc_realref (tan_z)))
168 {
169 mpc_t c99;
170
171 mpc_init2 (c99, prec);
172 mpfr_set_ui (mpc_realref (c99), 0, MPFR_RNDN);
173 mpfr_set (mpc_imagref (c99), tanh_y, MPFR_RNDN);
174
175 TEST_FAILED ("mpc_tan", z, tan_z, c99, MPC_RNDNN);
176 }
177
178 /* tan(-0 -i) = -0 +i*tanh(-1) */
179 mpc_conj (z, z, MPC_RNDNN);
180 mpfr_neg (tanh_y, tanh_y, MPFR_RNDN);
181 mpc_tan (tan_z, z, MPC_RNDNN);
182 if (mpfr_cmp (mpc_imagref (tan_z), tanh_y) != 0
183 || !mpfr_zero_p (mpc_realref (tan_z)) || !mpfr_signbit (mpc_realref (tan_z)))
184 {
185 mpc_t c99;
186
187 mpc_init2 (c99, prec);
188 mpfr_set_ui (mpc_realref (c99), 0, MPFR_RNDN);
189 mpfr_set (mpc_imagref (c99), tanh_y, MPFR_RNDN);
190
191 TEST_FAILED ("mpc_tan", z, tan_z, c99, MPC_RNDNN);
192 }
193
194 mpc_clear (tan_z);
195 mpc_clear (z);
196 mpfr_clear (tanh_y);
197 mpfr_clear (y);
198 }
199
200 /* test with reduced exponent range */
201 static void
bug20200211(void)202 bug20200211 (void)
203 {
204 mpfr_exp_t emin = mpfr_get_emin ();
205 mpc_t x, z, zr;
206
207 mpfr_set_emin (-148);
208 mpc_init2 (x, 24);
209 mpc_init2 (z, 24);
210 mpc_init2 (zr, 24);
211 mpfr_set_flt (mpc_realref (x), 0x3.b32d48p24, MPFR_RNDN);
212 mpfr_set_flt (mpc_imagref (x), -0x48.08bd0p0, MPFR_RNDN);
213 mpc_tan (z, x, MPC_RNDNN);
214 /* the real part should be 1.8638349976774607754968796608e-63,
215 but since that underflows, we should get +0 */
216 mpfr_set_flt (mpc_realref (zr), +0.0f, MPFR_RNDN);
217 mpfr_set_flt (mpc_imagref (zr), -1.0f, MPFR_RNDN);
218 if (mpc_cmp (z, zr))
219 {
220 printf ("Incorrect tangent with reduced exponent range:\n");
221 mpfr_printf ("Expected (%Re,%Re)\n", mpc_realref (zr), mpc_imagref (zr));
222 mpfr_printf ("Got (%Re,%Re)\n", mpc_realref (z), mpc_imagref (z));
223 exit (1);
224 }
225 mpc_clear (x);
226 mpc_clear (z);
227 mpc_clear (zr);
228 mpfr_set_emin (emin);
229 }
230
231 /* test failing with gcc 5.4.0, line 127 of tan.dat */
232 static void
bug20200301(void)233 bug20200301 (void)
234 {
235 mpc_t x, z, zr;
236 int inex;
237
238 mpc_init2 (x, 53);
239 mpc_init2 (z, 53);
240 mpc_init2 (zr, 53);
241 mpfr_set_d (mpc_realref (x), 0x4580CBF242683p-3, MPFR_RNDN);
242 mpfr_set_d (mpc_imagref (x), -0x1B3E8A3660D279p-3, MPFR_RNDN);
243 inex = mpc_tan (z, x, MPC_RNDNN);
244 mpfr_set_d (mpc_realref (zr), -0.0, MPFR_RNDN);
245 mpfr_set_d (mpc_imagref (zr), -1.0, MPFR_RNDN);
246 if (mpc_cmp (z, zr) != 0 || mpfr_signbit (mpc_realref (z)) == 0 ||
247 MPC_INEX_RE(inex) <= 0 || MPC_INEX_IM(inex) >= 0)
248 {
249 printf ("Incorrect tangent (bug20200301):\n");
250 mpfr_printf ("Expected (%Re,%Re)\n", mpc_realref (zr), mpc_imagref (zr));
251 mpfr_printf ("Got (%Re,%Re)\n", mpc_realref (z), mpc_imagref (z));
252 mpfr_printf ("expected ternary value (+1, -1)\n");
253 mpfr_printf ("got ternary value (%d, %d)\n", MPC_INEX_RE(inex),
254 MPC_INEX_IM(inex));
255 exit (1);
256 }
257 mpc_clear (x);
258 mpc_clear (z);
259 mpc_clear (zr);
260 }
261
262 #define MPC_FUNCTION_CALL \
263 P[0].mpc_inex = mpc_tan (P[1].mpc, P[2].mpc, P[3].mpc_rnd)
264 #define MPC_FUNCTION_CALL_REUSE_OP1 \
265 P[0].mpc_inex = mpc_tan (P[1].mpc, P[1].mpc, P[3].mpc_rnd)
266
267 #include "data_check.tpl"
268 #include "tgeneric.tpl"
269
270 int
main(void)271 main (void)
272 {
273 test_start ();
274
275 bug20200301 ();
276 bug20200211 ();
277
278 data_check_template ("tan.dsc", "tan.dat");
279
280 tgeneric_template ("tan.dsc", 2, 512, 7, 4);
281
282 /* FIXME: remove them? */
283 pure_real_argument ();
284 pure_imaginary_argument ();
285
286 test_end ();
287
288 return 0;
289 }
290