void _fmpq_poly_compose(fmpz * res, fmpz_t den, const fmpz * poly1, const fmpz_t den1, long len1, const fmpz * poly2, const fmpz_t den2, long len2) { if (*den2 == 1L) { _fmpz_poly_compose(res, poly1, len1, poly2, len2); fmpz_set(den, den1); _fmpq_poly_canonicalise(res, den, (len1 - 1L) * (len2 - 1L) + 1L); } else { fmpz_t one; fmpz * v = _fmpz_vec_init(len1); fmpz_init(one); fmpz_one(one); _fmpq_poly_rescale(v, den, poly1, den1, len1, one, den2); _fmpz_poly_compose(res, v, len1, poly2, len2); _fmpq_poly_canonicalise(res, den, (len1 - 1L) * (len2 - 1L) + 1L); fmpz_clear(one); _fmpz_vec_clear(v, len1); } }
void _fmpq_poly_compose_series_horner(fmpz * res, fmpz_t den, const fmpz * poly1, const fmpz_t den1, long len1, const fmpz * poly2, const fmpz_t den2, long len2, long n) { if (fmpz_is_one(den2)) { _fmpz_poly_compose_series(res, poly1, len1, poly2, len2, n); fmpz_set(den, den1); _fmpq_poly_canonicalise(res, den, n); } else if (n == 1) { fmpz_set(res, poly1); fmpz_set(den, den1); _fmpq_poly_canonicalise(res, den, 1); } else { long i = len1 - 1; long lenr; fmpz_t tden; fmpz * t = _fmpz_vec_init(n); fmpz_init(tden); _fmpz_vec_zero(res, n); lenr = len2; _fmpq_poly_scalar_mul_fmpz(res, den, poly2, den2, len2, poly1 + i); _fmpq_poly_scalar_div_fmpz(res, den, res, den, len2, den1); i--; _fmpq_poly_add(res, den, res, den, len2, poly1 + i, den1, 1); _fmpq_poly_canonicalise(res, den, lenr); while (i > 0) { i--; if (lenr + len2 - 1 < n) { _fmpq_poly_mul(t, tden, res, den, lenr, poly2, den2, len2); lenr = lenr + len2 - 1; } else { _fmpq_poly_mullow(t, tden, res, den, lenr, poly2, den2, len2, n); lenr = n; } _fmpq_poly_canonicalise(t, tden, lenr); _fmpq_poly_add(res, den, t, tden, lenr, poly1 + i, den1, 1); } _fmpq_poly_canonicalise(res, den, n); _fmpz_vec_clear(t, n); fmpz_clear(tden); } }
void _fmpq_poly_integral(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len) { slong k; fmpz_t t; fmpz_init(t); fmpz_one(t); for (k = len - 1; k > 0; k--) { fmpz_mul(rpoly + k, poly + k - 1, t); fmpz_mul_ui(t, t, k); } fmpz_mul(rden, den, t); fmpz_set_ui(t, UWORD(2)); for (k = 3; k < len; k++) { fmpz_mul(rpoly + k, rpoly + k, t); fmpz_mul_ui(t, t, k); } fmpz_zero(rpoly); _fmpq_poly_canonicalise(rpoly, rden, len); fmpz_clear(t); }
void _fmpq_poly_derivative(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, slong len) { _fmpz_poly_derivative(rpoly, poly, len); fmpz_set(rden, den); _fmpq_poly_canonicalise(rpoly, rden, len - 1); }
void _fmpq_poly_invsqrt_series(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, long n) { long m; fmpz * t, * u; fmpz_t tden, uden; if (n == 1) { fmpz_one(rpoly); fmpz_one(rden); return; } m = (n + 1) / 2; _fmpq_poly_invsqrt_series(rpoly, rden, poly, den, m); fmpz_init(tden); fmpz_init(uden); t = _fmpz_vec_init(n); u = _fmpz_vec_init(n); _fmpz_vec_zero(rpoly + m, n - m); _fmpq_poly_mul(t, tden, rpoly, rden, m, rpoly, rden, m); if (2*m - 1 < n) fmpz_zero(t + n - 1); _fmpq_poly_mullow(u, uden, t, tden, n, rpoly, rden, n, n); _fmpq_poly_mullow(t, tden, u, uden, n, poly, den, n, n); _fmpz_vec_neg(t + m, t + m, n - m); _fmpz_vec_zero(t, m); fmpz_mul_ui(tden, tden, 2UL); _fmpq_poly_canonicalise(t, tden, n); _fmpq_poly_add(rpoly, rden, rpoly, rden, m, t, tden, n); fmpz_clear(tden); fmpz_clear(uden); _fmpz_vec_clear(t, n); _fmpz_vec_clear(u, n); }
void _fmpq_poly_exp_series(fmpz * g, fmpz_t gden, const fmpz * h, const fmpz_t hden, long n) { long m; fmpz * t, * u; fmpz_t tden, uden; if (n < 2) { fmpz_one(g); fmpz_one(gden); return; } m = (n + 1) / 2; _fmpq_poly_exp_series(g, gden, h, hden, m); _fmpz_vec_zero(g + m, n - m); t = _fmpz_vec_init(n); u = _fmpz_vec_init(n); fmpz_init(tden); fmpz_init(uden); _fmpq_poly_log_series(t, tden, g, gden, n); _fmpq_poly_sub(t, tden, t, tden, n, h, hden, n); /* TODO: half of product is redundant! */ _fmpq_poly_mullow(u, uden, g, gden, n, t, tden, n, n); _fmpq_poly_sub(g, gden, g, gden, n, u, uden, n); _fmpq_poly_canonicalise(g, gden, n); fmpz_clear(tden); fmpz_clear(uden); _fmpz_vec_clear(t, n); _fmpz_vec_clear(u, n); }
void nf_elem_add_si(nf_elem_t a, const nf_elem_t b, slong c, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz * den = LNF_ELEM_DENREF(a); fmpz * num = LNF_ELEM_NUMREF(a); nf_elem_set(a, b, nf); if (c >= 0) fmpz_addmul_ui(num, den, c); else fmpz_submul_ui(num, den, -c); _fmpq_canonicalise(num, den); } else if (nf->flag & NF_QUADRATIC) { fmpz * den = QNF_ELEM_DENREF(a); fmpz * num = QNF_ELEM_NUMREF(a); slong len = 2; nf_elem_set(a, b, nf); while (len != 0 && fmpz_is_zero(num + len - 1)) len--; if (c >= 0) fmpz_addmul_ui(num, den, c); else fmpz_submul_ui(num, den, -c); _fmpq_poly_canonicalise(num, den, len); } else { fmpq_poly_add_si(NF_ELEM(a), NF_ELEM(b), c); } }
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); } }
void fmpq_poly_canonicalise(fmpq_poly_t poly) { _fmpq_poly_normalise(poly); _fmpq_poly_canonicalise(poly->coeffs, poly->den, poly->length); }
void _fmpq_poly_inv_series_newton(fmpz * Qinv, fmpz_t Qinvden, const fmpz * Q, const fmpz_t Qden, long n) { if (n == 1) { if (fmpz_sgn(Q) > 0) { fmpz_set(Qinv, Qden); fmpz_set(Qinvden, Q); } else { fmpz_neg(Qinv, Qden); fmpz_neg(Qinvden, Q); } } else { const long alloc = FLINT_MAX(n, 3 * FMPQ_POLY_INV_NEWTON_CUTOFF); long *a, i, m; fmpz *W, *Wden; W = _fmpz_vec_init(alloc + 1); Wden = W + alloc; for (i = 1; (1L << i) < n; i++) ; a = (long *) flint_malloc(i * sizeof(long)); a[i = 0] = n; while (n >= FMPQ_POLY_INV_NEWTON_CUTOFF) a[++i] = (n = (n + 1) / 2); /* Base case */ { fmpz *rev = W + 2 * FMPQ_POLY_INV_NEWTON_CUTOFF; _fmpz_poly_reverse(rev, Q, n, n); _fmpz_vec_zero(W, 2*n - 2); fmpz_one(W + (2*n - 2)); fmpz_one(Wden); _fmpq_poly_div(Qinv, Qinvden, W, Wden, 2*n - 1, rev, Qden, n); _fmpq_poly_canonicalise(Qinv, Qinvden, n); _fmpz_poly_reverse(Qinv, Qinv, n, n); } for (i--; i >= 0; i--) { m = n; n = a[i]; _fmpz_poly_mullow(W, Q, n, Qinv, m, n); fmpz_mul(Wden, Qden, Qinvden); _fmpz_poly_mullow(Qinv + m, Qinv, m, W + m, n - m, n - m); fmpz_mul(Qinvden, Qinvden, Wden); _fmpz_vec_scalar_mul_fmpz(Qinv, Qinv, m, Wden); _fmpz_vec_neg(Qinv + m, Qinv + m, n - m); _fmpq_poly_canonicalise(Qinv, Qinvden, n); } _fmpz_vec_clear(W, alloc + 1); flint_free(a); } }