source: git/factory/facFqBivar.cc @ ffd883

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