source: git/factory/facFqBivar.cc @ 4439f8e

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