facFqBivar.cc
Go to the documentation of this file.
1 /*****************************************************************************\
2  * Computer Algebra System SINGULAR
3 \*****************************************************************************/
4 /** @file facFqBivar.cc
5  *
6  * This file provides functions for factorizing a bivariate polynomial over
7  * \f$ F_{p} \f$ , \f$ F_{p}(\alpha ) \f$ or GF, based on "Modern Computer
8  * Algebra, Chapter 15" by J. von zur Gathen & J. Gerhard and "Factoring
9  * multivariate polynomials over a finite field" by L. Bernardin.
10  * Factor Recombination is described in "Factoring polynomials over global
11  * fields" by K. Belabas, M. van Hoeij, J. Klueners, A. Steel
12  *
13  *
14  * @author Martin Lee
15  *
16  **/
17 /*****************************************************************************/
18 
19 
20 #include "config.h"
21 
22 
23 #include "cf_assert.h"
24 #include "debug.h"
25 #include "timing.h"
26 
27 #include "canonicalform.h"
28 #include "cf_defs.h"
29 #include "cf_map_ext.h"
30 #include "cf_random.h"
31 #include "facHensel.h"
32 #include "facMul.h"
33 #include "cf_map.h"
34 #include "cf_irred.h"
35 #include "facFqBivarUtil.h"
36 #include "facFqBivar.h"
37 #include "cfNewtonPolygon.h"
38 
39 #ifdef HAVE_NTL
40 #include "NTLconvert.h"
41 
42 #ifdef HAVE_FLINT
43 #include "FLINTconvert.h"
44 #endif
45 
46 TIMING_DEFINE_PRINT(fac_fq_uni_factorizer)
47 TIMING_DEFINE_PRINT(fac_fq_bi_hensel_lift)
48 TIMING_DEFINE_PRINT(fac_fq_bi_factor_recombination)
49 TIMING_DEFINE_PRINT(fac_fq_bi_evaluation)
50 TIMING_DEFINE_PRINT(fac_fq_bi_shift_to_zero)
51 TIMING_DEFINE_PRINT(fac_fq_logarithmic)
52 TIMING_DEFINE_PRINT(fac_fq_compute_lattice_lift)
53 TIMING_DEFINE_PRINT(fac_fq_till_reduced)
54 TIMING_DEFINE_PRINT(fac_fq_reconstruction)
55 TIMING_DEFINE_PRINT(fac_fq_lift)
56 TIMING_DEFINE_PRINT(fac_fq_uni_total)
57 
59 {
60  if (L.isEmpty())
61  return 1;
62  else if (L.length() == 1)
63  return mod (L.getFirst()(0, 1) , M);
64  else if (L.length() == 2)
65  return mod (mulNTL (L.getFirst()(0, 1),L.getLast()(0, 1), b), M);
66  else
67  {
68  int l= L.length()/2;
72  for (int j= 1; j <= l; j++, i++)
73  tmp1.append (i.getItem());
74  tmp2= Difference (L, tmp1);
75  buf1= prodMod0 (tmp1, M, b);
76  buf2= prodMod0 (tmp2, M, b);
77  return mod (mulNTL (buf1,buf2, b), M);
78  }
79 }
80 
82  const Variable& alpha, CFList& list, const bool& GF,
83  bool& fail)
84 {
85  fail= false;
86  Variable x= Variable(2);
87  Variable y= Variable(1);
88  FFRandom genFF;
89  GFRandom genGF;
90  CanonicalForm random, mipo;
91  double bound;
92  int p= getCharacteristic ();
93  if (alpha.level() != 1)
94  {
95  mipo= getMipo (alpha);
96  int d= degree (mipo);
97  bound= pow ((double) p, (double) d);
98  }
99  else if (GF)
100  {
101  int d= getGFDegree();
102  bound= ipower (p, d);
103  }
104  else
105  bound= p;
106 
107  random= 0;
108  do
109  {
110  if (list.length() >= bound)
111  {
112  fail= true;
113  break;
114  }
115  if (list.isEmpty())
116  random= 0;
117  else if (GF)
118  {
119  if (list.length() == 1)
120  random= getGFGenerator();
121  else
122  random= genGF.generate();
123  }
124  else if (list.length() < p || alpha.level() == 1)
125  random= genFF.generate();
126  else if (alpha != x && list.length() >= p)
127  {
128  if (list.length() == p)
129  random= alpha;
130  else
131  {
132  AlgExtRandomF genAlgExt (alpha);
133  random= genAlgExt.generate();
134  }
135  }
136  if (find (list, random)) continue;
137  eval= F (random, x);
138  if (degree (eval) != degree (F, y))
139  { //leading coeff vanishes
140  if (!find (list, random))
141  list.append (random);
142  continue;
143  }
144  if (degree (gcd (deriv (eval, eval.mvar()), eval), eval.mvar()) > 0)
145  { //evaluated polynomial is not squarefree
146  if (!find (list, random))
147  list.append (random);
148  continue;
149  }
150  } while (find (list, random));
151 
152  return random;
153 }
154 
155 CFList
156 uniFactorizer (const CanonicalForm& A, const Variable& alpha, const bool& GF)
157 {
158  Variable x= A.mvar();
159  if (A.inCoeffDomain())
160  return CFList();
161  ASSERT (A.isUnivariate(),
162  "univariate polynomial expected or constant expected");
163  CFFList factorsA;
164  if (GF)
165  {
166  int k= getGFDegree();
167  char cGFName= gf_name;
170  Variable beta= rootOf (mipo.mapinto());
171  CanonicalForm buf= GF2FalphaRep (A, beta);
172  if (getCharacteristic() > 2)
173  {
174 #if (HAVE_FLINT && __FLINT_RELEASE >= 20400)
175  nmod_poly_t FLINTmipo, leadingCoeff;
176  fq_nmod_ctx_t fq_con;
177  fq_nmod_poly_t FLINTA;
178  fq_nmod_poly_factor_t FLINTFactorsA;
179 
180  nmod_poly_init (FLINTmipo, getCharacteristic());
181  convertFacCF2nmod_poly_t (FLINTmipo, mipo.mapinto());
182 
183  fq_nmod_ctx_init_modulus (fq_con, FLINTmipo, "Z");
184 
185  convertFacCF2Fq_nmod_poly_t (FLINTA, buf, fq_con);
186  fq_nmod_poly_make_monic (FLINTA, FLINTA, fq_con);
187 
188  fq_nmod_poly_factor_init (FLINTFactorsA, fq_con);
189  nmod_poly_init (leadingCoeff, getCharacteristic());
190 
191  fq_nmod_poly_factor (FLINTFactorsA, leadingCoeff, FLINTA, fq_con);
192 
193  factorsA= convertFLINTFq_nmod_poly_factor2FacCFFList (FLINTFactorsA, x,
194  beta, fq_con);
195 
196  fq_nmod_poly_factor_clear (FLINTFactorsA, fq_con);
197  fq_nmod_poly_clear (FLINTA, fq_con);
198  nmod_poly_clear (FLINTmipo);
199  nmod_poly_clear (leadingCoeff);
200  fq_nmod_ctx_clear (fq_con);
201 #else
203  {
205  zz_p::init (getCharacteristic());
206  }
207  zz_pX NTLMipo= convertFacCF2NTLzzpX (mipo.mapinto());
208  zz_pE::init (NTLMipo);
209  zz_pEX NTLA= convertFacCF2NTLzz_pEX (buf, NTLMipo);
210  MakeMonic (NTLA);
211  vec_pair_zz_pEX_long NTLFactorsA= CanZass (NTLA);
212  zz_pE multi= to_zz_pE (1);
213  factorsA= convertNTLvec_pair_zzpEX_long2FacCFFList (NTLFactorsA, multi,
214  x, beta);
215 #endif
216  }
217  else
218  {
219  GF2X NTLMipo= convertFacCF2NTLGF2X (mipo.mapinto());
220  GF2E::init (NTLMipo);
221  GF2EX NTLA= convertFacCF2NTLGF2EX (buf, NTLMipo);
222  MakeMonic (NTLA);
223  vec_pair_GF2EX_long NTLFactorsA= CanZass (NTLA);
224  GF2E multi= to_GF2E (1);
225  factorsA= convertNTLvec_pair_GF2EX_long2FacCFFList (NTLFactorsA, multi,
226  x, beta);
227  }
228  setCharacteristic (getCharacteristic(), k, cGFName);
229  for (CFFListIterator i= factorsA; i.hasItem(); i++)
230  {
231  buf= i.getItem().factor();
232  buf= Falpha2GFRep (buf);
233  i.getItem()= CFFactor (buf, i.getItem().exp());
234  }
235  prune (beta);
236  }
237  else if (alpha.level() != 1)
238  {
239  if (getCharacteristic() > 2)
240  {
241 #if (HAVE_FLINT && __FLINT_RELEASE >= 20400)
242  nmod_poly_t FLINTmipo, leadingCoeff;
243  fq_nmod_ctx_t fq_con;
244  fq_nmod_poly_t FLINTA;
245  fq_nmod_poly_factor_t FLINTFactorsA;
246 
247  nmod_poly_init (FLINTmipo, getCharacteristic());
248  convertFacCF2nmod_poly_t (FLINTmipo, getMipo (alpha));
249 
250  fq_nmod_ctx_init_modulus (fq_con, FLINTmipo, "Z");
251 
252  convertFacCF2Fq_nmod_poly_t (FLINTA, A, fq_con);
253  fq_nmod_poly_make_monic (FLINTA, FLINTA, fq_con);
254 
255  fq_nmod_poly_factor_init (FLINTFactorsA, fq_con);
256  nmod_poly_init (leadingCoeff, getCharacteristic());
257 
258  fq_nmod_poly_factor (FLINTFactorsA, leadingCoeff, FLINTA, fq_con);
259 
260  factorsA= convertFLINTFq_nmod_poly_factor2FacCFFList (FLINTFactorsA, x,
261  alpha, fq_con);
262 
263  fq_nmod_poly_factor_clear (FLINTFactorsA, fq_con);
264  fq_nmod_poly_clear (FLINTA, fq_con);
265  nmod_poly_clear (FLINTmipo);
266  nmod_poly_clear (leadingCoeff);
267  fq_nmod_ctx_clear (fq_con);
268 #else
270  {
272  zz_p::init (getCharacteristic());
273  }
274  zz_pX NTLMipo= convertFacCF2NTLzzpX (getMipo (alpha));
275  zz_pE::init (NTLMipo);
276  zz_pEX NTLA= convertFacCF2NTLzz_pEX (A, NTLMipo);
277  MakeMonic (NTLA);
278  vec_pair_zz_pEX_long NTLFactorsA= CanZass (NTLA);
279  zz_pE multi= to_zz_pE (1);
280  factorsA= convertNTLvec_pair_zzpEX_long2FacCFFList (NTLFactorsA, multi,
281  x, alpha);
282 #endif
283  }
284  else
285  {
286  GF2X NTLMipo= convertFacCF2NTLGF2X (getMipo (alpha));
287  GF2E::init (NTLMipo);
288  GF2EX NTLA= convertFacCF2NTLGF2EX (A, NTLMipo);
289  MakeMonic (NTLA);
290  vec_pair_GF2EX_long NTLFactorsA= CanZass (NTLA);
291  GF2E multi= to_GF2E (1);
292  factorsA= convertNTLvec_pair_GF2EX_long2FacCFFList (NTLFactorsA, multi,
293  x, alpha);
294  }
295  }
296  else
297  {
298 #ifdef HAVE_FLINT
299  if (degree (A) < 300)
300  {
301  nmod_poly_t FLINTA;
302  convertFacCF2nmod_poly_t (FLINTA, A);
303  nmod_poly_factor_t result;
304  nmod_poly_factor_init (result);
305  mp_limb_t leadingCoeff= nmod_poly_factor (result, FLINTA);
306  factorsA= convertFLINTnmod_poly_factor2FacCFFList (result, leadingCoeff, x);
307  if (factorsA.getFirst().factor().inCoeffDomain())
308  factorsA.removeFirst();
309  nmod_poly_factor_clear (result);
310  nmod_poly_clear (FLINTA);
311  }
312  else
313 #endif
314  if (getCharacteristic() > 2)
315  {
317  {
319  zz_p::init (getCharacteristic());
320  }
321  zz_pX NTLA= convertFacCF2NTLzzpX (A);
322  MakeMonic (NTLA);
323  vec_pair_zz_pX_long NTLFactorsA= CanZass (NTLA);
324  zz_p multi= to_zz_p (1);
325  factorsA= convertNTLvec_pair_zzpX_long2FacCFFList (NTLFactorsA, multi,
326  x);
327  }
328  else
329  {
330  GF2X NTLA= convertFacCF2NTLGF2X (A);
331  vec_pair_GF2X_long NTLFactorsA= CanZass (NTLA);
332  GF2 multi= to_GF2 (1);
333  factorsA= convertNTLvec_pair_GF2X_long2FacCFFList (NTLFactorsA, multi,
334  x);
335  }
336  }
337  CFList uniFactors;
338  for (CFFListIterator i= factorsA; i.hasItem(); i++)
339  uniFactors.append (i.getItem().factor());
340  return uniFactors;
341 }
342 
343 /// naive factor recombination as decribed in "Factoring
344 /// multivariate polynomials over a finite field" by L Bernardin.
345 CFList
347  const CanonicalForm& N, const ExtensionInfo& info,
348  DegreePattern& degs, const CanonicalForm& eval, int s,
349  int thres)
350 {
351  if (factors.length() == 0)
352  {
353  F= 1;
354  return CFList();
355  }
356  if (F.inCoeffDomain())
357  return CFList();
358 
359  Variable alpha= info.getAlpha();
360  Variable beta= info.getBeta();
361  CanonicalForm gamma= info.getGamma();
362  CanonicalForm delta= info.getDelta();
363  int k= info.getGFDegree();
364 
365  CanonicalForm M= N;
366  int l= degree (N);
367  Variable y= F.mvar();
368  Variable x= Variable (1);
369  CFList source, dest;
370  if (degs.getLength() <= 1 || factors.length() == 1)
371  {
372  CFList result= CFList(mapDown (F(y-eval, y), info, source, dest));
373  F= 1;
374  return result;
375  }
376 
377  DEBOUTLN (cerr, "LC (F, 1)*prodMod (factors, M) == F " <<
378  (mod (LC (F, 1)*prodMod (factors, M), M)/Lc (mod (LC (F, 1)*prodMod (factors, M), M)) == F/Lc (F)));
379  int degMipoBeta= 1;
380  if (!k && beta.level() != 1)
381  degMipoBeta= degree (getMipo (beta));
382 
383  CFList T, S, Diff;
384  T= factors;
385 
386  CFList result;
387  CanonicalForm buf, buf2, quot;
388 
389  buf= F;
390 
391  CanonicalForm g, LCBuf= LC (buf, x);
392  int * v= new int [T.length()];
393  for (int i= 0; i < T.length(); i++)
394  v[i]= 0;
395 
396  CFArray TT;
397  DegreePattern bufDegs1, bufDegs2;
398  bufDegs1= degs;
399  int subsetDeg;
400  TT= copy (factors);
401  bool nosubset= false;
402  bool recombination= false;
403  bool trueFactor= false;
405  CanonicalForm buf0= buf (0, x)*LCBuf;
406  while (T.length() >= 2*s && s <= thres)
407  {
408  while (nosubset == false)
409  {
410  if (T.length() == s)
411  {
412  delete [] v;
413  if (recombination)
414  {
415  T.insert (LCBuf);
416  g= prodMod (T, M);
417  T.removeFirst();
418  g /= content(g);
419  g= g (y - eval, y);
420  g /= Lc (g);
421  appendTestMapDown (result, g, info, source, dest);
422  F= 1;
423  return result;
424  }
425  else
426  {
427  appendMapDown (result, F (y - eval, y), info, source, dest);
428  F= 1;
429  return result;
430  }
431  }
432  S= subset (v, s, TT, nosubset);
433  if (nosubset) break;
434  subsetDeg= subsetDegree (S);
435  // skip those combinations that are not possible
436  if (!degs.find (subsetDeg))
437  continue;
438  else
439  {
440  test= prodMod0 (S, M);
441  test *= LCBuf;
442  test = mod (test, M);
443  if (fdivides (test, buf0))
444  {
445  S.insert (LCBuf);
446  g= prodMod (S, M);
447  S.removeFirst();
448  g /= content (g, x);
449  if (fdivides (g, buf, quot))
450  {
451  buf2= g (y - eval, y);
452  buf2 /= Lc (buf2);
453 
454  if (!k && beta.level() == 1)
455  {
456  if (degree (buf2, alpha) < degMipoBeta)
457  {
458  buf= quot;
459  LCBuf= LC (buf, x);
460  recombination= true;
461  appendTestMapDown (result, buf2, info, source, dest);
462  trueFactor= true;
463  }
464  }
465  else
466  {
467  if (!isInExtension (buf2, gamma, k, delta, source, dest))
468  {
469  buf= quot;
470  LCBuf= LC (buf, x);
471  recombination= true;
472  appendTestMapDown (result, buf2, info, source, dest);
473  trueFactor= true;
474  }
475  }
476  if (trueFactor)
477  {
478  T= Difference (T, S);
479  l -= degree (g);
480  M= power (y, l);
481  buf0= buf (0, x)*LCBuf;
482 
483  // compute new possible degree pattern
484  bufDegs2= DegreePattern (T);
485  bufDegs1.intersect (bufDegs2);
486  bufDegs1.refine ();
487  if (T.length() < 2*s || T.length() == s ||
488  bufDegs1.getLength() == 1)
489  {
490  delete [] v;
491  if (recombination)
492  {
493  buf= buf (y-eval,y);
494  buf /= Lc (buf);
495  appendTestMapDown (result, buf, info, source,
496  dest);
497  F= 1;
498  return result;
499  }
500  else
501  {
502  appendMapDown (result, F (y - eval, y), info, source, dest);
503  F= 1;
504  return result;
505  }
506  }
507  trueFactor= false;
508  TT= copy (T);
509  indexUpdate (v, s, T.length(), nosubset);
510  if (nosubset) break;
511  }
512  }
513  }
514  }
515  }
516  s++;
517  if (T.length() < 2*s || T.length() == s)
518  {
519  delete [] v;
520  if (recombination)
521  {
522  buf= buf (y-eval,y);
523  buf /= Lc (buf);
524  appendTestMapDown (result, buf, info, source, dest);
525  F= 1;
526  return result;
527  }
528  else
529  {
530  appendMapDown (result, F (y - eval, y), info, source, dest);
531  F= 1;
532  return result;
533  }
534  }
535  for (int i= 0; i < T.length(); i++)
536  v[i]= 0;
537  nosubset= false;
538  }
539  if (T.length() < 2*s)
540  {
541  appendMapDown (result, F (y - eval, y), info, source, dest);
542  F= 1;
543  delete [] v;
544  return result;
545  }
546 
547  if (s > thres)
548  {
549  factors= T;
550  F= buf;
551  degs= bufDegs1;
552  }
553 
554  delete [] v;
555  return result;
556 }
557 
558 /// naive factor recombination as decribed in "Factoring
559 /// multivariate polynomials over a finite field" by L Bernardin.
560 CFList
562  const CanonicalForm& N, DegreePattern& degs, const
563  CanonicalForm& eval, int s, int thres, const modpk& b,
564  const CanonicalForm& den
565  )
566 {
567  if (factors.length() == 0)
568  {
569  F= 1;
570  return CFList ();
571  }
572  if (F.inCoeffDomain())
573  return CFList();
574  Variable y= Variable (2);
575  if (degs.getLength() <= 1 || factors.length() == 1)
576  {
577  CFList result= CFList (F(y-eval,y));
578  F= 1;
579  return result;
580  }
581 #ifdef DEBUGOUTPUT
582  if (b.getp() == 0)
583  DEBOUTLN (cerr, "LC (F, 1)*prodMod (factors, N) == F " <<
584  (mod (LC (F, 1)*prodMod (factors, N),N)/Lc (mod (LC (F, 1)*prodMod (factors, N),N)) == F/Lc(F)));
585  else
586  DEBOUTLN (cerr, "LC (F, 1)*prodMod (factors, N) == F " <<
587  (mod (b(LC (F, 1)*prodMod (factors, N)),N)/Lc (mod (b(LC (F, 1)*prodMod (factors, N)),N)) == F/Lc(F)));
588 #endif
589 
590  CFList T, S;
591 
592  CanonicalForm M= N;
593  int l= degree (N);
594  T= factors;
595  CFList result;
596  Variable x= Variable (1);
597  CanonicalForm denom= den, denQuot;
598  CanonicalForm LCBuf= LC (F, x)*denom;
599  CanonicalForm g, quot, buf= F;
600  int * v= new int [T.length()];
601  for (int i= 0; i < T.length(); i++)
602  v[i]= 0;
603  bool nosubset= false;
604  CFArray TT;
605  DegreePattern bufDegs1, bufDegs2;
606  bufDegs1= degs;
607  int subsetDeg;
608  TT= copy (factors);
609  bool recombination= false;
611  bool isRat= (isOn (SW_RATIONAL) && getCharacteristic() == 0) ||
612  getCharacteristic() > 0;
613  if (!isRat)
614  On (SW_RATIONAL);
615  CanonicalForm buf0= mulNTL (buf (0, x), LCBuf);
616  if (!isRat)
617  Off (SW_RATIONAL);
618  while (T.length() >= 2*s && s <= thres)
619  {
620  while (nosubset == false)
621  {
622  if (T.length() == s)
623  {
624  delete [] v;
625  if (recombination)
626  {
627  T.insert (LCBuf);
628  g= prodMod (T, M);
629  if (b.getp() != 0)
630  g= b(g);
631  T.removeFirst();
632  g /= content (g,x);
633  result.append (g(y-eval,y));
634  F= 1;
635  return result;
636  }
637  else
638  {
639  result= CFList (F(y-eval,y));
640  F= 1;
641  return result;
642  }
643  }
644  S= subset (v, s, TT, nosubset);
645  if (nosubset) break;
646  subsetDeg= subsetDegree (S);
647  // skip those combinations that are not possible
648  if (!degs.find (subsetDeg))
649  continue;
650  else
651  {
652  if (!isRat)
653  On (SW_RATIONAL);
654  test= prodMod0 (S, M);
655  if (!isRat)
656  {
657  test *= bCommonDen (test);
658  Off (SW_RATIONAL);
659  }
660  test= mulNTL (test, LCBuf, b);
661  test= mod (test, M);
662  if (uniFdivides (test, buf0))
663  {
664  if (!isRat)
665  On (SW_RATIONAL);
666  S.insert (LCBuf);
667  g= prodMod (S, M);
668  S.removeFirst();
669  if (!isRat)
670  {
671  g *= bCommonDen(g);
672  Off (SW_RATIONAL);
673  }
674  if (b.getp() != 0)
675  g= b(g);
676  if (!isRat)
677  On (SW_RATIONAL);
678  g /= content (g, x);
679  if (!isRat)
680  {
681  On (SW_RATIONAL);
682  if (!Lc (g).inBaseDomain())
683  g /= Lc (g);
684  g *= bCommonDen (g);
685  Off (SW_RATIONAL);
686  g /= icontent (g);
687  On (SW_RATIONAL);
688  }
689  if (fdivides (g, buf, quot))
690  {
691  denom *= abs (lc (g));
692  recombination= true;
693  result.append (g (y-eval,y));
694  if (b.getp() != 0)
695  {
696  denQuot= bCommonDen (quot);
697  buf= quot*denQuot;
698  Off (SW_RATIONAL);
699  denom /= gcd (denom, denQuot);
700  On (SW_RATIONAL);
701  }
702  else
703  buf= quot;
704  LCBuf= LC (buf, x)*denom;
705  T= Difference (T, S);
706  l -= degree (g);
707  M= power (y, l);
708  buf0= mulNTL (buf (0, x), LCBuf);
709  if (!isRat)
710  Off (SW_RATIONAL);
711  // compute new possible degree pattern
712  bufDegs2= DegreePattern (T);
713  bufDegs1.intersect (bufDegs2);
714  bufDegs1.refine ();
715  if (T.length() < 2*s || T.length() == s ||
716  bufDegs1.getLength() == 1)
717  {
718  delete [] v;
719  if (recombination)
720  {
721  result.append (buf (y-eval,y));
722  F= 1;
723  return result;
724  }
725  else
726  {
727  result= CFList (F (y-eval,y));
728  F= 1;
729  return result;
730  }
731  }
732  TT= copy (T);
733  indexUpdate (v, s, T.length(), nosubset);
734  if (nosubset) break;
735  }
736  if (!isRat)
737  Off (SW_RATIONAL);
738  }
739  }
740  }
741  s++;
742  if (T.length() < 2*s || T.length() == s)
743  {
744  delete [] v;
745  if (recombination)
746  {
747  result.append (buf(y-eval,y));
748  F= 1;
749  return result;
750  }
751  else
752  {
753  result= CFList (F(y-eval,y));
754  F= 1;
755  return result;
756  }
757  }
758  for (int i= 0; i < T.length(); i++)
759  v[i]= 0;
760  nosubset= false;
761  }
762  delete [] v;
763  if (T.length() < 2*s)
764  {
765  result.append (F(y-eval,y));
766  F= 1;
767  return result;
768  }
769 
770  if (s > thres)
771  {
772  factors= T;
773  F= buf;
774  degs= bufDegs1;
775  }
776 
777  return result;
778 }
779 
781 {
783  {
785  zz_p::init (getCharacteristic());
786  }
787  zz_pX NTLIrredpoly;
788  int i=1, m= 2;
789  // extension of F_p needed
790  if (alpha.level() == 1 && beta.level() == 1 && k == 1)
791  {
792  i= 1;
793  m= 2;
794  } //extension of F_p(alpha) needed but want to factorize over F_p
795  else if (alpha.level() != 1 && beta.level() == 1 && k == 1)
796  {
797  i= 1;
798  m= degree (getMipo (alpha)) + 1;
799  } //extension of F_p(alpha) needed for first time
800  else if (alpha.level() != 1 && beta.level() == 1 && k != 1)
801  {
802  i= 2;
803  m= degree (getMipo (alpha));
804  }
805  else if (alpha.level() != 1 && beta.level() != 1 && k != 1)
806  {
807  m= degree (getMipo (beta));
808  i= degree (getMipo (alpha))/m + 1;
809  }
810  BuildIrred (NTLIrredpoly, i*m);
811  CanonicalForm newMipo= convertNTLzzpX2CF (NTLIrredpoly, Variable (1));
812  return rootOf (newMipo);
813 }
814 
815 void
816 earlyFactorDetection (CFList& reconstructedFactors, CanonicalForm& F, CFList&
817  factors, int& adaptedLiftBound, int*& factorsFoundIndex,
818  DegreePattern& degs, bool& success, int deg, const
820 {
821  DegreePattern bufDegs1= degs;
822  DegreePattern bufDegs2;
823  CFList T= factors;
824  CanonicalForm buf= F;
825  Variable x= Variable (1);
826  Variable y= Variable (2);
827  CanonicalForm g, quot;
828  CanonicalForm M= power (F.mvar(), deg);
829  adaptedLiftBound= 0;
830  int d= degree (F), l= 0;
831  bool isRat= (isOn (SW_RATIONAL) && getCharacteristic() == 0) ||
832  getCharacteristic() > 0;
833  if (!isRat)
834  On (SW_RATIONAL);
835  if (b.getp() != 0)
836  buf *= bCommonDen (buf);
837  CanonicalForm LCBuf= LC (buf, x)*den;
838  CanonicalForm buf0= mulNTL (buf (0,x), LCBuf);
839  CanonicalForm buf1= mulNTL (buf (1,x), LCBuf);
840  if (!isRat)
841  Off (SW_RATIONAL);
842  CanonicalForm test0, test1;
843  CanonicalForm denQuot;
844 
845  for (CFListIterator i= factors; i.hasItem(); i++, l++)
846  {
847  if (!bufDegs1.find (degree (i.getItem(), 1)) || factorsFoundIndex[l] == 1)
848  continue;
849  else
850  {
851  test1= mod (mulNTL (i.getItem() (1,x), LCBuf, b), M);
852  if (uniFdivides (test1, buf1))
853  {
854  test0= mod (mulNTL (i.getItem() (0,x), LCBuf, b), M);
855  if (uniFdivides (test0, buf0))
856  {
857  if (!isRat)
858  On (SW_RATIONAL);
859  g= mulMod2 (i.getItem(), LCBuf, M);
860  if (!isRat)
861  {
862  g *= bCommonDen(g);
863  Off (SW_RATIONAL);
864  }
865  if (b.getp() != 0)
866  g= b(g);
867  if (!isRat)
868  On (SW_RATIONAL);
869  g /= content (g, x);
870  if (!isRat)
871  {
872  On (SW_RATIONAL);
873  if (!Lc (g).inBaseDomain())
874  g /= Lc (g);
875  g *= bCommonDen (g);
876  Off (SW_RATIONAL);
877  g /= icontent (g);
878  On (SW_RATIONAL);
879  }
880  if (fdivides (g, buf, quot))
881  {
882  den *= abs (lc (g));
883  reconstructedFactors.append (g (y-eval,y));
884  factorsFoundIndex[l]= 1;
885  if (b.getp() != 0)
886  {
887  denQuot= bCommonDen (quot);
888  buf= quot*denQuot;
889  Off (SW_RATIONAL);
890  den /= gcd (den, denQuot);
891  On (SW_RATIONAL);
892  }
893  else
894  buf= quot;
895  d -= degree (g);
896  LCBuf= LC (buf, x)*den;
897  buf0= mulNTL (buf (0,x), LCBuf);
898  buf1= mulNTL (buf (1,x), LCBuf);
899  if (!isRat)
900  Off (SW_RATIONAL);
901  T= Difference (T, CFList (i.getItem()));
902  F= buf;
903 
904  // compute new possible degree pattern
905  bufDegs2= DegreePattern (T);
906  bufDegs1.intersect (bufDegs2);
907  bufDegs1.refine ();
908  if (bufDegs1.getLength() <= 1)
909  {
910  if (!buf.inCoeffDomain())
911  {
912  reconstructedFactors.append (buf (y-eval,y));
913  F= 1;
914  }
915  break;
916  }
917  }
918  if (!isRat)
919  Off (SW_RATIONAL);
920  }
921  }
922  }
923  }
924  adaptedLiftBound= d + 1;
925  if (adaptedLiftBound < deg)
926  {
927  degs= bufDegs1;
928  success= true;
929  }
930  if (bufDegs1.getLength() <= 1)
931  degs= bufDegs1;
932 }
933 
934 void
935 earlyFactorDetection (CFList& reconstructedFactors, CanonicalForm& F, CFList&
936  factors, int& adaptedLiftBound, int*& factorsFoundIndex,
937  DegreePattern& degs, bool& success, int deg, const
938  CanonicalForm& eval, const modpk& b)
939 {
940  CanonicalForm den= 1;
941  earlyFactorDetection (reconstructedFactors, F, factors, adaptedLiftBound,
942  factorsFoundIndex, degs, success, deg, eval, b, den);
943 }
944 
945 void
947  factors,int& adaptedLiftBound, int*& factorsFoundIndex,
948  DegreePattern& degs, bool& success, const
949  ExtensionInfo& info, const CanonicalForm& eval, int deg
950  )
951 {
952  Variable alpha= info.getAlpha();
953  Variable beta= info.getBeta();
954  CanonicalForm gamma= info.getGamma();
955  CanonicalForm delta= info.getDelta();
956  int k= info.getGFDegree();
957  DegreePattern bufDegs1= degs, bufDegs2;
958  CFList result;
959  CFList T= factors;
960  Variable y= F.mvar();
961  Variable x= Variable (1);
962  CanonicalForm buf= F, LCBuf= LC (buf, x), g, buf2;
963  CanonicalForm M= power (y, deg);
964  adaptedLiftBound= 0;
965  bool trueFactor= false;
966  int d= degree (F), l= 0;
967  CFList source, dest;
968  int degMipoBeta= 1;
969  if (!k && beta.level() != 1)
970  degMipoBeta= degree (getMipo (beta));
971  CanonicalForm quot;
972  for (CFListIterator i= factors; i.hasItem(); i++, l++)
973  {
974  if (!bufDegs1.find (degree (i.getItem(), 1)) || factorsFoundIndex[l] == 1)
975  continue;
976  else
977  {
978  g= mulMod2 (i.getItem(), LCBuf, M);
979  g /= content (g, x);
980  if (fdivides (g, buf, quot))
981  {
982  buf2= g (y - eval, y);
983  buf2 /= Lc (buf2);
984 
985  if (!k && beta == x)
986  {
987  if (degree (buf2, alpha) < degMipoBeta)
988  {
989  appendTestMapDown (reconstructedFactors, buf2, info, source, dest);
990  factorsFoundIndex[l]= 1;
991  buf= quot;
992  d -= degree (g);
993  LCBuf= LC (buf, x);
994  trueFactor= true;
995  }
996  }
997  else
998  {
999  if (!isInExtension (buf2, gamma, k, delta, source, dest))
1000  {
1001  appendTestMapDown (reconstructedFactors, buf2, info, source, dest);
1002  factorsFoundIndex[l]= 1;
1003  buf= quot;
1004  d -= degree (g);
1005  LCBuf= LC (buf, x);
1006  trueFactor= true;
1007  }
1008  }
1009  if (trueFactor)
1010  {
1011  T= Difference (T, CFList (i.getItem()));
1012  F= buf;
1013 
1014  // compute new possible degree pattern
1015  bufDegs2= DegreePattern (T);
1016  bufDegs1.intersect (bufDegs2);
1017  bufDegs1.refine ();
1018  trueFactor= false;
1019  if (bufDegs1.getLength() <= 1)
1020  {
1021  if (!buf.inCoeffDomain())
1022  {
1023  buf= buf (y - eval, y);
1024  buf /= Lc (buf);
1025  appendMapDown (reconstructedFactors, buf, info, source, dest);
1026  F= 1;
1027  }
1028  break;
1029  }
1030  }
1031  }
1032  }
1033  }
1034  adaptedLiftBound= d + 1;
1035  if (adaptedLiftBound < deg)
1036  {
1037  degs= bufDegs1;
1038  success= true;
1039  }
1040  if (bufDegs1.getLength() <= 1)
1041  degs= bufDegs1;
1042 }
1043 
1044 int*
1045 getCombinations (int * rightSide, int sizeOfRightSide, int& sizeOfOutput,
1046  int degreeLC)
1047 {
1048  Variable x= Variable (1);
1049  int p= getCharacteristic();
1050  int d= getGFDegree();
1051  char cGFName= gf_name;
1052  setCharacteristic(0);
1053  CanonicalForm buf= 1;
1054  for (int i= 0; i < sizeOfRightSide; i++)
1055  buf *= (power (x, rightSide [i]) + 1);
1056 
1057  int j= 0;
1058  for (CFIterator i= buf; i.hasTerms(); i++, j++)
1059  {
1060  if (i.exp() < degreeLC)
1061  {
1062  j++;
1063  break;
1064  }
1065  }
1066 
1067  ASSERT ( j > 1, "j > 1 expected" );
1068 
1069  int* result = new int [j - 1];
1070  sizeOfOutput= j - 1;
1071 
1072  int i= 0;
1073  for (CFIterator m = buf; i < j - 1; i++, m++)
1074  result [i]= m.exp();
1075 
1076  if (d > 1)
1077  setCharacteristic (p, d, cGFName);
1078  else
1079  setCharacteristic (p);
1080  return result;
1081 }
1082 
1083 int *
1084 getLiftPrecisions (const CanonicalForm& F, int& sizeOfOutput, int degreeLC)
1085 {
1086  int sizeOfNewtonPoly;
1087  int ** newtonPolyg= newtonPolygon (F, sizeOfNewtonPoly);
1088  int sizeOfRightSide;
1089  int * rightSide= getRightSide(newtonPolyg, sizeOfNewtonPoly, sizeOfRightSide);
1090  int * result= getCombinations(rightSide, sizeOfRightSide, sizeOfOutput,
1091  degreeLC);
1092  delete [] rightSide;
1093  for (int i= 0; i < sizeOfNewtonPoly; i++)
1094  delete [] newtonPolyg[i];
1095  delete [] newtonPolyg;
1096  return result;
1097 }
1098 
1099 void
1100 deleteFactors (CFList& factors, int* factorsFoundIndex)
1101 {
1102  CFList result;
1103  int i= 0;
1104  for (CFListIterator iter= factors; iter.hasItem(); iter++, i++)
1105  {
1106  if (factorsFoundIndex[i] == 1)
1107  continue;
1108  else
1109  result.append (iter.getItem());
1110  }
1111  factors= result;
1112 }
1113 
1114 CFList
1115 henselLiftAndEarly (CanonicalForm& A, bool& earlySuccess, CFList&
1116  earlyFactors, DegreePattern& degs, int& liftBound,
1117  const CFList& uniFactors, const ExtensionInfo& info,
1119 {
1120  Variable alpha= info.getAlpha();
1121  Variable beta= info.getBeta();
1122  CanonicalForm gamma= info.getGamma();
1123  CanonicalForm delta= info.getDelta();
1124  bool extension= info.isInExtension();
1125 
1126  int sizeOfLiftPre;
1127  int * liftPre= getLiftPrecisions (A, sizeOfLiftPre, degree (LC (A, 1), 2));
1128 
1129  Variable x= Variable (1);
1130  Variable y= Variable (2);
1131  CFArray Pi;
1132  CFList diophant;
1133  CFList bufUniFactors= uniFactors;
1134  On (SW_RATIONAL);
1135  CanonicalForm bufA= A;
1136  if (!Lc (A).inBaseDomain())
1137  {
1138  bufA /= Lc (A);
1139  CanonicalForm denBufA= bCommonDen (bufA);
1140  bufA *= denBufA;
1141  Off (SW_RATIONAL);
1142  den /= gcd (den, denBufA);
1143  }
1144  else
1145  {
1146  bufA= A;
1147  Off (SW_RATIONAL);
1148  den /= gcd (den, Lc (A));
1149  }
1150  CanonicalForm lcA0= 0;
1151  bool mipoHasDen= false;
1152  if (getCharacteristic() == 0 && b.getp() != 0)
1153  {
1154  if (alpha.level() == 1)
1155  {
1156  lcA0= lc (A (0, 2));
1157  A *= b.inverse (lcA0);
1158  A= b (A);
1159  for (CFListIterator i= bufUniFactors; i.hasItem(); i++)
1160  i.getItem()= b (i.getItem()*b.inverse (lc (i.getItem())));
1161  }
1162  else
1163  {
1164  lcA0= Lc (A (0,2));
1165  On (SW_RATIONAL);
1166  mipoHasDen= !bCommonDen(getMipo(alpha)).isOne();
1167  Off (SW_RATIONAL);
1168  CanonicalForm lcA0inverse= b.inverse (lcA0);
1169  A *= lcA0inverse;
1170  A= b (A);
1171  // Lc of bufUniFactors is in Z
1172  for (CFListIterator i= bufUniFactors; i.hasItem(); i++)
1173  i.getItem()= b (i.getItem()*b.inverse (lc (i.getItem())));
1174  }
1175  }
1176  bufUniFactors.insert (LC (A, x));
1177  CFMatrix M= CFMatrix (liftBound, bufUniFactors.length() - 1);
1178  earlySuccess= false;
1179  int newLiftBound= 0;
1180 
1181  int smallFactorDeg= tmin (11, liftPre [sizeOfLiftPre- 1] + 1);//this is a tunable parameter
1182  int dummy;
1183  int * factorsFoundIndex= new int [uniFactors.length()];
1184  for (int i= 0; i < uniFactors.length(); i++)
1185  factorsFoundIndex [i]= 0;
1186 
1187  CFList bufBufUniFactors;
1188  Variable v= alpha;
1189  if (smallFactorDeg >= liftBound || degree (A,y) <= 4)
1190  henselLift12 (A, bufUniFactors, liftBound, Pi, diophant, M, b, true);
1191  else if (sizeOfLiftPre > 1 && sizeOfLiftPre < 30)
1192  {
1193  henselLift12 (A, bufUniFactors, smallFactorDeg, Pi, diophant, M, b, true);
1194  if (mipoHasDen)
1195  {
1196  for (CFListIterator iter= bufUniFactors; iter.hasItem(); iter++)
1197  if (hasFirstAlgVar (iter.getItem(), v))
1198  break;
1199  if (v != alpha)
1200  {
1201  bufBufUniFactors= bufUniFactors;
1202  for (CFListIterator iter= bufBufUniFactors; iter.hasItem(); iter++)
1204  A= replacevar (A, alpha, v);
1205  }
1206  }
1207 
1208  if (!extension)
1209  {
1210  if (v==alpha)
1211  earlyFactorDetection (earlyFactors, bufA, bufUniFactors, newLiftBound,
1212  factorsFoundIndex, degs, earlySuccess,
1213  smallFactorDeg, eval, b, den);
1214  else
1215  earlyFactorDetection(earlyFactors, bufA, bufBufUniFactors, newLiftBound,
1216  factorsFoundIndex, degs, earlySuccess,
1217  smallFactorDeg, eval, b, den);
1218  }
1219  else
1220  extEarlyFactorDetection (earlyFactors, bufA, bufUniFactors, newLiftBound,
1221  factorsFoundIndex, degs, earlySuccess, info,
1222  eval, smallFactorDeg);
1223  if (degs.getLength() > 1 && !earlySuccess &&
1224  smallFactorDeg != liftPre [sizeOfLiftPre-1] + 1)
1225  {
1226  if (newLiftBound >= liftPre[sizeOfLiftPre-1]+1)
1227  {
1228  bufUniFactors.insert (LC (A, x));
1229  henselLiftResume12 (A, bufUniFactors, smallFactorDeg,
1230  liftPre[sizeOfLiftPre-1] + 1, Pi, diophant, M, b);
1231  if (v!=alpha)
1232  {
1233  bufBufUniFactors= bufUniFactors;
1234  for (CFListIterator iter= bufBufUniFactors; iter.hasItem(); iter++)
1236  }
1237  if (!extension)
1238  {
1239  if (v==alpha)
1240  earlyFactorDetection (earlyFactors, bufA, bufUniFactors, newLiftBound,
1241  factorsFoundIndex, degs, earlySuccess,
1242  liftPre[sizeOfLiftPre-1] + 1, eval, b, den);
1243  else
1244  earlyFactorDetection (earlyFactors,bufA,bufBufUniFactors,newLiftBound,
1245  factorsFoundIndex, degs, earlySuccess,
1246  liftPre[sizeOfLiftPre-1] + 1, eval, b, den);
1247  }
1248  else
1249  extEarlyFactorDetection (earlyFactors,bufA,bufUniFactors,newLiftBound,
1250  factorsFoundIndex, degs, earlySuccess, info,
1251  eval, liftPre[sizeOfLiftPre-1] + 1);
1252  }
1253  }
1254  else if (earlySuccess)
1255  liftBound= newLiftBound;
1256 
1257  int i= sizeOfLiftPre - 1;
1258  while (degs.getLength() > 1 && !earlySuccess && i - 1 >= 0)
1259  {
1260  if (newLiftBound >= liftPre[i] + 1)
1261  {
1262  bufUniFactors.insert (LC (A, x));
1263  henselLiftResume12 (A, bufUniFactors, liftPre[i] + 1,
1264  liftPre[i-1] + 1, Pi, diophant, M, b);
1265  if (v!=alpha)
1266  {
1267  bufBufUniFactors= bufUniFactors;
1268  for (CFListIterator iter= bufBufUniFactors; iter.hasItem(); iter++)
1270  }
1271  if (!extension)
1272  {
1273  if (v==alpha)
1274  earlyFactorDetection (earlyFactors, bufA, bufUniFactors, newLiftBound,
1275  factorsFoundIndex, degs, earlySuccess,
1276  liftPre[i-1] + 1, eval, b, den);
1277  else
1278  earlyFactorDetection (earlyFactors,bufA,bufBufUniFactors,newLiftBound,
1279  factorsFoundIndex, degs, earlySuccess,
1280  liftPre[i-1] + 1, eval, b, den);
1281  }
1282  else
1283  extEarlyFactorDetection (earlyFactors,bufA,bufUniFactors,newLiftBound,
1284  factorsFoundIndex, degs, earlySuccess, info,
1285  eval, liftPre[i-1] + 1);
1286  }
1287  else
1288  {
1289  liftBound= newLiftBound;
1290  break;
1291  }
1292  i--;
1293  }
1294  if (earlySuccess)
1295  liftBound= newLiftBound;
1296  //after here all factors are lifted to liftPre[sizeOfLiftPre-1]
1297  }
1298  else
1299  {
1300  henselLift12 (A, bufUniFactors, smallFactorDeg, Pi, diophant, M, b, true);
1301  if (mipoHasDen)
1302  {
1303  for (CFListIterator iter= bufUniFactors; iter.hasItem(); iter++)
1304  if (hasFirstAlgVar (iter.getItem(), v))
1305  break;
1306  if (v != alpha)
1307  {
1308  bufBufUniFactors= bufUniFactors;
1309  for (CFListIterator iter= bufBufUniFactors; iter.hasItem(); iter++)
1311  A= replacevar (A, alpha, v);
1312  }
1313  }
1314  if (!extension)
1315  {
1316  if (v==alpha)
1317  earlyFactorDetection (earlyFactors, bufA, bufUniFactors, newLiftBound,
1318  factorsFoundIndex, degs, earlySuccess,
1319  smallFactorDeg, eval, b, den);
1320  else
1321  earlyFactorDetection (earlyFactors, bufA, bufBufUniFactors, newLiftBound,
1322  factorsFoundIndex, degs, earlySuccess,
1323  smallFactorDeg, eval, b, den);
1324  }
1325  else
1326  extEarlyFactorDetection (earlyFactors, bufA, bufUniFactors, newLiftBound,
1327  factorsFoundIndex, degs, earlySuccess, info,
1328  eval, smallFactorDeg);
1329  int i= 1;
1330  while ((degree (A,y)/4)*i + 4 <= smallFactorDeg)
1331  i++;
1332  dummy= tmin (degree (A,y)+1, (degree (A,y)/4)*i+4);
1333  if (degs.getLength() > 1 && !earlySuccess && dummy > smallFactorDeg)
1334  {
1335  bufUniFactors.insert (LC (A, x));
1336  henselLiftResume12 (A, bufUniFactors, smallFactorDeg,
1337  dummy, Pi, diophant, M, b);
1338  if (v!=alpha)
1339  {
1340  bufBufUniFactors= bufUniFactors;
1341  for (CFListIterator iter= bufBufUniFactors; iter.hasItem(); iter++)
1343  }
1344  if (!extension)
1345  {
1346  if (v==alpha)
1347  earlyFactorDetection (earlyFactors, bufA, bufUniFactors, newLiftBound,
1348  factorsFoundIndex, degs, earlySuccess, dummy,eval,
1349  b, den);
1350  else
1351  earlyFactorDetection (earlyFactors, bufA,bufBufUniFactors, newLiftBound,
1352  factorsFoundIndex, degs, earlySuccess, dummy,eval,
1353  b, den);
1354  }
1355  else
1356  extEarlyFactorDetection (earlyFactors, bufA,bufUniFactors, newLiftBound,
1357  factorsFoundIndex, degs, earlySuccess, info,
1358  eval, dummy);
1359  }
1360  while (degs.getLength() > 1 && !earlySuccess && i < 4)
1361  {
1362  if (newLiftBound >= dummy)
1363  {
1364  bufUniFactors.insert (LC (A, x));
1365  dummy= tmin (degree (A,y)+1, (degree (A,y)/4)*(i+1)+4);
1366  henselLiftResume12 (A, bufUniFactors, (degree (A,y)/4)*i + 4,
1367  dummy, Pi, diophant, M, b);
1368  if (v!=alpha)
1369  {
1370  bufBufUniFactors= bufUniFactors;
1371  for (CFListIterator iter= bufBufUniFactors; iter.hasItem(); iter++)
1373  }
1374  if (!extension)
1375  {
1376  if (v==alpha)
1377  earlyFactorDetection (earlyFactors, bufA, bufUniFactors, newLiftBound,
1378  factorsFoundIndex, degs, earlySuccess, dummy,
1379  eval, b, den);
1380  else
1381  earlyFactorDetection (earlyFactors,bufA,bufBufUniFactors,newLiftBound,
1382  factorsFoundIndex, degs, earlySuccess, dummy,
1383  eval, b, den);
1384  }
1385  else
1386  extEarlyFactorDetection (earlyFactors,bufA,bufUniFactors,newLiftBound,
1387  factorsFoundIndex, degs, earlySuccess, info,
1388  eval, dummy);
1389  }
1390  else
1391  {
1392  liftBound= newLiftBound;
1393  break;
1394  }
1395  i++;
1396  }
1397  if (earlySuccess)
1398  liftBound= newLiftBound;
1399  }
1400 
1401  A= bufA;
1402  if (earlyFactors.length() > 0 && degs.getLength() > 1)
1403  {
1404  liftBound= degree (A,y) + 1;
1405  earlySuccess= true;
1406  deleteFactors (bufUniFactors, factorsFoundIndex);
1407  }
1408 
1409  delete [] factorsFoundIndex;
1410  delete [] liftPre;
1411 
1412  return bufUniFactors;
1413 }
1414 
1415 CFList
1416 henselLiftAndEarly (CanonicalForm& A, bool& earlySuccess, CFList&
1417  earlyFactors, DegreePattern& degs, int& liftBound,
1418  const CFList& uniFactors, const ExtensionInfo& info,
1419  const CanonicalForm& eval)
1420 {
1421  modpk dummy= modpk();
1422  CanonicalForm den= 1;
1423  return henselLiftAndEarly (A, earlySuccess, earlyFactors, degs, liftBound,
1424  uniFactors, info, eval, dummy, den);
1425 }
1426 
1427 #ifndef HAVE_FLINT
1428 long isReduced (const mat_zz_p& M)
1429 {
1430  long i, j, nonZero;
1431  for (i = 1; i <= M.NumRows(); i++)
1432  {
1433  nonZero= 0;
1434  for (j = 1; j <= M.NumCols(); j++)
1435  {
1436  if (!IsZero (M (i,j)))
1437  nonZero++;
1438  }
1439  if (nonZero != 1)
1440  return 0;
1441  }
1442  return 1;
1443 }
1444 #endif
1445 
1446 #ifdef HAVE_FLINT
1447 long isReduced (const nmod_mat_t M)
1448 {
1449  long i, j, nonZero;
1450  for (i = 1; i <= nmod_mat_nrows(M); i++)
1451  {
1452  nonZero= 0;
1453  for (j = 1; j <= nmod_mat_ncols (M); j++)
1454  {
1455  if (!(nmod_mat_entry (M, i-1, j-1)==0))
1456  nonZero++;
1457  }
1458  if (nonZero != 1)
1459  return 0;
1460  }
1461  return 1;
1462 }
1463 #endif
1464 
1465 long isReduced (const mat_zz_pE& M)
1466 {
1467  long i, j, nonZero;
1468  for (i = 1; i <= M.NumRows(); i++)
1469  {
1470  nonZero= 0;
1471  for (j = 1; j <= M.NumCols(); j++)
1472  {
1473  if (!IsZero (M (i,j)))
1474  nonZero++;
1475  }
1476  if (nonZero != 1)
1477  return 0;
1478  }
1479  return 1;
1480 }
1481 
1482 #ifndef HAVE_FLINT
1483 int * extractZeroOneVecs (const mat_zz_p& M)
1484 {
1485  long i, j;
1486  bool nonZeroOne= false;
1487  int * result= new int [M.NumCols()];
1488  for (i = 1; i <= M.NumCols(); i++)
1489  {
1490  for (j = 1; j <= M.NumRows(); j++)
1491  {
1492  if (!(IsOne (M (j,i)) || IsZero (M (j,i))))
1493  {
1494  nonZeroOne= true;
1495  break;
1496  }
1497  }
1498  if (!nonZeroOne)
1499  result [i - 1]= 1;
1500  else
1501  result [i - 1]= 0;
1502  nonZeroOne= false;
1503  }
1504  return result;
1505 }
1506 #endif
1507 
1508 #ifdef HAVE_FLINT
1509 int * extractZeroOneVecs (const nmod_mat_t M)
1510 {
1511  long i, j;
1512  bool nonZeroOne= false;
1513  int * result= new int [nmod_mat_ncols (M)];
1514  for (i = 0; i < nmod_mat_ncols (M); i++)
1515  {
1516  for (j = 0; j < nmod_mat_nrows (M); j++)
1517  {
1518  if (!((nmod_mat_entry (M, j, i) == 1) || (nmod_mat_entry (M, j,i) == 0)))
1519  {
1520  nonZeroOne= true;
1521  break;
1522  }
1523  }
1524  if (!nonZeroOne)
1525  result [i]= 1;
1526  else
1527  result [i]= 0;
1528  nonZeroOne= false;
1529  }
1530  return result;
1531 }
1532 #endif
1533 
1534 int * extractZeroOneVecs (const mat_zz_pE& M)
1535 {
1536  long i, j;
1537  bool nonZeroOne= false;
1538  int * result= new int [M.NumCols()];
1539  for (i = 1; i <= M.NumCols(); i++)
1540  {
1541  for (j = 1; j <= M.NumRows(); j++)
1542  {
1543  if (!(IsOne (M (j,i)) || IsZero (M (j,i))))
1544  {
1545  nonZeroOne= true;
1546  break;
1547  }
1548  }
1549  if (!nonZeroOne)
1550  result [i - 1]= 1;
1551  else
1552  result [i - 1]= 0;
1553  nonZeroOne= false;
1554  }
1555  return result;
1556 }
1557 
1558 void
1559 reconstructionTry (CFList& reconstructedFactors, CanonicalForm& F, const CFList&
1560  factors, const int liftBound, int& factorsFound, int*&
1561  factorsFoundIndex, mat_zz_pE& N, const CanonicalForm& eval,
1562  bool beenInThres
1563  )
1564 {
1565  Variable y= Variable (2);
1566  Variable x= Variable (1);
1567  CanonicalForm yToL= power (y, liftBound);
1568  CanonicalForm bufF= F (y-eval, y);
1569  if (factors.length() == 2)
1570  {
1571  CanonicalForm tmp1, tmp2, tmp3;
1572  tmp1= factors.getFirst();
1573  tmp2= factors.getLast();
1574  tmp1= mulMod2 (tmp1, LC (F,x), yToL);
1575  tmp1 /= content (tmp1, x);
1576  tmp1= tmp1 (y-eval, y);
1577  tmp2= mulMod2 (tmp2, LC (F,x), yToL);
1578  tmp2 /= content (tmp2, x);
1579  tmp2= tmp2 (y-eval, y);
1580  tmp3 = tmp1*tmp2;
1581  if (tmp3/Lc (tmp3) == bufF/Lc (bufF))
1582  {
1583  factorsFound++;
1584  F= 1;
1585  reconstructedFactors.append (tmp1);
1586  reconstructedFactors.append (tmp2);
1587  return;
1588  }
1589  }
1590  CanonicalForm quot, buf;
1592  for (long i= 1; i <= N.NumCols(); i++)
1593  {
1594  if (factorsFoundIndex [i - 1] == 1)
1595  continue;
1596  iter= factors;
1597  if (beenInThres)
1598  {
1599  int count= 1;
1600  while (count < i)
1601  {
1602  count++;
1603  iter++;
1604  }
1605  buf= iter.getItem();
1606  }
1607  else
1608  {
1609  buf= 1;
1610  for (long j= 1; j <= N.NumRows(); j++, iter++)
1611  {
1612  if (!IsZero (N (j,i)))
1613  buf= mulMod2 (buf, iter.getItem(), yToL);
1614  }
1615  }
1616  buf= mulMod2 (buf, LC (F,x), yToL);
1617  buf /= content (buf, x);
1618  buf= buf (y-eval,y);
1619  if (fdivides (buf, bufF, quot))
1620  {
1621  factorsFoundIndex[i - 1]= 1;
1622  factorsFound++;
1623  bufF= quot;
1624  bufF /= Lc (bufF);
1625  reconstructedFactors.append (buf);
1626  }
1627  if (degree (bufF) <= 0)
1628  return;
1629  if (factorsFound + 1 == N.NumCols())
1630  {
1631  reconstructedFactors.append (bufF);
1632  F= 1;
1633  return;
1634  }
1635  }
1636  if (reconstructedFactors.length() != 0)
1637  F= bufF (y+eval,y);
1638 }
1639 
1640 #ifndef HAVE_FLINT
1641 void
1642 reconstructionTry (CFList& reconstructedFactors, CanonicalForm& F, const CFList&
1643  factors, const int liftBound, int& factorsFound, int*&
1644  factorsFoundIndex, mat_zz_p& N, const CanonicalForm& eval,
1645  bool beenInThres
1646  )
1647 {
1648  Variable y= Variable (2);
1649  Variable x= Variable (1);
1650  CanonicalForm yToL= power (y, liftBound);
1651  CanonicalForm bufF= F (y-eval, y);
1652  if (factors.length() == 2)
1653  {
1654  CanonicalForm tmp1, tmp2, tmp3;
1655  tmp1= factors.getFirst();
1656  tmp2= factors.getLast();
1657  tmp1= mulMod2 (tmp1, LC (F,x), yToL);
1658  tmp1 /= content (tmp1, x);
1659  tmp1= tmp1 (y-eval, y);
1660  tmp2= mulMod2 (tmp2, LC (F,x), yToL);
1661  tmp2 /= content (tmp2, x);
1662  tmp2= tmp2 (y-eval,y);
1663  tmp3 = tmp1*tmp2;
1664  if (tmp3/Lc (tmp3) == bufF/Lc (bufF))
1665  {
1666  factorsFound++;
1667  F= 1;
1668  reconstructedFactors.append (tmp1);
1669  reconstructedFactors.append (tmp2);
1670  return;
1671  }
1672  }
1673  CanonicalForm quot, buf;
1675  for (long i= 1; i <= N.NumCols(); i++)
1676  {
1677  if (factorsFoundIndex [i - 1] == 1)
1678  continue;
1679  iter= factors;
1680  if (beenInThres)
1681  {
1682  int count= 1;
1683  while (count < i)
1684  {
1685  count++;
1686  iter++;
1687  }
1688  buf= iter.getItem();
1689  }
1690  else
1691  {
1692  buf= 1;
1693  for (long j= 1; j <= N.NumRows(); j++, iter++)
1694  {
1695  if (!IsZero (N (j,i)))
1696  buf= mulMod2 (buf, iter.getItem(), yToL);
1697  }
1698  }
1699  buf= mulMod2 (buf, LC (F,x), yToL);
1700  buf /= content (buf, x);
1701  buf= buf (y-eval,y);
1702  if (fdivides (buf, bufF, quot))
1703  {
1704  factorsFoundIndex[i - 1]= 1;
1705  factorsFound++;
1706  bufF= quot;
1707  bufF /= Lc (bufF);
1708  reconstructedFactors.append (buf);
1709  }
1710  if (degree (bufF) <= 0)
1711  return;
1712  if (factorsFound + 1 == N.NumCols())
1713  {
1714  reconstructedFactors.append (bufF);
1715  F=1;
1716  return;
1717  }
1718  }
1719  if (reconstructedFactors.length() != 0)
1720  F= bufF (y+eval,y);
1721 }
1722 #endif
1723 
1724 #ifdef HAVE_FLINT
1725 void
1726 reconstructionTry (CFList& reconstructedFactors, CanonicalForm& F, const CFList&
1727  factors, const int liftBound, int& factorsFound, int*&
1728  factorsFoundIndex, nmod_mat_t N, const CanonicalForm& eval,
1729  bool beenInThres
1730  )
1731 {
1732  Variable y= Variable (2);
1733  Variable x= Variable (1);
1734  CanonicalForm yToL= power (y, liftBound);
1735  CanonicalForm bufF= F (y-eval, y);
1736  if (factors.length() == 2)
1737  {
1738  CanonicalForm tmp1, tmp2, tmp3;
1739  tmp1= factors.getFirst();
1740  tmp2= factors.getLast();
1741  tmp1= mulMod2 (tmp1, LC (F,x), yToL);
1742  tmp1 /= content (tmp1, x);
1743  tmp1= tmp1 (y-eval, y);
1744  tmp2= mulMod2 (tmp2, LC (F,x), yToL);
1745  tmp2 /= content (tmp2, x);
1746  tmp2= tmp2 (y-eval, y);
1747  tmp3 = tmp1*tmp2;
1748  if (tmp3/Lc (tmp3) == bufF/Lc (bufF))
1749  {
1750  factorsFound++;
1751  F= 1;
1752  reconstructedFactors.append (tmp1);
1753  reconstructedFactors.append (tmp2);
1754  return;
1755  }
1756  }
1757  CanonicalForm quot, buf;
1759  for (long i= 0; i < nmod_mat_ncols (N); i++)
1760  {
1761  if (factorsFoundIndex [i] == 1)
1762  continue;
1763  iter= factors;
1764  if (beenInThres)
1765  {
1766  int count= 0;
1767  while (count < i)
1768  {
1769  count++;
1770  iter++;
1771  }
1772  buf= iter.getItem();
1773  }
1774  else
1775  {
1776  buf= 1;
1777  for (long j= 0; j < nmod_mat_nrows (N); j++, iter++)
1778  {
1779  if (!(nmod_mat_entry (N, j, i) == 0))
1780  buf= mulMod2 (buf, iter.getItem(), yToL);
1781  }
1782  }
1783  buf= mulMod2 (buf, LC (F,x), yToL);
1784  buf /= content (buf, x);
1785  buf= buf (y-eval,y);
1786  if (fdivides (buf, bufF, quot))
1787  {
1788  factorsFoundIndex[i]= 1;
1789  factorsFound++;
1790  bufF= quot;
1791  bufF /= Lc (bufF);
1792  reconstructedFactors.append (buf);
1793  }
1794  if (degree (F) <= 0)
1795  return;
1796  if (factorsFound + 1 == nmod_mat_ncols (N))
1797  {
1798  F= 1;
1799  reconstructedFactors.append (bufF);
1800  return;
1801  }
1802  }
1803  if (reconstructedFactors.length() != 0)
1804  F= bufF (y+eval,y);
1805 }
1806 #endif
1807 
1808 CFList
1809 reconstruction (CanonicalForm& G, CFList& factors, int* zeroOneVecs, int
1810  precision, const mat_zz_pE& N, const CanonicalForm& eval
1811  )
1812 {
1813  Variable y= Variable (2);
1814  Variable x= Variable (1);
1815  CanonicalForm F= G;
1816  CanonicalForm yToL= power (y, precision);
1817  CanonicalForm quot, buf;
1818  CFList result, factorsConsidered;
1819  CFList bufFactors= factors;
1821  for (long i= 1; i <= N.NumCols(); i++)
1822  {
1823  if (zeroOneVecs [i - 1] == 0)
1824  continue;
1825  iter= factors;
1826  buf= 1;
1827  factorsConsidered= CFList();
1828  for (long j= 1; j <= N.NumRows(); j++, iter++)
1829  {
1830  if (!IsZero (N (j,i)))
1831  {
1832  factorsConsidered.append (iter.getItem());
1833  buf= mulMod2 (buf, iter.getItem(), yToL);
1834  }
1835  }
1836  buf= mulMod2 (buf, LC (F,x), yToL);
1837  buf /= content (buf, x);
1838  if (fdivides (buf, F, quot))
1839  {
1840  F= quot;
1841  F /= Lc (F);
1842  result.append (buf (y-eval,y));
1843  bufFactors= Difference (bufFactors, factorsConsidered);
1844  }
1845  if (degree (F) <= 0)
1846  {
1847  G= F;
1848  factors= bufFactors;
1849  return result;
1850  }
1851  }
1852  G= F;
1853  factors= bufFactors;
1854  return result;
1855 }
1856 
1857 CFList
1858 monicReconstruction (CanonicalForm& G, CFList& factors, int* zeroOneVecs,
1859  int precision, const mat_zz_pE& N
1860  )
1861 {
1862  Variable y= Variable (2);
1863  Variable x= Variable (1);
1864  CanonicalForm F= G;
1865  CanonicalForm yToL= power (y, precision);
1866  CanonicalForm quot, buf, buf2;
1867  CFList result;
1868  CFList bufFactors= factors;
1869  CFList factorsConsidered;
1871  for (long i= 1; i <= N.NumCols(); i++)
1872  {
1873  if (zeroOneVecs [i - 1] == 0)
1874  continue;
1875  iter= factors;
1876  buf= 1;
1877  factorsConsidered= CFList();
1878  for (long j= 1; j <= N.NumRows(); j++, iter++)
1879  {
1880  if (!IsZero (N (j,i)))
1881  {
1882  factorsConsidered.append (iter.getItem());
1883  buf= mulMod2 (buf, iter.getItem(), yToL);
1884  }
1885  }
1886  buf2= buf;
1887  buf= mulMod2 (buf, LC (F,x), yToL);
1888  buf /= content (buf, x);
1889  if (fdivides (buf, F, quot))
1890  {
1891  F= quot;
1892  F /= Lc (F);
1893  result.append (buf2);
1894  bufFactors= Difference (bufFactors, factorsConsidered);
1895  }
1896  if (degree (F) <= 0)
1897  {
1898  G= F;
1899  factors= bufFactors;
1900  return result;
1901  }
1902  }
1903  G= F;
1904  factors= bufFactors;
1905  return result;
1906 }
1907 
1908 #ifndef HAVE_FLINT
1909 CFList
1910 extReconstruction (CanonicalForm& G, CFList& factors, int* zeroOneVecs, int
1911  precision, const mat_zz_p& N, const ExtensionInfo& info,
1912  const CanonicalForm& evaluation
1913  )
1914 {
1915  Variable y= Variable (2);
1916  Variable x= Variable (1);
1917  Variable alpha= info.getAlpha();
1918  Variable beta= info.getBeta();
1919  int k= info.getGFDegree();
1920  CanonicalForm gamma= info.getGamma();
1921  CanonicalForm delta= info.getDelta();
1922  CanonicalForm F= G;
1923  CanonicalForm yToL= power (y, precision);
1924  CFList result;
1925  CFList bufFactors= factors;
1926  CFList factorsConsidered;
1927  CanonicalForm buf2, quot, buf;
1929  for (long i= 1; i <= N.NumCols(); i++)
1930  {
1931  if (zeroOneVecs [i - 1] == 0)
1932  continue;
1933  iter= factors;
1934  buf= 1;
1935  factorsConsidered= CFList();
1936  for (long j= 1; j <= N.NumRows(); j++, iter++)
1937  {
1938  if (!IsZero (N (j,i)))
1939  {
1940  factorsConsidered.append (iter.getItem());
1941  buf= mulMod2 (buf, iter.getItem(), yToL);
1942  }
1943  }
1944  buf= mulMod2 (buf, LC (F,x), yToL);
1945  buf /= content (buf, x);
1946  buf2= buf (y-evaluation, y);
1947  buf2 /= Lc (buf2);
1948  if (!k && beta == x)
1949  {
1950  if (degree (buf2, alpha) < 1)
1951  {
1952  if (fdivides (buf, F, quot))
1953  {
1954  F= quot;
1955  F /= Lc (F);
1956  result.append (buf2);
1957  bufFactors= Difference (bufFactors, factorsConsidered);
1958  }
1959  }
1960  }
1961  else
1962  {
1963  CFList source, dest;
1964 
1965  if (!isInExtension (buf2, gamma, k, delta, source, dest))
1966  {
1967  if (fdivides (buf, F, quot))
1968  {
1969  F= quot;
1970  F /= Lc (F);
1971  result.append (buf2);
1972  bufFactors= Difference (bufFactors, factorsConsidered);
1973  }
1974  }
1975  }
1976  if (degree (F) <= 0)
1977  {
1978  G= F;
1979  factors= bufFactors;
1980  return result;
1981  }
1982  }
1983  G= F;
1984  factors= bufFactors;
1985  return result;
1986 }
1987 #endif
1988 
1989 #ifdef HAVE_FLINT
1990 CFList
1991 extReconstruction (CanonicalForm& G, CFList& factors, int* zeroOneVecs, int
1992  precision, const nmod_mat_t N, const ExtensionInfo& info,
1993  const CanonicalForm& evaluation
1994  )
1995 {
1996  Variable y= Variable (2);
1997  Variable x= Variable (1);
1998  Variable alpha= info.getAlpha();
1999  Variable beta= info.getBeta();
2000  int k= info.getGFDegree();
2001  CanonicalForm gamma= info.getGamma();
2002  CanonicalForm delta= info.getDelta();
2003  CanonicalForm F= G;
2004  CanonicalForm yToL= power (y, precision);
2005  CFList result;
2006  CFList bufFactors= factors;
2007  CFList factorsConsidered;
2008  CanonicalForm buf2, quot, buf;
2010  for (long i= 0; i < nmod_mat_ncols(N); i++)
2011  {
2012  if (zeroOneVecs [i] == 0)
2013  continue;
2014  iter= factors;
2015  buf= 1;
2016  factorsConsidered= CFList();
2017  for (long j= 0; j < nmod_mat_nrows(N); j++, iter++)
2018  {
2019  if (!(nmod_mat_entry (N, j, i) == 0))
2020  {
2021  factorsConsidered.append (iter.getItem());
2022  buf= mulMod2 (buf, iter.getItem(), yToL);
2023  }
2024  }
2025  buf= mulMod2 (buf, LC (F,x), yToL);
2026  buf /= content (buf, x);
2027  buf2= buf (y-evaluation, y);
2028  buf2 /= Lc (buf2);
2029  if (!k && beta == x)
2030  {
2031  if (degree (buf2, alpha) < 1)
2032  {
2033  if (fdivides (buf, F, quot))
2034  {
2035  F= quot;
2036  F /= Lc (F);
2037  result.append (buf2);
2038  bufFactors= Difference (bufFactors, factorsConsidered);
2039  }
2040  }
2041  }
2042  else
2043  {
2044  CFList source, dest;
2045 
2046  if (!isInExtension (buf2, gamma, k, delta, source, dest))
2047  {
2048  if (fdivides (buf, F, quot))
2049  {
2050  F= quot;
2051  F /= Lc (F);
2052  result.append (buf2);
2053  bufFactors= Difference (bufFactors, factorsConsidered);
2054  }
2055  }
2056  }
2057  if (degree (F) <= 0)
2058  {
2059  G= F;
2060  factors= bufFactors;
2061  return result;
2062  }
2063  }
2064  G= F;
2065  factors= bufFactors;
2066  return result;
2067 }
2068 #endif
2069 
2070 #ifndef HAVE_FLINT
2071 CFList
2072 reconstruction (CanonicalForm& G, CFList& factors, int* zeroOneVecs,
2073  int precision, const mat_zz_p& N, const CanonicalForm& eval)
2074 {
2075  Variable y= Variable (2);
2076  Variable x= Variable (1);
2077  CanonicalForm F= G;
2078  CanonicalForm yToL= power (y, precision);
2079  CanonicalForm quot, buf;
2080  CFList result;
2081  CFList bufFactors= factors;
2082  CFList factorsConsidered;
2084  for (long i= 1; i <= N.NumCols(); i++)
2085  {
2086  if (zeroOneVecs [i - 1] == 0)
2087  continue;
2088  iter= factors;
2089  buf= 1;
2090  factorsConsidered= CFList();
2091  for (long j= 1; j <= N.NumRows(); j++, iter++)
2092  {
2093  if (!IsZero (N (j,i)))
2094  {
2095  factorsConsidered.append (iter.getItem());
2096  buf= mulMod2 (buf, iter.getItem(), yToL);
2097  }
2098  }
2099  buf= mulMod2 (buf, LC (F,x), yToL);
2100  buf /= content (buf, x);
2101  if (fdivides (buf, F, quot))
2102  {
2103  F= quot;
2104  F /= Lc (F);
2105  result.append (buf (y-eval,y));
2106  bufFactors= Difference (bufFactors, factorsConsidered);
2107  }
2108  if (degree (F) <= 0)
2109  {
2110  G= F;
2111  factors= bufFactors;
2112  return result;
2113  }
2114  }
2115  G= F;
2116  factors= bufFactors;
2117  return result;
2118 }
2119 #endif
2120 
2121 #ifdef HAVE_FLINT
2122 CFList
2123 reconstruction (CanonicalForm& G, CFList& factors, int* zeroOneVecs,
2124  int precision, const nmod_mat_t N, const CanonicalForm& eval)
2125 {
2126  Variable y= Variable (2);
2127  Variable x= Variable (1);
2128  CanonicalForm F= G;
2129  CanonicalForm yToL= power (y, precision);
2130  CanonicalForm quot, buf;
2131  CFList result;
2132  CFList bufFactors= factors;
2133  CFList factorsConsidered;
2135  for (long i= 0; i < nmod_mat_ncols (N); i++)
2136  {
2137  if (zeroOneVecs [i] == 0)
2138  continue;
2139  iter= factors;
2140  buf= 1;
2141  factorsConsidered= CFList();
2142  for (long j= 0; j < nmod_mat_nrows (N); j++, iter++)
2143  {
2144  if (!(nmod_mat_entry (N, j, i) == 0))
2145  {
2146  factorsConsidered.append (iter.getItem());
2147  buf= mulMod2 (buf, iter.getItem(), yToL);
2148  }
2149  }
2150  buf= mulMod2 (buf, LC (F,x), yToL);
2151  buf /= content (buf, x);
2152  if (fdivides (buf, F, quot))
2153  {
2154  F= quot;
2155  F /= Lc (F);
2156  result.append (buf (y-eval,y));
2157  bufFactors= Difference (bufFactors, factorsConsidered);
2158  }
2159  if (degree (F) <= 0)
2160  {
2161  G= F;
2162  factors= bufFactors;
2163  return result;
2164  }
2165  }
2166  G= F;
2167  factors= bufFactors;
2168  return result;
2169 }
2170 #endif
2171 
2172 #ifndef HAVE_FLINT
2173 void
2174 extReconstructionTry (CFList& reconstructedFactors, CanonicalForm& F, const
2175  CFList& factors, const int liftBound, int& factorsFound,
2176  int*& factorsFoundIndex, mat_zz_p& N, bool beenInThres,
2177  const ExtensionInfo& info, const CanonicalForm& evaluation
2178  )
2179 {
2180  Variable y= Variable (2);
2181  Variable x= Variable (1);
2182  Variable alpha= info.getAlpha();
2183  Variable beta= info.getBeta();
2184  int k= info.getGFDegree();
2185  CanonicalForm gamma= info.getGamma();
2186  CanonicalForm delta= info.getDelta();
2187  CanonicalForm yToL= power (y, liftBound);
2188  CFList source, dest;
2189  if (factors.length() == 2)
2190  {
2191  CanonicalForm tmp1, tmp2, tmp3;
2192  tmp1= factors.getFirst();
2193  tmp2= factors.getLast();
2194  tmp1= mulMod2 (tmp1, LC (F,x), yToL);
2195  tmp1 /= content (tmp1, x);
2196  tmp2= mulMod2 (tmp2, LC (F,x), yToL);
2197  tmp2 /= content (tmp2, x);
2198  tmp3 = tmp1*tmp2;
2199  if (tmp3/Lc (tmp3) == F/Lc (F))
2200  {
2201  tmp1= tmp1 (y - evaluation, y);
2202  tmp2= tmp2 (y - evaluation, y);
2203  tmp1 /= Lc (tmp1);
2204  tmp2 /= Lc (tmp2);
2205  if (!k && beta == x && degree (tmp2, alpha) < 1 &&
2206  degree (tmp1, alpha) < 1)
2207  {
2208  factorsFound++;
2209  F= 1;
2210  tmp1= mapDown (tmp1, info, source, dest);
2211  tmp2= mapDown (tmp2, info, source, dest);
2212  reconstructedFactors.append (tmp1);
2213  reconstructedFactors.append (tmp2);
2214  return;
2215  }
2216  else if (!isInExtension (tmp2, gamma, k, delta, source, dest) &&
2217  !isInExtension (tmp1, gamma, k, delta, source, dest))
2218  {
2219  factorsFound++;
2220  F= 1;
2221  tmp1= mapDown (tmp1, info, source, dest);
2222  tmp2= mapDown (tmp2, info, source, dest);
2223  reconstructedFactors.append (tmp1);
2224  reconstructedFactors.append (tmp2);
2225  return;
2226  }
2227  }
2228  }
2229  CanonicalForm quot, buf, buf2;
2231  for (long i= 1; i <= N.NumCols(); i++)
2232  {
2233  if (factorsFoundIndex [i - 1] == 1)
2234  continue;
2235  iter= factors;
2236  if (beenInThres)
2237  {
2238  int count= 1;
2239  while (count < i)
2240  {
2241  count++;
2242  iter++;
2243  }
2244  buf= iter.getItem();
2245  }
2246  else
2247  {
2248  buf= 1;
2249  for (long j= 1; j <= N.NumRows(); j++, iter++)
2250  {
2251  if (!IsZero (N (j,i)))
2252  buf= mulMod2 (buf, iter.getItem(), yToL);
2253  }
2254  }
2255  buf= mulMod2 (buf, LC (F,x), yToL);
2256  buf /= content (buf, x);
2257  buf2= buf (y - evaluation, y);
2258  buf2 /= Lc (buf2);
2259  if (!k && beta == x)
2260  {
2261  if (degree (buf2, alpha) < 1)
2262  {
2263  if (fdivides (buf, F, quot))
2264  {
2265  factorsFoundIndex[i - 1]= 1;
2266  factorsFound++;
2267  F= quot;
2268  F /= Lc (F);
2269  buf2= mapDown (buf2, info, source, dest);
2270  reconstructedFactors.append (buf2);
2271  }
2272  }
2273  }
2274  else
2275  {
2276  if (!isInExtension (buf2, gamma, k, delta, source, dest))
2277  {
2278  if (fdivides (buf, F, quot))
2279  {
2280  factorsFoundIndex[i - 1]= 1;
2281  factorsFound++;
2282  F= quot;
2283  F /= Lc (F);
2284  buf2= mapDown (buf2, info, source, dest);
2285  reconstructedFactors.append (buf2);
2286  }
2287  }
2288  }
2289  if (degree (F) <= 0)
2290  return;
2291  if (factorsFound + 1 == N.NumCols())
2292  {
2293  CanonicalForm tmp= F (y - evaluation, y);
2294  tmp= mapDown (tmp, info, source, dest);
2295  reconstructedFactors.append (tmp);
2296  return;
2297  }
2298  }
2299 }
2300 #endif
2301 
2302 #ifdef HAVE_FLINT
2303 void
2304 extReconstructionTry (CFList& reconstructedFactors, CanonicalForm& F, const
2305  CFList& factors, const int liftBound, int& factorsFound,
2306  int*& factorsFoundIndex, nmod_mat_t N, bool beenInThres,
2307  const ExtensionInfo& info, const CanonicalForm& evaluation
2308  )
2309 {
2310  Variable y= Variable (2);
2311  Variable x= Variable (1);
2312  Variable alpha= info.getAlpha();
2313  Variable beta= info.getBeta();
2314  int k= info.getGFDegree();
2315  CanonicalForm gamma= info.getGamma();
2316  CanonicalForm delta= info.getDelta();
2317  CanonicalForm yToL= power (y, liftBound);
2318  CFList source, dest;
2319  if (factors.length() == 2)
2320  {
2321  CanonicalForm tmp1, tmp2, tmp3;
2322  tmp1= factors.getFirst();
2323  tmp2= factors.getLast();
2324  tmp1= mulMod2 (tmp1, LC (F,x), yToL);
2325  tmp1 /= content (tmp1, x);
2326  tmp2= mulMod2 (tmp2, LC (F,x), yToL);
2327  tmp2 /= content (tmp2, x);
2328  tmp3 = tmp1*tmp2;
2329  if (tmp3/Lc (tmp3) == F/Lc (F))
2330  {
2331  tmp1= tmp1 (y - evaluation, y);
2332  tmp2= tmp2 (y - evaluation, y);
2333  tmp1 /= Lc (tmp1);
2334  tmp2 /= Lc (tmp2);
2335  if (!k && beta == x && degree (tmp2, alpha) < 1 &&
2336  degree (tmp1, alpha) < 1)
2337  {
2338  factorsFound++;
2339  F= 1;
2340  tmp1= mapDown (tmp1, info, source, dest);
2341  tmp2= mapDown (tmp2, info, source, dest);
2342  reconstructedFactors.append (tmp1);
2343  reconstructedFactors.append (tmp2);
2344  return;
2345  }
2346  else if (!isInExtension (tmp2, gamma, k, delta, source, dest) &&
2347  !isInExtension (tmp1, gamma, k, delta, source, dest))
2348  {
2349  factorsFound++;
2350  F= 1;
2351  tmp1= mapDown (tmp1, info, source, dest);
2352  tmp2= mapDown (tmp2, info, source, dest);
2353  reconstructedFactors.append (tmp1);
2354  reconstructedFactors.append (tmp2);
2355  return;
2356  }
2357  }
2358  }
2359  CanonicalForm quot, buf, buf2;
2361  for (long i= 0; i < nmod_mat_ncols (N); i++)
2362  {
2363  if (factorsFoundIndex [i] == 1)
2364  continue;
2365  iter= factors;
2366  if (beenInThres)
2367  {
2368  int count= 0;
2369  while (count < i)
2370  {
2371  count++;
2372  iter++;
2373  }
2374  buf= iter.getItem();
2375  }
2376  else
2377  {
2378  buf= 1;
2379  for (long j= 0; j < nmod_mat_nrows (N); j++, iter++)
2380  {
2381  if (!(nmod_mat_entry (N, j, i) == 0))
2382  buf= mulMod2 (buf, iter.getItem(), yToL);
2383  }
2384  }
2385  buf= mulMod2 (buf, LC (F,x), yToL);
2386  buf /= content (buf, x);
2387  buf2= buf (y - evaluation, y);
2388  buf2 /= Lc (buf2);
2389  if (!k && beta == x)
2390  {
2391  if (degree (buf2, alpha) < 1)
2392  {
2393  if (fdivides (buf, F, quot))
2394  {
2395  factorsFoundIndex[i]= 1;
2396  factorsFound++;
2397  F= quot;
2398  F /= Lc (F);
2399  buf2= mapDown (buf2, info, source, dest);
2400  reconstructedFactors.append (buf2);
2401  }
2402  }
2403  }
2404  else
2405  {
2406  if (!isInExtension (buf2, gamma, k, delta, source, dest))
2407  {
2408  if (fdivides (buf, F, quot))
2409  {
2410  factorsFoundIndex[i]= 1;
2411  factorsFound++;
2412  F= quot;
2413  F /= Lc (F);
2414  buf2= mapDown (buf2, info, source, dest);
2415  reconstructedFactors.append (buf2);
2416  }
2417  }
2418  }
2419  if (degree (F) <= 0)
2420  return;
2421  if (factorsFound + 1 == nmod_mat_nrows (N))
2422  {
2423  CanonicalForm tmp= F (y - evaluation, y);
2424  tmp= mapDown (tmp, info, source, dest);
2425  reconstructedFactors.append (tmp);
2426  return;
2427  }
2428  }
2429 }
2430 #endif
2431 
2432 #ifndef HAVE_FLINT
2433 //over Fp
2434 int
2435 liftAndComputeLattice (const CanonicalForm& F, int* bounds, int sizeBounds, int
2436  start, int liftBound, int minBound, CFList& factors,
2437  mat_zz_p& NTLN, CFList& diophant, CFMatrix& M, CFArray&
2438  Pi, CFArray& bufQ, bool& irreducible
2439  )
2440 {
2441  CanonicalForm LCF= LC (F, 1);
2442  CFArray *A= new CFArray [factors.length() - 1];
2443  bool wasInBounds= false;
2444  bool hitBound= false;
2445  int l= (minBound+1)*2;
2446  int stepSize= 2;
2447  int oldL= l/2;
2448  bool reduced= false;
2449  mat_zz_p NTLK, *NTLC;
2450  CFMatrix C;
2451  CFArray buf;
2452  CFListIterator j;
2453  CanonicalForm truncF;
2454  Variable y= F.mvar();
2455  while (l <= liftBound)
2456  {
2457  TIMING_START (fac_fq_compute_lattice_lift);
2458  if (start)
2459  {
2460  henselLiftResume12 (F, factors, start, l, Pi, diophant, M);
2461  start= 0;
2462  }
2463  else
2464  {
2465  if (wasInBounds)
2466  henselLiftResume12 (F, factors, oldL, l, Pi, diophant, M);
2467  else
2468  henselLift12 (F, factors, l, Pi, diophant, M);
2469  }
2470  TIMING_END_AND_PRINT (fac_fq_compute_lattice_lift,
2471  "time to lift in compute lattice: ");
2472 
2473  factors.insert (LCF);
2474  j= factors;
2475  j++;
2476 
2477  truncF= mod (F, power (y, l));
2478  TIMING_START (fac_fq_logarithmic);
2479  for (int i= 0; i < factors.length() - 1; i++, j++)
2480  {
2481  if (!wasInBounds)
2482  A[i]= logarithmicDerivative (truncF, j.getItem(), l, bufQ[i]);
2483  else
2484  A[i]= logarithmicDerivative (truncF, j.getItem(), l, oldL, bufQ[i],
2485  bufQ[i]);
2486  }
2487  TIMING_END_AND_PRINT (fac_fq_logarithmic,
2488  "time to compute logarithmic derivative: ");
2489 
2490  for (int i= 0; i < sizeBounds; i++)
2491  {
2492  if (bounds [i] + 1 <= l/2)
2493  {
2494  wasInBounds= true;
2495  int k= tmin (bounds [i] + 1, l/2);
2496  C= CFMatrix (l - k, factors.length() - 1);
2497  for (int ii= 0; ii < factors.length() - 1; ii++)
2498  {
2499  if (A[ii].size() - 1 >= i)
2500  {
2501  buf= getCoeffs (A[ii] [i], k);
2502  writeInMatrix (C, buf, ii + 1, 0);
2503  }
2504  }
2506  NTLK= (*NTLC)*NTLN;
2507  transpose (NTLK, NTLK);
2508  kernel (NTLK, NTLK);
2509  transpose (NTLK, NTLK);
2510  NTLN *= NTLK;
2511  delete NTLC;
2512 
2513  if (NTLN.NumCols() == 1)
2514  {
2515  irreducible= true;
2516  break;
2517  }
2518  if (isReduced (NTLN) && l > (minBound+1)*2)
2519  {
2520  reduced= true;
2521  break;
2522  }
2523  }
2524  }
2525 
2526  if (irreducible)
2527  break;
2528  if (reduced)
2529  break;
2530  oldL= l;
2531  l += stepSize;
2532  stepSize *= 2;
2533  if (l > liftBound)
2534  {
2535  if (!hitBound)
2536  {
2537  l= liftBound;
2538  hitBound= true;
2539  }
2540  else
2541  break;
2542  }
2543  }
2544  delete [] A;
2545  if (!wasInBounds)
2546  {
2547  if (start)
2548  henselLiftResume12 (F, factors, start, degree (F) + 1, Pi, diophant, M);
2549  else
2550  henselLift12 (F, factors, degree (F) + 1, Pi, diophant, M);
2551  factors.insert (LCF);
2552  }
2553  return l;
2554 }
2555 #endif
2556 
2557 #ifdef HAVE_FLINT
2558 int
2559 liftAndComputeLattice (const CanonicalForm& F, int* bounds, int sizeBounds, int
2560  start, int liftBound, int minBound, CFList& factors,
2561  nmod_mat_t FLINTN, CFList& diophant, CFMatrix& M,CFArray&
2562  Pi, CFArray& bufQ, bool& irreducible
2563  )
2564 {
2565  CanonicalForm LCF= LC (F, 1);
2566  CFArray *A= new CFArray [factors.length() - 1];
2567  bool wasInBounds= false;
2568  bool hitBound= false;
2569  int l= (minBound+1)*2;
2570  int stepSize= 2;
2571  int oldL= l/2;
2572  bool reduced= false;
2573  long rank;
2574  nmod_mat_t FLINTK, FLINTC, null;
2575  CFMatrix C;
2576  CFArray buf;
2577  CFListIterator j;
2578  CanonicalForm truncF;
2579  Variable y= F.mvar();
2580  while (l <= liftBound)
2581  {
2582  TIMING_START (fac_fq_compute_lattice_lift);
2583  if (start)
2584  {
2585  henselLiftResume12 (F, factors, start, l, Pi, diophant, M);
2586  start= 0;
2587  }
2588  else
2589  {
2590  if (wasInBounds)
2591  henselLiftResume12 (F, factors, oldL, l, Pi, diophant, M);
2592  else
2593  henselLift12 (F, factors, l, Pi, diophant, M);
2594  }
2595  TIMING_END_AND_PRINT (fac_fq_compute_lattice_lift,
2596  "time to lift in compute lattice: ");
2597 
2598  factors.insert (LCF);
2599  j= factors;
2600  j++;
2601 
2602  truncF= mod (F, power (y, l));
2603  TIMING_START (fac_fq_logarithmic);
2604  for (int i= 0; i < factors.length() - 1; i++, j++)
2605  {
2606  if (!wasInBounds)
2607  A[i]= logarithmicDerivative (truncF, j.getItem(), l, bufQ[i]);
2608  else
2609  A[i]= logarithmicDerivative (truncF, j.getItem(), l, oldL, bufQ[i],
2610  bufQ[i]);
2611  }
2612  TIMING_END_AND_PRINT (fac_fq_logarithmic,
2613  "time to compute logarithmic derivative: ");
2614 
2615  for (int i= 0; i < sizeBounds; i++)
2616  {
2617  if (bounds [i] + 1 <= l/2)
2618  {
2619  wasInBounds= true;
2620  int k= tmin (bounds [i] + 1, l/2);
2621  C= CFMatrix (l - k, factors.length() - 1);
2622  for (int ii= 0; ii < factors.length() - 1; ii++)
2623  {
2624  if (A[ii].size() - 1 >= i)
2625  {
2626  buf= getCoeffs (A[ii] [i], k);
2627  writeInMatrix (C, buf, ii + 1, 0);
2628  }
2629  }
2630 
2631  convertFacCFMatrix2nmod_mat_t (FLINTC, C);
2632  nmod_mat_init (FLINTK, nmod_mat_nrows (FLINTC), nmod_mat_ncols (FLINTN),
2633  getCharacteristic());
2634  nmod_mat_mul (FLINTK, FLINTC, FLINTN);
2635  nmod_mat_init (null, nmod_mat_ncols (FLINTK), nmod_mat_ncols (FLINTK),
2636  getCharacteristic());
2637  rank= nmod_mat_nullspace (null, FLINTK);
2638  nmod_mat_clear (FLINTK);
2639  nmod_mat_window_init (FLINTK, null, 0, 0, nmod_mat_nrows(null), rank);
2640  nmod_mat_clear (FLINTC);
2641  nmod_mat_init_set (FLINTC, FLINTN);
2642  nmod_mat_clear (FLINTN);
2643  nmod_mat_init (FLINTN, nmod_mat_nrows (FLINTC), nmod_mat_ncols (FLINTK),
2644  getCharacteristic());
2645  nmod_mat_mul (FLINTN, FLINTC, FLINTK); //no aliasing allowed!!
2646 
2647  nmod_mat_clear (FLINTC);
2648  nmod_mat_window_clear (FLINTK);
2649  nmod_mat_clear (null);
2650  if (nmod_mat_ncols (FLINTN) == 1)
2651  {
2652  irreducible= true;
2653  break;
2654  }
2655  if (isReduced (FLINTN) && l > (minBound+1)*2)
2656  {
2657  reduced= true;
2658  break;
2659  }
2660  }
2661  }
2662 
2663  if (irreducible)
2664  break;
2665  if (reduced)
2666  break;
2667  oldL= l;
2668  l += stepSize;
2669  stepSize *= 2;
2670  if (l > liftBound)
2671  {
2672  if (!hitBound)
2673  {
2674  l= liftBound;
2675  hitBound= true;
2676  }
2677  else
2678  break;
2679  }
2680  }
2681  delete [] A;
2682  if (!wasInBounds)
2683  {
2684  if (start)
2685  henselLiftResume12 (F, factors, start, degree (F) + 1, Pi, diophant, M);
2686  else
2687  henselLift12 (F, factors, degree (F) + 1, Pi, diophant, M);
2688  factors.insert (LCF);
2689  }
2690  return l;
2691 }
2692 #endif
2693 
2694 #ifndef HAVE_FLINT
2695 //over field extension
2696 int
2697 extLiftAndComputeLattice (const CanonicalForm& F, int* bounds, int sizeBounds,
2698  int liftBound, int minBound, int start, CFList&
2699  factors, mat_zz_p& NTLN, CFList& diophant,
2700  CFMatrix& M, CFArray& Pi, CFArray& bufQ, bool&
2701  irreducible, const CanonicalForm& evaluation, const
2702  ExtensionInfo& info, CFList& source, CFList& dest
2703  )
2704 {
2705  bool GF= (CFFactory::gettype()==GaloisFieldDomain);
2706  CanonicalForm LCF= LC (F, 1);
2707  CFArray *A= new CFArray [factors.length() - 1];
2708  bool wasInBounds= false;
2709  bool hitBound= false;
2710  int degMipo;
2711  Variable alpha;
2712  alpha= info.getAlpha();
2713  degMipo= degree (getMipo (alpha));
2714 
2715  Variable gamma= info.getBeta();
2716  CanonicalForm primElemAlpha= info.getGamma();
2717  CanonicalForm imPrimElemAlpha= info.getDelta();
2718 
2719  int stepSize= 2;
2720  int l= ((minBound+1)/degMipo+1)*2;
2721  l= tmax (l, 2);
2722  if (start > l)
2723  l= start;
2724  int oldL= l/2;
2725  bool reduced= false;
2726  Variable y= F.mvar();
2727  Variable x= Variable (1);
2728  CanonicalForm powX, imBasis, truncF;
2729  CFMatrix Mat, C;
2730  CFArray buf;
2731  CFIterator iter;
2732  mat_zz_p* NTLMat, *NTLC, NTLK;
2733  CFListIterator j;
2734  while (l <= liftBound)
2735  {
2736  TIMING_START (fac_fq_compute_lattice_lift);
2737  if (start)
2738  {
2739  henselLiftResume12 (F, factors, start, l, Pi, diophant, M);
2740  start= 0;
2741  }
2742  else
2743  {
2744  if (wasInBounds)
2745  henselLiftResume12 (F, factors, oldL, l, Pi, diophant, M);
2746  else
2747  henselLift12 (F, factors, l, Pi, diophant, M);
2748  }
2749  TIMING_END_AND_PRINT (fac_fq_compute_lattice_lift,
2750  "time to lift in compute lattice: ");
2751 
2752  factors.insert (LCF);
2753 
2754  if (GF)
2756 
2757  powX= power (y-gamma, l);
2758  Mat= CFMatrix (l*degMipo, l*degMipo);
2759  for (int i= 0; i < l*degMipo; i++)
2760  {
2761  imBasis= mod (power (y, i), powX);
2762  imBasis= imBasis (power (y, degMipo), y);
2763  imBasis= imBasis (y, gamma);
2764  iter= imBasis;
2765  for (; iter.hasTerms(); iter++)
2766  Mat (iter.exp()+ 1, i+1)= iter.coeff();
2767  }
2768 
2769  NTLMat= convertFacCFMatrix2NTLmat_zz_p (Mat);
2770  *NTLMat= inv (*NTLMat);
2771 
2772  if (GF)
2773  setCharacteristic (getCharacteristic(), degMipo, info.getGFName());
2774 
2775  j= factors;
2776  j++;
2777 
2778  truncF= mod (F, power (y, l));
2779  TIMING_START (fac_fq_logarithmic);
2780  for (int i= 0; i < factors.length() - 1; i++, j++)
2781  {
2782  if (!wasInBounds)
2783  A[i]= logarithmicDerivative (truncF, j.getItem(), l, bufQ[i]);
2784  else
2785  A[i]= logarithmicDerivative (truncF, j.getItem(), l, oldL, bufQ[i],
2786  bufQ[i]);
2787  }
2788  TIMING_END_AND_PRINT (fac_fq_logarithmic,
2789  "time to compute logarithmic derivative: ");
2790 
2791  for (int i= 0; i < sizeBounds; i++)
2792  {
2793  if (bounds [i] + 1 <= (l/2)*degMipo)
2794  {
2795  wasInBounds= true;
2796  int k= tmin (bounds [i] + 1, (l/2)*degMipo);
2797  C= CFMatrix (l*degMipo - k, factors.length() - 1);
2798 
2799  for (int ii= 0; ii < factors.length() - 1; ii++)
2800  {
2801  if (A[ii].size() - 1 >= i)
2802  {
2803  if (GF)
2804  {
2805  A [ii] [i]= A [ii] [i] (y-evaluation, y);
2807  A[ii] [i]= GF2FalphaRep (A[ii] [i], alpha);
2808  if (alpha != gamma)
2809  A [ii] [i]= mapDown (A[ii] [i], imPrimElemAlpha, primElemAlpha,
2810  gamma, source, dest
2811  );
2812  buf= getCoeffs (A[ii] [i], k, l, degMipo, gamma, 0, *NTLMat);
2813  }
2814  else
2815  {
2816  A [ii] [i]= A [ii] [i] (y-evaluation, y);
2817  if (alpha != gamma)
2818  A[ii] [i]= mapDown (A[ii] [i], imPrimElemAlpha, primElemAlpha,
2819  gamma, source, dest
2820  );
2821  buf= getCoeffs (A[ii] [i], k, l, degMipo, gamma, 0, *NTLMat);
2822  }
2823  writeInMatrix (C, buf, ii + 1, 0);
2824  }
2825  if (GF)
2826  setCharacteristic (getCharacteristic(), degMipo, info.getGFName());
2827  }
2828 
2829  if (GF)
2831 
2833  NTLK= (*NTLC)*NTLN;
2834  transpose (NTLK, NTLK);
2835  kernel (NTLK, NTLK);
2836  transpose (NTLK, NTLK);
2837  NTLN *= NTLK;
2838  delete NTLC;
2839 
2840  if (GF)
2841  setCharacteristic (getCharacteristic(), degMipo, info.getGFName());
2842 
2843  if (NTLN.NumCols() == 1)
2844  {
2845  irreducible= true;
2846  break;
2847  }
2848  if (isReduced (NTLN))
2849  {
2850  reduced= true;
2851  break;
2852  }
2853  }
2854  }
2855 
2856  delete NTLMat;
2857 
2858  if (NTLN.NumCols() == 1)
2859  {
2860  irreducible= true;
2861  break;
2862  }
2863  if (reduced)
2864  break;
2865  oldL= l;
2866  l += stepSize;
2867  stepSize *= 2;
2868  if (l > liftBound)
2869  {
2870  if (!hitBound)
2871  {
2872  l= liftBound;
2873  hitBound= true;
2874  }
2875  else
2876  break;
2877  }
2878  }
2879  delete [] A;
2880  if (!wasInBounds)
2881  {
2882  if (start)
2883  henselLiftResume12 (F, factors, start, degree (F) + 1, Pi, diophant, M);
2884  else
2885  henselLift12 (F, factors, degree (F) + 1, Pi, diophant, M);
2886  factors.insert (LCF);
2887  }
2888  return l;
2889 }
2890 #endif
2891 
2892 #ifdef HAVE_FLINT
2893 //over field extension
2894 int
2895 extLiftAndComputeLattice (const CanonicalForm& F, int* bounds, int sizeBounds,
2896  int liftBound, int minBound, int start, CFList&
2897  factors, nmod_mat_t FLINTN, CFList& diophant,
2898  CFMatrix& M, CFArray& Pi, CFArray& bufQ, bool&
2899  irreducible, const CanonicalForm& evaluation, const
2900  ExtensionInfo& info, CFList& source, CFList& dest
2901  )
2902 {
2903  bool GF= (CFFactory::gettype()==GaloisFieldDomain);
2904  CanonicalForm LCF= LC (F, 1);
2905  CFArray *A= new CFArray [factors.length() - 1];
2906  bool wasInBounds= false;
2907  bool hitBound= false;
2908  int degMipo;
2909  Variable alpha;
2910  alpha= info.getAlpha();
2911  degMipo= degree (getMipo (alpha));
2912 
2913  Variable gamma= info.getBeta();
2914  CanonicalForm primElemAlpha= info.getGamma();
2915  CanonicalForm imPrimElemAlpha= info.getDelta();
2916 
2917  int stepSize= 2;
2918  int l= ((minBound+1)/degMipo+1)*2;
2919  l= tmax (l, 2);
2920  if (start > l)
2921  l= start;
2922  int oldL= l/2;
2923  bool reduced= false;
2924  Variable y= F.mvar();
2925  Variable x= Variable (1);
2926  CanonicalForm powX, imBasis, truncF;
2927  CFMatrix Mat, C;
2928  CFArray buf;
2929  CFIterator iter;
2930  long rank;
2931  nmod_mat_t FLINTMat, FLINTMatInv, FLINTC, FLINTK, null;
2932  CFListIterator j;
2933  while (l <= liftBound)
2934  {
2935  if (start)
2936  {
2937  henselLiftResume12 (F, factors, start, l, Pi, diophant, M);
2938  start= 0;
2939  }
2940  else
2941  {
2942  if (wasInBounds)
2943  henselLiftResume12 (F, factors, oldL, l, Pi, diophant, M);
2944  else
2945  henselLift12 (F, factors, l, Pi, diophant, M);
2946  }
2947 
2948  factors.insert (LCF);
2949 
2950  if (GF)
2952 
2953  powX= power (y-gamma, l);
2954  Mat= CFMatrix (l*degMipo, l*degMipo);
2955  for (int i= 0; i < l*degMipo; i++)
2956  {
2957  imBasis= mod (power (y, i), powX);
2958  imBasis= imBasis (power (y, degMipo), y);
2959  imBasis= imBasis (y, gamma);
2960  iter= imBasis;
2961  for (; iter.hasTerms(); iter++)
2962  Mat (iter.exp()+ 1, i+1)= iter.coeff();
2963  }
2964 
2965  convertFacCFMatrix2nmod_mat_t (FLINTMat, Mat);
2966  nmod_mat_init (FLINTMatInv, nmod_mat_nrows (FLINTMat),
2967  nmod_mat_nrows (FLINTMat), getCharacteristic());
2968  nmod_mat_inv (FLINTMatInv, FLINTMat);
2969 
2970  if (GF)
2971  setCharacteristic (getCharacteristic(), degMipo, info.getGFName());
2972 
2973  j= factors;
2974  j++;
2975 
2976  truncF= mod (F, power (y, l));
2977  for (int i= 0; i < factors.length() - 1; i++, j++)
2978  {
2979  if (!wasInBounds)
2980  A[i]= logarithmicDerivative (truncF, j.getItem(), l, bufQ[i]);
2981  else
2982  A[i]= logarithmicDerivative (truncF, j.getItem(), l, oldL, bufQ[i],
2983  bufQ[i]);
2984  }
2985 
2986  for (int i= 0; i < sizeBounds; i++)
2987  {
2988  if (bounds [i] + 1 <= (l/2)*degMipo)
2989  {
2990  wasInBounds= true;
2991  int k= tmin (bounds [i] + 1, (l/2)*degMipo);
2992  C= CFMatrix (l*degMipo - k, factors.length() - 1);
2993 
2994  for (int ii= 0; ii < factors.length() - 1; ii++)
2995  {
2996  if (A[ii].size() - 1 >= i)
2997  {
2998  if (GF)
2999  {
3000  A [ii] [i]= A [ii] [i] (y-evaluation, y);
3002  A[ii] [i]= GF2FalphaRep (A[ii] [i], alpha);
3003  if (alpha != gamma)
3004  A [ii] [i]= mapDown (A[ii] [i], imPrimElemAlpha, primElemAlpha,
3005  gamma, source, dest
3006  );
3007  buf= getCoeffs (A[ii] [i], k, l, degMipo, gamma, 0, FLINTMatInv);
3008  }
3009  else
3010  {
3011  A [ii] [i]= A [ii] [i] (y-evaluation, y);
3012  if (alpha != gamma)
3013  A[ii] [i]= mapDown (A[ii] [i], imPrimElemAlpha, primElemAlpha,
3014  gamma, source, dest
3015  );
3016  buf= getCoeffs (A[ii] [i], k, l, degMipo, gamma, 0, FLINTMatInv);
3017  }
3018  writeInMatrix (C, buf, ii + 1, 0);
3019  }
3020  if (GF)
3021  setCharacteristic (getCharacteristic(), degMipo, info.getGFName());
3022  }
3023 
3024  if (GF)
3026 
3027  convertFacCFMatrix2nmod_mat_t (FLINTC, C);
3028  nmod_mat_init (FLINTK, nmod_mat_nrows (FLINTC), nmod_mat_ncols (FLINTN),
3029  getCharacteristic());
3030  nmod_mat_mul (FLINTK, FLINTC, FLINTN);
3031  nmod_mat_init (null, nmod_mat_ncols (FLINTK), nmod_mat_ncols (FLINTK),
3032  getCharacteristic());
3033  rank= nmod_mat_nullspace (null, FLINTK);
3034  nmod_mat_clear (FLINTK);
3035  nmod_mat_window_init (FLINTK, null, 0, 0, nmod_mat_nrows(null), rank);
3036  nmod_mat_clear (FLINTC);
3037  nmod_mat_init_set (FLINTC, FLINTN);
3038  nmod_mat_clear (FLINTN);
3039  nmod_mat_init (FLINTN, nmod_mat_nrows (FLINTC), nmod_mat_ncols (FLINTK),
3040  getCharacteristic());
3041  nmod_mat_mul (FLINTN, FLINTC, FLINTK); //no aliasing allowed!!
3042 
3043  nmod_mat_clear (FLINTC);
3044  nmod_mat_window_clear (FLINTK);
3045  nmod_mat_clear (null);
3046 
3047  if (GF)
3048  setCharacteristic (getCharacteristic(), degMipo, info.getGFName());
3049 
3050  if (nmod_mat_ncols (FLINTN) == 1)
3051  {
3052  irreducible= true;
3053  break;
3054  }
3055  if (isReduced (FLINTN))
3056  {
3057  reduced= true;
3058  break;
3059  }
3060  }
3061  }
3062 
3063  nmod_mat_clear (FLINTMat);
3064  nmod_mat_clear (FLINTMatInv);
3065 
3066  if (nmod_mat_ncols (FLINTN) == 1)
3067  {
3068  irreducible= true;
3069  break;
3070  }
3071  if (reduced)
3072  break;
3073  oldL= l;
3074  l += stepSize;
3075  stepSize *= 2;
3076  if (l > liftBound)
3077  {
3078  if (!hitBound)
3079  {
3080  l= liftBound;
3081  hitBound= true;
3082  }
3083  else
3084  break;
3085  }
3086  }
3087  delete [] A;
3088  if (!wasInBounds)
3089  {
3090  if (start)
3091  henselLiftResume12 (F, factors, start, degree (F) + 1, Pi, diophant, M);
3092  else
3093  henselLift12 (F, factors, degree (F) + 1, Pi, diophant, M);
3094  factors.insert (LCF);
3095  }
3096  return l;
3097 }
3098 #endif
3099 
3100 // over Fq
3101 int
3102 liftAndComputeLattice (const CanonicalForm& F, int* bounds, int sizeBounds,
3103  int start, int liftBound, int minBound, CFList& factors,
3104  mat_zz_pE& NTLN, CFList& diophant, CFMatrix& M, CFArray&
3105  Pi, CFArray& bufQ, bool& irreducible
3106  )
3107 {
3108  CanonicalForm LCF= LC (F, 1);
3109  CFArray *A= new CFArray [factors.length() - 1];
3110  bool wasInBounds= false;
3111  bool hitBound= false;
3112  int l= (minBound+1)*2;
3113  int stepSize= 2;
3114  int oldL= l/2;
3115  bool reduced= false;
3116  CFListIterator j;
3117  mat_zz_pE* NTLC, NTLK;
3118  CFArray buf;
3119  CFMatrix C;
3120  Variable y= F.mvar();
3121  CanonicalForm truncF;
3122  while (l <= liftBound)
3123  {
3124  TIMING_START (fac_fq_compute_lattice_lift);
3125  if (start)
3126  {
3127  henselLiftResume12 (F, factors, start, l, Pi, diophant, M);
3128  start= 0;
3129  }
3130  else
3131  {
3132  if (wasInBounds)
3133  henselLiftResume12 (F, factors, oldL, l, Pi, diophant, M);
3134  else
3135  henselLift12 (F, factors, l, Pi, diophant, M);
3136  }
3137  TIMING_END_AND_PRINT (fac_fq_compute_lattice_lift,
3138  "time to lift in compute lattice: ");
3139 
3140  factors.insert (LCF);
3141  j= factors;
3142  j++;
3143 
3144  truncF= mod (F, power (y,l));
3145  TIMING_START (fac_fq_logarithmic);
3146  for (int i= 0; i < factors.length() - 1; i++, j++)
3147  {
3148  if (l == (minBound+1)*2)
3149  {
3150  A[i]= logarithmicDerivative (truncF, j.getItem(), l, bufQ[i]);
3151  }
3152  else
3153  {
3154  A[i]= logarithmicDerivative (truncF, j.getItem(), l, oldL, bufQ[i],
3155  bufQ[i]
3156  );
3157  }
3158  }
3159  TIMING_END_AND_PRINT (fac_fq_logarithmic,
3160  "time to compute logarithmic derivative: ");
3161 
3162  for (int i= 0; i < sizeBounds; i++)
3163  {
3164  if (bounds [i] + 1 <= l/2)
3165  {
3166  wasInBounds= true;
3167  int k= tmin (bounds [i] + 1, l/2);
3168  C= CFMatrix (l - k, factors.length() - 1);
3169  for (int ii= 0; ii < factors.length() - 1; ii++)
3170  {
3171 
3172  if (A[ii].size() - 1 >= i)
3173  {
3174  buf= getCoeffs (A[ii] [i], k);
3175  writeInMatrix (C, buf, ii + 1, 0);
3176  }
3177  }
3178 
3180  NTLK= (*NTLC)*NTLN;
3181  transpose (NTLK, NTLK);
3182  kernel (NTLK, NTLK);
3183  transpose (NTLK, NTLK);
3184  NTLN *= NTLK;
3185  delete NTLC;
3186 
3187  if (NTLN.NumCols() == 1)
3188  {
3189  irreducible= true;
3190  break;
3191  }
3192  if (isReduced (NTLN) && l > (minBound+1)*2)
3193  {
3194  reduced= true;
3195  break;
3196  }
3197  }
3198  }
3199 
3200  if (NTLN.NumCols() == 1)
3201  {
3202  irreducible= true;
3203  break;
3204  }
3205  if (reduced)
3206  break;
3207  oldL= l;
3208  l += stepSize;
3209  stepSize *= 2;
3210  if (l > liftBound)
3211  {
3212  if (!hitBound)
3213  {
3214  l= liftBound;
3215  hitBound= true;
3216  }
3217  else
3218  break;
3219  }
3220  }
3221  delete [] A;
3222  if (!wasInBounds)
3223  {
3224  if (start)
3225  henselLiftResume12 (F, factors, start, degree (F) + 1, Pi, diophant, M);
3226  else
3227  henselLift12 (F, factors, degree (F) + 1, Pi, diophant, M);
3228  factors.insert (LCF);
3229  }
3230  return l;
3231 }
3232 
3233 #ifdef HAVE_FLINT
3234 int
3235 liftAndComputeLatticeFq2Fp (const CanonicalForm& F, int* bounds, int sizeBounds,
3236  int start, int liftBound, int minBound, CFList&
3237  factors, nmod_mat_t FLINTN, CFList& diophant,
3238  CFMatrix& M, CFArray& Pi, CFArray& bufQ, bool&
3239  irreducible, const Variable& alpha
3240  )
3241 #else
3242 int
3243 liftAndComputeLatticeFq2Fp (const CanonicalForm& F, int* bounds, int sizeBounds,
3244  int start, int liftBound, int minBound, CFList&
3245  factors, mat_zz_p& NTLN, CFList& diophant, CFMatrix&
3246  M, CFArray& Pi, CFArray& bufQ, bool& irreducible,
3247  const Variable& alpha
3248  )
3249 #endif
3250 {
3251  CanonicalForm LCF= LC (F, 1);
3252  CFArray *A= new CFArray [factors.length() - 1];
3253  bool wasInBounds= false;
3254  int l= (minBound+1)*2;
3255  int oldL= l/2;
3256  int stepSize= 2;
3257  bool hitBound= false;
3258  int extensionDeg= degree (getMipo (alpha));
3259  bool reduced= false;
3260  CFListIterator j;
3261  CFMatrix C;
3262  CFArray buf;
3263 #ifdef HAVE_FLINT
3264  long rank;
3265  nmod_mat_t FLINTC, FLINTK, null;
3266 #else
3267  mat_zz_p* NTLC, NTLK;
3268 #endif
3269  Variable y= F.mvar();
3270  CanonicalForm truncF;
3271  while (l <= liftBound)
3272  {
3273  TIMING_START (fac_fq_compute_lattice_lift);
3274  if (start)
3275  {
3276  henselLiftResume12 (F, factors, start, l, Pi, diophant, M);
3277  start= 0;
3278  }
3279  else
3280  {
3281  if (wasInBounds)
3282  henselLiftResume12 (F, factors, oldL, l, Pi, diophant, M);
3283  else
3284  henselLift12 (F, factors, l, Pi, diophant, M);
3285  }
3286  TIMING_END_AND_PRINT (fac_fq_compute_lattice_lift,
3287  "time to lift in compute lattice: ");
3288 
3289  factors.insert (LCF);
3290  j= factors;
3291  j++;
3292 
3293  truncF= mod (F, power (y,l));
3294  TIMING_START (fac_fq_logarithmic);
3295  for (int i= 0; i < factors.length() - 1; i++, j++)
3296  {
3297  if (l == (minBound+1)*2)
3298  {
3299  A[i]= logarithmicDerivative (truncF, j.getItem(), l, bufQ[i]);
3300  }
3301  else
3302  {
3303  A[i]= logarithmicDerivative (truncF, j.getItem(), l, oldL, bufQ[i],
3304  bufQ[i]
3305  );
3306  }
3307  }
3308  TIMING_END_AND_PRINT (fac_fq_logarithmic,
3309  "time to compute logarithmic derivative: ");
3310 
3311  for (int i= 0; i < sizeBounds; i++)
3312  {
3313  if (bounds [i] + 1 <= l/2)
3314  {
3315  wasInBounds= true;
3316  int k= tmin (bounds [i] + 1, l/2);
3317  C= CFMatrix ((l - k)*extensionDeg, factors.length() - 1);
3318  for (int ii= 0; ii < factors.length() - 1; ii++)
3319  {
3320  if (A[ii].size() - 1 >= i)
3321  {
3322  buf= getCoeffs (A[ii] [i], k, alpha);
3323  writeInMatrix (C, buf, ii + 1, 0);
3324  }
3325  }
3326 
3327 #ifdef HAVE_FLINT
3328  convertFacCFMatrix2nmod_mat_t (FLINTC, C);
3329  nmod_mat_init (FLINTK, nmod_mat_nrows (FLINTC), nmod_mat_ncols (FLINTN),
3330  getCharacteristic());
3331  nmod_mat_mul (FLINTK, FLINTC, FLINTN);
3332  nmod_mat_init (null, nmod_mat_ncols (FLINTK), nmod_mat_ncols (FLINTK),
3333  getCharacteristic());
3334  rank= nmod_mat_nullspace (null, FLINTK);
3335  nmod_mat_clear (FLINTK);
3336  nmod_mat_window_init (FLINTK, null, 0, 0, nmod_mat_nrows(null), rank);
3337  nmod_mat_clear (FLINTC);
3338  nmod_mat_init_set (FLINTC, FLINTN);
3339  nmod_mat_clear (FLINTN);
3340  nmod_mat_init (FLINTN, nmod_mat_nrows (FLINTC), nmod_mat_ncols (FLINTK),
3341  getCharacteristic());
3342  nmod_mat_mul (FLINTN, FLINTC, FLINTK); //no aliasing allowed!!
3343 
3344  nmod_mat_clear (FLINTC);
3345  nmod_mat_window_clear (FLINTK);
3346  nmod_mat_clear (null);
3347 #else
3349  NTLK= (*NTLC)*NTLN;
3350  transpose (NTLK, NTLK);
3351  kernel (NTLK, NTLK);
3352  transpose (NTLK, NTLK);
3353  NTLN *= NTLK;
3354  delete NTLC;
3355 #endif
3356 
3357 #ifdef HAVE_FLINT
3358  if (nmod_mat_nrows (FLINTN) == 1)
3359 #else
3360  if (NTLN.NumCols() == 1)
3361 #endif
3362  {
3363  irreducible= true;
3364  break;
3365  }
3366 #ifdef HAVE_FLINT
3367  if (isReduced (FLINTN) && l > (minBound+1)*2)
3368 #else
3369  if (isReduced (NTLN) && l > (minBound+1)*2)
3370 #endif
3371  {
3372  reduced= true;
3373  break;
3374  }
3375  }
3376  }
3377 
3378 #ifdef HAVE_FLINT
3379  if (nmod_mat_ncols (FLINTN) == 1)
3380 #else
3381  if (NTLN.NumCols() == 1)
3382 #endif
3383  {
3384  irreducible= true;
3385  break;
3386  }
3387  if (reduced)
3388  break;
3389  oldL= l;
3390  l += stepSize;
3391  stepSize *= 2;
3392  if (l > liftBound)
3393  {
3394  if (!hitBound)
3395  {
3396  l= liftBound;
3397  hitBound= true;
3398  }
3399  else
3400  break;
3401  }
3402  }
3403  delete [] A;
3404  if (!wasInBounds)
3405  {
3406  if (start)
3407  henselLiftResume12 (F, factors, start, degree (F) + 1, Pi, diophant, M);
3408  else
3409  henselLift12 (F, factors, degree (F) + 1, Pi, diophant, M);
3410  factors.insert (LCF);
3411  }
3412  return l;
3413 }
3414 
3415 CFList
3416 increasePrecision (CanonicalForm& F, CFList& factors, int factorsFound,
3417  int oldNumCols, int oldL, int precision,
3418  const CanonicalForm& eval
3419  )
3420 {
3421  int d;
3422  bool isIrreducible= false;
3423  int* bounds= computeBounds (F, d, isIrreducible);
3424  Variable y= F.mvar();
3425  if (isIrreducible)
3426  {
3427  delete [] bounds;
3428  CanonicalForm G= F;
3429  F= 1;
3430  return CFList (G (y-eval, y));
3431  }
3432  CFArray * A= new CFArray [factors.length()];
3433  CFArray bufQ= CFArray (factors.length());
3434 #ifdef HAVE_FLINT
3435  nmod_mat_t FLINTN;
3436  nmod_mat_init (FLINTN,factors.length(),factors.length(), getCharacteristic());
3437  for (long i=factors.length()-1; i >= 0; i--)
3438  nmod_mat_entry (FLINTN, i, i)= 1;
3439 #else
3440  mat_zz_p NTLN;
3441  ident (NTLN, factors.length());
3442 #endif
3443  int minBound= bounds[0];
3444  for (int i= 1; i < d; i++)
3445  {
3446  if (bounds[i] != 0)
3447  minBound= tmin (minBound, bounds[i]);
3448  }
3449  int l= tmax (2*(minBound + 1), oldL);
3450  int oldL2= l/2;
3451  int stepSize= 2;
3452  bool useOldQs= false;
3453  bool hitBound= false;
3454  CFListIterator j;
3455  CFMatrix C;
3456  CFArray buf;
3457 #ifdef HAVE_FLINT
3458  long rank;
3459  nmod_mat_t FLINTC, FLINTK, null;
3460 #else
3461  mat_zz_p* NTLC, NTLK;
3462 #endif
3463  CanonicalForm truncF;
3464  while (l <= precision)
3465  {
3466  j= factors;
3467  truncF= mod (F, power (y,l));
3468  if (useOldQs)
3469  {
3470  for (int i= 0; i < factors.length(); i++, j++)
3471  A[i]= logarithmicDerivative (truncF, j.getItem(), l, oldL2, bufQ[i],
3472  bufQ[i]
3473  );
3474  }
3475  else
3476  {
3477  for (int i= 0; i < factors.length(); i++, j++)
3478  A[i]= logarithmicDerivative (truncF, j.getItem(), l, bufQ [i]);
3479  }
3480  useOldQs= true;
3481  for (int i= 0; i < d; i++)
3482  {
3483  if (bounds [i] + 1 <= l/2)
3484  {
3485  int k= tmin (bounds [i] + 1, l/2);
3486  C= CFMatrix (l - k, factors.length());
3487  for (int ii= 0; ii < factors.length(); ii++)
3488  {
3489  if (A[ii].size() - 1 >= i)
3490  {
3491  buf= getCoeffs (A[ii] [i], k);
3492  writeInMatrix (C, buf, ii + 1, 0);
3493  }
3494  }
3495 #ifdef HAVE_FLINT
3496  convertFacCFMatrix2nmod_mat_t (FLINTC, C);
3497  nmod_mat_init (FLINTK, nmod_mat_nrows (FLINTC), nmod_mat_ncols (FLINTN),
3498  getCharacteristic());
3499  nmod_mat_mul (FLINTK, FLINTC, FLINTN);
3500  nmod_mat_init (null, nmod_mat_ncols (FLINTK), nmod_mat_ncols (FLINTK),
3501  getCharacteristic());
3502  rank= nmod_mat_nullspace (null, FLINTK);
3503  nmod_mat_clear (FLINTK);
3504  nmod_mat_window_init (FLINTK, null, 0, 0, nmod_mat_nrows(null), rank);
3505  nmod_mat_clear (FLINTC);
3506  nmod_mat_init_set (FLINTC, FLINTN);
3507  nmod_mat_clear (FLINTN);
3508  nmod_mat_init (FLINTN, nmod_mat_nrows (FLINTC), nmod_mat_ncols (FLINTK),
3509  getCharacteristic());
3510  nmod_mat_mul (FLINTN, FLINTC, FLINTK); //no aliasing allowed!!
3511 
3512  nmod_mat_clear (FLINTC);
3513  nmod_mat_window_clear (FLINTK);
3514  nmod_mat_clear (null);
3515 #else
3517  NTLK= (*NTLC)*NTLN;
3518  transpose (NTLK, NTLK);
3519  kernel (NTLK, NTLK);
3520  transpose (NTLK, NTLK);
3521  NTLN *= NTLK;
3522  delete NTLC;
3523 #endif
3524 #ifdef HAVE_FLINT
3525  if (nmod_mat_ncols (FLINTN) == 1)
3526  {
3527  nmod_mat_clear (FLINTN);
3528 #else
3529  if (NTLN.NumCols() == 1)
3530  {
3531 #endif
3532  delete [] A;
3533  delete [] bounds;
3534  CanonicalForm G= F;
3535  F= 1;
3536  return CFList (G (y-eval,y));
3537  }
3538  }
3539  }
3540 
3541 #ifdef HAVE_FLINT
3542  if (nmod_mat_ncols (FLINTN) < oldNumCols - factorsFound)
3543  {
3544  if (isReduced (FLINTN))
3545  {
3546  int * factorsFoundIndex= new int [nmod_mat_ncols (FLINTN)];
3547  for (long i= 0; i < nmod_mat_ncols (FLINTN); i++)
3548 #else
3549  if (NTLN.NumCols() < oldNumCols - factorsFound)
3550  {
3551  if (isReduced (NTLN))
3552  {
3553  int * factorsFoundIndex= new int [NTLN.NumCols()];
3554  for (long i= 0; i < NTLN.NumCols(); i++)
3555 #endif
3556  factorsFoundIndex[i]= 0;
3557  int factorsFound2= 0;
3558  CFList result;
3559  CanonicalForm bufF= F;
3560 #ifdef HAVE_FLINT
3561  reconstructionTry (result, bufF, factors, degree (F) + 1, factorsFound2,
3562  factorsFoundIndex, FLINTN, eval, false
3563  );
3564  if (result.length() == nmod_mat_ncols (FLINTN))
3565  {
3566  nmod_mat_clear (FLINTN);
3567 #else
3568  reconstructionTry (result, bufF, factors, degree (F) + 1, factorsFound2,
3569  factorsFoundIndex, NTLN, eval, false
3570  );
3571  if (result.length() == NTLN.NumCols())
3572  {
3573 #endif
3574  delete [] factorsFoundIndex;
3575  delete [] A;
3576  delete [] bounds;
3577  F= 1;
3578  return result;
3579  }
3580  delete [] factorsFoundIndex;
3581  }
3582  else if (l == precision)
3583  {
3584  CanonicalForm bufF= F;
3585 #ifdef HAVE_FLINT
3586  int * zeroOne= extractZeroOneVecs (FLINTN);
3587  CFList result= reconstruction (bufF,factors,zeroOne,precision,FLINTN, eval);
3588  nmod_mat_clear (FLINTN);
3589 #else
3590  int * zeroOne= extractZeroOneVecs (NTLN);
3591  CFList result= reconstruction (bufF, factors, zeroOne, precision, NTLN, eval);
3592 #endif
3593  F= bufF;
3594  delete [] zeroOne;
3595  delete [] A;
3596  delete [] bounds;
3597  return result;
3598  }
3599  }
3600  oldL2= l;
3601  l += stepSize;
3602  stepSize *= 2;
3603  if (l > precision)
3604  {
3605  if (!hitBound)
3606  {
3607  l= precision;
3608  hitBound= true;
3609  }
3610  else
3611  break;
3612  }
3613  }
3614 #ifdef HAVE_FLINT
3615  nmod_mat_clear (FLINTN);
3616 #endif
3617  delete [] bounds;
3618  delete [] A;
3619  return CFList();
3620 }
3621 
3622 CFList
3623 increasePrecision (CanonicalForm& F, CFList& factors, int factorsFound,
3624  int oldNumCols, int oldL, const Variable&,
3625  int precision, const CanonicalForm& eval
3626  )
3627 {
3628  int d;
3629  bool isIrreducible= false;
3630  Variable y= F.mvar();
3631  int* bounds= computeBounds (F, d, isIrreducible);
3632  if (isIrreducible)
3633  {
3634  delete [] bounds;
3635  CanonicalForm G= F;
3636  F= 1;
3637  return CFList (G (y-eval,y));
3638  }
3639  CFArray * A= new CFArray [factors.length()];
3640  CFArray bufQ= CFArray (factors.length());
3641  mat_zz_pE NTLN;
3642  ident (NTLN, factors.length());
3643  int minBound= bounds[0];
3644  for (int i= 1; i < d; i++)
3645  {
3646  if (bounds[i] != 0)
3647  minBound= tmin (minBound, bounds[i]);
3648  }
3649  int l= tmax (2*(minBound + 1), oldL);
3650  int oldL2= l/2;
3651  int stepSize= 2;
3652  bool useOldQs= false;
3653  bool hitBound= false;
3654  CFListIterator j;
3655  CFMatrix C;
3656  mat_zz_pE* NTLC, NTLK;
3657  CFArray buf;
3658  CanonicalForm truncF;
3659  while (l <= precision)
3660  {
3661  j= factors;
3662  truncF= mod (F, power (y,l));
3663  if (useOldQs)
3664  {
3665  for (int i= 0; i < factors.length(); i++, j++)
3666  A[i]= logarithmicDerivative (truncF, j.getItem(), l, oldL2, bufQ[i],
3667  bufQ[i]
3668  );
3669  }
3670  else
3671  {
3672  for (int i= 0; i < factors.length(); i++, j++)
3673  A[i]= logarithmicDerivative (truncF, j.getItem(), l, bufQ [i]);
3674  }
3675  useOldQs= true;
3676  for (int i= 0; i < d; i++)
3677  {
3678  if (bounds [i] + 1 <= l/2)
3679  {
3680  int k= tmin (bounds [i] + 1, l/2);
3681  C= CFMatrix (l - k, factors.length());
3682  for (int ii= 0; ii < factors.length(); ii++)
3683  {
3684  if (A[ii].size() - 1 >= i)
3685  {
3686  buf= getCoeffs (A[ii] [i], k);
3687  writeInMatrix (C, buf, ii + 1, 0);
3688  }
3689  }
3691  NTLK= (*NTLC)*NTLN;
3692  transpose (NTLK, NTLK);
3693  kernel (NTLK, NTLK);
3694  transpose (NTLK, NTLK);
3695  NTLN *= NTLK;
3696  delete NTLC;
3697  if (NTLN.NumCols() == 1)
3698  {
3699  delete [] A;
3700  delete [] bounds;
3701  CanonicalForm G= F;
3702  F= 1;
3703  return CFList (G (y-eval,y));
3704  }
3705  }
3706  }
3707 
3708  if (NTLN.NumCols() < oldNumCols - factorsFound)
3709  {
3710  if (isReduced (NTLN))
3711  {
3712  int * factorsFoundIndex= new int [NTLN.NumCols()];
3713  for (long i= 0; i < NTLN.NumCols(); i++)
3714  factorsFoundIndex[i]= 0;
3715  int factorsFound2= 0;
3716  CFList result;
3717  CanonicalForm bufF= F;
3718  reconstructionTry (result, bufF, factors, degree (F) + 1, factorsFound2,
3719  factorsFoundIndex, NTLN, eval, false);
3720  if (result.length() == NTLN.NumCols())
3721  {
3722  delete [] factorsFoundIndex;
3723  delete [] A;
3724  delete [] bounds;
3725  F= 1;
3726  return result;
3727  }
3728  delete [] factorsFoundIndex;
3729  }
3730  else if (l == precision)
3731  {
3732  CanonicalForm bufF= F;
3733  int * zeroOne= extractZeroOneVecs (NTLN);
3734  CFList result= reconstruction (bufF, factors, zeroOne, precision, NTLN, eval);
3735  F= bufF;
3736  delete [] zeroOne;
3737  delete [] A;
3738  delete [] bounds;
3739  return result;
3740  }
3741  }
3742  oldL2= l;
3743  l += stepSize;
3744  stepSize *= 2;
3745  if (l > precision)
3746  {
3747  if (!hitBound)
3748  {
3749  l= precision;
3750  hitBound= true;
3751  }
3752  else
3753  break;
3754  }
3755  }
3756  delete [] bounds;
3757  delete [] A;
3758  return CFList();
3759 }
3760 
3761 //over field extension
3762 CFList
3763 extIncreasePrecision (CanonicalForm& F, CFList& factors, int factorsFound,
3764  int oldNumCols, int oldL, const CanonicalForm& evaluation,
3765  const ExtensionInfo& info, CFList& source, CFList& dest,
3766  int precision
3767  )
3768 {
3769  bool GF= (CFFactory::gettype()==GaloisFieldDomain);
3770  int degMipo= degree (getMipo (info.getAlpha()));
3771  Variable alpha= info.getAlpha();
3772  int d;
3773  bool isIrreducible= false;
3774  int* bounds= computeBounds (F, d, isIrreducible);
3775  if (isIrreducible)
3776  {
3777  delete [] bounds;
3778  Variable y= Variable (2);
3779  CanonicalForm tmp= F (y - evaluation, y);
3780  CFList source, dest;
3781  tmp= mapDown (tmp, info, source, dest);
3782  F= 1;
3783  return CFList (tmp);
3784  }
3785 
3786  CFArray * A= new CFArray [factors.length()];
3787  CFArray bufQ= CFArray (factors.length());
3788 #ifdef HAVE_FLINT
3789  nmod_mat_t FLINTN;
3790  nmod_mat_init (FLINTN,factors.length(),factors.length(), getCharacteristic());
3791  for (long i=factors.length()-1; i >= 0; i--)
3792  nmod_mat_entry (FLINTN, i, i)= 1;
3793 #else
3795  {
3797  zz_p::init (getCharacteristic());
3798  }
3799  mat_zz_p NTLN;
3800  ident (NTLN, factors.length());
3801 #endif
3802  int minBound= bounds[0];
3803  for (int i= 1; i < d; i++)
3804  {
3805  if (bounds[i] != 0)
3806  minBound= tmin (minBound, bounds[i]);
3807  }
3808  int l= tmax (oldL, 2*((minBound+1)/degMipo+1));
3809  int oldL2= l/2;
3810  int stepSize= 2;
3811  bool useOldQs= false;
3812  bool hitBound= false;
3813  Variable gamma= info.getBeta();
3814  CanonicalForm primElemAlpha= info.getGamma();
3815  CanonicalForm imPrimElemAlpha= info.getDelta();
3816  CFListIterator j;
3817  Variable y= F.mvar();
3818  CanonicalForm powX, imBasis, truncF;
3819  CFMatrix Mat, C;
3820  CFIterator iter;
3821 #ifdef HAVE_FLINT
3822  long rank;
3823  nmod_mat_t FLINTMat, FLINTMatInv, FLINTC, FLINTK, null;
3824 #else
3825  mat_zz_p* NTLMat,*NTLC, NTLK;
3826 #endif
3827  CFArray buf;
3828  while (l <= precision)
3829  {
3830  j= factors;
3831  if (GF)
3833  powX= power (y-gamma, l);
3834  Mat= CFMatrix (l*degMipo, l*degMipo);
3835  for (int i= 0; i < l*degMipo; i++)
3836  {
3837  imBasis= mod (power (y, i), powX);
3838  imBasis= imBasis (power (y, degMipo), y);
3839  imBasis= imBasis (y, gamma);
3840  iter= imBasis;
3841  for (; iter.hasTerms(); iter++)
3842  Mat (iter.exp()+ 1, i+1)= iter.coeff();
3843  }
3844 
3845 #ifdef HAVE_FLINT
3846  convertFacCFMatrix2nmod_mat_t (FLINTMat, Mat);
3847  nmod_mat_init (FLINTMatInv, nmod_mat_nrows (FLINTMat),
3848  nmod_mat_nrows (FLINTMat), getCharacteristic());
3849  nmod_mat_inv (FLINTMatInv, FLINTMat);
3850 #else
3851  NTLMat= convertFacCFMatrix2NTLmat_zz_p (Mat);
3852  *NTLMat= inv (*NTLMat);
3853 #endif
3854 
3855  if (GF)
3856  setCharacteristic (getCharacteristic(), degMipo, info.getGFName());
3857 
3858  truncF= mod (F, power (y, l));
3859  if (useOldQs)
3860  {
3861  for (int i= 0; i < factors.length(); i++, j++)
3862  A[i]= logarithmicDerivative (truncF, j.getItem(), l, oldL2, bufQ[i],
3863  bufQ[i]
3864  );
3865  }
3866  else
3867  {
3868  for (int i= 0; i < factors.length(); i++, j++)
3869  A[i]= logarithmicDerivative (truncF, j.getItem(), l, bufQ [i]);
3870  }
3871  useOldQs= true;
3872  for (int i= 0; i < d; i++)
3873  {
3874  if (bounds [i] + 1 <= (l/2)*degMipo)
3875  {
3876  int k= tmin (bounds [i] + 1, (l/2)*degMipo);
3877  C= CFMatrix (l*degMipo - k, factors.length());
3878  for (int ii= 0; ii < factors.length(); ii++)
3879  {
3880  if (A[ii].size() - 1 >= i)
3881  {
3882  if (GF)
3883  {
3884  A[ii] [i]= A [ii] [i] (y-evaluation, y);
3886  A[ii] [i]= GF2FalphaRep (A[ii] [i], alpha);
3887  if (alpha != gamma)
3888  A [ii] [i]= mapDown (A[ii] [i], imPrimElemAlpha, primElemAlpha,
3889  gamma, source, dest
3890  );
3891 #ifdef HAVE_FLINT
3892  buf= getCoeffs (A[ii] [i], k, l, degMipo, gamma, 0, FLINTMatInv);
3893 #else
3894  buf= getCoeffs (A[ii] [i], k, l, degMipo, gamma, 0, *NTLMat);
3895 #endif
3896  }
3897  else
3898  {
3899  A [ii] [i]= A [ii] [i] (y-evaluation, y);
3900  if (alpha != gamma)
3901  A[ii] [i]= mapDown (A[ii] [i], imPrimElemAlpha, primElemAlpha,
3902  gamma, source, dest
3903  );
3904 #ifdef HAVE_FLINT
3905  buf= getCoeffs (A[ii] [i], k, l, degMipo, gamma, 0, FLINTMatInv);
3906 #else
3907  buf= getCoeffs (A[ii] [i], k, l, degMipo, gamma, 0, *NTLMat);
3908 #endif
3909  }
3910  writeInMatrix (C, buf, ii + 1, 0);
3911  }
3912  if (GF)
3913  setCharacteristic (getCharacteristic(), degMipo, info.getGFName());
3914  }
3915 
3916  if (GF)
3918 
3919 #ifdef HAVE_FLINT
3920  convertFacCFMatrix2nmod_mat_t (FLINTC, C);
3921  nmod_mat_init (FLINTK, nmod_mat_nrows (FLINTC), nmod_mat_ncols (FLINTN),
3922  getCharacteristic());
3923  nmod_mat_mul (FLINTK, FLINTC, FLINTN);
3924  nmod_mat_init (null, nmod_mat_ncols (FLINTK), nmod_mat_ncols (FLINTK),
3925  getCharacteristic());
3926  rank= nmod_mat_nullspace (null, FLINTK);
3927  nmod_mat_clear (FLINTK);
3928  nmod_mat_window_init (FLINTK, null, 0, 0, nmod_mat_nrows(null), rank);
3929  nmod_mat_clear (FLINTC);
3930  nmod_mat_init_set (FLINTC, FLINTN);
3931  nmod_mat_clear (FLINTN);
3932  nmod_mat_init (FLINTN, nmod_mat_nrows (FLINTC), nmod_mat_ncols (FLINTK),
3933  getCharacteristic());
3934  nmod_mat_mul (FLINTN, FLINTC, FLINTK); //no aliasing allowed!!
3935 
3936  nmod_mat_clear (FLINTC);
3937  nmod_mat_window_clear (FLINTK);
3938  nmod_mat_clear (null);
3939 #else
3941  NTLK= (*NTLC)*NTLN;
3942  transpose (NTLK, NTLK);
3943  kernel (NTLK, NTLK);
3944  transpose (NTLK, NTLK);
3945  NTLN *= NTLK;
3946  delete NTLC;
3947 #endif
3948 
3949  if (GF)
3950  setCharacteristic (getCharacteristic(), degMipo, info.getGFName());
3951 
3952 #ifdef HAVE_FLINT
3953  if (nmod_mat_ncols (FLINTN) == 1)
3954  {
3955  nmod_mat_clear (FLINTMat);
3956  nmod_mat_clear (FLINTMatInv);
3957  nmod_mat_clear (FLINTN);
3958 #else
3959  if (NTLN.NumCols() == 1)
3960  {
3961  delete NTLMat;
3962 #endif
3963  Variable y= Variable (2);
3964  CanonicalForm tmp= F (y - evaluation, y);
3965  CFList source, dest;
3966  tmp= mapDown (tmp, info, source, dest);
3967  delete [] A;
3968  delete [] bounds;
3969  F= 1;
3970  return CFList (tmp);
3971  }
3972  }
3973  }
3974 
3975 #ifdef HAVE_FLINT
3976  nmod_mat_clear (FLINTMat);
3977  nmod_mat_clear (FLINTMatInv);
3978 #else
3979  delete NTLMat;
3980 #endif
3981 
3982 #ifdef HAVE_FLINT
3983  if (nmod_mat_ncols (FLINTN) < oldNumCols - factorsFound)
3984  {
3985  if (isReduced (FLINTN))
3986  {
3987  int * factorsFoundIndex= new int [nmod_mat_ncols (FLINTN)];
3988  for (long i= 0; i < nmod_mat_ncols (FLINTN); i++)
3989 #else
3990  if (NTLN.NumCols() < oldNumCols - factorsFound)
3991  {
3992  if (isReduced (NTLN))
3993  {
3994  int * factorsFoundIndex= new int [NTLN.NumCols()];
3995  for (long i= 0; i < NTLN.NumCols(); i++)
3996 #endif
3997  factorsFoundIndex[i]= 0;
3998  int factorsFound2= 0;
3999  CFList result;
4000  CanonicalForm bufF= F;
4001 #ifdef HAVE_FLINT
4002  extReconstructionTry (result, bufF, factors,degree (F)+1, factorsFound2,
4003  factorsFoundIndex, FLINTN, false, info, evaluation
4004  );
4005  if (result.length() == nmod_mat_ncols (FLINTN))
4006  {
4007  nmod_mat_clear (FLINTN);
4008 #else
4009  extReconstructionTry (result, bufF, factors,degree (F)+1, factorsFound2,
4010  factorsFoundIndex, NTLN, false, info, evaluation
4011  );
4012  if (result.length() == NTLN.NumCols())
4013  {
4014 #endif
4015  delete [] factorsFoundIndex;
4016  delete [] A;
4017  delete [] bounds;
4018  F= 1;
4019  return result;
4020  }
4021  delete [] factorsFoundIndex;
4022  }
4023  else if (l == precision)
4024  {
4025  CanonicalForm bufF= F;
4026 #ifdef HAVE_FLINT
4027  int * zeroOne= extractZeroOneVecs (FLINTN);
4028  CFList result= extReconstruction (bufF, factors, zeroOne, precision,
4029  FLINTN, info, evaluation
4030  );
4031  nmod_mat_clear (FLINTN);
4032 #else
4033  int * zeroOne= extractZeroOneVecs (NTLN);
4034  CFList result= extReconstruction (bufF, factors, zeroOne, precision,
4035  NTLN, info, evaluation
4036  );
4037 #endif
4038  F= bufF;
4039  delete [] zeroOne;
4040  delete [] A;
4041  delete [] bounds;
4042  return result;
4043  }
4044  }
4045  oldL2= l;
4046  l += stepSize;
4047  stepSize *= 2;
4048  if (l > precision)
4049  {
4050  if (!hitBound)
4051  {
4052  hitBound= true;
4053  l= precision;
4054  }
4055  else
4056  break;
4057  }
4058  }
4059 
4060 #ifdef HAVE_FLINT
4061  nmod_mat_clear (FLINTN);
4062 #endif
4063  delete [] bounds;
4064  delete [] A;
4065  return CFList();
4066 }
4067 
4068 CFList
4070  const Variable& alpha, int precision)
4071 {
4072  int d;
4073  bool isIrreducible= false;
4074  int* bounds= computeBounds (F, d, isIrreducible);
4075  if (isIrreducible)
4076  {
4077  delete [] bounds;
4078  return CFList (F);
4079  }
4080  CFArray * A= new CFArray [factors.length()];
4081  CFArray bufQ= CFArray (factors.length());
4083  {
4085  zz_p::init (getCharacteristic());
4086  }
4087  zz_pX NTLMipo= convertFacCF2NTLzzpX (getMipo (alpha));
4088  zz_pE::init (NTLMipo);
4089  mat_zz_pE NTLN;
4090  ident (NTLN, factors.length());
4091  int minBound= bounds[0];
4092  for (int i= 1; i < d; i++)
4093  {
4094  if (bounds[i] != 0)
4095  minBound= tmin (minBound, bounds[i]);
4096  }
4097  int l= tmin (2*(minBound + 1), precision);
4098  int oldL= l/2;
4099  int stepSize= 2;
4100  bool useOldQs= false;
4101  bool hitBound= false;
4102  CFListIterator j;
4103  CFMatrix C;
4104  CFArray buf;
4105  mat_zz_pE* NTLC, NTLK;
4106  Variable y= F.mvar();
4107  CanonicalForm truncF;
4108  while (l <= precision)
4109  {
4110  j= factors;
4111  truncF= mod (F, power (y, l));
4112  if (useOldQs)
4113  {
4114  for (int i= 0; i < factors.length(); i++, j++)
4115  A[i]= logarithmicDerivative (truncF, j.getItem(), l, oldL, bufQ[i], bufQ[i]);
4116  }
4117  else
4118  {
4119  for (int i= 0; i < factors.length(); i++, j++)
4120  A[i]= logarithmicDerivative (truncF, j.getItem(), l, bufQ [i]);
4121  }
4122  useOldQs= true;
4123  for (int i= 0; i < d; i++)
4124  {
4125  if (bounds [i] + 1 <= l/2)
4126  {
4127  int k= tmin (bounds [i] + 1, l/2);
4128  C= CFMatrix (l - k, factors.length());
4129  for (int ii= 0; ii < factors.length(); ii++)
4130  {
4131  if (A[ii].size() - 1 >= i)
4132  {
4133  buf= getCoeffs (A[ii] [i], k);
4134  writeInMatrix (C, buf, ii + 1, 0);
4135  }
4136  }
4138  NTLK= (*NTLC)*NTLN;
4139  transpose (NTLK, NTLK);
4140  kernel (NTLK, NTLK);
4141  transpose (NTLK, NTLK);
4142  NTLN *= NTLK;
4143  delete NTLC;
4144 
4145  if (NTLN.NumCols() == 1)
4146  {
4147  delete [] A;
4148  delete [] bounds;
4149  return CFList (F);
4150  }
4151  }
4152  }
4153 
4154  if (isReduced (NTLN) || l == precision)
4155  {
4156  CanonicalForm bufF= F;
4157  int * zeroOne= extractZeroOneVecs (NTLN);
4158  CFList bufFactors= factors;
4159  CFList result= monicReconstruction (bufF, factors, zeroOne, precision,
4160  NTLN
4161  );
4162  if (result.length() != NTLN.NumCols() && l != precision)
4163  factors= bufFactors;
4164  if (result.length() == NTLN.NumCols())
4165  {
4166  delete [] zeroOne;
4167  delete [] A;
4168  delete [] bounds;
4169  return result;
4170  }
4171  if (l == precision)
4172  {
4173  delete [] zeroOne;
4174  delete [] A;
4175  delete [] bounds;
4176  return Union (result, factors);
4177  }
4178  delete [] zeroOne;
4179  }
4180  oldL= l;
4181  l += stepSize;
4182  stepSize *= 2;
4183  if (l > precision)
4184  {
4185  if (!hitBound)
4186  {
4187  l= precision;
4188  hitBound= true;
4189  }
4190  else
4191  break;
4192  }
4193  }
4194  delete [] bounds;
4195  delete [] A;
4196  return CFList();
4197 }
4198 
4199 CFList
4200 increasePrecisionFq2Fp (CanonicalForm& F, CFList& factors, int factorsFound,
4201  int oldNumCols, int oldL, const Variable& alpha,
4202  int precision, const CanonicalForm& eval
4203  )
4204 {
4205  int d;
4206  bool isIrreducible= false;
4207  Variable y= F.mvar();
4208  int* bounds= computeBounds (F, d, isIrreducible);
4209  if (isIrreducible)
4210  {
4211  delete [] bounds;
4212  CanonicalForm G= F;
4213  F= 1;
4214  return CFList (G (y-eval,y));
4215  }
4216  int extensionDeg= degree (getMipo (alpha));
4217  CFArray * A= new CFArray [factors.length()];
4218  CFArray bufQ= CFArray (factors.length());
4219 #ifdef HAVE_FLINT
4220  nmod_mat_t FLINTN;
4221  nmod_mat_init (FLINTN,factors.length(),factors.length(), getCharacteristic());
4222  for (long i=factors.length()-1; i >= 0; i--)
4223  nmod_mat_entry (FLINTN, i, i)= 1;
4224 #else
4225  mat_zz_p NTLN;
4226  ident (NTLN, factors.length());
4227 #endif
4228  int minBound= bounds[0];
4229  for (int i= 1; i < d; i++)
4230  {
4231  if (bounds[i] != 0)
4232  minBound= tmin (minBound, bounds[i]);
4233  }
4234  int l= tmax (2*(minBound + 1), oldL);
4235  int oldL2= l/2;
4236  int stepSize= 2;
4237  bool useOldQs= false;
4238  bool hitBound= false;
4239  CFListIterator j;
4240  CFMatrix C;
4241 #ifdef HAVE_FLINT
4242  long rank;
4243  nmod_mat_t FLINTC, FLINTK, null;
4244 #else
4245  mat_zz_p* NTLC, NTLK;
4246 #endif
4247  CFArray buf;
4248  CanonicalForm truncF;
4249  while (l <= precision)
4250  {
4251  j= factors;
4252  truncF= mod (F, power (y, l));
4253  if (useOldQs)
4254  {
4255  for (int i= 0; i < factors.length(); i++, j++)
4256  A[i]= logarithmicDerivative (truncF, j.getItem(), l, oldL2, bufQ[i],
4257  bufQ[i]
4258  );
4259  }
4260  else
4261  {
4262  for (int i= 0; i < factors.length(); i++, j++)
4263  A[i]= logarithmicDerivative (truncF, j.getItem(), l, bufQ [i]);
4264  }
4265  useOldQs= true;
4266  for (int i= 0; i < d; i++)
4267  {
4268  if (bounds [i] + 1 <= l/2)
4269  {
4270  int k= tmin (bounds [i] + 1, l/2);
4271  C= CFMatrix ((l - k)*extensionDeg, factors.length());
4272  for (int ii= 0; ii < factors.length(); ii++)
4273  {
4274  if (A[ii].size() - 1 >= i)
4275  {
4276  buf= getCoeffs (A[ii] [i], k, alpha);
4277  writeInMatrix (C, buf, ii + 1, 0);
4278  }
4279  }
4280 #ifdef HAVE_FLINT
4281  convertFacCFMatrix2nmod_mat_t (FLINTC, C);
4282  nmod_mat_init (FLINTK, nmod_mat_nrows (FLINTC), nmod_mat_ncols (FLINTN),
4283  getCharacteristic());
4284  nmod_mat_mul (FLINTK, FLINTC, FLINTN);
4285  nmod_mat_init (null, nmod_mat_ncols (FLINTK), nmod_mat_ncols (FLINTK),
4286  getCharacteristic());
4287  rank= nmod_mat_nullspace (null, FLINTK);
4288  nmod_mat_clear (FLINTK);
4289  nmod_mat_window_init (FLINTK, null, 0, 0, nmod_mat_nrows(null), rank);
4290  nmod_mat_clear (FLINTC);
4291  nmod_mat_init_set (FLINTC, FLINTN);
4292  nmod_mat_clear (FLINTN);
4293  nmod_mat_init (FLINTN, nmod_mat_nrows (FLINTC), nmod_mat_ncols (FLINTK),
4294  getCharacteristic());
4295  nmod_mat_mul (FLINTN, FLINTC, FLINTK); //no aliasing allowed!!
4296 
4297  nmod_mat_clear (FLINTC);
4298  nmod_mat_window_clear (FLINTK);
4299  nmod_mat_clear (null);
4300 #else
4302  NTLK= (*NTLC)*NTLN;
4303  transpose (NTLK, NTLK);
4304  kernel (NTLK, NTLK);
4305  transpose (NTLK, NTLK);
4306  NTLN *= NTLK;
4307  delete NTLC;
4308 #endif
4309 #ifdef HAVE_FLINT
4310  if (nmod_mat_ncols (FLINTN) == 1)
4311  {
4312  nmod_mat_clear (FLINTN);
4313 #else
4314  if (NTLN.NumCols() == 1)
4315  {
4316 #endif
4317  delete [] A;
4318  delete [] bounds;
4319  CanonicalForm G= F;
4320  F= 1;
4321  return CFList (G (y-eval,y));
4322  }
4323  }
4324  }
4325 
4326 #ifdef HAVE_FLINT
4327  if (nmod_mat_ncols (FLINTN) < oldNumCols - factorsFound)
4328  {
4329  if (isReduced (FLINTN))
4330  {
4331  int * factorsFoundIndex= new int [nmod_mat_ncols (FLINTN)];
4332  for (long i= 0; i < nmod_mat_ncols (FLINTN); i++)
4333 #else
4334  if (NTLN.NumCols() < oldNumCols - factorsFound)
4335  {
4336  if (isReduced (NTLN))
4337  {
4338  int * factorsFoundIndex= new int [NTLN.NumCols()];
4339  for (long i= 0; i < NTLN.NumCols(); i++)
4340 #endif
4341  factorsFoundIndex[i]= 0;
4342  int factorsFound2= 0;
4343  CFList result;
4344  CanonicalForm bufF= F;
4345 #ifdef HAVE_FLINT
4346  reconstructionTry (result, bufF, factors, degree (F) + 1, factorsFound2,
4347  factorsFoundIndex, FLINTN, eval, false
4348  );
4349  if (result.length() == nmod_mat_ncols (FLINTN))
4350  {
4351  nmod_mat_clear (FLINTN);
4352 #else
4353  reconstructionTry (result, bufF, factors, degree (F) + 1, factorsFound2,
4354  factorsFoundIndex, NTLN, eval, false
4355  );
4356  if (result.length() == NTLN.NumCols())
4357  {
4358 #endif
4359  delete [] factorsFoundIndex;
4360  delete [] A;
4361  delete [] bounds;
4362  F= 1;
4363  return result;
4364  }
4365  delete [] factorsFoundIndex;
4366  }
4367  else if (l == precision)
4368  {
4369  CanonicalForm bufF= F;
4370 #ifdef HAVE_FLINT
4371  int * zeroOne= extractZeroOneVecs (FLINTN);
4372  CFList result= reconstruction (bufF,factors,zeroOne,precision,FLINTN, eval);
4373  nmod_mat_clear (FLINTN);
4374 #else
4375  int * zeroOne= extractZeroOneVecs (NTLN);
4376  CFList result= reconstruction (bufF, factors, zeroOne, precision, NTLN, eval);
4377 #endif
4378  F= bufF;
4379  delete [] zeroOne;
4380  delete [] A;
4381  delete [] bounds;
4382  return result;
4383  }
4384  }
4385  oldL2= l;
4386  l += stepSize;
4387  stepSize *= 2;
4388  if (l > precision)
4389  {
4390  if (!hitBound)
4391  {
4392  hitBound= true;
4393  l= precision;
4394  }
4395  else
4396  break;
4397  }
4398  }
4399 #ifdef HAVE_FLINT
4400  nmod_mat_clear (FLINTN);
4401 #endif
4402  delete [] bounds;
4403  delete [] A;
4404  return CFList();
4405 }
4406 
4407 #ifdef HAVE_FLINT
4408 CFList
4409 increasePrecision (CanonicalForm& F, CFList& factors, int oldL, int
4410  l, int d, int* bounds, CFArray& bufQ, nmod_mat_t FLINTN,
4411  const CanonicalForm& eval
4412  )
4413 #else
4414 CFList
4415 increasePrecision (CanonicalForm& F, CFList& factors, int oldL, int
4416  l, int d, int* bounds, CFArray& bufQ, mat_zz_p& NTLN,
4417  const CanonicalForm& eval
4418  )
4419 #endif
4420 {
4421  CFList result= CFList();
4422  CFArray * A= new CFArray [factors.length()];
4423  int oldL2= oldL/2;
4424  bool hitBound= false;
4425 #ifdef HAVE_FLINT
4426  if (nmod_mat_nrows (FLINTN) != factors.length()) //refined factors
4427  {
4428  nmod_mat_clear (FLINTN);
4429  nmod_mat_init(FLINTN,factors.length(),factors.length(),getCharacteristic());
4430  for (long i=factors.length()-1; i >= 0; i--)
4431  nmod_mat_entry (FLINTN, i, i)= 1;
4432  bufQ= CFArray (factors.length());
4433  }
4434 #else
4435  if (NTLN.NumRows() != factors.length()) //refined factors
4436  {
4437  ident (NTLN, factors.length());
4438  bufQ= CFArray (factors.length());
4439  }
4440 #endif
4441  bool useOldQs= false;
4442  CFListIterator j;
4443  CFMatrix C;
4444  CFArray buf;
4445 #ifdef HAVE_FLINT
4446  long rank;
4447  nmod_mat_t FLINTC, FLINTK, null;
4448 #else
4449  mat_zz_p* NTLC, NTLK;
4450 #endif
4451  CanonicalForm bufF, truncF;
4452  CFList bufUniFactors;
4453  Variable y= F.mvar();
4454  while (oldL <= l)
4455  {
4456  j= factors;
4457  truncF= mod (F, power (y, oldL));
4458  if (useOldQs)
4459  {
4460  for (int i= 0; i < factors.length(); i++, j++)
4461  A[i]= logarithmicDerivative (truncF, j.getItem(), oldL, oldL2, bufQ[i],
4462  bufQ[i]
4463  );
4464  }
4465  else
4466  {
4467  for (int i= 0; i < factors.length(); i++, j++)
4468  A[i]= logarithmicDerivative (truncF, j.getItem(), oldL, bufQ [i]);
4469  }
4470  useOldQs= true;
4471 
4472  for (int i= 0; i < d; i++)
4473  {
4474  if (bounds [i] + 1 <= oldL/2)
4475  {
4476  int k= tmin (bounds [i] + 1, oldL/2);
4477  C= CFMatrix (oldL - k, factors.length());
4478  for (int ii= 0; ii < factors.length(); ii++)
4479  {
4480  if (A[ii].size() - 1 >= i)
4481  {
4482  buf= getCoeffs (A[ii] [i], k);
4483  writeInMatrix (C, buf, ii + 1, 0);
4484  }
4485  }
4486 #ifdef HAVE_FLINT
4487  convertFacCFMatrix2nmod_mat_t (FLINTC, C);
4488  nmod_mat_init (FLINTK, nmod_mat_nrows (FLINTC), nmod_mat_ncols (FLINTN),
4489  getCharacteristic());
4490  nmod_mat_mul (FLINTK, FLINTC, FLINTN);
4491  nmod_mat_init (null, nmod_mat_ncols (FLINTK), nmod_mat_ncols (FLINTK),
4492  getCharacteristic());
4493  rank= nmod_mat_nullspace (null, FLINTK);
4494  nmod_mat_clear (FLINTK);
4495  nmod_mat_window_init (FLINTK, null, 0, 0, nmod_mat_nrows(null), rank);
4496  nmod_mat_clear (FLINTC);
4497  nmod_mat_init_set (FLINTC, FLINTN);
4498  nmod_mat_clear (FLINTN);
4499  nmod_mat_init (FLINTN, nmod_mat_nrows (FLINTC), nmod_mat_ncols (FLINTK),
4500  getCharacteristic());
4501  nmod_mat_mul (FLINTN, FLINTC, FLINTK); //no aliasing allowed!!
4502 
4503  nmod_mat_clear (FLINTC);
4504  nmod_mat_window_clear (FLINTK);
4505  nmod_mat_clear (null);
4506 #else
4508  NTLK= (*NTLC)*NTLN;
4509  transpose (NTLK, NTLK);
4510  kernel (NTLK, NTLK);
4511  transpose (NTLK, NTLK);
4512  NTLN *= NTLK;
4513  delete NTLC;
4514 #endif
4515 #ifdef HAVE_FLINT
4516  if (nmod_mat_ncols (FLINTN) == 1)
4517 #else
4518  if (NTLN.NumCols() == 1)
4519 #endif
4520  {
4521  delete [] A;
4522  return CFList (F (y-eval,y));
4523  }
4524  }
4525  }
4526 #ifdef HAVE_FLINT
4527  if (nmod_mat_ncols (FLINTN) == 1)
4528 #else
4529  if (NTLN.NumCols() == 1)
4530 #endif
4531  {
4532  delete [] A;
4533  return CFList (F (y-eval,y));
4534  }
4535  int * zeroOneVecs;
4536 #ifdef HAVE_FLINT
4537  zeroOneVecs= extractZeroOneVecs (FLINTN);
4538 #else
4539  zeroOneVecs= extractZeroOneVecs (NTLN);
4540 #endif
4541  bufF= F;
4542  bufUniFactors= factors;
4543 #ifdef HAVE_FLINT
4544  result= reconstruction (bufF, bufUniFactors, zeroOneVecs, oldL, FLINTN, eval);
4545 #else
4546  result= reconstruction (bufF, bufUniFactors, zeroOneVecs, oldL, NTLN, eval);
4547 #endif
4548  delete [] zeroOneVecs;
4549  if (degree (bufF) + 1 + degree (LC (bufF, 1)) < oldL && result.length() > 0)
4550  {
4551  F= bufF;
4552  factors= bufUniFactors;
4553  delete [] A;
4554  return result;
4555  }
4556 
4557  result= CFList();
4558  oldL2= oldL;
4559  oldL *= 2;
4560  if (oldL > l)
4561  {
4562  if (!hitBound)
4563  {
4564  oldL= l;
4565  hitBound= true;
4566  }
4567  else
4568  break;
4569  }
4570  }
4571  delete [] A;
4572  return result;
4573 }
4574 
4575 CFList
4576 increasePrecision (CanonicalForm& F, CFList& factors, int oldL, int
4577  l, int d, int* bounds, CFArray& bufQ, mat_zz_pE& NTLN,
4578  const CanonicalForm& eval
4579  )
4580 {
4581  CFList result= CFList();
4582  CFArray * A= new CFArray [factors.length()];
4583  int oldL2= oldL/2;
4584  bool hitBound= false;
4585  bool useOldQs= false;
4586  if (NTLN.NumRows() != factors.length()) //refined factors
4587  ident (NTLN, factors.length());
4588  CFListIterator j;
4589  CFMatrix C;
4590  CFArray buf;
4591  mat_zz_pE* NTLC, NTLK;
4592  CanonicalForm bufF, truncF;
4593  CFList bufUniFactors;
4594  Variable y= F.mvar();
4595  while (oldL <= l)
4596  {
4597  j= factors;
4598  truncF= mod (F, power (y, oldL));
4599  if (useOldQs)
4600  {
4601  for (int i= 0; i < factors.length(); i++, j++)
4602  A[i]= logarithmicDerivative (truncF, j.getItem(), oldL, oldL2, bufQ[i],
4603  bufQ[i]
4604  );
4605  }
4606  else
4607  {
4608  for (int i= 0; i < factors.length(); i++, j++)
4609  A[i]= logarithmicDerivative (truncF, j.getItem(), oldL, bufQ [i]);
4610  }
4611  useOldQs= true;
4612 
4613  for (int i= 0; i < d; i++)
4614  {
4615  if (bounds [i] + 1 <= oldL/2)
4616  {
4617  int k= tmin (bounds [i] + 1, oldL/2);
4618  C= CFMatrix (oldL - k, factors.length());
4619  for (int ii= 0; ii < factors.length(); ii++)
4620  {
4621  if (A[ii].size() - 1 >= i)
4622  {
4623  buf= getCoeffs (A[ii] [i], k);
4624  writeInMatrix (C, buf, ii + 1, 0);
4625  }
4626  }
4628  NTLK= (*NTLC)*NTLN;
4629  transpose (NTLK, NTLK);
4630  kernel (NTLK, NTLK);
4631  transpose (NTLK, NTLK);
4632  NTLN *= NTLK;
4633  delete NTLC;
4634 
4635  if (NTLN.NumCols() == 1)
4636  {
4637  delete [] A;
4638  return CFList (F (y-eval,y));
4639  }
4640  }
4641  }
4642  if (NTLN.NumCols() == 1)
4643  {
4644  delete [] A;
4645  return CFList (F (y-eval,y));
4646  }
4647 
4648  int * zeroOneVecs;
4649  zeroOneVecs= extractZeroOneVecs (NTLN);
4650  bufF= F;
4651  bufUniFactors= factors;
4652  result= reconstruction (bufF, bufUniFactors, zeroOneVecs, oldL, NTLN, eval);
4653  delete [] zeroOneVecs;
4654  if (degree (bufF) + 1 + degree (LC (bufF, 1)) < l && result.length() > 0)
4655  {
4656  F= bufF;
4657  factors= bufUniFactors;
4658  delete [] A;
4659  return result;
4660  }
4661 
4662  result= CFList();
4663  oldL2= oldL;
4664  oldL *= 2;
4665  if (oldL > l)
4666  {
4667  if (!hitBound)
4668  {
4669  oldL= l;
4670  hitBound= true;
4671  }
4672  else
4673  break;
4674  }
4675  }
4676  delete [] A;
4677  return result;
4678 }
4679 
4680 //over field extension
4681 #ifdef HAVE_FLINT
4682 CFList
4683 extIncreasePrecision (CanonicalForm& F, CFList& factors, int oldL, int l, int d,
4684  int* bounds, CFArray& bufQ, nmod_mat_t FLINTN, const
4685  CanonicalForm& evaluation, const ExtensionInfo& info,
4686  CFList& source, CFList& dest
4687  )
4688 #else
4689 CFList
4690 extIncreasePrecision (CanonicalForm& F, CFList& factors, int oldL, int l, int d,
4691  int* bounds, CFArray& bufQ, mat_zz_p& NTLN, const
4692  CanonicalForm& evaluation, const ExtensionInfo& info,
4693  CFList& source, CFList& dest
4694  )
4695 #endif
4696 {
4697  CFList result= CFList();
4698  CFArray * A= new CFArray [factors.length()];
4699  int oldL2= oldL/2; //be careful
4700  bool hitBound= false;
4701  bool useOldQs= false;
4702  bool GF= (CFFactory::gettype()==GaloisFieldDomain);
4703  int degMipo= degree (getMipo (info.getAlpha()));
4704  Variable alpha= info.getAlpha();
4705 
4706  Variable gamma= info.getBeta();
4707  CanonicalForm primElemAlpha= info.getGamma();
4708  CanonicalForm imPrimElemAlpha= info.getDelta();
4709 #ifdef HAVE_FLINT
4710  nmod_mat_clear (FLINTN);
4711  nmod_mat_init (FLINTN,factors.length(),factors.length(), getCharacteristic());
4712  for (long i=factors.length()-1; i >= 0; i--)
4713  nmod_mat_entry (FLINTN, i, i)= 1;
4714 #else
4715  if (NTLN.NumRows() != factors.length()) //refined factors
4716  ident (NTLN, factors.length());
4717 #endif
4718  Variable y= F.mvar();
4719  CFListIterator j;
4720  CanonicalForm powX, imBasis, bufF, truncF;
4721  CFMatrix Mat, C;
4722  CFIterator iter;
4723  CFArray buf;
4724 #ifdef HAVE_FLINT
4725  long rank;
4726  nmod_mat_t FLINTMat, FLINTMatInv, FLINTC, FLINTK, null;
4727 #else
4728  mat_zz_p* NTLC, NTLK, *NTLMat;
4729 #endif
4730  CFList bufUniFactors;
4731  while (oldL <= l)
4732  {
4733  j= factors;
4734  if (GF)
4736 
4737  powX= power (y-gamma, oldL);
4738  Mat= CFMatrix (oldL*degMipo, oldL*degMipo);
4739  for (int i= 0; i < oldL*degMipo; i++)
4740  {
4741  imBasis= mod (power (y, i), powX);
4742  imBasis= imBasis (power (y, degMipo), y);
4743  imBasis= imBasis (y, gamma);
4744  iter= imBasis;
4745  for (; iter.hasTerms(); iter++)
4746  Mat (iter.exp()+ 1, i+1)= iter.coeff();
4747  }
4748 
4749 #ifdef HAVE_FLINT
4750  convertFacCFMatrix2nmod_mat_t (FLINTMat, Mat);
4751  nmod_mat_init (FLINTMatInv, nmod_mat_nrows (FLINTMat),
4752  nmod_mat_nrows (FLINTMat), getCharacteristic());
4753  nmod_mat_inv (FLINTMatInv, FLINTMat);
4754 #else
4755  NTLMat= convertFacCFMatrix2NTLmat_zz_p (Mat);
4756  *NTLMat= inv (*NTLMat);
4757 #endif
4758 
4759  if (GF)
4760  setCharacteristic (getCharacteristic(), degMipo, info.getGFName());
4761 
4762  truncF= mod (F, power (y, oldL));
4763  if (useOldQs)
4764  {
4765  for (int i= 0; i < factors.length(); i++, j++)
4766  A[i]= logarithmicDerivative (truncF, j.getItem(), oldL, oldL2, bufQ[i],
4767  bufQ[i]);
4768  }
4769  else
4770  {
4771  for (int i= 0; i < factors.length(); i++, j++)
4772  A[i]= logarithmicDerivative (truncF, j.getItem(), oldL, bufQ [i]);
4773  }
4774  useOldQs= true;
4775 
4776  for (int i= 0; i < d; i++)
4777  {
4778  if (bounds [i] + 1 <= oldL/2)
4779  {
4780  int k= tmin (bounds [i] + 1, oldL/2);
4781  C= CFMatrix (oldL*degMipo - k, factors.length());
4782  for (int ii= 0; ii < factors.length(); ii++)
4783  {
4784  if (A[ii].size() - 1 >= i)
4785  {
4786  if (GF)
4787  {
4788  A [ii] [i]= A [ii] [i] (y-evaluation, y);
4790  A[ii] [i]= GF2FalphaRep (A[ii] [i], alpha);
4791  if (alpha != gamma)
4792  A [ii] [i]= mapDown (A[ii] [i], imPrimElemAlpha, primElemAlpha,
4793  gamma, source, dest
4794  );
4795 #ifdef HAVE_FLINT
4796  buf= getCoeffs (A[ii] [i], k, oldL, degMipo, gamma, 0, FLINTMatInv);
4797 #else
4798  buf= getCoeffs (A[ii] [i], k, oldL, degMipo, gamma, 0, *NTLMat);
4799 #endif
4800  }
4801  else
4802  {
4803  A [ii] [i]= A [ii] [i] (y-evaluation, y);
4804  if (alpha != gamma)
4805  A[ii] [i]= mapDown (A[ii] [i], imPrimElemAlpha, primElemAlpha,
4806  gamma, source, dest
4807  );
4808 #ifdef HAVE_FLINT
4809  buf= getCoeffs (A[ii] [i], k, oldL, degMipo, gamma, 0, FLINTMatInv);
4810 #else
4811  buf= getCoeffs (A[ii] [i], k, oldL, degMipo, gamma, 0, *NTLMat);
4812 #endif
4813  }
4814  writeInMatrix (C, buf, ii + 1, 0);
4815  }
4816  if (GF)
4817  setCharacteristic (getCharacteristic(), degMipo, info.getGFName());
4818  }
4819 
4820  if (GF)
4822 
4823 #ifdef HAVE_FLINT
4824  convertFacCFMatrix2nmod_mat_t (FLINTC, C);
4825  nmod_mat_init (FLINTK, nmod_mat_nrows (FLINTC), nmod_mat_ncols (FLINTN),
4826  getCharacteristic());
4827  nmod_mat_mul (FLINTK, FLINTC, FLINTN);
4828  nmod_mat_init (null, nmod_mat_ncols (FLINTK), nmod_mat_ncols (FLINTK),
4829  getCharacteristic());
4830  rank= nmod_mat_nullspace (null, FLINTK);
4831  nmod_mat_clear (FLINTK);
4832  nmod_mat_window_init (FLINTK, null, 0, 0, nmod_mat_nrows(null), rank);
4833  nmod_mat_clear (FLINTC);
4834  nmod_mat_init_set (FLINTC, FLINTN);
4835  nmod_mat_clear (FLINTN);
4836  nmod_mat_init (FLINTN, nmod_mat_nrows (FLINTC), nmod_mat_ncols (FLINTK),
4837  getCharacteristic());
4838  nmod_mat_mul (FLINTN, FLINTC, FLINTK); //no aliasing allowed!!
4839 
4840  nmod_mat_clear (FLINTC);
4841  nmod_mat_window_clear (FLINTK);
4842  nmod_mat_clear (null);
4843 #else
4845  NTLK= (*NTLC)*NTLN;
4846  transpose (NTLK, NTLK);
4847  kernel (NTLK, NTLK);
4848  transpose (NTLK, NTLK);
4849  NTLN *= NTLK;
4850  delete NTLC;
4851 #endif
4852 
4853  if (GF)
4854  setCharacteristic (getCharacteristic(), degMipo, info.getGFName());
4855 
4856 #ifdef HAVE_FLINT
4857  if (nmod_mat_ncols (FLINTN) == 1)
4858  {
4859  nmod_mat_clear (FLINTMat);
4860  nmod_mat_clear (FLINTMatInv);
4861 #else
4862  if (NTLN.NumCols() == 1)
4863  {
4864  delete NTLMat;
4865 #endif
4866  Variable y= Variable (2);
4867  CanonicalForm tmp= F (y - evaluation, y);
4868  CFList source, dest;
4869  tmp= mapDown (tmp, info, source, dest);
4870  delete [] A;
4871  return CFList (tmp);
4872  }
4873  }
4874  }
4875 
4876 #ifdef HAVE_FLINT
4877  nmod_mat_clear (FLINTMat);
4878  nmod_mat_clear (FLINTMatInv);
4879 #else
4880  delete NTLMat;
4881 #endif
4882 
4883 #ifdef HAVE_FLINT
4884  if (nmod_mat_ncols (FLINTN) == 1)
4885 #else
4886  if (NTLN.NumCols() == 1)
4887 #endif
4888  {
4889  Variable y= Variable (2);
4890  CanonicalForm tmp= F (y - evaluation, y);
4891  CFList source, dest;
4892  tmp= mapDown (tmp, info, source, dest);
4893  delete [] A;
4894  return CFList (tmp);
4895  }
4896 
4897  int * zeroOneVecs;
4898  bufF= F;
4899  bufUniFactors= factors;
4900 #ifdef HAVE_FLINT
4901  zeroOneVecs= extractZeroOneVecs (FLINTN);
4902  result= extReconstruction (bufF, bufUniFactors, zeroOneVecs, oldL, FLINTN,
4903  info, evaluation
4904  );
4905 #else
4906  zeroOneVecs= extractZeroOneVecs (NTLN);
4907  result= extReconstruction (bufF, bufUniFactors, zeroOneVecs, oldL, NTLN,
4908  info, evaluation
4909  );
4910 #endif
4911  delete [] zeroOneVecs;
4912  if (degree (bufF) + 1 + degree (LC (bufF, 1)) < l && result.length() > 0)
4913  {
4914  F= bufF;
4915  factors= bufUniFactors;
4916  return result;
4917  }
4918 
4919  result= CFList();
4920  oldL2= oldL;
4921  oldL *= 2;
4922  if (oldL > l)
4923  {
4924  if (!hitBound)
4925  {
4926  oldL= l;
4927  hitBound= true;
4928  }
4929  else
4930  break;
4931  }
4932  }
4933  delete [] A;
4934  return result;
4935 }
4936 
4937 #ifdef HAVE_FLINT
4938 CFList
4939 increasePrecisionFq2Fp (CanonicalForm& F, CFList& factors, int oldL, int l,
4940  int d, int* bounds, CFArray& bufQ, nmod_mat_t FLINTN,
4941  const Variable& alpha, const CanonicalForm& eval
4942  )
4943 #else
4944 CFList
4945 increasePrecisionFq2Fp (CanonicalForm& F, CFList& factors, int oldL, int l,
4946  int d, int* bounds, CFArray& bufQ, mat_zz_p& NTLN,
4947  const Variable& alpha, const CanonicalForm& eval
4948  )
4949 #endif
4950 {
4951  CFList result= CFList();
4952  CFArray * A= new CFArray [factors.length()];
4953  int extensionDeg= degree (getMipo (alpha));
4954  int oldL2= oldL/2;
4955  bool hitBound= false;
4956  bool useOldQs= false;
4957 #ifdef HAVE_FLINT
4958  if (nmod_mat_nrows (FLINTN) != factors.length()) //refined factors
4959  {
4960  nmod_mat_clear (FLINTN);
4961  nmod_mat_init(FLINTN,factors.length(),factors.length(),getCharacteristic());
4962  for (long i=factors.length()-1; i >= 0; i--)
4963  nmod_mat_entry (FLINTN, i, i)= 1;
4964  }
4965 #else
4966  if (NTLN.NumRows() != factors.length()) //refined factors
4967  ident (NTLN, factors.length());
4968 #endif
4969  CFListIterator j;
4970  CFMatrix C;
4971  CFArray buf;
4972 #ifdef HAVE_FLINT
4973  long rank;
4974  nmod_mat_t FLINTC, FLINTK, null;
4975 #else
4976  mat_zz_p* NTLC, NTLK;
4977 #endif
4978  CanonicalForm bufF, truncF;
4979  CFList bufUniFactors;
4980  Variable y= F.mvar();
4981  while (oldL <= l)
4982  {
4983  j= factors;
4984  truncF= mod (F, power (y, oldL));
4985  if (useOldQs)
4986  {
4987  for (int i= 0; i < factors.length(); i++, j++)
4988  A[i]= logarithmicDerivative (truncF, j.getItem(), oldL, oldL2, bufQ[i],
4989  bufQ[i]
4990  );
4991  }
4992  else
4993  {
4994  for (int i= 0; i < factors.length(); i++, j++)
4995  A[i]= logarithmicDerivative (truncF, j.getItem(), oldL, bufQ [i]);
4996  }
4997  useOldQs= true;
4998 
4999  for (int i= 0; i < d; i++)
5000  {
5001  if (bounds [i] + 1 <= oldL/2)
5002  {
5003  int k= tmin (bounds [i] + 1, oldL/2);
5004  C= CFMatrix ((oldL - k)*extensionDeg, factors.length());
5005  for (int ii= 0; ii < factors.length(); ii++)
5006  {
5007  if (A[ii].size() - 1 >= i)
5008  {
5009  buf= getCoeffs (A[ii] [i], k, alpha);
5010  writeInMatrix (C, buf, ii + 1, 0);
5011  }
5012  }
5013 #ifdef HAVE_FLINT
5014  convertFacCFMatrix2nmod_mat_t (FLINTC, C);
5015  nmod_mat_init (FLINTK, nmod_mat_nrows (FLINTC), nmod_mat_ncols (FLINTN),
5016  getCharacteristic());
5017  nmod_mat_mul (FLINTK, FLINTC, FLINTN);
5018  nmod_mat_init (null, nmod_mat_ncols (FLINTK), nmod_mat_ncols (FLINTK),
5019  getCharacteristic());
5020  rank= nmod_mat_nullspace (null, FLINTK);
5021  nmod_mat_clear (FLINTK);
5022  nmod_mat_window_init (FLINTK, null, 0, 0, nmod_mat_nrows(null), rank);
5023  nmod_mat_clear (FLINTC);
5024  nmod_mat_init_set (FLINTC, FLINTN);
5025  nmod_mat_clear (FLINTN);
5026  nmod_mat_init (FLINTN, nmod_mat_nrows (FLINTC), nmod_mat_ncols (FLINTK),
5027  getCharacteristic());
5028  nmod_mat_mul (FLINTN, FLINTC, FLINTK); //no aliasing allowed!!
5029 
5030  nmod_mat_clear (FLINTC);
5031  nmod_mat_window_clear (FLINTK);
5032  nmod_mat_clear (null);
5033 #else
5035  NTLK= (*NTLC)*NTLN;
5036  transpose (NTLK, NTLK);
5037  kernel (NTLK, NTLK);
5038  transpose (NTLK, NTLK);
5039  NTLN *= NTLK;
5040  delete NTLC;
5041 #endif
5042 #ifdef HAVE_FLINT
5043  if (nmod_mat_ncols (FLINTN) == 1)
5044 #else
5045  if (NTLN.NumCols() == 1)
5046 #endif
5047  {
5048  delete [] A;
5049  return CFList (F(y-eval,y));
5050  }
5051  }
5052  }
5053 
5054  int * zeroOneVecs;
5055 #ifdef HAVE_FLINT
5056  zeroOneVecs= extractZeroOneVecs (FLINTN);
5057 #else
5058  zeroOneVecs= extractZeroOneVecs (NTLN);
5059 #endif
5060 
5061  bufF= F;
5062  bufUniFactors= factors;
5063 #ifdef HAVE_FLINT
5064  result= reconstruction (bufF, bufUniFactors, zeroOneVecs, oldL, FLINTN, eval);
5065 #else
5066  result= reconstruction (bufF, bufUniFactors, zeroOneVecs, oldL, NTLN, eval);
5067 #endif
5068  delete [] zeroOneVecs;
5069  if (degree (bufF) + 1 + degree (LC (bufF, 1)) < l && result.length() > 0)
5070  {
5071  F= bufF;
5072  factors= bufUniFactors;
5073  delete [] A;
5074  return result;
5075  }
5076 
5077  result= CFList();
5078  oldL2= oldL;
5079  oldL *= 2;
5080  if (oldL > l)
5081  {
5082  if (!hitBound)
5083  {
5084  oldL= l;
5085  hitBound= true;
5086  }
5087  else
5088  break;
5089  }
5090  }
5091  delete [] A;
5092  return result;
5093 }
5094 
5095 #ifdef HAVE_FLINT
5096 CFList
5098  factors, int l, int liftBound, int d, int*
5099  bounds, nmod_mat_t FLINTN, CFList& diophant,
5100  CFMatrix& M, CFArray& Pi, CFArray& bufQ,
5101  const CanonicalForm& eval
5102  )
5103 #else
5104 CFList
5106  factors, int l, int liftBound, int d, int*
5107  bounds, mat_zz_p& NTLN, CFList& diophant,
5108  CFMatrix& M, CFArray& Pi, CFArray& bufQ,
5109  const CanonicalForm& eval
5110  )
5111 #endif
5112 {
5113  CanonicalForm LCF= LC (F, 1);
5114  CFList result;
5115  bool irreducible= false;
5116  CFList bufFactors= factors;
5117  CFList bufBufFactors;
5118  CFArray *A = new CFArray [bufFactors.length()];
5119  bool useOldQs= false;
5120  bool hitBound= false;
5121  int oldL= l;
5122  int stepSize= 8; //TODO choose better step size?
5123  l += tmax (tmin (8, degree (F) + 1 + degree (LC (F, 1))-l), 2);
5124 #ifdef HAVE_FLINT
5125  if (nmod_mat_nrows (FLINTN) != factors.length()) //refined factors
5126  {
5127  nmod_mat_clear (FLINTN);
5128  nmod_mat_init(FLINTN,factors.length(),factors.length(),getCharacteristic());
5129  for (long i=factors.length()-1; i >= 0; i--)
5130  nmod_mat_entry (FLINTN, i, i)= 1;
5131  }
5132 #else
5133  if (NTLN.NumRows() != factors.length()) //refined factors
5134  ident (NTLN, factors.length());
5135 #endif
5136  CFListIterator j;
5137  CFMatrix C;
5138  CFArray buf;
5139 #ifdef HAVE_FLINT
5140  long rank;
5141  nmod_mat_t FLINTC, FLINTK, null;
5142 #else
5143  mat_zz_p* NTLC, NTLK;
5144 #endif
5145  CanonicalForm bufF, truncF;
5146  Variable y= F.mvar();
5147  while (l <= liftBound)
5148  {
5149  bufFactors.insert (LCF);
5150  henselLiftResume12 (F, bufFactors, oldL, l, Pi, diophant, M);
5151  j= bufFactors;
5152  truncF= mod (F, power (y, l));
5153  if (useOldQs)
5154  {
5155  for (int i= 0; i < bufFactors.length(); i++, j++)
5156  A[i]= logarithmicDerivative (truncF, j.getItem(), l, oldL, bufQ[i],
5157  bufQ[i]);
5158  }
5159  else
5160  {
5161  for (int i= 0; i < bufFactors.length(); i++, j++)
5162  A[i]= logarithmicDerivative (truncF, j.getItem(), l, bufQ [i]);
5163  }
5164  for (int i= 0; i < d; i++)
5165  {
5166  if (bounds [i] + 1 <= l/2)
5167  {
5168  int k= tmin (bounds [i] + 1, l/2);
5169  C= CFMatrix (l - k, bufFactors.length());
5170  for (int ii= 0; ii < bufFactors.length(); ii++)
5171  {
5172  if (A[ii].size() - 1 >= i)
5173  {
5174  buf= getCoeffs (A[ii] [i], k);
5175  writeInMatrix (C, buf, ii + 1, 0);
5176  }
5177  }
5178 #ifdef HAVE_FLINT
5179  convertFacCFMatrix2nmod_mat_t (FLINTC, C);
5180  nmod_mat_init (FLINTK, nmod_mat_nrows (FLINTC), nmod_mat_ncols (FLINTN),
5181  getCharacteristic());
5182  nmod_mat_mul (FLINTK, FLINTC, FLINTN);
5183  nmod_mat_init (null, nmod_mat_ncols (FLINTK), nmod_mat_ncols (FLINTK),
5184  getCharacteristic());
5185  rank= nmod_mat_nullspace (null, FLINTK);
5186  nmod_mat_clear (FLINTK);
5187  nmod_mat_window_init (FLINTK, null, 0, 0, nmod_mat_nrows(null), rank);
5188  nmod_mat_clear (FLINTC);
5189  nmod_mat_init_set (FLINTC, FLINTN);
5190  nmod_mat_clear (FLINTN);
5191  nmod_mat_init (FLINTN, nmod_mat_nrows (FLINTC), nmod_mat_ncols (FLINTK),
5192  getCharacteristic());
5193  nmod_mat_mul (FLINTN, FLINTC, FLINTK); //no aliasing allowed!!
5194 
5195  nmod_mat_clear (FLINTC);
5196  nmod_mat_window_clear (FLINTK);
5197  nmod_mat_clear (null);
5198 #else
5200  NTLK= (*NTLC)*NTLN;
5201  transpose (NTLK, NTLK);
5202  kernel (NTLK, NTLK);
5203  transpose (NTLK, NTLK);
5204  NTLN *= NTLK;
5205  delete NTLC;
5206 #endif
5207 #ifdef HAVE_FLINT
5208  if (nmod_mat_ncols (FLINTN) == 1)
5209 #else
5210  if (NTLN.NumCols() == 1)
5211 #endif
5212  {
5213  irreducible= true;
5214  break;
5215  }
5216  }
5217  }
5218 
5219 #ifdef HAVE_FLINT
5220  if (nmod_mat_ncols (FLINTN) == 1)
5221 #else
5222  if (NTLN.NumCols() == 1)
5223 #endif
5224  {
5225  irreducible= true;
5226  break;
5227  }
5228 
5229 #ifdef HAVE_FLINT
5230  int * zeroOneVecs= extractZeroOneVecs (FLINTN);
5231 #else
5232  int * zeroOneVecs= extractZeroOneVecs (NTLN);
5233 #endif
5234  bufF= F;
5235  bufBufFactors= bufFactors;
5236 #ifdef HAVE_FLINT
5237  result= reconstruction (bufF, bufFactors, zeroOneVecs, l, FLINTN, eval);
5238 #else
5239  result= reconstruction (bufF, bufFactors, zeroOneVecs, l, NTLN, eval);
5240 #endif
5241  delete [] zeroOneVecs;
5242  if (result.length() > 0 && degree (bufF) + 1 + degree (LC (bufF, 1)) <= l)
5243  {
5244  F= bufF;
5245  factors= bufFactors;
5246  delete [] A;
5247  return result;
5248  }
5249  else
5250  {
5251  bufF= F;
5252  bufFactors= bufBufFactors;
5253  }
5254 
5255 #ifdef HAVE_FLINT
5256  if (isReduced (FLINTN))
5257 #else
5258  if (isReduced (NTLN))
5259 #endif
5260  {
5261  int factorsFound= 0;
5262  bufF= F;
5263 #ifdef HAVE_FLINT
5264  int* factorsFoundIndex= new int [nmod_mat_ncols (FLINTN)];
5265  for (long i= 0; i < nmod_mat_ncols (FLINTN); i++)
5266 #else
5267  int* factorsFoundIndex= new int [NTLN.NumCols()];
5268  for (long i= 0; i < NTLN.NumCols(); i++)
5269 #endif
5270  factorsFoundIndex[i]= 0;
5271 #ifdef HAVE_FLINT
5272  if (l < liftBound)
5273  reconstructionTry (result, bufF, bufFactors, l, factorsFound,
5274  factorsFoundIndex, FLINTN, eval, false
5275  );
5276  else
5277  reconstructionTry (result, bufF, bufFactors, degree (bufF) + 1 +
5278  degree (LCF), factorsFound, factorsFoundIndex,
5279  FLINTN, eval, false
5280  );
5281 
5282  if (nmod_mat_ncols (FLINTN) == result.length())
5283 #else
5284  if (l < liftBound)
5285  reconstructionTry (result, bufF, bufFactors, l, factorsFound,
5286  factorsFoundIndex, NTLN, eval, false
5287  );
5288  else
5289  reconstructionTry (result, bufF, bufFactors, degree (bufF) + 1 +
5290  degree (LCF), factorsFound, factorsFoundIndex,
5291  NTLN, eval, false
5292  );
5293 
5294  if (NTLN.NumCols() == result.length())
5295 #endif
5296  {
5297  delete [] A;
5298  delete [] factorsFoundIndex;
5299  return result;
5300  }
5301  delete [] factorsFoundIndex;
5302  }
5303  result= CFList();
5304  oldL= l;
5305  stepSize *= 2;
5306  l += stepSize;
5307  if (l > liftBound)
5308  {
5309  if (!hitBound)
5310  {
5311  l= liftBound;
5312  hitBound= true;
5313  }
5314  else
5315  break;
5316  }
5317  }
5318  if (irreducible)
5319  {
5320  delete [] A;
5321  return CFList (F (y-eval,y));
5322  }
5323  delete [] A;
5324  factors= bufFactors;
5325  return CFList();
5326 }
5327 
5328 //Fq
5329 CFList
5331  factors, int l, int liftBound, int d, int*
5332  bounds, mat_zz_pE& NTLN, CFList& diophant,
5333  CFMatrix& M, CFArray& Pi, CFArray& bufQ,
5334  const CanonicalForm& eval
5335  )
5336 {
5337  CanonicalForm LCF= LC (F, 1);
5338  CFList result;
5339  bool irreducible= false;
5340  CFList bufFactors= factors;
5341  CFList bufBufFactors;
5342  CFArray *A = new CFArray [bufFactors.length()];
5343  bool useOldQs= false;
5344  bool hitBound= false;
5345  int oldL= l;
5346  int stepSize= 8; //TODO choose better step size?
5347  l += tmax (tmin (8, degree (F) + 1 + degree (LC (F, 1))-l), 2);
5348  if (NTLN.NumRows() != factors.length()) //refined factors
5349  ident (NTLN, factors.length());
5350  CFListIterator j;
5351  CFArray buf;
5352  mat_zz_pE* NTLC, NTLK;
5353  CanonicalForm bufF, truncF;
5354  Variable y= F.mvar();
5355  while (l <= liftBound)
5356  {
5357  bufFactors.insert (LCF);
5358  henselLiftResume12 (F, bufFactors, oldL, l, Pi, diophant, M);
5359  j= bufFactors;
5360  truncF= mod (F, power (y, l));
5361  if (useOldQs)
5362  {
5363  for (int i= 0; i < bufFactors.length(); i++, j++)
5364  A[i]= logarithmicDerivative (truncF, j.getItem(), l, oldL, bufQ[i],
5365  bufQ[i]);
5366  }
5367  else
5368  {
5369  for (int i= 0; i < bufFactors.length(); i++, j++)
5370  A[i]= logarithmicDerivative (truncF, j.getItem(), l, bufQ [i]);
5371  }
5372  for (int i= 0; i < d; i++)
5373  {
5374  if (bounds [i] + 1 <= l/2)
5375  {
5376  int k= tmin (bounds [i] + 1, l/2);
5377  CFMatrix C= CFMatrix (l - k, bufFactors.length());
5378  for (int ii= 0; ii < bufFactors.length(); ii++)
5379  {
5380  if (A[ii].size() - 1 >= i)
5381  {
5382  buf= getCoeffs (A[ii] [i], k);
5383  writeInMatrix (C, buf, ii + 1, 0);
5384  }
5385  }
5387  NTLK= (*NTLC)*NTLN;
5388  transpose (NTLK, NTLK);
5389  kernel (NTLK, NTLK);
5390  transpose (NTLK, NTLK);
5391  NTLN *= NTLK;
5392  delete NTLC;
5393  if (NTLN.NumCols() == 1)
5394  {
5395  irreducible= true;
5396  break;
5397  }
5398  }
5399  }
5400  if (NTLN.NumCols() == 1)
5401  {
5402  irreducible= true;
5403  break;
5404  }
5405 
5406  int * zeroOneVecs= extractZeroOneVecs (NTLN);
5407  bufF= F;
5408  bufBufFactors= bufFactors;
5409  result= reconstruction (bufF, bufFactors, zeroOneVecs, l, NTLN, eval);
5410  delete [] zeroOneVecs;
5411  if (result.length() > 0 && degree (bufF) + 1 + degree (LC (bufF, 1)) <= l)
5412  {
5413  F= bufF;
5414  factors= bufFactors;
5415  delete [] A;
5416  return result;
5417  }
5418  else
5419  {
5420  bufF= F;
5421  bufFactors= bufBufFactors;
5422  }
5423 
5424  if (isReduced (NTLN))
5425  {
5426  int factorsFound= 0;
5427  bufF= F;
5428  int* factorsFoundIndex= new int [NTLN.NumCols()];
5429  for (long i= 0; i < NTLN.NumCols(); i++)
5430  factorsFoundIndex[i]= 0;
5431  if (l < liftBound)
5432  reconstructionTry (result, bufF, bufFactors, l, factorsFound,
5433  factorsFoundIndex, NTLN, eval, false
5434  );
5435  else
5436  reconstructionTry (result, bufF, bufFactors, degree (bufF) + 1 +
5437  degree (LCF), factorsFound, factorsFoundIndex,
5438  NTLN, eval, false
5439  );
5440  if (NTLN.NumCols() == result.length())
5441  {
5442  delete [] A;
5443  delete [] factorsFoundIndex;
5444  return result;
5445  }
5446  delete [] factorsFoundIndex;
5447  }
5448  result= CFList();
5449  oldL= l;
5450  stepSize *= 2;
5451  l += stepSize;
5452  if (l > liftBound)
5453  {
5454  if (!hitBound)
5455  {
5456  l= liftBound;
5457  hitBound= true;
5458  }
5459  else
5460  break;
5461  }
5462  }
5463  if (irreducible)
5464  {
5465  delete [] A;
5466  return CFList (F (y-eval,y));
5467  }
5468  delete [] A;
5469  factors= bufFactors;
5470  return CFList();
5471 }
5472 
5473 //over field extension
5474 #ifdef HAVE_FLINT
5475 CFList
5477  int liftBound, int d, int* bounds,
5478  nmod_mat_t FLINTN, CFList& diophant,
5479  CFMatrix& M, CFArray& Pi, CFArray& bufQ,
5480  const CanonicalForm& evaluation, const
5481  ExtensionInfo& info, CFList& source,
5482  CFList& dest
5483  )
5484 #else
5485 CFList
5487  int liftBound, int d, int* bounds,
5488  mat_zz_p& NTLN, CFList& diophant,
5489  CFMatrix& M, CFArray& Pi, CFArray& bufQ,
5490  const CanonicalForm& evaluation, const
5491  ExtensionInfo& info, CFList& source,
5492  CFList& dest
5493  )
5494 #endif
5495 {
5496  CanonicalForm LCF= LC (F, 1);
5497  CFList result;
5498  bool irreducible= false;
5499  CFList bufFactors= factors;
5500  CFList bufBufFactors;
5501  CFArray *A = new CFArray [bufFactors.length()];
5502  bool useOldQs= false;
5503  bool hitBound= false;
5504  bool GF= (CFFactory::gettype()==GaloisFieldDomain);
5505  int degMipo= degree (getMipo (info.getAlpha()));
5506  Variable alpha= info.getAlpha();
5507  int oldL= l; //be careful
5508  int stepSize= 8;
5509  l += tmax (tmin (8, degree (F) + 1 + degree (LC (F, 1))-l),2);
5510  Variable gamma= info.getBeta();
5511  CanonicalForm primElemAlpha= info.getGamma();
5512  CanonicalForm imPrimElemAlpha= info.getDelta();
5513 #ifdef HAVE_FLINT
5514  nmod_mat_clear (FLINTN);
5515  nmod_mat_init (FLINTN,factors.length(),factors.length(), getCharacteristic());
5516  for (long i=factors.length()-1; i >= 0; i--)
5517  nmod_mat_entry (FLINTN, i, i)= 1;
5518 #else
5519  if (NTLN.NumRows() != factors.length()) //refined factors
5520  ident (NTLN, factors.length());
5521 #endif
5522  Variable y= F.mvar();
5523  CanonicalForm powX, imBasis, bufF, truncF;
5524  CFMatrix Mat, C;
5525  CFIterator iter;
5526 #ifdef HAVE_FLINT
5527  long rank;
5528  nmod_mat_t FLINTMat, FLINTMatInv, FLINTC, FLINTK, null;
5529 #else
5530  mat_zz_p* NTLMat,*NTLC, NTLK;
5531 #endif
5532  CFListIterator j;
5533  CFArray buf;
5534  while (l <= liftBound)
5535  {
5536  bufFactors.insert (LCF);
5537  henselLiftResume12 (F, bufFactors, oldL, l, Pi, diophant, M);
5538 
5539  if (GF)
5541 
5542  powX= power (y-gamma, l);
5543  Mat= CFMatrix (l*degMipo, l*degMipo);
5544  for (int i= 0; i < l*degMipo; i++)
5545  {
5546 
5547  imBasis= mod (power (y, i), powX);
5548  imBasis= imBasis (power (y, degMipo), y);
5549  imBasis= imBasis (y, gamma);
5550  iter= imBasis;
5551  for (; iter.hasTerms(); iter++)
5552  Mat (iter.exp()+ 1, i+1)= iter.coeff();
5553  }
5554 
5555 #ifdef HAVE_FLINT
5556  convertFacCFMatrix2nmod_mat_t (FLINTMat, Mat);
5557  nmod_mat_init (FLINTMatInv, nmod_mat_nrows (FLINTMat),
5558  nmod_mat_nrows (FLINTMat), getCharacteristic());
5559  nmod_mat_inv (FLINTMatInv, FLINTMat);
5560 #else
5561  NTLMat= convertFacCFMatrix2NTLmat_zz_p (Mat);
5562  *NTLMat= inv (*NTLMat);
5563 #endif
5564 
5565  if (GF)
5566  setCharacteristic (getCharacteristic(), degMipo, info.getGFName());
5567 
5568  j= bufFactors;
5569  truncF= mod (F, power (y, l));
5570  if (useOldQs)
5571  {
5572  for (int i= 0; i < bufFactors.length(); i++, j++)
5573  A[i]= logarithmicDerivative (truncF, j.getItem(), l, oldL, bufQ[i],
5574  bufQ[i]);
5575  }
5576  else
5577  {
5578  for (int i= 0; i < bufFactors.length(); i++, j++)
5579  A[i]= logarithmicDerivative (truncF, j.getItem(), l, bufQ [i]);
5580  }
5581  for (int i= 0; i < d; i++)
5582  {
5583  if (bounds [i] + 1 <= l/2)
5584  {
5585  int k= tmin (bounds [i] + 1, l/2);
5586  C= CFMatrix (l*degMipo - k, bufFactors.length());
5587  for (int ii= 0; ii < bufFactors.length(); ii++)
5588  {
5589  if (A[ii].size() - 1 >= i)
5590  {
5591  if (GF)
5592  {
5593  A [ii] [i]= A [ii] [i] (y-evaluation, y);
5595  A[ii] [i]= GF2FalphaRep (A[ii] [i], alpha);
5596  if (alpha != gamma)
5597  A [ii] [i]= mapDown (A[ii] [i], imPrimElemAlpha, primElemAlpha,
5598  gamma, source, dest
5599  );
5600 #ifdef HAVE_FLINT
5601  buf= getCoeffs (A[ii] [i], k, l, degMipo, gamma, 0, FLINTMatInv);
5602 #else
5603  buf= getCoeffs (A[ii] [i], k, l, degMipo, gamma, 0, *NTLMat);
5604 #endif
5605  }
5606  else
5607  {
5608  A [ii] [i]= A [ii] [i] (y-evaluation, y);
5609  if (alpha != gamma)
5610  A[ii] [i]= mapDown (A[ii] [i], imPrimElemAlpha, primElemAlpha,
5611  gamma, source, dest
5612  );
5613 #ifdef HAVE_FLINT
5614  buf= getCoeffs (A[ii] [i], k, l, degMipo, gamma, 0, FLINTMatInv);
5615 #else
5616  buf= getCoeffs (A[ii] [i], k, l, degMipo, gamma, 0, *NTLMat);
5617 #endif
5618  }
5619  writeInMatrix (C, buf, ii + 1, 0);
5620  }
5621  if (GF)
5622  setCharacteristic (getCharacteristic(), degMipo, info.getGFName());
5623  }
5624 
5625  if (GF)
5627 
5628 #ifdef HAVE_FLINT
5629  convertFacCFMatrix2nmod_mat_t (FLINTC, C);
5630  nmod_mat_init (FLINTK, nmod_mat_nrows (FLINTC), nmod_mat_ncols (FLINTN),
5631  getCharacteristic());
5632  nmod_mat_mul (FLINTK, FLINTC, FLINTN);
5633  nmod_mat_init (null, nmod_mat_ncols (FLINTK), nmod_mat_ncols (FLINTK),
5634  getCharacteristic());
5635  rank= nmod_mat_nullspace (null, FLINTK);
5636  nmod_mat_clear (FLINTK);
5637  nmod_mat_window_init (FLINTK, null, 0, 0, nmod_mat_nrows(null), rank);
5638  nmod_mat_clear (FLINTC);
5639  nmod_mat_init_set (FLINTC, FLINTN);
5640  nmod_mat_clear (FLINTN);
5641  nmod_mat_init (FLINTN, nmod_mat_nrows (FLINTC), nmod_mat_ncols (FLINTK),
5642  getCharacteristic());
5643  nmod_mat_mul (FLINTN, FLINTC, FLINTK); //no aliasing allowed!!
5644 
5645  nmod_mat_clear (FLINTC);
5646  nmod_mat_window_clear (FLINTK);
5647  nmod_mat_clear (null);
5648 #else
5650  NTLK= (*NTLC)*NTLN;
5651  transpose (NTLK, NTLK);
5652  kernel (NTLK, NTLK);
5653  transpose (NTLK, NTLK);
5654  NTLN *= NTLK;
5655  delete NTLC;
5656 #endif
5657 
5658  if (GF)
5659  setCharacteristic (getCharacteristic(), degMipo, info.getGFName());
5660 
5661 #ifdef HAVE_FLINT
5662  if (nmod_mat_ncols (FLINTN) == 1)
5663 #else
5664  if (NTLN.NumCols() == 1)
5665 #endif
5666  {
5667  irreducible= true;
5668  break;
5669  }
5670  }
5671  }
5672 
5673 #ifdef HAVE_FLINT
5674  nmod_mat_clear (FLINTMat);
5675  nmod_mat_clear (FLINTMatInv);
5676  if (nmod_mat_ncols (FLINTN) == 1)
5677 #else
5678  delete NTLMat;
5679  if (NTLN.NumCols() == 1)
5680 #endif
5681  {
5682  irreducible= true;
5683  break;
5684  }
5685 
5686  bufF= F;
5687  bufBufFactors= bufFactors;
5688 #ifdef HAVE_FLINT
5689  int * zeroOneVecs= extractZeroOneVecs (FLINTN);
5690  result= extReconstruction (bufF, bufFactors, zeroOneVecs, l, FLINTN, info,
5691  evaluation
5692  );
5693 #else
5694  int * zeroOneVecs= extractZeroOneVecs (NTLN);
5695  result= extReconstruction (bufF, bufFactors, zeroOneVecs, l, NTLN, info,
5696  evaluation
5697  );
5698 #endif
5699  delete [] zeroOneVecs;
5700  if (result.length() > 0 && degree (bufF) + 1 + degree (LC (bufF, 1)) <= l)
5701  {
5702  F= bufF;
5703  factors= bufFactors;
5704  delete [] A;
5705  return result;
5706  }
5707  else
5708  {
5709  bufF= F;
5710  bufFactors= bufBufFactors;
5711  }
5712 
5713 #ifdef HAVE_FLINT
5714  if (isReduced (FLINTN))
5715 #else
5716  if (isReduced (NTLN))
5717 #endif
5718  {
5719  int factorsFound= 0;
5720  bufF= F;
5721 #ifdef HAVE_FLINT
5722  int* factorsFoundIndex= new int [nmod_mat_ncols (FLINTN)];
5723  for (long i= 0; i < nmod_mat_ncols (FLINTN); i++)
5724 #else
5725  int* factorsFoundIndex= new int [NTLN.NumCols()];
5726  for (long i= 0; i < NTLN.NumCols(); i++)
5727 #endif
5728  factorsFoundIndex[i]= 0;
5729 #ifdef HAVE_FLINT
5730  if (l < degree (bufF) + 1 + degree (LCF))
5731  extReconstructionTry (result, bufF, bufFactors, l, factorsFound,
5732  factorsFoundIndex, FLINTN, false, info, evaluation
5733  );
5734  else
5735  extReconstructionTry (result, bufF, bufFactors, degree (bufF) + 1 +
5736  degree (LCF), factorsFound, factorsFoundIndex,
5737  FLINTN, false, info, evaluation
5738  );
5739  if (nmod_mat_ncols (FLINTN) == result.length())
5740 #else
5741  if (l < degree (bufF) + 1 + degree (LCF))
5742  extReconstructionTry (result, bufF, bufFactors, l, factorsFound,
5743  factorsFoundIndex, NTLN, false, info, evaluation
5744  );
5745  else
5746  extReconstructionTry (result, bufF, bufFactors, degree (bufF) + 1 +
5747  degree (LCF), factorsFound, factorsFoundIndex,
5748  NTLN, false, info, evaluation
5749  );
5750  if (NTLN.NumCols() == result.length())
5751 #endif
5752  {
5753  delete [] A;
5754  delete [] factorsFoundIndex;
5755  return result;
5756  }
5757  delete [] factorsFoundIndex;
5758  }
5759  result= CFList();
5760  oldL= l;
5761  stepSize *= 2;
5762  l += stepSize;
5763  if (l > liftBound)
5764  {
5765  if (!hitBound)
5766  {
5767  l= liftBound;
5768  hitBound= true;
5769  }
5770  else
5771  break;
5772  }
5773  }
5774  if (irreducible)
5775  {
5776  delete [] A;
5777  Variable y= Variable (2);
5778  CanonicalForm tmp= F (y - evaluation, y);
5779  CFList source, dest;
5780  tmp= mapDown (tmp, info, source, dest);
5781  return CFList (tmp);
5782  }
5783  delete [] A;
5784  factors= bufFactors;
5785  return CFList();
5786 }
5787 
5788 #ifdef HAVE_FLINT
5789 CFList
5791  l, int liftBound, int d, int* bounds,
5792  nmod_mat_t FLINTN, CFList& diophant,
5793  CFMatrix& M, CFArray& Pi, CFArray& bufQ,
5794  const Variable& alpha,
5795  const CanonicalForm& eval
5796  )
5797 #else
5798 CFList
5800  l, int liftBound, int d, int* bounds,
5801  mat_zz_p& NTLN, CFList& diophant,
5802  CFMatrix& M, CFArray& Pi, CFArray& bufQ,
5803  const Variable& alpha,
5804  const CanonicalForm& eval
5805  )
5806 #endif
5807 {
5808  CanonicalForm LCF= LC (F, 1);
5809  CFList result;
5810  bool irreducible= false;
5811  CFList bufFactors= factors;
5812  CFList bufBufFactors;
5813  CFArray *A = new CFArray [bufFactors.length()];
5814  bool useOldQs= false;
5815  int extensionDeg= degree (getMipo (alpha));
5816  bool hitBound= false;
5817  int oldL= l;
5818  int stepSize= 8; //TODO choose better step size?
5819  l += tmax (tmin (8, degree (F) + 1 + degree (LC (F, 1))-l), 2);
5820 #ifdef HAVE_FLINT
5821  if (nmod_mat_nrows (FLINTN) != factors.length()) //refined factors
5822  {
5823  nmod_mat_clear (FLINTN);
5824  nmod_mat_init(FLINTN,factors.length(),factors.length(),getCharacteristic());
5825  for (long i=factors.length()-1; i >= 0; i--)
5826  nmod_mat_entry (FLINTN, i, i)= 1;
5827  }
5828 #else
5829  if (NTLN.NumRows() != factors.length()) //refined factors
5830  ident (NTLN, factors.length());
5831 #endif
5832  CFListIterator j;
5833  CFMatrix C;
5834 #ifdef HAVE_FLINT
5835  long rank;
5836  nmod_mat_t FLINTC, FLINTK, null;
5837 #else
5838  mat_zz_p* NTLC, NTLK;
5839 #endif
5840  CanonicalForm bufF, truncF;
5841  Variable y= F.mvar();
5842  while (l <= liftBound)
5843  {
5844  bufFactors.insert (LCF);
5845  henselLiftResume12 (F, bufFactors, oldL, l, Pi, diophant, M);
5846  j= bufFactors;
5847  truncF= mod (F, power (y, l));
5848  if (useOldQs)
5849  {
5850  for (int i= 0; i < bufFactors.length(); i++, j++)
5851  A[i]= logarithmicDerivative (truncF, j.getItem(), l, oldL, bufQ[i],
5852  bufQ[i]);
5853  }
5854  else
5855  {
5856  for (int i= 0; i < bufFactors.length(); i++, j++)
5857  A[i]= logarithmicDerivative (truncF, j.getItem(), l, bufQ [i]);
5858  }
5859  for (int i= 0; i < d; i++)
5860  {
5861  if (bounds [i] + 1 <= l/2)
5862  {
5863  int k= tmin (bounds [i] + 1, l/2);
5864  C= CFMatrix ((l - k)*extensionDeg, bufFactors.length());
5865  for (int ii= 0; ii < bufFactors.length(); ii++)
5866  {
5867  CFArray buf;
5868  if (A[ii].size() - 1 >= i)
5869  {
5870  buf= getCoeffs (A[ii] [i], k, alpha);
5871  writeInMatrix (C, buf, ii + 1, 0);
5872  }
5873  }
5874 #ifdef HAVE_FLINT
5875  convertFacCFMatrix2nmod_mat_t (FLINTC, C);
5876  nmod_mat_init (FLINTK, nmod_mat_nrows (FLINTC), nmod_mat_ncols (FLINTN),
5877  getCharacteristic());
5878  nmod_mat_mul (FLINTK, FLINTC, FLINTN);
5879  nmod_mat_init (null, nmod_mat_ncols (FLINTK), nmod_mat_ncols (FLINTK),
5880  getCharacteristic());
5881  rank= nmod_mat_nullspace (null, FLINTK);
5882  nmod_mat_clear (FLINTK);
5883  nmod_mat_window_init (FLINTK, null, 0, 0, nmod_mat_nrows(null), rank);
5884  nmod_mat_clear (FLINTC);
5885  nmod_mat_init_set (FLINTC, FLINTN);
5886  nmod_mat_clear (FLINTN);
5887  nmod_mat_init (FLINTN, nmod_mat_nrows (FLINTC), nmod_mat_ncols (FLINTK),
5888  getCharacteristic());
5889  nmod_mat_mul (FLINTN, FLINTC, FLINTK); //no aliasing allowed!!
5890 
5891  nmod_mat_clear (FLINTC);
5892  nmod_mat_window_clear (FLINTK);
5893  nmod_mat_clear (null);
5894 #else
5896  NTLK= (*NTLC)*NTLN;
5897  transpose (NTLK, NTLK);
5898  kernel (NTLK, NTLK);
5899  transpose (NTLK, NTLK);
5900  NTLN *= NTLK;
5901  delete NTLC;
5902 #endif
5903 #ifdef HAVE_FLINT
5904  if (nmod_mat_ncols (FLINTN) == 1)
5905 #else
5906  if (NTLN.NumCols() == 1)
5907 #endif
5908  {
5909  irreducible= true;
5910  break;
5911  }
5912  }
5913  }
5914 #ifdef HAVE_FLINT
5915  if (nmod_mat_ncols (FLINTN) == 1)
5916 #else
5917  if (NTLN.NumCols() == 1)
5918 #endif
5919  {
5920  irreducible= true;
5921  break;
5922  }
5923 
5924 #ifdef HAVE_FLINT
5925  int * zeroOneVecs= extractZeroOneVecs (FLINTN);
5926 #else
5927  int * zeroOneVecs= extractZeroOneVecs (NTLN);
5928 #endif
5929  CanonicalForm bufF= F;
5930  bufBufFactors= bufFactors;
5931 #ifdef HAVE_FLINT
5932  result= reconstruction (bufF, bufFactors, zeroOneVecs, l, FLINTN, eval);
5933 #else
5934  result= reconstruction (bufF, bufFactors, zeroOneVecs, l, NTLN, eval);
5935 #endif
5936  delete [] zeroOneVecs;
5937  if (result.length() > 0 && degree (bufF) + 1 + degree (LC (bufF, 1)) <= l)
5938  {
5939  F= bufF;
5940  factors= bufFactors;
5941  delete [] A;
5942  return result;
5943  }
5944  else
5945  {
5946  bufF= F;
5947  bufFactors= bufBufFactors;
5948  }
5949 
5950 #ifdef HAVE_FLINT
5951  if (isReduced (FLINTN))
5952 #else
5953  if (isReduced (NTLN))
5954 #endif
5955  {
5956  int factorsFound= 0;
5957  bufF= F;
5958 #ifdef HAVE_FLINT
5959  int* factorsFoundIndex= new int [nmod_mat_ncols (FLINTN)];
5960  for (long i= 0; i < nmod_mat_ncols (FLINTN); i++)
5961 #else
5962  int* factorsFoundIndex= new int [NTLN.NumCols()];
5963  for (long i= 0; i < NTLN.NumCols(); i++)
5964 #endif
5965  factorsFoundIndex[i]= 0;
5966 #ifdef HAVE_FLINT
5967  if (l < degree (bufF) + 1 + degree (LCF))
5968  reconstructionTry (result, bufF, bufFactors, l, factorsFound,
5969  factorsFoundIndex, FLINTN, eval, false
5970  );
5971  else
5972  reconstructionTry (result, bufF, bufFactors, degree (bufF) + 1 +
5973  degree (LCF), factorsFound, factorsFoundIndex,
5974  FLINTN, eval, false
5975  );
5976  if (nmod_mat_ncols (FLINTN) == result.length())
5977 #else
5978  if (l < degree (bufF) + 1 + degree (LCF))
5979  reconstructionTry (result, bufF, bufFactors, l, factorsFound,
5980  factorsFoundIndex, NTLN, eval, false
5981  );
5982  else
5983  reconstructionTry (result, bufF, bufFactors, degree (bufF) + 1 +
5984  degree (LCF), factorsFound, factorsFoundIndex,
5985  NTLN, eval, false
5986  );
5987  if (NTLN.NumCols() == result.length())
5988 #endif
5989  {
5990  delete [] A;
5991  delete [] factorsFoundIndex;
5992  return result;
5993  }
5994  delete [] factorsFoundIndex;
5995  }
5996  result= CFList();
5997  oldL= l;
5998  stepSize *= 2;
5999  l += stepSize;
6000  if (l > liftBound)
6001  {
6002  if (!hitBound)
6003  {
6004  l= liftBound;
6005  hitBound= true;
6006  }
6007  else
6008  break;
6009  }
6010  }
6011  if (irreducible)
6012  {
6013  delete [] A;
6014  return CFList (F (y-eval,y));
6015  }
6016  delete [] A;
6017  factors= bufFactors;
6018  return CFList();
6019 }
6020 
6021 #ifndef HAVE_FLINT
6022 void
6023 refineAndRestartLift (const CanonicalForm& F, const mat_zz_p& NTLN, int
6024  liftBound, int l, CFList& factors, CFMatrix& M, CFArray&
6025  Pi, CFList& diophant
6026  )
6027 {
6028  CFList bufFactors;
6029  Variable y= Variable (2);
6030  CanonicalForm LCF= LC (F, 1);
6033  for (long i= 1; i <= NTLN.NumCols(); i++)
6034  {
6035  iter= factors;
6036  buf= 1;
6037  for (long j= 1; j <= NTLN.NumRows(); j++, iter++)
6038  {
6039  if (!IsZero (NTLN (j,i)))
6040  buf= mulNTL (buf, mod (iter.getItem(), y));
6041  }
6042  bufFactors.append (buf);
6043  }
6044  factors= bufFactors;
6045  M= CFMatrix (liftBound, factors.length());
6046  Pi= CFArray();
6047  diophant= CFList();
6048  factors.insert (LCF);
6049  henselLift12 (F, factors, l, Pi, diophant, M);
6050 }
6051 #endif
6052 
6053 #ifdef HAVE_FLINT
6054 void
6055 refineAndRestartLift (const CanonicalForm& F, const nmod_mat_t FLINTN, int
6056  liftBound, int l, CFList& factors, CFMatrix& M, CFArray&
6057  Pi, CFList& diophant
6058  )
6059 {
6060  CFList bufFactors;
6061  Variable y= Variable (2);
6062  CanonicalForm LCF= LC (F, 1);
6065  for (long i= 0; i < nmod_mat_ncols (FLINTN); i++)
6066  {
6067  iter= factors;
6068  buf= 1;
6069  for (long j= 0; j < nmod_mat_nrows (FLINTN); j++, iter++)
6070  {
6071  if (!(nmod_mat_entry (FLINTN,j,i) == 0))
6072  buf= mulNTL (buf, mod (iter.getItem(), y));
6073  }
6074  bufFactors.append (buf);
6075  }
6076  factors= bufFactors;
6077  M= CFMatrix (liftBound, factors.length());
6078  Pi= CFArray();
6079  diophant= CFList();
6080  factors.insert (LCF);
6081  henselLift12 (F, factors, l, Pi, diophant, M);
6082 }
6083 #endif
6084 
6085 void
6086 refineAndRestartLift (const CanonicalForm& F, const mat_zz_pE& NTLN, int
6087  liftBound, int l, CFList& factors, CFMatrix& M, CFArray&
6088  Pi, CFList& diophant
6089  )
6090 {
6091  CFList bufFactors;
6092  Variable y= Variable (2);
6093  CanonicalForm LCF= LC (F, 1);
6096  for (long i= 1; i <= NTLN.NumCols(); i++)
6097  {
6098  iter= factors;
6099  buf= 1;
6100  for (long j= 1; j <= NTLN.NumRows(); j++, iter++)
6101  {
6102  if (!IsZero (NTLN (j,i)))
6103  buf= mulNTL (buf, mod (iter.getItem(), y));
6104  }
6105  bufFactors.append (buf);
6106  }
6107  factors= bufFactors;
6108  M= CFMatrix (liftBound, factors.length());
6109  Pi= CFArray();
6110  diophant= CFList();
6111  factors.insert (LCF);
6112  henselLift12 (F, factors, l, Pi, diophant, M);
6113 }
6114 
6115 #ifdef HAVE_FLINT
6116 CFList
6117 earlyReconstructionAndLifting (const CanonicalForm& F, const nmod_mat_t N,
6118  CanonicalForm& bufF, CFList& factors, int& l,
6119  int& factorsFound, bool beenInThres, CFMatrix& M,
6120  CFArray& Pi, CFList& diophant, bool symmetric,
6121  const CanonicalForm& evaluation
6122  )
6123 #else
6124 CFList
6125 earlyReconstructionAndLifting (const CanonicalForm& F, const mat_zz_p& N,
6126  CanonicalForm& bufF, CFList& factors, int& l,
6127  int& factorsFound, bool beenInThres, CFMatrix& M,
6128  CFArray& Pi, CFList& diophant, bool symmetric,
6129  const CanonicalForm& evaluation
6130  )
6131 #endif
6132 {
6133  int sizeOfLiftPre;
6134  int * liftPre= getLiftPrecisions (F, sizeOfLiftPre, degree (LC (F, 1), 2));
6135 
6136  Variable y= F.mvar();
6137  factorsFound= 0;
6138  CanonicalForm LCF= LC (F, 1);
6139  CFList result;
6140  int smallFactorDeg= tmin (11, liftPre [sizeOfLiftPre- 1] + 1);
6141 #ifdef HAVE_FLINT
6142  nmod_mat_t FLINTN;
6143  nmod_mat_init_set (FLINTN, N);
6144  int * factorsFoundIndex= new int [nmod_mat_ncols (FLINTN)];
6145  for (long i= 0; i < nmod_mat_ncols (FLINTN); i++)
6146 #else
6147  mat_zz_p NTLN= N;
6148  int * factorsFoundIndex= new int [NTLN.NumCols()];
6149  for (long i= 0; i < NTLN.NumCols(); i++)
6150 #endif
6151  factorsFoundIndex [i]= 0;
6152 
6153  if (degree (F) + 1 > smallFactorDeg)
6154  {
6155  if (l < smallFactorDeg)
6156  {
6157  TIMING_START (fac_fq_lift);
6158  factors.insert (LCF);
6159  henselLiftResume12 (F, factors, l, smallFactorDeg, Pi, diophant, M);
6160  TIMING_END_AND_PRINT (fac_fq_lift, "time to lift in reconstruction0: ");
6161  l= smallFactorDeg;
6162  }
6163 #ifdef HAVE_FLINT
6164  TIMING_START (fac_fq_reconstruction);
6165  reconstructionTry (result, bufF, factors, smallFactorDeg, factorsFound,
6166  factorsFoundIndex, FLINTN, evaluation, beenInThres
6167  );
6168  TIMING_END_AND_PRINT (fac_fq_reconstruction, "time to reconstruct0: ");
6169  if (result.length() == nmod_mat_ncols (FLINTN))
6170  {
6171  nmod_mat_clear (FLINTN);
6172 #else
6173  TIMING_START (fac_fq_reconstruction);
6174  reconstructionTry (result, bufF, factors, smallFactorDeg, factorsFound,
6175  factorsFoundIndex, NTLN, evaluation, beenInThres
6176  );
6177  TIMING_END_AND_PRINT (fac_fq_reconstruction, "time to reconstruct0: ");
6178  if (result.length() == NTLN.NumCols())
6179  {
6180 #endif
6181  delete [] liftPre;
6182  delete [] factorsFoundIndex;
6183  return result;
6184  }
6185  }
6186 
6187  int i= sizeOfLiftPre - 1;
6188  int dummy= 1;
6189  if (sizeOfLiftPre > 1 && sizeOfLiftPre < 30)
6190  {
6191  while (i > 0)
6192  {
6193  if (l < liftPre[i-1] + 1)
6194  {
6195  factors.insert (LCF);
6196  TIMING_START (fac_fq_lift);
6197  henselLiftResume12 (F, factors, l, liftPre[i-1] + 1, Pi, diophant, M);
6198  TIMING_END_AND_PRINT (fac_fq_lift, "time to lift in reconstruction1: ");
6199  l= liftPre[i-1] + 1;
6200  }
6201  else
6202  {
6203  i--;
6204  if (i != 0)
6205  continue;
6206  }
6207 #ifdef HAVE_FLINT
6208  TIMING_START (fac_fq_reconstruction);
6209  reconstructionTry (result, bufF, factors, l, factorsFound,
6210  factorsFoundIndex, FLINTN, evaluation, beenInThres
6211  );
6212  TIMING_END_AND_PRINT (fac_fq_reconstruction, "time to reconstruct1: ");
6213  if (result.length() == nmod_mat_ncols (FLINTN))
6214  {
6215  nmod_mat_clear (FLINTN);
6216 #else
6217  TIMING_START (fac_fq_reconstruction);
6218  reconstructionTry (result, bufF, factors, l, factorsFound,
6219  factorsFoundIndex, NTLN, evaluation, beenInThres
6220  );
6221  TIMING_END_AND_PRINT (fac_fq_reconstruction, "time to reconstruct1: ");
6222  if (result.length() == NTLN.NumCols())
6223  {
6224 #endif
6225  delete [] liftPre;
6226  delete [] factorsFoundIndex;
6227  return result;
6228  }
6229  i--;
6230  }
6231  }
6232  else
6233  {
6234  i= 1;
6235  while (((degree (F,y)/4)*i+1) + 4 <= smallFactorDeg)
6236  i++;
6237  while (i < 5)
6238  {
6239  dummy= tmin (degree (F,y)+1, ((degree (F,y)/4)+1)*i+4);
6240  if (l < dummy)
6241  {
6242  factors.insert (LCF);
6243  TIMING_START (fac_fq_lift);
6244  henselLiftResume12 (F, factors, l, dummy, Pi, diophant, M);
6245  TIMING_END_AND_PRINT (fac_fq_lift, "time to lift in reconstruction2: ");
6246  l= dummy;
6247  if (i == 1 && degree (F)%4==0 && symmetric && factors.length() == 2 &&
6248  LC (F,1).inCoeffDomain() &&
6249  (degree (factors.getFirst(), 1) == degree (factors.getLast(),1)))
6250  {
6251  Variable x= Variable (1);
6252  CanonicalForm g, h, gg, hh, multiplier1, multiplier2, check1, check2;
6253  int m= degree (F)/4+1;
6254  g= factors.getFirst();
6255  h= factors.getLast();
6256  g= mod (g, power (y,m));
6257  h= mod (h, power (y,m));
6258  g= g (y-evaluation, y);
6259  h= h (y-evaluation, y);
6260  gg= mod (swapvar (g,x,y),power (x,m));
6261  gg= gg (y + evaluation, y);
6262  multiplier1= factors.getLast()[m-1][0]/gg[m-1][0];
6263  gg= div (gg, power (y,m));
6264  gg= gg*power (y,m);
6265  hh= mod (swapvar (h,x,y),power (x,m));
6266  hh= hh (y + evaluation, y);
6267  multiplier2= factors.getFirst()[m-1][0]/hh[m-1][0];
6268  hh= div (hh, power (y,m));
6269  hh= hh*power (y,m);
6270  gg= multiplier1*gg+mod (factors.getLast(), power (y,m));
6271  hh= multiplier2*hh+mod (factors.getFirst(), power (y,m));
6272  check1= gg (y-evaluation,y);
6273  check2= hh (y-evaluation,y);
6274  CanonicalForm oldcheck1= check1;
6275  check1= swapvar (check1, x, y);
6276  if (check1/Lc (check1) == check2/Lc (check2))
6277  {
6278 #ifdef HAVE_FLINT
6279  nmod_mat_clear (FLINTN);
6280 #endif
6281  result.append (oldcheck1);
6282  result.append (check2);
6283  delete [] liftPre;
6284  delete [] factorsFoundIndex;
6285  return result;
6286  }
6287  }
6288  }
6289  else
6290  {
6291  i++;
6292  if (i < 5)
6293  continue;
6294  }
6295 #ifdef HAVE_FLINT
6296  TIMING_START (fac_fq_reconstruction);
6297  reconstructionTry (result, bufF, factors, l, factorsFound,
6298  factorsFoundIndex, FLINTN, evaluation, beenInThres
6299  );
6300  TIMING_END_AND_PRINT (fac_fq_reconstruction, "time to reconstruct2: ");
6301  if (result.length() == nmod_mat_ncols (FLINTN))
6302  {
6303  nmod_mat_clear (FLINTN);
6304 #else
6305  TIMING_START (fac_fq_reconstruction);
6306  reconstructionTry (result, bufF, factors, l, factorsFound,
6307  factorsFoundIndex, NTLN, evaluation, beenInThres
6308  );
6309  TIMING_END_AND_PRINT (fac_fq_reconstruction, "time to reconstruct2: ");
6310  if (result.length() == NTLN.NumCols())
6311  {
6312 #endif
6313  delete [] liftPre;
6314  delete [] factorsFoundIndex;
6315  return result;
6316  }
6317  i++;
6318  }
6319  }
6320 
6321 #ifdef HAVE_FLINT
6322  nmod_mat_clear (FLINTN);
6323 #endif
6324  delete [] liftPre;
6325  delete [] factorsFoundIndex;
6326  return result;
6327 }
6328 
6329 CFList
6330 earlyReconstructionAndLifting (const CanonicalForm& F, const mat_zz_pE& N,
6331  CanonicalForm& bufF, CFList& factors, int& l,
6332  int& factorsFound, bool beenInThres, CFMatrix& M,
6333  CFArray& Pi, CFList& diophant, bool symmetric,
6334  const CanonicalForm& evaluation
6335  )
6336 {
6337  int sizeOfLiftPre;
6338  int * liftPre= getLiftPrecisions (F, sizeOfLiftPre, degree (LC (F, 1), 2));
6339  Variable y= F.mvar();
6340  factorsFound= 0;
6341  CanonicalForm LCF= LC (F, 1);
6342  CFList result;
6343  int smallFactorDeg= 11;
6344  mat_zz_pE NTLN= N;
6345  int * factorsFoundIndex= new int [NTLN.NumCols()];
6346  for (long i= 0; i < NTLN.NumCols(); i++)
6347  factorsFoundIndex [i]= 0;
6348 
6349  if (degree (F) + 1 > smallFactorDeg)
6350  {
6351  if (l < smallFactorDeg)
6352  {
6353  TIMING_START (fac_fq_lift);
6354  factors.insert (LCF);
6355  henselLiftResume12 (F, factors, l, smallFactorDeg, Pi, diophant, M);
6356  TIMING_END_AND_PRINT (fac_fq_lift, "time to lift in reconstruction0: ");
6357  l= smallFactorDeg;
6358  }
6359  TIMING_START (fac_fq_reconstruction);
6360  reconstructionTry (result, bufF, factors, smallFactorDeg, factorsFound,
6361  factorsFoundIndex, NTLN, evaluation, beenInThres
6362  );
6363  TIMING_END_AND_PRINT (fac_fq_reconstruction, "time to reconstruct0: ");
6364  if (result.length() == NTLN.NumCols())
6365  {
6366  delete [] liftPre;
6367  delete [] factorsFoundIndex;
6368  return result;
6369  }
6370  }
6371 
6372  int i= sizeOfLiftPre - 1;
6373  int dummy= 1;
6374  if (sizeOfLiftPre > 1 && sizeOfLiftPre < 30)
6375  {
6376  while (i > 0)
6377  {
6378  if (l < liftPre[i-1] + 1)
6379  {
6380  factors.insert (LCF);
6381  TIMING_START (fac_fq_lift);
6382  henselLiftResume12 (F, factors, l, liftPre[i-1] + 1, Pi, diophant, M);
6383  TIMING_END_AND_PRINT (fac_fq_lift, "time to lift in reconstruction1: ");
6384  l= liftPre[i-1] + 1;
6385  }
6386  else
6387  {
6388  i--;
6389  if (i != 0)
6390  continue;
6391  }
6392  TIMING_START (fac_fq_reconstruction);
6393  reconstructionTry (result, bufF, factors, l, factorsFound,
6394  factorsFoundIndex, NTLN, evaluation, beenInThres
6395  );
6396  TIMING_END_AND_PRINT (fac_fq_reconstruction, "time to reconstruct1: ");
6397  if (result.length() == NTLN.NumCols())
6398  {
6399  delete [] liftPre;
6400  delete [] factorsFoundIndex;
6401  return result;
6402  }
6403  i--;
6404  }
6405  }
6406  else
6407  {
6408  i= 1;
6409  while ((degree (F,y)/4+1)*i + 4 <= smallFactorDeg)
6410  i++;
6411  while (i < 5)
6412  {
6413  dummy= tmin (degree (F,y)+1, (degree (F,y)/4+1)*i+4);
6414  if (l < dummy)
6415  {
6416  factors.insert (LCF);
6417  TIMING_START (fac_fq_lift);
6418  henselLiftResume12 (F, factors, l, dummy, Pi, diophant, M);
6419  TIMING_END_AND_PRINT (fac_fq_lift, "time to lift in reconstruction2: ");
6420  l= dummy;
6421  if (i == 1 && degree (F)%4==0 && symmetric && factors.length() == 2 &&
6422  LC (F,1).inCoeffDomain() &&
6423  (degree (factors.getFirst(), 1) == degree (factors.getLast(),1)))
6424  {
6425  Variable x= Variable (1);
6426  CanonicalForm g, h, gg, hh, multiplier1, multiplier2, check1, check2;
6427  int m= degree (F)/4+1;
6428  g= factors.getFirst();
6429  h= factors.getLast();
6430  g= mod (g, power (y,m));
6431  h= mod (h, power (y,m));
6432  g= g (y-evaluation, y);
6433  h= h (y-evaluation, y);
6434  gg= mod (swapvar (g,x,y),power (x,m));
6435  gg= gg (y + evaluation, y);
6436  multiplier1= factors.getLast()[m-1][0]/gg[m-1][0];
6437  gg= div (gg, power (y,m));
6438  gg= gg*power (y,m);
6439  hh= mod (swapvar (h,x,y),power (x,m));
6440  hh= hh (y + evaluation, y);
6441  multiplier2= factors.getFirst()[m-1][0]/hh[m-1][0];
6442  hh= div (hh, power (y,m));
6443  hh= hh*power (y,m);
6444  gg= multiplier1*gg+mod (factors.getLast(), power (y,m));
6445  hh= multiplier2*hh+mod (factors.getFirst(), power (y,m));
6446  check1= gg (y-evaluation,y);
6447  check2= hh (y-evaluation,y);
6448  CanonicalForm oldcheck1= check1;
6449  check1= swapvar (check1, x, y);
6450  if (check1/Lc (check1) == check2/Lc (check2))
6451  {
6452  result.append (oldcheck1);
6453  result.append (check2);
6454  delete [] liftPre;
6455  delete [] factorsFoundIndex;
6456  return result;
6457  }
6458  }
6459  }
6460  else
6461  {
6462  i++;
6463  if (i < 5)
6464  continue;
6465  }
6466  TIMING_START (fac_fq_reconstruction);
6467  reconstructionTry (result, bufF, factors, l, factorsFound,
6468  factorsFoundIndex, NTLN, evaluation, beenInThres
6469  );
6470  TIMING_END_AND_PRINT (fac_fq_reconstruction, "time to reconstruct2: ");
6471  if (result.length() == NTLN.NumCols())
6472  {
6473  delete [] liftPre;
6474  delete [] factorsFoundIndex;
6475  return result;
6476  }
6477  i++;
6478  }
6479  }
6480 
6481  delete [] liftPre;
6482  delete [] factorsFoundIndex;
6483  return result;
6484 }
6485 
6486 //over field extension
6487 #ifdef HAVE_FLINT
6488 CFList
6489 extEarlyReconstructionAndLifting (const CanonicalForm& F, const nmod_mat_t N,
6490  CanonicalForm& bufF, CFList& factors, int& l,
6491  int& factorsFound, bool beenInThres, CFMatrix&
6492  M, CFArray& Pi, CFList& diophant, const
6493  ExtensionInfo& info, const CanonicalForm&
6494  evaluation
6495  )
6496 #else
6497 CFList
6498 extEarlyReconstructionAndLifting (const CanonicalForm& F, const mat_zz_p& N,
6499  CanonicalForm& bufF, CFList& factors, int& l,
6500  int& factorsFound, bool beenInThres, CFMatrix&
6501  M, CFArray& Pi, CFList& diophant, const
6502  ExtensionInfo& info, const CanonicalForm&
6503  evaluation
6504  )
6505 #endif
6506 {
6507  int sizeOfLiftPre;
6508  int * liftPre= getLiftPrecisions (F, sizeOfLiftPre, degree (LC (F, 1), 2));
6509  Variable y= F.mvar();
6510  factorsFound= 0;
6511  CanonicalForm LCF= LC (F, 1);
6512  CFList result;
6513  int smallFactorDeg= 11;
6514 #ifdef HAVE_FLINT
6515  nmod_mat_t FLINTN;
6516  nmod_mat_init_set (FLINTN, N);
6517  int * factorsFoundIndex= new int [nmod_mat_ncols (FLINTN)];
6518  for (long i= 0; i < nmod_mat_ncols (FLINTN); i++)
6519 #else
6520  mat_zz_p NTLN= N;
6521  int * factorsFoundIndex= new int [NTLN.NumCols()];
6522  for (long i= 0; i < NTLN.NumCols(); i++)
6523 #endif
6524  factorsFoundIndex [i]= 0;
6525 
6526  if (degree (F) + 1 > smallFactorDeg)
6527  {
6528  if (l < smallFactorDeg)
6529  {
6530  TIMING_START (fac_fq_lift);
6531  factors.insert (LCF);
6532  henselLiftResume12 (F, factors, l, smallFactorDeg, Pi, diophant, M);
6533  TIMING_END_AND_PRINT (fac_fq_lift, "time to lift in reconstruction0: ");
6534  l= smallFactorDeg;
6535  }
6536  TIMING_START (fac_fq_reconstruction);
6537 #ifdef HAVE_FLINT
6538  extReconstructionTry (result, bufF, factors, smallFactorDeg, factorsFound,
6539  factorsFoundIndex, FLINTN, beenInThres, info,
6540  evaluation
6541  );
6542 #else
6543  extReconstructionTry (result, bufF, factors, smallFactorDeg, factorsFound,
6544  factorsFoundIndex, NTLN, beenInThres, info,
6545  evaluation
6546  );
6547 #endif
6548  TIMING_END_AND_PRINT (fac_fq_reconstruction, "time to reconstruct0: ");
6549 #ifdef HAVE_FLINT
6550  if (result.length() == nmod_mat_ncols (FLINTN))
6551  {
6552  nmod_mat_clear (FLINTN);
6553 #else
6554  if (result.length() == NTLN.NumCols())
6555  {
6556 #endif
6557  delete [] liftPre;
6558  delete [] factorsFoundIndex;
6559  return result;
6560  }
6561  }
6562 
6563  int i= sizeOfLiftPre - 1;
6564  int dummy= 1;
6565  if (sizeOfLiftPre > 1 && sizeOfLiftPre < 30)
6566  {
6567  while (i > 0)
6568  {
6569  if (l < liftPre[i-1] + 1)
6570  {
6571  factors.insert (LCF);
6572  TIMING_START (fac_fq_lift);
6573  henselLiftResume12 (F, factors, l, liftPre[i-1] + 1, Pi, diophant, M);
6574  TIMING_END_AND_PRINT (fac_fq_lift, "time to lift in reconstruction1: ");
6575  l= liftPre[i-1] + 1;
6576  }
6577  else
6578  {
6579  i--;
6580  if (i != 0)
6581  continue;
6582  }
6583  TIMING_START (fac_fq_reconstruction);
6584 #ifdef HAVE_FLINT
6585  extReconstructionTry (result, bufF, factors, l, factorsFound,
6586  factorsFoundIndex, FLINTN, beenInThres, info,
6587  evaluation
6588  );
6589 #else
6590  extReconstructionTry (result, bufF, factors, l, factorsFound,
6591  factorsFoundIndex, NTLN, beenInThres, info,
6592  evaluation
6593  );
6594 #endif
6595  TIMING_END_AND_PRINT (fac_fq_reconstruction, "time to reconstruct1: ");
6596 #ifdef HAVE_FLINT
6597  if (result.length() == nmod_mat_ncols (FLINTN))
6598  {
6599  nmod_mat_clear (FLINTN);
6600 #else
6601  if (result.length() == NTLN.NumCols())
6602  {
6603 #endif
6604  delete [] liftPre;
6605  delete [] factorsFoundIndex;
6606  return result;
6607  }
6608  i--;
6609  }
6610  }
6611  else
6612  {
6613  i= 1;
6614  while ((degree (F,y)/4+1)*i + 4 <= smallFactorDeg)
6615  i++;
6616  while (i < 5)
6617  {
6618  dummy= tmin (degree (F,y)+1, (degree (F,y)/4+1)*i+4);
6619  if (l < dummy)
6620  {
6621  factors.insert (LCF);
6622  TIMING_START (fac_fq_lift);
6623  henselLiftResume12 (F, factors, l, dummy, Pi, diophant, M);
6624  TIMING_END_AND_PRINT (fac_fq_lift, "time to lift in reconstruction2: ");
6625  l= dummy;
6626  }
6627  else
6628  {
6629  i++;
6630  if (i < 5)
6631  continue;
6632  }
6633  TIMING_START (fac_fq_reconstruction);
6634 #ifdef HAVE_FLINT
6635  extReconstructionTry (result, bufF, factors, l, factorsFound,
6636  factorsFoundIndex, FLINTN, beenInThres, info,
6637  evaluation
6638  );
6639 #else
6640  extReconstructionTry (result, bufF, factors, l, factorsFound,
6641  factorsFoundIndex, NTLN, beenInThres, info,
6642  evaluation
6643  );
6644 #endif
6645  TIMING_END_AND_PRINT (fac_fq_reconstruction, "time to reconstruct2: ");
6646 #ifdef HAVE_FLINT
6647  if (result.length() == nmod_mat_ncols (FLINTN))
6648  {
6649  nmod_mat_clear (FLINTN);
6650 #else
6651  if (result.length() == NTLN.NumCols())
6652  {
6653 #endif
6654  delete [] liftPre;
6655  delete [] factorsFoundIndex;
6656  return result;
6657  }
6658  i++;
6659  }
6660  }
6661 
6662 #ifdef HAVE_FLINT
6663  nmod_mat_clear (FLINTN);
6664 #endif
6665  delete [] liftPre;
6666  delete [] factorsFoundIndex;
6667  return result;
6668 }
6669 
6670 CFList
6672  degPat, CanonicalForm& H, CFList& diophant, CFArray& Pi,
6673  CFMatrix& M, bool& success, int d, const CanonicalForm& eval
6674  )
6675 {
6676  CanonicalForm F= G;
6677  CFList bufUniFactors= uniFactors;
6678  bufUniFactors.insert (LC (F, 1));
6679  int smallFactorDeg= d;
6680  DegreePattern degs= degPat;
6681  henselLift12 (F, bufUniFactors, smallFactorDeg, Pi, diophant, M);
6682  int adaptedLiftBound;
6683  success= false;
6684  int * factorsFoundIndex= new int [uniFactors.length()];
6685  for (int i= 0; i < uniFactors.length(); i++)
6686  factorsFoundIndex [i]= 0;
6687  CFList earlyFactors;
6688  earlyFactorDetection (earlyFactors, F, bufUniFactors, adaptedLiftBound,
6689  factorsFoundIndex, degs, success, smallFactorDeg, eval);
6690  delete [] factorsFoundIndex;
6691  if (degs.getLength() == 1)
6692  {
6693  degPat= degs;
6694  return earlyFactors;
6695  }
6696  if (success)
6697  {
6698  H= F;
6699  return earlyFactors;
6700  }
6701  int sizeOldF= size (G);
6702  if (size (F) < sizeOldF)
6703  {
6704  H= F;
6705  success= true;
6706  return earlyFactors;
6707  }
6708  else
6709  {
6710  uniFactors= bufUniFactors;
6711  return CFList();
6712  }
6713 }
6714 
6715 CFList
6717  degPat, CanonicalForm& H, CFList& diophant, CFArray& Pi,
6718  CFMatrix& M, bool& success, int d, const CanonicalForm&
6719  evaluation, const ExtensionInfo& info
6720  )
6721 {
6722  CanonicalForm F= G;
6723  CFList bufUniFactors= uniFactors;
6724  bufUniFactors.insert (LC (F, 1));
6725  int smallFactorDeg= d;
6726  DegreePattern degs= degPat;
6727  henselLift12 (F, bufUniFactors, smallFactorDeg, Pi, diophant, M);
6728  int adaptedLiftBound;
6729  success= false;
6730  int * factorsFoundIndex= new int [uniFactors.length()];
6731  for (int i= 0; i < uniFactors.length(); i++)
6732  factorsFoundIndex [i]= 0;
6733  CFList earlyFactors;
6734  extEarlyFactorDetection (earlyFactors, F, bufUniFactors, adaptedLiftBound,
6735  factorsFoundIndex, degs, success, info, evaluation,
6736  smallFactorDeg);
6737  delete [] factorsFoundIndex;
6738  if (degs.getLength() == 1)
6739  {
6740  degPat= degs;
6741  return earlyFactors;
6742  }
6743  if (success)
6744  {
6745  H= F;
6746  return earlyFactors;
6747  }
6748  Variable y= F.mvar();
6749  int sizeOldF= size (G);
6750  if (size (F) < sizeOldF)
6751  {
6752  H= F;
6753  success= true;
6754  return earlyFactors;
6755  }
6756  else
6757  {
6758  uniFactors= bufUniFactors;
6759  return CFList();
6760  }
6761 }
6762 
6763 CFList
6764 henselLiftAndLatticeRecombi (const CanonicalForm& G, const CFList& uniFactors,
6765  const Variable& alpha, const DegreePattern& degPat,
6766  bool symmetric, const CanonicalForm& eval
6767  )
6768 {
6769  DegreePattern degs= degPat;
6770  CanonicalForm F= G;
6771  CanonicalForm LCF= LC (F, 1);
6772  Variable y= F.mvar();
6773  Variable x= Variable (1);
6774  int d;
6775  bool isIrreducible= false;
6776  int* bounds= computeBounds (F, d, isIrreducible);
6777  if (isIrreducible)
6778  {
6779  delete [] bounds;
6780  return CFList (G);
6781  }
6782  int minBound= bounds[0];
6783  for (int i= 1; i < d; i++)
6784  {
6785  if (bounds[i] != 0)
6786  minBound= tmin (minBound, bounds[i]);
6787  }
6788 
6789  CFList bufUniFactors= uniFactors;
6790  CFArray Pi;
6791  CFList diophant;
6792  int liftBound= 2*totaldegree (F) - 1;
6793  CFMatrix M= CFMatrix (liftBound, bufUniFactors.length());
6794 
6795  CFList smallFactors;
6796  CanonicalForm H;
6797  bool success= false;
6798  smallFactors= sieveSmallFactors (F, bufUniFactors, degs, H, diophant, Pi, M,
6799  success, minBound + 1, eval
6800  );
6801 
6802  if (smallFactors.length() > 0)
6803  {
6804  if (smallFactors.length() == 1)
6805  {
6806  if (smallFactors.getFirst() == F)
6807  {
6808  delete [] bounds;
6809  return CFList (G (y-eval,y));
6810  }
6811  }
6812  if (degs.getLength() <= 1)
6813  {
6814  delete [] bounds;
6815  return smallFactors;
6816  }
6817  }
6818 
6819  int index;
6821  for (CFListIterator i= smallFactors; i.hasItem(); i++)
6822  {
6823  index= 1;
6824  tmp1= mod (i.getItem(),y-eval);
6825  tmp1 /= Lc (tmp1);
6826  for (CFListIterator j= bufUniFactors; j.hasItem(); j++, index++)
6827  {
6828  tmp2= mod (j.getItem(), y);
6829  tmp2 /= Lc (tmp2);
6830  if (tmp1 == tmp2)
6831  {
6832  index++;
6833  j.remove(index);
6834  break;
6835  }
6836  }
6837  }
6838 
6839  if (bufUniFactors.isEmpty())
6840  {
6841  delete [] bounds;
6842  return smallFactors;
6843  }
6844 
6845  if (success)
6846  {
6847  F= H;
6848  delete [] bounds;
6849  bounds= computeBounds (F, d, isIrreducible);
6850  if (isIrreducible)
6851  {
6852  smallFactors.append (F (y-eval,y));
6853  delete [] bounds;
6854  return smallFactors;
6855  }
6856  LCF= LC (F, 1);
6857 
6858  minBound= bounds[0];
6859  for (int i= 1; i < d; i++)
6860  {
6861  if (bounds[i] != 0)
6862  minBound= tmin (minBound, bounds[i]);
6863  }
6864  Pi= CFArray();
6865  diophant= CFList();
6866  liftBound= 2*totaldegree (F) - 1;
6867  M= CFMatrix (liftBound, bufUniFactors.length());
6868  DegreePattern bufDegs= DegreePattern (bufUniFactors);
6869  degs.intersect (bufDegs);
6870  degs.refine();
6871  if (degs.getLength() <= 1)
6872  {
6873  smallFactors.append (F (y-eval,y));
6874  delete [] bounds;
6875  return smallFactors;
6876  }
6877  }
6878 
6879  bool reduceFq2Fp= (degree (F) > getCharacteristic());
6880  bufUniFactors.insert (LCF);
6881  int l= 1;
6882 
6883 #ifdef HAVE_FLINT
6884  nmod_mat_t FLINTN;
6885 #else
6887  {
6889  zz_p::init (getCharacteristic());
6890  }
6891  mat_zz_p NTLN;
6892 #endif
6893 
6894  if (alpha.level() != 1)
6895  {
6896  zz_pX NTLMipo= convertFacCF2NTLzzpX (getMipo (alpha));
6897  zz_pE::init (NTLMipo);
6898  }
6899  mat_zz_pE NTLNe;
6900  if (alpha.level() == 1)
6901  {
6902 #ifdef HAVE_FLINT
6903  nmod_mat_init (FLINTN, bufUniFactors.length()-1, bufUniFactors.length()-1, getCharacteristic());
6904  for (long i= bufUniFactors.length()-2; i >= 0; i--)
6905  nmod_mat_entry (FLINTN, i, i)= 1;
6906 #else
6907  ident (NTLN, bufUniFactors.length() - 1);
6908 #endif
6909  }
6910  else
6911  {
6912  if (reduceFq2Fp)
6913 #ifdef HAVE_FLINT
6914  {
6915  nmod_mat_init (FLINTN, bufUniFactors.length()-1, bufUniFactors.length()-1, getCharacteristic());
6916  for (long i= bufUniFactors.length()-2; i >= 0; i--)
6917  nmod_mat_entry (FLINTN, i, i)= 1;
6918  }
6919 #else
6920  ident (NTLN, bufUniFactors.length() - 1);
6921 #endif
6922  else
6923  ident (NTLNe, bufUniFactors.length() - 1);
6924  }
6925  bool irreducible= false;
6926  CFArray bufQ= CFArray (bufUniFactors.length() - 1);
6927 
6928  int oldL;
6929  TIMING_START (fac_fq_till_reduced);
6930  if (success)
6931  {
6932  int start= 0;
6933  if (alpha.level() == 1)
6934  oldL= liftAndComputeLattice (F, bounds, d, start, liftBound, minBound,
6935 #ifdef HAVE_FLINT
6936  bufUniFactors, FLINTN, diophant, M, Pi, bufQ,
6937 #else
6938  bufUniFactors, NTLN, diophant, M, Pi, bufQ,
6939 #endif
6940  irreducible
6941  );
6942  else
6943  {
6944  if (reduceFq2Fp)
6945  oldL= liftAndComputeLatticeFq2Fp (F, bounds, d, start, liftBound,
6946 #ifdef HAVE_FLINT
6947  minBound, bufUniFactors, FLINTN,
6948 #else
6949  minBound, bufUniFactors, NTLN,
6950 #endif
6951  diophant, M, Pi, bufQ, irreducible,
6952  alpha
6953  );
6954  else
6955  oldL= liftAndComputeLattice (F, bounds, d, start, liftBound, minBound,
6956  bufUniFactors, NTLNe, diophant, M, Pi, bufQ,
6957  irreducible
6958  );
6959  }
6960  }
6961  else
6962  {
6963  if (alpha.level() == 1)
6964  {
6965  oldL= liftAndComputeLattice (F, bounds, d, minBound + 1, liftBound,
6966 #ifdef HAVE_FLINT
6967  minBound, bufUniFactors, FLINTN, diophant, M,
6968 #else
6969  minBound, bufUniFactors, NTLN, diophant, M,
6970 #endif
6971  Pi, bufQ, irreducible
6972  );
6973  }
6974  else
6975  {
6976  if (reduceFq2Fp)
6977  oldL= liftAndComputeLatticeFq2Fp (F, bounds, d, minBound + 1,
6978  liftBound, minBound, bufUniFactors,
6979 #ifdef HAVE_FLINT
6980  FLINTN, diophant, M, Pi, bufQ,
6981 #else
6982  NTLN, diophant, M, Pi, bufQ,
6983 #endif
6984  irreducible, alpha
6985  );
6986  else
6987  oldL= liftAndComputeLattice (F, bounds, d, minBound + 1, liftBound,
6988  minBound, bufUniFactors, NTLNe, diophant,
6989  M, Pi, bufQ, irreducible
6990  );
6991  }
6992  }
6993 
6994  TIMING_END_AND_PRINT (fac_fq_till_reduced,
6995  "time to compute a reduced lattice: ");
6996  bufUniFactors.removeFirst();
6997  if (oldL > liftBound)
6998  {
6999 #ifdef HAVE_FLINT
7000  if (alpha.level() == 1 || (alpha.level() != 1 && reduceFq2Fp))
7001  nmod_mat_clear (FLINTN);
7002 #endif
7003  delete [] bounds;
7004  return Union (smallFactors,
7005  factorRecombination (bufUniFactors, F,
7006  power (y, degree (F) + 1),
7007  degs, eval, 1, bufUniFactors.length()/2
7008  )
7009  );
7010  }
7011 
7012  l= oldL;
7013  if (irreducible)
7014  {
7015 #ifdef HAVE_FLINT
7016  if (alpha.level() == 1 || (alpha.level() != 1 && reduceFq2Fp))
7017  nmod_mat_clear (FLINTN);
7018 #endif
7019  delete [] bounds;
7020  return Union (CFList (F(y-eval,y)), smallFactors);
7021  }
7022 
7023  CanonicalForm yToL= power (y,l);
7024 
7025  CFList result;
7026  if (l >= degree (F) + 1)
7027  {
7028  int * factorsFoundIndex;
7029  if (alpha.level() == 1 || (alpha.level() != 1 && reduceFq2Fp))
7030  {
7031 #ifdef HAVE_FLINT
7032  factorsFoundIndex= new int [nmod_mat_ncols (FLINTN)];
7033  for (long i= 0; i < nmod_mat_ncols (FLINTN); i++)
7034 #else
7035  factorsFoundIndex= new int [NTLN.NumCols()];
7036  for (long i= 0; i < NTLN.NumCols(); i++)
7037 #endif
7038  factorsFoundIndex[i]= 0;
7039  }
7040  else
7041  {
7042  factorsFoundIndex= new int [NTLNe.NumCols()];
7043  for (long i= 0; i < NTLNe.NumCols(); i++)
7044  factorsFoundIndex[i]= 0;
7045  }
7046  int factorsFound= 0;
7047  CanonicalForm bufF= F;
7048  if (alpha.level() == 1 || (alpha.level() != 1 && reduceFq2Fp))
7049  reconstructionTry (result, bufF, bufUniFactors, degree (F) + 1,
7050 #ifdef HAVE_FLINT
7051  factorsFound, factorsFoundIndex, FLINTN, eval, false
7052 #else
7053  factorsFound, factorsFoundIndex, NTLN, eval, false
7054 #endif
7055  );
7056  else
7057  reconstructionTry (result, bufF, bufUniFactors, degree (F) + 1,
7058  factorsFound, factorsFoundIndex, NTLNe, eval, false
7059  );
7060  if (alpha.level() == 1 || (alpha.level() != 1 && reduceFq2Fp))
7061  {
7062 #ifdef HAVE_FLINT
7063  if (result.length() == nmod_mat_ncols (FLINTN))
7064  {
7065  if (alpha.level() == 1 || (alpha.level() != 1 && reduceFq2Fp))
7066  nmod_mat_clear (FLINTN);
7067 #else
7068  if (result.length() == NTLN.NumCols())
7069  {
7070 #endif
7071  delete [] factorsFoundIndex;
7072  delete [] bounds;
7073  return Union (result, smallFactors);
7074  }
7075  }
7076  else
7077  {
7078  if (result.length() == NTLNe.NumCols())
7079  {
7080  delete [] factorsFoundIndex;
7081  delete [] bounds;
7082  return Union (result, smallFactors);
7083  }
7084  }
7085  delete [] factorsFoundIndex;
7086  }
7087  if (l >= liftBound)
7088  {
7089  int * factorsFoundIndex;
7090  if (alpha.level() == 1 || (alpha.level() != 1 && reduceFq2Fp))
7091  {
7092 #ifdef HAVE_FLINT
7093  factorsFoundIndex= new int [nmod_mat_ncols (FLINTN)];
7094  for (long i= 0; i < nmod_mat_ncols (FLINTN); i++)
7095 #else
7096  factorsFoundIndex= new int [NTLN.NumCols()];
7097  for (long i= 0; i < NTLN.NumCols(); i++)
7098 #endif
7099  factorsFoundIndex[i]= 0;
7100  }
7101  else
7102  {
7103  factorsFoundIndex= new int [NTLNe.NumCols()];
7104  for (long i= 0; i < NTLNe.NumCols(); i++)
7105  factorsFoundIndex[i]= 0;
7106  }
7107  CanonicalForm bufF= F;
7108  int factorsFound= 0;
7109  if (alpha.level() == 1 || (alpha.level() != 1 && reduceFq2Fp))
7110  reconstructionTry (result, bufF, bufUniFactors, degree (F) + 1,
7111 #ifdef HAVE_FLINT
7112  factorsFound, factorsFoundIndex, FLINTN, eval, false
7113 #else
7114  factorsFound, factorsFoundIndex, NTLN, eval, false
7115 #endif
7116  );
7117  else
7118  reconstructionTry (result, bufF, bufUniFactors, degree (F) + 1,
7119  factorsFound, factorsFoundIndex, NTLNe, eval, false
7120  );
7121  if (alpha.level() == 1 || (alpha.level() != 1 && reduceFq2Fp))
7122  {
7123 #ifdef HAVE_FLINT
7124  if (result.length() == nmod_mat_ncols(FLINTN))
7125  {
7126  nmod_mat_clear (FLINTN);
7127 #else
7128  if (result.length() == NTLN.NumCols())
7129  {
7130 #endif
7131  delete [] factorsFoundIndex;
7132  delete [] bounds;
7133  return Union (result, smallFactors);
7134  }
7135  }
7136  else
7137  {
7138  if (result.length() == NTLNe.NumCols())
7139  {
7140  delete [] factorsFoundIndex;
7141  delete [] bounds;
7142  return Union (result, smallFactors);
7143  }
7144  }
7145  delete [] factorsFoundIndex;
7146  }
7147 
7148  result= CFList();
7149  bool beenInThres= false;
7150  int thres= 100;
7151  if (l <= thres)
7152  {
7153  if (alpha.level() == 1 || (alpha.level() != 1 && reduceFq2Fp))
7154  {
7155 #ifdef HAVE_FLINT
7156  if (nmod_mat_ncols (FLINTN) < bufUniFactors.length())
7157  {
7158  refineAndRestartLift (F, FLINTN, liftBound, l, bufUniFactors, M, Pi,
7159 #else
7160  if (NTLN.NumCols() < bufUniFactors.length())
7161  {
7162  refineAndRestartLift (F, NTLN, liftBound, l, bufUniFactors, M, Pi,
7163 #endif
7164  diophant
7165  );
7166  beenInThres= true;
7167  }
7168  }
7169  else
7170  {
7171  if (NTLNe.NumCols() < bufUniFactors.length())
7172  {
7173  refineAndRestartLift (F, NTLNe, liftBound, l, bufUniFactors, M, Pi,
7174  diophant
7175  );
7176  beenInThres= true;
7177  }
7178  }
7179  }
7180 
7181  CanonicalForm bufF= F;
7182  int factorsFound= 0;
7183  if (alpha.level() == 1 || (alpha.level() != 1 && reduceFq2Fp))
7184  {
7185 #ifdef HAVE_FLINT
7186  result= earlyReconstructionAndLifting (F, FLINTN, bufF, bufUniFactors, l,
7187 #else
7188  result= earlyReconstructionAndLifting (F, NTLN, bufF, bufUniFactors, l,
7189 #endif
7190  factorsFound, beenInThres, M, Pi,
7191  diophant, symmetric, eval
7192  );
7193 
7194 #ifdef HAVE_FLINT
7195  if (result.length() == nmod_mat_ncols (FLINTN))
7196  {
7197  nmod_mat_clear (FLINTN);
7198 #else
7199  if (result.length() == NTLN.NumCols())
7200  {
7201 #endif
7202  delete [] bounds;
7203  return Union (result, smallFactors);
7204  }
7205  }
7206  else
7207  {
7208  result= earlyReconstructionAndLifting (F, NTLNe, bufF, bufUniFactors, l,
7209  factorsFound, beenInThres, M, Pi,
7210  diophant, symmetric, eval
7211  );
7212 
7213  if (result.length() == NTLNe.NumCols())
7214  {
7215  delete [] bounds;
7216  return Union (result, smallFactors);
7217  }
7218  }
7219 
7220  if (result.length() > 0)
7221  {
7222  if (beenInThres)
7223  {
7224  int index;
7225  for (CFListIterator i= result; i.hasItem(); i++)
7226  {
7227  index= 1;
7228  tmp1= mod (i.getItem(), y-eval);
7229  tmp1 /= Lc (tmp1);
7230  for (CFListIterator j= bufUniFactors; j.hasItem(); j++, index++)
7231  {
7232  tmp2= mod (j.getItem(), y);
7233  tmp2 /= Lc (tmp2);
7234  if (tmp1 == tmp2)
7235  {
7236  index++;
7237  j.remove(index);
7238  break;
7239  }
7240  }
7241  }
7242  }
7243  else
7244  {
7245  int * zeroOne;
7246  long numCols, numRows;
7247  if (alpha.level() == 1 || (alpha.level() != 1 && reduceFq2Fp))
7248  {
7249 #ifdef HAVE_FLINT
7250  numCols= nmod_mat_ncols (FLINTN);
7251  numRows= nmod_mat_nrows (FLINTN);
7252  zeroOne= extractZeroOneVecs (FLINTN);
7253 #else
7254  numCols= NTLN.NumCols();
7255  numRows= NTLN.NumRows();
7256  zeroOne= extractZeroOneVecs (NTLN);
7257 #endif
7258  }
7259  else
7260  {
7261  numCols= NTLNe.NumCols();
7262  numRows= NTLNe.NumRows();
7263  zeroOne= extractZeroOneVecs (NTLNe);
7264  }
7265  CFList bufBufUniFactors= bufUniFactors;
7266  CFListIterator iter, iter2;
7268  CFList factorsConsidered;
7269  CanonicalForm tmp;
7270  for (int i= 0; i < numCols; i++)
7271  {
7272  if (zeroOne [i] == 0)
7273  continue;
7274  iter= bufUniFactors;
7275  buf= 1;
7276  factorsConsidered= CFList();
7277  for (int j= 0; j < numRows; j++, iter++)
7278  {
7279  if (alpha.level() == 1 || (alpha.level() != 1 && reduceFq2Fp))
7280  {
7281 #ifdef HAVE_FLINT
7282  if (!(nmod_mat_entry (FLINTN, j,i) == 0))
7283 #else
7284  if (!IsZero (NTLN (j + 1,i + 1)))
7285 #endif
7286  {
7287  factorsConsidered.append (iter.getItem());
7288  buf *= mod (iter.getItem(), y);
7289  }
7290  }
7291  else
7292  {
7293  if (!IsZero (NTLNe (j + 1,i + 1)))
7294  {
7295  factorsConsidered.append (iter.getItem());
7296  buf *= mod (iter.getItem(), y);
7297  }
7298  }
7299  }
7300  buf /= Lc (buf);
7301  for (iter2= result; iter2.hasItem(); iter2++)
7302  {
7303  tmp= mod (iter2.getItem(), y-eval);
7304  tmp /= Lc (tmp);
7305  if (tmp == buf)
7306  {
7307  bufBufUniFactors= Difference (bufBufUniFactors, factorsConsidered);
7308  break;
7309  }
7310  }
7311  }
7312  bufUniFactors= bufBufUniFactors;
7313  delete [] zeroOne;
7314  }
7315 
7316  int oldNumCols;
7317  CFList resultBufF;
7318  irreducible= false;
7319 
7320  if (alpha.level() == 1)
7321  {
7322 #ifdef HAVE_FLINT
7323  oldNumCols= nmod_mat_ncols (FLINTN);
7324 #else
7325  oldNumCols= NTLN.NumCols();
7326 #endif
7327  resultBufF= increasePrecision (bufF, bufUniFactors, factorsFound,
7328  oldNumCols, oldL, l, eval
7329  );
7330  }
7331  else
7332  {
7333  if (reduceFq2Fp)
7334  {
7335 #ifdef HAVE_FLINT
7336  oldNumCols= nmod_mat_ncols (FLINTN);
7337 #else
7338  oldNumCols= NTLN.NumCols();
7339 #endif
7340 
7341  resultBufF= increasePrecisionFq2Fp (bufF, bufUniFactors, factorsFound,
7342  oldNumCols, oldL, alpha, l, eval
7343  );
7344  }
7345  else
7346  {
7347  oldNumCols= NTLNe.NumCols();
7348 
7349  resultBufF= increasePrecision (bufF, bufUniFactors, factorsFound,
7350  oldNumCols, oldL, alpha, l, eval
7351  );
7352  }
7353  }
7354 
7355  if (bufUniFactors.isEmpty() || degree (bufF) <= 0)
7356  {
7357 #ifdef HAVE_FLINT
7358  if (alpha.level() == 1 || (alpha.level() != 1 && reduceFq2Fp))
7359  nmod_mat_clear (FLINTN);
7360 #endif
7361  delete [] bounds;
7362  result= Union (resultBufF, result);
7363  return Union (result, smallFactors);
7364  }
7365 
7366  for (CFListIterator i= bufUniFactors; i.hasItem(); i++)
7367  i.getItem()= mod (i.getItem(), y);
7368 
7369  result= Union (result, resultBufF);
7370  result= Union (result, smallFactors);
7371  delete [] bounds;
7372  DegreePattern bufDegs= DegreePattern (bufUniFactors);
7373  degs.intersect (bufDegs);
7374  degs.refine();
7375  if (degs.getLength() == 1 || bufUniFactors.length() == 1)
7376  {
7377 #ifdef HAVE_FLINT
7378  if (alpha.level() == 1 || (alpha.level() != 1 && reduceFq2Fp))
7379  nmod_mat_clear (FLINTN);
7380 #endif
7381  result.append (bufF (y-eval,y));
7382  return result;
7383  }
7384 #ifdef HAVE_FLINT
7385  if (alpha.level() == 1 || (alpha.level() != 1 && reduceFq2Fp))
7386  nmod_mat_clear (FLINTN);
7387 #endif
7388  return Union (result, henselLiftAndLatticeRecombi (bufF, bufUniFactors,
7389  alpha, degs, symmetric,
7390  eval
7391  )
7392  );
7393  }
7394 
7395  if (l < liftBound)
7396  {
7397  if (alpha.level() == 1)
7398  {
7399  result=increasePrecision (F, bufUniFactors, oldL, l, d, bounds, bufQ,
7400 #ifdef HAVE_FLINT
7401  FLINTN, eval
7402 #else
7403  NTLN, eval
7404 #endif
7405  );
7406  }
7407  else
7408  {
7409  if (reduceFq2Fp)
7410  {
7411  result=increasePrecisionFq2Fp (F, bufUniFactors, oldL, l, d, bounds,
7412 #ifdef HAVE_FLINT
7413  bufQ, FLINTN, alpha, eval
7414 #else
7415  bufQ, NTLN, alpha, eval
7416 #endif
7417  );
7418  }
7419  else
7420  {
7421  result=increasePrecision (F, bufUniFactors, oldL, l, d, bounds, bufQ,
7422  NTLNe, eval
7423  );
7424  }
7425  }
7426  if (alpha.level() == 1 || (alpha.level() != 1 && reduceFq2Fp))
7427  {
7428 #ifdef HAVE_FLINT
7429  if (result.length()== nmod_mat_ncols (FLINTN))
7430  {
7431  nmod_mat_clear (FLINTN);
7432 #else
7433  if (result.length()== NTLN.NumCols())
7434  {
7435 #endif
7436  delete [] bounds;
7437  result= Union (result, smallFactors);
7438  return result;
7439  }
7440  }
7441  else
7442  {
7443  if (result.length()== NTLNe.NumCols())
7444  {
7445  delete [] bounds;
7446  result= Union (result, smallFactors);
7447  return result;
7448  }
7449  }
7450 
7451  if (result.isEmpty())
7452  {
7453  if (alpha.level() == 1)
7454  result= furtherLiftingAndIncreasePrecision (F,bufUniFactors, l,
7455 #ifdef HAVE_FLINT
7456  liftBound,d,bounds,FLINTN,
7457 #else
7458  liftBound, d, bounds, NTLN,
7459 #endif
7460  diophant, M, Pi, bufQ, eval
7461  );
7462  else
7463  {
7464  if (reduceFq2Fp)
7465  result= furtherLiftingAndIncreasePrecisionFq2Fp (F,bufUniFactors, l,
7466  liftBound, d, bounds,
7467 #ifdef HAVE_FLINT
7468  FLINTN, diophant, M,
7469 #else
7470  NTLN, diophant, M,
7471 #endif
7472  Pi, bufQ, alpha, eval
7473  );
7474  else
7475  result= furtherLiftingAndIncreasePrecision (F,bufUniFactors, l,
7476  liftBound, d, bounds,
7477  NTLNe, diophant, M,
7478  Pi, bufQ, eval
7479  );
7480  }
7481 
7482  if (alpha.level() == 1 || (alpha.level() != 1 && reduceFq2Fp))
7483  {
7484 #ifdef HAVE_FLINT
7485  if (result.length() == nmod_mat_ncols (FLINTN))
7486  {
7487  nmod_mat_clear (FLINTN);
7488 #else
7489  if (result.length() == NTLN.NumCols())
7490  {
7491 #endif
7492  delete [] bounds;
7493  result= Union (result, smallFactors);
7494  return result;
7495  }
7496  }
7497  else
7498  {
7499  if (result.length() == NTLNe.NumCols())
7500  {
7501  delete [] bounds;
7502  result= Union (result, smallFactors);
7503  return result;
7504  }
7505  }
7506  }
7507  }
7508 
7509  DEBOUTLN (cerr, "lattice recombination failed");
7510 
7511  DegreePattern bufDegs= DegreePattern (bufUniFactors);
7512  degs.intersect (bufDegs);
7513  degs.refine();
7514 
7515  delete [] bounds;
7516  bounds= computeBounds (F, d, isIrreducible);
7517 #ifdef HAVE_FLINT
7518  if (alpha.level() == 1 || (alpha.level() != 1 && reduceFq2Fp))
7519  nmod_mat_clear (FLINTN);
7520 #endif
7521  if (isIrreducible)
7522  {
7523  delete [] bounds;
7524  result= Union (result, smallFactors);
7525  result.append (F (y-eval,y));
7526  return result;
7527  }
7528  minBound= bounds[0];
7529  for (int i= 1; i < d; i++)
7530  {
7531  if (bounds[i] != 0)
7532  minBound= tmin (minBound, bounds[i]);
7533  }
7534 
7535  if (minBound > 16 || result.length() == 0)
7536  {
7537  result= Union (result, smallFactors);
7538  CanonicalForm MODl= power (y, degree (F) + 1);
7539  delete [] bounds;
7540  return Union (result, factorRecombination (bufUniFactors, F, MODl, degs,
7541  eval, 1, bufUniFactors.length()/2
7542  )
7543  );
7544  }
7545  else
7546  {
7547  result= Union (result, smallFactors);
7548  for (CFListIterator i= bufUniFactors; i.hasItem(); i++)
7549  i.getItem()= mod (i.getItem(), y);
7550  delete [] bounds;
7551  return Union (result, henselLiftAndLatticeRecombi (F, bufUniFactors, alpha,
7552  degs,symmetric, eval
7553  )
7554  );
7555  }
7556 }
7557 
7559 init4ext (const ExtensionInfo& info, const CanonicalForm& evaluation,
7560  int& degMipo
7561  )
7562 {
7563  bool GF= (CFFactory::gettype() == GaloisFieldDomain);
7564  Variable alpha= info.getAlpha();
7565  if (GF)
7566  {
7567  degMipo= getGFDegree();
7568  CanonicalForm GFMipo= gf_mipo;
7570  GFMipo.mapinto();
7571  alpha= rootOf (GFMipo);
7572  setCharacteristic (getCharacteristic(), degMipo, info.getGFName());
7573  }
7574  else
7575  {
7576  alpha= info.getAlpha();
7577  degMipo= degree (getMipo (alpha));
7578  }
7579 
7580  Variable gamma;
7581  CanonicalForm primElemAlpha, imPrimElemAlpha;
7582  if ((!GF && evaluation != alpha) || (GF && evaluation != getGFGenerator()))
7583  {
7584  CanonicalForm bufEvaluation;
7585  if (GF)
7586  {
7588  bufEvaluation= GF2FalphaRep (evaluation, alpha);
7589  }
7590  else
7591  bufEvaluation= evaluation;
7592  CanonicalForm mipo= findMinPoly (bufEvaluation, alpha);
7593  gamma= rootOf (mipo);
7594  Variable V_buf;
7595  bool fail= false;
7596  primElemAlpha= primitiveElement (alpha, V_buf, fail);
7597  imPrimElemAlpha= map (primElemAlpha, alpha, bufEvaluation, gamma);
7598 
7599  if (GF)
7600  setCharacteristic (getCharacteristic(), degMipo, info.getGFName());
7601  }
7602  else
7603  gamma= alpha;
7604  ExtensionInfo info2= ExtensionInfo (alpha, gamma, primElemAlpha,
7605  imPrimElemAlpha, 1, info.getGFName(), true
7606  );
7607 
7608  return info2;
7609 }
7610 
7611 CFList
7613  const ExtensionInfo& extInfo, const
7614  DegreePattern& degPat, const CanonicalForm& eval
7615  )
7616 {
7617  CanonicalForm evaluation= eval;
7618  ExtensionInfo info= extInfo;
7619  Variable alpha;
7620  DegreePattern degs= degPat;
7621  CanonicalForm F= G;
7622  Variable x= Variable (1);
7623  Variable y= F.mvar();
7624  CFList bufUniFactors= uniFactors;
7625 
7626 
7627  int degMipo;
7628  ExtensionInfo info2= init4ext (info, evaluation, degMipo);
7629 
7630  CFList source, dest;
7631  CanonicalForm LCF= LC (F, 1);
7632 
7633  int d;
7634  bool isIrreducible= false;
7635  int* bounds= computeBounds (F, d, isIrreducible);
7636  if (isIrreducible)
7637  {
7638  delete [] bounds;
7639  CFList source, dest;
7640  CanonicalForm tmp= G (y - evaluation, y);
7641  tmp= mapDown (tmp, info, source, dest);
7642  return CFList (tmp);
7643  }
7644  int minBound= bounds[0];
7645  for (int i= 1; i < d; i++)
7646  {
7647  if (bounds[i] != 0)
7648  minBound= tmin (minBound, bounds[i]);
7649  }
7650 
7651 
7652  CFArray Pi;
7653  CFList diophant;
7654  int liftBound= tmax ((2*totaldegree (F) - 1)/degMipo + 1, degree (F) + 1 +
7655  degree (LC (F, 1)));
7656  CFMatrix M= CFMatrix (liftBound, bufUniFactors.length());
7657 
7658  CFList smallFactors;
7659  CanonicalForm H;
7660  bool success= false;
7661  smallFactors= extSieveSmallFactors (F, bufUniFactors, degs, H, diophant, Pi,
7662  M, success, minBound + 1, evaluation, info
7663  );
7664 
7665  if (smallFactors.length() > 0)
7666  {
7667  if (smallFactors.length() == 1)
7668  {
7669  if (smallFactors.getFirst() == F)
7670  {
7671  delete [] bounds;
7672  CFList source, dest;
7673  CanonicalForm tmp= G (y - evaluation, y);
7674  tmp= mapDown (tmp, info, source, dest);
7675  return CFList (tmp);
7676  }
7677  }
7678  if (degs.getLength() <= 1)
7679  {
7680  delete [] bounds;
7681  return smallFactors;
7682  }
7683  }
7684 
7685  int index;
7687  for (CFListIterator i= smallFactors; i.hasItem(); i++)
7688  {
7689  index= 1;
7690  tmp1= mod (i.getItem(), y - evaluation);
7691  tmp1 /= Lc (tmp1);
7692  for (CFListIterator j= bufUniFactors; j.hasItem(); j++, index++)
7693  {
7694  tmp2= mod (j.getItem(), y);
7695  tmp2 /= Lc (tmp2);
7696  if (tmp1 == tmp2)
7697  {
7698  index++;
7699  j.remove(index);
7700  break;
7701  }
7702  }
7703  }
7704 
7705  if (bufUniFactors.isEmpty())
7706  {
7707  delete [] bounds;
7708  return smallFactors;
7709  }
7710 
7711  if (success)
7712  {
7713  F= H/Lc(H);
7714  delete [] bounds;
7715  bounds= computeBounds (F, d, isIrreducible);
7716  if (isIrreducible)
7717  {
7718  delete [] bounds;
7719  CFList source, dest;
7720  CanonicalForm tmp= F (y - evaluation, y);
7721  tmp= mapDown (tmp, info, source, dest);
7722  smallFactors.append (tmp);
7723  return smallFactors;
7724  }
7725  LCF= LC (F, 1);
7726 
7727  minBound= bounds[0];
7728  for (int i= 1; i < d; i++)
7729  {
7730  if (bounds[i] != 0)
7731  minBound= tmin (minBound, bounds[i]);
7732  }
7733  Pi= CFArray();
7734  diophant= CFList();
7735  liftBound=tmax ((2*totaldegree (F) - 1)/degMipo + 1, degree (F) + 1 +
7736  degree (LC (F, 1)));
7737  M= CFMatrix (liftBound, bufUniFactors.length());
7738  DegreePattern bufDegs= DegreePattern (bufUniFactors);
7739  degs.intersect (bufDegs);
7740  degs.refine();
7741  if (degs.getLength() <= 1)
7742  {
7743  delete [] bounds;
7744  CFList source, dest;
7745  CanonicalForm tmp= F (y - evaluation, y);
7746  tmp= mapDown (tmp, info, source, dest);
7747  smallFactors.append (tmp);
7748  return smallFactors;
7749  }
7750  }
7751 
7752  bufUniFactors.insert (LCF);
7753  int l= 1;
7754 
7755 #ifdef HAVE_FLINT
7756  nmod_mat_t FLINTN;
7757  nmod_mat_init (FLINTN, bufUniFactors.length()-1, bufUniFactors.length()-1,
7758  getCharacteristic());
7759  for (long i= bufUniFactors.length()-2; i >= 0; i--)
7760  nmod_mat_entry (FLINTN, i, i)= 1;
7761 #else
7763  {
7765  zz_p::init (getCharacteristic());
7766  }
7767  zz_pX NTLMipo;
7768  mat_zz_p NTLN;
7769 
7770  ident (NTLN, bufUniFactors.length() - 1);
7771 #endif
7772  bool irreducible= false;
7773  CFArray bufQ= CFArray (bufUniFactors.length() - 1);
7774 
7775  int oldL;
7776  TIMING_START (fac_fq_till_reduced);
7777  if (success)
7778  {
7779  int start= 0;
7780 #ifdef HAVE_FLINT
7781  oldL= extLiftAndComputeLattice (F, bounds, d, liftBound, minBound, start,
7782  bufUniFactors, FLINTN, diophant,M, Pi, bufQ,
7783  irreducible, evaluation, info2, source, dest
7784  );
7785 #else
7786  oldL= extLiftAndComputeLattice (F, bounds, d, liftBound, minBound, start,
7787  bufUniFactors, NTLN, diophant, M, Pi, bufQ,
7788  irreducible, evaluation, info2, source, dest
7789  );
7790 #endif
7791  }
7792  else
7793  {
7794 #ifdef HAVE_FLINT
7795  oldL= extLiftAndComputeLattice (F, bounds, d, liftBound, minBound,
7796  minBound+1, bufUniFactors, FLINTN, diophant,
7797  M, Pi, bufQ, irreducible, evaluation, info2,
7798  source, dest
7799  );
7800 #else
7801  oldL= extLiftAndComputeLattice (F, bounds, d, liftBound, minBound,
7802  minBound + 1, bufUniFactors, NTLN, diophant,
7803  M, Pi, bufQ, irreducible, evaluation, info2,
7804  source, dest
7805  );
7806 #endif
7807  }
7808  TIMING_END_AND_PRINT (fac_fq_till_reduced,
7809  "time to compute a reduced lattice: ");
7810 
7811  bufUniFactors.removeFirst();
7812  if (oldL > liftBound)
7813  {
7814 #ifdef HAVE_FLINT
7815  nmod_mat_clear (FLINTN);
7816 #endif
7817  delete [] bounds;
7818  return Union (smallFactors, extFactorRecombination
7819  (bufUniFactors, F,
7820  power (y, degree (F) + 1),info,
7821  degs, evaluation, 1, bufUniFactors.length()/2
7822  )
7823  );
7824  }
7825 
7826  l= oldL;
7827  if (irreducible)
7828  {
7829 #ifdef HAVE_FLINT
7830  nmod_mat_clear (FLINTN);
7831 #endif
7832  delete [] bounds;
7833  CFList source, dest;
7834  CanonicalForm tmp= F (y - evaluation, y);
7835  tmp= mapDown (tmp, info, source, dest);
7836  return Union (CFList (tmp), smallFactors);
7837  }
7838 
7839  CanonicalForm yToL= power (y,l);
7840 
7841  CFList result;
7842  if (l >= degree (F) + 1)
7843  {
7844  int * factorsFoundIndex;
7845 
7846 #ifdef HAVE_FLINT
7847  factorsFoundIndex= new int [nmod_mat_ncols (FLINTN)];
7848  for (long i= 0; i < nmod_mat_ncols (FLINTN); i++)
7849 #else
7850  factorsFoundIndex= new int [NTLN.NumCols()];
7851  for (long i= 0; i < NTLN.NumCols(); i++)
7852 #endif
7853  factorsFoundIndex[i]= 0;
7854 
7855  int factorsFound= 0;
7856  CanonicalForm bufF= F;
7857 
7858 #ifdef HAVE_FLINT
7859  extReconstructionTry (result, bufF, bufUniFactors, degree (F) + 1,
7860  factorsFound, factorsFoundIndex, FLINTN, false, info,
7861  evaluation
7862  );
7863 
7864  if (result.length() == nmod_mat_ncols (FLINTN))
7865  {
7866  nmod_mat_clear (FLINTN);
7867 #else
7868  extReconstructionTry (result, bufF, bufUniFactors, degree (F) + 1,
7869  factorsFound, factorsFoundIndex, NTLN, false, info,
7870  evaluation
7871  );
7872 
7873  if (result.length() == NTLN.NumCols())
7874  {
7875 #endif
7876  delete [] factorsFoundIndex;
7877  delete [] bounds;
7878  return Union (result, smallFactors);
7879  }
7880 
7881  delete [] factorsFoundIndex;
7882  }
7883  if (l >= liftBound)
7884  {
7885  int * factorsFoundIndex;
7886 #ifdef HAVE_FLINT
7887  factorsFoundIndex= new int [nmod_mat_ncols (FLINTN)];
7888  for (long i= 0; i < nmod_mat_ncols (FLINTN); i++)
7889 #else
7890  factorsFoundIndex= new int [NTLN.NumCols()];
7891  for (long i= 0; i < NTLN.NumCols(); i++)
7892 #endif
7893  factorsFoundIndex[i]= 0;
7894  CanonicalForm bufF= F;
7895  int factorsFound= 0;
7896 
7897 #ifdef HAVE_FLINT
7898  extReconstructionTry (result, bufF, bufUniFactors, degree (F) + 1,
7899  factorsFound, factorsFoundIndex, FLINTN, false,
7900  info, evaluation
7901  );
7902 
7903  if (result.length() == nmod_mat_ncols (FLINTN))
7904  {
7905  nmod_mat_clear (FLINTN);
7906 #else
7907  extReconstructionTry (result, bufF, bufUniFactors, degree (F) + 1,
7908  factorsFound, factorsFoundIndex, NTLN, false,
7909  info, evaluation
7910  );
7911 
7912  if (result.length() == NTLN.NumCols())
7913  {
7914 #endif
7915  delete [] factorsFoundIndex;
7916  delete [] bounds;
7917  return Union (result, smallFactors);
7918  }
7919  delete [] factorsFoundIndex;
7920  }
7921 
7922  result= CFList();
7923  bool beenInThres= false;
7924  int thres= 100;
7925 #ifdef HAVE_FLINT
7926  if (l <= thres && bufUniFactors.length() > nmod_mat_ncols (FLINTN))
7927  {
7928  refineAndRestartLift (F, FLINTN, 2*totaldegree (F)-1, l, bufUniFactors, M, Pi,
7929  diophant
7930  );
7931 #else
7932  if (l <= thres && bufUniFactors.length() > NTLN.NumCols())
7933  {
7934  refineAndRestartLift (F, NTLN, 2*totaldegree (F)-1, l, bufUniFactors, M, Pi,
7935  diophant
7936  );
7937 #endif
7938  beenInThres= true;
7939  }
7940 
7941 
7942  CanonicalForm bufF= F;
7943  int factorsFound= 0;
7944 
7945 #ifdef HAVE_FLINT
7946  result= extEarlyReconstructionAndLifting (F, FLINTN, bufF, bufUniFactors, l,
7947  factorsFound, beenInThres, M, Pi,
7948  diophant, info, evaluation
7949  );
7950 
7951  if (result.length() == nmod_mat_ncols (FLINTN))
7952  {
7953  nmod_mat_clear (FLINTN);
7954 #else
7955  result= extEarlyReconstructionAndLifting (F, NTLN, bufF, bufUniFactors, l,
7956  factorsFound, beenInThres, M, Pi,
7957  diophant, info, evaluation
7958  );
7959 
7960  if (result.length() == NTLN.NumCols())
7961  {
7962 #endif
7963  delete [] bounds;
7964  return Union (result, smallFactors);
7965  }
7966 
7967  if (result.length() > 0)
7968  {
7969  if (beenInThres)
7970  {
7971  int index;
7972  for (CFListIterator i= result; i.hasItem(); i++)
7973  {
7974  index= 1;
7975  tmp1= mod (i.getItem(), y-evaluation);
7976  tmp1 /= Lc (tmp1);
7977  for (CFListIterator j= bufUniFactors; j.hasItem(); j++, index++)
7978  {
7979  tmp2= mod (j.getItem(), y);
7980  tmp2 /= Lc (tmp2);
7981  if (tmp1 == tmp2)
7982  {
7983  index++;
7984  j.remove(index);
7985  break;
7986  }
7987  }
7988  }
7989  }
7990  else
7991  {
7992 #ifdef HAVE_FLINT
7993  int * zeroOne= extractZeroOneVecs (FLINTN);
7994 #else
7995  int * zeroOne= extractZeroOneVecs (NTLN);
7996 #endif
7997  CFList bufBufUniFactors= bufUniFactors;
7998  CFListIterator iter, iter2;
8000  CFList factorsConsidered;
8001 #ifdef HAVE_FLINT
8002  for (int i= 0; i < nmod_mat_ncols (FLINTN); i++)
8003 #else
8004  for (int i= 0; i < NTLN.NumCols(); i++)
8005 #endif
8006  {
8007  if (zeroOne [i] == 0)
8008  continue;
8009  iter= bufUniFactors;
8010  buf= 1;
8011  factorsConsidered= CFList();
8012 #ifdef HAVE_FLINT
8013  for (int j= 0; j < nmod_mat_nrows (FLINTN); j++, iter++)
8014  {
8015  if (!(nmod_mat_entry (FLINTN, j, i) == 0))
8016 #else
8017  for (int j= 0; j < NTLN.NumRows(); j++, iter++)
8018  {
8019  if (!IsZero (NTLN (j + 1,i + 1)))
8020 #endif
8021  {
8022  factorsConsidered.append (iter.getItem());
8023  buf *= mod (iter.getItem(), y);
8024  }
8025  }
8026  buf /= Lc (buf);
8027  for (iter2= result; iter2.hasItem(); iter2++)
8028  {
8029  CanonicalForm tmp= mod (iter2.getItem(), y - evaluation);
8030  tmp /= Lc (tmp);
8031  if (tmp == buf)
8032  {
8033  bufBufUniFactors= Difference (bufBufUniFactors, factorsConsidered);
8034  break;
8035  }
8036  }
8037  }
8038  bufUniFactors= bufBufUniFactors;
8039  delete [] zeroOne;
8040  }
8041 
8042  int oldNumCols;
8043  CFList resultBufF;
8044  irreducible= false;
8045 
8046 #ifdef HAVE_FLINT //TODO
8047  oldNumCols= nmod_mat_ncols (FLINTN);
8048  resultBufF= extIncreasePrecision (bufF, bufUniFactors, factorsFound,
8049  oldNumCols, oldL, evaluation, info2,
8050  source, dest, l
8051  );
8052  nmod_mat_clear (FLINTN);
8053 #else
8054  oldNumCols= NTLN.NumCols();
8055  resultBufF= extIncreasePrecision (bufF, bufUniFactors, factorsFound,
8056  oldNumCols, oldL, evaluation, info2,
8057  source, dest, l
8058  );
8059 #endif
8060  if (bufUniFactors.isEmpty() || degree (bufF) <= 0)
8061  {
8062  delete [] bounds;
8063  result= Union (resultBufF, result);
8064  return Union (result, smallFactors);
8065  }
8066 
8067  for (CFListIterator i= bufUniFactors; i.hasItem(); i++)
8068  i.getItem()= mod (i.getItem(), y);
8069 
8070  delete [] bounds;
8071  CFList bufResult;
8072  DegreePattern bufDegs= DegreePattern (bufUniFactors);
8073  degs.intersect (bufDegs);
8074  degs.refine();
8075  result= Union (result, smallFactors);
8076  if (degs.getLength() == 1 || bufUniFactors.length() == 1)
8077  {
8078  CFList source, dest;
8079  CanonicalForm tmp= bufF (y - evaluation, y);
8080  tmp= mapDown (tmp, info, source, dest);
8081  result.append (tmp);
8082  return result;
8083  }
8084  return Union (result, extHenselLiftAndLatticeRecombi (bufF, bufUniFactors,
8085  info, degs, evaluation
8086  )
8087  );
8088  }
8089 
8090  if (l/degMipo < liftBound)
8091  {
8092 #ifdef HAVE_FLINT
8093  result=extIncreasePrecision (F, bufUniFactors, oldL, l, d, bounds, bufQ,
8094  FLINTN, evaluation, info2, source, dest
8095  );
8096 
8097  if (result.length()== nmod_mat_ncols (FLINTN))
8098  {
8099  nmod_mat_clear (FLINTN);
8100 #else
8101  result=extIncreasePrecision (F, bufUniFactors, oldL, l, d, bounds, bufQ,
8102  NTLN, evaluation, info2, source, dest
8103  );
8104 
8105  if (result.length()== NTLN.NumCols())
8106  {
8107 #endif
8108  delete [] bounds;
8109  result= Union (result, smallFactors);
8110  return result;
8111  }
8112 
8113  if (result.isEmpty())
8114  {
8115 #ifdef HAVE_FLINT
8116  result= extFurtherLiftingAndIncreasePrecision (F,bufUniFactors, l,
8117  liftBound, d,bounds,FLINTN,
8118  diophant, M, Pi, bufQ,
8119  evaluation, info2, source,
8120  dest
8121  );
8122  if (result.length()== nmod_mat_ncols (FLINTN))
8123  {
8124  nmod_mat_clear (FLINTN);
8125 #else
8126  result= extFurtherLiftingAndIncreasePrecision (F,bufUniFactors, l,
8127  liftBound, d, bounds, NTLN,
8128  diophant, M, Pi, bufQ,
8129  evaluation, info2, source,
8130  dest
8131  );
8132  if (result.length()== NTLN.NumCols())
8133  {
8134 #endif
8135  delete [] bounds;
8136  result= Union (result, smallFactors);
8137  return result;
8138  }
8139  }
8140  }
8141 
8142 #ifdef HAVE_FLINT
8143  nmod_mat_clear (FLINTN);
8144 #endif
8145 
8146  DEBOUTLN (cerr, "lattice recombination failed");
8147 
8148  DegreePattern bufDegs= DegreePattern (bufUniFactors);
8149  degs.intersect (bufDegs);
8150  degs.refine();
8151 
8152  delete [] bounds;
8153  bounds= computeBounds (F, d, isIrreducible);
8154  if (isIrreducible)
8155  {
8156  delete [] bounds;
8157  CFList source, dest;
8158  CanonicalForm tmp= F (y - evaluation, y);
8159  tmp= mapDown (tmp, info, source, dest);
8160  smallFactors.append (tmp);
8161  result= Union (result, smallFactors);
8162  return result;
8163  }
8164  minBound= bounds[0];
8165  for (int i= 1; i < d; i++)
8166  {
8167  if (bounds[i] != 0)
8168  minBound= tmin (minBound, bounds[i]);
8169  }
8170 
8171  if (minBound > 16 || result.length() == 0)
8172  {
8173  result= Union (result, smallFactors);
8174  CanonicalForm MODl= power (y, degree (F) + 1);
8175  delete [] bounds;
8176  return Union (result, extFactorRecombination (bufUniFactors, F, MODl, info,
8177  degs, evaluation, 1,
8178  bufUniFactors.length()/2
8179  )
8180  );
8181  }
8182  else
8183  {
8184  result= Union (result, smallFactors);
8185  for (CFListIterator i= bufUniFactors; i.hasItem(); i++)
8186  i.getItem()= mod (i.getItem(), y);
8187  delete [] bounds;
8188  return Union (result, extHenselLiftAndLatticeRecombi (F, bufUniFactors,
8189  info, degs, evaluation
8190  )
8191  );
8192  }
8193 }
8194 
8195 CFList
8196 extBiFactorize (const CanonicalForm& F, const ExtensionInfo& info);
8197 
8198 /// bivariate factorization over finite fields as decribed in "Factoring
8199 /// multivariate polynomials over a finite field" by L Bernardin.
8200 CFList
8201 biFactorize (const CanonicalForm& F, const ExtensionInfo& info)
8202 {
8203  if (F.inCoeffDomain())
8204  return CFList(F);
8205 
8206  CanonicalForm A= F;
8207  bool GF= (CFFactory::gettype() == GaloisFieldDomain);
8208 
8209  Variable alpha= info.getAlpha();
8210  Variable beta= info.getBeta();
8211  CanonicalForm gamma= info.getGamma();
8212  CanonicalForm delta= info.getDelta();
8213  int k= info.getGFDegree();
8214  bool extension= info.isInExtension();
8215  if (A.isUnivariate())
8216  {
8217  if (extension == false)
8218  return uniFactorizer (F, alpha, GF);
8219  else
8220  {
8221  CFList source, dest;
8222  A= mapDown (A, info, source, dest);
8223  return uniFactorizer (A, beta, GF);
8224  }
8225  }
8226 
8227  CFMap N;
8228  A= compress (A, N);
8229  Variable y= A.mvar();
8230 
8231  if (y.level() > 2) return CFList (F);
8232  Variable x= Variable (1);
8233 
8234  //remove and factorize content
8235  CanonicalForm contentAx= content (A, x);
8236  CanonicalForm contentAy= content (A);
8237 
8238  A= A/(contentAx*contentAy);
8239  CFList contentAxFactors, contentAyFactors;
8240 
8241  if (!extension)
8242  {
8243  contentAxFactors= uniFactorizer (contentAx, alpha, GF);
8244  contentAyFactors= uniFactorizer (contentAy, alpha, GF);
8245  }
8246 
8247  //trivial case
8248  CFList factors;
8249  if (A.inCoeffDomain())
8250  {
8251  append (factors, contentAxFactors);
8252  append (factors, contentAyFactors);
8253  decompress (factors, N);
8254  return factors;
8255  }
8256  else if (A.isUnivariate())
8257  {
8258  factors= uniFactorizer (A, alpha, GF);
8259  append (factors, contentAxFactors);
8260  append (factors, contentAyFactors);
8261  decompress (factors, N);
8262  return factors;
8263  }
8264 
8265 
8266  //check trivial case
8267  if (degree (A) == 1 || degree (A, 1) == 1 ||
8268  (size (A) == 2 && igcd (degree (A), degree (A,1))==1))
8269  {
8270  factors.append (A);
8271 
8272  appendSwapDecompress (factors, contentAxFactors, contentAyFactors,
8273  false, false, N);
8274 
8275  if (!extension)
8276  normalize (factors);
8277  return factors;
8278  }
8279 
8280  // check derivatives
8281  bool derivXZero= false;
8282  CanonicalForm derivX= deriv (A, x);
8283  CanonicalForm gcdDerivX;
8284  if (derivX.isZero())
8285  derivXZero= true;
8286  else
8287  {
8288  gcdDerivX= gcd (A, derivX);
8289  if (degree (gcdDerivX) > 0)
8290  {
8291  CanonicalForm g= A/gcdDerivX;
8292  CFList factorsG=
8293  Union (biFactorize (g, info), biFactorize (gcdDerivX, info));
8294  append (factorsG, contentAxFactors);
8295  append (factorsG, contentAyFactors);
8296  decompress (factorsG, N);
8297  if (!extension)
8298  normalize (factorsG);
8299  return factorsG;
8300  }
8301  }
8302  bool derivYZero= false;
8303  CanonicalForm derivY= deriv (A, y);
8304  CanonicalForm gcdDerivY;
8305  if (derivY.isZero())
8306  derivYZero= true;
8307  else
8308  {
8309  gcdDerivY= gcd (A, derivY);
8310  if (degree (gcdDerivY) > 0)
8311  {
8312  CanonicalForm g= A/gcdDerivY;
8313  CFList factorsG=
8314  Union (biFactorize (g, info), biFactorize (gcdDerivY, info));
8315  append (factorsG, contentAxFactors);
8316  append (factorsG, contentAyFactors);
8317  decompress (factorsG, N);
8318  if (!extension)
8319  normalize (factorsG);
8320  return factorsG;
8321  }
8322  }
8323  //main variable is chosen s.t. the degree in x is minimal
8324  bool swap= false;
8325  if ((degree (A) > degree (A, x)) || derivXZero)
8326  {
8327  if (!derivYZero)
8328  {
8329  A= swapvar (A, y, x);
8330  swap= derivXZero;
8331  derivXZero= derivYZero;
8332  derivYZero= swap;
8333  swap= true;
8334  }
8335  }
8336 
8337  int boundsLength;
8338  bool isIrreducible= false;
8339  int * bounds= computeBounds (A, boundsLength, isIrreducible);
8340  if (isIrreducible)
8341  {
8342  delete [] bounds;
8343  factors.append (A);
8344 
8345  appendSwapDecompress (factors, contentAxFactors, contentAyFactors,
8346  swap, false, N);
8347 
8348  if (!extension)
8349  normalize (factors);
8350  return factors;
8351  }
8352 
8353  int minBound= bounds[0];
8354  for (int i= 1; i < boundsLength; i++)
8355  {
8356  if (bounds[i] != 0)
8357  minBound= tmin (minBound, bounds[i]);
8358  }
8359 
8360  int boundsLength2;
8361  int * bounds2= computeBoundsWrtDiffMainvar (A, boundsLength2, isIrreducible);
8362  int minBound2= bounds2[0];
8363  for (int i= 1; i < boundsLength2; i++)
8364  {
8365  if (bounds2[i] != 0)
8366  minBound2= tmin (minBound2, bounds2[i]);
8367  }
8368 
8369 
8370  bool fail= false;
8371  CanonicalForm Aeval, evaluation, bufAeval, bufEvaluation, buf, tmp;
8372  CFList uniFactors, list, bufUniFactors;
8373  DegreePattern degs;
8374  DegreePattern bufDegs;
8375 
8376  bool fail2= false;
8377  CanonicalForm Aeval2, evaluation2, bufAeval2, bufEvaluation2;
8378  CFList bufUniFactors2, list2, uniFactors2;
8379  DegreePattern degs2;
8380  DegreePattern bufDegs2;
8381  bool swap2= false;
8382 
8383  // several univariate factorizations to obtain more information about the
8384  // degree pattern therefore usually less combinations have to be tried during
8385  // the recombination process
8386  int factorNums= 3;
8387  int subCheck1= substituteCheck (A, x);
8388  int subCheck2= substituteCheck (A, y);
8389  bool symmetric= false;
8390 
8391  TIMING_START (fac_fq_uni_total);
8392  for (int i= 0; i < factorNums; i++)
8393  {
8394  bufAeval= A;
8395  TIMING_START (fac_fq_bi_evaluation);
8396  bufEvaluation= evalPoint (A, bufAeval, alpha, list, GF, fail);
8397  TIMING_END_AND_PRINT (fac_fq_bi_evaluation, "time to find eval point: ");
8398  if (!derivXZero && !fail2 && !symmetric)
8399  {
8400  if (i == 0)
8401  {
8402  buf= swapvar (A, x, y);
8403  symmetric= (A/Lc (A) == buf/Lc (buf));
8404  }
8405  bufAeval2= buf;
8406  TIMING_START (fac_fq_bi_evaluation);
8407  bufEvaluation2= evalPoint (buf, bufAeval2, alpha, list2, GF, fail2);
8408  TIMING_END_AND_PRINT (fac_fq_bi_evaluation,
8409  "time to find eval point wrt y: ");
8410  }
8411  // first try to change main variable if there is no valid evaluation point
8412  if (fail && (i == 0))
8413  {
8414  if (!derivXZero && !fail2 && !symmetric)
8415  {
8416  bufEvaluation= bufEvaluation2;
8417  int dummy= subCheck2;
8418  subCheck2= subCheck1;
8419  subCheck1= dummy;
8420  tmp= A;
8421  A= buf;
8422  buf= tmp;
8423  bufAeval= bufAeval2;
8424  swap2= true;
8425  fail= false;
8426  }
8427  else
8428  fail= true;
8429  }
8430 
8431  // if there is no valid evaluation point pass to a field extension
8432  if (fail && (i == 0))
8433  {
8434  factors= extBiFactorize (A, info);
8435  appendSwapDecompress (factors, contentAxFactors, contentAyFactors,
8436  swap, swap2, N);
8437  normalize (factors);
8438  delete [] bounds;
8439  delete [] bounds2;
8440  return factors;
8441  }
8442 
8443  // there is at least one valid evaluation point
8444  // but we do not compute more univariate factorization over an extension
8445  if (fail && (i != 0))
8446  break;
8447 
8448  // univariate factorization
8449  TIMING_START (fac_fq_uni_factorizer);
8450  bufUniFactors= uniFactorizer (bufAeval, alpha, GF);
8451  TIMING_END_AND_PRINT (fac_fq_uni_factorizer,
8452  "time for univariate factorization over Fq: ");
8453  DEBOUTLN (cerr, "Lc (bufAeval)*prod (bufUniFactors)== bufAeval " <<
8454  (prod (bufUniFactors)*Lc (bufAeval) == bufAeval));
8455 
8456  if (!derivXZero && !fail2 && !symmetric)
8457  {
8458  TIMING_START (fac_fq_uni_factorizer);
8459  bufUniFactors2= uniFactorizer (bufAeval2, alpha, GF);
8460  TIMING_END_AND_PRINT (fac_fq_uni_factorizer,
8461  "time for univariate factorization in y over Fq: ");
8462  DEBOUTLN (cerr, "Lc (bufAeval2)*prod (bufUniFactors2)== bufAeval2 " <<
8463  (prod (bufUniFactors2)*Lc (bufAeval2) == bufAeval2));
8464  }
8465 
8466  if (bufUniFactors.length() == 1 ||
8467  (!fail2 && !derivXZero && !symmetric && (bufUniFactors2.length() == 1)))
8468  {
8469  if (extension)
8470  {
8471  CFList source, dest;
8472  appendMapDown (factors, A, info, source, dest);
8473  }
8474  else
8475  factors.append (A);
8476 
8477  appendSwapDecompress (factors, contentAxFactors, contentAyFactors,
8478  swap, swap2, N);
8479 
8480  if (!extension)
8481  normalize (factors);
8482  delete [] bounds;
8483  delete [] bounds2;
8484  return factors;
8485  }
8486 
8487  if (i == 0 && !extension)
8488  {
8489  if (subCheck1 > 0)
8490  {
8491  int subCheck= substituteCheck (bufUniFactors);
8492 
8493  if (subCheck > 1 && (subCheck1%subCheck == 0))
8494  {
8495  CanonicalForm bufA= A;
8496  subst (bufA, bufA, subCheck, x);
8497  factors= biFactorize (bufA, info);
8498  reverseSubst (factors, subCheck, x);
8499  appendSwapDecompress (factors, contentAxFactors, contentAyFactors,
8500  swap, swap2, N);
8501  if (!extension)
8502  normalize (factors);
8503  delete [] bounds;
8504  delete [] bounds2;
8505  return factors;
8506  }
8507  }
8508 
8509  if (!derivXZero && !fail2 && !symmetric && subCheck2 > 0)
8510  {
8511  int subCheck= substituteCheck (bufUniFactors2);
8512 
8513  if (subCheck > 1 && (subCheck2%subCheck == 0))
8514  {
8515  CanonicalForm bufA= A;
8516  subst (bufA, bufA, subCheck, y);
8517  factors= biFactorize (bufA, info);
8518  reverseSubst (factors, subCheck, y);
8519  appendSwapDecompress (factors, contentAxFactors, contentAyFactors,
8520  swap, swap2, N);
8521  if (!extension)
8522  normalize (factors);
8523  delete [] bounds;
8524  delete [] bounds2;
8525  return factors;
8526  }
8527  }
8528  }
8529 
8530  // degree analysis
8531  bufDegs = DegreePattern (bufUniFactors);
8532  if (!derivXZero && !fail2 && !symmetric)
8533  bufDegs2= DegreePattern (bufUniFactors2);
8534 
8535  if (i == 0)
8536  {
8537  Aeval= bufAeval;
8538  evaluation= bufEvaluation;
8539  uniFactors= bufUniFactors;
8540  degs= bufDegs;
8541  if (!derivXZero && !fail2 && !symmetric)
8542  {
8543  Aeval2= bufAeval2;
8544  evaluation2= bufEvaluation2;
8545  uniFactors2= bufUniFactors2;
8546  degs2= bufDegs2;
8547  }
8548  }
8549  else
8550  {
8551  degs.intersect (bufDegs);
8552  if (!derivXZero && !fail2 && !symmetric)
8553  {
8554  degs2.intersect (bufDegs2);
8555  if (bufUniFactors2.length() < uniFactors2.length())
8556  {
8557  uniFactors2= bufUniFactors2;
8558  Aeval2= bufAeval2;
8559  evaluation2= bufEvaluation2;
8560  }
8561  }
8562  if (bufUniFactors.length() < uniFactors.length())
8563  {
8564  uniFactors= bufUniFactors;
8565  Aeval= bufAeval;
8566  evaluation= bufEvaluation;
8567  }
8568  }
8569  list.append (bufEvaluation);
8570  if (!derivXZero && !fail2 && !symmetric)
8571  list2.append (bufEvaluation2);
8572  }
8573  TIMING_END_AND_PRINT (fac_fq_uni_total,
8574  "total time for univariate factorizations: ");
8575 
8576  if (!derivXZero && !fail2 && !symmetric)
8577  {
8578  if ((uniFactors.length() > uniFactors2.length() && minBound2 <= minBound)||
8579  (uniFactors.length() == uniFactors2.length()
8580  && degs.getLength() > degs2.getLength() && minBound2 <= minBound))
8581  {
8582  degs= degs2;
8583  uniFactors= uniFactors2;
8584  evaluation= evaluation2;
8585  Aeval= Aeval2;
8586  A= buf;
8587  swap2= true;
8588  }
8589  }
8590 
8591  if (degs.getLength() == 1) // A is irreducible
8592  {
8593  if (extension)
8594  {
8595  CFList source, dest;
8596  appendMapDown (factors, A, info, source, dest);
8597  }
8598  else
8599  factors.append (A);
8600  appendSwapDecompress (factors, contentAxFactors, contentAyFactors,
8601  swap, swap2, N);
8602  if (!extension)
8603  normalize (factors);
8604  delete [] bounds;
8605  delete [] bounds2;
8606  return factors;
8607  }
8608 
8609  int liftBound= degree (A, y) + 1;
8610 
8611  if (swap2)
8612  {
8613  delete [] bounds;
8614  bounds= bounds2;
8615  minBound= minBound2;
8616  }
8617 
8618  TIMING_START (fac_fq_bi_shift_to_zero);
8619  A= A (y + evaluation, y);
8620  TIMING_END_AND_PRINT (fac_fq_bi_shift_to_zero,
8621  "time to shift eval to zero: ");
8622 
8623  int degMipo= 1;
8624  if (extension && alpha.level() != 1 && k==1)
8625  degMipo= degree (getMipo (alpha));
8626 
8627  DEBOUTLN (cerr, "uniFactors= " << uniFactors);
8628 
8629  if ((GF && !extension) || (GF && extension && k != 1))
8630  {
8631  bool earlySuccess= false;
8632  CFList earlyFactors;
8633  TIMING_START (fac_fq_bi_hensel_lift);
8634  uniFactors= henselLiftAndEarly
8635  (A, earlySuccess, earlyFactors, degs, liftBound,
8636  uniFactors, info, evaluation);
8637  TIMING_END_AND_PRINT (fac_fq_bi_hensel_lift,
8638  "time for bivariate hensel lifting over Fq: ");
8639  DEBOUTLN (cerr, "lifted factors= " << uniFactors);
8640 
8641  CanonicalForm MODl= power (y, liftBound);
8642 
8643  TIMING_START (fac_fq_bi_factor_recombination);
8644  if (extension)
8645  factors= extFactorRecombination (uniFactors, A, MODl, info, degs,
8646  evaluation, 1, uniFactors.length()/2);
8647  else
8648  factors= factorRecombination (uniFactors, A, MODl, degs, evaluation, 1,
8649  uniFactors.length()/2);
8650  TIMING_END_AND_PRINT (fac_fq_bi_factor_recombination,
8651  "time for naive bivariate factor recombi over Fq: ");
8652 
8653  if (earlySuccess)
8654  factors= Union (earlyFactors, factors);
8655  else if (!earlySuccess && degs.getLength() == 1)
8656  factors= earlyFactors;
8657  }
8658  else if (degree (A) > 4 && beta.level() == 1 && (2*minBound)/degMipo < 32)
8659  {
8660  TIMING_START (fac_fq_bi_hensel_lift);
8661  if (extension)
8662  {
8663  CFList lll= extHenselLiftAndLatticeRecombi (A, uniFactors, info, degs,
8664  evaluation
8665  );
8666  factors= Union (lll, factors);
8667  }
8668  else if (alpha.level() == 1 && !GF)
8669  {
8670  CFList lll= henselLiftAndLatticeRecombi (A, uniFactors, alpha, degs,
8671  symmetric, evaluation);
8672  factors= Union (lll, factors);
8673  }
8674  else if (!extension && (alpha != x || GF))
8675  {
8676  CFList lll= henselLiftAndLatticeRecombi (A, uniFactors, alpha, degs,
8677  symmetric, evaluation);
8678  factors= Union (lll, factors);
8679  }
8680  TIMING_END_AND_PRINT (fac_fq_bi_hensel_lift,
8681  "time to bivar lift and LLL recombi over Fq: ");
8682  DEBOUTLN (cerr, "lifted factors= " << uniFactors);
8683  }
8684  else
8685  {
8686  bool earlySuccess= false;
8687  CFList earlyFactors;
8688  TIMING_START (fac_fq_bi_hensel_lift);
8689  uniFactors= henselLiftAndEarly
8690  (A, earlySuccess, earlyFactors, degs, liftBound,
8691  uniFactors, info, evaluation);
8692  TIMING_END_AND_PRINT (fac_fq_bi_hensel_lift,
8693  "time for bivar hensel lifting over Fq: ");
8694  DEBOUTLN (cerr, "lifted factors= " << uniFactors);
8695 
8696  CanonicalForm MODl= power (y, liftBound);
8697  if (!extension)
8698  {
8699  TIMING_START (fac_fq_bi_factor_recombination);
8700  factors= factorRecombination (uniFactors, A, MODl, degs, evaluation, 1, 3);
8701  TIMING_END_AND_PRINT (fac_fq_bi_factor_recombination,
8702  "time for small subset naive recombi over Fq: ");
8703 
8704  int oldUniFactorsLength= uniFactors.length();
8705  if (degree (A) > 0)
8706  {
8707  CFList tmp;
8708  TIMING_START (fac_fq_bi_hensel_lift);
8709  if (alpha.level() == 1)
8710  tmp= increasePrecision (A, uniFactors, 0, uniFactors.length(), 1,
8711  liftBound, evaluation
8712  );
8713  else
8714  {
8715  if (degree (A) > getCharacteristic())
8716  tmp= increasePrecisionFq2Fp (A, uniFactors, 0, uniFactors.length(),
8717  1, alpha, liftBound, evaluation
8718  );
8719  else
8720  tmp= increasePrecision (A, uniFactors, 0, uniFactors.length(), 1,
8721  alpha, liftBound, evaluation
8722  );
8723  }
8724  TIMING_END_AND_PRINT (fac_fq_bi_hensel_lift,
8725  "time to increase precision: ");
8726  factors= Union (factors, tmp);
8727  if (tmp.length() == 0 || (tmp.length() > 0 && uniFactors.length() != 0
8728  && uniFactors.length() != oldUniFactorsLength)
8729  )
8730  {
8731  DegreePattern bufDegs= DegreePattern (uniFactors);
8732  degs.intersect (bufDegs);
8733  degs.refine ();
8734  factors= Union (factors, factorRecombination (uniFactors, A, MODl,
8735  degs, evaluation, 4,
8736  uniFactors.length()/2
8737  )
8738  );
8739  }
8740  }
8741  }
8742  else
8743  {
8744  if (beta.level() != 1 || k > 1)
8745  {
8746  if (k > 1)
8747  {
8748  factors= extFactorRecombination (uniFactors, A, MODl, info, degs,
8749  evaluation, 1, uniFactors.length()/2
8750  );
8751  }
8752  else
8753  {
8754  factors= extFactorRecombination (uniFactors, A, MODl, info, degs,
8755  evaluation, 1, 3
8756  );
8757  if (degree (A) > 0)
8758  {
8759  CFList tmp= increasePrecision2 (A, uniFactors, alpha, liftBound);
8760  DegreePattern bufDegs= DegreePattern (tmp);
8761  degs.intersect (bufDegs);
8762  degs.refine ();
8763  factors= Union (factors, extFactorRecombination (tmp, A, MODl, info,
8764  degs, evaluation,
8765  1, tmp.length()/2
8766  )
8767  );
8768  }
8769  }
8770  }
8771  else
8772  {
8773  factors= extFactorRecombination (uniFactors, A, MODl, info, degs,
8774  evaluation, 1, 3
8775  );
8776  int oldUniFactorsLength= uniFactors.length();
8777  if (degree (A) > 0)
8778  {
8779  int degMipo;
8780  ExtensionInfo info2= init4ext (info, evaluation, degMipo);
8781 
8782  CFList source, dest;
8783  CFList tmp= extIncreasePrecision (A, uniFactors, 0,
8784  uniFactors.length(), 1, evaluation,
8785  info2, source, dest, liftBound
8786  );
8787  factors= Union (factors, tmp);
8788  if (tmp.length() == 0 || (tmp.length() > 0 && uniFactors.length() != 0
8789  && uniFactors.length() != oldUniFactorsLength)
8790  )
8791  {
8792  DegreePattern bufDegs= DegreePattern (uniFactors);
8793  degs.intersect (bufDegs);
8794  degs.refine ();
8795  factors= Union (factors,extFactorRecombination (uniFactors, A, MODl,
8796  info, degs, evaluation,
8797  4, uniFactors.length()/2
8798  )
8799  );
8800  }
8801  }
8802  }
8803  }
8804 
8805  if (earlySuccess)
8806  factors= Union (earlyFactors, factors);
8807  else if (!earlySuccess && degs.getLength() == 1)
8808  factors= earlyFactors;
8809  }
8810 
8811  if (!swap2)
8812  delete [] bounds2;
8813  delete [] bounds;
8814 
8815  appendSwapDecompress (factors, contentAxFactors, contentAyFactors,
8816  swap, swap2, N);
8817  if (!extension)
8818  normalize (factors);
8819 
8820  return factors;
8821 }
8822 
8823 CFList
8825 {
8826 
8827  CanonicalForm A= F;
8828  Variable alpha= info.getAlpha();
8829  Variable beta= info.getBeta();
8830  int k= info.getGFDegree();
8831  char cGFName= info.getGFName();
8832  CanonicalForm delta= info.getDelta();
8833 
8834  bool GF= (CFFactory::gettype() == GaloisFieldDomain);
8835  Variable x= Variable (1);
8836  CFList factors;
8837  if (!GF && alpha == x) // we are in F_p
8838  {
8839  bool extension= true;
8840  int p= getCharacteristic();
8841  if (p*p < (1<<16)) // pass to GF if possible
8842  {
8844  A= A.mapinto();
8845  ExtensionInfo info2= ExtensionInfo (extension);
8846  factors= biFactorize (A, info2);
8847 
8850  Variable vBuf= rootOf (mipo.mapinto());
8851  for (CFListIterator j= factors; j.hasItem(); j++)
8852  j.getItem()= GF2FalphaRep (j.getItem(), vBuf);
8853  prune (vBuf);
8854  }
8855  else // not able to pass to GF, pass to F_p(\alpha)
8856  {
8858  Variable v= rootOf (mipo);
8859  ExtensionInfo info2= ExtensionInfo (v);
8860  factors= biFactorize (A, info2);
8861  prune (v);
8862  }
8863  return factors;
8864  }
8865  else if (!GF && (alpha != x)) // we are in F_p(\alpha)
8866  {
8867  if (k == 1) // need factorization over F_p
8868  {
8869  int extDeg= degree (getMipo (alpha));
8870  extDeg++;
8871  CanonicalForm mipo= randomIrredpoly (extDeg, x);
8872  Variable v= rootOf (mipo);
8873  ExtensionInfo info2= ExtensionInfo (v);
8874  factors= biFactorize (A, info2);
8875  prune (v);
8876  }
8877  else
8878  {
8879  if (beta == x)
8880  {
8881  Variable v= chooseExtension (alpha, beta, k);
8882  CanonicalForm primElem, imPrimElem;
8883  bool primFail= false;
8884  Variable vBuf;
8885  primElem= primitiveElement (alpha, vBuf, primFail);
8886  ASSERT (!primFail, "failure in integer factorizer");
8887  if (primFail)
8888  ; //ERROR
8889  else
8890  imPrimElem= mapPrimElem (primElem, alpha, v);
8891 
8892  CFList source, dest;
8893  CanonicalForm bufA= mapUp (A, alpha, v, primElem, imPrimElem,
8894  source, dest);
8895  ExtensionInfo info2= ExtensionInfo (v, alpha, imPrimElem, primElem);
8896  factors= biFactorize (bufA, info2);
8897  prune (v);
8898  }
8899  else
8900  {
8901  Variable v= chooseExtension (alpha, beta, k);
8902  CanonicalForm primElem, imPrimElem;
8903  bool primFail= false;
8904  Variable vBuf;
8905  ASSERT (!primFail, "failure in integer factorizer");
8906  if (primFail)
8907  ; //ERROR
8908  else
8909  imPrimElem= mapPrimElem (delta, beta, v);
8910 
8911  CFList source, dest;
8912  CanonicalForm bufA= mapDown (A, info, source, dest);
8913  source= CFList();
8914  dest= CFList();
8915  bufA= mapUp (bufA, beta, v, delta, imPrimElem, source, dest);
8916  ExtensionInfo info2= ExtensionInfo (v, beta, imPrimElem, delta);
8917  factors= biFactorize (bufA, info2);
8918  prune (v);
8919  }
8920  }
8921  return factors;
8922  }
8923  else // we are in GF (p^k)
8924  {
8925  int p= getCharacteristic();
8926  int extensionDeg= getGFDegree();
8927  bool extension= true;
8928  if (k == 1) // need factorization over F_p
8929  {
8930  extensionDeg++;
8931  if (ipower (p, extensionDeg) < (1<<16))
8932  // pass to GF(p^k+1)
8933  {
8935  setCharacteristic (p);
8936  Variable vBuf= rootOf (mipo.mapinto());
8937  A= GF2FalphaRep (A, vBuf);
8938  setCharacteristic (p, extensionDeg, 'Z');
8939  ExtensionInfo info2= ExtensionInfo (extension);
8940  factors= biFactorize (A.mapinto(), info2);
8941  prune (vBuf);
8942  }
8943  else // not able to pass to another GF, pass to F_p(\alpha)
8944  {
8946  setCharacteristic (p);
8947  Variable vBuf= rootOf (mipo.mapinto());
8948  A= GF2FalphaRep (A, vBuf);
8949  Variable v= chooseExtension (vBuf, beta, k);
8950  ExtensionInfo info2= ExtensionInfo (v, extension);
8951  factors= biFactorize (A, info2);
8952  prune (vBuf);
8953  }
8954  }
8955  else // need factorization over GF (p^k)
8956  {
8957  if (ipower (p, 2*extensionDeg) < (1<<16))
8958  // pass to GF (p^2k)
8959  {
8960  setCharacteristic (p, 2*extensionDeg, 'Z');
8961  ExtensionInfo info2= ExtensionInfo (k, cGFName, extension);
8962  factors= biFactorize (GFMapUp (A, extensionDeg), info2);
8963  setCharacteristic (p, extensionDeg, cGFName);
8964  }
8965  else // not able to pass to GF (p^2k), pass to F_p (\alpha)
8966  {
8968  setCharacteristic (p);
8969  Variable v1= rootOf (mipo.mapinto());
8970  A= GF2FalphaRep (A, v1);
8971  Variable v2= chooseExtension (v1, v1, k);
8972  CanonicalForm primElem, imPrimElem;
8973  bool primFail= false;
8974  Variable vBuf;
8975  primElem= primitiveElement (v1, vBuf, primFail);
8976  ASSERT (!primFail, "failure in integer factorizer");
8977  if (primFail)
8978  ; //ERROR
8979  else
8980  imPrimElem= mapPrimElem (primElem, v1, v2);
8981 
8982  CFList source, dest;
8983  CanonicalForm bufA= mapUp (A, v1, v2, primElem, imPrimElem,
8984  source, dest);
8985  ExtensionInfo info2= ExtensionInfo (v2, v1, imPrimElem, primElem);
8986  factors= biFactorize (bufA, info2);
8987  setCharacteristic (p, k, cGFName);
8988  for (CFListIterator i= factors; i.hasItem(); i++)
8989  i.getItem()= Falpha2GFRep (i.getItem());
8990  prune (v1);
8991  }
8992  }
8993  return factors;
8994  }
8995 }
8996 
8997 #endif
8998 /* HAVE_NTL */
8999 
9000 
void deleteFactors(CFList &factors, int *factorsFoundIndex)
Definition: facFqBivar.cc:1100
TIMING_END_AND_PRINT(fac_alg_resultant, "time to compute resultant0: ")
int status int void size_t count
Definition: si_signals.h:59
GF2EX convertFacCF2NTLGF2EX(const CanonicalForm &f, const GF2X &mipo)
CanonicalForm in Z_2(a)[X] to NTL GF2EX.
Definition: NTLconvert.cc:1006
CanonicalForm power(const CanonicalForm &f, int n)
exponentiation
char getGFName() const
getter
CFFList append(const CFFList &Inputlist, const CFFactor &TheFactor)
void indexUpdate(int index [], const int &subsetSize, const int &setSize, bool &noSubset)
update index
List< CanonicalForm > CFList
CanonicalForm map(const CanonicalForm &primElem, const Variable &alpha, const CanonicalForm &F, const Variable &beta)
map from to such that is mapped onto
Definition: cf_map_ext.cc:400
Variable getAlpha() const
getter
const CanonicalForm const modpk & b
Definition: facFqBivar.cc:59
void subset(std::vector< int > &arr, int size, int left, int index, std::vector< int > &l, std::vector< std::vector< int > > &L)
Definition: gitfan.cc:549
CanonicalForm Falpha2GFRep(const CanonicalForm &F)
change representation by residue classes modulo a Conway polynomial to representation by primitive el...
Definition: cf_map_ext.cc:170
nmod_poly_init(FLINTmipo, getCharacteristic())
static CanonicalForm mapDown(const CanonicalForm &F, const Variable &alpha, const CanonicalForm &G, CFList &source, CFList &dest)
the CanonicalForm G is the output of map_up, returns F considered as an element over ...
Definition: cf_map_ext.cc:90
const CanonicalForm int s
Definition: facAbsFact.cc:55
DegreePattern provides a functionality to create, intersect and refine degree patterns.
Definition: DegreePattern.h:31
void reconstructionTry(CFList &reconstructedFactors, CanonicalForm &F, const CFList &factors, const int liftBound, int &factorsFound, int *&factorsFoundIndex, mat_zz_pE &N, const CanonicalForm &eval, bool beenInThres)
Definition: facFqBivar.cc:1559
generate random elements in GF
Definition: cf_random.h:31
const CanonicalForm int const CFList const Variable & y
Definition: facAbsFact.cc:57
CanonicalForm icontent(const CanonicalForm &f)
CanonicalForm icontent ( const CanonicalForm & f )
Definition: cf_gcd.cc:71
int j
Definition: facHensel.cc:105
CFList increasePrecisionFq2Fp(CanonicalForm &F, CFList &factors, int factorsFound, int oldNumCols, int oldL, const Variable &alpha, int precision, const CanonicalForm &eval)
Definition: facFqBivar.cc:4200
CF_NO_INLINE bool isOne() const
CF_INLINE bool CanonicalForm::isOne, isZero () const.
Definition: cf_inline.cc:354
long isReduced(const nmod_mat_t M)
Definition: facFqBivar.cc:1447
void remove(int moveright)
Definition: ftmpl_list.cc:526
CFArray copy(const CFList &list)
write elements of list into an array
CFFList convertNTLvec_pair_GF2EX_long2FacCFFList(const vec_pair_GF2EX_long &e, const GF2E &multi, const Variable &x, const Variable &alpha)
NAME: convertNTLvec_pair_GF2EX_long2FacCFFList.
Definition: NTLconvert.cc:954
Conversion to and from NTL.
This file defines functions for Hensel lifting.
static poly normalize(poly next_p, ideal add_generators, syStrategy syzstr, int *g_l, int *p_l, int crit_comp)
Definition: syz3.cc:1027
CFFList convertNTLvec_pair_GF2X_long2FacCFFList(const vec_pair_GF2X_long &e, GF2, const Variable &x)
NAME: convertNTLvec_pair_GF2X_long2FacCFFList.
Definition: NTLconvert.cc:439
static CanonicalForm bound(const CFMatrix &M)
Definition: cf_linsys.cc:460
This file defines functions for conversion to FLINT (www.flintlib.org) and back.
bool uniFdivides(const CanonicalForm &A, const CanonicalForm &B)
divisibility test for univariate polys
Definition: facMul.cc:3626
void convertFacCFMatrix2nmod_mat_t(nmod_mat_t M, const CFMatrix &m)
conversion of a factory matrix over Z/p to a nmod_mat_t
int isEmpty() const
Definition: ftmpl_list.cc:267
void Off(int sw)
switches
Matrix< CanonicalForm > CFMatrix
CanonicalForm LCF
Definition: facFactorize.cc:53
CFList henselLiftAndLatticeRecombi(const CanonicalForm &G, const CFList &uniFactors, const Variable &alpha, const DegreePattern &degPat, bool symmetric, const CanonicalForm &eval)
Definition: facFqBivar.cc:6764
CanonicalForm getDelta() const
getter
CanonicalForm buf1
Definition: facFqBivar.cc:71
This file provides functions to compute the Newton polygon of a bivariate polynomial.
functions to print debug output
template CanonicalForm tmax(const CanonicalForm &, const CanonicalForm &)
int * extractZeroOneVecs(const nmod_mat_t M)
Definition: facFqBivar.cc:1509
int getGFDegree() const
getter
CanonicalForm deriv(const CanonicalForm &f, const Variable &x)
TIMING_START(fac_alg_resultant)
CFArray getCoeffs(const CanonicalForm &F, const int k)
extract coefficients of for where is a variable of level 1
CanonicalForm primitiveElement(const Variable &alpha, Variable &beta, bool &fail)
determine a primitive element of , is a primitive element of a field which is isomorphic to ...
Definition: cf_map_ext.cc:310
factory&#39;s class for variables
Definition: factory.h:117
CFList henselLiftAndEarly(CanonicalForm &A, bool &earlySuccess, CFList &earlyFactors, DegreePattern &degs, int &liftBound, const CFList &uniFactors, const ExtensionInfo &info, const CanonicalForm &eval, modpk &b, CanonicalForm &den)
hensel Lifting and early factor detection
Definition: facFqBivar.cc:1115
int igcd(int a, int b)
Definition: cf_util.cc:51
CF_NO_INLINE CanonicalForm coeff() const
get the current coefficient
Variable chooseExtension(const Variable &alpha, const Variable &beta, int k)
chooses a field extension.
Definition: facFqBivar.cc:780
CF_NO_INLINE bool isZero() const
Definition: cf_inline.cc:372
CFList *& Aeval
<[in] poly
Definition: facFactorize.h:31
bool isInExtension(const CanonicalForm &F, const CanonicalForm &gamma, const int k, const CanonicalForm &delta, CFList &source, CFList &dest)
tests if F is not contained in a subfield defined by gamma (Fq case) or k (GF case) ...
GF2X convertFacCF2NTLGF2X(const CanonicalForm &f)
NAME: convertFacCF2NTLGF2X.
Definition: NTLconvert.cc:177
CFList uniFactorizer(const CanonicalForm &A, const Variable &alpha, const bool &GF)
Univariate factorization of squarefree monic polys over finite fields via NTL. If the characteristic ...
Definition: facFqBivar.cc:156
CFList extReconstruction(CanonicalForm &G, CFList &factors, int *zeroOneVecs, int precision, const nmod_mat_t N, const ExtensionInfo &info, const CanonicalForm &evaluation)
Definition: facFqBivar.cc:1991
ExtensionInfo init4ext(const ExtensionInfo &info, const CanonicalForm &evaluation, int &degMipo)
Definition: facFqBivar.cc:7559
int find(const int x) const
find an element x
void convertFacCF2Fq_nmod_poly_t(fq_nmod_poly_t result, const CanonicalForm &f, const fq_nmod_ctx_t ctx)
conversion of a factory univariate poly over F_q to a FLINT fq_nmod_poly_t
CFFListIterator iter
Definition: facAbsBiFact.cc:54
CFFList convertNTLvec_pair_zzpX_long2FacCFFList(const vec_pair_zz_pX_long &e, const zz_p multi, const Variable &x)
Definition: NTLconvert.cc:392
CFFList convertFLINTFq_nmod_poly_factor2FacCFFList(const fq_nmod_poly_factor_t fac, const Variable &x, const Variable &alpha, const fq_nmod_ctx_t fq_con)
conversion of a FLINT factorization over Fq (for word size p) to a CFFList
int liftAndComputeLattice(const CanonicalForm &F, int *bounds, int sizeBounds, int start, int liftBound, int minBound, CFList &factors, nmod_mat_t FLINTN, CFList &diophant, CFMatrix &M, CFArray &Pi, CFArray &bufQ, bool &irreducible)
Definition: facFqBivar.cc:2559
factory&#39;s main class
Definition: canonicalform.h:77
char gf_name
Definition: gfops.cc:52
nmod_poly_clear(FLINTmipo)
assertions for Factory
int * getRightSide(int **polygon, int sizeOfPolygon, int &sizeOfOutput)
get the y-direction slopes of all edges with positive slope in y-direction of a convex polygon with a...
CanonicalForm convertNTLzzpX2CF(const zz_pX &poly, const Variable &x)
Definition: NTLconvert.cc:248
fq_nmod_ctx_t fq_con
Definition: facHensel.cc:94
Array< CanonicalForm > CFArray
g
Definition: cfModGcd.cc:4031
int k
Definition: cfEzgcd.cc:92
const CanonicalForm int const CFList & evaluation
Definition: facAbsFact.cc:55
void appendSwapDecompress(CFList &factors1, const CFList &factors2, const CFList &factors3, const bool swap1, const bool swap2, const CFMap &N)
first swap Variables in factors1 if necessary, then append factors2 and factors3 on factors1 and fina...
Variable alpha
Definition: facAbsBiFact.cc:52
CFList sieveSmallFactors(const CanonicalForm &G, CFList &uniFactors, DegreePattern &degPat, CanonicalForm &H, CFList &diophant, CFArray &Pi, CFMatrix &M, bool &success, int d, const CanonicalForm &eval)
Definition: facFqBivar.cc:6671
CanonicalForm prodMod0(const CFList &L, const CanonicalForm &M, const modpk &b=modpk())
via divide-and-conquer
const CanonicalForm & M
Definition: facFqBivar.cc:58
void insert(const T &)
Definition: ftmpl_list.cc:193
bool isIrreducible(const CanonicalForm &f)
bool isIrreducible ( const CanonicalForm & f )
int extLiftAndComputeLattice(const CanonicalForm &F, int *bounds, int sizeBounds, int liftBound, int minBound, int start, CFList &factors, nmod_mat_t FLINTN, CFList &diophant, CFMatrix &M, CFArray &Pi, CFArray &bufQ, bool &irreducible, const CanonicalForm &evaluation, const ExtensionInfo &info, CFList &source, CFList &dest)
Definition: facFqBivar.cc:2895
static TreeM * G
Definition: janet.cc:32
CanonicalForm Lc(const CanonicalForm &f)
CFList extIncreasePrecision(CanonicalForm &F, CFList &factors, int factorsFound, int oldNumCols, int oldL, const CanonicalForm &evaluation, const ExtensionInfo &info, CFList &source, CFList &dest, int precision)
Definition: facFqBivar.cc:3763
CanonicalForm getMipo(const Variable &alpha, const Variable &x)
Definition: variable.cc:207
CanonicalForm generate() const
Definition: cf_random.cc:145
CanonicalForm compress(const CanonicalForm &f, CFMap &m)
CanonicalForm compress ( const CanonicalForm & f, CFMap & m )
Definition: cf_map.cc:210
void setCharacteristic(int c)
Definition: cf_char.cc:23
bool delta(X x, Y y, D d)
Definition: TestSuite.h:160
int getCharacteristic()
Definition: cf_char.cc:51
template bool find(const List< CanonicalForm > &, const CanonicalForm &)
Rational abs(const Rational &a)
Definition: GMPrat.cc:439
void prune(Variable &alpha)
Definition: variable.cc:261
void removeFirst()
Definition: ftmpl_list.cc:287
map polynomials
fq_nmod_ctx_clear(fq_con)
CFList monicReconstruction(CanonicalForm &G, CFList &factors, int *zeroOneVecs, int precision, const mat_zz_pE &N)
Definition: facFqBivar.cc:1858
CanonicalForm subst(const CanonicalForm &f, const CFList &a, const CFList &b, const CanonicalForm &Rstar, bool isFunctionField)
CanonicalForm content(const CanonicalForm &)
CanonicalForm content ( const CanonicalForm & f )
Definition: cf_gcd.cc:180
CanonicalForm mapinto() const
This file implements functions to map between extensions of finite fields.
CanonicalForm gf_mipo
Definition: gfops.cc:56
void intersect(const DegreePattern &degPat)
intersect two degree patterns
CFList factorRecombination(CFList &factors, CanonicalForm &F, const CanonicalForm &N, DegreePattern &degs, const CanonicalForm &eval, int s, int thres, const modpk &b, const CanonicalForm &den)
naive factor recombination as decribed in "Factoring multivariate polynomials over a finite field" by...
Definition: facFqBivar.cc:561
T getFirst() const
Definition: ftmpl_list.cc:279
CFFList convertNTLvec_pair_zzpEX_long2FacCFFList(const vec_pair_zz_pEX_long &e, const zz_pE &multi, const Variable &x, const Variable &alpha)
Definition: NTLconvert.cc:865
CanonicalForm lc(const CanonicalForm &f)
template List< Variable > Union(const List< Variable > &, const List< Variable > &)
Variable rootOf(const CanonicalForm &, char name='@')
returns a symbolic root of polynomial with name name Use it to define algebraic variables ...
Definition: variable.cc:162
CanonicalForm inverse(const CanonicalForm &f, bool symmetric=true) const
Definition: fac_util.cc:58
CFList extHenselLiftAndLatticeRecombi(const CanonicalForm &G, const CFList &uniFactors, const ExtensionInfo &extInfo, const DegreePattern &degPat, const CanonicalForm &eval)
Definition: facFqBivar.cc:7612
int ** newtonPolygon(const CanonicalForm &F, int &sizeOfNewtonPoly)
compute the Newton polygon of a bivariate polynomial
return modpk(p, k)
ExtensionInfo contains information about extension.
Definition: ExtensionInfo.h:50
CanonicalForm swapvar(const CanonicalForm &, const Variable &, const Variable &)
swapvar() - swap variables x1 and x2 in f.
Definition: cf_ops.cc:168
static CanonicalForm mapUp(const Variable &alpha, const Variable &beta)
and is a primitive element, returns the image of
Definition: cf_map_ext.cc:67
CanonicalForm mulNTL(const CanonicalForm &F, const CanonicalForm &G, const modpk &b)
multiplication of univariate polys using FLINT/NTL over F_p, F_q, Z/p^k, Z/p^k[t]/(f), Z, Q, Q(a), if we are in GF factory&#39;s default multiplication is used. If b!= 0 and getCharacteristic() == 0 the input will be considered as elements over Z/p^k or Z/p^k[t]/(f).
Definition: facMul.cc:407
const CanonicalForm CFMap CFMap & N
Definition: cfEzgcd.cc:48
mat_zz_p * convertFacCFMatrix2NTLmat_zz_p(const CFMatrix &m)
Definition: NTLconvert.cc:1166
CFFList convertFLINTnmod_poly_factor2FacCFFList(const nmod_poly_factor_t fac, const mp_limb_t leadingCoeff, const Variable &x)
conversion of a FLINT factorization over Z/p (for word size p) to a CFFList
CFList extBiFactorize(const CanonicalForm &F, const ExtensionInfo &info)
Factorization over an extension of initial field.
Definition: facFqBivar.cc:8824
void extEarlyFactorDetection(CFList &reconstructedFactors, CanonicalForm &F, CFList &factors, int &adaptedLiftBound, int *&factorsFoundIndex, DegreePattern &degs, bool &success, const ExtensionInfo &info, const CanonicalForm &eval, int deg)
detects factors of F at stage deg of Hensel lifting. No combinations of more than one factor are test...
Definition: facFqBivar.cc:946
CanonicalForm generate() const
Definition: cf_random.cc:66
CanonicalForm decompress(const CanonicalForm &F, const mpz_t *inverseM, const mpz_t *A)
decompress a bivariate poly
convertFacCF2nmod_poly_t(FLINTmipo, M)
void writeInMatrix(CFMatrix &M, const CFArray &A, const int column, const int startIndex)
write A into M starting at row startIndex
int status int void * buf
Definition: si_signals.h:59
This file defines functions for fast multiplication and division with remainder.
int level() const
Definition: factory.h:134
zz_pEX convertFacCF2NTLzz_pEX(const CanonicalForm &f, const zz_pX &mipo)
Definition: NTLconvert.cc:1063
bool isUnivariate() const
T & getItem() const
Definition: ftmpl_list.cc:431
const ExtensionInfo & info
< [in] sqrfree poly
#define A
Definition: sirandom.c:23
CanonicalForm generate() const
Definition: cf_random.cc:56
CFList & eval
Definition: facFactorize.cc:48
void extReconstructionTry(CFList &reconstructedFactors, CanonicalForm &F, const CFList &factors, const int liftBound, int &factorsFound, int *&factorsFoundIndex, nmod_mat_t N, bool beenInThres, const ExtensionInfo &info, const CanonicalForm &evaluation)
Definition: facFqBivar.cc:2304
int * getLiftPrecisions(const CanonicalForm &F, int &sizeOfOutput, int degreeLC)
compute lifting precisions from the shape of the Newton polygon of F
Definition: facFqBivar.cc:1084
void refineAndRestartLift(const CanonicalForm &F, const nmod_mat_t FLINTN, int liftBound, int l, CFList &factors, CFMatrix &M, CFArray &Pi, CFList &diophant)
Definition: facFqBivar.cc:6055
int * computeBoundsWrtDiffMainvar(const CanonicalForm &F, int &n, bool &isIrreducible)
as above just wrt to the other variable
Variable getBeta() const
getter
bool hasFirstAlgVar(const CanonicalForm &f, Variable &a)
check if poly f contains an algebraic variable a
Definition: cf_ops.cc:665
CFList reconstruction(CanonicalForm &G, CFList &factors, int *zeroOneVecs, int precision, const mat_zz_pE &N, const CanonicalForm &eval)
Definition: facFqBivar.cc:1809
CanonicalForm mulMod2(const CanonicalForm &A, const CanonicalForm &B, const CanonicalForm &M)
Karatsuba style modular multiplication for bivariate polynomials.
Definition: facMul.cc:2853
static const int SW_RATIONAL
set to 1 for computations over Q
Definition: cf_defs.h:28
int m
Definition: cfEzgcd.cc:121
bool isOn(int sw)
switches
void On(int sw)
switches
int substituteCheck(const CanonicalForm &F, const Variable &x)
check if a substitution x^n->x is possible
CFList increasePrecision(CanonicalForm &F, CFList &factors, int factorsFound, int oldNumCols, int oldL, int precision, const CanonicalForm &eval)
Definition: facFqBivar.cc:3416
generate random elements in F_p
Definition: cf_random.h:43
T getLast() const
Definition: ftmpl_list.cc:309
CanonicalForm getGFGenerator()
Definition: cf_char.cc:62
int subsetDegree(const CFList &S)
compute the sum of degrees in Variable(1) of elements in S
void appendMapDown(CFList &factors, const CanonicalForm &g, const ExtensionInfo &info, CFList &source, CFList &dest)
map g down into a subfield of the current field and append it to factors
factory switches.
generate random integers, random elements of finite fields
CanonicalForm H
Definition: facAbsFact.cc:64
CFList recombination(const CFList &factors1, const CFList &factors2, int s, int thres, const CanonicalForm &evalPoint, const Variable &x)
recombination of bivariate factors factors1 s. t. the result evaluated at evalPoint coincides with fa...
int * getCombinations(int *rightSide, int sizeOfRightSide, int &sizeOfOutput, int degreeLC)
Definition: facFqBivar.cc:1045
Variable mvar() const
mvar() returns the main variable of CO or Variable() if CO is in a base domain.
CanonicalForm findMinPoly(const CanonicalForm &F, const Variable &alpha)
compute minimal polynomial of via NTL
Definition: cf_map_ext.cc:434
CFList tmp2
Definition: facFqBivar.cc:70
void appendTestMapDown(CFList &factors, const CanonicalForm &f, const ExtensionInfo &info, CFList &source, CFList &dest)
test if g is in a subfield of the current field, if so map it down and append it to factors ...
CanonicalForm bCommonDen(const CanonicalForm &f)
CanonicalForm bCommonDen ( const CanonicalForm & f )
void earlyFactorDetection(CFList &reconstructedFactors, CanonicalForm &F, CFList &factors, int &adaptedLiftBound, int *&factorsFoundIndex, DegreePattern &degs, bool &success, int deg, const CanonicalForm &eval, const modpk &b, CanonicalForm &den)
Definition: facFqBivar.cc:816
CFList extFurtherLiftingAndIncreasePrecision(CanonicalForm &F, CFList &factors, int l, int liftBound, int d, int *bounds, nmod_mat_t FLINTN, CFList &diophant, CFMatrix &M, CFArray &Pi, CFArray &bufQ, const CanonicalForm &evaluation, const ExtensionInfo &info, CFList &source, CFList &dest)
Definition: facFqBivar.cc:5476
fq_nmod_poly_clear(prod, fq_con)
CFList increasePrecision2(const CanonicalForm &F, CFList &factors, const Variable &alpha, int precision)
Definition: facFqBivar.cc:4069
CFArray logarithmicDerivative(const CanonicalForm &F, const CanonicalForm &G, int l, CanonicalForm &Q)
compute the coefficients of the logarithmic derivative of G mod Variable (2)^l over Fq ...
static int index(p_Length length, p_Ord ord)
Definition: p_Procs_Impl.h:592
void refine()
Refine a degree pattern. Assumes that (*this)[0]:= d is the degree of the poly to be factored...
CFListIterator i
Definition: facFqBivar.cc:69
int size(const CanonicalForm &f, const Variable &v)
int size ( const CanonicalForm & f, const Variable & v )
Definition: cf_ops.cc:600
static BOOLEAN IsOne(number a, const coeffs r)
Definition: flintcf_Q.cc:359
CanonicalForm evalPoint(const CanonicalForm &F, CanonicalForm &eval, const Variable &alpha, CFList &list, const bool &GF, bool &fail)
find an evaluation point p, s.t. F(p,y) is squarefree and .
Definition: facFqBivar.cc:81
class to iterate through CanonicalForm&#39;s
Definition: cf_iter.h:44
CanonicalForm test
Definition: cfModGcd.cc:4037
CanonicalForm buf2
Definition: facFqBivar.cc:71
Variable beta
Definition: facAbsFact.cc:99
void henselLift12(const CanonicalForm &F, CFList &factors, int l, CFArray &Pi, CFList &diophant, CFMatrix &M, modpk &b, bool sort)
Hensel lift from univariate to bivariate.
Definition: facHensel.cc:1148
class CFMap
Definition: cf_map.h:84
bool fdivides(const CanonicalForm &f, const CanonicalForm &g)
bool fdivides ( const CanonicalForm & f, const CanonicalForm & g )
This file provides utility functions for bivariate factorization.
const Variable & v
< [in] a sqrfree bivariate poly
Definition: facBivar.h:37
return mod(mulNTL(buf1, buf2, b), M)
CFList extFactorRecombination(CFList &factors, CanonicalForm &F, const CanonicalForm &N, const ExtensionInfo &info, DegreePattern &degs, const CanonicalForm &eval, int s, int thres)
naive factor recombination as decribed in "Factoring multivariate polynomials over a finite field" by...
Definition: facFqBivar.cc:346
CFList extEarlyReconstructionAndLifting(const CanonicalForm &F, const nmod_mat_t N, CanonicalForm &bufF, CFList &factors, int &l, int &factorsFound, bool beenInThres, CFMatrix &M, CFArray &Pi, CFList &diophant, const ExtensionInfo &info, const CanonicalForm &evaluation)
Definition: facFqBivar.cc:6489
generate random irreducible univariate polynomials
CF_NO_INLINE CanonicalForm div(const CanonicalForm &, const CanonicalForm &)
CF_INLINE CanonicalForm div, mod ( const CanonicalForm & lhs, const CanonicalForm & rhs ) ...
Definition: cf_inline.cc:553
CanonicalForm GF2FalphaRep(const CanonicalForm &F, const Variable &alpha)
changes representation by primitive element to representation by residue classes modulo a Conway poly...
Definition: cf_map_ext.cc:162
generate random elements in F_p(alpha)
Definition: cf_random.h:70
int length() const
Definition: ftmpl_list.cc:273
int ipower(int b, int m)
int ipower ( int b, int m )
Definition: cf_util.cc:25
static int gettype()
Definition: cf_factory.h:28
#define swap(_i, _j)
zz_pX convertFacCF2NTLzzpX(const CanonicalForm &f)
Definition: NTLconvert.cc:100
CanonicalForm den(const CanonicalForm &f)
int getLength() const
getter
Definition: DegreePattern.h:86
CanonicalForm mipo
Definition: facAlgExt.cc:57
CF_NO_INLINE int hasTerms() const
check if iterator has reached the end of CanonicalForm
Factor< CanonicalForm > CFFactor
CanonicalForm GFMapUp(const CanonicalForm &F, int k)
maps a polynomial over to a polynomial over , d needs to be a multiple of k
Definition: cf_map_ext.cc:207
int gcd(int a, int b)
Definition: walkSupport.cc:836
CFList earlyReconstructionAndLifting(const CanonicalForm &F, const nmod_mat_t N, CanonicalForm &bufF, CFList &factors, int &l, int &factorsFound, bool beenInThres, CFMatrix &M, CFArray &Pi, CFList &diophant, bool symmetric, const CanonicalForm &evaluation)
Definition: facFqBivar.cc:6117
fq_nmod_poly_t prod
Definition: facHensel.cc:95
mat_zz_pE * convertFacCFMatrix2NTLmat_zz_pE(const CFMatrix &m)
Definition: NTLconvert.cc:1195
bool isInExtension() const
getter
CFList tmp1
Definition: facFqBivar.cc:70
int getGFDegree()
Definition: cf_char.cc:56
Variable x
Definition: cfModGcd.cc:4023
#define GaloisFieldDomain
Definition: cf_defs.h:22
int totaldegree(const CanonicalForm &f)
int totaldegree ( const CanonicalForm & f )
Definition: cf_ops.cc:523
CFList biFactorize(const CanonicalForm &F, const ExtensionInfo &info)
bivariate factorization over finite fields as decribed in "Factoring multivariate polynomials over a ...
Definition: facFqBivar.cc:8201
void henselLiftResume12(const CanonicalForm &F, CFList &factors, int start, int end, CFArray &Pi, const CFList &diophant, CFMatrix &M, const modpk &b)
resume Hensel lift from univariate to bivariate. Assumes factors are lifted to precision Variable (2)...
Definition: facHensel.cc:1214
CanonicalForm reverseSubst(const CanonicalForm &F, const int d, const Variable &x)
reverse a substitution x^d->x
static BOOLEAN IsZero(number a, const coeffs r)
Definition: flintcf_Q.cc:355
#define const
Definition: fegetopt.c:41
TIMING_DEFINE_PRINT(fac_fq_uni_factorizer) TIMING_DEFINE_PRINT(fac_fq_bi_hensel_lift) TIMING_DEFINE_PRINT(fac_fq_bi_factor_recombination) TIMING_DEFINE_PRINT(fac_fq_bi_evaluation) TIMING_DEFINE_PRINT(fac_fq_bi_shift_to_zero) TIMING_DEFINE_PRINT(fac_fq_logarithmic) TIMING_DEFINE_PRINT(fac_fq_compute_lattice_lift) TIMING_DEFINE_PRINT(fac_fq_till_reduced) TIMING_DEFINE_PRINT(fac_fq_reconstruction) TIMING_DEFINE_PRINT(fac_fq_lift) TIMING_DEFINE_PRINT(fac_fq_uni_total) CanonicalForm prodMod0(const CFList &L
CanonicalForm randomIrredpoly(int i, const Variable &x)
computes a random monic irreducible univariate polynomial in x over Fp of degree i via NTL ...
Definition: cf_irred.cc:42
#define ASSERT(expression, message)
Definition: cf_assert.h:99
CFList furtherLiftingAndIncreasePrecisionFq2Fp(CanonicalForm &F, CFList &factors, int l, int liftBound, int d, int *bounds, nmod_mat_t FLINTN, CFList &diophant, CFMatrix &M, CFArray &Pi, CFArray &bufQ, const Variable &alpha, const CanonicalForm &eval)
Definition: facFqBivar.cc:5790
This file provides functions for factorizing a bivariate polynomial over , or GF.
#define DEBOUTLN(stream, objects)
Definition: debug.h:49
CFList furtherLiftingAndIncreasePrecision(CanonicalForm &F, CFList &factors, int l, int liftBound, int d, int *bounds, nmod_mat_t FLINTN, CFList &diophant, CFMatrix &M, CFArray &Pi, CFArray &bufQ, const CanonicalForm &eval)
Definition: facFqBivar.cc:5097
void append(const T &)
Definition: ftmpl_list.cc:256
long fac_NTL_char
Definition: NTLconvert.cc:41
int p
Definition: cfModGcd.cc:4019
int degree(const CanonicalForm &f)
CanonicalForm mapPrimElem(const CanonicalForm &primElem, const Variable &alpha, const Variable &beta)
compute the image of a primitive element of in . We assume .
Definition: cf_map_ext.cc:377
static jList * T
Definition: janet.cc:31
CF_NO_INLINE int exp() const
get the current exponent
CanonicalForm LC(const CanonicalForm &f)
CanonicalForm replacevar(const CanonicalForm &, const Variable &, const Variable &)
CanonicalForm replacevar ( const CanonicalForm & f, const Variable & x1, const Variable & x2 ) ...
Definition: cf_ops.cc:271
static bool irreducible(const CFList &AS)
Definition: cfCharSets.cc:487
Rational pow(const Rational &a, int e)
Definition: GMPrat.cc:414
static Poly * h
Definition: janet.cc:972
int liftAndComputeLatticeFq2Fp(const CanonicalForm &F, int *bounds, int sizeBounds, int start, int liftBound, int minBound, CFList &factors, nmod_mat_t FLINTN, CFList &diophant, CFMatrix &M, CFArray &Pi, CFArray &bufQ, bool &irreducible, const Variable &alpha)
Definition: facFqBivar.cc:3235
class to do operations mod p^k for int&#39;s p and k
Definition: fac_util.h:22
CanonicalForm getGamma() const
getter
CFList extSieveSmallFactors(const CanonicalForm &G, CFList &uniFactors, DegreePattern &degPat, CanonicalForm &H, CFList &diophant, CFArray &Pi, CFMatrix &M, bool &success, int d, const CanonicalForm &evaluation, const ExtensionInfo &info)
Definition: facFqBivar.cc:6716
int * computeBounds(const CanonicalForm &F, int &n, bool &isIrreducible)
compute bounds for logarithmic derivative as described in K. Belabas, M. van Hoeij, J. Klüners, and A. Steel, Factoring polynomials over global fields
template List< Variable > Difference(const List< Variable > &, const List< Variable > &)
return result
Definition: facAbsBiFact.cc:76
int l
Definition: cfEzgcd.cc:93
int getp() const
Definition: fac_util.h:35
Header for factory&#39;s main class CanonicalForm.
CanonicalForm prodMod(const CFList &L, const CanonicalForm &M)
product of all elements in L modulo M via divide-and-conquer.
Definition: facMul.cc:3047
template CanonicalForm tmin(const CanonicalForm &, const CanonicalForm &)
bool inCoeffDomain() const
fq_nmod_ctx_init_modulus(fq_con, FLINTmipo, "Z")