source: git/factory/cf_gcd.cc @ 6e62ce

spielwiese
Last change on this file since 6e62ce was 6e62ce, checked in by Hans Schoenemann <hannes@…>, 5 years ago
use Flints mpoly for *= and gcd over ZZ/p, QQ, ZZ
  • Property mode set to 100644
File size: 8.9 KB
Line 
1/* emacs edit mode for this file is -*- C++ -*- */
2
3/**
4 * @file cf_gcd.cc
5 *
6 * gcd/content/lcm of polynomials
7 *
8 * To compute the GCD different variants are chosen automatically
9**/
10
11#include "config.h"
12
13
14#include "timing.h"
15#include "cf_assert.h"
16#include "debug.h"
17
18#include "cf_defs.h"
19#include "canonicalform.h"
20#include "cf_iter.h"
21#include "cf_reval.h"
22#include "cf_primes.h"
23#include "cf_algorithm.h"
24#include "cfEzgcd.h"
25#include "cfGcdAlgExt.h"
26#include "cfSubResGcd.h"
27#include "cfModGcd.h"
28#include "FLINTconvert.h"
29#include "facAlgFuncUtil.h"
30
31#ifdef HAVE_NTL
32#include <NTL/ZZX.h>
33#include "NTLconvert.h"
34bool isPurePoly(const CanonicalForm & );
35#endif
36
37void out_cf(const char *s1,const CanonicalForm &f,const char *s2);
38
39/** static CanonicalForm icontent ( const CanonicalForm & f, const CanonicalForm & c )
40 *
41 * icontent() - return gcd of c and all coefficients of f which
42 *   are in a coefficient domain.
43 *
44 * @sa icontent().
45 *
46**/
47static CanonicalForm
48icontent ( const CanonicalForm & f, const CanonicalForm & c )
49{
50    if ( f.inBaseDomain() )
51    {
52      if (c.isZero()) return abs(f);
53      return bgcd( f, c );
54    }
55    //else if ( f.inCoeffDomain() )
56    //   return gcd(f,c);
57    else
58    {
59        CanonicalForm g = c;
60        for ( CFIterator i = f; i.hasTerms() && ! g.isOne(); i++ )
61            g = icontent( i.coeff(), g );
62        return g;
63    }
64}
65
66/** CanonicalForm icontent ( const CanonicalForm & f )
67 *
68 * icontent() - return gcd over all coefficients of f which are
69 *   in a coefficient domain.
70 *
71**/
72CanonicalForm
73icontent ( const CanonicalForm & f )
74{
75    return icontent( f, 0 );
76}
77
78/** CanonicalForm gcd_poly ( const CanonicalForm & f, const CanonicalForm & g )
79 *
80 * gcd_poly() - calculate polynomial gcd.
81 *
82 * This is the dispatcher for polynomial gcd calculation.
83 * Different gcd variants get called depending the input, characteristic, and
84 * on switches (cf_defs.h)
85 *
86 * With the current settings from Singular (i.e. SW_USE_EZGCD= on,
87 * SW_USE_EZGCD_P= on, SW_USE_CHINREM_GCD= on, the EZ GCD variants are the
88 * default algorithms for multivariate polynomial GCD computations)
89 *
90 * @sa gcd(), cf_defs.h
91 *
92**/
93CanonicalForm gcd_poly ( const CanonicalForm & f, const CanonicalForm & g )
94{
95  CanonicalForm fc, gc;
96  bool fc_isUnivariate=f.isUnivariate();
97  bool gc_isUnivariate=g.isUnivariate();
98  bool fc_and_gc_Univariate=fc_isUnivariate && gc_isUnivariate;
99  fc = f;
100  gc = g;
101  if ( getCharacteristic() != 0 )
102  {
103    #if defined(HAVE_FLINT) && ( __FLINT_RELEASE >= 20503)
104    if ( isOn( SW_USE_FL_GCD_P)
105    && (CFFactory::gettype() != GaloisFieldDomain)
106    && (getCharacteristic()>500)
107    &&(!hasAlgVar(fc)) && (!hasAlgVar(gc)))
108    {
109      return gcdFlintMP_Zp(fc,gc);
110    }
111    #endif
112    #ifdef HAVE_NTL
113    if ((!fc_and_gc_Univariate) && (isOn( SW_USE_EZGCD_P )))
114    {
115      fc= EZGCD_P (fc, gc);
116    }
117    else if (isOn(SW_USE_FF_MOD_GCD) && !fc_and_gc_Univariate)
118    {
119      Variable a;
120      if (hasFirstAlgVar (fc, a) || hasFirstAlgVar (gc, a))
121        fc=modGCDFq (fc, gc, a);
122      else if (CFFactory::gettype() == GaloisFieldDomain)
123        fc=modGCDGF (fc, gc);
124      else
125        fc=modGCDFp (fc, gc);
126    }
127    else
128    #endif
129    fc = subResGCD_p( fc, gc );
130  }
131  else if (!fc_and_gc_Univariate) /* && char==0*/
132  {
133    #if defined(HAVE_FLINT) && ( __FLINT_RELEASE >= 20503)
134    if (( isOn( SW_USE_FL_GCD_0) )
135    &&(!hasAlgVar(fc)) && (!hasAlgVar(gc)))
136    {
137      return gcdFlintMP_QQ(fc,gc);
138    }
139    else
140    #endif
141    if ( isOn( SW_USE_EZGCD ) )
142      fc= ezgcd (fc, gc);
143    #ifdef HAVE_NTL
144    else if (isOn(SW_USE_CHINREM_GCD))
145      fc = modGCDZ( fc, gc);
146    #endif
147    else
148    {
149       fc = subResGCD_0( fc, gc );
150    }
151  }
152  else
153  {
154    fc = subResGCD_0( fc, gc );
155  }
156  if ((getCharacteristic()>0)&&(!hasAlgVar(fc))) fc/=fc.lc();
157  return fc;
158}
159
160/** static CanonicalForm cf_content ( const CanonicalForm & f, const CanonicalForm & g )
161 *
162 * cf_content() - return gcd(g, content(f)).
163 *
164 * content(f) is calculated with respect to f's main variable.
165 *
166 * @sa gcd(), content(), content( CF, Variable ).
167 *
168**/
169static CanonicalForm
170cf_content ( const CanonicalForm & f, const CanonicalForm & g )
171{
172    if ( f.inPolyDomain() || ( f.inExtension() && ! getReduce( f.mvar() ) ) )
173    {
174        CFIterator i = f;
175        CanonicalForm result = g;
176        while ( i.hasTerms() && ! result.isOne() )
177        {
178            result = gcd( i.coeff(), result );
179            i++;
180        }
181        return result;
182    }
183    else
184        return abs( f );
185}
186
187/** CanonicalForm content ( const CanonicalForm & f )
188 *
189 * content() - return content(f) with respect to main variable.
190 *
191 * Normalizes result.
192 *
193**/
194CanonicalForm
195content ( const CanonicalForm & f )
196{
197    if ( f.inPolyDomain() || ( f.inExtension() && ! getReduce( f.mvar() ) ) )
198    {
199        CFIterator i = f;
200        CanonicalForm result = abs( i.coeff() );
201        i++;
202        while ( i.hasTerms() && ! result.isOne() )
203        {
204            result = gcd( i.coeff(), result );
205            i++;
206        }
207        return result;
208    }
209    else
210        return abs( f );
211}
212
213/** CanonicalForm content ( const CanonicalForm & f, const Variable & x )
214 *
215 * content() - return content(f) with respect to x.
216 *
217 * x should be a polynomial variable.
218 *
219**/
220CanonicalForm
221content ( const CanonicalForm & f, const Variable & x )
222{
223    if (f.inBaseDomain()) return f;
224    ASSERT( x.level() > 0, "cannot calculate content with respect to algebraic variable" );
225    Variable y = f.mvar();
226
227    if ( y == x )
228        return cf_content( f, 0 );
229    else  if ( y < x )
230        return f;
231    else
232        return swapvar( content( swapvar( f, y, x ), y ), y, x );
233}
234
235/** CanonicalForm vcontent ( const CanonicalForm & f, const Variable & x )
236 *
237 * vcontent() - return content of f with repect to variables >= x.
238 *
239 * The content is recursively calculated over all coefficients in
240 * f having level less than x.  x should be a polynomial
241 * variable.
242 *
243**/
244CanonicalForm
245vcontent ( const CanonicalForm & f, const Variable & x )
246{
247    ASSERT( x.level() > 0, "cannot calculate vcontent with respect to algebraic variable" );
248
249    if ( f.mvar() <= x )
250        return content( f, x );
251    else {
252        CFIterator i;
253        CanonicalForm d = 0;
254        for ( i = f; i.hasTerms() && ! d.isOne(); i++ )
255            d = gcd( d, vcontent( i.coeff(), x ) );
256        return d;
257    }
258}
259
260/** CanonicalForm pp ( const CanonicalForm & f )
261 *
262 * pp() - return primitive part of f.
263 *
264 * Returns zero if f equals zero, otherwise f / content(f).
265 *
266**/
267CanonicalForm
268pp ( const CanonicalForm & f )
269{
270    if ( f.isZero() )
271        return f;
272    else
273        return f / content( f );
274}
275
276CanonicalForm
277gcd ( const CanonicalForm & f, const CanonicalForm & g )
278{
279    bool b = f.isZero();
280    if ( b || g.isZero() )
281    {
282        if ( b )
283            return abs( g );
284        else
285            return abs( f );
286    }
287    if ( f.inPolyDomain() || g.inPolyDomain() )
288    {
289        if ( f.mvar() != g.mvar() )
290        {
291            if ( f.mvar() > g.mvar() )
292                return cf_content( f, g );
293            else
294                return cf_content( g, f );
295        }
296        if (isOn(SW_USE_QGCD))
297        {
298          Variable m;
299          if (
300          (getCharacteristic() == 0) &&
301          (hasFirstAlgVar(f,m) || hasFirstAlgVar(g,m))
302          )
303          {
304            bool on_rational = isOn(SW_RATIONAL);
305            CanonicalForm r=QGCD(f,g);
306            On(SW_RATIONAL);
307            CanonicalForm cdF = bCommonDen( r );
308            if (!on_rational) Off(SW_RATIONAL);
309            return cdF*r;
310          }
311        }
312
313        if ( f.inExtension() && getReduce( f.mvar() ) )
314            return CanonicalForm(1);
315        else
316        {
317            if ( fdivides( f, g ) )
318                return abs( f );
319            else  if ( fdivides( g, f ) )
320                return abs( g );
321            if ( !( getCharacteristic() == 0 && isOn( SW_RATIONAL ) ) )
322            {
323                CanonicalForm d;
324                d = gcd_poly( f, g );
325                return abs( d );
326            }
327            else
328            {
329                CanonicalForm cdF = bCommonDen( f );
330                CanonicalForm cdG = bCommonDen( g );
331                Off( SW_RATIONAL );
332                CanonicalForm l = lcm( cdF, cdG );
333                On( SW_RATIONAL );
334                CanonicalForm F = f * l, G = g * l;
335                Off( SW_RATIONAL );
336                l = gcd_poly( F, G );
337                On( SW_RATIONAL );
338                return abs( l );
339            }
340        }
341    }
342    if ( f.inBaseDomain() && g.inBaseDomain() )
343        return bgcd( f, g );
344    else
345        return 1;
346}
347
348/** CanonicalForm lcm ( const CanonicalForm & f, const CanonicalForm & g )
349 *
350 * lcm() - return least common multiple of f and g.
351 *
352 * The lcm is calculated using the formula lcm(f, g) = f * g / gcd(f, g).
353 *
354 * Returns zero if one of f or g equals zero.
355 *
356**/
357CanonicalForm
358lcm ( const CanonicalForm & f, const CanonicalForm & g )
359{
360    if ( f.isZero() || g.isZero() )
361        return 0;
362    else
363        return ( f / gcd( f, g ) ) * g;
364}
365
Note: See TracBrowser for help on using the repository browser.