source: git/factory/cf_gcd.cc @ a08be4

spielwiese
Last change on this file since a08be4 was a08be4, checked in by Martin Lee <martinlee84@…>, 11 years ago
chg: use different gcd algorithm to compute content in psrgcd
  • Property mode set to 100644
File size: 34.7 KB
RevLine 
[493c477]1/* emacs edit mode for this file is -*- C++ -*- */
[9bab9f]2
[e4fe2b]3#include "config.h"
[ab4548f]4
[2a95b2]5#include "timing.h"
[650f2d8]6#include "cf_assert.h"
[93b061]7#include "debug.h"
8
[9bab9f]9#include "cf_defs.h"
10#include "canonicalform.h"
11#include "cf_iter.h"
12#include "cf_reval.h"
[edb4893]13#include "cf_primes.h"
[fbefc9]14#include "cf_algorithm.h"
[2072126]15#include "cf_factory.h"
[f63dbca]16#include "fac_util.h"
[6db552]17#include "templates/ftmpl_functions.h"
[bb82f0]18#include "algext.h"
[10af64]19#include "cf_gcd_smallp.h"
[6e2ef0e]20#include "cf_map_ext.h"
21#include "cf_util.h"
[d990001]22#include "gfops.h"
[edb4893]23
[f11d7b]24#ifdef HAVE_NTL
[034eec]25#include <NTL/ZZX.h>
[f11d7b]26#include "NTLconvert.h"
[a7ec94]27bool isPurePoly(const CanonicalForm & );
[447349]28#ifndef HAVE_FLINT
[a7ec94]29static CanonicalForm gcd_univar_ntl0( const CanonicalForm &, const CanonicalForm & );
[c4f4fd]30static CanonicalForm gcd_univar_ntlp( const CanonicalForm &, const CanonicalForm & );
[f11d7b]31#endif
[447349]32#endif
[f11d7b]33
[7e8c9e]34#ifdef HAVE_FLINT
35#include "FLINTconvert.h"
36static CanonicalForm gcd_univar_flint0 (const CanonicalForm &, const CanonicalForm &);
37static CanonicalForm gcd_univar_flintp (const CanonicalForm &, const CanonicalForm &);
38#endif
39
[a7ec94]40static CanonicalForm cf_content ( const CanonicalForm &, const CanonicalForm & );
[edb4893]41
[27bb97f]42void out_cf(const char *s1,const CanonicalForm &f,const char *s2);
[6f62c3]43
[110718]44CanonicalForm chinrem_gcd(const CanonicalForm & FF,const CanonicalForm & GG);
[f4b180]45
[f63dbca]46bool
[5b2d2b]47gcd_test_one ( const CanonicalForm & f, const CanonicalForm & g, bool swap, int & d )
[9bab9f]48{
[5b2d2b]49    d= 0;
[9bab9f]50    int count = 0;
51    // assume polys have same level;
[6e2ef0e]52
53    Variable v= Variable (1);
54    bool algExtension= (hasFirstAlgVar (f, v) || hasFirstAlgVar (g, v));
[f63dbca]55    CanonicalForm lcf, lcg;
[6f62c3]56    if ( swap )
57    {
[150dc8]58        lcf = swapvar( LC( f ), Variable(1), f.mvar() );
59        lcg = swapvar( LC( g ), Variable(1), f.mvar() );
[f63dbca]60    }
[6f62c3]61    else
62    {
[150dc8]63        lcf = LC( f, Variable(1) );
64        lcg = LC( g, Variable(1) );
[f63dbca]65    }
[6e2ef0e]66
[f63dbca]67    CanonicalForm F, G;
[6f62c3]68    if ( swap )
69    {
[150dc8]70        F=swapvar( f, Variable(1), f.mvar() );
71        G=swapvar( g, Variable(1), g.mvar() );
[f63dbca]72    }
[6f62c3]73    else
74    {
[150dc8]75        F = f;
76        G = g;
[f63dbca]77    }
[6e2ef0e]78
79    #define TEST_ONE_MAX 50
80    int p= getCharacteristic();
81    bool passToGF= false;
82    int k= 1;
83    if (p > 0 && p < TEST_ONE_MAX && CFFactory::gettype() != GaloisFieldDomain && !algExtension)
84    {
85      if (p == 2)
86        setCharacteristic (2, 6, 'Z');
87      else if (p == 3)
88        setCharacteristic (3, 4, 'Z');
89      else if (p == 5 || p == 7)
90        setCharacteristic (p, 3, 'Z');
91      else
92        setCharacteristic (p, 2, 'Z');
93      passToGF= true;
94    }
95    else if (p > 0 && CFFactory::gettype() == GaloisFieldDomain && ipower (p , getGFDegree()) < TEST_ONE_MAX)
96    {
97      k= getGFDegree();
98      if (ipower (p, 2*k) > TEST_ONE_MAX)
99        setCharacteristic (p, 2*k, gf_name);
100      else
101        setCharacteristic (p, 3*k, gf_name);
102      F= GFMapUp (F, k);
103      G= GFMapUp (G, k);
104      lcf= GFMapUp (lcf, k);
105      lcg= GFMapUp (lcg, k);
106    }
107    else if (p > 0 && p < TEST_ONE_MAX && algExtension)
108    {
109      bool extOfExt= false;
[d990001]110#ifdef HAVE_NTL
[6e2ef0e]111      int d= degree (getMipo (v));
112      CFList source, dest;
113      Variable v2;
114      CanonicalForm primElem, imPrimElem;
115      if (p == 2 && d < 6)
116      {
[bffe62d]117        if (fac_NTL_char != 2)
118        {
119          fac_NTL_char= 2;
120          zz_p::init (p);
121        }
[6e2ef0e]122        bool primFail= false;
123        Variable vBuf;
124        primElem= primitiveElement (v, vBuf, primFail);
125        ASSERT (!primFail, "failure in integer factorizer");
126        if (d < 3)
127        {
128          zz_pX NTLIrredpoly;
129          BuildIrred (NTLIrredpoly, d*3);
130          CanonicalForm newMipo= convertNTLzzpX2CF (NTLIrredpoly, Variable (1));
131          v2= rootOf (newMipo);
132        }
133        else
134        {
135          zz_pX NTLIrredpoly;
136          BuildIrred (NTLIrredpoly, d*2);
137          CanonicalForm newMipo= convertNTLzzpX2CF (NTLIrredpoly, Variable (1));
138          v2= rootOf (newMipo);
139        }
140        imPrimElem= mapPrimElem (primElem, v, v2);
141        extOfExt= true;
142      }
143      else if ((p == 3 && d < 4) || ((p == 5 || p == 7) && d < 3))
144      {
[bffe62d]145        if (fac_NTL_char != p)
146        {
147          fac_NTL_char= p;
148          zz_p::init (p);
149        }
[6e2ef0e]150        bool primFail= false;
151        Variable vBuf;
152        primElem= primitiveElement (v, vBuf, primFail);
153        ASSERT (!primFail, "failure in integer factorizer");
154        zz_pX NTLIrredpoly;
155        BuildIrred (NTLIrredpoly, d*2);
156        CanonicalForm newMipo= convertNTLzzpX2CF (NTLIrredpoly, Variable (1));
157        v2= rootOf (newMipo);
158        imPrimElem= mapPrimElem (primElem, v, v2);
159        extOfExt= true;
160      }
161      if (extOfExt)
162      {
163        F= mapUp (F, v, v2, primElem, imPrimElem, source, dest);
164        G= mapUp (G, v, v2, primElem, imPrimElem, source, dest);
165        lcf= mapUp (lcf, v, v2, primElem, imPrimElem, source, dest);
166        lcg= mapUp (lcg, v, v2, primElem, imPrimElem, source, dest);
167        v= v2;
168      }
[d990001]169#endif
[6e2ef0e]170    }
171
172    CFRandom * sample;
173    if ((!algExtension && p > 0) || p == 0)
174      sample = CFRandomFactory::generate();
175    else
176      sample = AlgExtRandomF (v).clone();
177
178    REvaluation e( 2, tmax( f.level(), g.level() ), *sample );
179    delete sample;
180
181    if (passToGF)
182    {
183      lcf= lcf.mapinto();
184      lcg= lcg.mapinto();
185    }
186
187    CanonicalForm eval1, eval2;
188    if (passToGF)
189    {
190      eval1= e (lcf);
191      eval2= e (lcg);
192    }
193    else
194    {
195      eval1= e (lcf);
196      eval2= e (lcg);
197    }
198
199    while ( ( eval1.isZero() || eval2.isZero() ) && count < TEST_ONE_MAX )
200    {
201        e.nextpoint();
202        count++;
203        eval1= e (lcf);
204        eval2= e (lcg);
205    }
206    if ( count >= TEST_ONE_MAX )
207    {
208        if (passToGF)
209          setCharacteristic (p);
210        if (k > 1)
211          setCharacteristic (p, k, gf_name);
212        return false;
213    }
214
215
216    if (passToGF)
217    {
218      F= F.mapinto();
219      G= G.mapinto();
220      eval1= e (F);
221      eval2= e (G);
222    }
223    else
224    {
225      eval1= e (F);
226      eval2= e (G);
227    }
228
229    CanonicalForm c= gcd (eval1, eval2);
[5b2d2b]230    d= c.degree();
231    bool result= d < 1;
232    if (d < 0)
233      d= 0;
[6e2ef0e]234
235    if (passToGF)
236      setCharacteristic (p);
237    if (k > 1)
238      setCharacteristic (p, k, gf_name);
239    return result;
[9bab9f]240}
241
[dd3e561]242//{{{ static CanonicalForm icontent ( const CanonicalForm & f, const CanonicalForm & c )
243//{{{ docu
244//
245// icontent() - return gcd of c and all coefficients of f which
246//   are in a coefficient domain.
247//
248// Used by icontent().
249//
250//}}}
[9bab9f]251static CanonicalForm
252icontent ( const CanonicalForm & f, const CanonicalForm & c )
253{
[c30347]254    if ( f.inBaseDomain() )
255    {
256      if (c.isZero()) return abs(f);
257      return bgcd( f, c );
258    }
[ef20c7]259    //else if ( f.inCoeffDomain() )
260    //   return gcd(f,c);
[c30347]261    else
262    {
[150dc8]263        CanonicalForm g = c;
264        for ( CFIterator i = f; i.hasTerms() && ! g.isOne(); i++ )
265            g = icontent( i.coeff(), g );
266        return g;
[9bab9f]267    }
268}
[dd3e561]269//}}}
[9bab9f]270
[dd3e561]271//{{{ CanonicalForm icontent ( const CanonicalForm & f )
272//{{{ docu
273//
274// icontent() - return gcd over all coefficients of f which are
275//   in a coefficient domain.
276//
277//}}}
[9bab9f]278CanonicalForm
279icontent ( const CanonicalForm & f )
280{
281    return icontent( f, 0 );
282}
[dd3e561]283//}}}
[9bab9f]284
[dd3e561]285//{{{ CanonicalForm extgcd ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & a, CanonicalForm & b )
286//{{{ docu
287//
288// extgcd() - returns polynomial extended gcd of f and g.
289//
290// Returns gcd(f, g) and a and b sucht that f*a+g*b=gcd(f, g).
291// The gcd is calculated using an extended euclidean polynomial
292// remainder sequence, so f and g should be polynomials over an
293// euclidean domain.  Normalizes result.
294//
295// Note: be sure that f and g have the same level!
296//
297//}}}
[9bab9f]298CanonicalForm
299extgcd ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & a, CanonicalForm & b )
300{
[e9a5b62]301  if (f.isZero())
302  {
303    a= 0;
304    b= 1;
305    return g;
306  }
307  else if (g.isZero())
308  {
309    a= 1;
310    b= 0;
311    return f;
312  }
[034eec]313#ifdef HAVE_NTL
[c8f95d]314#ifdef HAVE_FLINT
315  if (( getCharacteristic() > 0 ) && (CFFactory::gettype() != GaloisFieldDomain)
316  &&  (f.level()==g.level()) && isPurePoly(f) && isPurePoly(g))
317  {
318    nmod_poly_t F1, G1, A, B, R;
319    convertFacCF2nmod_poly_t (F1, f);
320    convertFacCF2nmod_poly_t (G1, g);
321    nmod_poly_init (R, getCharacteristic());
322    nmod_poly_init (A, getCharacteristic());
323    nmod_poly_init (B, getCharacteristic());
324    nmod_poly_xgcd (R, A, B, F1, G1);
325    a= convertnmod_poly_t2FacCF (A, f.mvar());
326    b= convertnmod_poly_t2FacCF (B, f.mvar());
327    CanonicalForm r= convertnmod_poly_t2FacCF (R, f.mvar());
328    nmod_poly_clear (F1);
329    nmod_poly_clear (G1);
330    nmod_poly_clear (A);
331    nmod_poly_clear (B);
332    nmod_poly_clear (R);
333    return r;
334  }
335#else
[963057]336  if (isOn(SW_USE_NTL_GCD_P) && ( getCharacteristic() > 0 ) && (CFFactory::gettype() != GaloisFieldDomain)
[a86cda]337  &&  (f.level()==g.level()) && isPurePoly(f) && isPurePoly(g))
[034eec]338  {
[c6eecb]339    if (fac_NTL_char!=getCharacteristic())
340    {
341      fac_NTL_char=getCharacteristic();
342      #ifdef NTL_ZZ
343      ZZ r;
344      r=getCharacteristic();
345      ZZ_pContext ccc(r);
346      #else
347      zz_pContext ccc(getCharacteristic());
348      #endif
349      ccc.restore();
350      #ifdef NTL_ZZ
351      ZZ_p::init(r);
352      #else
353      zz_p::init(getCharacteristic());
354      #endif
355    }
356    #ifdef NTL_ZZ
357    ZZ_pX F1=convertFacCF2NTLZZpX(f);
358    ZZ_pX G1=convertFacCF2NTLZZpX(g);
359    ZZ_pX R;
360    ZZ_pX A,B;
361    XGCD(R,A,B,F1,G1);
362    a=convertNTLZZpX2CF(A,f.mvar());
363    b=convertNTLZZpX2CF(B,f.mvar());
364    return convertNTLZZpX2CF(R,f.mvar());
365    #else
[034eec]366    zz_pX F1=convertFacCF2NTLzzpX(f);
367    zz_pX G1=convertFacCF2NTLzzpX(g);
368    zz_pX R;
369    zz_pX A,B;
370    XGCD(R,A,B,F1,G1);
371    a=convertNTLzzpX2CF(A,f.mvar());
372    b=convertNTLzzpX2CF(B,f.mvar());
373    return convertNTLzzpX2CF(R,f.mvar());
[c6eecb]374    #endif
[034eec]375  }
[c8f95d]376#endif
[fd2316c]377#ifdef HAVE_FLINT
378  if (( getCharacteristic() ==0) && (f.level()==g.level())
379       && isPurePoly(f) && isPurePoly(g))
380  {
381    fmpq_poly_t F1, G1;
382    convertFacCF2Fmpq_poly_t (F1, f);
383    convertFacCF2Fmpq_poly_t (G1, g);
384    fmpq_poly_t R, A, B;
385    fmpq_poly_init (R);
386    fmpq_poly_init (A);
387    fmpq_poly_init (B);
388    fmpq_poly_xgcd (R, A, B, F1, G1);
389    a= convertFmpq_poly_t2FacCF (A, f.mvar());
390    b= convertFmpq_poly_t2FacCF (B, f.mvar());
391    CanonicalForm r= convertFmpq_poly_t2FacCF (R, f.mvar());
392    fmpq_poly_clear (F1);
393    fmpq_poly_clear (G1);
394    fmpq_poly_clear (A);
395    fmpq_poly_clear (B);
396    fmpq_poly_clear (R);
397    return r;
398  }
399#else
[a86cda]400  if (isOn(SW_USE_NTL_GCD_0) && ( getCharacteristic() ==0)
401  && (f.level()==g.level()) && isPurePoly(f) && isPurePoly(g))
402  {
403    CanonicalForm fc=bCommonDen(f);
404    CanonicalForm gc=bCommonDen(g);
405    ZZX F1=convertFacCF2NTLZZX(f*fc);
406    ZZX G1=convertFacCF2NTLZZX(g*gc);
407    ZZX R=GCD(F1,G1);
408    CanonicalForm r=convertNTLZZX2CF(R,f.mvar());
409    ZZ RR;
410    ZZX A,B;
411    if (r.inCoeffDomain())
412    {
413      XGCD(RR,A,B,F1,G1,1);
414      CanonicalForm rr=convertZZ2CF(RR);
415      ASSERT (!rr.isZero(), "NTL:XGCD failed");
416      a=convertNTLZZX2CF(A,f.mvar())*fc/rr;
417      b=convertNTLZZX2CF(B,f.mvar())*gc/rr;
418      return CanonicalForm(1);
419    }
420    else
421    {
422      fc=bCommonDen(f);
423      gc=bCommonDen(g);
424      F1=convertFacCF2NTLZZX(f*fc/r);
425      G1=convertFacCF2NTLZZX(g*gc/r);
426      XGCD(RR,A,B,F1,G1,1);
427      a=convertNTLZZX2CF(A,f.mvar())*fc;
428      b=convertNTLZZX2CF(B,f.mvar())*gc;
429      CanonicalForm rr=convertZZ2CF(RR);
430      ASSERT (!rr.isZero(), "NTL:XGCD failed");
[8c00057]431      a /= rr;
432      b /= rr;
[a86cda]433      return r;
434    }
435  }
[fd2316c]436#endif
[034eec]437#endif
[a86cda]438  // may contain bug in the co-factors, see track 107
[034eec]439  CanonicalForm contf = content( f );
440  CanonicalForm contg = content( g );
[9bab9f]441
[034eec]442  CanonicalForm p0 = f / contf, p1 = g / contg;
443  CanonicalForm f0 = 1, f1 = 0, g0 = 0, g1 = 1, q, r;
[9bab9f]444
[c6eecb]445  while ( ! p1.isZero() )
446  {
[034eec]447      divrem( p0, p1, q, r );
448      p0 = p1; p1 = r;
449      r = g0 - g1 * q;
450      g0 = g1; g1 = r;
451      r = f0 - f1 * q;
452      f0 = f1; f1 = r;
453  }
454  CanonicalForm contp0 = content( p0 );
455  a = f0 / ( contf * contp0 );
456  b = g0 / ( contg * contp0 );
457  p0 /= contp0;
[c6eecb]458  if ( p0.sign() < 0 )
459  {
[034eec]460      p0 = -p0;
461      a = -a;
462      b = -b;
463  }
464  return p0;
[9bab9f]465}
[dd3e561]466//}}}
[9bab9f]467
[e2e4be]468//{{{ static CanonicalForm balance_p ( const CanonicalForm & f, const CanonicalForm & q )
[a7ec94]469//{{{ docu
470//
[e2e4be]471// balance_p() - map f from positive to symmetric representation
[a7ec94]472//   mod q.
473//
474// This makes sense for univariate polynomials over Z only.
475// q should be an integer.
476//
477// Used by gcd_poly_univar0().
478//
479//}}}
[edb4893]480static CanonicalForm
[e2e4be]481balance_p ( const CanonicalForm & f, const CanonicalForm & q )
482{
483    Variable x = f.mvar();
484    CanonicalForm result = 0, qh = q / 2;
485    CanonicalForm c;
486    CFIterator i;
487    for ( i = f; i.hasTerms(); i++ )
488    {
489        c = i.coeff();
490        if ( c.inCoeffDomain())
491        {
492          if ( c > qh )
493            result += power( x, i.exp() ) * (c - q);
494          else
495            result += power( x, i.exp() ) * c;
496        }
497        else
498          result += power( x, i.exp() ) * balance_p(c,q);
499    }
500    return result;
501}
502
503/*static CanonicalForm
[a7ec94]504balance ( const CanonicalForm & f, const CanonicalForm & q )
[edb4893]505{
[a7ec94]506    Variable x = f.mvar();
507    CanonicalForm result = 0, qh = q / 2;
508    CanonicalForm c;
509    CFIterator i;
510    for ( i = f; i.hasTerms(); i++ ) {
511        c = mod( i.coeff(), q );
512        if ( c > qh )
513            result += power( x, i.exp() ) * (c - q);
514        else
515            result += power( x, i.exp() ) * c;
[edb4893]516    }
[a7ec94]517    return result;
[e2e4be]518}*/
[a7ec94]519//}}}
520
[01e8874]521static CanonicalForm gcd_poly_univar0( const CanonicalForm & F, const CanonicalForm & G, bool primitive )
[a7ec94]522{
[f11d7b]523  CanonicalForm f, g, c, cg, cl, BB, B, M, q, Dp, newD, D, newq;
[01e8874]524  int p, i;
[f11d7b]525
526  if ( primitive )
527  {
528    f = F;
529    g = G;
530    c = 1;
531  }
532  else
533  {
534    CanonicalForm cF = content( F ), cG = content( G );
535    f = F / cF;
536    g = G / cG;
537    c = bgcd( cF, cG );
538  }
539  cg = gcd( f.lc(), g.lc() );
540  cl = ( f.lc() / cg ) * g.lc();
[93b061]541//     B = 2 * cg * tmin(
[150dc8]542//         maxnorm(f)*power(CanonicalForm(2),f.degree())*isqrt(f.degree()+1),
543//         maxnorm(g)*power(CanonicalForm(2),g.degree())*isqrt(g.degree()+1)
544//         )+1;
[f11d7b]545  M = tmin( maxNorm(f), maxNorm(g) );
546  BB = power(CanonicalForm(2),tmin(f.degree(),g.degree()))*M;
547  q = 0;
548  i = cf_getNumSmallPrimes() - 1;
549  while ( true )
550  {
551    B = BB;
552    while ( i >= 0 && q < B )
553    {
554      p = cf_getSmallPrime( i );
555      i--;
556      while ( i >= 0 && mod( cl, p ) == 0 )
557      {
558        p = cf_getSmallPrime( i );
559        i--;
560      }
561      setCharacteristic( p );
562      Dp = gcd( mapinto( f ), mapinto( g ) );
563      Dp = ( Dp / Dp.lc() ) * mapinto( cg );
564      setCharacteristic( 0 );
565      if ( Dp.degree() == 0 )
566        return c;
567      if ( q.isZero() )
568      {
569        D = mapinto( Dp );
570        q = p;
571        B = power(CanonicalForm(2),D.degree())*M+1;
572      }
573      else
574      {
575        if ( Dp.degree() == D.degree() )
576        {
577          chineseRemainder( D, q, mapinto( Dp ), p, newD, newq );
578          q = newq;
579          D = newD;
[150dc8]580        }
[f11d7b]581        else if ( Dp.degree() < D.degree() )
582        {
583          // all previous p's are bad primes
584          q = p;
585          D = mapinto( Dp );
586          B = power(CanonicalForm(2),D.degree())*M+1;
[150dc8]587        }
[f11d7b]588        // else p is a bad prime
589      }
590    }
591    if ( i >= 0 )
592    {
593      // now balance D mod q
[e2e4be]594      D = pp( balance_p( D, q ) );
[ebc602]595      if ( fdivides( D, f ) && fdivides( D, g ) )
[f11d7b]596        return D * c;
597      else
598        q = 0;
[edb4893]599    }
[f11d7b]600    else
[a7ec94]601      return gcd_poly( F, G );
[f11d7b]602    DEBOUTLN( cerr, "another try ..." );
603  }
[edb4893]604}
605
[c4f4fd]606static CanonicalForm
607gcd_poly_p( const CanonicalForm & f, const CanonicalForm & g )
608{
609    CanonicalForm pi, pi1;
610    CanonicalForm C, Ci, Ci1, Hi, bi, pi2;
611    bool bpure;
612    int delta = degree( f ) - degree( g );
613
614    if ( delta >= 0 )
615    {
616        pi = f; pi1 = g;
617    }
618    else
619    {
620        pi = g; pi1 = f; delta = -delta;
621    }
[a08be4]622    On (SW_USE_EZGCD_P);
[c4f4fd]623    Ci = content( pi ); Ci1 = content( pi1 );
[a08be4]624    Off (SW_USE_EZGCD_P);
[c4f4fd]625    pi1 = pi1 / Ci1; pi = pi / Ci;
626    C = gcd( Ci, Ci1 );
[5b2d2b]627    int d= 0;
[c4f4fd]628    if ( !( pi.isUnivariate() && pi1.isUnivariate() ) )
629    {
[5b2d2b]630        if ( gcd_test_one( pi1, pi, true, d ) )
[c4f4fd]631        {
632          C=abs(C);
633          //out_cf("GCD:",C,"\n");
634          return C;
635        }
636        bpure = false;
637    }
638    else
639    {
640        bpure = isPurePoly(pi) && isPurePoly(pi1);
[7e8c9e]641#ifdef HAVE_FLINT
642        if (bpure && (CFFactory::gettype() != GaloisFieldDomain))
643          return gcd_univar_flintp(pi,pi1)*C;
[7cb5590]644#else
645#ifdef HAVE_NTL
[c4f4fd]646        if ( isOn(SW_USE_NTL_GCD_P) && bpure && (CFFactory::gettype() != GaloisFieldDomain))
647            return gcd_univar_ntlp(pi, pi1 ) * C;
[7cb5590]648#endif
[c4f4fd]649#endif
650    }
651    Variable v = f.mvar();
652    Hi = power( LC( pi1, v ), delta );
[cb4f0c]653    int maxNumVars= tmax (getNumVars (pi), getNumVars (pi1));
654
655    if (!(pi.isUnivariate() && pi1.isUnivariate()))
656    {
657      if (size (Hi)*size (pi)/(maxNumVars*3) > 500) //maybe this needs more tuning
658      {
659        On (SW_USE_FF_MOD_GCD);
660        C *= gcd (pi, pi1);
661        Off (SW_USE_FF_MOD_GCD);
662        return C;
663      }
664    }
665
[c4f4fd]666    if ( (delta+1) % 2 )
667        bi = 1;
668    else
669        bi = -1;
[cb4f0c]670    CanonicalForm oldPi= pi, oldPi1= pi1, powHi;
[c4f4fd]671    while ( degree( pi1, v ) > 0 )
672    {
[6e2ef0e]673        if (!(pi.isUnivariate() && pi1.isUnivariate()))
674        {
675          if (size (pi)/maxNumVars > 500 || size (pi1)/maxNumVars > 500)
676          {
677            On (SW_USE_FF_MOD_GCD);
678            C *= gcd (oldPi, oldPi1);
679            Off (SW_USE_FF_MOD_GCD);
680            return C;
681          }
682        }
[c4f4fd]683        pi2 = psr( pi, pi1, v );
684        pi2 = pi2 / bi;
685        pi = pi1; pi1 = pi2;
[6e2ef0e]686        maxNumVars= tmax (getNumVars (pi), getNumVars (pi1));
[d1ea862]687        if (!(pi1.isUnivariate()) && (size (pi1)/maxNumVars > 500))
688        {
689            On (SW_USE_FF_MOD_GCD);
690            C *= gcd (oldPi, oldPi1);
691            Off (SW_USE_FF_MOD_GCD);
692            return C;
693        }
[c4f4fd]694        if ( degree( pi1, v ) > 0 )
695        {
696            delta = degree( pi, v ) - degree( pi1, v );
[cb4f0c]697            powHi= power (Hi, delta-1);
[c4f4fd]698            if ( (delta+1) % 2 )
[cb4f0c]699                bi = LC( pi, v ) * powHi*Hi;
[c4f4fd]700            else
[cb4f0c]701                bi = -LC( pi, v ) * powHi*Hi;
702            Hi = power( LC( pi1, v ), delta ) / powHi;
703            if (!(pi.isUnivariate() && pi1.isUnivariate()))
704            {
705              if (size (Hi)*size (pi)/(maxNumVars*3) > 500) //maybe this needs more tuning
706              {
707                On (SW_USE_FF_MOD_GCD);
708                C *= gcd (oldPi, oldPi1);
709                Off (SW_USE_FF_MOD_GCD);
710                return C;
711              }
712            }
[c4f4fd]713        }
714    }
715    if ( degree( pi1, v ) == 0 )
716    {
717      C=abs(C);
718      //out_cf("GCD:",C,"\n");
719      return C;
720    }
721    pi /= content( pi );
722    if ( bpure )
723        pi /= pi.lc();
724    C=abs(C*pi);
725    //out_cf("GCD:",C,"\n");
726    return C;
727}
728
[a7ec94]729static CanonicalForm
730gcd_poly_0( const CanonicalForm & f, const CanonicalForm & g )
731{
732    CanonicalForm pi, pi1;
[df497a]733    CanonicalForm C, Ci, Ci1, Hi, bi, pi2;
[a7ec94]734    int delta = degree( f ) - degree( g );
735
736    if ( delta >= 0 )
737    {
738        pi = f; pi1 = g;
739    }
740    else
741    {
742        pi = g; pi1 = f; delta = -delta;
743    }
[9bab9f]744    Ci = content( pi ); Ci1 = content( pi1 );
745    pi1 = pi1 / Ci1; pi = pi / Ci;
[df497a]746    C = gcd( Ci, Ci1 );
[5b2d2b]747    int d= 0;
[034eec]748    if ( pi.isUnivariate() && pi1.isUnivariate() )
749    {
[fd2316c]750#ifdef HAVE_FLINT
[7e8c9e]751        if (isPurePoly(pi) && isPurePoly(pi1) )
752            return gcd_univar_flint0(pi, pi1 ) * C;
[fd2316c]753#else
[7cb5590]754#ifdef HAVE_NTL
[a7ec94]755        if ( isOn(SW_USE_NTL_GCD_0) && isPurePoly(pi) && isPurePoly(pi1) )
756            return gcd_univar_ntl0(pi, pi1 ) * C;
[7cb5590]757#endif
[fd2316c]758#endif
[a7ec94]759        return gcd_poly_univar0( pi, pi1, true ) * C;
[edb4893]760    }
[5b2d2b]761    else if ( gcd_test_one( pi1, pi, true, d ) )
[034eec]762      return C;
[a7ec94]763    Variable v = f.mvar();
[9bab9f]764    Hi = power( LC( pi1, v ), delta );
765    if ( (delta+1) % 2 )
[150dc8]766        bi = 1;
[9bab9f]767    else
[150dc8]768        bi = -1;
[6f62c3]769    while ( degree( pi1, v ) > 0 )
770    {
[150dc8]771        pi2 = psr( pi, pi1, v );
772        pi2 = pi2 / bi;
773        pi = pi1; pi1 = pi2;
[6f62c3]774        if ( degree( pi1, v ) > 0 )
775        {
[150dc8]776            delta = degree( pi, v ) - degree( pi1, v );
777            if ( (delta+1) % 2 )
778                bi = LC( pi, v ) * power( Hi, delta );
779            else
780                bi = -LC( pi, v ) * power( Hi, delta );
781            Hi = power( LC( pi1, v ), delta ) / power( Hi, delta-1 );
782        }
[9bab9f]783    }
784    if ( degree( pi1, v ) == 0 )
[150dc8]785        return C;
[df497a]786    else
[150dc8]787        return C * pp( pi );
[9bab9f]788}
789
[b809a8]790//{{{ CanonicalForm gcd_poly ( const CanonicalForm & f, const CanonicalForm & g )
[dd3e561]791//{{{ docu
792//
793// gcd_poly() - calculate polynomial gcd.
794//
795// This is the dispatcher for polynomial gcd calculation.  We call either
796// ezgcd(), sparsemod() or gcd_poly1() in dependecy on the current
[e88604]797// characteristic and settings of SW_USE_EZGCD.
[dd3e561]798//
799// Used by gcd() and gcd_poly_univar0().
800//
801//}}}
[0b6919]802#if 0
[bfc606]803int si_factor_reminder=1;
[0b6919]804#endif
[b809a8]805CanonicalForm gcd_poly ( const CanonicalForm & f, const CanonicalForm & g )
[f63dbca]806{
[110718]807  CanonicalForm fc, gc, d1;
[ed9927]808  bool fc_isUnivariate=f.isUnivariate();
809  bool gc_isUnivariate=g.isUnivariate();
810  bool fc_and_gc_Univariate=fc_isUnivariate && gc_isUnivariate;
811  fc = f;
812  gc = g;
813  if ( getCharacteristic() != 0 )
814  {
[2072126]815    #ifdef HAVE_NTL
[e16f7d]816    if ((!fc_and_gc_Univariate) && (isOn( SW_USE_EZGCD_P )))
[49f1f45]817    {
[08daea]818      fc= EZGCD_P (fc, gc);
[c30347]819    }
[10af64]820    else if (isOn(SW_USE_FF_MOD_GCD) && !fc_and_gc_Univariate)
821    {
822      Variable a;
823      if (hasFirstAlgVar (fc, a) || hasFirstAlgVar (gc, a))
824        fc=GCD_Fp_extension (fc, gc, a);
[b5c084]825      else if (CFFactory::gettype() == GaloisFieldDomain)
[10af64]826        fc=GCD_GF (fc, gc);
[b5c084]827      else
828        fc=GCD_small_p (fc, gc);
[10af64]829    }
[efcd2dc]830    else
[2072126]831    #endif
[4a7e5c]832    fc = gcd_poly_p( fc, gc );
[110718]833  }
[c30347]834  else if (!fc_and_gc_Univariate)
[110718]835  {
[f7a4e9]836    if ( isOn( SW_USE_EZGCD ) )
837      fc= ezgcd (fc, gc);
[4a7e5c]838    else if (isOn(SW_USE_CHINREM_GCD))
[ed9927]839      fc = chinrem_gcd( fc, gc);
[c30347]840    else
841    {
[ed9927]842       fc = gcd_poly_0( fc, gc );
[c30347]843    }
[110718]844  }
845  else
846  {
847    fc = gcd_poly_0( fc, gc );
848  }
849  if ( d1.degree() > 0 )
850    fc *= d1;
851  return fc;
[f63dbca]852}
[dd3e561]853//}}}
[93b061]854
[dd3e561]855//{{{ static CanonicalForm cf_content ( const CanonicalForm & f, const CanonicalForm & g )
856//{{{ docu
857//
858// cf_content() - return gcd(g, content(f)).
859//
860// content(f) is calculated with respect to f's main variable.
861//
862// Used by gcd(), content(), content( CF, Variable ).
863//
864//}}}
[9bab9f]865static CanonicalForm
866cf_content ( const CanonicalForm & f, const CanonicalForm & g )
867{
[6f62c3]868    if ( f.inPolyDomain() || ( f.inExtension() && ! getReduce( f.mvar() ) ) )
869    {
[150dc8]870        CFIterator i = f;
871        CanonicalForm result = g;
[6f62c3]872        while ( i.hasTerms() && ! result.isOne() )
873        {
[a7ec94]874            result = gcd( i.coeff(), result );
[150dc8]875            i++;
876        }
877        return result;
[9bab9f]878    }
879    else
[a7ec94]880        return abs( f );
[9bab9f]881}
[dd3e561]882//}}}
[9bab9f]883
[4ea0ab]884//{{{ CanonicalForm content ( const CanonicalForm & f )
885//{{{ docu
886//
887// content() - return content(f) with respect to main variable.
888//
[dd3e561]889// Normalizes result.
890//
[4ea0ab]891//}}}
[9bab9f]892CanonicalForm
893content ( const CanonicalForm & f )
894{
[6f62c3]895    if ( f.inPolyDomain() || ( f.inExtension() && ! getReduce( f.mvar() ) ) )
896    {
[a7ec94]897        CFIterator i = f;
898        CanonicalForm result = abs( i.coeff() );
899        i++;
[6f62c3]900        while ( i.hasTerms() && ! result.isOne() )
901        {
[a7ec94]902            result = gcd( i.coeff(), result );
903            i++;
904        }
905        return result;
906    }
907    else
908        return abs( f );
[9bab9f]909}
[4ea0ab]910//}}}
[9bab9f]911
[dd3e561]912//{{{ CanonicalForm content ( const CanonicalForm & f, const Variable & x )
913//{{{ docu
914//
915// content() - return content(f) with respect to x.
916//
917// x should be a polynomial variable.
918//
919//}}}
[9bab9f]920CanonicalForm
921content ( const CanonicalForm & f, const Variable & x )
922{
[dd3e561]923    ASSERT( x.level() > 0, "cannot calculate content with respect to algebraic variable" );
924    Variable y = f.mvar();
925
926    if ( y == x )
[150dc8]927        return cf_content( f, 0 );
[dd3e561]928    else  if ( y < x )
[150dc8]929        return f;
[9bab9f]930    else
[150dc8]931        return swapvar( content( swapvar( f, y, x ), y ), y, x );
[9bab9f]932}
[dd3e561]933//}}}
[9bab9f]934
[dd3e561]935//{{{ CanonicalForm vcontent ( const CanonicalForm & f, const Variable & x )
936//{{{ docu
937//
938// vcontent() - return content of f with repect to variables >= x.
939//
940// The content is recursively calculated over all coefficients in
941// f having level less than x.  x should be a polynomial
942// variable.
943//
944//}}}
[9bab9f]945CanonicalForm
946vcontent ( const CanonicalForm & f, const Variable & x )
947{
[dd3e561]948    ASSERT( x.level() > 0, "cannot calculate vcontent with respect to algebraic variable" );
949
[9bab9f]950    if ( f.mvar() <= x )
[150dc8]951        return content( f, x );
[9bab9f]952    else {
[150dc8]953        CFIterator i;
954        CanonicalForm d = 0;
955        for ( i = f; i.hasTerms() && ! d.isOne(); i++ )
956            d = gcd( d, vcontent( i.coeff(), x ) );
957        return d;
[9bab9f]958    }
959}
[dd3e561]960//}}}
[9bab9f]961
[4ea0ab]962//{{{ CanonicalForm pp ( const CanonicalForm & f )
963//{{{ docu
964//
965// pp() - return primitive part of f.
966//
[dd3e561]967// Returns zero if f equals zero, otherwise f / content(f).
968//
[4ea0ab]969//}}}
[9bab9f]970CanonicalForm
971pp ( const CanonicalForm & f )
972{
973    if ( f.isZero() )
[150dc8]974        return f;
[9bab9f]975    else
[150dc8]976        return f / content( f );
[9bab9f]977}
[4ea0ab]978//}}}
[9bab9f]979
[ff6222]980CanonicalForm
[9bab9f]981gcd ( const CanonicalForm & f, const CanonicalForm & g )
982{
[a7ec94]983    bool b = f.isZero();
984    if ( b || g.isZero() )
985    {
986        if ( b )
987            return abs( g );
[abfc3b]988        else
[a7ec94]989            return abs( f );
990    }
991    if ( f.inPolyDomain() || g.inPolyDomain() )
992    {
993        if ( f.mvar() != g.mvar() )
994        {
995            if ( f.mvar() > g.mvar() )
996                return cf_content( f, g );
997            else
998                return cf_content( g, f );
999        }
[bb82f0]1000        if (isOn(SW_USE_QGCD))
1001        {
1002          Variable m;
[fc9f44]1003          if (
1004          (getCharacteristic() == 0) &&
[e6f7ee1]1005          (hasFirstAlgVar(f,m) || hasFirstAlgVar(g,m))
[bb82f0]1006          )
[fc31bce]1007          {
[713bdb]1008            bool on_rational = isOn(SW_RATIONAL);
1009            CanonicalForm r=QGCD(f,g);
[f06059]1010            On(SW_RATIONAL);
[713bdb]1011            CanonicalForm cdF = bCommonDen( r );
1012            if (!on_rational) Off(SW_RATIONAL);
1013            return cdF*r;
[fc31bce]1014          }
[bb82f0]1015        }
[713bdb]1016
[150dc8]1017        if ( f.inExtension() && getReduce( f.mvar() ) )
[bb82f0]1018            return CanonicalForm(1);
[a7ec94]1019        else
1020        {
[ebc602]1021            if ( fdivides( f, g ) )
[a7ec94]1022                return abs( f );
[ebc602]1023            else  if ( fdivides( g, f ) )
[a7ec94]1024                return abs( g );
1025            if ( !( getCharacteristic() == 0 && isOn( SW_RATIONAL ) ) )
1026            {
1027                CanonicalForm d;
[64a501]1028                d = gcd_poly( f, g );
[a7ec94]1029                return abs( d );
1030            }
1031            else
1032            {
[56d3c6]1033                //printf ("here\n");
[150dc8]1034                CanonicalForm cdF = bCommonDen( f );
1035                CanonicalForm cdG = bCommonDen( g );
1036                Off( SW_RATIONAL );
1037                CanonicalForm l = lcm( cdF, cdG );
1038                On( SW_RATIONAL );
1039                CanonicalForm F = f * l, G = g * l;
1040                Off( SW_RATIONAL );
[64a501]1041                l = gcd_poly( F, G );
[150dc8]1042                On( SW_RATIONAL );
[a7ec94]1043                return abs( l );
[150dc8]1044            }
1045        }
[a7ec94]1046    }
1047    if ( f.inBaseDomain() && g.inBaseDomain() )
1048        return bgcd( f, g );
[9bab9f]1049    else
[a7ec94]1050        return 1;
[9bab9f]1051}
1052
[dd3e561]1053//{{{ CanonicalForm lcm ( const CanonicalForm & f, const CanonicalForm & g )
1054//{{{ docu
1055//
1056// lcm() - return least common multiple of f and g.
1057//
1058// The lcm is calculated using the formula lcm(f, g) = f * g / gcd(f, g).
1059//
1060// Returns zero if one of f or g equals zero.
1061//
1062//}}}
[9bab9f]1063CanonicalForm
1064lcm ( const CanonicalForm & f, const CanonicalForm & g )
1065{
[dd3e561]1066    if ( f.isZero() || g.isZero() )
[a7ec94]1067        return 0;
[dd3e561]1068    else
[150dc8]1069        return ( f / gcd( f, g ) ) * g;
[9bab9f]1070}
[dd3e561]1071//}}}
[a7ec94]1072
1073#ifdef HAVE_NTL
[447349]1074#ifndef HAVE_FLINT
[a7ec94]1075static CanonicalForm
1076gcd_univar_ntl0( const CanonicalForm & F, const CanonicalForm & G )
1077{
1078    ZZX F1=convertFacCF2NTLZZX(F);
1079    ZZX G1=convertFacCF2NTLZZX(G);
1080    ZZX R=GCD(F1,G1);
1081    return convertNTLZZX2CF(R,F.mvar());
1082}
1083
[c4f4fd]1084static CanonicalForm
1085gcd_univar_ntlp( const CanonicalForm & F, const CanonicalForm & G )
1086{
1087  if (fac_NTL_char!=getCharacteristic())
1088  {
1089    fac_NTL_char=getCharacteristic();
1090    #ifdef NTL_ZZ
1091    ZZ r;
1092    r=getCharacteristic();
1093    ZZ_pContext ccc(r);
1094    #else
1095    zz_pContext ccc(getCharacteristic());
1096    #endif
1097    ccc.restore();
1098    #ifdef NTL_ZZ
1099    ZZ_p::init(r);
1100    #else
1101    zz_p::init(getCharacteristic());
1102    #endif
1103  }
1104  #ifdef NTL_ZZ
1105  ZZ_pX F1=convertFacCF2NTLZZpX(F);
1106  ZZ_pX G1=convertFacCF2NTLZZpX(G);
1107  ZZ_pX R=GCD(F1,G1);
1108  return  convertNTLZZpX2CF(R,F.mvar());
1109  #else
1110  zz_pX F1=convertFacCF2NTLzzpX(F);
1111  zz_pX G1=convertFacCF2NTLzzpX(G);
1112  zz_pX R=GCD(F1,G1);
1113  return  convertNTLzzpX2CF(R,F.mvar());
1114  #endif
1115}
[447349]1116#endif
[a7ec94]1117#endif
1118
[7e8c9e]1119#ifdef HAVE_FLINT
1120static CanonicalForm
1121gcd_univar_flintp (const CanonicalForm& F, const CanonicalForm& G)
1122{
1123  nmod_poly_t F1, G1;
1124  convertFacCF2nmod_poly_t (F1, F);
1125  convertFacCF2nmod_poly_t (G1, G);
1126  nmod_poly_gcd (F1, F1, G1);
1127  CanonicalForm result= convertnmod_poly_t2FacCF (F1, F.mvar());
1128  nmod_poly_clear (F1);
1129  nmod_poly_clear (G1);
1130  return result;
1131}
1132
1133static CanonicalForm
1134gcd_univar_flint0( const CanonicalForm & F, const CanonicalForm & G )
1135{
1136  fmpz_poly_t F1, G1;
1137  convertFacCF2Fmpz_poly_t(F1, F);
1138  convertFacCF2Fmpz_poly_t(G1, G);
1139  fmpz_poly_gcd (F1, F1, G1);
1140  CanonicalForm result= convertFmpz_poly_t2FacCF (F1, F.mvar());
1141  fmpz_poly_clear (F1);
1142  fmpz_poly_clear (G1);
1143  return result;
1144}
1145#endif
1146
1147
[a7ec94]1148/*
1149*  compute positions p1 and pe of optimal variables:
1150*    pe is used in "ezgcd" and
1151*    p1 in "gcd_poly1"
1152*/
[4a7e5c]1153/*static
[a7ec94]1154void optvalues ( const int * df, const int * dg, const int n, int & p1, int &pe )
1155{
1156    int i, o1, oe;
1157    if ( df[n] > dg[n] )
1158    {
1159        o1 = df[n]; oe = dg[n];
1160    }
1161    else
1162    {
1163        o1 = dg[n]; oe = df[n];
1164    }
1165    i = n-1;
1166    while ( i > 0 )
1167    {
1168        if ( df[i] != 0 )
1169        {
1170            if ( df[i] > dg[i] )
1171            {
1172                if ( o1 > df[i]) { o1 = df[i]; p1 = i; }
1173                if ( oe <= dg[i]) { oe = dg[i]; pe = i; }
1174            }
1175            else
1176            {
1177                if ( o1 > dg[i]) { o1 = dg[i]; p1 = i; }
1178                if ( oe <= df[i]) { oe = df[i]; pe = i; }
1179            }
1180        }
1181        i--;
1182    }
[4a7e5c]1183}*/
[a7ec94]1184
1185/*
1186*  make some changes of variables, see optvalues
1187*/
[4a7e5c]1188/*static void
[a7ec94]1189cf_prepgcd( const CanonicalForm & f, const CanonicalForm & g, int & cc, int & p1, int &pe )
1190{
1191    int i, k, n;
1192    n = f.level();
1193    cc = 0;
1194    p1 = pe = n;
1195    if ( n == 1 )
1196        return;
1197    int * degsf = new int[n+1];
1198    int * degsg = new int[n+1];
1199    for ( i = n; i > 0; i-- )
1200    {
1201        degsf[i] = degsg[i] = 0;
1202    }
1203    degsf = degrees( f, degsf );
1204    degsg = degrees( g, degsg );
1205
1206    k = 0;
1207    for ( i = n-1; i > 0; i-- )
1208    {
[f4b180]1209        if ( degsf[i] == 0 )
[a7ec94]1210        {
1211            if ( degsg[i] != 0 )
1212            {
1213                cc = -i;
1214                break;
1215            }
1216        }
1217        else
1218        {
1219            if ( degsg[i] == 0 )
1220            {
1221                cc = i;
1222                break;
1223            }
1224            else k++;
1225        }
1226    }
1227
1228    if ( ( cc == 0 ) && ( k != 0 ) )
1229        optvalues( degsf, degsg, n, p1, pe );
1230    if ( ( pe != 1 ) && ( degsf[1] != 0 ) )
1231        pe = -pe;
[f4b180]1232
[a7ec94]1233    delete [] degsf;
1234    delete [] degsg;
[4a7e5c]1235}*/
[6f62c3]1236
[2a95b2]1237TIMING_DEFINE_PRINT(chinrem_termination)
1238TIMING_DEFINE_PRINT(chinrem_recursion)
1239TIMING_DEFINE_PRINT(chinrem_reconstruction)
1240
[6f62c3]1241CanonicalForm chinrem_gcd ( const CanonicalForm & FF, const CanonicalForm & GG )
1242{
[297e92]1243  CanonicalForm f, g, cl, q(0), Dp, newD, D, newq;
[c1b9927]1244  int p, i, dp_deg, d_deg=-1;
[6f62c3]1245
[01e8874]1246  CanonicalForm cd ( bCommonDen( FF ));
[6f62c3]1247  f=cd*FF;
[297e92]1248  Variable x= Variable (1);
1249  CanonicalForm cf, cg;
1250  cf= icontent (f);
1251  f /= cf;
[08a6ebb]1252  //cd = bCommonDen( f ); f *=cd;
1253  //f /=vcontent(f,Variable(1));
[6f62c3]1254
1255  cd = bCommonDen( GG );
1256  g=cd*GG;
[297e92]1257  cg= icontent (g);
1258  g /= cg;
[08a6ebb]1259  //cd = bCommonDen( g ); g *=cd;
1260  //g /=vcontent(g,Variable(1));
[6f62c3]1261
[297e92]1262  CanonicalForm Dn, test= 0;
[4704674]1263  cl =  gcd (f.lc(),g.lc());
[597783]1264  CanonicalForm gcdcfcg= gcd (cf, cg);
[2488dc3]1265  CanonicalForm fp, gp;
[4704674]1266  CanonicalForm b= 1;
1267  int minCommonDeg= 0;
1268  for (i= tmax (f.level(), g.level()); i > 0; i--)
1269  {
1270    if (degree (f, i) <= 0 || degree (g, i) <= 0)
1271      continue;
1272    else
1273    {
1274      minCommonDeg= tmin (degree (g, i), degree (f, i));
1275      break;
1276    }
1277  }
1278  if (i == 0)
1279    return gcdcfcg;
1280  for (; i > 0; i--)
1281  {
1282    if (degree (f, i) <= 0 || degree (g, i) <= 0)
1283      continue;
1284    else
1285      minCommonDeg= tmin (minCommonDeg, tmin (degree (g, i), degree (f, i)));
1286  }
[cb7827]1287  b= 2*tmin (maxNorm (f), maxNorm (g))*abs (cl)*
1288     power (CanonicalForm (2), minCommonDeg);
[297e92]1289  bool equal= false;
[6f62c3]1290  i = cf_getNumBigPrimes() - 1;
1291
[cb7827]1292  CanonicalForm cof, cog, cofp, cogp, newCof, newCog, cofn, cogn;
[2488dc3]1293  int maxNumVars= tmax (getNumVars (f), getNumVars (g));
[297e92]1294  //Off (SW_RATIONAL);
[6f62c3]1295  while ( true )
1296  {
1297    p = cf_getBigPrime( i );
1298    i--;
[597783]1299    while ( i >= 0 && mod( cl*(lc(f)/cl)*(lc(g)/cl), p ) == 0 )
[6f62c3]1300    {
1301      p = cf_getBigPrime( i );
1302      i--;
1303    }
[c30347]1304    //printf("try p=%d\n",p);
[6f62c3]1305    setCharacteristic( p );
[2488dc3]1306    fp= mapinto (f);
1307    gp= mapinto (g);
[2a95b2]1308    TIMING_START (chinrem_recursion)
[517530]1309#ifdef HAVE_NTL
[2488dc3]1310    if (size (fp)/maxNumVars > 500 && size (gp)/maxNumVars > 500)
1311      Dp = GCD_small_p (fp, gp, cofp, cogp);
1312    else
1313    {
1314      Dp= gcd_poly (fp, gp);
1315      cofp= fp/Dp;
1316      cogp= gp/Dp;
1317    }
[517530]1318#else
[2488dc3]1319    Dp= gcd_poly (fp, gp);
1320    cofp= fp/Dp;
1321    cogp= gp/Dp;
[517530]1322#endif
[2a95b2]1323    TIMING_END_AND_PRINT (chinrem_recursion,
1324                          "time for gcd mod p in modular gcd: ");
[08a6ebb]1325    Dp /=Dp.lc();
[cb7827]1326    cofp /= lc (cofp);
1327    cogp /= lc (cogp);
[6f62c3]1328    setCharacteristic( 0 );
1329    dp_deg=totaldegree(Dp);
1330    if ( dp_deg == 0 )
[c30347]1331    {
1332      //printf(" -> 1\n");
[297e92]1333      return CanonicalForm(gcdcfcg);
[c30347]1334    }
[6f62c3]1335    if ( q.isZero() )
1336    {
1337      D = mapinto( Dp );
[cb7827]1338      cof= mapinto (cofp);
1339      cog= mapinto (cogp);
[6f62c3]1340      d_deg=dp_deg;
1341      q = p;
1342    }
1343    else
1344    {
1345      if ( dp_deg == d_deg )
1346      {
1347        chineseRemainder( D, q, mapinto( Dp ), p, newD, newq );
[cb7827]1348        chineseRemainder( cof, q, mapinto (cofp), p, newCof, newq);
1349        chineseRemainder( cog, q, mapinto (cogp), p, newCog, newq);
1350        cof= newCof;
1351        cog= newCog;
[6f62c3]1352        q = newq;
1353        D = newD;
1354      }
[f4b180]1355      else if ( dp_deg < d_deg )
[6f62c3]1356      {
[c30347]1357        //printf(" were all bad, try more\n");
[6f62c3]1358        // all previous p's are bad primes
1359        q = p;
1360        D = mapinto( Dp );
[cb7827]1361        cof= mapinto (cof);
1362        cog= mapinto (cog);
[6f62c3]1363        d_deg=dp_deg;
[297e92]1364        test= 0;
1365        equal= false;
[6f62c3]1366      }
[c30347]1367      else
1368      {
1369        //printf(" was bad, try more\n");
1370      }
[f4b180]1371      //else dp_deg > d_deg: bad prime
[6f62c3]1372    }
[08a6ebb]1373    if ( i >= 0 )
[6f62c3]1374    {
[2a95b2]1375      TIMING_START (chinrem_reconstruction);
[297e92]1376      Dn= Farey(D,q);
[cb7827]1377      cofn= Farey(cof,q);
1378      cogn= Farey(cog,q);
[2a95b2]1379      TIMING_END_AND_PRINT (chinrem_reconstruction,
1380                           "time for rational reconstruction in modular gcd: ");
[297e92]1381      int is_rat= isOn (SW_RATIONAL);
[56d3c6]1382      On (SW_RATIONAL);
[297e92]1383      cd = bCommonDen( Dn ); // we need On(SW_RATIONAL)
[cb7827]1384      cofn *= bCommonDen (cofn);
1385      cogn *= bCommonDen (cogn);
[297e92]1386      if (!is_rat)
1387        Off (SW_RATIONAL);
[c992ec1]1388      Dn *=cd;
[297e92]1389      if (test != Dn)
1390        test= Dn;
1391      else
1392        equal= true;
[c992ec1]1393      //Dn /=vcontent(Dn,Variable(1));
[2a95b2]1394      TIMING_START (chinrem_termination);
[1e4b53]1395      if ((terminationTest (f,g, cofn, cogn, Dn)) ||
[597783]1396          ((equal || q > b) && fdivides (Dn, f) && fdivides (Dn, g)))
[6f62c3]1397      {
[2a95b2]1398        TIMING_END_AND_PRINT (chinrem_termination,
1399                            "time for successful termination in modular gcd: ");
[c30347]1400        //printf(" -> success\n");
[297e92]1401        return Dn*gcdcfcg;
[6f62c3]1402      }
[2a95b2]1403      TIMING_END_AND_PRINT (chinrem_termination,
1404                          "time for unsuccessful termination in modular gcd: ");
[297e92]1405      equal= false;
[c992ec1]1406      //else: try more primes
[6f62c3]1407    }
1408    else
[c992ec1]1409    { // try other method
[c30347]1410      //printf("try other gcd\n");
[6f62c3]1411      Off(SW_USE_CHINREM_GCD);
1412      D=gcd_poly( f, g );
1413      On(SW_USE_CHINREM_GCD);
[297e92]1414      return D*gcdcfcg;
[6f62c3]1415    }
1416  }
1417}
[c5d0aed]1418
[cb7827]1419
Note: See TracBrowser for help on using the repository browser.