source: git/factory/cf_ops.cc @ 281760

spielwiese
Last change on this file since 281760 was 281760, checked in by Jens Schmidt <schmidt@…>, 27 years ago
* cf_ops.cc (fillVarsRec, getNumVars, getVars): moved from canonicalform.cc to cf_ops.cc git-svn-id: file:///usr/local/Singular/svn/trunk@580 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 12.3 KB
Line 
1/* emacs edit mode for this file is -*- C++ -*- */
2/* $Id: cf_ops.cc,v 1.5 1997-07-30 07:53:32 schmidt Exp $ */
3
4#include <config.h>
5
6#include "assert.h"
7
8#include "cf_defs.h"
9#include "canonicalform.h"
10#include "cf_iter.h"
11
12CanonicalForm
13psr( const CanonicalForm &f, const CanonicalForm &g, const Variable & x )
14{
15    return ( power( LC(g,x), degree(f,x)-degree(g,x)+1 ) * f ) % g;
16}
17
18CanonicalForm
19psq( const CanonicalForm &f, const CanonicalForm &g, const Variable & x )
20{
21    return ( power( LC(g,x), degree(f,x)-degree(g,x)+1 ) * f ) / g;
22}
23
24void
25psqr( const CanonicalForm &f, const CanonicalForm &g, CanonicalForm &q, CanonicalForm &r, const Variable& x )
26{
27    divrem( power( LC(g,x), degree(f,x)-degree(g,x)+1 ) * f, g, q, r );
28}
29
30static void swapvar_rec ( const CanonicalForm &f, CanonicalForm &result, const CanonicalForm &term );
31
32static void swapvar_between ( const CanonicalForm &f, CanonicalForm &result, const CanonicalForm &term, int expx2 );
33
34static Variable sv_x1, sv_x2;
35
36CanonicalForm
37swapvar ( const CanonicalForm &f, const Variable &x1, const Variable &x2 )
38{
39    ASSERT( x1.level() > 0 && x2.level() > 0, "cannot swap algebraic Variables" );
40    if ( f.inCoeffDomain() || x1 == x2 || ( x1 > f.mvar() && x2 > f.mvar() ) )
41        return f;
42    else {
43        CanonicalForm result = 0;
44        if ( x1 > x2 ) {
45            sv_x1 = x2; sv_x2 = x1;
46        }
47        else {
48            sv_x1 = x1; sv_x2 = x2;
49        }
50        if ( f.mvar() < sv_x2 )
51            swapvar_between( f, result, 1, 0 );
52        else
53            swapvar_rec( f, result, 1 );
54        return result;
55    }
56}
57
58void
59swapvar_rec ( const CanonicalForm &f, CanonicalForm &result, const CanonicalForm &term )
60{
61    if ( f.inCoeffDomain() || f.mvar() < sv_x1 )
62        result += term * f;
63    else  if ( f.mvar() == sv_x2 )
64        for ( CFIterator i = f; i.hasTerms(); i++ )
65            swapvar_between( i.coeff(), result, term, i.exp() );
66    else  if ( f.mvar() < sv_x2 )
67        swapvar_between( f, result, term, 0 );
68    else
69        for ( CFIterator i = f; i.hasTerms(); i++ )
70            swapvar_rec( i.coeff(), result, term*power( f.mvar(), i.exp() ) );
71}
72
73void
74swapvar_between ( const CanonicalForm &f, CanonicalForm &result, const CanonicalForm &term, int expx2 )
75{
76    if ( f.inCoeffDomain() || f.mvar() < sv_x1 )
77        result += term * power( sv_x1, expx2 ) * f;
78    else  if ( f.mvar() == sv_x1 )
79        for ( CFIterator i = f; i.hasTerms(); i++ )
80            result += power( sv_x2, i.exp() ) * term * i.coeff() * power( sv_x1, expx2 );
81    else
82        for ( CFIterator i = f; i.hasTerms(); i++ )
83            swapvar_between( i.coeff(), result, term*power( f.mvar(), i.exp() ), expx2 );
84}
85
86CanonicalForm
87apply ( const CanonicalForm & f, void (*mf)( CanonicalForm &, int & ) )
88{
89    if ( f.inCoeffDomain() ) {
90        int exp = 0;
91        CanonicalForm result;
92        mf( result, exp );
93        ASSERT( exp == 0, "illegal result, do not know what variable to use" );
94        return result;
95    }
96    else {
97        CanonicalForm result, coeff;
98        CFIterator i;
99        int exp;
100        Variable x = f.mvar();
101        for ( i = f; i.hasTerms(); i++ ) {
102            coeff = i.coeff();
103            exp = i.exp();
104            mf( coeff, exp );
105            if ( ! coeff.isZero() )
106                result += power( x, exp ) * coeff;
107        }
108        return result;
109    }
110}
111
112//{{{ static void degreesRec ( const CanonicalForm & f, int * degs )
113//{{{ docu
114//
115// degreesRec() - recursively get degrees of f.
116//
117//}}}
118static void
119degreesRec ( const CanonicalForm & f, int * degs )
120{
121    if ( ! f.inCoeffDomain() ) {
122        int level = f.level();
123        int deg = f.degree();
124        // calculate the maximum degree of all coefficients which
125        // are in the same level
126        if ( degs[level] < deg )
127            degs[level] = f.degree();
128        for ( CFIterator i = f; i.hasTerms(); i++ )
129            degreesRec( i.coeff(), degs );
130    }
131}
132//}}}
133
134//{{{ int * degrees ( const CanonicalForm & f, int * degs )
135//{{{ docu
136//
137// degress() - return the degrees of all polynomial variables in f.
138//
139// Returns 0 if f is in a coefficient domain, the degrees of f in
140// all its polynomial variables in an array of int otherwise:
141//
142//   degrees( f, 0 )[i] = degree( f, Variable(i) )
143//
144// If degs is not the zero pointer the degrees are stored in this
145// array.  In this case degs should be larger than the level of
146// f.  If degs is the zero pointer, an array of sufficient size
147// is allocated automatically.
148//
149//}}}
150int *
151degrees ( const CanonicalForm & f, int * degs )
152{
153    if ( f.inCoeffDomain() )
154        return 0;
155    else {
156        int level = f.level();
157        if ( degs == 0 )
158            degs = new int[level+1];
159        for ( int i = 0; i <= level; i++ )
160            degs[i] = 0;
161        degreesRec( f, degs );
162        return degs;
163    }
164}
165//}}}
166
167//{{{ CanonicalForm mapdomain ( const CanonicalForm & f, CanonicalForm (*mf)( const CanonicalForm & ) )
168//{{{ docu
169//
170// mapdomain() - map all coefficients of f through mf.
171//
172// Recursively descends down through f to the coefficients which
173// are in a coefficient domain mapping each such coefficient
174// through mf and returns the result.
175//
176//}}}
177CanonicalForm
178mapdomain ( const CanonicalForm & f, CanonicalForm (*mf)( const CanonicalForm & ) )
179{
180    if ( f.inCoeffDomain() )
181        return mf( f );
182    else {
183        CanonicalForm result = 0;
184        CFIterator i;
185        Variable x = f.mvar();
186        for ( i = f; i.hasTerms(); i++ )
187            result += power( x, i.exp() ) * mapdomain( i.coeff(), mf );
188        return result;
189    }
190}
191//}}}
192
193//{{{ int totaldegree ( const CanonicalForm & f )
194//{{{ docu
195//
196// totaldegree() - return the total degree of f.
197//
198// If f is zero, return -1.  If f is in a coefficient domain,
199// return 0.  Otherwise return the total degree of f in all
200// polynomial variables.
201//
202//}}}
203int
204totaldegree ( const CanonicalForm & f )
205{
206    if ( f.isZero() )
207        return -1;
208    else if ( f.inCoeffDomain() )
209        return 0;
210    else {
211        CFIterator i;
212        int cdeg = 0, dummy;
213        // calculate maximum over all coefficients of f, taking
214        // in account our own exponent
215        for ( i = f; i.hasTerms(); i++ )
216            if ( (dummy = totaldegree( i.coeff() ) + i.exp()) > cdeg )
217                cdeg = dummy;
218        return cdeg;
219    }
220}
221//}}}
222
223//{{{ int totaldegree ( const CanonicalForm & f, const Variable & v1, const Variable & v2 )
224//{{{ docu
225//
226// totaldegree() - return the total degree of f as a polynomial
227//   in the polynomial variables between v1 and v2 (inclusively).
228//
229// If f is zero, return -1.  If f is in a coefficient domain,
230// return 0.  Also, return 0 if v1 > v2.  Otherwise, take f to be
231// a polynomial in the polynomial variables between v1 and v2 and
232// return its total degree.
233//
234//}}}
235int
236totaldegree ( const CanonicalForm & f, const Variable & v1, const Variable & v2 )
237{
238    if ( f.isZero() )
239        return -1;
240    else if ( v1 > v2 )
241        return 0;
242    else if ( f.inCoeffDomain() )
243        return 0;
244    else if ( f.mvar() < v1 )
245        return 0;
246    else if ( f.mvar() == v1 )
247        return f.degree();
248    else if ( f.mvar() > v2 ) {
249        // v2's level is larger than f's level, descend down
250        CFIterator i;
251        int cdeg = 0, dummy;
252        // calculate maximum over all coefficients of f
253        for ( i = f; i.hasTerms(); i++ )
254            if ( (dummy = totaldegree( i.coeff(), v1, v2 )) > cdeg )
255                cdeg = dummy;
256        return cdeg;
257    }
258    else {
259        // v1 < f.mvar() <= v2
260        CFIterator i;
261        int cdeg = 0, dummy;
262        // calculate maximum over all coefficients of f, taking
263        // in account our own exponent
264        for ( i = f; i.hasTerms(); i++ )
265            if ( (dummy = totaldegree( i.coeff(), v1, v2 ) + i.exp()) > cdeg )
266                cdeg = dummy;
267        return cdeg;
268    }
269}
270//}}}
271
272//{{{ static void fillVarsRec ( const CanonicalForm & f, int * vars )
273//{{{ docu
274//
275// fillVarsRec - fill array describing occurences of variables in f.
276//
277// Only polynomial variables are looked up.  The information is
278// stored in the arrary vars.  vars should be large enough to
279// hold all information, i.e. larger than the level of f.
280//
281//}}}
282static void
283fillVarsRec ( const CanonicalForm & f, int * vars )
284{
285    int n;
286    if ( (n = f.level()) > 0 ) {
287        vars[n] = 1;
288        CFIterator i;
289        for ( i = f; i.hasTerms(); ++i )
290            fillVarsRec( i.coeff(), vars );
291    }
292}
293//}}}
294
295//{{{ int getNumVars( const CanonicalForm & f )
296//{{{ docu
297//
298// getNumVars() - get number of polynomial variables in f.
299//
300//}}}
301int
302getNumVars( const CanonicalForm & f )
303{
304    int n;
305    if ( f.inCoeffDomain() )
306        return 0;
307    else  if ( (n = f.level()) == 1 )
308        return 1;
309    else {
310        int * vars = new int[ n+1 ];
311        int i;
312        for ( i = 0; i < n; i++ ) vars[i] = 0;
313
314        // look for variables
315        for ( CFIterator I = f; I.hasTerms(); ++I )
316            fillVarsRec( I.coeff(), vars );
317
318        // count them
319        int m = 0;
320        for ( i = 1; i < n; i++ )
321            if ( vars[i] != 0 ) m++;
322
323        delete [] vars;
324        // do not forget to count our own variable
325        return m+1;
326    }
327}
328//}}}
329
330//{{{ CanonicalForm getVars( const CanonicalForm & f )
331//{{{ docu
332//
333// getVars() - get polynomial variables of f.
334//
335// Return the product of all of them, 1 if there are not any.
336//
337//}}}
338CanonicalForm
339getVars( const CanonicalForm & f )
340{
341    int n;
342    if ( f.inCoeffDomain() )
343        return 1;
344    else  if ( (n = f.level()) == 1 )
345        return Variable( 1 );
346    else {
347        int * vars = new int[ n+1 ];
348        int i;
349        for ( i = 0; i <= n; i++ ) vars[i] = 0;
350
351        // look for variables
352        for ( CFIterator I = f; I.hasTerms(); ++I )
353            fillVarsRec( I.coeff(), vars );
354
355        // multiply them all
356        CanonicalForm result = 1;
357        for ( i = n; i > 0; i-- )
358            if ( vars[i] != 0 ) result *= Variable( i );
359
360        delete [] vars;
361        // do not forget our own variable
362        return f.mvar() * result;
363    }
364}
365//}}}
366
367//{{{ CanonicalForm resultant( const CanonicalForm & f, const CanonicalForm & g, const Variable & x )
368//{{{ docu
369//
370// resultant() - return resultant of f and g with respect to x.
371//
372// We calculate the resultant using a subresultant PSR.
373//
374// flipFactor: Res(f, g) = flipFactor * Res(g, f)
375// F, G: f and g with x as main variable
376// pi, pi1, pi2: used to compute PSR
377// delta:
378// bi, Hi:
379//
380//}}}
381CanonicalForm
382resultant( const CanonicalForm & f, const CanonicalForm & g, const Variable & x )
383{
384    CanonicalForm Hi, bi, pi, pi1, pi2, F, G;
385    int delta, flipFactor;
386    Variable v;
387
388    ASSERT( x.level() > 0, "cannot calculate resultant in respect to algebraic variables" );
389
390    // some checks on triviality.  We will not use degree( v )
391    // here because this may involve variable swapping.
392    if ( f.isZero() || g.isZero() )
393        return 0;
394    if ( f.mvar() < x )
395        return power( f, g.degree( x ) );
396    if ( g.mvar() < x )
397        return power( g, f.degree( x ) );
398
399    // make x main variale
400    if ( f.mvar() > x || g.mvar() > x ) {
401        if ( f.mvar() > g.mvar() )
402            v = f.mvar();
403        else
404            v = g.mvar();
405        F = swapvar( f, v, x );
406        G = swapvar( g, v, x );
407    }
408    else {
409        v = x;
410        F = f;
411        G = g;
412    }
413    // at this point, we have to calculate resultant( F, G, v )
414    // where v is equal to or greater than the main variables
415    // of F and G
416
417    // trivial case: F or G in R.  Swapping will not occur
418    // when calling degree( v ).
419    if ( F.degree( v ) < 1 )
420        return power( f, G.degree( v ) );
421    if ( G.degree( v ) < 1 )
422        return power( g, F.degree( v ) );
423
424    // start the pseudo remainder sequence
425    if ( F.degree( v ) >= G.degree( v ) ) {
426        pi = F; pi1 = G;
427        flipFactor = 1;
428    }
429    else {
430        if ( (F.degree( v ) * G.degree( v )) % 2 )
431            flipFactor = -1;
432        else
433            flipFactor = 1;
434        pi = G; pi1 = F;
435    }
436
437    delta = degree( pi, v ) - degree( pi1, v );
438    Hi = power( LC( pi1, v ), delta );
439
440    // Ist hier nicht if und else zweig vertauscht ???
441    if ( (delta+1) % 2 )
442        bi = 1;
443    else
444        bi = -1;
445
446    // Ist pi1.isZero vielleich schneller ???
447    while ( degree( pi1, v ) >= 0 ) {
448        pi2 = psr( pi, pi1, v );
449        pi2 = pi2 / bi;
450        pi = pi1; pi1 = pi2;
451        if ( degree( pi1, v ) >= 0 ) {
452            delta = degree( pi, v ) - degree( pi1, v );
453
454            // Ist hier nicht if und else zweig vertauscht ???
455            if ( (delta+1) % 2 )
456                bi = LC( pi, v ) * power( Hi, delta );
457            else
458                bi = -LC( pi, v ) * power( Hi, delta );
459
460            // Was ist f"ur delta == 0 ???
461            Hi = power( LC( pi1, v ), delta ) / power( Hi, delta-1 );
462        }
463    }
464
465    // f and g have non-trivial common divisor
466    // if ( degree( pi, v ) > 0 )
467    // return 0;
468
469    // undo variable swap
470    if ( v == x )
471        // Gibt man hier nicht den letzten Rest der PSR zur"uck
472        // und nicht den Korrekturterm Hi ???
473        return Hi * flipFactor;
474    else
475        return swapvar( Hi, v, x ) * flipFactor;
476}
477//}}}
478
479static CanonicalForm
480cden ( const CanonicalForm & f )
481{
482    if ( f.inCoeffDomain() )
483        return f.den();
484    else {
485        CFIterator i;
486        CanonicalForm cd = 1;
487        for ( i = f; i.hasTerms(); i++ )
488            cd = lcm( cd, cden( i.coeff() ) );
489        return cd;
490    }
491}
492
493CanonicalForm
494common_den ( const CanonicalForm & f )
495{
496    if ( getCharacteristic() == 0 && isOn( SW_RATIONAL ) ) {
497        Off( SW_RATIONAL );
498        CanonicalForm cd = cden( f );
499        On( SW_RATIONAL );
500        return cd;
501    }
502    else
503        return 1;
504}
Note: See TracBrowser for help on using the repository browser.