source: git/factory/cf_resultant.cc @ 16f511

spielwiese
Last change on this file since 16f511 was 16f511, checked in by Oleksandr Motsak <motsak@…>, 11 years ago
Fixed the usage of "config.h" (if defined HAVE_CONFIG_H)
  • Property mode set to 100644
File size: 6.6 KB
Line 
1/* emacs edit mode for this file is -*- C++ -*- */
2
3//{{{ docu
4//
5// cf_resultant.cc - algorithms for calculating resultants.
6//
7// Header file: cf_algorithm.h
8//
9//}}}
10
11#ifdef HAVE_CONFIG_H
12#include "config.h"
13#endif /* HAVE_CONFIG_H */
14
15#include "cf_assert.h"
16
17#include "canonicalform.h"
18#include "variable.h"
19#include "cf_algorithm.h"
20
21//{{{ CFArray subResChain ( const CanonicalForm & f, const CanonicalForm & g, const Variable & x )
22//{{{ docu
23//
24// subResChain() - caculate extended subresultant chain.
25//
26// The chain is calculated from f and g with respect to variable
27// x which should not be an algebraic variable.  If f or q equals
28// zero, an array consisting of one zero entry is returned.
29//
30// Note: this is not the standard subresultant chain but the
31// *extended* chain!
32//
33// This algorithm is from the article of R. Loos - 'Generalized
34// Polynomial Remainder Sequences' in B. Buchberger - 'Computer
35// Algebra - Symbolic and Algebraic Computation' with some
36// necessary extensions concerning the calculation of the first
37// step.
38//
39//}}}
40CFArray
41subResChain ( const CanonicalForm & f, const CanonicalForm & g, const Variable & x )
42{
43    ASSERT( x.level() > 0, "cannot calculate subresultant sequence with respect to algebraic variables" );
44
45    CFArray trivialResult( 0, 0 );
46    CanonicalForm F, G;
47    Variable X;
48
49    // some checks on triviality
50    if ( f.isZero() || g.isZero() ) {
51        trivialResult[0] = 0;
52        return trivialResult;
53    }
54
55    // make x main variable
56    if ( f.mvar() > x || g.mvar() > x ) {
57        if ( f.mvar() > g.mvar() )
58            X = f.mvar();
59        else
60            X = g.mvar();
61        F = swapvar( f, X, x );
62        G = swapvar( g, X, x );
63    }
64    else {
65        X = x;
66        F = f;
67        G = g;
68    }
69    // at this point, we have to calculate the sequence of F and
70    // G in respect to X where X is equal to or greater than the
71    // main variables of F and G
72
73    // initialization of chain
74    int m = degree( F, X );
75    int n = degree( G, X );
76
77    int j = (m <= n) ? n : m-1;
78    int r;
79
80    CFArray S( 0, j+1 );
81    CanonicalForm R;
82    S[j+1] = F; S[j] = G;
83
84    // make sure that S[j+1] is regular and j < n
85    if ( m == n && j > 0 ) {
86        S[j-1] = LC( S[j], X ) * psr( S[j+1], S[j], X );
87        j--;
88    } else if ( m < n ) {
89        S[j-1] = LC( S[j], X ) * LC( S[j], X ) * S[j+1];
90        j--;
91    } else if ( m > n && j > 0 ) {
92        // calculate first step
93        r = degree( S[j], X );
94        R = LC( S[j+1], X );
95
96        // if there was a gap calculate similar polynomial
97        if ( j > r && r >= 0 )
98            S[r] = power( LC( S[j], X ), j - r ) * S[j] * power( R, j - r );
99
100        if ( r > 0 ) {
101            // calculate remainder
102            S[r-1] = psr( S[j+1], S[j], X ) * power( -R, j - r );
103            j = r-1;
104        }
105    }
106
107    while ( j > 0 ) {
108        // at this point, 0 < j < n and S[j+1] is regular
109        r = degree( S[j], X );
110        R = LC( S[j+1], X );
111
112        // if there was a gap calculate similar polynomial
113        if ( j > r && r >= 0 )
114            S[r] = (power( LC( S[j], X ), j - r ) * S[j]) / power( R, j - r );
115
116        if ( r <= 0 ) break;
117        // calculate remainder
118        S[r-1] = psr( S[j+1], S[j], X ) / power( -R, j - r + 2 );
119
120        j = r-1;
121        // again 0 <= j < r <= jOld and S[j+1] is regular
122    }
123
124    for ( j = 0; j <= S.max(); j++ ) {
125        // reswap variables if necessary
126        if ( X != x ) {
127            S[j] = swapvar( S[j], X, x );
128        }
129    }
130
131    return S;
132}
133//}}}
134
135//{{{ static CanonicalForm trivialResultant ( const CanonicalForm & f, const CanonicalForm & g, const Variable & x )
136//{{{ docu
137//
138// trivialResultant - calculate trivial resultants.
139//
140// x's level should be larger than f's and g's levels.  Either f
141// or g should be constant or both linear.
142//
143// Used by resultant().
144//
145//}}}
146static CanonicalForm
147trivialResultant ( const CanonicalForm & f, const CanonicalForm & g, const Variable & x )
148{
149    // f or g in R
150    if ( degree( f, x ) == 0 )
151        return power( f, degree( g, x ) );
152    if ( degree( g, x ) == 0 )
153        return power( g, degree( f, x ) );
154
155    // f and g are linear polynomials
156    return LC( f, x ) * g - LC( g, x ) * f;
157}
158//}}}
159
160//{{{ CanonicalForm resultant ( const CanonicalForm & f, const CanonicalForm & g, const Variable & x )
161//{{{ docu
162//
163// resultant() - return resultant of f and g with respect to x.
164//
165// The chain is calculated from f and g with respect to variable
166// x which should not be an algebraic variable.  If f or q equals
167// zero, zero is returned.  If f is a coefficient with respect to
168// x, f^degree(g, x) is returned, analogously for g.
169//
170// This algorithm serves as a wrapper around other resultant
171// algorithms which do the real work.  Here we use standard
172// properties of resultants only.
173//
174//}}}
175CanonicalForm
176resultant ( const CanonicalForm & f, const CanonicalForm & g, const Variable & x )
177{
178    ASSERT( x.level() > 0, "cannot calculate resultant with respect to algebraic variables" );
179
180    // some checks on triviality.  We will not use degree( v )
181    // here because this may involve variable swapping.
182    if ( f.isZero() || g.isZero() )
183        return 0;
184    if ( f.mvar() < x )
185        return power( f, g.degree( x ) );
186    if ( g.mvar() < x )
187        return power( g, f.degree( x ) );
188
189    // make x main variale
190    CanonicalForm F, G;
191    Variable X;
192    if ( f.mvar() > x || g.mvar() > x ) {
193        if ( f.mvar() > g.mvar() )
194            X = f.mvar();
195        else
196            X = g.mvar();
197        F = swapvar( f, X, x );
198        G = swapvar( g, X, x );
199    }
200    else {
201        X = x;
202        F = f;
203        G = g;
204    }
205    // at this point, we have to calculate resultant( F, G, X )
206    // where X is equal to or greater than the main variables
207    // of F and G
208
209    int m = degree( F, X );
210    int n = degree( G, X );
211    // catch trivial cases
212    if ( m+n <= 2 || m == 0 || n == 0 )
213        return swapvar( trivialResultant( F, G, X ), X, x );
214
215    // exchange F and G if necessary
216    int flipFactor;
217    if ( m < n ) {
218        CanonicalForm swap = F;
219        F = G; G = swap;
220        int degswap = m;
221        m = n; n = degswap;
222        if ( m & 1 && n & 1 )
223            flipFactor = -1;
224        else
225            flipFactor = 1;
226    } else
227        flipFactor = 1;
228
229    // this is not an effective way to calculate the resultant!
230    CanonicalForm extFactor;
231    if ( m == n ) {
232        if ( n & 1 )
233            extFactor = -LC( G, X );
234        else
235            extFactor = LC( G, X );
236    } else
237        extFactor = power( LC( F, X ), m-n-1 );
238
239    CanonicalForm result;
240    result = subResChain( F, G, X )[0] / extFactor;
241
242    return swapvar( result, X, x ) * flipFactor;
243}
244//}}}
Note: See TracBrowser for help on using the repository browser.