source: git/factory/facFqBivar.cc @ 45e474

spielwiese
Last change on this file since 45e474 was 45e474, checked in by Martin Lee <martinlee84@…>, 9 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<