source: git/factory/cf_gcd.cc @ 2080e2

spielwiese
Last change on this file since 2080e2 was 2080e2, checked in by Martin Lee <martinlee84@…>, 10 years ago
chg: renamed cf_gcd_smallp.* to cfModGcd.*
  • 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    else if (isOn(SW_USE_CHINREM_GCD))
128      fc = modGCDZ( fc, gc);
129    else
130    {
131       fc = subResGCD_0( fc, gc );
132    }
133  }
134  else
135  {
136    fc = subResGCD_0( fc, gc );
137  }
138  if ( d1.degree() > 0 )
139    fc *= d1;
140  return fc;
141}
142
143/** static CanonicalForm cf_content ( const CanonicalForm & f, const CanonicalForm & g )
144 *
145 * cf_content() - return gcd(g, content(f)).
146 *
147 * content(f) is calculated with respect to f's main variable.
148 *
149 * @sa gcd(), content(), content( CF, Variable ).
150 *
151**/
152static CanonicalForm
153cf_content ( const CanonicalForm & f, const CanonicalForm & g )
154{
155    if ( f.inPolyDomain() || ( f.inExtension() && ! getReduce( f.mvar() ) ) )
156    {
157        CFIterator i = f;
158        CanonicalForm result = g;
159        while ( i.hasTerms() && ! result.isOne() )
160        {
161            result = gcd( i.coeff(), result );
162            i++;
163        }
164        return result;
165    }
166    else
167        return abs( f );
168}
169
170/** CanonicalForm content ( const CanonicalForm & f )
171 *
172 * content() - return content(f) with respect to main variable.
173 *
174 * Normalizes result.
175 *
176**/
177CanonicalForm
178content ( const CanonicalForm & f )
179{
180    if ( f.inPolyDomain() || ( f.inExtension() && ! getReduce( f.mvar() ) ) )
181    {
182        CFIterator i = f;
183        CanonicalForm result = abs( i.coeff() );
184        i++;
185        while ( i.hasTerms() && ! result.isOne() )
186        {
187            result = gcd( i.coeff(), result );
188            i++;
189        }
190        return result;
191    }
192    else
193        return abs( f );
194}
195
196/** CanonicalForm content ( const CanonicalForm & f, const Variable & x )
197 *
198 * content() - return content(f) with respect to x.
199 *
200 * x should be a polynomial variable.
201 *
202**/
203CanonicalForm
204content ( const CanonicalForm & f, const Variable & x )
205{
206    if (f.inBaseDomain()) return f;
207    ASSERT( x.level() > 0, "cannot calculate content with respect to algebraic variable" );
208    Variable y = f.mvar();
209
210    if ( y == x )
211        return cf_content( f, 0 );
212    else  if ( y < x )
213        return f;
214    else
215        return swapvar( content( swapvar( f, y, x ), y ), y, x );
216}
217
218/** CanonicalForm vcontent ( const CanonicalForm & f, const Variable & x )
219 *
220 * vcontent() - return content of f with repect to variables >= x.
221 *
222 * The content is recursively calculated over all coefficients in
223 * f having level less than x.  x should be a polynomial
224 * variable.
225 *
226**/
227CanonicalForm
228vcontent ( const CanonicalForm & f, const Variable & x )
229{
230    ASSERT( x.level() > 0, "cannot calculate vcontent with respect to algebraic variable" );
231
232    if ( f.mvar() <= x )
233        return content( f, x );
234    else {
235        CFIterator i;
236        CanonicalForm d = 0;
237        for ( i = f; i.hasTerms() && ! d.isOne(); i++ )
238            d = gcd( d, vcontent( i.coeff(), x ) );
239        return d;
240    }
241}
242
243/** CanonicalForm pp ( const CanonicalForm & f )
244 *
245 * pp() - return primitive part of f.
246 *
247 * Returns zero if f equals zero, otherwise f / content(f).
248 *
249**/
250CanonicalForm
251pp ( const CanonicalForm & f )
252{
253    if ( f.isZero() )
254        return f;
255    else
256        return f / content( f );
257}
258
259CanonicalForm
260gcd ( const CanonicalForm & f, const CanonicalForm & g )
261{
262    bool b = f.isZero();
263    if ( b || g.isZero() )
264    {
265        if ( b )
266            return abs( g );
267        else
268            return abs( f );
269    }
270    if ( f.inPolyDomain() || g.inPolyDomain() )
271    {
272        if ( f.mvar() != g.mvar() )
273        {
274            if ( f.mvar() > g.mvar() )
275                return cf_content( f, g );
276            else
277                return cf_content( g, f );
278        }
279        if (isOn(SW_USE_QGCD))
280        {
281          Variable m;
282          if (
283          (getCharacteristic() == 0) &&
284          (hasFirstAlgVar(f,m) || hasFirstAlgVar(g,m))
285          )
286          {
287            bool on_rational = isOn(SW_RATIONAL);
288            CanonicalForm r=QGCD(f,g);
289            On(SW_RATIONAL);
290            CanonicalForm cdF = bCommonDen( r );
291            if (!on_rational) Off(SW_RATIONAL);
292            return cdF*r;
293          }
294        }
295
296        if ( f.inExtension() && getReduce( f.mvar() ) )
297            return CanonicalForm(1);
298        else
299        {
300            if ( fdivides( f, g ) )
301                return abs( f );
302            else  if ( fdivides( g, f ) )
303                return abs( g );
304            if ( !( getCharacteristic() == 0 && isOn( SW_RATIONAL ) ) )
305            {
306                CanonicalForm d;
307                d = gcd_poly( f, g );
308                return abs( d );
309            }
310            else
311            {
312                CanonicalForm cdF = bCommonDen( f );
313                CanonicalForm cdG = bCommonDen( g );
314                Off( SW_RATIONAL );
315                CanonicalForm l = lcm( cdF, cdG );
316                On( SW_RATIONAL );
317                CanonicalForm F = f * l, G = g * l;
318                Off( SW_RATIONAL );
319                l = gcd_poly( F, G );
320                On( SW_RATIONAL );
321                return abs( l );
322            }
323        }
324    }
325    if ( f.inBaseDomain() && g.inBaseDomain() )
326        return bgcd( f, g );
327    else
328        return 1;
329}
330
331/** CanonicalForm lcm ( const CanonicalForm & f, const CanonicalForm & g )
332 *
333 * lcm() - return least common multiple of f and g.
334 *
335 * The lcm is calculated using the formula lcm(f, g) = f * g / gcd(f, g).
336 *
337 * Returns zero if one of f or g equals zero.
338 *
339**/
340CanonicalForm
341lcm ( const CanonicalForm & f, const CanonicalForm & g )
342{
343    if ( f.isZero() || g.isZero() )
344        return 0;
345    else
346        return ( f / gcd( f, g ) ) * g;
347}
348
Note: See TracBrowser for help on using the repository browser.