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); } }
inline bool inverse(const DMatZZ& A, DMatZZ& result_inv) { DMatZZ::ElementType den; A.ring().init(den); bool result = fmpz_mat_inv(result_inv.fmpz_mat(), &den, A.fmpz_mat()); if (!fmpz_is_pm1(&den)) result = false; A.ring().clear(den); return result; }
inline bool solveLinear(const DMatZZ& A, const DMatZZ& B, DMatZZ& X) { DMatZZ::ElementType den; A.ring().init(den); bool result = fmpz_mat_solve(X.fmpz_mat(), &den, B.fmpz_mat(), A.fmpz_mat()); if (!fmpz_is_pm1(&den)) result = false; A.ring().clear(den); return result; }
void fmpz_poly_revert_series_lagrange(fmpz_poly_t Qinv, const fmpz_poly_t Q, slong n) { fmpz *Qcopy; int Qalloc; slong Qlen = Q->length; if (Qlen < 2 || !fmpz_is_zero(Q->coeffs) || !fmpz_is_pm1(Q->coeffs + 1)) { flint_printf("Exception (fmpz_poly_revert_series_lagrange). Input must have \n" "zero constant term and +1 or -1 as coefficient of x^1.\n"); abort(); } if (Qlen >= n) { Qcopy = Q->coeffs; Qalloc = 0; } else { slong i; Qcopy = (fmpz *) flint_malloc(n * sizeof(fmpz)); for (i = 0; i < Qlen; i++) Qcopy[i] = Q->coeffs[i]; for ( ; i < n; i++) Qcopy[i] = 0; Qalloc = 1; } if (Qinv != Q) { fmpz_poly_fit_length(Qinv, n); _fmpz_poly_revert_series_lagrange(Qinv->coeffs, Qcopy, n); } else { fmpz_poly_t t; fmpz_poly_init2(t, n); _fmpz_poly_revert_series_lagrange(t->coeffs, Qcopy, n); fmpz_poly_swap(Qinv, t); fmpz_poly_clear(t); } _fmpz_poly_set_length(Qinv, n); _fmpz_poly_normalise(Qinv); if (Qalloc) flint_free(Qcopy); }
void _fmpq_poly_revert_series_lagrange_fast(fmpz * Qinv, fmpz_t den, const fmpz * Q, const fmpz_t Qden, slong n) { slong i, j, k, m; fmpz *R, *Rden, *S, *T, *dens, *tmp; fmpz_t Sden, Tden, t; if (fmpz_is_one(Qden) && (n > 1) && fmpz_is_pm1(Q + 1)) { _fmpz_poly_revert_series(Qinv, Q, n); fmpz_one(den); return; } if (n <= 2) { fmpz_zero(Qinv); if (n == 2) { fmpz_set(Qinv + 1, Qden); fmpz_set(den, Q + 1); _fmpq_poly_canonicalise(Qinv, den, 2); } return; } m = n_sqrt(n); fmpz_init(t); dens = _fmpz_vec_init(n); R = _fmpz_vec_init((n - 1) * m); S = _fmpz_vec_init(n - 1); T = _fmpz_vec_init(n - 1); Rden = _fmpz_vec_init(m); fmpz_init(Sden); fmpz_init(Tden); fmpz_zero(Qinv); fmpz_one(dens); _fmpq_poly_inv_series(Ri(1), Rdeni(1), Q + 1, Qden, n - 1); _fmpq_poly_canonicalise(Ri(1), Rdeni(1), n - 1); for (i = 2; i <= m; i++) { _fmpq_poly_mullow(Ri(i), Rdeni(i), Ri(i-1), Rdeni(i-1), n - 1, Ri(1), Rdeni(1), n - 1, n - 1); _fmpq_poly_canonicalise(Ri(i), Rdeni(i), n - 1); } for (i = 1; i < m; i++) { fmpz_set(Qinv + i, Ri(i) + i - 1); fmpz_mul_ui(dens + i, Rdeni(i), i); } _fmpz_vec_set(S, Ri(m), n - 1); fmpz_set(Sden, Rdeni(m)); for (i = m; i < n; i += m) { fmpz_set(Qinv + i, S + i - 1); fmpz_mul_ui(dens + i, Sden, i); for (j = 1; j < m && i + j < n; j++) { fmpz_mul(t, S + 0, Ri(j) + i + j - 1); for (k = 1; k <= i + j - 1; k++) fmpz_addmul(t, S + k, Ri(j) + i + j - 1 - k); fmpz_set(Qinv + i + j, t); fmpz_mul(dens + i + j, Sden, Rdeni(j)); fmpz_mul_ui(dens + i + j, dens + i + j, i + j); } if (i + 1 < n) { _fmpq_poly_mullow(T, Tden, S, Sden, n - 1, Ri(m), Rdeni(m), n - 1, n - 1); _fmpq_poly_canonicalise(T, Tden, n - 1); fmpz_swap(Tden, Sden); tmp = S; S = T; T = tmp; } } _set_vec(Qinv, den, Qinv, dens, n); _fmpq_poly_canonicalise(Qinv, den, n); fmpz_clear(t); _fmpz_vec_clear(dens, n); _fmpz_vec_clear(R, (n - 1) * m); _fmpz_vec_clear(S, n - 1); _fmpz_vec_clear(T, n - 1); _fmpz_vec_clear(Rden, m); fmpz_clear(Sden); fmpz_clear(Tden); }
void _fmpq_poly_revert_series_lagrange(fmpz * Qinv, fmpz_t den, const fmpz * Q, const fmpz_t Qden, long n) { long i; fmpz *R, *S, *T, *dens, *tmp; fmpz_t Rden, Sden, Tden; if (fmpz_is_one(Qden) && (n > 1) && fmpz_is_pm1(Q + 1)) { _fmpz_poly_revert_series(Qinv, Q, n); fmpz_one(den); } else if (n <= 2) { fmpz_zero(Qinv); if (n == 2) { fmpz_set(Qinv + 1, Qden); fmpz_set(den, Q + 1); _fmpq_poly_canonicalise(Qinv, den, 2); } } else { dens = _fmpz_vec_init(n); R = _fmpz_vec_init(n - 1); S = _fmpz_vec_init(n - 1); T = _fmpz_vec_init(n - 1); fmpz_init(Rden); fmpz_init(Sden); fmpz_init(Tden); fmpz_zero(Qinv); fmpz_one(dens); fmpz_set(Qinv + 1, Qden); fmpz_set(dens + 1, Q + 1); _fmpq_poly_inv_series(R, Rden, Q + 1, Qden, n - 1); _fmpq_poly_canonicalise(R, Rden, n - 1); _fmpz_vec_set(S, R, n - 1); fmpz_set(Sden, Rden); for (i = 2; i < n; i++) { _fmpq_poly_mullow(T, Tden, S, Sden, n - 1, R, Rden, n - 1, n - 1); _fmpq_poly_canonicalise(T, Tden, n - 1); fmpz_set(Qinv + i, T + i - 1); fmpz_mul_ui(dens + i, Tden, i); tmp = S; S = T; T = tmp; fmpz_swap(Sden, Tden); } _set_vec(Qinv, den, Qinv, dens, n); _fmpq_poly_canonicalise(Qinv, den, n); _fmpz_vec_clear(R, n - 1); _fmpz_vec_clear(S, n - 1); _fmpz_vec_clear(T, n - 1); _fmpz_vec_clear(dens, n); fmpz_clear(Rden); fmpz_clear(Sden); fmpz_clear(Tden); } }
slong fmpr_div(fmpr_t z, const fmpr_t x, const fmpr_t y, slong prec, fmpr_rnd_t rnd) { if (fmpr_is_special(x) || fmpr_is_special(y)) { _fmpr_div_special(z, x, y); return FMPR_RESULT_EXACT; } /* division by power of two <=> shift exponents */ if (fmpz_is_pm1(fmpr_manref(y))) { if (fmpz_is_one(fmpr_manref(y))) fmpz_set(fmpr_manref(z), fmpr_manref(x)); else fmpz_neg(fmpr_manref(z), fmpr_manref(x)); fmpz_sub(fmpr_expref(z), fmpr_expref(x), fmpr_expref(y)); return _fmpr_normalise(fmpr_manref(z), fmpr_expref(z), prec, rnd); } else { slong xbits, ybits, extra, extra_pad, extra_control; int negative; fmpz_t t, u; /* todo: work out exact needed shift */ xbits = fmpz_bits(fmpr_manref(x)); ybits = fmpz_bits(fmpr_manref(y)); extra = prec - xbits + ybits; extra = FLINT_MAX(extra, 0); extra_pad = 32; extra_control = 24; extra += extra_pad; fmpz_init(t); fmpz_init(u); fmpz_mul_2exp(t, fmpr_manref(x), extra); fmpz_tdiv_q(u, t, fmpr_manref(y)); if (low_bits_are_zero(u, extra_control)) { fmpz_t v; fmpz_init(v); fmpz_mul(v, u, fmpr_manref(y)); negative = fmpz_sgn(fmpr_manref(x)) != fmpz_sgn(fmpr_manref(y)); if (!fmpz_equal(t, v)) { if (negative) fmpz_sub_ui(u, u, 1); else fmpz_add_ui(u, u, 1); } fmpz_clear(v); } fmpz_swap(fmpr_manref(z), u); fmpz_clear(t); fmpz_clear(u); fmpz_sub(fmpr_expref(z), fmpr_expref(x), fmpr_expref(y)); fmpz_sub_ui(fmpr_expref(z), fmpr_expref(z), extra); return _fmpr_normalise(fmpr_manref(z), fmpr_expref(z), prec, rnd); } }