void fmpr_pow_sloppy_fmpz(fmpr_t y, const fmpr_t b, const fmpz_t e, long prec, fmpr_rnd_t rnd) { long i, wp, bits; if (fmpz_is_zero(e)) { fmpr_set_ui(y, 1UL); return; } if (fmpz_sgn(e) < 0) { fmpz_t f; fmpz_init(f); fmpz_neg(f, e); fmpr_pow_sloppy_fmpz(y, b, f, prec + 2, (rnd == FMPR_RND_FLOOR || rnd == FMPR_RND_DOWN) ? FMPR_RND_UP : FMPR_RND_DOWN); fmpr_ui_div(y, 1UL, y, prec, rnd); fmpz_clear(f); } if (y == b) { fmpr_t t; fmpr_init(t); fmpr_set(t, b); fmpr_pow_sloppy_fmpz(y, t, e, prec, rnd); fmpr_clear(t); return; } fmpr_set(y, b); bits = fmpz_bits(e); wp = FMPR_PREC_ADD(prec, bits); for (i = bits - 2; i >= 0; i--) { fmpr_mul(y, y, y, wp, rnd); if (fmpz_tstbit(e, i)) fmpr_mul(y, y, b, wp, rnd); } }
void _fq_nmod_pow(mp_limb_t *rop, const mp_limb_t *op, slong len, const fmpz_t e, const fq_nmod_ctx_t ctx) { const slong d = fq_nmod_ctx_degree(ctx); if (fmpz_is_zero(e)) { rop[0] = WORD(1); _nmod_vec_zero(rop + 1, 2 * d - 1 - 1); } else if (fmpz_is_one(e)) { _nmod_vec_set(rop, op, len); _nmod_vec_zero(rop + len, 2 * d - 1 - len); } else { ulong bit; mp_limb_t *v = _nmod_vec_init(2 * d - 1); mp_limb_t *R, *S, *T; _nmod_vec_zero(v, 2 * d - 1); _nmod_vec_zero(rop, 2 * d - 1); /* Set bits to the bitmask with a 1 one place lower than the msb of e */ bit = fmpz_bits(e) - 2; /* Trial run without any polynomial arithmetic to determine the parity of the number of swaps; then set R and S accordingly */ { unsigned int swaps = 0U; ulong bit2 = bit; if (fmpz_tstbit(e, bit2)) swaps = ~swaps; while (bit2--) if (!fmpz_tstbit(e, bit2)) swaps = ~swaps; if (swaps == 0U) { R = rop; S = v; } else { R = v; S = rop; } } /* We unroll the first step of the loop, referring to {op, len} */ _nmod_poly_mul(R, op, len, op, len, ctx->mod); _fq_nmod_reduce(R, 2 * len - 1, ctx); if (fmpz_tstbit(e, bit)) { _nmod_poly_mul(S, R, d, op, len, ctx->mod); _fq_nmod_reduce(S, d + len - 1, ctx); T = R; R = S; S = T; } while (bit--) { if (fmpz_tstbit(e, bit)) { _nmod_poly_mul(S, R, d, R, d, ctx->mod); _fq_nmod_reduce(S, 2 * d - 1, ctx); _nmod_poly_mul(R, S, d, op, len, ctx->mod); _fq_nmod_reduce(R, d + len - 1, ctx); } else { _nmod_poly_mul(S, R, d, R, d, ctx->mod); _fq_nmod_reduce(S, 2 * d - 1, ctx); T = R; R = S; S = T; } } _nmod_vec_clear(v); } }
void acb_pow_fmpz_binexp(acb_t y, const acb_t b, const fmpz_t e, long prec) { long i, wp, bits; if (-2L <= *e && *e <= 4L) { if (*e == 0L) { acb_one(y); } else if (*e == 1L) { acb_set_round(y, b, prec); } else if (*e == -1L) { acb_inv(y, b, prec); } else if (*e == 2L) { acb_mul(y, b, b, prec); } else if (*e == 3L) { acb_cube(y, b, prec); } else if (*e == 4L) { acb_mul(y, b, b, prec); acb_mul(y, y, y, prec); } else { acb_inv(y, b, prec); acb_mul(y, y, y, prec); } return; } if (fmpz_sgn(e) < 0) { fmpz_t f; fmpz_init(f); fmpz_neg(f, e); acb_pow_fmpz_binexp(y, b, f, prec + 2); acb_inv(y, y, prec); fmpz_clear(f); return; } if (!COEFF_IS_MPZ(*e) && ((*e) % 3 == 0)) { fmpz e3 = (*e) / 3; acb_pow_fmpz_binexp(y, b, &e3, prec); acb_cube(y, y, prec); return; } if (y == b) { acb_t t; acb_init(t); acb_set(t, b); acb_pow_fmpz_binexp(y, t, e, prec); acb_clear(t); return; } acb_set(y, b); bits = fmpz_bits(e); wp = ARF_PREC_ADD(prec, bits); for (i = bits - 2; i >= 0; i--) { acb_mul(y, y, y, wp); if (fmpz_tstbit(e, i)) acb_mul(y, y, b, wp); } }
void arb_fib_fmpz(arb_t f, const fmpz_t n, slong prec) { arb_t t, u; slong wp, sign, i; if (fmpz_sgn(n) < 0) { fmpz_t m; fmpz_init(m); fmpz_neg(m, n); arb_fib_fmpz(f, m, prec); if (fmpz_is_even(m)) arb_neg(f, f); fmpz_clear(m); return; } if (fmpz_cmp_ui(n, 4) <= 0) { ulong x = fmpz_get_ui(n); arb_set_ui(f, x - (x > 1)); return; } wp = ARF_PREC_ADD(prec, 3 * fmpz_bits(n)); arb_init(u); arb_init(t); arb_set_ui(f, UWORD(1)); arb_set_ui(u, UWORD(1)); sign = -1; for (i = fmpz_flog_ui(n, UWORD(2)) - 1; i > 0; i--) { arb_mul(t, f, f, wp); arb_add(f, f, u, wp); arb_mul_2exp_si(f, f, -1); arb_mul(f, f, f, wp); arb_mul_2exp_si(f, f, 1); arb_submul_ui(f, t, 3, wp); arb_sub_si(f, f, 2 * sign, wp); arb_mul_ui(u, t, 5, wp); arb_add_si(u, u, 2 * sign, wp); sign = 1; if (fmpz_tstbit(n, i)) { arb_set(t, f); arb_add(f, f, u, wp); arb_mul_2exp_si(f, f, -1); arb_mul_2exp_si(t, t, 1); arb_add(u, f, t, wp); sign = -1; } } if (fmpz_tstbit(n, 0)) { arb_add(f, f, u, wp); arb_mul_2exp_si(f, f, -1); arb_mul(f, f, u, wp); arb_sub_si(f, f, sign, prec); } else { arb_mul(f, f, u, prec); } arb_clear(u); arb_clear(t); }