1 /* Test file for mpfr_frexp. 2 3 Copyright 2011-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_special (void) 27 { 28 mpfr_t x, y; 29 int inex; 30 mpfr_exp_t exp; 31 32 mpfr_init2 (x, 53); 33 mpfr_init2 (y, 53); 34 35 mpfr_set_nan (x); 36 inex = mpfr_frexp (&exp, y, x, MPFR_RNDN); 37 if (mpfr_nan_p (y) == 0 || inex != 0) 38 { 39 printf ("Error for mpfr_frexp(NaN)\n"); 40 exit (1); 41 } 42 43 mpfr_set_inf (x, 1); 44 inex = mpfr_frexp (&exp, y, x, MPFR_RNDN); 45 if (mpfr_inf_p (y) == 0 || mpfr_sgn (y) <= 0 || inex != 0) 46 { 47 printf ("Error for mpfr_frexp(+Inf)\n"); 48 exit (1); 49 } 50 51 mpfr_set_inf (x, -1); 52 inex = mpfr_frexp (&exp, y, x, MPFR_RNDN); 53 if (mpfr_inf_p (y) == 0 || mpfr_sgn (y) >= 0 || inex != 0) 54 { 55 printf ("Error for mpfr_frexp(-Inf)\n"); 56 exit (1); 57 } 58 59 mpfr_set_zero (x, 1); 60 inex = mpfr_frexp (&exp, y, x, MPFR_RNDN); 61 if (mpfr_zero_p (y) == 0 || mpfr_signbit (y) != 0 || inex != 0 || exp != 0) 62 { 63 printf ("Error for mpfr_frexp(+0)\n"); 64 exit (1); 65 } 66 67 mpfr_set_zero (x, -1); 68 inex = mpfr_frexp (&exp, y, x, MPFR_RNDN); 69 if (mpfr_zero_p (y) == 0 || mpfr_signbit (y) == 0 || inex != 0 || exp != 0) 70 { 71 printf ("Error for mpfr_frexp(-0)\n"); 72 exit (1); 73 } 74 75 mpfr_set_ui (x, 17, MPFR_RNDN); 76 inex = mpfr_frexp (&exp, y, x, MPFR_RNDN); 77 /* 17 = 17/32*2^5 */ 78 if (mpfr_cmp_ui_2exp (y, 17, -5) != 0 || inex != 0 || exp != 5) 79 { 80 printf ("Error for mpfr_frexp(17)\n"); 81 exit (1); 82 } 83 84 mpfr_set_si (x, -17, MPFR_RNDN); 85 inex = mpfr_frexp (&exp, y, x, MPFR_RNDN); 86 if (mpfr_cmp_si_2exp (y, -17, -5) != 0 || inex != 0 || exp != 5) 87 { 88 printf ("Error for mpfr_frexp(-17)\n"); 89 exit (1); 90 } 91 92 /* now reduce the precision of y */ 93 mpfr_set_prec (y, 4); 94 mpfr_set_ui (x, 17, MPFR_RNDN); 95 inex = mpfr_frexp (&exp, y, x, MPFR_RNDN); 96 /* 17 -> 16/32*2^5 */ 97 if (mpfr_cmp_ui_2exp (y, 16, -5) != 0 || inex >= 0 || exp != 5) 98 { 99 printf ("Error for mpfr_frexp(17) with prec=4, RNDN\n"); 100 exit (1); 101 } 102 103 mpfr_set_ui (x, 17, MPFR_RNDN); 104 inex = mpfr_frexp (&exp, y, x, MPFR_RNDZ); 105 if (mpfr_cmp_ui_2exp (y, 16, -5) != 0 || inex >= 0 || exp != 5) 106 { 107 printf ("Error for mpfr_frexp(17) with prec=4, RNDZ\n"); 108 exit (1); 109 } 110 111 mpfr_set_ui (x, 17, MPFR_RNDN); 112 inex = mpfr_frexp (&exp, y, x, MPFR_RNDD); 113 if (mpfr_cmp_ui_2exp (y, 16, -5) != 0 || inex >= 0 || exp != 5) 114 { 115 printf ("Error for mpfr_frexp(17) with prec=4, RNDD\n"); 116 exit (1); 117 } 118 119 mpfr_set_ui (x, 17, MPFR_RNDN); 120 inex = mpfr_frexp (&exp, y, x, MPFR_RNDU); 121 if (mpfr_cmp_ui_2exp (y, 18, -5) != 0 || inex <= 0 || exp != 5) 122 { 123 printf ("Error for mpfr_frexp(17) with prec=4, RNDU\n"); 124 exit (1); 125 } 126 127 mpfr_clear (y); 128 mpfr_clear (x); 129 } 130 131 static void check1 (void) 132 { 133 mpfr_exp_t emin, emax, e; 134 mpfr_t x, y1, y2; 135 int r, neg, red; 136 137 emin = mpfr_get_emin (); 138 emax = mpfr_get_emax (); 139 set_emin (MPFR_EMIN_MIN); 140 set_emax (MPFR_EMAX_MAX); 141 142 mpfr_init2 (x, 7); 143 mpfr_inits2 (4, y1, y2, (mpfr_ptr) 0); 144 145 mpfr_set_ui_2exp (x, 1, -2, MPFR_RNDN); 146 while (mpfr_regular_p (x)) 147 { 148 /* Test the exponents up to 3 and with the maximum exponent 149 (to check potential intermediate overflow). */ 150 if (MPFR_GET_EXP (x) == 4) 151 mpfr_set_exp (x, MPFR_EMAX_MAX); 152 e = MPFR_GET_EXP (x); 153 for (neg = 0; neg < 2; neg++) 154 { 155 RND_LOOP (r) 156 { 157 int inex1, inex2; 158 mpfr_exp_t e1, e2; 159 mpfr_flags_t flags1, flags2; 160 161 for (red = 0; red < 2; red++) 162 { 163 if (red) 164 { 165 /* e1: exponent of the rounded value of x. */ 166 MPFR_ASSERTN (e1 == e || e1 == e + 1); 167 set_emin (e); 168 set_emax (e); 169 mpfr_clear_flags (); 170 inex1 = e1 < 0 ? 171 mpfr_mul_2ui (y1, x, -e1, (mpfr_rnd_t) r) : 172 mpfr_div_2ui (y1, x, e1, (mpfr_rnd_t) r); 173 flags1 = __gmpfr_flags; 174 } 175 else 176 { 177 inex1 = mpfr_set (y1, x, (mpfr_rnd_t) r); 178 e1 = MPFR_IS_INF (y1) ? e + 1 : MPFR_GET_EXP (y1); 179 flags1 = inex1 != 0 ? MPFR_FLAGS_INEXACT : 0; 180 } 181 mpfr_clear_flags (); 182 inex2 = mpfr_frexp (&e2, y2, x, (mpfr_rnd_t) r); 183 flags2 = __gmpfr_flags; 184 set_emin (MPFR_EMIN_MIN); 185 set_emax (MPFR_EMAX_MAX); 186 if ((!red || e == 0) && 187 (! mpfr_regular_p (y2) || MPFR_GET_EXP (y2) != 0)) 188 { 189 printf ("Error in check1 for %s, red = %d, x = ", 190 mpfr_print_rnd_mode ((mpfr_rnd_t) r), red); 191 mpfr_dump (x); 192 printf ("Expected 1/2 <= |y| < 1, got y = "); 193 mpfr_dump (y2); 194 exit (1); 195 } 196 if (!red) 197 { 198 if (e2 > 0) 199 mpfr_mul_2ui (y2, y2, e2, MPFR_RNDN); 200 else if (e2 < 0) 201 mpfr_div_2ui (y2, y2, -e2, MPFR_RNDN); 202 } 203 if (! (SAME_SIGN (inex1, inex2) && 204 mpfr_equal_p (y1, y2) && 205 flags1 == flags2)) 206 { 207 printf ("Error in check1 for %s, red = %d, x = ", 208 mpfr_print_rnd_mode ((mpfr_rnd_t) r), red); 209 mpfr_dump (x); 210 printf ("Expected y1 = "); 211 mpfr_dump (y1); 212 printf ("Got y2 = "); 213 mpfr_dump (y2); 214 printf ("Expected inex ~= %d, got %d\n", inex1, inex2); 215 printf ("Expected flags:"); 216 flags_out (flags1); 217 printf ("Got flags: "); 218 flags_out (flags2); 219 exit (1); 220 } 221 } 222 } 223 mpfr_neg (x, x, MPFR_RNDN); 224 } 225 mpfr_nextabove (x); 226 } 227 228 mpfr_clears (x, y1, y2, (mpfr_ptr) 0); 229 set_emin (emin); 230 set_emax (emax); 231 } 232 233 int 234 main (int argc, char *argv[]) 235 { 236 tests_start_mpfr (); 237 238 check_special (); 239 check1 (); 240 241 tests_end_mpfr (); 242 return 0; 243 } 244