1 /* Test file for mpfr_set_z_2exp. 2 3 Copyright 1999, 2001-2023 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 #include "mpfr-test.h" 24 25 /* generate a random exponent in [__gmpfr_emin, __gmpfr_emax-1] */ 26 static mpfr_exp_t 27 randexp (void) 28 { 29 mpfr_uexp_t e; 30 31 if (MPFR_EXP_MAX <= MPFR_LIMB_MAX >> 1) 32 { 33 /* mpfr_uexp_t fits in a limb: we can generate the whole range 34 [emin, emax] directly. */ 35 e = randlimb (); 36 } 37 else 38 { 39 mpfr_uexp_t emax = (mpfr_uexp_t) -1; 40 41 e = 0; 42 while (emax != 0) 43 { 44 /* Since mp_limb_t < mpfr_uexp_t, the shift counts are valid. 45 Use GMP_NUMB_BITS - 1 instead of GMP_NUMB_BITS to avoid a 46 bug in GCC. */ 47 e = (e << (GMP_NUMB_BITS - 1)) + (randlimb () >> 1); 48 emax >>= GMP_NUMB_BITS - 1; 49 } 50 } 51 return (mpfr_exp_t) (e % (__gmpfr_emax - __gmpfr_emin)) + __gmpfr_emin; 52 } 53 54 static void 55 check0 (void) 56 { 57 mpz_t y; 58 mpfr_t x; 59 int inexact, r; 60 mpfr_exp_t e; 61 62 /* Check for +0 */ 63 mpfr_init (x); 64 mpz_init (y); 65 mpz_set_si (y, 0); 66 RND_LOOP (r) 67 { 68 e = randexp (); 69 inexact = mpfr_set_z_2exp (x, y, e, (mpfr_rnd_t) r); 70 if (!MPFR_IS_ZERO(x) || !MPFR_IS_POS(x) || inexact) 71 { 72 printf ("mpfr_set_z_2exp(x,0,e) failed for e="); 73 if (e < LONG_MIN) 74 printf ("(<LONG_MIN)"); 75 else if (e > LONG_MAX) 76 printf ("(>LONG_MAX)"); 77 else 78 printf ("%ld", (long) e); 79 printf (", rnd=%s\n", mpfr_print_rnd_mode ((mpfr_rnd_t) r)); 80 exit (1); 81 } 82 } 83 84 /* coverage test for huge exponent */ 85 mpz_setbit (y, GMP_NUMB_BITS); 86 mpfr_clear_flags (); 87 inexact = mpfr_set_z_2exp (x, y, mpfr_get_emax_max(), MPFR_RNDN); 88 MPFR_ASSERTN(inexact > 0); 89 MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) > 0); 90 MPFR_ASSERTN(mpfr_overflow_p ()); 91 mpfr_clear(x); 92 mpz_clear(y); 93 } 94 95 /* FIXME: It'd be better to examine the actual data in an mpfr_t to see that 96 it's as expected. Comparing mpfr_set_z with mpfr_cmp or against 97 mpfr_get_si is a rather indirect test of a low level routine. */ 98 99 static void 100 check (long i, mpfr_rnd_t rnd, int reduced) 101 { 102 mpfr_t f1, f2, f3; 103 mpz_t z; 104 mpfr_exp_t e, old_emin, old_emax; 105 int inex; 106 mpfr_flags_t flags; 107 108 old_emin = mpfr_get_emin (); 109 old_emax = mpfr_get_emax (); 110 111 /* using CHAR_BIT * sizeof(long) bits of precision ensures that 112 mpfr_set_z_2exp is exact below */ 113 mpfr_inits2 (CHAR_BIT * sizeof(long), f1, f2, f3, (mpfr_ptr) 0); 114 mpz_init (z); 115 mpz_set_ui (z, i); 116 /* the following loop ensures that no overflow occurs */ 117 do 118 e = randexp (); 119 while (e > mpfr_get_emax () - CHAR_BIT * sizeof(long)); 120 121 mpfr_clear_flags (); 122 inex = mpfr_set_z_2exp (f1, z, e, rnd); 123 flags = __gmpfr_flags; 124 125 if (inex != 0 || flags != 0 || 126 (mpfr_div_2si (f2, f1, e, rnd), mpfr_get_si (f2, MPFR_RNDZ) != i)) 127 { 128 printf ("Error in mpfr_set_z_2exp for i=%ld e=%" MPFR_EXP_FSPEC 129 "d rnd_mode=%d\n", i, (mpfr_eexp_t) e, rnd); 130 mpfr_set_si_2exp (f2, i, e, MPFR_RNDN); 131 printf ("expected "); mpfr_dump (f2); 132 printf ("with inex = %d and flags =", 0); 133 flags_out (0); 134 printf ("got "); mpfr_dump (f1); 135 printf ("with inex = %d and flags =", inex); 136 flags_out (flags); 137 exit (1); 138 } 139 140 if (reduced) 141 { 142 mpfr_exp_t ef, emin, emax; 143 int inex2, inex3; 144 mpfr_flags_t flags2, flags3; 145 146 ef = i == 0 ? 0 : mpfr_get_exp (f1); 147 for (emin = ef - 2; emin <= ef + 2; emin++) 148 for (emax = emin; emax <= ef + 2; emax++) 149 { 150 inex3 = mpfr_set (f3, f1, rnd); 151 MPFR_ASSERTN (inex3 == 0); 152 set_emin (emin); 153 set_emax (emax); 154 mpfr_clear_flags (); 155 inex2 = mpfr_set_z_2exp (f2, z, e, rnd); 156 flags2 = __gmpfr_flags; 157 mpfr_clear_flags (); 158 inex3 = mpfr_check_range (f3, 0, rnd); 159 flags3 = __gmpfr_flags; 160 if (!(mpfr_equal_p (f2, f3) && 161 SAME_SIGN (inex2, inex3) && 162 flags2 == flags3)) 163 { 164 printf ("Error in mpfr_set_z_2exp for i=%ld e=%" 165 MPFR_EXP_FSPEC "d rnd_mode=%d\nand emin=%" 166 MPFR_EXP_FSPEC "d emax=%" MPFR_EXP_FSPEC 167 "d\n", i, (mpfr_eexp_t) e, rnd, 168 (mpfr_eexp_t) emin, (mpfr_eexp_t) emax); 169 printf ("expected "); mpfr_dump (f3); 170 printf ("with inex = %d and flags =", inex3); 171 flags_out (flags3); 172 printf ("got "); mpfr_dump (f2); 173 printf ("with inex = %d and flags =", inex2); 174 flags_out (flags2); 175 exit (1); 176 } 177 } 178 set_emin (old_emin); 179 set_emax (old_emax); 180 } 181 182 mpfr_clears (f1, f2, f3, (mpfr_ptr) 0); 183 mpz_clear (z); 184 } 185 186 static void 187 check_huge (void) 188 { 189 if (getenv ("MPFR_CHECK_LARGEMEM") != NULL) 190 { 191 mpfr_t x; 192 mpz_t z; 193 long e; 194 195 /* Increase tests_memory_limit to the maximum in order to avoid 196 an obvious failure due to insufficient memory. */ 197 tests_memory_limit = (size_t) -1; /* no memory limit */ 198 199 mpfr_init2 (x, 32); 200 201 /* In r14140, with a 32-bit ABI (GCC's -m32): 202 - With UBsan (-fsanitize=undefined -fno-sanitize-recover), 203 this fails with: 204 set_z_2exp.c:71:26: runtime error: signed integer overflow: 205 67108864 * 32 cannot be represented in type 'long int' 206 - With -D_MPFR_EXP_FORMAT=4, this fails with: 207 Expected 0.10001000000000000000000000000000E5 208 Got 0 209 */ 210 mpz_init_set_ui (z, 17); 211 e = 0x7ffffff0; 212 mpz_mul_2exp (z, z, e); 213 mpz_add_ui (z, z, 1); 214 mpfr_set_z_2exp (x, z, -e, MPFR_RNDN); 215 if (mpfr_cmp_ui0 (x, 17) != 0) 216 { 217 printf ("Error 1 in check_huge\n"); 218 printf ("Expected 0.10001000000000000000000000000000E5\n"); 219 printf ("Got "); 220 mpfr_dump (x); 221 exit (1); 222 } 223 mpz_clear (z); 224 225 mpz_init_set_ui (z, 17); 226 mpz_mul_2exp (z, z, 0xffffffb0); 227 mpz_add_ui (z, z, 1); 228 mpfr_set_z_2exp (x, z, -1, MPFR_RNDN); 229 if (! MPFR_IS_INF (x) || MPFR_IS_NEG (x)) 230 { 231 printf ("Error 2 in check_huge\n"); 232 printf ("Expected @Inf@\n"); 233 printf ("Got "); 234 mpfr_dump (x); 235 exit (1); 236 } 237 mpz_clear (z); 238 239 mpfr_clear (x); 240 } 241 } 242 243 int 244 main (int argc, char *argv[]) 245 { 246 long j; 247 248 tests_start_mpfr (); 249 250 check (0, MPFR_RNDN, 0); 251 for (j = 0; j < 200000; j++) 252 check (randlimb () & LONG_MAX, RND_RAND (), j < 200); 253 check0 (); 254 255 check_huge (); 256 257 tests_end_mpfr (); 258 259 return 0; 260 } 261