Macaulay2 Engine
Loading...
Searching...
No Matches
aring-m2-gf.hpp
Go to the documentation of this file.
1// Copyright 2012 Michael E. Stillman
2
3#ifndef _aring_gf_m2_hpp_
4#define _aring_gf_m2_hpp_
5
40
41#include "interface/random.h"
42#include "aring.hpp"
43#include "buffer.hpp"
44#include "ringelem.hpp"
45#include "exceptions.hpp" // for exc::division_by_zero_error, exc::internal_error
46#include <iostream>
47
48#include "polyring.hpp"
49class RingMap;
50
51class GF;
52class PolynomialRing;
53class RingElement;
54
55namespace M2 {
56
57typedef int GFElement;
63{
64 friend class GF;
65 friend class ARingGFM2;
66
67 public:
71 GaloisFieldTable(const PolynomialRing &R, const ring_elem prim);
72
73 // debug display of the tables
74 void display(std::ostream &o) const;
75
76 GFElement characteristic() const { return mCharac; }
77 GFElement dimension() const { return mDimension; }
78 GFElement order() const { return mOrder; }
79 GFElement one() const { return mOne; }
80 GFElement minusOne() const { return mMinusOne; }
82 GFElement oneTable(GFElement a) const { return mOneTable[a]; }
84 const PolynomialRing &ring() const { return mOriginalRing; }
86 const RingElement *getGenerator() const { return mGenerator; }
88 private:
89 // CONSTANT usable fields.
96
99
102 const ring_elem mPrimitiveElement; // is an element of mOriginalRing
104 // the given generator of mOriginalRing is
105 // mPrimitiveElement^mGeneratorExponent (in this ring).
106};
107
124class ARingGFM2 : public SimpleARing<ARingGFM2>
125{
126 public:
127 static const RingID ringID = ring_GFM2;
128 typedef int ElementType;
129 typedef int elem;
130 typedef std::vector<elem> ElementContainerType;
141 ARingGFM2(const PolynomialRing &R, const ring_elem a);
142
143 GFElement characteristic() const { return mGF.characteristic(); }
144 void text_out(buffer &o) const;
145
146 const PolynomialRing &originalRing() const { return mGF.ring(); }
147 private:
149
153
154 static inline int modulus_add(int a, int b, int p)
155 {
156 int t = a + b;
157 return (t <= p ? t : t - p);
158 }
159
160 static inline int modulus_sub(int a, int b, int p)
161 {
162 int t = a - b;
163 return (t <= 0 ? t + p : t);
164 }
165
166 public:
167 unsigned int computeHashValue(const elem &a) const { return a; }
168 void getGenerator(elem &result_gen) const { result_gen = 1; }
169 int get_repr(elem f) const
170 { /*TODO: WRITE WRITE ;*/
171 (void) f;
172 throw exc::internal_error("get_repr not written");
173 }
174
176 {
177 result = ring_elem(a);
178 }
179
181 {
182 result = a.get_int();
183 }
184
186 {
187 return a.get_int();
188 }
189
190 bool is_unit(ElementType f) const { return f != 0; }
191 bool is_zero(ElementType f) const { return f == 0; }
192 bool is_equal(ElementType f, ElementType g) const { return f == g; }
194 {
195 if (f < g) return -1;
196 if (f > g) return 1;
197 return 0;
198 }
199
200 void copy(elem &result, elem a) const { result = a; }
201 void init(elem &result) const { result = 0; }
202 void init_set(elem &result, elem a) const { result = a; }
203 void set(elem &result, elem a) const { result = a; }
204 void set_zero(elem &result) const { result = 0; }
205 static void clear(elem &result) { (void) result; }
206
207 void set_from_long(elem &result, long a) const
208 {
209 int a1 = static_cast<int>(a % characteristic());
210 if (a1 < 0) a1 += characteristic();
211 result = mGF.fromZZTable(a1);
212 }
213
214 void set_var(elem &result, int v) const
215 {
216 (void) v;
217 result = 1;
218 }
219
220 void set_from_mpz(elem &result, mpz_srcptr a) const
221 {
222 int b = static_cast<int>(mpz_fdiv_ui(a, characteristic()));
223 result = mGF.fromZZTable(b);
224 }
225
226 bool set_from_mpq(elem &result, mpq_srcptr a) const
227 {
228 elem n, d;
229 set_from_mpz(n, mpq_numref(a));
230 set_from_mpz(d, mpq_denref(a));
231 if (is_zero(d)) return false;
232 divide(result, n, d);
233 return true;
234 }
235
237 {
238 (void) result;
239 (void) a;
240 return false;
241 }
242
243 void negate(elem &result, elem a) const
244 {
245 if (a != 0)
246 result = modulus_add(a, mGF.minusOne(), mGF.orderMinusOne());
247 else
248 result = 0;
249 }
250
251 void invert(elem &result, elem a) const
252 {
253 if (a == 0)
255 result = (a == mGF.one() ? mGF.one() : mGF.orderMinusOne() - a);
256 }
257
258 void add(elem &result, elem a, elem b) const
259 {
260 if (a == 0)
261 result = b;
262 else if (b == 0)
263 result = a;
264 else
265 {
266 int n = a - b;
267 if (n > 0)
268 {
269 if (n == mGF.minusOne())
270 result = 0;
271 else
272 result = modulus_add(b, mGF.oneTable(n), mGF.orderMinusOne());
273 }
274 else if (n < 0)
275 {
276 if (-n == mGF.minusOne())
277 result = 0;
278 else
279 result = modulus_add(a, mGF.oneTable(-n), mGF.orderMinusOne());
280 }
281 else
282 {
283 if (mGF.characteristic() == 2)
284 result = 0;
285 else
286 result =
287 modulus_add(a, mGF.oneTable(mGF.one()), mGF.orderMinusOne());
288 }
289 }
290 }
291
292 void subtract(elem &result, elem a, elem b) const
293 {
294 result = a;
295 if (b == 0) return;
296 elem c = modulus_add(b, mGF.minusOne(), mGF.orderMinusOne()); // c = -b
297 add(result, a, c);
298 }
299
301 {
302 elem ab;
303 mult(ab, a, b);
304 subtract(result, result, ab);
305 }
306
307 void mult(elem &result, elem a, elem b) const
308 {
309 if (a != 0 && b != 0)
310 {
311 int c = a + b;
312 if (c > mGF.orderMinusOne()) c -= mGF.orderMinusOne();
313 result = c;
314 }
315 else
316 result = 0;
317 }
318
319 void divide(elem &result, elem a, elem b) const
320 {
321 if (b == 0)
323 if (a != 0)
324 {
325 int c = a - b;
326 if (c <= 0) c += mGF.orderMinusOne();
327 result = c;
328 }
329 else
330 result = 0;
331 }
332
333 void power(elem &result, elem a, long n) const
334 {
335 if (a != 0)
336 {
337 long order1 = static_cast<long>(mGF.orderMinusOne());
338 result = static_cast<elem>((a * n) % order1);
339 if (result <= 0) result += mGF.orderMinusOne();
340 }
341 else
342 {
343 // a is the zero element
344 if (n > 0)
345 result = 0;
346 else if (n == 0)
347 result = mGF.one();
348 else
350 }
351 }
352
353 void power_mpz(elem &result, elem a, mpz_srcptr n) const
354 {
355 if (a != 0)
356 {
357 long n1 = mpz_fdiv_ui(n, mGF.orderMinusOne());
358 power(result, a, n1);
359 }
360 else
361 {
362 // a is the zero element
363 if (mpz_sgn(n) > 0)
364 result = 0;
365 else if (mpz_sgn(n) == 0)
366 result = mGF.one();
367 else
369 }
370 }
371
372 void swap(ElementType &a, ElementType &b) const
373 {
374 ElementType tmp = a;
375 a = b;
376 b = tmp;
377 }
378
379 void elem_text_out(buffer &o,
380 ElementType a,
381 bool p_one = true,
382 bool p_plus = false,
383 bool p_parens = false) const;
384
386 ElementType b,
387 ElementType &x,
388 ElementType &y) const
389 // returns x,y s.y. x*a + y*b == 0.
390 // if possible, x is set to 1.
391 // no need to consider the case a==0 or b==0.
392 {
393 assert(a != 0);
394 assert(b != 0);
395 x = mGF.one();
396 divide(y, a, b);
397 negate(y, y);
398 }
399
401 {
402 result = rawRandomInt(static_cast<int32_t>(characteristic()));
403 }
404
405 void fromSmallIntegerCoefficients(ElementType &result,
406 const std::vector<long> &poly) const;
407
408 bool promote(const Ring *Rf, const ring_elem f, elem &result) const;
409
410 void lift_to_original_ring(ring_elem &result, const ElementType &f) const;
411 // GF specific routine, used in getRepresentation
412
413 bool lift(const Ring *Rg, const elem f, ring_elem &result) const;
414
415 // map : this --> target(map)
416 // primelem --> map->elem(first_var)
417 // evaluate map(f)
418 void eval(const RingMap *map,
419 const elem f,
420 int first_var,
421 ring_elem &result) const;
422};
423};
424
425#endif
426// Local Variables:
427// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
428// indent-tabs-mode: nil
429// End:
Shared base of the aring framework (namespace M2) that unifies the engine's coefficient rings.
Append-only GC-backed byte buffer used throughout the engine for text output.
Engine-side finite field GF(p^n) built on top of (Z/p)[t] / f(t) for a primitive element of the resul...
Definition GF.hpp:62
void from_ring_elem(ElementType &result, const ring_elem &a) const
int compare_elems(ElementType f, ElementType g) const
bool is_zero(ElementType f) const
void set(elem &result, elem a) const
void power_mpz(elem &result, elem a, mpz_srcptr n) const
void set_zero(elem &result) const
void text_out(buffer &o) const
void power(elem &result, elem a, long n) const
bool is_unit(ElementType f) const
void init_set(elem &result, elem a) const
std::vector< elem > ElementContainerType
void swap(ElementType &a, ElementType &b) const
void subtract(elem &result, elem a, elem b) const
static int modulus_sub(int a, int b, int p)
void divide(elem &result, elem a, elem b) const
void lift_to_original_ring(ring_elem &result, const ElementType &f) const
bool is_equal(ElementType f, ElementType g) const
int get_repr(elem f) const
void syzygy(ElementType a, ElementType b, ElementType &x, ElementType &y) const
const PolynomialRing & originalRing() const
void subtract_multiple(elem &result, elem a, elem b) const
unsigned int computeHashValue(const elem &a) const
void elem_text_out(buffer &o, ElementType a, bool p_one=true, bool p_plus=false, bool p_parens=false) const
void fromSmallIntegerCoefficients(ElementType &result, const std::vector< long > &poly) const
static void clear(elem &result)
GFElement characteristic() const
void invert(elem &result, elem a) const
bool lift(const Ring *Rg, const elem f, ring_elem &result) const
void negate(elem &result, elem a) const
void set_from_mpz(elem &result, mpz_srcptr a) const
GaloisFieldTable mGF
ElementType from_ring_elem_const(const ring_elem &a) const
ARingGFM2(const PolynomialRing &R, const ring_elem a)
void init(elem &result) const
void mult(elem &result, elem a, elem b) const
void add(elem &result, elem a, elem b) const
bool set_from_BigReal(elem &result, gmp_RR a) const
static int modulus_add(int a, int b, int p)
Arithmetic functions ///////.
void set_from_long(elem &result, long a) const
void eval(const RingMap *map, const elem f, int first_var, ring_elem &result) const
void to_ring_elem(ring_elem &result, const ElementType &a) const
void copy(elem &result, elem a) const
bool promote(const Ring *Rf, const ring_elem f, elem &result) const
static const RingID ringID
void set_var(elem &result, int v) const
void getGenerator(elem &result_gen) const
bool set_from_mpq(elem &result, mpq_srcptr a) const
void random(ElementType &result) const
GFElement dimension() const
GFElement minusOne() const
GFElement generatorExponent() const
const ring_elem primitiveElement() const
GFElement order() const
GFElement oneTable(GFElement a) const
friend class ARingGFM2
const RingElement * getGenerator() const
GaloisFieldTable(const PolynomialRing &R, const ring_elem prim)
const ring_elem mPrimitiveElement
const PolynomialRing & ring() const
GFElement characteristic() const
GFElement orderMinusOne() const
GFElement * mFromIntTable
const RingElement * mGenerator
GFElement one() const
void display(std::ostream &o) const
const PolynomialRing & mOriginalRing
GFElement fromZZTable(GFElement a) const
A base class for simple ARings.
Definition aring.hpp:147
Abstract base for the engine's polynomial-ring hierarchy.
Definition polyring.hpp:96
Front-end-visible "ring element" value: an engine ring_elem paired with the Ring* that gives it meani...
Definition relem.hpp:67
xxx xxx xxx
Definition ring.hpp:102
Engine-side ring homomorphism: stores, for each source-ring variable, the target-ring element it maps...
Definition ringmap.hpp:60
namespace exc — internal C++ exception types and the TRY / CATCH macro pair.
int p
RingID
Definition aring.hpp:75
@ ring_GFM2
Definition aring.hpp:84
VALGRIND_MAKE_MEM_DEFINED & result(result)
mpfr_srcptr gmp_RR
Definition m2-types.h:148
int GFElement
Definition aring-CC.cpp:3
volatile int x
PolynomialRing — abstract polynomial-ring base, the engine's most-reused class.
int32_t rawRandomInt(int32_t max)
Definition random.cpp:44
Engine-boundary C API for the engine's PRNG and rational / real / complex random draws.
ring_elem — the universal value type carried by every Ring* in the engine.
int get_int() const
Definition ringelem.hpp:124