xref: /netbsd-src/external/lgpl3/mpc/dist/tests/ttan.c (revision 901e7e84758515fbf39dfc064cb0b45ab146d8b0)
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
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
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
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
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
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