source: git/factory/facFqBivar.cc @ c1b52b

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