1/* Test file for mpfr_cos. 2 3Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. 4Contributed by the Arenaire and Cacao 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 20http://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 <stdio.h> 24#include <stdlib.h> 25 26#include "mpfr-test.h" 27 28#ifdef CHECK_EXTERNAL 29static int 30test_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 51static void 52check53 (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 75static void 76check_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 140static void 141special_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 164static void 165overflowed_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 242static void 243bug20091030 (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 255int 256main (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