1 /* Test file for mpfr_frac. 2 3 Copyright 2002-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 #define PIP 70 26 #define PFP 70 27 #define PMAX (PIP+2*PFP) 28 29 static void 30 check0 (mpfr_ptr ip, mpfr_ptr fp, mpfr_prec_t prec, mpfr_rnd_t rnd) 31 { 32 mpfr_t sum, tmp, dst, fp2; 33 int inex1, inex2; 34 35 mpfr_init2 (sum, PMAX); 36 mpfr_init2 (tmp, PMAX); 37 mpfr_init2 (dst, prec); 38 mpfr_init2 (fp2, prec); 39 40 if (MPFR_SIGN (ip) != MPFR_SIGN (fp)) 41 { 42 printf ("Internal error (1)\n"); 43 exit (1); 44 } 45 if (mpfr_add (sum, ip, fp, MPFR_RNDZ)) 46 { 47 printf ("Wrong inexact flag in mpfr_add\n"); 48 exit (1); 49 } 50 if (MPFR_SIGN (sum) != MPFR_SIGN (fp)) 51 { 52 printf ("Internal error (2)\n"); 53 exit (1); 54 } 55 56 inex1 = mpfr_frac (dst, sum, rnd); 57 inex2 = mpfr_set (fp2, fp, rnd); 58 if (inex1 != inex2) 59 { 60 printf ("Wrong inexact flag in mpfr_frac for\n"); 61 mpfr_out_str (stdout, 2, 0, sum, MPFR_RNDN); 62 printf ("\nGot %d instead of %d\n", inex1, inex2); 63 exit (1); 64 } 65 if (!mpfr_number_p (dst) || 66 MPFR_SIGN (dst) != MPFR_SIGN (fp2) || 67 mpfr_cmp (dst, fp2)) 68 { 69 printf ("Error in mpfr_frac (y, x, %s) with\nx = ", 70 mpfr_print_rnd_mode (rnd)); 71 mpfr_out_str (stdout, 2, 0, sum, MPFR_RNDN); 72 printf ("\nGot "); 73 mpfr_out_str (stdout, 2, 0, dst, MPFR_RNDN); 74 printf ("\ninstead of "); 75 mpfr_out_str (stdout, 2, 0, fp2, MPFR_RNDN); 76 printf ("\n"); 77 exit (1); 78 } 79 80 if (prec == PMAX) 81 { 82 inex1 = mpfr_frac (sum, sum, rnd); 83 if (inex1) 84 { 85 printf ("Wrong inexact flag in mpfr_frac\n"); 86 exit (1); 87 } 88 if (!mpfr_number_p (sum) || 89 MPFR_SIGN (sum) != MPFR_SIGN (fp) || 90 mpfr_cmp (sum, fp)) 91 { 92 printf ("Error in mpfr_frac (x, x, %s) with\nx = ", 93 mpfr_print_rnd_mode (rnd)); 94 mpfr_add (tmp, ip, fp, MPFR_RNDZ); 95 mpfr_out_str (stdout, 2, 0, tmp, MPFR_RNDN); 96 printf ("\nGot "); 97 mpfr_out_str (stdout, 2, 0, sum, MPFR_RNDN); 98 printf ("\ninstead of "); 99 mpfr_out_str (stdout, 2, 0, fp, MPFR_RNDN); 100 printf ("\n"); 101 exit (1); 102 } 103 } 104 105 mpfr_clear (fp2); 106 mpfr_clear (dst); 107 mpfr_clear (tmp); 108 mpfr_clear (sum); 109 } 110 111 static void 112 check1 (mpfr_ptr ip, mpfr_ptr fp) 113 { 114 int rnd; 115 116 RND_LOOP (rnd) 117 { 118 check0 (ip, fp, PMAX, (mpfr_rnd_t) rnd); 119 check0 (ip, fp, 70, (mpfr_rnd_t) rnd); 120 mpfr_neg (fp, fp, MPFR_RNDN); 121 mpfr_neg (ip, ip, MPFR_RNDN); 122 check0 (ip, fp, PMAX, (mpfr_rnd_t) rnd); 123 check0 (ip, fp, 70, (mpfr_rnd_t) rnd); 124 mpfr_neg (fp, fp, MPFR_RNDN); 125 mpfr_neg (ip, ip, MPFR_RNDN); 126 } 127 } 128 129 static void 130 special (void) 131 { 132 mpfr_t z, t; 133 134 mpfr_init (z); 135 mpfr_init (t); 136 137 mpfr_set_nan (z); 138 mpfr_frac (t, z, MPFR_RNDN); 139 if (!mpfr_nan_p (t)) 140 { 141 printf ("Error for frac(NaN)\n"); 142 exit (1); 143 } 144 145 mpfr_set_prec (z, 6); 146 mpfr_set_prec (t, 3); 147 148 mpfr_set_str_binary (z, "0.101101E3"); 149 mpfr_frac (t, z, MPFR_RNDN); 150 mpfr_set_str_binary (z, "0.101"); 151 if (mpfr_cmp (t, z)) 152 { 153 printf ("Error in frac(0.101101E3)\n"); 154 exit (1); 155 } 156 157 mpfr_set_prec (z, 34); 158 mpfr_set_prec (t, 26); 159 mpfr_set_str_binary (z, "0.101101010000010011110011001101E9"); 160 mpfr_frac (t, z, MPFR_RNDN); 161 mpfr_set_str_binary (z, "0.000010011110011001101"); 162 if (mpfr_cmp (t, z)) 163 { 164 printf ("Error in frac(0.101101010000010011110011001101E9)\n"); 165 exit (1); 166 } 167 168 mpfr_clear (z); 169 mpfr_clear (t); 170 } 171 172 static void 173 bug20090918 (void) 174 { 175 mpfr_t x, y, z; 176 mp_limb_t y0; 177 int inexy, inexz; 178 int r, i; 179 const char *s[] = { "61680.352935791015625", "61680.999999" }; 180 mpfr_exp_t emin; 181 182 emin = mpfr_get_emin (); 183 mpfr_init2 (x, 32); 184 mpfr_init2 (y, 13); 185 186 for (i = 0; i <= 9; i++) 187 { 188 mpfr_set_str (x, s[i & 1], 10, MPFR_RNDZ); 189 190 RND_LOOP(r) 191 { 192 set_emin ((i >> 1) - 3); 193 inexy = mpfr_frac (y, x, (mpfr_rnd_t) r); 194 set_emin (emin); 195 y0 = MPFR_MANT(y)[0]; 196 while (y0 != 0 && (y0 >> 1) << 1 == y0) 197 y0 >>= 1; 198 if (y0 > 0x2000) 199 { 200 printf ("Error in bug20090918 (significand has more than" 201 " 13 bits), i = %d, %s.\n", i, 202 mpfr_print_rnd_mode ((mpfr_rnd_t) r)); 203 exit (1); 204 } 205 mpfr_init2 (z, 32); 206 inexz = mpfr_frac (z, x, MPFR_RNDN); 207 MPFR_ASSERTN (inexz == 0); /* exact */ 208 inexz = mpfr_prec_round (z, 13, (mpfr_rnd_t) r); 209 set_emin ((i >> 1) - 3); 210 inexz = mpfr_check_range (z, inexz, (mpfr_rnd_t) r); 211 set_emin (emin); 212 if (mpfr_cmp0 (y, z) != 0) 213 { 214 printf ("Error in bug20090918, i = %d, %s.\n", i, 215 mpfr_print_rnd_mode ((mpfr_rnd_t) r)); 216 printf ("Expected "); 217 mpfr_dump (z); 218 printf ("Got "); 219 mpfr_dump (y); 220 exit (1); 221 } 222 if (! SAME_SIGN (inexy, inexz)) 223 { 224 printf ("Incorrect ternary value in bug20090918, i = %d, %s.\n", 225 i, mpfr_print_rnd_mode ((mpfr_rnd_t) r)); 226 printf ("Expected %d, got %d.\n", inexz, inexy); 227 exit (1); 228 } 229 mpfr_clear (z); 230 } 231 } 232 233 mpfr_clear (x); 234 mpfr_clear (y); 235 } 236 237 #define TEST_FUNCTION mpfr_frac 238 #include "tgeneric.c" 239 240 int 241 main (void) 242 { 243 mpfr_t ip, fp; 244 int ni, nf1, nf2; 245 246 tests_start_mpfr (); 247 248 special (); 249 250 mpfr_init2 (ip, PIP); 251 mpfr_init2 (fp, PFP); 252 253 for (ni = -1; ni < PIP; ni++) 254 { 255 if (ni <= 0) 256 { /* ni + 1 */ 257 mpfr_set_si (ip, ni, MPFR_RNDN); 258 mpfr_add_ui (ip, ip, 1, MPFR_RNDN); 259 } 260 else 261 { /* 2^ni + 1 */ 262 mpfr_set_ui (ip, 1, MPFR_RNDN); 263 mpfr_mul_2ui (ip, ip, ni, MPFR_RNDN); 264 mpfr_add_ui (ip, ip, 1, MPFR_RNDN); 265 } 266 267 mpfr_set_ui (fp, 0, MPFR_RNDN); 268 check1 (ip, fp); 269 270 for (nf1 = 1; nf1 < PFP; nf1++) 271 { 272 mpfr_set_ui (fp, 1, MPFR_RNDN); 273 mpfr_div_2ui (fp, fp, nf1, MPFR_RNDN); 274 check1 (ip, fp); 275 nf2 = 1 + (randlimb () % (PFP - 1)); 276 mpfr_set_ui (fp, 1, MPFR_RNDN); 277 mpfr_div_2ui (fp, fp, nf2, MPFR_RNDN); 278 mpfr_add_ui (fp, fp, 1, MPFR_RNDN); 279 mpfr_div_2ui (fp, fp, nf1, MPFR_RNDN); 280 check1 (ip, fp); 281 } 282 } 283 284 mpfr_set_ui (ip, 1, MPFR_RNDN); 285 mpfr_div_ui (ip, ip, 0, MPFR_RNDN); 286 mpfr_set_ui (fp, 0, MPFR_RNDN); 287 check1 (ip, fp); /* test infinities */ 288 289 mpfr_clear (ip); 290 mpfr_clear (fp); 291 292 bug20090918 (); 293 294 test_generic (MPFR_PREC_MIN, 1000, 10); 295 296 tests_end_mpfr (); 297 return 0; 298 } 299