source: git/factory/fac_ezgcd.cc @ 9f7665

spielwiese
Last change on this file since 9f7665 was 9f7665, checked in by Oleksandr Motsak <motsak@…>, 10 years ago
Removed HAVE_CONFIG guards fix: fixed the inclusion of configure-generated *config.h's
  • Property mode set to 100644
File size: 17.9 KB
Line 
1/*****************************************************************************\
2 * Computer Algebra System SINGULAR
3\*****************************************************************************/
4/** @file fac_ezgcd.cc
5 *
6 * This file implements the GCD of two multivariate polynomials over Q using
7 * EZ-GCD as described in "Algorithms for Computer Algebra" by Geddes, Czapor,
8 * Labahnn
9 *
10 * @author Martin Lee
11 *
12 **/
13/*****************************************************************************/
14
15
16#include "config.h"
17
18
19#include "timing.h"
20#include "cf_assert.h"
21#include "debug.h"
22
23#include "cf_defs.h"
24#include "canonicalform.h"
25#include "fac_util.h" // HEADER for this file
26#include "cf_algorithm.h"
27#include "cf_reval.h"
28#include "cf_random.h"
29#include "cf_primes.h"
30#include "templates/ftmpl_functions.h"
31#include "cf_map.h"
32#include "facHensel.h"
33
34#ifdef HAVE_NTL
35
36TIMING_DEFINE_PRINT(ez_eval)
37TIMING_DEFINE_PRINT(ez_compress)
38TIMING_DEFINE_PRINT(ez_hensel_lift)
39TIMING_DEFINE_PRINT(ez_content)
40TIMING_DEFINE_PRINT(ez_termination)
41
42static
43int compress4EZGCD (const CanonicalForm& F, const CanonicalForm& G, CFMap & M,
44                    CFMap & N, int& both_non_zero)
45{
46  int n= tmax (F.level(), G.level());
47  int * degsf= new int [n + 1];
48  int * degsg= new int [n + 1];
49
50  for (int i = 0; i <= n; i++)
51    degsf[i]= degsg[i]= 0;
52
53  degsf= degrees (F, degsf);
54  degsg= degrees (G, degsg);
55
56  both_non_zero= 0;
57  int f_zero= 0;
58  int g_zero= 0;
59
60  for (int i= 1; i <= n; i++)
61  {
62    if (degsf[i] != 0 && degsg[i] != 0)
63    {
64      both_non_zero++;
65      continue;
66    }
67    if (degsf[i] == 0 && degsg[i] != 0 && i <= G.level())
68    {
69      f_zero++;
70      continue;
71    }
72    if (degsg[i] == 0 && degsf[i] && i <= F.level())
73    {
74      g_zero++;
75      continue;
76    }
77  }
78
79  if (both_non_zero == 0)
80  {
81    delete [] degsf;
82    delete [] degsg;
83    return 0;
84  }
85
86  // map Variables which do not occur in both polynomials to higher levels
87  int k= 1;
88  int l= 1;
89  for (int i= 1; i <= n; i++)
90  {
91    if (degsf[i] != 0 && degsg[i] == 0 && i <= F.level())
92    {
93      if (k + both_non_zero != i)
94      {
95        M.newpair (Variable (i), Variable (k + both_non_zero));
96        N.newpair (Variable (k + both_non_zero), Variable (i));
97      }
98      k++;
99    }
100    if (degsf[i] == 0 && degsg[i] != 0 && i <= G.level())
101    {
102      if (l + g_zero + both_non_zero != i)
103      {
104        M.newpair (Variable (i), Variable (l + g_zero + both_non_zero));
105        N.newpair (Variable (l + g_zero + both_non_zero), Variable (i));
106      }
107      l++;
108    }
109  }
110
111  // sort Variables x_{i} in decreasing order of
112  // min(deg_{x_{i}}(f),deg_{x_{i}}(g))
113  int m= tmin (F.level(), G.level());
114  int max_min_deg;
115  k= both_non_zero;
116  l= 0;
117  int i= 1;
118  while (k > 0)
119  {
120    max_min_deg= tmin (degsf[i], degsg[i]);
121    while (max_min_deg == 0)
122    {
123      i++;
124      max_min_deg= tmin (degsf[i], degsg[i]);
125    }
126    for (int j= i + 1; j <= m; j++)
127    {
128      if ((tmin (degsf[j],degsg[j]) < max_min_deg) &&
129          (tmin (degsf[j], degsg[j]) != 0))
130      {
131        max_min_deg= tmin (degsf[j], degsg[j]);
132        l= j;
133      }
134    }
135
136    if (l != 0)
137    {
138      if (l != k)
139      {
140        M.newpair (Variable (l), Variable(k));
141        N.newpair (Variable (k), Variable(l));
142        degsf[l]= 0;
143        degsg[l]= 0;
144        l= 0;
145      }
146      else
147      {
148        degsf[l]= 0;
149        degsg[l]= 0;
150        l= 0;
151      }
152    }
153    else if (l == 0)
154    {
155      if (i != k)
156      {
157        M.newpair (Variable (i), Variable (k));
158        N.newpair (Variable (k), Variable (i));
159        degsf[i]= 0;
160        degsg[i]= 0;
161      }
162      else
163      {
164        degsf[i]= 0;
165        degsg[i]= 0;
166      }
167      i++;
168    }
169    k--;
170  }
171
172  delete [] degsf;
173  delete [] degsg;
174
175  return both_non_zero;
176}
177
178static inline
179CanonicalForm myShift2Zero (const CanonicalForm& F, CFList& Feval,
180                            const CFList& evaluation)
181{
182  CanonicalForm A= F;
183  int k= 2;
184  for (CFListIterator i= evaluation; i.hasItem(); i++, k++)
185    A= A (Variable (k) + i.getItem(), k);
186
187  CanonicalForm buf= A;
188  Feval= CFList();
189  Feval.append (buf);
190  for (k= evaluation.length() + 1; k > 2; k--)
191  {
192    buf= mod (buf, Variable (k));
193    Feval.insert (buf);
194  }
195  return A;
196}
197
198static inline
199CanonicalForm myReverseShift (const CanonicalForm& F, const CFList& evaluation)
200{
201  int l= evaluation.length() + 1;
202  CanonicalForm result= F;
203  CFListIterator j= evaluation;
204  for (int i= 2; i < l + 1; i++, j++)
205  {
206    if (F.level() < i)
207      continue;
208    result= result (Variable (i) - j.getItem(), i);
209  }
210  return result;
211}
212
213static inline
214Evaluation optimize4Lift (const CanonicalForm& F, CFMap & M,
215                    CFMap & N, const Evaluation& A)
216{
217  int n= F.level();
218  int * degsf= new int [n + 1];
219
220  for (int i = 0; i <= n; i++)
221    degsf[i]= 0;
222
223  degsf= degrees (F, degsf);
224
225  Evaluation result= Evaluation (A.min(), A.max());
226  ASSERT (A.min() == 2, "expected A.min() == 2");
227  int max_deg;
228  int k= n;
229  int l= 1;
230  int i= 2;
231  int pos= 2;
232  while (k > 1)
233  {
234    max_deg= degsf [i];
235    while (max_deg == 0)
236    {
237      i++;
238      max_deg= degsf [i];
239    }
240    l= i;
241    for (int j= i + 1; j <=  n; j++)
242    {
243      if (degsf[j] > max_deg)
244      {
245        max_deg= degsf[j];
246        l= j;
247      }
248    }
249
250    if (l <= n)
251    {
252      if (l != pos)
253      {
254        result.setValue (pos, A [l]);
255        M.newpair (Variable (l), Variable (pos));
256        N.newpair (Variable (pos), Variable (l));
257        degsf[l]= 0;
258        l= 2;
259        if (k == 2 && n == 3)
260        {
261          result.setValue (l, A [pos]);
262          M.newpair (Variable (pos), Variable (l));
263          N.newpair (Variable (l), Variable (pos));
264          degsf[pos]= 0;
265        }
266      }
267      else
268      {
269        result.setValue (l, A [l]);
270        degsf [l]= 0;
271      }
272    }
273    pos++;
274    k--;
275    l= 2;
276  }
277
278  delete [] degsf;
279
280  return result;
281}
282
283static inline
284int Hensel (const CanonicalForm & UU, CFArray & G, const Evaluation & AA,
285            const CFArray& LeadCoeffs )
286{
287  CFList factors;
288  factors.append (G[1]);
289  factors.append (G[2]);
290
291  CFMap NN, MM;
292  Evaluation A= optimize4Lift (UU, MM, NN, AA);
293
294  CanonicalForm U= MM (UU);
295  CFArray LCs= CFArray (1,2);
296  LCs [1]= MM (LeadCoeffs [1]);
297  LCs [2]= MM (LeadCoeffs [2]);
298
299  CFList evaluation;
300  long termEstimate= size (U);
301  for (int i= A.min(); i <= A.max(); i++)
302  {
303    if (!A[i].isZero())
304    {
305      termEstimate *= degree (U,i)*2;
306      termEstimate /= 3;
307    }
308    evaluation.append (A [i]);
309  }
310  if (termEstimate/getNumVars(U) > 500)
311    return -1;
312  CFList UEval;
313  CanonicalForm shiftedU= myShift2Zero (U, UEval, evaluation);
314
315  if (size (shiftedU)/getNumVars (U) > 500)
316    return -1;
317
318  CFArray shiftedLCs= CFArray (2);
319  CFList shiftedLCsEval1, shiftedLCsEval2;
320  shiftedLCs[0]= myShift2Zero (LCs[1], shiftedLCsEval1, evaluation);
321  shiftedLCs[1]= myShift2Zero (LCs[2], shiftedLCsEval2, evaluation);
322  factors.insert (1);
323  int liftBound= degree (UEval.getLast(), 2) + 1;
324  CFArray Pi;
325  CFMatrix M= CFMatrix (liftBound, factors.length() - 1);
326  CFList diophant;
327  CFArray lcs= CFArray (2);
328  lcs [0]= shiftedLCsEval1.getFirst();
329  lcs [1]= shiftedLCsEval2.getFirst();
330  nonMonicHenselLift12 (UEval.getFirst(), factors, liftBound, Pi, diophant, M,
331                        lcs, false);
332
333  for (CFListIterator i= factors; i.hasItem(); i++)
334  {
335    if (!fdivides (i.getItem(), UEval.getFirst()))
336      return 0;
337  }
338
339  int * liftBounds;
340  bool noOneToOne= false;
341  if (U.level() > 2)
342  {
343    liftBounds= new int [U.level() - 1]; /* index: 0.. U.level()-2 */
344    liftBounds[0]= liftBound;
345    for (int i= 1; i < U.level() - 1; i++)
346      liftBounds[i]= degree (shiftedU, Variable (i + 2)) + 1;
347    factors= nonMonicHenselLift2 (UEval, factors, liftBounds, U.level() - 1,
348                                  false, shiftedLCsEval1, shiftedLCsEval2, Pi,
349                                  diophant, noOneToOne);
350    delete [] liftBounds;
351    if (noOneToOne)
352      return 0;
353  }
354  G[1]= factors.getFirst();
355  G[2]= factors.getLast();
356  G[1]= myReverseShift (G[1], evaluation);
357  G[2]= myReverseShift (G[2], evaluation);
358  G[1]= NN (G[1]);
359  G[2]= NN (G[2]);
360  return 1;
361}
362
363static
364bool findeval (const CanonicalForm & F, const CanonicalForm & G,
365               CanonicalForm & Fb, CanonicalForm & Gb, CanonicalForm & Db,
366               REvaluation & b, int delta, int degF, int degG, int maxeval,
367               int & count, int& k, int bound, int& l)
368{
369  if( count == 0 && delta != 0)
370  {
371    if( count++ > maxeval )
372      return false;
373  }
374  if (count > 0)
375  {
376    b.nextpoint(k);
377    if (k == 0)
378      k++;
379    l++;
380    if (l > bound)
381    {
382      l= 1;
383      k++;
384      if (k > tmax (F.level(), G.level()) - 1)
385        return false;
386      b.nextpoint (k);
387    }
388    if (count++ > maxeval)
389      return false;
390  }
391  while( true )
392  {
393    Fb = b( F );
394    if( degree( Fb, 1 ) == degF )
395    {
396      Gb = b( G );
397      if( degree( Gb, 1 ) == degG )
398      {
399        Db = gcd( Fb, Gb );
400        if( delta > 0 )
401        {
402          if( degree( Db, 1 ) <= delta )
403            return true;
404        }
405        else
406        {
407          k++;
408          return true;
409        }
410      }
411    }
412    if (k == 0)
413      k++;
414    b.nextpoint(k);
415    l++;
416    if (l > bound)
417    {
418      l= 1;
419      k++;
420      if (k > tmax (F.level(), G.level()) - 1)
421        return false;
422      b.nextpoint (k);
423    }
424    if( count++ > maxeval )
425      return false;
426  }
427}
428
429static CanonicalForm
430ezgcd ( const CanonicalForm & FF, const CanonicalForm & GG, REvaluation & b,
431        bool internal )
432{
433  bool isRat= isOn (SW_RATIONAL);
434
435  int maxNumVars= tmax (getNumVars (FF), getNumVars (GG));
436  int sizeF= size (FF);
437  int sizeG= size (GG);
438
439
440  if (!isRat)
441    On (SW_RATIONAL);
442  if (sizeF/maxNumVars > 500 && sizeG/maxNumVars > 500)
443  {
444    Off(SW_USE_EZGCD);
445    CanonicalForm result=gcd( FF, GG );
446    On(SW_USE_EZGCD);
447    if (!isRat)
448      Off (SW_RATIONAL);
449    result /= icontent (result);
450    DEBDECLEVEL( cerr, "ezgcd" );
451    return result;
452  }
453
454
455  CanonicalForm F, G, f, g, d, Fb, Gb, Db, Fbt, Gbt, Dbt, B0, B, D0, lcF, lcG,
456                lcD, cand, contcand, result;
457  CFArray DD( 1, 2 ), lcDD( 1, 2 );
458  int degF, degG, delta, t, count, maxeval;
459  REvaluation bt;
460  int gcdfound = 0;
461  Variable x = Variable(1);
462  count= 0;
463  maxeval= 200;
464  int o, l;
465  o= 0;
466  l= 1;
467
468  if (!isRat)
469    On (SW_RATIONAL);
470  F= FF*bCommonDen (FF);
471  G= GG*bCommonDen (GG);
472  if (!isRat)
473    Off (SW_RATIONAL);
474
475  TIMING_START (ez_compress)
476  CFMap M,N;
477  int smallestDegLev;
478  int best_level= compress4EZGCD (F, G, M, N, smallestDegLev);
479
480  if (best_level == 0)
481  {
482    DEBDECLEVEL( cerr, "ezgcd" );
483    return G.genOne();
484  }
485
486  F= M (F);
487  G= M (G);
488  TIMING_END_AND_PRINT (ez_compress, "time for compression in EZ: ")
489
490  DEBINCLEVEL( cerr, "ezgcd" );
491  DEBOUTLN( cerr, "FF = " << FF );
492  DEBOUTLN( cerr, "GG = " << GG );
493  TIMING_START (ez_content)
494  f = content( F, x ); g = content( G, x ); d = gcd( f, g );
495  DEBOUTLN( cerr, "f = " << f );
496  DEBOUTLN( cerr, "g = " << g );
497  F /= f; G /= g;
498  TIMING_END_AND_PRINT (ez_content, "time to extract content in EZ: ")
499  if ( F.isUnivariate() && G.isUnivariate() )
500  {
501    DEBDECLEVEL( cerr, "ezgcd" );
502    if(F.mvar()==G.mvar())
503      d*=gcd(F,G);
504    else
505      return N (d);
506    return N (d);
507  }
508  if ( F.isUnivariate())
509  {
510    g= content (G,G.mvar());
511    return N(d*gcd(F,g));
512  }
513  if ( G.isUnivariate())
514  {
515    f= content (F,F.mvar());
516    return N(d*gcd(G,f));
517  }
518
519  maxNumVars= tmax (getNumVars (F), getNumVars (G));
520  sizeF= size (F);
521  sizeG= size (G);
522
523  if (!isRat)
524    On (SW_RATIONAL);
525  if (sizeF/maxNumVars > 500 && sizeG/maxNumVars > 500)
526  {
527    Off(SW_USE_EZGCD);
528    result=gcd( F, G );
529    On(SW_USE_EZGCD);
530    if (!isRat)
531      Off (SW_RATIONAL);
532    result /= icontent (result);
533    DEBDECLEVEL( cerr, "ezgcd" );
534    return N (d*result);
535  }
536
537  int dummy= 0;
538  if ( gcd_test_one( F, G, false, dummy ) )
539  {
540    DEBDECLEVEL( cerr, "ezgcd" );
541    if (!isRat)
542      Off (SW_RATIONAL);
543    return N (d);
544  }
545  lcF = LC( F, x ); lcG = LC( G, x );
546  lcD = gcd( lcF, lcG );
547  delta = 0;
548  degF = degree( F, x ); degG = degree( G, x );
549  t = tmax( F.level(), G.level() );
550  if ( ! internal )
551    b = REvaluation( 2, t, IntRandom( 25 ) );
552  while ( ! gcdfound )
553  {
554    /// ---> A2
555    DEBOUTLN( cerr, "search for evaluation, delta = " << delta );
556    DEBOUTLN( cerr, "F = " << F );
557    DEBOUTLN( cerr, "G = " << G );
558    TIMING_START (ez_eval)
559    if (!findeval( F, G, Fb, Gb, Db, b, delta, degF, degG, maxeval, count,
560                   o, 25, l))
561    {
562      Off(SW_USE_EZGCD);
563      result=gcd( F, G );
564      On(SW_USE_EZGCD);
565      if (!isRat)
566        Off (SW_RATIONAL);
567      DEBDECLEVEL( cerr, "ezgcd" );
568      result /= icontent (result);
569      return N (d*result);
570    }
571    TIMING_END_AND_PRINT (ez_eval, "time to find eval point in EZ1: ")
572    DEBOUTLN( cerr, "found evaluation b = " << b );
573    DEBOUTLN( cerr, "F(b) = " << Fb );
574    DEBOUTLN( cerr, "G(b) = " << Gb );
575    DEBOUTLN( cerr, "D(b) = " << Db );
576    delta = degree( Db );
577    /// ---> A3
578    if (delta == degF)
579    {
580      if (degF <= degG  && fdivides (F, G))
581      {
582        DEBDECLEVEL( cerr, "ezgcd" );
583        if (!isRat)
584          Off (SW_RATIONAL);
585        return N (d*F);
586      }
587      else
588        delta--;
589    }
590    else if (delta == degG)
591    {
592      if (degG <= degF && fdivides( G, F ))
593      {
594        DEBDECLEVEL( cerr, "ezgcd" );
595        if (!isRat)
596          Off (SW_RATIONAL);
597        return N (d*G);
598      }
599      else
600        delta--;
601    }
602    if ( delta == 0 )
603    {
604      DEBDECLEVEL( cerr, "ezgcd" );
605      if (!isRat)
606        Off (SW_RATIONAL);
607      return N (d);
608    }
609    /// ---> A4
610    //deltaold = delta;
611    while ( 1 )
612    {
613      bt = b;
614      TIMING_START (ez_eval)
615      if (!findeval( F, G, Fbt, Gbt, Dbt, bt, delta, degF, degG, maxeval, count,
616                     o, 25,l ))
617      {
618        Off(SW_USE_EZGCD);
619        result=gcd( F, G );
620        On(SW_USE_EZGCD);
621        if (!isRat)
622          Off (SW_RATIONAL);
623        DEBDECLEVEL( cerr, "ezgcd" );
624        result /= icontent (result);
625        return N (d*result);
626      }
627      TIMING_END_AND_PRINT (ez_eval, "time to find eval point in EZ2: ")
628      int dd=degree( Dbt );
629      if ( dd /*degree( Dbt )*/ == 0 )
630      {
631        DEBDECLEVEL( cerr, "ezgcd" );
632        if (!isRat)
633          Off (SW_RATIONAL);
634        return N (d);
635      }
636      if ( dd /*degree( Dbt )*/ == delta )
637        break;
638      else  if ( dd /*degree( Dbt )*/ < delta )
639      {
640        delta = dd /*degree( Dbt )*/;
641        b = bt;
642        Db = Dbt; Fb = Fbt; Gb = Gbt;
643      }
644      DEBOUTLN( cerr, "now after A4, delta = " << delta );
645      /// ---> A5
646      if (delta == degF)
647      {
648        if (degF <= degG  && fdivides (F, G))
649        {
650          DEBDECLEVEL( cerr, "ezgcd" );
651          if (!isRat)
652            Off (SW_RATIONAL);
653          return N (d*F);
654        }
655        else
656          delta--;
657      }
658      else if (delta == degG)
659      {
660        if (degG <= degF && fdivides( G, F ))
661        {
662          DEBDECLEVEL( cerr, "ezgcd" );
663          if (!isRat)
664            Off (SW_RATIONAL);
665          return N (d*G);
666        }
667        else
668          delta--;
669      }
670      if ( delta == 0 )
671      {
672        DEBDECLEVEL( cerr, "ezgcd" );
673        if (!isRat)
674          Off (SW_RATIONAL);
675        return N (d);
676      }
677    }
678    if ( delta != degF && delta != degG )
679    {
680      /// ---> A6
681      bool B_is_F;
682      CanonicalForm xxx1, xxx2;
683      CanonicalForm buf;
684      DD[1] = Fb / Db;
685      buf= Gb/Db;
686      xxx1 = gcd( DD[1], Db );
687      xxx2 = gcd( buf, Db );
688      if (((xxx1.inCoeffDomain() && xxx2.inCoeffDomain()) &&
689          (size (F) <= size (G)))
690            || (xxx1.inCoeffDomain() && !xxx2.inCoeffDomain()))
691      {
692        B = F;
693        DD[2] = Db;
694        lcDD[1] = lcF;
695        lcDD[2] = lcD;
696        B_is_F = true;
697      }
698      else if (((xxx1.inCoeffDomain() && xxx2.inCoeffDomain()) &&
699                (size (G) < size (F)))
700                || (!xxx1.inCoeffDomain() && xxx2.inCoeffDomain()))
701      {
702        DD[1] = buf;
703        B = G;
704        DD[2] = Db;
705        lcDD[1] = lcG;
706        lcDD[2] = lcD;
707        B_is_F = false;
708      }
709      else
710      {
711        //special case
712        Off(SW_USE_EZGCD);
713        result=gcd( F, G );
714        On(SW_USE_EZGCD);
715        if (!isRat)
716          Off (SW_RATIONAL);
717        DEBDECLEVEL( cerr, "ezgcd" );
718        result /= icontent (result);
719        return N (d*result);
720      }
721      /// ---> A7
722      DD[2] = DD[2] * ( b( lcDD[2] ) / lc( DD[2] ) );
723      DD[1] = DD[1] * ( b( lcDD[1] ) / lc( DD[1] ) );
724      DEBOUTLN( cerr, "(hensel) B    = " << B );
725      DEBOUTLN( cerr, "(hensel) lcB  = " << LC( B, Variable(1) ) );
726      DEBOUTLN( cerr, "(hensel) b(B) = " << b(B) );
727      DEBOUTLN( cerr, "(hensel) DD   = " << DD );
728      DEBOUTLN( cerr, "(hensel) lcDD = " << lcDD );
729      TIMING_START (ez_hensel_lift)
730      gcdfound= Hensel (B*lcD, DD, b, lcDD);
731      TIMING_END_AND_PRINT (ez_hensel_lift, "time to hensel lift in EZ: ")
732      DEBOUTLN( cerr, "(hensel finished) DD   = " << DD );
733
734      if (gcdfound == -1)
735      {
736        Off (SW_USE_EZGCD);
737        result= gcd (F,G);
738        On (SW_USE_EZGCD);
739        if (!isRat)
740          Off (SW_RATIONAL);
741        DEBDECLEVEL( cerr, "ezgcd" );
742        result /= icontent (result);
743        return N (d*result);
744      }
745
746      if (gcdfound)
747      {
748        TIMING_START (ez_termination)
749        contcand= content (DD[2], Variable (1));
750        cand = DD[2] / contcand;
751        if (B_is_F)
752          gcdfound = fdivides( cand, G ) && cand*(DD[1]/(lcD/contcand)) == F;
753        else
754          gcdfound = fdivides( cand, F ) && cand*(DD[1]/(lcD/contcand)) == G;
755        TIMING_END_AND_PRINT (ez_termination,
756                              "time for termination test in EZ: ")
757      }
758      /// ---> A8 (gcdfound)
759    }
760    delta--;
761  }
762  /// ---> A9
763  DEBDECLEVEL( cerr, "ezgcd" );
764  cand *= bCommonDen (cand);
765  if (!isRat)
766    Off (SW_RATIONAL);
767  cand /= icontent (cand);
768  return N (d*cand);
769}
770#endif
771
772CanonicalForm
773ezgcd ( const CanonicalForm & FF, const CanonicalForm & GG )
774{
775#ifdef HAVE_NTL
776  REvaluation b;
777  return ezgcd( FF, GG, b, false );
778#else
779  Off (SW_USE_EZGCD);
780  return gcd (FF, GG);
781  On (SW_USE_EZGCD);
782#endif
783}
784
Note: See TracBrowser for help on using the repository browser.