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