/* exercises corner cases with inputs around 1 or 2 */ static void bad_case2 (void) { mpfr_t r, u; mpfr_prec_t pr, pu; int rnd; for (pr = MPFR_PREC_MIN; pr <= 192; pr++) for (pu = MPFR_PREC_MIN; pu <= 192; pu++) { mpfr_init2 (r, pr); mpfr_init2 (u, pu); mpfr_set_ui (u, 1, MPFR_RNDN); for (rnd = 0; rnd < MPFR_RND_MAX; rnd++) mpfr_rec_sqrt (r, u, (mpfr_rnd_t) rnd); mpfr_nextbelow (u); for (rnd = 0; rnd < MPFR_RND_MAX; rnd++) mpfr_rec_sqrt (r, u, (mpfr_rnd_t) rnd); mpfr_nextbelow (u); for (rnd = 0; rnd < MPFR_RND_MAX; rnd++) mpfr_rec_sqrt (r, u, (mpfr_rnd_t) rnd); mpfr_set_ui (u, 1, MPFR_RNDN); mpfr_nextabove (u); for (rnd = 0; rnd < MPFR_RND_MAX; rnd++) mpfr_rec_sqrt (r, u, (mpfr_rnd_t) rnd); mpfr_nextabove (u); for (rnd = 0; rnd < MPFR_RND_MAX; rnd++) mpfr_rec_sqrt (r, u, (mpfr_rnd_t) rnd); mpfr_set_ui (u, 2, MPFR_RNDN); for (rnd = 0; rnd < MPFR_RND_MAX; rnd++) mpfr_rec_sqrt (r, u, (mpfr_rnd_t) rnd); mpfr_nextbelow (u); for (rnd = 0; rnd < MPFR_RND_MAX; rnd++) mpfr_rec_sqrt (r, u, (mpfr_rnd_t) rnd); mpfr_nextbelow (u); for (rnd = 0; rnd < MPFR_RND_MAX; rnd++) mpfr_rec_sqrt (r, u, (mpfr_rnd_t) rnd); mpfr_set_ui (u, 2, MPFR_RNDN); mpfr_nextabove (u); for (rnd = 0; rnd < MPFR_RND_MAX; rnd++) mpfr_rec_sqrt (r, u, (mpfr_rnd_t) rnd); mpfr_nextabove (u); for (rnd = 0; rnd < MPFR_RND_MAX; rnd++) mpfr_rec_sqrt (r, u, (mpfr_rnd_t) rnd); mpfr_clear (r); mpfr_clear (u); } }
SeedValue seed_mpfr_rec_sqrt (SeedContext ctx, SeedObject function, SeedObject this_object, gsize argument_count, const SeedValue args[], SeedException *exception) { mpfr_rnd_t rnd; mpfr_ptr rop, op; gint ret; CHECK_ARG_COUNT("mpfr.rec_sqrt", 2); rop = seed_object_get_private(this_object); rnd = seed_value_to_mpfr_rnd_t(ctx, args[1], exception); if ( seed_value_is_object_of_class(ctx, args[0], mpfr_class) ) { op = seed_object_get_private(args[0]); } else { TYPE_EXCEPTION("mpfr.rec_sqrt", "mpfr_t"); } ret = mpfr_rec_sqrt(rop, op, rnd); return seed_value_from_int(ctx, ret, exception); }
static void special (void) { mpfr_t x, y; int inex; mpfr_init (x); mpfr_init (y); /* rec_sqrt(NaN) = NaN */ mpfr_set_nan (x); inex = mpfr_rec_sqrt (x, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_nan_p (x) && inex == 0); /* rec_sqrt(+Inf) = +0 */ mpfr_set_inf (x, 1); inex = mpfr_rec_sqrt (x, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_zero_p (x) && MPFR_IS_POS(x) && inex == 0); /* rec_sqrt(-Inf) = NaN */ mpfr_set_inf (x, -1); inex = mpfr_rec_sqrt (x, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_nan_p (x) && inex == 0); /* rec_sqrt(+0) = +Inf */ mpfr_set_ui (x, 0, MPFR_RNDN); inex = mpfr_rec_sqrt (x, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_inf_p (x) && MPFR_IS_POS(x) && inex == 0); /* rec_sqrt(-0) = +Inf */ mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_neg (x, x, MPFR_RNDN); inex = mpfr_rec_sqrt (x, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_inf_p (x) && MPFR_IS_POS(x) && inex == 0); /* rec_sqrt(-1) = NaN */ mpfr_set_si (x, -1, MPFR_RNDN); inex = mpfr_rec_sqrt (x, x, MPFR_RNDN); MPFR_ASSERTN(mpfr_nan_p (x) && inex == 0); /* rec_sqrt(1) = 1 */ mpfr_set_ui (x, 1, MPFR_RNDN); inex = mpfr_rec_sqrt (x, x, MPFR_RNDN); MPFR_ASSERTN((mpfr_cmp_ui (x, 1) == 0) && (inex == 0)); mpfr_set_prec (x, 23); mpfr_set_prec (y, 33); mpfr_set_str_binary (x, "1.0001110110101001010100e-1"); inex = mpfr_rec_sqrt (y, x, MPFR_RNDU); mpfr_set_prec (x, 33); mpfr_set_str_binary (x, "1.01010110101110100100100101011"); MPFR_ASSERTN (inex > 0 && mpfr_cmp (x, y) == 0); mpfr_clear (x); mpfr_clear (y); }
/* Worst case incorrectly rounded in r5573, found with the bad_cases test */ static void bad_case1 (void) { mpfr_t x, y, z; mpfr_init2 (x, 72); mpfr_inits2 (6, y, z, (mpfr_ptr) 0); mpfr_set_str (x, "1.08310518720928b30e@-120", 16, MPFR_RNDN); mpfr_set_str (z, "f.8@59", 16, MPFR_RNDN); /* z = rec_sqrt(x) rounded on 6 bits toward 0, the exact value being ~= f.bffffffffffffffffa11@59. */ mpfr_rec_sqrt (y, x, MPFR_RNDZ); if (mpfr_cmp0 (y, z) != 0) { printf ("Error in bad_case1\nexpected "); mpfr_out_str (stdout, 16, 0, z, MPFR_RNDN); printf ("\ngot "); mpfr_out_str (stdout, 16, 0, y, MPFR_RNDN); printf ("\n"); exit (1); } mpfr_clears (x, y, z, (mpfr_ptr) 0); }
int main() { long iter; flint_rand_t state; printf("rsqrt...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 100000; iter++) { long bits, res; fmpr_t x, z, w; mpfr_t X, Z; bits = 2 + n_randint(state, 200); fmpr_init(x); fmpr_init(z); fmpr_init(w); mpfr_init2(X, 2 * (bits + 100)); mpfr_init2(Z, bits); fmpr_randtest_special(x, state, bits + n_randint(state, 100), 10); fmpr_randtest_special(z, state, bits + n_randint(state, 100), 10); fmpr_get_mpfr(X, x, MPFR_RNDN); switch (n_randint(state, 4)) { case 0: mpfr_rec_sqrt(Z, X, MPFR_RNDZ); res = fmpr_rsqrt(z, x, bits, FMPR_RND_DOWN); break; case 1: mpfr_rec_sqrt(Z, X, MPFR_RNDA); res = fmpr_rsqrt(z, x, bits, FMPR_RND_UP); break; case 2: mpfr_rec_sqrt(Z, X, MPFR_RNDD); res = fmpr_rsqrt(z, x, bits, FMPR_RND_FLOOR); break; default: mpfr_rec_sqrt(Z, X, MPFR_RNDU); res = fmpr_rsqrt(z, x, bits, FMPR_RND_CEIL); break; } fmpr_set_mpfr(w, Z); if (!fmpr_equal(z, w) || !fmpr_check_ulp(z, res, bits)) { printf("FAIL\n\n"); printf("bits = %ld\n", bits); printf("x = "); fmpr_print(x); printf("\n\n"); printf("z = "); fmpr_print(z); printf("\n\n"); printf("w = "); fmpr_print(w); printf("\n\n"); abort(); } fmpr_clear(x); fmpr_clear(z); fmpr_clear(w); mpfr_clear(X); mpfr_clear(Z); } flint_randclear(state); flint_cleanup(); printf("PASS\n"); return EXIT_SUCCESS; }
/* Compare the result (z1,inex1) of mpfr_pow with all flags cleared with those of mpfr_pow with all flags set and of the other power functions. Arguments x and y are the input values; sx and sy are their string representations (sx may be null); rnd contains the rounding mode; s is a string containing the function that called test_others. */ static void test_others (const void *sx, const char *sy, mpfr_rnd_t rnd, mpfr_srcptr x, mpfr_srcptr y, mpfr_srcptr z1, int inex1, unsigned int flags, const char *s) { mpfr_t z2; int inex2; int spx = sx != NULL; if (!spx) sx = x; mpfr_init2 (z2, mpfr_get_prec (z1)); __gmpfr_flags = MPFR_FLAGS_ALL; inex2 = mpfr_pow (z2, x, y, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, MPFR_FLAGS_ALL, s, "mpfr_pow, flags set"); /* If y is an integer that fits in an unsigned long and is not -0, we can test mpfr_pow_ui. */ if (MPFR_IS_POS (y) && mpfr_integer_p (y) && mpfr_fits_ulong_p (y, MPFR_RNDN)) { unsigned long yy = mpfr_get_ui (y, MPFR_RNDN); mpfr_clear_flags (); inex2 = mpfr_pow_ui (z2, x, yy, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, flags, s, "mpfr_pow_ui, flags cleared"); __gmpfr_flags = MPFR_FLAGS_ALL; inex2 = mpfr_pow_ui (z2, x, yy, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, MPFR_FLAGS_ALL, s, "mpfr_pow_ui, flags set"); /* If x is an integer that fits in an unsigned long and is not -0, we can also test mpfr_ui_pow_ui. */ if (MPFR_IS_POS (x) && mpfr_integer_p (x) && mpfr_fits_ulong_p (x, MPFR_RNDN)) { unsigned long xx = mpfr_get_ui (x, MPFR_RNDN); mpfr_clear_flags (); inex2 = mpfr_ui_pow_ui (z2, xx, yy, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, flags, s, "mpfr_ui_pow_ui, flags cleared"); __gmpfr_flags = MPFR_FLAGS_ALL; inex2 = mpfr_ui_pow_ui (z2, xx, yy, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, MPFR_FLAGS_ALL, s, "mpfr_ui_pow_ui, flags set"); } } /* If y is an integer but not -0 and not huge, we can test mpfr_pow_z, and possibly mpfr_pow_si (and possibly mpfr_ui_div). */ if (MPFR_IS_ZERO (y) ? MPFR_IS_POS (y) : (mpfr_integer_p (y) && MPFR_GET_EXP (y) < 256)) { mpz_t yyy; /* If y fits in a long, we can test mpfr_pow_si. */ if (mpfr_fits_slong_p (y, MPFR_RNDN)) { long yy = mpfr_get_si (y, MPFR_RNDN); mpfr_clear_flags (); inex2 = mpfr_pow_si (z2, x, yy, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, flags, s, "mpfr_pow_si, flags cleared"); __gmpfr_flags = MPFR_FLAGS_ALL; inex2 = mpfr_pow_si (z2, x, yy, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, MPFR_FLAGS_ALL, s, "mpfr_pow_si, flags set"); /* If y = -1, we can test mpfr_ui_div. */ if (yy == -1) { mpfr_clear_flags (); inex2 = mpfr_ui_div (z2, 1, x, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, flags, s, "mpfr_ui_div, flags cleared"); __gmpfr_flags = MPFR_FLAGS_ALL; inex2 = mpfr_ui_div (z2, 1, x, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, MPFR_FLAGS_ALL, s, "mpfr_ui_div, flags set"); } /* If y = 2, we can test mpfr_sqr. */ if (yy == 2) { mpfr_clear_flags (); inex2 = mpfr_sqr (z2, x, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, flags, s, "mpfr_sqr, flags cleared"); __gmpfr_flags = MPFR_FLAGS_ALL; inex2 = mpfr_sqr (z2, x, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, MPFR_FLAGS_ALL, s, "mpfr_sqr, flags set"); } } /* Test mpfr_pow_z. */ mpz_init (yyy); mpfr_get_z (yyy, y, MPFR_RNDN); mpfr_clear_flags (); inex2 = mpfr_pow_z (z2, x, yyy, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, flags, s, "mpfr_pow_z, flags cleared"); __gmpfr_flags = MPFR_FLAGS_ALL; inex2 = mpfr_pow_z (z2, x, yyy, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, MPFR_FLAGS_ALL, s, "mpfr_pow_z, flags set"); mpz_clear (yyy); } /* If y = 0.5, we can test mpfr_sqrt, except if x is -0 or -Inf (because the rule for mpfr_pow on these special values is different). */ if (MPFR_IS_PURE_FP (y) && mpfr_cmp_str1 (y, "0.5") == 0 && ! ((MPFR_IS_ZERO (x) || MPFR_IS_INF (x)) && MPFR_IS_NEG (x))) { mpfr_clear_flags (); inex2 = mpfr_sqrt (z2, x, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, flags, s, "mpfr_sqrt, flags cleared"); __gmpfr_flags = MPFR_FLAGS_ALL; inex2 = mpfr_sqrt (z2, x, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, MPFR_FLAGS_ALL, s, "mpfr_sqrt, flags set"); } #if MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0) /* If y = -0.5, we can test mpfr_rec_sqrt, except if x = -Inf (because the rule for mpfr_pow on -Inf is different). */ if (MPFR_IS_PURE_FP (y) && mpfr_cmp_str1 (y, "-0.5") == 0 && ! (MPFR_IS_INF (x) && MPFR_IS_NEG (x))) { mpfr_clear_flags (); inex2 = mpfr_rec_sqrt (z2, x, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, flags, s, "mpfr_rec_sqrt, flags cleared"); __gmpfr_flags = MPFR_FLAGS_ALL; inex2 = mpfr_rec_sqrt (z2, x, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, MPFR_FLAGS_ALL, s, "mpfr_rec_sqrt, flags set"); } #endif /* If x is an integer that fits in an unsigned long and is not -0, we can test mpfr_ui_pow. */ if (MPFR_IS_POS (x) && mpfr_integer_p (x) && mpfr_fits_ulong_p (x, MPFR_RNDN)) { unsigned long xx = mpfr_get_ui (x, MPFR_RNDN); mpfr_clear_flags (); inex2 = mpfr_ui_pow (z2, xx, y, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, flags, s, "mpfr_ui_pow, flags cleared"); __gmpfr_flags = MPFR_FLAGS_ALL; inex2 = mpfr_ui_pow (z2, xx, y, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, MPFR_FLAGS_ALL, s, "mpfr_ui_pow, flags set"); /* If x = 2, we can test mpfr_exp2. */ if (xx == 2) { mpfr_clear_flags (); inex2 = mpfr_exp2 (z2, y, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, flags, s, "mpfr_exp2, flags cleared"); __gmpfr_flags = MPFR_FLAGS_ALL; inex2 = mpfr_exp2 (z2, y, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, MPFR_FLAGS_ALL, s, "mpfr_exp2, flags set"); } /* If x = 10, we can test mpfr_exp10. */ if (xx == 10) { mpfr_clear_flags (); inex2 = mpfr_exp10 (z2, y, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, flags, s, "mpfr_exp10, flags cleared"); __gmpfr_flags = MPFR_FLAGS_ALL; inex2 = mpfr_exp10 (z2, y, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, MPFR_FLAGS_ALL, s, "mpfr_exp10, flags set"); } } mpfr_clear (z2); }