source: git/ntl/doc/ZZX.txt @ 199b5c

fieker-DuValspielwiese
Last change on this file since 199b5c was 2cfffe, checked in by Hans Schönemann <hannes@…>, 22 years ago
This commit was generated by cvs2svn to compensate for changes in r6316, which included commits to RCS files with non-trunk default branches. git-svn-id: file:///usr/local/Singular/svn/trunk@6317 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 15.3 KB
Line 
1
2
3/**************************************************************************\
4
5MODULE: ZZX
6
7SUMMARY:
8
9The class ZZX implements polynomials in ZZ[X], i.e., univariate
10polynomials with integer coefficients.
11
12Polynomial multiplication is implemented using one of 4 different
13algorithms:
14
151) classical
16
172) Karatsuba
18
193) 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
244) CRT/FFT --- performs an FFT by working modulo several
25     small primes...good for polynomials with moderate coefficients
26     and huge degree.
27
28The choice of algorithm is somewhat heuristic, and may not always be
29perfect.
30
31Many thanks to Juergen Gerhard <jngerhar@plato.uni-paderborn.de> for
32pointing out the deficiency in the NTL-1.0 ZZX arithmetic, and for
33contributing the Schoenhage/Strassen code.
34
35Extensive 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
45class ZZX {
46public:
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
74long operator==(const ZZX& a, const ZZX& b);
75long operator!=(const ZZX& a, const ZZX& b);
76
77long IsZero(const ZZX& a);  // test for 0
78long 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
91ZZX operator+(const ZZX& a, const ZZX& b);
92ZZX operator-(const ZZX& a, const ZZX& b);
93ZZX operator-(const ZZX& a); // unary -
94
95ZZX& operator+=(ZZX& x, const ZZX& a);
96ZZX& operator-=(ZZX& x, const ZZX& a);
97
98ZZX& operator++(ZZX& x);  // prefix
99void operator++(ZZX& x, int);  // postfix
100
101ZZX& operator--(ZZX& x);  // prefix
102void operator--(ZZX& x, int);  // postfix
103
104
105// procedural versions:
106
107void add(ZZX& x, const ZZX& a, const ZZX& b); // x = a + b
108void sub(ZZX& x, const ZZX& a, const ZZX& b); // x = a - b
109void 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
123ZZX operator*(const ZZX& a, const ZZX& b);
124
125ZZX& operator*=(ZZX& x, const ZZX& a);
126
127
128// procedural versions:
129
130void mul(ZZX& x, const ZZX& a, const ZZX& b); // x = a * b
131
132void sqr(ZZX& x, const ZZX& a); // x = a^2
133ZZX 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
143LeftShift by n means multiplication by X^n
144RightShift by n means division by X^n
145
146A negative shift amount reverses the direction of the shift.
147
148\**************************************************************************/
149
150// operator notation:
151
152ZZX operator<<(const ZZX& a, long n);
153ZZX operator>>(const ZZX& a, long n);
154
155ZZX& operator<<=(ZZX& x, long n);
156ZZX& operator>>=(ZZX& x, long n);
157
158// procedural versions:
159
160void LeftShift(ZZX& x, const ZZX& a, long n);
161ZZX LeftShift(const ZZX& a, long n);
162
163void RightShift(ZZX& x, const ZZX& a, long n);
164ZZX 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
196ZZX operator/(const ZZX& a, const ZZX& b);
197ZZX operator/(const ZZX& a, const ZZ& b);
198ZZX operator/(const ZZX& a, long b);
199
200ZZX operator%(const ZZX& a, const ZZX& b);
201
202ZZX& operator/=(ZZX& x, const ZZX& b);
203ZZX& operator/=(ZZX& x, const ZZ& b);
204ZZX& operator/=(ZZX& x, long b);
205
206ZZX& operator%=(ZZX& x, const ZZX& b);
207
208
209// procedural versions:
210
211void 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
216void div(ZZX& q, const ZZX& a, const ZZX& b);
217void div(ZZX& q, const ZZX& a, const ZZ& b);
218void div(ZZX& q, const ZZX& a, long b);
219// same as DivRem, but only computes q
220
221void rem(ZZX& r, const ZZX& a, const ZZX& b);
222// same as DivRem, but only computes r
223
224
225
226// divide predicates:
227
228long divide(ZZX& q, const ZZX& a, const ZZX& b);
229long divide(ZZX& q, const ZZX& a, const ZZ& b);
230long divide(ZZX& q, const ZZX& a, long b);
231// if b | a, sets q = a/b and returns 1; otherwise returns 0
232
233
234long divide(const ZZX& a, const ZZX& b);
235long divide(const ZZX& a, const ZZ& b);
236long 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
245void content(ZZ& d, const ZZX& f);
246ZZ content(const ZZX& f);
247// d = content of f, sign(d) == sign(LeadCoeff(f)); content(0) == 0
248
249void PrimitivePart(ZZX& pp, const ZZX& f);
250ZZX PrimitivePart(const ZZX& f);
251// pp = primitive part of f, LeadCoeff(pp) >= 0; PrimitivePart(0) == 0
252
253
254
255// pseudo-division:
256
257void 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
262void PseudoDiv(ZZX& q, const ZZX& a, const ZZX& b);
263ZZX PseudoDiv(const ZZX& a, const ZZX& b);
264// same as PseudoDivRem, but only computes q
265
266void PseudoRem(ZZX& r, const ZZX& a, const ZZX& b);
267ZZX 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
278void GCD(ZZX& d, const ZZX& a, const ZZX& b);
279ZZX GCD(const ZZX& a, const ZZX& b);
280// d = gcd(a, b), LeadCoeff(d) >= 0.  Uses a modular algorithm.
281
282
283void 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
296I/O format:
297
298   [a_0 a_1 ... a_n],
299
300represents the polynomial a_0 + a_1*X + ... + a_n*X^n.
301
302
303\**************************************************************************/
304
305
306istream& operator>>(istream& s, ZZX& x);
307ostream& operator<<(ostream& s, const ZZX& a);
308
309
310/**************************************************************************\
311
312                             Some utility routines
313
314\**************************************************************************/
315
316
317long deg(const ZZX& a);  returns degree of a; deg(0) == -1
318
319const 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
323const ZZ& LeadCoeff(const ZZX& a);
324// read-only reference to leading term of a, or zero if a == 0
325
326const ZZ& ConstTerm(const ZZX& a);
327// read-only reference to constant term of a, or zero if a == 0
328
329void SetCoeff(ZZX& x, long i, const ZZ& a);
330void SetCoeff(ZZX& x, long i, long a);
331// makes coefficient of X^i equal to a; error is raised if i < 0
332
333void SetCoeff(ZZX& x, long i);
334// makes coefficient of X^i equal to 1; error is raised if i < 0
335
336void SetX(ZZX& x); // x is set to the monomial X
337
338long IsX(const ZZX& a); // test if x = X
339
340void diff(ZZX& x, const ZZX& a); // x = derivative of a
341ZZX diff(const ZZX& a);
342
343long MaxBits(const ZZX& f);
344// returns max NumBits of coefficients of f
345
346void reverse(ZZX& x, const ZZX& a, long hi);
347ZZX reverse(const ZZX& a, long hi);
348
349void reverse(ZZX& x, const ZZX& a);
350ZZX 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
356void VectorCopy(vec_ZZ& x, const ZZX& a, long n);
357vec_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
367All routines require n >= 0, otherwise an error is raised.
368
369\**************************************************************************/
370
371
372void trunc(ZZX& x, const ZZX& a, long m); // x = a % X^m
373ZZX trunc(const ZZX& a, long m);
374
375void MulTrunc(ZZX& x, const ZZX& a, const ZZX& b, long n);
376ZZX MulTrunc(const ZZX& a, const ZZX& b, long n);
377// x = a * b % X^n
378
379void SqrTrunc(ZZX& x, const ZZX& a, long n);
380ZZX SqrTrunc(const ZZX& a, long n);
381// x = a^2 % X^n
382
383void InvTrunc(ZZX& x, const ZZX& a, long n);
384ZZX 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
394The modulus f must be monic with deg(f) > 0,
395and other arguments must have smaller degree.
396
397\**************************************************************************/
398
399void MulMod(ZZX& x, const ZZX& a, const ZZX& b, const ZZX& f);
400ZZX MulMod(const ZZX& a, const ZZX& b, const ZZX& f);
401// x = a * b mod f
402
403void SqrMod(ZZX& x, const ZZX& a, const ZZX& f);
404ZZX SqrMod(const ZZX& a, const ZZX& f);
405// x = a^2 mod f
406
407void MulByXMod(ZZX& x, const ZZX& a, const ZZX& f);
408ZZX 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
420void TraceMod(ZZ& res, const ZZX& a, const ZZX& f);
421ZZ 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
425void TraceVec(vec_ZZ& S, const ZZX& f);
426vec_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
433void resultant(ZZ& res, const ZZX& a, const ZZX& b, long deterministic=0);
434ZZ 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
441void NormMod(ZZ& res, const ZZX& a, const ZZX& f, long deterministic=0);
442ZZ 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
449void discriminant(ZZ& d, const ZZX& a, long deterministic=0);
450ZZ 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
456void CharPolyMod(ZZX& g, const ZZX& a, const ZZX& f, long deterministic=0);
457ZZX 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
463void MinPolyMod(ZZX& g, const ZZX& a, const ZZX& f);
464ZZX 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
478long CRT(ZZX& a, ZZ& prod, const zz_pX& A);
479long 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
495NTL_vector_decl(ZZX,vec_ZZX)
496// vec_ZZX
497
498NTL_eq_vector_decl(ZZX,vec_ZZX)
499// == and !=
500
501NTL_io_vector_decl(ZZX,vec_ZZX)
502// I/O operators
503
504
505/**************************************************************************\
506
507                                Miscellany
508
509
510A ZZX f is represented as a vec_ZZ, which can be accessed as
511f.rep.  The constant term is f.rep[0] and the leading coefficient is
512f.rep[f.rep.length()-1], except if f is zero, in which case
513f.rep.length() == 0.  Note that the leading coefficient is always
514nonzero (unless f is zero).  One can freely access and modify f.rep,
515but one should always ensure that the leading coefficient is nonzero,
516which can be done by invoking f.normalize().
517
518
519
520\**************************************************************************/
521
522
523void clear(ZZX& x); // x = 0
524void set(ZZX& x); // x = 1
525
526void ZZX::normalize();
527// f.normalize() strips leading zeros from f.rep.
528
529void ZZX::SetMaxLength(long n);
530// f.SetMaxLength(n) pre-allocate spaces for n coefficients.  The
531// polynomial that f represents is unchanged.
532
533void ZZX::kill();
534// f.kill() sets f to 0 and frees all memory held by f.  Equivalent to
535// f.rep.kill().
536
537ZZX::ZZX(INIT_SIZE_TYPE, long n);
538// ZZX(INIT_SIZE, n) initializes to zero, but space is pre-allocated
539// for n coefficients
540
541static const ZZX& zero();
542// ZZX::zero() is a read-only reference to 0
543
544void swap(ZZX& x, ZZX& y);
545// swap x & y (by swapping pointers)
546
Note: See TracBrowser for help on using the repository browser.