Macaulay2 Engine
Loading...
Searching...
No Matches
aring-gf-flint-big.hpp
Go to the documentation of this file.
1// Copyright 2014 Michael E. Stillman
2
3#ifndef _aring_gf_flint_big_hpp_
4#define _aring_gf_flint_big_hpp_
5
44
45#include <vector>
46
47// The following needs to be included before any flint files are included.
48#include <M2/gc-include.h>
49
50// includes gmp.h, which is required for FLINT functions that use GMP
51#include <M2/math-include.h>
52
53#pragma GCC diagnostic push
54#pragma GCC diagnostic ignored "-Wconversion"
55#include <flint/flint.h> // for flint_free, flint_rand_t, fmpz_t
56#include <flint/fmpz.h> // for fmpz_clear_readonly, fmpz_init_set_...
57#include <flint/fq_nmod.h> // for fq_nmod_init2, fq_nmod_clear, fq_nm...
58#include <flint/nmod_poly.h> // for nmod_poly_degree, nmod_poly_get_coe...
59#pragma GCC diagnostic pop
60
61#include "aring.hpp"
62#include "buffer.hpp"
63#include "ringelem.hpp"
64#include "exceptions.hpp" // for exc::division_by_zero_error
65
66class PolynomialRing;
67class RingElement;
68
69namespace M2 {
70
88{
89 public:
91 typedef fq_nmod_struct ElementType;
92 // this type is defined in fq_nmod.h
93 // for debugging purposes (flint version 2.5):
94 // this is nmod_poly_struct, defined in nmod_poly.h
95 // typedef struct
96 // {
97 // mp_ptr coeffs;
98 // slong alloc;
99 // slong length;
100 // nmod_t mod;
101 // } nmod_poly_struct;
102
104 typedef std::vector<elem> ElementContainerType;
105
112 class Element : public ElementImpl<ElementType>
113 {
114 public:
115 Element() = delete;
117 {
118 // figure out how to move the value without the context
119 fq_nmod_init2(&mValue, mContext);
120 fq_nmod_set(&mValue, &other.mValue, mContext);
121 }
122 explicit Element(const ARingGFFlintBig& R) : mContext(R.mContext)
123 {
124 fq_nmod_init2(&mValue, mContext);
125 }
127 {
129 }
130 ~Element() { fq_nmod_clear(&mValue, mContext); }
131
132 protected:
133 const fq_nmod_ctx_struct* mContext;
134 };
135
148 {
149 const fq_nmod_ctx_struct* mContext;
150 const int mSize;
151 std::unique_ptr<ElementType[]> mData;
152
153 public:
154 ElementArray(const ARingGFFlintBig& R, size_t size)
155 : mContext(R.mContext), mSize(size), mData(new ElementType[size])
156 {
157 for (size_t i = 0; i < mSize; i++) fq_nmod_init2(&mData[i], mContext);
158 }
160 {
161 for (size_t i = 0; i < mSize; i++) fq_nmod_clear(&mData[i], mContext);
162 }
163 ElementType& operator[](size_t idx) { return mData[idx]; }
164 const ElementType& operator[](size_t idx) const { return mData[idx]; }
165 ElementType *data() { return mData.get(); }
166 const ElementType *data() const { return mData.get(); }
167 };
168
169 ARingGFFlintBig(const PolynomialRing& R, const ring_elem a);
170
172
173 const fq_nmod_ctx_struct* flintContext() const { return mContext; }
174 long characteristic() const { return mCharacteristic; }
175 long dimension() const { return mDimension; }
176 const PolynomialRing& originalRing() const { return mOriginalRing; }
177 void getGenerator(ElementType& result_gen) const;
178
179 void text_out(buffer& o) const;
180
181 private:
182 fq_nmod_ctx_t mContext;
183 const PolynomialRing& mOriginalRing; // This is a quotient ring k[a]/f(a).
184 const RingElement* mPrimitiveElement; // element in the original ring
185 unsigned int*
186 mPPowers; // array 0..mDimension of powers of mCharacteristic (mod 2^32)
189 mutable flint_rand_t mRandomState;
190
192 mutable bool mGeneratorComputed;
193
197
198 public:
199 unsigned int computeHashValue(const elem& a) const
200 {
201 unsigned int hash = 0;
202 long deg = nmod_poly_degree(&a);
203 for (long i = 0; i <= deg; i++)
204 hash += static_cast<unsigned int>(nmod_poly_get_coeff_ui(&a, i)) *
205 mPPowers[i];
206 // printf("computing hash value: %ld\n", hash);
207 return hash;
208 }
209
211 {
213 init(*b);
214 copy(*b, a);
215 size_t coeffs_size = sizeof(mp_limb_t)*b->alloc;
216 mp_ptr coeffs = reinterpret_cast<mp_ptr>(getmem_atomic(coeffs_size));
217 memcpy(coeffs,b->coeffs,coeffs_size);
218 flint_free(b->coeffs);
219 b->coeffs = coeffs;
220 result.poly_val = reinterpret_cast<Nterm*>(b);
221 }
222
224 {
225 ElementType* b = reinterpret_cast<ElementType*>(a.poly_val);
226 copy(result, *b);
227 }
228
230 {
231 return *reinterpret_cast<ElementType*>(a.poly_val);
232 }
233
234 bool is_unit(const ElementType& f) const { return not is_zero(f); }
235 bool is_zero(const ElementType& f) const
236 {
237 return fq_nmod_is_zero(&f, mContext);
238 }
239 bool is_equal(const ElementType& f, const ElementType& g) const
240 {
241 return fq_nmod_equal(&f, &g, mContext);
242 }
243
244 int compare_elems(const ElementType& f, const ElementType& g) const;
245
246 void copy(ElementType& result, const ElementType& a) const
247 {
248 fq_nmod_set(&result, &a, mContext);
249 }
250 void init(ElementType& result) const { fq_nmod_init2(&result, mContext); }
251 void init_set(ElementType& result, const ElementType& a) const
252 {
253 init(result);
254 copy(result, a);
255 }
256 void set(ElementType& result, const ElementType& a) const { copy(result, a); }
257 void set_zero(ElementType& result) const { fq_nmod_zero(&result, mContext); }
258 void clear(ElementType& result) const { fq_nmod_clear(&result, mContext); }
259 void set_from_long(ElementType& result, long a) const
260 {
261 long a1 = a % characteristic();
262 if (a1 < 0) a1 += characteristic();
263 fq_nmod_set_ui(&result, a1, mContext);
264 }
265
266 void set_var(ElementType& result, int v) const
267 {
268 if (v != 0) set_from_long(result, 1);
269 std::vector<long> poly = {0, 1};
271 }
272
273 void set_from_mpz(ElementType& result, mpz_srcptr a) const
274 {
275 int b = static_cast<int>(mpz_fdiv_ui(a, characteristic()));
277 }
278
279 bool set_from_mpq(ElementType& result, mpq_srcptr a) const
280 {
281 ElementType n, d;
282 init(n);
283 init(d);
284 set_from_mpz(n, mpq_numref(a));
285 set_from_mpz(d, mpq_denref(a));
286 if (is_zero(d)) return false;
287 divide(result, n, d);
288 return true;
289 }
290
292 {
293 (void) result;
294 (void) a;
295 return false;
296 }
297
298 void negate(ElementType& result, const ElementType& a) const
299 {
300 fq_nmod_neg(&result, &a, mContext);
301 }
302
303 void invert(ElementType& result, const ElementType& a) const
304 {
305 if (is_zero(a))
307 fq_nmod_inv(&result, &a, mContext);
308 }
309
311 const ElementType& a,
312 const ElementType& b) const
313 {
314 fq_nmod_add(&result, &a, &b, mContext);
315 }
316
318 const ElementType& a,
319 const ElementType& b) const
320 {
321 fq_nmod_sub(&result, &a, &b, mContext);
322 }
323
325 const ElementType& a,
326 const ElementType& b) const
327 {
328 ElementType c;
329 init(c);
330 mult(c, a, b);
332 clear(c);
333 }
334
336 const ElementType& a,
337 const ElementType& b) const
338 {
339 fq_nmod_mul(&result, &a, &b, mContext);
340 }
341
343 const ElementType& a,
344 const ElementType& b) const
345 {
346 // We need to handle the case when result is a, or b.
347 // This is why we use the temporary value 'c'.
348 ElementType c;
349 init(c);
350#if 0
351 printf("entering divide\n");
352 printf(" a = ");
353 fq_nmod_print_pretty(&a, mContext);
354 printf("\n b = ");
355 fq_nmod_print_pretty(&b, mContext);
356#endif
357 invert(c, b);
358#if 0
359 printf("\n 1/b = ");
360 fq_nmod_print_pretty(&c, mContext);
361#endif
362 mult(result, c, a);
363#if 0
364 printf("\n a/b = ");
365 fq_nmod_print_pretty(&result, mContext);
366 printf("\n");
367#endif
368 clear(c);
369 }
370
371 void power(ElementType& result, const ElementType& a, int n) const
372 {
373 if (n < 0)
374 {
375 invert(result, a);
376 fq_nmod_pow_ui(&result, &result, -n, mContext);
377 }
378 else
379 fq_nmod_pow_ui(&result, &a, n, mContext);
380 }
381
382 void power_mpz(ElementType& result, const ElementType& a, mpz_srcptr n) const
383 {
384 if (mpz_sgn(n) < 0 and is_zero(a))
386
388 init(base);
389 if (mpz_sgn(n) < 0)
390 invert(base, a);
391 else
392 copy(base, a);
393
394 mpz_t abs_n;
395 mpz_init(abs_n);
396 mpz_abs(abs_n, n);
397
398 fmpz_t fn;
399 fmpz_init_set_readonly(fn, abs_n);
400 fq_nmod_pow(&result, &base, fn, mContext);
401 fmpz_clear_readonly(fn);
402 mpz_clear(abs_n);
403 clear(base);
404 }
405
406 void swap(ElementType& a, ElementType& b) const
407 {
408 fq_nmod_swap(&a, &b, mContext);
409 }
410
411 void elem_text_out(buffer& o,
412 const ElementType& a,
413 bool p_one = true,
414 bool p_plus = false,
415 bool p_parens = false) const;
416
417 void syzygy(const ElementType& a,
418 const ElementType& b,
419 ElementType& x,
420 ElementType& y) const
421 // returns x,y s.y. x*a + y*b == 0.
422 // if possible, x is set to 1.
423 // no need to consider the case a==0 or b==0.
424 {
425 assert(not is_zero(a));
426 assert(not is_zero(b));
427 set_from_long(x, 1);
428 divide(y, a, b);
429 negate(y, y);
430 }
431
433 {
434 // printf("calling ARingGFFlintBig::random\n");
435 fq_nmod_randtest(&result, mRandomState, mContext);
436 }
437
438 void fromSmallIntegerCoefficients(ElementType& result,
439 const std::vector<long>& poly) const;
440
441 void getSmallIntegerCoefficients(const ElementType& a,
442 std::vector<long>& poly) const;
443
444 bool promote(const Ring* Rf, const ring_elem f, ElementType& result) const;
445
446 void lift_to_original_ring(ring_elem& result, const ElementType& f) const;
447 // GF specific routine, used in getRepresentation
448
449 bool lift(const Ring* Rg, const ElementType& f, ring_elem& result) const;
450
451 // map : this --> target(map)
452 // primelem --> map->elem(first_var)
453 // evaluate map(f)
454 void eval(const RingMap* map,
455 const ElementType& f,
456 int first_var,
457 ring_elem& result) const;
458};
459};
460
461#endif
462// Local Variables:
463// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
464// indent-tabs-mode: nil
465// 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.
Element(const ARingGFFlintBig &R, const ElementType &value)
const fq_nmod_ctx_struct * mContext
Element(const ARingGFFlintBig &R)
const ElementType & operator[](size_t idx) const
const fq_nmod_ctx_struct * mContext
ElementArray(const ARingGFFlintBig &R, size_t size)
std::unique_ptr< ElementType[]> mData
const PolynomialRing & originalRing() const
void fromSmallIntegerCoefficients(ElementType &result, const std::vector< long > &poly) const
void getGenerator(ElementType &result_gen) const
const PolynomialRing & mOriginalRing
bool lift(const Ring *Rg, const ElementType &f, ring_elem &result) const
void negate(ElementType &result, const ElementType &a) const
const fq_nmod_ctx_struct * flintContext() const
void syzygy(const ElementType &a, const ElementType &b, ElementType &x, ElementType &y) const
void from_ring_elem(ElementType &result, const ring_elem &a) const
void subtract_multiple(ElementType &result, const ElementType &a, const ElementType &b) const
const ElementType & from_ring_elem_const(const ring_elem &a) const
const RingElement * mPrimitiveElement
void power(ElementType &result, const ElementType &a, int n) const
void set_from_mpz(ElementType &result, mpz_srcptr a) const
void divide(ElementType &result, const ElementType &a, const ElementType &b) const
std::vector< elem > ElementContainerType
void set_var(ElementType &result, int v) const
void clear(ElementType &result) const
static const RingID ringID
bool is_equal(const ElementType &f, const ElementType &g) const
void lift_to_original_ring(ring_elem &result, const ElementType &f) const
bool is_zero(const ElementType &f) const
ARingGFFlintBig(const PolynomialRing &R, const ring_elem a)
bool promote(const Ring *Rf, const ring_elem f, ElementType &result) const
void subtract(ElementType &result, const ElementType &a, const ElementType &b) const
void init_set(ElementType &result, const ElementType &a) const
void invert(ElementType &result, const ElementType &a) const
void set(ElementType &result, const ElementType &a) const
void set_zero(ElementType &result) const
void add(ElementType &result, const ElementType &a, const ElementType &b) const
void text_out(buffer &o) const
bool set_from_BigReal(ElementType &result, gmp_RR a) const
bool set_from_mpq(ElementType &result, mpq_srcptr a) const
void to_ring_elem(ring_elem &result, const ElementType &a) const
void power_mpz(ElementType &result, const ElementType &a, mpz_srcptr n) const
void elem_text_out(buffer &o, const ElementType &a, bool p_one=true, bool p_plus=false, bool p_parens=false) const
void getSmallIntegerCoefficients(const ElementType &a, std::vector< long > &poly) const
void swap(ElementType &a, ElementType &b) const
unsigned int computeHashValue(const elem &a) const
Arithmetic functions ///////.
void random(ElementType &result) const
int compare_elems(const ElementType &f, const ElementType &g) const
void init(ElementType &result) const
void mult(ElementType &result, const ElementType &a, const ElementType &b) const
void eval(const RingMap *map, const ElementType &f, int first_var, ring_elem &result) const
void set_from_long(ElementType &result, long a) const
void copy(ElementType &result, const ElementType &a) const
bool is_unit(const ElementType &f) const
const ElementType & value() const
Definition aring.hpp:132
ElementImpl()=default
ElementType mValue
Definition aring.hpp:119
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.
static CanonicalForm base
Definition factory.cpp:289
RingID
Definition aring.hpp:75
@ ring_GFFlintBig
Definition aring.hpp:85
OrigFn fn
Definition m2-mem.cpp:273
char * getmem_atomic(size_t n)
Definition m2-mem.cpp:135
VALGRIND_MAKE_MEM_DEFINED & result(result)
#define getmemstructtype(S)
Definition m2-mem.h:143
mpfr_srcptr gmp_RR
Definition m2-types.h:148
Definition aring-CC.cpp:3
volatile int x
ring_elem — the universal value type carried by every Ring* in the engine.
Singly linked-list node carrying one term of a polynomial-ring element.
Definition ringelem.hpp:156
Nterm * poly_val
Definition ringelem.hpp:86