source: git/factory/facFqBivar.cc @ 84ac599

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