source: git/factory/cf_gcd.cc @ f4365f

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