# Ticket #10910: factor_nfinit_free.patch

File factor_nfinit_free.patch, 5.9 KB (added by lftabera, 10 years ago)

the good one

• ## sage/rings/polynomial/polynomial_element.pyx

```# HG changeset patch
# User Luis Felipe Tabera Alonso <lftabera@yahoo.es>
# Parent 2a2abbcad325ccca9399981ceddf5897eb467e64
#10910 Avoid nfinit while factoring polynomials

diff -r 2a2abbcad325 sage/rings/polynomial/polynomial_element.pyx```
 a sage: pol.factor() x^5 * (x^5 + (4/7*a - 6/7)*x^4 + (9/49*a^2 - 3/7*a + 15/49)*x^3 + (8/343*a^3 - 32/343*a^2 + 40/343*a - 20/343)*x^2 + (5/2401*a^4 - 20/2401*a^3 + 40/2401*a^2 - 5/343*a + 15/2401)*x - 6/16807*a^4 + 12/16807*a^3 - 18/16807*a^2 + 12/16807*a - 6/16807) Check that we do not compute nfinit:: sage: x = var('x') sage: N = NumberField(x^2-2,'x') sage: K = N['x'] sage: f1 = K.random_element(3) sage: f2 = K.random_element(3) sage: f = f1*f2 sage: hasattr(N, '_NumberField_generic__pari_nf') False sage: F1 = factor(f) sage: hasattr(N, '_NumberField_generic__pari_nf') False sage: _ = N.pari_nf() sage: F2 = factor(f) sage: hasattr(N, '_NumberField_generic__pari_nf') True sage: F1 -f 0 sage: F2 -f 0 Next example would be very slow if we had to compute a nfinit             structure. See #10910:: sage: x = var('x') sage: N = NumberField(x^8+1212/413*x^7+1222*x+1/17,'a') sage: K. = N[] sage: f = K.random_element(4) sage: g = K.random_element(4) sage: F = factor(f*g) sage: F - f*g 0 sage: hasattr(N, '_NumberField_generic__pari_nf') False Check that the factorization is correct. See #10910:: sage: K=QQ[sqrt(2**40+1), 3^(1/3)] sage: x = polygen(K) sage: f = x^3 - 3 sage: len(factor(f)) 2 """ # PERFORMANCE NOTE: #     In many tests with SMALL degree PARI is substantially g = M['x']([to_M(x) for x in self.list()]) F = g.factor() S = self.parent() v = [(S([from_M(x) for x in f.list()]), e) for f, e in g.factor()] v = [(S([from_M(x) for x in f.list()]), e) for f, e in F] return Factorization(v, from_M(F.unit())) elif is_FiniteField(R): if R.defining_polynomial().denominator() == 1: v = [ x._pari_("a") for x in self.list() ] f = pari(v).Polrev() Rpari = R.pari_nf() if (Rpari.variable() != "a"): Rpari = copy.copy(Rpari) Rpari[0] = Rpari[0]("a") Rpari[6] = [ x("a") for x in Rpari[6] ] G = list(Rpari.nffactor(f)) # PARI's nffactor() ignores the unit, _factor_pari_helper() # adds back the unit of the factorization. if hasattr(R, '_NumberField_generic__pari_nf'): # If we have a nf structure, this should be faster Rpari = R.pari_nf() if (Rpari.variable() != "a"): Rpari = copy.copy(Rpari) Rpari[0] = Rpari[0]("a") Rpari[6] = [ x("a") for x in Rpari[6] ] G = list(Rpari.nffactor(f)) # PARI's nffactor() ignores the unit, _factor_pari_helper() # adds back the unit of the factorization. else: # We do not compute a nf structure, since it may be # expensive nf = R.pari_polynomial('a') G = list(nf.nffactor(f)) return self._factor_pari_helper(G) else: Rdenom = R.defining_polynomial().denominator() new_Rpoly = (R.defining_polynomial() * Rdenom).change_variable_name("a") Rpari, Rdiff = new_Rpoly._pari_().nfinit(3) AZ = QQ['z'] Raux = NumberField(AZ(Rpari[0]),'alpha') S, gSRaux, fRauxS = Raux.change_generator(Raux(Rdiff)) phi_RS = R.Hom(S)([S.gen(0)]) phi_SR = S.Hom(R)([R.gen(0)]) d = R.degree() Rdenom_d = Rdenom**d x = R.polynomial_ring().gen() new_Rpoly = R.defining_polynomial()(x/Rdenom)*Rdenom_d S = NumberField(new_Rpoly, 'alpha') phi_RS = R.Hom(S)([S.gen()/Rdenom]) phi_SR = S.Hom(R)([R.gen()*Rdenom]) unit = self.leading_coefficient() temp_f = self * 1/unit v = [ gSRaux(phi_RS(x))._pari_("a") for x in temp_f.list() ] temp_f = self * ~unit v = [ (phi_RS(x))._pari_("a") for x in temp_f.list() ] f = pari(v).Polrev() pari_factors = Rpari.nffactor(f) factors = [ ( self.parent([ phi_SR(fRauxS(Raux(pari_factors[0][i][j]))) for j in range(len(pari_factors[0][i])) ]) , int(pari_factors[1][i]) ) nf = S.pari_polynomial('a') pari_factors = nf.nffactor(f) factors = [ ( self.parent([ phi_SR(S(pari_factors[0][i][j])) for j in range(len(pari_factors[0][i])) ]) , int(pari_factors[1][i]) ) for i in range(pari_factors.nrows()) ] return Factorization(factors, unit) elif is_RealField(R): n = pari.set_real_precision(int(3.5*R.prec()) + 1)