xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/tcos.c (revision fc4f42693f9b1c31f39f9cf50af1bf2010325808)
1 /* Test file for mpfr_cos.
2 
3 Copyright 2001-2016 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 http://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 <stdio.h>
24 #include <stdlib.h>
25 
26 #include "mpfr-test.h"
27 
28 #ifdef CHECK_EXTERNAL
29 static int
30 test_cos (mpfr_ptr a, mpfr_srcptr b, mpfr_rnd_t rnd_mode)
31 {
32   int res;
33   int ok = rnd_mode == MPFR_RNDN && mpfr_number_p (b) && mpfr_get_prec (a)>=53;
34   if (ok)
35     {
36       mpfr_print_raw (b);
37     }
38   res = mpfr_cos (a, b, rnd_mode);
39   if (ok)
40     {
41       printf (" ");
42       mpfr_print_raw (a);
43       printf ("\n");
44     }
45   return res;
46 }
47 #else
48 #define test_cos mpfr_cos
49 #endif
50 
51 static void
52 check53 (const char *xs, const char *cos_xs, mpfr_rnd_t rnd_mode)
53 {
54   mpfr_t xx, c;
55 
56   mpfr_inits2 (53, xx, c, (mpfr_ptr) 0);
57   mpfr_set_str1 (xx, xs); /* should be exact */
58   test_cos (c, xx, rnd_mode);
59   if (mpfr_cmp_str1 (c, cos_xs))
60     {
61       printf ("mpfr_cos failed for x=%s, rnd=%s\n",
62               xs, mpfr_print_rnd_mode (rnd_mode));
63       printf ("mpfr_cos gives cos(x)=");
64       mpfr_out_str(stdout, 10, 0, c, MPFR_RNDN);
65       printf(", expected %s\n", cos_xs);
66       exit (1);
67     }
68   mpfr_clears (xx, c, (mpfr_ptr) 0);
69 }
70 
71 #define TEST_FUNCTION test_cos
72 #define REDUCE_EMAX 262143 /* otherwise arg. reduction is too expensive */
73 #include "tgeneric.c"
74 
75 static void
76 check_nans (void)
77 {
78   mpfr_t  x, y;
79 
80   mpfr_init2 (x, 123L);
81   mpfr_init2 (y, 123L);
82 
83   mpfr_set_nan (x);
84   test_cos (y, x, MPFR_RNDN);
85   if (! mpfr_nan_p (y))
86     {
87       printf ("Error: cos(NaN) != NaN\n");
88       exit (1);
89     }
90 
91   mpfr_set_inf (x, 1);
92   test_cos (y, x, MPFR_RNDN);
93   if (! mpfr_nan_p (y))
94     {
95       printf ("Error: cos(Inf) != NaN\n");
96       exit (1);
97     }
98 
99   mpfr_set_inf (x, -1);
100   test_cos (y, x, MPFR_RNDN);
101   if (! mpfr_nan_p (y))
102     {
103       printf ("Error: cos(-Inf) != NaN\n");
104       exit (1);
105     }
106 
107   /* cos(+/-0) = 1 */
108   mpfr_set_ui (x, 0, MPFR_RNDN);
109   test_cos (y, x, MPFR_RNDN);
110   if (mpfr_cmp_ui (y, 1))
111     {
112       printf ("Error: cos(+0) != 1\n");
113       exit (1);
114     }
115   mpfr_neg (x, x, MPFR_RNDN);
116   test_cos (y, x, MPFR_RNDN);
117   if (mpfr_cmp_ui (y, 1))
118     {
119       printf ("Error: cos(-0) != 1\n");
120       exit (1);
121     }
122 
123   /* Compute ~Pi/2 to check */
124   /* FIXME: Too slow!
125   mpfr_set_prec (x, 20000);
126   mpfr_const_pi (x, MPFR_RNDD); mpfr_div_2ui (x, x, 1, MPFR_RNDN);
127   mpfr_set_prec (y, 24);
128   test_cos (y, x, MPFR_RNDN);
129   if (mpfr_cmp_str (y, "0.111001010110100011000001E-20000", 2, MPFR_RNDN))
130     {
131       printf("Error computing cos(~Pi/2)\n");
132       mpfr_dump (y);
133       exit (1);
134       } */
135 
136   mpfr_clear (x);
137   mpfr_clear (y);
138 }
139 
140 static void
141 special_overflow (void)
142 {
143   mpfr_t x, y;
144   mpfr_exp_t emin, emax;
145 
146   emin = mpfr_get_emin ();
147   emax = mpfr_get_emax ();
148 
149   mpfr_init2 (x, 24);
150   mpfr_init2 (y, 73);
151 
152   /* Check special case: An overflow in const_pi could occurs! */
153   set_emin (-125);
154   set_emax (128);
155   mpfr_set_str_binary (x, "0.111101010110110011101101E6");
156   test_cos (y, x, MPFR_RNDZ);
157   set_emin (emin);
158   set_emax (emax);
159 
160   mpfr_clear (x);
161   mpfr_clear (y);
162 }
163 
164 static void
165 overflowed_cos0 (void)
166 {
167   mpfr_t x, y;
168   int emax, i, inex, rnd, err = 0;
169   mpfr_exp_t old_emax;
170 
171   old_emax = mpfr_get_emax ();
172 
173   mpfr_init2 (x, 8);
174   mpfr_init2 (y, 8);
175 
176   for (emax = -1; emax <= 0; emax++)
177     {
178       mpfr_set_ui_2exp (y, 1, emax, MPFR_RNDN);
179       mpfr_nextbelow (y);
180       set_emax (emax);  /* 1 is not representable. */
181       /* and if emax < 0, 1 - eps is not representable either. */
182       for (i = -1; i <= 1; i++)
183         RND_LOOP (rnd)
184         {
185           mpfr_set_si_2exp (x, i, -512 * ABS (i), MPFR_RNDN);
186           mpfr_clear_flags ();
187           inex = mpfr_cos (x, x, (mpfr_rnd_t) rnd);
188           if ((i == 0 || emax < 0 || rnd == MPFR_RNDN || rnd == MPFR_RNDU) &&
189               ! mpfr_overflow_p ())
190             {
191               printf ("Error in overflowed_cos0 (i = %d, rnd = %s):\n"
192                       "  The overflow flag is not set.\n",
193                       i, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
194               err = 1;
195             }
196           if (rnd == MPFR_RNDZ || rnd == MPFR_RNDD)
197             {
198               if (inex >= 0)
199                 {
200                   printf ("Error in overflowed_cos0 (i = %d, rnd = %s):\n"
201                           "  The inexact value must be negative.\n",
202                           i, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
203                   err = 1;
204                 }
205               if (! mpfr_equal_p (x, y))
206                 {
207                   printf ("Error in overflowed_cos0 (i = %d, rnd = %s):\n"
208                           "  Got ", i, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
209                   mpfr_print_binary (x);
210                   printf (" instead of 0.11111111E%d.\n", emax);
211                   err = 1;
212                 }
213             }
214           else
215             {
216               if (inex <= 0)
217                 {
218                   printf ("Error in overflowed_cos0 (i = %d, rnd = %s):\n"
219                           "  The inexact value must be positive.\n",
220                           i, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
221                   err = 1;
222                 }
223               if (! (mpfr_inf_p (x) && MPFR_SIGN (x) > 0))
224                 {
225                   printf ("Error in overflowed_cos0 (i = %d, rnd = %s):\n"
226                           "  Got ", i, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd));
227                   mpfr_print_binary (x);
228                   printf (" instead of +Inf.\n");
229                   err = 1;
230                 }
231             }
232         }
233       set_emax (old_emax);
234     }
235 
236   if (err)
237     exit (1);
238   mpfr_clear (x);
239   mpfr_clear (y);
240 }
241 
242 static void
243 bug20091030 (void)
244 {
245   mpfr_t x, y;
246 
247   mpfr_init2 (x, 5);
248   mpfr_init2 (y, 2);
249   mpfr_set_str (x, "-0.11001E3", 2, MPFR_RNDN);
250   mpfr_cos (y, x, MPFR_RNDN);
251   mpfr_clear (x);
252   mpfr_clear (y);
253 }
254 
255 int
256 main (int argc, char *argv[])
257 {
258   mpfr_t x, y;
259   int inex;
260 
261   tests_start_mpfr ();
262 
263   special_overflow ();
264   check_nans ();
265 
266   mpfr_init (x);
267   mpfr_init (y);
268 
269   mpfr_set_prec (x, 53);
270   mpfr_set_prec (y, 2);
271   mpfr_set_str (x, "9.81333845856942e-1", 10, MPFR_RNDN);
272   test_cos (y, x, MPFR_RNDN);
273 
274   mpfr_set_prec (x, 30);
275   mpfr_set_prec (y, 30);
276   mpfr_set_str_binary (x, "1.00001010001101110010100010101e-1");
277   test_cos (y, x, MPFR_RNDU);
278   mpfr_set_str_binary (x, "1.10111100010101011110101010100e-1");
279   if (mpfr_cmp (y, x))
280     {
281       printf ("Error for prec=30, rnd=MPFR_RNDU\n");
282       printf ("expected "); mpfr_print_binary (x); puts ("");
283       printf ("     got "); mpfr_print_binary (y); puts ("");
284       exit (1);
285     }
286 
287   mpfr_set_prec (x, 59);
288   mpfr_set_prec (y, 59);
289   mpfr_set_str_binary (x, "1.01101011101111010011111110111111111011011101100111100011e-3");
290   test_cos (y, x, MPFR_RNDU);
291   mpfr_set_str_binary (x, "1.1111011111110010001001001011100111101110100010000010010011e-1");
292   if (mpfr_cmp (y, x))
293     {
294       printf ("Error for prec=59, rnd=MPFR_RNDU\n");
295       printf ("expected "); mpfr_print_binary (x); puts ("");
296       printf ("     got "); mpfr_print_binary (y); puts ("");
297       exit (1);
298     }
299 
300   mpfr_set_prec (x, 5);
301   mpfr_set_prec (y, 5);
302   mpfr_set_str_binary (x, "1.1100e-2");
303   test_cos (y, x, MPFR_RNDD);
304   mpfr_set_str_binary (x, "1.1100e-1");
305   if (mpfr_cmp (y, x))
306     {
307       printf ("Error for x=1.1100e-2, rnd=MPFR_RNDD\n");
308       printf ("expected 1.1100e-1, got "); mpfr_print_binary (y); puts ("");
309       exit (1);
310     }
311 
312   mpfr_set_prec (x, 32);
313   mpfr_set_prec (y, 32);
314 
315   mpfr_set_str_binary (x, "0.10001000001001011000100001E-6");
316   mpfr_set_str_binary (y, "0.1111111111111101101111001100001");
317   test_cos (x, x, MPFR_RNDN);
318   if (mpfr_cmp (x, y))
319     {
320       printf ("Error for prec=32 (1)\n");
321       exit (1);
322     }
323 
324   mpfr_set_str_binary (x, "-0.1101011110111100111010011001011E-1");
325   mpfr_set_str_binary (y, "0.11101001100110111011011010100011");
326   test_cos (x, x, MPFR_RNDN);
327   if (mpfr_cmp (x, y))
328     {
329       printf ("Error for prec=32 (2)\n");
330       exit (1);
331     }
332 
333   /* huge argument reduction */
334   mpfr_set_str_binary (x, "0.10000010000001101011101111001011E40");
335   mpfr_set_str_binary (y, "0.10011000001111010000101011001011E-1");
336   test_cos (x, x, MPFR_RNDN);
337   if (mpfr_cmp (x, y))
338     {
339       printf ("Error for prec=32 (3)\n");
340       exit (1);
341     }
342 
343   mpfr_set_prec (x, 3);
344   mpfr_set_prec (y, 3);
345   mpfr_set_str_binary (x, "0.110E60");
346   inex = mpfr_cos (y, x, MPFR_RNDD);
347   MPFR_ASSERTN(inex < 0);
348 
349   /* worst case from PhD thesis of Vincent Lefe`vre: x=8980155785351021/2^54 */
350   check53 ("4.984987858808754279e-1", "8.783012931285841817e-1", MPFR_RNDN);
351   check53 ("4.984987858808754279e-1", "8.783012931285840707e-1", MPFR_RNDD);
352   check53 ("4.984987858808754279e-1", "8.783012931285840707e-1", MPFR_RNDZ);
353   check53 ("4.984987858808754279e-1", "8.783012931285841817e-1", MPFR_RNDU);
354   check53 ("1.00031274099908640274",  "0.540039116973283217504", MPFR_RNDN);
355   check53 ("1.00229256850978698523",  "0.538371757797526551137", MPFR_RNDZ);
356   check53 ("1.00288304857059840103",  "0.537874062022526966409", MPFR_RNDZ);
357   check53 ("1.00591265847407274059",  "0.53531755997839769456",  MPFR_RNDN);
358 
359   check53 ("1.00591265847407274059", "0.53531755997839769456",  MPFR_RNDN);
360 
361   overflowed_cos0 ();
362   test_generic (2, 100, 15);
363 
364   /* check inexact flag */
365   mpfr_set_prec (x, 3);
366   mpfr_set_prec (y, 13);
367   mpfr_set_str_binary (x, "-0.100E196");
368   inex = mpfr_cos (y, x, MPFR_RNDU);
369   mpfr_set_prec (x, 13);
370   mpfr_set_str_binary (x, "0.1111111100101");
371   MPFR_ASSERTN (inex > 0 && mpfr_equal_p (x, y));
372 
373   mpfr_clear (x);
374   mpfr_clear (y);
375 
376   bug20091030 ();
377 
378   data_check ("data/cos", mpfr_cos, "mpfr_cos");
379   bad_cases (mpfr_cos, mpfr_acos, "mpfr_cos", 256, -40, 0, 4, 128, 800, 50);
380 
381   tests_end_mpfr ();
382   return 0;
383 }
384