# 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

b


2709  2709  sage: pol.factor() 
2710  2710  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) 
2711  2711  
 2712  Check that we do not compute nfinit:: 
 2713  
 2714  sage: x = var('x') 
 2715  sage: N = NumberField(x^22,'x') 
 2716  sage: K = N['x'] 
 2717  sage: f1 = K.random_element(3) 
 2718  sage: f2 = K.random_element(3) 
 2719  sage: f = f1*f2 
 2720  sage: hasattr(N, '_NumberField_generic__pari_nf') 
 2721  False 
 2722  sage: F1 = factor(f) 
 2723  sage: hasattr(N, '_NumberField_generic__pari_nf') 
 2724  False 
 2725  sage: _ = N.pari_nf() 
 2726  sage: F2 = factor(f) 
 2727  sage: hasattr(N, '_NumberField_generic__pari_nf') 
 2728  True 
 2729  sage: F1 f 
 2730  0 
 2731  sage: F2 f 
 2732  0 
 2733  
 2734  Next example would be very slow if we had to compute a nfinit structure. See #10910:: 
 2735  
 2736  sage: x = var('x') 
 2737  sage: N = NumberField(x^8+1212/413*x^7+1222*x+1/17,'a') 
 2738  sage: K.<t> = N[] 
 2739  sage: f = K.random_element(4) 
 2740  sage: g = K.random_element(4) 
 2741  sage: F = factor(f*g) 
 2742  sage: F  f*g 
 2743  0 
 2744  sage: hasattr(N, '_NumberField_generic__pari_nf') 
 2745  False 
 2746  
 2747  Check that the factorization is correct. See #10910:: 
 2748  
 2749  sage: K=QQ[sqrt(2**40+1), 3^(1/3)] 
 2750  sage: x = polygen(K) 
 2751  sage: f = x^3  3 
 2752  sage: len(factor(f)) 
 2753  2 
2712  2754  """ 
2713  2755  # PERFORMANCE NOTE: 
2714  2756  # In many tests with SMALL degree PARI is substantially 
… 
… 

2777  2819  g = M['x']([to_M(x) for x in self.list()]) 
2778  2820  F = g.factor() 
2779  2821  S = self.parent() 
2780   v = [(S([from_M(x) for x in f.list()]), e) for f, e in g.factor()] 
 2822  v = [(S([from_M(x) for x in f.list()]), e) for f, e in F] 
2781  2823  return Factorization(v, from_M(F.unit())) 
2782  2824  
2783  2825  elif is_FiniteField(R): 
… 
… 

2811  2853  if R.defining_polynomial().denominator() == 1: 
2812  2854  v = [ x._pari_("a") for x in self.list() ] 
2813  2855  f = pari(v).Polrev() 
2814   Rpari = R.pari_nf() 
2815   if (Rpari.variable() != "a"): 
2816   Rpari = copy.copy(Rpari) 
2817   Rpari[0] = Rpari[0]("a") 
2818   Rpari[6] = [ x("a") for x in Rpari[6] ] 
2819   G = list(Rpari.nffactor(f)) 
2820   # PARI's nffactor() ignores the unit, _factor_pari_helper() 
2821   # adds back the unit of the factorization. 
 2856  if hasattr(R, '_NumberField_generic__pari_nf'): 
 2857  # If we have a nf structure, this should be faster 
 2858  Rpari = R.pari_nf() 
 2859  if (Rpari.variable() != "a"): 
 2860  Rpari = copy.copy(Rpari) 
 2861  Rpari[0] = Rpari[0]("a") 
 2862  Rpari[6] = [ x("a") for x in Rpari[6] ] 
 2863  G = list(Rpari.nffactor(f)) 
 2864  # PARI's nffactor() ignores the unit, _factor_pari_helper() 
 2865  # adds back the unit of the factorization. 
 2866  
 2867  else: 
 2868  # We do not compute a nf structure, since it may be 
 2869  # expensive 
 2870  nf = R.pari_polynomial('a') 
 2871  G = list(nf.nffactor(f)) 
 2872  
2822  2873  return self._factor_pari_helper(G) 
2823  2874  
2824  2875  else: 
2825  2876  
2826  2877  Rdenom = R.defining_polynomial().denominator() 
2827   
2828   new_Rpoly = (R.defining_polynomial() * Rdenom).change_variable_name("a") 
2829   
2830   Rpari, Rdiff = new_Rpoly._pari_().nfinit(3) 
2831   
2832   AZ = QQ['z'] 
2833   Raux = NumberField(AZ(Rpari[0]),'alpha') 
2834   
2835   S, gSRaux, fRauxS = Raux.change_generator(Raux(Rdiff)) 
2836   
2837   phi_RS = R.Hom(S)([S.gen(0)]) 
2838   phi_SR = S.Hom(R)([R.gen(0)]) 
2839   
 2878  d = R.degree() 
 2879  Rdenom_d = Rdenom**d 
 2880  x = R.polynomial_ring().gen() 
 2881  new_Rpoly = R.defining_polynomial()(x/Rdenom)*Rdenom_d 
 2882  
 2883  S = NumberField(new_Rpoly, 'alpha') 
 2884  phi_RS = R.Hom(S)([S.gen()/Rdenom]) 
 2885  phi_SR = S.Hom(R)([R.gen()*Rdenom]) 
2840  2886  unit = self.leading_coefficient() 
2841   temp_f = self * 1/unit 
2842   
2843   v = [ gSRaux(phi_RS(x))._pari_("a") for x in temp_f.list() ] 
 2887  temp_f = self * ~unit 
 2888  v = [ (phi_RS(x))._pari_("a") for x in temp_f.list() ] 
2844  2889  f = pari(v).Polrev() 
2845   
2846   pari_factors = Rpari.nffactor(f) 
2847   
2848   factors = [ ( self.parent([ phi_SR(fRauxS(Raux(pari_factors[0][i][j]))) 
2849   for j in range(len(pari_factors[0][i])) ]) , 
2850   int(pari_factors[1][i]) ) 
 2890  nf = S.pari_polynomial('a') 
 2891  pari_factors = nf.nffactor(f) 
 2892  factors = [ ( self.parent([ phi_SR(S(pari_factors[0][i][j])) 
 2893  for j in range(len(pari_factors[0][i])) ]) , 
 2894  int(pari_factors[1][i]) ) 
2851  2895  for i in range(pari_factors.nrows()) ] 
2852  2896  
2853  2897  return Factorization(factors, unit) 
2854   
2855  2898  
2856  2899  elif is_RealField(R): 
2857  2900  n = pari.set_real_precision(int(3.5*R.prec()) + 1) 