1/* Test file for mpfr_set_z_2exp. 2 3Copyright 1999, 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/* generate a random exponent in [__gmpfr_emin, __gmpfr_emax-1] */ 26static mpfr_exp_t 27randexp (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 54static void 55check0 (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 99static void 100check (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 186static void 187check_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 243int 244main (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