1 /* Test file for mpfr_get_sj and mpfr_get_uj. 2 3 Copyright 2004-2020 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 https://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 #define MPFR_NEED_INTMAX_H 24 #include "mpfr-test.h" 25 26 #ifndef _MPFR_H_HAVE_INTMAX_T 27 28 int 29 main (void) 30 { 31 return 77; 32 } 33 34 #else 35 36 #ifndef NPRINTF_J 37 #define PRMAX(SPEC,V) printf (" %j" SPEC ",", V) 38 #else 39 #define PRMAX(SPEC,V) (void) 0 40 #endif 41 42 static void 43 check_sj (intmax_t s, mpfr_ptr x) 44 { 45 mpfr_exp_t emin, emax; 46 mpfr_t y; 47 int i; 48 49 mpfr_init2 (y, MPFR_PREC (x) + 2); 50 51 emin = mpfr_get_emin (); 52 emax = mpfr_get_emax (); 53 54 for (i = -1; i <= 1; i++) 55 { 56 int rnd; 57 int inex; 58 int fi, e; 59 mpfr_flags_t flags[2] = { 0, MPFR_FLAGS_ALL }, ex_flags, gt_flags; 60 61 inex = mpfr_set_si_2exp (y, i, -2, MPFR_RNDN); 62 MPFR_ASSERTN (inex == 0); 63 inex = mpfr_add (y, y, x, MPFR_RNDN); 64 MPFR_ASSERTN (inex == 0); 65 /* y = x + i/4, with -1 <= i <= 1 */ 66 RND_LOOP (rnd) 67 for (fi = 0; fi < numberof (flags); fi++) 68 { 69 intmax_t r; 70 71 if (rnd == MPFR_RNDZ && i < 0 && s >= 0) 72 continue; 73 if (rnd == MPFR_RNDZ && i > 0 && s <= 0) 74 continue; 75 if (rnd == MPFR_RNDD && i < 0) 76 continue; 77 if (rnd == MPFR_RNDU && i > 0) 78 continue; 79 if (rnd == MPFR_RNDA && ((MPFR_IS_POS(y) && i > 0) || 80 (MPFR_IS_NEG(y) && i < 0))) 81 continue; 82 83 for (e = 0; e < 2; e++) 84 { 85 if (e) 86 { 87 mpfr_exp_t ey; 88 89 if (MPFR_IS_ZERO (y)) 90 break; 91 ey = MPFR_GET_EXP (y); 92 set_emin (ey); 93 set_emax (ey); 94 } 95 /* rint (y) == x == s */ 96 __gmpfr_flags = ex_flags = flags[fi]; 97 if (i != 0) 98 ex_flags |= MPFR_FLAGS_INEXACT; 99 r = mpfr_get_sj (y, (mpfr_rnd_t) rnd); 100 gt_flags = __gmpfr_flags; 101 set_emin (emin); 102 set_emax (emax); 103 if ((r != s || gt_flags != ex_flags) && rnd != MPFR_RNDF) 104 { 105 printf ("Error in check_sj for fi = %d, y = ", fi); 106 mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN); 107 printf (" in %s%s\n", 108 mpfr_print_rnd_mode ((mpfr_rnd_t) rnd), 109 e ? ", reduced exponent range" : ""); 110 printf ("Expected:"); 111 PRMAX ("d", s); 112 flags_out (ex_flags); 113 printf ("Got: "); 114 PRMAX ("d", r); 115 flags_out (gt_flags); 116 exit (1); 117 } 118 } 119 } 120 } 121 122 mpfr_clear (y); 123 } 124 125 static void 126 check_uj (uintmax_t u, mpfr_ptr x) 127 { 128 mpfr_exp_t emin, emax; 129 mpfr_t y; 130 int i; 131 132 mpfr_init2 (y, MPFR_PREC (x) + 2); 133 134 emin = mpfr_get_emin (); 135 emax = mpfr_get_emax (); 136 137 for (i = -1; i <= 1; i++) 138 { 139 int rnd; 140 int inex; 141 int fi, e; 142 mpfr_flags_t flags[2] = { 0, MPFR_FLAGS_ALL }, ex_flags, gt_flags; 143 144 inex = mpfr_set_si_2exp (y, i, -2, MPFR_RNDN); 145 MPFR_ASSERTN (inex == 0); 146 inex = mpfr_add (y, y, x, MPFR_RNDN); 147 MPFR_ASSERTN (inex == 0); 148 /* y = x + i/4, with -1 <= i <= 1 */ 149 RND_LOOP (rnd) 150 for (fi = 0; fi < numberof (flags); fi++) 151 { 152 uintmax_t r; 153 154 if (rnd == MPFR_RNDZ && i < 0) 155 continue; 156 if (rnd == MPFR_RNDD && i < 0) 157 continue; 158 if (rnd == MPFR_RNDU && i > 0) 159 continue; 160 if (rnd == MPFR_RNDA && ((MPFR_IS_POS(y) && i > 0) || 161 (MPFR_IS_NEG(y) && i < 0))) 162 continue; 163 164 for (e = 0; e < 2; e++) 165 { 166 if (e) 167 { 168 mpfr_exp_t ey; 169 170 if (MPFR_IS_ZERO (y)) 171 break; 172 ey = MPFR_GET_EXP (y); 173 set_emin (ey); 174 set_emax (ey); 175 } 176 /* rint (y) == x == u */ 177 __gmpfr_flags = ex_flags = flags[fi]; 178 if (i != 0) 179 ex_flags |= MPFR_FLAGS_INEXACT; 180 r = mpfr_get_uj (y, (mpfr_rnd_t) rnd); 181 gt_flags = __gmpfr_flags; 182 set_emin (emin); 183 set_emax (emax); 184 if ((r != u || gt_flags != ex_flags) && rnd != MPFR_RNDF) 185 { 186 printf ("Error in check_uj for fi = %d, y = ", fi); 187 mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN); 188 printf (" in %s%s\n", 189 mpfr_print_rnd_mode ((mpfr_rnd_t) rnd), 190 e ? ", reduced exponent range" : ""); 191 printf ("Expected:"); 192 PRMAX ("u", u); 193 flags_out (ex_flags); 194 printf ("Got: "); 195 PRMAX ("u", r); 196 flags_out (gt_flags); 197 exit (1); 198 } 199 } 200 } 201 } 202 203 mpfr_clear (y); 204 } 205 206 #define CHECK_ERANGE(F,FMT,RES,INPUT,VALUE,E) \ 207 do \ 208 { \ 209 __gmpfr_flags = ex_flags = flags[fi]; \ 210 RES = F (x, (mpfr_rnd_t) rnd); \ 211 gt_flags = __gmpfr_flags; \ 212 if (E) \ 213 ex_flags |= MPFR_FLAGS_ERANGE; \ 214 if (RES == VALUE && gt_flags == ex_flags) \ 215 continue; \ 216 printf ("Error in check_erange for %s, %s, fi = %d on %s\n", \ 217 #F, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd), fi, INPUT); \ 218 printf ("Expected:"); \ 219 PRMAX (FMT, VALUE); \ 220 flags_out (ex_flags); \ 221 printf ("Got: "); \ 222 PRMAX (FMT, RES); \ 223 flags_out (gt_flags); \ 224 exit (1); \ 225 } \ 226 while (0) 227 228 #define CHECK_ERANGE_U(INPUT,VALUE,E) \ 229 CHECK_ERANGE (mpfr_get_uj, "u", u, INPUT, (uintmax_t) VALUE, E) 230 #define CHECK_ERANGE_S(INPUT,VALUE,E) \ 231 CHECK_ERANGE (mpfr_get_sj, "d", d, INPUT, (intmax_t) VALUE, E) 232 233 static void 234 check_erange (void) 235 { 236 mpfr_t x; 237 uintmax_t u; 238 intmax_t d; 239 int rnd; 240 int fi; 241 mpfr_flags_t flags[3] = { 0, MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE, 242 MPFR_FLAGS_ALL }, ex_flags, gt_flags; 243 244 /* Test for ERANGE flag + correct behavior if overflow */ 245 246 mpfr_init2 (x, 256); 247 248 RND_LOOP (rnd) 249 for (fi = 0; fi < numberof (flags); fi++) 250 { 251 mpfr_set_uj (x, UINTMAX_MAX, MPFR_RNDN); 252 CHECK_ERANGE_U ("UINTMAX_MAX", UINTMAX_MAX, 0); 253 mpfr_add_ui (x, x, 1, MPFR_RNDN); 254 CHECK_ERANGE_U ("UINTMAX_MAX+1", UINTMAX_MAX, 1); 255 mpfr_set_sj (x, -1, MPFR_RNDN); 256 CHECK_ERANGE_U ("-1", 0, 1); 257 mpfr_set_sj (x, INTMAX_MAX, MPFR_RNDN); 258 CHECK_ERANGE_S ("INTMAX_MAX", INTMAX_MAX, 0); 259 mpfr_add_ui (x, x, 1, MPFR_RNDN); 260 CHECK_ERANGE_S ("INTMAX_MAX+1", INTMAX_MAX, 1); 261 mpfr_set_sj (x, INTMAX_MIN, MPFR_RNDN); 262 CHECK_ERANGE_S ("INTMAX_MIN", INTMAX_MIN, 0); 263 mpfr_sub_ui (x, x, 1, MPFR_RNDN); 264 CHECK_ERANGE_S ("INTMAX_MIN-1", INTMAX_MIN, 1); 265 mpfr_set_nan (x); 266 CHECK_ERANGE_U ("NaN", 0, 1); 267 CHECK_ERANGE_S ("NaN", 0, 1); 268 } 269 270 mpfr_clear (x); 271 } 272 273 static void 274 test_get_uj_smallneg (void) 275 { 276 mpfr_t x; 277 int i; 278 279 mpfr_init2 (x, 64); 280 281 for (i = 1; i <= 4; i++) 282 { 283 int r; 284 285 mpfr_set_si_2exp (x, -i, -2, MPFR_RNDN); 286 RND_LOOP (r) 287 { 288 intmax_t s; 289 uintmax_t u; 290 291 mpfr_clear_erangeflag (); 292 s = mpfr_get_sj (x, r != MPFR_RNDF ? (mpfr_rnd_t) r : MPFR_RNDA); 293 if (mpfr_erangeflag_p ()) 294 { 295 printf ("ERROR for get_sj + ERANGE + small negative op" 296 " for rnd = %s and x = -%d/4\n", 297 mpfr_print_rnd_mode ((mpfr_rnd_t) r), i); 298 exit (1); 299 } 300 u = mpfr_get_uj (x, (mpfr_rnd_t) r); 301 if (u != 0) 302 { 303 printf ("ERROR for get_uj + ERANGE + small negative op" 304 " for rnd = %s and x = -%d/4\n", 305 mpfr_print_rnd_mode ((mpfr_rnd_t) r), i); 306 #ifndef NPRINTF_J 307 printf ("Expected 0, got %ju\n", u); 308 #endif 309 exit (1); 310 } 311 if ((s == 0) ^ !mpfr_erangeflag_p ()) 312 { 313 const char *Not = s == 0 ? "" : " not"; 314 315 printf ("ERROR for get_uj + ERANGE + small negative op" 316 " for rnd = %s and x = -%d/4\n", 317 mpfr_print_rnd_mode ((mpfr_rnd_t) r), i); 318 printf ("The rounded integer "); 319 #ifndef NPRINTF_J 320 printf("(%jd) ", s); 321 #endif 322 printf("is%s representable in unsigned long,\n" 323 "but the erange flag is%s set.\n", Not, Not); 324 exit (1); 325 } 326 } 327 } 328 329 mpfr_clear (x); 330 } 331 332 int 333 main (void) 334 { 335 mpfr_prec_t prec; 336 mpfr_t x, y; 337 intmax_t s; 338 uintmax_t u; 339 340 tests_start_mpfr (); 341 342 for (u = UINTMAX_MAX, prec = 0; u != 0; u /= 2, prec++) 343 { } 344 345 mpfr_init2 (x, prec + 4); 346 mpfr_init2 (y, prec + 4); 347 348 mpfr_set_ui (x, 0, MPFR_RNDN); 349 check_sj (0, x); 350 check_uj (0, x); 351 352 mpfr_set_ui (x, 1, MPFR_RNDN); 353 check_sj (1, x); 354 check_uj (1, x); 355 356 mpfr_neg (x, x, MPFR_RNDN); 357 check_sj (-1, x); 358 359 mpfr_set_si_2exp (x, 1, prec, MPFR_RNDN); 360 mpfr_sub_ui (x, x, 1, MPFR_RNDN); /* UINTMAX_MAX */ 361 362 mpfr_div_ui (y, x, 2, MPFR_RNDZ); 363 mpfr_trunc (y, y); /* INTMAX_MAX */ 364 for (s = INTMAX_MAX; s != 0; s /= 17) 365 { 366 check_sj (s, y); 367 mpfr_div_ui (y, y, 17, MPFR_RNDZ); 368 mpfr_trunc (y, y); 369 } 370 371 mpfr_div_ui (y, x, 2, MPFR_RNDZ); 372 mpfr_trunc (y, y); /* INTMAX_MAX */ 373 mpfr_neg (y, y, MPFR_RNDN); 374 if (INTMAX_MIN + INTMAX_MAX != 0) 375 mpfr_sub_ui (y, y, 1, MPFR_RNDN); /* INTMAX_MIN */ 376 for (s = INTMAX_MIN; s != 0; s /= 17) 377 { 378 check_sj (s, y); 379 mpfr_div_ui (y, y, 17, MPFR_RNDZ); 380 mpfr_trunc (y, y); 381 } 382 383 for (u = UINTMAX_MAX; u != 0; u /= 17) 384 { 385 check_uj (u, x); 386 mpfr_div_ui (x, x, 17, MPFR_RNDZ); 387 mpfr_trunc (x, x); 388 } 389 390 mpfr_clear (x); 391 mpfr_clear (y); 392 393 check_erange (); 394 test_get_uj_smallneg (); 395 396 tests_end_mpfr (); 397 return 0; 398 } 399 400 #endif 401