source: git/factory/facFqBivar.cc @ 1e9197

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