source: git/factory/facFqBivar.cc @ fea494

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