source: git/factory/facFqBivar.cc @ 7ed4f6c

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