/* Copyright (C) 2014 William Hart Copyright (C) 2015 Claus Fieker This file is part of FLINT. FLINT is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. See . */ #include #include "flint.h" #include "fmpz.h" #include "fmpz_vec.h" #include "fmpz_poly.h" #include "mpn_extras.h" void _fmpz_poly_resultant_modular_div(fmpz_t res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2, const fmpz_t divisor, slong nbits) { flint_bitcnt_t pbits; slong i, num_primes; fmpz_comb_t comb; fmpz_comb_temp_t comb_temp; fmpz_t ac, bc, l, modulus, div, la, lb; fmpz * A, * B, * lead_A, * lead_B; mp_ptr a, b, rarr, parr; mp_limb_t p, d; nmod_t mod; if (fmpz_is_zero(divisor)) { fmpz_zero(res); return; } /* special case, one of the polys is a constant */ if (len2 == 1) /* if len1 == 1 then so does len2 */ { fmpz_pow_ui(res, poly2, len1 - 1); fmpz_divexact(res, res, divisor); return; } fmpz_init(ac); fmpz_init(bc); /* compute content of poly1 and poly2 */ _fmpz_vec_content(ac, poly1, len1); _fmpz_vec_content(bc, poly2, len2); /* 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_init(l); /* we have, originally // res(p1, p2) = r d // with nbits(r) <= nbits // Now // res(p1, p2) = ac^(len2-1) bc^(len1-1) res(A, B) // So we need to split ac^(len2-1) bc^(len1-1) = xy // such that d mod x == 0 and gcd(ac^... /x, y) = 1 // Then we need to compute res(A,B)/(d/x) // res(p1, p2) = x y res(A,B) = r d // and // r = x y res(A,B)/d = y res(A, B)/(d/x) // The length of res(A, B) shrinks by length(y) */ if (!fmpz_is_one(ac)) { fmpz_pow_ui(l, ac, len2 - 1); fmpz_init(div); fmpz_init(la); fmpz_gcd(div, l, divisor); /* div = gcd(ac^(len2-1), divisor) */ fmpz_divexact(la, l, div); /* la = ac^(len2 -1)/gcd */ fmpz_divexact(div, divisor, div); /*div /= gcd */ nbits = nbits - fmpz_bits(la) + 1; } else { fmpz_init_set(div, divisor); } if (!fmpz_is_one(bc)) { fmpz_init(lb); fmpz_pow_ui(lb, bc, len1 - 1); fmpz_gcd(l, lb, div); fmpz_divexact(lb, lb, l); fmpz_divexact(div, div, l); nbits = nbits - fmpz_bits(lb) + 1; } /* get product of leading coefficients */ lead_A = A + len1 - 1; lead_B = B + len2 - 1; fmpz_mul(l, lead_A, lead_B); fmpz_init(modulus); fmpz_set_ui(modulus, 1); fmpz_zero(res); /* make space for polynomials mod p */ a = _nmod_vec_init(len1); b = _nmod_vec_init(len2); pbits = FLINT_BITS - 1; p = (UWORD(1)<length; slong len2 = poly2->length; if (len1 == 0 || len2 == 0 || fmpz_is_zero(divisor)) fmpz_zero(res); else if (len1 >= len2) _fmpz_poly_resultant_modular_div(res, poly1->coeffs, len1, poly2->coeffs, len2, divisor, nbits); else { _fmpz_poly_resultant_modular_div(res, poly2->coeffs, len2, poly1->coeffs, len1, divisor, nbits); if ((len1 > 1) && (!(len1 & WORD(1)) & !(len2 & WORD(1)))) fmpz_neg(res, res); } }