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

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