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