void mag_root(mag_t y, const mag_t x, ulong n) { if (n == 0) { mag_inf(y); } else if (n == 1 || mag_is_special(x)) { mag_set(y, x); } else if (n == 2) { mag_sqrt(y, x); } else if (n == 4) { mag_sqrt(y, x); mag_sqrt(y, y); } else { fmpz_t e, f; fmpz_init_set_ui(e, MAG_BITS); fmpz_init(f); /* We evaluate exp(log(1+2^(kn)x)/n) 2^-k where k is chosen so that 2^(kn) x ~= 2^30. TODO: this rewriting is probably unnecessary with the new exp/log functions. */ fmpz_sub(e, e, MAG_EXPREF(x)); fmpz_cdiv_q_ui(e, e, n); fmpz_mul_ui(f, e, n); mag_mul_2exp_fmpz(y, x, f); mag_log1p(y, y); mag_div_ui(y, y, n); mag_exp(y, y); fmpz_neg(e, e); mag_mul_2exp_fmpz(y, y, e); fmpz_clear(e); fmpz_clear(f); } }
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() { slong iter; flint_rand_t state; flint_printf("mul_2exp_fmpz...."); fflush(stdout); flint_randinit(state); for (iter = 0; iter < 100000 * arb_test_multiplier(); iter++) { fmpr_t x, y, z; mag_t xb, yb; fmpz_t e; fmpr_init(x); fmpr_init(y); fmpr_init(z); fmpz_init(e); mag_init(xb); mag_init(yb); mag_randtest_special(xb, state, 100); fmpz_randtest(e, state, 100); mag_get_fmpr(x, xb); mag_mul_2exp_fmpz(yb, xb, e); fmpr_mul_2exp_fmpz(y, x, e); mag_get_fmpr(z, yb); MAG_CHECK_BITS(yb) if (!fmpr_equal(z, y)) { flint_printf("FAIL\n\n"); flint_printf("x = "); fmpr_printd(x, 15); flint_printf("\n\n"); flint_printf("y = "); fmpr_printd(y, 15); flint_printf("\n\n"); flint_printf("z = "); fmpr_printd(z, 15); flint_printf("\n\n"); abort(); } fmpr_clear(x); fmpr_clear(y); fmpr_clear(z); mag_clear(xb); mag_clear(yb); fmpz_clear(e); } flint_randclear(state); flint_cleanup(); flint_printf("PASS\n"); return EXIT_SUCCESS; }