Codebase list ntl / a7863b2
NTL -- a library for doing numbery theory -- version 6.0 Changes between NTL 5.5.2 and 6.0 Replaced the old template-like macros for vectors, matrices, and pairs with true template classes: Vec<T>, Mat<T>, and Pair<S,T>. For backwards compatibilty, all the names that were used in previous versions (e.g., vec_ZZ_p, mat_ZZ_p) have been replaced with appropriate typedefs. For many years, I resisted the temptation of using templates, because compiler support was very inconsistent. But that no longer seems to be the case. This change, while rather sweeping, should create very few, if any, incompatibilities with existing software. The biggest issue would be for software that uses the old template-like macros: such macro invocations can simply be replaced with appropriate typedefs. Made the conversion interface more complete and uniform. Also, using template notation, one can and should now write conv<ZZ>(a) instead of to_ZZ(a) (for backward compatibility, all the old names to_XXX are still there, but many new conversions are not available under these old names). There are many new conversions provided. Moreover, whenever there is a conversion from a ring R to a ring S, there is a corresponding, coefficiet-wise conversion from the polynomial ring R[X] to the polynomial ring R[X]. In addition, using the template mechanism, there are generic conversions for vectors and matrices. For example, if there is a conversion from S to T, then there is automatically a corresponding component-wise conversion from Vec<S> to Vec<T>. Introduced a more general mechanism for accessing GF2's in packed structures via indexing (see the class ref_GF2 in the GF2 module). Employed ideas from David Harvey to make the single-precision FFT faster (about twice as fast in many cases). This speeds up many higher-level operations. Fixed all known bugs. Victor Shoup authored 11 years ago Bernhard R. Link committed 11 years ago
188 changed file(s) with 4626 addition(s) and 3354 deletion(s). Raw diff Collapse all Expand all
0 NTL -- a library for doing numbery theory -- version 5.5
1 Release date: 2009.04.08
0 NTL -- a library for doing numbery theory -- version 6.0
1 Release date: 2013.02.15
22
33 Author: Victor Shoup (victor@shoup.net)
44
1010 Its main use is to make the interfaces to the various finite
1111 field classes as uniform as possible.
1212
13 The header file for GF2 also declares the class ref_GF2, which
14 use used to represent non-const references to GF2's, such as
15 those obtained from indexing a vec_GF2, which "packs" GF2's
16 into words.
17
18 There are implicit conversions from ref_GF2 to const GF2
19 and from GF2& to ref_GF2. Therefore, if you want to declare
20 a function that takes a non-const reference to a GF2, you
21 should declare the parameter of type ref_GF2: this will
22 allow you to pass variables of type GF2 as well as
23 elements of vec_GF2's obtained through indexing.
24
25 For all functions defined below which take a parameter of type
26 GF2&, there is also a function that takes a parameter of type ref_GF2.
27 Theoretically, we could have just defined the functions that take
28 the ref_GF2 parameter type, because of the implicit conversion
29 from GF2& to ref_GF2; however, for efficiency reasons, both
30 flavors are actually provided. It is recommended that higher-level
31 functions use the ref_GF2 type exclusively.
32
33
1334 \**************************************************************************/
1435
1536 #include <NTL/ZZ.h>
37 #include <NTL/vector.h>
1638
1739
1840 class GF2 {
191213 static long GF2::modulus();
192214 // GF2::modulus() returns the value 2
193215
216 template<> class Vec<GF2>;
217 // Forward declaration of the explicit specialization
218 // of Vec<GF2>. This specialization is defined in <NTL/vec_GF2.h>,
219 // which must be included in source files that need to use Vec<GF2>.
220
221
3232 GF2EX(long i, GF2 c);
3333 GF2EX(long i, long c);
3434
35
35
36 typedef GF2E coeff_type;
37
38 // ...
39
3640 };
41
42
43
44
45
46 /**************************************************************************\
47
48 Accessing coefficients
49
50 The degree of a polynomial f is obtained as deg(f),
51 where the zero polynomial, by definition, has degree -1.
52
53 A polynomial f is represented as a coefficient vector.
54 Coefficients may be accesses in one of two ways.
55
56 The safe, high-level method is to call the function
57 coeff(f, i) to get the coefficient of X^i in the polynomial f,
58 and to call the function SetCoeff(f, i, a) to set the coefficient
59 of X^i in f to the scalar a.
60
61 One can also access the coefficients more directly via a lower level
62 interface. The coefficient of X^i in f may be accessed using
63 subscript notation f[i]. In addition, one may write f.SetLength(n)
64 to set the length of the underlying coefficient vector to n,
65 and f.SetMaxLength(n) to allocate space for n coefficients,
66 without changing the coefficient vector itself.
67
68 After setting coefficients using this low-level interface,
69 one must ensure that leading zeros in the coefficient vector
70 are stripped afterwards by calling the function f.normalize().
71
72 NOTE: the coefficient vector of f may also be accessed directly
73 as f.rep; however, this is not recommended. Also, for a properly
74 normalized polynomial f, we have f.rep.length() == deg(f)+1,
75 and deg(f) >= 0 => f.rep[deg(f)] != 0.
76
77 \**************************************************************************/
78
79
80
81 long deg(const GF2EX& a); // return deg(a); deg(0) == -1.
82
83 const GF2E& coeff(const GF2EX& a, long i);
84 // returns the coefficient of X^i, or zero if i not in range
85
86 const GF2E& LeadCoeff(const GF2EX& a);
87 // returns leading term of a, or zero if a == 0
88
89 const GF2E& ConstTerm(const GF2EX& a);
90 // returns constant term of a, or zero if a == 0
91
92 void SetCoeff(GF2EX& x, long i, const GF2E& a);
93 void SetCoeff(GF2EX& x, long i, GF2 a);
94 void SetCoeff(GF2EX& x, long i, long a);
95 // makes coefficient of X^i equal to a; error is raised if i < 0
96
97 void SetCoeff(GF2EX& x, long i);
98 // makes coefficient of X^i equal to 1; error is raised if i < 0
99
100 void SetX(GF2EX& x); // x is set to the monomial X
101
102 long IsX(const GF2EX& a); // test if x = X
103
104
105
106
107 GF2E& GF2EX::operator[](long i);
108 const GF2E& GF2EX::operator[](long i) const;
109 // indexing operators: f[i] is the coefficient of X^i ---
110 // i should satsify i >= 0 and i <= deg(f).
111 // No range checking (unless NTL_RANGE_CHECK is defined).
112
113 void GF2EX::SetLength(long n);
114 // f.SetLength(n) sets the length of the inderlying coefficient
115 // vector to n --- after this call, indexing f[i] for i = 0..n-1
116 // is valid.
117
118 void GF2EX::normalize();
119 // f.normalize() strips leading zeros from coefficient vector of f
120
121 void GF2EX::SetMaxLength(long n);
122 // f.SetMaxLength(n) pre-allocate spaces for n coefficients. The
123 // polynomial that f represents is unchanged.
37124
38125
39126
242329
243330 \**************************************************************************/
244331
245 long deg(const GF2EX& a); // return deg(a); deg(0) == -1.
246
247 const GF2E& coeff(const GF2EX& a, long i);
248 // returns a read-only reference to the coefficient of X^i, or zero if
249 // i not in range
250
251 const GF2E& LeadCoeff(const GF2EX& a);
252 // read-only reference to leading term of a, or zero if a == 0
253
254 const GF2E& ConstTerm(const GF2EX& a);
255 // read-only reference to constant term of a, or zero if a == 0
256
257 void SetCoeff(GF2EX& x, long i, const GF2E& a);
258 void SetCoeff(GF2EX& x, long i, GF2 a);
259 void SetCoeff(GF2EX& x, long i, long a);
260 // makes coefficient of X^i equal to a; error is raised if i < 0
261
262 void SetCoeff(GF2EX& x, long i);
263 // makes coefficient of X^i equal to 1; error is raised if i < 0
264
265 void SetX(GF2EX& x); // x is set to the monomial X
266
267 long IsX(const GF2EX& a); // test if x = X
268332
269333 void diff(GF2EX& x, const GF2EX& a); // x = derivative of a
270334 GF2EX diff(const GF2EX& a);
496560
497561 \**************************************************************************/
498562
499 NTL_vector_decl(GF2EX,vec_GF2EX)
500 // vec_GF2EX
501
502 NTL_eq_vector_decl(GF2EX,vec_GF2EX)
503 // == and !=
504
505 NTL_io_vector_decl(GF2EX,vec_GF2EX)
506 // I/O operators
563 typedef Vec<GF2EX> vec_GF2EX; // backward compatibility
507564
508565
509566
790847
791848 Miscellany
792849
793 A GF2EX f is represented as a vec_GF2E, which can be accessed as
794 f.rep. The constant term is f.rep[0] and the leading coefficient is
795 f.rep[f.rep.length()-1], except if f is zero, in which case
796 f.rep.length() == 0. Note that the leading coefficient is always
797 nonzero (unless f is zero). One can freely access and modify f.rep,
798 but one should always ensure that the leading coefficient is nonzero,
799 which can be done by invoking f.normalize().
800
801850
802851 \**************************************************************************/
803852
805854 void clear(GF2EX& x) // x = 0
806855 void set(GF2EX& x); // x = 1
807856
808 void GF2EX::normalize();
809 // f.normalize() strips leading zeros from f.rep.
810
811 void GF2EX::SetMaxLength(long n);
812 // f.SetMaxLength(n) pre-allocate spaces for n coefficients. The
813 // polynomial that f represents is unchanged.
814857
815858 void GF2EX::kill();
816859 // f.kill() sets f to 0 and frees all memory held by f. Equivalent to
2929
3030 GF2X(long i, GF2 c); // initialize to X^i*c
3131 GF2X(long i, long c);
32
32
33
34 typedef GF2 coeff_type;
35
36 // ...
37
3338 };
3439
3540
36 // SIZE INVARIANT: for any f in GF2X, def(f)+1 < 2^(NTL_BITS_PER_LONG-4).
41
42 /**************************************************************************\
43
44 Accessing coefficients
45
46 The degree of a polynomial f is obtained as deg(f),
47 where the zero polynomial, by definition, has degree -1.
48
49 A polynomial f is represented as a coefficient vector.
50 Coefficients may be accesses in one of two ways.
51
52 The safe, high-level method is to call the function
53 coeff(f, i) to get the coefficient of X^i in the polynomial f,
54 and to call the function SetCoeff(f, i, a) to set the coefficient
55 of X^i in f to the scalar a.
56
57 One can also access the coefficients more directly via a lower level
58 interface. The coefficient of X^i in f may be accessed using
59 subscript notation f[i]. In addition, one may write f.SetLength(n)
60 to set the length of the underlying coefficient vector to n,
61 and f.SetMaxLength(n) to allocate space for n coefficients,
62 without changing the coefficient vector itself.
63
64 After setting coefficients using this low-level interface,
65 one must ensure that leading zeros in the coefficient vector
66 are stripped afterwards by calling the function f.normalize().
67
68 NOTE: unlike other polynomial classes, the coefficient vector
69 for GF2X has a special representation, packing coefficients into
70 words. This has two consequences. First, when using the indexing
71 notation on a non-const polynomial f, the return type is ref_GF2,
72 rather than GF2&. For the most part, a ref_GF2 may be used like
73 a GF2& --- see GF2.txt for more details. Second, when applying
74 f.SetLength(n) to a polynomial f, this essentially has the effect
75 of zeroing out the coefficients of X^i for i >= n.
76
77 \**************************************************************************/
78
79 long deg(const GF2X& a); // return deg(a); deg(0) == -1.
80
81 const GF2 coeff(const GF2X& a, long i);
82 // returns the coefficient of X^i, or zero if i not in range
83
84 const GF2 LeadCoeff(const GF2X& a);
85 // returns leading term of a, or zero if a == 0
86
87 const GF2 ConstTerm(const GF2X& a);
88 // returns constant term of a, or zero if a == 0
89
90 void SetCoeff(GF2X& x, long i, GF2 a);
91 void SetCoeff(GF2X& x, long i, long a);
92 // makes coefficient of X^i equal to a; error is raised if i < 0
93
94 void SetCoeff(GF2X& x, long i);
95 // makes coefficient of X^i equal to 1; error is raised if i < 0
96
97 void SetX(GF2X& x); // x is set to the monomial X
98
99 long IsX(const GF2X& a); // test if x = X
100
101
102
103
104 ref_GF2 GF2X::operator[](long i);
105 const GF2 GF2X::operator[](long i) const;
106 // indexing operators: f[i] is the coefficient of X^i ---
107 // i should satsify i >= 0 and i <= deg(f)
108
109 void GF2X::SetLength(long n);
110 // f.SetLength(n) sets the length of the inderlying coefficient
111 // vector to n --- after this call, indexing f[i] for i = 0..n-1
112 // is valid.
113
114 void GF2X::normalize();
115 // f.normalize() strips leading zeros from coefficient vector of f
116
117 void GF2X::SetMaxLength(long n);
118 // f.SetMaxLength(n) pre-allocate spaces for n coefficients. The
119 // polynomial that f represents is unchanged.
120
121
37122
38123
39124
235320
236321 \**************************************************************************/
237322
238 long deg(const GF2X& a); // return deg(a); deg(0) == -1.
239
240 GF2 coeff(const GF2X& a, long i);
241 // returns the coefficient of X^i, or zero if i not in range
242
243 GF2 LeadCoeff(const GF2X& a);
244 // returns leading term of a, or zero if a == 0
245
246 GF2 ConstTerm(const GF2X& a);
247 // returns constant term of a, or zero if a == 0
248
249 void SetCoeff(GF2X& x, long i, GF2 a);
250 void SetCoeff(GF2X& x, long i, long a);
251 // makes coefficient of X^i equal to a; error is raised if i < 0
252
253 void SetCoeff(GF2X& x, long i);
254 // makes coefficient of X^i equal to 1; error is raised if i < 0
255
256 void SetX(GF2X& x); // x is set to the monomial X
257
258 long IsX(const GF2X& a); // test if x = X
259323
260324 void diff(GF2X& x, const GF2X& a);
261325 GF2X diff(const GF2X& a);
509573
510574 \**************************************************************************/
511575
512 NTL_vector_decl(GF2X,vec_GF2X)
513 // vec_GF2X
514
515 NTL_eq_vector_decl(GF2X,vec_GF2X)
516 // == and !=
517
518 NTL_io_vector_decl(GF2X,vec_GF2X)
519 // I/O operators
576
577 typedef Vec<GF2X> vec_GF2X; // backward compatibility
520578
521579
522580 /**************************************************************************\
725783 void clear(GF2X& x) // x = 0
726784 void set(GF2X& x); // x = 1
727785
728 void GF2X::normalize();
729 // f.normalize() strips leading zeros from f.rep.
730
731 void GF2X::SetMaxLength(long n);
732 // f.SetMaxLength(n) pre-allocate spaces for n coefficients. The
733 // polynomial that f represents is unchanged.
734786
735787 void GF2X::kill();
736 // f.kill() sets f to 0 and frees all memory held by f. Equivalent to
737 // f.rep.kill().
788 // f.kill() sets f to 0 and frees all memory held by f.
738789
739790 GF2X::GF2X(INIT_SIZE_TYPE, long n);
740791 // GF2X(INIT_SIZE, n) initializes to zero, but space is pre-allocated
746797 void swap(GF2X& x, GF2X& y);
747798 // swap x and y (via "pointer swapping")
748799
800 // SIZE INVARIANT: for any f in GF2X, deg(f)+1 < 2^(NTL_BITS_PER_LONG-4).
379379 // ...
380380 // c = MulModPrecon(a, b, n, bninv); // c = (a*b) % n
381381
382
383
384 // The following are vector versions of the MulMod routines
385 // They each compute x[i] = (a[i] * b[i])% n i = 0..k-1
386
387 void VectorMulMod(long k, long *x, const long *a, long b, long n);
388
389 void VectorMulMod(long k, long *x, const long *a, long b, long n,
390 double ninv);
391 // ninv == 1/((double) n)
392
393 void VectorMulModPrecon(long k, long *x, const long *a, long b, long n,
394 mulmod_precon_t bninv);
395 // bninv == MulModPrecon(b, n, ninv)
382396
383397
384398
5858 ZZX(long i, const ZZ& c); // initial value X^i*c
5959 ZZX(long i, long c);
6060
61
62 typedef ZZ coeff_type;
63
6164 // ...
6265
6366 };
67
68
69
70
71 /**************************************************************************\
72
73 Accessing coefficients
74
75 The degree of a polynomial f is obtained as deg(f),
76 where the zero polynomial, by definition, has degree -1.
77
78 A polynomial f is represented as a coefficient vector.
79 Coefficients may be accesses in one of two ways.
80
81 The safe, high-level method is to call the function
82 coeff(f, i) to get the coefficient of X^i in the polynomial f,
83 and to call the function SetCoeff(f, i, a) to set the coefficient
84 of X^i in f to the scalar a.
85
86 One can also access the coefficients more directly via a lower level
87 interface. The coefficient of X^i in f may be accessed using
88 subscript notation f[i]. In addition, one may write f.SetLength(n)
89 to set the length of the underlying coefficient vector to n,
90 and f.SetMaxLength(n) to allocate space for n coefficients,
91 without changing the coefficient vector itself.
92
93 After setting coefficients using this low-level interface,
94 one must ensure that leading zeros in the coefficient vector
95 are stripped afterwards by calling the function f.normalize().
96
97 NOTE: the coefficient vector of f may also be accessed directly
98 as f.rep; however, this is not recommended. Also, for a properly
99 normalized polynomial f, we have f.rep.length() == deg(f)+1,
100 and deg(f) >= 0 => f.rep[deg(f)] != 0.
101
102 \**************************************************************************/
103
104
105
106 long deg(const ZZX& a); // return deg(a); deg(0) == -1.
107
108 const ZZ& coeff(const ZZX& a, long i);
109 // returns the coefficient of X^i, or zero if i not in range
110
111 const ZZ& LeadCoeff(const ZZX& a);
112 // returns leading term of a, or zero if a == 0
113
114 const ZZ& ConstTerm(const ZZX& a);
115 // returns constant term of a, or zero if a == 0
116
117 void SetCoeff(ZZX& x, long i, const ZZ& a);
118 void SetCoeff(ZZX& x, long i, long a);
119 // makes coefficient of X^i equal to a; error is raised if i < 0
120
121 void SetCoeff(ZZX& x, long i);
122 // makes coefficient of X^i equal to 1; error is raised if i < 0
123
124 void SetX(ZZX& x); // x is set to the monomial X
125
126 long IsX(const ZZX& a); // test if x = X
127
128
129
130
131 ZZ& ZZX::operator[](long i);
132 const ZZ& ZZX::operator[](long i) const;
133 // indexing operators: f[i] is the coefficient of X^i ---
134 // i should satsify i >= 0 and i <= deg(f).
135 // No range checking (unless NTL_RANGE_CHECK is defined).
136
137 void ZZX::SetLength(long n);
138 // f.SetLength(n) sets the length of the inderlying coefficient
139 // vector to n --- after this call, indexing f[i] for i = 0..n-1
140 // is valid.
141
142 void ZZX::normalize();
143 // f.normalize() strips leading zeros from coefficient vector of f
144
145 void ZZX::SetMaxLength(long n);
146 // f.SetMaxLength(n) pre-allocate spaces for n coefficients. The
147 // polynomial that f represents is unchanged.
148
149
150
151
64152
65153
66154
313401 \**************************************************************************/
314402
315403
316 long deg(const ZZX& a); returns degree of a; deg(0) == -1
317
318 const ZZ& coeff(const ZZX& a, long i);
319 // returns a read-only reference to a.rep[i], or zero if i not in
320 // range
321
322 const ZZ& LeadCoeff(const ZZX& a);
323 // read-only reference to leading term of a, or zero if a == 0
324
325 const ZZ& ConstTerm(const ZZX& a);
326 // read-only reference to constant term of a, or zero if a == 0
327
328 void SetCoeff(ZZX& x, long i, const ZZ& a);
329 void SetCoeff(ZZX& x, long i, long a);
330 // makes coefficient of X^i equal to a; error is raised if i < 0
331
332 void SetCoeff(ZZX& x, long i);
333 // makes coefficient of X^i equal to 1; error is raised if i < 0
334
335 void SetX(ZZX& x); // x is set to the monomial X
336
337 long IsX(const ZZX& a); // test if x = X
338
339404 void diff(ZZX& x, const ZZX& a); // x = derivative of a
340405 ZZX diff(const ZZX& a);
341406
491556
492557 \**************************************************************************/
493558
494 NTL_vector_decl(ZZX,vec_ZZX)
495 // vec_ZZX
496
497 NTL_eq_vector_decl(ZZX,vec_ZZX)
498 // == and !=
499
500 NTL_io_vector_decl(ZZX,vec_ZZX)
501 // I/O operators
559
560 typedef Vec<ZZX> vec_ZZX; // backward compatibility
502561
503562
504563 /**************************************************************************\
505564
506565 Miscellany
507
508
509 A ZZX f is represented as a vec_ZZ, which can be accessed as
510 f.rep. The constant term is f.rep[0] and the leading coefficient is
511 f.rep[f.rep.length()-1], except if f is zero, in which case
512 f.rep.length() == 0. Note that the leading coefficient is always
513 nonzero (unless f is zero). One can freely access and modify f.rep,
514 but one should always ensure that the leading coefficient is nonzero,
515 which can be done by invoking f.normalize().
516
517566
518567
519568 \**************************************************************************/
521570
522571 void clear(ZZX& x); // x = 0
523572 void set(ZZX& x); // x = 1
524
525 void ZZX::normalize();
526 // f.normalize() strips leading zeros from f.rep.
527
528 void ZZX::SetMaxLength(long n);
529 // f.SetMaxLength(n) pre-allocate spaces for n coefficients. The
530 // polynomial that f represents is unchanged.
531573
532574 void ZZX::kill();
533575 // f.kill() sets f to 0 and frees all memory held by f. Equivalent to
3232 ZZ_pEX(long i, const ZZ_p& c);
3333 ZZ_pEX(long i, long c);
3434
35
35
36 typedef ZZ_pE coeff_type;
37
38 // ...
39
3640 };
41
42
43
44
45 /**************************************************************************\
46
47 Accessing coefficients
48
49 The degree of a polynomial f is obtained as deg(f),
50 where the zero polynomial, by definition, has degree -1.
51
52 A polynomial f is represented as a coefficient vector.
53 Coefficients may be accesses in one of two ways.
54
55 The safe, high-level method is to call the function
56 coeff(f, i) to get the coefficient of X^i in the polynomial f,
57 and to call the function SetCoeff(f, i, a) to set the coefficient
58 of X^i in f to the scalar a.
59
60 One can also access the coefficients more directly via a lower level
61 interface. The coefficient of X^i in f may be accessed using
62 subscript notation f[i]. In addition, one may write f.SetLength(n)
63 to set the length of the underlying coefficient vector to n,
64 and f.SetMaxLength(n) to allocate space for n coefficients,
65 without changing the coefficient vector itself.
66
67 After setting coefficients using this low-level interface,
68 one must ensure that leading zeros in the coefficient vector
69 are stripped afterwards by calling the function f.normalize().
70
71 NOTE: the coefficient vector of f may also be accessed directly
72 as f.rep; however, this is not recommended. Also, for a properly
73 normalized polynomial f, we have f.rep.length() == deg(f)+1,
74 and deg(f) >= 0 => f.rep[deg(f)] != 0.
75
76 \**************************************************************************/
77
78
79
80 long deg(const ZZ_pEX& a); // return deg(a); deg(0) == -1.
81
82 const ZZ_pE& coeff(const ZZ_pEX& a, long i);
83 // returns the coefficient of X^i, or zero if i not in range
84
85 const ZZ_pE& LeadCoeff(const ZZ_pEX& a);
86 // returns leading term of a, or zero if a == 0
87
88 const ZZ_pE& ConstTerm(const ZZ_pEX& a);
89 // returns constant term of a, or zero if a == 0
90
91 void SetCoeff(ZZ_pEX& x, long i, const ZZ_pE& a);
92 void SetCoeff(ZZ_pEX& x, long i, const ZZ_p& a);
93 void SetCoeff(ZZ_pEX& x, long i, long a);
94 // makes coefficient of X^i equal to a; error is raised if i < 0
95
96 void SetCoeff(ZZ_pEX& x, long i);
97 // makes coefficient of X^i equal to 1; error is raised if i < 0
98
99 void SetX(ZZ_pEX& x); // x is set to the monomial X
100
101 long IsX(const ZZ_pEX& a); // test if x = X
102
103
104
105
106 ZZ_pE& ZZ_pEX::operator[](long i);
107 const ZZ_pE& ZZ_pEX::operator[](long i) const;
108 // indexing operators: f[i] is the coefficient of X^i ---
109 // i should satsify i >= 0 and i <= deg(f).
110 // No range checking (unless NTL_RANGE_CHECK is defined).
111
112 void ZZ_pEX::SetLength(long n);
113 // f.SetLength(n) sets the length of the inderlying coefficient
114 // vector to n --- after this call, indexing f[i] for i = 0..n-1
115 // is valid.
116
117 void ZZ_pEX::normalize();
118 // f.normalize() strips leading zeros from coefficient vector of f
119
120 void ZZ_pEX::SetMaxLength(long n);
121 // f.SetMaxLength(n) pre-allocate spaces for n coefficients. The
122 // polynomial that f represents is unchanged.
123
124
125
126
37127
38128
39129
242332
243333 \**************************************************************************/
244334
245 long deg(const ZZ_pEX& a); // return deg(a); deg(0) == -1.
246
247 const ZZ_pE& coeff(const ZZ_pEX& a, long i);
248 // returns a read-only reference to the coefficient of X^i, or zero if
249 // i not in range
250
251 const ZZ_pE& LeadCoeff(const ZZ_pEX& a);
252 // read-only reference to leading term of a, or zero if a == 0
253
254 const ZZ_pE& ConstTerm(const ZZ_pEX& a);
255 // read-only reference to constant term of a, or zero if a == 0
256
257 void SetCoeff(ZZ_pEX& x, long i, const ZZ_pE& a);
258 void SetCoeff(ZZ_pEX& x, long i, const ZZ_p& a);
259 void SetCoeff(ZZ_pEX& x, long i, long a);
260 // makes coefficient of X^i equal to a; error is raised if i < 0
261
262 void SetCoeff(ZZ_pEX& x, long i);
263 // makes coefficient of X^i equal to 1; error is raised if i < 0
264
265 void SetX(ZZ_pEX& x); // x is set to the monomial X
266
267 long IsX(const ZZ_pEX& a); // test if x = X
268335
269336 void diff(ZZ_pEX& x, const ZZ_pEX& a); // x = derivative of a
270337 ZZ_pEX diff(const ZZ_pEX& a);
497564
498565 \**************************************************************************/
499566
500 NTL_vector_decl(ZZ_pEX,vec_ZZ_pEX)
501 // vec_ZZ_pEX
502
503 NTL_eq_vector_decl(ZZ_pEX,vec_ZZ_pEX)
504 // == and !=
505
506 NTL_io_vector_decl(ZZ_pEX,vec_ZZ_pEX)
507 // I/O operators
567
568 typedef Vec<ZZ_pEX> vec_ZZ_pEX; // backward compatibility
508569
509570
510571
790851
791852 Miscellany
792853
793 A ZZ_pEX f is represented as a vec_ZZ_pE, which can be accessed as
794 f.rep. The constant term is f.rep[0] and the leading coefficient is
795 f.rep[f.rep.length()-1], except if f is zero, in which case
796 f.rep.length() == 0. Note that the leading coefficient is always
797 nonzero (unless f is zero). One can freely access and modify f.rep,
798 but one should always ensure that the leading coefficient is nonzero,
799 which can be done by invoking f.normalize().
800
801854
802855 \**************************************************************************/
803856
804857
805858 void clear(ZZ_pEX& x) // x = 0
806859 void set(ZZ_pEX& x); // x = 1
807
808 void ZZ_pEX::normalize();
809 // f.normalize() strips leading zeros from f.rep.
810
811 void ZZ_pEX::SetMaxLength(long n);
812 // f.SetMaxLength(n) pre-allocate spaces for n coefficients. The
813 // polynomial that f represents is unchanged.
814860
815861 void ZZ_pEX::kill();
816862 // f.kill() sets f to 0 and frees all memory held by f. Equivalent to
3434 ZZ_pX(long i, long c);
3535
3636 ~ZZ_pX(); // destructor
37
38
39 typedef ZZ_p coeff_type;
40
41 // ...
42
3743
3844 };
3945
46
47
48
49
50 /**************************************************************************\
51
52 Accessing coefficients
53
54 The degree of a polynomial f is obtained as deg(f),
55 where the zero polynomial, by definition, has degree -1.
56
57 A polynomial f is represented as a coefficient vector.
58 Coefficients may be accesses in one of two ways.
59
60 The safe, high-level method is to call the function
61 coeff(f, i) to get the coefficient of X^i in the polynomial f,
62 and to call the function SetCoeff(f, i, a) to set the coefficient
63 of X^i in f to the scalar a.
64
65 One can also access the coefficients more directly via a lower level
66 interface. The coefficient of X^i in f may be accessed using
67 subscript notation f[i]. In addition, one may write f.SetLength(n)
68 to set the length of the underlying coefficient vector to n,
69 and f.SetMaxLength(n) to allocate space for n coefficients,
70 without changing the coefficient vector itself.
71
72 After setting coefficients using this low-level interface,
73 one must ensure that leading zeros in the coefficient vector
74 are stripped afterwards by calling the function f.normalize().
75
76 NOTE: the coefficient vector of f may also be accessed directly
77 as f.rep; however, this is not recommended. Also, for a properly
78 normalized polynomial f, we have f.rep.length() == deg(f)+1,
79 and deg(f) >= 0 => f.rep[deg(f)] != 0.
80
81 \**************************************************************************/
82
83
84
85 long deg(const ZZ_pX& a); // return deg(a); deg(0) == -1.
86
87 const ZZ_p& coeff(const ZZ_pX& a, long i);
88 // returns the coefficient of X^i, or zero if i not in range
89
90 const ZZ_p& LeadCoeff(const ZZ_pX& a);
91 // returns leading term of a, or zero if a == 0
92
93 const ZZ_p& ConstTerm(const ZZ_pX& a);
94 // returns constant term of a, or zero if a == 0
95
96 void SetCoeff(ZZ_pX& x, long i, const ZZ_p& a);
97 void SetCoeff(ZZ_pX& x, long i, long a);
98 // makes coefficient of X^i equal to a; error is raised if i < 0
99
100 void SetCoeff(ZZ_pX& x, long i);
101 // makes coefficient of X^i equal to 1; error is raised if i < 0
102
103 void SetX(ZZ_pX& x); // x is set to the monomial X
104
105 long IsX(const ZZ_pX& a); // test if x = X
106
107
108
109
110 ZZ_p& ZZ_pX::operator[](long i);
111 const ZZ_p& ZZ_pX::operator[](long i) const;
112 // indexing operators: f[i] is the coefficient of X^i ---
113 // i should satsify i >= 0 and i <= deg(f).
114 // No range checking (unless NTL_RANGE_CHECK is defined).
115
116
117 void ZZ_pX::SetLength(long n);
118 // f.SetLength(n) sets the length of the inderlying coefficient
119 // vector to n --- after this call, indexing f[i] for i = 0..n-1
120 // is valid.
121
122 void ZZ_pX::normalize();
123 // f.normalize() strips leading zeros from coefficient vector of f
124
125 void ZZ_pX::SetMaxLength(long n);
126 // f.SetMaxLength(n) pre-allocate spaces for n coefficients. The
127 // polynomial that f represents is unchanged.
40128
41129
42130
246334 Some utility routines
247335
248336 \**************************************************************************/
249
250 long deg(const ZZ_pX& a); // return deg(a); deg(0) == -1.
251
252 const ZZ_p& coeff(const ZZ_pX& a, long i);
253 // returns a read-only reference to the coefficient of X^i, or zero if
254 // i not in range
255
256 const ZZ_p& LeadCoeff(const ZZ_pX& a);
257 // read-only reference to leading term of a, or zero if a == 0
258
259 const ZZ_p& ConstTerm(const ZZ_pX& a);
260 // read-only reference to constant term of a, or zero if a == 0
261
262 void SetCoeff(ZZ_pX& x, long i, const ZZ_p& a);
263 void SetCoeff(ZZ_pX& x, long i, long a);
264 // makes coefficient of X^i equal to a; error is raised if i < 0
265
266 void SetCoeff(ZZ_pX& x, long i);
267 // makes coefficient of X^i equal to 1; error is raised if i < 0
268
269 void SetX(ZZ_pX& x); // x is set to the monomial X
270
271 long IsX(const ZZ_pX& a); // test if x = X
272337
273338 void diff(ZZ_pX& x, const ZZ_pX& a); // x = derivative of a
274339 ZZ_pX diff(const ZZ_pX& a);
573638
574639 \**************************************************************************/
575640
576 NTL_vector_decl(ZZ_pX,vec_ZZ_pX)
577 // vec_ZZ_pX
578
579 NTL_eq_vector_decl(ZZ_pX,vec_ZZ_pX)
580 // == and !=
581
582 NTL_io_vector_decl(ZZ_pX,vec_ZZ_pX)
583 // I/O operators
641 typedef Vec<ZZ_pX> vec_ZZ_pX; // backward compatibility
584642
585643
586644 /**************************************************************************\
795853
796854 Miscellany
797855
798 A ZZ_pX f is represented as a vec_ZZ_p, which can be accessed as
799 f.rep. The constant term is f.rep[0] and the leading coefficient is
800 f.rep[f.rep.length()-1], except if f is zero, in which case
801 f.rep.length() == 0. Note that the leading coefficient is always
802 nonzero (unless f is zero). One can freely access and modify f.rep,
803 but one should always ensure that the leading coefficient is nonzero,
804 which can be done by invoking f.normalize().
805856
806857 \**************************************************************************/
807858
808859
809860 void clear(ZZ_pX& x) // x = 0
810861 void set(ZZ_pX& x); // x = 1
811
812 void ZZ_pX::normalize();
813 // f.normalize() strips leading zeros from f.rep.
814
815 void ZZ_pX::SetMaxLength(long n);
816 // f.SetMaxLength(n) pre-allocate spaces for n coefficients. The
817 // polynomial that f represents is unchanged.
818862
819863 void ZZ_pX::kill();
820864 // f.kill() sets f to 0 and frees all memory held by f; Equivalent to
288288 NTL_SPMM_UL=off
289289 NTL_SPMM_ULL=off
290290 NTL_SPMM_ASM=off
291 NTL_FFT_BIGTAB=off
292 NTL_FFT_LAZYMUL=off
291293 NTL_TBL_REM=off
292294 NTL_AVOID_BRANCHING=off
293295 NTL_GF2X_NOINLINE=off
578580 # using assembly code. Only supported on select machines
579581 # and only under GCC.
580582
583 NTL_FFT_BIGTAB=off
584
585 # Precomputed tables are used to store all the roots of unity
586 # used in an FFT computation for the first NTL_FFT_BIGTAB_LIMIT
587 # FFT primes (the latter is defined in FFT.h). This can
588 # lead to significant time savings but at the const of some space:
589 # in the worst case, the precomputed tables will take of space
590 # log_2(NTL_FFT_BUGTAB_LIMIT) * M, where M is roughly the maxmimum
591 # space occupied by any one polynomial that was involved in an
592 # FFT computation (this could be a polynomial over zz_p, ZZ_p, or ZZ).
593
594
595 NTL_FFT_LAZYMUL=off
596
597 # This flag only has an effect when combined with the NTL_FFT_BIGTAB
598 # flag, and either the NTL_SPMM_ULL or NTL_SPMM_ASM flags.
599 # When set, a "lazy multiplication" strategy due to David Harvey:
600 # see his paper "FASTER ARITHMETIC FOR NUMBER-THEORETIC TRANSFORMS".
601
581602
582603
583604
1010
1111
1212 int: int, long, uint, ulong, ZZ, float, double, xdouble, quad_float, RR
13 GF2, zz_p, ZZ_p
1314
1415 long: int, long, uint, ulong, ZZ, float, double, xdouble, quad_float, RR
16 GF2, zz_p, ZZ_p
17
18 uint: int, long, uint, ulong, ZZ, float, double, xdouble, quad_float, RR
19 GF2, zz_p, ZZ_p
20
21 ulong: int, long, uint, ulong, ZZ, float, double, xdouble, quad_float, RR
22 GF2, zz_p, ZZ_p
23
24 ZZ: int, long, uint, ulong, ZZ, float, double, xdouble, quad_float, RR, cstr
25 GF2, zz_p, ZZ_p
1526
1627 float: int, long, uint, ulong, ZZ, float, double, xdouble, quad_float, RR
1728
1829 double: int, long, uint, ulong, ZZ, float, double, xdouble, quad_float, RR
19
20 uint: ZZ
21
22 ulong: ZZ
2330
2431 xdouble: int, long, uint, ulong, ZZ, float, double, xdouble, RR, cstr
2532
2835 RR: int, long, uint, ulong, ZZ, float, double, xdouble, quad_float,
2936 RR, cstr
3037
31 ZZ: int, long, uint, ulong, ZZ, float, double, xdouble, quad_float,
32 RR, cstr
3338
34 ZZ_p: long, ZZ
39 ZZ_p: long, ZZ, ZZ_p
3540
36 vec_ZZ_p: vec_ZZ
41 ZZ_pX: long, ZZ, ZZ_p; ZZX, ZZ_pX; ZZ_pE; vec_ZZ_p
3742
38 ZZ_pX: long, ZZ_p, ZZ, ZZX, vec_ZZ_p
43 zz_p: long, ZZ, zz_p
3944
40 zz_p: long, ZZ
45 zz_pX: long, ZZ, zz_p; ZZX, zz_pX; zz_pE; vec_zz_p
4146
42 vec_zz_p: vec_ZZ
47 ZZX: long, ZZ; ZZX, GF2X, zz_pX, ZZ_pX; vec_ZZ
4348
44 ZZ_pX: long, zz_p, ZZ, ZZX, vec_zz_p
49 GF2: long, ZZ, GF2
4550
46 vec_ZZ: vec_ZZ_p, vec_zz_p
51 GF2X: long, ZZ, GF2; ZZX, GF2X; GF2E; vec_GF2
4752
48 ZZX: long, ZZ, ZZ_pX, zz_pX
53 GF2E: long, ZZ, GF2, GF2E; GF2X
4954
50 GF2: long, ZZ
55 GF2EX: long, ZZ, GF2, GF2E; ZZX, GF2X, GF2EX; vec_GF2E
5156
57 ZZ_pE: long, ZZ, ZZ_p, ZZ_pE; ZZ_pX
58
59 ZZ_pEX: long, ZZ, ZZ_p, ZZ_pE; ZZX, ZZ_pX, ZZ_pEX; vec_ZZ_pE
60
61 zz_pE: long, ZZ, zz_p, zz_pE; zz_pX
62
63 zz_pEX: long, ZZ, zz_p, zz_pE; ZZX, zz_pX, zz_pEX; vec_zz_pE
64
65 vec_ZZ: ZZX
66 vec_ZZ_p: ZZ_pX
67 vec_zz_p: zz_pX
5268 vec_GF2: GF2X
53
54 GF2X: long, ZZ, GF2, vec_GF2
55
56 GF2E: long, ZZ, GF2, GF2X
57
58 GF2EX: long, ZZ, GF2, GF2E, GF2X, vec_GF2E
59
60 mat_ZZ_p: mat_ZZ
61
62 mat_zz_p: mat_ZZ
63
64 ZZ_pE: long, ZZ, ZZ_p, ZZ_pX
65
66 ZZ_pEX: long, ZZ, ZZ_p, ZZ_pE, ZZ_pX
67
68 zz_pE: long, ZZ, zz_p, zz_pX
69
70 zz_pEX: long, ZZ, zz_p, zz_pE, zz_pX
69 vec_ZZ_pE: ZZ_pEX
70 vec_zz_pE: zz_pEX
71 vec_GF2E: GF2EX
7172
7273
7374 ********** NOTES ***********
8384 form. To convert a of type S to x of type T, you can write
8485 conv(x, a);
8586 or
86 x = to_T(a);
87 x = conv<T>(a);
8788
88 E.g., to_int(a), to_long(a), to_uint(a), to_ulong(a),
89 to_ZZ(a), to_xdouble(a), to_RR(a).
90
91 [2] All conversions from an integral type to a bounded integral type
89 E.g., conv<int>(a), conv<ZZ>(a), conv< Vec<ZZ_p> >, etc.
90
91 The notation conv<T>(a) was introduced in NTL v6. Prior to
92 this, the notation to_T(a) was used. For backard compatibility,
93 the various "to_T" functions have been retained; however, their
94 use is dicouraged. Also note that new conversions have been
95 added in v6 for which there is no corresponding "to_T" function:
96 for these, one must use the new "conv<T>" notation.
97
98 Note that conv<T> is implemented as a template function:
99
100 template<class T, class S> T conv(const S& a)
101 { T x; conv(x, a); return x; }
102
103 Thus, the call conv<T>(a) always resolves to the procedure call
104 conv(x, a). Modern C++ compilers do a pretty good job implementing
105 the "named return value optimization", so this should not create too
106 any unnecessary temporary objects.
107
108 [2] In addition to the conversions listed, for generic vector types,
109 a template conversion operator is provided:
110
111 template<class T, class S>
112 void conv(Vec<T>& x, const Vec<S>& a) {
113 long n = a.length();
114 x.SetLength(n);
115 for (long i = 0; i < n; i++)
116 conv(x[i], a[i]);
117 }
118
119 This provides component-wise conversion. This, if there is a conversion
120 provided from S to T, then there is automatically a conversion provided
121 from Vec<S> to Vec<T>.
122
123 Note that because of the simple implementation, this input a is not allowed
124 to alias the output x.
125
126 Similarly, for generic matrix types Mat<T>, a template conversion
127 operator provides component-wise conversion. Again, the input may not
128 alias the output.
129
130 [3] All conversions from an integral type to a bounded integral type
92131 compute the result modulo 2^n, where n is the number of bits of the
93132 destination type: no overflow occurs.
94133
95 [3] All floating point to integral conversions compute the floor
134 [4] All floating point to signed integral conversions compute the floor
96135 function *exactly*, unless the destination type is int or long
97 and overflow occurs, in which case the behavior is undefined.
136 and overflow occurs, in which case the result is undefined.
137 An exception: converting an RR x to int or long will always
138 yield floor(x) modulo 2^n, where n is the number of bits
139 in the destination type.
140
141 [5] Conversions from floating point to unsigned int and unsigned long
142 are done via conversions to signed long: if the conversion to long
143 overflows, the result is undefined; otherwise, the result
144 is computed modulo 2^n, where n is the number of bits in
145 the destination type.
98146
99 [4] The ZZ to double conversion routine is very precise:
147 [6] The ZZ to double conversion routine is very precise:
100148 the result is the nearest double, breaking ties using the
101149 "round to even" rule. Overflow results in +/- Infinity.
102150 All this assumes the underlying floating point adheres to
103151 the IEEE standard.
104152
105 [5] All conversions to RR round to the current working precision.
153 [7] All conversions to RR round to the current working precision:
154 even converting an RR to an RR.
155
106156
107 [6] All conversions from long or ZZ to one of the "mod p" types
157 [8] All conversions from long or ZZ to one of the "mod p" types
108158 ZZ_p, ZZ_pX, ZZ_pE, ZZ_pEX,
109159 zz_p, zz_pX, zz_pE, zz_pEX,
110160 GF2, GF2X, GF2E, GF2EX
111 yield the the residue class modulo p.
161 yield the the residue class modulo p (or 2).
112162
113 [7] All polynomial to polynomial conversions apply coefficient-wise
114 conversion.
163 [9] All polynomial-to-polynomial conversions apply coefficient-wise
164 conversion. Note that as a rule, if a conversion S to T
165 is provided, then there is a corresponding conversion from
166 the polynomial ring S[X] to the polynomial ring T[X].
167
168 [10] All polynomial/vector conversions simply copy from/to the coefficient
169 vector of the polynomial.
115170
116 [8] All vector/matrix to vector/matrix conversions apply element-wise
117 conversion.
118
119 [9] The GF2X/ZZ_pX/zz_pX to GF2E/ZZ_pE/zz_pE conversions reduce
171 [11] The GF2X/ZZ_pX/zz_pX to GF2E/ZZ_pE/zz_pE conversions reduce
120172 the given polynomial modulo the current modulus.
121173
122 [10] All conversions from the type cstr apply the same algorithm
174 [12] All conversions from the type cstr apply the same algorithm
123175 as is used for reading from an I/O stream, so
124 ZZ x = to_ZZ("999999999999999999");
176 ZZ x = conv<ZZ>("999999999999999999");
125177 initializes the ZZ x to the integer 999999999999999999.
126178
127 [11] The conversions to vec_ZZ from vec_ZZ_p and vec_zz_p copy the
128 standard non-negative residues; likewise for the conversions
129 to ZZX from ZZ_pX and zz_pX.
130
11 COPYRIGHT NOTICE
22
33 NTL -- A Library for Doing Number Theory
4 Copyright (C) 1996-2009 Victor Shoup
4 Copyright (C) 1996-2013 Victor Shoup
55
66 The most recent version of NTL is available at http://www.shoup.net
77
3232 zz_pEX(long i, const zz_p& c);
3333 zz_pEX(long i, long c);
3434
35
36 typedef zz_pE coeff_type;
37
38 // ...
39
3540
3641 };
3742
43
44
45 /**************************************************************************\
46
47 Accessing coefficients
48
49 The degree of a polynomial f is obtained as deg(f),
50 where the zero polynomial, by definition, has degree -1.
51
52 A polynomial f is represented as a coefficient vector.
53 Coefficients may be accesses in one of two ways.
54
55 The safe, high-level method is to call the function
56 coeff(f, i) to get the coefficient of X^i in the polynomial f,
57 and to call the function SetCoeff(f, i, a) to set the coefficient
58 of X^i in f to the scalar a.
59
60 One can also access the coefficients more directly via a lower level
61 interface. The coefficient of X^i in f may be accessed using
62 subscript notation f[i]. In addition, one may write f.SetLength(n)
63 to set the length of the underlying coefficient vector to n,
64 and f.SetMaxLength(n) to allocate space for n coefficients,
65 without changing the coefficient vector itself.
66
67 After setting coefficients using this low-level interface,
68 one must ensure that leading zeros in the coefficient vector
69 are stripped afterwards by calling the function f.normalize().
70
71 NOTE: the coefficient vector of f may also be accessed directly
72 as f.rep; however, this is not recommended. Also, for a properly
73 normalized polynomial f, we have f.rep.length() == deg(f)+1,
74 and deg(f) >= 0 => f.rep[deg(f)] != 0.
75
76 \**************************************************************************/
77
78
79
80 long deg(const zz_pEX& a); // return deg(a); deg(0) == -1.
81
82 const zz_pE& coeff(const zz_pEX& a, long i);
83 // returns the coefficient of X^i, or zero if i not in range
84
85 const zz_pE& LeadCoeff(const zz_pEX& a);
86 // returns leading term of a, or zero if a == 0
87
88 const zz_pE& ConstTerm(const zz_pEX& a);
89 // returns constant term of a, or zero if a == 0
90
91 void SetCoeff(zz_pEX& x, long i, const zz_pE& a);
92 void SetCoeff(zz_pEX& x, long i, const zz_p& a);
93 void SetCoeff(zz_pEX& x, long i, long a);
94 // makes coefficient of X^i equal to a; error is raised if i < 0
95
96 void SetCoeff(zz_pEX& x, long i);
97 // makes coefficient of X^i equal to 1; error is raised if i < 0
98
99 void SetX(zz_pEX& x); // x is set to the monomial X
100
101 long IsX(const zz_pEX& a); // test if x = X
102
103
104
105
106 zz_pE& zz_pEX::operator[](long i);
107 const zz_pE& zz_pEX::operator[](long i) const;
108 // indexing operators: f[i] is the coefficient of X^i ---
109 // i should satsify i >= 0 and i <= deg(f).
110 // No range checking (unless NTL_RANGE_CHECK is defined).
111
112 void zz_pEX::SetLength(long n);
113 // f.SetLength(n) sets the length of the inderlying coefficient
114 // vector to n --- after this call, indexing f[i] for i = 0..n-1
115 // is valid.
116
117 void zz_pEX::normalize();
118 // f.normalize() strips leading zeros from coefficient vector of f
119
120 void zz_pEX::SetMaxLength(long n);
121 // f.SetMaxLength(n) pre-allocate spaces for n coefficients. The
122 // polynomial that f represents is unchanged.
38123
39124
40125
242327
243328 \**************************************************************************/
244329
245 long deg(const zz_pEX& a); // return deg(a); deg(0) == -1.
246
247 const zz_pE& coeff(const zz_pEX& a, long i);
248 // returns a read-only reference to the coefficient of X^i, or zero if
249 // i not in range
250
251 const zz_pE& LeadCoeff(const zz_pEX& a);
252 // read-only reference to leading term of a, or zero if a == 0
253
254 const zz_pE& ConstTerm(const zz_pEX& a);
255 // read-only reference to constant term of a, or zero if a == 0
256
257 void SetCoeff(zz_pEX& x, long i, const zz_pE& a);
258 void SetCoeff(zz_pEX& x, long i, const zz_p& a);
259 void SetCoeff(zz_pEX& x, long i, long a);
260 // makes coefficient of X^i equal to a; error is raised if i < 0
261
262 void SetCoeff(zz_pEX& x, long i);
263 // makes coefficient of X^i equal to 1; error is raised if i < 0
264
265 void SetX(zz_pEX& x); // x is set to the monomial X
266
267 long IsX(const zz_pEX& a); // test if x = X
268330
269331 void diff(zz_pEX& x, const zz_pEX& a); // x = derivative of a
270332 zz_pEX diff(const zz_pEX& a);
497559
498560 \**************************************************************************/
499561
500 NTL_vector_decl(zz_pEX,vec_zz_pEX)
501 // vec_zz_pEX
502
503 NTL_eq_vector_decl(zz_pEX,vec_zz_pEX)
504 // == and !=
505
506 NTL_io_vector_decl(zz_pEX,vec_zz_pEX)
507 // I/O operators
562
563 typedef Vec<zz_pEX> vec_zz_pEX; // backward compatibility
508564
509565
510566
790846
791847 Miscellany
792848
793 A zz_pEX f is represented as a vec_zz_pE, which can be accessed as
794 f.rep. The constant term is f.rep[0] and the leading coefficient is
795 f.rep[f.rep.length()-1], except if f is zero, in which case
796 f.rep.length() == 0. Note that the leading coefficient is always
797 nonzero (unless f is zero). One can freely access and modify f.rep,
798 but one should always ensure that the leading coefficient is nonzero,
799 which can be done by invoking f.normalize().
800
801849
802850 \**************************************************************************/
803851
804852
805853 void clear(zz_pEX& x) // x = 0
806854 void set(zz_pEX& x); // x = 1
807
808 void zz_pEX::normalize();
809 // f.normalize() strips leading zeros from f.rep.
810
811 void zz_pEX::SetMaxLength(long n);
812 // f.SetMaxLength(n) pre-allocate spaces for n coefficients. The
813 // polynomial that f represents is unchanged.
814855
815856 void zz_pEX::kill();
816857 // f.kill() sets f to 0 and frees all memory held by f. Equivalent to
2929
3030 zz_pX(long i, zz_p c); // initialize to X^i*c
3131 zz_pX(long i, long c);
32
33
34 typedef zz_p coeff_type;
35
36 // ...
37
3238
3339 };
40
41
42
43
44
45 /**************************************************************************\
46
47 Accessing coefficients
48
49 The degree of a polynomial f is obtained as deg(f),
50 where the zero polynomial, by definition, has degree -1.
51
52 A polynomial f is represented as a coefficient vector.
53 Coefficients may be accesses in one of two ways.
54
55 The safe, high-level method is to call the function
56 coeff(f, i) to get the coefficient of X^i in the polynomial f,
57 and to call the function SetCoeff(f, i, a) to set the coefficient
58 of X^i in f to the scalar a.
59
60 One can also access the coefficients more directly via a lower level
61 interface. The coefficient of X^i in f may be accessed using
62 subscript notation f[i]. In addition, one may write f.SetLength(n)
63 to set the length of the underlying coefficient vector to n,
64 and f.SetMaxLength(n) to allocate space for n coefficients,
65 without changing the coefficient vector itself.
66
67 After setting coefficients using this low-level interface,
68 one must ensure that leading zeros in the coefficient vector
69 are stripped afterwards by calling the function f.normalize().
70
71
72 NOTE: the coefficient vector of f may also be accessed directly
73 as f.rep; however, this is not recommended. Also, for a properly
74 normalized polynomial f, we have f.rep.length() == deg(f)+1,
75 and deg(f) >= 0 => f.rep[deg(f)] != 0.
76
77 \**************************************************************************/
78
79
80
81 long deg(const zz_pX& a); // return deg(a); deg(0) == -1.
82
83 const zz_p coeff(const zz_pX& a, long i);
84 // returns the coefficient of X^i, or zero if i not in range
85
86 const zz_p LeadCoeff(const zz_pX& a);
87 // returns leading term of a, or zero if a == 0
88
89 const zz_p ConstTerm(const zz_pX& a);
90 // returns constant term of a, or zero if a == 0
91
92 void SetCoeff(zz_pX& x, long i, zz_p a);
93 void SetCoeff(zz_pX& x, long i, long a);
94 // makes coefficient of X^i equal to a; error is raised if i < 0
95
96 void SetCoeff(zz_pX& x, long i);
97 // makes coefficient of X^i equal to 1; error is raised if i < 0
98
99 void SetX(zz_pX& x); // x is set to the monomial X
100
101 long IsX(const zz_pX& a); // test if x = X
102
103
104
105
106 zz_p& zz_pX::operator[](long i);
107 const zz_p& zz_pX::operator[](long i) const;
108 // indexing operators: f[i] is the coefficient of X^i ---
109 // i should satsify i >= 0 and i <= deg(f).
110 // No range checking (unless NTL_RANGE_CHECK is defined).
111
112 void zz_pX::SetLength(long n);
113 // f.SetLength(n) sets the length of the inderlying coefficient
114 // vector to n --- after this call, indexing f[i] for i = 0..n-1
115 // is valid.
116
117 void zz_pX::normalize();
118 // f.normalize() strips leading zeros from coefficient vector of f
119
120 void zz_pX::SetMaxLength(long n);
121 // f.SetMaxLength(n) pre-allocate spaces for n coefficients. The
122 // polynomial that f represents is unchanged.
34123
35124
36125
237326
238327 \**************************************************************************/
239328
240 long deg(const zz_pX& a); // return deg(a); deg(0) == -1.
241
242 zz_p coeff(const zz_pX& a, long i);
243 // returns the coefficient of X^i, or zero if i not in range
244
245 zz_p LeadCoeff(const zz_pX& a);
246 // returns leading term of a, or zero if a == 0
247
248 zz_p ConstTerm(const zz_pX& a);
249 // returns constant term of a, or zero if a == 0
250
251 void SetCoeff(zz_pX& x, long i, zz_p a);
252 void SetCoeff(zz_pX& x, long i, long a);
253 // makes coefficient of X^i equal to a; error is raised if i < 0
254
255 void SetCoeff(zz_pX& x, long i);
256 // makes coefficient of X^i equal to 1; error is raised if i < 0
257
258 void SetX(zz_pX& x); // x is set to the monomial X
259
260 long IsX(const zz_pX& a); // test if x = X
261329
262330 void diff(zz_pX& x, const zz_pX& a);
263331 zz_pX diff(const zz_pX& a);
572640
573641 \**************************************************************************/
574642
575 NTL_vector_decl(zz_pX,vec_zz_pX)
576 // vec_zz_pX
577
578 NTL_eq_vector_decl(zz_pX,vec_zz_pX)
579 // == and !=
580
581 NTL_io_vector_decl(zz_pX,vec_zz_pX)
582 // I/O operators
643
644 typedef Vec<zz_pX> vec_zz_pX; // backward compatibility
645
583646
584647
585648 /**************************************************************************\
795858
796859 Miscellany
797860
798 A zz_pX f is represented as a vec_zz_p, which can be accessed as
799 f.rep. The constant term is f.rep[0] and the leading coefficient is
800 f.rep[f.rep.length()-1], except if f is zero, in which case
801 f.rep.length() == 0. Note that the leading coefficient is always
802 nonzero (unless f is zero). One can freely access and modify f.rep,
803 but one should always ensure that the leading coefficient is nonzero,
804 which can be done by invoking f.normalize().
805
806861
807862 \**************************************************************************/
808863
809864
810865 void clear(zz_pX& x) // x = 0
811866 void set(zz_pX& x); // x = 1
812
813 void zz_pX::normalize();
814 // f.normalize() strips leading zeros from f.rep.
815
816 void zz_pX::SetMaxLength(long n);
817 // f.SetMaxLength(n) pre-allocate spaces for n coefficients. The
818 // polynomial that f represents is unchanged.
819867
820868 void zz_pX::kill();
821869 // f.kill() sets f to 0 and frees all memory held by f. Equivalent to
1212 #include <NTL/matrix.h>
1313 #include <NTL/vec_vec_GF2E.h>
1414
15 NTL_matrix_decl(GF2E,vec_GF2E,vec_vec_GF2E,mat_GF2E)
16 NTL_io_matrix_decl(GF2E,vec_GF2E,vec_vec_GF2E,mat_GF2E)
17 NTL_eq_matrix_decl(GF2E,vec_GF2E,vec_vec_GF2E,mat_GF2E)
15
16 typedef Mat<GF2E> mat_GF2E; // backward compatibility
17
1818
1919 void add(mat_GF2E& X, const mat_GF2E& A, const mat_GF2E& B);
2020 // X = A + B
1212 #include <NTL/matrix.h>
1313 #include <NTL/vec_vec_RR.h>
1414
15 NTL_matrix_decl(RR,vec_RR,vec_vec_RR,mat_RR)
16 NTL_io_matrix_decl(RR,vec_RR,vec_vec_RR,mat_RR)
17 NTL_eq_matrix_decl(RR,vec_RR,vec_vec_RR,mat_RR)
15 typedef Mat<RR> mat_RR; // backward compatibility
1816
1917 void add(mat_RR& X, const mat_RR& A, const mat_RR& B);
2018 // X = A + B
1212 #include <NTL/matrix.h>
1313 #include <NTL/vec_vec_ZZ.h>
1414
15 NTL_matrix_decl(ZZ,vec_ZZ,vec_vec_ZZ,mat_ZZ)
16 NTL_io_matrix_decl(ZZ,vec_ZZ,vec_vec_ZZ,mat_ZZ)
17 NTL_eq_matrix_decl(ZZ,vec_ZZ,vec_vec_ZZ,mat_ZZ)
15 typedef Mat<ZZ> mat_ZZ; // backward compatibility
1816
1917 void add(mat_ZZ& X, const mat_ZZ& A, const mat_ZZ& B);
2018 // X = A + B
1212 #include <NTL/matrix.h>
1313 #include <NTL/vec_vec_ZZ_p.h>
1414
15 NTL_matrix_decl(ZZ_p,vec_ZZ_p,vec_vec_ZZ_p,mat_ZZ_p)
16 NTL_io_matrix_decl(ZZ_p,vec_ZZ_p,vec_vec_ZZ_p,mat_ZZ_p)
17 NTL_eq_matrix_decl(ZZ_p,vec_ZZ_p,vec_vec_ZZ_p,mat_ZZ_p)
15
16 typedef mat_ZZ_p mat_ZZ_p; // backward compatibility
1817
1918 void add(mat_ZZ_p& X, const mat_ZZ_p& A, const mat_ZZ_p& B);
2019 // X = A + B
1212 #include <NTL/matrix.h>
1313 #include <NTL/vec_vec_ZZ_pE.h>
1414
15 NTL_matrix_decl(ZZ_pE,vec_ZZ_pE,vec_vec_ZZ_pE,mat_ZZ_pE)
16 NTL_io_matrix_decl(ZZ_pE,vec_ZZ_pE,vec_vec_ZZ_pE,mat_ZZ_pE)
17 NTL_eq_matrix_decl(ZZ_pE,vec_ZZ_pE,vec_vec_ZZ_pE,mat_ZZ_pE)
15
16 typedef Mat<ZZ_pE> mat_ZZ_pE; // backward compatibility
1817
1918 void add(mat_ZZ_pE& X, const mat_ZZ_pE& A, const mat_ZZ_pE& B);
2019 // X = A + B
1212 #include <NTL/matrix.h>
1313 #include "vec_vec_zz_p.h"
1414
15 NTL_matrix_decl(zz_p,vec_zz_p,vec_vec_zz_p,mat_zz_p)
16 NTL_io_matrix_decl(zz_p,vec_zz_p,vec_vec_zz_p,mat_zz_p)
17 NTL_eq_matrix_decl(zz_p,vec_zz_p,vec_vec_zz_p,mat_zz_p)
15
16 typedef Mat<zz_p> mat_zz_p; // backward compatibility
1817
1918 void add(mat_zz_p& X, const mat_zz_p& A, const mat_zz_p& B);
2019 // X = A + B
1212 #include <NTL/matrix.h>
1313 #include <NTL/vec_vec_lzz_pE.h>
1414
15 NTL_matrix_decl(zz_pE,vec_zz_pE,vec_vec_zz_pE,mat_zz_pE)
16 NTL_io_matrix_decl(zz_pE,vec_zz_pE,vec_vec_zz_pE,mat_zz_pE)
17 NTL_eq_matrix_decl(zz_pE,vec_zz_pE,vec_vec_zz_pE,mat_zz_pE)
15
16 typedef Mat<zz_pE> mat_zz_pE; // backward compatibility
1817
1918 void add(mat_zz_pE& X, const mat_zz_pE& A, const mat_zz_pE& B);
2019 // X = A + B
44
55 SUMMARY:
66
7 Macros are deined providing template-like classes for dynamic-sized,
8 recatngular matrices.
7 Matrix templates.
98
10 The macro NTL_matrix_decl(T,vec_T,vec_vec_T,mat_T) declares a new class
11 mat_T representing matrices over T, where vec_T and vec_vec_T are
12 classes representing "NTL vectors" over T and vec_T, respectively.
9 The declaration
1310
14 The implementation of mat_T can be instantiated with
15 NTL_matrix_impl(T,vec_T,vec_vec_T,mat_T).
11 Mat<T> M;
1612
17 If T supports I/O and/or equluality testing, then mat_T
18 can also be made to support these.
13 creates a 0 x 0 matrix.
1914
20 For example, the declaration
21
22 mat_T M;
23
24 creates a 0 x 0 matrix. We can make it have 10 rows and 20 columns like this:
15 We can make it have 10 rows and 20 columns like this:
2516
2617 M.SetDims(10, 20);
2718
2920 A matrix entry can be accessed as M[i][j], indexing from 0, or as
3021 M(i, j), indexing from 1.
3122
32 A matrix is represented as a vec_vec_T: a vector of rows, where
33 each row is a vec_T. Any attempt to resize one of the rows so
23 A matrix is represented as a Vec< Vec<T> >: a vector of rows, where
24 each row is a Vec<T>. Any attempt to resize one of the rows so
3425 as to create a non-rectangular matrix will result in a run-time
3526 error.
3627
4233
4334 \**************************************************************************/
4435
45 class mat_T {
46 mat_T(); // initially 0 x 0
36 template<class T>
37 class Mat {
4738
48 mat_T(const mat_T& a);
49 mat_T& operator=(const mat_T& a);
50 ~mat_T();
39 typedef typename Vec<T>::value_type value_type;
40 typedef typename Vec<T>::reference reference;
41 typedef typename Vec<T>::const_reference const_reference;
5142
52 mat_T(INIT_SIZE_TYPE, long n, long m);
53 // mat_T(INIT_SIZE, n, m) initializes an n x m matrix, invoking
43
44 Mat(); // initially 0 x 0
45
46 Mat(const Mat<T>& a);
47 Mat& operator=(const Mat<T>& a);
48 ~Mat();
49
50 Mat(INIT_SIZE_TYPE, long n, long m);
51 // Mat(INIT_SIZE, n, m) initializes an n x m matrix, invoking
5452 // the default constructor for T to initialize entries.
5553
5654 void SetDims(long n, long m);
6967 long NumCols() const;
7068 // M.NumCols() returns the number of columns of M
7169
72 vec_T& operator[](long i);
73 const vec_T& operator[](long i) const;
70 Vec<T>& operator[](long i);
71 const Vec<T>& operator[](long i) const;
7472 // access row i, initial index 0. Any attempt to change the length
7573 // of this row will raise an error.
7674
77 vec_T& operator()(long i);
78 const vec_T& operator()(long i) const;
75 Vec<T>& operator()(long i);
76 const Vec<T>& operator()(long i) const;
7977 // access row i, initial index 1. Any attempt to change the length
8078 // of this row will raise an error.
8179
82 T& operator()(long i, long j);
83 const T& operator()(long i, long j) const;
80 reference operator()(long i, long j);
81 const_reference operator()(long i, long j) const;
8482 // access element (i, j), both indices starting at 1
8583
86 long position(const vec_T& a) const;
84 const_reference get(long i, long j) const;
85 // access element (i, j), both indices starting at 0
86
87 void put(long i, long j, const T& a);
88 // same as M[i].put(j, a)
89
90 template <class U>
91 void put(long i, long j, const U& a);
92 // same as M[i].put(j, a)
93
94
95 long position(const Vec<T>& a) const;
8796 // returns index of a in matrix, or -1 if not present;
8897 // equivalent to rep(*this).position(a).
8998
9099
91 long position1(const vec_T& a) const;
100 long position1(const Vec<T>& a) const;
92101 // returns index of a in matrix, or -1 if not present;
93102 // equivalent to rep(*this).position1(a).
94103
104
95105
96106 };
97107
98 const vec_vec_T& rep(const mat_T& a);
108 template<class T>
109 const Vec< Vec<T> >& rep(const Mat<T>& a);
99110 // read-only access to underlying representation
100111
101 void swap(mat_T& X, mat_T& Y);
112 template<class T>
113 void swap(Mat<T>& X, Mat<T>& Y);
102114 // swaps X and Y (by swapping pointers)
103115
104 void MakeMatrix(mat_T& x, const vec_vec_T& a);
116 template<class T>
117 void MakeMatrix(Mat<T>& x, const vec_vec_T& a);
105118 // copies a to x, checking that it is "rectangular"
106119
107120 /**************************************************************************\
108121
109122 Input/Output
110123
111 The I/O operators can be declared with
112 NTL_io_matrix_decl(T,vec_T,vec_vec_T,mat_T), and
113 implemented using NTL_io_matrix_impl(T,vec_T,vec_vec_T,mat_T).
114 I/O is implemented using the underlying I/O operators for vec_vec_T.
115
116124 \**************************************************************************/
117125
118126
119 istream& operator>>(istream&, mat_T&);
120 ostream& operator<<(ostream&, const mat_T&);
127 template<class T>
128 istream& operator>>(istream&, Mat<T>&);
129
130 template<class T>
131 ostream& operator<<(ostream&, const Mat<T>&);
121132
122133 /**************************************************************************\
123134
124135 Equality Testing
125136
126 The equality testing operators == and != can be declared
127 NTL_eq_matrix_decl(T,vec_T,vec_vec_T,mat_T), and
128 implemented using NTL_eq_matrix_impl(T,vec_T,vec_vec_T,mat_T).
129 Equality testing is implemented using the underlying
130 equality operators for vec_vec_T.
131
132137
133138 \**************************************************************************/
134139
135140
136 long operator==(const mat_T& a, const mat_T& b);
137 long operator!=(const mat_T& a, const mat_T& b);
141 template<class T>
142 long operator==(const Mat<T>& a, const Mat<T>& b);
138143
144 template<class T>
145 long operator!=(const Mat<T>& a, const Mat<T>& b);
146
33
44 SUMMARY:
55
6 Macros are defined providing template-like classes for pairs.
7
8 The macro NTL_pair_decl(S,T,pair_S_T) declares a class pair_S_T whose
9 implementation can be instatntiated with NTL_pair_impl(S,T,pair_S_T). It is
10 presumed that the underlying types have a default constructor, a copy
11 constructor, and assignment operator, and a destructor (this is
12 normally the case for most types).
13
14 If S and T support I/O operator << and >>, then pair_S_T can be made
15 to support these operators as well using NTL_pair_io_decl(S,T,pair_S_T) and
16 NTL_pair_io_impl(S,T,pair_S_T).
17
18 The same goes for the equaltity operators == and != using
19 NTL_pair_eq_decl(S,T,pair_S_T) and NTL_pair_eq_impl(S,T,pair_S,T).
6 Pair templates.
207
218 The decalaration
229
23 pair_S_T p;
10 Pair<S,T> p;
2411
2512 creates a pair object using the default constructors for S and T. The
2613 member p.a is the first component (of type S) and the member p.b is
3320
3421 #include <NTL/tools.h>
3522
36 class pair_S_T {
23 template<class S, class T>
24 class Pair {
3725 public:
3826 S a;
3927 T b;
4028
41 pair_S_T();
29 Pair();
4230 // default constructor...invokes default constructors for S and T
4331
44 pair_S_T(const pair_S_T& x); // copy
32 Pair(const Pair<S,T>& x); // copy
4533
46 pair_S_T& operator=(const pair_S_T& x); // assignment
34 Pair& operator=(const Pair<S,T>& x); // assignment
4735
48 pair_S_T(const S& x, const T& y); // initialize with (x, y)
36 Pair(const S& x, const T& y); // initialize with (x, y)
4937
50 ~pair_S_T();
38 ~Pair();
5139 // destructor...invokes destructors for S and T
5240 };
5341
54 pair_S_T cons(const S& x, const T& y);
55 // returns pair_S_T(x, y)
42 template<class S, class T>
43 Pair<S,T> cons(const S& x, const T& y);
44 // returns Pair<S,T>(x, y)
5645
5746
5847 /**************************************************************************\
5948
6049 Input/Output
6150
62 The I/O operators can be declared with NTL_pair_io_decl(S,T,pair_S_T), and
63 implemented using NTL_pair_io_impl(S,T,pair_S_T).
64 Elements are read and written using the underlying I/O
65 operators << and >> for S and T.
66
67 The I/O format for a pair_a_b is
51 The I/O format for a Pair is
6852
6953 [a b]
7054
7155 \**************************************************************************/
7256
7357
58 template<class S, class T>
59 istream& operator>>(istream&, Pair<S,T>&);
7460
75 istream& operator>>(istream&, pair_S_T&);
76 ostream& operator<<(ostream&, const pair_S_T&);
61 template<class S, class T>
62 ostream& operator<<(ostream&, const Pair<S,T>&);
7763
7864
7965 /**************************************************************************\
8066
8167 Equality Testing
8268
83 The equality testing operators == and != can be declared with
84 NTL_pair_eq_decl(S,T,pair_S_T) and implemented with
85 NTL_pair_eq_impl(S,T,pair_S,T). The tests are performed using
86 the underlying operator == for S and T.
87
8869 \**************************************************************************/
8970
9071
91 long operator==(const pair_S_T& x, const pair_S_T& y);
92 long operator!=(const pair_S_T& x, const pair_S_T& y);
72 template<class S, class T>
73 long operator==(const Pair<S,T>& x, const Pair<S,T>& y);
74
75 template<class S, class T>
76 long operator!=(const Pair<S,T>& x, const Pair<S,T>& y);
9377
9478
9090 // int, long, float, double. See conversions.txt for complete details.
9191
9292
93
9394 // The following platform-dependent macros are defined:
9495
9596 #define NTL_BITS_PER_LONG (...) /* bits in a long */
1515 A Tour of NTL: Summary of Changes
1616 </p>
1717 </h1>
18
19 <p> <hr> <p>
20 <h3>
21 2013.02.15: Changes between NTL 5.5.2 and 6.0
22 </h3>
23
24 <ul>
25 <li>
26 Replaced the old template-like macros for vectors, matrices,
27 and pairs with true template classes: <tt>Vec&lt;T&gt;</tt>,
28 <tt>Mat&lt;T&gt;</tt>, and <tt>Pair&lt;S,T&gt;</tt>.
29
30 <p>
31 For backwards compatibilty, all the names that were used
32 in previous versions (e.g., <tt>vec_ZZ_p</tt>, <tt>mat_ZZ_p</tt>)
33 have been replaced with appropriate typedefs.
34
35 <p>
36 For many years, I resisted the temptation of using templates,
37 because compiler support was very inconsistent.
38 But that no longer seems to be the case.
39
40 <p>
41 This change, while rather sweeping, should create very few,
42 if any, incompatibilities with existing software.
43 The biggest issue would be for software that uses the
44 old template-like macros: such macro invocations can simply be
45 replaced with appropriate typedefs.
46
47 <p>
48 <li>
49 Made the conversion interface more complete and uniform.
50 Also, using template notation, one can and should now write
51 <tt>conv&lt;ZZ&gt;(a)</tt> instead of <tt>to_ZZ(a)</tt>
52 (for backward compatibility, all the old names <tt>to_XXX</tt>
53 are still there, but many new conversions are not available
54 under these old names).
55
56
57 <p>
58 There are many new conversions provided.
59 Moreover, whenever there is a conversion from a ring <i>R</i>
60 to a ring <i>S</i>, there is a corresponding, coefficiet-wise
61 conversion from the polynomial ring <i>R[X]</i> to the
62 polynomial ring <i>R[X]</i>.
63
64 <p>
65 In addition, using the template mechanism, there are
66 generic conversions for vectors and matrices.
67 For example, if there is a conversion from <tt>S</tt> to <tt>T</tt>,
68 then there is automatically a corresponding component-wise
69 conversion from <tt>Vec&lt;S&gt;</tt> to <tt>Vec&lt;T&gt;</tt>.
70
71
72 <p>
73 <li>
74 Introduced a more general mechanism for accessing <tt>GF2</tt>'s
75 in packed structures via indexing (see the class
76 <tt>ref_GF2</tt> in the <tt>GF2</tt> module).
77
78 <p>
79 <li>
80 Employed ideas from David Harvey to make the single-precision
81 FFT faster (about twice as fast in many cases).
82 This speeds up many higher-level operations.
83
84
85 <p>
86 <li>
87 Fixed all known bugs.
88
89
90 </ul>
91
92
1893
1994 <p> <hr> <p>
2095 <h3>
3030 <pre>
3131 #include &lt;NTL/ZZ.h&gt;
3232
33 NTL_CLIENT
33 using namespace std;
34 using namespace NTL;
3435
3536 int main()
3637 {
6162 with memory management and temporary objects.
6263
6364 <p>
64 Note the macro <tt>NTL_CLIENT</tt>.
65 When compiling NTL is ISO mode (the default), this
66 expands to
67 <pre>
68 using namespace std;
65 Note that by default, all of NTL's components
66 are in the namespace <tt>NTL</tt>;
67 with the "using directive"
68 <pre>
6969 using namespace NTL;
7070 </pre>
71 When compiling NTL in traditional mode, this expands
72 to the empty string.
73 More details <a href="tour-stdcxx.html">here</a>.
71 in the above example, one can access
72 these components directly.
73 More details on namespaces and NTL <a href="tour-stdcxx.html">here</a>.
7474
7575 <p> <hr> <p>
7676
8181 <pre>
8282 #include &lt;NTL/ZZ.h&gt;
8383
84 NTL_CLIENT
84
85 using namespace std;
86 using namespace NTL;
87
8588
8689 int main()
8790 {
206209 The following program prompts the user for an input,
207210 and applies a simple probabilistic primality test.
208211 Note that NTL already provides a slightly more sophisticated
209 prime test.
212 primality test.
210213
211214 <p>
212215 <pre>
213216 #include &lt;NTL/ZZ.h&gt;
214217
215 NTL_CLIENT
218 using namespace std;
219 using namespace NTL;
216220
217221 long witness(const ZZ&amp; n, const ZZ&amp; x)
218222 {
363367 ZZ x = 1; // error
364368 </pre>
365369 to initialize a <tt>ZZ</tt>.
366 As a design principle, NTL avoids implicit conversions, and unfortunately,
367 the only way to allow initializations like this in <tt>C++</tt>
368 is to define an implicit conversion operator.
369370 Instead, one could write
370371 <pre>
371 ZZ x = to_ZZ(1);
372 ZZ x = conv&lt;ZZ&gt;(1);
372373 </pre>
373374 This is an example of one of NTL's conversion routines.
374375 For very large constants, one can write:
375376 <pre>
376 ZZ x = to_ZZ("99999999999999999999");
377 ZZ x = conv&lt;ZZ&gt;("99999999999999999999");
377378 </pre>
378379 These examples illustrate conversion rountines in their
379380 functional forms.
380 The corresponding procedural forms are all called <tt>conv</tt>, e.g.,
381381 <pre>
382382 ZZ x;
383383 conv(x, 1);
394394 including comparison, arithmetic, shift, and bit-wise logical operations.
395395 One can mix <tt>ZZ</tt>s and <tt>long</tt>s in any expresion in
396396 a natural way.
397 As was already mentioned, NTL does not support implicit type conversion;
397 NTL does not support implicit type conversion;
398398 rather, for basic operations, it simply overloads the operators
399399 or functions in a way to achieve a kind of "promotion logic":
400400 if one input is a <tt>ZZ</tt> and the other is a <tt>long</tt>
2525 numbers in a vector of <tt>ZZ</tt>'s.
2626
2727 <pre>
28 #include &lt;NTL/vec_ZZ.h&gt;
29
30 NTL_CLIENT
31
32 ZZ sum(const vec_ZZ&amp; v)
28 #include &lt;NTL/ZZ.h&gt;
29 #include &lt;NTL/vector.h&gt;
30
31 using namespace std;
32 using namespace NTL;
33
34 ZZ sum(const Vec&lt;ZZ&gt;&amp; v)
3335 {
3436 ZZ acc;
3537
4345 </pre>
4446
4547 <p>
46 The class <tt>vec_ZZ</tt> is a dynamic-length array of <tt>ZZ</tt>s;
47 more generally, NTL provides template-like macros to create dynamic-length
48 vectors over any type T.
49 By convention, NTL names these vec_T.
50 The reason that macros are used instead of true templates is simple:
51 at the present time, compiler support for templates is not entirely
52 satisfactory, and their use would make NTL much more difficult to port.
53 At some point in the future, a template-version of NTL may be made
54 available.
48 The class <tt>Vec&lt;ZZ&gt;</tt> is a dynamic-length array of <tt>ZZ</tt>s;
49 more generally, NTL provides a template class <tt>Vec&lt;T&gt;</tt>
50 for
51 dynamic-length
52 vectors over any type <tt>T</tt>.
53
54 Some history is in order here.
55 NTL predates the STL and the <tt>vector</tt> template
56 found in modern <tt>C++</tt>.
57 Older versions of NTL (prior to v6) did not use templates, but instead
58 defined generic vectors using macros.
59 By convention, NTL named these <tt>vec_T</tt>.
60 For backward compatibility, NTL now provides typedefs
61 all these "legacy" vector types.
62
5563
5664 <p>
5765 Vectors in NTL are indexed from 0, but in many situations
6068 the above example could be written as follows.
6169
6270 <pre>
63 #include &lt;NTL/vec_ZZ.h&gt;
64
65 NTL_CLIENT
66
67 ZZ sum(ZZ&amp; s, const vec_ZZ&amp; v)
71 #include &lt;NTL/ZZ.h&gt;
72 #include &lt;NTL/vector.h&gt;
73
74 using namespace std;
75 using namespace NTL;
76
77 ZZ sum(ZZ&amp; s, const Vec&lt;ZZ&gt;&amp; v)
6878 {
6979 ZZ acc;
7080
8898
8999 The following example illustrates vector I/O,
90100 as well as changing the length of a vector.
91 This program reads a <tt>vec_ZZ</tt>,
101 This program reads a <tt>Vec&lt;ZZ&gt;</tt>,
92102 and then creates and prints a "palindrome".
93103
94104 <pre>
95 #include &lt;NTL/vec_ZZ.h&gt;
96
97 NTL_CLIENT
105 #include &lt;NTL/ZZ.h&gt;
106 #include &lt;NTL/vector.h&gt;
107
108 using namespace std;
109 using namespace NTL;
98110
99111 int main()
100112 {
101 vec_ZZ v;
113 Vec&lt;ZZ&gt; v;
102114 cin &gt;&gt; v;
103115
104116 long n = v.length();
131143
132144 <p>
133145
134 NTL pre-defines a number of vector types.
135 In addition, you can create your own.
136146 See <a href="vector.txt"><tt>vector.txt</tt></a> for
137147 complete details of NTL's generic vector mechanism.
138 Also see <a href="vec_ZZ.txt"><tt>vec_ZZ.txt</tt></a> for
139 complete details on the arithmetic operations for <tt>vec_ZZ</tt>s
148
149 Also note that for several fundamental vector types, such as
150 <tt>Vec&lt;ZZ&gt;.txt</tt>, there is a corresponding header file
151 <tt>&lt;NTL/vec_ZZ.h&gt;</tt> that defines
152 a number of basic arithmetic operations,
153 as well as provides the typedef
154 typedef <tt>vec_ZZ</tt> for backward compatibilty.
155 See <a href="vec_ZZ.txt"><tt>vec_ZZ.txt</tt></a> for
156 complete details on the arithmetic operations for <tt>Vec&lt;ZZ&gt;</tt>'s
140157 provided by NTL.
141158
142159
145162
146163 There is also basic support for matrices
147164 in NTL.
148 In general, the class <tt>mat_T</tt> is a special
149 kind of <tt>vec_vec_T</tt>, where each row is
165 In general, the class <tt>Mat&lt;T&gt;</tt> is a special
166 kind of <tt>Vec&lt; Vec&lt; T &gt; &gt;</tt>, where each row is
150167 a vector of the same length.
151168 Row <tt>i</tt> of matrix <tt>M</tt>
152169 can be accessed as <tt>M[i]</tt> (indexing from 0)
160177 which in fact is already provided by NTL.
161178
162179 <pre>
163 #include &lt;NTL/mat_ZZ.h&gt;
164
165 NTL_CLIENT
166
167 void mul(mat_ZZ&amp; X, const mat_ZZ&amp; A, const mat_ZZ&amp; B)
180 #include &lt;NTL/ZZ.h&gt;
181 #include &lt;NTL/matrix.h&gt;
182
183 using namespace std;
184 using namespace NTL;
185
186 void mul(Mat&lt;ZZ&gt;&amp; X, const Mat&lt;ZZ&gt;&amp; A, const Mat&lt;ZZ&gt;&amp; B)
168187 {
169188 long n = A.NumRows();
170189 long l = A.NumCols();
196215 <tt>Error</tt> function, which is a part of NTL and which simply
197216 prints the message and aborts.
198217 That is generally how NTL deals with errors.
199 Currently, NTL makes no use of exceptions (for the same reason
200 it does not use templates--see above), but a future version
201 may incorporate them.
202218
203219 <p>
204220 This routine will not work properly if <tt>X</tt> aliases
207223 In fact, all of NTL's routines allow outputs to alias inputs.
208224
209225 <p>
210
211 To call the multiplication routine, one can write
226 To call NTL's built-in multiplication routine
227 (declared in <tt>&lt;NTL/mat_ZZ.h&gt;</tt>), one can write
212228 <pre>
213229 mul(X, A, B);
214230 </pre>
222238 See <a href="matrix.txt"><tt>matrix.txt</tt></a>
223239 for complete details on NTL's generic matrix mechanism.
224240 Also see <a href="mat_ZZ.txt"><tt>mat_ZZ.txt</tt></a> for
225 complete details on the arithmetic operations for <tt>mat_ZZ</tt>s
241 complete details on the arithmetic operations for <tt>Mat&lt;ZZ&gt;</tt>'s
226242 provideed by NTL (including basic linear algebra).
227243 Also see <a href="LLL.txt"><tt>LLL.txt</tt></a>
228244 for details on routines for lattice basis reduction
3333 <pre>
3434 #include &lt;NTL/ZZXFactoring.h&gt;
3535
36 NTL_CLIENT
36 using namespace std;
37 using namespace NTL;
3738
3839 int main()
3940 {
4142
4243 cin &gt;&gt; f;
4344
44 vec_pair_ZZX_long factors;
45 Vec&lt; Pair&lt; ZZX, long &gt; &gt; factors;
4546 ZZ c;
4647
4748 factor(c, factors, f);
8485 computer algebra system: it is a library for programmers.
8586
8687 <p>
87 In this example, the type <tt>vec_pair_long_ZZ</tt>
88 is an NTL vector whose base type is <tt>pair_long_ZZ</tt>.
89 The type <tt>pair_long_ZZ</tt> is a type created by
90 another template-like macro mechanism.
91 In general, for types <tt>S</tt> and <tt>T</tt>,
92 one can create a type <tt>pair_S_T</tt> which is
93 a class with a field <tt>a</tt> of type <tt>S</tt>
94 and a field <tt>b</tt> of type <tt>T</tt>.
88 In this example, the type <tt>Vec&lt; Pair&lt; ZZX, long &gt; &gt;</tt>
89 is an NTL vector whose base type is <tt>Pair&lt; ZZX, long &gt;</tt>.
90 The type <tt>Pair&lt; ZZX, long &gt;</tt> is the instantiation
91 of a template "pair" type defined by NTL.
9592 See <a href="pair.txt"><tt>pair.txt</tt></a> for more details.
9693
9794
105102
106103 #include &lt;NTL/ZZX.h&gt;
107104
108 NTL_CLIENT
105 using namespace std;
106 using namespace NTL;
109107
110108 int main()
111109 {
112 vec_ZZX phi(INIT_SIZE, 100);
110 Vec&lt;ZZX&gt; phi(INIT_SIZE, 100);
113111
114112 for (long i = 1; i &lt;= 100; i++) {
115113 ZZX t;
133131 <p>
134132 First, instead of
135133 <pre>
136 vec_ZZX phi(INIT_SIZE, 100);
134 Vec&lt;ZZX&gt; phi(INIT_SIZE, 100);
137135 </pre>
138136 one can write
139137 <pre>
140 vec_ZZX phi;
138 Vec&lt;ZZX&gt; phi;
141139 phi.SetLength(100);
142140 </pre>
143141
169167 SetCoeff(t1, 0, -1);
170168 div(phi(i), t1, t);
171169 </pre>
172 Alternatively, one could directly access the coefficient vector:
170 Alternatively, one could directly access the coefficient vector as follows:
173171 <pre>
174172 ZZX t1;
175 t1.rep.SetLength(i+1); // all vector elements are initialized to zero
176 t1.rep[i] = 1;
177 t1.rep[0] = -1;
173 t1.SetLength(i+1); // all vector elements are initialized to zero
174 t1[i] = 1;
175 t1[0] = -1;
178176 t1.normalize(); // not necessary here, but good practice in general
179177 div(phi(i), t1, t);
180178 </pre>
181 The coefficient vector of a polynomial is always an NTL vector
182 over the ground ring: in this case <tt>vec_ZZ</tt>.
183 NTL does not try to be a dictator: it gives you free access
184 to the coefficient vector.
179 Generally, you can freely access the coefficient vector
180 of a polynomial, as above.
185181 However, after fiddling with this vector, you should "normalize"
186 the polynomial, so that the leading coefficient in non-zero:
182 the polynomial, so that the leading coefficient is non-zero:
187183 this is an invariant which all routines that work with polynomials
188184 expect to hold.
189185 Of course, if you can avoid directly accessing the
192188 change coefficients, and you can always read the value of a coefficient
193189 using the routine <tt>coeff</tt>, e.g.,
194190 <pre>
195 ... f.rep[i] == 1 ...
191 ... f[i] == 1 ...
196192 </pre>
197193 is equivalent to
198194 <pre>
205201
206202
207203 <p>
208 NTL provides a full compliment of operations for polynomials
204 NTL provides a full compliment of arithmetic operations for polynomials
209205 over the integers, in both operator and procedural form.
210206 All of the basic operations support a "promotion logic" similar
211207 to that for <tt>ZZ</tt>, except that inputs of <i>both</i> types
2424 represents the integers mod <tt>p</tt>.
2525 Despite the notation, <tt>p</tt> need not in general be prime,
2626 except in situations where this is mathematically required.
27 The classes <tt>vec_ZZ_p</tt>, <tt>mat_ZZ_p</tt>,
27 The classes <tt>Vec&lt;ZZ_p&gt;</tt> (a.k.a., <tt>vec_ZZ_p</tt>),
28 <tt>Mat&lt;ZZ_p&gt;</tt> (a.k.a., <tt>mat_ZZ_p</tt>),
2829 and <tt>ZZ_pX</tt> represent vectors, matrices, and polynomials
2930 mod <tt>p</tt>, and work much the same way as the corresponding
3031 classes for <tt>ZZ</tt>.
3738 <pre>
3839 #include &lt;NTL/ZZ_pXFactoring.h&gt;
3940
40 NTL_CLIENT
41 using namespace std;
42 using namespace NTL;
4143
4244 int main()
4345 {
4850 ZZ_pX f;
4951 cin &gt;&gt; f;
5052
51 vec_pair_ZZ_pX_long factors;
53 Vec&lt; Pair&lt; ZZ_pX, long &gt; &gt; factors;
5254
5355 CanZass(factors, f); // calls "Cantor/Zassenhaus" algorithm
5456
6971 NTL does not make any attempt to ensure that
7072 variables declared under one modulus are not used
7173 under a different one.
72 If that happens, the behavior of a program in this
73 case is completely unpredictable.
74 If that happens, the behavior of a program
75 is completely unpredictable.
7476
7577
7678 <p> <hr> <p>
8183
8284 <p>
8385 <pre>
84 #include &lt;NTL/vec_ZZ_p.h&gt;
85
86 NTL_CLIENT
87
88 void add(vec_ZZ_p&amp; x, const vec_ZZ_p&amp; a, const vec_ZZ_p&amp; b)
86 #include &lt;NTL/ZZ_p.h&gt;
87
88 using namespace std;
89 using namespace NTL;
90
91 void add(Vec&lt;ZZ_p&gt;&amp; x, const Vec&lt;ZZ_p&gt;&amp; a, const Vec&lt;ZZ_p&gt;&amp; b)
8992 {
9093 long n = a.length();
9194 if (b.length() != n) Error("vector add: dimension mismatch");
103106
104107 <p>
105108 <pre>
106 #include &lt;NTL/vec_ZZ_p.h&gt;
107
108 NTL_CLIENT
109
110 void InnerProduct(ZZ_p&amp; x, const vec_ZZ_p&amp; a, const vec_ZZ_p&amp; b)
109 #include &lt;NTL/ZZ_p.h&gt;
110
111 using namespace std;
112 using namespace NTL;
113
114 void InnerProduct(ZZ_p&amp; x, const Vec&lt;ZZ_p&gt;&amp; a, const Vec&lt;ZZ_p&gt;&amp; b)
111115 {
112116 long n = min(a.length(), b.length());
113117 long i;
114118 ZZ accum, t;
115119
116120 accum = 0;
117 for (i = 0; i < n; i++) {
121 for (i = 0; i &lt; n; i++) {
118122 mul(t, rep(a[i]), rep(b[i]));
119123 add(accum, accum, t);
120124 }
146150 when you want to work with vectors, matrices, or polynomials
147151 mod <tt>p</tt>.
148152 If you just want to do some simple modular arithemtic,
149 it is probably easier to just work with <tt>ZZ</tt>s directly.
153 it is probably easier to just work with <tt>ZZ</tt>'s directly.
150154 This is especially true if you want to work with many different
151155 moduli: modulus switching is supported, but it is a bit awkward.
152156
161165 see <a href="ZZ_pX.txt"><tt>ZZ_pX.txt</tt></a> for details on <tt>ZZ_pX</tt>;
162166 see <a href="ZZ_pXFactoring.txt"><tt>ZZ_pXFactoring.txt</tt></a> for details on
163167 the routines for factoring polynomials over <tt>ZZ_p</tt>;
164 see <a href="vec_ZZ_p.txt"><tt>vec_ZZ_p.txt</tt></a> for details on <tt>vec_ZZ_p</tt>;
165 see <a href="mat_ZZ_p.txt"><tt>mat_ZZ_p.txt</tt></a> for details on <tt>mat_ZZ_p</tt>.
168 see <a href="vec_ZZ_p.txt"><tt>vec_ZZ_p.txt</tt></a> for details
169 on mathematical operations on <tt>Vec&lt;ZZ_p&gt;</tt>'s;
170 see <a href="mat_ZZ_p.txt"><tt>mat_ZZ_p.txt</tt></a> for details on
171 mathematical operations on <tt>Mat&lt;ZZ_p&gt;</tt>'s.
166172
167173 <p> <hr> <p>
168174
177183 #include &lt;NTL/ZZX.h&gt;
178184 #include &lt;NTL/ZZ_pXFactoring.h&gt;
179185
180 NTL_CLIENT
186 using namespace std;
187 using namespace NTL;
181188
182189 long IrredTestMod(const ZZX&amp; f, const ZZ&amp; p)
183190 {
186193
187194 ZZ_p::init(p); // set the current modulus to p
188195
189 return DetIrredTest(to_ZZ_pX(f));
196 return DetIrredTest(conv&lt;ZZ_pX&gt;(f));
190197
191198 // old modulus is restored automatically when bak is destroyed
192199 // upon return
198205 more general and flexible than this example illustrates.
199206
200207 <p>
201 The function <tt>to_ZZ_pX</tt> is yet another of NTL's many
202 conversion functions.
208 Noe the use of the conversion function
209 <tt>conv&lt;ZZ_pX&gt;</tt>.
203210 We could also have used the equivalent procedural form:
204211 <pre>
205212 ZZ_pX f1;
218225 to be a small, single-precision prime.
219226 In this case, NTL provides a class <tt>zz_p</tt>, that
220227 acts just like <tt>ZZ_p</tt>,
221 along with corresponding classes <tt>vec_zz_p</tt>,
222 <tt>mat_zz_p</tt>, and <tt>zz_pX</tt>.
228 along with corresponding classes <tt>Vec&lt;zz_p&gt;</tt>,
229 <tt>Mat&lt;zz_p&gt;</tt>, and <tt>zz_pX</tt>.
223230 The interfaces to all of the routines are generally identical
224231 to those for <tt>ZZ_p</tt>.
225232 However, the routines are much more efficient, in both time and space.
234241 #include &lt;NTL/ZZX.h&gt;
235242 #include &lt;NTL/lzz_pXFactoring.h&gt;
236243
237 NTL_CLIENT
244 using namespace std;
245 using namespace NTL;
238246
239247 long IrredTestMod(const ZZX&amp; f, long p)
240248 {
243251
244252 zz_p::init(p);
245253
246 return DetIrredTest(to_zz_pX(f));
254 return DetIrredTest(conv&lt;zz_pX&gt;(f));
247255 }
248256 </pre>
249257
260268 <pre>
261269 #include &lt;NTL/ZZX.h&gt;
262270
263 NTL_CLIENT
271 using namespace std;
272 using namespace NTL;
264273
265274 void GCD(ZZX&amp; d, const ZZX&amp; a, const ZZX&amp; b)
266275 {
360369 Arithmetic mod 2 is such an important special case that NTL
361370 provides a class <tt>GF2</tt>, that
362371 acts just like <tt>ZZ_p</tt> when <tt>p == 2</tt>,
363 along with corresponding classes <tt>vec_GF2</tt>,
364 <tt>mat_GF2</tt>, and <tt>GF2X</tt>.
372 along with corresponding classes <tt>Vec&lt;GF2&gt;</tt>,
373 <tt>Mat&lt;GF2&gt;</tt>, and <tt>GF2X</tt>.
365374 The interfaces to all of the routines are generally identical
366375 to those for <tt>ZZ_p</tt>.
367376 However, the routines are much more efficient, in both time and space.
368377
369 <p>
370
371 This example illustrates the <tt>GF2X</tt> and <tt>mat_GF2</tt>
378 Note that <tt>Vec&lt;GF2&gt;</tt> is an explicit specialization
379 of the template class <tt>Vec&lt;T&gt;</tt>, with a special
380 implementation that packs the coefficients into the bits
381 of a machine word.
382 You need to include the header file <tt>&lt;NTL/vec_GF2.h&gt;</tt>
383 to use the class <tt>Vec&lt;GF2&gt;</tt>.
384
385 <p>
386
387 This example illustrates the <tt>GF2X</tt> and <tt>Mat&lt;GF2&gt;</tt>
372388 classes with a simple routine to test if a polynomial over GF(2)
373389 is irreducible using linear algebra.
374390 NTL's built-in irreducibility test is to be preferred, however.
378394 #include &lt;NTL/GF2X.h&gt;
379395 #include &lt;NTL/mat_GF2.h&gt;
380396
381 NTL_CLIENT
382
383 long MatIrredTest(const GF2X& f)
397 using namespace std;
398 using namespace NTL;
399
400 long MatIrredTest(const GF2X&amp; f)
384401 {
385402 long n = deg(f);
386403
389406
390407 if (GCD(f, diff(f)) != 1) return 0;
391408
392 mat_GF2 M;
409 Mat&lt;GF2&gt; M;
393410
394411 M.SetDims(n, n);
395412
3131
3232 int main()
3333 {
34 ZZ_p::init(to_ZZ(17)); // define GF(17)
34 ZZ_p::init(conv&lt;ZZ&gt;(17)); // define GF(17)
3535
3636 ZZ_pX P;
3737 BuildIrred(P, 10); // generate an irreducible polynomial P
374374 <a href="matrix.txt"><tt>matrix</tt></a>
375375
376376 </b> <td>
377 template-like macros for
377 template class for
378378 dynamic-size 2-dimensional arrays
379379
380380 <!-- ----------- mat_GF2.txt ----------- -->
514514 <a href="pair.txt"><tt>pair</tt></a>
515515
516516 </b> <td>
517 template-like macros for
517 template class for
518518 pairs
519519
520520
543543 <a href="vector.txt"><tt>vector</tt></a>
544544
545545 </b> <td>
546 template-like macros for
546 template class for
547547 dynamic-size vectors
548548
549549 <!-- ----------- vec_GF2.txt ----------- -->
666666
667667 These decalarations are found in "<tt>.h</tt>" files with
668668 corresponding names.
669 These header files simply provide typedefs for the
670 corresponding template types, mainly for
671 backward compatibility,
672 e.g.,
673 <tt>vec_double</tt> is a typedef for
674 <tt>Vec&lt;double&gt;</tt>,
675 and <tt>vec_vec_RR</tt> is a typedef for
676 <tt>Vec&lt; Vec&lt;RR&gt; &gt;</tt>.
669677 No additional functionality is provided.
670678
671679 <p>
672680 All of the header files for polynomial classes <tt>ZZ_pX</tt>,
673 <tt>ZZX</tt>, etc., declare generic vectors <tt>vec_ZZ_pX</tt>,
681 <tt>ZZX</tt>, etc., declare typedefs for the corresponding
682 vectors of polynomials <tt>vec_ZZ_pX</tt>,
674683 <tt>vec_ZZX</tt>, etc.
675684
676685 <p>
693702
694703 These decalarations are found in "<tt>.h</tt>" files with
695704 corresponding names.
696 These files also declare corresponding generic vector types
697 <tt>vec_pair_GF2EX_long</tt>, etc.
705 Again, these files mainly exist for backward compatibilty,
706 and provide typedefs for the corresponding template types,
707 e.g., <tt>pair_GF2EX_long</tt> is a typedef for
708 <tt>Pair&lt;GF2EX,long&gt;</tt>.
709 These files also give typedefs for the corresponding vector types,
710 e.g.,
711 <tt>vec_pair_GF2EX_long</tt> is a typedef for
712 <tt>Vec&lt; <tt>Pair&lt;GF2EX,long&gt; &gt;</tt>.
698713 No additional functionality is provided.
699714
700715
620620 </h3>
621621
622622 <p>
623 Compilers still vary in their ability to correctly implement
624 Standard C++ in all its glory.
625
626 <p>
627 NTL compiles correctly in in either Traditional or ISO
628 mode using recent versions (2.95 and later)
629 of the <i>GNU</i> compiler (which is free).
630
631
632 <p>
633 It has also been reported that
634 NTL compiles correctly in ISO mode using the
635 Metroworks CodeWarrior Pro 5, v. 5.3 compiler on a PowerMac 7500 running
636 on a 200MHz 604e.
637
638 <p>
639 NTL cannot be used with Microsoft Visual C++ versions 5 or 6
640 in ISO mode, although this compiler still works with NTL in Traditional mode.
641 I have tested NTL with Microsoft Visual C++ version 6,
642 and found that one can use the <tt>NTL_PSTD_NNS</tt> to useful effect,
643 especially if one wants to use the STL.
644 So one can wrap NTL in a namespace.
645 However, the <tt>NTL_PSTD_NHF</tt> still does not work:
646 MSVC++ 6 is very inconsistent about the location of a number of
647 names; even when one uses the new header files, some names
648 in the standard library are in namespace <tt>std</tt>,
649 while others are in the global namespace.
650 Further, it appears that Koenig lookup is not properly
651 implemented in MSVC++ 6, but luckily, NTL does not rely on this.
652
653 <p>
654 It appears that some later versions of Microsoft C++ are much
655 more standards compliant, and may in fact work with NTL in ISO mode.
656
657
658 <p>
659 As usual,
660 NTL should continue to work in Traditional mode on just about any
661 available <tt>C++</tt> compiler.
662
663 <p>
664
623 The first C++ standard was set in 1998, with some
624 revisions in 2003.
625 As I write this update in 2013, I believe it is safe
626 to say that most compileres released in the last
627 few years do a pretty good job of implementing the standard.
628
629 <p>
630 However, a new revision to tne standard appeared in 2011.
631 This new revision contains many new language and library
632 features.
633 Surely, it will be a number of years until
634 support for all these new feautures will be uniformly
635 available.
665636
666637
667638
168168
169169 Third, there are a number of conversion functions (see below), whose name
170170 in procedural form is <tt>conv</tt>, but whose name in
171 functioanl form is <tt>to_T</tt>, where <tt>T</tt> is the return type:
171 functional form is <tt>conv&lt;T&gt;</tt>, where <tt>T</tt> is the return type:
172172
173173 <pre>
174174 ZZ x;
175175 double a;
176176
177 x = to_ZZ(a); // functional form
178 conv(x, a); // procedural form
177 x = conv&lt;ZZ&gt;(a); // functional form
178 conv(x, a); // procedural form
179179 </pre>
180180
181181
206206 </h3>
207207 <p>
208208
209 NTL does not provide automatic conversions from, say,
210 <tt>int</tt> to <tt>ZZ</tt>.
211 Most <tt>C++</tt> experts consider such automatic conversions
212 bad form in library design, and I would agree with them.
213 Some earlier versions of NTL had automatic conversions,
214 but they caused too much trouble, so I took them out.
215 Indeed, combining function overloading and automatic conversions
216 is generally considered by programming language experts
217 to be a bad idea (but that did not stop
218 the designers of <tt>C++</tt> from doing it).
219 It makes it very difficult to figure out which function
220 ought to be called.
221 <tt>C++</tt> has an incredibly complex set of rules for doing this;
222 moreover, these rules have been changing over time,
223 and no two compilers seem to implement exactly the same
224 set of rules.
225 And if a compiler has a hard time doing this, imagine what it
226 is like for a programmer.
227 In fact, the rules have become so complicated, that the latest
228 edition of Stroustrup's <tt>C++</tt> book does not even explain them,
229 although
230 earlier verisons did.
231 Possible explanations:
232 <em>(a)</em> Stroustrup thinks his readers are
233 too stupid to understand the rules, or
234 <em>(b)</em> Stroustrup does not understand the rules, or
235 <em>(c)</em> the rules are so complicated that Stroustrup finds it embarassing
236 to talk about them.
237
238 <p>
239 Now it should be more clear why I didn't just implement,
240 say, the <tt>int</tt> to <tt>ZZ</tt> conversion function
241 as a <tt>ZZ</tt> constructor taking an argument of type <tt>int</tt>,
242 instead of calling it <tt>to_ZZ</tt>.
243 This would have introduced an automatic conversion, which I
244 wanted to avoid for the reasons explained above.
245 "OK. But why not make the constructor <tt>explict</tt>?" you ask.
246 The main reason is that this is a fairly recently introduced
247 language feature that is not universally available.
248 And even if it were, what about, say, the <tt>ZZ</tt> to <tt>int</tt>
249 conversion routine?
250 How would you name <em>that</em>?
251 The strategy I chose is simple, consistent, and portable.
252
253
254 <p>
255
256209 As mentioned above, there are numerous explicit conversion routines,
257210 which come in both functional and procedural forms.
258211 A complete list of these can be found in
259212 <a href="conversions.txt">conversions.txt</a>.
260213 This is the only place these are documented; they do not appear
261 in the ".txt" files.
262
263 <p>
264
265 Even though there are no automatic conversions, users
266 of NTL can still have most of their benefits, while
267 avoiding their pitfalls.
214 in the other ".txt" files.
215
216 <p>
217 It is worth mentioning here, however, that generic conversion operators
218 are provided for vectors and matrices, which act component-wise.
219 For example, since there is a conversion from <tt>ZZ</tt> to <tt>RR</tt>,
220 there is automatically a conversion from
221 <tt>Vec&lt;ZZ&gt;</tt> to <tt>Vec&lt;RR&gt</tt>.
222
223
224
225
226
227 <p>
228
229 Even though there are no implicity conversions, users
230 of NTL can still have most of their benefits.
268231 This is because all of the basic arithmetic operations
269232 (in both their functional and procedural forms),
270233 comparison operators, and assignment are overloaded
296259 This means that in addition to the declared function, there
297260 are two other functions that are logically equivalent to the following:
298261 <pre>
299 ZZ operator+(long a, const ZZ&amp; b) { return to_ZZ(a) + b; }
300 ZZ operator+(const ZZ&amp; a, long b) { return a + to_ZZ(b); }
262 ZZ operator+(long a, const ZZ&amp; b) { return conv&lt;ZZ&gt;(a) + b; }
263 ZZ operator+(const ZZ&amp; a, long b) { return a + conv&lt;ZZ&gt;(b); }
301264 </pre>
302265
303266 <p>
308271 </pre>
309272 than it is to write
310273 <pre>
311 x = y + to_ZZ(2);
274 x = y + conv&lt;ZZ&gt;(2);
312275 </pre>
313276 The former notation avoids the creation and destruction
314277 of a temporary <tt>ZZ</tt>
365328 ZZ_p: long
366329 ZZ_pX: long, ZZ_p
367330 zz_p: long
368 ZZ_pX: long, zz_p
331 zz_pX: long, zz_p
369332 ZZX: long, ZZ
370333 GF2: long
371334 GF2X: long, GF2
433396 Matrix by scalar and vector by scalar multiplication promote the scalar.
434397 E.g.,
435398 <pre>
436 vec_ZZ v, w;
399 Vec&lt;ZZ&gt; v, w;
437400 ...
438401 v = w*2;
439402 v = 2*w;
495458 </pre>
496459 One could also use an explicit conversion function:
497460 <pre>
498 a = a + to_ZZ(x);
461 a = a + conv&lt;ZZ&gt;(x);
499462 </pre>
500463 The second version guarantees that there is no loss of precision,
501464 and also guarantees that the floor of <tt>x</tt> is computed.
523486
524487 <p>
525488
526 Another pitfall too avoid is initialzing <tt>ZZ</tt>s
489 Another pitfall too avoid is initialzing <tt>ZZ</tt>'s
527490 with integer constants that are too big.
528491 Consider the following:
529492 <pre>
537500 program is as follows:
538501 <pre>
539502 ZZ x;
540 x = to_ZZ("1234567890123456789012");
503 x = conv&lt;ZZ&gt;("1234567890123456789012");
541504 </pre>
542505 Conversion functions are provided for converting <tt>C</tt> character strings
543506 to the types <tt>ZZ</tt>, <tt>RR</tt>, <tt>quad_float</tt>,
546509 <p>
547510 One should also be careful when converting to <tt>RR</tt>.
548511 All of these conversions round to the current working precision, which is
549 usually, but not always what one wants.
512 usually, but not always, what one wants.
550513
551514 <p>
552515 <p>
556519 <p>
557520
558521 An important feature of NTL is that aliasing of input and output
559 parameters is <i>always</i> allowed. For example, if you
522 parameters is generally allowed. For example, if you
560523 write <tt>mul(x, a, b)</tt>, then <tt>a</tt> or <tt>b</tt>
561524 may alias (have the same address as) <tt>x</tt>
562525 (or any object that <tt>x</tt> contains, e.g., scalar/vector
563526 or scalar/polynomial multiplication).
527
528 <p>
529 One exception to this rule:
530 the generic conversions provided for vectors and
531 matrices assume that their inputs do not alias their outputs.
564532
565533
566534 <p>
614582 For example, the global declarations
615583 <pre>
616584 ZZ global_integer;
617 vec_ZZ_p global_vector;
585 Vec&lt;ZZ_p&gt; global_vector;
618586 </pre>
619587 should always work, since their initialization only involves
620588 setting a pointer to 0.
635603 There is, however, one possible exception to this.
636604 A programmer might want to have a global constant initialized like this:
637605 <pre>
638 const quad_float Pi = to_quad_float("3.1415926535897932384626433832795029");
606 const quad_float Pi = conv&lt;quad_float&gt;("3.1415926535897932384626433832795029");
639607 </pre>
640608 While this probably will work fine on most platforms,
641609 it may not be an entirely portable construction,
648616 const quad_float&amp; Pi()
649617 {
650618 static quad_float pi =
651 to_quad_float("3.1415926535897932384626433832795029");
619 conv&lt;quad_float&gt;("3.1415926535897932384626433832795029");
652620 return pi;
653621 }
654622 </pre>
44
55 SUMMARY:
66
7 a vec_GF2 is a vector of GF2s that behaves much like generic NTL vectors
8 (see vector.txt), but there are some differences.
9
10 For efficiency, elements of a vec_GF2 are "packed" into a word.
11 One may use subscript notation v[i] or v(i) as an r-value
12 in an expression, and as an l-value in the following contexts:
13 * on the left-hand side of an assignment operator,
14 * on the left-hand side of +=, -=, *=, /=,
15 * and as an argument to ++ and --.
16
17 One may not use the expression v[i] or v(i) to initialize
18 a non-const reference parameter.
19
20 For example, if v, w are vec_GF2's, you can write:
21
22 v[i] = 0;
23 v[i] = v[j] + w[k];
24 v[i] += 1;
25 v[i]++;
26 v[i] += w[i];
27
28 It is perhaps helpful to describe how this is implemented,
29 without going into all the details.
30 The type of a subscript-expression is "subscript_GF2" or
31 "const_subscript_GF2", the latter chosen if the vector is read-only.
32 Both of these "helper" types have automatic conversions
33 operators to GF2. Moreover, assignment and increment operators
34 are defined for "subscript_GF2" (but not for "const_subscript_GF2").
35 These operators return references to themselves, so one can
36 iterate assignment operators as usual (as usual in NTL,
37 the return type of post-increment/decrement is void).
7
8 The class Vec<GF2> is explicitly specialized.
9 It behaves much like a generic Vec<T> (see vector.txt),
10 but there are some differences.
11
12 For efficiency, elements of a Vec<GF2> are "packed" into a word.
13 You can still use subscript notation v[i] or v(i).
14 For const vectors, these evaluate to values of type const GF2.
15 For non-const vectors, these evaluate to values of the
16 special type ref_GF2, which is defined in the GF2 header file.
17
18 There are implicit conversions from ref_GF2 to const GF2
19 and from GF2& to ref_GF2. Therefore, if you want to declare
20 a function that takes a non-const reference to a GF2, you
21 should declare the parameter of type ref_GF2: this will
22 allow you to pass variables of type GF2 as well as
23 elements of vec_GF2's obtained through indexing.
3824
3925 As an alternative, one can use the get and put methods below to access
4026 vector elements.
4127
4228 There is one subtle but important difference in the semantics
43 of vec_GF2 and that of generic NTL vectors. With a vec_GF2, whenever its
29 of Vec<GF2> and that of generic NTL vectors. With a Vec<GF2>, whenever its
4430 length is increased (via SetLength), the "new" bits are always 0.
4531 For example, if v.length() == 20, then
4632
5743
5844
5945
60 class vec_GF2 {
46 template<>
47 class Vec<GF2> {
6148
6249 public:
6350
64 vec_GF2(); // 0 length vector
65 vec_GF2(INIT_SIZE_TYPE, long n); // initialize to length n
66 // usage: vec_GF2(INIT_SIZE, n)
67
68 vec_GF2(const vec_GF2& a); // copy constructor
69 vec_GF2& operator=(const vec_GF2& a); // assignment
70 ~vec_GF2(); // destructor
51 Vec(); // 0 length vector
52 Vec(INIT_SIZE_TYPE, long n); // initialize to length n
53 // usage: Vec(INIT_SIZE, n)
54
55 Vec(const Vec<GF2>& a); // copy constructor
56 Vec& operator=(const Vec<GF2>& a); // assignment
57 ~Vec(); // destructor
7158
7259 void SetLength(long n); // set length to n bits
7360 void SetMaxLength(long n); // allocate space for n bits
9481
9582 void kill(); // free space and make length 0
9683
97 GF2 get(long i) const; // fetch value at index i (indexing from 0)
84 const GF2 get(long i) const; // fetch value at index i (indexing from 0)
9885
9986 void put(long i, GF2 a); // write value a to index i (indexing from 0)
10087 void put(long i, long a);
10188
102 // Here are the subscripting operators, defined using the
103 // "helper" classes subscript_GF2 and const_subscript_GF2.
104
105 subscript_GF2 operator[](long i);
106
107 subscript_GF2 operator()(long i);
108
109 const_subscript_GF2 operator[](long i) const;
110
111 const_subscript_GF2 operator()(long i) const;
89 // Here are the subscripting operators, defined using the
90 // "helper" class ref_GF2
91
92 ref_GF2 operator[](long i);
93 ref_GF2 operator()(long i);
94
95 const GF2 operator[](long i) const;
96 const GF2 operator()(long i) const;
97
98
99 // Some partial STL compatibility...also used
100 // to interface with the Matrix template class
101
102 typedef GF2 value_type;
103 typedef ref_GF2 reference;
104 typedef const GF2 const_reference;
105
106
112107
113108 };
114109
115110
116 void swap(vec_GF2& x, vec_GF2& y);
111
112 void swap(Vec<GF2>& x, Vec<GF2>& y);
117113 // swap x and y (fast pointer swap)
118114
119 void append(vec_GF2& v, GF2 a);
115 void append(Vec<GF2>& v, const GF2& a);
120116 // append a to v
121117
122 void append(vec_GF2& v, const vec_GF2& a);
118 void append(Vec<GF2>& v, const Vec<GF2>& a);
123119 // append a to v
124120
125121 // equality operators:
126122
127 long operator==(const vec_GF2& a, const vec_GF2& b);
128 long operator!=(const vec_GF2& a, const vec_GF2& b);
123 long operator==(const Vec<GF2>& a, const Vec<GF2>& b);
124 long operator!=(const Vec<GF2>& a, const Vec<GF2>& b);
129125
130126
131127 // I/O operators:
132128
133 ostream& operator<<(ostream& s, const vec_GF2& a);
134 istream& operator>>(istream& s, vec_GF2& a);
129 ostream& operator<<(ostream& s, const Vec<GF2>& a);
130 istream& operator>>(istream& s, Vec<GF2>& a);
135131
136132 // The I/O format is [a_0 a_1 ... a_{n-1}], where each a_i is "0" or "1".
137133 // On input, the a_i may be arbitrary integers, which are reduced mod 2.
134
135
136
137 typedef Vec<GF2> vec_GF2; // backward compatibility
138138
139139 // utility routines:
140140
170170 void mul(vec_GF2& x, long a, const vec_GF2& b);
171171 // x = a * b
172172
173 void InnerProduct(GF2& x, const vec_GF2& a, const vec_GF2& b);
173 void InnerProduct(ref_GF2 x, const vec_GF2& a, const vec_GF2& b);
174174 // vectors may differ in length
175175
176176 void VectorCopy(vec_GF2& x, const vec_GF2& a, long n);
1111 #include <NTL/GF2E.h>
1212 #include <NTL/vector.h>
1313
14 NTL_vector_decl(GF2E,vec_GF2E)
1514
16 NTL_io_vector_decl(GF2E,vec_GF2E)
17 // I/O operators are defined
18
19 NTL_eq_vector_decl(GF2E,vec_GF2E)
20 // operators == and != are defined
15 typedef Vec<GF2E> vec_GF2E; // backward compatibility
2116
2217 void mul(vec_GF2E& x, const vec_GF2E& a, const GF2E& b);
2318 void mul(vec_GF2E& x, const vec_GF2E& a, GF2 b);
88
99 \**************************************************************************/
1010
11 NTL_vector_decl(RR,vec_RR)
1211
13 NTL_eq_vector_decl(RR,vec_RR)
14 // == and !=
15
16 NTL_io_vector_decl(RR,vec_RR)
17 // I/O operators
12 typedef Vec<RR> vec_RR; // backward compatibility
1813
1914 void mul(vec_RR& x, const vec_RR& a, const RR& b);
2015 void mul(vec_RR& x, const vec_RR& a, double b);
88
99 \**************************************************************************/
1010
11 NTL_vector_decl(ZZ,vec_ZZ)
1211
13 NTL_eq_vector_decl(ZZ,vec_ZZ)
14 // == and !=
15
16 NTL_io_vector_decl(ZZ,vec_ZZ)
17 // I/O operators
12 typedef Vec<ZZ> vec_ZZ; // backward compatibility
1813
1914 void mul(vec_ZZ& x, const vec_ZZ& a, const ZZ& b);
2015 void mul(vec_ZZ& x, const vec_ZZ& a, long b);
1212 #include <NTL/vec_ZZ.h>
1313 #include <NTL/vector.h>
1414
15 NTL_vector_decl(ZZ_p,vec_ZZ_p)
1615
17 NTL_io_vector_decl(ZZ_p,vec_ZZ_p)
18 // I/O operators are defined
19
20 NTL_eq_vector_decl(ZZ_p,vec_ZZ_p)
21 // operators == and != are defined
16 typedef Vec<ZZ_p> vec_ZZ_p; // backward compatibility
2217
2318 void mul(vec_ZZ_p& x, const vec_ZZ_p& a, const ZZ_p& b);
2419 void mul(vec_ZZ_p& x, const vec_ZZ_p& a, long b);
1212 #include <NTL/vec_ZZ.h>
1313 #include <NTL/vector.h>
1414
15 NTL_vector_decl(ZZ_pE,vec_ZZ_pE)
16
17 NTL_io_vector_decl(ZZ_pE,vec_ZZ_pE)
18 // I/O operators are defined
19
20 NTL_eq_vector_decl(ZZ_pE,vec_ZZ_pE)
21 // operators == and != are defined
15 typedef Vec<ZZ_pE> vec_ZZ_pE; // backward compatibility
2216
2317 void mul(vec_ZZ_pE& x, const vec_ZZ_pE& a, const ZZ_pE& b);
2418 void mul(vec_ZZ_pE& x, const vec_ZZ_pE& a, const ZZ_p& b);
1212 #include "vec_zz.h"
1313 #include <NTL/vector.h>
1414
15 NTL_vector_decl(zz_p,vec_zz_p)
16
17 NTL_io_vector_decl(zz_p,vec_zz_p)
18 // I/O operators are defined
19
20 NTL_eq_vector_decl(zz_p,vec_zz_p)
21 // operators == and != are defined
15 typedef Vec<zz_p> vec_zz_p; // backward compatibility
2216
2317 void mul(vec_zz_p& x, const vec_zz_p& a, zz_p b);
2418 void mul(vec_zz_p& x, const vec_zz_p& a, long b);
1212 #include <NTL/vec_ZZ.h>
1313 #include <NTL/vector.h>
1414
15 NTL_vector_decl(zz_pE,vec_zz_pE)
16
17 NTL_io_vector_decl(zz_pE,vec_zz_pE)
18 // I/O operators are defined
19
20 NTL_eq_vector_decl(zz_pE,vec_zz_pE)
21 // operators == and != are defined
15 typedef Vec<zz_pE> vec_zz_pE; // backward compatibility
2216
2317 void mul(vec_zz_pE& x, const vec_zz_pE& a, const zz_pE& b);
2418 void mul(vec_zz_pE& x, const vec_zz_pE& a, const zz_p& b);
55
66 SUMMARY:
77
8 Macros are defined providing template-like classes for dynamic-sized
9 arrays.
10
11 The macro NTL_vector_decl(T,vec_T) declares a class vec_T, whose
12 implementation can be instantiated with NTL_vector_impl(T,vec_T). It is
13 presumed that the underlying type have a public default constructor, copy
14 constructor, assignment operator, and a destructor (this is
15 normally the case for most types).
16
17 Note that the type T must be a type name (you'll need to make
18 a typedef for the type if this is not the case).
19
20 If the type T supports I/O operator << and >>, then vec_T can be
21 made to support these operators as well using NTL_io_vector_decl(T,vec_T) and
22 NTL_io_vector_impl(T,vec_T).
23
24 The same goes for equality operators == and != using
25 NTL_eq_vector_decl(T,vec_T) and NTL_eq_vector_impl(T,vec_T).
8 Template class for dynamic-sized vectors.
269
2710 The declaration
2811
29 vec_T v;
12 Vec<T> v;
3013
3114 creates a zero-length vector. To grow this vector to length n,
3215 execute
5538
5639 v.MaxLength() is the largest value of n for which v.SetLength(n) was invoked,
5740 and is equal to the number of entries that have been initialized.
58 v.SetMaxLength(n) will allocate space for and
59 initialize up to n elements, without changing v.length().
41 v.SetMaxLength(n) will allocate space for and initialize up to n elements,
42 without changing v.length().
6043
6144 When v's destructor is called, all constructed elements will be
6245 destructed, and all space will be relinquished.
8366
8467 \**************************************************************************/
8568
86 class vec_T {
69 template<class T>
70 class Vec {
8771 public:
8872
89 vec_T(); // initially length 0
90
91 vec_T(const vec_T& a);
73 Vec(); // initially length 0
74
75 Vec(const Vec<T>& a);
9276 // copy constructor; currently, this is implemented by
9377 // initializing elements using T's defaults constructor and
9478 // copying elements from a using T's assigment operator.
9579
96 vec_T& operator=(const vec_T& a);
97 // assignment...performs an element-wise assignment
80 Vec& operator=(const Vec<T>& a);
81 // assignment: performs an element-wise assignment
9882 // using T's assignment operator.
9983
100 ~vec_T();
84 ~Vec();
85 // destructor: calls T's destructor for all initialized
86 // elements in the vector, and then frees the vector itself
10187
10288 void SetLength(long n);
10389 // set current length to n, growing vector if necessary
10490
10591 long length() const;
10692 // current length
107 // SIZE INVARIANT: length()*sizeof(T) < 2^(NTL_BITS_PER_LONG-4)
10893
10994 T& operator[](long i);
11095 const T& operator[](long i) const;
11196 // indexing operation, starting from 0.
112 // The first version is applied to non-const vec_T,
97 // The first version is applied to non-const Vec<T>,
11398 // and returns a non-const reference to a T, while the second version
114 // is applied to a const vec_T and returns a const reference to a T.
99 // is applied to a const Vec<T> and returns a const reference to a T.
115100
116101 T& operator()(long i);
117102 const T& operator()(long i) const;
118103 // indexing operation, starting from 1
119 // The first version is applied to non-const vec_T,
104 // The first version is applied to non-const Vec<T>,
120105 // and returns a non-const reference to a T, while the second version
121 // is applied to a const vec_T and returns a const reference to a T.
106 // is applied to a const Vec<T> and returns a const reference to a T.
122107
123108 T* elts();
124109 const T* elts() const;
125110 // returns address of first vector element (or 0 if no space has
126111 // been allocated for this vector). If a vector potentially has
127112 // length 0, it is safer to write v.elts() instead of &v[0].
128 // The first version is applied to non-const vec_T,
113 // The first version is applied to non-const Vec<T>,
129114 // and returns a non-const pointer to a T, while the second version
130 // is applied to a const vec_T and returns a const reference to a T.
131
132
133 // the remaining member functions are a bit esoteric (skip on first
134 // reading):
135
136 vec_T(INIT_SIZE_TYPE, long n);
137 // vec_T(INIT_SIZE, n) initializes with an intial length of n.
115 // is applied to a const Vec<T> and returns a const reference to a T.
116
117
118 // Alternative access interface
119
120 const T& get(long i) const;
121 // v.get(i) returns v[i]
122
123 void put(long i, const T& a);
124 // v.put(i, a) equivalent to v[i] = q
125
126
127
128 // Some STL compatibility
129
130 typedef T value_type;
131 typedef value_type& reference;
132 typedef const value_type& const_reference;
133 typedef value_type *iterator;
134 typedef const value_type *const_iterator;
135
136 T* data();
137 const T* data() const;
138 // v.data() same as v.elts()
139
140 T* begin();
141 const T* begin() const;
142 // v.begin() same as v.elts()
143
144 T* end();
145 const T* end() const;
146 // pointer to last element (or NULL)
147
148 T& at(long i);
149 const T& at(long i) const;
150 // indexing with range checking
151
152
153 // the remaining member functions are a bit esoteric (skip on first
154 // reading)
155
156 Vec(INIT_SIZE_TYPE, long n);
157 // Vec(INIT_SIZE, n) initializes with an intial length of n.
138158
139159 void kill();
140160 // release space and set to length 0
170190
171191 long position(const T& a) const;
172192 // returns position of a in the vector, or -1 if it is not there.
173 // The search is conducted from position 0 to MaxAlloc()-1 of the vector,
193 // The search is conducted from position 0 to allocated()-1 the vector,
174194 // and an error is raised if the object is found at position MaxLength()
175195 // or higher (in which case a references an uninitialized object).
176196 // Note that if NTL_CLEAN_PTR flag is set, this routine takes
192212 \**************************************************************************/
193213
194214
195 void swap(vec_T& x, vec_T& y);
215 template<class T>
216 void swap(Vec<T>& x, Vec<T>& y);
196217 // swaps x & y by swapping pointers
197218
198 void append(vec_T& v, const T& a);
219 template<class T>
220 void append(Vec<T>& v, const T& a);
199221 // appends a to the end of v
200222
201 void append(vec_T& v, const vec_T& w);
223 template<class T>
224 void append(Vec<T>& v, const Vec<T>& w);
202225 // appends w to the end of v
203226
204227
208231
209232 Input/Output
210233
211 The I/O operators can be declared with NTL_io_vector_decl(T,vec_T), and
212 implemented using NTL_io_vector_impl(T,vec_T). Elements are read and written
213 using the underlying I/O operators << and >> for T.
214234
215235 The I/O format for a vector v with n elements is:
216236
218238
219239 \**************************************************************************/
220240
221 istream& operator>>(istream&, vec_T&);
222 ostream& operator<<(ostream&, const vec_T&);
241 template<class T>
242 istream& operator>>(istream&, Vec<T>&);
243
244 template<class T>
245 ostream& operator<<(ostream&, const Vec<T>&);
223246
224247
225248
227250
228251 Equality Testing
229252
230 The equality testing operators == and != can be declared
231 with NTL_eq_vector_decl(T,vec_T) and implemented with
232 NTL_eq_vector_impl(T,vec_T).
233 The tests are performed using the underlying operator == for T.
234
235 \**************************************************************************/
236
237
238 long operator==(const vec_T& a, const vec_T& b);
239 long operator!=(const vec_T& a, const vec_T& b);
253 \**************************************************************************/
254
255
256 template<class T>
257 long operator==(const Vec<T>& a, const Vec<T>& b);
258
259 template<class T>
260 long operator!=(const Vec<T>& a, const Vec<T>& b);
240261
241262
242263 /**************************************************************************\
258279 is called, whose default implementation invokes the default destructor
259280 for T n times.
260281
261 Both of these default implementations can be overridden as follows.
262 Instead of implementing vec_T with NTL_vector_impl(T,vec_T), implement it
263 with NTL_vector_impl_plain(T,vec_T), and then write your own BlockConstruct and
264 BlockDestroy.
265
282 Both of these default implementations can be overridden as follows
283 by overloading these functions with a custom implementation.
284
266285 For an example of this, see vec_ZZ_p.c.
267286
268287 \**************************************************************************/
22 #ifndef NTL_FFT__H
33 #define NTL_FFT__H
44
5 #include <NTL/ZZ.h>
6 #include <NTL/vector.h>
57 #include <NTL/vec_long.h>
6 #include <NTL/ZZ.h>
78
89 NTL_OPEN_NNS
910
3132 // This can be increased, with a slight performance penalty.
3233
3334
35 // New interface
36
37 class FFTMultipliers {
38 public:
39 long MaxK;
40 Vec< Vec<long> > wtab_precomp;
41 Vec< Vec<mulmod_precon_t> > wqinvtab_precomp;
42
43 FFTMultipliers() : MaxK(-1) { }
44 };
45
46
47 struct FFTPrimeInfo {
48 long q; // the prime itself
49 double qinv; // 1/((double) q)
50
51 Vec<long> RootTable;
52 // RootTable[j] = w^{2^{MaxRoot-j}},
53 // where w is a primitive 2^MaxRoot root of unity
54 // for q
55
56 Vec<long> RootInvTable;
57 // RootInvTable[j] = 1/RootTable[j] mod q
58
59 Vec<long> TwoInvTable;
60 // TwoInvTable[j] = 1/2^j mod q
61
62 Vec<mulmod_precon_t> TwoInvPreconTable;
63 // mulmod preconditioning data
64
65 FFTMultipliers MulTab;
66 FFTMultipliers InvMulTab;
67
68 };
69
70
71 #define NTL_FFT_BIGTAB_LIMIT (256)
72 // big tables are only used for the first NTL_FFT_BIGTAB_LIMIT primes
73 // TODO: maybe we should have a similar limit for the degree of
74 // the convolution as well.
75
76
77 extern FFTPrimeInfo *FFTTables;
78
79
80 // legacy interface
3481
3582 extern long NumFFTPrimes;
36
3783 extern long *FFTPrime;
38 extern long **RootTable;
39 extern long **RootInvTable;
40 extern long **TwoInvTable;
4184 extern double *FFTPrimeInv;
4285
43 /****************
44
45 RootTable[i][j] = w^{2^{MaxRoot-j}},
46 where w is a primitive 2^MaxRoot root of unity
47 for FFTPrime[i]
48
49 RootInvTable[i][j] = 1/RootTable[i][j] mod FFTPrime[i]
50
51 TwoInvTable[i][j] = 1/2^j mod FFTPrime[i]
52
53 These tables are allocated and initialized at run-time
54 with UseFFTPrime(i).
55
56 *****************/
5786
5887
5988 long CalcMaxRoot(long p);
6695 void FFT(long* A, const long* a, long k, long q, const long* root);
6796 // the low-level FFT routine.
6897 // computes a 2^k point FFT modulo q, using the table root for the roots.
98 // A and a may overlap.
99
100 void FFT(long* A, const long* a, long k, long q, const long* root, FFTMultipliers& tab);
101
102
103 inline
104 void FFTFwd(long* A, const long *a, long k, long i)
105 // Slightly higher level interface...using the ith FFT prime
106 // A and a cannot overlap
107 {
108 FFTPrimeInfo& info = FFTTables[i];
109 #ifdef NTL_FFT_BIGTAB
110 if (i < NTL_FFT_BIGTAB_LIMIT)
111 FFT(A, a, k, info.q, &info.RootTable[0], info.MulTab);
112 else
113 FFT(A, a, k, info.q, &info.RootTable[0]);
114 #else
115 FFT(A, a, k, info.q, &info.RootTable[0]);
116 #endif
117 }
118
119 inline
120 void FFTRev(long* A, const long *a, long k, long i)
121 // Slightly higher level interface...using the ith FFT prime
122 // A and a cannot overlap
123 {
124 FFTPrimeInfo& info = FFTTables[i];
125 #ifdef NTL_FFT_BIGTAB
126 if (i < NTL_FFT_BIGTAB_LIMIT)
127 FFT(A, a, k, info.q, &info.RootInvTable[0], info.InvMulTab);
128 else
129 FFT(A, a, k, info.q, &info.RootInvTable[0]);
130 #else
131 FFT(A, a, k, info.q, &info.RootInvTable[0]);
132 #endif
133 }
134
135 inline
136 void FFTMulTwoInv(long* A, const long *a, long k, long i)
137 {
138 FFTPrimeInfo& info = FFTTables[i];
139 VectorMulModPrecon(1L << k, A, a, info.TwoInvTable[k], info.q,
140 info.TwoInvPreconTable[k]);
141 }
142
69143
70144 NTL_CLOSE_NNS
71145
1616 };
1717
1818
19 NTL_vector_decl(IntFactor,vec_IntFactor)
19 typedef Vec<IntFactor> vec_IntFactor;
2020 typedef vec_IntFactor FacVec;
2121
2222 void FactorInt(FacVec& fvec, long n);
22 #define NTL_GF2__H
33
44 #include <NTL/ZZ.h>
5 #include <NTL/vector.h>
56
67 NTL_OPEN_NNS
78
89 class GF2 {
910 public:
1011
11 long _GF2__rep;
12
13
14 GF2() { _GF2__rep = 0; }
15
12 unsigned long _GF2__rep;
13
14
15 GF2() : _GF2__rep(0) { }
1616 GF2(const GF2& a) : _GF2__rep(a._GF2__rep) { }
1717
18 GF2(INIT_VAL_TYPE, long a) : _GF2__rep(a & 1) { }
19 GF2(INIT_LOOP_HOLE_TYPE, unsigned long a) : _GF2__rep(a) { }
20
1821 ~GF2() { }
1922
2023 GF2& operator=(const GF2& a) { _GF2__rep = a._GF2__rep; return *this; }
21
2224 GF2& operator=(long a) { _GF2__rep = a & 1; return *this; }
2325
2426 static long modulus() { return 2; }
2628
2729 };
2830
29 inline void conv(GF2& x, long a) { x._GF2__rep = a & 1; }
31
32
33 class ref_GF2 {
34 public:
35
36 unsigned long *_ref_GF2__ptr;
37 long _ref_GF2__pos;
38
39 ref_GF2() : _ref_GF2__ptr(0), _ref_GF2__pos(0) { }
40 ref_GF2(const ref_GF2& a) :
41 _ref_GF2__ptr(a._ref_GF2__ptr), _ref_GF2__pos(a._ref_GF2__pos) { }
42 ref_GF2(GF2& a) :
43 _ref_GF2__ptr(&a._GF2__rep), _ref_GF2__pos(0) { }
44 ref_GF2(INIT_LOOP_HOLE_TYPE, unsigned long *ptr, long pos) :
45 _ref_GF2__ptr(ptr), _ref_GF2__pos(pos) { }
46
47 operator const GF2() const
48 {
49 return GF2(INIT_LOOP_HOLE, (*_ref_GF2__ptr >> _ref_GF2__pos) & 1);
50 }
51
52 ~ref_GF2() { }
53
54 ref_GF2 operator=(const ref_GF2& a)
55 {
56 unsigned long rval = (*a._ref_GF2__ptr >> a._ref_GF2__pos) & 1;
57 unsigned long lval = *_ref_GF2__ptr;
58 lval = (lval & ~(1UL << _ref_GF2__pos)) | (rval << _ref_GF2__pos);
59 *_ref_GF2__ptr = lval;
60 return *this;
61 }
62
63 ref_GF2 operator=(const GF2& a)
64 {
65 unsigned long rval = (a._GF2__rep) & 1;
66 unsigned long lval = *_ref_GF2__ptr;
67 lval = (lval & ~(1UL << _ref_GF2__pos)) | (rval << _ref_GF2__pos);
68 *_ref_GF2__ptr = lval;
69 return *this;
70 }
71
72
73 ref_GF2 operator=(long a)
74 {
75 unsigned long rval = a & 1;
76 unsigned long lval = *_ref_GF2__ptr;
77 lval = (lval & ~(1UL << _ref_GF2__pos)) | (rval << _ref_GF2__pos);
78 *_ref_GF2__ptr = lval;
79 return *this;
80 }
81
82
83 };
84
85
86
87
88 // functions
89
90
91 inline long rep(GF2 a) { return a._GF2__rep; }
92
93
94
95 inline long IsZero(GF2 a)
96 { return a._GF2__rep == 0; }
97
98 inline long IsOne(GF2 a)
99 { return a._GF2__rep == 1; }
100
101
102
103
30104 inline GF2 to_GF2(long a)
31 { GF2 x; conv(x, a); return x; }
32
33 inline void conv(GF2& x, const ZZ& a) { x._GF2__rep = IsOdd(a); }
105 { return GF2(INIT_VAL, a); }
106
34107 inline GF2 to_GF2(const ZZ& a)
35 { GF2 x; conv(x, a); return x; }
36
37 inline long rep(GF2 a) { return a._GF2__rep; }
38
39
40 inline void clear(GF2& x) { x._GF2__rep = 0; }
41 inline void set(GF2& x) { x._GF2__rep = 1; }
42
43 inline void swap(GF2& x, GF2& y)
44 { long t; t = x._GF2__rep; x._GF2__rep = y._GF2__rep; y._GF2__rep = t; }
45
46 inline void add(GF2& x, GF2 a, GF2 b)
47 { x._GF2__rep = a._GF2__rep ^ b._GF2__rep; }
48
49 inline void sub(GF2& x, GF2 a, GF2 b)
50 { x._GF2__rep = a._GF2__rep ^ b._GF2__rep; }
51
52 inline void negate(GF2& x, GF2 a)
53 { x._GF2__rep = a._GF2__rep; }
54
55 inline void add(GF2& x, GF2 a, long b)
56 { x._GF2__rep = a._GF2__rep ^ (b & 1); }
57
58 inline void add(GF2& x, long a, GF2 b)
59 { x._GF2__rep = (a & 1) ^ b._GF2__rep; }
60
61 inline void sub(GF2& x, GF2 a, long b)
62 { x._GF2__rep = a._GF2__rep ^ (b & 1); }
63
64 inline void sub(GF2& x, long a, GF2 b)
65 { x._GF2__rep = (a & 1) ^ b._GF2__rep; }
108 { return GF2(INIT_LOOP_HOLE, IsOdd(a)); }
109
110
111
66112
67113 inline GF2 operator+(GF2 a, GF2 b)
68 { GF2 x; add(x, a, b); return x; }
114 { return GF2(INIT_LOOP_HOLE, a._GF2__rep ^ b._GF2__rep); }
69115
70116 inline GF2 operator+(GF2 a, long b)
71 { GF2 x; add(x, a, b); return x; }
117 { return a + to_GF2(b); }
72118
73119 inline GF2 operator+(long a, GF2 b)
74 { GF2 x; add(x, a, b); return x; }
120 { return to_GF2(a) + b; }
75121
76122 inline GF2 operator-(GF2 a, GF2 b)
77 { GF2 x; sub(x, a, b); return x; }
123 { return a + b; }
78124
79125 inline GF2 operator-(GF2 a, long b)
80 { GF2 x; sub(x, a, b); return x; }
126 { return a + b; }
81127
82128 inline GF2 operator-(long a, GF2 b)
83 { GF2 x; sub(x, a, b); return x; }
129 { return a + b; }
84130
85131 inline GF2 operator-(GF2 a)
86 { GF2 x; negate(x, a); return x; }
87
88 inline GF2& operator+=(GF2& x, GF2 b)
89 { add(x, x, b); return x; }
90
91 inline GF2& operator+=(GF2& x, long b)
92 { add(x, x, b); return x; }
93
94 inline GF2& operator-=(GF2& x, GF2 b)
95 { sub(x, x, b); return x; }
96
97 inline GF2& operator-=(GF2& x, long b)
98 { sub(x, x, b); return x; }
99
100 inline GF2& operator++(GF2& x) { add(x, x, 1); return x; }
101 inline void operator++(GF2& x, int) { add(x, x, 1); }
102 inline GF2& operator--(GF2& x) { sub(x, x, 1); return x; }
103 inline void operator--(GF2& x, int) { sub(x, x, 1); }
104
105
106 inline void mul(GF2& x, GF2 a, GF2 b)
107 { x._GF2__rep = a._GF2__rep & b._GF2__rep; }
108
109 inline void mul(GF2& x, GF2 a, long b)
110 { x._GF2__rep = a._GF2__rep & b; }
111
112 inline void mul(GF2& x, long a, GF2 b)
113 { x._GF2__rep = a & b._GF2__rep; }
114
115 inline void sqr(GF2& x, GF2 a)
116 { x = a; }
132 { return a; }
133
117134
118135 inline GF2 sqr(GF2 a)
119136 { return a; }
120137
121138 inline GF2 operator*(GF2 a, GF2 b)
122 { GF2 x; mul(x, a, b); return x; }
139 { return GF2(INIT_LOOP_HOLE, a._GF2__rep & b._GF2__rep); }
123140
124141 inline GF2 operator*(GF2 a, long b)
125 { GF2 x; mul(x, a, b); return x; }
142 { return a * to_GF2(b); }
126143
127144 inline GF2 operator*(long a, GF2 b)
128 { GF2 x; mul(x, a, b); return x; }
129
130
131 inline GF2& operator*=(GF2& x, GF2 b)
132 { mul(x, x, b); return x; }
133
134 inline GF2& operator*=(GF2& x, long b)
135 { mul(x, x, b); return x; }
136
137
138 void div(GF2& x, GF2 a, GF2 b);
139 void div(GF2& x, long a, GF2 b);
140 void div(GF2& x, GF2 a, long b);
141
142 void inv(GF2& x, GF2 a);
143
145 { return to_GF2(a) * b; }
146
147
148
149
150
151
152 inline GF2 operator/(GF2 a, GF2 b)
153 {
154 if (IsZero(b)) Error("GF2: division by zero");
155 return a;
156 }
157
158 inline GF2 operator/(GF2 a, long b)
159 { return a / to_GF2(b); }
160
161 inline GF2 operator/(long a, GF2 b)
162 { return to_GF2(a) / b; }
163
164
165
144166 inline GF2 inv(GF2 a)
145 { GF2 x; inv(x, a); return x; }
146
147 inline GF2 operator/(GF2 a, GF2 b)
148 { GF2 x; div(x, a, b); return x; }
149
150 inline GF2 operator/(GF2 a, long b)
151 { GF2 x; div(x, a, b); return x; }
152
153 inline GF2 operator/(long a, GF2 b)
154 { GF2 x; div(x, a, b); return x; }
155
156
157 inline GF2& operator/=(GF2& x, GF2 b)
158 { div(x, x, b); return x; }
159
160 inline GF2& operator/=(GF2& x, long b)
161 { div(x, x, b); return x; }
162
163
164 void power(GF2& x, GF2 a, long e);
165 inline GF2 power(GF2 a, long e)
166 { GF2 x; power(x, a, e); return x; }
167
168
169 inline long IsZero(GF2 a)
170 { return a._GF2__rep == 0; }
171
172 inline long IsOne(GF2 a)
173 { return a._GF2__rep == 1; }
167 { return 1 / a; }
168
169
170
171
172
173
174174
175175 inline long operator==(GF2 a, GF2 b)
176176 { return a._GF2__rep == b._GF2__rep; }
177177
178 inline long operator!=(GF2 a, GF2 b)
179 { return !(a == b); }
180
181 inline long operator==(GF2 a, long b) { return a._GF2__rep == (b & 1); }
182 inline long operator==(long a, GF2 b) { return (a & 1) == b._GF2__rep; }
183
178
179 inline long operator==(GF2 a, long b)
180 { return a == to_GF2(b); }
181
182 inline long operator==(long a, GF2 b)
183 { return to_GF2(a) == b; }
184
185 inline long operator!=(GF2 a, GF2 b) { return !(a == b); }
184186 inline long operator!=(GF2 a, long b) { return !(a == b); }
185187 inline long operator!=(long a, GF2 b) { return !(a == b); }
186188
189
190
191 GF2 power(GF2 a, long e);
192
193
194
195 inline GF2 random_GF2()
196 { return GF2(INIT_LOOP_HOLE, RandomBnd(2)); }
197
198
199
200 // procedural versions
201
202 inline GF2& operator+=(GF2& x, GF2 b)
203 { return x = x + b; }
204
205 inline GF2& operator+=(GF2& x, long b)
206 { return x = x + b; }
207
208 inline GF2& operator-=(GF2& x, GF2 b)
209 { return x = x - b; }
210
211 inline GF2& operator-=(GF2& x, long b)
212 { return x = x - b; }
213
214 inline GF2& operator++(GF2& x) { return x = x + 1; }
215 inline void operator++(GF2& x, int) { x = x + 1; }
216 inline GF2& operator--(GF2& x) { return x = x - 1; }
217 inline void operator--(GF2& x, int) { x = x - 1; }
218
219 inline GF2& operator*=(GF2& x, GF2 b)
220 { return x = x * b; }
221
222 inline GF2& operator*=(GF2& x, long b)
223 { return x = x * b; }
224
225 inline GF2& operator/=(GF2& x, GF2 b)
226 { return x = x / b; }
227
228 inline GF2& operator/=(GF2& x, long b)
229 { return x = x / b; }
230
231
232
233
234 inline void conv(GF2& x, long a) { x = to_GF2(a); }
235
236 inline void conv(GF2& x, const ZZ& a) { x = to_GF2(a); }
237
238
239 inline void clear(GF2& x) { x = 0; }
240
241 inline void set(GF2& x) { x = 1; }
242
243 inline void swap(GF2& x, GF2& y)
244 { GF2 t; t = x; x = y; y = t; }
245
246 inline void add(GF2& x, GF2 a, GF2 b)
247 { x = a + b; }
248
249 inline void sub(GF2& x, GF2 a, GF2 b)
250 { x = a - b; }
251
252 inline void negate(GF2& x, GF2 a)
253 { x = -a; }
254
255 inline void add(GF2& x, GF2 a, long b)
256 { x = a + b; }
257
258 inline void add(GF2& x, long a, GF2 b)
259 { x = a + b; }
260
261 inline void sub(GF2& x, GF2 a, long b)
262 { x = a - b; }
263
264 inline void sub(GF2& x, long a, GF2 b)
265 { x = a - b; }
266
267
268 inline void mul(GF2& x, GF2 a, GF2 b)
269 { x = a * b; }
270
271 inline void mul(GF2& x, GF2 a, long b)
272 { x = a * b; }
273
274 inline void mul(GF2& x, long a, GF2 b)
275 { x = a * b; }
276
277 inline void sqr(GF2& x, GF2 a)
278 { x = sqr(a); }
279
280
281 inline void div(GF2& x, GF2 a, GF2 b)
282 { x = a / b; }
283
284 inline void div(GF2& x, long a, GF2 b)
285 { x = a / b; }
286
287 inline void div(GF2& x, GF2 a, long b)
288 { x = a / b; }
289
290 inline void inv(GF2& x, GF2 a)
291 { x = inv(a); }
292
293
294 inline void power(GF2& x, GF2 a, long e)
295 { x = power(a, e); }
296
297
298
187299 inline void random(GF2& x)
188 { x._GF2__rep = RandomBnd(2); }
189
190 inline GF2 random_GF2()
191 { GF2 x; random(x); return x; }
300 { x = random_GF2(); }
301
302 // ref_GF2 variants...theoretically, these would
303 // have sufficed, because of the implicit conversion
304 // from GF2& to ref_GF2, but it may be a bit more efficient
305 // to explicitly overload everything. Moreover,
306 // the return types of the += type operators would
307 // not be right.
308
309
310 inline ref_GF2 operator+=(ref_GF2 x, GF2 b)
311 { return x = x + b; }
312
313 inline ref_GF2 operator+=(ref_GF2 x, long b)
314 { return x = x + b; }
315
316 inline ref_GF2 operator-=(ref_GF2 x, GF2 b)
317 { return x = x - b; }
318
319 inline ref_GF2 operator-=(ref_GF2 x, long b)
320 { return x = x - b; }
321
322 inline ref_GF2 operator++(ref_GF2 x) { return x = x + 1; }
323 inline void operator++(ref_GF2 x, int) { x = x + 1; }
324 inline ref_GF2 operator--(ref_GF2 x) { return x = x - 1; }
325 inline void operator--(ref_GF2 x, int) { x = x - 1; }
326
327 inline ref_GF2 operator*=(ref_GF2 x, GF2 b)
328 { return x = x * b; }
329
330 inline ref_GF2 operator*=(ref_GF2 x, long b)
331 { return x = x * b; }
332
333 inline ref_GF2 operator/=(ref_GF2 x, GF2 b)
334 { return x = x / b; }
335
336 inline ref_GF2 operator/=(ref_GF2 x, long b)
337 { return x = x / b; }
338
339
340
341
342 inline void conv(ref_GF2 x, long a) { x = to_GF2(a); }
343
344 inline void conv(ref_GF2 x, const ZZ& a) { x = to_GF2(a); }
345
346
347 inline void clear(ref_GF2 x) { x = 0; }
348
349 inline void set(ref_GF2 x) { x = 1; }
350
351 inline void swap(ref_GF2 x, ref_GF2 y)
352 { GF2 t; t = x; x = y; y = t; }
353
354 inline void add(ref_GF2 x, GF2 a, GF2 b)
355 { x = a + b; }
356
357 inline void sub(ref_GF2 x, GF2 a, GF2 b)
358 { x = a - b; }
359
360 inline void negate(ref_GF2 x, GF2 a)
361 { x = -a; }
362
363 inline void add(ref_GF2 x, GF2 a, long b)
364 { x = a + b; }
365
366 inline void add(ref_GF2 x, long a, GF2 b)
367 { x = a + b; }
368
369 inline void sub(ref_GF2 x, GF2 a, long b)
370 { x = a - b; }
371
372 inline void sub(ref_GF2 x, long a, GF2 b)
373 { x = a - b; }
374
375
376 inline void mul(ref_GF2 x, GF2 a, GF2 b)
377 { x = a * b; }
378
379 inline void mul(ref_GF2 x, GF2 a, long b)
380 { x = a * b; }
381
382 inline void mul(ref_GF2 x, long a, GF2 b)
383 { x = a * b; }
384
385 inline void sqr(ref_GF2 x, GF2 a)
386 { x = sqr(a); }
387
388
389 inline void div(ref_GF2 x, GF2 a, GF2 b)
390 { x = a / b; }
391
392 inline void div(ref_GF2 x, long a, GF2 b)
393 { x = a / b; }
394
395 inline void div(ref_GF2 x, GF2 a, long b)
396 { x = a / b; }
397
398 inline void inv(ref_GF2 x, GF2 a)
399 { x = inv(a); }
400
401
402 inline void power(ref_GF2 x, GF2 a, long e)
403 { x = power(a, e); }
404
405
406
407 inline void random(ref_GF2 x)
408 { x = random_GF2(); }
409
410
411
412
413 // I/O...for input, we only provide the ref_GF2 variant
192414
193415 NTL_SNS ostream& operator<<(NTL_SNS ostream& s, GF2 a);
194416
195 NTL_SNS istream& operator>>(NTL_SNS istream& s, GF2& x);
417 NTL_SNS istream& operator>>(NTL_SNS istream& s, ref_GF2 x);
418
419 /* additional legacy conversions for v6 conversion regime */
420
421 inline void conv(int& x, GF2 a) { conv(x, rep(a)); }
422 inline void conv(unsigned int& x, GF2 a) { conv(x, rep(a)); }
423 inline void conv(long& x, GF2 a) { conv(x, rep(a)); }
424 inline void conv(unsigned long& x, GF2 a) { conv(x, rep(a)); }
425 inline void conv(ZZ& x, GF2 a) { conv(x, rep(a)); }
426
427
428 inline void conv(GF2& x, GF2 a) { x = a; }
429 inline void conv(ref_GF2 x, GF2 a) { x = a; }
430
431 /* ------------------------------------- */
432
433
434 // Finally, we declare an specialization Vec<GF2>:
435
436 template<> class Vec<GF2>;
196437
197438 NTL_CLOSE_NNS
198439
415415
416416 // ****** trace
417417
418 inline void trace(GF2& x, const GF2E& a)
418 inline void trace(ref_GF2 x, const GF2E& a)
419419 { TraceMod(x, a._GF2E__rep, GF2E::modulus()); }
420420 inline GF2 trace(const GF2E& a)
421421 { return TraceMod(a._GF2E__rep, GF2E::modulus()); }
444444 inline GF2E& GF2E::operator=(long a) { conv(*this, a); return *this; }
445445 inline GF2E& GF2E::operator=(GF2 a) { conv(*this, a); return *this; }
446446
447
448 /* additional legacy conversions for v6 conversion regime */
449
450 inline void conv(GF2X& x, const GF2E& a) { x = rep(a); }
451 inline void conv(GF2E& x, const GF2E& a) { x = a; }
452
453
454 /* ------------------------------------- */
455
456
457 // overload these functions for Vec<GF2E>.
458 // They are defined in vec_GF2E.c
459 void BlockConstruct(GF2E* p, long n);
460 void BlockDestroy(GF2E* p, long n);
461
462
463
447464 NTL_CLOSE_NNS
448465
449466 #endif
5454
5555 { rep.kill(); }
5656
57
58
59 typedef GF2E coeff_type;
60 void SetLength(long n) { rep.SetLength(n); }
61 GF2E& operator[](long i) { return rep[i]; }
62 const GF2E& operator[](long i) const { return rep[i]; }
63
64
65
66
5767 static const GF2EX& zero();
5868
5969
240250 { GF2EX x; conv(x, a); NTL_OPT_RETURN(GF2EX, x); }
241251
242252 #ifndef NTL_TRANSITION
243 inline GF2EX to_GF2EX(GF2X& a)
253 inline GF2EX to_GF2EX(const GF2X& a)
244254 { GF2EX x; conv(x, a); NTL_OPT_RETURN(GF2EX, x); }
245255 #endif
246256
250260 inline GF2EX& GF2EX::operator=(const GF2E& a) { conv(*this, a); return *this; }
251261 inline GF2EX& GF2EX::operator=(GF2 a) { conv(*this, a); return *this; }
252262 inline GF2EX& GF2EX::operator=(long a) { conv(*this, a); return *this; }
263
264
265
266
267 /* additional legacy conversions for v6 conversion regime */
268
269 inline void conv(GF2EX& x, const GF2EX& a)
270 { x = a; }
271
272 inline void conv(vec_GF2E& x, const GF2EX& a)
273 { x = a.rep; }
274
275 class ZZX;
276 void conv(GF2EX& x, const ZZX& a);
277
278
279 /* ------------------------------------- */
280
253281
254282
255283
699727
700728
701729
702 NTL_vector_decl(GF2EX,vec_GF2EX)
703
704 NTL_eq_vector_decl(GF2EX,vec_GF2EX)
705
706 NTL_io_vector_decl(GF2EX,vec_GF2EX)
707
708
730 typedef Vec<GF2EX> vec_GF2EX;
709731
710732
711733
3535
3636 void SetMaxLength(long n);
3737
38
39
40 typedef GF2 coeff_type;
41 void SetLength(long n);
42 ref_GF2 operator[](long i);
43 const GF2 operator[](long i) const;
44
45
46
47
3848 static long HexOutput;
3949
4050 inline GF2X(long i, GF2 c);
5161
5262 long IsX(const GF2X& a);
5363
54 GF2 coeff(const GF2X& a, long i);
55
56 GF2 LeadCoeff(const GF2X& a);
57
58 GF2 ConstTerm(const GF2X& a);
64 const GF2 coeff(const GF2X& a, long i);
65
66 const GF2 LeadCoeff(const GF2X& a);
67
68 const GF2 ConstTerm(const GF2X& a);
5969
6070
6171 inline void clear(GF2X& x)
242252
243253
244254
245 NTL_vector_decl(GF2X,vec_GF2X)
246
247 NTL_io_vector_decl(GF2X,vec_GF2X)
248
249 NTL_eq_vector_decl(GF2X,vec_GF2X)
250
255 typedef Vec<GF2X> vec_GF2X;
251256
252257 void LeftShift(GF2X& c, const GF2X& a, long n);
253258 inline GF2X LeftShift(const GF2X& a, long n)
514519 inline vec_GF2 to_vec_GF2(const GF2X& a)
515520 { vec_GF2 x; conv(x, a); NTL_OPT_RETURN(vec_GF2, x); }
516521
522
523
524 /* additional legacy conversions for v6 conversion regime */
525
526 inline void conv(GF2X& x, const GF2X& a)
527 { x = a; }
528
529 class ZZX;
530 void conv(GF2X& x, const ZZX& a);
531 void conv(ZZX& x, const GF2X& a);
532
533
534 /* ------------------------------------- */
535
536
537
538
539
517540 inline GF2X& GF2X::operator=(long a)
518541 { conv(*this, a); return *this; }
519542
618641 const GF2XTransMultiplier& B, const GF2XModulus& F)
619642 { vec_GF2 x; UpdateMap(x, a, B, F); NTL_OPT_RETURN(vec_GF2, x); }
620643
621 inline void project(GF2& x, const vec_GF2& a, const GF2X& b)
644 inline void project(ref_GF2 x, const vec_GF2& a, const GF2X& b)
622645 { x = to_GF2(InnerProduct(a.rep, b.xrep)); }
623646
624647 inline GF2 project(const vec_GF2& a, const GF2X& b)
647670 { vec_GF2 x; TraceVec(x, f); NTL_OPT_RETURN(vec_GF2, x); }
648671
649672
650 void TraceMod(GF2& x, const GF2X& a, const GF2XModulus& F);
673 void TraceMod(ref_GF2 x, const GF2X& a, const GF2XModulus& F);
651674
652675 inline GF2 TraceMod(const GF2X& a, const GF2XModulus& F)
653676 { GF2 x; TraceMod(x, a, F); return x; }
654677
655 void TraceMod(GF2& x, const GF2X& a, const GF2X& f);
678 void TraceMod(ref_GF2 x, const GF2X& a, const GF2X& f);
656679
657680 inline GF2 TraceMod(const GF2X& a, const GF2X& f)
658681 { GF2 x; TraceMod(x, a, f); return x; }
423423 inline ZZ FloorToZZ(const RR& a)
424424 { ZZ z; conv(z, a); NTL_OPT_RETURN(ZZ, z); }
425425
426
427 /* additional legacy conversions for v6 conversion regime */
428
429 inline void conv(unsigned int& x, const RR& a)
430 { long z; conv(z, a); conv(x, z); }
431
432 inline void conv(unsigned long& x, const RR& a)
433 { long z; conv(z, a); conv(x, z); }
434
435
436 /* ------------------------------------- */
437
426438 void MakeRR(RR& z, const ZZ& a, long e);
427439 inline RR MakeRR(const ZZ& a, long e)
428440 { RR z; MakeRR(z, a, e); NTL_OPT_RETURN(RR, z); }
6464
6565
6666
67 WordVector() { rep = 0; }
68 WordVector(INIT_SIZE_TYPE, long n) { rep = 0; DoSetLength(n); }
69 WordVector(const WordVector& a) { rep = 0; *this = a; }
67 WordVector() : rep(0) { }
68 WordVector(INIT_SIZE_TYPE, long n) : rep(0) { DoSetLength(n); }
69 WordVector(const WordVector& a) : rep(0) { *this = a; }
7070
7171 WordVector& operator=(const WordVector& a);
7272
2929 // May be private in future versions.
3030
3131
32 ZZ()
32 ZZ() : rep(0) { }
3333 // initial value is 0.
3434
35 { rep = 0; }
36
37
38 ZZ(INIT_SIZE_TYPE, long k)
35
36 ZZ(INIT_SIZE_TYPE, long k) : rep(0)
3937 // initial value is 0, but space is pre-allocated so that numbers
4038 // x with x.size() <= k can be stored without re-allocation.
4139 // Call with ZZ(INIT_SIZE, k).
4442
4543
4644 {
47 rep = 0;
4845 NTL_zsetlength(&rep, k);
4946 }
5047
51 ZZ(const ZZ& a)
48 ZZ(const ZZ& a) : rep(0)
5249 // initial value is a.
5350
5451 {
55 rep = 0;
5652 NTL_zcopy(a.rep, &rep);
5753 }
5854
5955
60 ZZ(INIT_VAL_TYPE, long a) { rep = 0; NTL_zintoz(a, &rep); }
61 ZZ(INIT_VAL_TYPE, int a) { rep = 0; NTL_zintoz(a, &rep); }
62
63 ZZ(INIT_VAL_TYPE, unsigned long a) { rep = 0; NTL_zuintoz(a, &rep); }
64 ZZ(INIT_VAL_TYPE, unsigned int a) { rep = 0; NTL_zuintoz((unsigned long) a, &rep); }
56 ZZ(INIT_VAL_TYPE, long a) : rep(0) { NTL_zintoz(a, &rep); }
57 ZZ(INIT_VAL_TYPE, int a) : rep(0) { NTL_zintoz(a, &rep); }
58
59 ZZ(INIT_VAL_TYPE, unsigned long a) : rep(0) { NTL_zuintoz(a, &rep); }
60 ZZ(INIT_VAL_TYPE, unsigned int a) : rep(0) { NTL_zuintoz((unsigned long) a, &rep); }
6561
6662 inline ZZ(INIT_VAL_TYPE, const char *);
6763 inline ZZ(INIT_VAL_TYPE, float);
8884 { NTL_zsetlength(&rep, k); }
8985
9086 long size() const
87 // returns the number of (NTL_ZZ_NBIT-bit) digits of |a|; the size of 0 is 0.
9188 { return NTL_zsize(rep); }
9289
93 // returns the number of (NTL_ZZ_NBIT-bit) digits of |a|; the size of 0 is 0.
90 long null() const
91 // test of rep is null
92 { return !rep; }
93
94 long MaxAlloc() const
95 // returns max allocation request, possibly rounded up a bit...
96 { return NTL_zmaxalloc(rep); }
9497
9598
9699 long SinglePrecision() const
165168 inline ZZ to_ZZ(unsigned int a) { return ZZ(INIT_VAL, a); }
166169
167170 void conv(ZZ& x, const char *s);
168 inline ZZ::ZZ(INIT_VAL_TYPE, const char *s) { rep = 0; conv(*this, s); }
171 inline ZZ::ZZ(INIT_VAL_TYPE, const char *s) : rep(0) { conv(*this, s); }
169172 inline ZZ to_ZZ(const char *s) { return ZZ(INIT_VAL, s); }
170173
171174 inline void conv(ZZ& x, double a) { NTL_zdoubtoz(a, &x.rep); }
172 inline ZZ::ZZ(INIT_VAL_TYPE, double a) { rep = 0; conv(*this, a); }
175 inline ZZ::ZZ(INIT_VAL_TYPE, double a) : rep(0) { conv(*this, a); }
173176 inline ZZ to_ZZ(double a) { return ZZ(INIT_VAL, a); }
174177
175178 inline void conv(ZZ& x, float a) { NTL_zdoubtoz(double(a), &x.rep); }
176 inline ZZ::ZZ(INIT_VAL_TYPE, float a) { rep = 0; conv(*this, a); }
179 inline ZZ::ZZ(INIT_VAL_TYPE, float a) : rep(0) { conv(*this, a); }
177180 inline ZZ to_ZZ(float a) { return ZZ(INIT_VAL, a); }
178181
179182 inline void conv(long& x, const ZZ& a) { x = NTL_ztoint(a.rep); }
17221725 // significantly faster. There are four possible implementations:
17231726 // - default: uses MulMod2 above (lots of floating point)
17241727 // - NTL_SPMM_ULL: uses unsigned long long (if possible)
1725 // - NTL_SMPP_ASM: uses assembly language (if possible)
1728 // - NTL_SPMM_ASM: uses assembly language (if possible)
17261729 // - NTL_SPMM_UL: uses only unsigned long arithmetic (portable, slower).
17271730
17281731 #if (!defined(NTL_SINGLE_MUL) && (defined(NTL_SPMM_ULL) || defined(NTL_SPMM_ASM)))
20142017 // computes a^e mod n, e >= 0
20152018
20162019
2020 inline
2021 void VectorMulModPrecon(long k, long *x, const long *a, long b, long n,
2022 mulmod_precon_t bninv)
2023 {
2024 for (long i = 0; i < k; i++)
2025 x[i] = MulModPrecon(a[i], b, n, bninv);
2026 }
2027
2028 inline
2029 void VectorMulMod(long k, long *x, const long *a, long b, long n,
2030 double ninv)
2031 {
2032 mulmod_precon_t bninv;
2033 bninv = PrepMulModPrecon(b, n, ninv);
2034 VectorMulModPrecon(k, x, a, b, n, bninv);
2035 }
2036
2037
2038 inline
2039 void VectorMulMod(long k, long *x, const long *a, long b, long n)
2040 {
2041 double ninv = 1/((double) n);
2042 VectorMulMod(k, x, a, b, n, ninv);
2043 }
2044
2045
20172046 NTL_CLOSE_NNS
20182047
20192048
5757
5858 { rep.kill(); }
5959
60
61
62 typedef ZZ coeff_type;
63 void SetLength(long n) { rep.SetLength(n); }
64 ZZ& operator[](long i) { return rep[i]; }
65 const ZZ& operator[](long i) const { return rep[i]; }
66
67
68
69
6070 static const ZZX& zero();
6171
6272 inline ZZX(long i, const ZZ& c);
280290 void conv(ZZX& x, const zz_pX& a);
281291 inline ZZX to_ZZX(const zz_pX& a)
282292 { ZZX x; conv(x, a); NTL_OPT_RETURN(ZZX, x); }
293
294
295
296
297 /* additional legacy conversions for v6 conversion regime */
298
299 inline void conv(ZZX& x, const ZZX& a)
300 { x = a; }
301
302 inline void conv(vec_ZZ& x, const ZZX& a)
303 { x = a.rep; }
304
305
306 /* ------------------------------------- */
283307
284308
285309
711735
712736
713737
714 // vectors
715
716 NTL_vector_decl(ZZX,vec_ZZX)
717
718 NTL_eq_vector_decl(ZZX,vec_ZZX)
719
720 NTL_io_vector_decl(ZZX,vec_ZZX)
738 typedef Vec<ZZX> vec_ZZX;
739
721740
722741 NTL_CLOSE_NNS
723742
428428
429429 inline ZZ_p& ZZ_p::operator=(long a) { conv(*this, a); return *this; }
430430
431
432
433 /* additional legacy conversions for v6 conversion regime */
434
435 inline void conv(int& x, const ZZ_p& a) { conv(x, rep(a)); }
436 inline void conv(unsigned int& x, const ZZ_p& a) { conv(x, rep(a)); }
437 inline void conv(long& x, const ZZ_p& a) { conv(x, rep(a)); }
438 inline void conv(unsigned long& x, const ZZ_p& a) { conv(x, rep(a)); }
439 inline void conv(ZZ& x, const ZZ_p& a) { conv(x, rep(a)); }
440
441 inline void conv(ZZ_p& x, const ZZ_p& a) { x = a; }
442
443 /* ------------------------------------- */
444
445
446
447
448 // overload these functions for Vec<ZZ_p>.
449 // They are defined in vec_ZZ_p.c
450 void BlockConstruct(ZZ_p* p, long n);
451 void BlockDestroy(ZZ_p* p, long n);
452
453
431454 NTL_CLOSE_NNS
432455
433456 #endif
482482 inline ZZ_pE& operator/=(ZZ_pE& x, long b)
483483 { div(x, x, b); return x; }
484484
485
486
487 /* additional legacy conversions for v6 conversion regime */
488
489 inline void conv(ZZ_pX& x, const ZZ_pE& a) { x = rep(a); }
490 inline void conv(ZZ_pE& x, const ZZ_pE& a) { x = a; }
491
492
493 /* ------------------------------------- */
494
495
496
485497 NTL_CLOSE_NNS
486498
487499 #endif
4444 // free space held by this polynomial. Value becomes 0.
4545
4646 { rep.kill(); }
47
48
49
50 typedef ZZ_pE coeff_type;
51 void SetLength(long n) { rep.SetLength(n); }
52 ZZ_pE& operator[](long i) { return rep[i]; }
53 const ZZ_pE& operator[](long i) const { return rep[i]; }
54
55
56
57
4758
4859 static const ZZ_pEX& zero();
4960
240251
241252 inline ZZ_pEX& ZZ_pEX::operator=(const ZZ_pE& a)
242253 { conv(*this, a); return *this; }
254
255
256
257
258 /* additional legacy conversions for v6 conversion regime */
259
260 inline void conv(ZZ_pEX& x, const ZZ_pEX& a)
261 { x = a; }
262
263 inline void conv(vec_ZZ_pE& x, const ZZ_pEX& a)
264 { x = a.rep; }
265
266 class ZZX;
267 void conv(ZZ_pEX& x, const ZZX& a);
268
269
270 /* ------------------------------------- */
271
272
243273
244274
245275 /*************************************************************
705735
706736
707737
708 NTL_vector_decl(ZZ_pEX,vec_ZZ_pEX)
709
710 NTL_eq_vector_decl(ZZ_pEX,vec_ZZ_pEX)
711
712 NTL_io_vector_decl(ZZ_pEX,vec_ZZ_pEX)
738 typedef Vec<ZZ_pEX> vec_ZZ_pEX;
713739
714740
715741
9292
9393 { rep.kill(); }
9494
95
96 typedef ZZ_p coeff_type;
97 void SetLength(long n) { rep.SetLength(n); }
98 ZZ_p& operator[](long i) { return rep[i]; }
99 const ZZ_p& operator[](long i) const { return rep[i]; }
100
101
95102 static const ZZ_pX& zero();
96103
97104
285292
286293 inline ZZ_pX to_ZZ_pX(const vec_ZZ_p& a)
287294 { ZZ_pX x; conv(x, a); NTL_OPT_RETURN(ZZ_pX, x); }
295
296
297
298
299
300 /* additional legacy conversions for v6 conversion regime */
301
302 inline void conv(ZZ_pX& x, const ZZ_pX& a)
303 { x = a; }
304
305 inline void conv(vec_ZZ_p& x, const ZZ_pX& a)
306 { x = a.rep; }
307
308
309 /* ------------------------------------- */
288310
289311
290312
9951017
9961018 *****************************************************************/
9971019
998 NTL_vector_decl(ZZ_pX,vec_ZZ_pX)
999
1000 NTL_eq_vector_decl(ZZ_pX,vec_ZZ_pX)
1001
1002 NTL_io_vector_decl(ZZ_pX,vec_ZZ_pX)
1020 typedef Vec<ZZ_pX> vec_ZZ_pX;
10031021
10041022
10051023
508508 These routines use malloc and free.
509509
510510 ***********************************************************************/
511
512
513 long _ntl_zmaxalloc(_ntl_verylong x);
514 /* max allocation request, possibly rounded up a bit */
511515
512516
513517 void _ntl_zsetlength(_ntl_verylong *v, long len);
626630 #define NTL_zscompare _ntl_zscompare
627631 #define NTL_zsdiv _ntl_zsdiv
628632 #define NTL_zsetbit _ntl_zsetbit
633 #define NTL_zmaxalloc _ntl_zmaxalloc
629634 #define NTL_zsetlength _ntl_zsetlength
630635 #define NTL_zsign _ntl_zsign
631636 #define NTL_zsize _ntl_zsize
410410 * and NTL_SPMM_ASM.
411411 * This plays a crucial role in the "small prime FFT" used to
412412 * implement polynomial arithmetic, and in other CRT-based methods
413 * (such as linear algebra over ZZ), as well as polynomial andd matrix
413 * (such as linear algebra over ZZ), as well as polynomial and matrix
414414 * arithmetic over zz_p.
415415 */
416416
456456
457457
458458
459 /*
460 * The following two flags provide additional control for how the
461 * FFT modulo single-precision primes is implemented.
462 */
463
464 #if 0
465 #define NTL_FFT_BIGTAB
466
467 /*
468 * Precomputed tables are used to store all the roots of unity
469 * used in an FFT computation for the first NTL_FFT_BIGTAB_LIMIT
470 * FFT primes (the latter is defined in FFT.h). This can
471 * lead to significant time savings but at the const of some space:
472 * in the worst case, the precomputed tables will take of space
473 * log_2(NTL_FFT_BUGTAB_LIMIT) * M, where M is roughly the maxmimum
474 * space occupied by any one polynomial that was involved in an
475 * FFT computation (this could be a polynomial over zz_p, ZZ_p, or ZZ).
476 *
477 * To re-build after changing this flag: rm *.o; make ntl.a
478 */
479
480 #endif
481
482
483 #if 0
484 #define NTL_FFT_LAZYMUL
485
486 /*
487 * This flag only has an effect when combined with the NTL_FFT_BIGTAB
488 * flag, and either the NTL_SPMM_ULL or NTL_SPMM_ASM flags.
489 * When set, a "lazy multiplication" strategy due to David Harvey:
490 * see his paper "FASTER ARITHMETIC FOR NUMBER-THEORETIC TRANSFORMS".
491 *
492 * To re-build after changing this flag: rm *.o; make ntl.a
493 */
494
495
496 #endif
497
498
499
459500
460501
461502 /* The next five flags NTL_AVOID_BRANCHING, NTL_TBL_REM,
410410 * and NTL_SPMM_ASM.
411411 * This plays a crucial role in the "small prime FFT" used to
412412 * implement polynomial arithmetic, and in other CRT-based methods
413 * (such as linear algebra over ZZ), as well as polynomial andd matrix
413 * (such as linear algebra over ZZ), as well as polynomial and matrix
414414 * arithmetic over zz_p.
415415 */
416416
456456
457457
458458
459 /*
460 * The following two flags provide additional control for how the
461 * FFT modulo single-precision primes is implemented.
462 */
463
464 #if 0
465 #define NTL_FFT_BIGTAB
466
467 /*
468 * Precomputed tables are used to store all the roots of unity
469 * used in an FFT computation for the first NTL_FFT_BIGTAB_LIMIT
470 * FFT primes (the latter is defined in FFT.h). This can
471 * lead to significant time savings but at the const of some space:
472 * in the worst case, the precomputed tables will take of space
473 * log_2(NTL_FFT_BUGTAB_LIMIT) * M, where M is roughly the maxmimum
474 * space occupied by any one polynomial that was involved in an
475 * FFT computation (this could be a polynomial over zz_p, ZZ_p, or ZZ).
476 *
477 * To re-build after changing this flag: rm *.o; make ntl.a
478 */
479
480 #endif
481
482
483 #if 0
484 #define NTL_FFT_LAZYMUL
485
486 /*
487 * This flag only has an effect when combined with the NTL_FFT_BIGTAB
488 * flag, and either the NTL_SPMM_ULL or NTL_SPMM_ASM flags.
489 * When set, a "lazy multiplication" strategy due to David Harvey:
490 * see his paper "FASTER ARITHMETIC FOR NUMBER-THEORETIC TRANSFORMS".
491 *
492 * To re-build after changing this flag: rm *.o; make ntl.a
493 */
494
495
496 #endif
497
498
499
459500
460501
461502 /* The next five flags NTL_AVOID_BRANCHING, NTL_TBL_REM,
400400
401401 ***********************************************************************/
402402
403 long _ntl_gmaxalloc(_ntl_gbigint x);
404 /* max allocation request, possibly rounded up a bit */
403405
404406 void _ntl_gsetlength(_ntl_gbigint *v, long len);
405407 /* Allocates enough space to hold a len-digit number,
513515 #define NTL_zscompare _ntl_gscompare
514516 #define NTL_zsdiv _ntl_gsdiv
515517 #define NTL_zsetbit _ntl_gsetbit
518 #define NTL_zmaxalloc _ntl_gmaxalloc
516519 #define NTL_zsetlength _ntl_gsetlength
517520 #define NTL_zsign _ntl_gsign
518521 #define NTL_zsize _ntl_gsize
340340 { zz_p x; random(x); return x; }
341341
342342
343
343344 // ****** input/output
344345
345346 NTL_SNS ostream& operator<<(NTL_SNS ostream& s, zz_p a);
347348 NTL_SNS istream& operator>>(NTL_SNS istream& s, zz_p& x);
348349
349350
351 /* additional legacy conversions for v6 conversion regime */
352
353 inline void conv(int& x, zz_p a) { conv(x, rep(a)); }
354 inline void conv(unsigned int& x, zz_p a) { conv(x, rep(a)); }
355 inline void conv(long& x, zz_p a) { conv(x, rep(a)); }
356 inline void conv(unsigned long& x, zz_p a) { conv(x, rep(a)); }
357 inline void conv(ZZ& x, zz_p a) { conv(x, rep(a)); }
358
359
360 inline void conv(zz_p& x, zz_p a) { x = a; }
361
362 /* ------------------------------------- */
363
364
365
350366 NTL_CLOSE_NNS
351367
352368 #endif
482482 inline zz_pE& operator/=(zz_pE& x, long b)
483483 { div(x, x, b); return x; }
484484
485
486
487 /* additional legacy conversions for v6 conversion regime */
488
489 inline void conv(zz_pX& x, const zz_pE& a) { x = rep(a); }
490 inline void conv(zz_pE& x, const zz_pE& a) { x = a; }
491
492
493 /* ------------------------------------- */
494
495
485496 NTL_CLOSE_NNS
486497
487498 #endif
4343 // free space held by this polynomial. Value becomes 0.
4444
4545 { rep.kill(); }
46
47
48
49 typedef zz_pE coeff_type;
50 void SetLength(long n) { rep.SetLength(n); }
51 zz_pE& operator[](long i) { return rep[i]; }
52 const zz_pE& operator[](long i) const { return rep[i]; }
53
54
55
4656
4757 static const zz_pEX& zero();
4858
239249
240250 inline zz_pEX& zz_pEX::operator=(const zz_pE& a)
241251 { conv(*this, a); return *this; }
252
253
254
255
256 /* additional legacy conversions for v6 conversion regime */
257
258 inline void conv(zz_pEX& x, const zz_pEX& a)
259 { x = a; }
260
261 inline void conv(vec_zz_pE& x, const zz_pEX& a)
262 { x = a.rep; }
263
264 class ZZX;
265 void conv(zz_pEX& x, const ZZX& a);
266
267
268 /* ------------------------------------- */
269
242270
243271
244272 /*************************************************************
704732
705733
706734
707 NTL_vector_decl(zz_pEX,vec_zz_pEX)
708
709 NTL_eq_vector_decl(zz_pEX,vec_zz_pEX)
710
711 NTL_io_vector_decl(zz_pEX,vec_zz_pEX)
712
713
735 typedef Vec<zz_pEX> vec_zz_pEX;
714736
715737
716738
100100
101101 { rep.kill(); }
102102
103
104
105 typedef zz_p coeff_type;
106 void SetLength(long n) { rep.SetLength(n); }
107 zz_p& operator[](long i) { return rep[i]; }
108 const zz_p& operator[](long i) const { return rep[i]; }
109
110
111
112
103113 static const zz_pX& zero();
104114
105115 zz_pX(zz_pX& x, INIT_TRANS_TYPE) : rep(x.rep, INIT_TRANS) { }
144154 // degree of a polynomial.
145155 // note that the zero polynomial has degree -1.
146156
147 zz_p coeff(const zz_pX& a, long i);
157 const zz_p coeff(const zz_pX& a, long i);
148158 // zero if i not in range
149159
150160 void GetCoeff(zz_p& x, const zz_pX& a, long i);
151161 // x = a[i], or zero if i not in range
152162
153 zz_p LeadCoeff(const zz_pX& a);
163 const zz_p LeadCoeff(const zz_pX& a);
154164 // zero if a == 0
155165
156 zz_p ConstTerm(const zz_pX& a);
166 const zz_p ConstTerm(const zz_pX& a);
157167 // zero if a == 0
158168
159169 void SetCoeff(zz_pX& x, long i, zz_p a);
299309
300310 inline zz_pX& zz_pX::operator=(long a)
301311 { conv(*this, a); return *this; }
312
313
314 /* additional legacy conversions for v6 conversion regime */
315
316 inline void conv(zz_pX& x, const zz_pX& a)
317 { x = a; }
318
319 inline void conv(vec_zz_p& x, const zz_pX& a)
320 { x = a.rep; }
321
322
323 /* ------------------------------------- */
302324
303325
304326
533555
534556 void SetSize(long NewK);
535557
536 fftRep() { k = MaxK = -1; NumPrimes = zz_pInfo->NumPrimes; }
558 fftRep() { k = MaxK = -1; NumPrimes = 0; }
537559 fftRep(INIT_SIZE_TYPE, long InitK)
538 { k = MaxK = -1; NumPrimes = zz_pInfo->NumPrimes; SetSize(InitK); }
560 { k = MaxK = -1; NumPrimes = 0; SetSize(InitK); }
539561 ~fftRep();
540562 };
541563
9851007
9861008 *****************************************************************/
9871009
988 NTL_vector_decl(zz_pX,vec_zz_pX)
989
990 NTL_eq_vector_decl(zz_pX,vec_zz_pX)
991
992 NTL_io_vector_decl(zz_pX,vec_zz_pX)
993
1010 typedef Vec<zz_pX> vec_zz_pX;
9941011
9951012
9961013 /**********************************************************
12381255 { zz_pX x; CharPolyMod(x, a, f); NTL_OPT_RETURN(zz_pX, x); }
12391256
12401257
1258
1259
1260
12411261 NTL_CLOSE_NNS
12421262
12431263 #endif
22 #define NTL_mat_GF2__H
33
44
5 #include <NTL/matrix.h>
56 #include <NTL/vec_vec_GF2.h>
67
78 NTL_OPEN_NNS
89
910
10 class mat_GF2 {
11 public:
12
13 vec_vec_GF2 _mat_GF2__rep;
14 long _mat_GF2__numcols;
15
16 mat_GF2() { _mat_GF2__numcols = 0; }
17 mat_GF2(const mat_GF2& a);
18 mat_GF2& operator=(const mat_GF2& a);
19 ~mat_GF2() { }
20
21 mat_GF2(INIT_SIZE_TYPE, long n, long m);
22
23 void kill();
24
25 void SetDims(long n, long m);
26
27 long NumRows() const { return _mat_GF2__rep.length(); }
28 long NumCols() const { return _mat_GF2__numcols; }
29
30 vec_GF2& operator[](long i) { return _mat_GF2__rep[i]; }
31 const vec_GF2& operator[](long i) const { return _mat_GF2__rep[i]; }
32
33 vec_GF2& operator()(long i) { return _mat_GF2__rep[i-1]; }
34 const vec_GF2& operator()(long i) const { return _mat_GF2__rep[i-1]; }
35
36 GF2 get(long i, long j) const { return _mat_GF2__rep[i].get(j); }
37 void put(long i, long j, GF2 a) { _mat_GF2__rep[i].put(j, a); }
38 void put(long i, long j, long a) { _mat_GF2__rep[i].put(j, a); }
39
40 subscript_GF2 operator()(long i, long j)
41 { return subscript_GF2(_mat_GF2__rep[i-1], j-1); }
42
43 const_subscript_GF2 operator()(long i, long j) const
44 { return const_subscript_GF2(_mat_GF2__rep[i-1], j-1); }
45
46 long position(const vec_GF2& a) const { return _mat_GF2__rep.position(a); }
47 long position1(const vec_GF2& a) const { return _mat_GF2__rep.position1(a); }
48
49 mat_GF2(mat_GF2& x, INIT_TRANS_TYPE) :
50 _mat_GF2__rep(x._mat_GF2__rep, INIT_TRANS), _mat_GF2__numcols(x._mat_GF2__numcols) { }
51 };
52
53 inline const vec_vec_GF2& rep(const mat_GF2& a)
54 { return a._mat_GF2__rep; }
55
56
57 void swap(mat_GF2& X, mat_GF2& Y);
58
59 void conv(mat_GF2& x, const vec_vec_GF2& a);
60 inline mat_GF2 to_mat_GF2(const vec_vec_GF2& a)
61 { mat_GF2 x; conv(x, a); NTL_OPT_RETURN(mat_GF2, x); }
11 typedef Mat<GF2> mat_GF2;
6212
6313
14 // some backward compaitibilty stuff
6415
65 long operator==(const mat_GF2& a, const mat_GF2& b);
66 long operator!=(const mat_GF2& a, const mat_GF2& b);
16 inline void conv(mat_GF2& x, const vec_vec_GF2& a) {
17 MakeMatrix(x, a);
18 }
6719
68
69 NTL_SNS istream& operator>>(NTL_SNS istream&, mat_GF2&);
70 NTL_SNS ostream& operator<<(NTL_SNS ostream&, const mat_GF2&);
20 inline mat_GF2 to_mat_GF2(const vec_vec_GF2& a) {
21 mat_GF2 x; conv(x, a); NTL_OPT_RETURN(mat_GF2, x);
22 }
7123
7224
7325
9850
9951 long IsIdent(const mat_GF2& A, long n);
10052 void transpose(mat_GF2& X, const mat_GF2& A);
101 void solve(GF2& d, vec_GF2& X, const mat_GF2& A, const vec_GF2& b);
102 void inv(GF2& d, mat_GF2& X, const mat_GF2& A);
53 void solve(ref_GF2 d, vec_GF2& X, const mat_GF2& A, const vec_GF2& b);
54 void inv(ref_GF2 d, mat_GF2& X, const mat_GF2& A);
10355
10456 inline void sqr(mat_GF2& X, const mat_GF2& A)
10557 { mul(X, A, A); }
13789
13890
13991
140 void determinant(GF2& x, const mat_GF2& a);
92 void determinant(ref_GF2 x, const mat_GF2& a);
14193 inline GF2 determinant(const mat_GF2& a)
14294 { GF2 x; determinant(x, a); return x; }
14395
66
77 NTL_OPEN_NNS
88
9 NTL_matrix_decl(GF2E,vec_GF2E,vec_vec_GF2E,mat_GF2E)
10 NTL_io_matrix_decl(GF2E,vec_GF2E,vec_vec_GF2E,mat_GF2E)
11 NTL_eq_matrix_decl(GF2E,vec_GF2E,vec_vec_GF2E,mat_GF2E)
9 typedef Mat<GF2E> mat_GF2E;
1210
1311 void add(mat_GF2E& X, const mat_GF2E& A, const mat_GF2E& B);
1412 inline void sub(mat_GF2E& X, const mat_GF2E& A, const mat_GF2E& B)
66
77 NTL_OPEN_NNS
88
9 NTL_matrix_decl(RR,vec_RR,vec_vec_RR,mat_RR)
10 NTL_io_matrix_decl(RR,vec_RR,vec_vec_RR,mat_RR)
11 NTL_eq_matrix_decl(RR,vec_RR,vec_vec_RR,mat_RR)
9 typedef Mat<RR> mat_RR;
1210
1311 void add(mat_RR& X, const mat_RR& A, const mat_RR& B);
1412 void sub(mat_RR& X, const mat_RR& A, const mat_RR& B);
88
99 NTL_OPEN_NNS
1010
11 NTL_matrix_decl(ZZ,vec_ZZ,vec_vec_ZZ,mat_ZZ)
12 NTL_io_matrix_decl(ZZ,vec_ZZ,vec_vec_ZZ,mat_ZZ)
13 NTL_eq_matrix_decl(ZZ,vec_ZZ,vec_vec_ZZ,mat_ZZ)
11 typedef Mat<ZZ> mat_ZZ;
1412
1513
1614 void add(mat_ZZ& X, const mat_ZZ& A, const mat_ZZ& B);
77
88 NTL_OPEN_NNS
99
10 NTL_matrix_decl(ZZ_p,vec_ZZ_p,vec_vec_ZZ_p,mat_ZZ_p)
11 NTL_io_matrix_decl(ZZ_p,vec_ZZ_p,vec_vec_ZZ_p,mat_ZZ_p)
12 NTL_eq_matrix_decl(ZZ_p,vec_ZZ_p,vec_vec_ZZ_p,mat_ZZ_p)
10 typedef Mat<ZZ_p> mat_ZZ_p;
1311
1412 void add(mat_ZZ_p& X, const mat_ZZ_p& A, const mat_ZZ_p& B);
1513 void sub(mat_ZZ_p& X, const mat_ZZ_p& A, const mat_ZZ_p& B);
55
66 NTL_OPEN_NNS
77
8 NTL_matrix_decl(ZZ_pE,vec_ZZ_pE,vec_vec_ZZ_pE,mat_ZZ_pE)
9
10 NTL_io_matrix_decl(ZZ_pE,vec_ZZ_pE,vec_vec_ZZ_pE,mat_ZZ_pE)
11
12 NTL_eq_matrix_decl(ZZ_pE,vec_ZZ_pE,vec_vec_ZZ_pE,mat_ZZ_pE)
8 typedef Mat<ZZ_pE> mat_ZZ_pE;
139
1410 void add(mat_ZZ_pE& X, const mat_ZZ_pE& A, const mat_ZZ_pE& B);
1511 void sub(mat_ZZ_pE& X, const mat_ZZ_pE& A, const mat_ZZ_pE& B);
66
77 NTL_OPEN_NNS
88
9 NTL_matrix_decl(zz_p,vec_zz_p,vec_vec_zz_p,mat_zz_p)
10 NTL_io_matrix_decl(zz_p,vec_zz_p,vec_vec_zz_p,mat_zz_p)
11 NTL_eq_matrix_decl(zz_p,vec_zz_p,vec_vec_zz_p,mat_zz_p)
9 typedef Mat<zz_p> mat_zz_p;
1210
1311
1412 void add(mat_zz_p& X, const mat_zz_p& A, const mat_zz_p& B);
55
66 NTL_OPEN_NNS
77
8 NTL_matrix_decl(zz_pE,vec_zz_pE,vec_vec_zz_pE,mat_zz_pE)
9
10 NTL_io_matrix_decl(zz_pE,vec_zz_pE,vec_vec_zz_pE,mat_zz_pE)
11
12 NTL_eq_matrix_decl(zz_pE,vec_zz_pE,vec_vec_zz_pE,mat_zz_pE)
8 typedef Mat<zz_pE> mat_zz_pE;
139
1410 void add(mat_zz_pE& X, const mat_zz_pE& A, const mat_zz_pE& B);
1511 void sub(mat_zz_pE& X, const mat_zz_pE& A, const mat_zz_pE& B);
66
77 // matrix templates
88
9
10 #define NTL_matrix_decl(T,vec_T,vec_vec_T,mat_T) \
11 class mat_T { \
12 public: \
13 \
14 vec_vec_T _mat__rep; \
15 long _mat__numcols; \
16 \
17 \
18 mat_T() { _mat__numcols = 0; } \
19 mat_T(const mat_T& l__a); \
20 mat_T& operator=(const mat_T& l__a); \
21 ~mat_T() { } \
22 \
23 mat_T(NTL_NNS INIT_SIZE_TYPE, long l__n, long l__m); \
24 \
25 void kill(); \
26 \
27 void SetDims(long l__n, long l__m); \
28 \
29 long NumRows() const { return _mat__rep.length(); } \
30 long NumCols() const { return _mat__numcols; } \
31 \
32 vec_T& operator[](long l__i) { return _mat__rep[l__i]; } \
33 const vec_T& operator[](long l__i) const { return _mat__rep[l__i]; } \
34 \
35 vec_T& operator()(long l__i) { return _mat__rep[l__i-1]; } \
36 const vec_T& operator()(long l__i) const { return _mat__rep[l__i-1]; } \
37 \
38 T& operator()(long l__i, long l__j) { return _mat__rep[l__i-1][l__j-1]; } \
39 const T& operator()(long l__i, long l__j) const \
40 { return _mat__rep[l__i-1][l__j-1]; } \
41 \
42 \
43 \
44 long position(const vec_T& l__a) const { return _mat__rep.position(l__a); } \
45 long position1(const vec_T& l__a) const { return _mat__rep.position1(l__a); } \
46 mat_T(mat_T& l__x, NTL_NNS INIT_TRANS_TYPE) : \
47 _mat__rep(l__x._mat__rep, NTL_NNS INIT_TRANS), _mat__numcols(l__x._mat__numcols) { } \
48 }; \
49 \
50 inline const vec_vec_T& rep(const mat_T& l__a) \
51 { return l__a._mat__rep; } \
52 \
53 void swap(mat_T& l__X, mat_T& l__Y); \
54 \
55 void MakeMatrix(mat_T& l__x, const vec_vec_T& l__a); \
56
57
58
59 #define NTL_eq_matrix_decl(T,vec_T,vec_vec_T,mat_T) \
60 long operator==(const mat_T& l__a, const mat_T& l__b); \
61 long operator!=(const mat_T& l__a, const mat_T& l__b); \
62
63
64
65 #define NTL_io_matrix_decl(T,vec_T,vec_vec_T,mat_T) \
66 NTL_SNS istream& operator>>(NTL_SNS istream&, mat_T&); \
67 NTL_SNS ostream& operator<<(NTL_SNS ostream&, const mat_T&); \
68
69
70 #define NTL_matrix_impl(T,vec_T,vec_vec_T,mat_T) \
71 mat_T::mat_T(const mat_T& l__a) \
72 { \
73 _mat__numcols = 0; \
74 SetDims(l__a.NumRows(), l__a.NumCols()); \
75 _mat__rep = l__a._mat__rep; \
76 } \
77 \
78 mat_T& mat_T::operator=(const mat_T& l__a) \
79 { \
80 SetDims(l__a.NumRows(), l__a.NumCols()); \
81 _mat__rep = l__a._mat__rep; \
82 return *this; \
83 } \
84 \
85 \
86 mat_T::mat_T(NTL_NNS INIT_SIZE_TYPE, long l__n, long l__m) \
87 { \
88 _mat__numcols = 0; \
89 SetDims(l__n, l__m); \
90 } \
91 \
92 void mat_T::kill() \
93 { \
94 _mat__numcols = 0; \
95 _mat__rep.kill(); \
96 } \
97 \
98 void mat_T::SetDims(long l__n, long l__m) \
99 { \
100 if (l__n < 0 || l__m < 0) \
101 NTL_NNS Error("SetDims: bad args"); \
102 \
103 if (l__m != _mat__numcols) { \
104 _mat__rep.kill(); \
105 _mat__numcols = l__m; \
106 } \
107 \
108 long l__oldmax = _mat__rep.MaxLength(); \
109 long l__i; \
110 _mat__rep.SetLength(l__n); \
111 \
112 for (l__i = l__oldmax; l__i < l__n; l__i++) \
113 _mat__rep[l__i].FixLength(l__m); \
114 } \
115 \
116 \
117 void MakeMatrix(mat_T& l__x, const vec_vec_T& l__a) \
118 { \
119 long l__n = l__a.length(); \
120 \
121 if (l__n == 0) { \
122 l__x.SetDims(0, 0); \
123 return; \
124 } \
125 \
126 long l__m = l__a[0].length(); \
127 long l__i; \
128 \
129 for (l__i = 1; l__i < l__n; l__i++) \
130 if (l__a[l__i].length() != l__m) \
131 NTL_NNS Error("nonrectangular matrix"); \
132 \
133 l__x.SetDims(l__n, l__m); \
134 for (l__i = 0; l__i < l__n; l__i++) \
135 l__x[l__i] = l__a[l__i]; \
136 } \
137 \
138 void swap(mat_T& l__X, mat_T& l__Y) \
139 { \
140 NTL_NNS swap(l__X._mat__numcols, l__Y._mat__numcols); \
141 swap(l__X._mat__rep, l__Y._mat__rep); \
142 } \
143 \
144
145
146
147
148
149
150 #define NTL_eq_matrix_impl(T,vec_T,vec_vec_T,mat_T) \
151 long operator==(const mat_T& l__a, const mat_T& l__b) \
152 { \
153 if (l__a.NumCols() != l__b.NumCols()) \
154 return 0; \
155 \
156 if (l__a.NumRows() != l__b.NumRows()) \
157 return 0; \
158 \
159 long l__n = l__a.NumRows(); \
160 long l__i; \
161 \
162 for (l__i = 0; l__i < l__n; l__i++) \
163 if (l__a[l__i] != l__b[l__i]) \
164 return 0; \
165 \
166 return 1; \
167 } \
168 \
169 \
170 long operator!=(const mat_T& l__a, const mat_T& l__b) \
171 { \
172 return !(l__a == l__b); \
173 } \
174
175
176
177
178 #define NTL_io_matrix_impl(T,vec_T,vec_vec_T,mat_T) \
179 NTL_SNS istream& operator>>(NTL_SNS istream& l__s, mat_T& l__x) \
180 { \
181 vec_vec_T l__buf; \
182 l__s >> l__buf; \
183 MakeMatrix(l__x, l__buf); \
184 return l__s; \
185 } \
186 \
187 NTL_SNS ostream& operator<<(NTL_SNS ostream& l__s, const mat_T& l__a) \
188 { \
189 long l__n = l__a.NumRows(); \
190 long l__i; \
191 l__s << "["; \
192 for (l__i = 0; l__i < l__n; l__i++) { \
193 l__s << l__a[l__i]; \
194 l__s << "\n"; \
195 } \
196 l__s << "]"; \
197 return l__s; \
198 } \
199
200
9 NTL_OPEN_NNS
10
11
12 template<class T>
13 class Mat {
14 public:
15
16 // pseudo-private fields
17 Vec< Vec<T> > _mat__rep;
18 long _mat__numcols;
19
20
21
22 // really public fields
23
24 typedef typename Vec<T>::value_type value_type;
25 typedef typename Vec<T>::reference reference;
26 typedef typename Vec<T>::const_reference const_reference;
27
28
29 Mat() : _mat__numcols(0) { }
30 Mat(const Mat<T>& a);
31 Mat& operator=(const Mat<T>& a);
32 ~Mat() { }
33
34 Mat(INIT_SIZE_TYPE, long n, long m);
35
36 void kill();
37
38 void SetDims(long n, long m);
39
40 long NumRows() const { return _mat__rep.length(); }
41 long NumCols() const { return _mat__numcols; }
42
43 Vec<T>& operator[](long i) { return _mat__rep[i]; }
44 const Vec<T>& operator[](long i) const { return _mat__rep[i]; }
45
46 Vec<T>& operator()(long i) { return _mat__rep[i-1]; }
47 const Vec<T>& operator()(long i) const { return _mat__rep[i-1]; }
48
49 reference operator()(long i, long j) { return _mat__rep[i-1][j-1]; }
50 const_reference operator()(long i, long j) const
51 { return _mat__rep[i-1][j-1]; }
52
53 const_reference get(long i, long j) const { return _mat__rep[i].get(j); }
54 void put(long i, long j, const T& a) { _mat__rep[i].put(j, a); }
55
56 template <class U>
57 void put(long i, long j, const U& a) { _mat__rep[i].put(j, a); }
58
59
60 long position(const Vec<T>& a) const { return _mat__rep.position(a); }
61 long position1(const Vec<T>& a) const { return _mat__rep.position1(a); }
62 Mat(Mat<T>& x, INIT_TRANS_TYPE) :
63 _mat__rep(x._mat__rep, INIT_TRANS), _mat__numcols(x._mat__numcols) { }
64 };
65
66 template<class T>
67 inline const Vec< Vec<T> >& rep(const Mat<T>& a)
68 { return a._mat__rep; }
69
70
71 template<class T>
72 Mat<T>::Mat(const Mat<T>& a) : _mat__numcols(0)
73 {
74 SetDims(a.NumRows(), a.NumCols());
75 _mat__rep = a._mat__rep;
76 }
77
78 template<class T>
79 Mat<T>& Mat<T>::operator=(const Mat<T>& a)
80 {
81 SetDims(a.NumRows(), a.NumCols());
82 _mat__rep = a._mat__rep;
83 return *this;
84 }
85
86 template<class T>
87 Mat<T>::Mat(INIT_SIZE_TYPE, long n, long m) : _mat__numcols(0)
88 {
89 SetDims(n, m);
90 }
91
92 template<class T>
93 void Mat<T>::kill()
94 {
95 _mat__numcols = 0;
96 _mat__rep.kill();
97 }
98
99 template<class T>
100 void Mat<T>::SetDims(long n, long m)
101 {
102 if (n < 0 || m < 0)
103 Error("SetDims: bad args");
104
105 if (m != _mat__numcols) {
106 _mat__rep.kill();
107 _mat__numcols = m;
108 }
109
110 long oldmax = _mat__rep.MaxLength();
111 long i;
112 _mat__rep.SetLength(n);
113
114 for (i = oldmax; i < n; i++)
115 _mat__rep[i].FixLength(m);
116 }
117
118
119 template<class T>
120 void MakeMatrix(Mat<T>& x, const Vec< Vec<T> >& a)
121 {
122 long n = a.length();
123
124 if (n == 0) {
125 x.SetDims(0, 0);
126 return;
127 }
128
129 long m = a[0].length();
130 long i;
131
132 for (i = 1; i < n; i++)
133 if (a[i].length() != m)
134 Error("nonrectangular matrix");
135
136 x.SetDims(n, m);
137 for (i = 0; i < n; i++)
138 x[i] = a[i];
139 }
140
141 template<class T>
142 void swap(Mat<T>& X, Mat<T>& Y)
143 {
144 swap(X._mat__numcols, Y._mat__numcols);
145 swap(X._mat__rep, Y._mat__rep);
146 }
147
148 template<class T>
149 long operator==(const Mat<T>& a, const Mat<T>& b)
150 {
151 if (a.NumCols() != b.NumCols())
152 return 0;
153
154 if (a.NumRows() != b.NumRows())
155 return 0;
156
157 long n = a.NumRows();
158 long i;
159
160 for (i = 0; i < n; i++)
161 if (a[i] != b[i])
162 return 0;
163
164 return 1;
165 }
166
167
168 template<class T>
169 long operator!=(const Mat<T>& a, const Mat<T>& b)
170 {
171 return !(a == b);
172 }
173
174
175 template<class T>
176 NTL_SNS istream& operator>>(NTL_SNS istream& s, Mat<T>& x)
177 {
178 Vec< Vec<T> > buf;
179 s >> buf;
180 MakeMatrix(x, buf);
181 return s;
182 }
183
184 template<class T>
185 NTL_SNS ostream& operator<<(NTL_SNS ostream& s, const Mat<T>& a)
186 {
187 long n = a.NumRows();
188 long i;
189 s << "[";
190 for (i = 0; i < n; i++) {
191 s << a[i];
192 s << "\n";
193 }
194 s << "]";
195 return s;
196 }
197
198
199 // conversion
200
201 template<class T, class S>
202 void conv(Mat<T>& x, const Mat<S>& a)
203 {
204 x.SetDims(a.NumRows(), a.NumCols());
205 conv(x._mat__rep, a._mat__rep);
206 }
207
208
209
210 NTL_CLOSE_NNS
201211
202212
203213 #endif
33
44 #include <NTL/tools.h>
55
6 #define NTL_pair_decl(S,T,pair_S_T) \
7 class pair_S_T { \
8 public: \
9 S a; \
10 T b; \
11 \
12 pair_S_T() { } \
13 pair_S_T(const pair_S_T& l__x) : a(l__x.a), b(l__x.b) { } \
14 pair_S_T& operator=(const pair_S_T& l__x) { a = l__x.a; b = l__x.b; return *this; } \
15 pair_S_T(const S& l__x, const T& l__y) : a(l__x), b(l__y) { } \
16 ~pair_S_T() { } \
17 }; \
18 \
19 inline pair_S_T cons(const S& l__x, const T& l__y) { return pair_S_T(l__x, l__y); } \
6 // pair templates
7
8 NTL_OPEN_NNS
9
10 template<class S, class T>
11 class Pair {
12 public:
13 S a;
14 T b;
15
16 Pair() { }
17 Pair(const Pair<S,T>& x) : a(x.a), b(x.b) { }
18 Pair(const S& x, const T& y) : a(x), b(y) { }
19 Pair<S,T>& operator=(const Pair<S,T>& x) { a = x.a; b = x.b; return *this; }
20 ~Pair() { }
21 };
22
23 template<class S, class T>
24 inline Pair<S,T> cons(const S& x, const T& y) { return Pair<S,T>(x, y); }
2025
2126
2227
28 template<class S, class T>
29 inline long operator==(const Pair<S,T>& x, const Pair<S,T>& y)
30 { return x.a == y.a && x.b == y.b; }
2331
24 #define NTL_pair_io_decl(S,T,pair_S_T) \
25 NTL_SNS istream& operator>>(NTL_SNS istream&, pair_S_T&); \
26 \
27 NTL_SNS ostream& operator<<(NTL_SNS ostream&, const pair_S_T&); \
32 template<class S, class T>
33 inline long operator!=(const Pair<S,T>& x, const Pair<S,T>& y)
34 { return !(x == y); }
2835
2936
3037
31 #define NTL_pair_eq_decl(S,T,pair_S_T) \
32 inline long operator==(const pair_S_T& l__x, const pair_S_T& l__y) \
33 { return l__x.a == l__y.a && l__x.b == l__y.b; } \
34 inline long operator!=(const pair_S_T& l__x, const pair_S_T& l__y) \
35 { return !(l__x == l__y); } \
38 template<class S, class T>
39 NTL_SNS istream& operator>>(NTL_SNS istream& s, Pair<S,T>& x)
40 {
41 long c;
42
43 if (!s) Error("bad pair input");
44
45 c = s.peek();
46 while (IsWhiteSpace(c)) {
47 s.get();
48 c = s.peek();
49 }
50
51 if (c != '[')
52 Error("bad pair input");
53
54 s.get();
55
56 if (!(s >> x.a))
57 Error("bad pair input");
58 if (!(s >> x.b))
59 Error("bad pair input");
60
61 c = s.peek();
62 while (IsWhiteSpace(c)) {
63 s.get();
64 c = s.peek();
65 }
66
67 if (c != ']')
68 Error("bad pair input");
69
70 s.get();
71
72 return s;
73 }
74
75 template<class S, class T>
76 NTL_SNS ostream& operator<<(NTL_SNS ostream& s, const Pair<S,T>& x)
77 {
78 return s << "[" << x.a << " " << x.b << "]";
79 }
3680
3781
38
39 // For compatability...
40 #define NTL_pair_impl(S,T,pair_S_T)
41
42
43 #define NTL_pair_io_impl(S,T,pair_S_T) \
44 NTL_SNS istream& operator>>(NTL_SNS istream& l__s, pair_S_T& l__x) \
45 { \
46 long l__c; \
47 \
48 if (!l__s) NTL_NNS Error("bad pair input"); \
49 \
50 l__c = l__s.peek(); \
51 while (NTL_NNS IsWhiteSpace(l__c)) { \
52 l__s.get(); \
53 l__c = l__s.peek(); \
54 } \
55 \
56 if (l__c != '[') \
57 NTL_NNS Error("bad pair input"); \
58 \
59 l__s.get(); \
60 \
61 if (!(l__s >> l__x.a)) \
62 NTL_NNS Error("bad pair input"); \
63 if (!(l__s >> l__x.b)) \
64 NTL_NNS Error("bad pair input"); \
65 \
66 l__c = l__s.peek(); \
67 while (NTL_NNS IsWhiteSpace(l__c)) { \
68 l__s.get(); \
69 l__c = l__s.peek(); \
70 } \
71 \
72 if (l__c != ']') \
73 NTL_NNS Error("bad pair input"); \
74 \
75 l__s.get(); \
76 \
77 return l__s; \
78 } \
79 \
80 NTL_SNS ostream& operator<<(NTL_SNS ostream& l__s, const pair_S_T& l__x) \
81 { \
82 return l__s << "[" << l__x.a << " " << l__x.b << "]"; \
83 } \
84
85
86
87 // For compatability...
88 #define NTL_pair_eq_impl(S,T,pair_S_T)
89
90
82 NTL_CLOSE_NNS
9183
9284
9385 #endif
77
88 NTL_OPEN_NNS
99
10 NTL_pair_decl(GF2EX,long,pair_GF2EX_long)
11 NTL_pair_io_decl(GF2EX,long,pair_GF2EX_long)
12 NTL_pair_eq_decl(GF2EX,long,pair_GF2EX_long)
1310
14 NTL_vector_decl(pair_GF2EX_long,vec_pair_GF2EX_long)
15 NTL_io_vector_decl(pair_GF2EX_long,vec_pair_GF2EX_long)
16 NTL_eq_vector_decl(pair_GF2EX_long,vec_pair_GF2EX_long)
11 typedef Pair<GF2EX,long> pair_GF2EX_long;
12
13 typedef Vec<pair_GF2EX_long> vec_pair_GF2EX_long;
1714
1815 NTL_CLOSE_NNS
1916
77
88 NTL_OPEN_NNS
99
10 NTL_pair_decl(GF2X,long,pair_GF2X_long)
11 NTL_pair_io_decl(GF2X,long,pair_GF2X_long)
12 NTL_pair_eq_decl(GF2X,long,pair_GF2X_long)
13
14 NTL_vector_decl(pair_GF2X_long,vec_pair_GF2X_long)
15 NTL_io_vector_decl(pair_GF2X_long,vec_pair_GF2X_long)
16 NTL_eq_vector_decl(pair_GF2X_long,vec_pair_GF2X_long)
10 typedef Pair<GF2X,long> pair_GF2X_long;
11 typedef Vec<pair_GF2X_long> vec_pair_GF2X_long;
1712
1813 NTL_CLOSE_NNS
1914
77
88 NTL_OPEN_NNS
99
10 NTL_pair_decl(ZZX,long,pair_ZZX_long)
11 NTL_pair_io_decl(ZZX,long,pair_ZZX_long)
12 NTL_pair_eq_decl(ZZX,long,pair_ZZX_long)
13
14 NTL_vector_decl(pair_ZZX_long,vec_pair_ZZX_long)
15 NTL_io_vector_decl(pair_ZZX_long,vec_pair_ZZX_long)
16 NTL_eq_vector_decl(pair_ZZX_long,vec_pair_ZZX_long)
10 typedef Pair<ZZX,long> pair_ZZX_long;
11 typedef Vec<pair_ZZX_long> vec_pair_ZZX_long;
1712
1813 NTL_CLOSE_NNS
1914
66
77 NTL_OPEN_NNS
88
9 NTL_pair_decl(ZZ_pEX,long,pair_ZZ_pEX_long)
10 NTL_pair_io_decl(ZZ_pEX,long,pair_ZZ_pEX_long)
11 NTL_pair_eq_decl(ZZ_pEX,long,pair_ZZ_pEX_long)
12
13
14 NTL_vector_decl(pair_ZZ_pEX_long,vec_pair_ZZ_pEX_long)
15 NTL_io_vector_decl(pair_ZZ_pEX_long,vec_pair_ZZ_pEX_long)
16 NTL_eq_vector_decl(pair_ZZ_pEX_long,vec_pair_ZZ_pEX_long)
9 typedef Pair<ZZ_pEX,long> pair_ZZ_pEX_long;
10 typedef Vec<pair_ZZ_pEX_long> vec_pair_ZZ_pEX_long;
1711
1812 NTL_CLOSE_NNS
1913
77
88 NTL_OPEN_NNS
99
10 NTL_pair_decl(ZZ_pX,long,pair_ZZ_pX_long)
11 NTL_pair_io_decl(ZZ_pX,long,pair_ZZ_pX_long)
12 NTL_pair_eq_decl(ZZ_pX,long,pair_ZZ_pX_long)
13
14 NTL_vector_decl(pair_ZZ_pX_long,vec_pair_ZZ_pX_long)
15 NTL_io_vector_decl(pair_ZZ_pX_long,vec_pair_ZZ_pX_long)
16 NTL_eq_vector_decl(pair_ZZ_pX_long,vec_pair_ZZ_pX_long)
10 typedef Pair<ZZ_pX,long> pair_ZZ_pX_long;
11 typedef Vec<pair_ZZ_pX_long> vec_pair_ZZ_pX_long;
1712
1813 NTL_CLOSE_NNS
1914
66
77 NTL_OPEN_NNS
88
9 NTL_pair_decl(zz_pEX,long,pair_zz_pEX_long)
10 NTL_pair_io_decl(zz_pEX,long,pair_zz_pEX_long)
11 NTL_pair_eq_decl(zz_pEX,long,pair_zz_pEX_long)
12
13
14 NTL_vector_decl(pair_zz_pEX_long,vec_pair_zz_pEX_long)
15 NTL_io_vector_decl(pair_zz_pEX_long,vec_pair_zz_pEX_long)
16 NTL_eq_vector_decl(pair_zz_pEX_long,vec_pair_zz_pEX_long)
9 typedef Pair<zz_pEX,long> pair_zz_pEX_long;
10 typedef Vec<pair_zz_pEX_long> vec_pair_zz_pEX_long;
1711
1812 NTL_CLOSE_NNS
1913
77
88 NTL_OPEN_NNS
99
10 NTL_pair_decl(zz_pX,long,pair_zz_pX_long)
11 NTL_pair_io_decl(zz_pX,long,pair_zz_pX_long)
12 NTL_pair_eq_decl(zz_pX,long,pair_zz_pX_long)
13
14 NTL_vector_decl(pair_zz_pX_long,vec_pair_zz_pX_long)
15 NTL_io_vector_decl(pair_zz_pX_long,vec_pair_zz_pX_long)
16 NTL_eq_vector_decl(pair_zz_pX_long,vec_pair_zz_pX_long)
10 typedef Pair<zz_pX,long> pair_zz_pX_long;
11 typedef Vec<pair_zz_pX_long> vec_pair_zz_pX_long;
1712
1813 NTL_CLOSE_NNS
1914
280280 inline void conv(quad_float& x, const char *s)
281281 { x = to_quad_float(s); }
282282
283
284
285 /* additional legacy conversions for v6 conversion regime */
286
287 inline void conv(unsigned int& x, const quad_float& a)
288 { long z; conv(z, a); conv(x, z); }
289
290 inline void conv(unsigned long& x, const quad_float& a)
291 { long z; conv(z, a); conv(x, z); }
292
293
294 /* ------------------------------------- */
295
283296 long IsFinite(quad_float *x);
284297
285298 long PrecisionOK();
243243 inline double to_double(double a) { return a; }
244244
245245
246
247 /* additional legacy conversions for v6 conversion regime */
248
249
250 inline void conv(unsigned int& x, int a) { x = ((unsigned int)(a)); }
251 inline void conv(unsigned int& x, long a) { x = ((unsigned int)(a)); }
252 inline void conv(unsigned int& x, unsigned a) { x = a; }
253 inline void conv(unsigned int& x, unsigned long a) { x = ((unsigned int)(a)); }
254 inline void conv(unsigned int& x, float a) { x = ((unsigned int) to_long(a)); }
255 inline void conv(unsigned int& x, double a) { x = ((unsigned int) to_long(a)); }
256
257 inline void conv(unsigned long& x, int a) { x = ((unsigned long)(a)); }
258 inline void conv(unsigned long& x, long a) { x = ((unsigned long)(a)); }
259 inline void conv(unsigned long& x, unsigned a) { x = ((unsigned long)(a)); }
260 inline void conv(unsigned long& x, unsigned long a) { x = a; }
261 inline void conv(unsigned long& x, float a) { x = ((unsigned int) to_long(a)); }
262 inline void conv(unsigned long& x, double a) { x = ((unsigned int) to_long(a)); }
263
264
265 /* ------------------------------------- */
266
267
268 // new style converson function
269 // example: ZZ x = conv<ZZ>(1);
270 // note: modern C++ compilers should implemented
271 // "named return value optimization", so the
272 // result statement should not create a temporary
273
274 template<class T, class S>
275 T conv(const S& a)
276 {
277 T x;
278 conv(x, a);
279 return x;
280 }
281
282
246283 long SkipWhiteSpace(NTL_SNS istream& s);
247284 long IsWhiteSpace(long c);
248285 long IsEOFChar(long c);
274311
275312 void PrintTime(NTL_SNS ostream& s, double t);
276313
314
315
316 #if (defined(__GNUC__) && (__GNUC__ >= 4))
317
318 // on relative modern versions of gcc, we can
319 // decalare "restricted" pointers in C++
320
321 #define NTL_RESTRICT __restrict
322
323 #else
324
325 #define NTL_RESTRICT
326
327 #endif
328
277329 NTL_CLOSE_NNS
278330
279331
66
77 NTL_OPEN_NNS
88
9 class vec_GF2;
10
11 class subscript_GF2 {
12 public:
13 vec_GF2& v;
14 long i;
15
16 subscript_GF2(vec_GF2& vv, long ii) : v(vv), i(ii) { }
17
18 inline const subscript_GF2& operator=(const subscript_GF2&) const;
19 inline const subscript_GF2& operator=(GF2) const;
20 inline const subscript_GF2& operator=(long) const;
21
22 inline operator GF2() const;
23 };
24
25 class const_subscript_GF2 {
26 public:
27 const vec_GF2& v;
28 long i;
29
30 const_subscript_GF2(const vec_GF2& vv, long ii) : v(vv), i(ii) { }
31
32 inline operator GF2() const;
33
34 private:
35 void operator=(const const_subscript_GF2&); // disabled
36
37 };
38
39
40 class vec_GF2 {
9
10 // Vec<GF2> is an explicit specialization of Vec<T>.
11 // Vec<GF2> is declared, but not defined, in GF2.h,
12 // to prevent the generic Vec from being used.
13
14 template<>
15 class Vec<GF2> {
4116
4217 public:
4318
5833 //the following are "really" public
5934
6035
61 vec_GF2() : _len(0), _maxlen(0) {}
62 vec_GF2(INIT_SIZE_TYPE, long n) : _len(0), _maxlen(0) { SetLength(n); }
63 vec_GF2(const vec_GF2& a) : _len(0), _maxlen(0) { *this = a; }
64
65 vec_GF2& operator=(const vec_GF2& a);
66
67 ~vec_GF2() {}
36 Vec() : _len(0), _maxlen(0) {}
37 Vec(INIT_SIZE_TYPE, long n) : _len(0), _maxlen(0) { SetLength(n); }
38 Vec(const Vec<GF2>& a) : _len(0), _maxlen(0) { *this = a; }
39
40 Vec& operator=(const Vec<GF2>& a);
41
42 ~Vec() {}
6843
6944 void kill();
7045
7853 long fixed() const { return _maxlen & 1; }
7954
8055
81 vec_GF2(vec_GF2& x, INIT_TRANS_TYPE) :
56 Vec(Vec<GF2>& x, INIT_TRANS_TYPE) :
8257 rep(x.rep, INIT_TRANS), _len(x._len), _maxlen(x._maxlen) { }
8358
84 GF2 get(long i) const;
59 const GF2 get(long i) const;
8560 void put(long i, GF2 a);
8661 void put(long i, long a) { put(i, to_GF2(a)); }
8762
88 subscript_GF2 operator[](long i)
89 { return subscript_GF2(*this, i); }
90
91 subscript_GF2 operator()(long i)
92 { return subscript_GF2(*this, i-1); }
93
94 const_subscript_GF2 operator[](long i) const
95 { return const_subscript_GF2(*this, i); }
96
97 const_subscript_GF2 operator()(long i) const
98 { return const_subscript_GF2(*this, i-1); }
63 ref_GF2 operator[](long i);
64
65 ref_GF2 operator()(long i)
66 { return (*this)[i-1]; }
67
68 const GF2 operator[](long i) const
69 { return get(i); }
70
71 const GF2 operator()(long i) const
72 { return get(i-1); }
73
74
75
76 // Some partial STL compatibility...also used
77 // to interface with the Matrix template class
78
79 typedef GF2 value_type;
80 typedef ref_GF2 reference;
81 typedef const GF2 const_reference;
9982
10083 };
10184
102 inline subscript_GF2::operator GF2() const
103 {
104 return v.get(i);
105 }
106
107 inline const_subscript_GF2::operator GF2() const
108 {
109 return v.get(i);
110 }
111
112 inline const subscript_GF2&
113 subscript_GF2::operator=(const subscript_GF2& a) const
114 { v.put(i, a.v.get(a.i)); return *this; }
115
116 inline const subscript_GF2&
117 subscript_GF2::operator=(GF2 a) const
118 { v.put(i, a); return *this; }
119
120 inline const subscript_GF2&
121 subscript_GF2::operator=(long a) const
122 { v.put(i, a); return *this; }
123
124 inline const subscript_GF2& operator+=(const subscript_GF2& x, GF2 b)
125 { x = x + b; return x; }
126
127 inline const subscript_GF2& operator+=(const subscript_GF2& x, long b)
128 { x = x + b; return x; }
129
130 inline const subscript_GF2& operator-=(const subscript_GF2& x, GF2 b)
131 { x = x - b; return x; }
132
133 inline const subscript_GF2& operator-=(const subscript_GF2& x, long b)
134 { x = x - b; return x; }
135
136 inline const subscript_GF2& operator*=(const subscript_GF2& x, GF2 b)
137 { x = x * b; return x; }
138
139 inline const subscript_GF2& operator*=(const subscript_GF2& x, long b)
140 { x = x * b; return x; }
141
142 inline const subscript_GF2& operator/=(const subscript_GF2& x, GF2 b)
143 { x = x / b; return x; }
144
145 inline const subscript_GF2& operator/=(const subscript_GF2& x, long b)
146 { x = x / b; return x; }
147
148 inline const subscript_GF2& operator++(const subscript_GF2& x)
149 { x = x + 1; return x; }
150
151 inline void operator++(const subscript_GF2& x, int)
152 { x = x + 1; }
153
154 inline const subscript_GF2& operator--(const subscript_GF2& x)
155 { x = x - 1; return x; }
156
157 inline void operator--(const subscript_GF2& x, int)
158 { x = x - 1; }
85 typedef Vec<GF2> vec_GF2;
86
87
88 // sepcialized conversion
89
90 inline void conv(vec_GF2& x, const vec_GF2& a)
91 { x = a; }
92
15993
16094 void swap(vec_GF2& x, vec_GF2& y);
161 void append(vec_GF2& v, GF2 a);
95 void append(vec_GF2& v, const GF2& a);
16296 void append(vec_GF2& v, const vec_GF2& a);
16397
16498 long operator==(const vec_GF2& a, const vec_GF2& b);
206140 inline void negate(vec_GF2& x, const vec_GF2& a)
207141 { x = a; }
208142
209 inline void InnerProduct(GF2& x, const vec_GF2& a, const vec_GF2& b)
143 inline void InnerProduct(ref_GF2 x, const vec_GF2& a, const vec_GF2& b)
210144 { x = to_GF2(InnerProduct(a.rep, b.rep)); }
211145
212146 long IsZero(const vec_GF2& a);
55
66 NTL_OPEN_NNS
77
8 NTL_vector_decl(GF2E,vec_GF2E)
9
10 NTL_io_vector_decl(GF2E,vec_GF2E)
11
12 NTL_eq_vector_decl(GF2E,vec_GF2E)
13
8 typedef Vec<GF2E> vec_GF2E;
149
1510 void mul(vec_GF2E& x, const vec_GF2E& a, const GF2E& b);
1611 inline void mul(vec_GF2E& x, const GF2E& a, const vec_GF2E& b)
66
77 NTL_OPEN_NNS
88
9 NTL_vector_decl(GF2XVec,vec_GF2XVec)
9 typedef Vec<GF2XVec> vec_GF2XVec;
1010
1111 NTL_CLOSE_NNS
1212
66
77 NTL_OPEN_NNS
88
9 NTL_vector_decl(RR,vec_RR)
10
11 NTL_eq_vector_decl(RR,vec_RR)
12
13 NTL_io_vector_decl(RR,vec_RR)
9 typedef Vec<RR> vec_RR;
1410
1511 void mul(vec_RR& x, const vec_RR& a, const RR& b);
1612 inline void mul(vec_RR& x, const RR& a, const vec_RR& b)
66
77 NTL_OPEN_NNS
88
9 NTL_vector_decl(ZZ,vec_ZZ)
10
11 NTL_eq_vector_decl(ZZ,vec_ZZ)
12
13 NTL_io_vector_decl(ZZ,vec_ZZ)
9 typedef Vec<ZZ> vec_ZZ;
1410
1511 void mul(vec_ZZ& x, const vec_ZZ& a, const ZZ& b);
1612 inline void mul(vec_ZZ& x, const ZZ& a, const vec_ZZ& b)
66
77 NTL_OPEN_NNS
88
9 NTL_vector_decl(ZZVec,vec_ZZVec)
9 typedef Vec<ZZVec> vec_ZZVec;
1010
1111 NTL_CLOSE_NNS
1212
66
77 NTL_OPEN_NNS
88
9 NTL_vector_decl(ZZ_p,vec_ZZ_p)
9 typedef Vec<ZZ_p> vec_ZZ_p;
1010
11 NTL_io_vector_decl(ZZ_p,vec_ZZ_p)
12
13 NTL_eq_vector_decl(ZZ_p,vec_ZZ_p)
1411
1512 void conv(vec_ZZ_p& x, const vec_ZZ& a);
1613 inline vec_ZZ_p to_vec_ZZ_p(const vec_ZZ& a)
55
66 NTL_OPEN_NNS
77
8 typedef Vec<ZZ_pE> vec_ZZ_pE;
89
9 NTL_vector_decl(ZZ_pE,vec_ZZ_pE)
10
11 NTL_io_vector_decl(ZZ_pE,vec_ZZ_pE)
12
13 NTL_eq_vector_decl(ZZ_pE,vec_ZZ_pE)
1410
1511 void mul(vec_ZZ_pE& x, const vec_ZZ_pE& a, const ZZ_pE& b);
1612 inline void mul(vec_ZZ_pE& x, const ZZ_pE& a, const vec_ZZ_pE& b)
55
66 NTL_OPEN_NNS
77
8 NTL_vector_decl(double,vec_double)
9
10 NTL_io_vector_decl(double,vec_double)
11
12 NTL_eq_vector_decl(double,vec_double)
8 typedef Vec<double> vec_double;
139
1410 NTL_CLOSE_NNS
1511
55
66 NTL_OPEN_NNS
77
8 NTL_vector_decl(long,vec_long)
9
10 NTL_io_vector_decl(long,vec_long)
11
12 NTL_eq_vector_decl(long,vec_long)
8 typedef Vec<long> vec_long;
139
1410 NTL_CLOSE_NNS
1511
66
77 NTL_OPEN_NNS
88
9 NTL_vector_decl(zz_p,vec_zz_p)
10
11 NTL_io_vector_decl(zz_p,vec_zz_p)
12
13 NTL_eq_vector_decl(zz_p,vec_zz_p)
9 typedef Vec<zz_p> vec_zz_p;
1410
1511 void conv(vec_zz_p& x, const vec_ZZ& a);
1612 inline vec_zz_p to_vec_zz_p(const vec_ZZ& a)
66 NTL_OPEN_NNS
77
88
9 NTL_vector_decl(zz_pE,vec_zz_pE)
10
11 NTL_io_vector_decl(zz_pE,vec_zz_pE)
12
13 NTL_eq_vector_decl(zz_pE,vec_zz_pE)
9 typedef Vec<zz_pE> vec_zz_pE;
1410
1511 void mul(vec_zz_pE& x, const vec_zz_pE& a, const zz_pE& b);
1612 inline void mul(vec_zz_pE& x, const zz_pE& a, const vec_zz_pE& b)
66
77 NTL_OPEN_NNS
88
9 NTL_vector_decl(quad_float,vec_quad_float)
10
11 NTL_io_vector_decl(quad_float,vec_quad_float)
12
13 NTL_eq_vector_decl(quad_float,vec_quad_float)
9 typedef Vec<quad_float> vec_quad_float;
1410
1511 NTL_CLOSE_NNS
1612
55
66 NTL_OPEN_NNS
77
8 NTL_vector_decl(_ntl_ulong,vec_ulong)
9
10 NTL_io_vector_decl(_ntl_ulong,vec_ulong)
11
12 NTL_eq_vector_decl(_ntl_ulong,vec_ulong)
8 typedef Vec<unsigned long> vec_ulong;
139
1410 NTL_CLOSE_NNS
1511
66
77 NTL_OPEN_NNS
88
9 NTL_vector_decl(vec_GF2,vec_vec_GF2)
10
11 NTL_eq_vector_decl(vec_GF2,vec_vec_GF2)
12
13 NTL_io_vector_decl(vec_GF2,vec_vec_GF2)
9 typedef Vec< Vec<GF2> > vec_vec_GF2;
1410
1511 NTL_CLOSE_NNS
1612
55
66 NTL_OPEN_NNS
77
8 NTL_vector_decl(vec_GF2E,vec_vec_GF2E)
9
10 NTL_eq_vector_decl(vec_GF2E,vec_vec_GF2E)
11
12 NTL_io_vector_decl(vec_GF2E,vec_vec_GF2E)
8 typedef Vec< Vec<GF2E> > vec_vec_GF2E;
139
1410 NTL_CLOSE_NNS
1511
55
66 NTL_OPEN_NNS
77
8 NTL_vector_decl(vec_RR,vec_vec_RR)
9
10 NTL_eq_vector_decl(vec_RR,vec_vec_RR)
11
12 NTL_io_vector_decl(vec_RR,vec_vec_RR)
8 typedef Vec< Vec<RR> > vec_vec_RR;
139
1410 NTL_CLOSE_NNS
1511
55
66 NTL_OPEN_NNS
77
8 NTL_vector_decl(vec_ZZ,vec_vec_ZZ)
9
10 NTL_eq_vector_decl(vec_ZZ,vec_vec_ZZ)
11
12 NTL_io_vector_decl(vec_ZZ,vec_vec_ZZ)
8 typedef Vec< Vec<ZZ> > vec_vec_ZZ;
139
1410 NTL_CLOSE_NNS
1511
55
66 NTL_OPEN_NNS
77
8 NTL_vector_decl(vec_ZZ_p,vec_vec_ZZ_p)
9
10 NTL_eq_vector_decl(vec_ZZ_p,vec_vec_ZZ_p)
11
12 NTL_io_vector_decl(vec_ZZ_p,vec_vec_ZZ_p)
8 typedef Vec< Vec<ZZ_p> > vec_vec_ZZ_p;
139
1410 NTL_CLOSE_NNS
1511
55
66 NTL_OPEN_NNS
77
8 NTL_vector_decl(vec_ZZ_pE,vec_vec_ZZ_pE)
9
10 NTL_eq_vector_decl(vec_ZZ_pE,vec_vec_ZZ_pE)
11
12 NTL_io_vector_decl(vec_ZZ_pE,vec_vec_ZZ_pE)
8 typedef Vec< Vec<ZZ_pE> > vec_vec_ZZ_pE;
139
1410 NTL_CLOSE_NNS
1511
55
66 NTL_OPEN_NNS
77
8 NTL_vector_decl(vec_long,vec_vec_long)
9
10 NTL_eq_vector_decl(vec_long,vec_vec_long)
11
12 NTL_io_vector_decl(vec_long,vec_vec_long)
8 typedef Vec< Vec<long> > vec_vec_long;
139
1410 NTL_CLOSE_NNS
1511
55
66 NTL_OPEN_NNS
77
8 NTL_vector_decl(vec_zz_p,vec_vec_zz_p)
9
10 NTL_eq_vector_decl(vec_zz_p,vec_vec_zz_p)
11
12 NTL_io_vector_decl(vec_zz_p,vec_vec_zz_p)
8 typedef Vec< Vec<zz_p> > vec_vec_zz_p;
139
1410 NTL_CLOSE_NNS
1511
55
66 NTL_OPEN_NNS
77
8 NTL_vector_decl(vec_zz_pE,vec_vec_zz_pE)
9
10 NTL_eq_vector_decl(vec_zz_pE,vec_vec_zz_pE)
11
12 NTL_io_vector_decl(vec_zz_pE,vec_vec_zz_pE)
8 typedef Vec< Vec<zz_pE> > vec_vec_zz_pE;
139
1410 NTL_CLOSE_NNS
1511
55
66 NTL_OPEN_NNS
77
8 NTL_vector_decl(vec_ulong,vec_vec_ulong)
9
10 NTL_eq_vector_decl(vec_ulong,vec_vec_ulong)
11
12 NTL_io_vector_decl(vec_ulong,vec_vec_ulong)
8 typedef Vec< Vec<unsigned long> > vec_vec_ulong;
139
1410 NTL_CLOSE_NNS
1511
66
77 NTL_OPEN_NNS
88
9 NTL_vector_decl(xdouble,vec_xdouble)
9 typedef Vec<xdouble> vec_xdouble;
1010
11 NTL_io_vector_decl(xdouble,vec_xdouble)
12
13 NTL_eq_vector_decl(xdouble,vec_xdouble)
1411
1512 NTL_CLOSE_NNS
1613
4141
4242 #ifndef NTL_RANGE_CHECK
4343 #define NTL_RANGE_CHECK_CODE
44 #define NTL_RANGE_CHECK_CODE1(i)
4445 #else
4546 #define NTL_RANGE_CHECK_CODE if (l__i < 0 || !_vec__rep || l__i >= NTL_VEC_HEAD(_vec__rep)->length) RangeError(l__i);
47
48 #define NTL_RANGE_CHECK_CODE1(i) if ((i) < 0 || !_vec__rep || (i) >= NTL_VEC_HEAD(_vec__rep)->length) RangeError(i);
49
4650 #endif
4751
4852 // vectors are allocated in chunks of this size
6468 #endif
6569
6670
67 #define NTL_vector_default(T) \
68 void BlockConstruct(T* l__p, long l__n) \
69 { \
70 long l__i; \
71 \
72 for (l__i = 0; l__i < l__n; l__i++) \
73 (void) new(_ntl_vector_placement_fn(&l__p[l__i])) T; \
74 } \
75 \
76 void BlockDestroy(T* l__p, long l__n) \
77 { \
78 long l__i; \
79 \
80 for (l__i = 0; l__i < l__n; l__i++) \
81 l__p[l__i].~T(); \
71 NTL_OPEN_NNS
72
73
74 template<class T>
75 void BlockConstruct(T* p, long n)
76 {
77 for (long i = 0; i < n; i++)
78 (void) new(_ntl_vector_placement_fn(&p[i])) T;
79 }
80
81 template<class T>
82 void BlockDestroy(T* p, long n)
83 {
84 for (long i = 0; i < n; i++)
85 p[i].~T();
8286 }
8387
8488
8589
86 #define NTL_vector_decl(T,vec_T) \
87 class vec_T { \
88 public: \
89 T *_vec__rep; \
90 \
91 void RangeError(long l__i) const; \
92 \
93 vec_T() { _vec__rep = 0; } \
94 vec_T(NTL_NNS INIT_SIZE_TYPE, long l__n) { _vec__rep = 0; SetLength(l__n); } \
95 vec_T(const vec_T& l__a) { _vec__rep = 0; *this = l__a; } \
96 vec_T& operator=(const vec_T& l__a); \
97 ~vec_T(); \
98 void kill(); \
99 \
100 void SetLength(long l__n); \
101 void SetMaxLength(long l__n); \
102 void FixLength(long l__n); \
103 void QuickSetLength(long l__n) { NTL_VEC_HEAD(_vec__rep)->length = l__n; } \
104 \
105 long length() const { return (!_vec__rep) ? 0 : NTL_VEC_HEAD(_vec__rep)->length; } \
106 long MaxLength() const { return (!_vec__rep) ? 0 : NTL_VEC_HEAD(_vec__rep)->init; } \
107 long allocated() const { return (!_vec__rep) ? 0 : NTL_VEC_HEAD(_vec__rep)->alloc; } \
108 long fixed() const { return _vec__rep && NTL_VEC_HEAD(_vec__rep)->fixed; } \
109 \
110 T& operator[](long l__i) \
111 { \
112 NTL_RANGE_CHECK_CODE \
113 return _vec__rep[l__i]; \
114 } \
115 \
116 const T& operator[](long l__i) const \
117 { \
118 NTL_RANGE_CHECK_CODE \
119 return _vec__rep[l__i]; \
120 } \
121 \
122 T& RawGet(long l__i) \
123 { \
124 return _vec__rep[l__i]; \
125 } \
126 \
127 const T& RawGet(long l__i) const \
128 { \
129 return _vec__rep[l__i]; \
130 } \
131 \
132 T& operator()(long l__i) { return (*this)[l__i-1]; } \
133 const T& operator()(long l__i) const { return (*this)[l__i-1]; } \
134 \
135 \
136 const T* elts() const { return _vec__rep; } \
137 T* elts() { return _vec__rep; } \
138 \
139 \
140 vec_T(vec_T& l__x, NTL_NNS INIT_TRANS_TYPE) { _vec__rep = l__x._vec__rep; l__x._vec__rep = 0; } \
141 long position(const T& l__a) const; \
142 long position1(const T& l__a) const; \
143 }; \
144 \
145 void swap(vec_T& l__x, vec_T& l__y); \
146 void append(vec_T& l__v, const T& l__a); \
147 void append(vec_T& l__v, const vec_T& l__w); \
148
149
150
151
152 #define NTL_io_vector_decl(T,vec_T) \
153 NTL_SNS istream& operator>>(NTL_SNS istream&, vec_T&); \
154 \
155 NTL_SNS ostream& operator<<(NTL_SNS ostream&, const vec_T&); \
156
157
158 #define NTL_eq_vector_decl(T,vec_T) \
159 long operator==(const vec_T& l__a, const vec_T& l__b); \
160 long operator!=(const vec_T& l__a, const vec_T& l__b);
161
162
163 #define NTL_vector_impl(T,vec_T) NTL_vector_default(T) NTL_vector_impl_plain(T,vec_T)
90 template<class T>
91 class Vec {
92 public:
93
94 T *_vec__rep;
95
96 void RangeError(long i) const;
97
98 Vec() : _vec__rep(0) { }
99 Vec(INIT_SIZE_TYPE, long n) : _vec__rep(0) { SetLength(n); }
100 Vec(const Vec<T>& a) : _vec__rep(0) { *this = a; }
101 Vec<T>& operator=(const Vec<T>& a);
102 ~Vec();
103 void kill();
104
105 void SetMaxLength(long n);
106 void FixLength(long n);
107 void QuickSetLength(long n) { NTL_VEC_HEAD(_vec__rep)->length = n; }
108
109 void SetLength(long n) {
110 if (_vec__rep && !NTL_VEC_HEAD(_vec__rep)->fixed &&
111 n >= 0 && n <= NTL_VEC_HEAD(_vec__rep)->init)
112 NTL_VEC_HEAD(_vec__rep)->length = n;
113 else
114 DoSetLength(n);
115 }
116
117 long length() const
118 { return (!_vec__rep) ? 0 : NTL_VEC_HEAD(_vec__rep)->length; }
119
120 long MaxLength() const
121 { return (!_vec__rep) ? 0 : NTL_VEC_HEAD(_vec__rep)->init; }
122
123 long allocated() const
124 { return (!_vec__rep) ? 0 : NTL_VEC_HEAD(_vec__rep)->alloc; }
125
126 long fixed() const
127 { return _vec__rep && NTL_VEC_HEAD(_vec__rep)->fixed; }
128
129 T& operator[](long i)
130 {
131 NTL_RANGE_CHECK_CODE1(i)
132 return _vec__rep[i];
133 }
134
135 const T& operator[](long i) const
136 {
137 NTL_RANGE_CHECK_CODE1(i)
138 return _vec__rep[i];
139 }
140
141 T& RawGet(long i)
142 {
143 return _vec__rep[i];
144 }
145
146 const T& RawGet(long i) const
147 {
148 return _vec__rep[i];
149 }
150
151 T& operator()(long i) { return (*this)[i-1]; }
152 const T& operator()(long i) const { return (*this)[i-1]; }
153
154
155 const T* elts() const { return _vec__rep; }
156 T* elts() { return _vec__rep; }
157
158
159 Vec(Vec<T>& x, INIT_TRANS_TYPE)
160 { _vec__rep = x._vec__rep; x._vec__rep = 0; }
161
162 long position(const T& a) const;
163 long position1(const T& a) const;
164
165 // Some compatibility with vec_GF2
166
167 const T& get(long i) const
168 { return (*this)[i]; }
169
170 void put(long i, const T& a)
171 { (*this)[i] = a; }
172
173
174 // Some STL compatibility
175
176 typedef T value_type;
177 typedef value_type& reference;
178 typedef const value_type& const_reference;
179 typedef value_type *iterator;
180 typedef const value_type *const_iterator;
181
182 const T* data() const { return elts(); }
183 T* data() { return elts(); }
184
185 T* begin() { return elts(); }
186 const T* begin() const { return elts(); }
187
188 T* end() {
189 if (elts())
190 return elts() + length();
191 else
192 return 0;
193 }
194
195 const T* end() const {
196 if (elts())
197 return elts() + length();
198 else
199 return 0;
200 }
201
202 T& at(long i) {
203 if ((i) < 0 || !_vec__rep || (i) >= NTL_VEC_HEAD(_vec__rep)->length)
204 RangeError(i);
205 return _vec__rep[i];
206 }
207
208 const T& at(long i) const {
209 if ((i) < 0 || !_vec__rep || (i) >= NTL_VEC_HEAD(_vec__rep)->length)
210 RangeError(i);
211 return _vec__rep[i];
212 }
213
214
215 private:
216 void DoSetLength(long n);
217 };
218
164219
165220
166221 #if (!defined(NTL_CLEAN_PTR))
167222
168 #define NTL_vector_impl_position(T,vec_T) \
169 long vec_T::position(const T& l__a) const \
170 { \
171 if (!_vec__rep) return -1; \
172 long l__num_alloc = NTL_VEC_HEAD(_vec__rep)->alloc; \
173 long l__num_init = NTL_VEC_HEAD(_vec__rep)->init; \
174 if (&l__a < _vec__rep || &l__a >= _vec__rep + l__num_alloc) return -1; \
175 long l__res = (&l__a) - _vec__rep; \
176 \
177 if (l__res < 0 || l__res >= l__num_alloc || \
178 _vec__rep + l__res != &l__a) return -1; \
179 \
180 if (l__res >= l__num_init) \
181 NTL_NNS Error("position: reference to uninitialized object"); \
182 return l__res; \
183 } \
184 \
185 long vec_T::position1(const T& l__a) const \
186 { \
187 if (!_vec__rep) return -1; \
188 long l__len = NTL_VEC_HEAD(_vec__rep)->length; \
189 if (&l__a < _vec__rep || &l__a >= _vec__rep + l__len) return -1; \
190 long l__res = (&l__a) - _vec__rep; \
191 \
192 if (l__res < 0 || l__res >= l__len || \
193 _vec__rep + l__res != &l__a) return -1; \
194 \
195 return l__res; \
196 } \
223 template<class T>
224 long Vec<T>::position(const T& a) const
225 {
226 if (!_vec__rep) return -1;
227 long num_alloc = NTL_VEC_HEAD(_vec__rep)->alloc;
228 long num_init = NTL_VEC_HEAD(_vec__rep)->init;
229 if (&a < _vec__rep || &a >= _vec__rep + num_alloc) return -1;
230 long res = (&a) - _vec__rep;
231
232 if (res < 0 || res >= num_alloc ||
233 _vec__rep + res != &a) return -1;
234
235 if (res >= num_init)
236 Error("position: reference to uninitialized object");
237 return res;
238 }
239
240 template<class T>
241 long Vec<T>::position1(const T& a) const
242 {
243 if (!_vec__rep) return -1;
244 long len = NTL_VEC_HEAD(_vec__rep)->length;
245 if (&a < _vec__rep || &a >= _vec__rep + len) return -1;
246 long res = (&a) - _vec__rep;
247
248 if (res < 0 || res >= len ||
249 _vec__rep + res != &a) return -1;
250
251 return res;
252 }
197253
198254
199255 #else
200256
201 #define NTL_vector_impl_position(T,vec_T) \
202 long vec_T::position(const T& l__a) const \
203 { \
204 if (!_vec__rep) return -1; \
205 long l__num_alloc = NTL_VEC_HEAD(_vec__rep)->alloc; \
206 long l__num_init = NTL_VEC_HEAD(_vec__rep)->init; \
207 long l__res; \
208 l__res = 0; \
209 while (l__res < l__num_alloc && _vec__rep + l__res != &l__a) l__res++; \
210 if (l__res >= l__num_alloc) return -1; \
211 if (l__res >= l__num_init) \
212 NTL_NNS Error("position: reference to uninitialized object"); \
213 return l__res; \
214 } \
215 \
216 long vec_T::position1(const T& l__a) const \
217 { \
218 if (!_vec__rep) return -1; \
219 long l__len = NTL_VEC_HEAD(_vec__rep)->length; \
220 long l__res; \
221 l__res = 0; \
222 while (l__res < l__len && _vec__rep + l__res != &l__a) l__res++; \
223 if (l__res >= l__len) return -1; \
224 return l__res; \
225 } \
257 template<class T>
258 long Vec<T>::position(const T& a) const
259 {
260 if (!_vec__rep) return -1;
261 long num_alloc = NTL_VEC_HEAD(_vec__rep)->alloc;
262 long num_init = NTL_VEC_HEAD(_vec__rep)->init;
263 long res;
264 res = 0;
265 while (res < num_alloc && _vec__rep + res != &a) res++;
266 if (res >= num_alloc) return -1;
267 if (res >= num_init)
268 Error("position: reference to uninitialized object");
269 return res;
270 }
271
272 template<class T>
273 long Vec<T>::position1(const T& a) const
274 {
275 if (!_vec__rep) return -1;
276 long len = NTL_VEC_HEAD(_vec__rep)->length;
277 long res;
278 res = 0;
279 while (res < len && _vec__rep + res != &a) res++;
280 if (res >= len) return -1;
281 return res;
282 }
226283
227284
228285 #endif
229286
230 #define NTL_vector_impl_plain(T,vec_T) \
231 \
232 void vec_T::SetLength(long l__n) \
233 { \
234 long l__m; \
235 \
236 if (l__n < 0) { \
237 NTL_NNS Error("negative length in vector::SetLength"); \
238 } \
239 if (NTL_OVERFLOW(l__n, sizeof(T), 0)) \
240 NTL_NNS Error("excessive length in vector::SetLength"); \
241 \
242 if (_vec__rep && NTL_VEC_HEAD(_vec__rep)->fixed) {\
243 if (NTL_VEC_HEAD(_vec__rep)->length == l__n) \
244 return; \
245 else \
246 NTL_NNS Error("SetLength: can't change this vector's length"); \
247 } \
248 if (l__n == 0) { \
249 if (_vec__rep) NTL_VEC_HEAD(_vec__rep)->length = 0; \
250 return; \
251 } \
252 \
253 if (!_vec__rep) { \
254 l__m = ((l__n+NTL_VectorMinAlloc-1)/NTL_VectorMinAlloc) * NTL_VectorMinAlloc; \
255 char *l__p = (char *) NTL_SNS_MALLOC(l__m, sizeof(T), sizeof(_ntl_AlignedVectorHeader)); \
256 if (!l__p) { \
257 NTL_NNS Error("out of memory in vector::SetLength()"); \
258 } \
259 _vec__rep = (T *) (l__p + sizeof(_ntl_AlignedVectorHeader)); \
260 \
261 BlockConstruct(_vec__rep, l__n); \
262 \
263 NTL_VEC_HEAD(_vec__rep)->length = l__n; \
264 NTL_VEC_HEAD(_vec__rep)->init = l__n; \
265 NTL_VEC_HEAD(_vec__rep)->alloc = l__m; \
266 NTL_VEC_HEAD(_vec__rep)->fixed = 0; \
267 } \
268 else if (l__n <= NTL_VEC_HEAD(_vec__rep)->init) { \
269 NTL_VEC_HEAD(_vec__rep)->length = l__n; \
270 } \
271 else { \
272 if (l__n > NTL_VEC_HEAD(_vec__rep)->alloc) { \
273 l__m = NTL_NNS max(l__n, long(NTL_VectorExpansionRatio*NTL_VEC_HEAD(_vec__rep)->alloc)); \
274 l__m = ((l__m+NTL_VectorMinAlloc-1)/NTL_VectorMinAlloc) * NTL_VectorMinAlloc; \
275 char *l__p = ((char *) _vec__rep) - sizeof(_ntl_AlignedVectorHeader); \
276 l__p = (char *) NTL_SNS_REALLOC(l__p, l__m, sizeof(T), sizeof(_ntl_AlignedVectorHeader)); \
277 if (!l__p) { \
278 NTL_NNS Error("out of memory in vector::SetLength()"); \
279 } \
280 _vec__rep = (T *) (l__p + sizeof(_ntl_AlignedVectorHeader)); \
281 NTL_VEC_HEAD(_vec__rep)->alloc = l__m; \
282 } \
283 BlockConstruct(_vec__rep + NTL_VEC_HEAD(_vec__rep)->init, l__n - NTL_VEC_HEAD(_vec__rep)->init); \
284 NTL_VEC_HEAD(_vec__rep)->length = l__n; \
285 NTL_VEC_HEAD(_vec__rep)->init = l__n; \
286 } \
287 } \
288 \
289 \
290 void vec_T::SetMaxLength(long l__n) \
291 { \
292 long l__OldLength = length(); \
293 SetLength(l__n); \
294 SetLength(l__OldLength); \
295 } \
296 \
297 void vec_T::FixLength(long l__n) \
298 { \
299 if (_vec__rep) NTL_NNS Error("FixLength: can't fix this vector"); \
300 if (l__n < 0) NTL_NNS Error("FixLength: negative length"); \
301 if (l__n > 0) \
302 SetLength(l__n); \
303 else { \
304 char *l__p = (char *) NTL_SNS_MALLOC(0, sizeof(T), sizeof(_ntl_AlignedVectorHeader)); \
305 if (!l__p) { \
306 NTL_NNS Error("out of memory in vector::FixLength()"); \
307 } \
308 _vec__rep = (T *) (l__p + sizeof(_ntl_AlignedVectorHeader)); \
309 \
310 NTL_VEC_HEAD(_vec__rep)->length = 0; \
311 NTL_VEC_HEAD(_vec__rep)->init = 0; \
312 NTL_VEC_HEAD(_vec__rep)->alloc = 0; \
313 } \
314 NTL_VEC_HEAD(_vec__rep)->fixed = 1; \
315 } \
316 \
317 vec_T& vec_T::operator=(const vec_T& l__a) \
318 { \
319 long l__i, l__n; \
320 T *l__p; \
321 const T *l__ap; \
322 \
323 l__n = l__a.length(); \
324 SetLength(l__n); \
325 l__ap = l__a.elts(); \
326 l__p = elts(); \
327 \
328 for (l__i = 0; l__i < l__n; l__i++) \
329 l__p[l__i] = l__ap[l__i]; \
330 return *this; \
331 } \
332 \
333 \
334 vec_T::~vec_T() \
335 { \
336 if (!_vec__rep) return; \
337 BlockDestroy(_vec__rep, NTL_VEC_HEAD(_vec__rep)->init); \
338 NTL_SNS free(((char *) _vec__rep) - sizeof(_ntl_AlignedVectorHeader)); \
339 } \
340 \
341 void vec_T::kill() \
342 { \
343 if (!_vec__rep) return; \
344 if (NTL_VEC_HEAD(_vec__rep)->fixed) NTL_NNS Error("can't kill this vector"); \
345 BlockDestroy(_vec__rep, NTL_VEC_HEAD(_vec__rep)->init); \
346 NTL_SNS free(((char *) _vec__rep) - sizeof(_ntl_AlignedVectorHeader)); \
347 _vec__rep = 0; \
348 } \
349 \
350 void vec_T::RangeError(long l__i) const \
351 { \
352 NTL_SNS cerr << "index out of range in vector: "; \
353 NTL_SNS cerr << l__i; \
354 if (!_vec__rep) \
355 NTL_SNS cerr << "(0)"; \
356 else \
357 NTL_SNS cerr << "(" << NTL_VEC_HEAD(_vec__rep)->length << ")"; \
358 NTL_NNS Error(""); \
359 } \
360 \
361 NTL_vector_impl_position(T,vec_T) \
362 \
363 void swap(vec_T& l__x, vec_T& l__y) \
364 { \
365 T* l__t; \
366 long l__xf = l__x.fixed(); \
367 long l__yf = l__y.fixed(); \
368 if (l__xf != l__yf || \
369 (l__xf && NTL_VEC_HEAD(l__x._vec__rep)->length != NTL_VEC_HEAD(l__y._vec__rep)->length)) \
370 NTL_NNS Error("swap: can't swap these vectors"); \
371 l__t = l__x._vec__rep; \
372 l__x._vec__rep = l__y._vec__rep; \
373 l__y._vec__rep = l__t; \
374 } \
375 \
376 void append(vec_T& l__v, const T& l__a) \
377 { \
378 long l__l = l__v.length(); \
379 if (l__l >= l__v.allocated()) { \
380 long l__pos = l__v.position(l__a); \
381 l__v.SetLength(l__l+1); \
382 if (l__pos != -1) \
383 l__v[l__l] = l__v.RawGet(l__pos); \
384 else \
385 l__v[l__l] = l__a; \
386 } \
387 else { \
388 l__v.SetLength(l__l+1); \
389 l__v[l__l] = l__a; \
390 } \
391 } \
392 \
393 void append(vec_T& l__v, const vec_T& l__w) \
394 { \
395 long l__l = l__v.length(); \
396 long l__m = l__w.length(); \
397 long l__i; \
398 l__v.SetLength(l__l+l__m); \
399 for (l__i = 0; l__i < l__m; l__i++) \
400 l__v[l__l+l__i] = l__w[l__i]; \
287
288 template<class T>
289 void Vec<T>::DoSetLength(long n)
290 {
291 long m;
292
293 if (n < 0) {
294 Error("negative length in vector::SetLength");
295 }
296 if (NTL_OVERFLOW(n, sizeof(T), 0))
297 Error("excessive length in vector::SetLength");
298
299 if (_vec__rep && NTL_VEC_HEAD(_vec__rep)->fixed) {
300 if (NTL_VEC_HEAD(_vec__rep)->length == n)
301 return;
302 else
303 Error("SetLength: can't change this vector's length");
304 }
305 if (n == 0) {
306 if (_vec__rep) NTL_VEC_HEAD(_vec__rep)->length = 0;
307 return;
308 }
309
310 if (!_vec__rep) {
311 m = ((n+NTL_VectorMinAlloc-1)/NTL_VectorMinAlloc) * NTL_VectorMinAlloc;
312 char *p = (char *) NTL_SNS_MALLOC(m, sizeof(T), sizeof(_ntl_AlignedVectorHeader));
313 if (!p) {
314 Error("out of memory in vector::SetLength()");
315 }
316 _vec__rep = (T *) (p + sizeof(_ntl_AlignedVectorHeader));
317
318 BlockConstruct(_vec__rep, n);
319
320 NTL_VEC_HEAD(_vec__rep)->length = n;
321 NTL_VEC_HEAD(_vec__rep)->init = n;
322 NTL_VEC_HEAD(_vec__rep)->alloc = m;
323 NTL_VEC_HEAD(_vec__rep)->fixed = 0;
324 }
325 else if (n <= NTL_VEC_HEAD(_vec__rep)->init) {
326 NTL_VEC_HEAD(_vec__rep)->length = n;
327 }
328 else {
329 if (n > NTL_VEC_HEAD(_vec__rep)->alloc) {
330 m = max(n, long(NTL_VectorExpansionRatio*NTL_VEC_HEAD(_vec__rep)->alloc));
331 m = ((m+NTL_VectorMinAlloc-1)/NTL_VectorMinAlloc) * NTL_VectorMinAlloc;
332 char *p = ((char *) _vec__rep) - sizeof(_ntl_AlignedVectorHeader);
333 p = (char *) NTL_SNS_REALLOC(p, m, sizeof(T), sizeof(_ntl_AlignedVectorHeader));
334 if (!p) {
335 Error("out of memory in vector::SetLength()");
336 }
337 _vec__rep = (T *) (p + sizeof(_ntl_AlignedVectorHeader));
338 NTL_VEC_HEAD(_vec__rep)->alloc = m;
339 }
340 BlockConstruct(_vec__rep + NTL_VEC_HEAD(_vec__rep)->init, n - NTL_VEC_HEAD(_vec__rep)->init);
341 NTL_VEC_HEAD(_vec__rep)->length = n;
342 NTL_VEC_HEAD(_vec__rep)->init = n;
343 }
344 }
345
346
347 template<class T>
348 void Vec<T>::SetMaxLength(long n)
349 {
350 long OldLength = length();
351 SetLength(n);
352 SetLength(OldLength);
353 }
354
355 template<class T>
356 void Vec<T>::FixLength(long n)
357 {
358 if (_vec__rep) Error("FixLength: can't fix this vector");
359 if (n < 0) Error("FixLength: negative length");
360 if (n > 0)
361 SetLength(n);
362 else {
363 char *p = (char *) NTL_SNS_MALLOC(0, sizeof(T), sizeof(_ntl_AlignedVectorHeader));
364 if (!p) {
365 Error("out of memory in vector::FixLength()");
366 }
367 _vec__rep = (T *) (p + sizeof(_ntl_AlignedVectorHeader));
368
369 NTL_VEC_HEAD(_vec__rep)->length = 0;
370 NTL_VEC_HEAD(_vec__rep)->init = 0;
371 NTL_VEC_HEAD(_vec__rep)->alloc = 0;
372 }
373 NTL_VEC_HEAD(_vec__rep)->fixed = 1;
374 }
375
376 template<class T>
377 Vec<T>& Vec<T>::operator=(const Vec<T>& a)
378 {
379 long i, n;
380 T *p;
381 const T *ap;
382
383 n = a.length();
384 SetLength(n);
385 ap = a.elts();
386 p = elts();
387
388 for (i = 0; i < n; i++)
389 p[i] = ap[i];
390 return *this;
391 }
392
393
394 template<class T>
395 Vec<T>::~Vec<T>()
396 {
397 if (!_vec__rep) return;
398 BlockDestroy(_vec__rep, NTL_VEC_HEAD(_vec__rep)->init);
399 NTL_SNS free(((char *) _vec__rep) - sizeof(_ntl_AlignedVectorHeader));
400 }
401
402 template<class T>
403 void Vec<T>::kill()
404 {
405 if (!_vec__rep) return;
406 if (NTL_VEC_HEAD(_vec__rep)->fixed) Error("can't kill this vector");
407 BlockDestroy(_vec__rep, NTL_VEC_HEAD(_vec__rep)->init);
408 NTL_SNS free(((char *) _vec__rep) - sizeof(_ntl_AlignedVectorHeader));
409 _vec__rep = 0;
410 }
411
412 template<class T>
413 void Vec<T>::RangeError(long i) const
414 {
415 NTL_SNS cerr << "index out of range in vector: ";
416 NTL_SNS cerr << i;
417 if (!_vec__rep)
418 NTL_SNS cerr << "(0)";
419 else
420 NTL_SNS cerr << "(" << NTL_VEC_HEAD(_vec__rep)->length << ")";
421 Error("");
422 }
423
424 template<class T>
425 void swap(Vec<T>& x, Vec<T>& y)
426 {
427 T* t;
428 long xf = x.fixed();
429 long yf = y.fixed();
430 if (xf != yf ||
431 (xf && NTL_VEC_HEAD(x._vec__rep)->length != NTL_VEC_HEAD(y._vec__rep)->length))
432 Error("swap: can't swap these vectors");
433 t = x._vec__rep;
434 x._vec__rep = y._vec__rep;
435 y._vec__rep = t;
436 }
437
438 template<class T>
439 void append(Vec<T>& v, const T& a)
440 {
441 long l = v.length();
442 if (l >= v.allocated()) {
443 long pos = v.position(a);
444 v.SetLength(l+1);
445 if (pos != -1)
446 v[l] = v.RawGet(pos);
447 else
448 v[l] = a;
449 }
450 else {
451 v.SetLength(l+1);
452 v[l] = a;
453 }
454 }
455
456 template<class T>
457 void append(Vec<T>& v, const Vec<T>& w)
458 {
459 long l = v.length();
460 long m = w.length();
461 long i;
462 v.SetLength(l+m);
463 for (i = 0; i < m; i++)
464 v[l+i] = w[i];
401465 }
402466
403467
404468
405469
406470
407 #define NTL_io_vector_impl(T,vec_T) \
408 NTL_SNS istream & operator>>(NTL_SNS istream& l__s, vec_T& l__a) \
409 { \
410 vec_T l__ibuf; \
411 long l__c; \
412 long l__n; \
413 if (!l__s) NTL_NNS Error("bad vector input"); \
414 \
415 l__c = l__s.peek(); \
416 while (NTL_NNS IsWhiteSpace(l__c)) { \
417 l__s.get(); \
418 l__c = l__s.peek(); \
419 } \
420 if (l__c != '[') { \
421 NTL_NNS Error("bad vector input"); \
422 } \
423 \
424 l__n = 0; \
425 l__ibuf.SetLength(0); \
426 \
427 l__s.get(); \
428 l__c = l__s.peek(); \
429 while (NTL_NNS IsWhiteSpace(l__c)) { \
430 l__s.get(); \
431 l__c = l__s.peek(); \
432 } \
433 while (l__c != ']' && !NTL_NNS IsEOFChar(l__c)) { \
434 if (l__n % NTL_VectorInputBlock == 0) l__ibuf.SetMaxLength(l__n + NTL_VectorInputBlock); \
435 l__n++; \
436 l__ibuf.SetLength(l__n); \
437 if (!(l__s >> l__ibuf[l__n-1])) NTL_NNS Error("bad vector input"); \
438 l__c = l__s.peek(); \
439 while (NTL_NNS IsWhiteSpace(l__c)) { \
440 l__s.get(); \
441 l__c = l__s.peek(); \
442 } \
443 } \
444 if (NTL_NNS IsEOFChar(l__c)) NTL_NNS Error("bad vector input"); \
445 l__s.get(); \
446 \
447 l__a = l__ibuf; \
448 return l__s; \
449 } \
450 \
451 \
452 NTL_SNS ostream& operator<<(NTL_SNS ostream& l__s, const vec_T& l__a) \
453 { \
454 long l__i, l__n; \
455 \
456 l__n = l__a.length(); \
457 \
458 l__s << '['; \
459 \
460 for (l__i = 0; l__i < l__n; l__i++) { \
461 l__s << l__a[l__i]; \
462 if (l__i < l__n-1) l__s << " "; \
463 } \
464 \
465 l__s << ']'; \
466 \
467 return l__s; \
468 } \
469
470 #define NTL_eq_vector_impl(T,vec_T) \
471 long operator==(const vec_T& l__a, const vec_T& l__b) \
472 { \
473 long l__n = l__a.length(); \
474 if (l__b.length() != l__n) return 0; \
475 const T* l__ap = l__a.elts(); \
476 const T* l__bp = l__b.elts(); \
477 long l__i; \
478 for (l__i = 0; l__i < l__n; l__i++) if (l__ap[l__i] != l__bp[l__i]) return 0; \
479 return 1; \
480 } \
481 long operator!=(const vec_T& l__a, const vec_T& l__b) \
482 { return !(l__a == l__b); }
483
484
471 template<class T>
472 NTL_SNS istream & operator>>(NTL_SNS istream& s, Vec<T>& a)
473 {
474 Vec<T> ibuf;
475 long c;
476 long n;
477 if (!s) Error("bad vector input");
478
479 c = s.peek();
480 while (IsWhiteSpace(c)) {
481 s.get();
482 c = s.peek();
483 }
484 if (c != '[') {
485 Error("bad vector input");
486 }
487
488 n = 0;
489 ibuf.SetLength(0);
490
491 s.get();
492 c = s.peek();
493 while (IsWhiteSpace(c)) {
494 s.get();
495 c = s.peek();
496 }
497 while (c != ']' && !IsEOFChar(c)) {
498 if (n % NTL_VectorInputBlock == 0) ibuf.SetMaxLength(n + NTL_VectorInputBlock);
499 n++;
500 ibuf.SetLength(n);
501 if (!(s >> ibuf[n-1])) Error("bad vector input");
502 c = s.peek();
503 while (IsWhiteSpace(c)) {
504 s.get();
505 c = s.peek();
506 }
507 }
508 if (IsEOFChar(c)) Error("bad vector input");
509 s.get();
510
511 a = ibuf;
512 return s;
513 }
514
515
516 template<class T>
517 NTL_SNS ostream& operator<<(NTL_SNS ostream& s, const Vec<T>& a)
518 {
519 long i, n;
520
521 n = a.length();
522
523 s << '[';
524
525 for (i = 0; i < n; i++) {
526 s << a[i];
527 if (i < n-1) s << " ";
528 }
529
530 s << ']';
531
532 return s;
533 }
534
535 template<class T>
536 long operator==(const Vec<T>& a, const Vec<T>& b)
537 {
538 long n = a.length();
539 if (b.length() != n) return 0;
540 const T* ap = a.elts();
541 const T* bp = b.elts();
542 long i;
543 for (i = 0; i < n; i++) if (ap[i] != bp[i]) return 0;
544 return 1;
545 }
546
547
548
549 template<class T>
550 long operator!=(const Vec<T>& a, const Vec<T>& b)
551 { return !(a == b); }
552
553
554
555
556 // conversions
557
558 template<class T, class S>
559 void conv(Vec<T>& x, const Vec<S>& a)
560 {
561 long n = a.length();
562 x.SetLength(n);
563 for (long i = 0; i < n; i++)
564 conv(x[i], a[i]);
565 }
566
567
568 NTL_CLOSE_NNS
569
570
571
572
573
485574
486575
487576 #endif
11 #ifndef NTL_version__H
22 #define NTL_version__H
33
4 #define NTL_VERSION "5.5.2"
4 #define NTL_VERSION "6.0.0"
55
6 #define NTL_MAJOR_VERSION (5)
7 #define NTL_MINOR_VERSION (5)
8 #define NTL_REVISION (2)
6 #define NTL_MAJOR_VERSION (6)
7 #define NTL_MINOR_VERSION (0)
8 #define NTL_REVISION (0)
99
1010 #endif
1111
216216 inline void conv(xdouble& x, double a) { x = to_xdouble(a); }
217217 inline void conv(xdouble& x, const char *a) { x = to_xdouble(a); }
218218
219
220
221 /* additional legacy conversions for v6 conversion regime */
222
223
224 inline void conv(unsigned int& x, const xdouble& a)
225 { long z; conv(z, a); conv(x, z); }
226
227 inline void conv(unsigned long& x, const xdouble& a)
228 { long z; conv(z, a); conv(x, z); }
229
230 /* ------------------------------------- */
231
219232 NTL_SNS ostream& operator<<(NTL_SNS ostream& s, const xdouble& a);
220233
221234 NTL_SNS istream& operator>>(NTL_SNS istream& s, xdouble& x);
0 ntl-5.5.2
0 ntl-6.0.0
119119 #endif
120120
121121
122
123
124122 #ifdef NTL_AVOID_BRANCHING
125123 cout << "NTL_AVOID_BRANCHING\n";
126124 #endif
127125
126 #ifdef NTL_FFT_BIGTAB
127 cout << "NTL_FFT_BIGTAB\n";
128 #endif
129
130 #ifdef NTL_FFT_LAZYMUL
131 cout << "NTL_FFT_LAZYMUL\n";
132 #endif
128133
129134
130135 #ifdef NTL_TBL_REM
7272 'NTL_CLEAN_INT' => 'off',
7373 'NTL_CLEAN_PTR' => 'off',
7474 'NTL_RANGE_CHECK' => 'off',
75 'NTL_FFT_BIGTAB' => 'off',
76 'NTL_FFT_LAZYMUL' => 'off',
7577
7678 );
7779
55
66 NTL_START_IMPL
77
8
9 FFTPrimeInfo *FFTTables = 0;
10 Vec<FFTPrimeInfo> FFTTables_store;
11
12 long *FFTPrime = 0;
13 Vec<long> FFTPrime_store;
14
15 double *FFTPrimeInv = 0;
16 Vec<double> FFTPrimeInv_store;
17
18 // We separate the pointer from the Vec, to ensure
19 // portability: global initialization of C++ objects
20 // can be problematic.
21
22
23
824 long NumFFTPrimes = 0;
925
1026
11
12 long *FFTPrime = 0;
13 long **RootTable = 0;
14 long **RootInvTable = 0;
15 long **TwoInvTable = 0;
16 double *FFTPrimeInv = 0;
1727
1828
1929 static
129139 }
130140
131141
142
132143 void UseFFTPrime(long index)
133144 {
134 if (index < 0 || index > NumFFTPrimes)
145 long numprimes = FFTTables_store.length();
146
147 if (index < 0 || index > numprimes)
135148 Error("invalid FFT prime index");
136149
137 if (index < NumFFTPrimes) return;
150 if (index < numprimes) return;
151
152 // index == numprimes
138153
139154 long q, w;
140155
141156 NextFFTPrime(q, w);
142157
158 double qinv = 1/((double) q);
159
143160 long mr = CalcMaxRoot(q);
144161
145 // tables are allocated in increments of 100
146
147 if (index == 0) {
148 FFTPrime = (long *) NTL_MALLOC(100, sizeof(long), 0);
149 RootTable = (long **) NTL_MALLOC(100, sizeof(long *), 0);
150 RootInvTable = (long **) NTL_MALLOC(100, sizeof(long *), 0);
151 TwoInvTable = (long **) NTL_MALLOC(100, sizeof(long *), 0);
152 FFTPrimeInv = (double *) NTL_MALLOC(100, sizeof(double), 0);
153 }
154 else if ((index % 100) == 0) {
155 FFTPrime = (long *) NTL_REALLOC(FFTPrime, index+100, sizeof(long), 0);
156 RootTable = (long **)
157 NTL_REALLOC(RootTable, index+100, sizeof(long *), 0);
158 RootInvTable = (long **)
159 NTL_REALLOC(RootInvTable, index+100, sizeof(long *), 0);
160 TwoInvTable = (long **)
161 NTL_REALLOC(TwoInvTable, index+100, sizeof(long *), 0);
162 FFTPrimeInv = (double *)
163 NTL_REALLOC(FFTPrimeInv, index+100, sizeof(double), 0);
164 }
165
166 if (!FFTPrime || !RootTable || !RootInvTable || !TwoInvTable ||
167 !FFTPrimeInv)
168 Error("out of space");
169
170 FFTPrime[index] = q;
171
172 long *rt, *rit, *tit;
173
174 if (!(rt = RootTable[index] = (long*) NTL_MALLOC(mr+1, sizeof(long), 0)))
175 Error("out of space");
176 if (!(rit = RootInvTable[index] = (long*) NTL_MALLOC(mr+1, sizeof(long), 0)))
177 Error("out of space");
178 if (!(tit = TwoInvTable[index] = (long*) NTL_MALLOC(mr+1, sizeof(long), 0)))
179 Error("out of space");
162 FFTTables_store.SetLength(numprimes+1);
163 FFTTables = FFTTables_store.elts();
164
165 FFTPrimeInfo& info = FFTTables[numprimes];
166
167 info.q = q;
168 info.qinv = qinv;
169
170 info.RootTable.SetLength(mr+1);
171 info.RootInvTable.SetLength(mr+1);
172 info.TwoInvTable.SetLength(mr+1);
173 info.TwoInvPreconTable.SetLength(mr+1);
174
175 long *rt = &info.RootTable[0];
176 long *rit = &info.RootInvTable[0];
177 long *tit = &info.TwoInvTable[0];
178 mulmod_precon_t *tipt = &info.TwoInvPreconTable[0];
180179
181180 long j;
182181 long t;
194193 for (j = 1; j <= mr; j++)
195194 tit[j] = MulMod(tit[j-1], t, q);
196195
197 FFTPrimeInv[index] = 1/double(q);
198
199 NumFFTPrimes++;
200 }
196 for (j = 0; j <= mr; j++)
197 tipt[j] = PrepMulModPrecon(tit[j], q, qinv);
198
199
200 // initialize data structures for the legacy inteface
201
202 NumFFTPrimes = FFTTables_store.length();
201203
202
203 static
204 long RevInc(long a, long k)
205 {
206 long j, m;
207
208 j = k;
209 m = 1L << (k-1);
210
211 while (j && (m & a)) {
212 a ^= m;
213 m >>= 1;
214 j--;
215 }
216 if (j) a ^= m;
217 return a;
218 }
219
220 static
221 void BitReverseCopy(long *A, const long *a, long k)
222 {
223 static long* mem[NTL_FFTMaxRoot+1];
224
225 long n = 1L << k;
226 long* rev;
227 long i, j;
228
229 rev = mem[k];
230 if (!rev) {
231 rev = mem[k] = (long *) NTL_MALLOC(n, sizeof(long), 0);
232 if (!rev) Error("out of memory in BitReverseCopy");
233 for (i = 0, j = 0; i < n; i++, j = RevInc(j, k))
234 rev[i] = j;
235 }
236
237 for (i = 0; i < n; i++)
238 A[rev[i]] = a[i];
239 }
240
241
204 FFTPrime_store.SetLength(NumFFTPrimes);
205 FFTPrime = FFTPrime_store.elts();
206 FFTPrime[NumFFTPrimes-1] = q;
207
208 FFTPrimeInv_store.SetLength(NumFFTPrimes);
209 FFTPrimeInv = FFTPrimeInv_store.elts();
210 FFTPrimeInv[NumFFTPrimes-1] = qinv;
211 }
242212
243213
244214
247217 * For very large inputs, it should be relatively cache friendly.
248218 * The inner loop has been unrolled and pipelined, to exploit any
249219 * low-level parallelism in the machine.
220 *
221 * This version now allows input to alias output.
250222 */
251223
252224
253225
226
227 static
228 long RevInc(long a, long k)
229 {
230 long j, m;
231
232 j = k;
233 m = 1L << (k-1);
234
235 while (j && (m & a)) {
236 a ^= m;
237 m >>= 1;
238 j--;
239 }
240 if (j) a ^= m;
241 return a;
242 }
243
244
245
246 static Vec<long> brc_mem[NTL_FFTMaxRoot+1];
247
248 static
249 void BitReverseCopy(long *A, const long *a, long k)
250 {
251 long n = 1L << k;
252 long* rev;
253 long i, j;
254
255 rev = brc_mem[k].elts();
256 if (!rev) {
257 brc_mem[k].SetLength(n);
258 rev = brc_mem[k].elts();
259 for (i = 0, j = 0; i < n; i++, j = RevInc(j, k))
260 rev[i] = j;
261 }
262
263 for (i = 0; i < n; i++)
264 A[rev[i]] = a[i];
265 }
266
267 static
268 void BitReverseCopy(unsigned long *A, const long *a, long k)
269 {
270 long n = 1L << k;
271 long* rev;
272 long i, j;
273
274 rev = brc_mem[k].elts();
275 if (!rev) {
276 brc_mem[k].SetLength(n);
277 rev = brc_mem[k].elts();
278 for (i = 0, j = 0; i < n; i++, j = RevInc(j, k))
279 rev[i] = j;
280 }
281
282 for (i = 0; i < n; i++)
283 A[rev[i]] = a[i];
284 }
285
286
287
254288 void FFT(long* A, const long* a, long k, long q, const long* root)
255
256289 // performs a 2^k-point convolution modulo q
257290
258291 {
262295 return;
263296 }
264297 if (k == 1) {
265 A[0] = AddMod(a[0], a[1], q);
266 A[1] = SubMod(a[0], a[1], q);
298 long a0 = AddMod(a[0], a[1], q);
299 long a1 = SubMod(a[0], a[1], q);
300 A[0] = a0;
301 A[1] = a1;
267302 return;
268303 }
269304 }
272307
273308
274309
275 static long tab_size = 0;
276 static long *wtab = 0;
277 static mulmod_precon_t *wqinvtab = 0;
278
279 if (!tab_size) {
280 tab_size = k;
281
282 wtab = (long *) NTL_MALLOC(1L << (k-2), sizeof(long), 0);
283 wqinvtab = (mulmod_precon_t *)
284 NTL_MALLOC(1L << (k-2), sizeof(mulmod_precon_t), 0);
285 if (!wtab || !wqinvtab) Error("out of space");
286 }
287 else if (tab_size < k) {
288 tab_size = k;
289
290 wtab = (long *) NTL_REALLOC(wtab, 1L << (k-2), sizeof(long), 0);
291 wqinvtab = (mulmod_precon_t *)
292 NTL_REALLOC(wqinvtab, 1L << (k-2), sizeof(mulmod_precon_t), 0);
293 if (!wtab || !wqinvtab) Error("out of space");
294 }
295
310 static Vec<long> wtab_store;
311 static Vec<mulmod_precon_t> wqinvtab_store;
312 static Vec<long> AA_store;
313
314 wtab_store.SetLength(1L << (k-2));
315 wqinvtab_store.SetLength(1L << (k-2));
316 AA_store.SetLength(1L << k);
317
318 long * NTL_RESTRICT wtab = wtab_store.elts();
319 mulmod_precon_t * NTL_RESTRICT wqinvtab = wqinvtab_store.elts();
320 long *AA = AA_store.elts();
296321
297322 double qinv = 1/((double) q);
298323
300325 wqinvtab[0] = PrepMulModPrecon(1, q, qinv);
301326
302327
303 BitReverseCopy(A, a, k);
328 BitReverseCopy(AA, a, k);
304329
305330 long n = 1L << k;
306331
307 long s, m, m_half, m_fourth, i, j, t, u, t1, u1, uu, uu1, tt, tt1;
332 long s, m, m_half, m_fourth, i, j, t, u, t1, u1, tt, tt1;
308333
309334 long w;
310335 mulmod_precon_t wqinv;
312337 // s = 1
313338
314339 for (i = 0; i < n; i += 2) {
315 t = A[i + 1];
316 u = A[i];
317 A[i] = AddMod(u, t, q);
318 A[i+1] = SubMod(u, t, q);
340 t = AA[i + 1];
341 u = AA[i];
342 AA[i] = AddMod(u, t, q);
343 AA[i+1] = SubMod(u, t, q);
319344 }
320345
321346
325350 m_half = 1L << (s-1);
326351 m_fourth = 1L << (s-2);
327352
328 // prepare wtab...
329
330353 w = root[s];
331354 wqinv = PrepMulModPrecon(w, q, qinv);
332355
333 for (i = m_half-1, j = m_fourth-1; i >= 0; i -= 2, j--) {
356 // prepare wtab...
357
358 if (s == 2) {
359 wtab[1] = MulModPrecon(wtab[0], w, q, wqinv);
360 wqinvtab[1] = PrepMulModPrecon(wtab[1], q, qinv);
361 }
362 else {
363 // some software pipelining
364
365 i = m_half-1; j = m_fourth-1;
334366 wtab[i-1] = wtab[j];
335367 wqinvtab[i-1] = wqinvtab[j];
336368 wtab[i] = MulModPrecon(wtab[i-1], w, q, wqinv);
337 wqinvtab[i] = PrepMulModPrecon(wtab[i], q, qinv);
369
370 i -= 2; j --;
371
372 for (; i >= 0; i -= 2, j --) {
373 long wp2 = wtab[i+2];
374 long wm1 = wtab[j];
375 wqinvtab[i+2] = PrepMulModPrecon(wp2, q, qinv);
376 wtab[i-1] = wm1;
377 wqinvtab[i-1] = wqinvtab[j];
378 wtab[i] = MulModPrecon(wm1, w, q, wqinv);
379 }
380
381 wqinvtab[1] = PrepMulModPrecon(wtab[1], q, qinv);
338382 }
339383
340384 for (i = 0; i < n; i+= m) {
341385
386 long * NTL_RESTRICT AA0 = &AA[i];
387 long * NTL_RESTRICT AA1 = &AA[i + m_half];
342388
343 t = A[i + m_half];
344 u = A[i];
345 t1 = MulModPrecon(A[i + 1+ m_half], w, q, wqinv);
346 u1 = A[i+1];
389 t = AA1[0];
390 u = AA0[0];
391 t1 = MulModPrecon(AA1[1], w, q, wqinv);
392 u1 = AA0[1];
347393
348394 for (j = 0; j < m_half-2; j += 2) {
349 tt = MulModPrecon(A[i + j + 2 + m_half], wtab[j+2], q, wqinvtab[j+2]);
350 uu = A[i + j + 2];
351
352
353 tt1 = MulModPrecon(A[i + j + 3+ m_half], wtab[j+3], q, wqinvtab[j+3]);
354 uu1 = A[i + j + 3];
355
356 A[i + j] = AddMod(u, t, q);
357 A[i + j + m_half] = SubMod(u, t, q);
358 A[i + j + 1] = AddMod(u1, t1, q);
359 A[i + j + 1 + m_half] = SubMod(u1, t1, q);
395 long a02 = AA0[j+2];
396 long a03 = AA0[j+3];
397 long a12 = AA1[j+2];
398 long a13 = AA1[j+3];
399 long w2 = wtab[j+2];
400 long w3 = wtab[j+3];
401 mulmod_precon_t wqi2 = wqinvtab[j+2];
402 mulmod_precon_t wqi3 = wqinvtab[j+3];
403
404 tt = MulModPrecon(a12, w2, q, wqi2);
405 long b00 = AddMod(u, t, q);
406 long b10 = SubMod(u, t, q);
360407 t = tt;
408 u = a02;
409
410 tt1 = MulModPrecon(a13, w3, q, wqi3);
411 long b01 = AddMod(u1, t1, q);
412 long b11 = SubMod(u1, t1, q);
361413 t1 = tt1;
362 u = uu;
363 u1 = uu1;
414 u1 = a03;
415
416 AA0[j] = b00;
417 AA1[j] = b10;
418 AA0[j+1] = b01;
419 AA1[j+1] = b11;
364420 }
365421
366422
367 A[i + j] = AddMod(u, t, q);
368 A[i + j + m_half] = SubMod(u, t, q);
369 A[i + j + 1] = AddMod(u1, t1, q);
370 A[i + j + 1 + m_half] = SubMod(u1, t1, q);
371
372
373
423 AA0[j] = AddMod(u, t, q);
424 AA1[j] = SubMod(u, t, q);
425 AA0[j + 1] = AddMod(u1, t1, q);
426 AA1[j + 1] = SubMod(u1, t1, q);
374427 }
375428 }
376429
387440
388441 // j = 0, 1
389442
390 t = A[m_half];
391 u = A[0];
392 t1 = MulModPrecon(A[1+ m_half], w, q, wqinv);
393 u1 = A[1];
443 t = AA[m_half];
444 u = AA[0];
445 t1 = MulModPrecon(AA[1+ m_half], w, q, wqinv);
446 u1 = AA[1];
394447
395448 A[0] = AddMod(u, t, q);
396449 A[m_half] = SubMod(u, t, q);
398451 A[1 + m_half] = SubMod(u1, t1, q);
399452
400453 for (j = 2; j < m_half; j += 2) {
401 t = MulModPrecon(A[j + m_half], wtab[j >> 1], q, wqinvtab[j >> 1]);
402 u = A[j];
403 t1 = MulModPrecon(A[j + 1+ m_half], wtab[j >> 1], q,
454 t = MulModPrecon(AA[j + m_half], wtab[j >> 1], q, wqinvtab[j >> 1]);
455 u = AA[j];
456 t1 = MulModPrecon(AA[j + 1+ m_half], wtab[j >> 1], q,
404457 wqinvtab[j >> 1]);
405458 t1 = MulModPrecon(t1, w, q, wqinv);
406 u1 = A[j + 1];
459 u1 = AA[j + 1];
407460
408461 A[j] = AddMod(u, t, q);
409462 A[j + m_half] = SubMod(u, t, q);
414467 }
415468
416469
470
471 #if (!defined(NTL_FFT_LAZYMUL) || defined(NTL_SINGLE_MUL) || \
472 (!defined(NTL_SPMM_ULL) && !defined(NTL_SPMM_ASM)))
473
474 // FFT with precomputed tables
475
476 #define NTL_PIPELINE (1)
477
478 static
479 void PrecompFFTMultipliers(long k, long q, const long *root, FFTMultipliers& tab)
480 {
481 if (k < 1) Error("PrecompFFTMultipliers: bad input");
482
483 if (k <= tab.MaxK) return;
484
485 tab.wtab_precomp.SetLength(k+1);
486 tab.wqinvtab_precomp.SetLength(k+1);
487
488 double qinv = 1/((double) q);
489
490 if (tab.MaxK == -1) {
491 tab.wtab_precomp[1].SetLength(1);
492 tab.wqinvtab_precomp[1].SetLength(1);
493 tab.wtab_precomp[1][0] = 1;
494 tab.wqinvtab_precomp[1][0] = PrepMulModPrecon(1, q, qinv);
495 tab.MaxK = 1;
496 }
497
498 for (long s = tab.MaxK+1; s <= k; s++) {
499 tab.wtab_precomp[s].SetLength(1L << (s-1));
500 tab.wqinvtab_precomp[s].SetLength(1L << (s-1));
501
502 long m = 1L << s;
503 long m_half = 1L << (s-1);
504 long m_fourth = 1L << (s-2);
505
506 long *wtab_last = tab.wtab_precomp[s-1].elts();
507 mulmod_precon_t *wqinvtab_last = tab.wqinvtab_precomp[s-1].elts();
508
509 long *wtab = tab.wtab_precomp[s].elts();
510 mulmod_precon_t *wqinvtab = tab.wqinvtab_precomp[s].elts();
511
512 for (long i = 0; i < m_fourth; i++) {
513 wtab[i] = wtab_last[i];
514 wqinvtab[i] = wqinvtab_last[i];
515 }
516
517 long w = root[s];
518 mulmod_precon_t wqinv = PrepMulModPrecon(w, q, qinv);
519
520 // prepare wtab...
521
522 if (s == 2) {
523 wtab[1] = MulModPrecon(wtab[0], w, q, wqinv);
524 wqinvtab[1] = PrepMulModPrecon(wtab[1], q, qinv);
525 }
526 else {
527 // some software pipelining
528 long i, j;
529
530 i = m_half-1; j = m_fourth-1;
531 wtab[i-1] = wtab[j];
532 wqinvtab[i-1] = wqinvtab[j];
533 wtab[i] = MulModPrecon(wtab[i-1], w, q, wqinv);
534
535 i -= 2; j --;
536
537 for (; i >= 0; i -= 2, j --) {
538 long wp2 = wtab[i+2];
539 long wm1 = wtab[j];
540 wqinvtab[i+2] = PrepMulModPrecon(wp2, q, qinv);
541 wtab[i-1] = wm1;
542 wqinvtab[i-1] = wqinvtab[j];
543 wtab[i] = MulModPrecon(wm1, w, q, wqinv);
544 }
545
546 wqinvtab[1] = PrepMulModPrecon(wtab[1], q, qinv);
547 }
548 }
549
550 tab.MaxK = k;
551 }
552
553
554
555 void FFT(long* A, const long* a, long k, long q, const long* root, FFTMultipliers& tab)
556 // performs a 2^k-point convolution modulo q
557
558 {
559 if (k <= 1) {
560 if (k == 0) {
561 A[0] = a[0];
562 return;
563 }
564 if (k == 1) {
565 long a0 = AddMod(a[0], a[1], q);
566 long a1 = SubMod(a[0], a[1], q);
567 A[0] = a0;
568 A[1] = a1;
569 return;
570 }
571 }
572
573
574
575 // assume k > 1
576
577 if (k > tab.MaxK) PrecompFFTMultipliers(k, q, root, tab);
578
579 static Vec<long> AA_store;
580 AA_store.SetLength(1L << k);
581 long *AA = AA_store.elts();
582
583 BitReverseCopy(AA, a, k);
584
585 long n = 1L << k;
586
587 long s, m, m_half, m_fourth, i, j, t, u, t1, u1, tt, tt1;
588
589 // s = 1
590
591 for (i = 0; i < n; i += 2) {
592 t = AA[i + 1];
593 u = AA[i];
594 AA[i] = AddMod(u, t, q);
595 AA[i+1] = SubMod(u, t, q);
596 }
597
598
599 for (s = 2; s < k; s++) {
600 m = 1L << s;
601 m_half = 1L << (s-1);
602 m_fourth = 1L << (s-2);
603
604 const long* wtab = tab.wtab_precomp[s].elts();
605 const mulmod_precon_t *wqinvtab = tab.wqinvtab_precomp[s].elts();
606
607 for (i = 0; i < n; i+= m) {
608
609 long *AA0 = &AA[i];
610 long *AA1 = &AA[i + m_half];
611
612 #if (NTL_PIPELINE)
613
614 // pipelining: seems to be faster
615
616 t = AA1[0];
617 u = AA0[0];
618 t1 = MulModPrecon(AA1[1], wtab[1], q, wqinvtab[1]);
619 u1 = AA0[1];
620
621 for (j = 0; j < m_half-2; j += 2) {
622 long a02 = AA0[j+2];
623 long a03 = AA0[j+3];
624 long a12 = AA1[j+2];
625 long a13 = AA1[j+3];
626 long w2 = wtab[j+2];
627 long w3 = wtab[j+3];
628 mulmod_precon_t wqi2 = wqinvtab[j+2];
629 mulmod_precon_t wqi3 = wqinvtab[j+3];
630
631 tt = MulModPrecon(a12, w2, q, wqi2);
632 long b00 = AddMod(u, t, q);
633 long b10 = SubMod(u, t, q);
634
635 tt1 = MulModPrecon(a13, w3, q, wqi3);
636 long b01 = AddMod(u1, t1, q);
637 long b11 = SubMod(u1, t1, q);
638
639 AA0[j] = b00;
640 AA1[j] = b10;
641 AA0[j+1] = b01;
642 AA1[j+1] = b11;
643
644
645 t = tt;
646 u = a02;
647 t1 = tt1;
648 u1 = a03;
649 }
650
651
652 AA0[j] = AddMod(u, t, q);
653 AA1[j] = SubMod(u, t, q);
654 AA0[j + 1] = AddMod(u1, t1, q);
655 AA1[j + 1] = SubMod(u1, t1, q);
656 }
657 #else
658 for (j = 0; j < m_half; j += 2) {
659 const long a00 = AA0[j];
660 const long a01 = AA0[j+1];
661 const long a10 = AA1[j];
662 const long a11 = AA1[j+1];
663
664 const long w0 = wtab[j];
665 const long w1 = wtab[j+1];
666 const mulmod_precon_t wqi0 = wqinvtab[j];
667 const mulmod_precon_t wqi1 = wqinvtab[j+1];
668
669 const long tt = MulModPrecon(a10, w0, q, wqi0);
670 const long uu = a00;
671 const long b00 = AddMod(uu, tt, q);
672 const long b10 = SubMod(uu, tt, q);
673
674 const long tt1 = MulModPrecon(a11, w1, q, wqi1);
675 const long uu1 = a01;
676 const long b01 = AddMod(uu1, tt1, q);
677 const long b11 = SubMod(uu1, tt1, q);
678
679 AA0[j] = b00;
680 AA0[j+1] = b01;
681 AA1[j] = b10;
682 AA1[j+1] = b11;
683 }
684 }
685 #endif
686 }
687
688
689 // s == k, special case
690 {
691 m = 1L << s;
692 m_half = 1L << (s-1);
693 m_fourth = 1L << (s-2);
694
695 const long* wtab = tab.wtab_precomp[s].elts();
696 const mulmod_precon_t *wqinvtab = tab.wqinvtab_precomp[s].elts();
697
698 for (i = 0; i < n; i+= m) {
699
700 long *AA0 = &AA[i];
701 long *AA1 = &AA[i + m_half];
702 long *A0 = &A[i];
703 long *A1 = &A[i + m_half];
704
705 #if (NTL_PIPELINE)
706
707 // pipelining: seems to be faster
708
709 t = AA1[0];
710 u = AA0[0];
711 t1 = MulModPrecon(AA1[1], wtab[1], q, wqinvtab[1]);
712 u1 = AA0[1];
713
714 for (j = 0; j < m_half-2; j += 2) {
715 long a02 = AA0[j+2];
716 long a03 = AA0[j+3];
717 long a12 = AA1[j+2];
718 long a13 = AA1[j+3];
719 long w2 = wtab[j+2];
720 long w3 = wtab[j+3];
721 mulmod_precon_t wqi2 = wqinvtab[j+2];
722 mulmod_precon_t wqi3 = wqinvtab[j+3];
723
724 tt = MulModPrecon(a12, w2, q, wqi2);
725 long b00 = AddMod(u, t, q);
726 long b10 = SubMod(u, t, q);
727
728 tt1 = MulModPrecon(a13, w3, q, wqi3);
729 long b01 = AddMod(u1, t1, q);
730 long b11 = SubMod(u1, t1, q);
731
732 A0[j] = b00;
733 A1[j] = b10;
734 A0[j+1] = b01;
735 A1[j+1] = b11;
736
737
738 t = tt;
739 u = a02;
740 t1 = tt1;
741 u1 = a03;
742 }
743
744
745 A0[j] = AddMod(u, t, q);
746 A1[j] = SubMod(u, t, q);
747 A0[j + 1] = AddMod(u1, t1, q);
748 A1[j + 1] = SubMod(u1, t1, q);
749 }
750 #else
751 for (j = 0; j < m_half; j += 2) {
752 const long a00 = AA0[j];
753 const long a01 = AA0[j+1];
754 const long a10 = AA1[j];
755 const long a11 = AA1[j+1];
756
757 const long w0 = wtab[j];
758 const long w1 = wtab[j+1];
759 const mulmod_precon_t wqi0 = wqinvtab[j];
760 const mulmod_precon_t wqi1 = wqinvtab[j+1];
761
762 const long tt = MulModPrecon(a10, w0, q, wqi0);
763 const long uu = a00;
764 const long b00 = AddMod(uu, tt, q);
765 const long b10 = SubMod(uu, tt, q);
766
767 const long tt1 = MulModPrecon(a11, w1, q, wqi1);
768 const long uu1 = a01;
769 const long b01 = AddMod(uu1, tt1, q);
770 const long b11 = SubMod(uu1, tt1, q);
771
772 A0[j] = b00;
773 A0[j+1] = b01;
774 A1[j] = b10;
775 A1[j+1] = b11;
776 }
777 }
778 #endif
779 }
780
781 }
782
783
784 #else
785
786 // FFT with precomputed tables and David Harvey's lazy multiplication
787 // strategy.
788
789
790 static inline
791 unsigned long LazyPrepMulModPrecon(long b, long n, double ninv)
792 {
793 unsigned long q, r;
794
795 q = (long) ( (((double) b) * NTL_SP_FBOUND) * ninv );
796 r = (((unsigned long) b) << NTL_SP_NBITS ) - q * ((unsigned long) n);
797
798 if (r >> (NTL_BITS_PER_LONG-1)) {
799 q--;
800 r += n;
801 }
802 else if (((long) r) >= n) {
803 q++;
804 r -=n;
805 }
806
807 unsigned long res = q << (NTL_BITS_PER_LONG - NTL_SP_NBITS);
808 long qq, rr;
809
810 rr = MulDivRem(qq, (long) r, 4, n, 4*ninv);
811
812 res = res + (qq << (NTL_BITS_PER_LONG - NTL_SP_NBITS-2));
813
814 return res;
815 }
816
817 static inline
818 unsigned long LazyMulModPrecon(unsigned long a, unsigned long b,
819 unsigned long n, unsigned long bninv)
820 {
821 unsigned long q = MulHiUL(a, bninv);
822 unsigned long res = a*b - q*n;
823 return res;
824 }
825
826
827 static inline
828 unsigned long LazyReduce(unsigned long a, unsigned long q)
829 {
830 unsigned long res;
831 #if (NTL_ARITH_RIGHT_SHIFT && defined(NTL_AVOID_BRANCHING) && !defined(NTL_CLEAN_INT))
832 res = a - q;
833 res += (((long) res) >> (NTL_BITS_PER_LONG-1)) & q;
834 #elif (defined(NTL_AVOID_BRANCHING))
835 res = a - q;
836 res += (-(res >> (NTL_BITS_PER_LONG-1))) & q;
837 #else
838 if (a >= q)
839 res = a - q;
840 else
841 res = a;
842 #endif
843
844 return res;
845 }
846
847
848 static
849 void LazyPrecompFFTMultipliers(long k, long q, const long *root, FFTMultipliers& tab)
850 {
851 if (k < 1) Error("LazyPrecompFFTMultipliers: bad input");
852
853 if (k <= tab.MaxK) return;
854
855 tab.wtab_precomp.SetLength(k+1);
856 tab.wqinvtab_precomp.SetLength(k+1);
857
858 double qinv = 1/((double) q);
859
860 if (tab.MaxK == -1) {
861 tab.wtab_precomp[1].SetLength(1);
862 tab.wqinvtab_precomp[1].SetLength(1);
863 tab.wtab_precomp[1][0] = 1;
864 tab.wqinvtab_precomp[1][0] = LazyPrepMulModPrecon(1, q, qinv);
865 tab.MaxK = 1;
866 }
867
868 for (long s = tab.MaxK+1; s <= k; s++) {
869 tab.wtab_precomp[s].SetLength(1L << (s-1));
870 tab.wqinvtab_precomp[s].SetLength(1L << (s-1));
871
872 long m = 1L << s;
873 long m_half = 1L << (s-1);
874 long m_fourth = 1L << (s-2);
875
876 long *wtab_last = tab.wtab_precomp[s-1].elts();
877 mulmod_precon_t *wqinvtab_last = tab.wqinvtab_precomp[s-1].elts();
878
879 long *wtab = tab.wtab_precomp[s].elts();
880 mulmod_precon_t *wqinvtab = tab.wqinvtab_precomp[s].elts();
881
882 for (long i = 0; i < m_fourth; i++) {
883 wtab[i] = wtab_last[i];
884 wqinvtab[i] = wqinvtab_last[i];
885 }
886
887 long w = root[s];
888 mulmod_precon_t wqinv = LazyPrepMulModPrecon(w, q, qinv);
889
890 // prepare wtab...
891
892 if (s == 2) {
893 wtab[1] = LazyReduce(LazyMulModPrecon(wtab[0], w, q, wqinv), q);
894 wqinvtab[1] = LazyPrepMulModPrecon(wtab[1], q, qinv);
895 }
896 else {
897 // some software pipelining
898 long i, j;
899
900 i = m_half-1; j = m_fourth-1;
901 wtab[i-1] = wtab[j];
902 wqinvtab[i-1] = wqinvtab[j];
903 wtab[i] = LazyReduce(LazyMulModPrecon(wtab[i-1], w, q, wqinv), q);
904
905 i -= 2; j --;
906
907 for (; i >= 0; i -= 2, j --) {
908 long wp2 = wtab[i+2];
909 long wm1 = wtab[j];
910 wqinvtab[i+2] = LazyPrepMulModPrecon(wp2, q, qinv);
911 wtab[i-1] = wm1;
912 wqinvtab[i-1] = wqinvtab[j];
913 wtab[i] = LazyReduce(LazyMulModPrecon(wm1, w, q, wqinv), q);
914 }
915
916 wqinvtab[1] = LazyPrepMulModPrecon(wtab[1], q, qinv);
917 }
918 }
919
920 tab.MaxK = k;
921 }
922
923
924
925
926 void FFT(long* A, const long* a, long k, long q, const long* root, FFTMultipliers& tab)
927
928 // performs a 2^k-point convolution modulo q
929
930 {
931 if (k <= 1) {
932 if (k == 0) {
933 A[0] = a[0];
934 return;
935 }
936 if (k == 1) {
937 long a0 = AddMod(a[0], a[1], q);
938 long a1 = SubMod(a[0], a[1], q);
939 A[0] = a0;
940 A[1] = a1;
941 return;
942 }
943 }
944
945 // assume k > 1
946
947 if (k > tab.MaxK) LazyPrecompFFTMultipliers(k, q, root, tab);
948
949 static Vec<unsigned long> AA_store;
950 AA_store.SetLength(1L << k);
951 unsigned long *AA = AA_store.elts();
952
953
954
955 BitReverseCopy(AA, a, k);
956
957 long n = 1L << k;
958
959
960 /* we work with redundant representations, in the range [0, 4q) */
961
962
963
964 long s, m, m_half, m_fourth, i, j;
965 unsigned long t, u, t1, u1;
966
967 long two_q = 2 * q;
968
969 // s = 1
970
971 for (i = 0; i < n; i += 2) {
972 t = AA[i + 1];
973 u = AA[i];
974 AA[i] = u + t;
975 AA[i+1] = u - t + q;
976 }
977
978
979 // s = 2
980
981 {
982 const long * NTL_RESTRICT wtab = tab.wtab_precomp[2].elts();
983 const mulmod_precon_t * NTL_RESTRICT wqinvtab = tab.wqinvtab_precomp[2].elts();
984
985 for (i = 0; i < n; i += 4) {
986
987 unsigned long * NTL_RESTRICT AA0 = &AA[i];
988 unsigned long * NTL_RESTRICT AA1 = &AA[i + 2];
989
990 {
991 const long w1 = wtab[0];
992 const mulmod_precon_t wqi1 = wqinvtab[0];
993 const unsigned long a11 = AA1[0];
994 const unsigned long a01 = AA0[0];
995
996 const unsigned long tt1 = LazyMulModPrecon(a11, w1, q, wqi1);
997 const unsigned long uu1 = LazyReduce(a01, two_q);
998 const unsigned long b01 = uu1 + tt1;
999 const unsigned long b11 = uu1 - tt1 + two_q;
1000
1001 AA0[0] = b01;
1002 AA1[0] = b11;
1003 }
1004 {
1005 const long w1 = wtab[1];
1006 const mulmod_precon_t wqi1 = wqinvtab[1];
1007 const unsigned long a11 = AA1[1];
1008 const unsigned long a01 = AA0[1];
1009
1010 const unsigned long tt1 = LazyMulModPrecon(a11, w1, q, wqi1);
1011 const unsigned long uu1 = LazyReduce(a01, two_q);
1012 const unsigned long b01 = uu1 + tt1;
1013 const unsigned long b11 = uu1 - tt1 + two_q;
1014
1015 AA0[1] = b01;
1016 AA1[1] = b11;
1017 }
1018 }
1019 }
1020
1021
1022 // s = 3..k
1023
1024 for (s = 3; s <= k; s++) {
1025 m = 1L << s;
1026 m_half = 1L << (s-1);
1027 m_fourth = 1L << (s-2);
1028
1029 const long* NTL_RESTRICT wtab = tab.wtab_precomp[s].elts();
1030 const mulmod_precon_t * NTL_RESTRICT wqinvtab = tab.wqinvtab_precomp[s].elts();
1031
1032 for (i = 0; i < n; i += m) {
1033
1034 unsigned long * NTL_RESTRICT AA0 = &AA[i];
1035 unsigned long * NTL_RESTRICT AA1 = &AA[i + m_half];
1036
1037 for (j = 0; j < m_half; j += 4) {
1038 {
1039 const long w1 = wtab[j+0];
1040 const mulmod_precon_t wqi1 = wqinvtab[j+0];
1041 const unsigned long a11 = AA1[j+0];
1042 const unsigned long a01 = AA0[j+0];
1043
1044 const unsigned long tt1 = LazyMulModPrecon(a11, w1, q, wqi1);
1045 const unsigned long uu1 = LazyReduce(a01, two_q);
1046 const unsigned long b01 = uu1 + tt1;
1047 const unsigned long b11 = uu1 - tt1 + two_q;
1048
1049 AA0[j+0] = b01;
1050 AA1[j+0] = b11;
1051 }
1052 {
1053 const long w1 = wtab[j+1];
1054 const mulmod_precon_t wqi1 = wqinvtab[j+1];
1055 const unsigned long a11 = AA1[j+1];
1056 const unsigned long a01 = AA0[j+1];
1057
1058 const unsigned long tt1 = LazyMulModPrecon(a11, w1, q, wqi1);
1059 const unsigned long uu1 = LazyReduce(a01, two_q);
1060 const unsigned long b01 = uu1 + tt1;
1061 const unsigned long b11 = uu1 - tt1 + two_q;
1062
1063 AA0[j+1] = b01;
1064 AA1[j+1] = b11;
1065 }
1066 {
1067 const long w1 = wtab[j+2];
1068 const mulmod_precon_t wqi1 = wqinvtab[j+2];
1069 const unsigned long a11 = AA1[j+2];
1070 const unsigned long a01 = AA0[j+2];
1071
1072 const unsigned long tt1 = LazyMulModPrecon(a11, w1, q, wqi1);
1073 const unsigned long uu1 = LazyReduce(a01, two_q);
1074 const unsigned long b01 = uu1 + tt1;
1075 const unsigned long b11 = uu1 - tt1 + two_q;
1076
1077 AA0[j+2] = b01;
1078 AA1[j+2] = b11;
1079 }
1080 {
1081 const long w1 = wtab[j+3];
1082 const mulmod_precon_t wqi1 = wqinvtab[j+3];
1083 const unsigned long a11 = AA1[j+3];
1084 const unsigned long a01 = AA0[j+3];
1085
1086 const unsigned long tt1 = LazyMulModPrecon(a11, w1, q, wqi1);
1087 const unsigned long uu1 = LazyReduce(a01, two_q);
1088 const unsigned long b01 = uu1 + tt1;
1089 const unsigned long b11 = uu1 - tt1 + two_q;
1090
1091 AA0[j+3] = b01;
1092 AA1[j+3] = b11;
1093 }
1094 }
1095 }
1096 }
1097
1098 /* need to reduce redundant representations */
1099
1100 for (i = 0; i < n; i++) {
1101 unsigned long tmp = LazyReduce(AA[i], two_q);
1102 A[i] = LazyReduce(tmp, q);
1103 }
1104 }
1105
1106
1107 #endif
1108
1109
1110
1111
1112
4171113 NTL_END_IMPL
11 #include <NTL/FacVec.h>
22 #include <NTL/ZZ.h>
33
4 #include <NTL/new.h>
54
65 NTL_START_IMPL
76
8 NTL_vector_impl(IntFactor,vec_IntFactor)
97
108 static
119 void swap(IntFactor& x, IntFactor& y)
55 NTL_START_IMPL
66
77
8 void div(GF2& x, GF2 a, GF2 b)
9 {
10 if (b == 0) Error("GF2: division by zero");
11 x = a;
12 }
13
14 void div(GF2& x, long a, GF2 b)
15 {
16 if (b == 0) Error("GF2: division by zero");
17 x = a;
18 }
19
20 void div(GF2& x, GF2 a, long b)
21 {
22 if ((b & 1) == 0) Error("GF2: division by zero");
23 x = a;
24 }
25
26 void inv(GF2& x, GF2 a)
27 {
28 if (a == 0) Error("GF2: division by zero");
29 x = a;
30 }
31
32 void power(GF2& x, GF2 a, long e)
8 GF2 power(GF2 a, long e)
339 {
3410 if (e == 0) {
35 x = 1;
36 return;
11 return to_GF2(1);
3712 }
3813
39 if (e < 0 && a == 0)
14 if (e < 0 && IsZero(a))
4015 Error("GF2: division by zero");
4116
42 x = a;
17 return a;
4318 }
4419
4520 ostream& operator<<(ostream& s, GF2 a)
5227 return s;
5328 }
5429
55 istream& operator>>(istream& s, GF2& x)
30 istream& operator>>(istream& s, ref_GF2 x)
5631 {
5732 static ZZ a;
5833
11
22 #include <NTL/GF2EX.h>
33 #include <NTL/vec_vec_GF2.h>
4 #include <NTL/ZZX.h>
45
56 #include <NTL/new.h>
67
237238 x.rep = a;
238239 x.normalize();
239240 }
241
242
243
244 /* additional legacy conversions for v6 conversion regime */
245
246 void conv(GF2EX& x, const ZZX& a)
247 {
248 long n = a.rep.length();
249 long i;
250
251 x.rep.SetLength(n);
252 for (i = 0; i < n; i++)
253 conv(x.rep[i], a.rep[i]);
254
255 x.normalize();
256 }
257
258
259 /* ------------------------------------- */
260
261
240262
241263
242264 void add(GF2EX& x, const GF2EX& a, const GF2EX& b)
22052227
22062228 U.normalize();
22072229 }
2208
2209 NTL_vector_impl(GF2EX,vec_GF2EX)
2210
2211 NTL_eq_vector_impl(GF2EX,vec_GF2EX)
2212
2213 NTL_io_vector_impl(GF2EX,vec_GF2EX)
2214
2215
22162230
22172231
22182232 void IterBuild(GF2E* a, long n)
32303244 }
32313245 }
32323246
3233 void ProjectedInnerProduct(GF2& x, const vec_GF2E& a,
3247 void ProjectedInnerProduct(ref_GF2 x, const vec_GF2E& a,
32343248 const vec_vec_GF2& b)
32353249 {
32363250 long n = min(a.length(), b.length());
21022102
21032103 if (deg(f) == 1) {
21042104 factors.SetLength(0);
2105 append(factors, cons(f, 1));
2105 append(factors, cons(f, 1L));
21062106 return;
21072107 }
21082108
5353 xrep.QuickSetLength(n);
5454 }
5555
56
57
58 void GF2X::SetLength(long n)
59 {
60 if (n < 0) {
61 Error("SetLength: negative index");
62 return;
63 }
64
65 long w = (n + NTL_BITS_PER_LONG - 1)/NTL_BITS_PER_LONG;
66 long old_w = xrep.length();
67
68 xrep.SetLength(w);
69
70 long i;
71
72 if (w > old_w) {
73 // zero out new words
74
75 for (i = old_w; i < w; i++)
76 xrep[i] = 0;
77 }
78 else {
79 // zero out high order bits of last word
80
81
82 long wi = n/NTL_BITS_PER_LONG;
83 long bi = n - wi*NTL_BITS_PER_LONG;
84
85 if (bi == 0) return;
86 unsigned long mask = (1UL << bi) - 1UL;
87 xrep[wi] &= mask;
88 }
89 }
90
91
92 ref_GF2 GF2X::operator[](long i)
93 {
94 if (i < 0) Error("GF2X: subscript out of range");
95 long wi = i/NTL_BITS_PER_LONG;
96 if (wi >= xrep.length()) Error("GF2X: subscript out of range");
97 long bi = i - wi*NTL_BITS_PER_LONG;
98 return ref_GF2(INIT_LOOP_HOLE, &xrep[wi], bi);
99 }
100
101
102 const GF2 GF2X::operator[](long i) const
103 {
104 if (i < 0) Error("GF2X: subscript out of range");
105 long wi = i/NTL_BITS_PER_LONG;
106 if (wi >= xrep.length()) Error("GF2X: subscript out of range");
107 long bi = i - wi*NTL_BITS_PER_LONG;
108 return to_GF2((xrep[wi] & (1UL << bi)) != 0);
109 }
110
111
112
113
114
56115 long IsZero(const GF2X& a)
57116 { return a.xrep.length() == 0; }
58117
70129 return a.xrep.length() == 1 && a.xrep[0] == 2;
71130 }
72131
73 GF2 coeff(const GF2X& a, long i)
132 const GF2 coeff(const GF2X& a, long i)
74133 {
75134 if (i < 0) return to_GF2(0);
76135 long wi = i/NTL_BITS_PER_LONG;
80139 return to_GF2((a.xrep[wi] & (1UL << bi)) != 0);
81140 }
82141
83 GF2 LeadCoeff(const GF2X& a)
142 const GF2 LeadCoeff(const GF2X& a)
84143 {
85144 if (IsZero(a))
86145 return to_GF2(0);
88147 return to_GF2(1);
89148 }
90149
91 GF2 ConstTerm(const GF2X& a)
150 const GF2 ConstTerm(const GF2X& a)
92151 {
93152 if (IsZero(a))
94153 return to_GF2(0);
161220 long bi = i - wi*NTL_BITS_PER_LONG;
162221
163222 x.xrep[wi] &= ~(1UL << bi);
164 if (wi == n-1) x.normalize();
223 if (wi == n-1 && !x.xrep[wi]) x.normalize();
165224 }
166225
167226 void SetCoeff(GF2X& x, long i, GF2 a)
14931552 }
14941553
14951554
1496 /****** implementation of vec_GF2X ******/
1497
1498
1499 NTL_vector_impl(GF2X,vec_GF2X)
1500
1501 NTL_io_vector_impl(GF2X,vec_GF2X)
1502
1503 NTL_eq_vector_impl(GF2X,vec_GF2X)
1504
1505
1506
15071555 void MulByX(GF2X& x, const GF2X& a)
15081556 {
15091557 long n = a.xrep.length();
11
22 #include <NTL/GF2X.h>
33 #include <NTL/vec_long.h>
4
5 #ifndef NTL_WIZARD_HACK
6
7 #include <NTL/ZZX.h>
8
9 #endif
410
511 #include <NTL/new.h>
612
24712477 VectorCopy(x, a, deg(a)+1);
24722478 }
24732479
2480
2481
2482 /* additional legacy conversions for v6 conversion regime */
2483
2484 #ifndef NTL_WIZARD_HACK
2485 void conv(GF2X& x, const ZZX& a)
2486 {
2487 long n = deg(a) + 1;
2488 long i;
2489
2490 x.SetLength(n);
2491 for (i = 0; i < n; i++)
2492 conv(x[i], a[i]);
2493 x.normalize();
2494 }
2495
2496 void conv(ZZX& x, const GF2X& a)
2497 {
2498 long n = deg(a) + 1;
2499 long i;
2500
2501 x.rep.SetLength(n);
2502 for (i = 0; i < n; i++)
2503 x.rep[i] = rep(coeff(a, i));
2504
2505 x.normalize();
2506 }
2507 #endif
2508
2509 /* ------------------------------------- */
2510
24742511 void VectorCopy(vec_GF2& x, const GF2X& a, long n)
24752512 {
24762513 if (n < 0) Error("VectorCopy: negative length");
32373274 }
32383275 }
32393276
3240 void TraceMod(GF2& x, const GF2X& a, const GF2XModulus& F)
3277 void TraceMod(ref_GF2 x, const GF2X& a, const GF2XModulus& F)
32413278 {
32423279 long n = F.n;
32433280
32503287 project(x, F.tracevec, a);
32513288 }
32523289
3253 void TraceMod(GF2& x, const GF2X& a, const GF2X& f)
3290 void TraceMod(ref_GF2 x, const GF2X& a, const GF2X& f)
32543291 {
32553292 if (deg(a) >= deg(f) || deg(f) <= 0)
32563293 Error("trace: bad args");
1414 make sure these changes are implemented in the template files
1515 mfile and cfile, and then run:
1616
17 - update ../README and ../doc/copying.txt
18
1719 ./configure
1820 cp makefile def_makefile
1921 cp ../include/NTL/config.h ../include/NTL/def_config.h
5151 #endif
5252
5353 #if defined(NTL_AVOID_BRANCHING)
54 printf("AVOID_BRANCHING");
54 printf("AVOID_BRANCHING ");
55 #endif
56
57 #if defined(NTL_FFT_BIGTAB)
58 printf("FFT_BIGTAB ");
59 #endif
60
61 #if defined(NTL_FFT_LAZYMUL)
62 printf("FFT_LAZYMUL ");
5563 #endif
5664
5765
124132 }
125133
126134 double t;
127 long i, j;
135 long i;
128136 long iter;
129137
130 UseFFTPrime(0);
131
132 vec_long aa, AA;
133
134 aa.SetLength(4096);
135 AA.SetLength(4096);
136
137 for (i = 0; i < 4096; i++)
138 aa[i] = RandomBnd(FFTPrime[0]);
139
140
141 FFT(AA.elts(), aa.elts(), 12, FFTPrime[0], &RootTable[0][0]);
138 const int nprimes = 10;
139 long r;
140
141
142 for (r = 0; r < nprimes; r++) UseFFTPrime(r);
143
144 vec_long aa[nprimes], AA[nprimes];
145
146 for (r = 0; r < nprimes; r++) {
147 aa[r].SetLength(4096);
148 AA[r].SetLength(4096);
149
150 for (i = 0; i < 4096; i++)
151 aa[r][i] = RandomBnd(FFTPrime[r]);
152
153
154 FFTFwd(AA[r].elts(), aa[r].elts(), 12, r);
155 }
142156
143157 iter = 1;
144158
145159 do {
146160 t = GetTime();
147161 for (i = 0; i < iter; i++) {
148 for (j = 0; j < 10; j++) FFT(AA.elts(), aa.elts(), 12, FFTPrime[0], &RootTable[0][0]);
162 for (r = 0; r < nprimes; r++) FFTFwd(AA[r].elts(), aa[r].elts(), 12, r);
149163 }
150164 t = GetTime() - t;
151165 iter = 2*iter;
162176 for (w = 0; w < 5; w++) {
163177 t = GetTime();
164178 for (i = 0; i < iter; i++) {
165 for (j = 0; j < 10; j++) FFT(AA.elts(), aa.elts(), 12, FFTPrime[0], &RootTable[0][0]);
179 for (r = 0; r < nprimes; r++) FFTFwd(AA[r].elts(), aa[r].elts(), 12, r);
166180 }
167181 t = GetTime() - t;
168182 tvec[w] = t;
216216 #endif
217217
218218
219 #ifdef NTL_FFT_BIGTAB
220 cout << "NTL_FFT_BIGTAB\n";
221 #endif
222
223 #ifdef NTL_FFT_LAZYMUL
224 cout << "NTL_FFT_LAZYMUL\n";
225 #endif
226
227
228
229
219230
220231 #ifdef NTL_TBL_REM
221232 cerr << "NTL_TBL_REM\n";
275275 negate(z.x, z.x);
276276 }
277277
278 void NegatePrec(RR& x, const RR& a, const RR& b, long p)
278 void NegatePrec(RR& x, const RR& a, long p)
279279 {
280280 if (p < 1 || NTL_OVERFLOW(p, 1, 0))
281281 Error("NegatePrec: bad precsion");
292292 abs(z.x, z.x);
293293 }
294294
295 void AbsPrec(RR& x, const RR& a, const RR& b, long p)
295 void AbsPrec(RR& x, const RR& a, long p)
296296 {
297297 if (p < 1 || NTL_OVERFLOW(p, 1, 0))
298298 Error("AbsPrec: bad precsion");
334334 xcopy(z, t);
335335 }
336336
337 void SqrPrec(RR& x, const RR& a, const RR& b, long p)
337 void SqrPrec(RR& x, const RR& a, long p)
338338 {
339339 if (p < 1 || NTL_OVERFLOW(p, 1, 0))
340340 Error("SqrPrec: bad precsion");
478478 }
479479 }
480480
481 void TruncPrec(RR& x, const RR& a, const RR& b, long p)
481 void TruncPrec(RR& x, const RR& a, long p)
482482 {
483483 if (p < 1 || NTL_OVERFLOW(p, 1, 0))
484484 Error("TruncPrec: bad precsion");
504504 }
505505 }
506506
507 void FloorPrec(RR& x, const RR& a, const RR& b, long p)
507 void FloorPrec(RR& x, const RR& a, long p)
508508 {
509509 if (p < 1 || NTL_OVERFLOW(p, 1, 0))
510510 Error("FloorPrec: bad precsion");
530530 }
531531 }
532532
533 void CeilPrec(RR& x, const RR& a, const RR& b, long p)
533 void CeilPrec(RR& x, const RR& a, long p)
534534 {
535535 if (p < 1 || NTL_OVERFLOW(p, 1, 0))
536536 Error("CeilPrec: bad precsion");
569569 xcopy(z, t);
570570 }
571571
572 void RoundPrec(RR& x, const RR& a, const RR& b, long p)
572 void RoundPrec(RR& x, const RR& a, long p)
573573 {
574574 if (p < 1 || NTL_OVERFLOW(p, 1, 0))
575575 Error("RoundPrec: bad precsion");
766766 void conv(long& z, const RR& a)
767767 {
768768 ZZ t;
769 conv(t, a);
770 conv(z, t);
769 if (a.e >= NTL_BITS_PER_LONG)
770 z = 0;
771 else {
772 conv(t, a);
773 conv(z, t);
774 }
771775 }
772776
773777 void conv(double& z, const RR& aa)
781785 conv(x, a.x);
782786 z = _ntl_ldexp(x, a.e);
783787 }
788
789
784790
785791
786792 void add(RR& z, const RR& a, double b)
00
11 for i in $*
22 do
3 rm -f $i
4 rm -f $i.exe
5 rm -f .libs/$i
6 rm -f .libs/$i.exe
3 rm -f "$i"
4 rm -f "$i.exe"
5 rm -f ".libs/$i"
6 rm -f ".libs/$i.exe"
7 rm -rf "$i.dSYM"
78 done
89
910 exit 0
55 echo "running CanZassTest"
66 ./CanZassTest < CanZassTestIn > XXX
77 sh RemoveProg CanZassTest
8 if diff XXX CanZassTestOut
8 if diff -b XXX CanZassTestOut
99 then
1010 echo "CanZassTest OK"
1111 else
1919 echo "running BerlekampTest"
2020 ./BerlekampTest < BerlekampTestIn > XXX
2121 sh RemoveProg BerlekampTest
22 if diff XXX BerlekampTestOut
22 if diff -b XXX BerlekampTestOut
2323 then
2424 echo "BerlekampTest OK"
2525 else
3434 echo "running ZZXFacTest"
3535 ./ZZXFacTest < ZZXFacTestIn > XXX
3636 sh RemoveProg ZZXFacTest
37 if diff XXX ZZXFacTestOut
37 if diff -b XXX ZZXFacTestOut
3838 then
3939 echo "ZZXFacTest OK"
4040 else
7373 echo "running MatrixTest"
7474 ./MatrixTest < MatrixTestIn > XXX
7575 sh RemoveProg MatrixTest
76 if diff XXX MatrixTestOut
76 if diff -b XXX MatrixTestOut
7777 then
7878 echo "MatrixTest OK"
7979 else
8787 echo "running CharPolyTest"
8888 ./CharPolyTest < CharPolyTestIn > XXX
8989 sh RemoveProg CharPolyTest
90 if diff XXX CharPolyTestOut
90 if diff -b XXX CharPolyTestOut
9191 then
9292 echo "CharPolyTest OK"
9393 else
110110 echo "running RRTest"
111111 ./RRTest < RRTestIn > XXX
112112 sh RemoveProg RRTest
113 if diff XXX RRTestOut
113 if diff -b XXX RRTestOut
114114 then
115115 echo "RRTest OK"
116116 else
124124 echo "running QuadTest"
125125 ./QuadTest < QuadTestIn > XXX
126126 sh RemoveProg QuadTest
127 if diff XXX QuadTestOut
127 if diff -b XXX QuadTestOut
128128 then
129129 echo "QuadTest OK"
130130 else
139139 echo "running LLLTest"
140140 ./LLLTest < LLLTestIn > XXX
141141 sh RemoveProg LLLTest
142 if diff XXX LLLTestOut
142 if diff -b XXX LLLTestOut
143143 then
144144 echo "LLLTest OK"
145145 else
0 1:0:1
0 2:0:0
0 WinNTL-5_5_2
0 WinNTL-6_0_0
4848 cp tools.c small/src
4949 cp vec_ZZ.c small/src
5050 cp vec_ZZ_p.c small/src
51 cp vec_long.c small/src
5251 cp GF2.c small/src
5352 cp WordVector.c small/src
5453 cp vec_GF2.c small/src
00 # This is a perl script, invoked from a shell
11
2 # use warnings; # this doesn't work on older versions of perl
2 use warnings; # this doesn't work on older versions of perl
33
44
55 sub GenConfigHeader {
8888 'NTL_GF2X_ALTCODE' => 0,
8989 'NTL_GF2X_ALTCODE1' => 0,
9090 'NTL_GF2X_NOINLINE' => 0,
91 'NTL_FFT_BIGTAB' => 0,
92 'NTL_FFT_LAZYMUL' => 0,
9193
9294 'WIZARD_HACK' => '#define NTL_WIZARD_HACK',
9395
103105
104106
105107
106 # set AVOID_BRANCHING and SPMM flags...try all pairs
108 # set AVOID_BRANCHING, SPMM, and FFT flags...try all combinations
107109
108110
109111 $time = "999999999999999";
110112 $aflag = "default";
111113 $bflag = "default";
114 $cflag = "default";
115 $dflag = "default";
116
112117
113118 foreach $aflag1 ("default", "NTL_AVOID_BRANCHING") {
114119 foreach $bflag1 ("default", "NTL_SPMM_UL", "NTL_SPMM_ULL", "NTL_SPMM_ASM") {
120 foreach $cflag1 ("default", "NTL_FFT_BIGTAB") {
121 foreach $dflag1 ("default", "NTL_FFT_LAZYMUL") {
122
123
124 $Config{$aflag1} = 1;
125 $Config{$bflag1} = 1;
126 $Config{$cflag1} = 1;
127 $Config{$dflag1} = 1;
128
129
130 if ($Config{"NTL_FFT_LAZYMUL"}) {
131
132 if ($Config{"NTL_FFT_BIGTAB"} == 0 ||
133 ($Config{"NTL_SPMM_ULL"} == 0 && $Config{"NTL_SPMM_ASM"} == 0)) {
134
135 $Config{$aflag1} = 0;
136 $Config{$bflag1} = 0;
137 $Config{$cflag1} = 0;
138 $Config{$dflag1} = 0;
139
140 print "skip: $aflag1 $bflag1 $cflag1 $dflag1\n";
141 next;
142 }
143
144 }
145
146 print "run: $aflag1 $bflag1 $cflag1 $dflag1\n";
147 GenConfigHeader();
148 $time1 = RunProg("Poly1TimeTest");
149
150 if ($time1 < $time) {
151 $aflag = $aflag1;
152 $bflag = $bflag1;
153 $cflag = $cflag1;
154 $dflag = $dflag1;
155 $time = $time1;
156 }
157
158 $Config{$aflag1} = 0;
159 $Config{$bflag1} = 0;
160 $Config{$cflag1} = 0;
161 $Config{$dflag1} = 0;
162 unlink("FFT.o");
163 unlink("ZZ_pX.o");
164 }
165 }
166 }
167 }
168
169 $Config{$aflag} = 1;
170 $Config{$bflag} = 1;
171 $Config{$cflag} = 1;
172 $Config{$dflag} = 1;
173 unlink("lip.o"); # AVOID_BRANCHING affects this too
174 unlink("ZZ_pX.o"); # FFT_BIGTABS and FFT_LAZYMUL affect this
175 unlink("lzz_pX.o"); # FFT_BIGTABS and FFT_LAZYMUL affect this
176
177
178 # set the flags GF2X_NOINLINE and GF2X_ALTCODE...try all pairs
179
180 $time = "999999999999999";
181 $aflag = "default";
182 $bflag = "default";
183
184 foreach $aflag1 ("default", "NTL_GF2X_NOINLINE") {
185 foreach $bflag1 ("default", "NTL_GF2X_ALTCODE", "NTL_GF2X_ALTCODE1") {
115186
116187 $Config{$aflag1} = 1;
117188 $Config{$bflag1} = 1;
118189 GenConfigHeader();
119 $time1 = RunProg("Poly1TimeTest");
190 $time1 = RunProg("GF2XTimeTest");
120191
121192 if ($time1 < $time) {
122193 $aflag = $aflag1;
126197
127198 $Config{$aflag1} = 0;
128199 $Config{$bflag1} = 0;
129 unlink("FFT.o");
130 }
131 }
132
133 $Config{$aflag} = 1;
134 $Config{$bflag} = 1;
135 unlink("lip.o"); # AVOID_BRANCHING affects this too
136
137
138 # set the flags GF2X_NOINLINE and GF2X_ALTCODE...try all pairs
139
140 $time = "999999999999999";
141 $aflag = "default";
142 $bflag = "default";
143
144 foreach $aflag1 ("default", "NTL_GF2X_NOINLINE") {
145 foreach $bflag1 ("default", "NTL_GF2X_ALTCODE", "NTL_GF2X_ALTCODE1") {
146
147 $Config{$aflag1} = 1;
148 $Config{$bflag1} = 1;
149 GenConfigHeader();
150 $time1 = RunProg("GF2XTimeTest");
151
152 if ($time1 < $time) {
153 $aflag = $aflag1;
154 $bflag = $bflag1;
155 $time = $time1;
156 }
157
158 $Config{$aflag1} = 0;
159 $Config{$bflag1} = 0;
160200 unlink("GF2X.o");
161201 }
162202 }
861861 long db = deg(b);
862862
863863 if (da < db) {
864 r = b;
864 r = a;
865865 clear(q);
866866 return;
867867 }
23292329 }
23302330 }
23312331
2332 // vectors
2333
2334 NTL_vector_impl(ZZX,vec_ZZX)
2335
2336 NTL_eq_vector_impl(ZZX,vec_ZZX)
2337
2338 NTL_io_vector_impl(ZZX,vec_ZZX)
2339
2340
23412332
23422333 void CopyReverse(ZZX& x, const ZZX& a, long hi)
23432334
116116 GCD(d, f, t1);
117117
118118 if (deg(d) == 0) {
119 append(u, cons(f, 1));
119 append(u, cons(f, 1L));
120120 return;
121121 }
122122
22
33 #include <NTL/ZZ_pEX.h>
44 #include <NTL/vec_vec_ZZ_p.h>
5 #include <NTL/ZZX.h>
56
67 #include <NTL/new.h>
78
306307 x.rep = a;
307308 x.normalize();
308309 }
310
311
312
313 /* additional legacy conversions for v6 conversion regime */
314
315 void conv(ZZ_pEX& x, const ZZX& a)
316 {
317 long n = a.rep.length();
318 long i;
319
320 x.rep.SetLength(n);
321 for (i = 0; i < n; i++)
322 conv(x.rep[i], a.rep[i]);
323
324 x.normalize();
325 }
326
327
328 /* ------------------------------------- */
309329
310330
311331 void add(ZZ_pEX& x, const ZZ_pEX& a, const ZZ_pEX& b)
19631983 mul(s, s, z);
19641984 mul(t, t, z);
19651985 }
1966
1967 NTL_vector_impl(ZZ_pEX,vec_ZZ_pEX)
1968
1969 NTL_eq_vector_impl(ZZ_pEX,vec_ZZ_pEX)
1970
1971 NTL_io_vector_impl(ZZ_pEX,vec_ZZ_pEX)
19721986
19731987 void IterBuild(ZZ_pE* a, long n)
19741988 {
30803094 break;
30813095 }
30823096 }
3083
3084 rres = res;
3085 }
3097 }
3098 rres = res;
30863099 }
30873100
30883101 void resultant(ZZ_pE& rres, const ZZ_pEX& a, const ZZ_pEX& b)
15291529
15301530 if (deg(f) == 1) {
15311531 factors.SetLength(0);
1532 append(factors, cons(f, 1));
1532 append(factors, cons(f, 1L));
15331533 return;
15341534 }
15351535
14201420
14211421
14221422 static vec_long ModularRepBuf;
1423 static vec_long FFTBuf;
1424
1425
14261423
14271424
14281425 void ToModularRep(vec_long& x, const ZZ_p& a)
14961493
14971494 long n, i, j, m, j1;
14981495 vec_long& t = ModularRepBuf;
1499 vec_long& s = FFTBuf;
15001496 ZZ_p accum;
15011497
15021498
15351531 }
15361532
15371533
1538 s.SetLength(n);
1539 long *sp = s.elts();
1540
15411534 for (i = 0; i < ZZ_pInfo->NumPrimes; i++) {
1542 long *Root = &RootTable[i][0];
15431535 long *yp = &y.tbl[i][0];
1544 FFT(sp, yp, y.k, FFTPrime[i], Root);
1545 for (j = 0; j < n; j++)
1546 yp[j] = sp[j];
1536 FFTFwd(yp, yp, k, i);
15471537 }
15481538 }
15491539
15591549
15601550 long n, i, j, m, j1;
15611551 vec_long& t = ModularRepBuf;
1562 vec_long& s = FFTBuf;
15631552 ZZ_p accum;
15641553
15651554 if (k > ZZ_pInfo->MaxRoot)
16021591 }
16031592
16041593
1605 s.SetLength(n);
1606 long *sp = s.elts();
1607
16081594 for (i = 0; i < ZZ_pInfo->NumPrimes; i++) {
1609 long *Root = &RootInvTable[i][0];
16101595 long *yp = &y.tbl[i][0];
1611 long w = TwoInvTable[i][k];
1612 long q = FFTPrime[i];
1613 double qinv = ((double) 1)/((double) q);
1614 FFT(sp, yp, y.k, q, Root);
1615 for (j = 0; j < n; j++)
1616 yp[j] = MulMod(sp[j], w, q, qinv);
1596 FFTRev(yp, yp, k, i);
1597 FFTMulTwoInv(yp, yp, k, i);
16171598 }
16181599
16191600 }
16301611 long k, n, i, j, l;
16311612
16321613 vec_long& t = ModularRepBuf;
1633 vec_long& s = FFTBuf;;
16341614
16351615 t.SetLength(ZZ_pInfo->NumPrimes);
16361616
16371617 k = y.k;
16381618 n = (1L << k);
16391619
1640 s.SetLength(n);
1641 long *sp = s.elts();
16421620
16431621 for (i = 0; i < ZZ_pInfo->NumPrimes; i++) {
16441622 long *yp = &y.tbl[i][0];
1645 long q = FFTPrime[i];
1646 double qinv = ((double) 1)/((double) q);
1647 long w = TwoInvTable[i][k];
1648 long *Root = &RootInvTable[i][0];
1649
1650 FFT(sp, yp, k, q, Root);
1651
1652 for (j = 0; j < n; j++) yp[j] = MulMod(sp[j], w, q, qinv);
1623 FFTRev(yp, yp, k, i);
1624 FFTMulTwoInv(yp, yp, k, i);
16531625 }
16541626
16551627 hi = min(hi, n-1);
16801652 long k, n, i, j, l;
16811653
16821654 vec_long& t = ModularRepBuf;
1683 vec_long& s = FFTBuf;
16841655
16851656 k = y.k;
16861657 n = (1L << k);
16871658
16881659 t.SetLength(ZZ_pInfo->NumPrimes);
1689 s.SetLength(n);
1690 long *sp = s.elts();
16911660
16921661 for (i = 0; i < ZZ_pInfo->NumPrimes; i++) {
16931662 long *yp = &y.tbl[i][0];
1694 long q = FFTPrime[i];
1695 long *Root = &RootTable[i][0];
1696
1697 FFT(sp, yp, k, q, Root);
1698 for (j = 0; j < n; j++)
1699 yp[j] = sp[j];
1663 FFTFwd(yp, yp, k, i);
17001664 }
17011665
17021666 hi = min(hi, n-1);
17281692
17291693 for (i = 0; i < ZZ_pInfo->NumPrimes; i++) {
17301694 long *zp = &z.tbl[i][0];
1731 long q = FFTPrime[i];
1732 double qinv = ((double) 1)/((double) q);
1733 long w = TwoInvTable[i][k];
1734 long *Root = &RootInvTable[i][0];
1735
1736 FFT(zp, &y.tbl[i][0], k, q, Root);
1737
1738 for (j = 0; j < n; j++) zp[j] = MulMod(zp[j], w, q, qinv);
1695 const long *yp = &y.tbl[i][0];
1696
1697 FFTRev(zp, yp, k, i);
1698 FFTMulTwoInv(zp, zp, k, i);
17391699 }
17401700
17411701 hi = min(hi, n-1);
17711731 long k, n, i, j;
17721732
17731733 vec_long& t = ModularRepBuf;
1774 vec_long& s = FFTBuf;
17751734
17761735 k = y.k;
17771736 n = (1L << k);
17781737
17791738 t.SetLength(ZZ_pInfo->NumPrimes);
1780 s.SetLength(n);
1781 long *sp = s.elts();
17821739
17831740 for (i = 0; i < ZZ_pInfo->NumPrimes; i++) {
17841741 long *yp = &y.tbl[i][0];
1785 long q = FFTPrime[i];
1786 double qinv = ((double) 1)/((double) q);
1787 long w = TwoInvTable[i][k];
1788 long *Root = &RootInvTable[i][0];
1789
1790 FFT(sp, yp, k, q, Root);
1791
1792 for (j = 0; j < n; j++) yp[j] = MulMod(sp[j], w, q, qinv);
1742 FFTRev(yp, yp, k, i);
1743 FFTMulTwoInv(yp, yp, k, i);
17931744 }
17941745
17951746 for (j = lo; j <= hi; j++) {
19831934 long NumPrimes = ZZ_pInfo->NumPrimes;
19841935
19851936 for (i = 0; i < NumPrimes; i++) {
1986 long *Root = &RootTable[i][0];
19871937 long *xp = &x.tbl[i][0];
19881938 long *ap = (m == 0 ? 0 : &a.tbl[i][0]);
19891939 for (j = 0; j < m; j++)
19911941 for (j = m; j < n; j++)
19921942 sp[j] = 0;
19931943
1994 FFT(xp, sp, k, FFTPrime[i], Root);
1944 FFTFwd(xp, sp, k, i);
19951945 }
19961946 }
19971947
893893 res.SetLength(m);
894894 f.rep = res;
895895 }
896
897 NTL_vector_impl(ZZ_pX,vec_ZZ_pX)
898
899 NTL_eq_vector_impl(ZZ_pX,vec_ZZ_pX)
900
901 NTL_io_vector_impl(ZZ_pX,vec_ZZ_pX)
902
903896
904897
905898
16801673 break;
16811674 }
16821675 }
1683
1684 rres = res;
1685 }
1676 }
1677
1678 rres = res;
16861679 }
16871680
16881681
19101910
19111911 if (deg(f) == 1) {
19121912 factors.SetLength(0);
1913 append(factors, cons(f, 1));
1913 append(factors, cons(f, 1L));
19141914 return;
19151915 }
19161916
18051805 #endif
18061806
18071807
1808 long _ntl_zmaxalloc(_ntl_verylong x)
1809 {
1810 if (!x)
1811 return 0;
1812 else
1813 return (x[-1] >> 1) - 1;
1814 }
1815
18081816
18091817 void _ntl_zsetlength(_ntl_verylong *v, long len)
18101818 {
18571865 }
18581866 }
18591867 else {
1860 len++;
1861 len = ((len+(MIN_SETL-1))/MIN_SETL)*MIN_SETL;
1868 len++; /* as above, always allocate one more than requested */
1869 len = ((len+(MIN_SETL-1))/MIN_SETL)*MIN_SETL;
18621870
18631871 /* test len again */
18641872 if (NTL_OVERFLOW(len, NTL_NBITS, 0))
410410 * and NTL_SPMM_ASM.
411411 * This plays a crucial role in the "small prime FFT" used to
412412 * implement polynomial arithmetic, and in other CRT-based methods
413 * (such as linear algebra over ZZ), as well as polynomial andd matrix
413 * (such as linear algebra over ZZ), as well as polynomial and matrix
414414 * arithmetic over zz_p.
415415 */
416416
456456
457457
458458
459 /*
460 * The following two flags provide additional control for how the
461 * FFT modulo single-precision primes is implemented.
462 */
463
464 #if @{NTL_FFT_BIGTAB}
465 #define NTL_FFT_BIGTAB
466
467 /*
468 * Precomputed tables are used to store all the roots of unity
469 * used in an FFT computation for the first NTL_FFT_BIGTAB_LIMIT
470 * FFT primes (the latter is defined in FFT.h). This can
471 * lead to significant time savings but at the const of some space:
472 * in the worst case, the precomputed tables will take of space
473 * log_2(NTL_FFT_BUGTAB_LIMIT) * M, where M is roughly the maxmimum
474 * space occupied by any one polynomial that was involved in an
475 * FFT computation (this could be a polynomial over zz_p, ZZ_p, or ZZ).
476 *
477 * To re-build after changing this flag: rm *.o; make ntl.a
478 */
479
480 #endif
481
482
483 #if @{NTL_FFT_LAZYMUL}
484 #define NTL_FFT_LAZYMUL
485
486 /*
487 * This flag only has an effect when combined with the NTL_FFT_BIGTAB
488 * flag, and either the NTL_SPMM_ULL or NTL_SPMM_ASM flags.
489 * When set, a "lazy multiplication" strategy due to David Harvey:
490 * see his paper "FASTER ARITHMETIC FOR NUMBER-THEORETIC TRANSFORMS".
491 *
492 * To re-build after changing this flag: rm *.o; make ntl.a
493 */
494
495
496 #endif
497
498
499
459500
460501
461502 /* The next five flags NTL_AVOID_BRANCHING, NTL_TBL_REM,
9999 GMP_LIBDIR=$(GMP_PREFIX)/lib
100100 # directory containing libgmp.a if using GMP
101101
102 GMP_OPT_INCDIR=# -I$(GMP_INCDIR) # GMP
103 GMP_OPT_LIBDIR=# -L$(GMP_LIBDIR) # GMP
102 GMP_OPT_INCDIR=# -I$(GMP_INCDIR) # GMPI
103 GMP_OPT_LIBDIR=# -L$(GMP_LIBDIR) # GMPL
104104 GMP_OPT_LIB=# -lgmp # GMP
105105 # uncomment these if using GMP
106106
159159 O07=$(O06) lzz_pX.o lzz_pX1.o lzz_pXCharPoly.o lzz_pXFactoring.o
160160 O08=$(O07) mat_GF2.o mat_GF2E.o mat_RR.o mat_ZZ.o mat_ZZ_p.o
161161 O09=$(O08) mat_ZZ_pE.o mat_lzz_p.o mat_lzz_pE.o mat_poly_ZZ.o
162 O10=$(O09) mat_poly_ZZ_p.o mat_poly_lzz_p.o pair_GF2EX_long.o
163 O11=$(O10) pair_GF2X_long.o pair_ZZX_long.o pair_ZZ_pEX_long.o
164 O12=$(O11) pair_ZZ_pX_long.o pair_lzz_pEX_long.o pair_lzz_pX_long.o
165 O13=$(O12) quad_float.o tools.o vec_GF2.o vec_GF2E.o vec_GF2XVec.o
166 O14=$(O13) vec_RR.o vec_ZZ.o vec_ZZVec.o vec_ZZ_p.o vec_ZZ_pE.o
167 O15=$(O14) vec_double.o vec_long.o vec_lzz_p.o vec_lzz_pE.o vec_quad_float.o
168 O16=$(O15) vec_vec_GF2.o vec_vec_GF2E.o vec_vec_RR.o vec_vec_ZZ.o
169 O17=$(O16) vec_vec_ZZ_p.o vec_vec_ZZ_pE.o vec_vec_long.o vec_vec_lzz_p.o
170 O18=$(O17) vec_vec_lzz_pE.o vec_xdouble.o xdouble.o
171 O19=$(O18) G_LLL_FP.o G_LLL_QP.o G_LLL_XD.o G_LLL_RR.o vec_ulong.o vec_vec_ulong.o
162 O10=$(O09) mat_poly_ZZ_p.o mat_poly_lzz_p.o
163 O11=$(O10)
164 O12=$(O11)
165 O13=$(O12) quad_float.o tools.o vec_GF2.o vec_GF2E.o
166 O14=$(O13) vec_RR.o vec_ZZ.o vec_ZZ_p.o vec_ZZ_pE.o
167 O15=$(O14) vec_lzz_p.o vec_lzz_pE.o
168 O16=$(O15)
169 O17=$(O16)
170 O18=$(O17) xdouble.o
171 O19=$(O18) G_LLL_FP.o G_LLL_QP.o G_LLL_XD.o G_LLL_RR.o
172172
173173 OBJ=$(O19)
174174
184184 S07=$(S06) lzz_pEXFactoring.c lzz_pX.c lzz_pX1.c
185185 S08=$(S07) lzz_pXCharPoly.c lzz_pXFactoring.c mat_GF2.c mat_GF2E.c
186186 S09=$(S08) mat_RR.c mat_ZZ.c mat_ZZ_p.c mat_ZZ_pE.c mat_lzz_p.c mat_lzz_pE.c
187 S10=$(S09) mat_poly_ZZ.c mat_poly_ZZ_p.c mat_poly_lzz_p.c pair_GF2EX_long.c
188 S11=$(S10) pair_GF2X_long.c pair_ZZX_long.c pair_ZZ_pEX_long.c
189 S12=$(S11) pair_ZZ_pX_long.c pair_lzz_pEX_long.c pair_lzz_pX_long.c
190 S13=$(S12) quad_float.c tools.c vec_GF2.c vec_GF2E.c vec_GF2XVec.c vec_RR.c
191 S14=$(S13) vec_ZZ.c vec_ZZVec.c vec_ZZ_p.c vec_ZZ_pE.c vec_double.c
192 S15=$(S14) vec_long.c vec_lzz_p.c vec_lzz_pE.c vec_quad_float.c
193 S16=$(S15) vec_vec_GF2.c vec_vec_GF2E.c vec_vec_RR.c vec_vec_ZZ.c
194 S17=$(S16) vec_vec_ZZ_p.c vec_vec_ZZ_pE.c vec_vec_long.c vec_vec_lzz_p.c
195 S18=$(S17) vec_vec_lzz_pE.c vec_xdouble.c xdouble.c
187 S10=$(S09) mat_poly_ZZ.c mat_poly_ZZ_p.c mat_poly_lzz_p.c
188 S11=$(S10)
189 S12=$(S11)
190 S13=$(S12) quad_float.c tools.c vec_GF2.c vec_GF2E.c vec_RR.c
191 S14=$(S13) vec_ZZ.c vec_ZZ_p.c vec_ZZ_pE.c
192 S15=$(S14) vec_lzz_p.c vec_lzz_pE.c
193 S16=$(S15)
194 S17=$(S16)
195 S18=$(S17) xdouble.c
196196 S19=$(S18) G_LLL_FP.c G_LLL_QP.c G_LLL_XD.c G_LLL_RR.c
197 S20=$(S19) vec_ulong.c vec_vec_ulong.c
198
199 SRC = $(S20)
197
198 SRC = $(S19)
200199
201200 # library source files that are header files
202201
515514 ######################################################################
516515
517516 WO1 = FFT.o GetTime.o ctools.o ZZ.o ZZVec.o ZZ_p.o ZZ_pX.o
518 WO2 = $(WO1) ZZ_pX1.o lip.o tools.o vec_ZZ.o vec_ZZ_p.o vec_long.o
517 WO2 = $(WO1) ZZ_pX1.o lip.o tools.o vec_ZZ.o vec_ZZ_p.o
519518 WO3 = $(WO2) GF2.o WordVector.o vec_GF2.o GF2X.o GF2X1.o
520519
521520 WOBJ = $(WO3)
355355 }
356356
357357
358 long _ntl_gmaxalloc(_ntl_gbigint x)
359 {
360 if (!x)
361 return 0;
362 else
363 return (ALLOC(x) >> 2) - 1;
364 }
365
358366 #define MIN_SETL (4)
359367 /* _ntl_gsetlength allocates a multiple of MIN_SETL digits */
360368
413421 }
414422 }
415423 else {
416 len++;
417 len = ((len+(MIN_SETL-1))/MIN_SETL)*MIN_SETL;
424 len++; /* as above, always allocate one more than explicitly reqested */
425 len = ((len+(MIN_SETL-1))/MIN_SETL)*MIN_SETL;
418426
419427 /* test len again */
420428 if (NTL_OVERFLOW(len, NTL_ZZ_NBITS, 0))
41884196 c = (struct crt_body *) NTL_MALLOC(1, sizeof(struct crt_body), 0);
41894197 if (!c) ghalt("out of memory");
41904198
4191 if (n >= 600) {
4199 if (n >= 600) {
41924200 struct crt_body_gmp1 *C = &c->U.G1;
41934201 long *q;
41944202 long i, j;
42754283 for (i = (1L << (levels-1)) - 2; i >= 0; i--)
42764284 _ntl_gmul(prod_vec[2*i+1], prod_vec[2*i+2], &prod_vec[i]);
42774285
4278
4286 /*** new asymptotically fast code to compute inv_vec ***/
4287
4288 _ntl_gone(&rem_vec[0]);
4289 for (i = 0; i < (1L << (levels-1)) - 1; i++) {
4290 _ntl_gmod(rem_vec[i], prod_vec[2*i+1], &temps[0]);
4291 _ntl_gmul(temps[0], prod_vec[2*i+2], &temps[1]);
4292 _ntl_gmod(temps[1], prod_vec[2*i+1], &rem_vec[2*i+1]);
4293
4294 _ntl_gmod(rem_vec[i], prod_vec[2*i+2], &temps[0]);
4295 _ntl_gmul(temps[0], prod_vec[2*i+1], &temps[1]);
4296 _ntl_gmod(temps[1], prod_vec[2*i+2], &rem_vec[2*i+2]);
4297 }
4298
4299 for (i = (1L << (levels-1)) - 1; i < vec_len; i++) {
4300 for (j = index_vec[i]; j < index_vec[i+1]; j++) {
4301 long tt, tt1, tt2;
4302 _ntl_gsdiv(prod_vec[i], q[j], &temps[0]);
4303 tt = _ntl_gsmod(temps[0], q[j]);
4304 tt1 = _ntl_gsmod(rem_vec[i], q[j]);
4305 SP_MUL_MOD(tt2, tt, tt1, q[j]);
4306 inv_vec[j] = sp_inv_mod(tt2, q[j]);
4307 }
4308 }
4309
4310
4311
4312 #if 0
42794313 /* the following is asymptotically the bottleneck...but it
42804314 * it probably doesn't matter. */
42814315
4316 fprintf(stderr, "checking in lip\n");
42824317 for (i = 0; i < n; i++) {
42834318 long tt;
42844319 _ntl_gsdiv(prod_vec[0], q[i], &temps[0]);
42854320 tt = mpn_mod_1(DATA(temps[0]), SIZE(temps[0]), q[i]);
4286 inv_vec[i] = sp_inv_mod(tt, q[i]);
4287 }
4321 if (inv_vec[i] != sp_inv_mod(tt, q[i]))
4322 fprintf(stderr, "oops in lip\n");
4323
4324 /* inv_vec[i] = sp_inv_mod(tt, q[i]); */
4325
4326 }
4327 #endif
42884328
42894329 c->strategy = 2;
42904330 C->n = n;
33
44 #include <NTL/lzz_pEX.h>
55 #include <NTL/vec_vec_lzz_p.h>
6 #include <NTL/ZZX.h>
67
78 #include <NTL/new.h>
89
308309 x.rep = a;
309310 x.normalize();
310311 }
312
313
314
315
316 /* additional legacy conversions for v6 conversion regime */
317
318 void conv(zz_pEX& x, const ZZX& a)
319 {
320 long n = a.rep.length();
321 long i;
322
323 x.rep.SetLength(n);
324 for (i = 0; i < n; i++)
325 conv(x.rep[i], a.rep[i]);
326
327 x.normalize();
328 }
329
330
331 /* ------------------------------------- */
332
311333
312334
313335 void add(zz_pEX& x, const zz_pEX& a, const zz_pEX& b)
19661988 mul(t, t, z);
19671989 }
19681990
1969 NTL_vector_impl(zz_pEX,vec_zz_pEX)
1970
1971 NTL_eq_vector_impl(zz_pEX,vec_zz_pEX)
1972
1973 NTL_io_vector_impl(zz_pEX,vec_zz_pEX)
19741991
19751992 void IterBuild(zz_pE* a, long n)
19761993 {
30833100 break;
30843101 }
30853102 }
3086
3087 rres = res;
3088 }
3103 }
3104 rres = res;
30893105 }
30903106
30913107 void resultant(zz_pE& rres, const zz_pEX& a, const zz_pEX& b)
15321532
15331533 if (deg(f) == 1) {
15341534 factors.SetLength(0);
1535 append(factors, cons(f, 1));
1535 append(factors, cons(f, 1L));
15361536 return;
15371537 }
15381538
142142
143143
144144
145 zz_p coeff(const zz_pX& a, long i)
145 const zz_p coeff(const zz_pX& a, long i)
146146 {
147147 if (i < 0 || i > deg(a))
148148 return zz_p::zero();
151151 }
152152
153153
154 zz_p LeadCoeff(const zz_pX& a)
154 const zz_p LeadCoeff(const zz_pX& a)
155155 {
156156 if (IsZero(a))
157157 return zz_p::zero();
159159 return a.rep[deg(a)];
160160 }
161161
162 zz_p ConstTerm(const zz_pX& a)
162 const zz_p ConstTerm(const zz_pX& a)
163163 {
164164 if (IsZero(a))
165165 return zz_p::zero();
13821382 return;
13831383 }
13841384
1385 if (NumPrimes != zz_pInfo->NumPrimes)
1385 if (MaxK == -1)
1386 NumPrimes = zz_pInfo->NumPrimes;
1387 else if (NumPrimes != zz_pInfo->NumPrimes)
13861388 Error("fftRep: inconsistent use");
13871389
13881390 long i, n;
14041406 fftRep::fftRep(const fftRep& R)
14051407 {
14061408 k = MaxK = R.k;
1409 NumPrimes = 0;
1410
1411 if (k < 0) return;
1412
14071413 NumPrimes = R.NumPrimes;
1408
1409 if (k < 0) return;
14101414
14111415 long i, j, n;
14121416
14251429 {
14261430 if (this == &R) return *this;
14271431
1428 if (NumPrimes != R.NumPrimes)
1432 if (MaxK >= 0 && R.MaxK >= 0 && NumPrimes != R.NumPrimes)
14291433 Error("fftRep: inconsistent use");
14301434
14311435 if (R.k < 0) {
14321436 k = -1;
14331437 return *this;
14341438 }
1439
1440 NumPrimes = R.NumPrimes;
14351441
14361442 if (R.k > MaxK) {
14371443 long i, n;
14761482 free(tbl[i]);
14771483 }
14781484
1479
1480
1481 static vec_long FFTBuf;
14821485
14831486
14841487
15481551 // if deg(x) >= 2^k, then x is first reduced modulo X^n-1.
15491552 {
15501553 long n, i, j, m, j1;
1551 vec_long& s = FFTBuf;;
15521554 zz_p accum;
15531555 long NumPrimes = zz_pInfo->NumPrimes;
15541556
16051607 }
16061608
16071609
1608 s.SetLength(n);
1609 long *sp = s.elts();
1610
16111610 if (index >= 0) {
1612 long *Root = &RootTable[index][0];
16131611 long *yp = &y.tbl[0][0];
1614 FFT(sp, yp, y.k, FFTPrime[index], Root);
1615 for (j = 0; j < n; j++)
1616 yp[j] = sp[j];
1612 FFTFwd(yp, yp, k, index);
16171613 }
16181614 else {
16191615 for (i = 0; i < zz_pInfo->NumPrimes; i++) {
1620 long *Root = &RootTable[i][0];
16211616 long *yp = &y.tbl[i][0];
1622 FFT(sp, yp, y.k, FFTPrime[i], Root);
1623 for (j = 0; j < n; j++)
1624 yp[j] = sp[j];
1617 FFTFwd(yp, yp, k, i);
16251618 }
16261619 }
16271620 }
16351628
16361629 {
16371630 long n, i, j, m, j1;
1638 vec_long& s = FFTBuf;
16391631 zz_p accum;
16401632 long NumPrimes = zz_pInfo->NumPrimes;
16411633
16951687 }
16961688
16971689
1698 s.SetLength(n);
1699 long *sp = s.elts();
1700
17011690 if (index >= 0) {
1702 long *Root = &RootInvTable[index][0];
17031691 long *yp = &y.tbl[0][0];
1704 long w = TwoInvTable[index][k];
1705 long q = FFTPrime[index];
1706 double qinv = ((double) 1)/((double) q);
1707 FFT(sp, yp, y.k, q, Root);
1708 for (j = 0; j < n; j++)
1709 yp[j] = MulMod(sp[j], w, q, qinv);
1692 FFTRev(yp, yp, k, index);
1693 FFTMulTwoInv(yp, yp, k, index);
17101694 }
17111695 else {
17121696 for (i = 0; i < zz_pInfo->NumPrimes; i++) {
1713 long *Root = &RootInvTable[i][0];
17141697 long *yp = &y.tbl[i][0];
1715 long w = TwoInvTable[i][k];
1716 long q = FFTPrime[i];
1717 double qinv = ((double) 1)/((double) q);
1718 FFT(sp, yp, y.k, q, Root);
1719 for (j = 0; j < n; j++)
1720 yp[j] = MulMod(sp[j], w, q, qinv);
1698 FFTRev(yp, yp, k, i);
1699 FFTMulTwoInv(yp, yp, k, i);
17211700 }
17221701 }
17231702 }
17331712 long NumPrimes = zz_pInfo->NumPrimes;
17341713
17351714 long t[4];
1736 vec_long& s = FFTBuf;
17371715
17381716 k = y.k;
17391717 n = (1L << k);
17401718
1741 s.SetLength(n);
1742 long *sp = s.elts();
1743
17441719 long index = zz_pInfo->index;
17451720
17461721 if (index >= 0) {
17471722 long *yp = &y.tbl[0][0];
1748 long q = FFTPrime[index];
1749 double qinv = FFTPrimeInv[index];
1750 long w = TwoInvTable[index][k];
1751 long *Root = &RootInvTable[index][0];
1752
1753 FFT(sp, yp, k, q, Root);
1754
1755 for (j = 0; j < n; j++) yp[j] = MulMod(sp[j], w, q, qinv);
1723 FFTRev(yp, yp, k, index);
1724 FFTMulTwoInv(yp, yp, k, index);
17561725 }
17571726 else {
17581727 for (i = 0; i < NumPrimes; i++) {
17591728 long *yp = &y.tbl[i][0];
1760 long q = FFTPrime[i];
1761 double qinv = FFTPrimeInv[i];
1762 long w = TwoInvTable[i][k];
1763 long *Root = &RootInvTable[i][0];
1764
1765 FFT(sp, yp, k, q, Root);
1766
1767 for (j = 0; j < n; j++) yp[j] = MulMod(sp[j], w, q, qinv);
1729 FFTRev(yp, yp, k, i);
1730 FFTMulTwoInv(yp, yp, k, i);
17681731 }
17691732 }
17701733
18031766 long NumPrimes = zz_pInfo->NumPrimes;
18041767
18051768 long t[4];
1806 vec_long& s = FFTBuf;
18071769
18081770 k = y.k;
18091771 n = (1L << k);
18101772
1811 s.SetLength(n);
1812 long *sp = s.elts();
1813
18141773 long index = zz_pInfo->index;
18151774
18161775 if (index >= 0) {
18171776 long *yp = &y.tbl[0][0];
1818 long q = FFTPrime[index];
1819 long *Root = &RootTable[index][0];
1820
1821 FFT(sp, yp, k, q, Root);
1822 for (j = 0; j < n; j++)
1823 yp[j] = sp[j];
1777 FFTFwd(yp, yp, k, index);
18241778 }
18251779 else {
18261780 for (i = 0; i < NumPrimes; i++) {
18271781 long *yp = &y.tbl[i][0];
1828 long q = FFTPrime[i];
1829 long *Root = &RootTable[i][0];
1830
1831 FFT(sp, yp, k, q, Root);
1832 for (j = 0; j < n; j++)
1833 yp[j] = sp[j];
1782 FFTFwd(yp, yp, k, i);
18341783 }
18351784 }
18361785
18711820
18721821 if (index >= 0) {
18731822 long *zp = &z.tbl[0][0];
1874 long q = FFTPrime[index];
1875 double qinv = FFTPrimeInv[index];
1876 long w = TwoInvTable[index][k];
1877 long *Root = &RootInvTable[index][0];
1878
1879 FFT(zp, &y.tbl[0][0], k, q, Root);
1880
1881 for (j = 0; j < n; j++) zp[j] = MulMod(zp[j], w, q, qinv);
1823 const long *yp = &y.tbl[0][0];
1824 FFTRev(zp, yp, k, index);
1825 FFTMulTwoInv(zp, zp, k, index);
18821826 }
18831827 else {
18841828 for (i = 0; i < NumPrimes; i++) {
18851829 long *zp = &z.tbl[i][0];
1886 long q = FFTPrime[i];
1887 double qinv = FFTPrimeInv[i];
1888 long w = TwoInvTable[i][k];
1889 long *Root = &RootInvTable[i][0];
1890
1891 FFT(zp, &y.tbl[i][0], k, q, Root);
1892
1893 for (j = 0; j < n; j++) zp[j] = MulMod(zp[j], w, q, qinv);
1830 const long *yp = &y.tbl[i][0];
1831 FFTRev(zp, yp, k, i);
1832 FFTMulTwoInv(zp, zp, k, i);
18941833 }
18951834 }
18961835
19341873 long NumPrimes = zz_pInfo->NumPrimes;
19351874
19361875 long t[4];
1937 vec_long& s = FFTBuf;
19381876
19391877 k = y.k;
19401878 n = (1L << k);
1941
1942 s.SetLength(n);
1943 long *sp = s.elts();
19441879
19451880 long index = zz_pInfo->index;
19461881 if (index >= 0) {
19471882 long *yp = &y.tbl[0][0];
1948 long q = FFTPrime[index];
1949 double qinv = FFTPrimeInv[index];
1950 long w = TwoInvTable[index][k];
1951 long *Root = &RootInvTable[index][0];
1952
1953 FFT(sp, yp, k, q, Root);
1954
1955 for (j = 0; j < n; j++) yp[j] = MulMod(sp[j], w, q, qinv);
1883 FFTRev(yp, yp, k, index);
1884 FFTMulTwoInv(yp, yp, k, index);
19561885
19571886 for (j = lo; j <= hi; j++) {
19581887 if (j >= n)
19651894 else {
19661895 for (i = 0; i < NumPrimes; i++) {
19671896 long *yp = &y.tbl[i][0];
1968 long q = FFTPrime[i];
1969 double qinv = FFTPrimeInv[i];
1970 long w = TwoInvTable[i][k];
1971 long *Root = &RootInvTable[i][0];
1972
1973 FFT(sp, yp, k, q, Root);
1974
1975 for (j = 0; j < n; j++) yp[j] = MulMod(sp[j], w, q, qinv);
1897 FFTRev(yp, yp, k, i);
1898 FFTMulTwoInv(yp, yp, k, i);
19761899 }
19771900
19781901 for (j = lo; j <= hi; j++) {
887887 res.SetLength(m);
888888 f.rep = res;
889889 }
890
891 NTL_vector_impl(zz_pX,vec_zz_pX)
892
893 NTL_eq_vector_impl(zz_pX,vec_zz_pX)
894
895 NTL_io_vector_impl(zz_pX,vec_zz_pX)
896
897890
898891
899892
16831676 break;
16841677 }
16851678 }
1686
1687 rres = res;
1688 }
1679 }
1680
1681 rres = res;
16891682 }
16901683
16911684
19191919
19201920 if (deg(f) == 1) {
19211921 factors.SetLength(0);
1922 append(factors, cons(f, 1));
1922 append(factors, cons(f, 1L));
19231923 return;
19241924 }
19251925
9999 GMP_LIBDIR=$(GMP_PREFIX)/lib
100100 # directory containing libgmp.a if using GMP
101101
102 GMP_OPT_INCDIR=# -I$(GMP_INCDIR) # GMP
103 GMP_OPT_LIBDIR=# -L$(GMP_LIBDIR) # GMP
102 GMP_OPT_INCDIR=# -I$(GMP_INCDIR) # GMPI
103 GMP_OPT_LIBDIR=# -L$(GMP_LIBDIR) # GMPL
104104 GMP_OPT_LIB=# -lgmp # GMP
105105 # uncomment these if using GMP
106106
159159 O07=$(O06) lzz_pX.o lzz_pX1.o lzz_pXCharPoly.o lzz_pXFactoring.o
160160 O08=$(O07) mat_GF2.o mat_GF2E.o mat_RR.o mat_ZZ.o mat_ZZ_p.o
161161 O09=$(O08) mat_ZZ_pE.o mat_lzz_p.o mat_lzz_pE.o mat_poly_ZZ.o
162 O10=$(O09) mat_poly_ZZ_p.o mat_poly_lzz_p.o pair_GF2EX_long.o
163 O11=$(O10) pair_GF2X_long.o pair_ZZX_long.o pair_ZZ_pEX_long.o
164 O12=$(O11) pair_ZZ_pX_long.o pair_lzz_pEX_long.o pair_lzz_pX_long.o
165 O13=$(O12) quad_float.o tools.o vec_GF2.o vec_GF2E.o vec_GF2XVec.o
166 O14=$(O13) vec_RR.o vec_ZZ.o vec_ZZVec.o vec_ZZ_p.o vec_ZZ_pE.o
167 O15=$(O14) vec_double.o vec_long.o vec_lzz_p.o vec_lzz_pE.o vec_quad_float.o
168 O16=$(O15) vec_vec_GF2.o vec_vec_GF2E.o vec_vec_RR.o vec_vec_ZZ.o
169 O17=$(O16) vec_vec_ZZ_p.o vec_vec_ZZ_pE.o vec_vec_long.o vec_vec_lzz_p.o
170 O18=$(O17) vec_vec_lzz_pE.o vec_xdouble.o xdouble.o
171 O19=$(O18) G_LLL_FP.o G_LLL_QP.o G_LLL_XD.o G_LLL_RR.o vec_ulong.o vec_vec_ulong.o
162 O10=$(O09) mat_poly_ZZ_p.o mat_poly_lzz_p.o
163 O11=$(O10)
164 O12=$(O11)
165 O13=$(O12) quad_float.o tools.o vec_GF2.o vec_GF2E.o
166 O14=$(O13) vec_RR.o vec_ZZ.o vec_ZZ_p.o vec_ZZ_pE.o
167 O15=$(O14) vec_lzz_p.o vec_lzz_pE.o
168 O16=$(O15)
169 O17=$(O16)
170 O18=$(O17) xdouble.o
171 O19=$(O18) G_LLL_FP.o G_LLL_QP.o G_LLL_XD.o G_LLL_RR.o
172172
173173 OBJ=$(O19)
174174
184184 S07=$(S06) lzz_pEXFactoring.c lzz_pX.c lzz_pX1.c
185185 S08=$(S07) lzz_pXCharPoly.c lzz_pXFactoring.c mat_GF2.c mat_GF2E.c
186186 S09=$(S08) mat_RR.c mat_ZZ.c mat_ZZ_p.c mat_ZZ_pE.c mat_lzz_p.c mat_lzz_pE.c
187 S10=$(S09) mat_poly_ZZ.c mat_poly_ZZ_p.c mat_poly_lzz_p.c pair_GF2EX_long.c
188 S11=$(S10) pair_GF2X_long.c pair_ZZX_long.c pair_ZZ_pEX_long.c
189 S12=$(S11) pair_ZZ_pX_long.c pair_lzz_pEX_long.c pair_lzz_pX_long.c
190 S13=$(S12) quad_float.c tools.c vec_GF2.c vec_GF2E.c vec_GF2XVec.c vec_RR.c
191 S14=$(S13) vec_ZZ.c vec_ZZVec.c vec_ZZ_p.c vec_ZZ_pE.c vec_double.c
192 S15=$(S14) vec_long.c vec_lzz_p.c vec_lzz_pE.c vec_quad_float.c
193 S16=$(S15) vec_vec_GF2.c vec_vec_GF2E.c vec_vec_RR.c vec_vec_ZZ.c
194 S17=$(S16) vec_vec_ZZ_p.c vec_vec_ZZ_pE.c vec_vec_long.c vec_vec_lzz_p.c
195 S18=$(S17) vec_vec_lzz_pE.c vec_xdouble.c xdouble.c
187 S10=$(S09) mat_poly_ZZ.c mat_poly_ZZ_p.c mat_poly_lzz_p.c
188 S11=$(S10)
189 S12=$(S11)
190 S13=$(S12) quad_float.c tools.c vec_GF2.c vec_GF2E.c vec_RR.c
191 S14=$(S13) vec_ZZ.c vec_ZZ_p.c vec_ZZ_pE.c
192 S15=$(S14) vec_lzz_p.c vec_lzz_pE.c
193 S16=$(S15)
194 S17=$(S16)
195 S18=$(S17) xdouble.c
196196 S19=$(S18) G_LLL_FP.c G_LLL_QP.c G_LLL_XD.c G_LLL_RR.c
197 S20=$(S19) vec_ulong.c vec_vec_ulong.c
198
199 SRC = $(S20)
197
198 SRC = $(S19)
200199
201200 # library source files that are header files
202201
515514 ######################################################################
516515
517516 WO1 = FFT.o GetTime.o ctools.o ZZ.o ZZVec.o ZZ_p.o ZZ_pX.o
518 WO2 = $(WO1) ZZ_pX1.o lip.o tools.o vec_ZZ.o vec_ZZ_p.o vec_long.o
517 WO2 = $(WO1) ZZ_pX1.o lip.o tools.o vec_ZZ.o vec_ZZ_p.o
519518 WO3 = $(WO2) GF2.o WordVector.o vec_GF2.o GF2X.o GF2X1.o
520519
521520 WOBJ = $(WO3)
55 #include <NTL/new.h>
66
77 NTL_START_IMPL
8
9
10 mat_GF2::mat_GF2(const mat_GF2& a)
11 {
12 _mat_GF2__numcols = 0;
13 SetDims(a.NumRows(), a.NumCols());
14 _mat_GF2__rep = a._mat_GF2__rep;
15 }
16
17 mat_GF2& mat_GF2::operator=(const mat_GF2& a)
18 {
19 SetDims(a.NumRows(), a.NumCols());
20 _mat_GF2__rep = a._mat_GF2__rep;
21 return *this;
22 }
23
24
25 mat_GF2::mat_GF2(INIT_SIZE_TYPE, long n, long m)
26 {
27 _mat_GF2__numcols = 0;
28 SetDims(n, m);
29 }
30
31 void mat_GF2::kill()
32 {
33 _mat_GF2__numcols = 0;
34 _mat_GF2__rep.kill();
35 }
36
37 void mat_GF2::SetDims(long n, long m)
38 {
39 if (n < 0 || m < 0)
40 Error("SetDims: bad args");
41
42 if (m != _mat_GF2__numcols) {
43 _mat_GF2__rep.kill();
44 _mat_GF2__numcols = m;
45 }
46
47 long oldmax = _mat_GF2__rep.MaxLength();
48 long i;
49 _mat_GF2__rep.SetLength(n);
50
51 for (i = oldmax; i < n; i++)
52 _mat_GF2__rep[i].FixLength(m);
53 }
54
55
56 void conv(mat_GF2& x, const vec_vec_GF2& a)
57 {
58 long n = a.length();
59
60 if (n == 0) {
61 x.SetDims(0, 0);
62 return;
63 }
64
65 long m = a[0].length();
66 long i;
67
68 for (i = 1; i < n; i++)
69 if (a[i].length() != m)
70 Error("nonrectangular matrix");
71
72 x.SetDims(n, m);
73 for (i = 0; i < n; i++)
74 x[i] = a[i];
75 }
76
77 void swap(mat_GF2& X, mat_GF2& Y)
78 {
79 swap(X._mat_GF2__numcols, Y._mat_GF2__numcols);
80 swap(X._mat_GF2__rep, Y._mat_GF2__rep);
81 }
82
83
84
85 long operator==(const mat_GF2& a, const mat_GF2& b)
86 {
87 if (a.NumCols() != b.NumCols())
88 return 0;
89
90 if (a.NumRows() != b.NumRows())
91 return 0;
92
93 long n = a.NumRows();
94 long i;
95
96 for (i = 0; i < n; i++)
97 if (a[i] != b[i])
98 return 0;
99
100 return 1;
101 }
102
103
104 long operator!=(const mat_GF2& a, const mat_GF2& b)
105 {
106 return !(a == b);
107 }
108
109 istream& operator>>(istream& s, mat_GF2& x)
110 {
111 vec_vec_GF2 buf;
112 s >> buf;
113 conv(x, buf);
114 return s;
115 }
116
117 ostream& operator<<(ostream& s, const mat_GF2& a)
118 {
119 long n = a.NumRows();
120 long i;
121 s << "[";
122 for (i = 0; i < n; i++) {
123 s << a[i];
124 s << "\n";
125 }
126 s << "]";
127 return s;
128 }
1298
1309
13110 void add(mat_GF2& X, const mat_GF2& A, const mat_GF2& B)
272151 }
273152
274153
275 void determinant(GF2& d, const mat_GF2& M_in)
154 void determinant(ref_GF2 d, const mat_GF2& M_in)
276155 {
277156 long k, n;
278157 long i, j;
435314
436315
437316
438 void solve(GF2& d, vec_GF2& X, const mat_GF2& A, const vec_GF2& b)
317 void solve(ref_GF2 d, vec_GF2& X, const mat_GF2& A, const vec_GF2& b)
439318
440319 {
441320 long n = A.NumRows();
520399
521400
522401
523 void inv(GF2& d, mat_GF2& X, const mat_GF2& A)
402 void inv(ref_GF2 d, mat_GF2& X, const mat_GF2& A)
524403 {
525404 long n = A.NumRows();
526405 if (A.NumCols() != n)
55 #include <NTL/new.h>
66
77 NTL_START_IMPL
8
9 NTL_matrix_impl(GF2E,vec_GF2E,vec_vec_GF2E,mat_GF2E)
10 NTL_io_matrix_impl(GF2E,vec_GF2E,vec_vec_GF2E,mat_GF2E)
11 NTL_eq_matrix_impl(GF2E,vec_GF2E,vec_vec_GF2E,mat_GF2E)
12
138
149
1510 void add(mat_GF2E& X, const mat_GF2E& A, const mat_GF2E& B)
33 #include <NTL/new.h>
44
55 NTL_START_IMPL
6
7 NTL_matrix_impl(RR,vec_RR,vec_vec_RR,mat_RR)
8 NTL_io_matrix_impl(RR,vec_RR,vec_vec_RR,mat_RR)
9 NTL_eq_matrix_impl(RR,vec_RR,vec_vec_RR,mat_RR)
10
116
127
138 void add(mat_RR& X, const mat_RR& A, const mat_RR& B)
33 #include <NTL/new.h>
44
55 NTL_START_IMPL
6
7 NTL_matrix_impl(ZZ,vec_ZZ,vec_vec_ZZ,mat_ZZ)
8 NTL_io_matrix_impl(ZZ,vec_ZZ,vec_vec_ZZ,mat_ZZ)
9 NTL_eq_matrix_impl(ZZ,vec_ZZ,vec_vec_ZZ,mat_ZZ)
10
116
127
138 void add(mat_ZZ& X, const mat_ZZ& A, const mat_ZZ& B)
22 #include <NTL/vec_ZZVec.h>
33 #include <NTL/vec_long.h>
44
5 #include <NTL/new.h>
6
75 NTL_START_IMPL
8
9 NTL_matrix_impl(ZZ_p,vec_ZZ_p,vec_vec_ZZ_p,mat_ZZ_p)
10 NTL_io_matrix_impl(ZZ_p,vec_ZZ_p,vec_vec_ZZ_p,mat_ZZ_p)
11 NTL_eq_matrix_impl(ZZ_p,vec_ZZ_p,vec_vec_ZZ_p,mat_ZZ_p)
12
136
147
158 void add(mat_ZZ_p& X, const mat_ZZ_p& A, const mat_ZZ_p& B)
33 #include <NTL/new.h>
44
55 NTL_START_IMPL
6
7 NTL_matrix_impl(ZZ_pE,vec_ZZ_pE,vec_vec_ZZ_pE,mat_ZZ_pE)
8
9 NTL_io_matrix_impl(ZZ_pE,vec_ZZ_pE,vec_vec_ZZ_pE,mat_ZZ_pE)
10
11 NTL_eq_matrix_impl(ZZ_pE,vec_ZZ_pE,vec_vec_ZZ_pE,mat_ZZ_pE)
12
136
147
158 void add(mat_ZZ_pE& X, const mat_ZZ_pE& A, const mat_ZZ_pE& B)
77 #include <NTL/vec_double.h>
88
99 NTL_START_IMPL
10
11 NTL_matrix_impl(zz_p,vec_zz_p,vec_vec_zz_p,mat_zz_p)
12 NTL_io_matrix_impl(zz_p,vec_zz_p,vec_vec_zz_p,mat_zz_p)
13 NTL_eq_matrix_impl(zz_p,vec_zz_p,vec_vec_zz_p,mat_zz_p)
14
1510
1611
1712 void add(mat_zz_p& X, const mat_zz_p& A, const mat_zz_p& B)
33 #include <NTL/new.h>
44
55 NTL_START_IMPL
6
7 NTL_matrix_impl(zz_pE,vec_zz_pE,vec_vec_zz_pE,mat_zz_pE)
8
9 NTL_io_matrix_impl(zz_pE,vec_zz_pE,vec_vec_zz_pE,mat_zz_pE)
10
11 NTL_eq_matrix_impl(zz_pE,vec_zz_pE,vec_vec_zz_pE,mat_zz_pE)
12
136
147
158 void add(mat_zz_pE& X, const mat_zz_pE& A, const mat_zz_pE& B)
159159 O07=$(O06) lzz_pX.o lzz_pX1.o lzz_pXCharPoly.o lzz_pXFactoring.o
160160 O08=$(O07) mat_GF2.o mat_GF2E.o mat_RR.o mat_ZZ.o mat_ZZ_p.o
161161 O09=$(O08) mat_ZZ_pE.o mat_lzz_p.o mat_lzz_pE.o mat_poly_ZZ.o
162 O10=$(O09) mat_poly_ZZ_p.o mat_poly_lzz_p.o pair_GF2EX_long.o
163 O11=$(O10) pair_GF2X_long.o pair_ZZX_long.o pair_ZZ_pEX_long.o
164 O12=$(O11) pair_ZZ_pX_long.o pair_lzz_pEX_long.o pair_lzz_pX_long.o
165 O13=$(O12) quad_float.o tools.o vec_GF2.o vec_GF2E.o vec_GF2XVec.o
166 O14=$(O13) vec_RR.o vec_ZZ.o vec_ZZVec.o vec_ZZ_p.o vec_ZZ_pE.o
167 O15=$(O14) vec_double.o vec_long.o vec_lzz_p.o vec_lzz_pE.o vec_quad_float.o
168 O16=$(O15) vec_vec_GF2.o vec_vec_GF2E.o vec_vec_RR.o vec_vec_ZZ.o
169 O17=$(O16) vec_vec_ZZ_p.o vec_vec_ZZ_pE.o vec_vec_long.o vec_vec_lzz_p.o
170 O18=$(O17) vec_vec_lzz_pE.o vec_xdouble.o xdouble.o
171 O19=$(O18) G_LLL_FP.o G_LLL_QP.o G_LLL_XD.o G_LLL_RR.o vec_ulong.o vec_vec_ulong.o
162 O10=$(O09) mat_poly_ZZ_p.o mat_poly_lzz_p.o
163 O11=$(O10)
164 O12=$(O11)
165 O13=$(O12) quad_float.o tools.o vec_GF2.o vec_GF2E.o
166 O14=$(O13) vec_RR.o vec_ZZ.o vec_ZZ_p.o vec_ZZ_pE.o
167 O15=$(O14) vec_lzz_p.o vec_lzz_pE.o
168 O16=$(O15)
169 O17=$(O16)
170 O18=$(O17) xdouble.o
171 O19=$(O18) G_LLL_FP.o G_LLL_QP.o G_LLL_XD.o G_LLL_RR.o
172172
173173 OBJ=$(O19)
174174
184184 S07=$(S06) lzz_pEXFactoring.c lzz_pX.c lzz_pX1.c
185185 S08=$(S07) lzz_pXCharPoly.c lzz_pXFactoring.c mat_GF2.c mat_GF2E.c
186186 S09=$(S08) mat_RR.c mat_ZZ.c mat_ZZ_p.c mat_ZZ_pE.c mat_lzz_p.c mat_lzz_pE.c
187 S10=$(S09) mat_poly_ZZ.c mat_poly_ZZ_p.c mat_poly_lzz_p.c pair_GF2EX_long.c
188 S11=$(S10) pair_GF2X_long.c pair_ZZX_long.c pair_ZZ_pEX_long.c
189 S12=$(S11) pair_ZZ_pX_long.c pair_lzz_pEX_long.c pair_lzz_pX_long.c
190 S13=$(S12) quad_float.c tools.c vec_GF2.c vec_GF2E.c vec_GF2XVec.c vec_RR.c
191 S14=$(S13) vec_ZZ.c vec_ZZVec.c vec_ZZ_p.c vec_ZZ_pE.c vec_double.c
192 S15=$(S14) vec_long.c vec_lzz_p.c vec_lzz_pE.c vec_quad_float.c
193 S16=$(S15) vec_vec_GF2.c vec_vec_GF2E.c vec_vec_RR.c vec_vec_ZZ.c
194 S17=$(S16) vec_vec_ZZ_p.c vec_vec_ZZ_pE.c vec_vec_long.c vec_vec_lzz_p.c
195 S18=$(S17) vec_vec_lzz_pE.c vec_xdouble.c xdouble.c
187 S10=$(S09) mat_poly_ZZ.c mat_poly_ZZ_p.c mat_poly_lzz_p.c
188 S11=$(S10)
189 S12=$(S11)
190 S13=$(S12) quad_float.c tools.c vec_GF2.c vec_GF2E.c vec_RR.c
191 S14=$(S13) vec_ZZ.c vec_ZZ_p.c vec_ZZ_pE.c
192 S15=$(S14) vec_lzz_p.c vec_lzz_pE.c
193 S16=$(S15)
194 S17=$(S16)
195 S18=$(S17) xdouble.c
196196 S19=$(S18) G_LLL_FP.c G_LLL_QP.c G_LLL_XD.c G_LLL_RR.c
197 S20=$(S19) vec_ulong.c vec_vec_ulong.c
198
199 SRC = $(S20)
197
198 SRC = $(S19)
200199
201200 # library source files that are header files
202201
515514 ######################################################################
516515
517516 WO1 = FFT.o GetTime.o ctools.o ZZ.o ZZVec.o ZZ_p.o ZZ_pX.o
518 WO2 = $(WO1) ZZ_pX1.o lip.o tools.o vec_ZZ.o vec_ZZ_p.o vec_long.o
517 WO2 = $(WO1) ZZ_pX1.o lip.o tools.o vec_ZZ.o vec_ZZ_p.o
519518 WO3 = $(WO2) GF2.o WordVector.o vec_GF2.o GF2X.o GF2X1.o
520519
521520 WOBJ = $(WO3)
+0
-16
src/pair_GF2EX_long.c less more
0
1 #include <NTL/pair_GF2EX_long.h>
2
3 #include <NTL/new.h>
4
5 NTL_START_IMPL
6
7 NTL_pair_impl(GF2EX,long,pair_GF2EX_long)
8 NTL_pair_io_impl(GF2EX,long,pair_GF2EX_long)
9 NTL_pair_eq_impl(GF2EX,long,pair_GF2EX_long)
10
11 NTL_vector_impl(pair_GF2EX_long,vec_pair_GF2EX_long)
12 NTL_io_vector_impl(pair_GF2EX_long,vec_pair_GF2EX_long)
13 NTL_eq_vector_impl(pair_GF2EX_long,vec_pair_GF2EX_long)
14
15 NTL_END_IMPL
+0
-16
src/pair_GF2X_long.c less more
0
1 #include <NTL/pair_GF2X_long.h>
2
3 #include <NTL/new.h>
4
5 NTL_START_IMPL
6
7 NTL_pair_impl(GF2X,long,pair_GF2X_long)
8 NTL_pair_io_impl(GF2X,long,pair_GF2X_long)
9 NTL_pair_eq_impl(GF2X,long,pair_GF2X_long)
10
11 NTL_vector_impl(pair_GF2X_long,vec_pair_GF2X_long)
12 NTL_io_vector_impl(pair_GF2X_long,vec_pair_GF2X_long)
13 NTL_eq_vector_impl(pair_GF2X_long,vec_pair_GF2X_long)
14
15 NTL_END_IMPL
+0
-16
src/pair_ZZX_long.c less more
0
1 #include <NTL/pair_ZZX_long.h>
2
3 #include <NTL/new.h>
4
5 NTL_START_IMPL
6
7 NTL_pair_impl(ZZX,long,pair_ZZX_long)
8 NTL_pair_io_impl(ZZX,long,pair_ZZX_long)
9 NTL_pair_eq_impl(ZZX,long,pair_ZZX_long)
10
11 NTL_vector_impl(pair_ZZX_long,vec_pair_ZZX_long)
12 NTL_io_vector_impl(pair_ZZX_long,vec_pair_ZZX_long)
13 NTL_eq_vector_impl(pair_ZZX_long,vec_pair_ZZX_long)
14
15 NTL_END_IMPL
+0
-17
src/pair_ZZ_pEX_long.c less more
0
1 #include <NTL/pair_ZZ_pEX_long.h>
2
3 #include <NTL/new.h>
4
5 NTL_START_IMPL
6
7 NTL_pair_impl(ZZ_pEX,long,pair_ZZ_pEX_long)
8 NTL_pair_io_impl(ZZ_pEX,long,pair_ZZ_pEX_long)
9 NTL_pair_eq_impl(ZZ_pEX,long,pair_ZZ_pEX_long)
10
11 NTL_vector_impl(pair_ZZ_pEX_long,vec_pair_ZZ_pEX_long)
12 NTL_io_vector_impl(pair_ZZ_pEX_long,vec_pair_ZZ_pEX_long)
13 NTL_eq_vector_impl(pair_ZZ_pEX_long,vec_pair_ZZ_pEX_long)
14
15 NTL_END_IMPL
16
+0
-16
src/pair_ZZ_pX_long.c less more
0
1 #include <NTL/pair_ZZ_pX_long.h>
2
3 #include <NTL/new.h>
4
5 NTL_START_IMPL
6
7 NTL_pair_impl(ZZ_pX,long,pair_ZZ_pX_long)
8 NTL_pair_io_impl(ZZ_pX,long,pair_ZZ_pX_long)
9 NTL_pair_eq_impl(ZZ_pX,long,pair_ZZ_pX_long)
10
11 NTL_vector_impl(pair_ZZ_pX_long,vec_pair_ZZ_pX_long)
12 NTL_io_vector_impl(pair_ZZ_pX_long,vec_pair_ZZ_pX_long)
13 NTL_eq_vector_impl(pair_ZZ_pX_long,vec_pair_ZZ_pX_long)
14
15 NTL_END_IMPL
+0
-16
src/pair_lzz_pEX_long.c less more
0
1 #include <NTL/pair_lzz_pEX_long.h>
2
3 #include <NTL/new.h>
4
5 NTL_START_IMPL
6
7 NTL_pair_impl(zz_pEX,long,pair_zz_pEX_long)
8 NTL_pair_io_impl(zz_pEX,long,pair_zz_pEX_long)
9 NTL_pair_eq_impl(zz_pEX,long,pair_zz_pEX_long)
10
11 NTL_vector_impl(pair_zz_pEX_long,vec_pair_zz_pEX_long)
12 NTL_io_vector_impl(pair_zz_pEX_long,vec_pair_zz_pEX_long)
13 NTL_eq_vector_impl(pair_zz_pEX_long,vec_pair_zz_pEX_long)
14
15 NTL_END_IMPL
+0
-16
src/pair_lzz_pX_long.c less more
0
1 #include <NTL/pair_lzz_pX_long.h>
2
3 #include <NTL/new.h>
4
5 NTL_START_IMPL
6
7 NTL_pair_impl(zz_pX,long,pair_zz_pX_long)
8 NTL_pair_io_impl(zz_pX,long,pair_zz_pX_long)
9 NTL_pair_eq_impl(zz_pX,long,pair_zz_pX_long)
10
11 NTL_vector_impl(pair_zz_pX_long,vec_pair_zz_pX_long)
12 NTL_io_vector_impl(pair_zz_pX_long,vec_pair_zz_pX_long)
13 NTL_eq_vector_impl(pair_zz_pX_long,vec_pair_zz_pX_long)
14
15 NTL_END_IMPL
125125 _maxlen |= 1;
126126 }
127127
128 GF2 vec_GF2::get(long i) const
128 const GF2 vec_GF2::get(long i) const
129129 {
130130 const vec_GF2& v = *this;
131131
141141 return to_GF2(0);
142142 }
143143
144 ref_GF2 vec_GF2::operator[](long i)
145 {
146 vec_GF2& v = *this;
147
148 if (i < 0 || i >= v.length())
149 Error("vec_GF2: subscript out of range");
150
151 long q = i/NTL_BITS_PER_LONG;
152 long p = i - q*NTL_BITS_PER_LONG;
153 return ref_GF2(INIT_LOOP_HOLE, &v.rep[q], p);
154 }
155
156
157
144158 static
145159 void SetBit(vec_GF2& v, long i)
146160 {
187201 }
188202
189203
190 void append(vec_GF2& v, GF2 a)
204 void append(vec_GF2& v, const GF2& a)
191205 {
192206 long n = v.length();
193207 v.SetLength(n+1);
0
10
21 #include <NTL/vec_GF2E.h>
32
4 #include <NTL/new.h>
53
64 NTL_START_IMPL
7
8
9
10
11
125
136 void BlockConstruct(GF2E* x, long n)
147 {
4538 }
4639 }
4740
48
49
50 NTL_vector_impl_plain(GF2E,vec_GF2E)
51
52 NTL_io_vector_impl(GF2E,vec_GF2E)
53
54 NTL_eq_vector_impl(GF2E,vec_GF2E)
5541
5642
5743 void InnerProduct(GF2E& x, const vec_GF2E& a, const vec_GF2E& b)
+0
-10
src/vec_GF2XVec.c less more
0
1 #include <NTL/vec_GF2XVec.h>
2
3 #include <NTL/new.h>
4
5 NTL_START_IMPL
6
7 NTL_vector_impl(GF2XVec,vec_GF2XVec)
8
9 NTL_END_IMPL
00
11 #include <NTL/vec_RR.h>
22
3 #include <NTL/new.h>
43
54 NTL_START_IMPL
65
7
8 NTL_vector_impl(RR,vec_RR)
9
10 NTL_eq_vector_impl(RR,vec_RR)
11
12 NTL_io_vector_impl(RR,vec_RR)
136
147 void InnerProduct(RR& xx, const vec_RR& a, const vec_RR& b)
158 {
00
11 #include <NTL/vec_ZZ.h>
22
3 #include <NTL/new.h>
4
53 NTL_START_IMPL
64
7
8 NTL_vector_impl(ZZ,vec_ZZ)
9
10 NTL_eq_vector_impl(ZZ,vec_ZZ)
11
12 NTL_io_vector_impl(ZZ,vec_ZZ)
135
146 void InnerProduct(ZZ& xx, const vec_ZZ& a, const vec_ZZ& b)
157 {
+0
-10
src/vec_ZZVec.c less more
0
1 #include <NTL/vec_ZZVec.h>
2
3 #include <NTL/new.h>
4
5 NTL_START_IMPL
6
7 NTL_vector_impl(ZZVec,vec_ZZVec)
8
9 NTL_END_IMPL
00
11
22 #include <NTL/vec_ZZ_p.h>
3
4 #include <NTL/new.h>
53
64 NTL_START_IMPL
75
4139 }
4240
4341
44 NTL_vector_impl_plain(ZZ_p,vec_ZZ_p)
45
46 NTL_io_vector_impl(ZZ_p,vec_ZZ_p)
47
48 NTL_eq_vector_impl(ZZ_p,vec_ZZ_p)
49
50
5142 void conv(vec_ZZ_p& x, const vec_ZZ& a)
5243 {
5344 long i, n;
00
11 #include <NTL/vec_ZZ_pE.h>
22
3 #include <NTL/new.h>
43
54 NTL_START_IMPL
6
7 NTL_vector_impl(ZZ_pE,vec_ZZ_pE)
8
9 NTL_io_vector_impl(ZZ_pE,vec_ZZ_pE)
10
11 NTL_eq_vector_impl(ZZ_pE,vec_ZZ_pE)
12
135
146 void InnerProduct(ZZ_pE& x, const vec_ZZ_pE& a, const vec_ZZ_pE& b)
157 {
+0
-21
src/vec_double.c less more
0
1 #include <NTL/vec_double.h>
2
3 #include <NTL/new.h>
4
5 NTL_START_IMPL
6
7 static inline
8 void BlockConstruct(double *, double) { }
9
10 static inline
11 void BlockDestroy(double *, double) { }
12
13 NTL_vector_impl_plain(double,vec_double)
14
15 NTL_io_vector_impl(double,vec_double)
16
17 NTL_eq_vector_impl(double,vec_double)
18
19 NTL_END_IMPL
20
+0
-21
src/vec_long.c less more
0
1 #include <NTL/vec_long.h>
2
3 #include <NTL/new.h>
4
5 NTL_START_IMPL
6
7 static inline
8 void BlockConstruct(long *, long) { }
9
10 static inline
11 void BlockDestroy(long *, long) { }
12
13 NTL_vector_impl_plain(long,vec_long)
14
15 NTL_io_vector_impl(long,vec_long)
16
17 NTL_eq_vector_impl(long,vec_long)
18
19 NTL_END_IMPL
20
00
11 #include <NTL/vec_lzz_p.h>
22
3 #include <NTL/new.h>
4
53 NTL_START_IMPL
6
7 NTL_vector_impl(zz_p,vec_zz_p)
8
9 NTL_io_vector_impl(zz_p,vec_zz_p)
10
11 NTL_eq_vector_impl(zz_p,vec_zz_p)
124
135 void conv(vec_zz_p& x, const vec_ZZ& a)
146 {
00
11 #include <NTL/vec_lzz_pE.h>
22
3 #include <NTL/new.h>
4
53 NTL_START_IMPL
6
7 NTL_vector_impl(zz_pE,vec_zz_pE)
8
9 NTL_io_vector_impl(zz_pE,vec_zz_pE)
10
11 NTL_eq_vector_impl(zz_pE,vec_zz_pE)
12
134
145 void InnerProduct(zz_pE& x, const vec_zz_pE& a, const vec_zz_pE& b)
156 {
+0
-15
src/vec_quad_float.c less more
0
1 #include <NTL/vec_quad_float.h>
2
3 #include <NTL/new.h>
4
5 NTL_START_IMPL
6
7 NTL_vector_impl(quad_float,vec_quad_float)
8
9 NTL_io_vector_impl(quad_float,vec_quad_float)
10
11 NTL_eq_vector_impl(quad_float,vec_quad_float)
12
13 NTL_END_IMPL
14
+0
-21
src/vec_ulong.c less more
0
1 #include <NTL/vec_ulong.h>
2
3 #include <NTL/new.h>
4
5 NTL_START_IMPL
6
7 static inline
8 void BlockConstruct(_ntl_ulong *, long) { }
9
10 static inline
11 void BlockDestroy(_ntl_ulong *, long) { }
12
13 NTL_vector_impl_plain(_ntl_ulong,vec_ulong)
14
15 NTL_io_vector_impl(_ntl_ulong,vec_ulong)
16
17 NTL_eq_vector_impl(_ntl_ulong,vec_ulong)
18
19 NTL_END_IMPL
20
+0
-16
src/vec_vec_GF2.c less more
0
1 #include <NTL/vec_vec_GF2.h>
2
3 #include <NTL/new.h>
4
5 NTL_START_IMPL
6
7
8 NTL_vector_impl(vec_GF2,vec_vec_GF2)
9
10 NTL_eq_vector_impl(vec_GF2,vec_vec_GF2)
11
12 NTL_io_vector_impl(vec_GF2,vec_vec_GF2)
13
14 NTL_END_IMPL
15
+0
-14
src/vec_vec_GF2E.c less more
0
1 #include <NTL/vec_vec_GF2E.h>
2
3 #include <NTL/new.h>
4
5 NTL_START_IMPL
6
7 NTL_vector_impl(vec_GF2E,vec_vec_GF2E)
8
9 NTL_eq_vector_impl(vec_GF2E,vec_vec_GF2E)
10
11 NTL_io_vector_impl(vec_GF2E,vec_vec_GF2E)
12
13 NTL_END_IMPL
+0
-15
src/vec_vec_RR.c less more
0
1 #include <NTL/vec_vec_RR.h>
2
3 #include <NTL/new.h>
4
5 NTL_START_IMPL
6
7 NTL_vector_impl(vec_RR,vec_vec_RR)
8
9 NTL_eq_vector_impl(vec_RR,vec_vec_RR)
10
11 NTL_io_vector_impl(vec_RR,vec_vec_RR)
12
13 NTL_END_IMPL
14
+0
-15
src/vec_vec_ZZ.c less more
0
1 #include <NTL/vec_vec_ZZ.h>
2
3 #include <NTL/new.h>
4
5 NTL_START_IMPL
6
7 NTL_vector_impl(vec_ZZ,vec_vec_ZZ)
8
9 NTL_eq_vector_impl(vec_ZZ,vec_vec_ZZ)
10
11 NTL_io_vector_impl(vec_ZZ,vec_vec_ZZ)
12
13 NTL_END_IMPL
14
+0
-14
src/vec_vec_ZZ_p.c less more
0
1 #include <NTL/vec_vec_ZZ_p.h>
2
3 #include <NTL/new.h>
4
5 NTL_START_IMPL
6
7 NTL_vector_impl(vec_ZZ_p,vec_vec_ZZ_p)
8
9 NTL_eq_vector_impl(vec_ZZ_p,vec_vec_ZZ_p)
10
11 NTL_io_vector_impl(vec_ZZ_p,vec_vec_ZZ_p)
12
13 NTL_END_IMPL
+0
-14
src/vec_vec_ZZ_pE.c less more
0
1 #include <NTL/vec_vec_ZZ_pE.h>
2
3 #include <NTL/new.h>
4
5 NTL_START_IMPL
6
7 NTL_vector_impl(vec_ZZ_pE,vec_vec_ZZ_pE)
8
9 NTL_eq_vector_impl(vec_ZZ_pE,vec_vec_ZZ_pE)
10
11 NTL_io_vector_impl(vec_ZZ_pE,vec_vec_ZZ_pE)
12
13 NTL_END_IMPL
+0
-15
src/vec_vec_long.c less more
0
1 #include <NTL/vec_vec_long.h>
2
3 #include <NTL/new.h>
4
5 NTL_START_IMPL
6
7 NTL_vector_impl(vec_long,vec_vec_long)
8
9 NTL_eq_vector_impl(vec_long,vec_vec_long)
10
11 NTL_io_vector_impl(vec_long,vec_vec_long)
12
13
14 NTL_END_IMPL
+0
-14
src/vec_vec_lzz_p.c less more
0
1 #include <NTL/vec_vec_lzz_p.h>
2
3 #include <NTL/new.h>
4
5 NTL_START_IMPL
6
7 NTL_vector_impl(vec_zz_p,vec_vec_zz_p)
8
9 NTL_eq_vector_impl(vec_zz_p,vec_vec_zz_p)
10
11 NTL_io_vector_impl(vec_zz_p,vec_vec_zz_p)
12
13 NTL_END_IMPL
+0
-14
src/vec_vec_lzz_pE.c less more
0
1 #include <NTL/vec_vec_lzz_pE.h>
2
3 #include <NTL/new.h>
4
5 NTL_START_IMPL
6
7 NTL_vector_impl(vec_zz_pE,vec_vec_zz_pE)
8
9 NTL_eq_vector_impl(vec_zz_pE,vec_vec_zz_pE)
10
11 NTL_io_vector_impl(vec_zz_pE,vec_vec_zz_pE)
12
13 NTL_END_IMPL
+0
-15
src/vec_vec_ulong.c less more
0
1 #include <NTL/vec_vec_ulong.h>
2
3 #include <NTL/new.h>
4
5 NTL_START_IMPL
6
7 NTL_vector_impl(vec_ulong,vec_vec_ulong)
8
9 NTL_eq_vector_impl(vec_ulong,vec_vec_ulong)
10
11 NTL_io_vector_impl(vec_ulong,vec_vec_ulong)
12
13
14 NTL_END_IMPL
+0
-14
src/vec_xdouble.c less more
0
1 #include <NTL/vec_xdouble.h>
2
3 #include <NTL/new.h>
4
5 NTL_START_IMPL
6
7 NTL_vector_impl(xdouble,vec_xdouble)
8
9 NTL_io_vector_impl(xdouble,vec_xdouble)
10
11 NTL_eq_vector_impl(xdouble,vec_xdouble)
12
13 NTL_END_IMPL