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