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
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 | |
2 | 2 | |
3 | 3 | Author: Victor Shoup (victor@shoup.net) |
4 | 4 |
10 | 10 | Its main use is to make the interfaces to the various finite |
11 | 11 | field classes as uniform as possible. |
12 | 12 | |
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 | ||
13 | 34 | \**************************************************************************/ |
14 | 35 | |
15 | 36 | #include <NTL/ZZ.h> |
37 | #include <NTL/vector.h> | |
16 | 38 | |
17 | 39 | |
18 | 40 | class GF2 { |
191 | 213 | static long GF2::modulus(); |
192 | 214 | // GF2::modulus() returns the value 2 |
193 | 215 | |
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 |
32 | 32 | GF2EX(long i, GF2 c); |
33 | 33 | GF2EX(long i, long c); |
34 | 34 | |
35 | ||
35 | ||
36 | typedef GF2E coeff_type; | |
37 | ||
38 | // ... | |
39 | ||
36 | 40 | }; |
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. | |
37 | 124 | |
38 | 125 | |
39 | 126 | |
242 | 329 | |
243 | 330 | \**************************************************************************/ |
244 | 331 | |
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 | |
268 | 332 | |
269 | 333 | void diff(GF2EX& x, const GF2EX& a); // x = derivative of a |
270 | 334 | GF2EX diff(const GF2EX& a); |
496 | 560 | |
497 | 561 | \**************************************************************************/ |
498 | 562 | |
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 | |
507 | 564 | |
508 | 565 | |
509 | 566 | |
790 | 847 | |
791 | 848 | Miscellany |
792 | 849 | |
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 | ||
801 | 850 | |
802 | 851 | \**************************************************************************/ |
803 | 852 | |
805 | 854 | void clear(GF2EX& x) // x = 0 |
806 | 855 | void set(GF2EX& x); // x = 1 |
807 | 856 | |
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. | |
814 | 857 | |
815 | 858 | void GF2EX::kill(); |
816 | 859 | // f.kill() sets f to 0 and frees all memory held by f. Equivalent to |
29 | 29 | |
30 | 30 | GF2X(long i, GF2 c); // initialize to X^i*c |
31 | 31 | GF2X(long i, long c); |
32 | ||
32 | ||
33 | ||
34 | typedef GF2 coeff_type; | |
35 | ||
36 | // ... | |
37 | ||
33 | 38 | }; |
34 | 39 | |
35 | 40 | |
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 | ||
37 | 122 | |
38 | 123 | |
39 | 124 | |
235 | 320 | |
236 | 321 | \**************************************************************************/ |
237 | 322 | |
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 | |
259 | 323 | |
260 | 324 | void diff(GF2X& x, const GF2X& a); |
261 | 325 | GF2X diff(const GF2X& a); |
509 | 573 | |
510 | 574 | \**************************************************************************/ |
511 | 575 | |
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 | |
520 | 578 | |
521 | 579 | |
522 | 580 | /**************************************************************************\ |
725 | 783 | void clear(GF2X& x) // x = 0 |
726 | 784 | void set(GF2X& x); // x = 1 |
727 | 785 | |
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. | |
734 | 786 | |
735 | 787 | 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. | |
738 | 789 | |
739 | 790 | GF2X::GF2X(INIT_SIZE_TYPE, long n); |
740 | 791 | // GF2X(INIT_SIZE, n) initializes to zero, but space is pre-allocated |
746 | 797 | void swap(GF2X& x, GF2X& y); |
747 | 798 | // swap x and y (via "pointer swapping") |
748 | 799 | |
800 | // SIZE INVARIANT: for any f in GF2X, deg(f)+1 < 2^(NTL_BITS_PER_LONG-4). |
379 | 379 | // ... |
380 | 380 | // c = MulModPrecon(a, b, n, bninv); // c = (a*b) % n |
381 | 381 | |
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) | |
382 | 396 | |
383 | 397 | |
384 | 398 |
58 | 58 | ZZX(long i, const ZZ& c); // initial value X^i*c |
59 | 59 | ZZX(long i, long c); |
60 | 60 | |
61 | ||
62 | typedef ZZ coeff_type; | |
63 | ||
61 | 64 | // ... |
62 | 65 | |
63 | 66 | }; |
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 | ||
64 | 152 | |
65 | 153 | |
66 | 154 | |
313 | 401 | \**************************************************************************/ |
314 | 402 | |
315 | 403 | |
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 | ||
339 | 404 | void diff(ZZX& x, const ZZX& a); // x = derivative of a |
340 | 405 | ZZX diff(const ZZX& a); |
341 | 406 | |
491 | 556 | |
492 | 557 | \**************************************************************************/ |
493 | 558 | |
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 | |
502 | 561 | |
503 | 562 | |
504 | 563 | /**************************************************************************\ |
505 | 564 | |
506 | 565 | 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 | ||
517 | 566 | |
518 | 567 | |
519 | 568 | \**************************************************************************/ |
521 | 570 | |
522 | 571 | void clear(ZZX& x); // x = 0 |
523 | 572 | 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. | |
531 | 573 | |
532 | 574 | void ZZX::kill(); |
533 | 575 | // f.kill() sets f to 0 and frees all memory held by f. Equivalent to |
32 | 32 | ZZ_pEX(long i, const ZZ_p& c); |
33 | 33 | ZZ_pEX(long i, long c); |
34 | 34 | |
35 | ||
35 | ||
36 | typedef ZZ_pE coeff_type; | |
37 | ||
38 | // ... | |
39 | ||
36 | 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 | 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 | ||
37 | 127 | |
38 | 128 | |
39 | 129 | |
242 | 332 | |
243 | 333 | \**************************************************************************/ |
244 | 334 | |
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 | |
268 | 335 | |
269 | 336 | void diff(ZZ_pEX& x, const ZZ_pEX& a); // x = derivative of a |
270 | 337 | ZZ_pEX diff(const ZZ_pEX& a); |
497 | 564 | |
498 | 565 | \**************************************************************************/ |
499 | 566 | |
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 | |
508 | 569 | |
509 | 570 | |
510 | 571 | |
790 | 851 | |
791 | 852 | Miscellany |
792 | 853 | |
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 | ||
801 | 854 | |
802 | 855 | \**************************************************************************/ |
803 | 856 | |
804 | 857 | |
805 | 858 | void clear(ZZ_pEX& x) // x = 0 |
806 | 859 | 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. | |
814 | 860 | |
815 | 861 | void ZZ_pEX::kill(); |
816 | 862 | // f.kill() sets f to 0 and frees all memory held by f. Equivalent to |
34 | 34 | ZZ_pX(long i, long c); |
35 | 35 | |
36 | 36 | ~ZZ_pX(); // destructor |
37 | ||
38 | ||
39 | typedef ZZ_p coeff_type; | |
40 | ||
41 | // ... | |
42 | ||
37 | 43 | |
38 | 44 | }; |
39 | 45 | |
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. | |
40 | 128 | |
41 | 129 | |
42 | 130 | |
246 | 334 | Some utility routines |
247 | 335 | |
248 | 336 | \**************************************************************************/ |
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 | |
272 | 337 | |
273 | 338 | void diff(ZZ_pX& x, const ZZ_pX& a); // x = derivative of a |
274 | 339 | ZZ_pX diff(const ZZ_pX& a); |
573 | 638 | |
574 | 639 | \**************************************************************************/ |
575 | 640 | |
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 | |
584 | 642 | |
585 | 643 | |
586 | 644 | /**************************************************************************\ |
795 | 853 | |
796 | 854 | Miscellany |
797 | 855 | |
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 | 856 | |
806 | 857 | \**************************************************************************/ |
807 | 858 | |
808 | 859 | |
809 | 860 | void clear(ZZ_pX& x) // x = 0 |
810 | 861 | 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. | |
818 | 862 | |
819 | 863 | void ZZ_pX::kill(); |
820 | 864 | // f.kill() sets f to 0 and frees all memory held by f; Equivalent to |
288 | 288 | NTL_SPMM_UL=off |
289 | 289 | NTL_SPMM_ULL=off |
290 | 290 | NTL_SPMM_ASM=off |
291 | NTL_FFT_BIGTAB=off | |
292 | NTL_FFT_LAZYMUL=off | |
291 | 293 | NTL_TBL_REM=off |
292 | 294 | NTL_AVOID_BRANCHING=off |
293 | 295 | NTL_GF2X_NOINLINE=off |
578 | 580 | # using assembly code. Only supported on select machines |
579 | 581 | # and only under GCC. |
580 | 582 | |
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 | ||
581 | 602 | |
582 | 603 | |
583 | 604 |
10 | 10 | |
11 | 11 | |
12 | 12 | int: int, long, uint, ulong, ZZ, float, double, xdouble, quad_float, RR |
13 | GF2, zz_p, ZZ_p | |
13 | 14 | |
14 | 15 | 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 | |
15 | 26 | |
16 | 27 | float: int, long, uint, ulong, ZZ, float, double, xdouble, quad_float, RR |
17 | 28 | |
18 | 29 | double: int, long, uint, ulong, ZZ, float, double, xdouble, quad_float, RR |
19 | ||
20 | uint: ZZ | |
21 | ||
22 | ulong: ZZ | |
23 | 30 | |
24 | 31 | xdouble: int, long, uint, ulong, ZZ, float, double, xdouble, RR, cstr |
25 | 32 | |
28 | 35 | RR: int, long, uint, ulong, ZZ, float, double, xdouble, quad_float, |
29 | 36 | RR, cstr |
30 | 37 | |
31 | ZZ: int, long, uint, ulong, ZZ, float, double, xdouble, quad_float, | |
32 | RR, cstr | |
33 | 38 | |
34 | ZZ_p: long, ZZ | |
39 | ZZ_p: long, ZZ, ZZ_p | |
35 | 40 | |
36 | vec_ZZ_p: vec_ZZ | |
41 | ZZ_pX: long, ZZ, ZZ_p; ZZX, ZZ_pX; ZZ_pE; vec_ZZ_p | |
37 | 42 | |
38 | ZZ_pX: long, ZZ_p, ZZ, ZZX, vec_ZZ_p | |
43 | zz_p: long, ZZ, zz_p | |
39 | 44 | |
40 | zz_p: long, ZZ | |
45 | zz_pX: long, ZZ, zz_p; ZZX, zz_pX; zz_pE; vec_zz_p | |
41 | 46 | |
42 | vec_zz_p: vec_ZZ | |
47 | ZZX: long, ZZ; ZZX, GF2X, zz_pX, ZZ_pX; vec_ZZ | |
43 | 48 | |
44 | ZZ_pX: long, zz_p, ZZ, ZZX, vec_zz_p | |
49 | GF2: long, ZZ, GF2 | |
45 | 50 | |
46 | vec_ZZ: vec_ZZ_p, vec_zz_p | |
51 | GF2X: long, ZZ, GF2; ZZX, GF2X; GF2E; vec_GF2 | |
47 | 52 | |
48 | ZZX: long, ZZ, ZZ_pX, zz_pX | |
53 | GF2E: long, ZZ, GF2, GF2E; GF2X | |
49 | 54 | |
50 | GF2: long, ZZ | |
55 | GF2EX: long, ZZ, GF2, GF2E; ZZX, GF2X, GF2EX; vec_GF2E | |
51 | 56 | |
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 | |
52 | 68 | 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 | |
71 | 72 | |
72 | 73 | |
73 | 74 | ********** NOTES *********** |
83 | 84 | form. To convert a of type S to x of type T, you can write |
84 | 85 | conv(x, a); |
85 | 86 | or |
86 | x = to_T(a); | |
87 | x = conv<T>(a); | |
87 | 88 | |
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 | |
92 | 131 | compute the result modulo 2^n, where n is the number of bits of the |
93 | 132 | destination type: no overflow occurs. |
94 | 133 | |
95 | [3] All floating point to integral conversions compute the floor | |
134 | [4] All floating point to signed integral conversions compute the floor | |
96 | 135 | 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. | |
98 | 146 | |
99 | [4] The ZZ to double conversion routine is very precise: | |
147 | [6] The ZZ to double conversion routine is very precise: | |
100 | 148 | the result is the nearest double, breaking ties using the |
101 | 149 | "round to even" rule. Overflow results in +/- Infinity. |
102 | 150 | All this assumes the underlying floating point adheres to |
103 | 151 | the IEEE standard. |
104 | 152 | |
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 | ||
106 | 156 | |
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 | |
108 | 158 | ZZ_p, ZZ_pX, ZZ_pE, ZZ_pEX, |
109 | 159 | zz_p, zz_pX, zz_pE, zz_pEX, |
110 | 160 | GF2, GF2X, GF2E, GF2EX |
111 | yield the the residue class modulo p. | |
161 | yield the the residue class modulo p (or 2). | |
112 | 162 | |
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. | |
115 | 170 | |
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 | |
120 | 172 | the given polynomial modulo the current modulus. |
121 | 173 | |
122 | [10] All conversions from the type cstr apply the same algorithm | |
174 | [12] All conversions from the type cstr apply the same algorithm | |
123 | 175 | as is used for reading from an I/O stream, so |
124 | ZZ x = to_ZZ("999999999999999999"); | |
176 | ZZ x = conv<ZZ>("999999999999999999"); | |
125 | 177 | initializes the ZZ x to the integer 999999999999999999. |
126 | 178 | |
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 |
1 | 1 | COPYRIGHT NOTICE |
2 | 2 | |
3 | 3 | NTL -- A Library for Doing Number Theory |
4 | Copyright (C) 1996-2009 Victor Shoup | |
4 | Copyright (C) 1996-2013 Victor Shoup | |
5 | 5 | |
6 | 6 | The most recent version of NTL is available at http://www.shoup.net |
7 | 7 |
32 | 32 | zz_pEX(long i, const zz_p& c); |
33 | 33 | zz_pEX(long i, long c); |
34 | 34 | |
35 | ||
36 | typedef zz_pE coeff_type; | |
37 | ||
38 | // ... | |
39 | ||
35 | 40 | |
36 | 41 | }; |
37 | 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. | |
38 | 123 | |
39 | 124 | |
40 | 125 | |
242 | 327 | |
243 | 328 | \**************************************************************************/ |
244 | 329 | |
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 | |
268 | 330 | |
269 | 331 | void diff(zz_pEX& x, const zz_pEX& a); // x = derivative of a |
270 | 332 | zz_pEX diff(const zz_pEX& a); |
497 | 559 | |
498 | 560 | \**************************************************************************/ |
499 | 561 | |
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 | |
508 | 564 | |
509 | 565 | |
510 | 566 | |
790 | 846 | |
791 | 847 | Miscellany |
792 | 848 | |
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 | ||
801 | 849 | |
802 | 850 | \**************************************************************************/ |
803 | 851 | |
804 | 852 | |
805 | 853 | void clear(zz_pEX& x) // x = 0 |
806 | 854 | 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. | |
814 | 855 | |
815 | 856 | void zz_pEX::kill(); |
816 | 857 | // f.kill() sets f to 0 and frees all memory held by f. Equivalent to |
29 | 29 | |
30 | 30 | zz_pX(long i, zz_p c); // initialize to X^i*c |
31 | 31 | zz_pX(long i, long c); |
32 | ||
33 | ||
34 | typedef zz_p coeff_type; | |
35 | ||
36 | // ... | |
37 | ||
32 | 38 | |
33 | 39 | }; |
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. | |
34 | 123 | |
35 | 124 | |
36 | 125 | |
237 | 326 | |
238 | 327 | \**************************************************************************/ |
239 | 328 | |
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 | |
261 | 329 | |
262 | 330 | void diff(zz_pX& x, const zz_pX& a); |
263 | 331 | zz_pX diff(const zz_pX& a); |
572 | 640 | |
573 | 641 | \**************************************************************************/ |
574 | 642 | |
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 | ||
583 | 646 | |
584 | 647 | |
585 | 648 | /**************************************************************************\ |
795 | 858 | |
796 | 859 | Miscellany |
797 | 860 | |
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 | ||
806 | 861 | |
807 | 862 | \**************************************************************************/ |
808 | 863 | |
809 | 864 | |
810 | 865 | void clear(zz_pX& x) // x = 0 |
811 | 866 | 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. | |
819 | 867 | |
820 | 868 | void zz_pX::kill(); |
821 | 869 | // f.kill() sets f to 0 and frees all memory held by f. Equivalent to |
12 | 12 | #include <NTL/matrix.h> |
13 | 13 | #include <NTL/vec_vec_GF2E.h> |
14 | 14 | |
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 | ||
18 | 18 | |
19 | 19 | void add(mat_GF2E& X, const mat_GF2E& A, const mat_GF2E& B); |
20 | 20 | // X = A + B |
12 | 12 | #include <NTL/matrix.h> |
13 | 13 | #include <NTL/vec_vec_RR.h> |
14 | 14 | |
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 | |
18 | 16 | |
19 | 17 | void add(mat_RR& X, const mat_RR& A, const mat_RR& B); |
20 | 18 | // X = A + B |
12 | 12 | #include <NTL/matrix.h> |
13 | 13 | #include <NTL/vec_vec_ZZ.h> |
14 | 14 | |
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 | |
18 | 16 | |
19 | 17 | void add(mat_ZZ& X, const mat_ZZ& A, const mat_ZZ& B); |
20 | 18 | // X = A + B |
12 | 12 | #include <NTL/matrix.h> |
13 | 13 | #include <NTL/vec_vec_ZZ_p.h> |
14 | 14 | |
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 | |
18 | 17 | |
19 | 18 | void add(mat_ZZ_p& X, const mat_ZZ_p& A, const mat_ZZ_p& B); |
20 | 19 | // X = A + B |
12 | 12 | #include <NTL/matrix.h> |
13 | 13 | #include <NTL/vec_vec_ZZ_pE.h> |
14 | 14 | |
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 | |
18 | 17 | |
19 | 18 | void add(mat_ZZ_pE& X, const mat_ZZ_pE& A, const mat_ZZ_pE& B); |
20 | 19 | // X = A + B |
12 | 12 | #include <NTL/matrix.h> |
13 | 13 | #include "vec_vec_zz_p.h" |
14 | 14 | |
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 | |
18 | 17 | |
19 | 18 | void add(mat_zz_p& X, const mat_zz_p& A, const mat_zz_p& B); |
20 | 19 | // X = A + B |
12 | 12 | #include <NTL/matrix.h> |
13 | 13 | #include <NTL/vec_vec_lzz_pE.h> |
14 | 14 | |
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 | |
18 | 17 | |
19 | 18 | void add(mat_zz_pE& X, const mat_zz_pE& A, const mat_zz_pE& B); |
20 | 19 | // X = A + B |
4 | 4 | |
5 | 5 | SUMMARY: |
6 | 6 | |
7 | Macros are deined providing template-like classes for dynamic-sized, | |
8 | recatngular matrices. | |
7 | Matrix templates. | |
9 | 8 | |
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 | |
13 | 10 | |
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; | |
16 | 12 | |
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. | |
19 | 14 | |
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: | |
25 | 16 | |
26 | 17 | M.SetDims(10, 20); |
27 | 18 | |
29 | 20 | A matrix entry can be accessed as M[i][j], indexing from 0, or as |
30 | 21 | M(i, j), indexing from 1. |
31 | 22 | |
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 | |
34 | 25 | as to create a non-rectangular matrix will result in a run-time |
35 | 26 | error. |
36 | 27 | |
42 | 33 | |
43 | 34 | \**************************************************************************/ |
44 | 35 | |
45 | class mat_T { | |
46 | mat_T(); // initially 0 x 0 | |
36 | template<class T> | |
37 | class Mat { | |
47 | 38 | |
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; | |
51 | 42 | |
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 | |
54 | 52 | // the default constructor for T to initialize entries. |
55 | 53 | |
56 | 54 | void SetDims(long n, long m); |
69 | 67 | long NumCols() const; |
70 | 68 | // M.NumCols() returns the number of columns of M |
71 | 69 | |
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; | |
74 | 72 | // access row i, initial index 0. Any attempt to change the length |
75 | 73 | // of this row will raise an error. |
76 | 74 | |
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; | |
79 | 77 | // access row i, initial index 1. Any attempt to change the length |
80 | 78 | // of this row will raise an error. |
81 | 79 | |
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; | |
84 | 82 | // access element (i, j), both indices starting at 1 |
85 | 83 | |
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; | |
87 | 96 | // returns index of a in matrix, or -1 if not present; |
88 | 97 | // equivalent to rep(*this).position(a). |
89 | 98 | |
90 | 99 | |
91 | long position1(const vec_T& a) const; | |
100 | long position1(const Vec<T>& a) const; | |
92 | 101 | // returns index of a in matrix, or -1 if not present; |
93 | 102 | // equivalent to rep(*this).position1(a). |
94 | 103 | |
104 | ||
95 | 105 | |
96 | 106 | }; |
97 | 107 | |
98 | const vec_vec_T& rep(const mat_T& a); | |
108 | template<class T> | |
109 | const Vec< Vec<T> >& rep(const Mat<T>& a); | |
99 | 110 | // read-only access to underlying representation |
100 | 111 | |
101 | void swap(mat_T& X, mat_T& Y); | |
112 | template<class T> | |
113 | void swap(Mat<T>& X, Mat<T>& Y); | |
102 | 114 | // swaps X and Y (by swapping pointers) |
103 | 115 | |
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); | |
105 | 118 | // copies a to x, checking that it is "rectangular" |
106 | 119 | |
107 | 120 | /**************************************************************************\ |
108 | 121 | |
109 | 122 | Input/Output |
110 | 123 | |
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 | ||
116 | 124 | \**************************************************************************/ |
117 | 125 | |
118 | 126 | |
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>&); | |
121 | 132 | |
122 | 133 | /**************************************************************************\ |
123 | 134 | |
124 | 135 | Equality Testing |
125 | 136 | |
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 | ||
132 | 137 | |
133 | 138 | \**************************************************************************/ |
134 | 139 | |
135 | 140 | |
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); | |
138 | 143 | |
144 | template<class T> | |
145 | long operator!=(const Mat<T>& a, const Mat<T>& b); | |
146 |
3 | 3 | |
4 | 4 | SUMMARY: |
5 | 5 | |
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. | |
20 | 7 | |
21 | 8 | The decalaration |
22 | 9 | |
23 | pair_S_T p; | |
10 | Pair<S,T> p; | |
24 | 11 | |
25 | 12 | creates a pair object using the default constructors for S and T. The |
26 | 13 | member p.a is the first component (of type S) and the member p.b is |
33 | 20 | |
34 | 21 | #include <NTL/tools.h> |
35 | 22 | |
36 | class pair_S_T { | |
23 | template<class S, class T> | |
24 | class Pair { | |
37 | 25 | public: |
38 | 26 | S a; |
39 | 27 | T b; |
40 | 28 | |
41 | pair_S_T(); | |
29 | Pair(); | |
42 | 30 | // default constructor...invokes default constructors for S and T |
43 | 31 | |
44 | pair_S_T(const pair_S_T& x); // copy | |
32 | Pair(const Pair<S,T>& x); // copy | |
45 | 33 | |
46 | pair_S_T& operator=(const pair_S_T& x); // assignment | |
34 | Pair& operator=(const Pair<S,T>& x); // assignment | |
47 | 35 | |
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) | |
49 | 37 | |
50 | ~pair_S_T(); | |
38 | ~Pair(); | |
51 | 39 | // destructor...invokes destructors for S and T |
52 | 40 | }; |
53 | 41 | |
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) | |
56 | 45 | |
57 | 46 | |
58 | 47 | /**************************************************************************\ |
59 | 48 | |
60 | 49 | Input/Output |
61 | 50 | |
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 | |
68 | 52 | |
69 | 53 | [a b] |
70 | 54 | |
71 | 55 | \**************************************************************************/ |
72 | 56 | |
73 | 57 | |
58 | template<class S, class T> | |
59 | istream& operator>>(istream&, Pair<S,T>&); | |
74 | 60 | |
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>&); | |
77 | 63 | |
78 | 64 | |
79 | 65 | /**************************************************************************\ |
80 | 66 | |
81 | 67 | Equality Testing |
82 | 68 | |
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 | ||
88 | 69 | \**************************************************************************/ |
89 | 70 | |
90 | 71 | |
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); | |
93 | 77 | |
94 | 78 |
90 | 90 | // int, long, float, double. See conversions.txt for complete details. |
91 | 91 | |
92 | 92 | |
93 | ||
93 | 94 | // The following platform-dependent macros are defined: |
94 | 95 | |
95 | 96 | #define NTL_BITS_PER_LONG (...) /* bits in a long */ |
15 | 15 | A Tour of NTL: Summary of Changes |
16 | 16 | </p> |
17 | 17 | </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<T></tt>, | |
28 | <tt>Mat<T></tt>, and <tt>Pair<S,T></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<ZZ>(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<S></tt> to <tt>Vec<T></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 | ||
18 | 93 | |
19 | 94 | <p> <hr> <p> |
20 | 95 | <h3> |
30 | 30 | <pre> |
31 | 31 | #include <NTL/ZZ.h> |
32 | 32 | |
33 | NTL_CLIENT | |
33 | using namespace std; | |
34 | using namespace NTL; | |
34 | 35 | |
35 | 36 | int main() |
36 | 37 | { |
61 | 62 | with memory management and temporary objects. |
62 | 63 | |
63 | 64 | <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> | |
69 | 69 | using namespace NTL; |
70 | 70 | </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>. | |
74 | 74 | |
75 | 75 | <p> <hr> <p> |
76 | 76 | |
81 | 81 | <pre> |
82 | 82 | #include <NTL/ZZ.h> |
83 | 83 | |
84 | NTL_CLIENT | |
84 | ||
85 | using namespace std; | |
86 | using namespace NTL; | |
87 | ||
85 | 88 | |
86 | 89 | int main() |
87 | 90 | { |
206 | 209 | The following program prompts the user for an input, |
207 | 210 | and applies a simple probabilistic primality test. |
208 | 211 | Note that NTL already provides a slightly more sophisticated |
209 | prime test. | |
212 | primality test. | |
210 | 213 | |
211 | 214 | <p> |
212 | 215 | <pre> |
213 | 216 | #include <NTL/ZZ.h> |
214 | 217 | |
215 | NTL_CLIENT | |
218 | using namespace std; | |
219 | using namespace NTL; | |
216 | 220 | |
217 | 221 | long witness(const ZZ& n, const ZZ& x) |
218 | 222 | { |
363 | 367 | ZZ x = 1; // error |
364 | 368 | </pre> |
365 | 369 | 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. | |
369 | 370 | Instead, one could write |
370 | 371 | <pre> |
371 | ZZ x = to_ZZ(1); | |
372 | ZZ x = conv<ZZ>(1); | |
372 | 373 | </pre> |
373 | 374 | This is an example of one of NTL's conversion routines. |
374 | 375 | For very large constants, one can write: |
375 | 376 | <pre> |
376 | ZZ x = to_ZZ("99999999999999999999"); | |
377 | ZZ x = conv<ZZ>("99999999999999999999"); | |
377 | 378 | </pre> |
378 | 379 | These examples illustrate conversion rountines in their |
379 | 380 | functional forms. |
380 | The corresponding procedural forms are all called <tt>conv</tt>, e.g., | |
381 | 381 | <pre> |
382 | 382 | ZZ x; |
383 | 383 | conv(x, 1); |
394 | 394 | including comparison, arithmetic, shift, and bit-wise logical operations. |
395 | 395 | One can mix <tt>ZZ</tt>s and <tt>long</tt>s in any expresion in |
396 | 396 | a natural way. |
397 | As was already mentioned, NTL does not support implicit type conversion; | |
397 | NTL does not support implicit type conversion; | |
398 | 398 | rather, for basic operations, it simply overloads the operators |
399 | 399 | or functions in a way to achieve a kind of "promotion logic": |
400 | 400 | if one input is a <tt>ZZ</tt> and the other is a <tt>long</tt> |
25 | 25 | numbers in a vector of <tt>ZZ</tt>'s. |
26 | 26 | |
27 | 27 | <pre> |
28 | #include <NTL/vec_ZZ.h> | |
29 | ||
30 | NTL_CLIENT | |
31 | ||
32 | ZZ sum(const vec_ZZ& v) | |
28 | #include <NTL/ZZ.h> | |
29 | #include <NTL/vector.h> | |
30 | ||
31 | using namespace std; | |
32 | using namespace NTL; | |
33 | ||
34 | ZZ sum(const Vec<ZZ>& v) | |
33 | 35 | { |
34 | 36 | ZZ acc; |
35 | 37 | |
43 | 45 | </pre> |
44 | 46 | |
45 | 47 | <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<ZZ></tt> is a dynamic-length array of <tt>ZZ</tt>s; | |
49 | more generally, NTL provides a template class <tt>Vec<T></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 | ||
55 | 63 | |
56 | 64 | <p> |
57 | 65 | Vectors in NTL are indexed from 0, but in many situations |
60 | 68 | the above example could be written as follows. |
61 | 69 | |
62 | 70 | <pre> |
63 | #include <NTL/vec_ZZ.h> | |
64 | ||
65 | NTL_CLIENT | |
66 | ||
67 | ZZ sum(ZZ& s, const vec_ZZ& v) | |
71 | #include <NTL/ZZ.h> | |
72 | #include <NTL/vector.h> | |
73 | ||
74 | using namespace std; | |
75 | using namespace NTL; | |
76 | ||
77 | ZZ sum(ZZ& s, const Vec<ZZ>& v) | |
68 | 78 | { |
69 | 79 | ZZ acc; |
70 | 80 | |
88 | 98 | |
89 | 99 | The following example illustrates vector I/O, |
90 | 100 | 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<ZZ></tt>, | |
92 | 102 | and then creates and prints a "palindrome". |
93 | 103 | |
94 | 104 | <pre> |
95 | #include <NTL/vec_ZZ.h> | |
96 | ||
97 | NTL_CLIENT | |
105 | #include <NTL/ZZ.h> | |
106 | #include <NTL/vector.h> | |
107 | ||
108 | using namespace std; | |
109 | using namespace NTL; | |
98 | 110 | |
99 | 111 | int main() |
100 | 112 | { |
101 | vec_ZZ v; | |
113 | Vec<ZZ> v; | |
102 | 114 | cin >> v; |
103 | 115 | |
104 | 116 | long n = v.length(); |
131 | 143 | |
132 | 144 | <p> |
133 | 145 | |
134 | NTL pre-defines a number of vector types. | |
135 | In addition, you can create your own. | |
136 | 146 | See <a href="vector.txt"><tt>vector.txt</tt></a> for |
137 | 147 | 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<ZZ>.txt</tt>, there is a corresponding header file | |
151 | <tt><NTL/vec_ZZ.h></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<ZZ></tt>'s | |
140 | 157 | provided by NTL. |
141 | 158 | |
142 | 159 | |
145 | 162 | |
146 | 163 | There is also basic support for matrices |
147 | 164 | 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<T></tt> is a special | |
166 | kind of <tt>Vec< Vec< T > ></tt>, where each row is | |
150 | 167 | a vector of the same length. |
151 | 168 | Row <tt>i</tt> of matrix <tt>M</tt> |
152 | 169 | can be accessed as <tt>M[i]</tt> (indexing from 0) |
160 | 177 | which in fact is already provided by NTL. |
161 | 178 | |
162 | 179 | <pre> |
163 | #include <NTL/mat_ZZ.h> | |
164 | ||
165 | NTL_CLIENT | |
166 | ||
167 | void mul(mat_ZZ& X, const mat_ZZ& A, const mat_ZZ& B) | |
180 | #include <NTL/ZZ.h> | |
181 | #include <NTL/matrix.h> | |
182 | ||
183 | using namespace std; | |
184 | using namespace NTL; | |
185 | ||
186 | void mul(Mat<ZZ>& X, const Mat<ZZ>& A, const Mat<ZZ>& B) | |
168 | 187 | { |
169 | 188 | long n = A.NumRows(); |
170 | 189 | long l = A.NumCols(); |
196 | 215 | <tt>Error</tt> function, which is a part of NTL and which simply |
197 | 216 | prints the message and aborts. |
198 | 217 | 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. | |
202 | 218 | |
203 | 219 | <p> |
204 | 220 | This routine will not work properly if <tt>X</tt> aliases |
207 | 223 | In fact, all of NTL's routines allow outputs to alias inputs. |
208 | 224 | |
209 | 225 | <p> |
210 | ||
211 | To call the multiplication routine, one can write | |
226 | To call NTL's built-in multiplication routine | |
227 | (declared in <tt><NTL/mat_ZZ.h></tt>), one can write | |
212 | 228 | <pre> |
213 | 229 | mul(X, A, B); |
214 | 230 | </pre> |
222 | 238 | See <a href="matrix.txt"><tt>matrix.txt</tt></a> |
223 | 239 | for complete details on NTL's generic matrix mechanism. |
224 | 240 | 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<ZZ></tt>'s | |
226 | 242 | provideed by NTL (including basic linear algebra). |
227 | 243 | Also see <a href="LLL.txt"><tt>LLL.txt</tt></a> |
228 | 244 | for details on routines for lattice basis reduction |
33 | 33 | <pre> |
34 | 34 | #include <NTL/ZZXFactoring.h> |
35 | 35 | |
36 | NTL_CLIENT | |
36 | using namespace std; | |
37 | using namespace NTL; | |
37 | 38 | |
38 | 39 | int main() |
39 | 40 | { |
41 | 42 | |
42 | 43 | cin >> f; |
43 | 44 | |
44 | vec_pair_ZZX_long factors; | |
45 | Vec< Pair< ZZX, long > > factors; | |
45 | 46 | ZZ c; |
46 | 47 | |
47 | 48 | factor(c, factors, f); |
84 | 85 | computer algebra system: it is a library for programmers. |
85 | 86 | |
86 | 87 | <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< Pair< ZZX, long > ></tt> | |
89 | is an NTL vector whose base type is <tt>Pair< ZZX, long ></tt>. | |
90 | The type <tt>Pair< ZZX, long ></tt> is the instantiation | |
91 | of a template "pair" type defined by NTL. | |
95 | 92 | See <a href="pair.txt"><tt>pair.txt</tt></a> for more details. |
96 | 93 | |
97 | 94 | |
105 | 102 | |
106 | 103 | #include <NTL/ZZX.h> |
107 | 104 | |
108 | NTL_CLIENT | |
105 | using namespace std; | |
106 | using namespace NTL; | |
109 | 107 | |
110 | 108 | int main() |
111 | 109 | { |
112 | vec_ZZX phi(INIT_SIZE, 100); | |
110 | Vec<ZZX> phi(INIT_SIZE, 100); | |
113 | 111 | |
114 | 112 | for (long i = 1; i <= 100; i++) { |
115 | 113 | ZZX t; |
133 | 131 | <p> |
134 | 132 | First, instead of |
135 | 133 | <pre> |
136 | vec_ZZX phi(INIT_SIZE, 100); | |
134 | Vec<ZZX> phi(INIT_SIZE, 100); | |
137 | 135 | </pre> |
138 | 136 | one can write |
139 | 137 | <pre> |
140 | vec_ZZX phi; | |
138 | Vec<ZZX> phi; | |
141 | 139 | phi.SetLength(100); |
142 | 140 | </pre> |
143 | 141 | |
169 | 167 | SetCoeff(t1, 0, -1); |
170 | 168 | div(phi(i), t1, t); |
171 | 169 | </pre> |
172 | Alternatively, one could directly access the coefficient vector: | |
170 | Alternatively, one could directly access the coefficient vector as follows: | |
173 | 171 | <pre> |
174 | 172 | 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; | |
178 | 176 | t1.normalize(); // not necessary here, but good practice in general |
179 | 177 | div(phi(i), t1, t); |
180 | 178 | </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. | |
185 | 181 | 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: | |
187 | 183 | this is an invariant which all routines that work with polynomials |
188 | 184 | expect to hold. |
189 | 185 | Of course, if you can avoid directly accessing the |
192 | 188 | change coefficients, and you can always read the value of a coefficient |
193 | 189 | using the routine <tt>coeff</tt>, e.g., |
194 | 190 | <pre> |
195 | ... f.rep[i] == 1 ... | |
191 | ... f[i] == 1 ... | |
196 | 192 | </pre> |
197 | 193 | is equivalent to |
198 | 194 | <pre> |
205 | 201 | |
206 | 202 | |
207 | 203 | <p> |
208 | NTL provides a full compliment of operations for polynomials | |
204 | NTL provides a full compliment of arithmetic operations for polynomials | |
209 | 205 | over the integers, in both operator and procedural form. |
210 | 206 | All of the basic operations support a "promotion logic" similar |
211 | 207 | to that for <tt>ZZ</tt>, except that inputs of <i>both</i> types |
24 | 24 | represents the integers mod <tt>p</tt>. |
25 | 25 | Despite the notation, <tt>p</tt> need not in general be prime, |
26 | 26 | 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<ZZ_p></tt> (a.k.a., <tt>vec_ZZ_p</tt>), | |
28 | <tt>Mat<ZZ_p></tt> (a.k.a., <tt>mat_ZZ_p</tt>), | |
28 | 29 | and <tt>ZZ_pX</tt> represent vectors, matrices, and polynomials |
29 | 30 | mod <tt>p</tt>, and work much the same way as the corresponding |
30 | 31 | classes for <tt>ZZ</tt>. |
37 | 38 | <pre> |
38 | 39 | #include <NTL/ZZ_pXFactoring.h> |
39 | 40 | |
40 | NTL_CLIENT | |
41 | using namespace std; | |
42 | using namespace NTL; | |
41 | 43 | |
42 | 44 | int main() |
43 | 45 | { |
48 | 50 | ZZ_pX f; |
49 | 51 | cin >> f; |
50 | 52 | |
51 | vec_pair_ZZ_pX_long factors; | |
53 | Vec< Pair< ZZ_pX, long > > factors; | |
52 | 54 | |
53 | 55 | CanZass(factors, f); // calls "Cantor/Zassenhaus" algorithm |
54 | 56 | |
69 | 71 | NTL does not make any attempt to ensure that |
70 | 72 | variables declared under one modulus are not used |
71 | 73 | 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. | |
74 | 76 | |
75 | 77 | |
76 | 78 | <p> <hr> <p> |
81 | 83 | |
82 | 84 | <p> |
83 | 85 | <pre> |
84 | #include <NTL/vec_ZZ_p.h> | |
85 | ||
86 | NTL_CLIENT | |
87 | ||
88 | void add(vec_ZZ_p& x, const vec_ZZ_p& a, const vec_ZZ_p& b) | |
86 | #include <NTL/ZZ_p.h> | |
87 | ||
88 | using namespace std; | |
89 | using namespace NTL; | |
90 | ||
91 | void add(Vec<ZZ_p>& x, const Vec<ZZ_p>& a, const Vec<ZZ_p>& b) | |
89 | 92 | { |
90 | 93 | long n = a.length(); |
91 | 94 | if (b.length() != n) Error("vector add: dimension mismatch"); |
103 | 106 | |
104 | 107 | <p> |
105 | 108 | <pre> |
106 | #include <NTL/vec_ZZ_p.h> | |
107 | ||
108 | NTL_CLIENT | |
109 | ||
110 | void InnerProduct(ZZ_p& x, const vec_ZZ_p& a, const vec_ZZ_p& b) | |
109 | #include <NTL/ZZ_p.h> | |
110 | ||
111 | using namespace std; | |
112 | using namespace NTL; | |
113 | ||
114 | void InnerProduct(ZZ_p& x, const Vec<ZZ_p>& a, const Vec<ZZ_p>& b) | |
111 | 115 | { |
112 | 116 | long n = min(a.length(), b.length()); |
113 | 117 | long i; |
114 | 118 | ZZ accum, t; |
115 | 119 | |
116 | 120 | accum = 0; |
117 | for (i = 0; i < n; i++) { | |
121 | for (i = 0; i < n; i++) { | |
118 | 122 | mul(t, rep(a[i]), rep(b[i])); |
119 | 123 | add(accum, accum, t); |
120 | 124 | } |
146 | 150 | when you want to work with vectors, matrices, or polynomials |
147 | 151 | mod <tt>p</tt>. |
148 | 152 | 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. | |
150 | 154 | This is especially true if you want to work with many different |
151 | 155 | moduli: modulus switching is supported, but it is a bit awkward. |
152 | 156 | |
161 | 165 | see <a href="ZZ_pX.txt"><tt>ZZ_pX.txt</tt></a> for details on <tt>ZZ_pX</tt>; |
162 | 166 | see <a href="ZZ_pXFactoring.txt"><tt>ZZ_pXFactoring.txt</tt></a> for details on |
163 | 167 | 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<ZZ_p></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<ZZ_p></tt>'s. | |
166 | 172 | |
167 | 173 | <p> <hr> <p> |
168 | 174 | |
177 | 183 | #include <NTL/ZZX.h> |
178 | 184 | #include <NTL/ZZ_pXFactoring.h> |
179 | 185 | |
180 | NTL_CLIENT | |
186 | using namespace std; | |
187 | using namespace NTL; | |
181 | 188 | |
182 | 189 | long IrredTestMod(const ZZX& f, const ZZ& p) |
183 | 190 | { |
186 | 193 | |
187 | 194 | ZZ_p::init(p); // set the current modulus to p |
188 | 195 | |
189 | return DetIrredTest(to_ZZ_pX(f)); | |
196 | return DetIrredTest(conv<ZZ_pX>(f)); | |
190 | 197 | |
191 | 198 | // old modulus is restored automatically when bak is destroyed |
192 | 199 | // upon return |
198 | 205 | more general and flexible than this example illustrates. |
199 | 206 | |
200 | 207 | <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<ZZ_pX></tt>. | |
203 | 210 | We could also have used the equivalent procedural form: |
204 | 211 | <pre> |
205 | 212 | ZZ_pX f1; |
218 | 225 | to be a small, single-precision prime. |
219 | 226 | In this case, NTL provides a class <tt>zz_p</tt>, that |
220 | 227 | 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<zz_p></tt>, | |
229 | <tt>Mat<zz_p></tt>, and <tt>zz_pX</tt>. | |
223 | 230 | The interfaces to all of the routines are generally identical |
224 | 231 | to those for <tt>ZZ_p</tt>. |
225 | 232 | However, the routines are much more efficient, in both time and space. |
234 | 241 | #include <NTL/ZZX.h> |
235 | 242 | #include <NTL/lzz_pXFactoring.h> |
236 | 243 | |
237 | NTL_CLIENT | |
244 | using namespace std; | |
245 | using namespace NTL; | |
238 | 246 | |
239 | 247 | long IrredTestMod(const ZZX& f, long p) |
240 | 248 | { |
243 | 251 | |
244 | 252 | zz_p::init(p); |
245 | 253 | |
246 | return DetIrredTest(to_zz_pX(f)); | |
254 | return DetIrredTest(conv<zz_pX>(f)); | |
247 | 255 | } |
248 | 256 | </pre> |
249 | 257 | |
260 | 268 | <pre> |
261 | 269 | #include <NTL/ZZX.h> |
262 | 270 | |
263 | NTL_CLIENT | |
271 | using namespace std; | |
272 | using namespace NTL; | |
264 | 273 | |
265 | 274 | void GCD(ZZX& d, const ZZX& a, const ZZX& b) |
266 | 275 | { |
360 | 369 | Arithmetic mod 2 is such an important special case that NTL |
361 | 370 | provides a class <tt>GF2</tt>, that |
362 | 371 | 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<GF2></tt>, | |
373 | <tt>Mat<GF2></tt>, and <tt>GF2X</tt>. | |
365 | 374 | The interfaces to all of the routines are generally identical |
366 | 375 | to those for <tt>ZZ_p</tt>. |
367 | 376 | However, the routines are much more efficient, in both time and space. |
368 | 377 | |
369 | <p> | |
370 | ||
371 | This example illustrates the <tt>GF2X</tt> and <tt>mat_GF2</tt> | |
378 | Note that <tt>Vec<GF2></tt> is an explicit specialization | |
379 | of the template class <tt>Vec<T></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><NTL/vec_GF2.h></tt> | |
383 | to use the class <tt>Vec<GF2></tt>. | |
384 | ||
385 | <p> | |
386 | ||
387 | This example illustrates the <tt>GF2X</tt> and <tt>Mat<GF2></tt> | |
372 | 388 | classes with a simple routine to test if a polynomial over GF(2) |
373 | 389 | is irreducible using linear algebra. |
374 | 390 | NTL's built-in irreducibility test is to be preferred, however. |
378 | 394 | #include <NTL/GF2X.h> |
379 | 395 | #include <NTL/mat_GF2.h> |
380 | 396 | |
381 | NTL_CLIENT | |
382 | ||
383 | long MatIrredTest(const GF2X& f) | |
397 | using namespace std; | |
398 | using namespace NTL; | |
399 | ||
400 | long MatIrredTest(const GF2X& f) | |
384 | 401 | { |
385 | 402 | long n = deg(f); |
386 | 403 | |
389 | 406 | |
390 | 407 | if (GCD(f, diff(f)) != 1) return 0; |
391 | 408 | |
392 | mat_GF2 M; | |
409 | Mat<GF2> M; | |
393 | 410 | |
394 | 411 | M.SetDims(n, n); |
395 | 412 |
31 | 31 | |
32 | 32 | int main() |
33 | 33 | { |
34 | ZZ_p::init(to_ZZ(17)); // define GF(17) | |
34 | ZZ_p::init(conv<ZZ>(17)); // define GF(17) | |
35 | 35 | |
36 | 36 | ZZ_pX P; |
37 | 37 | BuildIrred(P, 10); // generate an irreducible polynomial P |
374 | 374 | <a href="matrix.txt"><tt>matrix</tt></a> |
375 | 375 | |
376 | 376 | </b> <td> |
377 | template-like macros for | |
377 | template class for | |
378 | 378 | dynamic-size 2-dimensional arrays |
379 | 379 | |
380 | 380 | <!-- ----------- mat_GF2.txt ----------- --> |
514 | 514 | <a href="pair.txt"><tt>pair</tt></a> |
515 | 515 | |
516 | 516 | </b> <td> |
517 | template-like macros for | |
517 | template class for | |
518 | 518 | pairs |
519 | 519 | |
520 | 520 | |
543 | 543 | <a href="vector.txt"><tt>vector</tt></a> |
544 | 544 | |
545 | 545 | </b> <td> |
546 | template-like macros for | |
546 | template class for | |
547 | 547 | dynamic-size vectors |
548 | 548 | |
549 | 549 | <!-- ----------- vec_GF2.txt ----------- --> |
666 | 666 | |
667 | 667 | These decalarations are found in "<tt>.h</tt>" files with |
668 | 668 | 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<double></tt>, | |
675 | and <tt>vec_vec_RR</tt> is a typedef for | |
676 | <tt>Vec< Vec<RR> ></tt>. | |
669 | 677 | No additional functionality is provided. |
670 | 678 | |
671 | 679 | <p> |
672 | 680 | 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>, | |
674 | 683 | <tt>vec_ZZX</tt>, etc. |
675 | 684 | |
676 | 685 | <p> |
693 | 702 | |
694 | 703 | These decalarations are found in "<tt>.h</tt>" files with |
695 | 704 | 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<GF2EX,long></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< <tt>Pair<GF2EX,long> ></tt>. | |
698 | 713 | No additional functionality is provided. |
699 | 714 | |
700 | 715 |
620 | 620 | </h3> |
621 | 621 | |
622 | 622 | <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. | |
665 | 636 | |
666 | 637 | |
667 | 638 |
168 | 168 | |
169 | 169 | Third, there are a number of conversion functions (see below), whose name |
170 | 170 | 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<T></tt>, where <tt>T</tt> is the return type: | |
172 | 172 | |
173 | 173 | <pre> |
174 | 174 | ZZ x; |
175 | 175 | double a; |
176 | 176 | |
177 | x = to_ZZ(a); // functional form | |
178 | conv(x, a); // procedural form | |
177 | x = conv<ZZ>(a); // functional form | |
178 | conv(x, a); // procedural form | |
179 | 179 | </pre> |
180 | 180 | |
181 | 181 | |
206 | 206 | </h3> |
207 | 207 | <p> |
208 | 208 | |
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 | ||
256 | 209 | As mentioned above, there are numerous explicit conversion routines, |
257 | 210 | which come in both functional and procedural forms. |
258 | 211 | A complete list of these can be found in |
259 | 212 | <a href="conversions.txt">conversions.txt</a>. |
260 | 213 | 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<ZZ></tt> to <tt>Vec<RR></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. | |
268 | 231 | This is because all of the basic arithmetic operations |
269 | 232 | (in both their functional and procedural forms), |
270 | 233 | comparison operators, and assignment are overloaded |
296 | 259 | This means that in addition to the declared function, there |
297 | 260 | are two other functions that are logically equivalent to the following: |
298 | 261 | <pre> |
299 | ZZ operator+(long a, const ZZ& b) { return to_ZZ(a) + b; } | |
300 | ZZ operator+(const ZZ& a, long b) { return a + to_ZZ(b); } | |
262 | ZZ operator+(long a, const ZZ& b) { return conv<ZZ>(a) + b; } | |
263 | ZZ operator+(const ZZ& a, long b) { return a + conv<ZZ>(b); } | |
301 | 264 | </pre> |
302 | 265 | |
303 | 266 | <p> |
308 | 271 | </pre> |
309 | 272 | than it is to write |
310 | 273 | <pre> |
311 | x = y + to_ZZ(2); | |
274 | x = y + conv<ZZ>(2); | |
312 | 275 | </pre> |
313 | 276 | The former notation avoids the creation and destruction |
314 | 277 | of a temporary <tt>ZZ</tt> |
365 | 328 | ZZ_p: long |
366 | 329 | ZZ_pX: long, ZZ_p |
367 | 330 | zz_p: long |
368 | ZZ_pX: long, zz_p | |
331 | zz_pX: long, zz_p | |
369 | 332 | ZZX: long, ZZ |
370 | 333 | GF2: long |
371 | 334 | GF2X: long, GF2 |
433 | 396 | Matrix by scalar and vector by scalar multiplication promote the scalar. |
434 | 397 | E.g., |
435 | 398 | <pre> |
436 | vec_ZZ v, w; | |
399 | Vec<ZZ> v, w; | |
437 | 400 | ... |
438 | 401 | v = w*2; |
439 | 402 | v = 2*w; |
495 | 458 | </pre> |
496 | 459 | One could also use an explicit conversion function: |
497 | 460 | <pre> |
498 | a = a + to_ZZ(x); | |
461 | a = a + conv<ZZ>(x); | |
499 | 462 | </pre> |
500 | 463 | The second version guarantees that there is no loss of precision, |
501 | 464 | and also guarantees that the floor of <tt>x</tt> is computed. |
523 | 486 | |
524 | 487 | <p> |
525 | 488 | |
526 | Another pitfall too avoid is initialzing <tt>ZZ</tt>s | |
489 | Another pitfall too avoid is initialzing <tt>ZZ</tt>'s | |
527 | 490 | with integer constants that are too big. |
528 | 491 | Consider the following: |
529 | 492 | <pre> |
537 | 500 | program is as follows: |
538 | 501 | <pre> |
539 | 502 | ZZ x; |
540 | x = to_ZZ("1234567890123456789012"); | |
503 | x = conv<ZZ>("1234567890123456789012"); | |
541 | 504 | </pre> |
542 | 505 | Conversion functions are provided for converting <tt>C</tt> character strings |
543 | 506 | to the types <tt>ZZ</tt>, <tt>RR</tt>, <tt>quad_float</tt>, |
546 | 509 | <p> |
547 | 510 | One should also be careful when converting to <tt>RR</tt>. |
548 | 511 | 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. | |
550 | 513 | |
551 | 514 | <p> |
552 | 515 | <p> |
556 | 519 | <p> |
557 | 520 | |
558 | 521 | 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 | |
560 | 523 | write <tt>mul(x, a, b)</tt>, then <tt>a</tt> or <tt>b</tt> |
561 | 524 | may alias (have the same address as) <tt>x</tt> |
562 | 525 | (or any object that <tt>x</tt> contains, e.g., scalar/vector |
563 | 526 | 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. | |
564 | 532 | |
565 | 533 | |
566 | 534 | <p> |
614 | 582 | For example, the global declarations |
615 | 583 | <pre> |
616 | 584 | ZZ global_integer; |
617 | vec_ZZ_p global_vector; | |
585 | Vec<ZZ_p> global_vector; | |
618 | 586 | </pre> |
619 | 587 | should always work, since their initialization only involves |
620 | 588 | setting a pointer to 0. |
635 | 603 | There is, however, one possible exception to this. |
636 | 604 | A programmer might want to have a global constant initialized like this: |
637 | 605 | <pre> |
638 | const quad_float Pi = to_quad_float("3.1415926535897932384626433832795029"); | |
606 | const quad_float Pi = conv<quad_float>("3.1415926535897932384626433832795029"); | |
639 | 607 | </pre> |
640 | 608 | While this probably will work fine on most platforms, |
641 | 609 | it may not be an entirely portable construction, |
648 | 616 | const quad_float& Pi() |
649 | 617 | { |
650 | 618 | static quad_float pi = |
651 | to_quad_float("3.1415926535897932384626433832795029"); | |
619 | conv<quad_float>("3.1415926535897932384626433832795029"); | |
652 | 620 | return pi; |
653 | 621 | } |
654 | 622 | </pre> |
4 | 4 | |
5 | 5 | SUMMARY: |
6 | 6 | |
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. | |
38 | 24 | |
39 | 25 | As an alternative, one can use the get and put methods below to access |
40 | 26 | vector elements. |
41 | 27 | |
42 | 28 | 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 | |
44 | 30 | length is increased (via SetLength), the "new" bits are always 0. |
45 | 31 | For example, if v.length() == 20, then |
46 | 32 | |
57 | 43 | |
58 | 44 | |
59 | 45 | |
60 | class vec_GF2 { | |
46 | template<> | |
47 | class Vec<GF2> { | |
61 | 48 | |
62 | 49 | public: |
63 | 50 | |
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 | |
71 | 58 | |
72 | 59 | void SetLength(long n); // set length to n bits |
73 | 60 | void SetMaxLength(long n); // allocate space for n bits |
94 | 81 | |
95 | 82 | void kill(); // free space and make length 0 |
96 | 83 | |
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) | |
98 | 85 | |
99 | 86 | void put(long i, GF2 a); // write value a to index i (indexing from 0) |
100 | 87 | void put(long i, long a); |
101 | 88 | |
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 | ||
112 | 107 | |
113 | 108 | }; |
114 | 109 | |
115 | 110 | |
116 | void swap(vec_GF2& x, vec_GF2& y); | |
111 | ||
112 | void swap(Vec<GF2>& x, Vec<GF2>& y); | |
117 | 113 | // swap x and y (fast pointer swap) |
118 | 114 | |
119 | void append(vec_GF2& v, GF2 a); | |
115 | void append(Vec<GF2>& v, const GF2& a); | |
120 | 116 | // append a to v |
121 | 117 | |
122 | void append(vec_GF2& v, const vec_GF2& a); | |
118 | void append(Vec<GF2>& v, const Vec<GF2>& a); | |
123 | 119 | // append a to v |
124 | 120 | |
125 | 121 | // equality operators: |
126 | 122 | |
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); | |
129 | 125 | |
130 | 126 | |
131 | 127 | // I/O operators: |
132 | 128 | |
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); | |
135 | 131 | |
136 | 132 | // The I/O format is [a_0 a_1 ... a_{n-1}], where each a_i is "0" or "1". |
137 | 133 | // 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 | |
138 | 138 | |
139 | 139 | // utility routines: |
140 | 140 | |
170 | 170 | void mul(vec_GF2& x, long a, const vec_GF2& b); |
171 | 171 | // x = a * b |
172 | 172 | |
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); | |
174 | 174 | // vectors may differ in length |
175 | 175 | |
176 | 176 | void VectorCopy(vec_GF2& x, const vec_GF2& a, long n); |
11 | 11 | #include <NTL/GF2E.h> |
12 | 12 | #include <NTL/vector.h> |
13 | 13 | |
14 | NTL_vector_decl(GF2E,vec_GF2E) | |
15 | 14 | |
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 | |
21 | 16 | |
22 | 17 | void mul(vec_GF2E& x, const vec_GF2E& a, const GF2E& b); |
23 | 18 | void mul(vec_GF2E& x, const vec_GF2E& a, GF2 b); |
8 | 8 | |
9 | 9 | \**************************************************************************/ |
10 | 10 | |
11 | NTL_vector_decl(RR,vec_RR) | |
12 | 11 | |
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 | |
18 | 13 | |
19 | 14 | void mul(vec_RR& x, const vec_RR& a, const RR& b); |
20 | 15 | void mul(vec_RR& x, const vec_RR& a, double b); |
8 | 8 | |
9 | 9 | \**************************************************************************/ |
10 | 10 | |
11 | NTL_vector_decl(ZZ,vec_ZZ) | |
12 | 11 | |
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 | |
18 | 13 | |
19 | 14 | void mul(vec_ZZ& x, const vec_ZZ& a, const ZZ& b); |
20 | 15 | void mul(vec_ZZ& x, const vec_ZZ& a, long b); |
12 | 12 | #include <NTL/vec_ZZ.h> |
13 | 13 | #include <NTL/vector.h> |
14 | 14 | |
15 | NTL_vector_decl(ZZ_p,vec_ZZ_p) | |
16 | 15 | |
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 | |
22 | 17 | |
23 | 18 | void mul(vec_ZZ_p& x, const vec_ZZ_p& a, const ZZ_p& b); |
24 | 19 | void mul(vec_ZZ_p& x, const vec_ZZ_p& a, long b); |
12 | 12 | #include <NTL/vec_ZZ.h> |
13 | 13 | #include <NTL/vector.h> |
14 | 14 | |
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 | |
22 | 16 | |
23 | 17 | void mul(vec_ZZ_pE& x, const vec_ZZ_pE& a, const ZZ_pE& b); |
24 | 18 | void mul(vec_ZZ_pE& x, const vec_ZZ_pE& a, const ZZ_p& b); |
12 | 12 | #include "vec_zz.h" |
13 | 13 | #include <NTL/vector.h> |
14 | 14 | |
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 | |
22 | 16 | |
23 | 17 | void mul(vec_zz_p& x, const vec_zz_p& a, zz_p b); |
24 | 18 | void mul(vec_zz_p& x, const vec_zz_p& a, long b); |
12 | 12 | #include <NTL/vec_ZZ.h> |
13 | 13 | #include <NTL/vector.h> |
14 | 14 | |
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 | |
22 | 16 | |
23 | 17 | void mul(vec_zz_pE& x, const vec_zz_pE& a, const zz_pE& b); |
24 | 18 | void mul(vec_zz_pE& x, const vec_zz_pE& a, const zz_p& b); |
5 | 5 | |
6 | 6 | SUMMARY: |
7 | 7 | |
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. | |
26 | 9 | |
27 | 10 | The declaration |
28 | 11 | |
29 | vec_T v; | |
12 | Vec<T> v; | |
30 | 13 | |
31 | 14 | creates a zero-length vector. To grow this vector to length n, |
32 | 15 | execute |
55 | 38 | |
56 | 39 | v.MaxLength() is the largest value of n for which v.SetLength(n) was invoked, |
57 | 40 | 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(). | |
60 | 43 | |
61 | 44 | When v's destructor is called, all constructed elements will be |
62 | 45 | destructed, and all space will be relinquished. |
83 | 66 | |
84 | 67 | \**************************************************************************/ |
85 | 68 | |
86 | class vec_T { | |
69 | template<class T> | |
70 | class Vec { | |
87 | 71 | public: |
88 | 72 | |
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); | |
92 | 76 | // copy constructor; currently, this is implemented by |
93 | 77 | // initializing elements using T's defaults constructor and |
94 | 78 | // copying elements from a using T's assigment operator. |
95 | 79 | |
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 | |
98 | 82 | // using T's assignment operator. |
99 | 83 | |
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 | |
101 | 87 | |
102 | 88 | void SetLength(long n); |
103 | 89 | // set current length to n, growing vector if necessary |
104 | 90 | |
105 | 91 | long length() const; |
106 | 92 | // current length |
107 | // SIZE INVARIANT: length()*sizeof(T) < 2^(NTL_BITS_PER_LONG-4) | |
108 | 93 | |
109 | 94 | T& operator[](long i); |
110 | 95 | const T& operator[](long i) const; |
111 | 96 | // 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>, | |
113 | 98 | // 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. | |
115 | 100 | |
116 | 101 | T& operator()(long i); |
117 | 102 | const T& operator()(long i) const; |
118 | 103 | // 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>, | |
120 | 105 | // 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. | |
122 | 107 | |
123 | 108 | T* elts(); |
124 | 109 | const T* elts() const; |
125 | 110 | // returns address of first vector element (or 0 if no space has |
126 | 111 | // been allocated for this vector). If a vector potentially has |
127 | 112 | // 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>, | |
129 | 114 | // 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. | |
138 | 158 | |
139 | 159 | void kill(); |
140 | 160 | // release space and set to length 0 |
170 | 190 | |
171 | 191 | long position(const T& a) const; |
172 | 192 | // 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, | |
174 | 194 | // and an error is raised if the object is found at position MaxLength() |
175 | 195 | // or higher (in which case a references an uninitialized object). |
176 | 196 | // Note that if NTL_CLEAN_PTR flag is set, this routine takes |
192 | 212 | \**************************************************************************/ |
193 | 213 | |
194 | 214 | |
195 | void swap(vec_T& x, vec_T& y); | |
215 | template<class T> | |
216 | void swap(Vec<T>& x, Vec<T>& y); | |
196 | 217 | // swaps x & y by swapping pointers |
197 | 218 | |
198 | void append(vec_T& v, const T& a); | |
219 | template<class T> | |
220 | void append(Vec<T>& v, const T& a); | |
199 | 221 | // appends a to the end of v |
200 | 222 | |
201 | void append(vec_T& v, const vec_T& w); | |
223 | template<class T> | |
224 | void append(Vec<T>& v, const Vec<T>& w); | |
202 | 225 | // appends w to the end of v |
203 | 226 | |
204 | 227 | |
208 | 231 | |
209 | 232 | Input/Output |
210 | 233 | |
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. | |
214 | 234 | |
215 | 235 | The I/O format for a vector v with n elements is: |
216 | 236 | |
218 | 238 | |
219 | 239 | \**************************************************************************/ |
220 | 240 | |
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>&); | |
223 | 246 | |
224 | 247 | |
225 | 248 | |
227 | 250 | |
228 | 251 | Equality Testing |
229 | 252 | |
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); | |
240 | 261 | |
241 | 262 | |
242 | 263 | /**************************************************************************\ |
258 | 279 | is called, whose default implementation invokes the default destructor |
259 | 280 | for T n times. |
260 | 281 | |
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 | ||
266 | 285 | For an example of this, see vec_ZZ_p.c. |
267 | 286 | |
268 | 287 | \**************************************************************************/ |
2 | 2 | #ifndef NTL_FFT__H |
3 | 3 | #define NTL_FFT__H |
4 | 4 | |
5 | #include <NTL/ZZ.h> | |
6 | #include <NTL/vector.h> | |
5 | 7 | #include <NTL/vec_long.h> |
6 | #include <NTL/ZZ.h> | |
7 | 8 | |
8 | 9 | NTL_OPEN_NNS |
9 | 10 | |
31 | 32 | // This can be increased, with a slight performance penalty. |
32 | 33 | |
33 | 34 | |
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 | |
34 | 81 | |
35 | 82 | extern long NumFFTPrimes; |
36 | ||
37 | 83 | extern long *FFTPrime; |
38 | extern long **RootTable; | |
39 | extern long **RootInvTable; | |
40 | extern long **TwoInvTable; | |
41 | 84 | extern double *FFTPrimeInv; |
42 | 85 | |
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 | *****************/ | |
57 | 86 | |
58 | 87 | |
59 | 88 | long CalcMaxRoot(long p); |
66 | 95 | void FFT(long* A, const long* a, long k, long q, const long* root); |
67 | 96 | // the low-level FFT routine. |
68 | 97 | // 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 | ||
69 | 143 | |
70 | 144 | NTL_CLOSE_NNS |
71 | 145 |
16 | 16 | }; |
17 | 17 | |
18 | 18 | |
19 | NTL_vector_decl(IntFactor,vec_IntFactor) | |
19 | typedef Vec<IntFactor> vec_IntFactor; | |
20 | 20 | typedef vec_IntFactor FacVec; |
21 | 21 | |
22 | 22 | void FactorInt(FacVec& fvec, long n); |
2 | 2 | #define NTL_GF2__H |
3 | 3 | |
4 | 4 | #include <NTL/ZZ.h> |
5 | #include <NTL/vector.h> | |
5 | 6 | |
6 | 7 | NTL_OPEN_NNS |
7 | 8 | |
8 | 9 | class GF2 { |
9 | 10 | public: |
10 | 11 | |
11 | long _GF2__rep; | |
12 | ||
13 | ||
14 | GF2() { _GF2__rep = 0; } | |
15 | ||
12 | unsigned long _GF2__rep; | |
13 | ||
14 | ||
15 | GF2() : _GF2__rep(0) { } | |
16 | 16 | GF2(const GF2& a) : _GF2__rep(a._GF2__rep) { } |
17 | 17 | |
18 | GF2(INIT_VAL_TYPE, long a) : _GF2__rep(a & 1) { } | |
19 | GF2(INIT_LOOP_HOLE_TYPE, unsigned long a) : _GF2__rep(a) { } | |
20 | ||
18 | 21 | ~GF2() { } |
19 | 22 | |
20 | 23 | GF2& operator=(const GF2& a) { _GF2__rep = a._GF2__rep; return *this; } |
21 | ||
22 | 24 | GF2& operator=(long a) { _GF2__rep = a & 1; return *this; } |
23 | 25 | |
24 | 26 | static long modulus() { return 2; } |
26 | 28 | |
27 | 29 | }; |
28 | 30 | |
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 | ||
30 | 104 | 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 | ||
34 | 107 | 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 | ||
66 | 112 | |
67 | 113 | 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); } | |
69 | 115 | |
70 | 116 | inline GF2 operator+(GF2 a, long b) |
71 | { GF2 x; add(x, a, b); return x; } | |
117 | { return a + to_GF2(b); } | |
72 | 118 | |
73 | 119 | inline GF2 operator+(long a, GF2 b) |
74 | { GF2 x; add(x, a, b); return x; } | |
120 | { return to_GF2(a) + b; } | |
75 | 121 | |
76 | 122 | inline GF2 operator-(GF2 a, GF2 b) |
77 | { GF2 x; sub(x, a, b); return x; } | |
123 | { return a + b; } | |
78 | 124 | |
79 | 125 | inline GF2 operator-(GF2 a, long b) |
80 | { GF2 x; sub(x, a, b); return x; } | |
126 | { return a + b; } | |
81 | 127 | |
82 | 128 | inline GF2 operator-(long a, GF2 b) |
83 | { GF2 x; sub(x, a, b); return x; } | |
129 | { return a + b; } | |
84 | 130 | |
85 | 131 | 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 | ||
117 | 134 | |
118 | 135 | inline GF2 sqr(GF2 a) |
119 | 136 | { return a; } |
120 | 137 | |
121 | 138 | 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); } | |
123 | 140 | |
124 | 141 | inline GF2 operator*(GF2 a, long b) |
125 | { GF2 x; mul(x, a, b); return x; } | |
142 | { return a * to_GF2(b); } | |
126 | 143 | |
127 | 144 | 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 | ||
144 | 166 | 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 | ||
174 | 174 | |
175 | 175 | inline long operator==(GF2 a, GF2 b) |
176 | 176 | { return a._GF2__rep == b._GF2__rep; } |
177 | 177 | |
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); } | |
184 | 186 | inline long operator!=(GF2 a, long b) { return !(a == b); } |
185 | 187 | inline long operator!=(long a, GF2 b) { return !(a == b); } |
186 | 188 | |
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 | ||
187 | 299 | 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 | |
192 | 414 | |
193 | 415 | NTL_SNS ostream& operator<<(NTL_SNS ostream& s, GF2 a); |
194 | 416 | |
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>; | |
196 | 437 | |
197 | 438 | NTL_CLOSE_NNS |
198 | 439 |
415 | 415 | |
416 | 416 | // ****** trace |
417 | 417 | |
418 | inline void trace(GF2& x, const GF2E& a) | |
418 | inline void trace(ref_GF2 x, const GF2E& a) | |
419 | 419 | { TraceMod(x, a._GF2E__rep, GF2E::modulus()); } |
420 | 420 | inline GF2 trace(const GF2E& a) |
421 | 421 | { return TraceMod(a._GF2E__rep, GF2E::modulus()); } |
444 | 444 | inline GF2E& GF2E::operator=(long a) { conv(*this, a); return *this; } |
445 | 445 | inline GF2E& GF2E::operator=(GF2 a) { conv(*this, a); return *this; } |
446 | 446 | |
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 | ||
447 | 464 | NTL_CLOSE_NNS |
448 | 465 | |
449 | 466 | #endif |
54 | 54 | |
55 | 55 | { rep.kill(); } |
56 | 56 | |
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 | ||
57 | 67 | static const GF2EX& zero(); |
58 | 68 | |
59 | 69 | |
240 | 250 | { GF2EX x; conv(x, a); NTL_OPT_RETURN(GF2EX, x); } |
241 | 251 | |
242 | 252 | #ifndef NTL_TRANSITION |
243 | inline GF2EX to_GF2EX(GF2X& a) | |
253 | inline GF2EX to_GF2EX(const GF2X& a) | |
244 | 254 | { GF2EX x; conv(x, a); NTL_OPT_RETURN(GF2EX, x); } |
245 | 255 | #endif |
246 | 256 | |
250 | 260 | inline GF2EX& GF2EX::operator=(const GF2E& a) { conv(*this, a); return *this; } |
251 | 261 | inline GF2EX& GF2EX::operator=(GF2 a) { conv(*this, a); return *this; } |
252 | 262 | 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 | ||
253 | 281 | |
254 | 282 | |
255 | 283 | |
699 | 727 | |
700 | 728 | |
701 | 729 | |
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; | |
709 | 731 | |
710 | 732 | |
711 | 733 |
35 | 35 | |
36 | 36 | void SetMaxLength(long n); |
37 | 37 | |
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 | ||
38 | 48 | static long HexOutput; |
39 | 49 | |
40 | 50 | inline GF2X(long i, GF2 c); |
51 | 61 | |
52 | 62 | long IsX(const GF2X& a); |
53 | 63 | |
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); | |
59 | 69 | |
60 | 70 | |
61 | 71 | inline void clear(GF2X& x) |
242 | 252 | |
243 | 253 | |
244 | 254 | |
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; | |
251 | 256 | |
252 | 257 | void LeftShift(GF2X& c, const GF2X& a, long n); |
253 | 258 | inline GF2X LeftShift(const GF2X& a, long n) |
514 | 519 | inline vec_GF2 to_vec_GF2(const GF2X& a) |
515 | 520 | { vec_GF2 x; conv(x, a); NTL_OPT_RETURN(vec_GF2, x); } |
516 | 521 | |
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 | ||
517 | 540 | inline GF2X& GF2X::operator=(long a) |
518 | 541 | { conv(*this, a); return *this; } |
519 | 542 | |
618 | 641 | const GF2XTransMultiplier& B, const GF2XModulus& F) |
619 | 642 | { vec_GF2 x; UpdateMap(x, a, B, F); NTL_OPT_RETURN(vec_GF2, x); } |
620 | 643 | |
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) | |
622 | 645 | { x = to_GF2(InnerProduct(a.rep, b.xrep)); } |
623 | 646 | |
624 | 647 | inline GF2 project(const vec_GF2& a, const GF2X& b) |
647 | 670 | { vec_GF2 x; TraceVec(x, f); NTL_OPT_RETURN(vec_GF2, x); } |
648 | 671 | |
649 | 672 | |
650 | void TraceMod(GF2& x, const GF2X& a, const GF2XModulus& F); | |
673 | void TraceMod(ref_GF2 x, const GF2X& a, const GF2XModulus& F); | |
651 | 674 | |
652 | 675 | inline GF2 TraceMod(const GF2X& a, const GF2XModulus& F) |
653 | 676 | { GF2 x; TraceMod(x, a, F); return x; } |
654 | 677 | |
655 | void TraceMod(GF2& x, const GF2X& a, const GF2X& f); | |
678 | void TraceMod(ref_GF2 x, const GF2X& a, const GF2X& f); | |
656 | 679 | |
657 | 680 | inline GF2 TraceMod(const GF2X& a, const GF2X& f) |
658 | 681 | { GF2 x; TraceMod(x, a, f); return x; } |
423 | 423 | inline ZZ FloorToZZ(const RR& a) |
424 | 424 | { ZZ z; conv(z, a); NTL_OPT_RETURN(ZZ, z); } |
425 | 425 | |
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 | ||
426 | 438 | void MakeRR(RR& z, const ZZ& a, long e); |
427 | 439 | inline RR MakeRR(const ZZ& a, long e) |
428 | 440 | { RR z; MakeRR(z, a, e); NTL_OPT_RETURN(RR, z); } |
64 | 64 | |
65 | 65 | |
66 | 66 | |
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; } | |
70 | 70 | |
71 | 71 | WordVector& operator=(const WordVector& a); |
72 | 72 |
29 | 29 | // May be private in future versions. |
30 | 30 | |
31 | 31 | |
32 | ZZ() | |
32 | ZZ() : rep(0) { } | |
33 | 33 | // initial value is 0. |
34 | 34 | |
35 | { rep = 0; } | |
36 | ||
37 | ||
38 | ZZ(INIT_SIZE_TYPE, long k) | |
35 | ||
36 | ZZ(INIT_SIZE_TYPE, long k) : rep(0) | |
39 | 37 | // initial value is 0, but space is pre-allocated so that numbers |
40 | 38 | // x with x.size() <= k can be stored without re-allocation. |
41 | 39 | // Call with ZZ(INIT_SIZE, k). |
44 | 42 | |
45 | 43 | |
46 | 44 | { |
47 | rep = 0; | |
48 | 45 | NTL_zsetlength(&rep, k); |
49 | 46 | } |
50 | 47 | |
51 | ZZ(const ZZ& a) | |
48 | ZZ(const ZZ& a) : rep(0) | |
52 | 49 | // initial value is a. |
53 | 50 | |
54 | 51 | { |
55 | rep = 0; | |
56 | 52 | NTL_zcopy(a.rep, &rep); |
57 | 53 | } |
58 | 54 | |
59 | 55 | |
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); } | |
65 | 61 | |
66 | 62 | inline ZZ(INIT_VAL_TYPE, const char *); |
67 | 63 | inline ZZ(INIT_VAL_TYPE, float); |
88 | 84 | { NTL_zsetlength(&rep, k); } |
89 | 85 | |
90 | 86 | long size() const |
87 | // returns the number of (NTL_ZZ_NBIT-bit) digits of |a|; the size of 0 is 0. | |
91 | 88 | { return NTL_zsize(rep); } |
92 | 89 | |
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); } | |
94 | 97 | |
95 | 98 | |
96 | 99 | long SinglePrecision() const |
165 | 168 | inline ZZ to_ZZ(unsigned int a) { return ZZ(INIT_VAL, a); } |
166 | 169 | |
167 | 170 | 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); } | |
169 | 172 | inline ZZ to_ZZ(const char *s) { return ZZ(INIT_VAL, s); } |
170 | 173 | |
171 | 174 | 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); } | |
173 | 176 | inline ZZ to_ZZ(double a) { return ZZ(INIT_VAL, a); } |
174 | 177 | |
175 | 178 | 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); } | |
177 | 180 | inline ZZ to_ZZ(float a) { return ZZ(INIT_VAL, a); } |
178 | 181 | |
179 | 182 | inline void conv(long& x, const ZZ& a) { x = NTL_ztoint(a.rep); } |
1722 | 1725 | // significantly faster. There are four possible implementations: |
1723 | 1726 | // - default: uses MulMod2 above (lots of floating point) |
1724 | 1727 | // - 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) | |
1726 | 1729 | // - NTL_SPMM_UL: uses only unsigned long arithmetic (portable, slower). |
1727 | 1730 | |
1728 | 1731 | #if (!defined(NTL_SINGLE_MUL) && (defined(NTL_SPMM_ULL) || defined(NTL_SPMM_ASM))) |
2014 | 2017 | // computes a^e mod n, e >= 0 |
2015 | 2018 | |
2016 | 2019 | |
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 | ||
2017 | 2046 | NTL_CLOSE_NNS |
2018 | 2047 | |
2019 | 2048 |
57 | 57 | |
58 | 58 | { rep.kill(); } |
59 | 59 | |
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 | ||
60 | 70 | static const ZZX& zero(); |
61 | 71 | |
62 | 72 | inline ZZX(long i, const ZZ& c); |
280 | 290 | void conv(ZZX& x, const zz_pX& a); |
281 | 291 | inline ZZX to_ZZX(const zz_pX& a) |
282 | 292 | { 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 | /* ------------------------------------- */ | |
283 | 307 | |
284 | 308 | |
285 | 309 | |
711 | 735 | |
712 | 736 | |
713 | 737 | |
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 | ||
721 | 740 | |
722 | 741 | NTL_CLOSE_NNS |
723 | 742 |
428 | 428 | |
429 | 429 | inline ZZ_p& ZZ_p::operator=(long a) { conv(*this, a); return *this; } |
430 | 430 | |
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 | ||
431 | 454 | NTL_CLOSE_NNS |
432 | 455 | |
433 | 456 | #endif |
482 | 482 | inline ZZ_pE& operator/=(ZZ_pE& x, long b) |
483 | 483 | { div(x, x, b); return x; } |
484 | 484 | |
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 | ||
485 | 497 | NTL_CLOSE_NNS |
486 | 498 | |
487 | 499 | #endif |
44 | 44 | // free space held by this polynomial. Value becomes 0. |
45 | 45 | |
46 | 46 | { 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 | ||
47 | 58 | |
48 | 59 | static const ZZ_pEX& zero(); |
49 | 60 | |
240 | 251 | |
241 | 252 | inline ZZ_pEX& ZZ_pEX::operator=(const ZZ_pE& a) |
242 | 253 | { 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 | ||
243 | 273 | |
244 | 274 | |
245 | 275 | /************************************************************* |
705 | 735 | |
706 | 736 | |
707 | 737 | |
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; | |
713 | 739 | |
714 | 740 | |
715 | 741 |
92 | 92 | |
93 | 93 | { rep.kill(); } |
94 | 94 | |
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 | ||
95 | 102 | static const ZZ_pX& zero(); |
96 | 103 | |
97 | 104 | |
285 | 292 | |
286 | 293 | inline ZZ_pX to_ZZ_pX(const vec_ZZ_p& a) |
287 | 294 | { 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 | /* ------------------------------------- */ | |
288 | 310 | |
289 | 311 | |
290 | 312 | |
995 | 1017 | |
996 | 1018 | *****************************************************************/ |
997 | 1019 | |
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; | |
1003 | 1021 | |
1004 | 1022 | |
1005 | 1023 |
508 | 508 | These routines use malloc and free. |
509 | 509 | |
510 | 510 | ***********************************************************************/ |
511 | ||
512 | ||
513 | long _ntl_zmaxalloc(_ntl_verylong x); | |
514 | /* max allocation request, possibly rounded up a bit */ | |
511 | 515 | |
512 | 516 | |
513 | 517 | void _ntl_zsetlength(_ntl_verylong *v, long len); |
626 | 630 | #define NTL_zscompare _ntl_zscompare |
627 | 631 | #define NTL_zsdiv _ntl_zsdiv |
628 | 632 | #define NTL_zsetbit _ntl_zsetbit |
633 | #define NTL_zmaxalloc _ntl_zmaxalloc | |
629 | 634 | #define NTL_zsetlength _ntl_zsetlength |
630 | 635 | #define NTL_zsign _ntl_zsign |
631 | 636 | #define NTL_zsize _ntl_zsize |
410 | 410 | * and NTL_SPMM_ASM. |
411 | 411 | * This plays a crucial role in the "small prime FFT" used to |
412 | 412 | * 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 | |
414 | 414 | * arithmetic over zz_p. |
415 | 415 | */ |
416 | 416 | |
456 | 456 | |
457 | 457 | |
458 | 458 | |
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 | ||
459 | 500 | |
460 | 501 | |
461 | 502 | /* The next five flags NTL_AVOID_BRANCHING, NTL_TBL_REM, |
410 | 410 | * and NTL_SPMM_ASM. |
411 | 411 | * This plays a crucial role in the "small prime FFT" used to |
412 | 412 | * 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 | |
414 | 414 | * arithmetic over zz_p. |
415 | 415 | */ |
416 | 416 | |
456 | 456 | |
457 | 457 | |
458 | 458 | |
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 | ||
459 | 500 | |
460 | 501 | |
461 | 502 | /* The next five flags NTL_AVOID_BRANCHING, NTL_TBL_REM, |
400 | 400 | |
401 | 401 | ***********************************************************************/ |
402 | 402 | |
403 | long _ntl_gmaxalloc(_ntl_gbigint x); | |
404 | /* max allocation request, possibly rounded up a bit */ | |
403 | 405 | |
404 | 406 | void _ntl_gsetlength(_ntl_gbigint *v, long len); |
405 | 407 | /* Allocates enough space to hold a len-digit number, |
513 | 515 | #define NTL_zscompare _ntl_gscompare |
514 | 516 | #define NTL_zsdiv _ntl_gsdiv |
515 | 517 | #define NTL_zsetbit _ntl_gsetbit |
518 | #define NTL_zmaxalloc _ntl_gmaxalloc | |
516 | 519 | #define NTL_zsetlength _ntl_gsetlength |
517 | 520 | #define NTL_zsign _ntl_gsign |
518 | 521 | #define NTL_zsize _ntl_gsize |
340 | 340 | { zz_p x; random(x); return x; } |
341 | 341 | |
342 | 342 | |
343 | ||
343 | 344 | // ****** input/output |
344 | 345 | |
345 | 346 | NTL_SNS ostream& operator<<(NTL_SNS ostream& s, zz_p a); |
347 | 348 | NTL_SNS istream& operator>>(NTL_SNS istream& s, zz_p& x); |
348 | 349 | |
349 | 350 | |
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 | ||
350 | 366 | NTL_CLOSE_NNS |
351 | 367 | |
352 | 368 | #endif |
482 | 482 | inline zz_pE& operator/=(zz_pE& x, long b) |
483 | 483 | { div(x, x, b); return x; } |
484 | 484 | |
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 | ||
485 | 496 | NTL_CLOSE_NNS |
486 | 497 | |
487 | 498 | #endif |
43 | 43 | // free space held by this polynomial. Value becomes 0. |
44 | 44 | |
45 | 45 | { 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 | ||
46 | 56 | |
47 | 57 | static const zz_pEX& zero(); |
48 | 58 | |
239 | 249 | |
240 | 250 | inline zz_pEX& zz_pEX::operator=(const zz_pE& a) |
241 | 251 | { 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 | ||
242 | 270 | |
243 | 271 | |
244 | 272 | /************************************************************* |
704 | 732 | |
705 | 733 | |
706 | 734 | |
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; | |
714 | 736 | |
715 | 737 | |
716 | 738 |
100 | 100 | |
101 | 101 | { rep.kill(); } |
102 | 102 | |
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 | ||
103 | 113 | static const zz_pX& zero(); |
104 | 114 | |
105 | 115 | zz_pX(zz_pX& x, INIT_TRANS_TYPE) : rep(x.rep, INIT_TRANS) { } |
144 | 154 | // degree of a polynomial. |
145 | 155 | // note that the zero polynomial has degree -1. |
146 | 156 | |
147 | zz_p coeff(const zz_pX& a, long i); | |
157 | const zz_p coeff(const zz_pX& a, long i); | |
148 | 158 | // zero if i not in range |
149 | 159 | |
150 | 160 | void GetCoeff(zz_p& x, const zz_pX& a, long i); |
151 | 161 | // x = a[i], or zero if i not in range |
152 | 162 | |
153 | zz_p LeadCoeff(const zz_pX& a); | |
163 | const zz_p LeadCoeff(const zz_pX& a); | |
154 | 164 | // zero if a == 0 |
155 | 165 | |
156 | zz_p ConstTerm(const zz_pX& a); | |
166 | const zz_p ConstTerm(const zz_pX& a); | |
157 | 167 | // zero if a == 0 |
158 | 168 | |
159 | 169 | void SetCoeff(zz_pX& x, long i, zz_p a); |
299 | 309 | |
300 | 310 | inline zz_pX& zz_pX::operator=(long a) |
301 | 311 | { 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 | /* ------------------------------------- */ | |
302 | 324 | |
303 | 325 | |
304 | 326 | |
533 | 555 | |
534 | 556 | void SetSize(long NewK); |
535 | 557 | |
536 | fftRep() { k = MaxK = -1; NumPrimes = zz_pInfo->NumPrimes; } | |
558 | fftRep() { k = MaxK = -1; NumPrimes = 0; } | |
537 | 559 | fftRep(INIT_SIZE_TYPE, long InitK) |
538 | { k = MaxK = -1; NumPrimes = zz_pInfo->NumPrimes; SetSize(InitK); } | |
560 | { k = MaxK = -1; NumPrimes = 0; SetSize(InitK); } | |
539 | 561 | ~fftRep(); |
540 | 562 | }; |
541 | 563 | |
985 | 1007 | |
986 | 1008 | *****************************************************************/ |
987 | 1009 | |
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; | |
994 | 1011 | |
995 | 1012 | |
996 | 1013 | /********************************************************** |
1238 | 1255 | { zz_pX x; CharPolyMod(x, a, f); NTL_OPT_RETURN(zz_pX, x); } |
1239 | 1256 | |
1240 | 1257 | |
1258 | ||
1259 | ||
1260 | ||
1241 | 1261 | NTL_CLOSE_NNS |
1242 | 1262 | |
1243 | 1263 | #endif |
2 | 2 | #define NTL_mat_GF2__H |
3 | 3 | |
4 | 4 | |
5 | #include <NTL/matrix.h> | |
5 | 6 | #include <NTL/vec_vec_GF2.h> |
6 | 7 | |
7 | 8 | NTL_OPEN_NNS |
8 | 9 | |
9 | 10 | |
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; | |
62 | 12 | |
63 | 13 | |
14 | // some backward compaitibilty stuff | |
64 | 15 | |
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 | } | |
67 | 19 | |
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 | } | |
71 | 23 | |
72 | 24 | |
73 | 25 | |
98 | 50 | |
99 | 51 | long IsIdent(const mat_GF2& A, long n); |
100 | 52 | 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); | |
103 | 55 | |
104 | 56 | inline void sqr(mat_GF2& X, const mat_GF2& A) |
105 | 57 | { mul(X, A, A); } |
137 | 89 | |
138 | 90 | |
139 | 91 | |
140 | void determinant(GF2& x, const mat_GF2& a); | |
92 | void determinant(ref_GF2 x, const mat_GF2& a); | |
141 | 93 | inline GF2 determinant(const mat_GF2& a) |
142 | 94 | { GF2 x; determinant(x, a); return x; } |
143 | 95 |
6 | 6 | |
7 | 7 | NTL_OPEN_NNS |
8 | 8 | |
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; | |
12 | 10 | |
13 | 11 | void add(mat_GF2E& X, const mat_GF2E& A, const mat_GF2E& B); |
14 | 12 | inline void sub(mat_GF2E& X, const mat_GF2E& A, const mat_GF2E& B) |
6 | 6 | |
7 | 7 | NTL_OPEN_NNS |
8 | 8 | |
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; | |
12 | 10 | |
13 | 11 | void add(mat_RR& X, const mat_RR& A, const mat_RR& B); |
14 | 12 | void sub(mat_RR& X, const mat_RR& A, const mat_RR& B); |
8 | 8 | |
9 | 9 | NTL_OPEN_NNS |
10 | 10 | |
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; | |
14 | 12 | |
15 | 13 | |
16 | 14 | void add(mat_ZZ& X, const mat_ZZ& A, const mat_ZZ& B); |
7 | 7 | |
8 | 8 | NTL_OPEN_NNS |
9 | 9 | |
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; | |
13 | 11 | |
14 | 12 | void add(mat_ZZ_p& X, const mat_ZZ_p& A, const mat_ZZ_p& B); |
15 | 13 | void sub(mat_ZZ_p& X, const mat_ZZ_p& A, const mat_ZZ_p& B); |
5 | 5 | |
6 | 6 | NTL_OPEN_NNS |
7 | 7 | |
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; | |
13 | 9 | |
14 | 10 | void add(mat_ZZ_pE& X, const mat_ZZ_pE& A, const mat_ZZ_pE& B); |
15 | 11 | void sub(mat_ZZ_pE& X, const mat_ZZ_pE& A, const mat_ZZ_pE& B); |
6 | 6 | |
7 | 7 | NTL_OPEN_NNS |
8 | 8 | |
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; | |
12 | 10 | |
13 | 11 | |
14 | 12 | void add(mat_zz_p& X, const mat_zz_p& A, const mat_zz_p& B); |
5 | 5 | |
6 | 6 | NTL_OPEN_NNS |
7 | 7 | |
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; | |
13 | 9 | |
14 | 10 | void add(mat_zz_pE& X, const mat_zz_pE& A, const mat_zz_pE& B); |
15 | 11 | void sub(mat_zz_pE& X, const mat_zz_pE& A, const mat_zz_pE& B); |
6 | 6 | |
7 | 7 | // matrix templates |
8 | 8 | |
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 | |
201 | 211 | |
202 | 212 | |
203 | 213 | #endif |
3 | 3 | |
4 | 4 | #include <NTL/tools.h> |
5 | 5 | |
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); } | |
20 | 25 | |
21 | 26 | |
22 | 27 | |
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; } | |
23 | 31 | |
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); } | |
28 | 35 | |
29 | 36 | |
30 | 37 | |
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 | } | |
36 | 80 | |
37 | 81 | |
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 | |
91 | 83 | |
92 | 84 | |
93 | 85 | #endif |
7 | 7 | |
8 | 8 | NTL_OPEN_NNS |
9 | 9 | |
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) | |
13 | 10 | |
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; | |
17 | 14 | |
18 | 15 | NTL_CLOSE_NNS |
19 | 16 |
7 | 7 | |
8 | 8 | NTL_OPEN_NNS |
9 | 9 | |
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; | |
17 | 12 | |
18 | 13 | NTL_CLOSE_NNS |
19 | 14 |
7 | 7 | |
8 | 8 | NTL_OPEN_NNS |
9 | 9 | |
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; | |
17 | 12 | |
18 | 13 | NTL_CLOSE_NNS |
19 | 14 |
6 | 6 | |
7 | 7 | NTL_OPEN_NNS |
8 | 8 | |
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; | |
17 | 11 | |
18 | 12 | NTL_CLOSE_NNS |
19 | 13 |
7 | 7 | |
8 | 8 | NTL_OPEN_NNS |
9 | 9 | |
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; | |
17 | 12 | |
18 | 13 | NTL_CLOSE_NNS |
19 | 14 |
6 | 6 | |
7 | 7 | NTL_OPEN_NNS |
8 | 8 | |
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; | |
17 | 11 | |
18 | 12 | NTL_CLOSE_NNS |
19 | 13 |
7 | 7 | |
8 | 8 | NTL_OPEN_NNS |
9 | 9 | |
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; | |
17 | 12 | |
18 | 13 | NTL_CLOSE_NNS |
19 | 14 |
280 | 280 | inline void conv(quad_float& x, const char *s) |
281 | 281 | { x = to_quad_float(s); } |
282 | 282 | |
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 | ||
283 | 296 | long IsFinite(quad_float *x); |
284 | 297 | |
285 | 298 | long PrecisionOK(); |
243 | 243 | inline double to_double(double a) { return a; } |
244 | 244 | |
245 | 245 | |
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 | ||
246 | 283 | long SkipWhiteSpace(NTL_SNS istream& s); |
247 | 284 | long IsWhiteSpace(long c); |
248 | 285 | long IsEOFChar(long c); |
274 | 311 | |
275 | 312 | void PrintTime(NTL_SNS ostream& s, double t); |
276 | 313 | |
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 | ||
277 | 329 | NTL_CLOSE_NNS |
278 | 330 | |
279 | 331 |
6 | 6 | |
7 | 7 | NTL_OPEN_NNS |
8 | 8 | |
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> { | |
41 | 16 | |
42 | 17 | public: |
43 | 18 | |
58 | 33 | //the following are "really" public |
59 | 34 | |
60 | 35 | |
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() {} | |
68 | 43 | |
69 | 44 | void kill(); |
70 | 45 | |
78 | 53 | long fixed() const { return _maxlen & 1; } |
79 | 54 | |
80 | 55 | |
81 | vec_GF2(vec_GF2& x, INIT_TRANS_TYPE) : | |
56 | Vec(Vec<GF2>& x, INIT_TRANS_TYPE) : | |
82 | 57 | rep(x.rep, INIT_TRANS), _len(x._len), _maxlen(x._maxlen) { } |
83 | 58 | |
84 | GF2 get(long i) const; | |
59 | const GF2 get(long i) const; | |
85 | 60 | void put(long i, GF2 a); |
86 | 61 | void put(long i, long a) { put(i, to_GF2(a)); } |
87 | 62 | |
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; | |
99 | 82 | |
100 | 83 | }; |
101 | 84 | |
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 | ||
159 | 93 | |
160 | 94 | 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); | |
162 | 96 | void append(vec_GF2& v, const vec_GF2& a); |
163 | 97 | |
164 | 98 | long operator==(const vec_GF2& a, const vec_GF2& b); |
206 | 140 | inline void negate(vec_GF2& x, const vec_GF2& a) |
207 | 141 | { x = a; } |
208 | 142 | |
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) | |
210 | 144 | { x = to_GF2(InnerProduct(a.rep, b.rep)); } |
211 | 145 | |
212 | 146 | long IsZero(const vec_GF2& a); |
5 | 5 | |
6 | 6 | NTL_OPEN_NNS |
7 | 7 | |
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; | |
14 | 9 | |
15 | 10 | void mul(vec_GF2E& x, const vec_GF2E& a, const GF2E& b); |
16 | 11 | inline void mul(vec_GF2E& x, const GF2E& a, const vec_GF2E& b) |
6 | 6 | |
7 | 7 | NTL_OPEN_NNS |
8 | 8 | |
9 | NTL_vector_decl(GF2XVec,vec_GF2XVec) | |
9 | typedef Vec<GF2XVec> vec_GF2XVec; | |
10 | 10 | |
11 | 11 | NTL_CLOSE_NNS |
12 | 12 |
6 | 6 | |
7 | 7 | NTL_OPEN_NNS |
8 | 8 | |
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; | |
14 | 10 | |
15 | 11 | void mul(vec_RR& x, const vec_RR& a, const RR& b); |
16 | 12 | inline void mul(vec_RR& x, const RR& a, const vec_RR& b) |
6 | 6 | |
7 | 7 | NTL_OPEN_NNS |
8 | 8 | |
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; | |
14 | 10 | |
15 | 11 | void mul(vec_ZZ& x, const vec_ZZ& a, const ZZ& b); |
16 | 12 | inline void mul(vec_ZZ& x, const ZZ& a, const vec_ZZ& b) |
6 | 6 | |
7 | 7 | NTL_OPEN_NNS |
8 | 8 | |
9 | NTL_vector_decl(ZZVec,vec_ZZVec) | |
9 | typedef Vec<ZZVec> vec_ZZVec; | |
10 | 10 | |
11 | 11 | NTL_CLOSE_NNS |
12 | 12 |
6 | 6 | |
7 | 7 | NTL_OPEN_NNS |
8 | 8 | |
9 | NTL_vector_decl(ZZ_p,vec_ZZ_p) | |
9 | typedef Vec<ZZ_p> vec_ZZ_p; | |
10 | 10 | |
11 | NTL_io_vector_decl(ZZ_p,vec_ZZ_p) | |
12 | ||
13 | NTL_eq_vector_decl(ZZ_p,vec_ZZ_p) | |
14 | 11 | |
15 | 12 | void conv(vec_ZZ_p& x, const vec_ZZ& a); |
16 | 13 | inline vec_ZZ_p to_vec_ZZ_p(const vec_ZZ& a) |
5 | 5 | |
6 | 6 | NTL_OPEN_NNS |
7 | 7 | |
8 | typedef Vec<ZZ_pE> vec_ZZ_pE; | |
8 | 9 | |
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) | |
14 | 10 | |
15 | 11 | void mul(vec_ZZ_pE& x, const vec_ZZ_pE& a, const ZZ_pE& b); |
16 | 12 | inline void mul(vec_ZZ_pE& x, const ZZ_pE& a, const vec_ZZ_pE& b) |
5 | 5 | |
6 | 6 | NTL_OPEN_NNS |
7 | 7 | |
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; | |
13 | 9 | |
14 | 10 | NTL_CLOSE_NNS |
15 | 11 |
5 | 5 | |
6 | 6 | NTL_OPEN_NNS |
7 | 7 | |
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; | |
13 | 9 | |
14 | 10 | NTL_CLOSE_NNS |
15 | 11 |
6 | 6 | |
7 | 7 | NTL_OPEN_NNS |
8 | 8 | |
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; | |
14 | 10 | |
15 | 11 | void conv(vec_zz_p& x, const vec_ZZ& a); |
16 | 12 | inline vec_zz_p to_vec_zz_p(const vec_ZZ& a) |
6 | 6 | NTL_OPEN_NNS |
7 | 7 | |
8 | 8 | |
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; | |
14 | 10 | |
15 | 11 | void mul(vec_zz_pE& x, const vec_zz_pE& a, const zz_pE& b); |
16 | 12 | inline void mul(vec_zz_pE& x, const zz_pE& a, const vec_zz_pE& b) |
6 | 6 | |
7 | 7 | NTL_OPEN_NNS |
8 | 8 | |
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; | |
14 | 10 | |
15 | 11 | NTL_CLOSE_NNS |
16 | 12 |
5 | 5 | |
6 | 6 | NTL_OPEN_NNS |
7 | 7 | |
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; | |
13 | 9 | |
14 | 10 | NTL_CLOSE_NNS |
15 | 11 |
6 | 6 | |
7 | 7 | NTL_OPEN_NNS |
8 | 8 | |
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; | |
14 | 10 | |
15 | 11 | NTL_CLOSE_NNS |
16 | 12 |
5 | 5 | |
6 | 6 | NTL_OPEN_NNS |
7 | 7 | |
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; | |
13 | 9 | |
14 | 10 | NTL_CLOSE_NNS |
15 | 11 |
5 | 5 | |
6 | 6 | NTL_OPEN_NNS |
7 | 7 | |
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; | |
13 | 9 | |
14 | 10 | NTL_CLOSE_NNS |
15 | 11 |
5 | 5 | |
6 | 6 | NTL_OPEN_NNS |
7 | 7 | |
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; | |
13 | 9 | |
14 | 10 | NTL_CLOSE_NNS |
15 | 11 |
5 | 5 | |
6 | 6 | NTL_OPEN_NNS |
7 | 7 | |
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; | |
13 | 9 | |
14 | 10 | NTL_CLOSE_NNS |
15 | 11 |
5 | 5 | |
6 | 6 | NTL_OPEN_NNS |
7 | 7 | |
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; | |
13 | 9 | |
14 | 10 | NTL_CLOSE_NNS |
15 | 11 |
5 | 5 | |
6 | 6 | NTL_OPEN_NNS |
7 | 7 | |
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; | |
13 | 9 | |
14 | 10 | NTL_CLOSE_NNS |
15 | 11 |
5 | 5 | |
6 | 6 | NTL_OPEN_NNS |
7 | 7 | |
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; | |
13 | 9 | |
14 | 10 | NTL_CLOSE_NNS |
15 | 11 |
5 | 5 | |
6 | 6 | NTL_OPEN_NNS |
7 | 7 | |
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; | |
13 | 9 | |
14 | 10 | NTL_CLOSE_NNS |
15 | 11 |
5 | 5 | |
6 | 6 | NTL_OPEN_NNS |
7 | 7 | |
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; | |
13 | 9 | |
14 | 10 | NTL_CLOSE_NNS |
15 | 11 |
6 | 6 | |
7 | 7 | NTL_OPEN_NNS |
8 | 8 | |
9 | NTL_vector_decl(xdouble,vec_xdouble) | |
9 | typedef Vec<xdouble> vec_xdouble; | |
10 | 10 | |
11 | NTL_io_vector_decl(xdouble,vec_xdouble) | |
12 | ||
13 | NTL_eq_vector_decl(xdouble,vec_xdouble) | |
14 | 11 | |
15 | 12 | NTL_CLOSE_NNS |
16 | 13 |
41 | 41 | |
42 | 42 | #ifndef NTL_RANGE_CHECK |
43 | 43 | #define NTL_RANGE_CHECK_CODE |
44 | #define NTL_RANGE_CHECK_CODE1(i) | |
44 | 45 | #else |
45 | 46 | #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 | ||
46 | 50 | #endif |
47 | 51 | |
48 | 52 | // vectors are allocated in chunks of this size |
64 | 68 | #endif |
65 | 69 | |
66 | 70 | |
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(); | |
82 | 86 | } |
83 | 87 | |
84 | 88 | |
85 | 89 | |
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 | ||
164 | 219 | |
165 | 220 | |
166 | 221 | #if (!defined(NTL_CLEAN_PTR)) |
167 | 222 | |
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 | } | |
197 | 253 | |
198 | 254 | |
199 | 255 | #else |
200 | 256 | |
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 | } | |
226 | 283 | |
227 | 284 | |
228 | 285 | #endif |
229 | 286 | |
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]; | |
401 | 465 | } |
402 | 466 | |
403 | 467 | |
404 | 468 | |
405 | 469 | |
406 | 470 | |
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 | ||
485 | 574 | |
486 | 575 | |
487 | 576 | #endif |
1 | 1 | #ifndef NTL_version__H |
2 | 2 | #define NTL_version__H |
3 | 3 | |
4 | #define NTL_VERSION "5.5.2" | |
4 | #define NTL_VERSION "6.0.0" | |
5 | 5 | |
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) | |
9 | 9 | |
10 | 10 | #endif |
11 | 11 |
216 | 216 | inline void conv(xdouble& x, double a) { x = to_xdouble(a); } |
217 | 217 | inline void conv(xdouble& x, const char *a) { x = to_xdouble(a); } |
218 | 218 | |
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 | ||
219 | 232 | NTL_SNS ostream& operator<<(NTL_SNS ostream& s, const xdouble& a); |
220 | 233 | |
221 | 234 | NTL_SNS istream& operator>>(NTL_SNS istream& s, xdouble& x); |
119 | 119 | #endif |
120 | 120 | |
121 | 121 | |
122 | ||
123 | ||
124 | 122 | #ifdef NTL_AVOID_BRANCHING |
125 | 123 | cout << "NTL_AVOID_BRANCHING\n"; |
126 | 124 | #endif |
127 | 125 | |
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 | |
128 | 133 | |
129 | 134 | |
130 | 135 | #ifdef NTL_TBL_REM |
72 | 72 | 'NTL_CLEAN_INT' => 'off', |
73 | 73 | 'NTL_CLEAN_PTR' => 'off', |
74 | 74 | 'NTL_RANGE_CHECK' => 'off', |
75 | 'NTL_FFT_BIGTAB' => 'off', | |
76 | 'NTL_FFT_LAZYMUL' => 'off', | |
75 | 77 | |
76 | 78 | ); |
77 | 79 |
5 | 5 | |
6 | 6 | NTL_START_IMPL |
7 | 7 | |
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 | ||
8 | 24 | long NumFFTPrimes = 0; |
9 | 25 | |
10 | 26 | |
11 | ||
12 | long *FFTPrime = 0; | |
13 | long **RootTable = 0; | |
14 | long **RootInvTable = 0; | |
15 | long **TwoInvTable = 0; | |
16 | double *FFTPrimeInv = 0; | |
17 | 27 | |
18 | 28 | |
19 | 29 | static |
129 | 139 | } |
130 | 140 | |
131 | 141 | |
142 | ||
132 | 143 | void UseFFTPrime(long index) |
133 | 144 | { |
134 | if (index < 0 || index > NumFFTPrimes) | |
145 | long numprimes = FFTTables_store.length(); | |
146 | ||
147 | if (index < 0 || index > numprimes) | |
135 | 148 | Error("invalid FFT prime index"); |
136 | 149 | |
137 | if (index < NumFFTPrimes) return; | |
150 | if (index < numprimes) return; | |
151 | ||
152 | // index == numprimes | |
138 | 153 | |
139 | 154 | long q, w; |
140 | 155 | |
141 | 156 | NextFFTPrime(q, w); |
142 | 157 | |
158 | double qinv = 1/((double) q); | |
159 | ||
143 | 160 | long mr = CalcMaxRoot(q); |
144 | 161 | |
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]; | |
180 | 179 | |
181 | 180 | long j; |
182 | 181 | long t; |
194 | 193 | for (j = 1; j <= mr; j++) |
195 | 194 | tit[j] = MulMod(tit[j-1], t, q); |
196 | 195 | |
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(); | |
201 | 203 | |
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 | } | |
242 | 212 | |
243 | 213 | |
244 | 214 | |
247 | 217 | * For very large inputs, it should be relatively cache friendly. |
248 | 218 | * The inner loop has been unrolled and pipelined, to exploit any |
249 | 219 | * low-level parallelism in the machine. |
220 | * | |
221 | * This version now allows input to alias output. | |
250 | 222 | */ |
251 | 223 | |
252 | 224 | |
253 | 225 | |
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 | ||
254 | 288 | void FFT(long* A, const long* a, long k, long q, const long* root) |
255 | ||
256 | 289 | // performs a 2^k-point convolution modulo q |
257 | 290 | |
258 | 291 | { |
262 | 295 | return; |
263 | 296 | } |
264 | 297 | 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; | |
267 | 302 | return; |
268 | 303 | } |
269 | 304 | } |
272 | 307 | |
273 | 308 | |
274 | 309 | |
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(); | |
296 | 321 | |
297 | 322 | double qinv = 1/((double) q); |
298 | 323 | |
300 | 325 | wqinvtab[0] = PrepMulModPrecon(1, q, qinv); |
301 | 326 | |
302 | 327 | |
303 | BitReverseCopy(A, a, k); | |
328 | BitReverseCopy(AA, a, k); | |
304 | 329 | |
305 | 330 | long n = 1L << k; |
306 | 331 | |
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; | |
308 | 333 | |
309 | 334 | long w; |
310 | 335 | mulmod_precon_t wqinv; |
312 | 337 | // s = 1 |
313 | 338 | |
314 | 339 | 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); | |
319 | 344 | } |
320 | 345 | |
321 | 346 | |
325 | 350 | m_half = 1L << (s-1); |
326 | 351 | m_fourth = 1L << (s-2); |
327 | 352 | |
328 | // prepare wtab... | |
329 | ||
330 | 353 | w = root[s]; |
331 | 354 | wqinv = PrepMulModPrecon(w, q, qinv); |
332 | 355 | |
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; | |
334 | 366 | wtab[i-1] = wtab[j]; |
335 | 367 | wqinvtab[i-1] = wqinvtab[j]; |
336 | 368 | 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); | |
338 | 382 | } |
339 | 383 | |
340 | 384 | for (i = 0; i < n; i+= m) { |
341 | 385 | |
386 | long * NTL_RESTRICT AA0 = &AA[i]; | |
387 | long * NTL_RESTRICT AA1 = &AA[i + m_half]; | |
342 | 388 | |
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]; | |
347 | 393 | |
348 | 394 | 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); | |
360 | 407 | 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); | |
361 | 413 | 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; | |
364 | 420 | } |
365 | 421 | |
366 | 422 | |
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); | |
374 | 427 | } |
375 | 428 | } |
376 | 429 | |
387 | 440 | |
388 | 441 | // j = 0, 1 |
389 | 442 | |
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]; | |
394 | 447 | |
395 | 448 | A[0] = AddMod(u, t, q); |
396 | 449 | A[m_half] = SubMod(u, t, q); |
398 | 451 | A[1 + m_half] = SubMod(u1, t1, q); |
399 | 452 | |
400 | 453 | 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, | |
404 | 457 | wqinvtab[j >> 1]); |
405 | 458 | t1 = MulModPrecon(t1, w, q, wqinv); |
406 | u1 = A[j + 1]; | |
459 | u1 = AA[j + 1]; | |
407 | 460 | |
408 | 461 | A[j] = AddMod(u, t, q); |
409 | 462 | A[j + m_half] = SubMod(u, t, q); |
414 | 467 | } |
415 | 468 | |
416 | 469 | |
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 | ||
417 | 1113 | NTL_END_IMPL |
1 | 1 | #include <NTL/FacVec.h> |
2 | 2 | #include <NTL/ZZ.h> |
3 | 3 | |
4 | #include <NTL/new.h> | |
5 | 4 | |
6 | 5 | NTL_START_IMPL |
7 | 6 | |
8 | NTL_vector_impl(IntFactor,vec_IntFactor) | |
9 | 7 | |
10 | 8 | static |
11 | 9 | void swap(IntFactor& x, IntFactor& y) |
5 | 5 | NTL_START_IMPL |
6 | 6 | |
7 | 7 | |
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) | |
33 | 9 | { |
34 | 10 | if (e == 0) { |
35 | x = 1; | |
36 | return; | |
11 | return to_GF2(1); | |
37 | 12 | } |
38 | 13 | |
39 | if (e < 0 && a == 0) | |
14 | if (e < 0 && IsZero(a)) | |
40 | 15 | Error("GF2: division by zero"); |
41 | 16 | |
42 | x = a; | |
17 | return a; | |
43 | 18 | } |
44 | 19 | |
45 | 20 | ostream& operator<<(ostream& s, GF2 a) |
52 | 27 | return s; |
53 | 28 | } |
54 | 29 | |
55 | istream& operator>>(istream& s, GF2& x) | |
30 | istream& operator>>(istream& s, ref_GF2 x) | |
56 | 31 | { |
57 | 32 | static ZZ a; |
58 | 33 |
1 | 1 | |
2 | 2 | #include <NTL/GF2EX.h> |
3 | 3 | #include <NTL/vec_vec_GF2.h> |
4 | #include <NTL/ZZX.h> | |
4 | 5 | |
5 | 6 | #include <NTL/new.h> |
6 | 7 | |
237 | 238 | x.rep = a; |
238 | 239 | x.normalize(); |
239 | 240 | } |
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 | ||
240 | 262 | |
241 | 263 | |
242 | 264 | void add(GF2EX& x, const GF2EX& a, const GF2EX& b) |
2205 | 2227 | |
2206 | 2228 | U.normalize(); |
2207 | 2229 | } |
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 | ||
2216 | 2230 | |
2217 | 2231 | |
2218 | 2232 | void IterBuild(GF2E* a, long n) |
3230 | 3244 | } |
3231 | 3245 | } |
3232 | 3246 | |
3233 | void ProjectedInnerProduct(GF2& x, const vec_GF2E& a, | |
3247 | void ProjectedInnerProduct(ref_GF2 x, const vec_GF2E& a, | |
3234 | 3248 | const vec_vec_GF2& b) |
3235 | 3249 | { |
3236 | 3250 | long n = min(a.length(), b.length()); |
2102 | 2102 | |
2103 | 2103 | if (deg(f) == 1) { |
2104 | 2104 | factors.SetLength(0); |
2105 | append(factors, cons(f, 1)); | |
2105 | append(factors, cons(f, 1L)); | |
2106 | 2106 | return; |
2107 | 2107 | } |
2108 | 2108 |
53 | 53 | xrep.QuickSetLength(n); |
54 | 54 | } |
55 | 55 | |
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 | ||
56 | 115 | long IsZero(const GF2X& a) |
57 | 116 | { return a.xrep.length() == 0; } |
58 | 117 | |
70 | 129 | return a.xrep.length() == 1 && a.xrep[0] == 2; |
71 | 130 | } |
72 | 131 | |
73 | GF2 coeff(const GF2X& a, long i) | |
132 | const GF2 coeff(const GF2X& a, long i) | |
74 | 133 | { |
75 | 134 | if (i < 0) return to_GF2(0); |
76 | 135 | long wi = i/NTL_BITS_PER_LONG; |
80 | 139 | return to_GF2((a.xrep[wi] & (1UL << bi)) != 0); |
81 | 140 | } |
82 | 141 | |
83 | GF2 LeadCoeff(const GF2X& a) | |
142 | const GF2 LeadCoeff(const GF2X& a) | |
84 | 143 | { |
85 | 144 | if (IsZero(a)) |
86 | 145 | return to_GF2(0); |
88 | 147 | return to_GF2(1); |
89 | 148 | } |
90 | 149 | |
91 | GF2 ConstTerm(const GF2X& a) | |
150 | const GF2 ConstTerm(const GF2X& a) | |
92 | 151 | { |
93 | 152 | if (IsZero(a)) |
94 | 153 | return to_GF2(0); |
161 | 220 | long bi = i - wi*NTL_BITS_PER_LONG; |
162 | 221 | |
163 | 222 | x.xrep[wi] &= ~(1UL << bi); |
164 | if (wi == n-1) x.normalize(); | |
223 | if (wi == n-1 && !x.xrep[wi]) x.normalize(); | |
165 | 224 | } |
166 | 225 | |
167 | 226 | void SetCoeff(GF2X& x, long i, GF2 a) |
1493 | 1552 | } |
1494 | 1553 | |
1495 | 1554 | |
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 | ||
1507 | 1555 | void MulByX(GF2X& x, const GF2X& a) |
1508 | 1556 | { |
1509 | 1557 | long n = a.xrep.length(); |
1 | 1 | |
2 | 2 | #include <NTL/GF2X.h> |
3 | 3 | #include <NTL/vec_long.h> |
4 | ||
5 | #ifndef NTL_WIZARD_HACK | |
6 | ||
7 | #include <NTL/ZZX.h> | |
8 | ||
9 | #endif | |
4 | 10 | |
5 | 11 | #include <NTL/new.h> |
6 | 12 | |
2471 | 2477 | VectorCopy(x, a, deg(a)+1); |
2472 | 2478 | } |
2473 | 2479 | |
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 | ||
2474 | 2511 | void VectorCopy(vec_GF2& x, const GF2X& a, long n) |
2475 | 2512 | { |
2476 | 2513 | if (n < 0) Error("VectorCopy: negative length"); |
3237 | 3274 | } |
3238 | 3275 | } |
3239 | 3276 | |
3240 | void TraceMod(GF2& x, const GF2X& a, const GF2XModulus& F) | |
3277 | void TraceMod(ref_GF2 x, const GF2X& a, const GF2XModulus& F) | |
3241 | 3278 | { |
3242 | 3279 | long n = F.n; |
3243 | 3280 | |
3250 | 3287 | project(x, F.tracevec, a); |
3251 | 3288 | } |
3252 | 3289 | |
3253 | void TraceMod(GF2& x, const GF2X& a, const GF2X& f) | |
3290 | void TraceMod(ref_GF2 x, const GF2X& a, const GF2X& f) | |
3254 | 3291 | { |
3255 | 3292 | if (deg(a) >= deg(f) || deg(f) <= 0) |
3256 | 3293 | Error("trace: bad args"); |
14 | 14 | make sure these changes are implemented in the template files |
15 | 15 | mfile and cfile, and then run: |
16 | 16 | |
17 | - update ../README and ../doc/copying.txt | |
18 | ||
17 | 19 | ./configure |
18 | 20 | cp makefile def_makefile |
19 | 21 | cp ../include/NTL/config.h ../include/NTL/def_config.h |
51 | 51 | #endif |
52 | 52 | |
53 | 53 | #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 "); | |
55 | 63 | #endif |
56 | 64 | |
57 | 65 | |
124 | 132 | } |
125 | 133 | |
126 | 134 | double t; |
127 | long i, j; | |
135 | long i; | |
128 | 136 | long iter; |
129 | 137 | |
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 | } | |
142 | 156 | |
143 | 157 | iter = 1; |
144 | 158 | |
145 | 159 | do { |
146 | 160 | t = GetTime(); |
147 | 161 | 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); | |
149 | 163 | } |
150 | 164 | t = GetTime() - t; |
151 | 165 | iter = 2*iter; |
162 | 176 | for (w = 0; w < 5; w++) { |
163 | 177 | t = GetTime(); |
164 | 178 | 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); | |
166 | 180 | } |
167 | 181 | t = GetTime() - t; |
168 | 182 | tvec[w] = t; |
216 | 216 | #endif |
217 | 217 | |
218 | 218 | |
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 | ||
219 | 230 | |
220 | 231 | #ifdef NTL_TBL_REM |
221 | 232 | cerr << "NTL_TBL_REM\n"; |
275 | 275 | negate(z.x, z.x); |
276 | 276 | } |
277 | 277 | |
278 | void NegatePrec(RR& x, const RR& a, const RR& b, long p) | |
278 | void NegatePrec(RR& x, const RR& a, long p) | |
279 | 279 | { |
280 | 280 | if (p < 1 || NTL_OVERFLOW(p, 1, 0)) |
281 | 281 | Error("NegatePrec: bad precsion"); |
292 | 292 | abs(z.x, z.x); |
293 | 293 | } |
294 | 294 | |
295 | void AbsPrec(RR& x, const RR& a, const RR& b, long p) | |
295 | void AbsPrec(RR& x, const RR& a, long p) | |
296 | 296 | { |
297 | 297 | if (p < 1 || NTL_OVERFLOW(p, 1, 0)) |
298 | 298 | Error("AbsPrec: bad precsion"); |
334 | 334 | xcopy(z, t); |
335 | 335 | } |
336 | 336 | |
337 | void SqrPrec(RR& x, const RR& a, const RR& b, long p) | |
337 | void SqrPrec(RR& x, const RR& a, long p) | |
338 | 338 | { |
339 | 339 | if (p < 1 || NTL_OVERFLOW(p, 1, 0)) |
340 | 340 | Error("SqrPrec: bad precsion"); |
478 | 478 | } |
479 | 479 | } |
480 | 480 | |
481 | void TruncPrec(RR& x, const RR& a, const RR& b, long p) | |
481 | void TruncPrec(RR& x, const RR& a, long p) | |
482 | 482 | { |
483 | 483 | if (p < 1 || NTL_OVERFLOW(p, 1, 0)) |
484 | 484 | Error("TruncPrec: bad precsion"); |
504 | 504 | } |
505 | 505 | } |
506 | 506 | |
507 | void FloorPrec(RR& x, const RR& a, const RR& b, long p) | |
507 | void FloorPrec(RR& x, const RR& a, long p) | |
508 | 508 | { |
509 | 509 | if (p < 1 || NTL_OVERFLOW(p, 1, 0)) |
510 | 510 | Error("FloorPrec: bad precsion"); |
530 | 530 | } |
531 | 531 | } |
532 | 532 | |
533 | void CeilPrec(RR& x, const RR& a, const RR& b, long p) | |
533 | void CeilPrec(RR& x, const RR& a, long p) | |
534 | 534 | { |
535 | 535 | if (p < 1 || NTL_OVERFLOW(p, 1, 0)) |
536 | 536 | Error("CeilPrec: bad precsion"); |
569 | 569 | xcopy(z, t); |
570 | 570 | } |
571 | 571 | |
572 | void RoundPrec(RR& x, const RR& a, const RR& b, long p) | |
572 | void RoundPrec(RR& x, const RR& a, long p) | |
573 | 573 | { |
574 | 574 | if (p < 1 || NTL_OVERFLOW(p, 1, 0)) |
575 | 575 | Error("RoundPrec: bad precsion"); |
766 | 766 | void conv(long& z, const RR& a) |
767 | 767 | { |
768 | 768 | 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 | } | |
771 | 775 | } |
772 | 776 | |
773 | 777 | void conv(double& z, const RR& aa) |
781 | 785 | conv(x, a.x); |
782 | 786 | z = _ntl_ldexp(x, a.e); |
783 | 787 | } |
788 | ||
789 | ||
784 | 790 | |
785 | 791 | |
786 | 792 | void add(RR& z, const RR& a, double b) |
0 | 0 | |
1 | 1 | for i in $* |
2 | 2 | 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" | |
7 | 8 | done |
8 | 9 | |
9 | 10 | exit 0 |
5 | 5 | echo "running CanZassTest" |
6 | 6 | ./CanZassTest < CanZassTestIn > XXX |
7 | 7 | sh RemoveProg CanZassTest |
8 | if diff XXX CanZassTestOut | |
8 | if diff -b XXX CanZassTestOut | |
9 | 9 | then |
10 | 10 | echo "CanZassTest OK" |
11 | 11 | else |
19 | 19 | echo "running BerlekampTest" |
20 | 20 | ./BerlekampTest < BerlekampTestIn > XXX |
21 | 21 | sh RemoveProg BerlekampTest |
22 | if diff XXX BerlekampTestOut | |
22 | if diff -b XXX BerlekampTestOut | |
23 | 23 | then |
24 | 24 | echo "BerlekampTest OK" |
25 | 25 | else |
34 | 34 | echo "running ZZXFacTest" |
35 | 35 | ./ZZXFacTest < ZZXFacTestIn > XXX |
36 | 36 | sh RemoveProg ZZXFacTest |
37 | if diff XXX ZZXFacTestOut | |
37 | if diff -b XXX ZZXFacTestOut | |
38 | 38 | then |
39 | 39 | echo "ZZXFacTest OK" |
40 | 40 | else |
73 | 73 | echo "running MatrixTest" |
74 | 74 | ./MatrixTest < MatrixTestIn > XXX |
75 | 75 | sh RemoveProg MatrixTest |
76 | if diff XXX MatrixTestOut | |
76 | if diff -b XXX MatrixTestOut | |
77 | 77 | then |
78 | 78 | echo "MatrixTest OK" |
79 | 79 | else |
87 | 87 | echo "running CharPolyTest" |
88 | 88 | ./CharPolyTest < CharPolyTestIn > XXX |
89 | 89 | sh RemoveProg CharPolyTest |
90 | if diff XXX CharPolyTestOut | |
90 | if diff -b XXX CharPolyTestOut | |
91 | 91 | then |
92 | 92 | echo "CharPolyTest OK" |
93 | 93 | else |
110 | 110 | echo "running RRTest" |
111 | 111 | ./RRTest < RRTestIn > XXX |
112 | 112 | sh RemoveProg RRTest |
113 | if diff XXX RRTestOut | |
113 | if diff -b XXX RRTestOut | |
114 | 114 | then |
115 | 115 | echo "RRTest OK" |
116 | 116 | else |
124 | 124 | echo "running QuadTest" |
125 | 125 | ./QuadTest < QuadTestIn > XXX |
126 | 126 | sh RemoveProg QuadTest |
127 | if diff XXX QuadTestOut | |
127 | if diff -b XXX QuadTestOut | |
128 | 128 | then |
129 | 129 | echo "QuadTest OK" |
130 | 130 | else |
139 | 139 | echo "running LLLTest" |
140 | 140 | ./LLLTest < LLLTestIn > XXX |
141 | 141 | sh RemoveProg LLLTest |
142 | if diff XXX LLLTestOut | |
142 | if diff -b XXX LLLTestOut | |
143 | 143 | then |
144 | 144 | echo "LLLTest OK" |
145 | 145 | else |
48 | 48 | cp tools.c small/src |
49 | 49 | cp vec_ZZ.c small/src |
50 | 50 | cp vec_ZZ_p.c small/src |
51 | cp vec_long.c small/src | |
52 | 51 | cp GF2.c small/src |
53 | 52 | cp WordVector.c small/src |
54 | 53 | cp vec_GF2.c small/src |
0 | 0 | # This is a perl script, invoked from a shell |
1 | 1 | |
2 | # use warnings; # this doesn't work on older versions of perl | |
2 | use warnings; # this doesn't work on older versions of perl | |
3 | 3 | |
4 | 4 | |
5 | 5 | sub GenConfigHeader { |
88 | 88 | 'NTL_GF2X_ALTCODE' => 0, |
89 | 89 | 'NTL_GF2X_ALTCODE1' => 0, |
90 | 90 | 'NTL_GF2X_NOINLINE' => 0, |
91 | 'NTL_FFT_BIGTAB' => 0, | |
92 | 'NTL_FFT_LAZYMUL' => 0, | |
91 | 93 | |
92 | 94 | 'WIZARD_HACK' => '#define NTL_WIZARD_HACK', |
93 | 95 | |
103 | 105 | |
104 | 106 | |
105 | 107 | |
106 | # set AVOID_BRANCHING and SPMM flags...try all pairs | |
108 | # set AVOID_BRANCHING, SPMM, and FFT flags...try all combinations | |
107 | 109 | |
108 | 110 | |
109 | 111 | $time = "999999999999999"; |
110 | 112 | $aflag = "default"; |
111 | 113 | $bflag = "default"; |
114 | $cflag = "default"; | |
115 | $dflag = "default"; | |
116 | ||
112 | 117 | |
113 | 118 | foreach $aflag1 ("default", "NTL_AVOID_BRANCHING") { |
114 | 119 | 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") { | |
115 | 186 | |
116 | 187 | $Config{$aflag1} = 1; |
117 | 188 | $Config{$bflag1} = 1; |
118 | 189 | GenConfigHeader(); |
119 | $time1 = RunProg("Poly1TimeTest"); | |
190 | $time1 = RunProg("GF2XTimeTest"); | |
120 | 191 | |
121 | 192 | if ($time1 < $time) { |
122 | 193 | $aflag = $aflag1; |
126 | 197 | |
127 | 198 | $Config{$aflag1} = 0; |
128 | 199 | $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; | |
160 | 200 | unlink("GF2X.o"); |
161 | 201 | } |
162 | 202 | } |
861 | 861 | long db = deg(b); |
862 | 862 | |
863 | 863 | if (da < db) { |
864 | r = b; | |
864 | r = a; | |
865 | 865 | clear(q); |
866 | 866 | return; |
867 | 867 | } |
2329 | 2329 | } |
2330 | 2330 | } |
2331 | 2331 | |
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 | ||
2341 | 2332 | |
2342 | 2333 | void CopyReverse(ZZX& x, const ZZX& a, long hi) |
2343 | 2334 |
116 | 116 | GCD(d, f, t1); |
117 | 117 | |
118 | 118 | if (deg(d) == 0) { |
119 | append(u, cons(f, 1)); | |
119 | append(u, cons(f, 1L)); | |
120 | 120 | return; |
121 | 121 | } |
122 | 122 |
2 | 2 | |
3 | 3 | #include <NTL/ZZ_pEX.h> |
4 | 4 | #include <NTL/vec_vec_ZZ_p.h> |
5 | #include <NTL/ZZX.h> | |
5 | 6 | |
6 | 7 | #include <NTL/new.h> |
7 | 8 | |
306 | 307 | x.rep = a; |
307 | 308 | x.normalize(); |
308 | 309 | } |
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 | /* ------------------------------------- */ | |
309 | 329 | |
310 | 330 | |
311 | 331 | void add(ZZ_pEX& x, const ZZ_pEX& a, const ZZ_pEX& b) |
1963 | 1983 | mul(s, s, z); |
1964 | 1984 | mul(t, t, z); |
1965 | 1985 | } |
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) | |
1972 | 1986 | |
1973 | 1987 | void IterBuild(ZZ_pE* a, long n) |
1974 | 1988 | { |
3080 | 3094 | break; |
3081 | 3095 | } |
3082 | 3096 | } |
3083 | ||
3084 | rres = res; | |
3085 | } | |
3097 | } | |
3098 | rres = res; | |
3086 | 3099 | } |
3087 | 3100 | |
3088 | 3101 | void resultant(ZZ_pE& rres, const ZZ_pEX& a, const ZZ_pEX& b) |
1529 | 1529 | |
1530 | 1530 | if (deg(f) == 1) { |
1531 | 1531 | factors.SetLength(0); |
1532 | append(factors, cons(f, 1)); | |
1532 | append(factors, cons(f, 1L)); | |
1533 | 1533 | return; |
1534 | 1534 | } |
1535 | 1535 |
1420 | 1420 | |
1421 | 1421 | |
1422 | 1422 | static vec_long ModularRepBuf; |
1423 | static vec_long FFTBuf; | |
1424 | ||
1425 | ||
1426 | 1423 | |
1427 | 1424 | |
1428 | 1425 | void ToModularRep(vec_long& x, const ZZ_p& a) |
1496 | 1493 | |
1497 | 1494 | long n, i, j, m, j1; |
1498 | 1495 | vec_long& t = ModularRepBuf; |
1499 | vec_long& s = FFTBuf; | |
1500 | 1496 | ZZ_p accum; |
1501 | 1497 | |
1502 | 1498 | |
1535 | 1531 | } |
1536 | 1532 | |
1537 | 1533 | |
1538 | s.SetLength(n); | |
1539 | long *sp = s.elts(); | |
1540 | ||
1541 | 1534 | for (i = 0; i < ZZ_pInfo->NumPrimes; i++) { |
1542 | long *Root = &RootTable[i][0]; | |
1543 | 1535 | 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); | |
1547 | 1537 | } |
1548 | 1538 | } |
1549 | 1539 | |
1559 | 1549 | |
1560 | 1550 | long n, i, j, m, j1; |
1561 | 1551 | vec_long& t = ModularRepBuf; |
1562 | vec_long& s = FFTBuf; | |
1563 | 1552 | ZZ_p accum; |
1564 | 1553 | |
1565 | 1554 | if (k > ZZ_pInfo->MaxRoot) |
1602 | 1591 | } |
1603 | 1592 | |
1604 | 1593 | |
1605 | s.SetLength(n); | |
1606 | long *sp = s.elts(); | |
1607 | ||
1608 | 1594 | for (i = 0; i < ZZ_pInfo->NumPrimes; i++) { |
1609 | long *Root = &RootInvTable[i][0]; | |
1610 | 1595 | 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); | |
1617 | 1598 | } |
1618 | 1599 | |
1619 | 1600 | } |
1630 | 1611 | long k, n, i, j, l; |
1631 | 1612 | |
1632 | 1613 | vec_long& t = ModularRepBuf; |
1633 | vec_long& s = FFTBuf;; | |
1634 | 1614 | |
1635 | 1615 | t.SetLength(ZZ_pInfo->NumPrimes); |
1636 | 1616 | |
1637 | 1617 | k = y.k; |
1638 | 1618 | n = (1L << k); |
1639 | 1619 | |
1640 | s.SetLength(n); | |
1641 | long *sp = s.elts(); | |
1642 | 1620 | |
1643 | 1621 | for (i = 0; i < ZZ_pInfo->NumPrimes; i++) { |
1644 | 1622 | 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); | |
1653 | 1625 | } |
1654 | 1626 | |
1655 | 1627 | hi = min(hi, n-1); |
1680 | 1652 | long k, n, i, j, l; |
1681 | 1653 | |
1682 | 1654 | vec_long& t = ModularRepBuf; |
1683 | vec_long& s = FFTBuf; | |
1684 | 1655 | |
1685 | 1656 | k = y.k; |
1686 | 1657 | n = (1L << k); |
1687 | 1658 | |
1688 | 1659 | t.SetLength(ZZ_pInfo->NumPrimes); |
1689 | s.SetLength(n); | |
1690 | long *sp = s.elts(); | |
1691 | 1660 | |
1692 | 1661 | for (i = 0; i < ZZ_pInfo->NumPrimes; i++) { |
1693 | 1662 | 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); | |
1700 | 1664 | } |
1701 | 1665 | |
1702 | 1666 | hi = min(hi, n-1); |
1728 | 1692 | |
1729 | 1693 | for (i = 0; i < ZZ_pInfo->NumPrimes; i++) { |
1730 | 1694 | 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); | |
1739 | 1699 | } |
1740 | 1700 | |
1741 | 1701 | hi = min(hi, n-1); |
1771 | 1731 | long k, n, i, j; |
1772 | 1732 | |
1773 | 1733 | vec_long& t = ModularRepBuf; |
1774 | vec_long& s = FFTBuf; | |
1775 | 1734 | |
1776 | 1735 | k = y.k; |
1777 | 1736 | n = (1L << k); |
1778 | 1737 | |
1779 | 1738 | t.SetLength(ZZ_pInfo->NumPrimes); |
1780 | s.SetLength(n); | |
1781 | long *sp = s.elts(); | |
1782 | 1739 | |
1783 | 1740 | for (i = 0; i < ZZ_pInfo->NumPrimes; i++) { |
1784 | 1741 | 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); | |
1793 | 1744 | } |
1794 | 1745 | |
1795 | 1746 | for (j = lo; j <= hi; j++) { |
1983 | 1934 | long NumPrimes = ZZ_pInfo->NumPrimes; |
1984 | 1935 | |
1985 | 1936 | for (i = 0; i < NumPrimes; i++) { |
1986 | long *Root = &RootTable[i][0]; | |
1987 | 1937 | long *xp = &x.tbl[i][0]; |
1988 | 1938 | long *ap = (m == 0 ? 0 : &a.tbl[i][0]); |
1989 | 1939 | for (j = 0; j < m; j++) |
1991 | 1941 | for (j = m; j < n; j++) |
1992 | 1942 | sp[j] = 0; |
1993 | 1943 | |
1994 | FFT(xp, sp, k, FFTPrime[i], Root); | |
1944 | FFTFwd(xp, sp, k, i); | |
1995 | 1945 | } |
1996 | 1946 | } |
1997 | 1947 |
893 | 893 | res.SetLength(m); |
894 | 894 | f.rep = res; |
895 | 895 | } |
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 | ||
903 | 896 | |
904 | 897 | |
905 | 898 | |
1680 | 1673 | break; |
1681 | 1674 | } |
1682 | 1675 | } |
1683 | ||
1684 | rres = res; | |
1685 | } | |
1676 | } | |
1677 | ||
1678 | rres = res; | |
1686 | 1679 | } |
1687 | 1680 | |
1688 | 1681 |
1910 | 1910 | |
1911 | 1911 | if (deg(f) == 1) { |
1912 | 1912 | factors.SetLength(0); |
1913 | append(factors, cons(f, 1)); | |
1913 | append(factors, cons(f, 1L)); | |
1914 | 1914 | return; |
1915 | 1915 | } |
1916 | 1916 |
1805 | 1805 | #endif |
1806 | 1806 | |
1807 | 1807 | |
1808 | long _ntl_zmaxalloc(_ntl_verylong x) | |
1809 | { | |
1810 | if (!x) | |
1811 | return 0; | |
1812 | else | |
1813 | return (x[-1] >> 1) - 1; | |
1814 | } | |
1815 | ||
1808 | 1816 | |
1809 | 1817 | void _ntl_zsetlength(_ntl_verylong *v, long len) |
1810 | 1818 | { |
1857 | 1865 | } |
1858 | 1866 | } |
1859 | 1867 | 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; | |
1862 | 1870 | |
1863 | 1871 | /* test len again */ |
1864 | 1872 | if (NTL_OVERFLOW(len, NTL_NBITS, 0)) |
410 | 410 | * and NTL_SPMM_ASM. |
411 | 411 | * This plays a crucial role in the "small prime FFT" used to |
412 | 412 | * 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 | |
414 | 414 | * arithmetic over zz_p. |
415 | 415 | */ |
416 | 416 | |
456 | 456 | |
457 | 457 | |
458 | 458 | |
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 | ||
459 | 500 | |
460 | 501 | |
461 | 502 | /* The next five flags NTL_AVOID_BRANCHING, NTL_TBL_REM, |
99 | 99 | GMP_LIBDIR=$(GMP_PREFIX)/lib |
100 | 100 | # directory containing libgmp.a if using GMP |
101 | 101 | |
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 | |
104 | 104 | GMP_OPT_LIB=# -lgmp # GMP |
105 | 105 | # uncomment these if using GMP |
106 | 106 | |
159 | 159 | O07=$(O06) lzz_pX.o lzz_pX1.o lzz_pXCharPoly.o lzz_pXFactoring.o |
160 | 160 | O08=$(O07) mat_GF2.o mat_GF2E.o mat_RR.o mat_ZZ.o mat_ZZ_p.o |
161 | 161 | 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 | |
172 | 172 | |
173 | 173 | OBJ=$(O19) |
174 | 174 | |
184 | 184 | S07=$(S06) lzz_pEXFactoring.c lzz_pX.c lzz_pX1.c |
185 | 185 | S08=$(S07) lzz_pXCharPoly.c lzz_pXFactoring.c mat_GF2.c mat_GF2E.c |
186 | 186 | 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 | |
196 | 196 | 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) | |
200 | 199 | |
201 | 200 | # library source files that are header files |
202 | 201 | |
515 | 514 | ###################################################################### |
516 | 515 | |
517 | 516 | 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 | |
519 | 518 | WO3 = $(WO2) GF2.o WordVector.o vec_GF2.o GF2X.o GF2X1.o |
520 | 519 | |
521 | 520 | WOBJ = $(WO3) |
355 | 355 | } |
356 | 356 | |
357 | 357 | |
358 | long _ntl_gmaxalloc(_ntl_gbigint x) | |
359 | { | |
360 | if (!x) | |
361 | return 0; | |
362 | else | |
363 | return (ALLOC(x) >> 2) - 1; | |
364 | } | |
365 | ||
358 | 366 | #define MIN_SETL (4) |
359 | 367 | /* _ntl_gsetlength allocates a multiple of MIN_SETL digits */ |
360 | 368 | |
413 | 421 | } |
414 | 422 | } |
415 | 423 | 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; | |
418 | 426 | |
419 | 427 | /* test len again */ |
420 | 428 | if (NTL_OVERFLOW(len, NTL_ZZ_NBITS, 0)) |
4188 | 4196 | c = (struct crt_body *) NTL_MALLOC(1, sizeof(struct crt_body), 0); |
4189 | 4197 | if (!c) ghalt("out of memory"); |
4190 | 4198 | |
4191 | if (n >= 600) { | |
4199 | if (n >= 600) { | |
4192 | 4200 | struct crt_body_gmp1 *C = &c->U.G1; |
4193 | 4201 | long *q; |
4194 | 4202 | long i, j; |
4275 | 4283 | for (i = (1L << (levels-1)) - 2; i >= 0; i--) |
4276 | 4284 | _ntl_gmul(prod_vec[2*i+1], prod_vec[2*i+2], &prod_vec[i]); |
4277 | 4285 | |
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 | |
4279 | 4313 | /* the following is asymptotically the bottleneck...but it |
4280 | 4314 | * it probably doesn't matter. */ |
4281 | 4315 | |
4316 | fprintf(stderr, "checking in lip\n"); | |
4282 | 4317 | for (i = 0; i < n; i++) { |
4283 | 4318 | long tt; |
4284 | 4319 | _ntl_gsdiv(prod_vec[0], q[i], &temps[0]); |
4285 | 4320 | 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 | |
4288 | 4328 | |
4289 | 4329 | c->strategy = 2; |
4290 | 4330 | C->n = n; |
3 | 3 | |
4 | 4 | #include <NTL/lzz_pEX.h> |
5 | 5 | #include <NTL/vec_vec_lzz_p.h> |
6 | #include <NTL/ZZX.h> | |
6 | 7 | |
7 | 8 | #include <NTL/new.h> |
8 | 9 | |
308 | 309 | x.rep = a; |
309 | 310 | x.normalize(); |
310 | 311 | } |
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 | ||
311 | 333 | |
312 | 334 | |
313 | 335 | void add(zz_pEX& x, const zz_pEX& a, const zz_pEX& b) |
1966 | 1988 | mul(t, t, z); |
1967 | 1989 | } |
1968 | 1990 | |
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) | |
1974 | 1991 | |
1975 | 1992 | void IterBuild(zz_pE* a, long n) |
1976 | 1993 | { |
3083 | 3100 | break; |
3084 | 3101 | } |
3085 | 3102 | } |
3086 | ||
3087 | rres = res; | |
3088 | } | |
3103 | } | |
3104 | rres = res; | |
3089 | 3105 | } |
3090 | 3106 | |
3091 | 3107 | void resultant(zz_pE& rres, const zz_pEX& a, const zz_pEX& b) |
1532 | 1532 | |
1533 | 1533 | if (deg(f) == 1) { |
1534 | 1534 | factors.SetLength(0); |
1535 | append(factors, cons(f, 1)); | |
1535 | append(factors, cons(f, 1L)); | |
1536 | 1536 | return; |
1537 | 1537 | } |
1538 | 1538 |
142 | 142 | |
143 | 143 | |
144 | 144 | |
145 | zz_p coeff(const zz_pX& a, long i) | |
145 | const zz_p coeff(const zz_pX& a, long i) | |
146 | 146 | { |
147 | 147 | if (i < 0 || i > deg(a)) |
148 | 148 | return zz_p::zero(); |
151 | 151 | } |
152 | 152 | |
153 | 153 | |
154 | zz_p LeadCoeff(const zz_pX& a) | |
154 | const zz_p LeadCoeff(const zz_pX& a) | |
155 | 155 | { |
156 | 156 | if (IsZero(a)) |
157 | 157 | return zz_p::zero(); |
159 | 159 | return a.rep[deg(a)]; |
160 | 160 | } |
161 | 161 | |
162 | zz_p ConstTerm(const zz_pX& a) | |
162 | const zz_p ConstTerm(const zz_pX& a) | |
163 | 163 | { |
164 | 164 | if (IsZero(a)) |
165 | 165 | return zz_p::zero(); |
1382 | 1382 | return; |
1383 | 1383 | } |
1384 | 1384 | |
1385 | if (NumPrimes != zz_pInfo->NumPrimes) | |
1385 | if (MaxK == -1) | |
1386 | NumPrimes = zz_pInfo->NumPrimes; | |
1387 | else if (NumPrimes != zz_pInfo->NumPrimes) | |
1386 | 1388 | Error("fftRep: inconsistent use"); |
1387 | 1389 | |
1388 | 1390 | long i, n; |
1404 | 1406 | fftRep::fftRep(const fftRep& R) |
1405 | 1407 | { |
1406 | 1408 | k = MaxK = R.k; |
1409 | NumPrimes = 0; | |
1410 | ||
1411 | if (k < 0) return; | |
1412 | ||
1407 | 1413 | NumPrimes = R.NumPrimes; |
1408 | ||
1409 | if (k < 0) return; | |
1410 | 1414 | |
1411 | 1415 | long i, j, n; |
1412 | 1416 | |
1425 | 1429 | { |
1426 | 1430 | if (this == &R) return *this; |
1427 | 1431 | |
1428 | if (NumPrimes != R.NumPrimes) | |
1432 | if (MaxK >= 0 && R.MaxK >= 0 && NumPrimes != R.NumPrimes) | |
1429 | 1433 | Error("fftRep: inconsistent use"); |
1430 | 1434 | |
1431 | 1435 | if (R.k < 0) { |
1432 | 1436 | k = -1; |
1433 | 1437 | return *this; |
1434 | 1438 | } |
1439 | ||
1440 | NumPrimes = R.NumPrimes; | |
1435 | 1441 | |
1436 | 1442 | if (R.k > MaxK) { |
1437 | 1443 | long i, n; |
1476 | 1482 | free(tbl[i]); |
1477 | 1483 | } |
1478 | 1484 | |
1479 | ||
1480 | ||
1481 | static vec_long FFTBuf; | |
1482 | 1485 | |
1483 | 1486 | |
1484 | 1487 | |
1548 | 1551 | // if deg(x) >= 2^k, then x is first reduced modulo X^n-1. |
1549 | 1552 | { |
1550 | 1553 | long n, i, j, m, j1; |
1551 | vec_long& s = FFTBuf;; | |
1552 | 1554 | zz_p accum; |
1553 | 1555 | long NumPrimes = zz_pInfo->NumPrimes; |
1554 | 1556 | |
1605 | 1607 | } |
1606 | 1608 | |
1607 | 1609 | |
1608 | s.SetLength(n); | |
1609 | long *sp = s.elts(); | |
1610 | ||
1611 | 1610 | if (index >= 0) { |
1612 | long *Root = &RootTable[index][0]; | |
1613 | 1611 | 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); | |
1617 | 1613 | } |
1618 | 1614 | else { |
1619 | 1615 | for (i = 0; i < zz_pInfo->NumPrimes; i++) { |
1620 | long *Root = &RootTable[i][0]; | |
1621 | 1616 | 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); | |
1625 | 1618 | } |
1626 | 1619 | } |
1627 | 1620 | } |
1635 | 1628 | |
1636 | 1629 | { |
1637 | 1630 | long n, i, j, m, j1; |
1638 | vec_long& s = FFTBuf; | |
1639 | 1631 | zz_p accum; |
1640 | 1632 | long NumPrimes = zz_pInfo->NumPrimes; |
1641 | 1633 | |
1695 | 1687 | } |
1696 | 1688 | |
1697 | 1689 | |
1698 | s.SetLength(n); | |
1699 | long *sp = s.elts(); | |
1700 | ||
1701 | 1690 | if (index >= 0) { |
1702 | long *Root = &RootInvTable[index][0]; | |
1703 | 1691 | 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); | |
1710 | 1694 | } |
1711 | 1695 | else { |
1712 | 1696 | for (i = 0; i < zz_pInfo->NumPrimes; i++) { |
1713 | long *Root = &RootInvTable[i][0]; | |
1714 | 1697 | 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); | |
1721 | 1700 | } |
1722 | 1701 | } |
1723 | 1702 | } |
1733 | 1712 | long NumPrimes = zz_pInfo->NumPrimes; |
1734 | 1713 | |
1735 | 1714 | long t[4]; |
1736 | vec_long& s = FFTBuf; | |
1737 | 1715 | |
1738 | 1716 | k = y.k; |
1739 | 1717 | n = (1L << k); |
1740 | 1718 | |
1741 | s.SetLength(n); | |
1742 | long *sp = s.elts(); | |
1743 | ||
1744 | 1719 | long index = zz_pInfo->index; |
1745 | 1720 | |
1746 | 1721 | if (index >= 0) { |
1747 | 1722 | 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); | |
1756 | 1725 | } |
1757 | 1726 | else { |
1758 | 1727 | for (i = 0; i < NumPrimes; i++) { |
1759 | 1728 | 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); | |
1768 | 1731 | } |
1769 | 1732 | } |
1770 | 1733 | |
1803 | 1766 | long NumPrimes = zz_pInfo->NumPrimes; |
1804 | 1767 | |
1805 | 1768 | long t[4]; |
1806 | vec_long& s = FFTBuf; | |
1807 | 1769 | |
1808 | 1770 | k = y.k; |
1809 | 1771 | n = (1L << k); |
1810 | 1772 | |
1811 | s.SetLength(n); | |
1812 | long *sp = s.elts(); | |
1813 | ||
1814 | 1773 | long index = zz_pInfo->index; |
1815 | 1774 | |
1816 | 1775 | if (index >= 0) { |
1817 | 1776 | 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); | |
1824 | 1778 | } |
1825 | 1779 | else { |
1826 | 1780 | for (i = 0; i < NumPrimes; i++) { |
1827 | 1781 | 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); | |
1834 | 1783 | } |
1835 | 1784 | } |
1836 | 1785 | |
1871 | 1820 | |
1872 | 1821 | if (index >= 0) { |
1873 | 1822 | 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); | |
1882 | 1826 | } |
1883 | 1827 | else { |
1884 | 1828 | for (i = 0; i < NumPrimes; i++) { |
1885 | 1829 | 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); | |
1894 | 1833 | } |
1895 | 1834 | } |
1896 | 1835 | |
1934 | 1873 | long NumPrimes = zz_pInfo->NumPrimes; |
1935 | 1874 | |
1936 | 1875 | long t[4]; |
1937 | vec_long& s = FFTBuf; | |
1938 | 1876 | |
1939 | 1877 | k = y.k; |
1940 | 1878 | n = (1L << k); |
1941 | ||
1942 | s.SetLength(n); | |
1943 | long *sp = s.elts(); | |
1944 | 1879 | |
1945 | 1880 | long index = zz_pInfo->index; |
1946 | 1881 | if (index >= 0) { |
1947 | 1882 | 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); | |
1956 | 1885 | |
1957 | 1886 | for (j = lo; j <= hi; j++) { |
1958 | 1887 | if (j >= n) |
1965 | 1894 | else { |
1966 | 1895 | for (i = 0; i < NumPrimes; i++) { |
1967 | 1896 | 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); | |
1976 | 1899 | } |
1977 | 1900 | |
1978 | 1901 | for (j = lo; j <= hi; j++) { |
887 | 887 | res.SetLength(m); |
888 | 888 | f.rep = res; |
889 | 889 | } |
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 | ||
897 | 890 | |
898 | 891 | |
899 | 892 | |
1683 | 1676 | break; |
1684 | 1677 | } |
1685 | 1678 | } |
1686 | ||
1687 | rres = res; | |
1688 | } | |
1679 | } | |
1680 | ||
1681 | rres = res; | |
1689 | 1682 | } |
1690 | 1683 | |
1691 | 1684 |
1919 | 1919 | |
1920 | 1920 | if (deg(f) == 1) { |
1921 | 1921 | factors.SetLength(0); |
1922 | append(factors, cons(f, 1)); | |
1922 | append(factors, cons(f, 1L)); | |
1923 | 1923 | return; |
1924 | 1924 | } |
1925 | 1925 |
99 | 99 | GMP_LIBDIR=$(GMP_PREFIX)/lib |
100 | 100 | # directory containing libgmp.a if using GMP |
101 | 101 | |
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 | |
104 | 104 | GMP_OPT_LIB=# -lgmp # GMP |
105 | 105 | # uncomment these if using GMP |
106 | 106 | |
159 | 159 | O07=$(O06) lzz_pX.o lzz_pX1.o lzz_pXCharPoly.o lzz_pXFactoring.o |
160 | 160 | O08=$(O07) mat_GF2.o mat_GF2E.o mat_RR.o mat_ZZ.o mat_ZZ_p.o |
161 | 161 | 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 | |
172 | 172 | |
173 | 173 | OBJ=$(O19) |
174 | 174 | |
184 | 184 | S07=$(S06) lzz_pEXFactoring.c lzz_pX.c lzz_pX1.c |
185 | 185 | S08=$(S07) lzz_pXCharPoly.c lzz_pXFactoring.c mat_GF2.c mat_GF2E.c |
186 | 186 | 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 | |
196 | 196 | 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) | |
200 | 199 | |
201 | 200 | # library source files that are header files |
202 | 201 | |
515 | 514 | ###################################################################### |
516 | 515 | |
517 | 516 | 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 | |
519 | 518 | WO3 = $(WO2) GF2.o WordVector.o vec_GF2.o GF2X.o GF2X1.o |
520 | 519 | |
521 | 520 | WOBJ = $(WO3) |
5 | 5 | #include <NTL/new.h> |
6 | 6 | |
7 | 7 | 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 | } | |
129 | 8 | |
130 | 9 | |
131 | 10 | void add(mat_GF2& X, const mat_GF2& A, const mat_GF2& B) |
272 | 151 | } |
273 | 152 | |
274 | 153 | |
275 | void determinant(GF2& d, const mat_GF2& M_in) | |
154 | void determinant(ref_GF2 d, const mat_GF2& M_in) | |
276 | 155 | { |
277 | 156 | long k, n; |
278 | 157 | long i, j; |
435 | 314 | |
436 | 315 | |
437 | 316 | |
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) | |
439 | 318 | |
440 | 319 | { |
441 | 320 | long n = A.NumRows(); |
520 | 399 | |
521 | 400 | |
522 | 401 | |
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) | |
524 | 403 | { |
525 | 404 | long n = A.NumRows(); |
526 | 405 | if (A.NumCols() != n) |
5 | 5 | #include <NTL/new.h> |
6 | 6 | |
7 | 7 | 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 | ||
13 | 8 | |
14 | 9 | |
15 | 10 | void add(mat_GF2E& X, const mat_GF2E& A, const mat_GF2E& B) |
3 | 3 | #include <NTL/new.h> |
4 | 4 | |
5 | 5 | 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 | ||
11 | 6 | |
12 | 7 | |
13 | 8 | void add(mat_RR& X, const mat_RR& A, const mat_RR& B) |
3 | 3 | #include <NTL/new.h> |
4 | 4 | |
5 | 5 | 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 | ||
11 | 6 | |
12 | 7 | |
13 | 8 | void add(mat_ZZ& X, const mat_ZZ& A, const mat_ZZ& B) |
2 | 2 | #include <NTL/vec_ZZVec.h> |
3 | 3 | #include <NTL/vec_long.h> |
4 | 4 | |
5 | #include <NTL/new.h> | |
6 | ||
7 | 5 | 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 | ||
13 | 6 | |
14 | 7 | |
15 | 8 | void add(mat_ZZ_p& X, const mat_ZZ_p& A, const mat_ZZ_p& B) |
3 | 3 | #include <NTL/new.h> |
4 | 4 | |
5 | 5 | 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 | ||
13 | 6 | |
14 | 7 | |
15 | 8 | void add(mat_ZZ_pE& X, const mat_ZZ_pE& A, const mat_ZZ_pE& B) |
7 | 7 | #include <NTL/vec_double.h> |
8 | 8 | |
9 | 9 | 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 | ||
15 | 10 | |
16 | 11 | |
17 | 12 | void add(mat_zz_p& X, const mat_zz_p& A, const mat_zz_p& B) |
3 | 3 | #include <NTL/new.h> |
4 | 4 | |
5 | 5 | 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 | ||
13 | 6 | |
14 | 7 | |
15 | 8 | void add(mat_zz_pE& X, const mat_zz_pE& A, const mat_zz_pE& B) |
159 | 159 | O07=$(O06) lzz_pX.o lzz_pX1.o lzz_pXCharPoly.o lzz_pXFactoring.o |
160 | 160 | O08=$(O07) mat_GF2.o mat_GF2E.o mat_RR.o mat_ZZ.o mat_ZZ_p.o |
161 | 161 | 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 | |
172 | 172 | |
173 | 173 | OBJ=$(O19) |
174 | 174 | |
184 | 184 | S07=$(S06) lzz_pEXFactoring.c lzz_pX.c lzz_pX1.c |
185 | 185 | S08=$(S07) lzz_pXCharPoly.c lzz_pXFactoring.c mat_GF2.c mat_GF2E.c |
186 | 186 | 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 | |
196 | 196 | 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) | |
200 | 199 | |
201 | 200 | # library source files that are header files |
202 | 201 | |
515 | 514 | ###################################################################### |
516 | 515 | |
517 | 516 | 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 | |
519 | 518 | WO3 = $(WO2) GF2.o WordVector.o vec_GF2.o GF2X.o GF2X1.o |
520 | 519 | |
521 | 520 | WOBJ = $(WO3) |
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 |
125 | 125 | _maxlen |= 1; |
126 | 126 | } |
127 | 127 | |
128 | GF2 vec_GF2::get(long i) const | |
128 | const GF2 vec_GF2::get(long i) const | |
129 | 129 | { |
130 | 130 | const vec_GF2& v = *this; |
131 | 131 | |
141 | 141 | return to_GF2(0); |
142 | 142 | } |
143 | 143 | |
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 | ||
144 | 158 | static |
145 | 159 | void SetBit(vec_GF2& v, long i) |
146 | 160 | { |
187 | 201 | } |
188 | 202 | |
189 | 203 | |
190 | void append(vec_GF2& v, GF2 a) | |
204 | void append(vec_GF2& v, const GF2& a) | |
191 | 205 | { |
192 | 206 | long n = v.length(); |
193 | 207 | v.SetLength(n+1); |
0 | ||
1 | 0 | |
2 | 1 | #include <NTL/vec_GF2E.h> |
3 | 2 | |
4 | #include <NTL/new.h> | |
5 | 3 | |
6 | 4 | NTL_START_IMPL |
7 | ||
8 | ||
9 | ||
10 | ||
11 | ||
12 | 5 | |
13 | 6 | void BlockConstruct(GF2E* x, long n) |
14 | 7 | { |
45 | 38 | } |
46 | 39 | } |
47 | 40 | |
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) | |
55 | 41 | |
56 | 42 | |
57 | 43 | void InnerProduct(GF2E& x, const vec_GF2E& a, const vec_GF2E& b) |
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 |
0 | 0 | |
1 | 1 | #include <NTL/vec_RR.h> |
2 | 2 | |
3 | #include <NTL/new.h> | |
4 | 3 | |
5 | 4 | NTL_START_IMPL |
6 | 5 | |
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) | |
13 | 6 | |
14 | 7 | void InnerProduct(RR& xx, const vec_RR& a, const vec_RR& b) |
15 | 8 | { |
0 | 0 | |
1 | 1 | #include <NTL/vec_ZZ.h> |
2 | 2 | |
3 | #include <NTL/new.h> | |
4 | ||
5 | 3 | NTL_START_IMPL |
6 | 4 | |
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) | |
13 | 5 | |
14 | 6 | void InnerProduct(ZZ& xx, const vec_ZZ& a, const vec_ZZ& b) |
15 | 7 | { |
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 |
0 | 0 | |
1 | 1 | |
2 | 2 | #include <NTL/vec_ZZ_p.h> |
3 | ||
4 | #include <NTL/new.h> | |
5 | 3 | |
6 | 4 | NTL_START_IMPL |
7 | 5 | |
41 | 39 | } |
42 | 40 | |
43 | 41 | |
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 | ||
51 | 42 | void conv(vec_ZZ_p& x, const vec_ZZ& a) |
52 | 43 | { |
53 | 44 | long i, n; |
0 | 0 | |
1 | 1 | #include <NTL/vec_ZZ_pE.h> |
2 | 2 | |
3 | #include <NTL/new.h> | |
4 | 3 | |
5 | 4 | 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 | ||
13 | 5 | |
14 | 6 | void InnerProduct(ZZ_pE& x, const vec_ZZ_pE& a, const vec_ZZ_pE& b) |
15 | 7 | { |
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 | ||
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 |
0 | 0 | |
1 | 1 | #include <NTL/vec_lzz_p.h> |
2 | 2 | |
3 | #include <NTL/new.h> | |
4 | ||
5 | 3 | 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) | |
12 | 4 | |
13 | 5 | void conv(vec_zz_p& x, const vec_ZZ& a) |
14 | 6 | { |
0 | 0 | |
1 | 1 | #include <NTL/vec_lzz_pE.h> |
2 | 2 | |
3 | #include <NTL/new.h> | |
4 | ||
5 | 3 | 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 | ||
13 | 4 | |
14 | 5 | void InnerProduct(zz_pE& x, const vec_zz_pE& a, const vec_zz_pE& b) |
15 | 6 | { |
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 | ||
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 |