source: git/factory/cf_gcd.cc @ ad8e1b

fieker-DuValspielwiese
Last change on this file since ad8e1b was ad8e1b, checked in by Hans Schönemann <hannes@…>, 16 years ago
*hannes: QGCD, fieldGCD, etc git-svn-id: file:///usr/local/Singular/svn/trunk@10949 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 28.1 KB
RevLine 
[493c477]1/* emacs edit mode for this file is -*- C++ -*- */
[ad8e1b]2/* $Id: cf_gcd.cc,v 1.65 2008-08-06 13:53:15 Singular Exp $ */
[9bab9f]3
[ab4548f]4#include <config.h>
5
[9bab9f]6#include "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"
[f63dbca]15#include "fac_util.h"
[71da5e]16#include "ftmpl_functions.h"
[49f1f45]17#include "ffreval.h"
[bb82f0]18#include "algext.h"
[598ff8b]19#include "fieldGCD.h"
[edb4893]20
[f11d7b]21#ifdef HAVE_NTL
[034eec]22#include <NTL/ZZX.h>
[f11d7b]23#include "NTLconvert.h"
[a7ec94]24bool isPurePoly(const CanonicalForm & );
25static CanonicalForm gcd_univar_ntl0( const CanonicalForm &, const CanonicalForm & );
26static CanonicalForm gcd_univar_ntlp( const CanonicalForm &, const CanonicalForm & );
[f11d7b]27#endif
28
[a7ec94]29static CanonicalForm cf_content ( const CanonicalForm &, const CanonicalForm & );
30static bool gcd_avoid_mtaildegree ( CanonicalForm &, CanonicalForm &, CanonicalForm & );
31static void cf_prepgcd( const CanonicalForm &, const CanonicalForm &, int &, int &, int & );
[edb4893]32
[6f62c3]33void out_cf(char *s1,const CanonicalForm &f,char *s2);
34
[110718]35CanonicalForm chinrem_gcd(const CanonicalForm & FF,const CanonicalForm & GG);
36CanonicalForm newGCD(CanonicalForm A, CanonicalForm B);
[f4b180]37
[f63dbca]38bool
39gcd_test_one ( const CanonicalForm & f, const CanonicalForm & g, bool swap )
[9bab9f]40{
41    int count = 0;
42    // assume polys have same level;
43    CFRandom * sample = CFRandomFactory::generate();
[f63dbca]44    REvaluation e( 2, tmax( f.level(), g.level() ), *sample );
[9bab9f]45    delete sample;
[f63dbca]46    CanonicalForm lcf, lcg;
[6f62c3]47    if ( swap )
48    {
[150dc8]49        lcf = swapvar( LC( f ), Variable(1), f.mvar() );
50        lcg = swapvar( LC( g ), Variable(1), f.mvar() );
[f63dbca]51    }
[6f62c3]52    else
53    {
[150dc8]54        lcf = LC( f, Variable(1) );
55        lcg = LC( g, Variable(1) );
[f63dbca]56    }
[df497a]57    #define TEST_ONE_MAX 50
58    while ( ( e( lcf ).isZero() || e( lcg ).isZero() ) && count < TEST_ONE_MAX )
59    {
[150dc8]60        e.nextpoint();
61        count++;
[9bab9f]62    }
[df497a]63    if ( count == TEST_ONE_MAX )
[150dc8]64        return false;
[f63dbca]65    CanonicalForm F, G;
[6f62c3]66    if ( swap )
67    {
[150dc8]68        F=swapvar( f, Variable(1), f.mvar() );
69        G=swapvar( g, Variable(1), g.mvar() );
[f63dbca]70    }
[6f62c3]71    else
72    {
[150dc8]73        F = f;
74        G = g;
[f63dbca]75    }
[9bab9f]76    if ( e(F).taildegree() > 0 && e(G).taildegree() > 0 )
[150dc8]77        return false;
[9bab9f]78    return gcd( e( F ), e( G ) ).degree() < 1;
79}
80
[dd3e561]81//{{{ static CanonicalForm icontent ( const CanonicalForm & f, const CanonicalForm & c )
82//{{{ docu
83//
84// icontent() - return gcd of c and all coefficients of f which
85//   are in a coefficient domain.
86//
87// Used by icontent().
88//
89//}}}
[9bab9f]90static CanonicalForm
91icontent ( const CanonicalForm & f, const CanonicalForm & c )
92{
[c30347]93    if ( f.inBaseDomain() )
94    {
95      if (c.isZero()) return abs(f);
96      return bgcd( f, c );
97    }
[ef20c7]98    //else if ( f.inCoeffDomain() )
99    //   return gcd(f,c);
[c30347]100    else
101    {
[150dc8]102        CanonicalForm g = c;
103        for ( CFIterator i = f; i.hasTerms() && ! g.isOne(); i++ )
104            g = icontent( i.coeff(), g );
105        return g;
[9bab9f]106    }
107}
[dd3e561]108//}}}
[9bab9f]109
[dd3e561]110//{{{ CanonicalForm icontent ( const CanonicalForm & f )
111//{{{ docu
112//
113// icontent() - return gcd over all coefficients of f which are
114//   in a coefficient domain.
115//
116//}}}
[9bab9f]117CanonicalForm
118icontent ( const CanonicalForm & f )
119{
120    return icontent( f, 0 );
121}
[dd3e561]122//}}}
[9bab9f]123
[dd3e561]124//{{{ CanonicalForm extgcd ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & a, CanonicalForm & b )
125//{{{ docu
126//
127// extgcd() - returns polynomial extended gcd of f and g.
128//
129// Returns gcd(f, g) and a and b sucht that f*a+g*b=gcd(f, g).
130// The gcd is calculated using an extended euclidean polynomial
131// remainder sequence, so f and g should be polynomials over an
132// euclidean domain.  Normalizes result.
133//
134// Note: be sure that f and g have the same level!
135//
136//}}}
[9bab9f]137CanonicalForm
138extgcd ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & a, CanonicalForm & b )
139{
[034eec]140#ifdef HAVE_NTL
[2667bc8]141  if (isOn(SW_USE_NTL_GCD_P) && ( getCharacteristic() > 0 )
[034eec]142  && isPurePoly(f) && isPurePoly(g))
143  {
[c6eecb]144    if (fac_NTL_char!=getCharacteristic())
145    {
146      fac_NTL_char=getCharacteristic();
147      #ifdef NTL_ZZ
148      ZZ r;
149      r=getCharacteristic();
150      ZZ_pContext ccc(r);
151      #else
152      zz_pContext ccc(getCharacteristic());
153      #endif
154      ccc.restore();
155      #ifdef NTL_ZZ
156      ZZ_p::init(r);
157      #else
158      zz_p::init(getCharacteristic());
159      #endif
160    }
161    #ifdef NTL_ZZ
162    ZZ_pX F1=convertFacCF2NTLZZpX(f);
163    ZZ_pX G1=convertFacCF2NTLZZpX(g);
164    ZZ_pX R;
165    ZZ_pX A,B;
166    XGCD(R,A,B,F1,G1);
167    a=convertNTLZZpX2CF(A,f.mvar());
168    b=convertNTLZZpX2CF(B,f.mvar());
169    return convertNTLZZpX2CF(R,f.mvar());
170    #else
[034eec]171    zz_pX F1=convertFacCF2NTLzzpX(f);
172    zz_pX G1=convertFacCF2NTLzzpX(g);
173    zz_pX R;
174    zz_pX A,B;
175    XGCD(R,A,B,F1,G1);
176    a=convertNTLzzpX2CF(A,f.mvar());
177    b=convertNTLzzpX2CF(B,f.mvar());
178    return convertNTLzzpX2CF(R,f.mvar());
[c6eecb]179    #endif
[034eec]180  }
181#endif
182  CanonicalForm contf = content( f );
183  CanonicalForm contg = content( g );
[9bab9f]184
[034eec]185  CanonicalForm p0 = f / contf, p1 = g / contg;
186  CanonicalForm f0 = 1, f1 = 0, g0 = 0, g1 = 1, q, r;
[9bab9f]187
[c6eecb]188  while ( ! p1.isZero() )
189  {
[034eec]190      divrem( p0, p1, q, r );
191      p0 = p1; p1 = r;
192      r = g0 - g1 * q;
193      g0 = g1; g1 = r;
194      r = f0 - f1 * q;
195      f0 = f1; f1 = r;
196  }
197  CanonicalForm contp0 = content( p0 );
198  a = f0 / ( contf * contp0 );
199  b = g0 / ( contg * contp0 );
200  p0 /= contp0;
[c6eecb]201  if ( p0.sign() < 0 )
202  {
[034eec]203      p0 = -p0;
204      a = -a;
205      b = -b;
206  }
207  return p0;
[9bab9f]208}
[dd3e561]209//}}}
[9bab9f]210
[a7ec94]211//{{{ static CanonicalForm balance ( const CanonicalForm & f, const CanonicalForm & q )
212//{{{ docu
213//
214// balance() - map f from positive to symmetric representation
215//   mod q.
216//
217// This makes sense for univariate polynomials over Z only.
218// q should be an integer.
219//
220// Used by gcd_poly_univar0().
221//
222//}}}
[edb4893]223static CanonicalForm
[a7ec94]224balance ( const CanonicalForm & f, const CanonicalForm & q )
[edb4893]225{
[a7ec94]226    Variable x = f.mvar();
227    CanonicalForm result = 0, qh = q / 2;
228    CanonicalForm c;
229    CFIterator i;
230    for ( i = f; i.hasTerms(); i++ ) {
231        c = mod( i.coeff(), q );
232        if ( c > qh )
233            result += power( x, i.exp() ) * (c - q);
234        else
235            result += power( x, i.exp() ) * c;
[edb4893]236    }
[a7ec94]237    return result;
238}
239//}}}
240
241static CanonicalForm
242gcd_poly_univar0( const CanonicalForm & F, const CanonicalForm & G, bool primitive )
243{
[f11d7b]244  CanonicalForm f, g, c, cg, cl, BB, B, M, q, Dp, newD, D, newq;
245  int p, i, n;
246
247  if ( primitive )
248  {
249    f = F;
250    g = G;
251    c = 1;
252  }
253  else
254  {
255    CanonicalForm cF = content( F ), cG = content( G );
256    f = F / cF;
257    g = G / cG;
258    c = bgcd( cF, cG );
259  }
260  cg = gcd( f.lc(), g.lc() );
261  cl = ( f.lc() / cg ) * g.lc();
[93b061]262//     B = 2 * cg * tmin(
[150dc8]263//         maxnorm(f)*power(CanonicalForm(2),f.degree())*isqrt(f.degree()+1),
264//         maxnorm(g)*power(CanonicalForm(2),g.degree())*isqrt(g.degree()+1)
265//         )+1;
[f11d7b]266  M = tmin( maxNorm(f), maxNorm(g) );
267  BB = power(CanonicalForm(2),tmin(f.degree(),g.degree()))*M;
268  q = 0;
269  i = cf_getNumSmallPrimes() - 1;
270  while ( true )
271  {
272    B = BB;
273    while ( i >= 0 && q < B )
274    {
275      p = cf_getSmallPrime( i );
276      i--;
277      while ( i >= 0 && mod( cl, p ) == 0 )
278      {
279        p = cf_getSmallPrime( i );
280        i--;
281      }
282      setCharacteristic( p );
283      Dp = gcd( mapinto( f ), mapinto( g ) );
284      Dp = ( Dp / Dp.lc() ) * mapinto( cg );
285      setCharacteristic( 0 );
286      if ( Dp.degree() == 0 )
287        return c;
288      if ( q.isZero() )
289      {
290        D = mapinto( Dp );
291        q = p;
292        B = power(CanonicalForm(2),D.degree())*M+1;
293      }
294      else
295      {
296        if ( Dp.degree() == D.degree() )
297        {
298          chineseRemainder( D, q, mapinto( Dp ), p, newD, newq );
299          q = newq;
300          D = newD;
[150dc8]301        }
[f11d7b]302        else if ( Dp.degree() < D.degree() )
303        {
304          // all previous p's are bad primes
305          q = p;
306          D = mapinto( Dp );
307          B = power(CanonicalForm(2),D.degree())*M+1;
[150dc8]308        }
[f11d7b]309        // else p is a bad prime
310      }
311    }
312    if ( i >= 0 )
313    {
314      // now balance D mod q
315      D = pp( balance( D, q ) );
[ebc602]316      if ( fdivides( D, f ) && fdivides( D, g ) )
[f11d7b]317        return D * c;
318      else
319        q = 0;
[edb4893]320    }
[f11d7b]321    else
[a7ec94]322      return gcd_poly( F, G );
[f11d7b]323    DEBOUTLN( cerr, "another try ..." );
324  }
[edb4893]325}
326
[a7ec94]327static CanonicalForm
328gcd_poly_p( const CanonicalForm & f, const CanonicalForm & g )
[9bab9f]329{
[df497a]330    CanonicalForm pi, pi1;
[a7ec94]331    CanonicalForm C, Ci, Ci1, Hi, bi, pi2;
[fda36e]332    bool bpure;
[a7ec94]333    int delta = degree( f ) - degree( g );
[9bab9f]334
[a7ec94]335    if ( delta >= 0 )
[df497a]336    {
[150dc8]337        pi = f; pi1 = g;
[9bab9f]338    }
[df497a]339    else
340    {
[a7ec94]341        pi = g; pi1 = f; delta = -delta;
342    }
343    Ci = content( pi ); Ci1 = content( pi1 );
344    pi1 = pi1 / Ci1; pi = pi / Ci;
345    C = gcd( Ci, Ci1 );
346    if ( !( pi.isUnivariate() && pi1.isUnivariate() ) )
347    {
[6f62c3]348        //out_cf("F:",f,"\n");
349        //out_cf("G:",g,"\n");
350        //out_cf("newGCD:",newGCD(f,g),"\n");
[110718]351        if (isOn(SW_USE_GCD_P) && (getCharacteristic()>0))
352        {
353          return newGCD(f,g);
354        }
[fda36e]355        if ( gcd_test_one( pi1, pi, true ) )
[6f62c3]356        {
357          C=abs(C);
358          //out_cf("GCD:",C,"\n");
359          return C;
360        }
[fda36e]361        bpure = false;
[a7ec94]362    }
363    else
364    {
[fda36e]365        bpure = isPurePoly(pi) && isPurePoly(pi1);
366#ifdef HAVE_NTL
367        if ( isOn(SW_USE_NTL_GCD_P) && bpure )
368            return gcd_univar_ntlp(pi, pi1 ) * C;
[a7ec94]369#endif
[fda36e]370    }
[a7ec94]371    Variable v = f.mvar();
372    Hi = power( LC( pi1, v ), delta );
373    if ( (delta+1) % 2 )
374        bi = 1;
375    else
376        bi = -1;
377    while ( degree( pi1, v ) > 0 ) {
378        pi2 = psr( pi, pi1, v );
379        pi2 = pi2 / bi;
380        pi = pi1; pi1 = pi2;
381        if ( degree( pi1, v ) > 0 ) {
382            delta = degree( pi, v ) - degree( pi1, v );
383            if ( (delta+1) % 2 )
384                bi = LC( pi, v ) * power( Hi, delta );
385            else
386                bi = -LC( pi, v ) * power( Hi, delta );
387            Hi = power( LC( pi1, v ), delta ) / power( Hi, delta-1 );
388        }
[9bab9f]389    }
[a7ec94]390    if ( degree( pi1, v ) == 0 )
[6f62c3]391    {
392      C=abs(C);
393      //out_cf("GCD:",C,"\n");
394      return C;
395    }
[fda36e]396    pi /= content( pi );
397    if ( bpure )
398        pi /= pi.lc();
[6f62c3]399    C=abs(C*pi);
400    //out_cf("GCD:",C,"\n");
401    return C;
[a7ec94]402}
403
404static CanonicalForm
405gcd_poly_0( const CanonicalForm & f, const CanonicalForm & g )
406{
407    CanonicalForm pi, pi1;
[df497a]408    CanonicalForm C, Ci, Ci1, Hi, bi, pi2;
[a7ec94]409    int delta = degree( f ) - degree( g );
410
411    if ( delta >= 0 )
412    {
413        pi = f; pi1 = g;
414    }
415    else
416    {
417        pi = g; pi1 = f; delta = -delta;
418    }
[9bab9f]419    Ci = content( pi ); Ci1 = content( pi1 );
420    pi1 = pi1 / Ci1; pi = pi / Ci;
[df497a]421    C = gcd( Ci, Ci1 );
[034eec]422    if ( pi.isUnivariate() && pi1.isUnivariate() )
423    {
424#ifdef HAVE_NTL
[a7ec94]425        if ( isOn(SW_USE_NTL_GCD_0) && isPurePoly(pi) && isPurePoly(pi1) )
426            return gcd_univar_ntl0(pi, pi1 ) * C;
[df497a]427#endif
[a7ec94]428        return gcd_poly_univar0( pi, pi1, true ) * C;
[edb4893]429    }
[034eec]430    else if ( gcd_test_one( pi1, pi, true ) )
431      return C;
[a7ec94]432    Variable v = f.mvar();
[9bab9f]433    Hi = power( LC( pi1, v ), delta );
434    if ( (delta+1) % 2 )
[150dc8]435        bi = 1;
[9bab9f]436    else
[150dc8]437        bi = -1;
[6f62c3]438    while ( degree( pi1, v ) > 0 )
439    {
[150dc8]440        pi2 = psr( pi, pi1, v );
441        pi2 = pi2 / bi;
442        pi = pi1; pi1 = pi2;
[6f62c3]443        if ( degree( pi1, v ) > 0 )
444        {
[150dc8]445            delta = degree( pi, v ) - degree( pi1, v );
446            if ( (delta+1) % 2 )
447                bi = LC( pi, v ) * power( Hi, delta );
448            else
449                bi = -LC( pi, v ) * power( Hi, delta );
450            Hi = power( LC( pi1, v ), delta ) / power( Hi, delta-1 );
451        }
[9bab9f]452    }
453    if ( degree( pi1, v ) == 0 )
[150dc8]454        return C;
[df497a]455    else
[150dc8]456        return C * pp( pi );
[9bab9f]457}
458
[b809a8]459//{{{ CanonicalForm gcd_poly ( const CanonicalForm & f, const CanonicalForm & g )
[dd3e561]460//{{{ docu
461//
462// gcd_poly() - calculate polynomial gcd.
463//
464// This is the dispatcher for polynomial gcd calculation.  We call either
465// ezgcd(), sparsemod() or gcd_poly1() in dependecy on the current
466// characteristic and settings of SW_USE_EZGCD and SW_USE_SPARSEMOD, resp.
467//
468// Used by gcd() and gcd_poly_univar0().
469//
470//}}}
[0b6919]471#if 0
[bfc606]472int si_factor_reminder=1;
[0b6919]473#endif
[b809a8]474CanonicalForm gcd_poly ( const CanonicalForm & f, const CanonicalForm & g )
[f63dbca]475{
[110718]476  CanonicalForm fc, gc, d1;
477  int mp, cc, p1, pe;
478  mp = f.level()+1;
[ed9927]479  bool fc_isUnivariate=f.isUnivariate();
480  bool gc_isUnivariate=g.isUnivariate();
481  bool fc_and_gc_Univariate=fc_isUnivariate && gc_isUnivariate;
[1e6de6]482#if 1
[c30347]483  if (( getCharacteristic() == 0 )
484  && (f.level() >4)
485  && (g.level() >4)
486  && isOn( SW_USE_CHINREM_GCD)
[ed9927]487  && (!fc_and_gc_Univariate)
[c30347]488  && (isPurePoly_m(f))
489  && (isPurePoly_m(g))
490  )
491  {
492      return chinrem_gcd( f, g );
493  }
494#endif
[ed9927]495  cf_prepgcd( f, g, cc, p1, pe);
496  if ( cc != 0 )
[110718]497  {
[ed9927]498    if ( cc > 0 )
[abfc3b]499    {
[ed9927]500      fc = replacevar( f, Variable(cc), Variable(mp) );
501      gc = g;
[e074407]502    }
[ed9927]503    else
[110718]504    {
[ed9927]505      fc = replacevar( g, Variable(-cc), Variable(mp) );
506      gc = f;
[110718]507    }
[ed9927]508    return cf_content( fc, gc );
509  }
510// now each appearing variable is in f and g
511  fc = f;
512  gc = g;
513  if( gcd_avoid_mtaildegree ( fc, gc, d1 ) )
514      return d1;
515  if ( getCharacteristic() != 0 )
516  {
[598ff8b]517    if (isOn(SW_USE_fieldGCD)
518    && (!fc_and_gc_Univariate)
519    && (getCharacteristic() >100))
520    {
[ad8e1b]521      return fieldGCD(f,g);
[598ff8b]522    }
523    else if (isOn( SW_USE_EZGCD_P ) && (!fc_and_gc_Univariate))
[49f1f45]524    {
[ed9927]525      if ( pe == 1 )
526        fc = fin_ezgcd( fc, gc );
527      else if ( pe > 0 )// no variable at position 1
[49f1f45]528      {
[ed9927]529        fc = replacevar( fc, Variable(pe), Variable(1) );
530        gc = replacevar( gc, Variable(pe), Variable(1) );
531        fc = replacevar( fin_ezgcd( fc, gc ), Variable(1), Variable(pe) );
[49f1f45]532      }
533      else
534      {
[ed9927]535        pe = -pe;
536        fc = swapvar( fc, Variable(pe), Variable(1) );
537        gc = swapvar( gc, Variable(pe), Variable(1) );
538        fc = swapvar( fin_ezgcd( fc, gc ), Variable(1), Variable(pe) );
[49f1f45]539      }
[c30347]540    }
[ed9927]541    else if (isOn(SW_USE_GCD_P))
542    {
543      fc=newGCD(fc,gc);
544    }
545    else if ( p1 == fc.level() )
546      fc = gcd_poly_p( fc, gc );
547    else
548    {
549      fc = replacevar( fc, Variable(p1), Variable(mp) );
550      gc = replacevar( gc, Variable(p1), Variable(mp) );
551      fc = replacevar( gcd_poly_p( fc, gc ), Variable(mp), Variable(p1) );
552    }
[110718]553  }
[c30347]554  else if (!fc_and_gc_Univariate)
[110718]555  {
[c30347]556    if (
557    isOn(SW_USE_CHINREM_GCD)
[ed9927]558    && (gc.level() >5)
559    && (fc.level() >5)
560    && (isPurePoly_m(fc)) && (isPurePoly_m(gc))
[c30347]561    )
562    {
[ed9927]563    #if 0
564      if ( p1 == fc.level() )
565        fc = chinrem_gcd( fc, gc );
566      else
567      {
568        fc = replacevar( fc, Variable(p1), Variable(mp) );
569        gc = replacevar( gc, Variable(p1), Variable(mp) );
570        fc = replacevar( chinrem_gcd( fc, gc ), Variable(mp), Variable(p1) );
571      }
572    #else
573      fc = chinrem_gcd( fc, gc);
574    #endif
[c30347]575    }
[110718]576    if ( isOn( SW_USE_EZGCD ) )
577    {
[ed9927]578      if ( pe == 1 )
579        fc = ezgcd( fc, gc );
580      else if ( pe > 0 )// no variable at position 1
581      {
582        fc = replacevar( fc, Variable(pe), Variable(1) );
583        gc = replacevar( gc, Variable(pe), Variable(1) );
584        fc = replacevar( ezgcd( fc, gc ), Variable(1), Variable(pe) );
585      }
586      else
587      {
588        pe = -pe;
589        fc = swapvar( fc, Variable(pe), Variable(1) );
590        gc = swapvar( gc, Variable(pe), Variable(1) );
591        fc = swapvar( ezgcd( fc, gc ), Variable(1), Variable(pe) );
592      }
[1b73cc0]593    }
[110718]594    else if (
595    isOn(SW_USE_CHINREM_GCD)
[ed9927]596    && (isPurePoly_m(fc)) && (isPurePoly_m(gc))
[110718]597    )
[de1a82]598    {
[ed9927]599    #if 0
600      if ( p1 == fc.level() )
601        fc = chinrem_gcd( fc, gc );
602      else
603      {
604        fc = replacevar( fc, Variable(p1), Variable(mp) );
605        gc = replacevar( gc, Variable(p1), Variable(mp) );
606        fc = replacevar( chinrem_gcd( fc, gc ), Variable(mp), Variable(p1) );
607      }
608    #else
609      fc = chinrem_gcd( fc, gc);
610    #endif
[f63dbca]611    }
[c30347]612    else
613    {
[ed9927]614       fc = gcd_poly_0( fc, gc );
[c30347]615    }
[110718]616  }
617  else
618  {
619    fc = gcd_poly_0( fc, gc );
620  }
621  if ( d1.degree() > 0 )
622    fc *= d1;
623  return fc;
[f63dbca]624}
[dd3e561]625//}}}
[93b061]626
[dd3e561]627//{{{ static CanonicalForm cf_content ( const CanonicalForm & f, const CanonicalForm & g )
628//{{{ docu
629//
630// cf_content() - return gcd(g, content(f)).
631//
632// content(f) is calculated with respect to f's main variable.
633//
634// Used by gcd(), content(), content( CF, Variable ).
635//
636//}}}
[9bab9f]637static CanonicalForm
638cf_content ( const CanonicalForm & f, const CanonicalForm & g )
639{
[6f62c3]640    if ( f.inPolyDomain() || ( f.inExtension() && ! getReduce( f.mvar() ) ) )
641    {
[150dc8]642        CFIterator i = f;
643        CanonicalForm result = g;
[6f62c3]644        while ( i.hasTerms() && ! result.isOne() )
645        {
[a7ec94]646            result = gcd( i.coeff(), result );
[150dc8]647            i++;
648        }
649        return result;
[9bab9f]650    }
651    else
[a7ec94]652        return abs( f );
[9bab9f]653}
[dd3e561]654//}}}
[9bab9f]655
[4ea0ab]656//{{{ CanonicalForm content ( const CanonicalForm & f )
657//{{{ docu
658//
659// content() - return content(f) with respect to main variable.
660//
[dd3e561]661// Normalizes result.
662//
[4ea0ab]663//}}}
[9bab9f]664CanonicalForm
665content ( const CanonicalForm & f )
666{
[6f62c3]667    if ( f.inPolyDomain() || ( f.inExtension() && ! getReduce( f.mvar() ) ) )
668    {
[a7ec94]669        CFIterator i = f;
670        CanonicalForm result = abs( i.coeff() );
671        i++;
[6f62c3]672        while ( i.hasTerms() && ! result.isOne() )
673        {
[a7ec94]674            result = gcd( i.coeff(), result );
675            i++;
676        }
677        return result;
678    }
679    else
680        return abs( f );
[9bab9f]681}
[4ea0ab]682//}}}
[9bab9f]683
[dd3e561]684//{{{ CanonicalForm content ( const CanonicalForm & f, const Variable & x )
685//{{{ docu
686//
687// content() - return content(f) with respect to x.
688//
689// x should be a polynomial variable.
690//
691//}}}
[9bab9f]692CanonicalForm
693content ( const CanonicalForm & f, const Variable & x )
694{
[dd3e561]695    ASSERT( x.level() > 0, "cannot calculate content with respect to algebraic variable" );
696    Variable y = f.mvar();
697
698    if ( y == x )
[150dc8]699        return cf_content( f, 0 );
[dd3e561]700    else  if ( y < x )
[150dc8]701        return f;
[9bab9f]702    else
[150dc8]703        return swapvar( content( swapvar( f, y, x ), y ), y, x );
[9bab9f]704}
[dd3e561]705//}}}
[9bab9f]706
[dd3e561]707//{{{ CanonicalForm vcontent ( const CanonicalForm & f, const Variable & x )
708//{{{ docu
709//
710// vcontent() - return content of f with repect to variables >= x.
711//
712// The content is recursively calculated over all coefficients in
713// f having level less than x.  x should be a polynomial
714// variable.
715//
716//}}}
[9bab9f]717CanonicalForm
718vcontent ( const CanonicalForm & f, const Variable & x )
719{
[dd3e561]720    ASSERT( x.level() > 0, "cannot calculate vcontent with respect to algebraic variable" );
721
[9bab9f]722    if ( f.mvar() <= x )
[150dc8]723        return content( f, x );
[9bab9f]724    else {
[150dc8]725        CFIterator i;
726        CanonicalForm d = 0;
727        for ( i = f; i.hasTerms() && ! d.isOne(); i++ )
728            d = gcd( d, vcontent( i.coeff(), x ) );
729        return d;
[9bab9f]730    }
731}
[dd3e561]732//}}}
[9bab9f]733
[4ea0ab]734//{{{ CanonicalForm pp ( const CanonicalForm & f )
735//{{{ docu
736//
737// pp() - return primitive part of f.
738//
[dd3e561]739// Returns zero if f equals zero, otherwise f / content(f).
740//
[4ea0ab]741//}}}
[9bab9f]742CanonicalForm
743pp ( const CanonicalForm & f )
744{
745    if ( f.isZero() )
[150dc8]746        return f;
[9bab9f]747    else
[150dc8]748        return f / content( f );
[9bab9f]749}
[4ea0ab]750//}}}
[9bab9f]751
[ff6222]752CanonicalForm
[9bab9f]753gcd ( const CanonicalForm & f, const CanonicalForm & g )
754{
[a7ec94]755    bool b = f.isZero();
756    if ( b || g.isZero() )
757    {
758        if ( b )
759            return abs( g );
[abfc3b]760        else
[a7ec94]761            return abs( f );
762    }
763    if ( f.inPolyDomain() || g.inPolyDomain() )
764    {
765        if ( f.mvar() != g.mvar() )
766        {
767            if ( f.mvar() > g.mvar() )
768                return cf_content( f, g );
769            else
770                return cf_content( g, f );
771        }
[bb82f0]772        if (isOn(SW_USE_QGCD))
773        {
774          Variable m;
775          if ((hasFirstAlgVar(f,m) || hasFirstAlgVar(g,m))
776          //&& f.isUnivariate()
777          //&& g.isUnivariate()
778          && (getCharacteristic() == 0)
779          )
[fc31bce]780          {
[ad8e1b]781            //if ((f.level()==g.level()) && f.isUnivariate() && g.isUnivariate())
782            //  return univarQGCD(f,g);
783            //else
[fc31bce]784              return QGCD(f,g);
785          }
[bb82f0]786        }
787           
[150dc8]788        if ( f.inExtension() && getReduce( f.mvar() ) )
[bb82f0]789            return CanonicalForm(1);
[a7ec94]790        else
791        {
[ebc602]792            if ( fdivides( f, g ) )
[a7ec94]793                return abs( f );
[ebc602]794            else  if ( fdivides( g, f ) )
[a7ec94]795                return abs( g );
796            if ( !( getCharacteristic() == 0 && isOn( SW_RATIONAL ) ) )
797            {
798                CanonicalForm d;
[5944b4]799#if 1
[a7ec94]800                do{ d = gcd_poly( f, g ); }
[ebc602]801                while ((!fdivides(d,f)) || (!fdivides(d,g)));
[5944b4]802#else
803                while(1)
[f4b180]804                {
805                  d = gcd_poly( f, g );
[5944b4]806                  if ((fdivides(d,f)) && (fdivides(d,g))) break;
807                  printf("g"); fflush(stdout);
808                }
809#endif
[a7ec94]810                return abs( d );
811            }
812            else
813            {
[150dc8]814                CanonicalForm cdF = bCommonDen( f );
815                CanonicalForm cdG = bCommonDen( g );
816                Off( SW_RATIONAL );
817                CanonicalForm l = lcm( cdF, cdG );
818                On( SW_RATIONAL );
819                CanonicalForm F = f * l, G = g * l;
820                Off( SW_RATIONAL );
[a7ec94]821                do { l = gcd_poly( F, G ); }
[ebc602]822                while ((!fdivides(l,F)) || (!fdivides(l,G)));
[150dc8]823                On( SW_RATIONAL );
[a7ec94]824                return abs( l );
[150dc8]825            }
826        }
[a7ec94]827    }
828    if ( f.inBaseDomain() && g.inBaseDomain() )
829        return bgcd( f, g );
[9bab9f]830    else
[a7ec94]831        return 1;
[9bab9f]832}
833
[dd3e561]834//{{{ CanonicalForm lcm ( const CanonicalForm & f, const CanonicalForm & g )
835//{{{ docu
836//
837// lcm() - return least common multiple of f and g.
838//
839// The lcm is calculated using the formula lcm(f, g) = f * g / gcd(f, g).
840//
841// Returns zero if one of f or g equals zero.
842//
843//}}}
[9bab9f]844CanonicalForm
845lcm ( const CanonicalForm & f, const CanonicalForm & g )
846{
[dd3e561]847    if ( f.isZero() || g.isZero() )
[a7ec94]848        return 0;
[dd3e561]849    else
[150dc8]850        return ( f / gcd( f, g ) ) * g;
[9bab9f]851}
[dd3e561]852//}}}
[a7ec94]853
854#ifdef HAVE_NTL
855
856static CanonicalForm
857gcd_univar_ntl0( const CanonicalForm & F, const CanonicalForm & G )
858{
859    ZZX F1=convertFacCF2NTLZZX(F);
860    ZZX G1=convertFacCF2NTLZZX(G);
861    ZZX R=GCD(F1,G1);
862    return convertNTLZZX2CF(R,F.mvar());
863}
864
865static CanonicalForm
866gcd_univar_ntlp( const CanonicalForm & F, const CanonicalForm & G )
867{
[c6eecb]868  if (fac_NTL_char!=getCharacteristic())
869  {
870    fac_NTL_char=getCharacteristic();
871    #ifdef NTL_ZZ
872    ZZ r;
873    r=getCharacteristic();
874    ZZ_pContext ccc(r);
875    #else
[a7ec94]876    zz_pContext ccc(getCharacteristic());
[c6eecb]877    #endif
[a7ec94]878    ccc.restore();
[c6eecb]879    #ifdef NTL_ZZ
880    ZZ_p::init(r);
881    #else
[a7ec94]882    zz_p::init(getCharacteristic());
[c6eecb]883    #endif
884  }
885  #ifdef NTL_ZZ
886  ZZ_pX F1=convertFacCF2NTLZZpX(F);
887  ZZ_pX G1=convertFacCF2NTLZZpX(G);
888  ZZ_pX R=GCD(F1,G1);
889  return  convertNTLZZpX2CF(R,F.mvar());
890  #else
891  zz_pX F1=convertFacCF2NTLzzpX(F);
892  zz_pX G1=convertFacCF2NTLzzpX(G);
893  zz_pX R=GCD(F1,G1);
894  return  convertNTLzzpX2CF(R,F.mvar());
895  #endif
[a7ec94]896}
897
898#endif
899
900static bool
901gcd_avoid_mtaildegree ( CanonicalForm & f1, CanonicalForm & g1, CanonicalForm & d1 )
902{
903    bool rdy = true;
904    int df = f1.taildegree();
905    int dg = g1.taildegree();
906
907    d1 = d1.genOne();
908    if ( dg == 0 )
909    {
910        if ( df == 0 )
911            return false;
912        else
913        {
914            if ( f1.degree() == df )
915                d1 = cf_content( g1, LC( f1 ) );
916            else
917            {
918                f1 /= power( f1.mvar(), df );
919                rdy = false;
920            }
921        }
922    }
923    else
924    {
925        if ( df == 0)
926        {
927            if ( g1.degree() == dg )
928                d1 = cf_content( f1, LC( g1 ) );
929            else
930            {
931                g1 /= power( g1.mvar(), dg );
932                rdy = false;
933            }
934        }
935        else
936        {
937            if ( df > dg )
938                d1 = power( f1.mvar(), dg );
939            else
940                d1 = power( f1.mvar(), df );
941            if ( f1.degree() == df )
942            {
943                if (g1.degree() == dg)
944                    d1 *= gcd( LC( f1 ), LC( g1 ) );
945                else
946                {
947                    g1 /= power( g1.mvar(), dg);
948                    d1 *= cf_content( g1, LC( f1 ) );
949                }
950            }
951            else
952            {
953                f1 /= power( f1.mvar(), df );
954                if ( g1.degree() == dg )
955                    d1 *= cf_content( f1, LC( g1 ) );
956                else
957                {
958                    g1 /= power( g1.mvar(), dg );
959                    rdy = false;
960                }
961            }
962        }
963    }
964    return rdy;
965}
966
967/*
968*  compute positions p1 and pe of optimal variables:
969*    pe is used in "ezgcd" and
970*    p1 in "gcd_poly1"
971*/
972static
973void optvalues ( const int * df, const int * dg, const int n, int & p1, int &pe )
974{
975    int i, o1, oe;
976    if ( df[n] > dg[n] )
977    {
978        o1 = df[n]; oe = dg[n];
979    }
980    else
981    {
982        o1 = dg[n]; oe = df[n];
983    }
984    i = n-1;
985    while ( i > 0 )
986    {
987        if ( df[i] != 0 )
988        {
989            if ( df[i] > dg[i] )
990            {
991                if ( o1 > df[i]) { o1 = df[i]; p1 = i; }
992                if ( oe <= dg[i]) { oe = dg[i]; pe = i; }
993            }
994            else
995            {
996                if ( o1 > dg[i]) { o1 = dg[i]; p1 = i; }
997                if ( oe <= df[i]) { oe = df[i]; pe = i; }
998            }
999        }
1000        i--;
1001    }
1002}
1003
1004/*
1005*  make some changes of variables, see optvalues
1006*/
1007static void
1008cf_prepgcd( const CanonicalForm & f, const CanonicalForm & g, int & cc, int & p1, int &pe )
1009{
1010    int i, k, n;
1011    n = f.level();
1012    cc = 0;
1013    p1 = pe = n;
1014    if ( n == 1 )
1015        return;
1016    int * degsf = new int[n+1];
1017    int * degsg = new int[n+1];
1018    for ( i = n; i > 0; i-- )
1019    {
1020        degsf[i] = degsg[i] = 0;
1021    }
1022    degsf = degrees( f, degsf );
1023    degsg = degrees( g, degsg );
1024
1025    k = 0;
1026    for ( i = n-1; i > 0; i-- )
1027    {
[f4b180]1028        if ( degsf[i] == 0 )
[a7ec94]1029        {
1030            if ( degsg[i] != 0 )
1031            {
1032                cc = -i;
1033                break;
1034            }
1035        }
1036        else
1037        {
1038            if ( degsg[i] == 0 )
1039            {
1040                cc = i;
1041                break;
1042            }
1043            else k++;
1044        }
1045    }
1046
1047    if ( ( cc == 0 ) && ( k != 0 ) )
1048        optvalues( degsf, degsg, n, p1, pe );
1049    if ( ( pe != 1 ) && ( degsf[1] != 0 ) )
1050        pe = -pe;
[f4b180]1051
[a7ec94]1052    delete [] degsf;
1053    delete [] degsg;
1054}
[6f62c3]1055
1056
1057static CanonicalForm
1058balance_p ( const CanonicalForm & f, const CanonicalForm & q )
1059{
1060    Variable x = f.mvar();
1061    CanonicalForm result = 0, qh = q / 2;
1062    CanonicalForm c;
1063    CFIterator i;
1064    for ( i = f; i.hasTerms(); i++ )
1065    {
1066        c = i.coeff();
1067        if ( c.inCoeffDomain())
1068        {
1069          if ( c > qh )
1070            result += power( x, i.exp() ) * (c - q);
1071          else
1072            result += power( x, i.exp() ) * c;
1073        }
[f4b180]1074        else
[6f62c3]1075          result += power( x, i.exp() ) * balance_p(c,q);
1076    }
1077    return result;
1078}
1079
1080CanonicalForm chinrem_gcd ( const CanonicalForm & FF, const CanonicalForm & GG )
1081{
1082  CanonicalForm f, g, cg, cl, q, Dp, newD, D, newq;
[c992ec1]1083  int p, i, dp_deg, d_deg;;
[6f62c3]1084
1085  CanonicalForm cd = bCommonDen( FF );
1086  f=cd*FF;
1087  f /=vcontent(f,Variable(1));
[08a6ebb]1088  //cd = bCommonDen( f ); f *=cd;
1089  //f /=vcontent(f,Variable(1));
[6f62c3]1090
1091  cd = bCommonDen( GG );
1092  g=cd*GG;
1093  g /=vcontent(g,Variable(1));
[08a6ebb]1094  //cd = bCommonDen( g ); g *=cd;
1095  //g /=vcontent(g,Variable(1));
[6f62c3]1096
1097  q = 0;
1098  i = cf_getNumBigPrimes() - 1;
1099  cl =  f.lc()* g.lc();
1100
1101  while ( true )
1102  {
1103    p = cf_getBigPrime( i );
1104    i--;
1105    while ( i >= 0 && mod( cl, p ) == 0 )
1106    {
1107      p = cf_getBigPrime( i );
1108      i--;
1109    }
[c30347]1110    //printf("try p=%d\n",p);
[6f62c3]1111    setCharacteristic( p );
[c30347]1112    Dp = gcd_poly( mapinto( f ), mapinto( g ) );
[08a6ebb]1113    Dp /=Dp.lc();
[6f62c3]1114    setCharacteristic( 0 );
1115    dp_deg=totaldegree(Dp);
1116    if ( dp_deg == 0 )
[c30347]1117    {
1118      //printf(" -> 1\n");
[6f62c3]1119      return CanonicalForm(1);
[c30347]1120    }
[6f62c3]1121    if ( q.isZero() )
1122    {
1123      D = mapinto( Dp );
1124      d_deg=dp_deg;
1125      q = p;
1126    }
1127    else
1128    {
1129      if ( dp_deg == d_deg )
1130      {
1131        chineseRemainder( D, q, mapinto( Dp ), p, newD, newq );
1132        q = newq;
1133        D = newD;
1134      }
[f4b180]1135      else if ( dp_deg < d_deg )
[6f62c3]1136      {
[c30347]1137        //printf(" were all bad, try more\n");
[6f62c3]1138        // all previous p's are bad primes
1139        q = p;
1140        D = mapinto( Dp );
1141        d_deg=dp_deg;
1142      }
[c30347]1143      else
1144      {
1145        //printf(" was bad, try more\n");
1146      }
[f4b180]1147      //else dp_deg > d_deg: bad prime
[6f62c3]1148    }
[08a6ebb]1149    if ( i >= 0 )
[6f62c3]1150    {
[c992ec1]1151      CanonicalForm Dn= Farey(D,q);
1152      int is_rat=isOn(SW_RATIONAL);
1153      On(SW_RATIONAL);
1154      CanonicalForm cd = bCommonDen( Dn ); // we need On(SW_RATIONAL)
1155      if (!is_rat) Off(SW_RATIONAL);
1156      Dn *=cd;
1157      //Dn /=vcontent(Dn,Variable(1));
1158      if ( fdivides( Dn, f ) && fdivides( Dn, g ) )
[6f62c3]1159      {
[c30347]1160        //printf(" -> success\n");
[c992ec1]1161        return Dn;
[6f62c3]1162      }
[c992ec1]1163      //else: try more primes
[6f62c3]1164    }
1165    else
[c992ec1]1166    { // try other method
[c30347]1167      //printf("try other gcd\n");
[6f62c3]1168      Off(SW_USE_CHINREM_GCD);
1169      D=gcd_poly( f, g );
1170      On(SW_USE_CHINREM_GCD);
1171      return D;
1172    }
1173  }
1174}
[bb82f0]1175#include "algext.cc"
Note: See TracBrowser for help on using the repository browser.