1 1.1 mrg /* Test file for mpfr_ui_sub. 2 1.1 mrg 3 1.1.1.6 mrg Copyright 2000-2023 Free Software Foundation, Inc. 4 1.1.1.3 mrg Contributed by the AriC and Caramba projects, INRIA. 5 1.1 mrg 6 1.1 mrg This file is part of the GNU MPFR Library. 7 1.1 mrg 8 1.1 mrg The GNU MPFR Library is free software; you can redistribute it and/or modify 9 1.1 mrg it under the terms of the GNU Lesser General Public License as published by 10 1.1 mrg the Free Software Foundation; either version 3 of the License, or (at your 11 1.1 mrg option) any later version. 12 1.1 mrg 13 1.1 mrg The GNU MPFR Library is distributed in the hope that it will be useful, but 14 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15 1.1 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16 1.1 mrg License for more details. 17 1.1 mrg 18 1.1 mrg You should have received a copy of the GNU Lesser General Public License 19 1.1 mrg along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see 20 1.1.1.5 mrg https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., 21 1.1 mrg 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ 22 1.1 mrg 23 1.1 mrg #include <float.h> 24 1.1 mrg 25 1.1 mrg #include "mpfr-test.h" 26 1.1 mrg 27 1.1 mrg static void 28 1.1 mrg special (void) 29 1.1 mrg { 30 1.1 mrg mpfr_t x, y, res; 31 1.1 mrg int inexact; 32 1.1 mrg 33 1.1 mrg mpfr_init (x); 34 1.1 mrg mpfr_init (y); 35 1.1 mrg mpfr_init (res); 36 1.1 mrg 37 1.1 mrg mpfr_set_prec (x, 24); 38 1.1 mrg mpfr_set_prec (y, 24); 39 1.1 mrg mpfr_set_str_binary (y, "0.111100110001011010111"); 40 1.1 mrg inexact = mpfr_ui_sub (x, 1, y, MPFR_RNDN); 41 1.1 mrg if (inexact) 42 1.1 mrg { 43 1.1 mrg printf ("Wrong inexact flag: got %d, expected 0\n", inexact); 44 1.1 mrg exit (1); 45 1.1 mrg } 46 1.1 mrg 47 1.1 mrg mpfr_set_prec (x, 24); 48 1.1 mrg mpfr_set_prec (y, 24); 49 1.1 mrg mpfr_set_str_binary (y, "0.111100110001011010111"); 50 1.1 mrg if ((inexact = mpfr_ui_sub (x, 38181761, y, MPFR_RNDN)) >= 0) 51 1.1 mrg { 52 1.1 mrg printf ("Wrong inexact flag: got %d, expected -1\n", inexact); 53 1.1 mrg exit (1); 54 1.1 mrg } 55 1.1 mrg 56 1.1 mrg mpfr_set_prec (x, 63); 57 1.1 mrg mpfr_set_prec (y, 63); 58 1.1 mrg mpfr_set_str_binary (y, "0.111110010010100100110101101010001001100101110001000101110111111E-1"); 59 1.1 mrg if ((inexact = mpfr_ui_sub (x, 1541116494, y, MPFR_RNDN)) <= 0) 60 1.1 mrg { 61 1.1 mrg printf ("Wrong inexact flag: got %d, expected +1\n", inexact); 62 1.1 mrg exit (1); 63 1.1 mrg } 64 1.1 mrg 65 1.1 mrg mpfr_set_prec (x, 32); 66 1.1 mrg mpfr_set_prec (y, 32); 67 1.1 mrg mpfr_set_str_binary (y, "0.11011000110111010001011100011100E-1"); 68 1.1 mrg if ((inexact = mpfr_ui_sub (x, 2000375416, y, MPFR_RNDN)) >= 0) 69 1.1 mrg { 70 1.1 mrg printf ("Wrong inexact flag: got %d, expected -1\n", inexact); 71 1.1 mrg exit (1); 72 1.1 mrg } 73 1.1 mrg 74 1.1 mrg mpfr_set_prec (x, 24); 75 1.1 mrg mpfr_set_prec (y, 24); 76 1.1 mrg mpfr_set_str_binary (y, "0.110011011001010011110111E-2"); 77 1.1 mrg if ((inexact = mpfr_ui_sub (x, 927694848, y, MPFR_RNDN)) <= 0) 78 1.1 mrg { 79 1.1 mrg printf ("Wrong inexact flag: got %d, expected +1\n", inexact); 80 1.1 mrg exit (1); 81 1.1 mrg } 82 1.1 mrg 83 1.1 mrg /* bug found by Mathieu Dutour, 12 Apr 2001 */ 84 1.1 mrg mpfr_set_prec (x, 5); 85 1.1 mrg mpfr_set_prec (y, 5); 86 1.1 mrg mpfr_set_prec (res, 5); 87 1.1 mrg mpfr_set_str_binary (x, "1e-12"); 88 1.1 mrg 89 1.1 mrg mpfr_ui_sub (y, 1, x, MPFR_RNDD); 90 1.1 mrg mpfr_set_str_binary (res, "0.11111"); 91 1.1 mrg if (mpfr_cmp (y, res)) 92 1.1 mrg { 93 1.1 mrg printf ("Error in mpfr_ui_sub (y, 1, x, MPFR_RNDD) for x=2^(-12)\nexpected 1.1111e-1, got "); 94 1.1 mrg mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN); 95 1.1 mrg printf ("\n"); 96 1.1 mrg exit (1); 97 1.1 mrg } 98 1.1 mrg 99 1.1 mrg mpfr_ui_sub (y, 1, x, MPFR_RNDU); 100 1.1 mrg mpfr_set_str_binary (res, "1.0"); 101 1.1 mrg if (mpfr_cmp (y, res)) 102 1.1 mrg { 103 1.1 mrg printf ("Error in mpfr_ui_sub (y, 1, x, MPFR_RNDU) for x=2^(-12)\n" 104 1.1 mrg "expected 1.0, got "); 105 1.1 mrg mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN); 106 1.1 mrg printf ("\n"); 107 1.1 mrg exit (1); 108 1.1 mrg } 109 1.1 mrg 110 1.1 mrg mpfr_ui_sub (y, 1, x, MPFR_RNDN); 111 1.1 mrg mpfr_set_str_binary (res, "1.0"); 112 1.1 mrg if (mpfr_cmp (y, res)) 113 1.1 mrg { 114 1.1 mrg printf ("Error in mpfr_ui_sub (y, 1, x, MPFR_RNDN) for x=2^(-12)\n" 115 1.1 mrg "expected 1.0, got "); 116 1.1 mrg mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN); 117 1.1 mrg printf ("\n"); 118 1.1 mrg exit (1); 119 1.1 mrg } 120 1.1 mrg 121 1.1 mrg mpfr_set_prec (x, 10); 122 1.1 mrg mpfr_set_prec (y, 10); 123 1.1 mrg mpfr_urandomb (x, RANDS); 124 1.1 mrg mpfr_ui_sub (y, 0, x, MPFR_RNDN); 125 1.1 mrg if (MPFR_IS_ZERO(x)) 126 1.1 mrg MPFR_ASSERTN(MPFR_IS_ZERO(y)); 127 1.1 mrg else 128 1.1 mrg MPFR_ASSERTN(mpfr_cmpabs (x, y) == 0 && mpfr_sgn (x) != mpfr_sgn (y)); 129 1.1 mrg 130 1.1 mrg mpfr_set_prec (x, 73); 131 1.1 mrg mpfr_set_str_binary (x, "0.1101111010101011011011100011010000000101110001011111001011011000101111101E-99"); 132 1.1 mrg mpfr_ui_sub (x, 1, x, MPFR_RNDZ); 133 1.1 mrg mpfr_nextabove (x); 134 1.1 mrg MPFR_ASSERTN(mpfr_cmp_ui (x, 1) == 0); 135 1.1 mrg 136 1.1 mrg mpfr_clear (x); 137 1.1 mrg mpfr_clear (y); 138 1.1 mrg mpfr_clear (res); 139 1.1 mrg } 140 1.1 mrg 141 1.1 mrg /* checks that (y-x) gives the right results with 53 bits of precision */ 142 1.1 mrg static void 143 1.1 mrg check (unsigned long y, const char *xs, mpfr_rnd_t rnd_mode, const char *zs) 144 1.1 mrg { 145 1.1 mrg mpfr_t xx, zz; 146 1.1 mrg 147 1.1 mrg mpfr_inits2 (53, xx, zz, (mpfr_ptr) 0); 148 1.1 mrg mpfr_set_str1 (xx, xs); 149 1.1 mrg mpfr_ui_sub (zz, y, xx, rnd_mode); 150 1.1 mrg if (mpfr_cmp_str1 (zz, zs) ) 151 1.1 mrg { 152 1.1 mrg printf ("expected difference is %s, got\n",zs); 153 1.1 mrg mpfr_out_str(stdout, 10, 0, zz, MPFR_RNDN); 154 1.1 mrg printf ("mpfr_ui_sub failed for y=%lu x=%s with rnd_mode=%s\n", 155 1.1 mrg y, xs, mpfr_print_rnd_mode (rnd_mode)); 156 1.1 mrg exit (1); 157 1.1 mrg } 158 1.1 mrg mpfr_clears (xx, zz, (mpfr_ptr) 0); 159 1.1 mrg } 160 1.1 mrg 161 1.1 mrg /* if u = o(x-y), v = o(u-x), w = o(v+y), then x-y = u-w */ 162 1.1 mrg static void 163 1.1 mrg check_two_sum (mpfr_prec_t p) 164 1.1 mrg { 165 1.1 mrg unsigned int x; 166 1.1 mrg mpfr_t y, u, v, w; 167 1.1 mrg mpfr_rnd_t rnd; 168 1.1.1.3 mrg int inexact, cmp; 169 1.1 mrg 170 1.1 mrg mpfr_inits2 (p, y, u, v, w, (mpfr_ptr) 0); 171 1.1 mrg do 172 1.1 mrg { 173 1.1 mrg x = randlimb (); 174 1.1 mrg } 175 1.1 mrg while (x < 1); 176 1.1 mrg mpfr_urandomb (y, RANDS); 177 1.1 mrg rnd = MPFR_RNDN; 178 1.1 mrg inexact = mpfr_ui_sub (u, x, y, rnd); 179 1.1 mrg mpfr_sub_ui (v, u, x, rnd); 180 1.1 mrg mpfr_add (w, v, y, rnd); 181 1.1.1.3 mrg cmp = mpfr_cmp_ui (w, 0); 182 1.1 mrg /* as u = (x-y) + w, we should have inexact and w of same sign */ 183 1.1.1.3 mrg if (! SAME_SIGN (inexact, cmp)) 184 1.1 mrg { 185 1.1 mrg printf ("Wrong inexact flag for prec=%u, rnd=%s\n", 186 1.1 mrg (unsigned int) p, mpfr_print_rnd_mode (rnd)); 187 1.1.1.3 mrg printf ("x = %u\n", x); 188 1.1.1.3 mrg printf ("y = "); mpfr_dump (y); 189 1.1.1.3 mrg printf ("u = "); mpfr_dump (u); 190 1.1.1.3 mrg printf ("v = "); mpfr_dump (v); 191 1.1.1.3 mrg printf ("w = "); mpfr_dump (w); 192 1.1 mrg printf ("inexact = %d\n", inexact); 193 1.1 mrg exit (1); 194 1.1 mrg } 195 1.1 mrg mpfr_clears (y, u, v, w, (mpfr_ptr) 0); 196 1.1 mrg } 197 1.1 mrg 198 1.1 mrg static void 199 1.1 mrg check_nans (void) 200 1.1 mrg { 201 1.1 mrg mpfr_t x, y; 202 1.1 mrg 203 1.1 mrg mpfr_init2 (x, 123L); 204 1.1 mrg mpfr_init2 (y, 123L); 205 1.1 mrg 206 1.1 mrg /* 1 - nan == nan */ 207 1.1 mrg mpfr_set_nan (x); 208 1.1 mrg mpfr_ui_sub (y, 1L, x, MPFR_RNDN); 209 1.1 mrg MPFR_ASSERTN (mpfr_nan_p (y)); 210 1.1 mrg 211 1.1 mrg /* 1 - +inf == -inf */ 212 1.1 mrg mpfr_set_inf (x, 1); 213 1.1 mrg mpfr_ui_sub (y, 1L, x, MPFR_RNDN); 214 1.1 mrg MPFR_ASSERTN (mpfr_inf_p (y)); 215 1.1 mrg MPFR_ASSERTN (mpfr_sgn (y) < 0); 216 1.1 mrg 217 1.1 mrg /* 1 - -inf == +inf */ 218 1.1 mrg mpfr_set_inf (x, -1); 219 1.1 mrg mpfr_ui_sub (y, 1L, x, MPFR_RNDN); 220 1.1 mrg MPFR_ASSERTN (mpfr_inf_p (y)); 221 1.1 mrg MPFR_ASSERTN (mpfr_sgn (y) > 0); 222 1.1 mrg 223 1.1 mrg mpfr_clear (x); 224 1.1 mrg mpfr_clear (y); 225 1.1 mrg } 226 1.1 mrg 227 1.1 mrg /* Check mpfr_ui_sub with u = 0 (unsigned). */ 228 1.1 mrg static void check_neg (void) 229 1.1 mrg { 230 1.1 mrg mpfr_t x, yneg, ysub; 231 1.1 mrg int i, s; 232 1.1 mrg int r; 233 1.1 mrg 234 1.1 mrg mpfr_init2 (x, 64); 235 1.1 mrg mpfr_init2 (yneg, 32); 236 1.1 mrg mpfr_init2 (ysub, 32); 237 1.1 mrg 238 1.1 mrg for (i = 0; i <= 25; i++) 239 1.1 mrg { 240 1.1 mrg mpfr_sqrt_ui (x, i, MPFR_RNDN); 241 1.1 mrg for (s = 0; s <= 1; s++) 242 1.1 mrg { 243 1.1 mrg RND_LOOP (r) 244 1.1 mrg { 245 1.1 mrg int tneg, tsub; 246 1.1 mrg 247 1.1 mrg tneg = mpfr_neg (yneg, x, (mpfr_rnd_t) r); 248 1.1 mrg tsub = mpfr_ui_sub (ysub, 0, x, (mpfr_rnd_t) r); 249 1.1 mrg MPFR_ASSERTN (mpfr_equal_p (yneg, ysub)); 250 1.1 mrg MPFR_ASSERTN (!(MPFR_IS_POS (yneg) ^ MPFR_IS_POS (ysub))); 251 1.1 mrg MPFR_ASSERTN (tneg == tsub); 252 1.1 mrg } 253 1.1 mrg mpfr_neg (x, x, MPFR_RNDN); 254 1.1 mrg } 255 1.1 mrg } 256 1.1 mrg 257 1.1 mrg mpfr_clear (x); 258 1.1 mrg mpfr_clear (yneg); 259 1.1 mrg mpfr_clear (ysub); 260 1.1 mrg } 261 1.1 mrg 262 1.1.1.3 mrg static void 263 1.1.1.3 mrg check_overflow (void) 264 1.1.1.3 mrg { 265 1.1.1.3 mrg mpfr_exp_t emin, emax; 266 1.1.1.3 mrg mpfr_t x, y1, y2; 267 1.1.1.3 mrg int inex1, inex2, rnd_mode; 268 1.1.1.4 mrg mpfr_flags_t flags1, flags2; 269 1.1.1.3 mrg 270 1.1.1.3 mrg emin = mpfr_get_emin (); 271 1.1.1.3 mrg emax = mpfr_get_emax (); 272 1.1.1.3 mrg set_emin (MPFR_EMIN_MIN); 273 1.1.1.3 mrg set_emax (MPFR_EMAX_MAX); 274 1.1.1.3 mrg 275 1.1.1.3 mrg mpfr_inits2 (32, x, y1, y2, (mpfr_ptr) 0); 276 1.1.1.3 mrg mpfr_setmax (x, MPFR_EMAX_MAX); 277 1.1.1.3 mrg mpfr_neg (x, x, MPFR_RNDN); 278 1.1.1.4 mrg RND_LOOP_NO_RNDF (rnd_mode) 279 1.1.1.4 mrg { 280 1.1.1.4 mrg if (rnd_mode == MPFR_RNDU || rnd_mode == MPFR_RNDA) 281 1.1.1.4 mrg { 282 1.1.1.4 mrg inex1 = mpfr_overflow (y1, (mpfr_rnd_t) rnd_mode, 1); 283 1.1.1.4 mrg flags1 = MPFR_FLAGS_OVERFLOW | MPFR_FLAGS_INEXACT; 284 1.1.1.4 mrg } 285 1.1.1.4 mrg else 286 1.1.1.4 mrg { 287 1.1.1.4 mrg mpfr_neg (y1, x, MPFR_RNDN); 288 1.1.1.4 mrg inex1 = -1; 289 1.1.1.4 mrg flags1 = MPFR_FLAGS_INEXACT; 290 1.1.1.4 mrg } 291 1.1.1.4 mrg mpfr_clear_flags (); 292 1.1.1.4 mrg inex2 = mpfr_ui_sub (y2, 1, x, (mpfr_rnd_t) rnd_mode); 293 1.1.1.4 mrg flags2 = __gmpfr_flags; 294 1.1.1.4 mrg if (!(mpfr_equal_p (y1, y2) && 295 1.1.1.4 mrg SAME_SIGN (inex1, inex2) && 296 1.1.1.4 mrg flags1 == flags2)) 297 1.1.1.4 mrg { 298 1.1.1.4 mrg printf ("Error in check_overflow for %s\n", 299 1.1.1.4 mrg mpfr_print_rnd_mode ((mpfr_rnd_t) rnd_mode)); 300 1.1.1.4 mrg printf ("Expected "); 301 1.1.1.4 mrg mpfr_dump (y1); 302 1.1.1.4 mrg printf (" with inex = %d, flags =", inex1); 303 1.1.1.4 mrg flags_out (flags1); 304 1.1.1.4 mrg printf ("Got "); 305 1.1.1.4 mrg mpfr_dump (y2); 306 1.1.1.4 mrg printf (" with inex = %d, flags =", inex2); 307 1.1.1.4 mrg flags_out (flags2); 308 1.1.1.4 mrg exit (1); 309 1.1.1.4 mrg } 310 1.1.1.4 mrg } 311 1.1.1.3 mrg mpfr_clears (x, y1, y2, (mpfr_ptr) 0); 312 1.1.1.3 mrg 313 1.1.1.3 mrg set_emin (emin); 314 1.1.1.3 mrg set_emax (emax); 315 1.1.1.3 mrg } 316 1.1.1.3 mrg 317 1.1.1.3 mrg #define TEST_FUNCTION mpfr_ui_sub 318 1.1.1.3 mrg #define ULONG_ARG1 319 1.1.1.3 mrg #include "tgeneric.c" 320 1.1.1.3 mrg 321 1.1 mrg int 322 1.1 mrg main (int argc, char *argv[]) 323 1.1 mrg { 324 1.1 mrg mpfr_prec_t p; 325 1.1 mrg unsigned k; 326 1.1 mrg 327 1.1 mrg tests_start_mpfr (); 328 1.1 mrg 329 1.1 mrg check_nans (); 330 1.1 mrg 331 1.1 mrg special (); 332 1.1 mrg for (p=2; p<100; p++) 333 1.1 mrg for (k=0; k<100; k++) 334 1.1 mrg check_two_sum (p); 335 1.1 mrg 336 1.1 mrg check(1196426492, "1.4218093058435347e-3", MPFR_RNDN, 337 1.1 mrg "1.1964264919985781e9"); 338 1.1 mrg check(1092583421, "-1.0880649218158844e9", MPFR_RNDN, 339 1.1 mrg "2.1806483428158845901e9"); 340 1.1 mrg check(948002822, "1.22191250737771397120e+20", MPFR_RNDN, 341 1.1 mrg "-1.2219125073682338611e20"); 342 1.1 mrg check(832100416, "4.68311314939691330000e-215", MPFR_RNDD, 343 1.1 mrg "8.3210041599999988079e8"); 344 1.1 mrg check(1976245324, "1.25296395864546893357e+232", MPFR_RNDZ, 345 1.1 mrg "-1.2529639586454686577e232"); 346 1.1 mrg check(2128997392, "-1.08496826129284207724e+187", MPFR_RNDU, 347 1.1 mrg "1.0849682612928422704e187"); 348 1.1 mrg check(293607738, "-1.9967571564050541e-5", MPFR_RNDU, 349 1.1 mrg "2.9360773800002003e8"); 350 1.1 mrg check(354270183, "2.9469161763489528e3", MPFR_RNDN, 351 1.1 mrg "3.5426723608382362e8"); 352 1.1.1.3 mrg check_overflow (); 353 1.1 mrg 354 1.1 mrg check_neg (); 355 1.1 mrg 356 1.1.1.4 mrg test_generic (MPFR_PREC_MIN, 1000, 100); 357 1.1.1.3 mrg 358 1.1 mrg tests_end_mpfr (); 359 1.1 mrg return 0; 360 1.1 mrg } 361