source: git/factory/facFqBivar.cc @ 0facdc

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