source: git/factory/facFqBivar.cc @ d87069

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