source: git/factory/cf_gcd_smallp.cc @ 9879d0

spielwiese
Last change on this file since 9879d0 was 9879d0, checked in by Martin Lee <martinlee84@…>, 11 years ago
chg: tuning parameter in sparseGCDFp chg: switch to dense modular GCD
  • Property mode set to 100644
File size: 133.7 KB
RevLine 
[10af64]1// -*- c++ -*-
2//*****************************************************************************
3/** @file cf_gcd_smallp.cc
4 *
5 * @author Martin Lee
6 * @date 22.10.2009
7 *
[806c18]8 * This file implements the GCD of two polynomials over \f$ F_{p} \f$ ,
9 * \f$ F_{p}(\alpha ) \f$ or GF based on Alg. 7.2. as described in "Algorithms
[10af64]10 * for Computer Algebra" by Geddes, Czapor, Labahnn
11 *
12 * @par Copyright:
13 *   (c) by The SINGULAR Team, see LICENSE file
14 *
15**/
16//*****************************************************************************
17
[e4fe2b]18#include "config.h"
[10af64]19
[650f2d8]20#include "cf_assert.h"
[10af64]21#include "debug.h"
22#include "timing.h"
23
24#include "canonicalform.h"
[81d96c]25#include "algext.h"
[10af64]26#include "cf_map.h"
[88f3644]27#include "cf_util.h"
[6db552]28#include "templates/ftmpl_functions.h"
[10af64]29#include "cf_random.h"
[0349c20]30#include "cf_reval.h"
[08daea]31#include "facHensel.h"
[015711]32#include "cf_iter.h"
[e243418]33#include "cfNewtonPolygon.h"
[517530]34#include "cf_algorithm.h"
[0d74e7]35#include "cf_primes.h"
[10af64]36
[c4f4fd]37// iinline helper functions:
[51615d6]38#include "cf_map_ext.h"
[9c115e1]39
[10af64]40#ifdef HAVE_NTL
[04dd0c]41#include <NTLconvert.h>
[10af64]42#endif
43
[8fa570]44#ifdef HAVE_FLINT
45#include "FLINTconvert.h"
46#endif
47
[911444]48#include "cf_gcd_smallp.h"
49
[e76d7a6]50TIMING_DEFINE_PRINT(gcd_recursion)
51TIMING_DEFINE_PRINT(newton_interpolation)
[2a95b2]52TIMING_DEFINE_PRINT(termination_test)
53TIMING_DEFINE_PRINT(ez_p_compress)
54TIMING_DEFINE_PRINT(ez_p_hensel_lift)
55TIMING_DEFINE_PRINT(ez_p_eval)
56TIMING_DEFINE_PRINT(ez_p_content)
[10af64]57
[1e4b53]58bool
59terminationTest (const CanonicalForm& F, const CanonicalForm& G,
60                 const CanonicalForm& coF, const CanonicalForm& coG,
61                 const CanonicalForm& cand)
62{
63  CanonicalForm LCCand= abs (LC (cand));
64  if (LCCand*abs (LC (coF)) == abs (LC (F)))
65  {
66    if (LCCand*abs (LC (coG)) == abs (LC (G)))
67    {
68      if (abs (cand)*abs (coF) == abs (F))
69      {
70        if (abs (cand)*abs (coG) == abs (G))
71          return true;
72      }
73      return false;
74    }
75    return false;
76  }
77  return false;
78}
79
[517530]80#ifdef HAVE_NTL
81
[08daea]82static const double log2exp= 1.442695041;
83
[806c18]84/// compressing two polynomials F and G, M is used for compressing,
[10af64]85/// N to reverse the compression
86int myCompress (const CanonicalForm& F, const CanonicalForm& G, CFMap & M,
[08daea]87                CFMap & N, bool topLevel)
[806c18]88{
[10af64]89  int n= tmax (F.level(), G.level());
90  int * degsf= new int [n + 1];
91  int * degsg= new int [n + 1];
92
93  for (int i = 0; i <= n; i++)
94    degsf[i]= degsg[i]= 0;
[806c18]95
[10af64]96  degsf= degrees (F, degsf);
97  degsg= degrees (G, degsg);
[806c18]98
[10af64]99  int both_non_zero= 0;
100  int f_zero= 0;
101  int g_zero= 0;
102  int both_zero= 0;
103
[806c18]104  if (topLevel)
[10af64]105  {
[806c18]106    for (int i= 1; i <= n; i++)
[10af64]107    {
[806c18]108      if (degsf[i] != 0 && degsg[i] != 0)
[10af64]109      {
110        both_non_zero++;
111        continue;
112      }
[806c18]113      if (degsf[i] == 0 && degsg[i] != 0 && i <= G.level())
[10af64]114      {
115        f_zero++;
116        continue;
117      }
[806c18]118      if (degsg[i] == 0 && degsf[i] && i <= F.level())
[10af64]119      {
120        g_zero++;
121        continue;
122      }
123    }
124
[806c18]125    if (both_non_zero == 0)
[dec1024]126    {
127      delete [] degsf;
128      delete [] degsg;
129      return 0;
130    }
[10af64]131
132    // map Variables which do not occur in both polynomials to higher levels
133    int k= 1;
134    int l= 1;
[806c18]135    for (int i= 1; i <= n; i++)
136    {
137      if (degsf[i] != 0 && degsg[i] == 0 && i <= F.level())
[10af64]138      {
[806c18]139        if (k + both_non_zero != i)
[10af64]140        {
141          M.newpair (Variable (i), Variable (k + both_non_zero));
142          N.newpair (Variable (k + both_non_zero), Variable (i));
143        }
144        k++;
145      }
[806c18]146      if (degsf[i] == 0 && degsg[i] != 0 && i <= G.level())
[10af64]147      {
[806c18]148        if (l + g_zero + both_non_zero != i)
[10af64]149        {
150          M.newpair (Variable (i), Variable (l + g_zero + both_non_zero));
151          N.newpair (Variable (l + g_zero + both_non_zero), Variable (i));
152        }
153        l++;
154      }
155    }
[806c18]156
[10af64]157    // sort Variables x_{i} in increasing order of
[806c18]158    // min(deg_{x_{i}}(f),deg_{x_{i}}(g))
[9ff686]159    int m= tmax (F.level(), G.level());
160    int min_max_deg;
[10af64]161    k= both_non_zero;
162    l= 0;
163    int i= 1;
[806c18]164    while (k > 0)
[10af64]165    {
[9ff686]166      if (degsf [i] != 0 && degsg [i] != 0)
167        min_max_deg= tmax (degsf[i], degsg[i]);
168      else
169        min_max_deg= 0;
170      while (min_max_deg == 0)
[10af64]171      {
172        i++;
[9ff686]173        if (degsf [i] != 0 && degsg [i] != 0)
174          min_max_deg= tmax (degsf[i], degsg[i]);
175        else
176          min_max_deg= 0;
[10af64]177      }
[806c18]178      for (int j= i + 1; j <=  m; j++)
[10af64]179      {
[9ff686]180        if (degsf[j] != 0 && degsg [j] != 0 &&
181            tmax (degsf[j],degsg[j]) <= min_max_deg)
[10af64]182        {
[9ff686]183          min_max_deg= tmax (degsf[j], degsg[j]);
[806c18]184          l= j;
[10af64]185        }
186      }
[806c18]187      if (l != 0)
[10af64]188      {
[806c18]189        if (l != k)
[10af64]190        {
191          M.newpair (Variable (l), Variable(k));
192          N.newpair (Variable (k), Variable(l));
193          degsf[l]= 0;
194          degsg[l]= 0;
195          l= 0;
196        }
[806c18]197        else
[10af64]198        {
199          degsf[l]= 0;
200          degsg[l]= 0;
201          l= 0;
202        }
[806c18]203      }
204      else if (l == 0)
[10af64]205      {
[806c18]206        if (i != k)
[10af64]207        {
208          M.newpair (Variable (i), Variable (k));
209          N.newpair (Variable (k), Variable (i));
210          degsf[i]= 0;
211          degsg[i]= 0;
212        }
[806c18]213        else
[10af64]214        {
215          degsf[i]= 0;
216          degsg[i]= 0;
217        }
218        i++;
[806c18]219      }
[10af64]220      k--;
221    }
222  }
[806c18]223  else
[10af64]224  {
225    //arrange Variables such that no gaps occur
[806c18]226    for (int i= 1; i <= n; i++)
[10af64]227    {
[806c18]228      if (degsf[i] == 0 && degsg[i] == 0)
[10af64]229      {
230        both_zero++;
231        continue;
232      }
[806c18]233      else
[10af64]234      {
[806c18]235        if (both_zero != 0)
[10af64]236        {
237          M.newpair (Variable (i), Variable (i - both_zero));
238          N.newpair (Variable (i - both_zero), Variable (i));
239        }
240      }
241    }
242  }
243
244  delete [] degsf;
245  delete [] degsg;
246
[c4f4fd]247  return 1;
[10af64]248}
249
[806c18]250static inline CanonicalForm
[dec1024]251uni_content (const CanonicalForm & F);
252
253CanonicalForm
254uni_content (const CanonicalForm& F, const Variable& x)
255{
256  if (F.inCoeffDomain())
257    return F.genOne();
258  if (F.level() == x.level() && F.isUnivariate())
259    return F;
260  if (F.level() != x.level() && F.isUnivariate())
261    return F.genOne();
[806c18]262
[dec1024]263  if (x.level() != 1)
264  {
265    CanonicalForm f= swapvar (F, x, Variable (1));
266    CanonicalForm result= uni_content (f);
267    return swapvar (result, x, Variable (1));
268  }
269  else
270    return uni_content (F);
[806c18]271}
[dec1024]272
[806c18]273/// compute the content of F, where F is considered as an element of
274/// \f$ R[x_{1}][x_{2},\ldots ,x_{n}] \f$
275static inline CanonicalForm
276uni_content (const CanonicalForm & F)
277{
[10af64]278  if (F.inBaseDomain())
279    return F.genOne();
280  if (F.level() == 1 && F.isUnivariate())
281    return F;
282  if (F.level() != 1 && F.isUnivariate())
283    return F.genOne();
[c4f4fd]284  if (degree (F,1) == 0) return F.genOne();
[10af64]285
286  int l= F.level();
[806c18]287  if (l == 2)
[10af64]288    return content(F);
[806c18]289  else
[10af64]290  {
291    CanonicalForm pol, c = 0;
292    CFIterator i = F;
[806c18]293    for (; i.hasTerms(); i++)
[10af64]294    {
[806c18]295      pol= i.coeff();
[10af64]296      pol= uni_content (pol);
297      c= gcd (c, pol);
298      if (c.isOne())
299        return c;
300    }
301    return c;
302  }
303}
304
[806c18]305CanonicalForm
306extractContents (const CanonicalForm& F, const CanonicalForm& G,
307                 CanonicalForm& contentF, CanonicalForm& contentG,
[dec1024]308                 CanonicalForm& ppF, CanonicalForm& ppG, const int d)
309{
310  CanonicalForm uniContentF, uniContentG, gcdcFcG;
311  contentF= 1;
312  contentG= 1;
313  ppF= F;
314  ppG= G;
315  CanonicalForm result= 1;
316  for (int i= 1; i <= d; i++)
317  {
318    uniContentF= uni_content (F, Variable (i));
319    uniContentG= uni_content (G, Variable (i));
320    gcdcFcG= gcd (uniContentF, uniContentG);
321    contentF *= uniContentF;
322    contentG *= uniContentG;
323    ppF /= uniContentF;
324    ppG /= uniContentG;
325    result *= gcdcFcG;
326  }
327  return result;
328}
329
[10af64]330/// compute the leading coefficient of F, where F is considered as an element
331/// of \f$ R[x_{1}][x_{2},\ldots ,x_{n}] \f$, order on Mon (x_{2},\ldots ,x_{n})
[c4f4fd]332/// is dp.
[10af64]333static inline
[806c18]334CanonicalForm uni_lcoeff (const CanonicalForm& F)
[10af64]335{
[c1b9927]336  if (F.level() > 1)
[10af64]337  {
338    Variable x= Variable (2);
339    int deg= totaldegree (F, x, F.mvar());
340    for (CFIterator i= F; i.hasTerms(); i++)
341    {
342      if (i.exp() + totaldegree (i.coeff(), x, i.coeff().mvar()) == deg)
[806c18]343        return uni_lcoeff (i.coeff());
[10af64]344    }
345  }
[c1b9927]346  return F;
[10af64]347}
348
349/// Newton interpolation - Incremental algorithm.
350/// Given a list of values alpha_i and a list of polynomials u_i, 1 <= i <= n,
351/// computes the interpolation polynomial assuming that
352/// the polynomials in u are the results of evaluating the variabe x
353/// of the unknown polynomial at the alpha values.
354/// This incremental version receives only the values of alpha_n and u_n and
355/// the previous interpolation polynomial for points 1 <= i <= n-1, and computes
356/// the polynomial interpolating in all the points.
357/// newtonPoly must be equal to (x - alpha_1) * ... * (x - alpha_{n-1})
358static inline CanonicalForm
[9ff686]359newtonInterp(const CanonicalForm alpha, const CanonicalForm u,
360             const CanonicalForm newtonPoly, const CanonicalForm oldInterPoly,
361             const Variable & x)
[10af64]362{
363  CanonicalForm interPoly;
364
[9ff686]365  interPoly= oldInterPoly + ((u - oldInterPoly(alpha, x))/newtonPoly(alpha, x))
366             *newtonPoly;
[10af64]367  return interPoly;
368}
369
[806c18]370/// compute a random element a of \f$ F_{p}(\alpha ) \f$ ,
[10af64]371/// s.t. F(a) \f$ \neq 0 \f$ , F is a univariate polynomial, returns
[806c18]372/// fail if there are no field elements left which have not been used before
373static inline CanonicalForm
[10af64]374randomElement (const CanonicalForm & F, const Variable & alpha, CFList & list,
[806c18]375               bool & fail)
[10af64]376{
377  fail= false;
378  Variable x= F.mvar();
379  AlgExtRandomF genAlgExt (alpha);
380  FFRandom genFF;
381  CanonicalForm random, mipo;
382  mipo= getMipo (alpha);
383  int p= getCharacteristic ();
384  int d= degree (mipo);
[c4f4fd]385  int bound= ipower (p, d);
[806c18]386  do
[10af64]387  {
388    if (list.length() == bound)
389    {
390      fail= true;
391      break;
392    }
[806c18]393    if (list.length() < p)
[10af64]394    {
395      random= genFF.generate();
396      while (find (list, random))
397        random= genFF.generate();
398    }
[806c18]399    else
[10af64]400    {
401      random= genAlgExt.generate();
402      while (find (list, random))
403        random= genAlgExt.generate();
404    }
[806c18]405    if (F (random, x) == 0)
[10af64]406    {
407      list.append (random);
408      continue;
409    }
410  } while (find (list, random));
411  return random;
412}
413
[9ff686]414static inline
415Variable chooseExtension (const Variable & alpha)
416{
[bffe62d]417  if (fac_NTL_char != getCharacteristic())
418  {
419    fac_NTL_char= getCharacteristic();
420    zz_p::init (getCharacteristic());
421  }
[9ff686]422  zz_pX NTLIrredpoly;
423  int i, m;
424  // extension of F_p needed
425  if (alpha.level() == 1)
426  {
427    i= 1;
428    m= 2;
429  } //extension of F_p(alpha)
430  if (alpha.level() != 1)
431  {
432    i= 4;
433    m= degree (getMipo (alpha));
434  }
435  BuildIrred (NTLIrredpoly, i*m);
436  CanonicalForm newMipo= convertNTLzzpX2CF (NTLIrredpoly, Variable (1));
437  return rootOf (newMipo);
438}
439
[806c18]440/// chooses a suitable extension of \f$ F_{p}(\alpha ) \f$
[10af64]441/// we do not extend \f$ F_{p}(\alpha ) \f$ itself but extend \f$ F_{p} \f$ ,
[806c18]442/// s.t. \f$ F_{p}(\alpha ) \subset F_{p}(\beta ) \f$
[10af64]443static inline
[806c18]444void choose_extension (const int& d, const int& num_vars, Variable& beta)
[10af64]445{
446  int p= getCharacteristic();
[bffe62d]447  if (p != fac_NTL_char)
448  {
449    fac_NTL_char= p;
450    zz_p::init (p);
451  }
[9a12097]452  zz_pX NTLirredpoly;
[10af64]453  //TODO: replace d by max_{i} (deg_x{i}(f))
[806c18]454  int i= (int) (log ((double) ipower (d + 1, num_vars))/log ((double) p));
[10af64]455  int m= degree (getMipo (beta));
456  if (i <= 1)
457    i= 2;
[806c18]458  BuildIrred (NTLirredpoly, i*m);
[9a12097]459  CanonicalForm mipo= convertNTLzzpX2CF (NTLirredpoly, Variable(1));
[806c18]460  beta= rootOf (mipo);
[10af64]461}
462
[597783]463CanonicalForm
464GCD_Fp_extension (const CanonicalForm& F, const CanonicalForm& G,
465                  CanonicalForm& coF, CanonicalForm& coG,
466                  Variable & alpha, CFList& l, bool& topLevel);
467
468CanonicalForm
469GCD_Fp_extension (const CanonicalForm& F, const CanonicalForm& G,
470                  Variable & alpha, CFList& l, bool& topLevel)
471{
472  CanonicalForm dummy1, dummy2;
473  CanonicalForm result= GCD_Fp_extension (F, G, dummy1, dummy2, alpha, l,
474                                          topLevel);
475  return result;
476}
477
[806c18]478/// GCD of F and G over \f$ F_{p}(\alpha ) \f$ ,
[dec1024]479/// l and topLevel are only used internally, output is monic
[10af64]480/// based on Alg. 7.2. as described in "Algorithms for
481/// Computer Algebra" by Geddes, Czapor, Labahn
[806c18]482CanonicalForm
483GCD_Fp_extension (const CanonicalForm& F, const CanonicalForm& G,
[597783]484                  CanonicalForm& coF, CanonicalForm& coG,
[806c18]485                  Variable & alpha, CFList& l, bool& topLevel)
486{
[10af64]487  CanonicalForm A= F;
488  CanonicalForm B= G;
[597783]489  if (F.isZero() && degree(G) > 0)
490  {
491    coF= 0;
492    coG= Lc (G);
493    return G/Lc(G);
494  }
495  else if (G.isZero() && degree (F) > 0)
496  {
497    coF= Lc (F);
498    coG= 0;
499    return F/Lc(F);
500  }
501  else if (F.isZero() && G.isZero())
502  {
503    coF= coG= 0;
504    return F.genOne();
505  }
506  if (F.inBaseDomain() || G.inBaseDomain())
507  {
508    coF= F;
509    coG= G;
510    return F.genOne();
511  }
512  if (F.isUnivariate() && fdivides(F, G, coG))
513  {
514    coF= Lc (F);
515    return F/Lc(F);
516  }
517  if (G.isUnivariate() && fdivides(G, F, coF))
518  {
519    coG= Lc (G);
520    return G/Lc(G);
521  }
522  if (F == G)
523  {
524    coF= coG= Lc (F);
525    return F/Lc(F);
526  }
[806c18]527
[10af64]528  CFMap M,N;
[dec1024]529  int best_level= myCompress (A, B, M, N, topLevel);
[10af64]530
[597783]531  if (best_level == 0)
532  {
533    coF= F;
534    coG= G;
535    return B.genOne();
536  }
[10af64]537
538  A= M(A);
539  B= M(B);
540
541  Variable x= Variable(1);
542
[806c18]543  //univariate case
544  if (A.isUnivariate() && B.isUnivariate())
[597783]545  {
546    CanonicalForm result= gcd (A, B);
547    coF= N (A/result);
548    coG= N (B/result);
549    return N (result);
550  }
[806c18]551
[10af64]552  CanonicalForm cA, cB;    // content of A and B
553  CanonicalForm ppA, ppB;    // primitive part of A and B
554  CanonicalForm gcdcAcB;
[c4f4fd]555
[ea5ff1d]556  cA = uni_content (A);
557  cB = uni_content (B);
558  gcdcAcB= gcd (cA, cB);
559  ppA= A/cA;
560  ppB= B/cB;
[10af64]561
[e243418]562  int sizeNewtonPolyg;
563  int ** newtonPolyg= NULL;
564  mat_ZZ MM;
565  vec_ZZ V;
[ea095d]566  bool compressConvexDense= false; //(ppA.level() == 2 && ppB.level() == 2);
[e243418]567  if (compressConvexDense)
568  {
[597783]569    CanonicalForm bufcA= cA;
570    CanonicalForm bufcB= cB;
[e243418]571    cA= content (ppA, 1);
572    cB= content (ppB, 1);
573    ppA /= cA;
574    ppB /= cB;
575    gcdcAcB *= gcd (cA, cB);
[597783]576    cA *= bufcA;
577    cB *= bufcB;
[e243418]578    if (ppA.isUnivariate() || ppB.isUnivariate())
579    {
580      if (ppA.level() == ppB.level())
[597783]581      {
582        CanonicalForm result= gcd (ppA, ppB);
583        coF= N ((ppA/result)*(cA/gcdcAcB));
584        coG= N ((ppB/result)*(cB/gcdcAcB));
585        return N (result*gcdcAcB);
586      }
[e243418]587      else
[597783]588      {
589        coF= N (ppA*(cA/gcdcAcB));
590        coG= N (ppB*(cB/gcdcAcB));
[a9a6dcb]591        return N (gcdcAcB);
[597783]592      }
[e243418]593    }
594
595    newtonPolyg= newtonPolygon (ppA,ppB, sizeNewtonPolyg);
596    convexDense (newtonPolyg, sizeNewtonPolyg, MM, V);
597
598    for (int i= 0; i < sizeNewtonPolyg; i++)
599      delete [] newtonPolyg[i];
600    delete [] newtonPolyg;
601
602    ppA= compress (ppA, MM, V, false);
603    ppB= compress (ppB, MM, V, false);
604    MM= inv (MM);
605
606    if (ppA.isUnivariate() && ppB.isUnivariate())
607    {
608      if (ppA.level() == ppB.level())
[597783]609      {
610        CanonicalForm result= gcd (ppA, ppB);
611        coF= N (decompress ((ppA/result), MM, V)*(cA/gcdcAcB));
612        coG= N (decompress ((ppB/result), MM, V)*(cB/gcdcAcB));
613        return N (decompress (result, MM, V)*gcdcAcB);
614      }
[e243418]615      else
[597783]616      {
617        coF= N (decompress (ppA, MM, V));
618        coG= N (decompress (ppB, MM, V));
[a9a6dcb]619        return N (gcdcAcB);
[597783]620      }
[e243418]621    }
622  }
623
[10af64]624  CanonicalForm lcA, lcB;  // leading coefficients of A and B
[806c18]625  CanonicalForm gcdlcAlcB;
[10af64]626
627  lcA= uni_lcoeff (ppA);
628  lcB= uni_lcoeff (ppB);
[806c18]629
[597783]630  /*if (fdivides (lcA, lcB))
[806c18]631  {
[10af64]632    if (fdivides (A, B))
[806c18]633      return F/Lc(F);
[10af64]634  }
635  if (fdivides (lcB, lcA))
[806c18]636  {
637    if (fdivides (B, A))
[10af64]638      return G/Lc(G);
[597783]639  }*/
[10af64]640
641  gcdlcAlcB= gcd (lcA, lcB);
642
643  int d= totaldegree (ppA, Variable(2), Variable (ppA.level()));
644
[dec1024]645  if (d == 0)
[597783]646  {
647    coF= N (ppA*(cA/gcdcAcB));
648    coG= N (ppB*(cB/gcdcAcB));
[a9a6dcb]649    return N(gcdcAcB);
[597783]650  }
[a9a6dcb]651
[10af64]652  int d0= totaldegree (ppB, Variable(2), Variable (ppB.level()));
[806c18]653  if (d0 < d)
654    d= d0;
[dec1024]655  if (d == 0)
[597783]656  {
657    coF= N (ppA*(cA/gcdcAcB));
658    coG= N (ppB*(cB/gcdcAcB));
[a9a6dcb]659    return N(gcdcAcB);
[597783]660  }
[10af64]661
662  CanonicalForm m, random_element, G_m, G_random_element, H, cH, ppH;
[597783]663  CanonicalForm newtonPoly, coF_random_element, coG_random_element, coF_m,
664                coG_m, ppCoF, ppCoG;
[10af64]665
666  newtonPoly= 1;
667  m= gcdlcAlcB;
668  G_m= 0;
[597783]669  coF= 0;
670  coG= 0;
[10af64]671  H= 0;
672  bool fail= false;
[dec1024]673  topLevel= false;
[10af64]674  bool inextension= false;
675  Variable V_buf= alpha;
676  CanonicalForm prim_elem, im_prim_elem;
677  CFList source, dest;
[597783]678  int bound1= degree (ppA, 1);
679  int bound2= degree (ppB, 1);
[806c18]680  do
[10af64]681  {
[597783]682    random_element= randomElement (m*lcA*lcB, V_buf, l, fail);
[806c18]683    if (fail)
[10af64]684    {
685      source= CFList();
686      dest= CFList();
[c4f4fd]687
[9ff686]688      Variable V_buf3= V_buf;
689      V_buf= chooseExtension (V_buf);
[10af64]690      bool prim_fail= false;
691      Variable V_buf2;
692      prim_elem= primitiveElement (alpha, V_buf2, prim_fail);
[c4f4fd]693
[9ff686]694      if (V_buf3 != alpha)
695      {
696        m= mapDown (m, prim_elem, im_prim_elem, alpha, source, dest);
[597783]697        G_m= mapDown (G_m, prim_elem, im_prim_elem, alpha, source, dest);
698        coF_m= mapDown (coF_m, prim_elem, im_prim_elem, alpha, source, dest);
699        coG_m= mapDown (coG_m, prim_elem, im_prim_elem, alpha, source, dest);
[9ff686]700        newtonPoly= mapDown (newtonPoly, prim_elem, im_prim_elem, alpha,
701                             source, dest);
702        ppA= mapDown (ppA, prim_elem, im_prim_elem, alpha, source, dest);
703        ppB= mapDown (ppB, prim_elem, im_prim_elem, alpha, source, dest);
704        gcdlcAlcB= mapDown (gcdlcAlcB, prim_elem, im_prim_elem, alpha,
705                            source, dest);
[597783]706        lcA= mapDown (lcA, prim_elem, im_prim_elem, alpha, source, dest);
707        lcB= mapDown (lcB, prim_elem, im_prim_elem, alpha, source, dest);
[9ff686]708        for (CFListIterator i= l; i.hasItem(); i++)
709          i.getItem()= mapDown (i.getItem(), prim_elem, im_prim_elem, alpha,
710                                source, dest);
711      }
712
[10af64]713      ASSERT (!prim_fail, "failure in integer factorizer");
714      if (prim_fail)
715        ; //ERROR
716      else
717        im_prim_elem= mapPrimElem (prim_elem, alpha, V_buf);
[c4f4fd]718
[10af64]719      DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (alpha));
[04dd0c]720      DEBOUTLN (cerr, "getMipo (V_buf2)= " << getMipo (V_buf2));
[10af64]721      inextension= true;
[806c18]722      for (CFListIterator i= l; i.hasItem(); i++)
723        i.getItem()= mapUp (i.getItem(), alpha, V_buf, prim_elem,
[10af64]724                             im_prim_elem, source, dest);
725      m= mapUp (m, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
726      G_m= mapUp (G_m, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
[597783]727      coF_m= mapUp (coF_m, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
728      coG_m= mapUp (coG_m, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
[806c18]729      newtonPoly= mapUp (newtonPoly, alpha, V_buf, prim_elem, im_prim_elem,
[10af64]730                          source, dest);
731      ppA= mapUp (ppA, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
732      ppB= mapUp (ppB, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
[806c18]733      gcdlcAlcB= mapUp (gcdlcAlcB, alpha, V_buf, prim_elem, im_prim_elem,
[10af64]734                         source, dest);
[597783]735      lcA= mapUp (lcA, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
736      lcB= mapUp (lcB, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
[10af64]737
738      fail= false;
[597783]739      random_element= randomElement (m*lcA*lcB, V_buf, l, fail );
[a5cc7b3]740      DEBOUTLN (cerr, "fail= " << fail);
[10af64]741      CFList list;
742      TIMING_START (gcd_recursion);
[806c18]743      G_random_element=
[597783]744      GCD_Fp_extension (ppA (random_element, x), ppB (random_element, x),
745                        coF_random_element, coG_random_element, V_buf,
[dec1024]746                        list, topLevel);
[806c18]747      TIMING_END_AND_PRINT (gcd_recursion,
[10af64]748                            "time for recursive call: ");
749      DEBOUTLN (cerr, "G_random_element= " << G_random_element);
750    }
[806c18]751    else
[10af64]752    {
753      CFList list;
754      TIMING_START (gcd_recursion);
[806c18]755      G_random_element=
[597783]756      GCD_Fp_extension (ppA(random_element, x), ppB(random_element, x),
757                        coF_random_element, coG_random_element, V_buf,
[dec1024]758                        list, topLevel);
[806c18]759      TIMING_END_AND_PRINT (gcd_recursion,
[10af64]760                            "time for recursive call: ");
761      DEBOUTLN (cerr, "G_random_element= " << G_random_element);
762    }
763
[a76d6fe]764    if (!G_random_element.inCoeffDomain())
765      d0= totaldegree (G_random_element, Variable(2),
766                       Variable (G_random_element.level()));
767    else
768      d0= 0;
769
[dec1024]770    if (d0 == 0)
[597783]771    {
772      coF= N (ppA*(cA/gcdcAcB));
773      coG= N (ppB*(cB/gcdcAcB));
[a9a6dcb]774      return N(gcdcAcB);
[597783]775    }
[806c18]776    if (d0 >  d)
[10af64]777    {
778      if (!find (l, random_element))
779        l.append (random_element);
780      continue;
781    }
782
[806c18]783    G_random_element=
[10af64]784    (gcdlcAlcB(random_element, x)/uni_lcoeff (G_random_element))
785    * G_random_element;
[597783]786    coF_random_element= (lcA(random_element,x)/uni_lcoeff(coF_random_element))
787                        *coF_random_element;
788    coG_random_element= (lcB(random_element,x)/uni_lcoeff(coG_random_element))
789                        *coG_random_element;
[10af64]790
[a76d6fe]791    if (!G_random_element.inCoeffDomain())
792      d0= totaldegree (G_random_element, Variable(2),
793                       Variable (G_random_element.level()));
794    else
795      d0= 0;
796
[806c18]797    if (d0 <  d)
[10af64]798    {
799      m= gcdlcAlcB;
800      newtonPoly= 1;
801      G_m= 0;
802      d= d0;
[597783]803      coF_m= 0;
804      coG_m= 0;
[10af64]805    }
806
807    TIMING_START (newton_interpolation);
808    H= newtonInterp (random_element, G_random_element, newtonPoly, G_m, x);
[597783]809    coF= newtonInterp (random_element, coF_random_element, newtonPoly, coF_m,x);
810    coG= newtonInterp (random_element, coG_random_element, newtonPoly, coG_m,x);
[806c18]811    TIMING_END_AND_PRINT (newton_interpolation,
[10af64]812                          "time for newton interpolation: ");
813
[806c18]814    //termination test
[597783]815    if ((uni_lcoeff (H) == gcdlcAlcB) || (G_m == H))
[10af64]816    {
[2a95b2]817      TIMING_START (termination_test);
[597783]818      if (gcdlcAlcB.isOne())
819        cH= 1;
820      else
821        cH= uni_content (H);
[10af64]822      ppH= H/cH;
[597783]823      CanonicalForm lcppH= gcdlcAlcB/cH;
824      CanonicalForm ccoF= lcA/lcppH;
825      ccoF /= Lc (ccoF);
826      CanonicalForm ccoG= lcB/lcppH;
827      ccoG /= Lc (ccoG);
828      ppCoF= coF/ccoF;
829      ppCoG= coG/ccoG;
[806c18]830      if (inextension)
[10af64]831      {
[597783]832        if (((degree (ppCoF,1)+degree (ppH,1) == bound1) &&
833             (degree (ppCoG,1)+degree (ppH,1) == bound2) &&
[1e4b53]834             terminationTest (ppA, ppB, ppCoF, ppCoG, ppH)) || 
[597783]835             (fdivides (ppH, ppA, ppCoF) && fdivides (ppH, ppB, ppCoG)))
[dec1024]836        {
[597783]837          CFList u, v;
[c723d80]838          DEBOUTLN (cerr, "ppH before mapDown= " << ppH);
[621271b]839          ppH /= Lc(ppH);
[c723d80]840          ppH= mapDown (ppH, prim_elem, im_prim_elem, alpha, u, v);
[597783]841          ppCoF= mapDown (ppCoF, prim_elem, im_prim_elem, alpha, u, v);
[f4d7641]842          ppCoG= mapDown (ppCoG, prim_elem, im_prim_elem, alpha, u, v);
[c723d80]843          DEBOUTLN (cerr, "ppH after mapDown= " << ppH);
[e243418]844          if (compressConvexDense)
[597783]845          {
[e243418]846            ppH= decompress (ppH, MM, V);
[597783]847            ppCoF= decompress (ppCoF, MM, V);
848            ppCoG= decompress (ppCoG, MM, V);
849          }
850          coF= N ((cA/gcdcAcB)*ppCoF);
851          coG= N ((cB/gcdcAcB)*ppCoG);
[2a95b2]852          TIMING_END_AND_PRINT (termination_test,
853                                "time for successful termination test Fq: ");
[10af64]854          return N(gcdcAcB*ppH);
[dec1024]855        }
[10af64]856      }
[597783]857      else if (((degree (ppCoF,1)+degree (ppH,1) == bound1) &&
858                (degree (ppCoG,1)+degree (ppH,1) == bound2) &&
[1e4b53]859                terminationTest (ppA, ppB, ppCoF, ppCoG, ppH)) ||
[597783]860                (fdivides (ppH, ppA, ppCoF) && fdivides (ppH, ppB, ppCoG)))
[dec1024]861      {
[e243418]862        if (compressConvexDense)
[597783]863        {
[e243418]864          ppH= decompress (ppH, MM, V);
[597783]865          ppCoF= decompress (ppCoF, MM, V);
866          ppCoG= decompress (ppCoG, MM, V);
867        }
868        coF= N ((cA/gcdcAcB)*ppCoF);
[2a95b2]869        coG= N ((cB/gcdcAcB)*ppCoG);
870        TIMING_END_AND_PRINT (termination_test,
871                              "time for successful termination test Fq: ");
[dec1024]872        return N(gcdcAcB*ppH);
873      }
[2a95b2]874      TIMING_END_AND_PRINT (termination_test,
875                            "time for unsuccessful termination test Fq: ");
[10af64]876    }
877
878    G_m= H;
[597783]879    coF_m= coF;
880    coG_m= coG;
[10af64]881    newtonPoly= newtonPoly*(x - random_element);
882    m= m*(x - random_element);
883    if (!find (l, random_element))
884      l.append (random_element);
885  } while (1);
886}
887
[806c18]888/// compute a random element a of GF, s.t. F(a) \f$ \neq 0 \f$ , F is a
[10af64]889/// univariate polynomial, returns fail if there are no field elements left
890/// which have not been used before
[04dd0c]891static inline
[10af64]892CanonicalForm
893GFRandomElement (const CanonicalForm& F, CFList& list, bool& fail)
894{
895  fail= false;
896  Variable x= F.mvar();
897  GFRandom genGF;
898  CanonicalForm random;
899  int p= getCharacteristic();
900  int d= getGFDegree();
[c4f4fd]901  int bound= ipower (p, d);
[806c18]902  do
[10af64]903  {
904    if (list.length() == bound)
905    {
906      fail= true;
907      break;
908    }
909    if (list.length() < 1)
910      random= 0;
[806c18]911    else
[10af64]912    {
913      random= genGF.generate();
914      while (find (list, random))
915        random= genGF.generate();
916    }
[806c18]917    if (F (random, x) == 0)
[10af64]918    {
919      list.append (random);
920      continue;
921    }
922  } while (find (list, random));
923  return random;
924}
925
[597783]926CanonicalForm
927GCD_GF (const CanonicalForm& F, const CanonicalForm& G,
928        CanonicalForm& coF, CanonicalForm& coG,
929        CFList& l, bool& topLevel);
930
931CanonicalForm
932GCD_GF (const CanonicalForm& F, const CanonicalForm& G, CFList& l,
933        bool& topLevel)
934{
935  CanonicalForm dummy1, dummy2;
936  CanonicalForm result= GCD_GF (F, G, dummy1, dummy2, l, topLevel);
937  return result;
938}
939
[10af64]940/// GCD of F and G over GF, based on Alg. 7.2. as described in "Algorithms for
941/// Computer Algebra" by Geddes, Czapor, Labahn
942/// Usually this algorithm will be faster than GCD_Fp_extension since GF has
943/// faster field arithmetics, however it might fail if the input is large since
944/// the size of the base field is bounded by 2^16, output is monic
[597783]945CanonicalForm
946GCD_GF (const CanonicalForm& F, const CanonicalForm& G,
947        CanonicalForm& coF, CanonicalForm& coG,
[806c18]948        CFList& l, bool& topLevel)
949{
[10af64]950  CanonicalForm A= F;
951  CanonicalForm B= G;
[597783]952  if (F.isZero() && degree(G) > 0)
953  {
954    coF= 0;
955    coG= Lc (G);
956    return G/Lc(G);
957  }
958  else if (G.isZero() && degree (F) > 0)
959  {
960    coF= Lc (F);
961    coG= 0;
962    return F/Lc(F);
963  }
964  else if (F.isZero() && G.isZero())
965  {
966    coF= coG= 0;
967    return F.genOne();
968  }
969  if (F.inBaseDomain() || G.inBaseDomain())
970  {
971    coF= F;
972    coG= G;
973    return F.genOne();
974  }
975  if (F.isUnivariate() && fdivides(F, G, coG))
976  {
977    coF= Lc (F);
978    return F/Lc(F);
979  }
980  if (G.isUnivariate() && fdivides(G, F, coF))
981  {
982    coG= Lc (G);
983    return G/Lc(G);
984  }
985  if (F == G)
986  {
987    coF= coG= Lc (F);
988    return F/Lc(F);
989  }
[806c18]990
[10af64]991  CFMap M,N;
[dec1024]992  int best_level= myCompress (A, B, M, N, topLevel);
[10af64]993
[597783]994  if (best_level == 0)
995  {
996    coF= F;
997    coG= G;
998    return B.genOne();
999  }
[10af64]1000
1001  A= M(A);
1002  B= M(B);
1003
1004  Variable x= Variable(1);
1005
[806c18]1006  //univariate case
1007  if (A.isUnivariate() && B.isUnivariate())
[597783]1008  {
1009    CanonicalForm result= gcd (A, B);
1010    coF= N (A/result);
1011    coG= N (B/result);
1012    return N (result);
1013  }
[10af64]1014
1015  CanonicalForm cA, cB;    // content of A and B
1016  CanonicalForm ppA, ppB;    // primitive part of A and B
1017  CanonicalForm gcdcAcB;
1018
[ea5ff1d]1019  cA = uni_content (A);
1020  cB = uni_content (B);
1021  gcdcAcB= gcd (cA, cB);
1022  ppA= A/cA;
1023  ppB= B/cB;
[10af64]1024
[e243418]1025  int sizeNewtonPolyg;
1026  int ** newtonPolyg= NULL;
1027  mat_ZZ MM;
1028  vec_ZZ V;
[ea095d]1029  bool compressConvexDense= false; //(ppA.level() == 2 && ppB.level() == 2);
[e243418]1030  if (compressConvexDense)
1031  {
[597783]1032    CanonicalForm bufcA= cA;
1033    CanonicalForm bufcB= cB;
[e243418]1034    cA= content (ppA, 1);
1035    cB= content (ppB, 1);
1036    ppA /= cA;
1037    ppB /= cB;
1038    gcdcAcB *= gcd (cA, cB);
[597783]1039    cA *= bufcA;
1040    cB *= bufcB;
[e243418]1041    if (ppA.isUnivariate() || ppB.isUnivariate())
1042    {
1043      if (ppA.level() == ppB.level())
[597783]1044      {
1045        CanonicalForm result= gcd (ppA, ppB);
1046        coF= N ((ppA/result)*(cA/gcdcAcB));
1047        coG= N ((ppB/result)*(cB/gcdcAcB));
1048        return N (result*gcdcAcB);
1049      }
[e243418]1050      else
[597783]1051      {
1052        coF= N (ppA*(cA/gcdcAcB));
1053        coG= N (ppB*(cB/gcdcAcB));
[a9a6dcb]1054        return N (gcdcAcB);
[597783]1055      }
[e243418]1056    }
1057
1058    newtonPolyg= newtonPolygon (ppA,ppB, sizeNewtonPolyg);
1059    convexDense (newtonPolyg, sizeNewtonPolyg, MM, V);
1060
1061    for (int i= 0; i < sizeNewtonPolyg; i++)
1062      delete [] newtonPolyg[i];
1063    delete [] newtonPolyg;
1064
1065    ppA= compress (ppA, MM, V, false);
1066    ppB= compress (ppB, MM, V, false);
1067    MM= inv (MM);
1068
1069    if (ppA.isUnivariate() && ppB.isUnivariate())
1070    {
1071      if (ppA.level() == ppB.level())
[597783]1072      {
1073        CanonicalForm result= gcd (ppA, ppB);
1074        coF= N (decompress ((ppA/result), MM, V)*(cA/gcdcAcB));
1075        coG= N (decompress ((ppB/result), MM, V)*(cB/gcdcAcB));
1076        return N (decompress (result, MM, V)*gcdcAcB);
1077      }
[e243418]1078      else
[597783]1079      {
1080        coF= N (decompress (ppA, MM, V));
1081        coG= N (decompress (ppB, MM, V));
[a9a6dcb]1082        return N (gcdcAcB);
[597783]1083      }
[e243418]1084    }
1085  }
1086
[10af64]1087  CanonicalForm lcA, lcB;  // leading coefficients of A and B
[806c18]1088  CanonicalForm gcdlcAlcB;
[10af64]1089
1090  lcA= uni_lcoeff (ppA);
1091  lcB= uni_lcoeff (ppB);
1092
[597783]1093  /*if (fdivides (lcA, lcB))
[806c18]1094  {
[597783]1095    if (fdivides (ppA, ppB, coG))
1096    {
1097      coF= 1;
1098      if (compressConvexDense)
1099        coG= decompress (coG, MM, V);
1100      coG= N (coG*(cB/gcdcAcB));
[806c18]1101      return F;
[597783]1102    }
[806c18]1103  }
1104  if (fdivides (lcB, lcA))
1105  {
[597783]1106    if (fdivides (ppB, ppA, coF))
1107    {
1108      coG= 1;
1109      if (compressConvexDense)
1110        coF= decompress (coF, MM, V);
1111      coF= N (coF*(cA/gcdcAcB));
[10af64]1112      return G;
[597783]1113    }
1114  }*/
[10af64]1115
1116  gcdlcAlcB= gcd (lcA, lcB);
1117
1118  int d= totaldegree (ppA, Variable(2), Variable (ppA.level()));
[dec1024]1119  if (d == 0)
[597783]1120  {
1121    coF= N (ppA*(cA/gcdcAcB));
1122    coG= N (ppB*(cB/gcdcAcB));
[a9a6dcb]1123    return N(gcdcAcB);
[597783]1124  }
[10af64]1125  int d0= totaldegree (ppB, Variable(2), Variable (ppB.level()));
[806c18]1126  if (d0 < d)
1127    d= d0;
[dec1024]1128  if (d == 0)
[597783]1129  {
1130    coF= N (ppA*(cA/gcdcAcB));
1131    coG= N (ppB*(cB/gcdcAcB));
[a9a6dcb]1132    return N(gcdcAcB);
[597783]1133  }
[10af64]1134
1135  CanonicalForm m, random_element, G_m, G_random_element, H, cH, ppH;
[597783]1136  CanonicalForm newtonPoly, coF_random_element, coG_random_element, coF_m,
1137                coG_m, ppCoF, ppCoG;
[10af64]1138
1139  newtonPoly= 1;
1140  m= gcdlcAlcB;
1141  G_m= 0;
[597783]1142  coF= 0;
1143  coG= 0;
[10af64]1144  H= 0;
1145  bool fail= false;
[597783]1146  //topLevel= false;
[10af64]1147  bool inextension= false;
[c1b9927]1148  int p=-1;
[10af64]1149  int k= getGFDegree();
1150  int kk;
[88f3644]1151  int expon;
[10af64]1152  char gf_name_buf= gf_name;
[597783]1153  int bound1= degree (ppA, 1);
1154  int bound2= degree (ppB, 1);
[806c18]1155  do
[10af64]1156  {
[597783]1157    random_element= GFRandomElement (m*lcA*lcB, l, fail);
[806c18]1158    if (fail)
1159    {
[10af64]1160      p= getCharacteristic();
[9ff686]1161      expon= 2;
[806c18]1162      kk= getGFDegree();
1163      if (ipower (p, kk*expon) < (1 << 16))
[10af64]1164        setCharacteristic (p, kk*(int)expon, 'b');
[806c18]1165      else
[10af64]1166      {
[04dd0c]1167        expon= (int) floor((log ((double)((1<<16) - 1)))/(log((double)p)*kk));
[10af64]1168        ASSERT (expon >= 2, "not enough points in GCD_GF");
1169        setCharacteristic (p, (int)(kk*expon), 'b');
1170      }
1171      inextension= true;
1172      fail= false;
[806c18]1173      for (CFListIterator i= l; i.hasItem(); i++)
[10af64]1174        i.getItem()= GFMapUp (i.getItem(), kk);
1175      m= GFMapUp (m, kk);
1176      G_m= GFMapUp (G_m, kk);
1177      newtonPoly= GFMapUp (newtonPoly, kk);
[597783]1178      coF_m= GFMapUp (coF_m, kk);
1179      coG_m= GFMapUp (coG_m, kk);
[10af64]1180      ppA= GFMapUp (ppA, kk);
1181      ppB= GFMapUp (ppB, kk);
1182      gcdlcAlcB= GFMapUp (gcdlcAlcB, kk);
[597783]1183      lcA= GFMapUp (lcA, kk);
1184      lcB= GFMapUp (lcB, kk);
1185      random_element= GFRandomElement (m*lcA*lcB, l, fail);
[a5cc7b3]1186      DEBOUTLN (cerr, "fail= " << fail);
[10af64]1187      CFList list;
1188      TIMING_START (gcd_recursion);
[806c18]1189      G_random_element= GCD_GF (ppA(random_element, x), ppB(random_element, x),
[597783]1190                                coF_random_element, coG_random_element,
[dec1024]1191                                list, topLevel);
[806c18]1192      TIMING_END_AND_PRINT (gcd_recursion,
[10af64]1193                            "time for recursive call: ");
1194      DEBOUTLN (cerr, "G_random_element= " << G_random_element);
1195    }
[806c18]1196    else
[10af64]1197    {
1198      CFList list;
1199      TIMING_START (gcd_recursion);
[806c18]1200      G_random_element= GCD_GF (ppA(random_element, x), ppB(random_element, x),
[597783]1201                                coF_random_element, coG_random_element,
[dec1024]1202                                list, topLevel);
[806c18]1203      TIMING_END_AND_PRINT (gcd_recursion,
[10af64]1204                            "time for recursive call: ");
1205      DEBOUTLN (cerr, "G_random_element= " << G_random_element);
1206    }
1207
[a76d6fe]1208    if (!G_random_element.inCoeffDomain())
1209      d0= totaldegree (G_random_element, Variable(2),
1210                       Variable (G_random_element.level()));
1211    else
1212      d0= 0;
1213
[806c18]1214    if (d0 == 0)
[10af64]1215    {
[806c18]1216      if (inextension)
[10af64]1217        setCharacteristic (p, k, gf_name_buf);
[597783]1218      coF= N (ppA*(cA/gcdcAcB));
1219      coG= N (ppB*(cB/gcdcAcB));
[a9a6dcb]1220      return N(gcdcAcB);
[806c18]1221    }
1222    if (d0 >  d)
[10af64]1223    {
1224      if (!find (l, random_element))
1225        l.append (random_element);
1226      continue;
1227    }
1228
[806c18]1229    G_random_element=
[10af64]1230    (gcdlcAlcB(random_element, x)/uni_lcoeff(G_random_element)) *
1231     G_random_element;
[597783]1232
1233    coF_random_element= (lcA(random_element,x)/uni_lcoeff(coF_random_element))
1234                        *coF_random_element;
1235    coG_random_element= (lcB(random_element,x)/uni_lcoeff(coG_random_element))
1236                        *coG_random_element;
1237
[a76d6fe]1238    if (!G_random_element.inCoeffDomain())
1239      d0= totaldegree (G_random_element, Variable(2),
1240                       Variable (G_random_element.level()));
1241    else
1242      d0= 0;
[10af64]1243
[806c18]1244    if (d0 < d)
[10af64]1245    {
1246      m= gcdlcAlcB;
1247      newtonPoly= 1;
1248      G_m= 0;
1249      d= d0;
[597783]1250      coF_m= 0;
1251      coG_m= 0;
[10af64]1252    }
1253
1254    TIMING_START (newton_interpolation);
1255    H= newtonInterp (random_element, G_random_element, newtonPoly, G_m, x);
[597783]1256    coF= newtonInterp (random_element, coF_random_element, newtonPoly, coF_m,x);
1257    coG= newtonInterp (random_element, coG_random_element, newtonPoly, coG_m,x);
1258    TIMING_END_AND_PRINT (newton_interpolation,
1259                          "time for newton interpolation: ");
[10af64]1260
[806c18]1261    //termination test
[597783]1262    if ((uni_lcoeff (H) == gcdlcAlcB) || (G_m == H))
[10af64]1263    {
[2a95b2]1264      TIMING_START (termination_test);
[597783]1265      if (gcdlcAlcB.isOne())
1266        cH= 1;
1267      else
1268        cH= uni_content (H);
[10af64]1269      ppH= H/cH;
[597783]1270      CanonicalForm lcppH= gcdlcAlcB/cH;
1271      CanonicalForm ccoF= lcA/lcppH;
1272      ccoF /= Lc (ccoF);
1273      CanonicalForm ccoG= lcB/lcppH;
1274      ccoG /= Lc (ccoG);
1275      ppCoF= coF/ccoF;
1276      ppCoG= coG/ccoG;
[806c18]1277      if (inextension)
[10af64]1278      {
[597783]1279        if (((degree (ppCoF,1)+degree (ppH,1) == bound1) &&
1280             (degree (ppCoG,1)+degree (ppH,1) == bound2) &&
[1e4b53]1281             terminationTest (ppA, ppB, ppCoF, ppCoG, ppH)) ||
[597783]1282             (fdivides (ppH, ppA, ppCoF) && fdivides (ppH, ppB, ppCoG)))
[10af64]1283        {
1284          DEBOUTLN (cerr, "ppH before mapDown= " << ppH);
1285          ppH= GFMapDown (ppH, k);
[597783]1286          ppCoF= GFMapDown (ppCoF, k);
1287          ppCoG= GFMapDown (ppCoG, k);
[10af64]1288          DEBOUTLN (cerr, "ppH after mapDown= " << ppH);
[e243418]1289          if (compressConvexDense)
[597783]1290          {
[e243418]1291            ppH= decompress (ppH, MM, V);
[597783]1292            ppCoF= decompress (ppCoF, MM, V);
1293            ppCoG= decompress (ppCoG, MM, V);
1294          }
1295          coF= N ((cA/gcdcAcB)*ppCoF);
1296          coG= N ((cB/gcdcAcB)*ppCoG);
[10af64]1297          setCharacteristic (p, k, gf_name_buf);
[2a95b2]1298          TIMING_END_AND_PRINT (termination_test,
1299                                "time for successful termination GF: ");
[10af64]1300          return N(gcdcAcB*ppH);
1301        }
1302      }
[806c18]1303      else
[10af64]1304      {
[597783]1305      if (((degree (ppCoF,1)+degree (ppH,1) == bound1) &&
1306           (degree (ppCoG,1)+degree (ppH,1) == bound2) &&
[1e4b53]1307           terminationTest (ppA, ppB, ppCoF, ppCoG, ppH)) ||
[597783]1308           (fdivides (ppH, ppA, ppCoF) && fdivides (ppH, ppB, ppCoG)))
[dec1024]1309        {
[e243418]1310          if (compressConvexDense)
[597783]1311          {
[e243418]1312            ppH= decompress (ppH, MM, V);
[597783]1313            ppCoF= decompress (ppCoF, MM, V);
1314            ppCoG= decompress (ppCoG, MM, V);
1315          }
1316          coF= N ((cA/gcdcAcB)*ppCoF);
1317          coG= N ((cB/gcdcAcB)*ppCoG);
[2a95b2]1318          TIMING_END_AND_PRINT (termination_test,
1319                                "time for successful termination GF: ");
[10af64]1320          return N(gcdcAcB*ppH);
[dec1024]1321        }
[10af64]1322      }
[2a95b2]1323      TIMING_END_AND_PRINT (termination_test,
1324                            "time for unsuccessful termination GF: ");
[10af64]1325    }
1326
1327    G_m= H;
[597783]1328    coF_m= coF;
1329    coG_m= coG;
[10af64]1330    newtonPoly= newtonPoly*(x - random_element);
1331    m= m*(x - random_element);
1332    if (!find (l, random_element))
1333      l.append (random_element);
1334  } while (1);
1335}
1336
1337/// F is assumed to be an univariate polynomial in x,
[806c18]1338/// computes a random monic irreducible univariate polynomial of random
[10af64]1339/// degree < i in x which does not divide F
[806c18]1340CanonicalForm
1341randomIrredpoly (int i, const Variable & x)
[10af64]1342{
1343  int p= getCharacteristic();
[bffe62d]1344  if (fac_NTL_char != p)
1345  {
1346    fac_NTL_char= p;
1347    zz_p::init (p);
1348  }
[9a12097]1349  zz_pX NTLirredpoly;
[10af64]1350  CanonicalForm CFirredpoly;
[04dd0c]1351  BuildIrred (NTLirredpoly, i + 1);
[9a12097]1352  CFirredpoly= convertNTLzzpX2CF (NTLirredpoly, x);
[10af64]1353  return CFirredpoly;
[806c18]1354}
[10af64]1355
[04dd0c]1356static inline
[10af64]1357CanonicalForm
1358FpRandomElement (const CanonicalForm& F, CFList& list, bool& fail)
1359{
1360  fail= false;
1361  Variable x= F.mvar();
1362  FFRandom genFF;
1363  CanonicalForm random;
1364  int p= getCharacteristic();
[88f3644]1365  int bound= p;
[806c18]1366  do
[10af64]1367  {
1368    if (list.length() == bound)
1369    {
1370      fail= true;
1371      break;
1372    }
1373    if (list.length() < 1)
1374      random= 0;
[806c18]1375    else
[10af64]1376    {
1377      random= genFF.generate();
1378      while (find (list, random))
1379        random= genFF.generate();
1380    }
[806c18]1381    if (F (random, x) == 0)
[10af64]1382    {
1383      list.append (random);
1384      continue;
1385    }
1386  } while (find (list, random));
1387  return random;
1388}
1389
[597783]1390CanonicalForm
1391GCD_small_p (const CanonicalForm& F, const CanonicalForm&  G,
1392             CanonicalForm& coF, CanonicalForm& coG,
1393             bool& topLevel, CFList& l);
1394
1395CanonicalForm
1396GCD_small_p (const CanonicalForm& F, const CanonicalForm& G,
1397             bool& topLevel, CFList& l)
1398{
1399  CanonicalForm dummy1, dummy2;
1400  CanonicalForm result= GCD_small_p (F, G, dummy1, dummy2, topLevel, l);
1401  return result;
1402}
1403
1404CanonicalForm
1405GCD_small_p (const CanonicalForm& F, const CanonicalForm&  G,
1406             CanonicalForm& coF, CanonicalForm& coG,
1407             bool& topLevel, CFList& l)
[10af64]1408{
1409  CanonicalForm A= F;
1410  CanonicalForm B= G;
[597783]1411  if (F.isZero() && degree(G) > 0)
1412  {
1413    coF= 0;
1414    coG= Lc (G);
1415    return G/Lc(G);
1416  }
1417  else if (G.isZero() && degree (F) > 0)
1418  {
1419    coF= Lc (F);
1420    coG= 0;
1421    return F/Lc(F);
1422  }
1423  else if (F.isZero() && G.isZero())
1424  {
1425    coF= coG= 0;
1426    return F.genOne();
1427  }
1428  if (F.inBaseDomain() || G.inBaseDomain())
1429  {
1430    coF= F;
1431    coG= G;
1432    return F.genOne();
1433  }
1434  if (F.isUnivariate() && fdivides(F, G, coG))
1435  {
1436    coF= Lc (F);
1437    return F/Lc(F);
1438  }
1439  if (G.isUnivariate() && fdivides(G, F, coF))
1440  {
1441    coG= Lc (G);
1442    return G/Lc(G);
1443  }
1444  if (F == G)
1445  {
1446    coF= coG= Lc (F);
1447    return F/Lc(F);
1448  }
[10af64]1449  CFMap M,N;
[dec1024]1450  int best_level= myCompress (A, B, M, N, topLevel);
[10af64]1451
[597783]1452  if (best_level == 0)
1453  {
1454    coF= F;
1455    coG= G;
1456    return B.genOne();
1457  }
[10af64]1458
1459  A= M(A);
1460  B= M(B);
1461
[c4f4fd]1462  Variable x= Variable (1);
1463
[806c18]1464  //univariate case
1465  if (A.isUnivariate() && B.isUnivariate())
[597783]1466  {
1467    CanonicalForm result= gcd (A, B);
1468    coF= N (A/result);
1469    coG= N (B/result);
1470    return N (result);
1471  }
[10af64]1472
1473  CanonicalForm cA, cB;    // content of A and B
1474  CanonicalForm ppA, ppB;    // primitive part of A and B
1475  CanonicalForm gcdcAcB;
[dec1024]1476
[ea5ff1d]1477  cA = uni_content (A);
1478  cB = uni_content (B);
1479  gcdcAcB= gcd (cA, cB);
1480  ppA= A/cA;
1481  ppB= B/cB;
[10af64]1482
[e243418]1483  int sizeNewtonPolyg;
1484  int ** newtonPolyg= NULL;
1485  mat_ZZ MM;
1486  vec_ZZ V;
[ea095d]1487  bool compressConvexDense= false; //(ppA.level() == 2 && ppB.level() == 2);
[e243418]1488  if (compressConvexDense)
1489  {
[597783]1490    CanonicalForm bufcA= cA;
1491    CanonicalForm bufcB= cB;
[e243418]1492    cA= content (ppA, 1);
1493    cB= content (ppB, 1);
1494    ppA /= cA;
1495    ppB /= cB;
1496    gcdcAcB *= gcd (cA, cB);
[597783]1497    cA *= bufcA;
1498    cB *= bufcB;
[e243418]1499    if (ppA.isUnivariate() || ppB.isUnivariate())
1500    {
1501      if (ppA.level() == ppB.level())
[597783]1502      {
1503        CanonicalForm result= gcd (ppA, ppB);
1504        coF= N ((ppA/result)*(cA/gcdcAcB));
1505        coG= N ((ppB/result)*(cB/gcdcAcB));
1506        return N (result*gcdcAcB);
1507      }
[e243418]1508      else
[597783]1509      {
1510        coF= N (ppA*(cA/gcdcAcB));
1511        coG= N (ppB*(cB/gcdcAcB));
[a9a6dcb]1512        return N (gcdcAcB);
[597783]1513      }
[e243418]1514    }
1515
1516    newtonPolyg= newtonPolygon (ppA,ppB, sizeNewtonPolyg);
1517    convexDense (newtonPolyg, sizeNewtonPolyg, MM, V);
1518
1519    for (int i= 0; i < sizeNewtonPolyg; i++)
1520      delete [] newtonPolyg[i];
1521    delete [] newtonPolyg;
1522
1523    ppA= compress (ppA, MM, V, false);
1524    ppB= compress (ppB, MM, V, false);
1525    MM= inv (MM);
1526
1527    if (ppA.isUnivariate() && ppB.isUnivariate())
1528    {
1529      if (ppA.level() == ppB.level())
[597783]1530      {
1531        CanonicalForm result= gcd (ppA, ppB);
1532        coF= N (decompress ((ppA/result), MM, V)*(cA/gcdcAcB));
1533        coG= N (decompress ((ppB/result), MM, V)*(cB/gcdcAcB));
1534        return N (decompress (result, MM, V)*gcdcAcB);
1535      }
[e243418]1536      else
[597783]1537      {
1538        coF= N (decompress (ppA, MM, V));
1539        coG= N (decompress (ppB, MM, V));
[a9a6dcb]1540        return N (gcdcAcB);
[597783]1541      }
[e243418]1542    }
1543  }
1544
[10af64]1545  CanonicalForm lcA, lcB;  // leading coefficients of A and B
[806c18]1546  CanonicalForm gcdlcAlcB;
[10af64]1547  lcA= uni_lcoeff (ppA);
1548  lcB= uni_lcoeff (ppB);
1549
[597783]1550  /*if (fdivides (lcA, lcB))
[806c18]1551  {
[10af64]1552    if (fdivides (A, B))
1553      return F/Lc(F);
[806c18]1554  }
[10af64]1555  if (fdivides (lcB, lcA))
[806c18]1556  {
1557    if (fdivides (B, A))
[10af64]1558      return G/Lc(G);
[597783]1559  }*/
[c4f4fd]1560
[806c18]1561  gcdlcAlcB= gcd (lcA, lcB);
1562
[10af64]1563  int d= totaldegree (ppA, Variable (2), Variable (ppA.level()));
1564  int d0;
1565
[dec1024]1566  if (d == 0)
[597783]1567  {
1568    coF= N (ppA*(cA/gcdcAcB));
1569    coG= N (ppB*(cB/gcdcAcB));
[a9a6dcb]1570    return N(gcdcAcB);
[597783]1571  }
[a9a6dcb]1572
[10af64]1573  d0= totaldegree (ppB, Variable (2), Variable (ppB.level()));
1574
[806c18]1575  if (d0 < d)
[10af64]1576    d= d0;
1577
[806c18]1578  if (d == 0)
[597783]1579  {
1580    coF= N (ppA*(cA/gcdcAcB));
1581    coG= N (ppB*(cB/gcdcAcB));
[a9a6dcb]1582    return N(gcdcAcB);
[597783]1583  }
[10af64]1584
1585  CanonicalForm m, random_element, G_m, G_random_element, H, cH, ppH;
[597783]1586  CanonicalForm newtonPoly, coF_random_element, coG_random_element,
1587                coF_m, coG_m, ppCoF, ppCoG;
1588
1589  newtonPoly= 1;
[10af64]1590  m= gcdlcAlcB;
1591  H= 0;
[597783]1592  coF= 0;
1593  coG= 0;
[10af64]1594  G_m= 0;
1595  Variable alpha, V_buf;
1596  bool fail= false;
1597  bool inextension= false;
[d1dc39]1598  topLevel= false;
[10af64]1599  CFList source, dest;
[597783]1600  int bound1= degree (ppA, 1);
1601  int bound2= degree (ppB, 1);
[806c18]1602  do
[10af64]1603  {
1604    if (inextension)
[597783]1605      random_element= randomElement (m*lcA*lcB, V_buf, l, fail);
[10af64]1606    else
[597783]1607      random_element= FpRandomElement (m*lcA*lcB, l, fail);
[10af64]1608
1609    if (!fail && !inextension)
1610    {
1611      CFList list;
1612      TIMING_START (gcd_recursion);
[806c18]1613      G_random_element=
[597783]1614      GCD_small_p (ppA (random_element,x), ppB (random_element,x),
[d1dc39]1615                   coF_random_element, coG_random_element, topLevel,
[597783]1616                   list);
[806c18]1617      TIMING_END_AND_PRINT (gcd_recursion,
[10af64]1618                            "time for recursive call: ");
1619      DEBOUTLN (cerr, "G_random_element= " << G_random_element);
1620    }
1621    else if (!fail && inextension)
1622    {
[806c18]1623      CFList list;
[10af64]1624      TIMING_START (gcd_recursion);
[806c18]1625      G_random_element=
[597783]1626      GCD_Fp_extension (ppA (random_element, x), ppB (random_element, x),
1627                        coF_random_element, coG_random_element, alpha,
[d1dc39]1628                        list, topLevel);
[806c18]1629      TIMING_END_AND_PRINT (gcd_recursion,
[10af64]1630                            "time for recursive call: ");
[806c18]1631      DEBOUTLN (cerr, "G_random_element= " << G_random_element);
[10af64]1632    }
1633    else if (fail && !inextension)
1634    {
1635      source= CFList();
1636      dest= CFList();
1637      CFList list;
[a5cc7b3]1638      CanonicalForm mipo;
[dec1024]1639      int deg= 2;
[a5cc7b3]1640      do {
[806c18]1641        mipo= randomIrredpoly (deg, x);
[a5cc7b3]1642        alpha= rootOf (mipo);
1643        inextension= true;
1644        fail= false;
[597783]1645        random_element= randomElement (m*lcA*lcB, alpha, l, fail);
[a5cc7b3]1646        deg++;
[806c18]1647      } while (fail);
[10af64]1648      list= CFList();
[9ff686]1649      V_buf= alpha;
[10af64]1650      TIMING_START (gcd_recursion);
[806c18]1651      G_random_element=
[597783]1652      GCD_Fp_extension (ppA (random_element, x), ppB (random_element, x),
1653                        coF_random_element, coG_random_element, alpha,
[d1dc39]1654                        list, topLevel);
[806c18]1655      TIMING_END_AND_PRINT (gcd_recursion,
[10af64]1656                            "time for recursive call: ");
1657      DEBOUTLN (cerr, "G_random_element= " << G_random_element);
1658    }
1659    else if (fail && inextension)
1660    {
1661      source= CFList();
1662      dest= CFList();
[9ff686]1663
1664      Variable V_buf3= V_buf;
1665      V_buf= chooseExtension (V_buf);
[10af64]1666      bool prim_fail= false;
1667      Variable V_buf2;
1668      CanonicalForm prim_elem, im_prim_elem;
1669      prim_elem= primitiveElement (alpha, V_buf2, prim_fail);
[806c18]1670
[9ff686]1671      if (V_buf3 != alpha)
1672      {
1673        m= mapDown (m, prim_elem, im_prim_elem, alpha, source, dest);
[597783]1674        G_m= mapDown (G_m, prim_elem, im_prim_elem, alpha, source, dest);
1675        coF_m= mapDown (coF_m, prim_elem, im_prim_elem, alpha, source, dest);
1676        coG_m= mapDown (coG_m, prim_elem, im_prim_elem, alpha, source, dest);
[9ff686]1677        newtonPoly= mapDown (newtonPoly, prim_elem, im_prim_elem, alpha,
1678                             source, dest);
1679        ppA= mapDown (ppA, prim_elem, im_prim_elem, alpha, source, dest);
1680        ppB= mapDown (ppB, prim_elem, im_prim_elem, alpha, source, dest);
1681        gcdlcAlcB= mapDown (gcdlcAlcB, prim_elem, im_prim_elem, alpha, source,
1682                            dest);
[597783]1683        lcA= mapDown (lcA, prim_elem, im_prim_elem, alpha, source, dest);
1684        lcB= mapDown (lcB, prim_elem, im_prim_elem, alpha, source, dest);
[9ff686]1685        for (CFListIterator i= l; i.hasItem(); i++)
1686          i.getItem()= mapDown (i.getItem(), prim_elem, im_prim_elem, alpha,
1687                                source, dest);
1688      }
1689
[10af64]1690      ASSERT (!prim_fail, "failure in integer factorizer");
1691      if (prim_fail)
1692        ; //ERROR
1693      else
1694        im_prim_elem= mapPrimElem (prim_elem, alpha, V_buf);
1695
1696      DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (alpha));
1697      DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (V_buf2));
1698
[806c18]1699      for (CFListIterator i= l; i.hasItem(); i++)
1700        i.getItem()= mapUp (i.getItem(), alpha, V_buf, prim_elem,
[10af64]1701                             im_prim_elem, source, dest);
1702      m= mapUp (m, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
1703      G_m= mapUp (G_m, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
[597783]1704      coF_m= mapUp (coF_m, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
1705      coG_m= mapUp (coG_m, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
[806c18]1706      newtonPoly= mapUp (newtonPoly, alpha, V_buf, prim_elem, im_prim_elem,
[10af64]1707                          source, dest);
1708      ppA= mapUp (ppA, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
1709      ppB= mapUp (ppB, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
[806c18]1710      gcdlcAlcB= mapUp (gcdlcAlcB, alpha, V_buf, prim_elem, im_prim_elem,
[10af64]1711                         source, dest);
[597783]1712      lcA= mapUp (lcA, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
1713      lcB= mapUp (lcB, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
[10af64]1714      fail= false;
[597783]1715      random_element= randomElement (m*lcA*lcB, V_buf, l, fail );
[a5cc7b3]1716      DEBOUTLN (cerr, "fail= " << fail);
[10af64]1717      CFList list;
1718      TIMING_START (gcd_recursion);
[806c18]1719      G_random_element=
[597783]1720      GCD_Fp_extension (ppA (random_element, x), ppB (random_element, x),
1721                        coF_random_element, coG_random_element, V_buf,
[d1dc39]1722                        list, topLevel);
[806c18]1723      TIMING_END_AND_PRINT (gcd_recursion,
[10af64]1724                            "time for recursive call: ");
1725      DEBOUTLN (cerr, "G_random_element= " << G_random_element);
[806c18]1726    }
[10af64]1727
[a76d6fe]1728    if (!G_random_element.inCoeffDomain())
1729      d0= totaldegree (G_random_element, Variable(2),
1730                       Variable (G_random_element.level()));
1731    else
1732      d0= 0;
[10af64]1733
1734    if (d0 == 0)
[597783]1735    {
1736      coF= N (ppA*(cA/gcdcAcB));
1737      coG= N (ppB*(cB/gcdcAcB));
[a9a6dcb]1738      return N(gcdcAcB);
[597783]1739    }
1740
[806c18]1741    if (d0 >  d)
1742    {
[10af64]1743      if (!find (l, random_element))
1744        l.append (random_element);
1745      continue;
1746    }
1747
1748    G_random_element= (gcdlcAlcB(random_element,x)/uni_lcoeff(G_random_element))
[806c18]1749                       *G_random_element;
[10af64]1750
[597783]1751    coF_random_element= (lcA(random_element,x)/uni_lcoeff(coF_random_element))
1752                        *coF_random_element;
1753    coG_random_element= (lcB(random_element,x)/uni_lcoeff(coG_random_element))
1754                        *coG_random_element;
[806c18]1755
[a76d6fe]1756    if (!G_random_element.inCoeffDomain())
1757      d0= totaldegree (G_random_element, Variable(2),
1758                       Variable (G_random_element.level()));
1759    else
1760      d0= 0;
[10af64]1761
[806c18]1762    if (d0 <  d)
[10af64]1763    {
1764      m= gcdlcAlcB;
1765      newtonPoly= 1;
1766      G_m= 0;
1767      d= d0;
[597783]1768      coF_m= 0;
1769      coG_m= 0;
[10af64]1770    }
[806c18]1771
[10af64]1772    TIMING_START (newton_interpolation);
1773    H= newtonInterp (random_element, G_random_element, newtonPoly, G_m, x);
[597783]1774    coF= newtonInterp (random_element, coF_random_element, newtonPoly, coF_m,x);
1775    coG= newtonInterp (random_element, coG_random_element, newtonPoly, coG_m,x);
[806c18]1776    TIMING_END_AND_PRINT (newton_interpolation,
[10af64]1777                          "time for newton_interpolation: ");
1778
1779    //termination test
[597783]1780    if ((uni_lcoeff (H) == gcdlcAlcB) || (G_m == H))
[10af64]1781    {
[2a95b2]1782      TIMING_START (termination_test);
[597783]1783      if (gcdlcAlcB.isOne())
1784        cH= 1;
1785      else
1786        cH= uni_content (H);
[10af64]1787      ppH= H/cH;
1788      ppH /= Lc (ppH);
[597783]1789      CanonicalForm lcppH= gcdlcAlcB/cH;
1790      CanonicalForm ccoF= lcppH/Lc (lcppH);
1791      CanonicalForm ccoG= lcppH/Lc (lcppH);
1792      ppCoF= coF/ccoF;
1793      ppCoG= coG/ccoG;
[10af64]1794      DEBOUTLN (cerr, "ppH= " << ppH);
[597783]1795      if (((degree (ppCoF,1)+degree (ppH,1) == bound1) &&
1796           (degree (ppCoG,1)+degree (ppH,1) == bound2) &&
[1e4b53]1797           terminationTest (ppA, ppB, ppCoF, ppCoG, ppH)) ||
[597783]1798           (fdivides (ppH, ppA, ppCoF) && fdivides (ppH, ppB, ppCoG)))
[dec1024]1799      {
[e243418]1800        if (compressConvexDense)
[597783]1801        {
[e243418]1802          ppH= decompress (ppH, MM, V);
[597783]1803          ppCoF= decompress (ppCoF, MM, V);
1804          ppCoG= decompress (ppCoG, MM, V);
1805        }
1806        coF= N ((cA/gcdcAcB)*ppCoF);
1807        coG= N ((cB/gcdcAcB)*ppCoG);
[2a95b2]1808        TIMING_END_AND_PRINT (termination_test,
1809                              "time for successful termination Fp: ");
[10af64]1810        return N(gcdcAcB*ppH);
[dec1024]1811      }
[2a95b2]1812      TIMING_END_AND_PRINT (termination_test,
1813                            "time for unsuccessful termination Fp: ");
[10af64]1814    }
1815
1816    G_m= H;
[597783]1817    coF_m= coF;
1818    coG_m= coG;
[10af64]1819    newtonPoly= newtonPoly*(x - random_element);
1820    m= m*(x - random_element);
1821    if (!find (l, random_element))
1822      l.append (random_element);
1823  } while (1);
1824}
1825
[08daea]1826CFArray
1827solveVandermonde (const CFArray& M, const CFArray& A)
1828{
1829  int r= M.size();
1830  ASSERT (A.size() == r, "vector does not have right size");
1831
1832  if (r == 1)
1833  {
1834    CFArray result= CFArray (1);
1835    result [0]= A [0] / M [0];
1836    return result;
1837  }
1838  // check solvability
1839  bool notDistinct= false;
1840  for (int i= 0; i < r - 1; i++)
1841  {
1842    for (int j= i + 1; j < r; j++)
1843    {
1844      if (M [i] == M [j])
1845      {
1846        notDistinct= true;
1847        break;
1848      }
1849    }
1850  }
1851  if (notDistinct)
1852    return CFArray();
1853
1854  CanonicalForm master= 1;
1855  Variable x= Variable (1);
1856  for (int i= 0; i < r; i++)
1857    master *= x - M [i];
1858  CFList Pj;
1859  CanonicalForm tmp;
1860  for (int i= 0; i < r; i++)
1861  {
1862    tmp= master/(x - M [i]);
1863    tmp /= tmp (M [i], 1);
1864    Pj.append (tmp);
1865  }
1866  CFArray result= CFArray (r);
1867
1868  CFListIterator j= Pj;
1869  for (int i= 1; i <= r; i++, j++)
1870  {
1871    tmp= 0;
1872    for (int l= 0; l < A.size(); l++)
1873      tmp += A[l]*j.getItem()[l];
1874    result[i - 1]= tmp;
1875  }
1876  return result;
1877}
1878
1879CFArray
1880solveGeneralVandermonde (const CFArray& M, const CFArray& A)
1881{
1882  int r= M.size();
1883  ASSERT (A.size() == r, "vector does not have right size");
1884  if (r == 1)
1885  {
1886    CFArray result= CFArray (1);
1887    result [0]= A[0] / M [0];
1888    return result;
1889  }
1890  // check solvability
1891  bool notDistinct= false;
1892  for (int i= 0; i < r - 1; i++)
1893  {
1894    for (int j= i + 1; j < r; j++)
1895    {
1896      if (M [i] == M [j])
1897      {
1898        notDistinct= true;
1899        break;
1900      }
1901    }
1902  }
1903  if (notDistinct)
1904    return CFArray();
1905
1906  CanonicalForm master= 1;
1907  Variable x= Variable (1);
1908  for (int i= 0; i < r; i++)
1909    master *= x - M [i];
1910  master *= x;
1911  CFList Pj;
1912  CanonicalForm tmp;
1913  for (int i= 0; i < r; i++)
1914  {
1915    tmp= master/(x - M [i]);
1916    tmp /= tmp (M [i], 1);
1917    Pj.append (tmp);
1918  }
1919
1920  CFArray result= CFArray (r);
1921
1922  CFListIterator j= Pj;
1923  for (int i= 1; i <= r; i++, j++)
1924  {
1925    tmp= 0;
1926
1927    for (int l= 1; l <= A.size(); l++)
1928      tmp += A[l - 1]*j.getItem()[l];
1929    result[i - 1]= tmp;
1930  }
1931  return result;
1932}
1933
1934/// M in row echolon form, rk rank of M
1935CFArray
1936readOffSolution (const CFMatrix& M, const long rk)
1937{
1938  CFArray result= CFArray (rk);
1939  CanonicalForm tmp1, tmp2, tmp3;
1940  for (int i= rk; i >= 1; i--)
1941  {
1942    tmp3= 0;
1943    tmp1= M (i, M.columns());
1944    for (int j= M.columns() - 1; j >= 1; j--)
1945    {
1946      tmp2= M (i, j);
1947      if (j == i)
1948        break;
1949      else
1950        tmp3 += tmp2*result[j - 1];
1951    }
1952    result[i - 1]= (tmp1 - tmp3)/tmp2;
1953  }
1954  return result;
1955}
1956
1957CFArray
1958readOffSolution (const CFMatrix& M, const CFArray& L, const CFArray& partialSol)
1959{
1960  CFArray result= CFArray (M.rows());
1961  CanonicalForm tmp1, tmp2, tmp3;
1962  int k;
1963  for (int i= M.rows(); i >= 1; i--)
1964  {
1965    tmp3= 0;
1966    tmp1= L[i - 1];
1967    k= 0;
1968    for (int j= M.columns(); j >= 1; j--, k++)
1969    {
1970      tmp2= M (i, j);
1971      if (j == i)
1972        break;
1973      else
1974      {
1975        if (k > partialSol.size() - 1)
1976          tmp3 += tmp2*result[j - 1];
1977        else
1978          tmp3 += tmp2*partialSol[partialSol.size() - k - 1];
1979      }
1980    }
1981    result [i - 1]= (tmp1 - tmp3)/tmp2;
1982  }
1983  return result;
1984}
1985
1986long
1987gaussianElimFp (CFMatrix& M, CFArray& L)
1988{
1989  ASSERT (L.size() <= M.rows(), "dimension exceeded");
1990  CFMatrix *N;
1991  N= new CFMatrix (M.rows(), M.columns() + 1);
1992
1993  for (int i= 1; i <= M.rows(); i++)
1994    for (int j= 1; j <= M.columns(); j++)
1995      (*N) (i, j)= M (i, j);
1996
1997  int j= 1;
1998  for (int i= 0; i < L.size(); i++, j++)
1999    (*N) (j, M.columns() + 1)= L[i];
[8fa570]2000#ifdef HAVE_FLINT
2001  nmod_mat_t FLINTN;
2002  convertFacCFMatrix2nmod_mat_t (FLINTN, *N);
[147b6d]2003  long rk= nmod_mat_rref (FLINTN);
[8fa570]2004
2005  N= convertNmod_mat_t2FacCFMatrix (FLINTN);
2006  nmod_mat_clear (FLINTN);
2007#else
[08daea]2008  int p= getCharacteristic ();
[bffe62d]2009  if (fac_NTL_char != p)
2010  {
2011    fac_NTL_char= p;
2012    zz_p::init (p);
2013  }
[08daea]2014  mat_zz_p *NTLN= convertFacCFMatrix2NTLmat_zz_p(*N);
2015  long rk= gauss (*NTLN);
2016
2017  N= convertNTLmat_zz_p2FacCFMatrix (*NTLN);
[8fa570]2018#endif
[08daea]2019
2020  L= CFArray (M.rows());
2021  for (int i= 0; i < M.rows(); i++)
2022    L[i]= (*N) (i + 1, M.columns() + 1);
2023  M= (*N) (1, M.rows(), 1, M.columns());
[618da5]2024  delete N;
[08daea]2025  return rk;
2026}
2027
2028long
2029gaussianElimFq (CFMatrix& M, CFArray& L, const Variable& alpha)
2030{
2031  ASSERT (L.size() <= M.rows(), "dimension exceeded");
2032  CFMatrix *N;
2033  N= new CFMatrix (M.rows(), M.columns() + 1);
2034
2035  for (int i= 1; i <= M.rows(); i++)
2036    for (int j= 1; j <= M.columns(); j++)
2037      (*N) (i, j)= M (i, j);
2038
2039  int j= 1;
2040  for (int i= 0; i < L.size(); i++, j++)
2041    (*N) (j, M.columns() + 1)= L[i];
2042  int p= getCharacteristic ();
[bffe62d]2043  if (fac_NTL_char != p)
2044  {
2045    fac_NTL_char= p;
2046    zz_p::init (p);
2047  }
[08daea]2048  zz_pX NTLMipo= convertFacCF2NTLzzpX (getMipo (alpha));
2049  zz_pE::init (NTLMipo);
2050  mat_zz_pE *NTLN= convertFacCFMatrix2NTLmat_zz_pE(*N);
2051  long rk= gauss (*NTLN);
2052
2053  N= convertNTLmat_zz_pE2FacCFMatrix (*NTLN, alpha);
2054
2055  M= (*N) (1, M.rows(), 1, M.columns());
2056  L= CFArray (M.rows());
2057  for (int i= 0; i < M.rows(); i++)
2058    L[i]= (*N) (i + 1, M.columns() + 1);
[618da5]2059
2060  delete N;
[08daea]2061  return rk;
2062}
2063
2064CFArray
2065solveSystemFp (const CFMatrix& M, const CFArray& L)
2066{
2067  ASSERT (L.size() <= M.rows(), "dimension exceeded");
2068  CFMatrix *N;
2069  N= new CFMatrix (M.rows(), M.columns() + 1);
2070
2071  for (int i= 1; i <= M.rows(); i++)
2072    for (int j= 1; j <= M.columns(); j++)
2073      (*N) (i, j)= M (i, j);
2074
2075  int j= 1;
2076  for (int i= 0; i < L.size(); i++, j++)
2077    (*N) (j, M.columns() + 1)= L[i];
[8fa570]2078
2079#ifdef HAVE_FLINT
2080  nmod_mat_t FLINTN;
2081  convertFacCFMatrix2nmod_mat_t (FLINTN, *N);
[147b6d]2082  long rk= nmod_mat_rref (FLINTN);
[8fa570]2083#else
[08daea]2084  int p= getCharacteristic ();
[bffe62d]2085  if (fac_NTL_char != p)
2086  {
2087    fac_NTL_char= p;
2088    zz_p::init (p);
2089  }
[08daea]2090  mat_zz_p *NTLN= convertFacCFMatrix2NTLmat_zz_p(*N);
2091  long rk= gauss (*NTLN);
[8fa570]2092#endif
[08daea]2093  if (rk != M.columns())
[618da5]2094  {
[8fa570]2095#ifdef HAVE_FLINT
2096    nmod_mat_clear (FLINTN);
2097#endif
[618da5]2098    delete N;
[08daea]2099    return CFArray();
[618da5]2100  }
[8fa570]2101#ifdef HAVE_FLINT
2102  N= convertNmod_mat_t2FacCFMatrix (FLINTN);
2103  nmod_mat_clear (FLINTN);
2104#else
[08daea]2105  N= convertNTLmat_zz_p2FacCFMatrix (*NTLN);
[8fa570]2106#endif
[08daea]2107  CFArray A= readOffSolution (*N, rk);
2108
[618da5]2109  delete N;
[08daea]2110  return A;
2111}
2112
2113CFArray
2114solveSystemFq (const CFMatrix& M, const CFArray& L, const Variable& alpha)
2115{
2116  ASSERT (L.size() <= M.rows(), "dimension exceeded");
2117  CFMatrix *N;
2118  N= new CFMatrix (M.rows(), M.columns() + 1);
2119
2120  for (int i= 1; i <= M.rows(); i++)
2121    for (int j= 1; j <= M.columns(); j++)
2122      (*N) (i, j)= M (i, j);
2123  int j= 1;
2124  for (int i= 0; i < L.size(); i++, j++)
2125    (*N) (j, M.columns() + 1)= L[i];
2126  int p= getCharacteristic ();
[bffe62d]2127  if (fac_NTL_char != p)
2128  {
2129    fac_NTL_char= p;
2130    zz_p::init (p);
2131  }
[08daea]2132  zz_pX NTLMipo= convertFacCF2NTLzzpX (getMipo (alpha));
2133  zz_pE::init (NTLMipo);
2134  mat_zz_pE *NTLN= convertFacCFMatrix2NTLmat_zz_pE(*N);
2135  long rk= gauss (*NTLN);
2136  if (rk != M.columns())
[618da5]2137  {
2138    delete N;
[08daea]2139    return CFArray();
[618da5]2140  }
[08daea]2141  N= convertNTLmat_zz_pE2FacCFMatrix (*NTLN, alpha);
2142
2143  CFArray A= readOffSolution (*N, rk);
2144
[618da5]2145  delete N;
[08daea]2146  return A;
2147}
[6f6320]2148#endif
[08daea]2149
2150CFArray
2151getMonoms (const CanonicalForm& F)
2152{
2153  if (F.inCoeffDomain())
2154  {
2155    CFArray result= CFArray (1);
2156    result [0]= 1;
2157    return result;
2158  }
2159  if (F.isUnivariate())
2160  {
2161    CFArray result= CFArray (size(F));
2162    int j= 0;
2163    for (CFIterator i= F; i.hasTerms(); i++, j++)
2164      result[j]= power (F.mvar(), i.exp());
2165    return result;
2166  }
2167  int numMon= size (F);
2168  CFArray result= CFArray (numMon);
2169  int j= 0;
2170  CFArray recResult;
2171  Variable x= F.mvar();
2172  CanonicalForm powX;
2173  for (CFIterator i= F; i.hasTerms(); i++)
2174  {
2175    powX= power (x, i.exp());
2176    recResult= getMonoms (i.coeff());
2177    for (int k= 0; k < recResult.size(); k++)
2178      result[j+k]= powX*recResult[k];
2179    j += recResult.size();
2180  }
2181  return result;
2182}
2183
[6f6320]2184#ifdef HAVE_NTL
[08daea]2185CFArray
2186evaluateMonom (const CanonicalForm& F, const CFList& evalPoints)
2187{
2188  if (F.inCoeffDomain())
2189  {
2190    CFArray result= CFArray (1);
2191    result [0]= F;
2192    return result;
2193  }
2194  if (F.isUnivariate())
2195  {
2196    ASSERT (evalPoints.length() == 1,
2197            "expected an eval point with only one component");
2198    CFArray result= CFArray (size(F));
2199    int j= 0;
2200    CanonicalForm evalPoint= evalPoints.getLast();
2201    for (CFIterator i= F; i.hasTerms(); i++, j++)
2202      result[j]= power (evalPoint, i.exp());
2203    return result;
2204  }
2205  int numMon= size (F);
2206  CFArray result= CFArray (numMon);
2207  int j= 0;
2208  CanonicalForm evalPoint= evalPoints.getLast();
2209  CFList buf= evalPoints;
2210  buf.removeLast();
2211  CFArray recResult;
2212  CanonicalForm powEvalPoint;
2213  for (CFIterator i= F; i.hasTerms(); i++)
2214  {
2215    powEvalPoint= power (evalPoint, i.exp());
2216    recResult= evaluateMonom (i.coeff(), buf);
2217    for (int k= 0; k < recResult.size(); k++)
2218      result[j+k]= powEvalPoint*recResult[k];
2219    j += recResult.size();
2220  }
2221  return result;
2222}
2223
2224CFArray
2225evaluate (const CFArray& A, const CFList& evalPoints)
2226{
2227  CFArray result= A.size();
2228  CanonicalForm tmp;
2229  int k;
2230  for (int i= 0; i < A.size(); i++)
2231  {
2232    tmp= A[i];
2233    k= 1;
2234    for (CFListIterator j= evalPoints; j.hasItem(); j++, k++)
2235      tmp= tmp (j.getItem(), k);
2236    result[i]= tmp;
2237  }
2238  return result;
2239}
2240
2241CFList
2242evaluationPoints (const CanonicalForm& F, const CanonicalForm& G,
2243                  CanonicalForm& Feval, CanonicalForm& Geval,
2244                  const CanonicalForm& LCF, const bool& GF,
2245                  const Variable& alpha, bool& fail, CFList& list
2246                 )
2247{
2248  int k= tmax (F.level(), G.level()) - 1;
2249  Variable x= Variable (1);
2250  CFList result;
2251  FFRandom genFF;
2252  GFRandom genGF;
2253  int p= getCharacteristic ();
2254  int bound;
2255  if (alpha != Variable (1))
2256  {
2257    bound= ipower (p, degree (getMipo(alpha)));
2258    bound= ipower (bound, k);
2259  }
2260  else if (GF)
2261  {
2262    bound= ipower (p, getGFDegree());
2263    bound= ipower (bound, k);
2264  }
2265  else
2266    bound= ipower (p, k);
2267
2268  CanonicalForm random;
2269  int j;
2270  bool zeroOneOccured= false;
2271  bool allEqual= false;
2272  CanonicalForm buf;
2273  do
2274  {
2275    random= 0;
2276    // possible overflow if list.length() does not fit into a int
2277    if (list.length() >= bound)
2278    {
2279      fail= true;
2280      break;
2281    }
2282    for (int i= 0; i < k; i++)
2283    {
2284      if (GF)
2285      {
2286        result.append (genGF.generate());
2287        random += result.getLast()*power (x, i);
2288      }
[1372ae]2289      else if (alpha.level() != 1)
[08daea]2290      {
2291        AlgExtRandomF genAlgExt (alpha);
2292        result.append (genAlgExt.generate());
2293        random += result.getLast()*power (x, i);
2294      }
2295      else
2296      {
2297        result.append (genFF.generate());
2298        random += result.getLast()*power (x, i);
2299      }
2300      if (result.getLast().isOne() || result.getLast().isZero())
2301        zeroOneOccured= true;
2302    }
2303    if (find (list, random))
2304    {
2305      zeroOneOccured= false;
2306      allEqual= false;
2307      result= CFList();
2308      continue;
2309    }
2310    if (zeroOneOccured)
2311    {
2312      list.append (random);
2313      zeroOneOccured= false;
2314      allEqual= false;
2315      result= CFList();
2316      continue;
2317    }
2318    // no zero at this point
2319    if (k > 1)
2320    {
2321      allEqual= true;
2322      CFIterator iter= random;
2323      buf= iter.coeff();
2324      iter++;
2325      for (; iter.hasTerms(); iter++)
2326        if (buf != iter.coeff())
2327          allEqual= false;
2328    }
2329    if (allEqual)
2330    {
2331      list.append (random);
2332      allEqual= false;
2333      zeroOneOccured= false;
2334      result= CFList();
2335      continue;
2336    }
2337
2338    Feval= F;
2339    Geval= G;
2340    CanonicalForm LCeval= LCF;
2341    j= 1;
2342    for (CFListIterator i= result; i.hasItem(); i++, j++)
2343    {
2344      Feval= Feval (i.getItem(), j);
2345      Geval= Geval (i.getItem(), j);
2346      LCeval= LCeval (i.getItem(), j);
2347    }
2348
2349    if (LCeval.isZero())
2350    {
2351      if (!find (list, random))
2352        list.append (random);
2353      zeroOneOccured= false;
2354      allEqual= false;
2355      result= CFList();
2356      continue;
2357    }
2358
2359    if (list.length() >= bound)
2360    {
2361      fail= true;
2362      break;
2363    }
2364  } while (find (list, random));
2365
2366  return result;
2367}
2368
2369/// multiply two lists componentwise
2370void mult (CFList& L1, const CFList& L2)
2371{
2372  ASSERT (L1.length() == L2.length(), "lists of the same size expected");
2373
2374  CFListIterator j= L2;
2375  for (CFListIterator i= L1; i.hasItem(); i++, j++)
2376    i.getItem() *= j.getItem();
2377}
2378
2379void eval (const CanonicalForm& A, const CanonicalForm& B, CanonicalForm& Aeval,
2380           CanonicalForm& Beval, const CFList& L)
2381{
2382  Aeval= A;
2383  Beval= B;
2384  int j= 1;
2385  for (CFListIterator i= L; i.hasItem(); i++, j++)
2386  {
2387    Aeval= Aeval (i.getItem(), j);
2388    Beval= Beval (i.getItem(), j);
2389  }
2390}
2391
[c1b9927]2392CanonicalForm
[08daea]2393monicSparseInterpol (const CanonicalForm& F, const CanonicalForm& G,
2394                     const CanonicalForm& skeleton, const Variable& alpha,
2395                     bool& fail, CFArray*& coeffMonoms, CFArray& Monoms
2396                    )
2397{
2398  CanonicalForm A= F;
2399  CanonicalForm B= G;
2400  if (F.isZero() && degree(G) > 0) return G/Lc(G);
2401  else if (G.isZero() && degree (F) > 0) return F/Lc(F);
2402  else if (F.isZero() && G.isZero()) return F.genOne();
2403  if (F.inBaseDomain() || G.inBaseDomain()) return F.genOne();
2404  if (F.isUnivariate() && fdivides(F, G)) return F/Lc(F);
2405  if (G.isUnivariate() && fdivides(G, F)) return G/Lc(G);
2406  if (F == G) return F/Lc(F);
2407
2408  CFMap M,N;
2409  int best_level= myCompress (A, B, M, N, false);
2410
2411  if (best_level == 0)
2412    return B.genOne();
2413
2414  A= M(A);
2415  B= M(B);
2416
2417  Variable x= Variable (1);
[f71453]2418  ASSERT (degree (A, x) == 0, "expected degree (F, 1) == 0");
2419  ASSERT (degree (B, x) == 0, "expected degree (G, 1) == 0");
[08daea]2420
[c1b9927]2421  //univariate case
[08daea]2422  if (A.isUnivariate() && B.isUnivariate())
2423    return N (gcd (A, B));
2424
2425  CanonicalForm skel= M(skeleton);
2426  CanonicalForm cA, cB;    // content of A and B
2427  CanonicalForm ppA, ppB;    // primitive part of A and B
2428  CanonicalForm gcdcAcB;
2429  cA = uni_content (A);
2430  cB = uni_content (B);
2431  gcdcAcB= gcd (cA, cB);
2432  ppA= A/cA;
2433  ppB= B/cB;
2434
2435  CanonicalForm lcA, lcB;  // leading coefficients of A and B
2436  CanonicalForm gcdlcAlcB;
2437  lcA= uni_lcoeff (ppA);
2438  lcB= uni_lcoeff (ppB);
2439
2440  if (fdivides (lcA, lcB))
2441  {
2442    if (fdivides (A, B))
2443      return F/Lc(F);
2444  }
2445  if (fdivides (lcB, lcA))
2446  {
2447    if (fdivides (B, A))
2448      return G/Lc(G);
2449  }
2450
2451  gcdlcAlcB= gcd (lcA, lcB);
2452  int skelSize= size (skel, skel.mvar());
2453
2454  int j= 0;
2455  int biggestSize= 0;
2456
2457  for (CFIterator i= skel; i.hasTerms(); i++, j++)
2458    biggestSize= tmax (biggestSize, size (i.coeff()));
2459
2460  CanonicalForm g, Aeval, Beval;
2461
2462  CFList evalPoints;
2463  bool evalFail= false;
2464  CFList list;
2465  bool GF= false;
2466  CanonicalForm LCA= LC (A);
2467  CanonicalForm tmp;
2468  CFArray gcds= CFArray (biggestSize);
2469  CFList * pEvalPoints= new CFList [biggestSize];
2470  Variable V_buf= alpha;
2471  CFList source, dest;
2472  CanonicalForm prim_elem, im_prim_elem;
2473  for (int i= 0; i < biggestSize; i++)
2474  {
2475    if (i == 0)
2476      evalPoints= evaluationPoints (A, B, Aeval, Beval, LCA, GF, V_buf, evalFail,
2477                                    list);
2478    else
2479    {
2480      mult (evalPoints, pEvalPoints [0]);
2481      eval (A, B, Aeval, Beval, evalPoints);
2482    }
2483
2484    if (evalFail)
2485    {
[9ff686]2486      if (V_buf.level() != 1)
[08daea]2487      {
2488        do
2489        {
[9ff686]2490          Variable V_buf2= chooseExtension (V_buf);
[08daea]2491          source= CFList();
2492          dest= CFList();
2493
2494          bool prim_fail= false;
2495          Variable V_buf3;
2496          prim_elem= primitiveElement (V_buf, V_buf3, prim_fail);
2497
2498          ASSERT (!prim_fail, "failure in integer factorizer");
2499          if (prim_fail)
2500            ; //ERROR
2501          else
2502            im_prim_elem= mapPrimElem (prim_elem, V_buf, V_buf2);
2503
2504          DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (V_buf));
2505          DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (V_buf2));
2506
2507          for (CFListIterator j= list; j.hasItem(); j++)
2508            j.getItem()= mapUp (j.getItem(), V_buf, V_buf2, prim_elem,
2509                                im_prim_elem, source, dest);
2510          for (int k= 0; k < i; k++)
2511          {
2512            for (CFListIterator j= pEvalPoints[k]; j.hasItem(); j++)
2513              j.getItem()= mapUp (j.getItem(), V_buf, V_buf2, prim_elem,
2514                                  im_prim_elem, source, dest);
2515            gcds[k]= mapUp (gcds[k], V_buf, V_buf2, prim_elem, im_prim_elem,
2516                            source, dest);
2517          }
2518
[9ff686]2519          if (alpha.level() != 1)
[08daea]2520          {
2521            A= mapUp (A, V_buf, V_buf2, prim_elem, im_prim_elem, source,dest);
2522            B= mapUp (B, V_buf, V_buf2, prim_elem, im_prim_elem, source,dest);
2523          }
2524          evalFail= false;
2525          evalPoints= evaluationPoints (A, B, Aeval, Beval, LCA, GF, V_buf,
2526                                        evalFail, list);
2527        } while (evalFail);
2528      }
2529      else
2530      {
2531        CanonicalForm mipo;
2532        int deg= 2;
2533        do {
2534          mipo= randomIrredpoly (deg, x);
2535          V_buf= rootOf (mipo);
2536          evalFail= false;
2537          evalPoints= evaluationPoints (A, B, Aeval, Beval, LCA, GF, V_buf,
[c1b9927]2538                                        evalFail, list);
[08daea]2539          deg++;
2540        } while (evalFail);
2541      }
2542    }
2543
2544    g= gcd (Aeval, Beval);
2545    g /= Lc (g);
2546
2547    if (degree (g) != degree (skel) || (skelSize != size (g)))
2548    {
2549      delete[] pEvalPoints;
2550      fail= true;
2551      return 0;
2552    }
2553    CFIterator l= skel;
2554    for (CFIterator k= g; k.hasTerms(); k++, l++)
2555    {
2556      if (k.exp() != l.exp())
2557      {
2558        delete[] pEvalPoints;
2559        fail= true;
2560        return 0;
2561      }
2562    }
2563    pEvalPoints[i]= evalPoints;
2564    gcds[i]= g;
2565
2566    tmp= 0;
2567    int j= 0;
2568    for (CFListIterator k= evalPoints; k.hasItem(); k++, j++)
2569      tmp += k.getItem()*power (x, j);
2570    list.append (tmp);
2571  }
2572
2573  if (Monoms.size() == 0)
2574    Monoms= getMonoms (skel);
2575  if (coeffMonoms == NULL)
2576    coeffMonoms= new CFArray [skelSize];
2577  j= 0;
2578  for (CFIterator i= skel; i.hasTerms(); i++, j++)
2579    coeffMonoms[j]= getMonoms (i.coeff());
2580
2581  CFArray* pL= new CFArray [skelSize];
2582  CFArray* pM= new CFArray [skelSize];
2583  for (int i= 0; i < biggestSize; i++)
2584  {
2585    CFIterator l= gcds [i];
2586    evalPoints= pEvalPoints [i];
2587    for (int k= 0; k < skelSize; k++, l++)
2588    {
2589      if (i == 0)
2590        pL[k]= CFArray (biggestSize);
2591      pL[k] [i]= l.coeff();
2592
2593      if (i == 0)
2594        pM[k]= evaluate (coeffMonoms [k], evalPoints);
2595    }
2596  }
2597
2598  CFArray solution;
2599  CanonicalForm result= 0;
2600  int ind= 0;
2601  CFArray bufArray;
2602  CFMatrix Mat;
2603  for (int k= 0; k < skelSize; k++)
2604  {
2605    if (biggestSize != coeffMonoms[k].size())
2606    {
2607      bufArray= CFArray (coeffMonoms[k].size());
2608      for (int i= 0; i < coeffMonoms[k].size(); i++)
2609        bufArray [i]= pL[k] [i];
2610      solution= solveGeneralVandermonde (pM [k], bufArray);
2611    }
2612    else
2613      solution= solveGeneralVandermonde (pM [k], pL[k]);
2614
2615    if (solution.size() == 0)
2616    {
2617      delete[] pEvalPoints;
2618      delete[] pM;
2619      delete[] pL;
2620      delete[] coeffMonoms;
2621      fail= true;
2622      return 0;
2623    }
2624    for (int l= 0; l < solution.size(); l++)
2625      result += solution[l]*Monoms [ind + l];
2626    ind += solution.size();
2627  }
2628
2629  delete[] pEvalPoints;
2630  delete[] pM;
2631  delete[] pL;
2632
[9ff686]2633  if (alpha.level() != 1 && V_buf != alpha)
[08daea]2634  {
2635    CFList u, v;
2636    result= mapDown (result, prim_elem, im_prim_elem, alpha, u, v);
2637  }
2638
2639  result= N(result);
2640  if (fdivides (result, F) && fdivides (result, G))
2641    return result;
2642  else
2643  {
2644    delete[] coeffMonoms;
2645    fail= true;
2646    return 0;
2647  }
2648}
2649
2650CanonicalForm
2651nonMonicSparseInterpol (const CanonicalForm& F, const CanonicalForm& G,
2652                        const CanonicalForm& skeleton, const Variable& alpha,
2653                        bool& fail, CFArray*& coeffMonoms, CFArray& Monoms
2654                       )
2655{
2656  CanonicalForm A= F;
2657  CanonicalForm B= G;
2658  if (F.isZero() && degree(G) > 0) return G/Lc(G);
2659  else if (G.isZero() && degree (F) > 0) return F/Lc(F);
2660  else if (F.isZero() && G.isZero()) return F.genOne();
2661  if (F.inBaseDomain() || G.inBaseDomain()) return F.genOne();
2662  if (F.isUnivariate() && fdivides(F, G)) return F/Lc(F);
2663  if (G.isUnivariate() && fdivides(G, F)) return G/Lc(G);
2664  if (F == G) return F/Lc(F);
2665
2666  CFMap M,N;
2667  int best_level= myCompress (A, B, M, N, false);
2668
2669  if (best_level == 0)
2670    return B.genOne();
2671
2672  A= M(A);
2673  B= M(B);
2674
2675  Variable x= Variable (1);
[f71453]2676  ASSERT (degree (A, x) == 0, "expected degree (F, 1) == 0");
2677  ASSERT (degree (B, x) == 0, "expected degree (G, 1) == 0");
[08daea]2678
[c1b9927]2679  //univariate case
[08daea]2680  if (A.isUnivariate() && B.isUnivariate())
2681    return N (gcd (A, B));
2682
2683  CanonicalForm skel= M(skeleton);
2684
2685  CanonicalForm cA, cB;    // content of A and B
2686  CanonicalForm ppA, ppB;    // primitive part of A and B
2687  CanonicalForm gcdcAcB;
2688  cA = uni_content (A);
2689  cB = uni_content (B);
2690  gcdcAcB= gcd (cA, cB);
2691  ppA= A/cA;
2692  ppB= B/cB;
2693
2694  CanonicalForm lcA, lcB;  // leading coefficients of A and B
2695  CanonicalForm gcdlcAlcB;
2696  lcA= uni_lcoeff (ppA);
2697  lcB= uni_lcoeff (ppB);
2698
2699  if (fdivides (lcA, lcB))
2700  {
2701    if (fdivides (A, B))
2702      return F/Lc(F);
2703  }
2704  if (fdivides (lcB, lcA))
2705  {
2706    if (fdivides (B, A))
2707      return G/Lc(G);
2708  }
2709
2710  gcdlcAlcB= gcd (lcA, lcB);
2711  int skelSize= size (skel, skel.mvar());
2712
2713  int j= 0;
2714  int biggestSize= 0;
2715  int bufSize;
2716  int numberUni= 0;
2717  for (CFIterator i= skel; i.hasTerms(); i++, j++)
2718  {
2719    bufSize= size (i.coeff());
2720    biggestSize= tmax (biggestSize, bufSize);
2721    numberUni += bufSize;
2722  }
2723  numberUni--;
2724  numberUni= (int) ceil ( (double) numberUni / (skelSize - 1));
2725  biggestSize= tmax (biggestSize , numberUni);
2726
2727  numberUni= biggestSize + size (LC(skel)) - 1;
2728  int biggestSize2= tmax (numberUni, biggestSize);
2729
2730  CanonicalForm g, Aeval, Beval;
2731
2732  CFList evalPoints;
2733  CFArray coeffEval;
2734  bool evalFail= false;
2735  CFList list;
2736  bool GF= false;
2737  CanonicalForm LCA= LC (A);
2738  CanonicalForm tmp;
2739  CFArray gcds= CFArray (biggestSize);
2740  CFList * pEvalPoints= new CFList [biggestSize];
2741  Variable V_buf= alpha;
2742  CFList source, dest;
2743  CanonicalForm prim_elem, im_prim_elem;
2744  for (int i= 0; i < biggestSize; i++)
2745  {
2746    if (i == 0)
2747    {
2748      if (getCharacteristic() > 3)
2749        evalPoints= evaluationPoints (A, B, Aeval, Beval, LCA, GF, V_buf,
2750                                    evalFail, list);
2751      else
2752        evalFail= true;
2753
2754      if (evalFail)
2755      {
[9ff686]2756        if (V_buf.level() != 1)
[08daea]2757        {
2758          do
2759          {
[9ff686]2760            Variable V_buf2= chooseExtension (V_buf);
[08daea]2761            source= CFList();
2762            dest= CFList();
2763
2764            bool prim_fail= false;
2765            Variable V_buf3;
2766            prim_elem= primitiveElement (V_buf, V_buf3, prim_fail);
2767
2768            ASSERT (!prim_fail, "failure in integer factorizer");
2769            if (prim_fail)
2770              ; //ERROR
2771            else
2772              im_prim_elem= mapPrimElem (prim_elem, V_buf, V_buf2);
2773
2774            DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (V_buf));
2775            DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (V_buf2));
2776
[c1b9927]2777            for (CFListIterator i= list; i.hasItem(); i++)
[08daea]2778              i.getItem()= mapUp (i.getItem(), V_buf, V_buf2, prim_elem,
2779                                im_prim_elem, source, dest);
2780            evalFail= false;
2781            evalPoints= evaluationPoints (A, B, Aeval, Beval, LCA, GF, V_buf,
2782                                          evalFail, list);
2783          } while (evalFail);
2784        }
2785        else
2786        {
2787          CanonicalForm mipo;
2788          int deg= 2;
2789          do {
2790            mipo= randomIrredpoly (deg, x);
2791            V_buf= rootOf (mipo);
2792            evalFail= false;
2793            evalPoints= evaluationPoints (A, B, Aeval, Beval, LCA, GF, V_buf,
2794                                          evalFail, list);
2795            deg++;
2796          } while (evalFail);
2797        }
2798      }
2799    }
2800    else
2801    {
2802      mult (evalPoints, pEvalPoints[0]);
2803      eval (A, B, Aeval, Beval, evalPoints);
2804    }
2805
2806    g= gcd (Aeval, Beval);
2807    g /= Lc (g);
2808
2809    if (degree (g) != degree (skel) || (skelSize != size (g)))
2810    {
2811      delete[] pEvalPoints;
2812      fail= true;
2813      return 0;
2814    }
2815    CFIterator l= skel;
2816    for (CFIterator k= g; k.hasTerms(); k++, l++)
2817    {
2818      if (k.exp() != l.exp())
2819      {
2820        delete[] pEvalPoints;
2821        fail= true;
2822        return 0;
2823      }
2824    }
2825    pEvalPoints[i]= evalPoints;
2826    gcds[i]= g;
2827
2828    tmp= 0;
2829    int j= 0;
2830    for (CFListIterator k= evalPoints; k.hasItem(); k++, j++)
2831      tmp += k.getItem()*power (x, j);
2832    list.append (tmp);
2833  }
2834
2835  if (Monoms.size() == 0)
2836    Monoms= getMonoms (skel);
2837
2838  if (coeffMonoms == NULL)
2839    coeffMonoms= new CFArray [skelSize];
2840
2841  j= 0;
2842  for (CFIterator i= skel; i.hasTerms(); i++, j++)
2843    coeffMonoms[j]= getMonoms (i.coeff());
2844
2845  int minimalColumnsIndex;
2846  if (skelSize > 1)
2847    minimalColumnsIndex= 1;
2848  else
2849    minimalColumnsIndex= 0;
[c1b9927]2850  int minimalColumns=-1;
[08daea]2851
2852  CFArray* pM= new CFArray [skelSize];
2853  CFMatrix Mat;
[c1b9927]2854  // find the Matrix with minimal number of columns
[08daea]2855  for (int i= 0; i < skelSize; i++)
2856  {
2857    pM[i]= CFArray (coeffMonoms[i].size());
2858    if (i == 1)
2859      minimalColumns= coeffMonoms[i].size();
2860    if (i > 1)
2861    {
2862      if (minimalColumns > coeffMonoms[i].size())
2863      {
2864        minimalColumns= coeffMonoms[i].size();
2865        minimalColumnsIndex= i;
2866      }
2867    }
2868  }
2869  CFMatrix* pMat= new CFMatrix [2];
2870  pMat[0]= CFMatrix (biggestSize, coeffMonoms[0].size());
2871  pMat[1]= CFMatrix (biggestSize, coeffMonoms[minimalColumnsIndex].size());
2872  CFArray* pL= new CFArray [skelSize];
2873  for (int i= 0; i < biggestSize; i++)
2874  {
2875    CFIterator l= gcds [i];
2876    evalPoints= pEvalPoints [i];
2877    for (int k= 0; k < skelSize; k++, l++)
2878    {
2879      if (i == 0)
2880        pL[k]= CFArray (biggestSize);
[c1b9927]2881      pL[k] [i]= l.coeff();
[08daea]2882
2883      if (i == 0 && k != 0 && k != minimalColumnsIndex)
2884        pM[k]= evaluate (coeffMonoms[k], evalPoints);
2885      else if (i == 0 && (k == 0 || k == minimalColumnsIndex))
2886        coeffEval= evaluate (coeffMonoms[k], evalPoints);
2887      if (i > 0 && (k == 0 || k == minimalColumnsIndex))
2888        coeffEval= evaluate (coeffMonoms[k], evalPoints);
2889
2890      if (k == 0)
2891      {
2892        if (pMat[k].rows() >= i + 1)
2893        {
2894          for (int ind= 1; ind < coeffEval.size() + 1; ind++)
2895            pMat[k] (i + 1, ind)= coeffEval[ind - 1];
2896        }
2897      }
2898      if (k == minimalColumnsIndex)
2899      {
2900        if (pMat[1].rows() >= i + 1)
2901        {
2902          for (int ind= 1; ind < coeffEval.size() + 1; ind++)
2903            pMat[1] (i + 1, ind)= coeffEval[ind - 1];
2904        }
2905      }
2906    }
2907  }
2908
2909  CFArray solution;
2910  CanonicalForm result= 0;
2911  int ind= 1;
2912  int matRows, matColumns;
2913  matRows= pMat[1].rows();
[c1b9927]2914  matColumns= pMat[0].columns() - 1;
[08daea]2915  matColumns += pMat[1].columns();
2916
2917  Mat= CFMatrix (matRows, matColumns);
2918  for (int i= 1; i <= matRows; i++)
2919    for (int j= 1; j <= pMat[1].columns(); j++)
2920      Mat (i, j)= pMat[1] (i, j);
2921
[c1b9927]2922  for (int j= pMat[1].columns() + 1; j <= matColumns;
[08daea]2923       j++, ind++)
2924  {
[c1b9927]2925    for (int i= 1; i <= matRows; i++)
[08daea]2926      Mat (i, j)= (-pMat [0] (i, ind + 1))*pL[minimalColumnsIndex] [i - 1];
2927  }
2928
2929  CFArray firstColumn= CFArray (pMat[0].rows());
2930  for (int i= 0; i < pMat[0].rows(); i++)
[c1b9927]2931    firstColumn [i]= pMat[0] (i + 1, 1);
[08daea]2932
2933  CFArray bufArray= pL[minimalColumnsIndex];
2934
2935  for (int i= 0; i < biggestSize; i++)
2936    pL[minimalColumnsIndex] [i] *= firstColumn[i];
2937
2938  CFMatrix bufMat= pMat[1];
2939  pMat[1]= Mat;
2940
[9ff686]2941  if (V_buf.level() != 1)
[c1b9927]2942    solution= solveSystemFq (pMat[1],
[08daea]2943                             pL[minimalColumnsIndex], V_buf);
2944  else
[c1b9927]2945    solution= solveSystemFp (pMat[1],
[08daea]2946                             pL[minimalColumnsIndex]);
2947
2948  if (solution.size() == 0)
2949  { //Javadi's method failed, try deKleine, Monagan, Wittkopf instead
2950    CFMatrix bufMat0= pMat[0];
2951    delete [] pMat;
2952    pMat= new CFMatrix [skelSize];
[c1b9927]2953    pL[minimalColumnsIndex]= bufArray;
[618da5]2954    CFList* bufpEvalPoints= NULL;
[08daea]2955    CFArray bufGcds;
2956    if (biggestSize != biggestSize2)
2957    {
2958      bufpEvalPoints= pEvalPoints;
2959      pEvalPoints= new CFList [biggestSize2];
2960      bufGcds= gcds;
2961      gcds= CFArray (biggestSize2);
2962      for (int i= 0; i < biggestSize; i++)
2963      {
2964        pEvalPoints[i]= bufpEvalPoints [i];
2965        gcds[i]= bufGcds[i];
2966      }
2967      for (int i= 0; i < biggestSize2 - biggestSize; i++)
2968      {
2969        mult (evalPoints, pEvalPoints[0]);
2970        eval (A, B, Aeval, Beval, evalPoints);
2971        g= gcd (Aeval, Beval);
2972        g /= Lc (g);
2973        if (degree (g) != degree (skel) || (skelSize != size (g)))
2974        {
2975          delete[] pEvalPoints;
2976          delete[] pMat;
2977          delete[] pL;
2978          delete[] coeffMonoms;
2979          delete[] pM;
[618da5]2980          if (bufpEvalPoints != NULL)
2981            delete [] bufpEvalPoints;
[08daea]2982          fail= true;
2983          return 0;
2984        }
2985        CFIterator l= skel;
2986        for (CFIterator k= g; k.hasTerms(); k++, l++)
2987        {
2988          if (k.exp() != l.exp())
2989          {
2990            delete[] pEvalPoints;
2991            delete[] pMat;
2992            delete[] pL;
2993            delete[] coeffMonoms;
2994            delete[] pM;
[618da5]2995            if (bufpEvalPoints != NULL)
2996              delete [] bufpEvalPoints;
[08daea]2997            fail= true;
2998            return 0;
2999          }
3000        }
3001        pEvalPoints[i + biggestSize]= evalPoints;
3002        gcds[i + biggestSize]= g;
3003      }
3004    }
3005    for (int i= 0; i < biggestSize; i++)
3006    {
3007      CFIterator l= gcds [i];
3008      evalPoints= pEvalPoints [i];
3009      for (int k= 1; k < skelSize; k++, l++)
3010      {
3011        if (i == 0)
3012          pMat[k]= CFMatrix (biggestSize2,coeffMonoms[k].size()+biggestSize2-1);
3013        if (k == minimalColumnsIndex)
3014          continue;
3015        coeffEval= evaluate (coeffMonoms[k], evalPoints);
[c1b9927]3016        if (pMat[k].rows() >= i + 1)
[08daea]3017        {
3018          for (int ind= 1; ind < coeffEval.size() + 1; ind++)
3019            pMat[k] (i + 1, ind)= coeffEval[ind - 1];
3020        }
3021      }
3022    }
3023    Mat= bufMat0;
3024    pMat[0]= CFMatrix (biggestSize2, coeffMonoms[0].size() + biggestSize2 - 1);
3025    for (int j= 1; j <= Mat.rows(); j++)
3026      for (int k= 1; k <= Mat.columns(); k++)
3027        pMat [0] (j,k)= Mat (j,k);
3028    Mat= bufMat;
3029    for (int j= 1; j <= Mat.rows(); j++)
3030      for (int k= 1; k <= Mat.columns(); k++)
3031        pMat [minimalColumnsIndex] (j,k)= Mat (j,k);
3032    // write old matrix entries into new matrices
3033    for (int i= 0; i < skelSize; i++)
3034    {
3035      bufArray= pL[i];
3036      pL[i]= CFArray (biggestSize2);
3037      for (int j= 0; j < bufArray.size(); j++)
3038        pL[i] [j]= bufArray [j];
3039    }
3040    //write old vector entries into new and add new entries to old matrices
3041    for (int i= 0; i < biggestSize2 - biggestSize; i++)
3042    {
3043      CFIterator l= gcds [i + biggestSize];
3044      evalPoints= pEvalPoints [i + biggestSize];
3045      for (int k= 0; k < skelSize; k++, l++)
3046      {
[c1b9927]3047        pL[k] [i + biggestSize]= l.coeff();
[08daea]3048        coeffEval= evaluate (coeffMonoms[k], evalPoints);
[c1b9927]3049        if (pMat[k].rows() >= i + biggestSize + 1)
3050        {
[08daea]3051          for (int ind= 1; ind < coeffEval.size() + 1; ind++)
3052            pMat[k] (i + biggestSize + 1, ind)= coeffEval[ind - 1];
3053        }
3054      }
3055    }
3056    // begin new
3057    for (int i= 0; i < skelSize; i++)
3058    {
3059      if (pL[i].size() > 1)
3060      {
[c1b9927]3061        for (int j= 2; j <= pMat[i].rows(); j++)
3062          pMat[i] (j, coeffMonoms[i].size() + j - 1)=
[08daea]3063              -pL[i] [j - 1];
3064      }
3065    }
3066
3067    matColumns= biggestSize2 - 1;
3068    matRows= 0;
3069    for (int i= 0; i < skelSize; i++)
3070    {
[9ff686]3071      if (V_buf.level() == 1)
[d1dc39]3072        (void) gaussianElimFp (pMat[i], pL[i]);
[08daea]3073      else
[d1dc39]3074        (void) gaussianElimFq (pMat[i], pL[i], V_buf);
[08daea]3075
3076      if (pMat[i] (coeffMonoms[i].size(), coeffMonoms[i].size()) == 0)
3077      {
3078        delete[] pEvalPoints;
3079        delete[] pMat;
3080        delete[] pL;
3081        delete[] coeffMonoms;
3082        delete[] pM;
[618da5]3083        if (bufpEvalPoints != NULL)
3084          delete [] bufpEvalPoints;
[08daea]3085        fail= true;
3086        return 0;
3087      }
3088      matRows += pMat[i].rows() - coeffMonoms[i].size();
3089    }
3090
3091    CFMatrix bufMat;
3092    Mat= CFMatrix (matRows, matColumns);
3093    ind= 0;
3094    bufArray= CFArray (matRows);
3095    CFArray bufArray2;
3096    for (int i= 0; i < skelSize; i++)
3097    {
3098      bufMat= pMat[i] (coeffMonoms[i].size() + 1, pMat[i].rows(),
3099                       coeffMonoms[i].size() + 1, pMat[i].columns());
3100
3101      for (int j= 1; j <= bufMat.rows(); j++)
3102        for (int k= 1; k <= bufMat.columns(); k++)
3103          Mat (j + ind, k)= bufMat(j, k);
3104      bufArray2= coeffMonoms[i].size();
3105      for (int j= 1; j <= pMat[i].rows(); j++)
3106      {
3107        if (j > coeffMonoms[i].size())
3108          bufArray [j-coeffMonoms[i].size() + ind - 1]= pL[i] [j - 1];
[c1b9927]3109        else
[08daea]3110          bufArray2 [j - 1]= pL[i] [j - 1];
3111      }
3112      pL[i]= bufArray2;
3113      ind += bufMat.rows();
3114      pMat[i]= pMat[i] (1, coeffMonoms[i].size(), 1, pMat[i].columns());
3115    }
3116
[9ff686]3117    if (V_buf.level() != 1)
[08daea]3118      solution= solveSystemFq (Mat, bufArray, V_buf);
3119    else
3120      solution= solveSystemFp (Mat, bufArray);
3121
3122    if (solution.size() == 0)
3123    {
3124      delete[] pEvalPoints;
3125      delete[] pMat;
3126      delete[] pL;
3127      delete[] coeffMonoms;
3128      delete[] pM;
[618da5]3129      if (bufpEvalPoints != NULL)
3130        delete [] bufpEvalPoints;
[08daea]3131      fail= true;
3132      return 0;
3133    }
3134
3135    ind= 0;
3136    result= 0;
3137    CFArray bufSolution;
3138    for (int i= 0; i < skelSize; i++)
3139    {
3140      bufSolution= readOffSolution (pMat[i], pL[i], solution);
3141      for (int i= 0; i < bufSolution.size(); i++, ind++)
3142        result += Monoms [ind]*bufSolution[i];
3143    }
[9ff686]3144    if (alpha.level() != 1 && V_buf != alpha)
[08daea]3145    {
3146      CFList u, v;
3147      result= mapDown (result, prim_elem, im_prim_elem, alpha, u, v);
3148    }
3149    result= N(result);
3150    if (fdivides (result, F) && fdivides (result, G))
[618da5]3151    {
3152      delete[] pEvalPoints;
3153      delete[] pMat;
3154      delete[] pL;
3155      delete[] pM;
3156      if (bufpEvalPoints != NULL)
3157        delete [] bufpEvalPoints;
[08daea]3158      return result;
[618da5]3159    }
[08daea]3160    else
3161    {
[618da5]3162      delete[] pEvalPoints;
3163      delete[] pMat;
3164      delete[] pL;
3165      delete[] coeffMonoms;
3166      delete[] pM;
3167      if (bufpEvalPoints != NULL)
3168        delete [] bufpEvalPoints;
[08daea]3169      fail= true;
3170      return 0;
3171    }
3172  } // end of deKleine, Monagan & Wittkopf
3173
3174  result += Monoms[0];
3175  int ind2= 0, ind3= 2;
3176  ind= 0;
3177  for (int l= 0; l < minimalColumnsIndex; l++)
3178    ind += coeffMonoms[l].size();
3179  for (int l= solution.size() - pMat[0].columns() + 1; l < solution.size();
3180       l++, ind2++, ind3++)
3181  {
3182    result += solution[l]*Monoms [1 + ind2];
[c1b9927]3183    for (int i= 0; i < pMat[0].rows(); i++)
[08daea]3184      firstColumn[i] += solution[l]*pMat[0] (i + 1, ind3);
3185  }
3186  for (int l= 0; l < solution.size() + 1 - pMat[0].columns(); l++)
3187    result += solution[l]*Monoms [ind + l];
3188  ind= coeffMonoms[0].size();
3189  for (int k= 1; k < skelSize; k++)
3190  {
3191    if (k == minimalColumnsIndex)
3192    {
3193      ind += coeffMonoms[k].size();
3194      continue;
3195    }
3196    if (k != minimalColumnsIndex)
3197    {
3198      for (int i= 0; i < biggestSize; i++)
3199        pL[k] [i] *= firstColumn [i];
3200    }
3201
3202    if (biggestSize != coeffMonoms[k].size() && k != minimalColumnsIndex)
3203    {
3204      bufArray= CFArray (coeffMonoms[k].size());
3205      for (int i= 0; i < bufArray.size(); i++)
3206        bufArray [i]= pL[k] [i];
3207      solution= solveGeneralVandermonde (pM[k], bufArray);
3208    }
3209    else
3210      solution= solveGeneralVandermonde (pM[k], pL[k]);
3211
3212    if (solution.size() == 0)
3213    {
3214      delete[] pEvalPoints;
3215      delete[] pMat;
3216      delete[] pL;
3217      delete[] coeffMonoms;
3218      delete[] pM;
3219      fail= true;
3220      return 0;
3221    }
3222    if (k != minimalColumnsIndex)
3223    {
3224      for (int l= 0; l < solution.size(); l++)
3225        result += solution[l]*Monoms [ind + l];
3226      ind += solution.size();
3227    }
3228  }
3229
3230  delete[] pEvalPoints;
3231  delete[] pMat;
3232  delete[] pL;
3233  delete[] pM;
3234
[9ff686]3235  if (alpha.level() != 1 && V_buf != alpha)
[08daea]3236  {
3237    CFList u, v;
3238    result= mapDown (result, prim_elem, im_prim_elem, alpha, u, v);
3239  }
3240  result= N(result);
3241
3242  if (fdivides (result, F) && fdivides (result, G))
3243    return result;
3244  else
3245  {
3246    delete[] coeffMonoms;
3247    fail= true;
3248    return 0;
3249  }
3250}
3251
3252CanonicalForm sparseGCDFq (const CanonicalForm& F, const CanonicalForm& G,
3253                           const Variable & alpha, CFList& l, bool& topLevel)
3254{
3255  CanonicalForm A= F;
3256  CanonicalForm B= G;
3257  if (F.isZero() && degree(G) > 0) return G/Lc(G);
3258  else if (G.isZero() && degree (F) > 0) return F/Lc(F);
3259  else if (F.isZero() && G.isZero()) return F.genOne();
3260  if (F.inBaseDomain() || G.inBaseDomain()) return F.genOne();
3261  if (F.isUnivariate() && fdivides(F, G)) return F/Lc(F);
3262  if (G.isUnivariate() && fdivides(G, F)) return G/Lc(G);
3263  if (F == G) return F/Lc(F);
3264
3265  CFMap M,N;
3266  int best_level= myCompress (A, B, M, N, topLevel);
3267
3268  if (best_level == 0) return B.genOne();
3269
3270  A= M(A);
3271  B= M(B);
3272
3273  Variable x= Variable (1);
3274
[c1b9927]3275  //univariate case
[08daea]3276  if (A.isUnivariate() && B.isUnivariate())
3277    return N (gcd (A, B));
3278
3279  CanonicalForm cA, cB;    // content of A and B
3280  CanonicalForm ppA, ppB;    // primitive part of A and B
3281  CanonicalForm gcdcAcB;
[ea5ff1d]3282
3283  cA = uni_content (A);
3284  cB = uni_content (B);
3285  gcdcAcB= gcd (cA, cB);
3286  ppA= A/cA;
3287  ppB= B/cB;
[08daea]3288
3289  CanonicalForm lcA, lcB;  // leading coefficients of A and B
3290  CanonicalForm gcdlcAlcB;
3291  lcA= uni_lcoeff (ppA);
3292  lcB= uni_lcoeff (ppB);
3293
3294  if (fdivides (lcA, lcB))
3295  {
3296    if (fdivides (A, B))
3297      return F/Lc(F);
3298  }
3299  if (fdivides (lcB, lcA))
3300  {
3301    if (fdivides (B, A))
3302      return G/Lc(G);
3303  }
3304
3305  gcdlcAlcB= gcd (lcA, lcB);
3306
3307  int d= totaldegree (ppA, Variable (2), Variable (ppA.level()));
3308  int d0;
3309
[c1b9927]3310  if (d == 0)
[a9a6dcb]3311    return N(gcdcAcB);
[08daea]3312  d0= totaldegree (ppB, Variable (2), Variable (ppB.level()));
3313
3314  if (d0 < d)
3315    d= d0;
3316
3317  if (d == 0)
[a9a6dcb]3318    return N(gcdcAcB);
[08daea]3319
3320  CanonicalForm m, random_element, G_m, G_random_element, H, cH, ppH, skeleton;
3321  CanonicalForm newtonPoly= 1;
3322  m= gcdlcAlcB;
3323  G_m= 0;
3324  H= 0;
3325  bool fail= false;
3326  topLevel= false;
3327  bool inextension= false;
3328  Variable V_buf= alpha;
3329  CanonicalForm prim_elem, im_prim_elem;
3330  CFList source, dest;
3331  do // first do
3332  {
3333    random_element= randomElement (m, V_buf, l, fail);
3334    if (random_element == 0 && !fail)
3335    {
3336      if (!find (l, random_element))
3337        l.append (random_element);
3338      continue;
3339    }
3340    if (fail)
3341    {
3342      source= CFList();
3343      dest= CFList();
3344
[9ff686]3345      Variable V_buf3= V_buf;
3346      V_buf= chooseExtension (V_buf);
[08daea]3347      bool prim_fail= false;
3348      Variable V_buf2;
3349      prim_elem= primitiveElement (alpha, V_buf2, prim_fail);
3350
[9ff686]3351      if (V_buf3 != alpha)
3352      {
3353        m= mapDown (m, prim_elem, im_prim_elem, alpha, source, dest);
3354        G_m= mapDown (m, prim_elem, im_prim_elem, alpha, source, dest);
3355        newtonPoly= mapDown (newtonPoly, prim_elem, im_prim_elem, alpha,
3356                             source, dest);
3357        ppA= mapDown (ppA, prim_elem, im_prim_elem, alpha, source, dest);
3358        ppB= mapDown (ppB, prim_elem, im_prim_elem, alpha, source, dest);
3359        gcdlcAlcB= mapDown (gcdlcAlcB, prim_elem, im_prim_elem, alpha, source,
3360                            dest);
3361        for (CFListIterator i= l; i.hasItem(); i++)
3362          i.getItem()= mapDown (i.getItem(), prim_elem, im_prim_elem, alpha,
3363                                source, dest);
3364      }
3365
[08daea]3366      ASSERT (!prim_fail, "failure in integer factorizer");
3367      if (prim_fail)
3368        ; //ERROR
3369      else
3370        im_prim_elem= mapPrimElem (prim_elem, alpha, V_buf);
3371
3372      DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (alpha));
3373      DEBOUTLN (cerr, "getMipo (V_buf2)= " << getMipo (V_buf2));
3374      inextension= true;
[c1b9927]3375      for (CFListIterator i= l; i.hasItem(); i++)
[08daea]3376        i.getItem()= mapUp (i.getItem(), alpha, V_buf, prim_elem,
3377                             im_prim_elem, source, dest);
3378      m= mapUp (m, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
3379      G_m= mapUp (G_m, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
3380      newtonPoly= mapUp (newtonPoly, alpha, V_buf, prim_elem, im_prim_elem,
3381                          source, dest);
3382      ppA= mapUp (ppA, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
3383      ppB= mapUp (ppB, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
3384      gcdlcAlcB= mapUp (gcdlcAlcB, alpha, V_buf, prim_elem, im_prim_elem,
3385                         source, dest);
3386
3387      fail= false;
3388      random_element= randomElement (m, V_buf, l, fail );
3389      DEBOUTLN (cerr, "fail= " << fail);
3390      CFList list;
3391      TIMING_START (gcd_recursion);
3392      G_random_element=
3393      sparseGCDFq (ppA (random_element, x), ppB (random_element, x), V_buf,
3394                        list, topLevel);
3395      TIMING_END_AND_PRINT (gcd_recursion,
3396                            "time for recursive call: ");
3397      DEBOUTLN (cerr, "G_random_element= " << G_random_element);
3398    }
3399    else
3400    {
3401      CFList list;
3402      TIMING_START (gcd_recursion);
3403      G_random_element=
3404      sparseGCDFq (ppA(random_element, x), ppB(random_element, x), V_buf,
3405                        list, topLevel);
3406      TIMING_END_AND_PRINT (gcd_recursion,
3407                            "time for recursive call: ");
3408      DEBOUTLN (cerr, "G_random_element= " << G_random_element);
3409    }
3410
[a76d6fe]3411    if (!G_random_element.inCoeffDomain())
3412      d0= totaldegree (G_random_element, Variable(2),
3413                       Variable (G_random_element.level()));
3414    else
3415      d0= 0;
3416
[08daea]3417    if (d0 == 0)
[a9a6dcb]3418      return N(gcdcAcB);
[08daea]3419    if (d0 >  d)
3420    {
3421      if (!find (l, random_element))
3422        l.append (random_element);
3423      continue;
3424    }
3425
3426    G_random_element=
3427    (gcdlcAlcB(random_element, x)/uni_lcoeff (G_random_element))
3428    * G_random_element;
3429
3430    skeleton= G_random_element;
[a76d6fe]3431    if (!G_random_element.inCoeffDomain())
3432      d0= totaldegree (G_random_element, Variable(2),
3433                       Variable (G_random_element.level()));
3434    else
3435      d0= 0;
3436
[08daea]3437    if (d0 <  d)
3438    {
3439      m= gcdlcAlcB;
3440      newtonPoly= 1;
3441      G_m= 0;
3442      d= d0;
3443    }
3444
3445    H= newtonInterp (random_element, G_random_element, newtonPoly, G_m, x);
3446    if (uni_lcoeff (H) == gcdlcAlcB)
3447    {
3448      cH= uni_content (H);
3449      ppH= H/cH;
3450      if (inextension)
3451      {
3452        CFList u, v;
3453        //maybe it's better to test if ppH is an element of F(\alpha) before
3454        //mapping down
[c723d80]3455        if (fdivides (ppH, ppA) && fdivides (ppH, ppB))
[08daea]3456        {
[c723d80]3457          DEBOUTLN (cerr, "ppH before mapDown= " << ppH);
3458          ppH= mapDown (ppH, prim_elem, im_prim_elem, alpha, u, v);
3459          ppH /= Lc(ppH);
3460          DEBOUTLN (cerr, "ppH after mapDown= " << ppH);
[08daea]3461          return N(gcdcAcB*ppH);
3462        }
3463      }
[c723d80]3464      else if (fdivides (ppH, ppA) && fdivides (ppH, ppB))
[08daea]3465        return N(gcdcAcB*ppH);
3466    }
3467    G_m= H;
3468    newtonPoly= newtonPoly*(x - random_element);
3469    m= m*(x - random_element);
3470    if (!find (l, random_element))
3471      l.append (random_element);
3472
[d08ed8]3473    if (getCharacteristic () > 3 && size (skeleton) < 100)
[08daea]3474    {
3475      CFArray Monoms;
3476      CFArray *coeffMonoms= NULL;
3477      do //second do
3478      {
3479        random_element= randomElement (m, V_buf, l, fail);
3480        if (random_element == 0 && !fail)
3481        {
3482          if (!find (l, random_element))
3483            l.append (random_element);
3484          continue;
3485        }
3486        if (fail)
3487        {
3488          source= CFList();
3489          dest= CFList();
3490
[9ff686]3491          Variable V_buf3= V_buf;
3492          V_buf= chooseExtension (V_buf);
[08daea]3493          bool prim_fail= false;
3494          Variable V_buf2;
3495          prim_elem= primitiveElement (alpha, V_buf2, prim_fail);
3496
[9ff686]3497          if (V_buf3 != alpha)
3498          {
3499            m= mapDown (m, prim_elem, im_prim_elem, alpha, source, dest);
3500            G_m= mapDown (m, prim_elem, im_prim_elem, alpha, source, dest);
3501            newtonPoly= mapDown (newtonPoly, prim_elem, im_prim_elem, alpha,
3502                                 source, dest);
3503            ppA= mapDown (ppA, prim_elem, im_prim_elem, alpha, source, dest);
3504            ppB= mapDown (ppB, prim_elem, im_prim_elem, alpha, source, dest);
3505            gcdlcAlcB= mapDown (gcdlcAlcB, prim_elem, im_prim_elem, alpha,
3506                                source, dest);
3507            for (CFListIterator i= l; i.hasItem(); i++)
3508              i.getItem()= mapDown (i.getItem(), prim_elem, im_prim_elem, alpha,
3509                                    source, dest);
3510          }
3511
[08daea]3512          ASSERT (!prim_fail, "failure in integer factorizer");
3513          if (prim_fail)
3514            ; //ERROR
3515          else
3516            im_prim_elem= mapPrimElem (prim_elem, alpha, V_buf);
3517
3518          DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (alpha));
3519          DEBOUTLN (cerr, "getMipo (V_buf2)= " << getMipo (V_buf2));
3520          inextension= true;
[c1b9927]3521          for (CFListIterator i= l; i.hasItem(); i++)
[08daea]3522            i.getItem()= mapUp (i.getItem(), alpha, V_buf, prim_elem,
3523                                im_prim_elem, source, dest);
3524          m= mapUp (m, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
3525          G_m= mapUp (G_m, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
3526          newtonPoly= mapUp (newtonPoly, alpha, V_buf, prim_elem, im_prim_elem,
3527                              source, dest);
3528          ppA= mapUp (ppA, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
3529          ppB= mapUp (ppB, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
3530
3531          gcdlcAlcB= mapUp (gcdlcAlcB, alpha, V_buf, prim_elem, im_prim_elem,
3532                            source, dest);
3533
3534          fail= false;
3535          random_element= randomElement (m, V_buf, l, fail);
3536          DEBOUTLN (cerr, "fail= " << fail);
3537          CFList list;
3538          TIMING_START (gcd_recursion);
3539
3540          //sparseInterpolation
3541          bool sparseFail= false;
3542          if (LC (skeleton).inCoeffDomain())
[c1b9927]3543            G_random_element=
[08daea]3544            monicSparseInterpol (ppA (random_element, x), ppB(random_element,x),
3545                                skeleton,V_buf, sparseFail, coeffMonoms,Monoms);
3546          else
3547            G_random_element=
3548            nonMonicSparseInterpol (ppA(random_element,x),ppB(random_element,x),
3549                                    skeleton, V_buf, sparseFail, coeffMonoms,
3550                                    Monoms);
3551          if (sparseFail)
3552            break;
3553
3554          TIMING_END_AND_PRINT (gcd_recursion,
3555                                "time for recursive call: ");
3556          DEBOUTLN (cerr, "G_random_element= " << G_random_element);
3557        }
3558        else
3559        {
3560          CFList list;
3561          TIMING_START (gcd_recursion);
3562          bool sparseFail= false;
3563          if (LC (skeleton).inCoeffDomain())
[c1b9927]3564            G_random_element=
[08daea]3565            monicSparseInterpol (ppA (random_element, x),ppB(random_element, x),
3566                                skeleton,V_buf, sparseFail,coeffMonoms, Monoms);
3567          else
3568            G_random_element=
3569            nonMonicSparseInterpol (ppA(random_element,x),ppB(random_element,x),
[c1b9927]3570                                    skeleton, V_buf, sparseFail, coeffMonoms,
[08daea]3571                                    Monoms);
3572          if (sparseFail)
3573            break;
3574
3575          TIMING_END_AND_PRINT (gcd_recursion,
3576                                "time for recursive call: ");
3577          DEBOUTLN (cerr, "G_random_element= " << G_random_element);
3578        }
3579
[a76d6fe]3580        if (!G_random_element.inCoeffDomain())
3581          d0= totaldegree (G_random_element, Variable(2),
3582                           Variable (G_random_element.level()));
3583        else
3584          d0= 0;
3585
[08daea]3586        if (d0 == 0)
[a9a6dcb]3587          return N(gcdcAcB);
[08daea]3588        if (d0 >  d)
3589        {
3590          if (!find (l, random_element))
3591            l.append (random_element);
3592          continue;
3593        }
3594
3595        G_random_element=
3596        (gcdlcAlcB(random_element, x)/uni_lcoeff (G_random_element))
3597        * G_random_element;
3598
[a76d6fe]3599        if (!G_random_element.inCoeffDomain())
3600          d0= totaldegree (G_random_element, Variable(2),
3601                          Variable (G_random_element.level()));
3602        else
3603          d0= 0;
3604
[08daea]3605        if (d0 <  d)
3606        {
3607          m= gcdlcAlcB;
3608          newtonPoly= 1;
3609          G_m= 0;
3610          d= d0;
3611        }
3612
3613        TIMING_START (newton_interpolation);
3614        H= newtonInterp (random_element, G_random_element, newtonPoly, G_m, x);
3615        TIMING_END_AND_PRINT (newton_interpolation,
3616                              "time for newton interpolation: ");
3617
3618        //termination test
3619        if (uni_lcoeff (H) == gcdlcAlcB)
3620        {
3621          cH= uni_content (H);
3622          ppH= H/cH;
3623          if (inextension)
3624          {
3625            CFList u, v;
3626            //maybe it's better to test if ppH is an element of F(\alpha) before
3627            //mapping down
[c723d80]3628            if (fdivides (ppH, ppA) && fdivides (ppH, ppB))
[08daea]3629            {
[c723d80]3630              DEBOUTLN (cerr, "ppH before mapDown= " << ppH);
3631              ppH= mapDown (ppH, prim_elem, im_prim_elem, alpha, u, v);
3632              ppH /= Lc(ppH);
3633              DEBOUTLN (cerr, "ppH after mapDown= " << ppH);
[08daea]3634              return N(gcdcAcB*ppH);
3635            }
3636          }
[c723d80]3637          else if (fdivides (ppH, ppA) && fdivides (ppH, ppB))
[08daea]3638          {
3639            return N(gcdcAcB*ppH);
3640          }
3641        }
3642
3643        G_m= H;
3644        newtonPoly= newtonPoly*(x - random_element);
3645        m= m*(x - random_element);
3646        if (!find (l, random_element))
3647          l.append (random_element);
3648
3649      } while (1);
3650    }
3651  } while (1);
3652}
3653
3654CanonicalForm sparseGCDFp (const CanonicalForm& F, const CanonicalForm& G,
3655                           bool& topLevel, CFList& l)
3656{
3657  CanonicalForm A= F;
3658  CanonicalForm B= G;
3659  if (F.isZero() && degree(G) > 0) return G/Lc(G);
3660  else if (G.isZero() && degree (F) > 0) return F/Lc(F);
3661  else if (F.isZero() && G.isZero()) return F.genOne();
3662  if (F.inBaseDomain() || G.inBaseDomain()) return F.genOne();
3663  if (F.isUnivariate() && fdivides(F, G)) return F/Lc(F);
3664  if (G.isUnivariate() && fdivides(G, F)) return G/Lc(G);
3665  if (F == G) return F/Lc(F);
3666
3667  CFMap M,N;
3668  int best_level= myCompress (A, B, M, N, topLevel);
3669
3670  if (best_level == 0) return B.genOne();
3671
3672  A= M(A);
3673  B= M(B);
3674
3675  Variable x= Variable (1);
3676
[c1b9927]3677  //univariate case
[08daea]3678  if (A.isUnivariate() && B.isUnivariate())
3679    return N (gcd (A, B));
3680
3681  CanonicalForm cA, cB;    // content of A and B
3682  CanonicalForm ppA, ppB;    // primitive part of A and B
3683  CanonicalForm gcdcAcB;
[ea5ff1d]3684
3685  cA = uni_content (A);
3686  cB = uni_content (B);
3687  gcdcAcB= gcd (cA, cB);
3688  ppA= A/cA;
3689  ppB= B/cB;
[08daea]3690
3691  CanonicalForm lcA, lcB;  // leading coefficients of A and B
3692  CanonicalForm gcdlcAlcB;
3693  lcA= uni_lcoeff (ppA);
3694  lcB= uni_lcoeff (ppB);
3695
3696  if (fdivides (lcA, lcB))
3697  {
3698    if (fdivides (A, B))
3699      return F/Lc(F);
3700  }
3701  if (fdivides (lcB, lcA))
3702  {
3703    if (fdivides (B, A))
3704      return G/Lc(G);
3705  }
3706
3707  gcdlcAlcB= gcd (lcA, lcB);
3708
3709  int d= totaldegree (ppA, Variable (2), Variable (ppA.level()));
3710  int d0;
3711
3712  if (d == 0)
[a9a6dcb]3713    return N(gcdcAcB);
3714
[08daea]3715  d0= totaldegree (ppB, Variable (2), Variable (ppB.level()));
3716
3717  if (d0 < d)
3718    d= d0;
3719
3720  if (d == 0)
[a9a6dcb]3721    return N(gcdcAcB);
[08daea]3722
3723  CanonicalForm m, random_element, G_m, G_random_element, H, cH, ppH, skeleton;
3724  CanonicalForm newtonPoly= 1;
3725  m= gcdlcAlcB;
3726  G_m= 0;
3727  H= 0;
3728  bool fail= false;
3729  topLevel= false;
3730  bool inextension= false;
3731  Variable V_buf, alpha;
3732  CanonicalForm prim_elem, im_prim_elem;
3733  CFList source, dest;
3734  do //first do
3735  {
3736    if (inextension)
[9ff686]3737      random_element= randomElement (m, V_buf, l, fail);
[08daea]3738    else
3739      random_element= FpRandomElement (m, l, fail);
3740    if (random_element == 0 && !fail)
3741    {
3742      if (!find (l, random_element))
3743        l.append (random_element);
3744      continue;
3745    }
3746
3747    if (!fail && !inextension)
3748    {
3749      CFList list;
3750      TIMING_START (gcd_recursion);
3751      G_random_element=
3752      sparseGCDFp (ppA (random_element,x), ppB (random_element,x), topLevel,
3753                   list);
3754      TIMING_END_AND_PRINT (gcd_recursion,
3755                            "time for recursive call: ");
3756      DEBOUTLN (cerr, "G_random_element= " << G_random_element);
3757    }
3758    else if (!fail && inextension)
3759    {
3760      CFList list;
3761      TIMING_START (gcd_recursion);
3762      G_random_element=
3763      sparseGCDFq (ppA (random_element, x), ppB (random_element, x), alpha,
3764                        list, topLevel);
3765      TIMING_END_AND_PRINT (gcd_recursion,
3766                            "time for recursive call: ");
3767      DEBOUTLN (cerr, "G_random_element= " << G_random_element);
3768    }
3769    else if (fail && !inextension)
3770    {
3771      source= CFList();
3772      dest= CFList();
3773      CFList list;
3774      CanonicalForm mipo;
3775      int deg= 2;
3776      do
3777      {
3778        mipo= randomIrredpoly (deg, x);
3779        alpha= rootOf (mipo);
3780        inextension= true;
3781        fail= false;
[c1b9927]3782        random_element= randomElement (m, alpha, l, fail);
[08daea]3783        deg++;
3784      } while (fail);
[9ff686]3785      V_buf= alpha;
[08daea]3786      list= CFList();
3787      TIMING_START (gcd_recursion);
3788      G_random_element=
3789      sparseGCDFq (ppA (random_element, x), ppB (random_element, x), alpha,
3790                        list, topLevel);
3791      TIMING_END_AND_PRINT (gcd_recursion,
3792                            "time for recursive call: ");
3793      DEBOUTLN (cerr, "G_random_element= " << G_random_element);
3794    }
3795    else if (fail && inextension)
3796    {
3797      source= CFList();
3798      dest= CFList();
[9ff686]3799
3800      Variable V_buf3= V_buf;
3801      V_buf= chooseExtension (V_buf);
[08daea]3802      bool prim_fail= false;
3803      Variable V_buf2;
3804      CanonicalForm prim_elem, im_prim_elem;
3805      prim_elem= primitiveElement (alpha, V_buf2, prim_fail);
3806
[9ff686]3807      if (V_buf3 != alpha)
3808      {
3809        m= mapDown (m, prim_elem, im_prim_elem, alpha, source, dest);
3810        G_m= mapDown (m, prim_elem, im_prim_elem, alpha, source, dest);
3811        newtonPoly= mapDown (newtonPoly, prim_elem, im_prim_elem, alpha, source,
3812                             dest);
3813        ppA= mapDown (ppA, prim_elem, im_prim_elem, alpha, source, dest);
3814        ppB= mapDown (ppB, prim_elem, im_prim_elem, alpha, source, dest);
3815        gcdlcAlcB= mapDown (gcdlcAlcB, prim_elem, im_prim_elem, alpha, source,
3816                            dest);
3817        for (CFListIterator i= l; i.hasItem(); i++)
3818          i.getItem()= mapDown (i.getItem(), prim_elem, im_prim_elem, alpha,
3819                                source, dest);
3820      }
3821
[08daea]3822      ASSERT (!prim_fail, "failure in integer factorizer");
3823      if (prim_fail)
3824        ; //ERROR
3825      else
3826        im_prim_elem= mapPrimElem (prim_elem, alpha, V_buf);
3827
3828      DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (alpha));
3829      DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (V_buf2));
3830
3831      for (CFListIterator i= l; i.hasItem(); i++)
3832        i.getItem()= mapUp (i.getItem(), alpha, V_buf, prim_elem,
3833                             im_prim_elem, source, dest);
3834      m= mapUp (m, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
3835      G_m= mapUp (G_m, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
3836      newtonPoly= mapUp (newtonPoly, alpha, V_buf, prim_elem, im_prim_elem,
3837                          source, dest);
3838      ppA= mapUp (ppA, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
3839      ppB= mapUp (ppB, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
3840      gcdlcAlcB= mapUp (gcdlcAlcB, alpha, V_buf, prim_elem, im_prim_elem,
3841                         source, dest);
3842      fail= false;
3843      random_element= randomElement (m, V_buf, l, fail );
3844      DEBOUTLN (cerr, "fail= " << fail);
3845      CFList list;
3846      TIMING_START (gcd_recursion);
3847      G_random_element=
3848      sparseGCDFq (ppA (random_element, x), ppB (random_element, x), V_buf,
3849                        list, topLevel);
3850      TIMING_END_AND_PRINT (gcd_recursion,
3851                            "time for recursive call: ");
3852      DEBOUTLN (cerr, "G_random_element= " << G_random_element);
3853    }
3854
[a76d6fe]3855    if (!G_random_element.inCoeffDomain())
3856      d0= totaldegree (G_random_element, Variable(2),
3857                       Variable (G_random_element.level()));
3858    else
3859      d0= 0;
3860
[08daea]3861    if (d0 == 0)
[a9a6dcb]3862      return N(gcdcAcB);
[08daea]3863    if (d0 >  d)
3864    {
3865      if (!find (l, random_element))
3866        l.append (random_element);
3867      continue;
3868    }
3869
3870    G_random_element=
3871    (gcdlcAlcB(random_element, x)/uni_lcoeff (G_random_element))
3872    * G_random_element;
3873
3874    skeleton= G_random_element;
3875
[a76d6fe]3876    if (!G_random_element.inCoeffDomain())
3877      d0= totaldegree (G_random_element, Variable(2),
3878                       Variable (G_random_element.level()));
3879    else
3880      d0= 0;
3881
[08daea]3882    if (d0 <  d)
3883    {
3884      m= gcdlcAlcB;
3885      newtonPoly= 1;
3886      G_m= 0;
3887      d= d0;
3888    }
3889
3890    H= newtonInterp (random_element, G_random_element, newtonPoly, G_m, x);
3891
3892    if (uni_lcoeff (H) == gcdlcAlcB)
3893    {
3894      cH= uni_content (H);
3895      ppH= H/cH;
3896      ppH /= Lc (ppH);
3897      DEBOUTLN (cerr, "ppH= " << ppH);
3898
[c723d80]3899      if (fdivides (ppH, ppA) && fdivides (ppH, ppB))
[08daea]3900        return N(gcdcAcB*ppH);
3901    }
3902    G_m= H;
3903    newtonPoly= newtonPoly*(x - random_element);
3904    m= m*(x - random_element);
3905    if (!find (l, random_element))
3906      l.append (random_element);
3907
[9879d0]3908    if ((getCharacteristic() > 3 && size (skeleton) < 200))
[08daea]3909    {
3910      CFArray Monoms;
3911      CFArray* coeffMonoms= NULL;
3912
3913      do //second do
3914      {
3915        if (inextension)
3916          random_element= randomElement (m, alpha, l, fail);
3917        else
3918          random_element= FpRandomElement (m, l, fail);
3919        if (random_element == 0 && !fail)
3920        {
3921          if (!find (l, random_element))
3922            l.append (random_element);
3923          continue;
3924        }
3925
3926        bool sparseFail= false;
3927        if (!fail && !inextension)
3928        {
3929          CFList list;
3930          TIMING_START (gcd_recursion);
3931          if (LC (skeleton).inCoeffDomain())
3932            G_random_element=
3933            monicSparseInterpol(ppA(random_element, x), ppB (random_element, x),
3934                                skeleton, Variable(1), sparseFail, coeffMonoms,
3935                                Monoms);
3936          else
3937            G_random_element=
3938            nonMonicSparseInterpol(ppA(random_element,x), ppB(random_element,x),
3939                                    skeleton, Variable (1), sparseFail,
3940                                    coeffMonoms, Monoms);
3941          TIMING_END_AND_PRINT (gcd_recursion,
3942                                "time for recursive call: ");
3943          DEBOUTLN (cerr, "G_random_element= " << G_random_element);
3944        }
3945        else if (!fail && inextension)
3946        {
3947          CFList list;
3948          TIMING_START (gcd_recursion);
3949          if (LC (skeleton).inCoeffDomain())
3950            G_random_element=
3951            monicSparseInterpol(ppA (random_element,x), ppB (random_element, x),
3952                                skeleton, alpha, sparseFail, coeffMonoms,
3953                                Monoms);
3954          else
3955            G_random_element=
3956            nonMonicSparseInterpol(ppA(random_element,x), ppB(random_element,x),
3957                                   skeleton, alpha, sparseFail, coeffMonoms,
3958                                   Monoms);
3959          TIMING_END_AND_PRINT (gcd_recursion,
3960                                "time for recursive call: ");
3961          DEBOUTLN (cerr, "G_random_element= " << G_random_element);
3962        }
3963        else if (fail && !inextension)
3964        {
3965          source= CFList();
3966          dest= CFList();
3967          CFList list;
3968          CanonicalForm mipo;
3969          int deg= 2;
[c1b9927]3970          do
[08daea]3971          {
3972            mipo= randomIrredpoly (deg, x);
3973            alpha= rootOf (mipo);
3974            inextension= true;
3975            fail= false;
3976            random_element= randomElement (m, alpha, l, fail);
3977            deg++;
3978          } while (fail);
[9ff686]3979          V_buf= alpha;
[08daea]3980          list= CFList();
3981          TIMING_START (gcd_recursion);
3982          if (LC (skeleton).inCoeffDomain())
3983            G_random_element=
3984            monicSparseInterpol (ppA (random_element,x), ppB (random_element,x),
3985                                skeleton, alpha, sparseFail, coeffMonoms,
3986                                Monoms);
3987          else
3988            G_random_element=
3989            nonMonicSparseInterpol(ppA(random_element,x), ppB(random_element,x),
3990                                   skeleton, alpha, sparseFail, coeffMonoms,
3991                                   Monoms);
3992          TIMING_END_AND_PRINT (gcd_recursion,
3993                                "time for recursive call: ");
3994          DEBOUTLN (cerr, "G_random_element= " << G_random_element);
3995        }
3996        else if (fail && inextension)
3997        {
3998          source= CFList();
3999          dest= CFList();
[9ff686]4000
4001          Variable V_buf3= V_buf;
4002          V_buf= chooseExtension (V_buf);
[08daea]4003          bool prim_fail= false;
4004          Variable V_buf2;
4005          CanonicalForm prim_elem, im_prim_elem;
4006          prim_elem= primitiveElement (alpha, V_buf2, prim_fail);
4007
[9ff686]4008          if (V_buf3 != alpha)
4009          {
4010            m= mapDown (m, prim_elem, im_prim_elem, alpha, source, dest);
4011            G_m= mapDown (m, prim_elem, im_prim_elem, alpha, source, dest);
4012            newtonPoly= mapDown (newtonPoly, prim_elem, im_prim_elem, alpha,
4013                                 source, dest);
4014            ppA= mapDown (ppA, prim_elem, im_prim_elem, alpha, source, dest);
4015            ppB= mapDown (ppB, prim_elem, im_prim_elem, alpha, source, dest);
4016            gcdlcAlcB= mapDown (gcdlcAlcB, prim_elem, im_prim_elem, alpha,
4017                                source, dest);
4018            for (CFListIterator i= l; i.hasItem(); i++)
4019              i.getItem()= mapDown (i.getItem(), prim_elem, im_prim_elem, alpha,
4020                                    source, dest);
4021          }
4022
[08daea]4023          ASSERT (!prim_fail, "failure in integer factorizer");
4024          if (prim_fail)
4025            ; //ERROR
4026          else
4027            im_prim_elem= mapPrimElem (prim_elem, alpha, V_buf);
4028
4029          DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (alpha));
4030          DEBOUTLN (cerr, "getMipo (alpha)= " << getMipo (V_buf2));
4031
4032          for (CFListIterator i= l; i.hasItem(); i++)
4033            i.getItem()= mapUp (i.getItem(), alpha, V_buf, prim_elem,
4034                                im_prim_elem, source, dest);
4035          m= mapUp (m, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
4036          G_m= mapUp (G_m, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
4037          newtonPoly= mapUp (newtonPoly, alpha, V_buf, prim_elem, im_prim_elem,
4038                              source, dest);
4039          ppA= mapUp (ppA, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
4040          ppB= mapUp (ppB, alpha, V_buf, prim_elem, im_prim_elem, source, dest);
4041          gcdlcAlcB= mapUp (gcdlcAlcB, alpha, V_buf, prim_elem, im_prim_elem,
4042                            source, dest);
4043          fail= false;
4044          random_element= randomElement (m, V_buf, l, fail );
4045          DEBOUTLN (cerr, "fail= " << fail);
4046          CFList list;
4047          TIMING_START (gcd_recursion);
4048          if (LC (skeleton).inCoeffDomain())
4049            G_random_element=
4050            monicSparseInterpol (ppA (random_element, x), ppB (random_element, x),
4051                                skeleton, V_buf, sparseFail, coeffMonoms,
4052                                Monoms);
4053          else
4054            G_random_element=
4055            nonMonicSparseInterpol (ppA(random_element,x), ppB(random_element,x),
4056                                    skeleton, V_buf, sparseFail,
4057                                    coeffMonoms, Monoms);
4058          TIMING_END_AND_PRINT (gcd_recursion,
4059                                "time for recursive call: ");
4060          DEBOUTLN (cerr, "G_random_element= " << G_random_element);
4061        }
4062
4063        if (sparseFail)
4064          break;
4065
[a76d6fe]4066        if (!G_random_element.inCoeffDomain())
4067          d0= totaldegree (G_random_element, Variable(2),
4068                           Variable (G_random_element.level()));
4069        else
4070          d0= 0;
4071
[08daea]4072        if (d0 == 0)
[a9a6dcb]4073          return N(gcdcAcB);
[08daea]4074        if (d0 >  d)
4075        {
4076          if (!find (l, random_element))
4077            l.append (random_element);
4078          continue;
4079        }
4080
4081        G_random_element=
4082        (gcdlcAlcB(random_element, x)/uni_lcoeff (G_random_element))
4083        * G_random_element;
4084
[a76d6fe]4085        if (!G_random_element.inCoeffDomain())
4086          d0= totaldegree (G_random_element, Variable(2),
4087                           Variable (G_random_element.level()));
4088        else
4089          d0= 0;
4090
[08daea]4091        if (d0 <  d)
4092        {
4093          m= gcdlcAlcB;
4094          newtonPoly= 1;
4095          G_m= 0;
4096          d= d0;
4097        }
4098
4099        TIMING_START (newton_interpolation);
4100        H= newtonInterp (random_element, G_random_element, newtonPoly, G_m, x);
4101        TIMING_END_AND_PRINT (newton_interpolation,
4102                              "time for newton interpolation: ");
4103
4104        //termination test
4105        if (uni_lcoeff (H) == gcdlcAlcB)
4106        {
4107          cH= uni_content (H);
4108          ppH= H/cH;
4109          ppH /= Lc (ppH);
4110          DEBOUTLN (cerr, "ppH= " << ppH);
[c723d80]4111          if (fdivides (ppH, ppA) && fdivides (ppH, ppB))
[08daea]4112            return N(gcdcAcB*ppH);
4113        }
4114
4115        G_m= H;
4116        newtonPoly= newtonPoly*(x - random_element);
4117        m= m*(x - random_element);
4118        if (!find (l, random_element))
4119          l.append (random_element);
4120
4121      } while (1); //end of second do
4122    }
[9879d0]4123    else
4124      return N(gcdcAcB*GCD_small_p (ppA, ppB));
[08daea]4125  } while (1); //end of first do
4126}
4127
4128static inline
4129int compress4EZGCD (const CanonicalForm& F, const CanonicalForm& G, CFMap & M,
4130                    CFMap & N, int& both_non_zero)
4131{
4132  int n= tmax (F.level(), G.level());
4133  int * degsf= new int [n + 1];
4134  int * degsg= new int [n + 1];
4135
4136  for (int i = 0; i <= n; i++)
4137    degsf[i]= degsg[i]= 0;
4138
4139  degsf= degrees (F, degsf);
4140  degsg= degrees (G, degsg);
4141
4142  both_non_zero= 0;
4143  int f_zero= 0;
4144  int g_zero= 0;
4145
4146  for (int i= 1; i <= n; i++)
4147  {
4148    if (degsf[i] != 0 && degsg[i] != 0)
4149    {
4150      both_non_zero++;
4151      continue;
4152    }
4153    if (degsf[i] == 0 && degsg[i] != 0 && i <= G.level())
4154    {
4155      f_zero++;
4156      continue;
4157    }
4158    if (degsg[i] == 0 && degsf[i] && i <= F.level())
4159    {
4160      g_zero++;
4161      continue;
4162    }
4163  }
4164
[618da5]4165  if (both_non_zero == 0)
4166  {
4167    delete [] degsf;
4168    delete [] degsg;
4169    return 0;
4170  }
[08daea]4171
4172  // map Variables which do not occur in both polynomials to higher levels
4173  int k= 1;
4174  int l= 1;
4175  for (int i= 1; i <= n; i++)
4176  {
4177    if (degsf[i] != 0 && degsg[i] == 0 && i <= F.level())
4178    {
4179      if (k + both_non_zero != i)
4180      {
4181        M.newpair (Variable (i), Variable (k + both_non_zero));
4182        N.newpair (Variable (k + both_non_zero), Variable (i));
4183      }
4184      k++;
4185    }
4186    if (degsf[i] == 0 && degsg[i] != 0 && i <= G.level())
4187    {
4188      if (l + g_zero + both_non_zero != i)
4189      {
4190        M.newpair (Variable (i), Variable (l + g_zero + both_non_zero));
4191        N.newpair (Variable (l + g_zero + both_non_zero), Variable (i));
4192      }
4193      l++;
4194    }
4195  }
4196
4197  // sort Variables x_{i} in decreasing order of
4198  // min(deg_{x_{i}}(f),deg_{x_{i}}(g))
4199  int m= tmin (F.level(), G.level());
4200  int max_min_deg;
4201  k= both_non_zero;
4202  l= 0;
4203  int i= 1;
4204  while (k > 0)
4205  {
4206    max_min_deg= tmin (degsf[i], degsg[i]);
4207    while (max_min_deg == 0)
4208    {
4209      i++;
4210      max_min_deg= tmin (degsf[i], degsg[i]);
4211    }
4212    for (int j= i + 1; j <= m; j++)
4213    {
4214      if ((tmin (degsf[j],degsg[j]) < max_min_deg) &&
4215          (tmin (degsf[j], degsg[j]) != 0))
4216      {
4217        max_min_deg= tmin (degsf[j], degsg[j]);
4218        l= j;
4219      }
4220    }
4221
4222    if (l != 0)
4223    {
4224      if (l != k)
4225      {
4226        M.newpair (Variable (l), Variable(k));
4227        N.newpair (Variable (k), Variable(l));
4228        degsf[l]= 0;
4229        degsg[l]= 0;
4230        l= 0;
4231      }
4232      else
4233      {
4234        degsf[l]= 0;
4235        degsg[l]= 0;
4236        l= 0;
4237      }
4238    }
4239    else if (l == 0)
4240    {
4241      if (i != k)
4242      {
4243        M.newpair (Variable (i), Variable (k));
4244        N.newpair (Variable (k), Variable (i));
4245        degsf[i]= 0;
4246        degsg[i]= 0;
4247      }
4248      else
4249      {
4250        degsf[i]= 0;
4251        degsg[i]= 0;
4252      }
4253      i++;
4254    }
4255    k--;
4256  }
4257
4258  delete [] degsf;
4259  delete [] degsg;
4260
4261  return both_non_zero;
4262}
4263
4264static inline
4265CanonicalForm myShift2Zero (const CanonicalForm& F, CFList& Feval,
4266                            const CFList& evaluation)
4267{
4268  CanonicalForm A= F;
4269  int k= 2;
4270  for (CFListIterator i= evaluation; i.hasItem(); i++, k++)
4271    A= A (Variable (k) + i.getItem(), k);
4272
4273  CanonicalForm buf= A;
4274  Feval= CFList();
4275  Feval.append (buf);
4276  for (k= evaluation.length() + 1; k > 2; k--)
4277  {
4278    buf= mod (buf, Variable (k));
4279    Feval.insert (buf);
4280  }
4281  return A;
4282}
4283
4284static inline
4285CanonicalForm myReverseShift (const CanonicalForm& F, const CFList& evaluation)
4286{
4287  int l= evaluation.length() + 1;
4288  CanonicalForm result= F;
4289  CFListIterator j= evaluation;
4290  for (int i= 2; i < l + 1; i++, j++)
4291  {
4292    if (F.level() < i)
4293      continue;
4294    result= result (Variable (i) - j.getItem(), i);
4295  }
4296  return result;
4297}
4298
4299static inline
[9ff686]4300Evaluation optimize4Lift (const CanonicalForm& F, CFMap & M,
4301                    CFMap & N, const Evaluation& A)
4302{
4303  int n= F.level();
4304  int * degsf= new int [n + 1];
4305
4306  for (int i = 0; i <= n; i++)
4307    degsf[i]= 0;
4308
4309  degsf= degrees (F, degsf);
4310
4311  Evaluation result= Evaluation (A.min(), A.max());
4312  ASSERT (A.min() == 2, "expected A.min() == 2");
4313  int max_deg;
4314  int k= n;
4315  int l= 1;
4316  int i= 2;
4317  int pos= 2;
4318  while (k > 1)
4319  {
4320    max_deg= degsf [i];
4321    while (max_deg == 0)
4322    {
4323      i++;
4324      max_deg= degsf [i];
4325    }
4326    l= i;
4327    for (int j= i + 1; j <=  n; j++)
4328    {
4329      if (degsf[j] > max_deg)
4330      {
4331        max_deg= degsf[j];
4332        l= j;
4333      }
4334    }
4335
4336    if (l <= n)
4337    {
4338      if (l != pos)
4339      {
4340        result.setValue (pos, A [l]);
4341        M.newpair (Variable (l), Variable (pos));
4342        N.newpair (Variable (pos), Variable (l));
4343        degsf[l]= 0;
4344        l= 2;
4345        if (k == 2 && n == 3)
4346        {
4347          result.setValue (l, A [pos]);
4348          M.newpair (Variable (pos), Variable (l));
4349          N.newpair (Variable (l), Variable (pos));
4350          degsf[pos]= 0;
4351        }
4352      }
4353      else
4354      {
4355        result.setValue (l, A [l]);
4356        degsf [l]= 0;
4357      }
4358    }
4359    pos++;
4360    k--;
4361    l= 2;
4362  }
4363
4364  delete [] degsf;
4365
4366  return result;
4367}
4368
4369static inline
4370int Hensel_P (const CanonicalForm & UU, CFArray & G, const Evaluation & AA,
[0349c20]4371              const CFArray& LeadCoeffs )
[08daea]4372{
4373  CFList factors;
4374  factors.append (G[1]);
4375  factors.append (G[2]);
[9ff686]4376
4377  CFMap NN, MM;
4378  Evaluation A= optimize4Lift (UU, MM, NN, AA);
4379
4380  CanonicalForm U= MM (UU);
4381  CFArray LCs= CFArray (1,2);
4382  LCs [1]= MM (LeadCoeffs [1]);
4383  LCs [2]= MM (LeadCoeffs [2]);
4384
[08daea]4385  CFList evaluation;
[ce41efa]4386  long termEstimate= size (U);
[08daea]4387  for (int i= A.min(); i <= A.max(); i++)
[ce41efa]4388  {
4389    if (!A[i].isZero())
4390    {
4391      termEstimate *= degree (U,i)*2;
4392      termEstimate /= 3;
4393    }
[08daea]4394    evaluation.append (A [i]);
[ce41efa]4395  }
4396  if (termEstimate/getNumVars(U) > 500)
4397    return -1;
[08daea]4398  CFList UEval;
4399  CanonicalForm shiftedU= myShift2Zero (U, UEval, evaluation);
[9ff686]4400
4401  if (size (shiftedU)/getNumVars (U) > 500)
4402    return -1;
4403
[08daea]4404  CFArray shiftedLCs= CFArray (2);
4405  CFList shiftedLCsEval1, shiftedLCsEval2;
4406  shiftedLCs[0]= myShift2Zero (LCs[1], shiftedLCsEval1, evaluation);
4407  shiftedLCs[1]= myShift2Zero (LCs[2], shiftedLCsEval2, evaluation);
4408  factors.insert (1);
4409  int liftBound= degree (UEval.getLast(), 2) + 1;
4410  CFArray Pi;
4411  CFMatrix M= CFMatrix (liftBound, factors.length() - 1);
4412  CFList diophant;
4413  CFArray lcs= CFArray (2);
4414  lcs [0]= shiftedLCsEval1.getFirst();
4415  lcs [1]= shiftedLCsEval2.getFirst();
[81d96c]4416  nonMonicHenselLift12 (UEval.getFirst(), factors, liftBound, Pi, diophant, M,
4417                        lcs, false);
[08daea]4418
4419  for (CFListIterator i= factors; i.hasItem(); i++)
4420  {
[9ff686]4421    if (!fdivides (i.getItem(), UEval.getFirst()))
4422      return 0;
[08daea]4423  }
[9ff686]4424
[08daea]4425  int * liftBounds;
[9189e93]4426  bool noOneToOne= false;
[08daea]4427  if (U.level() > 2)
4428  {
[ea88e0]4429    liftBounds= new int [U.level() - 1]; /* index: 0.. U.level()-2 */
[08daea]4430    liftBounds[0]= liftBound;
[ea88e0]4431    for (int i= 1; i < U.level() - 1; i++)
[08daea]4432      liftBounds[i]= degree (shiftedU, Variable (i + 2)) + 1;
[81d96c]4433    factors= nonMonicHenselLift2 (UEval, factors, liftBounds, U.level() - 1,
4434                                  false, shiftedLCsEval1, shiftedLCsEval2, Pi,
4435                                  diophant, noOneToOne);
[9ff686]4436    delete [] liftBounds;
4437    if (noOneToOne)
4438      return 0;
[08daea]4439  }
4440  G[1]= factors.getFirst();
4441  G[2]= factors.getLast();
4442  G[1]= myReverseShift (G[1], evaluation);
4443  G[2]= myReverseShift (G[2], evaluation);
[9ff686]4444  G[1]= NN (G[1]);
4445  G[2]= NN (G[2]);
4446  return 1;
[08daea]4447}
4448
4449static inline
4450bool findeval_P (const CanonicalForm & F, const CanonicalForm & G,
4451                 CanonicalForm & Fb, CanonicalForm & Gb, CanonicalForm & Db,
[9ff686]4452                 REvaluation & b, int delta, int degF, int degG, int maxeval,
4453                 int & count, int& k, int bound, int& l)
[08daea]4454{
4455  if( count == 0 && delta != 0)
4456  {
4457    if( count++ > maxeval )
4458      return false;
4459  }
4460  if (count > 0)
4461  {
[9ff686]4462    b.nextpoint(k);
[b5c084]4463    if (k == 0)
4464      k++;
[9ff686]4465    l++;
4466    if (l > bound)
4467    {
4468      l= 1;
4469      k++;
4470      if (k > tmax (F.level(), G.level()) - 1)
4471        return false;
4472      b.nextpoint (k);
4473    }
[08daea]4474    if (count++ > maxeval)
4475      return false;
4476  }
4477  while( true )
4478  {
4479    Fb = b( F );
4480    if( degree( Fb, 1 ) == degF )
4481    {
4482      Gb = b( G );
4483      if( degree( Gb, 1 ) == degG )
4484      {
4485        Db = gcd( Fb, Gb );
4486        if( delta > 0 )
4487        {
4488          if( degree( Db, 1 ) <= delta )
4489            return true;
4490        }
4491        else
4492          return true;
4493      }
4494    }
[9ff686]4495    if (k == 0)
4496      k++;
4497    b.nextpoint(k);
4498    l++;
4499    if (l > bound)
4500    {
4501      l= 1;
4502      k++;
4503      if (k > tmax (F.level(), G.level()) - 1)
4504        return false;
4505      b.nextpoint (k);
4506    }
[08daea]4507    if( count++ > maxeval )
4508      return false;
4509  }
4510}
4511
4512// parameters for heuristic
4513static int maxNumEval= 200;
4514static int sizePerVars1= 500; //try dense gcd if size/#variables is bigger
4515
4516/// Extended Zassenhaus GCD for finite fields
4517CanonicalForm EZGCD_P( const CanonicalForm & FF, const CanonicalForm & GG )
4518{
4519  if (FF.isZero() && degree(GG) > 0) return GG/Lc(GG);
4520  else if (GG.isZero() && degree (FF) > 0) return FF/Lc(FF);
4521  else if (FF.isZero() && GG.isZero()) return FF.genOne();
4522  if (FF.inBaseDomain() || GG.inBaseDomain()) return FF.genOne();
4523  if (FF.isUnivariate() && fdivides(FF, GG)) return FF/Lc(FF);
4524  if (GG.isUnivariate() && fdivides(GG, FF)) return GG/Lc(GG);
4525  if (FF == GG) return FF/Lc(FF);
4526
4527  CanonicalForm F, G, f, g, d, Fb, Gb, Db, Fbt, Gbt, Dbt, B0, B, D0, lcF, lcG,
4528                lcD;
4529  CFArray DD( 1, 2 ), lcDD( 1, 2 );
4530  int degF, degG, delta, count;
4531  int maxeval;
4532  maxeval= tmin((getCharacteristic()/
4533                (int)(ilog2(getCharacteristic())*log2exp))*2, maxNumEval);
4534  count= 0; // number of eval. used
[9ff686]4535  REvaluation b, bt;
4536  int gcdfound = 0;
[08daea]4537  Variable x = Variable(1);
4538
4539  F= FF;
4540  G= GG;
4541
4542  CFMap M,N;
4543  int smallestDegLev;
[2a95b2]4544  TIMING_START (ez_p_compress)
[08daea]4545  int best_level= compress4EZGCD (F, G, M, N, smallestDegLev);
4546
4547  if (best_level == 0) return G.genOne();
4548
4549  F= M (F);
4550  G= M (G);
[2a95b2]4551  TIMING_END_AND_PRINT (ez_p_compress, "time for compression in EZ_P: ")
[08daea]4552
[2a95b2]4553  TIMING_START (ez_p_content)
[08daea]4554  f = content( F, x ); g = content( G, x );
4555  d = gcd( f, g );
4556  F /= f; G /= g;
[2a95b2]4557  TIMING_END_AND_PRINT (ez_p_content, "time to extract content in EZ_P: ")
[08daea]4558
4559  if( F.isUnivariate() && G.isUnivariate() )
4560  {
4561    if( F.mvar() == G.mvar() )
4562      d *= gcd( F, G );
[b770bf]4563    else
4564      return N (d);
[08daea]4565    return N (d);
4566  }
[b770bf]4567  if ( F.isUnivariate())
4568  {
4569    g= content (G,G.mvar());
4570    return N(d*gcd(F,g));
4571  }
4572  if ( G.isUnivariate())
4573  {
4574    f= content (F,F.mvar());
4575    return N(d*gcd(G,f));
4576  }
[08daea]4577
4578  int maxNumVars= tmax (getNumVars (F), getNumVars (G));
[9ff686]4579  Variable a, oldA;
[08daea]4580  int sizeF= size (F);
4581  int sizeG= size (G);
4582
4583  if (sizeF/maxNumVars > sizePerVars1 && sizeG/maxNumVars > sizePerVars1)
4584  {
4585    if (hasFirstAlgVar (F, a) || hasFirstAlgVar (G, a))
4586      return N (d*GCD_Fp_extension (F, G, a));
4587    else if (CFFactory::gettype() == GaloisFieldDomain)
4588      return N (d*GCD_GF (F, G));
4589    else
4590      return N (d*GCD_small_p (F, G));
4591  }
4592
[5b2d2b]4593  int dummy= 0;
4594  if( gcd_test_one( F, G, false, dummy ) )
[08daea]4595  {
4596    return N (d);
4597  }
4598
[9ff686]4599  bool passToGF= false;
4600  bool extOfExt= false;
4601  int p= getCharacteristic();
4602  bool algExtension= (hasFirstAlgVar(F,a) || hasFirstAlgVar(G,a));
4603  int k= 1;
4604  CanonicalForm primElem, imPrimElem;
4605  CFList source, dest;
4606  if (p < 50 && CFFactory::gettype() != GaloisFieldDomain && !algExtension)
[08daea]4607  {
[9ff686]4608    if (p == 2)
[6e8834]4609      setCharacteristic (2, 12, 'Z');
[9ff686]4610    else if (p == 3)
4611      setCharacteristic (3, 4, 'Z');
4612    else if (p == 5 || p == 7)
4613      setCharacteristic (p, 3, 'Z');
4614    else
4615      setCharacteristic (p, 2, 'Z');
4616    passToGF= true;
4617    F= F.mapinto();
4618    G= G.mapinto();
4619    maxeval= 2*ipower (p, getGFDegree());
[08daea]4620  }
[9ff686]4621  else if (CFFactory::gettype() == GaloisFieldDomain &&
4622           ipower (p , getGFDegree()) < 50)
[08daea]4623  {
[9ff686]4624    k= getGFDegree();
4625    if (ipower (p, 2*k) > 50)
4626      setCharacteristic (p, 2*k, gf_name);
[08daea]4627    else
[9ff686]4628      setCharacteristic (p, 3*k, gf_name);
4629    F= GFMapUp (F, k);
4630    G= GFMapUp (G, k);
4631    maxeval= tmin (2*ipower (p, getGFDegree()), maxNumEval);
4632  }
[fd8511]4633  else if (p < 50 && algExtension && CFFactory::gettype() != GaloisFieldDomain)
[9ff686]4634  {
4635    int d= degree (getMipo (a));
4636    oldA= a;
4637    Variable v2;
4638    if (p == 2 && d < 6)
4639    {
[bffe62d]4640      if (fac_NTL_char != p)
4641      {
4642        fac_NTL_char= p;
4643        zz_p::init (p);
4644      }
[9ff686]4645      bool primFail= false;
4646      Variable vBuf;
4647      primElem= primitiveElement (a, vBuf, primFail);
4648      ASSERT (!primFail, "failure in integer factorizer");
4649      if (d < 3)
4650      {
4651        zz_pX NTLIrredpoly;
4652        BuildIrred (NTLIrredpoly, d*3);
4653        CanonicalForm newMipo= convertNTLzzpX2CF (NTLIrredpoly, Variable (1));
4654        v2= rootOf (newMipo);
4655      }
[08daea]4656      else
[9ff686]4657      {
4658        zz_pX NTLIrredpoly;
4659        BuildIrred (NTLIrredpoly, d*2);
4660        CanonicalForm newMipo= convertNTLzzpX2CF (NTLIrredpoly, Variable (1));
4661        v2= rootOf (newMipo);
4662      }
4663      imPrimElem= mapPrimElem (primElem, a, v2);
4664      extOfExt= true;
4665    }
4666    else if ((p == 3 && d < 4) || ((p == 5 || p == 7) && d < 3))
4667    {
[bffe62d]4668      if (fac_NTL_char != p)
4669      {
4670        fac_NTL_char= p;
4671        zz_p::init (p);
4672      }
[9ff686]4673      bool primFail= false;
4674      Variable vBuf;
4675      primElem= primitiveElement (a, vBuf, primFail);
4676      ASSERT (!primFail, "failure in integer factorizer");
4677      zz_pX NTLIrredpoly;
4678      BuildIrred (NTLIrredpoly, d*2);
4679      CanonicalForm newMipo= convertNTLzzpX2CF (NTLIrredpoly, Variable (1));
4680      v2= rootOf (newMipo);
4681      imPrimElem= mapPrimElem (primElem, a, v2);
4682      extOfExt= true;
4683    }
4684    if (extOfExt)
4685    {
4686      maxeval= tmin (2*ipower (p, degree (getMipo (v2))), maxNumEval);
4687      F= mapUp (F, a, v2, primElem, imPrimElem, source, dest);
4688      G= mapUp (G, a, v2, primElem, imPrimElem, source, dest);
4689      a= v2;
[08daea]4690    }
4691  }
[9ff686]4692
4693  lcF = LC( F, x ); lcG = LC( G, x );
4694  lcD = gcd( lcF, lcG );
4695
4696  delta = 0;
4697  degF = degree( F, x ); degG = degree( G, x );
4698
4699  if(hasFirstAlgVar(G,a))
4700    b = REvaluation( 2, tmax(F.level(), G.level()), AlgExtRandomF( a ) );
4701  else
4702  { // both not in extension given by algebraic variable
4703    if (CFFactory::gettype() != GaloisFieldDomain)
4704      b = REvaluation( 2, tmax(F.level(), G.level()), FFRandom() );
4705    else
4706      b = REvaluation( 2, tmax(F.level(), G.level()), GFRandom() );
4707  }
4708
[e26667]4709  CanonicalForm cand, contcand;
[9ff686]4710  CanonicalForm result;
4711  int o, t;
4712  o= 0;
4713  t= 1;
4714  int goodPointCount= 0;
[08daea]4715  while( !gcdfound )
4716  {
[2a95b2]4717    TIMING_START (ez_p_eval);
[9ff686]4718    if( !findeval_P( F, G, Fb, Gb, Db, b, delta, degF, degG, maxeval, count, o,
4719         maxeval/maxNumVars, t ))
[08daea]4720    { // too many eval. used --> try another method
[9ff686]4721      Off (SW_USE_EZGCD_P);
4722      result= gcd (F,G);
4723      On (SW_USE_EZGCD_P);
4724      if (passToGF)
[08daea]4725      {
[0a7d0ca]4726        CanonicalForm mipo= gf_mipo;
[9ff686]4727        setCharacteristic (p);
[0a7d0ca]4728        Variable alpha= rootOf (mipo.mapinto());
[9ff686]4729        result= GF2FalphaRep (result, alpha);
[08daea]4730      }
[9ff686]4731      if (k > 1)
4732      {
4733        result= GFMapDown (result, k);
4734        setCharacteristic (p, k, gf_name);
4735      }
4736      if (extOfExt)
4737        result= mapDown (result, primElem, imPrimElem, oldA, dest, source);
4738      return N (d*result);
[08daea]4739    }
[2a95b2]4740    TIMING_END_AND_PRINT (ez_p_eval, "time for eval point search in EZ_P1: ");
[08daea]4741    delta = degree( Db );
4742    if( delta == 0 )
[9ff686]4743    {
4744      if (passToGF)
4745        setCharacteristic (p);
4746      if (k > 1)
4747        setCharacteristic (p, k, gf_name);
[08daea]4748      return N (d);
[9ff686]4749    }
[08daea]4750    while( true )
4751    {
4752      bt = b;
[2a95b2]4753      TIMING_START (ez_p_eval);
[9ff686]4754      if( !findeval_P(F,G,Fbt,Gbt,Dbt, bt, delta, degF, degG, maxeval, count, o,
4755           maxeval/maxNumVars, t ))
[08daea]4756      { // too many eval. used --> try another method
[9ff686]4757        Off (SW_USE_EZGCD_P);
4758        result= gcd (F,G);
4759        On (SW_USE_EZGCD_P);
4760        if (passToGF)
[08daea]4761        {
[0a7d0ca]4762          CanonicalForm mipo= gf_mipo;
[9ff686]4763          setCharacteristic (p);
[0a7d0ca]4764          Variable alpha= rootOf (mipo.mapinto());
[9ff686]4765          result= GF2FalphaRep (result, alpha);
[08daea]4766        }
[9ff686]4767        if (k > 1)
4768        {
4769          result= GFMapDown (result, k);
4770          setCharacteristic (p, k, gf_name);
4771        }
4772        if (extOfExt)
4773          result= mapDown (result, primElem, imPrimElem, oldA, dest, source);
4774        return N (d*result);
[08daea]4775      }
[2a95b2]4776      TIMING_END_AND_PRINT (ez_p_eval, "time for eval point search in EZ_P2: ");
[08daea]4777      int dd = degree( Dbt );
4778      if( dd == 0 )
[9ff686]4779      {
4780        if (passToGF)
4781          setCharacteristic (p);
4782        if (k > 1)
4783          setCharacteristic (p, k, gf_name);
[08daea]4784        return N (d);
[9ff686]4785      }
[08daea]4786      if( dd == delta )
[9ff686]4787      {
4788        goodPointCount++;
4789        if (goodPointCount == 5)
4790          break;
4791      }
[08daea]4792      if( dd < delta )
4793      {
[9ff686]4794        goodPointCount= 0;
[08daea]4795        delta = dd;
4796        b = bt;
4797        Db = Dbt; Fb = Fbt; Gb = Gbt;
4798      }
[9ff686]4799      if (delta == degF)
4800      {
4801        if (degF <= degG && fdivides (F, G))
4802        {
4803          if (passToGF)
4804          {
[0a7d0ca]4805            CanonicalForm mipo= gf_mipo;
[9ff686]4806            setCharacteristic (p);
[0a7d0ca]4807            Variable alpha= rootOf (mipo.mapinto());
[9ff686]4808            F= GF2FalphaRep (F, alpha);
4809          }
4810          if (k > 1)
4811          {
4812            F= GFMapDown (F, k);
4813            setCharacteristic (p, k, gf_name);
4814          }
4815          if (extOfExt)
4816            F= mapDown (F, primElem, imPrimElem, oldA, dest, source);
4817          return N (d*F);
4818        }
4819        else
4820          delta--;
4821      }
4822      else if (delta == degG)
4823      {
4824        if (degG <= degF && fdivides (G, F))
4825        {
4826          if (passToGF)
4827          {
[0a7d0ca]4828            CanonicalForm mipo= gf_mipo;
[9ff686]4829            setCharacteristic (p);
[0a7d0ca]4830            Variable alpha= rootOf (mipo.mapinto());
[9ff686]4831            G= GF2FalphaRep (G, alpha);
4832          }
4833          if (k > 1)
4834          {
4835            G= GFMapDown (G, k);
4836            setCharacteristic (p, k, gf_name);
4837          }
4838          if (extOfExt)
4839            G= mapDown (G, primElem, imPrimElem, oldA, dest, source);
4840          return N (d*G);
4841        }
4842        else
4843          delta--;
4844      }
[08daea]4845    }
4846    if( delta != degF && delta != degG )
4847    {
4848      bool B_is_F;
4849      CanonicalForm xxx1, xxx2;
4850      CanonicalForm buf;
4851      DD[1] = Fb / Db;
4852      buf= Gb/Db;
4853      xxx1 = gcd( DD[1], Db );
4854      xxx2 = gcd( buf, Db );
4855      if (((xxx1.inCoeffDomain() && xxx2.inCoeffDomain()) &&
[c1b9927]4856          (size (F) <= size (G)))
[08daea]4857          || (xxx1.inCoeffDomain() && !xxx2.inCoeffDomain()))
4858      {
4859        B = F;
4860        DD[2] = Db;
4861        lcDD[1] = lcF;
4862        lcDD[2] = lcD;
4863        B_is_F = true;
4864      }
4865      else if (((xxx1.inCoeffDomain() && xxx2.inCoeffDomain()) &&
[c1b9927]4866               (size (G) < size (F)))
[08daea]4867               || (!xxx1.inCoeffDomain() && xxx2.inCoeffDomain()))
4868      {
4869        DD[1] = buf;
4870        B = G;
4871        DD[2] = Db;
4872        lcDD[1] = lcG;
4873        lcDD[2] = lcD;
4874        B_is_F = false;
4875      }
4876      else // special case handling
4877      {
[9ff686]4878        Off (SW_USE_EZGCD_P);
4879        result= gcd (F,G);
4880        On (SW_USE_EZGCD_P);
4881        if (passToGF)
4882        {
[0a7d0ca]4883          CanonicalForm mipo= gf_mipo;
[9ff686]4884          setCharacteristic (p);
[0a7d0ca]4885          Variable alpha= rootOf (mipo.mapinto());
[9ff686]4886          result= GF2FalphaRep (result, alpha);
4887        }
4888        if (k > 1)
[08daea]4889        {
[9ff686]4890          result= GFMapDown (result, k);
4891          setCharacteristic (p, k, gf_name);
4892        }
4893        if (extOfExt)
4894          result= mapDown (result, primElem, imPrimElem, oldA, dest, source);
4895        return N (d*result);
4896      }
4897      DD[2] = DD[2] * ( b( lcDD[2] ) / lc( DD[2] ) );
4898      DD[1] = DD[1] * ( b( lcDD[1] ) / lc( DD[1] ) );
4899
4900      if (size (B*lcDD[2])/maxNumVars > sizePerVars1)
4901      {
4902        if (algExtension)
4903        {
4904          result= GCD_Fp_extension (F, G, a);
4905          if (extOfExt)
4906            result= mapDown (result, primElem, imPrimElem, oldA, dest, source);
4907          return N (d*result);
4908        }
4909        if (CFFactory::gettype() == GaloisFieldDomain)
4910        {
4911          result= GCD_GF (F, G);
4912          if (passToGF)
4913          {
[0a7d0ca]4914            CanonicalForm mipo= gf_mipo;
[9ff686]4915            setCharacteristic (p);
[0a7d0ca]4916            Variable alpha= rootOf (mipo.mapinto());
[9ff686]4917            result= GF2FalphaRep (result, alpha);
4918          }
4919          if (k > 1)
[08daea]4920          {
[9ff686]4921            result= GFMapDown (result, k);
4922            setCharacteristic (p, k, gf_name);
[08daea]4923          }
[9ff686]4924          return N (d*result);
[08daea]4925        }
4926        else
[9ff686]4927          return N (d*GCD_small_p (F,G));
[08daea]4928      }
4929
[2a95b2]4930      TIMING_START (ez_p_hensel_lift);
[0349c20]4931      gcdfound= Hensel_P (B*lcD, DD, b, lcDD);
[2a95b2]4932      TIMING_END_AND_PRINT (ez_p_hensel_lift, "time for Hensel lift in EZ_P: ");
[08daea]4933
[7964658]4934      if (gcdfound == -1) //things became dense
[9ff686]4935      {
[7964658]4936        if (algExtension)
[9ff686]4937        {
[7964658]4938          result= GCD_Fp_extension (F, G, a);
4939          if (extOfExt)
4940            result= mapDown (result, primElem, imPrimElem, oldA, dest, source);
4941          return N (d*result);
[9ff686]4942        }
[7964658]4943        if (CFFactory::gettype() == GaloisFieldDomain)
[9ff686]4944        {
[7964658]4945          result= GCD_GF (F, G);
4946          if (passToGF)
4947          {
4948            CanonicalForm mipo= gf_mipo;
4949            setCharacteristic (p);
4950            Variable alpha= rootOf (mipo.mapinto());
4951            result= GF2FalphaRep (result, alpha);
4952          }
4953          if (k > 1)
4954          {
4955            result= GFMapDown (result, k);
4956            setCharacteristic (p, k, gf_name);
4957          }
4958          return N (d*result);
[9ff686]4959        }
[7964658]4960        else
[0d74e7]4961        {
4962          if (p >= cf_getBigPrime(0))
4963            return N (d*sparseGCDFp (F,G));
4964          else
4965            return N (d*GCD_small_p (F,G));
4966        }
[9ff686]4967      }
4968
4969      if (gcdfound == 1)
[08daea]4970      {
[2a95b2]4971        TIMING_START (termination_test);
[e26667]4972        contcand= content (DD[2], Variable (1));
4973        cand = DD[2] / contcand;
4974        if (B_is_F)
4975          gcdfound = fdivides( cand, G ) && cand*(DD[1]/(lcD/contcand)) == F;
4976        else
4977          gcdfound = fdivides( cand, F ) && cand*(DD[1]/(lcD/contcand)) == G;
[2a95b2]4978        TIMING_END_AND_PRINT (termination_test,
4979                              "time for termination test EZ_P: ");
[9ff686]4980
4981        if (passToGF && gcdfound)
4982        {
[0a7d0ca]4983          CanonicalForm mipo= gf_mipo;
[9ff686]4984          setCharacteristic (p);
[0a7d0ca]4985          Variable alpha= rootOf (mipo.mapinto());
[9ff686]4986          cand= GF2FalphaRep (cand, alpha);
4987        }
4988        if (k > 1 && gcdfound)
4989        {
4990          cand= GFMapDown (cand, k);
4991          setCharacteristic (p, k, gf_name);
4992        }
4993        if (extOfExt && gcdfound)
4994          cand= mapDown (cand, primElem, imPrimElem, oldA, dest, source);
[08daea]4995      }
4996    }
[9ff686]4997    delta--;
4998    goodPointCount= 0;
[08daea]4999  }
5000  return N (d*cand);
5001}
5002
5003
[10af64]5004#endif
Note: See TracBrowser for help on using the repository browser.