source: git/factory/facFqBivar.cc @ c1f4d51

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