slong fmpr_rsqrt(fmpr_t y, const fmpr_t x, slong prec, fmpr_rnd_t rnd) { slong r; if (fmpr_is_special(x)) { if (fmpr_is_zero(x)) fmpr_pos_inf(y); else if (fmpr_is_pos_inf(x)) fmpr_zero(y); else fmpr_nan(y); return FMPR_RESULT_EXACT; } if (fmpr_sgn(x) < 0) { fmpr_nan(y); return FMPR_RESULT_EXACT; } /* special case: 4^n */ if (fmpz_is_one(fmpr_manref(x)) && fmpz_is_even(fmpr_expref(x))) { r = fmpr_set_round(y, x, prec, rnd); fmpz_tdiv_q_2exp(fmpr_expref(y), fmpr_expref(y), 1); fmpz_neg(fmpr_expref(y), fmpr_expref(y)); return r; } { fmpr_t t; fmpz_t e; fmpr_init(t); fmpz_init(e); fmpz_neg(e, fmpr_expref(x)); if (fmpz_is_odd(e)) fmpz_add_ui(e, e, 1); fmpr_mul_2exp_fmpz(t, x, e); CALL_MPFR_FUNC(r, mpfr_rec_sqrt, y, t, prec, rnd); fmpz_tdiv_q_2exp(e, e, 1); fmpr_mul_2exp_fmpz(y, y, e); fmpr_clear(t); fmpz_clear(e); return r; } }
void fmpr_divappr_abs_ubound(fmpr_t z, const fmpr_t x, const fmpr_t y, slong prec) { if (fmpr_is_special(x) || fmpr_is_special(y) || fmpz_is_pm1(fmpr_manref(y))) { fmpr_div(z, x, y, prec, FMPR_RND_UP); fmpr_abs(z, z); } else { fmpz_t t, u; slong xbits, ybits, tbits, ubits, shift; xbits = fmpz_bits(fmpr_manref(x)); ybits = fmpz_bits(fmpr_manref(y)); fmpz_init(t); fmpz_init(u); ubits = FLINT_MIN(ybits, prec); tbits = prec + ubits + 1; /* upper bound for |x|, shifted */ if (xbits <= tbits) { fmpz_mul_2exp(t, fmpr_manref(x), tbits - xbits); fmpz_abs(t, t); } else if (fmpz_sgn(fmpr_manref(x)) > 0) { fmpz_cdiv_q_2exp(t, fmpr_manref(x), xbits - tbits); } else { fmpz_fdiv_q_2exp(t, fmpr_manref(x), xbits - tbits); fmpz_neg(t, t); } /* lower bound for |y|, shifted */ if (ybits <= ubits) fmpz_mul_2exp(u, fmpr_manref(y), ubits - ybits); else fmpz_tdiv_q_2exp(u, fmpr_manref(y), ybits - ubits); fmpz_abs(u, u); fmpz_cdiv_q(fmpr_manref(z), t, u); shift = (ubits - ybits) - (tbits - xbits); fmpz_sub(fmpr_expref(z), fmpr_expref(x), fmpr_expref(y)); if (shift >= 0) fmpz_add_ui(fmpr_expref(z), fmpr_expref(z), shift); else fmpz_sub_ui(fmpr_expref(z), fmpr_expref(z), -shift); _fmpr_normalise(fmpr_manref(z), fmpr_expref(z), prec, FMPR_RND_UP); fmpz_clear(t); fmpz_clear(u); } }
void _fmpz_vec_scalar_tdiv_q_2exp(fmpz * vec1, const fmpz * vec2, slong len2, ulong exp) { slong i; for (i = 0; i < len2; i++) fmpz_tdiv_q_2exp(vec1 + i, vec2 + i, exp); }
void mag_expinv(mag_t res, const mag_t x) { if (mag_is_zero(x)) { mag_one(res); } else if (mag_is_inf(x)) { mag_zero(res); } else if (fmpz_sgn(MAG_EXPREF(x)) <= 0) { mag_one(res); } else if (fmpz_cmp_ui(MAG_EXPREF(x), 2 * MAG_BITS) > 0) { fmpz_t t; fmpz_init(t); /* If x > 2^60, exp(-x) < 2^(-2^60 / log(2)) */ /* -1/log(2) < -369/256 */ fmpz_set_si(t, -369); fmpz_mul_2exp(t, t, 2 * MAG_BITS - 8); mag_one(res); mag_mul_2exp_fmpz(res, res, t); fmpz_clear(t); } else { fmpz_t t; slong e = MAG_EXP(x); fmpz_init(t); fmpz_set_ui(t, MAG_MAN(x)); if (e >= MAG_BITS) fmpz_mul_2exp(t, t, e - MAG_BITS); else fmpz_tdiv_q_2exp(t, t, MAG_BITS - e); /* upper bound for 1/e */ mag_set_ui_2exp_si(res, 395007543, -30); mag_pow_fmpz(res, res, t); fmpz_clear(t); } }
int main(void) { long iter; int result; flint_rand_t state; printf("abs_ubound_ui_2exp...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 100000; iter++) { fmpz_t x, y; long bits, yexp; long exp; mp_limb_t man; fmpz_init(x); fmpz_init(y); fmpz_randtest_not_zero(x, state, 1 + n_randint(state, 400)); bits = 1 + n_randint(state, FLINT_BITS - 1); /* compute an exactly rounded mantissa */ fmpz_abs(y, x); if (fmpz_is_zero(y)) { yexp = 0; } else { yexp = fmpz_bits(y) - bits; if (yexp >= 0) { fmpz_cdiv_q_2exp(y, y, yexp); if (fmpz_bits(y) == bits + 1) { fmpz_tdiv_q_2exp(y, y, 1); yexp--; } } else { fmpz_mul_2exp(y, y, -yexp); } } man = fmpz_abs_ubound_ui_2exp(&exp, x, bits); if (FLINT_BIT_COUNT(man) != bits) { printf("wrong number of bits!\n"); printf("bits = %ld, count = %u\n\n", bits, FLINT_BIT_COUNT(man)); printf("x = "); fmpz_print(x); printf("\n\n"); printf("bits(x) = %ld\n\n", fmpz_bits(x)); printf("y = "); fmpz_print(y); printf("\n\n"); printf("yexp = %ld\n\n", yexp); printf("man = %lu, exp = %ld\n", man, exp); abort(); } /* ok if equal */ result = (fmpz_cmp_ui(y, man) == 0); /* ok if mantissa is 1 larger */ if (!result) { result = ((exp == yexp) && (fmpz_cmp_ui(y, man - 1) == 0)); } /* ok if the exact mantissa is 2^r-1 and overflow to 2^r happened */ if (!result) { fmpz_t t; fmpz_init(t); fmpz_set_ui(t, man); fmpz_mul_ui(t, t, 2); fmpz_sub_ui(t, t, 1); result = (exp == yexp + 1) && fmpz_equal(t, y); fmpz_clear(t); } if (!result) { printf("different from exact ceiling division\n"); printf("bits = %ld\n\n", bits); printf("x = "); fmpz_print(x); printf("\n\n"); printf("bits(x) = %ld\n\n", fmpz_bits(x)); printf("y = "); fmpz_print(y); printf(", yexp = %ld\n\n", yexp); printf("man = %lu, exp = %ld\n", man, exp); abort(); } fmpz_clear(x); fmpz_clear(y); } flint_randclear(state); _fmpz_cleanup(); printf("PASS\n"); return 0; }
void arb_exp_arf_bb(arb_t z, const arf_t x, slong prec, int minus_one) { slong k, iter, bits, r, mag, q, wp, N; slong argred_bits, start_bits; mp_bitcnt_t Qexp[1]; int inexact; fmpz_t t, u, T, Q; arb_t w; if (arf_is_zero(x)) { if (minus_one) arb_zero(z); else arb_one(z); return; } if (arf_is_special(x)) { abort(); } mag = arf_abs_bound_lt_2exp_si(x); /* We assume that this function only gets called with something reasonable as input (huge/tiny input will be handled by the main exp wrapper). */ if (mag > 200 || mag < -2 * prec - 100) { flint_printf("arb_exp_arf_bb: unexpectedly large/small input\n"); abort(); } if (prec < 100000000) { argred_bits = 16; start_bits = 32; } else { argred_bits = 32; start_bits = 64; } /* Argument reduction: exp(x) -> exp(x/2^q). This improves efficiency of the first iteration in the bit-burst algorithm. */ q = FLINT_MAX(0, mag + argred_bits); /* Determine working precision. */ wp = prec + 10 + 2 * q + 2 * FLINT_BIT_COUNT(prec); if (minus_one && mag < 0) wp += (-mag); fmpz_init(t); fmpz_init(u); fmpz_init(Q); fmpz_init(T); arb_init(w); /* Convert x/2^q to a fixed-point number. */ inexact = arf_get_fmpz_fixed_si(t, x, -wp + q); /* Aliasing of z and x is safe now that only use t. */ /* Start with z = 1. */ arb_one(z); /* Bit-burst loop. */ for (iter = 0, bits = start_bits; !fmpz_is_zero(t); iter++, bits *= 2) { /* Extract bits. */ r = FLINT_MIN(bits, wp); fmpz_tdiv_q_2exp(u, t, wp - r); /* Binary splitting (+1 fixed-point ulp truncation error). */ mag = fmpz_bits(u) - r; N = bs_num_terms(mag, wp); _arb_exp_sum_bs_powtab(T, Q, Qexp, u, r, N); /* T = T / Q (+1 fixed-point ulp error). */ if (*Qexp >= wp) { fmpz_tdiv_q_2exp(T, T, *Qexp - wp); fmpz_tdiv_q(T, T, Q); } else { fmpz_mul_2exp(T, T, wp - *Qexp); fmpz_tdiv_q(T, T, Q); } /* T = 1 + T */ fmpz_one(Q); fmpz_mul_2exp(Q, Q, wp); fmpz_add(T, T, Q); /* Now T = exp(u) with at most 2 fixed-point ulp error. */ /* Set z = z * T. */ arf_set_fmpz(arb_midref(w), T); arf_mul_2exp_si(arb_midref(w), arb_midref(w), -wp); mag_set_ui_2exp_si(arb_radref(w), 2, -wp); arb_mul(z, z, w, wp); /* Remove used bits. */ fmpz_mul_2exp(u, u, wp - r); fmpz_sub(t, t, u); } /* We have exp(x + eps) - exp(x) < 2*eps (by assumption that the argument reduction is large enough). */ if (inexact) arb_add_error_2exp_si(z, -wp + 1); fmpz_clear(t); fmpz_clear(u); fmpz_clear(Q); fmpz_clear(T); arb_clear(w); /* exp(x) = exp(x/2^q)^(2^q) */ for (k = 0; k < q; k++) arb_mul(z, z, z, wp); if (minus_one) arb_sub_ui(z, z, 1, wp); arb_set_round(z, z, prec); }