void _fmpq_poly_scalar_mul_fmpz(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, long len, const fmpz_t c) { fmpz_t gcd; /* GCD( den, c ) */ if (fmpz_is_zero(c)) { _fmpz_vec_zero(rpoly, len); fmpz_one(rden); return; } fmpz_init(gcd); fmpz_one(gcd); if (*c != 1L) fmpz_gcd(gcd, c, den); if (*gcd == 1L) { _fmpz_vec_scalar_mul_fmpz(rpoly, poly, len, c); fmpz_set(rden, den); } else { fmpz_t c2; fmpz_init(c2); fmpz_divexact(c2, c, gcd); _fmpz_vec_scalar_mul_fmpz(rpoly, poly, len, c2); fmpz_divexact(rden, den, gcd); fmpz_clear(c2); } fmpz_clear(gcd); }
/* Assumes poly1 and poly2 are not length 0. */ void _fmpz_poly_mul_classical(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { if (len1 == 1 && len2 == 1) /* Special case if the length of both inputs is 1 */ { fmpz_mul(res, poly1, poly2); } else /* Ordinary case */ { slong i; /* Set res[i] = poly1[i]*poly2[0] */ _fmpz_vec_scalar_mul_fmpz(res, poly1, len1, poly2); /* Set res[i+len1-1] = in1[len1-1]*in2[i] */ _fmpz_vec_scalar_mul_fmpz(res + len1, poly2 + 1, len2 - 1, poly1 + len1 - 1); /* out[i+j] += in1[i]*in2[j] */ for (i = 0; i < len1 - 1; i++) _fmpz_vec_scalar_addmul_fmpz(res + i + 1, poly2 + 1, len2 - 1, poly1 + i); } }
/* Assumes poly1 and poly2 are not length 0 and 0 < n <= len1 + len2 - 1. */ void _fmpz_poly_mullow_classical(fmpz * res, const fmpz * poly1, long len1, const fmpz * poly2, long len2, long n) { if ((len1 == 1 && len2 == 1) || n == 1) /* Special case if the length of output is 1 */ { fmpz_mul(res, poly1, poly2); } else /* Ordinary case */ { long i; /* Set res[i] = poly1[i]*poly2[0] */ _fmpz_vec_scalar_mul_fmpz(res, poly1, FLINT_MIN(len1, n), poly2); /* Set res[i+len1-1] = in1[len1-1]*in2[i] */ if (n > len1) _fmpz_vec_scalar_mul_fmpz(res + len1, poly2 + 1, n - len1, poly1 + len1 - 1); /* out[i+j] += in1[i]*in2[j] */ for (i = 0; i < FLINT_MIN(len1, n) - 1; i++) _fmpz_vec_scalar_addmul_fmpz(res + i + 1, poly2 + 1, FLINT_MIN(len2, n - i) - 1, poly1 + i); } }
int padic_poly_get_fmpz_poly(fmpz_poly_t rop, const padic_poly_t op, const padic_ctx_t ctx) { const slong len = op->length; if (op->val < 0) { return 0; } if (padic_poly_is_zero(op)) { fmpz_poly_zero(rop); return 1; } fmpz_poly_fit_length(rop, len); _fmpz_poly_set_length(rop, len); if (op->val == 0) { _fmpz_vec_set(rop->coeffs, op->coeffs, len); } else /* op->val > 0 */ { fmpz_t pow; fmpz_init(pow); fmpz_pow_ui(pow, ctx->p, op->val); _fmpz_vec_scalar_mul_fmpz(rop->coeffs, op->coeffs, len, pow); fmpz_clear(pow); } return 1; }
/* Assumes poly1 and poly2 are not length 0 and len1 >= len2. */ void _fmpz_poly_mulmid_classical(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { if ((len1 == 1) && (len2 == 1)) /* Special case if the length of both inputs is 1 */ { fmpz_mul(res, poly1, poly2); } else /* Ordinary case */ { slong i; /* Set res[i] = poly1[i]*poly2[0] */ _fmpz_vec_scalar_mul_fmpz(res, poly1 + len2 - 1, len1 - len2 + 1, poly2); /* out[i+j] += in1[i]*in2[j] */ for (i = 0; i < len2 - 1; i++) _fmpz_vec_scalar_addmul_fmpz(res, poly2 + len2 - i - 1, FLINT_MIN(i + 1, len1 - len2 + 1), poly1 + i); for (; i < len1 - 1; i++) _fmpz_vec_scalar_addmul_fmpz(res + i - len2 + 2, poly2 + 1, FLINT_MIN(len2 - 1, len1 - i - 1), poly1 + i); } }
void _qadic_exp_balanced(fmpz *rop, const fmpz *x, slong v, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N, const fmpz_t pN) { const slong d = j[lena - 1]; fmpz_t pw; fmpz *r, *s, *t; slong i, w; r = _fmpz_vec_init(d); s = _fmpz_vec_init(2*d - 1); t = _fmpz_vec_init(d); fmpz_init(pw); fmpz_pow_ui(pw, p, v); _fmpz_vec_scalar_mul_fmpz(t, x, len, pw); _fmpz_vec_scalar_mod_fmpz(t, t, len, pN); _fmpz_vec_zero(t + len, d - len); fmpz_set(pw, p); fmpz_one(rop + 0); _fmpz_vec_zero(rop + 1, d - 1); w = 1; while (!_fmpz_vec_is_zero(t, d)) { fmpz_mul(pw, pw, pw); for (i = 0; i < d; i++) { fmpz_fdiv_r(r + i, t + i, pw); fmpz_sub(t + i, t + i, r + i); } if (!_fmpz_vec_is_zero(r, d)) { _qadic_exp_bsplit(r, r, w, d, a, j, lena, p, N); _fmpz_poly_mul(s, rop, d, r, d); _fmpz_poly_reduce(s, 2*d - 1, a, j, lena); _fmpz_vec_scalar_mod_fmpz(rop, s, d, pN); } w *= 2; } _fmpz_vec_clear(r, d); _fmpz_vec_clear(s, 2*d - 1); _fmpz_vec_clear(t, d); fmpz_clear(pw); }
int main(void) { int i, result; FLINT_TEST_INIT(state); flint_printf("content...."); fflush(stdout); /* Check that content(a f) = abs(a) content(f) */ for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_t a, c, d; fmpz *f; slong len = n_randint(state, 100); fmpz_init(a); fmpz_init(c); fmpz_init(d); f = _fmpz_vec_init(len); _fmpz_vec_randtest(f, state, len, 200); fmpz_randtest(a, state, 100); _fmpz_vec_content(c, f, len); _fmpz_vec_scalar_mul_fmpz(f, f, len, a); fmpz_abs(a, a); fmpz_mul(c, a, c); _fmpz_vec_content(d, f, len); result = (fmpz_equal(c, d)); if (!result) { flint_printf("FAIL:\n"); fmpz_print(c), flint_printf("\n\n"); fmpz_print(d), flint_printf("\n\n"); abort(); } fmpz_clear(a); fmpz_clear(c); fmpz_clear(d); _fmpz_vec_clear(f, len); } FLINT_TEST_CLEANUP(state); flint_printf("PASS\n"); return 0; }
void _fmpz_poly_pseudo_divrem_basecase(fmpz * Q, fmpz * R, ulong * d, const fmpz * A, long lenA, const fmpz * B, long lenB) { const fmpz * leadB = B + (lenB - 1); long iQ = lenA - lenB, iR = lenA - 1; fmpz_t rem; fmpz_init(rem); *d = 0; _fmpz_vec_zero(Q, lenA - lenB + 1); if (R != A) _fmpz_vec_set(R, A, lenA); while (iR >= lenB - 1) { fmpz_fdiv_qr(Q + iQ, rem, R + iR, leadB); if (!fmpz_is_zero(rem)) { _fmpz_vec_scalar_mul_fmpz(Q, Q, lenA - lenB + 1, leadB); fmpz_set(Q + iQ, R + iR); _fmpz_vec_scalar_mul_fmpz(R, R, lenA, leadB); (*d)++; } if (lenB > 1) _fmpz_vec_scalar_submul_fmpz(R + (iR - lenB + 1), B, lenB - 1, Q + iQ); fmpz_zero(R + iR); iR--; iQ--; } fmpz_clear(rem); }
void fmpz_poly_scalar_mul_fmpz(fmpz_poly_t poly1, const fmpz_poly_t poly2, const fmpz_t x) { /* Either scalar or input poly is zero */ if ((*x == 0) || (poly2->length == 0)) { fmpz_poly_zero(poly1); return; } fmpz_poly_fit_length(poly1, poly2->length); _fmpz_vec_scalar_mul_fmpz(poly1->coeffs, poly2->coeffs, poly2->length, x); _fmpz_poly_set_length(poly1, poly2->length); }
/* Assumes len > 0. */ void _fmpz_poly_sqr_classical(fmpz *rop, const fmpz *op, long len) { if (len == 1) /* Special case */ { fmpz_mul(rop, op, op); } else /* Ordinary case */ { long i; _fmpz_vec_scalar_mul_fmpz(rop, op, len, op); _fmpz_vec_scalar_mul_fmpz(rop + len, op + 1, len - 1, op + len - 1); for (i = 1; i < len - 1; i++) _fmpz_vec_scalar_addmul_fmpz(rop + i + 1, op + 1, i - 1, op + i); for (i = 1; i < 2 * len - 2; i++) fmpz_mul_ui(rop + i, rop + i, 2); for (i = 1; i < len - 1; i++) fmpz_addmul(rop + 2 * i, op + i, op + i); } }
void _fmpz_poly_pseudo_divrem_cohen(fmpz * Q, fmpz * R, const fmpz * A, long lenA, const fmpz * B, long lenB) { const fmpz * leadB = B + (lenB - 1); long e, lenQ; fmpz_t pow; if (lenB == 1) { fmpz_init(pow); fmpz_pow_ui(pow, leadB, lenA - 1); _fmpz_vec_scalar_mul_fmpz(Q, A, lenA, pow); _fmpz_vec_zero(R, lenA); fmpz_clear(pow); return; } lenQ = lenA - lenB + 1; _fmpz_vec_zero(Q, lenQ); if (R != A) _fmpz_vec_set(R, A, lenA); e = lenA - lenB; /* Unroll the first run of the while loop */ { fmpz_set(Q + (lenQ - 1), R + (lenA - 1)); _fmpz_vec_scalar_mul_fmpz(R, R, lenA - 1, leadB); _fmpz_vec_scalar_submul_fmpz(R + (lenA - lenB), B, lenB - 1, R + (lenA - 1)); fmpz_zero(R + (lenA - 1)); for (lenA -= 2; (lenA >= 0) && (R[lenA] == 0L); lenA--) ; lenA++; } while (lenA >= lenB) { _fmpz_vec_scalar_mul_fmpz(Q, Q, lenQ, leadB); fmpz_add(Q + (lenA - lenB), Q + (lenA - lenB), R + (lenA - 1)); _fmpz_vec_scalar_mul_fmpz(R, R, lenA - 1, leadB); _fmpz_vec_scalar_submul_fmpz(R + lenA - lenB, B, lenB - 1, R + (lenA - 1)); fmpz_zero(R + (lenA - 1)); for (lenA -= 2; (lenA >= 0) && (R[lenA] == 0L); lenA--) ; lenA++; e--; } fmpz_init(pow); fmpz_pow_ui(pow, leadB, e); _fmpz_vec_scalar_mul_fmpz(Q, Q, lenQ, pow); _fmpz_vec_scalar_mul_fmpz(R, R, lenA, pow); fmpz_clear(pow); }
/* Assumes poly1 and poly2 are not length 0. */ void _fmpz_poly_mulhigh_classical(fmpz * res, const fmpz * poly1, long len1, const fmpz * poly2, long len2, long start) { _fmpz_vec_zero(res, start); if (len1 == 1 && len2 == 1) /* Special case if the length of both inputs is 1 */ { if (start == 0) fmpz_mul(res, poly1, poly2); } else /* Ordinary case */ { long i, m, n; /* Set res[i] = poly1[i]*poly2[0] */ if (start < len1) _fmpz_vec_scalar_mul_fmpz(res + start, poly1 + start, len1 - start, poly2); /* Set res[i+len1-1] = in1[len1-1]*in2[i] */ m = FLINT_MAX(len1 - 1, start); _fmpz_vec_scalar_mul_fmpz(res + m, poly2 + m - len1 + 1, len2 - 1 + len1 - m, poly1 + len1 - 1); /* out[i+j] += in1[i]*in2[j] */ m = FLINT_MAX(start, len2 - 1); for (i = m - len2 + 1; i < len1 - 1; i++) { n = FLINT_MAX(i + 1, start); _fmpz_vec_scalar_addmul_fmpz(res + n, poly2 + n - i, len2 + i - n, poly1 + i); } } }
static void _qadic_exp_bsplit(fmpz *y, const fmpz *x, slong v, slong len, const fmpz *a, const slong *j, slong lena, const fmpz_t p, slong N) { const slong d = j[lena - 1]; const slong n = _padic_exp_bound(v, N, p); if (n == 1) { fmpz_one(y + 0); _fmpz_vec_zero(y + 1, d - 1); } else { fmpz *P, *T; fmpz_t Q, R; slong f; P = _fmpz_vec_init(2*d - 1); T = _fmpz_vec_init(2*d - 1); fmpz_init(Q); fmpz_init(R); _qadic_exp_bsplit_series(P, Q, T, x, len, 1, n, a, j, lena); fmpz_add(T + 0, T + 0, Q); /* (T,Q) := (T,Q) + 1 */ /* Note exp(x) is a unit so val(T) == val(Q). */ f = fmpz_remove(Q, Q, p); fmpz_pow_ui(R, p, f); _fmpz_vec_scalar_divexact_fmpz(T, T, d, R); _padic_inv(Q, Q, p, N); _fmpz_vec_scalar_mul_fmpz(y, T, d, Q); _fmpz_vec_clear(P, 2*d - 1); _fmpz_vec_clear(T, 2*d - 1); fmpz_clear(Q); fmpz_clear(R); } }
void fmpq_poly_randtest_unsigned(fmpq_poly_t poly, flint_rand_t state, long len, mp_bitcnt_t bits) { ulong m; m = n_randlimb(NULL); fmpq_poly_fit_length(poly, len); _fmpq_poly_set_length(poly, len); if (m & 1UL) { _fmpz_vec_randtest_unsigned(poly->coeffs, state, len, bits); } else { fmpz_t x; fmpz_init(x); fmpz_randtest_unsigned(x, state, bits / 2); _fmpz_vec_randtest_unsigned(poly->coeffs, state, len, (bits + 1) / 2); _fmpz_vec_scalar_mul_fmpz(poly->coeffs, poly->coeffs, len, x); fmpz_clear(x); } if (m & 2UL) { fmpz_randtest_not_zero(poly->den, state, FLINT_MAX(bits, 1)); fmpz_abs(poly->den, poly->den); fmpq_poly_canonicalise(poly); } else { fmpz_set_ui(poly->den, 1); _fmpq_poly_normalise(poly); } }
/* Assumes len1 != 0 != len2 */ int _fmpz_poly_gcd_heuristic(fmpz * res, const fmpz * poly1, long len1, const fmpz * poly2, long len2) { ulong bits1, bits2, max_bits, pack_bits, bound_bits, bits_G, bits_Q; ulong limbs1, limbs2, limbsg, pack_limbs, qlimbs; ulong log_glen, log_length; long sign1, sign2, glen, qlen; fmpz_t ac, bc, d, gc; fmpz * A, * B, * G, * Q, * t; mp_ptr array1, array2, arrayg, q, temp; int divides; fmpz_init(ac); fmpz_init(bc); fmpz_init(d); /* compute gcd of content of poly1 and poly2 */ _fmpz_poly_content(ac, poly1, len1); _fmpz_poly_content(bc, poly2, len2); fmpz_gcd(d, ac, bc); /* special case, one of the polys is a constant */ if (len2 == 1) /* if len1 == 1 then so does len2 */ { fmpz_set(res, d); fmpz_clear(ac); fmpz_clear(bc); fmpz_clear(d); return 1; } /* divide poly1 and poly2 by their content */ A = _fmpz_vec_init(len1); B = _fmpz_vec_init(len2); _fmpz_vec_scalar_divexact_fmpz(A, poly1, len1, ac); _fmpz_vec_scalar_divexact_fmpz(B, poly2, len2, bc); fmpz_clear(ac); fmpz_clear(bc); /* special case, one of the polys is length 2 */ if (len2 == 2) /* if len1 == 2 then so does len2 */ { Q = _fmpz_vec_init(len1 - len2 + 1); if (_fmpz_poly_divides(Q, A, len1, B, 2)) { _fmpz_vec_scalar_mul_fmpz(res, B, 2, d); if (fmpz_sgn(res + 1) < 0) _fmpz_vec_neg(res, res, 2); } else { fmpz_set(res, d); fmpz_zero(res + 1); } fmpz_clear(d); _fmpz_vec_clear(A, len1); _fmpz_vec_clear(B, len2); _fmpz_vec_clear(Q, len1 - len2 + 1); return 1; } /* Determine how many bits (pack_bits) to pack into. The bound bound_bits ensures that if G | A and G | B with G primitive then G is the gcd of A and B. The bound is taken from http://arxiv.org/abs/cs/0206032v1 */ bits1 = FLINT_ABS(_fmpz_vec_max_bits(A, len1)); bits2 = FLINT_ABS(_fmpz_vec_max_bits(B, len2)); max_bits = FLINT_MAX(bits1, bits2); bound_bits = FLINT_MIN(bits1, bits2) + 6; pack_bits = FLINT_MAX(bound_bits, max_bits); /* need to pack original polys */ pack_limbs = (pack_bits - 1)/FLINT_BITS + 1; if (pack_bits >= 32) /* pack into multiples of limbs if >= 32 bits */ pack_bits = FLINT_BITS*pack_limbs; /* allocate space to pack into */ limbs1 = (pack_bits*len1 - 1)/FLINT_BITS + 1; limbs2 = (pack_bits*len2 - 1)/FLINT_BITS + 1; array1 = flint_calloc(limbs1, sizeof(mp_limb_t)); array2 = flint_calloc(limbs2, sizeof(mp_limb_t)); arrayg = flint_calloc(limbs2, sizeof(mp_limb_t)); /* pack first poly and normalise */ sign1 = (long) fmpz_sgn(A + len1 - 1); _fmpz_poly_bit_pack(array1, A, len1, pack_bits, sign1); while (array1[limbs1 - 1] == 0) limbs1--; /* pack second poly and normalise */ sign2 = (long) fmpz_sgn(B + len2 - 1); _fmpz_poly_bit_pack(array2, B, len2, pack_bits, sign2); while (array2[limbs2 - 1] == 0) limbs2--; /* compute integer GCD */ limbsg = mpn_gcd_full(arrayg, array1, limbs1, array2, limbs2); /* Make space for unpacked gcd. May have one extra coeff due to 1 0 -x being packed as 0 -1 -x. */ glen = FLINT_MIN((limbsg*FLINT_BITS)/pack_bits + 1, len2); G = _fmpz_vec_init(glen); /* unpack gcd */ _fmpz_poly_bit_unpack(G, glen, arrayg, pack_bits, 0); while (G[glen - 1] == 0) glen--; /* divide by any content */ fmpz_init(gc); _fmpz_poly_content(gc, G, glen); if (!fmpz_is_one(gc)) limbsg = mpn_tdiv_q_fmpz_inplace(arrayg, limbsg, gc); /* make space for quotient and remainder of first poly by gcd */ qlimbs = limbs1 - limbsg + 1; qlen = FLINT_MIN(len1, (qlimbs*FLINT_BITS)/pack_bits + 1); qlimbs = (qlen*pack_bits - 1)/FLINT_BITS + 1; q = flint_calloc(qlimbs, sizeof(mp_limb_t)); temp = flint_malloc(limbsg*sizeof(mp_limb_t)); divides = 0; if (mpn_divides(q, array1, limbs1, arrayg, limbsg, temp)) { /* unpack quotient of first poly by gcd */ Q = _fmpz_vec_init(len1); t = _fmpz_vec_init(len1 + glen); _fmpz_poly_bit_unpack(Q, qlen, q, pack_bits, 0); while (Q[qlen - 1] == 0) qlen--; /* divide by content */ _fmpz_vec_scalar_divexact_fmpz(G, G, glen, gc); /* check if we really need to multiply out to check for exact quotient */ bits_G = FLINT_ABS(_fmpz_vec_max_bits(G, glen)); bits_Q = FLINT_ABS(_fmpz_vec_max_bits(Q, qlen)); log_glen = FLINT_BIT_COUNT(glen); log_length = FLINT_MIN(log_glen, FLINT_BIT_COUNT(qlen)); divides = (bits_G + bits_Q + log_length < pack_bits); if (!divides) /* need to multiply out to check exact quotient */ divides = multiplies_out(A, len1, Q, qlen, G, glen, sign1, t); if (divides) /* quotient really was exact */ { mpn_zero(q, qlimbs); if (mpn_divides(q, array2, limbs2, arrayg, limbsg, temp)) { /* unpack quotient of second poly by gcd */ qlimbs = limbs2 - limbsg + 1; qlen = FLINT_MIN(len2, (qlimbs*FLINT_BITS - 1)/pack_bits + 1); _fmpz_poly_bit_unpack(Q, qlen, q, pack_bits, 0); while (Q[qlen - 1] == 0) qlen--; /* check if we really need to multiply out to check for exact quotient */ bits_Q = FLINT_ABS(_fmpz_vec_max_bits(Q, qlen)); log_length = FLINT_MIN(log_glen, FLINT_BIT_COUNT(qlen)); divides = (bits_G + bits_Q + log_length < pack_bits); if (!divides) /* we need to multiply out */ divides = multiplies_out(B, len2, Q, qlen, G, glen, sign1, t); } } _fmpz_vec_clear(t, len1 + glen); _fmpz_vec_clear(Q, len1); } flint_free(q); flint_free(temp); flint_free(arrayg); flint_free(array1); flint_free(array2); fmpz_clear(gc); _fmpz_vec_clear(A, len1); _fmpz_vec_clear(B, len2); /* we found the gcd, so multiply by content */ if (divides) { _fmpz_vec_zero(res + glen, len2 - glen); _fmpz_vec_scalar_mul_fmpz(res, G, glen, d); } fmpz_clear(d); _fmpz_vec_clear(G, glen); return divides; }
static void _qadic_exp_bsplit_series(fmpz *P, fmpz_t Q, fmpz *T, const fmpz *x, slong len, slong lo, slong hi, const fmpz *a, const slong *j, slong lena) { const slong d = j[lena - 1]; if (hi - lo == 1) { _fmpz_vec_set(P, x, len); _fmpz_vec_zero(P + len, 2*d - 1 - len); fmpz_set_si(Q, lo); _fmpz_vec_set(T, P, 2*d - 1); } else if (hi - lo == 2) { _fmpz_poly_sqr(P, x, len); _fmpz_vec_zero(P + (2*len - 1), d - (2*len - 1)); _fmpz_poly_reduce(P, 2*len - 1, a, j, lena); fmpz_set_si(Q, lo); fmpz_mul_si(Q, Q, lo + 1); _fmpz_vec_scalar_mul_si(T, x, len, lo + 1); _fmpz_vec_zero(T + len, d - len); _fmpz_vec_add(T, T, P, d); } else { const slong m = (lo + hi) / 2; fmpz *PR, *TR, *W; fmpz_t QR; PR = _fmpz_vec_init(2*d - 1); TR = _fmpz_vec_init(2*d - 1); W = _fmpz_vec_init(2*d - 1); fmpz_init(QR); _qadic_exp_bsplit_series(P, Q, T, x, len, lo, m, a, j, lena); _qadic_exp_bsplit_series(PR, QR, TR, x, len, m, hi, a, j, lena); _fmpz_poly_mul(W, TR, d, P, d); _fmpz_poly_reduce(W, 2*d - 1, a, j, lena); _fmpz_vec_scalar_mul_fmpz(T, T, d, QR); _fmpz_vec_add(T, T, W, d); _fmpz_poly_mul(W, P, d, PR, d); _fmpz_poly_reduce(W, 2*d - 1, a, j, lena); _fmpz_vec_swap(P, W, d); fmpz_mul(Q, Q, QR); _fmpz_vec_clear(PR, 2*d - 1); _fmpz_vec_clear(TR, 2*d - 1); _fmpz_vec_clear(W, 2*d - 1); fmpz_clear(QR); } }
int main(void) { int i, result; flint_rand_t state; printf("scalar_submul_fmpz...."); fflush(stdout); flint_randinit(state); /* Compare with fmpz_vec_scalar_submul_si */ for (i = 0; i < 10000; i++) { fmpz *a, *b, *c; long len, n; fmpz_t n1; len = n_randint(state, 100); n = (long) n_randbits(state, FLINT_BITS - 1); if (n_randint(state, 2)) n = -n; fmpz_init(n1); fmpz_set_si(n1, n); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); c = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_randtest(b, state, len, 200); _fmpz_vec_set(c, b, len); _fmpz_vec_scalar_submul_fmpz(b, a, len, n1); _fmpz_vec_scalar_submul_si(c, a, len, n); result = (_fmpz_vec_equal(c, b, len)); if (!result) { printf("FAIL:\n"); _fmpz_vec_print(c, len), printf("\n\n"); _fmpz_vec_print(b, len), printf("\n\n"); abort(); } fmpz_clear(n1); _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); } /* Compute a different way */ for (i = 0; i < 10000; i++) { fmpz *a, *b, *c, *d; long len = n_randint(state, 100); fmpz_t n1; fmpz_init(n1); fmpz_randtest(n1, state, 200); a = _fmpz_vec_init(len); b = _fmpz_vec_init(len); c = _fmpz_vec_init(len); d = _fmpz_vec_init(len); _fmpz_vec_randtest(a, state, len, 200); _fmpz_vec_randtest(b, state, len, 200); _fmpz_vec_set(c, b, len); _fmpz_vec_scalar_submul_fmpz(b, a, len, n1); _fmpz_vec_scalar_mul_fmpz(d, a, len, n1); _fmpz_vec_sub(c, c, d, len); result = (_fmpz_vec_equal(c, b, len)); if (!result) { printf("FAIL:\n"); _fmpz_vec_print(c, len), printf("\n\n"); _fmpz_vec_print(b, len), printf("\n\n"); abort(); } fmpz_clear(n1); _fmpz_vec_clear(a, len); _fmpz_vec_clear(b, len); _fmpz_vec_clear(c, len); _fmpz_vec_clear(d, len); } flint_randclear(state); _fmpz_cleanup(); printf("PASS\n"); return 0; }
void _padic_poly_sub(fmpz *rop, slong *val, slong N, const fmpz *op1, slong val1, slong len1, slong N1, const fmpz *op2, slong val2, slong len2, slong N2, const padic_ctx_t ctx) { const slong len = FLINT_MAX(len1, len2); *val = FLINT_MIN(val1, val2); if (val1 == val2) { _fmpz_poly_sub(rop, op1, len1, op2, len2); _padic_poly_canonicalise(rop, val, len, ctx->p); } else { fmpz_t x; fmpz_init(x); if (val1 < val2) /* F := p^g (G - p^{h-g} H) */ { fmpz_pow_ui(x, ctx->p, val2 - val1); if (rop == op1) { _fmpz_vec_zero(rop + len1, len2 - len1); _fmpz_vec_scalar_submul_fmpz(rop, op2, len2, x); } else { _fmpz_vec_scalar_mul_fmpz(rop, op2, len2, x); _fmpz_vec_neg(rop, rop, len2); _fmpz_poly_add(rop, op1, len1, rop, len2); } } else /* F := p^h (p^(g-h) G - H) */ { fmpz_pow_ui(x, ctx->p, val1 - val2); if (rop == op2) { _fmpz_vec_neg(rop, op2, len2); _fmpz_vec_zero(rop + len2, len1 - len2); _fmpz_vec_scalar_addmul_fmpz(rop, op1, len1, x); } else { _fmpz_vec_scalar_mul_fmpz(rop, op1, len1, x); _fmpz_poly_sub(rop, rop, len1, op2, len2); } } fmpz_clear(x); } /* Reduce */ if (N - *val > 0) { fmpz_t pow; int alloc; alloc = _padic_ctx_pow_ui(pow, N - *val, ctx); if (N >= N1 && N >= N2) { slong i; for (i = 0; i < len; i++) if (fmpz_sgn(rop + i) < 0) fmpz_add(rop + i, rop + i, pow); } else { _fmpz_vec_scalar_mod_fmpz(rop, rop, len, pow); } if (alloc) fmpz_clear(pow); } else { _fmpz_vec_zero(rop, len); *val = 0; } }
void _fmpq_poly_scalar_div_mpq(fmpz * rpoly, fmpz_t rden, const fmpz * poly, const fmpz_t den, long len, const fmpz_t r, const fmpz_t s) { fmpz_t gcd1; /* GCD( poly, r ) */ fmpz_t gcd2; /* GCD( s, den ) */ fmpz_init(gcd1); fmpz_init(gcd2); fmpz_set_ui(gcd1, 1); fmpz_set_ui(gcd2, 1); if (*r != 1L) { _fmpz_vec_content(gcd1, poly, len); if (*gcd1 != 1L) fmpz_gcd(gcd1, gcd1, r); } if (*den != 1L && *s != 1L) fmpz_gcd(gcd2, s, den); if (*gcd1 == 1L) { if (*gcd2 == 1L) { _fmpz_vec_scalar_mul_fmpz(rpoly, poly, len, s); fmpz_mul(rden, den, r); } else { fmpz_t s2; fmpz_init(s2); fmpz_divexact(s2, s, gcd2); _fmpz_vec_scalar_mul_fmpz(rpoly, poly, len, s2); fmpz_divexact(rden, den, gcd2); fmpz_mul(rden, rden, r); fmpz_clear(s2); } } else { fmpz_t r2; fmpz_init(r2); fmpz_divexact(r2, r, gcd1); if (*gcd2 == 1L) { _fmpz_vec_scalar_divexact_fmpz(rpoly, poly, len, gcd1); _fmpz_vec_scalar_mul_fmpz(rpoly, rpoly, len, s); fmpz_mul(rden, den, r2); } else { fmpz_t s2; fmpz_init(s2); fmpz_divexact(s2, s, gcd2); _fmpz_vec_scalar_divexact_fmpz(rpoly, poly, len, gcd1); _fmpz_vec_scalar_mul_fmpz(rpoly, rpoly, len, s2); fmpz_divexact(rden, den, gcd2); fmpz_mul(rden, rden, r2); fmpz_clear(s2); } fmpz_clear(r2); } if (_fmpz_vec_is_zero(rpoly, len)) fmpz_set_ui(rden, 1); if (fmpz_sgn(rden) < 0) { _fmpz_vec_neg(rpoly, rpoly, len); fmpz_neg(rden, rden); } fmpz_clear(gcd1); fmpz_clear(gcd2); }
void _fmpz_poly_compose_divconquer(fmpz * res, const fmpz * poly1, long len1, const fmpz * poly2, long len2) { long i, j, k, n; long *hlen, alloc, powlen; fmpz *v, **h, *pow, *temp; if (len1 == 1) { fmpz_set(res, poly1); return; } if (len2 == 1) { _fmpz_poly_evaluate_fmpz(res, poly1, len1, poly2); return; } if (len1 == 2) { _fmpz_poly_compose_horner(res, poly1, len1, poly2, len2); return; } /* Initialisation */ hlen = (long *) malloc(((len1 + 1) / 2) * sizeof(long)); for (k = 1; (2 << k) < len1; k++) ; hlen[0] = hlen[1] = ((1 << k) - 1) * (len2 - 1) + 1; for (i = k - 1; i > 0; i--) { long hi = (len1 + (1 << i) - 1) / (1 << i); for (n = (hi + 1) / 2; n < hi; n++) hlen[n] = ((1 << i) - 1) * (len2 - 1) + 1; } powlen = (1 << k) * (len2 - 1) + 1; alloc = 0; for (i = 0; i < (len1 + 1) / 2; i++) alloc += hlen[i]; v = _fmpz_vec_init(alloc + 2 * powlen); h = (fmpz **) malloc(((len1 + 1) / 2) * sizeof(fmpz *)); h[0] = v; for (i = 0; i < (len1 - 1) / 2; i++) { h[i + 1] = h[i] + hlen[i]; hlen[i] = 0; } hlen[(len1 - 1) / 2] = 0; pow = v + alloc; temp = pow + powlen; /* Let's start the actual work */ for (i = 0, j = 0; i < len1 / 2; i++, j += 2) { if (poly1[j + 1] != 0L) { _fmpz_vec_scalar_mul_fmpz(h[i], poly2, len2, poly1 + j + 1); fmpz_add(h[i], h[i], poly1 + j); hlen[i] = len2; } else if (poly1[j] != 0L) { fmpz_set(h[i], poly1 + j); hlen[i] = 1; } } if ((len1 & 1L)) { if (poly1[j] != 0L) { fmpz_set(h[i], poly1 + j); hlen[i] = 1; } } _fmpz_poly_mul(pow, poly2, len2, poly2, len2); powlen = 2 * len2 - 1; for (n = (len1 + 1) / 2; n > 2; n = (n + 1) / 2) { if (hlen[1] > 0) { long templen = powlen + hlen[1] - 1; _fmpz_poly_mul(temp, pow, powlen, h[1], hlen[1]); _fmpz_poly_add(h[0], temp, templen, h[0], hlen[0]); hlen[0] = FLINT_MAX(hlen[0], templen); } for (i = 1; i < n / 2; i++) { if (hlen[2*i + 1] > 0) { _fmpz_poly_mul(h[i], pow, powlen, h[2*i + 1], hlen[2*i + 1]); hlen[i] = hlen[2*i + 1] + powlen - 1; } else hlen[i] = 0; _fmpz_poly_add(h[i], h[i], hlen[i], h[2*i], hlen[2*i]); hlen[i] = FLINT_MAX(hlen[i], hlen[2*i]); } if ((n & 1L)) { _fmpz_vec_set(h[i], h[2*i], hlen[2*i]); hlen[i] = hlen[2*i]; } _fmpz_poly_mul(temp, pow, powlen, pow, powlen); powlen += powlen - 1; { fmpz * t = pow; pow = temp; temp = t; } } _fmpz_poly_mul(res, pow, powlen, h[1], hlen[1]); _fmpz_vec_add(res, res, h[0], hlen[0]); _fmpz_vec_clear(v, alloc + 2 * powlen); free(h); free(hlen); }
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); } }