source: git/factory/cf_gcd.cc @ c4f4fd

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