source: git/ntl/include/NTL/ZZ_pX.h @ 77902f

spielwiese
Last change on this file since 77902f was 77902f, checked in by Hans Schönemann <hannes@…>, 21 years ago
*hannes: iostream adaption git-svn-id: file:///usr/local/Singular/svn/trunk@6321 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 34.1 KB
Line 
1
2
3#ifndef NTL_ZZ_pX__H
4#define NTL_ZZ_pX__H
5
6#include <NTL/vector.h>
7#include <NTL/ZZ_p.h>
8#include <NTL/vec_ZZ.h>
9#include <NTL/vec_ZZ_p.h>
10#include <NTL/FFT.h>
11
12NTL_OPEN_NNS
13
14
15
16
17// some cross-over points
18// macros are used so as to be consistent with zz_pX
19
20#define NTL_ZZ_pX_FFT_CROSSOVER (20) 
21#define NTL_ZZ_pX_NEWTON_CROSSOVER (45)
22#define NTL_ZZ_pX_DIV_CROSSOVER (90)
23#define NTL_ZZ_pX_HalfGCD_CROSSOVER (25)
24#define NTL_ZZ_pX_GCD_CROSSOVER (180)
25#define NTL_ZZ_pX_BERMASS_CROSSOVER (90)
26#define NTL_ZZ_pX_TRACE_CROSSOVER (90)
27
28
29
30/************************************************************
31
32                         ZZ_pX
33
34The class ZZ_pX implements polynomial arithmetic modulo p.
35Polynomials are represented as vec_ZZ_p's.
36If f is a ZZ_pX, then f.rep is a vec_ZZ_p.
37The zero polynomial is represented as a zero length vector.
38Otherwise. f.rep[0] is the constant-term, and f.rep[f.rep.length()-1]
39is the leading coefficient, which is always non-zero.
40The member f.rep is public, so the vector representation is fully
41accessible.
42Use the member function normalize() to strip leading zeros.
43
44**************************************************************/
45
46
47class ZZ_pX {
48
49public:
50
51typedef vec_ZZ_p VectorBaseType; 
52
53
54vec_ZZ_p rep;
55
56
57/***************************************************************
58
59          Constructors, Destructors, and Assignment
60
61****************************************************************/
62
63
64ZZ_pX()
65//  initial value 0
66
67   { }
68
69
70ZZ_pX(INIT_SIZE_TYPE, long n) { rep.SetMaxLength(n); }
71
72ZZ_pX(const ZZ_pX& a) : rep(a.rep) { }
73// initial value is a
74
75
76ZZ_pX& operator=(const ZZ_pX& a) 
77   { rep = a.rep; return *this; }
78
79~ZZ_pX() { }
80
81void normalize();
82// strip leading zeros
83
84void SetMaxLength(long n) 
85// pre-allocate space for n coefficients.
86// Value is unchanged
87
88   { rep.SetMaxLength(n); }
89
90
91void kill() 
92// free space held by this polynomial.  Value becomes 0.
93
94   { rep.kill(); }
95
96static const ZZ_pX& zero();
97
98
99ZZ_pX(ZZ_pX& x, INIT_TRANS_TYPE) : rep(x.rep, INIT_TRANS) { }
100
101inline ZZ_pX(long i, const ZZ_p& c);
102inline ZZ_pX(long i, long c);
103
104ZZ_pX& operator=(long a);
105ZZ_pX& operator=(const ZZ_p& a);
106
107
108};
109
110
111
112
113/********************************************************************
114
115                           input and output
116
117I/O format:
118
119   [a_0 a_1 ... a_n],
120
121represents the polynomial a_0 + a_1*X + ... + a_n*X^n.
122
123On output, all coefficients will be integers between 0 and p-1,
124amd a_n not zero (the zero polynomial is [ ]).
125On input, the coefficients are arbitrary integers which are
126then reduced modulo p, and leading zeros stripped.
127
128*********************************************************************/
129
130
131/**********************************************************
132
133                   Some utility routines
134
135***********************************************************/
136
137
138inline long deg(const ZZ_pX& a) { return a.rep.length() - 1; }
139// degree of a polynomial.
140// note that the zero polynomial has degree -1.
141
142const ZZ_p& coeff(const ZZ_pX& a, long i);
143// zero if i not in range
144
145void GetCoeff(ZZ_p& x, const ZZ_pX& a, long i);
146// x = a[i], or zero if i not in range
147
148const ZZ_p& LeadCoeff(const ZZ_pX& a);
149// zero if a == 0
150
151const ZZ_p& ConstTerm(const ZZ_pX& a);
152// zero if a == 0
153
154void SetCoeff(ZZ_pX& x, long i, const ZZ_p& a);
155// x[i] = a, error is raised if i < 0
156
157void SetCoeff(ZZ_pX& x, long i, long a);
158
159void SetCoeff(ZZ_pX& x, long i);
160// x[i] = 1, error is raised if i < 0
161
162inline ZZ_pX::ZZ_pX(long i, const ZZ_p& a)
163   { SetCoeff(*this, i, a); } 
164
165inline ZZ_pX::ZZ_pX(long i, long a)
166   { SetCoeff(*this, i, a); } 
167
168void SetX(ZZ_pX& x);
169// x is set to the monomial X
170
171long IsX(const ZZ_pX& a);
172// test if x = X
173
174inline void clear(ZZ_pX& x) 
175// x = 0
176
177   { x.rep.SetLength(0); }
178
179inline void set(ZZ_pX& x)
180// x = 1
181
182   { x.rep.SetLength(1); set(x.rep[0]); }
183
184inline void swap(ZZ_pX& x, ZZ_pX& y)
185// swap x & y (only pointers are swapped)
186
187   { swap(x.rep, y.rep); }
188
189void random(ZZ_pX& x, long n);
190inline ZZ_pX random_ZZ_pX(long n)
191   { ZZ_pX x; random(x, n); NTL_OPT_RETURN(ZZ_pX, x); }
192// generate a random polynomial of degree < n
193
194void trunc(ZZ_pX& x, const ZZ_pX& a, long m);
195// x = a % X^m
196
197inline ZZ_pX trunc(const ZZ_pX& a, long m)
198   { ZZ_pX x; trunc(x, a, m); NTL_OPT_RETURN(ZZ_pX, x); }
199
200void RightShift(ZZ_pX& x, const ZZ_pX& a, long n);
201// x = a/X^n
202
203inline ZZ_pX RightShift(const ZZ_pX& a, long n)
204   { ZZ_pX x; RightShift(x, a, n); NTL_OPT_RETURN(ZZ_pX, x); }
205
206void LeftShift(ZZ_pX& x, const ZZ_pX& a, long n);
207// x = a*X^n
208
209inline ZZ_pX LeftShift(const ZZ_pX& a, long n)
210   { ZZ_pX x; LeftShift(x, a, n); NTL_OPT_RETURN(ZZ_pX, x); }
211
212#ifndef NTL_TRANSITION
213
214inline ZZ_pX operator>>(const ZZ_pX& a, long n)
215   { ZZ_pX x; RightShift(x, a, n); NTL_OPT_RETURN(ZZ_pX, x); }
216
217inline ZZ_pX operator<<(const ZZ_pX& a, long n)
218   { ZZ_pX x; LeftShift(x, a, n); NTL_OPT_RETURN(ZZ_pX, x); }
219
220inline ZZ_pX& operator<<=(ZZ_pX& x, long n)
221   { LeftShift(x, x, n); return x; }
222
223inline ZZ_pX& operator>>=(ZZ_pX& x, long n)
224   { RightShift(x, x, n); return x; }
225
226#endif
227
228
229
230void diff(ZZ_pX& x, const ZZ_pX& a);
231// x = derivative of a
232
233inline ZZ_pX diff(const ZZ_pX& a)
234   { ZZ_pX x; diff(x, a); NTL_OPT_RETURN(ZZ_pX, x); }
235
236
237void MakeMonic(ZZ_pX& x);
238
239void reverse(ZZ_pX& c, const ZZ_pX& a, long hi);
240
241inline ZZ_pX reverse(const ZZ_pX& a, long hi)
242   { ZZ_pX x; reverse(x, a, hi); NTL_OPT_RETURN(ZZ_pX, x); }
243
244inline void reverse(ZZ_pX& c, const ZZ_pX& a)
245{  reverse(c, a, deg(a)); }
246
247inline ZZ_pX reverse(const ZZ_pX& a)
248   { ZZ_pX x; reverse(x, a); NTL_OPT_RETURN(ZZ_pX, x); }
249
250inline void VectorCopy(vec_ZZ_p& x, const ZZ_pX& a, long n)
251   { VectorCopy(x, a.rep, n); }
252
253inline vec_ZZ_p VectorCopy(const ZZ_pX& a, long n)
254   { return VectorCopy(a.rep, n); }
255
256
257
258
259/*******************************************************************
260
261                        conversion routines
262
263********************************************************************/
264
265
266
267void conv(ZZ_pX& x, long a);
268void conv(ZZ_pX& x, const ZZ& a);
269void conv(ZZ_pX& x, const ZZ_p& a);
270void conv(ZZ_pX& x, const vec_ZZ_p& a);
271
272inline ZZ_pX to_ZZ_pX(long a)
273   { ZZ_pX x; conv(x, a); NTL_OPT_RETURN(ZZ_pX, x); }
274
275inline ZZ_pX to_ZZ_pX(const ZZ& a)
276   { ZZ_pX x; conv(x, a); NTL_OPT_RETURN(ZZ_pX, x); }
277
278inline ZZ_pX to_ZZ_pX(const ZZ_p& a)
279   { ZZ_pX x; conv(x, a); NTL_OPT_RETURN(ZZ_pX, x); }
280
281inline ZZ_pX to_ZZ_pX(const vec_ZZ_p& a)
282   { ZZ_pX x; conv(x, a); NTL_OPT_RETURN(ZZ_pX, x); }
283
284
285
286/*************************************************************
287
288                        Comparison
289
290**************************************************************/
291
292long IsZero(const ZZ_pX& a); 
293
294long IsOne(const ZZ_pX& a);
295
296inline long operator==(const ZZ_pX& a, const ZZ_pX& b)
297{
298   return a.rep == b.rep;
299}
300
301inline long operator!=(const ZZ_pX& a, const ZZ_pX& b)
302{
303   return !(a == b);
304}
305
306long operator==(const ZZ_pX& a, long b);
307long operator==(const ZZ_pX& a, const ZZ_p& b);
308
309inline long operator==(long a, const ZZ_pX& b) { return b == a; }
310inline long operator==(const ZZ_p& a, const ZZ_pX& b) { return b == a; }
311
312inline long operator!=(const ZZ_pX& a, long b) { return !(a == b); }
313inline long operator!=(const ZZ_pX& a, const ZZ_p& b) { return !(a == b); }
314
315inline long operator!=(long a, const ZZ_pX& b) { return !(a == b); }
316inline long operator!=(const ZZ_p& a, const ZZ_pX& b) { return !(a == b); }
317
318
319/***************************************************************
320
321                         Addition
322
323****************************************************************/
324
325void add(ZZ_pX& x, const ZZ_pX& a, const ZZ_pX& b);
326// x = a + b
327
328void sub(ZZ_pX& x, const ZZ_pX& a, const ZZ_pX& b);
329// x = a - b
330
331void negate(ZZ_pX& x, const ZZ_pX& a);
332// x = -a
333
334// scalar versions
335
336void add(ZZ_pX& x, const ZZ_pX& a, const ZZ_p& b); // x = a + b
337void add(ZZ_pX& x, const ZZ_pX& a, long b);
338
339inline void add(ZZ_pX& x, const ZZ_p& a, const ZZ_pX& b) { add(x, b, a); }
340inline void add(ZZ_pX& x, long a, const ZZ_pX& b) { add(x, b, a); }
341
342
343void sub(ZZ_pX & x, const ZZ_pX& a, const ZZ_p& b); // x = a - b
344
345void sub(ZZ_pX& x, const ZZ_pX& a, long b);
346void sub(ZZ_pX& x, const ZZ_pX& a, const ZZ_p& b);
347
348void sub(ZZ_pX& x, long a, const ZZ_pX& b);
349void sub(ZZ_pX& x, const ZZ_p& a, const ZZ_pX& b);
350
351inline ZZ_pX operator+(const ZZ_pX& a, const ZZ_pX& b)
352   { ZZ_pX x; add(x, a, b); NTL_OPT_RETURN(ZZ_pX, x); }
353
354inline ZZ_pX operator+(const ZZ_pX& a, const ZZ_p& b)
355   { ZZ_pX x; add(x, a, b); NTL_OPT_RETURN(ZZ_pX, x); }
356
357inline ZZ_pX operator+(const ZZ_pX& a, long b)
358   { ZZ_pX x; add(x, a, b); NTL_OPT_RETURN(ZZ_pX, x); }
359
360inline ZZ_pX operator+(const ZZ_p& a, const ZZ_pX& b)
361   { ZZ_pX x; add(x, a, b); NTL_OPT_RETURN(ZZ_pX, x); }
362
363inline ZZ_pX operator+(long a, const ZZ_pX& b)
364   { ZZ_pX x; add(x, a, b); NTL_OPT_RETURN(ZZ_pX, x); }
365
366
367inline ZZ_pX operator-(const ZZ_pX& a, const ZZ_pX& b)
368   { ZZ_pX x; sub(x, a, b); NTL_OPT_RETURN(ZZ_pX, x); }
369
370inline ZZ_pX operator-(const ZZ_pX& a, const ZZ_p& b)
371   { ZZ_pX x; sub(x, a, b); NTL_OPT_RETURN(ZZ_pX, x); }
372
373inline ZZ_pX operator-(const ZZ_pX& a, long b)
374   { ZZ_pX x; sub(x, a, b); NTL_OPT_RETURN(ZZ_pX, x); }
375
376inline ZZ_pX operator-(const ZZ_p& a, const ZZ_pX& b)
377   { ZZ_pX x; sub(x, a, b); NTL_OPT_RETURN(ZZ_pX, x); }
378
379inline ZZ_pX operator-(long a, const ZZ_pX& b)
380   { ZZ_pX x; sub(x, a, b); NTL_OPT_RETURN(ZZ_pX, x); }
381
382
383inline ZZ_pX& operator+=(ZZ_pX& x, const ZZ_pX& b)
384   { add(x, x, b); return x; }
385
386inline ZZ_pX& operator+=(ZZ_pX& x, const ZZ_p& b)
387   { add(x, x, b); return x; }
388
389inline ZZ_pX& operator+=(ZZ_pX& x, long b)
390   { add(x, x, b); return x; }
391
392inline ZZ_pX& operator-=(ZZ_pX& x, const ZZ_pX& b)
393   { sub(x, x, b); return x; }
394
395inline ZZ_pX& operator-=(ZZ_pX& x, const ZZ_p& b)
396   { sub(x, x, b); return x; }
397
398inline ZZ_pX& operator-=(ZZ_pX& x, long b)
399   { sub(x, x, b); return x; }
400
401
402inline ZZ_pX operator-(const ZZ_pX& a) 
403   { ZZ_pX x; negate(x, a); NTL_OPT_RETURN(ZZ_pX, x); }
404
405inline ZZ_pX& operator++(ZZ_pX& x) { add(x, x, 1); return x; }
406inline void operator++(ZZ_pX& x, int) { add(x, x, 1); }
407inline ZZ_pX& operator--(ZZ_pX& x) { sub(x, x, 1); return x; }
408inline void operator--(ZZ_pX& x, int) { sub(x, x, 1); }
409
410/*****************************************************************
411
412                        Multiplication
413
414******************************************************************/
415
416
417void mul(ZZ_pX& x, const ZZ_pX& a, const ZZ_pX& b);
418// x = a * b
419
420void sqr(ZZ_pX& x, const ZZ_pX& a);
421inline ZZ_pX sqr(const ZZ_pX& a)
422   { ZZ_pX x; sqr(x, a); NTL_OPT_RETURN(ZZ_pX, x); }
423// x = a^2
424
425void mul(ZZ_pX & x, const ZZ_pX& a, const ZZ_p& b); 
426void mul(ZZ_pX& x, const ZZ_pX& a, long b);
427
428
429inline void mul(ZZ_pX& x, const ZZ_p& a, const ZZ_pX& b)
430   { mul(x, b, a); }
431
432inline void mul(ZZ_pX& x, long a, const ZZ_pX& b)
433   { mul(x, b, a); }
434
435inline ZZ_pX operator*(const ZZ_pX& a, const ZZ_pX& b)
436   { ZZ_pX x; mul(x, a, b); NTL_OPT_RETURN(ZZ_pX, x); }
437
438inline ZZ_pX operator*(const ZZ_pX& a, const ZZ_p& b)
439   { ZZ_pX x; mul(x, a, b); NTL_OPT_RETURN(ZZ_pX, x); }
440
441inline ZZ_pX operator*(const ZZ_pX& a, long b)
442   { ZZ_pX x; mul(x, a, b); NTL_OPT_RETURN(ZZ_pX, x); }
443
444inline ZZ_pX operator*(const ZZ_p& a, const ZZ_pX& b)
445   { ZZ_pX x; mul(x, a, b); NTL_OPT_RETURN(ZZ_pX, x); }
446
447inline ZZ_pX operator*(long a, const ZZ_pX& b)
448   { ZZ_pX x; mul(x, a, b); NTL_OPT_RETURN(ZZ_pX, x); }
449
450inline ZZ_pX& operator*=(ZZ_pX& x, const ZZ_pX& b)
451   { mul(x, x, b); return x; }
452
453inline ZZ_pX& operator*=(ZZ_pX& x, const ZZ_p& b)
454   { mul(x, x, b); return x; }
455
456inline ZZ_pX& operator*=(ZZ_pX& x, long b)
457   { mul(x, x, b); return x; }
458
459
460void PlainMul(ZZ_pX& x, const ZZ_pX& a, const ZZ_pX& b);
461// always uses the "classical" algorithm
462
463void PlainSqr(ZZ_pX& x, const ZZ_pX& a);
464// always uses the "classical" algorithm
465
466
467void FFTMul(ZZ_pX& x, const ZZ_pX& a, const ZZ_pX& b);
468// always uses the FFT
469
470void FFTSqr(ZZ_pX& x, const ZZ_pX& a);
471// always uses the FFT
472
473void MulTrunc(ZZ_pX& x, const ZZ_pX& a, const ZZ_pX& b, long n);
474// x = a * b % X^n
475
476inline ZZ_pX MulTrunc(const ZZ_pX& a, const ZZ_pX& b, long n)
477   { ZZ_pX x; MulTrunc(x, a, b, n); NTL_OPT_RETURN(ZZ_pX, x); }
478
479void PlainMulTrunc(ZZ_pX& x, const ZZ_pX& a, const ZZ_pX& b, long n);
480void FFTMulTrunc(ZZ_pX& x, const ZZ_pX& a, const ZZ_pX& b, long n);
481
482void SqrTrunc(ZZ_pX& x, const ZZ_pX& a, long n);
483// x = a^2 % X^n
484
485inline ZZ_pX SqrTrunc(const ZZ_pX& a, long n)
486   { ZZ_pX x; SqrTrunc(x, a, n); NTL_OPT_RETURN(ZZ_pX, x); }
487
488void PlainSqrTrunc(ZZ_pX& x, const ZZ_pX& a, long n);
489void FFTSqrTrunc(ZZ_pX& x, const ZZ_pX& a, long n);
490
491
492void power(ZZ_pX& x, const ZZ_pX& a, long e);
493inline ZZ_pX power(const ZZ_pX& a, long e)
494   { ZZ_pX x; power(x, a, e); NTL_OPT_RETURN(ZZ_pX, x); }
495
496
497// The following data structures and routines allow one
498// to hand-craft various algorithms, using the FFT convolution
499// algorithms directly.
500// Look in the file ZZ_pX.c for examples.
501
502
503
504
505// FFT representation of polynomials
506
507class FFTRep {
508public:
509   long k;                // a 2^k point representation
510   long MaxK;             // maximum space allocated
511   long **tbl;
512   long NumPrimes; 
513
514   void SetSize(long NewK);
515
516   FFTRep(const FFTRep& R);
517   FFTRep& operator=(const FFTRep& R);
518
519   FFTRep() { k = MaxK = -1; tbl = 0; NumPrimes = 0; }
520   FFTRep(INIT_SIZE_TYPE, long InitK) 
521   { k = MaxK = -1; tbl = 0; NumPrimes = 0; SetSize(InitK); }
522   ~FFTRep();
523};
524
525
526void ToFFTRep(FFTRep& y, const ZZ_pX& x, long k, long lo, long hi);
527// computes an n = 2^k point convolution of x[lo..hi].
528
529inline void ToFFTRep(FFTRep& y, const ZZ_pX& x, long k)
530
531   { ToFFTRep(y, x, k, 0, deg(x)); }
532
533void RevToFFTRep(FFTRep& y, const vec_ZZ_p& x,
534                 long k, long lo, long hi, long offset);
535// computes an n = 2^k point convolution of X^offset*x[lo..hi] mod X^n-1
536// using "inverted" evaluation points.
537
538
539void FromFFTRep(ZZ_pX& x, FFTRep& y, long lo, long hi);
540// converts from FFT-representation to coefficient representation
541// only the coefficients lo..hi are computed
542// NOTE: this version destroys the data in y
543
544// non-destructive versions of the above
545
546void NDFromFFTRep(ZZ_pX& x, const FFTRep& y, long lo, long hi, FFTRep& temp);
547void NDFromFFTRep(ZZ_pX& x, const FFTRep& y, long lo, long hi);
548
549void RevFromFFTRep(vec_ZZ_p& x, FFTRep& y, long lo, long hi);
550
551   // converts from FFT-representation to coefficient representation
552   // using "inverted" evaluation points.
553   // only the coefficients lo..hi are computed
554
555
556
557
558void FromFFTRep(ZZ_p* x, FFTRep& y, long lo, long hi);
559// convert out coefficients lo..hi of y, store result in x.
560// no normalization is done.
561
562
563// direct manipulation of FFT reps
564
565void mul(FFTRep& z, const FFTRep& x, const FFTRep& y);
566void sub(FFTRep& z, const FFTRep& x, const FFTRep& y);
567void add(FFTRep& z, const FFTRep& x, const FFTRep& y);
568
569void reduce(FFTRep& x, const FFTRep& a, long k);
570// reduces a 2^l point FFT-rep to a 2^k point FFT-rep
571
572void AddExpand(FFTRep& x, const FFTRep& a);
573//  x = x + (an "expanded" version of a)
574
575
576
577
578
579// This data structure holds unconvoluted modular representations
580// of polynomials
581
582class ZZ_pXModRep {
583private:
584   ZZ_pXModRep(const ZZ_pXModRep&); // disabled
585   void operator=(const ZZ_pXModRep&); // disabled
586
587public:
588   long n;
589   long MaxN;
590   long **tbl;
591   long NumPrimes; 
592
593   void SetSize(long NewN);
594
595   ZZ_pXModRep() { n = MaxN = 0; tbl = 0; NumPrimes = 0; }
596   ZZ_pXModRep(INIT_SIZE_TYPE, long k) 
597   { n = MaxN = 0; tbl = 0; NumPrimes = 0; SetSize(k); }
598   ~ZZ_pXModRep();
599};
600
601
602void ToZZ_pXModRep(ZZ_pXModRep& x, const ZZ_pX& a, long lo, long hi);
603
604void ToFFTRep(FFTRep& x, const ZZ_pXModRep& a, long k, long lo, long hi);
605// converts coefficients lo..hi to a 2^k-point FFTRep.
606// must have hi-lo+1 < 2^k
607
608
609
610
611
612/*************************************************************
613
614                      Division
615
616**************************************************************/
617
618void DivRem(ZZ_pX& q, ZZ_pX& r, const ZZ_pX& a, const ZZ_pX& b);
619// q = a/b, r = a%b
620
621void div(ZZ_pX& q, const ZZ_pX& a, const ZZ_pX& b);
622// q = a/b
623
624void div(ZZ_pX& q, const ZZ_pX& a, const ZZ_p& b);
625void div(ZZ_pX& q, const ZZ_pX& a, long b);
626
627
628void rem(ZZ_pX& r, const ZZ_pX& a, const ZZ_pX& b);
629// r = a%b
630
631long divide(ZZ_pX& q, const ZZ_pX& a, const ZZ_pX& b);
632// if b | a, sets q = a/b and returns 1; otherwise returns 0
633
634long divide(const ZZ_pX& a, const ZZ_pX& b);
635// if b | a, sets q = a/b and returns 1; otherwise returns 0
636
637void InvTrunc(ZZ_pX& x, const ZZ_pX& a, long m);
638// computes x = a^{-1} % X^m
639// constant term must be non-zero
640
641inline ZZ_pX InvTrunc(const ZZ_pX& a, long m)
642   { ZZ_pX x; InvTrunc(x, a, m); NTL_OPT_RETURN(ZZ_pX, x); }
643
644
645
646// These always use "classical" arithmetic
647void PlainDivRem(ZZ_pX& q, ZZ_pX& r, const ZZ_pX& a, const ZZ_pX& b);
648void PlainDiv(ZZ_pX& q, const ZZ_pX& a, const ZZ_pX& b);
649void PlainRem(ZZ_pX& r, const ZZ_pX& a, const ZZ_pX& b);
650
651void PlainRem(ZZ_pX& r, const ZZ_pX& a, const ZZ_pX& b, ZZVec& tmp);
652void PlainDivRem(ZZ_pX& q, ZZ_pX& r, const ZZ_pX& a, const ZZ_pX& b,
653                 ZZVec& tmp);
654
655
656// These always use FFT arithmetic
657void FFTDivRem(ZZ_pX& q, ZZ_pX& r, const ZZ_pX& a, const ZZ_pX& b);
658void FFTDiv(ZZ_pX& q, const ZZ_pX& a, const ZZ_pX& b);
659void FFTRem(ZZ_pX& r, const ZZ_pX& a, const ZZ_pX& b);
660
661void PlainInvTrunc(ZZ_pX& x, const ZZ_pX& a, long m);
662// always uses "classical" algorithm
663// ALIAS RESTRICTION: input may not alias output
664
665void NewtonInvTrunc(ZZ_pX& x, const ZZ_pX& a, long m);
666// uses a Newton Iteration with the FFT.
667// ALIAS RESTRICTION: input may not alias output
668
669
670inline ZZ_pX operator/(const ZZ_pX& a, const ZZ_pX& b)
671   { ZZ_pX x; div(x, a, b); NTL_OPT_RETURN(ZZ_pX, x); }
672
673inline ZZ_pX operator/(const ZZ_pX& a, const ZZ_p& b)
674   { ZZ_pX x; div(x, a, b); NTL_OPT_RETURN(ZZ_pX, x); }
675
676inline ZZ_pX operator/(const ZZ_pX& a, long b)
677   { ZZ_pX x; div(x, a, b); NTL_OPT_RETURN(ZZ_pX, x); }
678
679inline ZZ_pX& operator/=(ZZ_pX& x, const ZZ_p& b)
680   { div(x, x, b); return x; }
681
682inline ZZ_pX& operator/=(ZZ_pX& x, long b)
683   { div(x, x, b); return x; }
684
685inline ZZ_pX& operator/=(ZZ_pX& x, const ZZ_pX& b)
686   { div(x, x, b); return x; }
687
688
689inline ZZ_pX operator%(const ZZ_pX& a, const ZZ_pX& b)
690   { ZZ_pX x; rem(x, a, b); NTL_OPT_RETURN(ZZ_pX, x); }
691
692inline ZZ_pX& operator%=(ZZ_pX& x, const ZZ_pX& b)
693   { rem(x, x, b); return x; }
694
695
696/***********************************************************
697
698                         GCD's
699
700************************************************************/
701
702
703void GCD(ZZ_pX& x, const ZZ_pX& a, const ZZ_pX& b);
704// x = GCD(a, b),  x is always monic (or zero if a==b==0).
705
706inline ZZ_pX GCD(const ZZ_pX& a, const ZZ_pX& b)
707   { ZZ_pX x; GCD(x, a, b); NTL_OPT_RETURN(ZZ_pX, x); }
708
709void XGCD(ZZ_pX& d, ZZ_pX& s, ZZ_pX& t, const ZZ_pX& a, const ZZ_pX& b);
710// d = gcd(a,b), a s + b t = d
711
712void PlainXGCD(ZZ_pX& d, ZZ_pX& s, ZZ_pX& t, const ZZ_pX& a, const ZZ_pX& b);
713// same as above, but uses classical algorithm
714
715
716void PlainGCD(ZZ_pX& x, const ZZ_pX& a, const ZZ_pX& b);
717// always uses "cdlassical" arithmetic
718
719
720class ZZ_pXMatrix {
721private:
722
723   ZZ_pXMatrix(const ZZ_pXMatrix&);  // disable
724   ZZ_pX elts[2][2];
725
726public:
727
728   ZZ_pXMatrix() { }
729   ~ZZ_pXMatrix() { }
730
731   void operator=(const ZZ_pXMatrix&);
732   ZZ_pX& operator() (long i, long j) { return elts[i][j]; }
733   const ZZ_pX& operator() (long i, long j) const { return elts[i][j]; }
734};
735
736
737void HalfGCD(ZZ_pXMatrix& M_out, const ZZ_pX& U, const ZZ_pX& V, long d_red);
738// deg(U) > deg(V),   1 <= d_red <= deg(U)+1.
739//
740// This computes a 2 x 2 polynomial matrix M_out such that
741//    M_out * (U, V)^T = (U', V')^T,
742// where U', V' are consecutive polynomials in the Euclidean remainder
743// sequence of U, V, and V' is the polynomial of highest degree
744// satisfying deg(V') <= deg(U) - d_red.
745
746void XHalfGCD(ZZ_pXMatrix& M_out, ZZ_pX& U, ZZ_pX& V, long d_red);
747
748// same as above, except that U is replaced by U', and V by V'
749
750
751/*************************************************************
752
753             Modular Arithmetic without pre-conditioning
754
755**************************************************************/
756
757// arithmetic mod f.
758// all inputs and outputs are polynomials of degree less than deg(f).
759// ASSUMPTION: f is assumed monic, and deg(f) > 0.
760// NOTE: if you want to do many computations with a fixed f,
761//       use the ZZ_pXModulus data structure and associated routines below.
762
763
764
765void MulMod(ZZ_pX& x, const ZZ_pX& a, const ZZ_pX& b, const ZZ_pX& f);
766// x = (a * b) % f
767
768inline ZZ_pX MulMod(const ZZ_pX& a, const ZZ_pX& b, const ZZ_pX& f)
769   { ZZ_pX x; MulMod(x, a, b, f); NTL_OPT_RETURN(ZZ_pX, x); }
770
771void SqrMod(ZZ_pX& x, const ZZ_pX& a, const ZZ_pX& f);
772// x = a^2 % f
773
774inline ZZ_pX SqrMod(const ZZ_pX& a,  const ZZ_pX& f)
775   { ZZ_pX x; SqrMod(x, a, f); NTL_OPT_RETURN(ZZ_pX, x); }
776
777void MulByXMod(ZZ_pX& x, const ZZ_pX& a, const ZZ_pX& f);
778// x = (a * X) mod f
779
780inline ZZ_pX MulByXMod(const ZZ_pX& a,  const ZZ_pX& f)
781   { ZZ_pX x; MulByXMod(x, a, f); NTL_OPT_RETURN(ZZ_pX, x); }
782
783
784
785void InvMod(ZZ_pX& x, const ZZ_pX& a, const ZZ_pX& f);
786// x = a^{-1} % f, error is a is not invertible
787
788inline ZZ_pX InvMod(const ZZ_pX& a,  const ZZ_pX& f)
789   { ZZ_pX x; InvMod(x, a, f); NTL_OPT_RETURN(ZZ_pX, x); }
790
791long InvModStatus(ZZ_pX& x, const ZZ_pX& a, const ZZ_pX& f);
792// if (a, f) = 1, returns 0 and sets x = a^{-1} % f
793// otherwise, returns 1 and sets x = (a, f)
794
795
796
797
798/******************************************************************
799
800        Modular Arithmetic with Pre-conditioning
801
802*******************************************************************/
803
804
805// If you need to do a lot of arithmetic modulo a fixed f,
806// build ZZ_pXModulus F for f.  This pre-computes information about f
807// that speeds up the computation a great deal.
808
809
810class ZZ_pXModulus {
811public:
812   ZZ_pXModulus() : UseFFT(0), n(-1)  { }
813   ~ZZ_pXModulus() { }
814   
815
816   // the following members may become private in future
817   ZZ_pX f;   // the modulus
818   long UseFFT;// flag indicating whether FFT should be used.
819   long n;     // n = deg(f)
820   long k;     // least k s/t 2^k >= n
821   long l;     // least l s/t 2^l >= 2n-3
822   FFTRep FRep; // 2^k point rep of f
823                // H = rev((rev(f))^{-1} rem X^{n-1})
824   FFTRep HRep; // 2^l point rep of H
825   vec_ZZ_p tracevec;  // mutable
826
827   // but these will remain public
828   ZZ_pXModulus(const ZZ_pX& ff);
829
830   const ZZ_pX& val() const { return f; }
831   operator const ZZ_pX& () const { return f; }
832
833};
834
835inline long deg(const ZZ_pXModulus& F) { return F.n; }
836
837void build(ZZ_pXModulus& F, const ZZ_pX& f);
838// deg(f) > 0.
839
840
841void rem21(ZZ_pX& x, const ZZ_pX& a, const ZZ_pXModulus& F);
842// x = a % f
843// deg(a) <= 2(n-1), where n = F.n = deg(f)
844
845void rem(ZZ_pX& x, const ZZ_pX& a, const ZZ_pXModulus& F);
846// x = a % f, no restrictions on deg(a);  makes repeated calls to rem21
847
848inline ZZ_pX operator%(const ZZ_pX& a, const ZZ_pXModulus& F)
849   { ZZ_pX x; rem(x, a, F); NTL_OPT_RETURN(ZZ_pX, x); }
850
851inline ZZ_pX& operator%=(ZZ_pX& x, const ZZ_pXModulus& F)
852   { rem(x, x, F); return x; } 
853
854void DivRem(ZZ_pX& q, ZZ_pX& r, const ZZ_pX& a, const ZZ_pXModulus& F);
855
856void div(ZZ_pX& q, const ZZ_pX& a, const ZZ_pXModulus& F);
857
858inline ZZ_pX operator/(const ZZ_pX& a, const ZZ_pXModulus& F)
859   { ZZ_pX x; div(x, a, F); NTL_OPT_RETURN(ZZ_pX, x); }
860
861inline ZZ_pX& operator/=(ZZ_pX& x, const ZZ_pXModulus& F)
862   { div(x, x, F); return x; } 
863
864void MulMod(ZZ_pX& x, const ZZ_pX& a, const ZZ_pX& b, const ZZ_pXModulus& F);
865// x = (a * b) % f
866// deg(a), deg(b) < n
867
868inline ZZ_pX MulMod(const ZZ_pX& a, const ZZ_pX& b, const ZZ_pXModulus& F)
869   { ZZ_pX x; MulMod(x, a, b, F); NTL_OPT_RETURN(ZZ_pX, x); }
870
871void SqrMod(ZZ_pX& x, const ZZ_pX& a, const ZZ_pXModulus& F);
872// x = a^2 % f
873// deg(a) < n
874
875inline ZZ_pX SqrMod(const ZZ_pX& a, const ZZ_pXModulus& F)
876   { ZZ_pX x; SqrMod(x, a, F); NTL_OPT_RETURN(ZZ_pX, x); }
877
878void PowerMod(ZZ_pX& x, const ZZ_pX& a, const ZZ& e, const ZZ_pXModulus& F);
879// x = a^e % f, e >= 0
880
881inline ZZ_pX PowerMod(const ZZ_pX& a, const ZZ& e, const ZZ_pXModulus& F)
882   { ZZ_pX x; PowerMod(x, a, e, F); NTL_OPT_RETURN(ZZ_pX, x); }
883
884inline void PowerMod(ZZ_pX& x, const ZZ_pX& a, long e, const ZZ_pXModulus& F)
885   { PowerMod(x, a, ZZ_expo(e), F); }
886
887inline ZZ_pX PowerMod(const ZZ_pX& a, long e, const ZZ_pXModulus& F)
888   { ZZ_pX x; PowerMod(x, a, e, F); NTL_OPT_RETURN(ZZ_pX, x); }
889
890
891
892void PowerXMod(ZZ_pX& x, const ZZ& e, const ZZ_pXModulus& F);
893// x = X^e % f, e >= 0
894
895inline ZZ_pX PowerXMod(const ZZ& e, const ZZ_pXModulus& F)
896   { ZZ_pX x; PowerXMod(x, e, F); NTL_OPT_RETURN(ZZ_pX, x); }
897
898inline void PowerXMod(ZZ_pX& x, long e, const ZZ_pXModulus& F)
899   { PowerXMod(x, ZZ_expo(e), F); }
900
901inline ZZ_pX PowerXMod(long e, const ZZ_pXModulus& F)
902   { ZZ_pX x; PowerXMod(x, e, F); NTL_OPT_RETURN(ZZ_pX, x); }
903
904void PowerXPlusAMod(ZZ_pX& x, const ZZ_p& a, const ZZ& e, const ZZ_pXModulus& F);
905// x = (X + a)^e % f, e >= 0
906
907inline ZZ_pX PowerXPlusAMod(const ZZ_p& a, const ZZ& e, const ZZ_pXModulus& F)
908   { ZZ_pX x; PowerXPlusAMod(x, a, e, F); NTL_OPT_RETURN(ZZ_pX, x); }
909
910inline void PowerXPlusAMod(ZZ_pX& x, const ZZ_p& a, long e, const ZZ_pXModulus& F)
911   { PowerXPlusAMod(x, a, ZZ_expo(e), F); }
912
913
914inline ZZ_pX PowerXPlusAMod(const ZZ_p& a, long e, const ZZ_pXModulus& F)
915   { ZZ_pX x; PowerXPlusAMod(x, a, e, F); NTL_OPT_RETURN(ZZ_pX, x); }
916
917// If you need to compute a * b % f for a fixed b, but for many a's
918// (for example, computing powers of b modulo f), it is
919// much more efficient to first build a ZZ_pXMultiplier B for b,
920// and then use the routine below.
921
922class ZZ_pXMultiplier {
923public:
924   ZZ_pXMultiplier() : UseFFT(0)  { }
925   ZZ_pXMultiplier(const ZZ_pX& b, const ZZ_pXModulus& F);
926
927   ~ZZ_pXMultiplier() { }
928
929
930   // the following members may become private in the future
931   ZZ_pX b;   
932   long UseFFT;
933   FFTRep B1; 
934   FFTRep B2; 
935
936   // but this will remain public
937   const ZZ_pX& val() const { return b; }
938
939};
940
941void build(ZZ_pXMultiplier& B, const ZZ_pX& b, const ZZ_pXModulus& F);
942
943void MulMod(ZZ_pX& x, const ZZ_pX& a, const ZZ_pXMultiplier& B,
944                                      const ZZ_pXModulus& F);
945
946inline ZZ_pX MulMod(const ZZ_pX& a, const ZZ_pXMultiplier& B,
947                                          const ZZ_pXModulus& F)
948   { ZZ_pX x; MulMod(x, a, B, F); NTL_OPT_RETURN(ZZ_pX, x); }
949
950// x = (a * b) % f
951
952
953/*******************************************************
954
955              Evaluation and related problems
956
957********************************************************/
958
959
960void BuildFromRoots(ZZ_pX& x, const vec_ZZ_p& a);
961// computes the polynomial (X-a[0]) ... (X-a[n-1]), where n = a.length()
962
963inline ZZ_pX BuildFromRoots(const vec_ZZ_p& a)
964   { ZZ_pX x; BuildFromRoots(x, a); NTL_OPT_RETURN(ZZ_pX, x); }
965
966
967void eval(ZZ_p& b, const ZZ_pX& f, const ZZ_p& a);
968// b = f(a)
969
970inline ZZ_p eval(const ZZ_pX& f, const ZZ_p& a)
971   { ZZ_p x; eval(x, f, a); NTL_OPT_RETURN(ZZ_p, x); }
972
973void eval(vec_ZZ_p& b, const ZZ_pX& f, const vec_ZZ_p& a);
974//  b[i] = f(a[i])
975
976inline vec_ZZ_p eval(const ZZ_pX& f, const vec_ZZ_p& a)
977   { vec_ZZ_p x; eval(x, f, a); NTL_OPT_RETURN(vec_ZZ_p, x); }
978
979
980void interpolate(ZZ_pX& f, const vec_ZZ_p& a, const vec_ZZ_p& b);
981// computes f such that f(a[i]) = b[i]
982
983inline ZZ_pX interpolate(const vec_ZZ_p& a, const vec_ZZ_p& b)
984   { ZZ_pX x; interpolate(x, a, b); NTL_OPT_RETURN(ZZ_pX, x); }
985
986
987/*****************************************************************
988
989                       vectors of ZZ_pX's
990
991*****************************************************************/
992
993NTL_vector_decl(ZZ_pX,vec_ZZ_pX)
994
995NTL_eq_vector_decl(ZZ_pX,vec_ZZ_pX)
996
997
998/**********************************************************
999
1000         Modular Composition and Minimal Polynomials
1001
1002***********************************************************/
1003
1004
1005// algorithms for computing g(h) mod f
1006
1007
1008
1009void CompMod(ZZ_pX& x, const ZZ_pX& g, const ZZ_pX& h, const ZZ_pXModulus& F);
1010// x = g(h) mod f
1011
1012inline ZZ_pX CompMod(const ZZ_pX& g, const ZZ_pX& h, 
1013                           const ZZ_pXModulus& F)
1014   { ZZ_pX x; CompMod(x, g, h, F); NTL_OPT_RETURN(ZZ_pX, x); }
1015
1016void Comp2Mod(ZZ_pX& x1, ZZ_pX& x2, const ZZ_pX& g1, const ZZ_pX& g2,
1017              const ZZ_pX& h, const ZZ_pXModulus& F);
1018// xi = gi(h) mod f (i=1,2)
1019
1020void Comp3Mod(ZZ_pX& x1, ZZ_pX& x2, ZZ_pX& x3, 
1021              const ZZ_pX& g1, const ZZ_pX& g2, const ZZ_pX& g3,
1022              const ZZ_pX& h, const ZZ_pXModulus& F);
1023// xi = gi(h) mod f (i=1..3)
1024
1025
1026
1027// The routine build (see below) which is implicitly called
1028// by the various compose and UpdateMap routines builds a table
1029// of polynomials. 
1030// If ZZ_pXArgBound > 0, then the table is limited in
1031// size to approximamtely that many KB.
1032// If ZZ_pXArgBound <= 0, then it is ignored, and space is allocated
1033// so as to maximize speed.
1034// Initially, ZZ_pXArgBound = 0.
1035
1036
1037// If a single h is going to be used with many g's
1038// then you should build a ZZ_pXArgument for h,
1039// and then use the compose routine below.
1040// build computes and stores h, h^2, ..., h^m mod f.
1041// After this pre-computation, composing a polynomial of degree
1042// roughly n with h takes n/m multiplies mod f, plus n^2
1043// scalar multiplies.
1044// Thus, increasing m increases the space requirement and the pre-computation
1045// time, but reduces the composition time.
1046// If ZZ_pXArgBound > 0, a table of size less than m may be built.
1047
1048struct ZZ_pXArgument {
1049   vec_ZZ_pX H;
1050};
1051
1052extern long ZZ_pXArgBound;
1053
1054
1055void build(ZZ_pXArgument& H, const ZZ_pX& h, const ZZ_pXModulus& F, long m);
1056
1057// m must be > 0, otherwise an error is raised
1058
1059void CompMod(ZZ_pX& x, const ZZ_pX& g, const ZZ_pXArgument& H, 
1060             const ZZ_pXModulus& F);
1061
1062inline ZZ_pX
1063CompMod(const ZZ_pX& g, const ZZ_pXArgument& H, const ZZ_pXModulus& F)
1064   { ZZ_pX x; CompMod(x, g, H, F); NTL_OPT_RETURN(ZZ_pX, x); }
1065
1066
1067#ifndef NTL_TRANSITION
1068
1069void UpdateMap(vec_ZZ_p& x, const vec_ZZ_p& a,
1070               const ZZ_pXMultiplier& B, const ZZ_pXModulus& F);
1071
1072inline vec_ZZ_p
1073UpdateMap(const vec_ZZ_p& a, 
1074          const ZZ_pXMultiplier& B, const ZZ_pXModulus& F)
1075   { vec_ZZ_p x; UpdateMap(x, a, B, F); 
1076     NTL_OPT_RETURN(vec_ZZ_p, x); }
1077
1078#endif
1079
1080
1081/* computes (a, b), (a, (b*X)%f), ..., (a, (b*X^{n-1})%f),
1082   where ( , ) denotes the vector inner product.
1083
1084   This is really a "transposed" MulMod by B.
1085*/
1086
1087void PlainUpdateMap(vec_ZZ_p& x, const vec_ZZ_p& a,
1088                    const ZZ_pX& b, const ZZ_pX& f);
1089
1090// same as above, but uses only classical arithmetic
1091
1092
1093void ProjectPowers(vec_ZZ_p& x, const vec_ZZ_p& a, long k,
1094                   const ZZ_pX& h, const ZZ_pXModulus& F);
1095
1096inline vec_ZZ_p ProjectPowers(const vec_ZZ_p& a, long k,
1097                   const ZZ_pX& h, const ZZ_pXModulus& F)
1098{
1099   vec_ZZ_p x;
1100   ProjectPowers(x, a, k, h, F);
1101   NTL_OPT_RETURN(vec_ZZ_p, x);
1102}
1103
1104
1105// computes (a, 1), (a, h), ..., (a, h^{k-1} % f)
1106// this is really a "transposed" compose.
1107
1108void ProjectPowers(vec_ZZ_p& x, const vec_ZZ_p& a, long k,
1109                   const ZZ_pXArgument& H, const ZZ_pXModulus& F);
1110
1111inline vec_ZZ_p ProjectPowers(const vec_ZZ_p& a, long k,
1112                   const ZZ_pXArgument& H, const ZZ_pXModulus& F)
1113{
1114   vec_ZZ_p x;
1115   ProjectPowers(x, a, k, H, F);
1116   NTL_OPT_RETURN(vec_ZZ_p, x);
1117}
1118
1119// same as above, but uses a pre-computed ZZ_pXArgument
1120
1121inline void project(ZZ_p& x, const vec_ZZ_p& a, const ZZ_pX& b)
1122   { InnerProduct(x, a, b.rep); }
1123
1124inline ZZ_p project(const vec_ZZ_p& a, const ZZ_pX& b)
1125   {  ZZ_p x; project(x, a, b); NTL_OPT_RETURN(ZZ_p, x); }
1126
1127void MinPolySeq(ZZ_pX& h, const vec_ZZ_p& a, long m);
1128// computes the minimum polynomial of a linealy generated sequence;
1129// m is a bound on the degree of the polynomial;
1130// required: a.length() >= 2*m
1131
1132inline ZZ_pX MinPolySeq(const vec_ZZ_p& a, long m)
1133   { ZZ_pX x; MinPolySeq(x, a, m); NTL_OPT_RETURN(ZZ_pX, x); }
1134
1135void ProbMinPolyMod(ZZ_pX& h, const ZZ_pX& g, const ZZ_pXModulus& F, long m);
1136
1137inline ZZ_pX ProbMinPolyMod(const ZZ_pX& g, const ZZ_pXModulus& F, long m)
1138   { ZZ_pX x; ProbMinPolyMod(x, g, F, m); NTL_OPT_RETURN(ZZ_pX, x); }
1139
1140
1141inline void ProbMinPolyMod(ZZ_pX& h, const ZZ_pX& g, const ZZ_pXModulus& F)
1142   { ProbMinPolyMod(h, g, F, F.n); }
1143
1144inline ZZ_pX ProbMinPolyMod(const ZZ_pX& g, const ZZ_pXModulus& F)
1145   { ZZ_pX x; ProbMinPolyMod(x, g, F); NTL_OPT_RETURN(ZZ_pX, x); }
1146
1147
1148// computes the monic minimal polynomial if (g mod f).
1149// m = a bound on the degree of the minimal polynomial.
1150// If this argument is not supplied, it defaults to deg(f).
1151// The algorithm is probabilistic, always returns a divisor of
1152// the minimal polynomial, and returns a proper divisor with
1153// probability at most m/p.
1154
1155void MinPolyMod(ZZ_pX& h, const ZZ_pX& g, const ZZ_pXModulus& F, long m);
1156
1157inline ZZ_pX MinPolyMod(const ZZ_pX& g, const ZZ_pXModulus& F, long m)
1158   { ZZ_pX x; MinPolyMod(x, g, F, m); NTL_OPT_RETURN(ZZ_pX, x); }
1159
1160inline void MinPolyMod(ZZ_pX& h, const ZZ_pX& g, const ZZ_pXModulus& F)
1161   { MinPolyMod(h, g, F, F.n); }
1162
1163inline ZZ_pX MinPolyMod(const ZZ_pX& g, const ZZ_pXModulus& F)
1164   { ZZ_pX x; MinPolyMod(x, g, F); NTL_OPT_RETURN(ZZ_pX, x); }
1165
1166// same as above, but guarantees that result is correct
1167
1168void IrredPolyMod(ZZ_pX& h, const ZZ_pX& g, const ZZ_pXModulus& F, long m);
1169
1170inline ZZ_pX IrredPolyMod(const ZZ_pX& g, const ZZ_pXModulus& F, long m)
1171   { ZZ_pX x; IrredPolyMod(x, g, F, m); NTL_OPT_RETURN(ZZ_pX, x); }
1172
1173
1174inline void IrredPolyMod(ZZ_pX& h, const ZZ_pX& g, const ZZ_pXModulus& F)
1175   { IrredPolyMod(h, g, F, F.n); }
1176
1177inline ZZ_pX IrredPolyMod(const ZZ_pX& g, const ZZ_pXModulus& F)
1178   { ZZ_pX x; IrredPolyMod(x, g, F); NTL_OPT_RETURN(ZZ_pX, x); }
1179
1180// same as above, but assumes that f is irreducible,
1181// or at least that the minimal poly of g is itself irreducible.
1182// The algorithm is deterministic (and is always correct).
1183
1184/*****************************************************************
1185
1186                   Traces, norms, resultants
1187
1188******************************************************************/
1189
1190void TraceVec(vec_ZZ_p& S, const ZZ_pX& f);
1191
1192inline vec_ZZ_p TraceVec(const ZZ_pX& f)
1193   { vec_ZZ_p x; TraceVec(x, f); NTL_OPT_RETURN(vec_ZZ_p, x); }
1194
1195void FastTraceVec(vec_ZZ_p& S, const ZZ_pX& f);
1196void PlainTraceVec(vec_ZZ_p& S, const ZZ_pX& f);
1197
1198void TraceMod(ZZ_p& x, const ZZ_pX& a, const ZZ_pXModulus& F);
1199
1200inline ZZ_p TraceMod(const ZZ_pX& a, const ZZ_pXModulus& F)
1201   { ZZ_p x; TraceMod(x, a, F); NTL_OPT_RETURN(ZZ_p, x); }
1202
1203void TraceMod(ZZ_p& x, const ZZ_pX& a, const ZZ_pX& f);
1204
1205inline ZZ_p TraceMod(const ZZ_pX& a, const ZZ_pX& f)
1206   { ZZ_p x; TraceMod(x, a, f); NTL_OPT_RETURN(ZZ_p, x); }
1207
1208
1209
1210void ComputeTraceVec(const ZZ_pXModulus& F);
1211
1212
1213void NormMod(ZZ_p& x, const ZZ_pX& a, const ZZ_pX& f);
1214
1215inline ZZ_p NormMod(const ZZ_pX& a, const ZZ_pX& f)
1216   { ZZ_p x; NormMod(x, a, f); NTL_OPT_RETURN(ZZ_p, x); }
1217
1218void resultant(ZZ_p& rres, const ZZ_pX& a, const ZZ_pX& b);
1219
1220inline ZZ_p resultant(const ZZ_pX& a, const ZZ_pX& b)
1221   { ZZ_p x; resultant(x, a, b); NTL_OPT_RETURN(ZZ_p, x); }
1222
1223void CharPolyMod(ZZ_pX& g, const ZZ_pX& a, const ZZ_pX& f);
1224// g = char poly of (a mod f)
1225
1226inline ZZ_pX CharPolyMod(const ZZ_pX& a, const ZZ_pX& f)
1227   { ZZ_pX x; CharPolyMod(x, a, f); NTL_OPT_RETURN(ZZ_pX, x); }
1228
1229
1230
1231NTL_CLOSE_NNS
1232
1233#endif
Note: See TracBrowser for help on using the repository browser.