1 | |
---|
2 | |
---|
3 | /**************************************************************************\ |
---|
4 | |
---|
5 | MODULE: ZZX |
---|
6 | |
---|
7 | SUMMARY: |
---|
8 | |
---|
9 | The class ZZX implements polynomials in ZZ[X], i.e., univariate |
---|
10 | polynomials with integer coefficients. |
---|
11 | |
---|
12 | Polynomial multiplication is implemented using one of 4 different |
---|
13 | algorithms: |
---|
14 | |
---|
15 | 1) classical |
---|
16 | |
---|
17 | 2) Karatsuba |
---|
18 | |
---|
19 | 3) Schoenhage & Strassen --- performs an FFT by working |
---|
20 | modulo a "Fermat number" of appropriate size... |
---|
21 | good for polynomials with huge coefficients |
---|
22 | and moderate degree |
---|
23 | |
---|
24 | 4) CRT/FFT --- performs an FFT by working modulo several |
---|
25 | small primes...good for polynomials with moderate coefficients |
---|
26 | and huge degree. |
---|
27 | |
---|
28 | The choice of algorithm is somewhat heuristic, and may not always be |
---|
29 | perfect. |
---|
30 | |
---|
31 | Many thanks to Juergen Gerhard <jngerhar@plato.uni-paderborn.de> for |
---|
32 | pointing out the deficiency in the NTL-1.0 ZZX arithmetic, and for |
---|
33 | contributing the Schoenhage/Strassen code. |
---|
34 | |
---|
35 | Extensive use is made of modular algorithms to enhance performance |
---|
36 | (e.g., the GCD algorithm and amny others). |
---|
37 | |
---|
38 | \**************************************************************************/ |
---|
39 | |
---|
40 | #include <NTL/vec_ZZ.h> |
---|
41 | #include "zz_pX.h" |
---|
42 | #include <NTL/ZZ_pX.h> |
---|
43 | |
---|
44 | |
---|
45 | class ZZX { |
---|
46 | public: |
---|
47 | |
---|
48 | |
---|
49 | ZZX(); // initial value 0 |
---|
50 | |
---|
51 | ZZX(const ZZX& a); // copy |
---|
52 | |
---|
53 | ZZX& operator=(const ZZX& a); // assignment |
---|
54 | ZZX& operator=(const ZZ& a); |
---|
55 | ZZX& operator=(long a); |
---|
56 | |
---|
57 | ~ZZX(); |
---|
58 | |
---|
59 | ZZX(long i, const ZZ& c); // initial value X^i*c |
---|
60 | ZZX(long i, long c); |
---|
61 | |
---|
62 | // ... |
---|
63 | |
---|
64 | }; |
---|
65 | |
---|
66 | |
---|
67 | |
---|
68 | /**************************************************************************\ |
---|
69 | |
---|
70 | Comparison |
---|
71 | |
---|
72 | \**************************************************************************/ |
---|
73 | |
---|
74 | long operator==(const ZZX& a, const ZZX& b); |
---|
75 | long operator!=(const ZZX& a, const ZZX& b); |
---|
76 | |
---|
77 | long IsZero(const ZZX& a); // test for 0 |
---|
78 | long IsOne(const ZZX& a); // test for 1 |
---|
79 | |
---|
80 | // PROMOTIONS: operators ==, != promote {long, ZZ} to ZZX on (a, b). |
---|
81 | |
---|
82 | |
---|
83 | /**************************************************************************\ |
---|
84 | |
---|
85 | Addition |
---|
86 | |
---|
87 | \**************************************************************************/ |
---|
88 | |
---|
89 | // operator notation: |
---|
90 | |
---|
91 | ZZX operator+(const ZZX& a, const ZZX& b); |
---|
92 | ZZX operator-(const ZZX& a, const ZZX& b); |
---|
93 | ZZX operator-(const ZZX& a); // unary - |
---|
94 | |
---|
95 | ZZX& operator+=(ZZX& x, const ZZX& a); |
---|
96 | ZZX& operator-=(ZZX& x, const ZZX& a); |
---|
97 | |
---|
98 | ZZX& operator++(ZZX& x); // prefix |
---|
99 | void operator++(ZZX& x, int); // postfix |
---|
100 | |
---|
101 | ZZX& operator--(ZZX& x); // prefix |
---|
102 | void operator--(ZZX& x, int); // postfix |
---|
103 | |
---|
104 | |
---|
105 | // procedural versions: |
---|
106 | |
---|
107 | void add(ZZX& x, const ZZX& a, const ZZX& b); // x = a + b |
---|
108 | void sub(ZZX& x, const ZZX& a, const ZZX& b); // x = a - b |
---|
109 | void negate(ZZX& x, const ZZX& a); // x = -a |
---|
110 | |
---|
111 | // PROMOTIONS: binary +, - and procedures add, sub promote {long, ZZ} |
---|
112 | // to ZZX on (a, b). |
---|
113 | |
---|
114 | |
---|
115 | /**************************************************************************\ |
---|
116 | |
---|
117 | Multiplication |
---|
118 | |
---|
119 | \**************************************************************************/ |
---|
120 | |
---|
121 | // operator notation: |
---|
122 | |
---|
123 | ZZX operator*(const ZZX& a, const ZZX& b); |
---|
124 | |
---|
125 | ZZX& operator*=(ZZX& x, const ZZX& a); |
---|
126 | |
---|
127 | |
---|
128 | // procedural versions: |
---|
129 | |
---|
130 | void mul(ZZX& x, const ZZX& a, const ZZX& b); // x = a * b |
---|
131 | |
---|
132 | void sqr(ZZX& x, const ZZX& a); // x = a^2 |
---|
133 | ZZX sqr(const ZZX& a); |
---|
134 | |
---|
135 | // PROMOTIONS: operator * and procedure mul promote {long, ZZ} to ZZX |
---|
136 | // on (a, b). |
---|
137 | |
---|
138 | |
---|
139 | /**************************************************************************\ |
---|
140 | |
---|
141 | Shift Operations |
---|
142 | |
---|
143 | LeftShift by n means multiplication by X^n |
---|
144 | RightShift by n means division by X^n |
---|
145 | |
---|
146 | A negative shift amount reverses the direction of the shift. |
---|
147 | |
---|
148 | \**************************************************************************/ |
---|
149 | |
---|
150 | // operator notation: |
---|
151 | |
---|
152 | ZZX operator<<(const ZZX& a, long n); |
---|
153 | ZZX operator>>(const ZZX& a, long n); |
---|
154 | |
---|
155 | ZZX& operator<<=(ZZX& x, long n); |
---|
156 | ZZX& operator>>=(ZZX& x, long n); |
---|
157 | |
---|
158 | // procedural versions: |
---|
159 | |
---|
160 | void LeftShift(ZZX& x, const ZZX& a, long n); |
---|
161 | ZZX LeftShift(const ZZX& a, long n); |
---|
162 | |
---|
163 | void RightShift(ZZX& x, const ZZX& a, long n); |
---|
164 | ZZX RightShift(const ZZX& a, long n); |
---|
165 | |
---|
166 | |
---|
167 | |
---|
168 | /**************************************************************************\ |
---|
169 | |
---|
170 | Division |
---|
171 | |
---|
172 | \**************************************************************************/ |
---|
173 | |
---|
174 | |
---|
175 | // Given polynomials a, b in ZZ[X], there exist polynomials |
---|
176 | // q, r in QQ[X] such that a = b*q + r, deg(r) < deg(b). |
---|
177 | // These routines return q and/or r if q and/or r lie(s) in ZZ[X], |
---|
178 | // and otherwise raise an error. |
---|
179 | |
---|
180 | // Note that if the leading coefficient of b is 1 or -1, |
---|
181 | // then q and r always lie in ZZ[X], and no error can occur. |
---|
182 | |
---|
183 | // For example, you can write f/2 for a ZZX f. If all coefficients |
---|
184 | // of f are even, the result is f with a factor of two removed; |
---|
185 | // otherwise, an error is raised. More generally, f/g will be |
---|
186 | // evaluate q in ZZ[X] such that f = q*g if such a q exists, |
---|
187 | // and will otherwise raise an error. |
---|
188 | |
---|
189 | // See also below the routines for pseudo-division and division |
---|
190 | // predicates for routines that are perhaps more useful in |
---|
191 | // some situations. |
---|
192 | |
---|
193 | |
---|
194 | // operator notation: |
---|
195 | |
---|
196 | ZZX operator/(const ZZX& a, const ZZX& b); |
---|
197 | ZZX operator/(const ZZX& a, const ZZ& b); |
---|
198 | ZZX operator/(const ZZX& a, long b); |
---|
199 | |
---|
200 | ZZX operator%(const ZZX& a, const ZZX& b); |
---|
201 | |
---|
202 | ZZX& operator/=(ZZX& x, const ZZX& b); |
---|
203 | ZZX& operator/=(ZZX& x, const ZZ& b); |
---|
204 | ZZX& operator/=(ZZX& x, long b); |
---|
205 | |
---|
206 | ZZX& operator%=(ZZX& x, const ZZX& b); |
---|
207 | |
---|
208 | |
---|
209 | // procedural versions: |
---|
210 | |
---|
211 | void DivRem(ZZX& q, ZZX& r, const ZZX& a, const ZZX& b); |
---|
212 | // computes q, r such that a = b q + r and deg(r) < deg(b). |
---|
213 | // requires LeadCoeff(b) is a unit (+1, -1); otherwise, |
---|
214 | // an error is raised. |
---|
215 | |
---|
216 | void div(ZZX& q, const ZZX& a, const ZZX& b); |
---|
217 | void div(ZZX& q, const ZZX& a, const ZZ& b); |
---|
218 | void div(ZZX& q, const ZZX& a, long b); |
---|
219 | // same as DivRem, but only computes q |
---|
220 | |
---|
221 | void rem(ZZX& r, const ZZX& a, const ZZX& b); |
---|
222 | // same as DivRem, but only computes r |
---|
223 | |
---|
224 | |
---|
225 | |
---|
226 | // divide predicates: |
---|
227 | |
---|
228 | long divide(ZZX& q, const ZZX& a, const ZZX& b); |
---|
229 | long divide(ZZX& q, const ZZX& a, const ZZ& b); |
---|
230 | long divide(ZZX& q, const ZZX& a, long b); |
---|
231 | // if b | a, sets q = a/b and returns 1; otherwise returns 0 |
---|
232 | |
---|
233 | |
---|
234 | long divide(const ZZX& a, const ZZX& b); |
---|
235 | long divide(const ZZX& a, const ZZ& b); |
---|
236 | long divide(const ZZX& a, long b); |
---|
237 | // if b | a, returns 1; otherwise returns 0 |
---|
238 | |
---|
239 | // These algorithms employ a modular approach, performing the division |
---|
240 | // modulo small primes (reconstructing q via the CRT). It is |
---|
241 | // usually much faster than the general division routines above |
---|
242 | // (especially when b does not divide a). |
---|
243 | |
---|
244 | |
---|
245 | void content(ZZ& d, const ZZX& f); |
---|
246 | ZZ content(const ZZX& f); |
---|
247 | // d = content of f, sign(d) == sign(LeadCoeff(f)); content(0) == 0 |
---|
248 | |
---|
249 | void PrimitivePart(ZZX& pp, const ZZX& f); |
---|
250 | ZZX PrimitivePart(const ZZX& f); |
---|
251 | // pp = primitive part of f, LeadCoeff(pp) >= 0; PrimitivePart(0) == 0 |
---|
252 | |
---|
253 | |
---|
254 | |
---|
255 | // pseudo-division: |
---|
256 | |
---|
257 | void PseudoDivRem(ZZX& q, ZZX& r, const ZZX& a, const ZZX& b); |
---|
258 | // performs pseudo-division: computes q and r with deg(r) < deg(b), |
---|
259 | // and LeadCoeff(b)^(deg(a)-deg(b)+1) a = b q + r. Only the classical |
---|
260 | // algorithm is used. |
---|
261 | |
---|
262 | void PseudoDiv(ZZX& q, const ZZX& a, const ZZX& b); |
---|
263 | ZZX PseudoDiv(const ZZX& a, const ZZX& b); |
---|
264 | // same as PseudoDivRem, but only computes q |
---|
265 | |
---|
266 | void PseudoRem(ZZX& r, const ZZX& a, const ZZX& b); |
---|
267 | ZZX PseudoRem(const ZZX& a, const ZZX& b); |
---|
268 | // same as PseudoDivRem, but only computes r |
---|
269 | |
---|
270 | |
---|
271 | /**************************************************************************\ |
---|
272 | |
---|
273 | GCD's |
---|
274 | |
---|
275 | \**************************************************************************/ |
---|
276 | |
---|
277 | |
---|
278 | void GCD(ZZX& d, const ZZX& a, const ZZX& b); |
---|
279 | ZZX GCD(const ZZX& a, const ZZX& b); |
---|
280 | // d = gcd(a, b), LeadCoeff(d) >= 0. Uses a modular algorithm. |
---|
281 | |
---|
282 | |
---|
283 | void XGCD(ZZ& r, ZZX& s, ZZX& t, const ZZX& a, const ZZX& b, |
---|
284 | long deterministic=0); |
---|
285 | // r = resultant of a and b; if r != 0, then computes s and t such |
---|
286 | // that: a*s + b*t = r; otherwise s and t not affected. if |
---|
287 | // !deterministic, then resultant computation may use a randomized |
---|
288 | // strategy that errs with probability no more than 2^{-80}. |
---|
289 | |
---|
290 | |
---|
291 | |
---|
292 | /**************************************************************************\ |
---|
293 | |
---|
294 | Input/Output |
---|
295 | |
---|
296 | I/O format: |
---|
297 | |
---|
298 | [a_0 a_1 ... a_n], |
---|
299 | |
---|
300 | represents the polynomial a_0 + a_1*X + ... + a_n*X^n. |
---|
301 | |
---|
302 | |
---|
303 | \**************************************************************************/ |
---|
304 | |
---|
305 | |
---|
306 | istream& operator>>(istream& s, ZZX& x); |
---|
307 | ostream& operator<<(ostream& s, const ZZX& a); |
---|
308 | |
---|
309 | |
---|
310 | /**************************************************************************\ |
---|
311 | |
---|
312 | Some utility routines |
---|
313 | |
---|
314 | \**************************************************************************/ |
---|
315 | |
---|
316 | |
---|
317 | long deg(const ZZX& a); returns degree of a; deg(0) == -1 |
---|
318 | |
---|
319 | const ZZ& coeff(const ZZX& a, long i); |
---|
320 | // returns a read-only reference to a.rep[i], or zero if i not in |
---|
321 | // range |
---|
322 | |
---|
323 | const ZZ& LeadCoeff(const ZZX& a); |
---|
324 | // read-only reference to leading term of a, or zero if a == 0 |
---|
325 | |
---|
326 | const ZZ& ConstTerm(const ZZX& a); |
---|
327 | // read-only reference to constant term of a, or zero if a == 0 |
---|
328 | |
---|
329 | void SetCoeff(ZZX& x, long i, const ZZ& a); |
---|
330 | void SetCoeff(ZZX& x, long i, long a); |
---|
331 | // makes coefficient of X^i equal to a; error is raised if i < 0 |
---|
332 | |
---|
333 | void SetCoeff(ZZX& x, long i); |
---|
334 | // makes coefficient of X^i equal to 1; error is raised if i < 0 |
---|
335 | |
---|
336 | void SetX(ZZX& x); // x is set to the monomial X |
---|
337 | |
---|
338 | long IsX(const ZZX& a); // test if x = X |
---|
339 | |
---|
340 | void diff(ZZX& x, const ZZX& a); // x = derivative of a |
---|
341 | ZZX diff(const ZZX& a); |
---|
342 | |
---|
343 | long MaxBits(const ZZX& f); |
---|
344 | // returns max NumBits of coefficients of f |
---|
345 | |
---|
346 | void reverse(ZZX& x, const ZZX& a, long hi); |
---|
347 | ZZX reverse(const ZZX& a, long hi); |
---|
348 | |
---|
349 | void reverse(ZZX& x, const ZZX& a); |
---|
350 | ZZX reverse(const ZZX& a); |
---|
351 | |
---|
352 | // x = reverse of a[0]..a[hi] (hi >= -1); |
---|
353 | // hi defaults to deg(a) in second version |
---|
354 | |
---|
355 | |
---|
356 | void VectorCopy(vec_ZZ& x, const ZZX& a, long n); |
---|
357 | vec_ZZ VectorCopy(const ZZX& a, long n); |
---|
358 | // x = copy of coefficient vector of a of length exactly n. |
---|
359 | // input is truncated or padded with zeroes as appropriate. |
---|
360 | |
---|
361 | |
---|
362 | |
---|
363 | /**************************************************************************\ |
---|
364 | |
---|
365 | Arithmetic mod X^n |
---|
366 | |
---|
367 | All routines require n >= 0, otherwise an error is raised. |
---|
368 | |
---|
369 | \**************************************************************************/ |
---|
370 | |
---|
371 | |
---|
372 | void trunc(ZZX& x, const ZZX& a, long m); // x = a % X^m |
---|
373 | ZZX trunc(const ZZX& a, long m); |
---|
374 | |
---|
375 | void MulTrunc(ZZX& x, const ZZX& a, const ZZX& b, long n); |
---|
376 | ZZX MulTrunc(const ZZX& a, const ZZX& b, long n); |
---|
377 | // x = a * b % X^n |
---|
378 | |
---|
379 | void SqrTrunc(ZZX& x, const ZZX& a, long n); |
---|
380 | ZZX SqrTrunc(const ZZX& a, long n); |
---|
381 | // x = a^2 % X^n |
---|
382 | |
---|
383 | void InvTrunc(ZZX& x, const ZZX& a, long n); |
---|
384 | ZZX InvTrunc(const ZZX& a, long n); |
---|
385 | // computes x = a^{-1} % X^m. Must have ConstTerm(a) invertible. |
---|
386 | |
---|
387 | |
---|
388 | |
---|
389 | |
---|
390 | /**************************************************************************\ |
---|
391 | |
---|
392 | Modular Arithmetic |
---|
393 | |
---|
394 | The modulus f must be monic with deg(f) > 0, |
---|
395 | and other arguments must have smaller degree. |
---|
396 | |
---|
397 | \**************************************************************************/ |
---|
398 | |
---|
399 | void MulMod(ZZX& x, const ZZX& a, const ZZX& b, const ZZX& f); |
---|
400 | ZZX MulMod(const ZZX& a, const ZZX& b, const ZZX& f); |
---|
401 | // x = a * b mod f |
---|
402 | |
---|
403 | void SqrMod(ZZX& x, const ZZX& a, const ZZX& f); |
---|
404 | ZZX SqrMod(const ZZX& a, const ZZX& f); |
---|
405 | // x = a^2 mod f |
---|
406 | |
---|
407 | void MulByXMod(ZZX& x, const ZZX& a, const ZZX& f); |
---|
408 | ZZX MulByXMod(const ZZX& a, const ZZX& f); |
---|
409 | // x = a*X mod f |
---|
410 | |
---|
411 | |
---|
412 | /**************************************************************************\ |
---|
413 | |
---|
414 | traces, norms, resultants, discriminants, |
---|
415 | minimal and characteristic polynomials |
---|
416 | |
---|
417 | \**************************************************************************/ |
---|
418 | |
---|
419 | |
---|
420 | void TraceMod(ZZ& res, const ZZX& a, const ZZX& f); |
---|
421 | ZZ TraceMod(const ZZX& a, const ZZX& f); |
---|
422 | // res = trace of (a mod f). f must be monic, 0 < deg(f), deg(a) < |
---|
423 | // deg(f) |
---|
424 | |
---|
425 | void TraceVec(vec_ZZ& S, const ZZX& f); |
---|
426 | vec_ZZ TraceVec(const ZZX& f); |
---|
427 | // S[i] = Trace(X^i mod f), for i = 0..deg(f)-1. |
---|
428 | // f must be a monic polynomial. |
---|
429 | |
---|
430 | |
---|
431 | // The following routines use a modular approach. |
---|
432 | |
---|
433 | void resultant(ZZ& res, const ZZX& a, const ZZX& b, long deterministic=0); |
---|
434 | ZZ resultant(const ZZX& a, const ZZX& b, long deterministic=0); |
---|
435 | // res = resultant of a and b. If !deterministic, then it may use a |
---|
436 | // randomized strategy that errs with probability no more than |
---|
437 | // 2^{-80}. |
---|
438 | |
---|
439 | |
---|
440 | |
---|
441 | void NormMod(ZZ& res, const ZZX& a, const ZZX& f, long deterministic=0); |
---|
442 | ZZ NormMod(const ZZX& a, const ZZX& f, long deterministic=0); |
---|
443 | // res = norm of (a mod f). f must be monic, 0 < deg(f), deg(a) < |
---|
444 | // deg(f). If !deterministic, then it may use a randomized strategy |
---|
445 | // that errs with probability no more than 2^{-80}. |
---|
446 | |
---|
447 | |
---|
448 | |
---|
449 | void discriminant(ZZ& d, const ZZX& a, long deterministic=0); |
---|
450 | ZZ discriminant(const ZZX& a, long deterministic=0); |
---|
451 | // d = discriminant of a = (-1)^{m(m-1)/2} resultant(a, a')/lc(a), |
---|
452 | // where m = deg(a). If !deterministic, then it may use a randomized |
---|
453 | // strategy that errs with probability no more than 2^{-80}. |
---|
454 | |
---|
455 | |
---|
456 | void CharPolyMod(ZZX& g, const ZZX& a, const ZZX& f, long deterministic=0); |
---|
457 | ZZX CharPolyMod(const ZZX& a, const ZZX& f, long deterministic=0); |
---|
458 | // g = char poly of (a mod f). f must be monic. If !deterministic, |
---|
459 | // then it may use a randomized strategy that errs with probability no |
---|
460 | // more than 2^{-80}. |
---|
461 | |
---|
462 | |
---|
463 | void MinPolyMod(ZZX& g, const ZZX& a, const ZZX& f); |
---|
464 | ZZX MinPolyMod(const ZZX& a, const ZZX& f); |
---|
465 | // g = min poly of (a mod f). f must be monic, 0 < deg(f), deg(a) < |
---|
466 | // deg(f). May use a probabilistic strategy that errs with |
---|
467 | // probability no more than 2^{-80}. |
---|
468 | |
---|
469 | |
---|
470 | |
---|
471 | |
---|
472 | /**************************************************************************\ |
---|
473 | |
---|
474 | Incremental Chinese Remaindering |
---|
475 | |
---|
476 | \**************************************************************************/ |
---|
477 | |
---|
478 | long CRT(ZZX& a, ZZ& prod, const zz_pX& A); |
---|
479 | long CRT(ZZX& a, ZZ& prod, const ZZ_pX& A); |
---|
480 | // Incremental Chinese Remaindering: If p is the current zz_p/ZZ_p modulus with |
---|
481 | // (p, prod) = 1; Computes a' such that a' = a mod prod and a' = A mod p, |
---|
482 | // with coefficients in the interval (-p*prod/2, p*prod/2]; |
---|
483 | // Sets a := a', prod := p*prod, and returns 1 if a's value changed. |
---|
484 | |
---|
485 | |
---|
486 | |
---|
487 | |
---|
488 | |
---|
489 | /**************************************************************************\ |
---|
490 | |
---|
491 | vectors of ZZX's |
---|
492 | |
---|
493 | \**************************************************************************/ |
---|
494 | |
---|
495 | NTL_vector_decl(ZZX,vec_ZZX) |
---|
496 | // vec_ZZX |
---|
497 | |
---|
498 | NTL_eq_vector_decl(ZZX,vec_ZZX) |
---|
499 | // == and != |
---|
500 | |
---|
501 | NTL_io_vector_decl(ZZX,vec_ZZX) |
---|
502 | // I/O operators |
---|
503 | |
---|
504 | |
---|
505 | /**************************************************************************\ |
---|
506 | |
---|
507 | Miscellany |
---|
508 | |
---|
509 | |
---|
510 | A ZZX f is represented as a vec_ZZ, which can be accessed as |
---|
511 | f.rep. The constant term is f.rep[0] and the leading coefficient is |
---|
512 | f.rep[f.rep.length()-1], except if f is zero, in which case |
---|
513 | f.rep.length() == 0. Note that the leading coefficient is always |
---|
514 | nonzero (unless f is zero). One can freely access and modify f.rep, |
---|
515 | but one should always ensure that the leading coefficient is nonzero, |
---|
516 | which can be done by invoking f.normalize(). |
---|
517 | |
---|
518 | |
---|
519 | |
---|
520 | \**************************************************************************/ |
---|
521 | |
---|
522 | |
---|
523 | void clear(ZZX& x); // x = 0 |
---|
524 | void set(ZZX& x); // x = 1 |
---|
525 | |
---|
526 | void ZZX::normalize(); |
---|
527 | // f.normalize() strips leading zeros from f.rep. |
---|
528 | |
---|
529 | void ZZX::SetMaxLength(long n); |
---|
530 | // f.SetMaxLength(n) pre-allocate spaces for n coefficients. The |
---|
531 | // polynomial that f represents is unchanged. |
---|
532 | |
---|
533 | void ZZX::kill(); |
---|
534 | // f.kill() sets f to 0 and frees all memory held by f. Equivalent to |
---|
535 | // f.rep.kill(). |
---|
536 | |
---|
537 | ZZX::ZZX(INIT_SIZE_TYPE, long n); |
---|
538 | // ZZX(INIT_SIZE, n) initializes to zero, but space is pre-allocated |
---|
539 | // for n coefficients |
---|
540 | |
---|
541 | static const ZZX& zero(); |
---|
542 | // ZZX::zero() is a read-only reference to 0 |
---|
543 | |
---|
544 | void swap(ZZX& x, ZZX& y); |
---|
545 | // swap x & y (by swapping pointers) |
---|
546 | |
---|