void nf_elem_scalar_div_fmpq(nf_elem_t a, const nf_elem_t b, const fmpq_t c, const nf_t nf) { if (nf->flag & NF_LINEAR) { fmpz * den = LNF_ELEM_DENREF(a); fmpz * num = LNF_ELEM_NUMREF(a); const fmpz * const den2 = LNF_ELEM_DENREF(b); const fmpz * const num2 = LNF_ELEM_NUMREF(b); _fmpq_mul(num, den, num2, den2, fmpq_denref(c), fmpq_numref(c)); } else if (nf->flag & NF_QUADRATIC) { fmpz * den = QNF_ELEM_DENREF(a); fmpz * num = QNF_ELEM_NUMREF(a); const fmpz * const den2 = QNF_ELEM_DENREF(b); const fmpz * const num2 = QNF_ELEM_NUMREF(b); _fmpq_poly_scalar_div_fmpq(num, den, num2, den2, 2, fmpq_numref(c), fmpq_denref(c)); } else { fmpq_poly_scalar_div_fmpq(NF_ELEM(a), NF_ELEM(b), c); } }
void _fmpq_poly_div(fmpz * Q, fmpz_t q, const fmpz * A, const fmpz_t a, long lenA, const fmpz * B, const fmpz_t b, long lenB) { long lenQ = lenA - lenB + 1; ulong d; const fmpz * lead = B + (lenB - 1); if (lenB == 1) { _fmpq_poly_scalar_div_fmpq(Q, q, A, a, lenA, B, b); return; } /* From pseudo division over Z we have lead^d * A = Q * B + R and thus {A, a} = {b * Q, a * lead^d} * {B, b} + {R, a * lead^d}. */ _fmpz_poly_pseudo_div(Q, &d, A, lenA, B, lenB); /* 1. lead^d == +-1. {Q, q} = {b Q, a} up to sign */ if (d == 0UL || *lead == 1L || *lead == -1L) { fmpz_one(q); _fmpq_poly_scalar_mul_fmpz(Q, q, Q, q, lenQ, b); _fmpq_poly_scalar_div_fmpz(Q, q, Q, q, lenQ, a); if (*lead == -1L && d % 2UL) _fmpz_vec_neg(Q, Q, lenQ); } /* 2. lead^d != +-1. {Q, q} = {b Q, a lead^d} */ else { /* TODO: Improve this. Clearly we do not need to compute den = a lead^d in many cases, but can determine the GCD from lead alone already. */ fmpz_t den; fmpz_init(den); fmpz_pow_ui(den, lead, d); fmpz_mul(den, a, den); fmpz_one(q); _fmpq_poly_scalar_mul_fmpz(Q, q, Q, q, lenQ, b); _fmpq_poly_scalar_div_fmpz(Q, q, Q, q, lenQ, den); fmpz_clear(den); } }
void fmpq_poly_scalar_div_fmpq(fmpq_poly_t rop, const fmpq_poly_t op, const fmpq_t c) { if (fmpq_is_zero(c)) { flint_printf("Exception (fmpq_poly_scalar_div_fmpq). Division by zero.\n"); abort(); } if (fmpq_poly_is_zero(op)) { fmpq_poly_zero(rop); } else { fmpq_poly_fit_length(rop, op->length); _fmpq_poly_set_length(rop, op->length); _fmpq_poly_scalar_div_fmpq(rop->coeffs, rop->den, op->coeffs, op->den, op->length, fmpq_numref(c), fmpq_denref(c)); } }
void _fmpq_poly_divrem(fmpz * Q, fmpz_t q, fmpz * R, fmpz_t r, const fmpz * A, const fmpz_t a, slong lenA, const fmpz * B, const fmpz_t b, slong lenB, const fmpz_preinvn_t inv) { slong lenQ = lenA - lenB + 1; slong lenR = lenB - 1; ulong d; const fmpz * lead = B + (lenB - 1); if (lenB == 1) { _fmpq_poly_scalar_div_fmpq(Q, q, A, a, lenA, B, b); fmpz_one(r); return; } /* From pseudo division over Z we have lead^d * A = Q * B + R and thus {A, a} = {b * Q, a * lead^d} * {B, b} + {R, a * lead^d}. */ _fmpz_poly_pseudo_divrem(Q, R, &d, A, lenA, B, lenB, inv); /* Determine the actual length of R */ for ( ; lenR != 0 && fmpz_is_zero(R + (lenR - 1)); lenR--) ; /* 1. lead^d == +-1. {Q, q} = {b Q, a}, {R, r} = {R, a} up to sign */ if (d == UWORD(0) || *lead == WORD(1) || *lead == WORD(-1)) { fmpz_one(q); _fmpq_poly_scalar_mul_fmpz(Q, q, Q, q, lenQ, b); _fmpq_poly_scalar_div_fmpz(Q, q, Q, q, lenQ, a); fmpz_one(r); if (lenR > 0) _fmpq_poly_scalar_div_fmpz(R, r, R, r, lenR, a); if (*lead == WORD(-1) && d % UWORD(2)) { _fmpz_vec_neg(Q, Q, lenQ); _fmpz_vec_neg(R, R, lenR); } } /* 2. lead^d != +-1. {Q, q} = {b Q, a lead^d}, {R, r} = {R, a lead^d} */ else { /* TODO: Improve this. Clearly we do not need to compute den = a lead^d in many cases, but can determine the GCD from lead alone already. */ fmpz_t den; fmpz_init(den); fmpz_pow_ui(den, lead, d); fmpz_mul(den, a, den); fmpz_one(q); _fmpq_poly_scalar_mul_fmpz(Q, q, Q, q, lenQ, b); _fmpq_poly_scalar_div_fmpz(Q, q, Q, q, lenQ, den); fmpz_one(r); if (lenR > 0) _fmpq_poly_scalar_div_fmpz(R, r, R, r, lenR, den); fmpz_clear(den); } }