source: git/factory/cf_gcd.cc @ c992ec1

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