source: git/factory/facFqBivar.cc @ 894604

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