Macaulay2 Engine
Loading...
Searching...
No Matches
aring-zzp.hpp
Go to the documentation of this file.
1// Copyright 2011 Michael E. Stillman
2
3#ifndef _aring_zzp_hpp_
4#define _aring_zzp_hpp_
5
39
40#include "interface/random.h"
41#include "aring.hpp"
42#include "buffer.hpp"
43#include "ringelem.hpp"
44#include "exceptions.hpp"
45
46class Z_mod;
47class RingMap;
48
49namespace M2 {
66class ARingZZp : public SimpleARing<ARingZZp>
67{
68 // Integers mod p, implemented as
69 // exponents of a primitive element a
70 // Representation:
71 // 0 means 0
72 // 1 <= n <= p-1 means a^n (mod p)
73
74 // 0 represents 0
75 // p-1 represents 1
76 // 1..p-2 represent numbers in range 2..p-1
77
78 public:
79 static const RingID ringID = ring_ZZp;
81 typedef int ElementType;
82 typedef int elem;
83 typedef std::vector<elem> ElementContainerType;
84
85 ARingZZp(size_t prime);
86
87 ~ARingZZp();
88
89 // ring informational
90 size_t characteristic() const { return charac; }
91 size_t cardinality() const { return charac; }
92 static int findPrimitiveRoot(int P);
93
94 void text_out(buffer &o) const;
95
97 // Routines to help in switch from coeffrings to aring //
98 // these will be renamed or go away (hopefully) /////////
100 unsigned int computeHashValue(const elem &a) const { return a; }
101 void init_set(elem &result, elem a) const { result = a; }
102 void set(elem &result, elem a) const { result = a; }
104 // ElementType informational ////
106
107 bool is_unit(ElementType f) const { return f != 0; }
108 bool is_zero(ElementType f) const { return f == 0; }
109 bool is_equal(ElementType f, ElementType g) const { return f == g; }
111 {
112 int a = exp_table[f];
113 int b = exp_table[g];
114 if (a < b) return -1;
115 if (a > b) return 1;
116 return 0;
117 }
118
120 // to/from ringelem ////////
122 // These simply repackage the element as either a ringelem or an
123 // 'ElementType'.
124 // No reinitialization is done.
125 // Do not take the same element and store it as two different ring_elem's!!
127 {
128 if (a == 0)
130 else if (a == p1)
131 result = ring_elem(0);
132 else
133 result = ring_elem(a);
134 }
135
137 {
138 if (a.get_int() == 0)
139 result = p1;
140 else if (a.get_int() == p1)
141 result = 0;
142 else
143 result = a.get_int();
144 }
145
147 {
148 if (a.get_int() == 0)
149 return p1;
150 else if (a.get_int() == p1)
151 return 0;
152 else
153 return a.get_int();
154 }
155
156 // 'init', 'init_set' functions
157
158 void init(elem &result) const { result = 0; }
159 static void clear(elem &result) { (void) result; }
160
161 void set_zero(elem &result) const { result = 0; }
162 void set_from_long(elem &result, long a) const
163 {
164 a = a % p;
165 if (a < 0) a += p;
166 result = log_table[a];
167 }
168
169 void set_var(elem &result, int v) const
170 {
171 (void) v;
172 result = 1;
173 }
174
175 void set_from_mpz(elem &result, mpz_srcptr a) const
176 {
177 int b = static_cast<int>(mpz_fdiv_ui(a, p));
178 result = log_table[b];
179 }
180
181 bool set_from_mpq(elem &result, mpq_srcptr a) const
182 {
183 ElementType n, d;
184 set_from_mpz(n, mpq_numref(a));
185 set_from_mpz(d, mpq_denref(a));
186 if (is_zero(d)) return false;
187 divide(result, n, d);
188 return true;
189 }
190
192 {
193 (void) result;
194 (void) a;
195 return false;
196 }
197
198 // arithmetic
199 void negate(elem &result, elem a) const
200 {
201 if (a != 0)
202 {
203 result = minus_one + a;
204 if (result > p1) result -= p1;
205 }
206 else
207 result = 0;
208 }
209
210 void invert(elem &result, elem a) const
211 {
212 if (is_zero(a)) throw exc::division_by_zero_error();
213 result = p1 - a;
214 if (result == 0) result = p1;
215 }
216
217 void add(elem &result, elem a, elem b) const
218 {
219 int e1 = exp_table[a];
220 int e2 = exp_table[b];
221 int n = e1 + e2;
222 if (n >= p) n -= p;
223 result = log_table[n];
224 }
225
226 void subtract(elem &result, elem a, elem b) const
227 {
228 int e1 = exp_table[a];
229 int e2 = exp_table[b];
230 int n = e1 - e2;
231 if (n < 0) n += p;
232 result = log_table[n];
233 }
234
235 inline int modulus_add(int a, int b, int p) const
236 {
237 int t = a + b;
238 return (t <= p ? t : t - p);
239 }
240
241 inline int modulus_sub(int a, int b, int p) const
242 {
243 int t = a - b;
244 return (t < 0 ? t + p : t);
245 }
246
248 {
249 // we assume: a, b are NONZERO!!
250 // result -= a*b
251
252 // the change in code below mimics that of coeffrings.cpp which was 15-20% faster in
253 // testing for some reason (in small characteristics). The assembly generated is much more
254 // clean than it was previously.
255
256 //int ab = a + b;
257 //if (ab > p1) ab -= p1;
258 int ab = modulus_add(a,b,p1);
259 //int n = exp_table[result] - exp_table[ab];
260 //if (n < 0) n += p;
261 int n = modulus_sub(exp_table[result],exp_table[ab],p);
262 result = log_table[n];
263 }
264
265 void mult(elem &result, elem a, elem b) const
266 {
267 if (a != 0 && b != 0)
268 {
269 int c = a + b;
270 if (c > p1) c -= p1;
271 result = c;
272 }
273 else
274 result = 0;
275 }
276
277 void divide(elem &result, elem a, elem b) const
278 {
279 if (b == 0)
281 if (a != 0)
282 {
283 int c = a - b;
284 if (c <= 0) c += p1;
285 result = c;
286 }
287 else
288 result = 0;
289 }
290
291 void power(elem &result, elem a, int n) const
292 {
293 if (a != 0)
294 {
295 result = (a * n) % p1;
296 if (result <= 0) result += p1;
297 }
298 else
299 {
300 // a == 0
301 if (n == 0) result = p1; // the element 1 in this ring.
302 else if (n > 0) result = 0;
303 else throw exc::division_by_zero_error();
304 }
305 }
306
307 void power_mpz(elem &result, elem a, mpz_srcptr n) const
308 {
309 if (a != 0)
310 {
311 int n1 = static_cast<int>(mpz_fdiv_ui(n, p1));
312 power(result, a, n1);
313 }
314 else
315 {
316 if (mpz_sgn(n) == 0) result = p1; // the element 1 in this ring.
317 else if (mpz_sgn(n) < 0) throw exc::division_by_zero_error();
318 else result = 0; // result is 0 in the ring.
319 }
320 }
321
322 void swap(ElementType &a, ElementType &b) const
323 {
324 ElementType tmp = a;
325 a = b;
326 b = tmp;
327 }
328
329 void elem_text_out(buffer &o,
330 ElementType a,
331 bool p_one = true,
332 bool p_plus = false,
333 bool p_parens = false) const;
334
336 ElementType b,
337 ElementType &x,
338 ElementType &y) const
339 // returns x,y s.y. x*a + y*b == 0.
340 // if possible, x is set to 1.
341 // no need to consider the case a==0 or b==0.
342 {
343 x = p1;
344 divide(y, a, b);
345 negate(y, y);
346 }
347
348 void random(ElementType &result) const { result = rawRandomInt((int32_t)p); }
349 void eval(const RingMap *map,
350 const elem f,
351 int first_var,
352 ring_elem &result) const;
353
354 long coerceToLongInteger(const elem &f) const
355 {
356 int n = exp_table[f];
357 if (n > p / 2) n -= p;
358 return n;
359 }
361 {
362 int n = exp_table[f];
363 return n;
364 }
365
366 private:
367 void initialize_tables();
368
369 size_t charac;
370 int p; // charac == p ??
371 int p1; // p-1
373 int prim_root; // element we will use for our primitive root
374 int *log_table; // 0..p-1
375 int *exp_table; // 0..p-1
376};
377};
378
379#endif
380
381// Local Variables:
382// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
383// indent-tabs-mode: nil
384// 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.
void swap(ElementType &a, ElementType &b) const
void syzygy(ElementType a, ElementType b, ElementType &x, ElementType &y) const
static int findPrimitiveRoot(int P)
Definition aring-zzp.cpp:7
ARingZZp(size_t prime)
Definition aring-zzp.cpp:56
ElementType from_ring_elem_const(const ring_elem &a) const
void set_from_long(elem &result, long a) const
void negate(elem &result, elem a) const
int modulus_add(int a, int b, int p) const
void invert(elem &result, elem a) const
void mult(elem &result, elem a, elem b) const
void set(elem &result, elem a) const
size_t characteristic() const
Definition aring-zzp.hpp:90
Z_mod ring_type
Definition aring-zzp.hpp:80
unsigned int computeHashValue(const elem &a) const
void subtract(elem &result, elem a, elem b) const
void init(elem &result) const
void init_set(elem &result, elem a) const
static void clear(elem &result)
void add(elem &result, elem a, elem b) const
void set_zero(elem &result) const
void elem_text_out(buffer &o, ElementType a, bool p_one=true, bool p_plus=false, bool p_parens=false) const
Definition aring-zzp.cpp:74
void set_from_mpz(elem &result, mpz_srcptr a) const
static const RingID ringID
Definition aring-zzp.hpp:79
size_t cardinality() const
Definition aring-zzp.hpp:91
void to_ring_elem(ring_elem &result, const ElementType &a) const
bool is_zero(ElementType f) const
void from_ring_elem(ElementType &result, const ring_elem &a) const
void text_out(buffer &o) const
Definition aring-zzp.cpp:72
bool is_equal(ElementType f, ElementType g) const
void power_mpz(elem &result, elem a, mpz_srcptr n) const
bool is_unit(ElementType f) const
std::vector< elem > ElementContainerType
Definition aring-zzp.hpp:83
int modulus_sub(int a, int b, int p) const
void subtract_multiple(elem &result, elem a, elem b) const
void divide(elem &result, elem a, elem b) const
long coerceToNonnegativeLongInteger(const elem &f) const
void set_var(elem &result, int v) const
long coerceToLongInteger(const elem &f) const
void power(elem &result, elem a, int n) const
bool set_from_BigReal(elem &result, gmp_RR a) const
void initialize_tables()
Definition aring-zzp.cpp:25
void random(ElementType &result) const
int compare_elems(ElementType f, ElementType g) const
bool set_from_mpq(elem &result, mpq_srcptr a) const
void eval(const RingMap *map, const elem f, int first_var, ring_elem &result) const
Definition aring-zzp.cpp:92
A base class for simple ARings.
Definition aring.hpp:147
Engine-side ring homomorphism: stores, for each source-ring variable, the target-ring element it maps...
Definition ringmap.hpp:60
Engine-side Z/p ring for small primes (p < 32767), using a discrete-log (Zech) representation.
Definition ZZp.hpp:63
namespace exc — internal C++ exception types and the TRY / CATCH macro pair.
RingID
Definition aring.hpp:75
@ ring_ZZp
Definition aring.hpp:81
VALGRIND_MAKE_MEM_DEFINED & result(result)
mpfr_srcptr gmp_RR
Definition m2-types.h:148
Definition aring-CC.cpp:3
volatile int x
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