1 | /* emacs edit mode for this file is -*- C++ -*- */ |
---|
2 | /* $Id: cf_algorithm.cc,v 1.6 1998-03-12 10:26:14 schmidt Exp $ */ |
---|
3 | |
---|
4 | //{{{ docu |
---|
5 | // |
---|
6 | // cf_algorithm.cc - simple mathematical algorithms. |
---|
7 | // |
---|
8 | // A 'mathematical' algorithm is an algorithm which calculates |
---|
9 | // some mathematical function in contrast to a 'structural' |
---|
10 | // algorithm which gives structural information on polynomials. |
---|
11 | // |
---|
12 | // Compare these functions to the functions in cf_ops.cc, which are |
---|
13 | // structural algorithms. |
---|
14 | // |
---|
15 | // Used by: cf_gcd.cc, cf_resultant.cc, fac_distrib.cc, |
---|
16 | // fac_ezgcd.cc, fac_util.cc, sm_sparsemod.cc |
---|
17 | // |
---|
18 | //}}} |
---|
19 | |
---|
20 | #include <config.h> |
---|
21 | |
---|
22 | #include "assert.h" |
---|
23 | |
---|
24 | #include "cf_defs.h" |
---|
25 | #include "canonicalform.h" |
---|
26 | #include "cf_algorithm.h" |
---|
27 | #include "variable.h" |
---|
28 | #include "cf_iter.h" |
---|
29 | |
---|
30 | //{{{ CanonicalForm psr ( const CanonicalForm & f, const CanonicalForm & g, const Variable & x ) |
---|
31 | //{{{ docu |
---|
32 | // |
---|
33 | // psr() - calculate pseudo remainder of `f' and `g' with respect |
---|
34 | // to `x'. |
---|
35 | // |
---|
36 | // `x' should be a polynomial variable, `g' must not equal zero. |
---|
37 | // |
---|
38 | // For f and g in R[x], R an integral domain, g != 0, there is a |
---|
39 | // unique representation |
---|
40 | // |
---|
41 | // lc(g)^s*f = g*q + r |
---|
42 | // |
---|
43 | // with r = 0 or deg(r) < deg(g) and s = 0 if f = 0 or |
---|
44 | // s = max( 0, deg(f)-deg(g)+1 ) otherwise. |
---|
45 | // Then r = psr(f, g) and q = psq(f, g) are called pseudo |
---|
46 | // remainder and pseudo quotient, resp. |
---|
47 | // |
---|
48 | // See H.-J. Reiffen/G. Scheja/U. Vetter - 'Algebra', 2nd ed., |
---|
49 | // par. 15 for a reference. |
---|
50 | // |
---|
51 | //}}} |
---|
52 | CanonicalForm |
---|
53 | psr ( const CanonicalForm & f, const CanonicalForm & g, const Variable & x ) |
---|
54 | { |
---|
55 | ASSERT( x.level() > 0, "illegal variable" ); |
---|
56 | ASSERT( g != 0, "division by zero" ); |
---|
57 | |
---|
58 | int m = degree( f, x ); |
---|
59 | int n = degree( g, x ); |
---|
60 | if ( m < 0 || m < n ) |
---|
61 | return f; |
---|
62 | else |
---|
63 | return ( power( LC( g, x ), m-n+1 ) * f ) % g; |
---|
64 | } |
---|
65 | //}}} |
---|
66 | |
---|
67 | //{{{ CanonicalForm psq ( const CanonicalForm & f, const CanonicalForm & g, const Variable & x ) |
---|
68 | //{{{ docu |
---|
69 | // |
---|
70 | // psq() - calculate pseudo quotient of `f' and `g' with respect |
---|
71 | // to `x'. |
---|
72 | // |
---|
73 | // `x' should be a polynomial variable, `g' must not equal zero. |
---|
74 | // See `psr()' for more detailed information. |
---|
75 | // |
---|
76 | //}}} |
---|
77 | CanonicalForm |
---|
78 | psq ( const CanonicalForm & f, const CanonicalForm & g, const Variable & x ) |
---|
79 | { |
---|
80 | ASSERT( x.level() > 0, "illegal variable" ); |
---|
81 | ASSERT( g != 0, "division by zero" ); |
---|
82 | |
---|
83 | int m = degree( f, x ); |
---|
84 | int n = degree( g, x ); |
---|
85 | if ( m < 0 || m < n ) |
---|
86 | return 0; |
---|
87 | else |
---|
88 | return ( power( LC( g, x ), m-n+1 ) * f ) / g; |
---|
89 | } |
---|
90 | //}}} |
---|
91 | |
---|
92 | //{{{ void psqr ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & q, CanonicalForm & r, const Variable & x ) |
---|
93 | //{{{ docu |
---|
94 | // |
---|
95 | // psqr() - calculate pseudo quotient and remainder of `f' and |
---|
96 | // `g' with respect to `x'. |
---|
97 | // |
---|
98 | // `x' should be a polynomial variable, `g' must not equal zero. |
---|
99 | // See `psr()' for more detailed information. |
---|
100 | // |
---|
101 | //}}} |
---|
102 | void |
---|
103 | psqr ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & q, CanonicalForm & r, const Variable& x ) |
---|
104 | { |
---|
105 | ASSERT( x.level() > 0, "illegal variable" ); |
---|
106 | ASSERT( g != 0, "division by zero" ); |
---|
107 | |
---|
108 | int m = degree( f, x ); |
---|
109 | int n = degree( g, x ); |
---|
110 | if ( m < 0 || m < n ) { |
---|
111 | q = 0; r = f; |
---|
112 | } |
---|
113 | else |
---|
114 | divrem( power( LC( g, x ), m-n+1 ) * f, g, q, r ); |
---|
115 | } |
---|
116 | //}}} |
---|
117 | |
---|
118 | //{{{ static CanonicalForm internalBCommonDen ( const CanonicalForm & f ) |
---|
119 | //{{{ docu |
---|
120 | // |
---|
121 | // internalBCommonDen() - recursively calculate multivariate |
---|
122 | // common denominator of coefficients of `f'. |
---|
123 | // |
---|
124 | // Used by: bCommonDen() |
---|
125 | // |
---|
126 | //}}} |
---|
127 | static CanonicalForm |
---|
128 | internalBCommonDen ( const CanonicalForm & f ) |
---|
129 | { |
---|
130 | if ( f.inBaseDomain() ) |
---|
131 | return f.den(); |
---|
132 | else { |
---|
133 | CanonicalForm result = 1; |
---|
134 | for ( CFIterator i = f; i.hasTerms(); i++ ) |
---|
135 | result = blcm( result, internalBCommonDen( i.coeff() ) ); |
---|
136 | return result; |
---|
137 | } |
---|
138 | } |
---|
139 | //}}} |
---|
140 | |
---|
141 | //{{{ CanonicalForm bCommonDen ( const CanonicalForm & f ) |
---|
142 | //{{{ docu |
---|
143 | // |
---|
144 | // bCommonDen() - calculate multivariate common denominator of |
---|
145 | // coefficients of `f'. |
---|
146 | // |
---|
147 | // The common denominator is calculated with respect to all |
---|
148 | // coefficients of `f' which are in a base domain. In other |
---|
149 | // words, common_den( `f' ) * `f' is guaranteed to have integer |
---|
150 | // coefficients only. The common denominator of zero equals is |
---|
151 | // one. |
---|
152 | // |
---|
153 | // Returns something non-trivial iff the current domain is Q. |
---|
154 | // |
---|
155 | //}}} |
---|
156 | CanonicalForm |
---|
157 | bCommonDen ( const CanonicalForm & f ) |
---|
158 | { |
---|
159 | if ( getCharacteristic() == 0 && isOn( SW_RATIONAL ) ) { |
---|
160 | // otherwise `bgcd()' returns one |
---|
161 | Off( SW_RATIONAL ); |
---|
162 | CanonicalForm result = internalBCommonDen( f ); |
---|
163 | On( SW_RATIONAL ); |
---|
164 | return result; |
---|
165 | } else |
---|
166 | return CanonicalForm( 1 ); |
---|
167 | } |
---|
168 | //}}} |
---|
169 | |
---|
170 | //{{{ bool divides ( const CanonicalForm & f, const CanonicalForm & g ) |
---|
171 | //{{{ docu |
---|
172 | // |
---|
173 | // divides() - check whether `f' divides `g'. |
---|
174 | // |
---|
175 | // Uses some extra checks to avoid polynomial division. |
---|
176 | // |
---|
177 | //}}} |
---|
178 | bool |
---|
179 | divides ( const CanonicalForm & f, const CanonicalForm & g ) |
---|
180 | { |
---|
181 | if ( g.level() > 0 && g.level() == f.level() ) |
---|
182 | if ( divides( f.tailcoeff(), g.tailcoeff() ) && divides( f.LC(), g.LC() ) ) { |
---|
183 | CanonicalForm q, r; |
---|
184 | bool ok = divremt( g, f, q, r ); |
---|
185 | return ok && r.isZero(); |
---|
186 | } |
---|
187 | else |
---|
188 | return false; |
---|
189 | else { |
---|
190 | CanonicalForm q, r; |
---|
191 | bool ok = divremt( g, f, q, r ); |
---|
192 | return ok && r.isZero(); |
---|
193 | } |
---|
194 | } |
---|
195 | //}}} |
---|
196 | |
---|
197 | //{{{ CanonicalForm maxNorm ( const CanonicalForm & f ) |
---|
198 | //{{{ docu |
---|
199 | // |
---|
200 | // maxNorm() - get maximum norm of `f'. |
---|
201 | // |
---|
202 | // That is, the base coefficient of `f' with the largest absolute |
---|
203 | // value. |
---|
204 | // |
---|
205 | // Valid for arbitrary polynomials over arbitrary domains, but |
---|
206 | // most useful for multivariate polynomials over Z. |
---|
207 | // |
---|
208 | //}}} |
---|
209 | CanonicalForm |
---|
210 | maxNorm ( const CanonicalForm & f ) |
---|
211 | { |
---|
212 | if ( f.inBaseDomain() ) |
---|
213 | return abs( f ); |
---|
214 | else { |
---|
215 | CanonicalForm result = 0; |
---|
216 | for ( CFIterator i = f; i.hasTerms(); i++ ) { |
---|
217 | CanonicalForm coeffMaxNorm = maxNorm( i.coeff() ); |
---|
218 | if ( coeffMaxNorm > result ) |
---|
219 | result = coeffMaxNorm; |
---|
220 | } |
---|
221 | return result; |
---|
222 | } |
---|
223 | } |
---|
224 | //}}} |
---|
225 | |
---|
226 | //{{{ CanonicalForm euclideanNorm ( const CanonicalForm & f ) |
---|
227 | //{{{ docu |
---|
228 | // |
---|
229 | // euclideanNorm() - get euclidean norm of `f'. |
---|
230 | // |
---|
231 | // That is, returns the largest integer smaller or equal |
---|
232 | // norm(`f') = sqrt(sum( `f'[i]^2 )). `f' should be an |
---|
233 | // univariate polynomial over Z. |
---|
234 | // |
---|
235 | //}}} |
---|
236 | CanonicalForm |
---|
237 | euclideanNorm ( const CanonicalForm & f ) |
---|
238 | { |
---|
239 | ASSERT( (f.inBaseDomain() || f.isUnivariate()) && f.LC().inZ(), |
---|
240 | "illegal polynomial" ); |
---|
241 | |
---|
242 | CanonicalForm result = 0; |
---|
243 | for ( CFIterator i = f; i.hasTerms(); i++ ) { |
---|
244 | CanonicalForm coeff = i.coeff(); |
---|
245 | result += coeff*coeff; |
---|
246 | } |
---|
247 | return sqrt( result ); |
---|
248 | } |
---|
249 | //}}} |
---|