1 /* Test file for mpz_set_fr / mpfr_get_z / mpfr_get_z_2exp. 2 3 Copyright 2004, 2006-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 static void 26 check_diff (void) 27 { 28 int inex; 29 mpfr_t x; 30 mpz_t z; 31 mpfr_exp_t emin; 32 33 mpz_init (z); 34 mpfr_init2 (x, 2); 35 36 mpfr_set_ui (x, 2047, MPFR_RNDU); 37 mpz_set_fr (z, x, MPFR_RNDN); 38 if (mpz_cmp_ui (z, 2048) != 0) 39 { 40 printf ("get_z RU 2048 failed\n"); 41 exit (1); 42 } 43 44 mpfr_set_prec (x, 6); 45 mpfr_set_str (x, "17.5", 10, MPFR_RNDN); 46 inex = mpfr_get_z (z, x, MPFR_RNDN); 47 if (inex <= 0 || mpz_cmp_ui (z, 18) != 0) 48 { 49 printf ("get_z RN 17.5 failed\n"); 50 exit (1); 51 } 52 53 /* save default emin */ 54 emin = mpfr_get_emin ();; 55 56 set_emin (17); 57 mpfr_set_ui (x, 0, MPFR_RNDN); 58 inex = mpfr_get_z (z, x, MPFR_RNDN); 59 if (inex != 0 || mpz_cmp_ui (z, 0) != 0) 60 { 61 printf ("get_z 0 failed\n"); 62 exit (1); 63 } 64 65 /* restore default emin */ 66 set_emin (emin); 67 68 mpfr_clear (x); 69 mpz_clear (z); 70 } 71 72 static void 73 check_one (mpz_ptr z) 74 { 75 mpfr_exp_t emin, emax; 76 int inex; 77 int sh, neg; 78 mpfr_t f; 79 mpz_t got, ex, t; 80 81 emin = mpfr_get_emin (); 82 emax = mpfr_get_emax (); 83 84 mpfr_init2 (f, MAX (mpz_sizeinbase (z, 2), MPFR_PREC_MIN)); 85 mpz_init (got); 86 mpz_init (ex); 87 mpz_init (t); 88 89 for (sh = -2*GMP_NUMB_BITS ; sh < 2*GMP_NUMB_BITS ; sh++) 90 { 91 inex = mpfr_set_z (f, z, MPFR_RNDN); /* exact */ 92 MPFR_ASSERTN (inex == 0); 93 94 inex = sh < 0 ? 95 mpfr_div_2ui (f, f, -sh, MPFR_RNDN) : 96 mpfr_mul_2ui (f, f, sh, MPFR_RNDN); 97 MPFR_ASSERTN (inex == 0); 98 99 for (neg = 0; neg <= 1; neg++) 100 { 101 int rnd; 102 103 /* Test (-1)^neg * z * 2^sh */ 104 105 RND_LOOP_NO_RNDF (rnd) 106 { 107 int ex_inex, same; 108 int d, fi, e; 109 mpfr_flags_t flags[3] = { 0, MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE, 110 MPFR_FLAGS_ALL }, ex_flags, gt_flags; 111 112 if (neg) 113 mpz_neg (ex, z); 114 else 115 mpz_set (ex, z); 116 117 if (sh < 0) 118 switch (rnd) 119 { 120 case MPFR_RNDN: 121 mpz_set_si (t, neg ? -1 : 1); 122 mpz_mul_2exp (t, t, -sh - 1); 123 mpz_add (ex, ex, t); 124 /* d = mpz_divisible_2exp_p (ex, -sh); */ 125 d = mpz_scan1 (ex, 0) >= -sh; 126 mpz_tdiv_q_2exp (ex, ex, -sh); 127 if (d && mpz_tstbit (ex, 0) != 0) /* even rounding */ 128 { 129 if (neg) 130 mpz_add_ui (ex, ex, 1); 131 else 132 mpz_sub_ui (ex, ex, 1); 133 } 134 break; 135 case MPFR_RNDZ: 136 mpz_tdiv_q_2exp (ex, ex, -sh); 137 break; 138 case MPFR_RNDU: 139 mpz_cdiv_q_2exp (ex, ex, -sh); 140 break; 141 case MPFR_RNDD: 142 mpz_fdiv_q_2exp (ex, ex, -sh); 143 break; 144 case MPFR_RNDA: 145 if (neg) 146 mpz_fdiv_q_2exp (ex, ex, -sh); 147 else 148 mpz_cdiv_q_2exp (ex, ex, -sh); 149 break; 150 default: 151 MPFR_ASSERTN (0); 152 } 153 else 154 mpz_mul_2exp (ex, ex, sh); 155 156 ex_inex = - mpfr_cmp_z (f, ex); 157 ex_inex = VSIGN (ex_inex); 158 159 for (fi = 0; fi < numberof (flags); fi++) 160 for (e = 0; e < 2; e++) 161 { 162 if (e) 163 { 164 mpfr_exp_t ef; 165 166 if (MPFR_IS_ZERO (f)) 167 break; 168 ef = MPFR_GET_EXP (f); 169 set_emin (ef); 170 set_emax (ef); 171 } 172 ex_flags = __gmpfr_flags = flags[fi]; 173 if (ex_inex != 0) 174 ex_flags |= MPFR_FLAGS_INEXACT; 175 inex = mpfr_get_z (got, f, (mpfr_rnd_t) rnd); 176 inex = VSIGN (inex); 177 gt_flags = __gmpfr_flags; 178 set_emin (emin); 179 set_emax (emax); 180 same = SAME_SIGN (inex, ex_inex); 181 182 if (mpz_cmp (got, ex) != 0 || 183 !same || gt_flags != ex_flags) 184 { 185 printf ("Error in check_one for sh=%d, fi=%d, %s%s\n", 186 sh, fi, 187 mpfr_print_rnd_mode ((mpfr_rnd_t) rnd), 188 e ? ", reduced exponent range" : ""); 189 printf (" f = "); mpfr_dump (f); 190 printf ("expected "); mpz_out_str (stdout, 10, ex); 191 printf ("\n got "); mpz_out_str (stdout, 10, got); 192 printf ("\nExpected inex ~ %d, got %d (%s)\n", 193 ex_inex, inex, same ? "OK" : "wrong"); 194 printf ("Flags:\n"); 195 printf (" in"); flags_out (flags[fi]); 196 printf ("expected"); flags_out (ex_flags); 197 printf (" got"); flags_out (gt_flags); 198 exit (1); 199 } 200 } 201 } 202 203 mpfr_neg (f, f, MPFR_RNDN); 204 } 205 } 206 207 mpfr_clear (f); 208 mpz_clear (got); 209 mpz_clear (ex); 210 mpz_clear (t); 211 } 212 213 static void 214 check (void) 215 { 216 mpz_t z; 217 218 mpz_init (z); 219 220 mpz_set_ui (z, 0L); 221 check_one (z); 222 223 mpz_set_si (z, 17L); 224 check_one (z); 225 226 mpz_set_si (z, 123L); 227 check_one (z); 228 229 mpz_rrandomb (z, RANDS, 2*GMP_NUMB_BITS); 230 check_one (z); 231 232 mpz_rrandomb (z, RANDS, 5*GMP_NUMB_BITS); 233 check_one (z); 234 235 mpz_clear (z); 236 } 237 238 static void 239 special (void) 240 { 241 int inex; 242 mpfr_t x; 243 mpz_t z; 244 int i, fi; 245 int rnd; 246 mpfr_exp_t e; 247 mpfr_flags_t flags[3] = { 0, MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE, 248 MPFR_FLAGS_ALL }, ex_flags, gt_flags; 249 250 mpfr_init2 (x, 2); 251 mpz_init (z); 252 253 RND_LOOP (rnd) 254 for (i = -1; i <= 1; i++) 255 for (fi = 0; fi < numberof (flags); fi++) 256 { 257 ex_flags = flags[fi] | MPFR_FLAGS_ERANGE; 258 if (i != 0) 259 mpfr_set_nan (x); 260 else 261 mpfr_set_inf (x, i); 262 __gmpfr_flags = flags[fi]; 263 inex = mpfr_get_z (z, x, (mpfr_rnd_t) rnd); 264 gt_flags = __gmpfr_flags; 265 if (gt_flags != ex_flags || inex != 0 || mpz_cmp_ui (z, 0) != 0) 266 { 267 printf ("special() failed on mpfr_get_z" 268 " for %s, i = %d, fi = %d\n", 269 mpfr_print_rnd_mode ((mpfr_rnd_t) rnd), i, fi); 270 printf ("Expected z = 0, inex = 0,"); 271 flags_out (ex_flags); 272 printf ("Got z = "); 273 mpz_out_str (stdout, 10, z); 274 printf (", inex = %d,", inex); 275 flags_out (gt_flags); 276 exit (1); 277 } 278 __gmpfr_flags = flags[fi]; 279 e = mpfr_get_z_2exp (z, x); 280 gt_flags = __gmpfr_flags; 281 if (gt_flags != ex_flags || e != __gmpfr_emin || 282 mpz_cmp_ui (z, 0) != 0) 283 { 284 printf ("special() failed on mpfr_get_z_2exp" 285 " for %s, i = %d, fi = %d\n", 286 mpfr_print_rnd_mode ((mpfr_rnd_t) rnd), i, fi); 287 printf ("Expected z = 0, e = %" MPFR_EXP_FSPEC "d,", 288 (mpfr_eexp_t) __gmpfr_emin); 289 flags_out (ex_flags); 290 printf ("Got z = "); 291 mpz_out_str (stdout, 10, z); 292 printf (", e = %" MPFR_EXP_FSPEC "d,", (mpfr_eexp_t) e); 293 flags_out (gt_flags); 294 exit (1); 295 } 296 } 297 298 mpfr_clear (x); 299 mpz_clear (z); 300 } 301 302 int 303 main (void) 304 { 305 tests_start_mpfr (); 306 307 check (); 308 check_diff (); 309 special (); 310 311 tests_end_mpfr (); 312 return 0; 313 } 314