-
Notifications
You must be signed in to change notification settings - Fork 0
/
fields.hpp
289 lines (275 loc) · 9.93 KB
/
fields.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
#ifndef __FIELDS_H_
#define __FIELDS_H_
/*****************************************************************************\
* This file is part of DynGB. *
* *
* DynGB is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 2 of the License, or *
* (at your option) any later version. *
* *
* DynGB is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with DynGB. If not, see <http://www.gnu.org/licenses/>. *
\*****************************************************************************/
#include <vector>
using std::vector;
#include <iostream>
using std::ostream;
#include "system_constants.hpp"
/**
@defgroup FieldsGroup Fields
@brief classes for performing field arithmetic
*/
// forward declaration
class Prime_Field_Element;
/**
@class Prime_Field
@author John Perry
@date 2015
@brief Information necessary for a field modulo a prime.
@ingroup FieldsGroup
@details This class encapsulates the information necessary for a field modulo a prime:
both the modulus @f$m@f$ and a list of inverses of non-zero elements.
The constructors do not verify that @f$m@f$ is prime,
but expect misbehavior if not.
@warning The constructor does not check whether the supplied modulus is prime.
If @f$m@f$ is not prime, behavior is undefined, and probably spectacularly bad.
*/
class Prime_Field
{
public:
/** @name Construction */
///@{
/**
@brief Please read detailed information.
@param modulus All computation in this field is done modulo this number;
it should be prime, but we do not check this. See this warning.
@param show_modulus indicates whether the modulus is shown when printing an
element of this field. You probably don't want this.
@warning This constructor does not check whether @p modulus is prime.
If @f$m@f$ is not prime, behavior is undefined,
and probably spectacularly bad.
*/
Prime_Field(UCOEF_TYPE modulus, bool show_modulus = false);
/**
@brief Copy constructor: copies previously-computed inverses.
@param F the source to copy
Allocates new data, so you can discard <c>F</c> later if you want.
*/
explicit Prime_Field(const Prime_Field & F);
///@}
/** @name Destruction */
///@{
~Prime_Field();
///@}
/**
@name Basic properties
The following functions give information about the prime field,
but do not modify it.
*/
///@{
/** @brief Returns the field's modulus. */
COEF_TYPE modulus() const { return m; }
/**
@brief Returns the inverse of @f$a@f$, modulo @f$m@f$.
@param a the element of this field whose inverse we desire
@return @f$ a^{-1} @f$
@details Looks up the inverse in a table.
*/
COEF_TYPE inverse(COEF_TYPE a) const { return Fi[a]; };
/** @brief “unity” is the multiplicative identity. */
Prime_Field_Element unity() const;
/** @brief “zero” is the additive identity. */
Prime_Field_Element zero() const;
///@}
/** \name I/O */
///@{
/** @brief determines whether to print the modulus */
void set_print_modulus(bool b);
/** @brief indicates whether to print the modulus */
bool get_print_modulus() const;
///@}
/** @name Modification */
Prime_Field & operator = (const Prime_Field & other) {
m = other.m;
print_modulus = other.print_modulus;
Fi = other.Fi;
return *this;
}
///@{
///@}
protected:
/** @brief characteristic/modulus of the field */
COEF_TYPE m;
/**
@brief for @f$i\neq0@f$, @f$Fi_i@f$ is multiplicative inverse
of @f$i@f$, mod @f$m@f$
*/
vector<COEF_TYPE> Fi;
/**
@brief determines whether a coefficient's modulus is printed
*/
bool print_modulus;
};
/**
@class Prime_Field_Element
@author John Perry
@date 2015
@brief Element of a field of prime characteristic.
@ingroup FieldsGroup
@details This class encapsulates an element of a field of prime characteristic
(Prime_Field).
@warning Do not delete the prime field that <c>this</c> lives in while
<c>this</c> is still active.
Behavior is unpredictable in this circumstance,
as the field is necessary for some record keeping, e.g.,
to look up multiplicative inverses.
*/
class Prime_Field_Element
{
public:
/** @name Construction */
///@{
/**
@brief Constructs a prime field element in the specified field,
with the value 0.
@param field this element’s parent
@details A pointer to <c>field</c> is attached to <c>this</c>
in order to find inverses during arithmetic.
@warning Do not delete this field while <c>this</c> is still active.
Behavior is unpredictable in this circumstance.
*/
explicit Prime_Field_Element(const Prime_Field *field);
/**
@brief Constructs a prime field element in the specified field,
with the specified value.
@param value the element’s value
@param field the element’s base field
@details A pointer to <c>field</c> is attached to <c>this</c>
in order to find inverses during arithmetic.
@warning Do not delete this field while <c>this</c> is still active.
Behavior is unpredictable in this circumstance.
*/
Prime_Field_Element(COEF_TYPE value, const Prime_Field *field);
/** @brief constructs a prime field element from another */
Prime_Field_Element(const Prime_Field_Element & other) {
a = other.a; F = other.F; m = other.m;
}
///@}
/** @name Basic properties
The following functions give information about the monomial,
but do not modify it.
*/
///@{
/** @brief The value of the element. This always satisfies @f$0\leq a\leq m@f$. */
COEF_TYPE value() const;
/** @brief The field's modulus. */
COEF_TYPE modulus() const;
/** @brief The field this element lies in. */
const Prime_Field * field() const;
/** @brief <c>true</c> iff <c>this</c> and <c>b</c> have the same modulus. */
bool like(const Prime_Field_Element & b) const;
/** @brief Returns the multiplicative inverse of <c>this</c>. */
COEF_TYPE inverse() const;
/** @brief Is <c>this</c> the additive identity? */
inline bool is_zero() const { return a == 0; };
/** @brief Is <c>this</c> the multiplicative identity? */
bool is_one() const;
///@}
/** @name Modification */
///@{
/** @brief assignment to other */
Prime_Field_Element & operator = (const Prime_Field_Element & other) {
a = other.a; F = other.F; m = other.m;
return *this;
}
/** @brief for initializing arrays of Prime_Field_Element */
void assign(COEF_TYPE val, const Prime_Field * K) {
a = val; F = K; m = F->modulus();
}
///@}
/**
@name Computation
Computes something, and may modify <c>this</c>.
*/
///@{
/** @brief “Negates” <c>this</c>. */
void negate();
/**
@brief increases the value of <c>this</c>.
@param other element to add
*/
void operator +=(const Prime_Field_Element &other);
/**
@brief decreases the value of <c>this</c>.
@param other element to subtract
*/
void operator -=(const Prime_Field_Element &other);
/**
@brief multiply the value of <c>this</c> by @p other
@param other element to multiply
*/
void operator *=(const Prime_Field_Element &other);
/**
@brief Changes the value of <c>this</c>.
@param b scalar to multiply
@details This function is useful for avoiding the construction
of a prime field element when you know what you want to multiply.
*/
void operator *=(const COEF_TYPE b);
/**
@brief Changes the value of <c>this</c>.
@param other element to multiply
@details Multiplies by multiplicative inverse of <c>other</c>. */
void operator /=(const Prime_Field_Element &other);
///@}
/** @name Friend functions for computation
Will not modify <c>this</c>.
*/
///@{
/** @brief Does not modify <c>this</c>. */
friend Prime_Field_Element operator+(const Prime_Field_Element &,
const Prime_Field_Element &);
/** @brief Does not modify <c>this</c>. */
friend Prime_Field_Element operator-(const Prime_Field_Element &,
const Prime_Field_Element &);
/** @brief Does not modify <c>this</c>. */
friend Prime_Field_Element operator*(const Prime_Field_Element &,
const Prime_Field_Element &);
/** @brief Does not modify <c>this</c>. */
friend Prime_Field_Element operator+(const Prime_Field_Element &, const int);
/** @brief Does not modify <c>this</c>. */
friend Prime_Field_Element operator-(const Prime_Field_Element &, const int);
/** @brief Does not modify <c>this</c>. */
friend Prime_Field_Element operator*(const Prime_Field_Element &, const int);
/**
@brief Does not modify <c>this</c>. If you want to modify <c>this</c>,
see negate().
*/
friend Prime_Field_Element operator-(const Prime_Field_Element &);
///@}
/** @name I/O
@brief Will not modify <c>this</c>.
*/
///@{
friend ostream & operator << (ostream &, const Prime_Field_Element &);
///@}
protected:
/** @brief the field this element lives in; used to find inverses */
const Prime_Field *F;
/**
@brief the number’s value; descendants should ensure @f$0\leq a<m@f$
*/
COEF_TYPE a;
/**
@brief the number’ modulus, stored here to avoid the expense of
accessing it in @f$F@f$.
*/
COEF_TYPE m;
};
#endif