source: git/factory/cf_gcd.cc @ b2e2b0

spielwiese
Last change on this file since b2e2b0 was b2e2b0, checked in by Max Horn <max@…>, 4 years ago
Fix a bunch of warnings
  • 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 (0) {} // dummy, to be able to build without NTL and FLINT
104    #if defined(HAVE_FLINT) && ( __FLINT_RELEASE >= 20503)
105    if ( isOn( SW_USE_FL_GCD_P)
106    && (CFFactory::gettype() != GaloisFieldDomain)
107    && (getCharacteristic()>10)
108    &&(!hasAlgVar(fc)) && (!hasAlgVar(gc)))
109    {
110      return gcdFlintMP_Zp(fc,gc);
111    }
112    #endif
113    #ifdef HAVE_NTL
114    if ((!fc_and_gc_Univariate) && (isOn( SW_USE_EZGCD_P )))
115    {
116      fc= EZGCD_P (fc, gc);
117    }
118    #endif
119    #ifdef HAVE_NTL
120    else if (isOn(SW_USE_FF_MOD_GCD) && !fc_and_gc_Univariate)
121    {
122      Variable a;
123      if (hasFirstAlgVar (fc, a) || hasFirstAlgVar (gc, a))
124        fc=modGCDFq (fc, gc, a);
125      else if (CFFactory::gettype() == GaloisFieldDomain)
126        fc=modGCDGF (fc, gc);
127      else
128        fc=modGCDFp (fc, gc);
129    }
130    #endif
131    else
132    fc = subResGCD_p( fc, gc );
133  }
134  else if (!fc_and_gc_Univariate) /* && char==0*/
135  {
136    #if defined(HAVE_FLINT) && ( __FLINT_RELEASE >= 20503)
137    if (( isOn( SW_USE_FL_GCD_0) )
138    &&(!hasAlgVar(fc)) && (!hasAlgVar(gc)))
139    {
140      return gcdFlintMP_QQ(fc,gc);
141    }
142    else
143    #endif
144    #ifdef HAVE_NTL
145    if ( isOn( SW_USE_EZGCD ) )
146      fc= ezgcd (fc, gc);
147    #endif 
148    #ifdef HAVE_NTL
149    else if (isOn(SW_USE_CHINREM_GCD))
150      fc = modGCDZ( fc, gc);
151    else
152    #endif
153    {
154       fc = subResGCD_0( fc, gc );
155    }
156  }
157  else
158  {
159    fc = subResGCD_0( fc, gc );
160  }
161  if ((getCharacteristic()>0)&&(!hasAlgVar(fc))) fc/=fc.lc();
162  return fc;
163}
164
165/** static CanonicalForm cf_content ( const CanonicalForm & f, const CanonicalForm & g )
166 *
167 * cf_content() - return gcd(g, content(f)).
168 *
169 * content(f) is calculated with respect to f's main variable.
170 *
171 * @sa gcd(), content(), content( CF, Variable ).
172 *
173**/
174static CanonicalForm
175cf_content ( const CanonicalForm & f, const CanonicalForm & g )
176{
177    if ( f.inPolyDomain() || ( f.inExtension() && ! getReduce( f.mvar() ) ) )
178    {
179        CFIterator i = f;
180        CanonicalForm result = g;
181        while ( i.hasTerms() && ! result.isOne() )
182        {
183            result = gcd( i.coeff(), result );
184            i++;
185        }
186        return result;
187    }
188    else
189        return abs( f );
190}
191
192/** CanonicalForm content ( const CanonicalForm & f )
193 *
194 * content() - return content(f) with respect to main variable.
195 *
196 * Normalizes result.
197 *
198**/
199CanonicalForm
200content ( const CanonicalForm & f )
201{
202    if ( f.inPolyDomain() || ( f.inExtension() && ! getReduce( f.mvar() ) ) )
203    {
204        CFIterator i = f;
205        CanonicalForm result = abs( i.coeff() );
206        i++;
207        while ( i.hasTerms() && ! result.isOne() )
208        {
209            result = gcd( i.coeff(), result );
210            i++;
211        }
212        return result;
213    }
214    else
215        return abs( f );
216}
217
218/** CanonicalForm content ( const CanonicalForm & f, const Variable & x )
219 *
220 * content() - return content(f) with respect to x.
221 *
222 * x should be a polynomial variable.
223 *
224**/
225CanonicalForm
226content ( const CanonicalForm & f, const Variable & x )
227{
228    if (f.inBaseDomain()) return f;
229    ASSERT( x.level() > 0, "cannot calculate content with respect to algebraic variable" );
230    Variable y = f.mvar();
231
232    if ( y == x )
233        return cf_content( f, 0 );
234    else  if ( y < x )
235        return f;
236    else
237        return swapvar( content( swapvar( f, y, x ), y ), y, x );
238}
239
240/** CanonicalForm vcontent ( const CanonicalForm & f, const Variable & x )
241 *
242 * vcontent() - return content of f with repect to variables >= x.
243 *
244 * The content is recursively calculated over all coefficients in
245 * f having level less than x.  x should be a polynomial
246 * variable.
247 *
248**/
249CanonicalForm
250vcontent ( const CanonicalForm & f, const Variable & x )
251{
252    ASSERT( x.level() > 0, "cannot calculate vcontent with respect to algebraic variable" );
253
254    if ( f.mvar() <= x )
255        return content( f, x );
256    else {
257        CFIterator i;
258        CanonicalForm d = 0;
259        for ( i = f; i.hasTerms() && ! d.isOne(); i++ )
260            d = gcd( d, vcontent( i.coeff(), x ) );
261        return d;
262    }
263}
264
265/** CanonicalForm pp ( const CanonicalForm & f )
266 *
267 * pp() - return primitive part of f.
268 *
269 * Returns zero if f equals zero, otherwise f / content(f).
270 *
271**/
272CanonicalForm
273pp ( const CanonicalForm & f )
274{
275    if ( f.isZero() )
276        return f;
277    else
278        return f / content( f );
279}
280
281CanonicalForm
282gcd ( const CanonicalForm & f, const CanonicalForm & g )
283{
284    bool b = f.isZero();
285    if ( b || g.isZero() )
286    {
287        if ( b )
288            return abs( g );
289        else
290            return abs( f );
291    }
292    if ( f.inPolyDomain() || g.inPolyDomain() )
293    {
294        if ( f.mvar() != g.mvar() )
295        {
296            if ( f.mvar() > g.mvar() )
297                return cf_content( f, g );
298            else
299                return cf_content( g, f );
300        }
301        if (isOn(SW_USE_QGCD))
302        {
303          Variable m;
304          if (
305          (getCharacteristic() == 0) &&
306          (hasFirstAlgVar(f,m) || hasFirstAlgVar(g,m))
307          )
308          {
309            bool on_rational = isOn(SW_RATIONAL);
310            CanonicalForm r=QGCD(f,g);
311            On(SW_RATIONAL);
312            CanonicalForm cdF = bCommonDen( r );
313            if (!on_rational) Off(SW_RATIONAL);
314            return cdF*r;
315          }
316        }
317
318        if ( f.inExtension() && getReduce( f.mvar() ) )
319            return CanonicalForm(1);
320        else
321        {
322            if ( fdivides( f, g ) )
323                return abs( f );
324            else  if ( fdivides( g, f ) )
325                return abs( g );
326            if ( !( getCharacteristic() == 0 && isOn( SW_RATIONAL ) ) )
327            {
328                CanonicalForm d;
329                d = gcd_poly( f, g );
330                return abs( d );
331            }
332            else
333            {
334                CanonicalForm cdF = bCommonDen( f );
335                CanonicalForm cdG = bCommonDen( g );
336                CanonicalForm F = f * cdF, G = g * cdG;
337                Off( SW_RATIONAL );
338                CanonicalForm l = gcd_poly( F, G );
339                On( SW_RATIONAL );
340                return abs( l );
341            }
342        }
343    }
344    if ( f.inBaseDomain() && g.inBaseDomain() )
345        return bgcd( f, g );
346    else
347        return 1;
348}
349
350/** CanonicalForm lcm ( const CanonicalForm & f, const CanonicalForm & g )
351 *
352 * lcm() - return least common multiple of f and g.
353 *
354 * The lcm is calculated using the formula lcm(f, g) = f * g / gcd(f, g).
355 *
356 * Returns zero if one of f or g equals zero.
357 *
358**/
359CanonicalForm
360lcm ( const CanonicalForm & f, const CanonicalForm & g )
361{
362    if ( f.isZero() || g.isZero() )
363        return 0;
364    else
365        return ( f / gcd( f, g ) ) * g;
366}
367
Note: See TracBrowser for help on using the repository browser.