Macaulay2 Engine
Loading...
Searching...
No Matches
ring.cpp
Go to the documentation of this file.
1// Copyright 1995-2020 Michael E. Stillman
2
3#include "ring.hpp"
4
5#include "ZZ.hpp" // for RingZZ
6#include "coeffrings.hpp" // for CoefficientRingR
7#include "exceptions.hpp" // for exc::engine_error
8#include "freemod.hpp" // for FreeModule
9#include "monoid.hpp" // for Monoid
10#include "poly.hpp" // for PolyRing
11#include "polyring.hpp" // for PolynomialRing
12
13const Monoid *Ring::degree_monoid() const { return degree_ring->getMonoid(); }
14#if 1
15RingZZ *makeIntegerRing() { return new RingZZ; }
16#endif
17#if 0
18ARingZZ* makeIntegerRing()
19{
21}
22#endif
23
25{
26 if (cR == nullptr) cR = new CoefficientRingR(this);
27 return cR;
28}
29
31 const PolynomialRing *DR,
32 const std::vector<int> &heft_vector)
33{
34 // Remember: if this is a poly ring, the ring is K[M].
35 // If this is a basic routine, K = this, M = trivial monoid.
36 // If this is a frac field, K = R, M = trivial monoid.
37 mCharacteristic = P0;
38 if (DR == nullptr)
40 else
41 degree_ring = DR;
42 mHeftVector = heft_vector;
43
45 _isfield = 0;
46
50}
51
54{
55 return new FreeModule(this, 0, false);
56}
57
59{
60 return new FreeModule(this, 0, true);
61}
62
64{
65 return new FreeModule(this, n, false);
66}
67
68bool Ring::is_field() const { return _isfield == 1; }
70{
71 if (_isfield >= 0)
72 {
73 _isfield = 1;
74 return true;
75 }
76 else
77 {
78 ERROR("attempting to declare a ring with known non-units to be a field");
79 return false;
80 }
81}
83{
84 if (_isfield >= 0) return zero();
85 return copy(_non_unit);
86}
87
88void Ring::set_non_unit(ring_elem non_unit) const
89{
90 bool was_field = (_isfield == 1);
91 const_cast<Ring *>(this)->_isfield = -1;
92 const_cast<Ring *>(this)->_non_unit = non_unit;
93 if (was_field)
94 throw exc::engine_error("a non unit was found in a ring declared to be a field");
95}
96
97ring_elem Ring::var(int v) const
98{
99 (void) v;
100 // The default behavior is to just return 0.
101 return zeroV;
102}
103
106//
107// The method used is successive squaring.
108// Which classes actually use this?
109ring_elem Ring::power(const ring_elem gg, mpz_srcptr m) const
110{
111 ring_elem ff = gg;
112 int cmp = mpz_sgn(m); // the sign of m, <0, ==0, >0
113 if (cmp == 0) return one();
114 mpz_t n;
115 mpz_init_set(n, m);
116 // @TODO MES: rewrite this so it inverts before creating n.
117 // That way we don't have to catch any exceptions here.
118 // e.g. as
119#if 0
120 if (cmp < 0)
121 ff = invert(ff);
122 mpz_init_set(n, m);
123 mpz_t n;
124 if (cmp < 0)
125 mpz_neg(n, n);
126#endif
127 if (cmp < 0)
128 {
129 mpz_neg(n, n);
130 ff = invert(
131 ff); // this can raise an exception, in which case we need to free n.
132 if (is_zero(ff))
133 {
134 ERROR(
135 "either element not invertible, or no method available to "
136 "compute its inverse");
137 mpz_clear(n);
138 return ff;
139 }
140 }
141 ring_elem prod = from_long(1);
142 ring_elem base = copy(ff);
143 ring_elem tmp;
144
145 for (;;)
146 {
147 if (RingZZ::mod_ui(n, 2) == 1)
148 {
149 tmp = mult(prod, base);
150 prod = tmp;
151 }
152 mpz_tdiv_q_2exp(n, n, 1);
153 if (mpz_sgn(n) == 0)
154 {
155 mpz_clear(n);
156 return prod;
157 }
158 else
159 {
160 tmp = mult(base, base);
161 base = tmp;
162 }
163 }
164}
165
166ring_elem Ring::power(const ring_elem gg, int n) const
167{
168 // TODO: reorganize to match the above routine (but using an int).
169 ring_elem ff = gg;
170 if (n == 0) return one();
171 if (n < 0)
172 {
173 n = -n;
174 ff = invert(ff);
175 if (is_zero(ff))
176 {
177 ERROR("negative power of noninvertible element requested");
178 return ff;
179 }
180 }
181
182 // The exponent 'n' should be > 0 here.
183 ring_elem prod = from_long(1);
184 ring_elem base = copy(ff);
185 ring_elem tmp;
186
187 for (;;)
188 {
189 if ((n % 2) != 0)
190 {
191 tmp = mult(prod, base);
192 prod = tmp;
193 }
194 n >>= 1;
195 if (n == 0) { return prod; }
196 else
197 {
198 tmp = mult(base, base);
199 base = tmp;
200 }
201 }
202}
203
204void Ring::mult_to(ring_elem &f, const ring_elem g) const { f = mult(f, g); }
205void Ring::add_to(ring_elem &f, const ring_elem &g) const { f = add(f, g); }
206void Ring::subtract_to(ring_elem &f, const ring_elem &g) const
207{
208 f = subtract(f, g);
209}
210void Ring::negate_to(ring_elem &f) const { f = negate(f); }
212{
213 if (is_zero(g)) return f;
214 return zero();
215}
216
218{
219 if (is_zero(g)) return g;
220 return divide(f, g);
221}
222
224 const ring_elem g,
225 ring_elem &quot) const
226{
227 if (is_zero(g))
228 {
229 quot = g; // zero
230 return f;
231 }
232 quot = divide(f, g);
233 return zero();
234}
235
236std::pair<bool, long> Ring::coerceToLongInteger(ring_elem a) const
237{
238 (void) a;
239 return std::pair<bool, long>(false,
240 0); // the default is that it cannot be lifted.
241}
242
244{
245 (void) z;
246 result = from_long(0);
247 return false;
248}
249
251{
252 (void) z;
253 result = from_long(0);
254 return false;
255}
256
258{
259 (void) z;
260 result = from_long(0);
261 return false;
262}
263
265{
266 result = from_long(0);
267 return false;
268}
269
270bool Ring::from_double(double a, ring_elem &result) const
271{
272 (void) a;
273 result = from_long(0);
274 return false;
275}
276bool Ring::from_complex_double(double re, double im, ring_elem &result) const
277{
278 (void) re;
279 (void) im;
280 result = from_long(0);
281 return false;
282}
283
285{
286 ERROR("random scalar elements for this ring are not implemented");
287 return 0;
288}
289
291{
292 // Here we assume that 'this' is a field:
293 if (is_zero(f)) return from_long(1);
294 return invert(f);
295}
296
298// Implementation for a basic ring
299{
300 if (is_zero(f))
301 {
302 f = g;
303 return !is_zero(f);
304 }
305 return true;
306}
307
309// default implementation
310{
311 // The default implementation here ASSUMES that result and g are in the same
312 // ring!
313 if (is_zero(result)) result = g;
314}
315
317// default implementation
318{
319 return f;
320}
321
323// default implementation
324{
325 lower_content(f, g);
326 return f;
327}
328
330// default implementation
331{
332 // The default implementation here ASSUMES that f and c are in the same ring!
333 return divide(f, c);
334}
335
341
348
350{
351 (void) a;
352 (void) exp;
353}
354
355ring_elem Ring::diff(ring_elem a, ring_elem b, int use_coeff) const
356{
357 (void) use_coeff;
358 return mult(a, b);
359}
360
361bool Ring::in_subring(int nslots, const ring_elem a) const
362{
363 (void) nslots;
364 (void) a;
365 return true;
366}
367
368void Ring::degree_of_var(int n, const ring_elem a, int &lo, int &hi) const
369{
370 (void) n;
371 (void) a;
372 lo = 0;
373 hi = 0;
374}
375
376ring_elem Ring::divide_by_var(int n, int d, const ring_elem a) const
377{
378 (void) n;
379 if (d == 0) return a;
380 return from_long(0);
381}
382
384{
385 (void) exp;
386 return a;
387}
388
390 int,
391 int deg,
392 const std::vector<int> &) const
393{
394 if (deg != 0) ERROR("homogenize: no homogenization exists");
395 return f;
396}
397
399 int,
400 const std::vector<int> &) const
401{
402 return f;
403}
404
405bool Ring::is_homogeneous(const ring_elem) const { return true; }
406
408// returns true iff f is homogeneous
409{
410 (void) f;
411 degree_monoid()->one(d);
412 return true;
413}
414
416 const std::vector<int> &,
417 int &lo,
418 int &hi) const
419{
420 lo = hi = 0;
421}
422
424{
425 (void) a;
426 return -1;
427}
428
430{
431 (void) a;
433 return result;
434}
435
436// These next three routines are only overridden by RRR,CCC,polynomial rings,
437// and quotient rings
438unsigned long Ring::get_precision() const { return 0; }
440// Default is to return f itself.
441{
442 (void) epsilon;
443 return f;
444}
445
447// If any real number appearing in f has larger absolute value than norm,
448// replace norm.
449{
450 // Default for rings not over RRR or CCC is to do nothing.
451 (void) norm;
452 (void) f;
453}
454
467// SumCollector: default version //
470{
471 const Ring *R;
473
474 public:
475 SumCollectorDefault(const Ring *R0) : R(R0), result(R->zero()) {}
477 virtual void add(ring_elem f) { R->add_to(result, f); }
479 {
480 ring_elem val = result;
481 result = R->zero();
482 return val;
483 }
484};
485
487{
488 return new SumCollectorDefault(this);
489}
490
491// Local Variables:
492// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
493// indent-tabs-mode: nil
494// End:
exponents::ConstExponents const_exponents
exponents::Exponents exponents_t
Legacy RingZZ — a Ring-derived integer ring backed by GMP mpz_t.
Generic CoefficientRing adapter that wraps an arbitrary const Ring* and forwards every operation to i...
Engine-side free module R^n over a Ring.
Definition freemod.hpp:66
Engine-side commutative monomial monoid: variable names, ordering, multidegree machinery,...
Definition monoid.hpp:89
static const PolyRing * get_trivial_poly_ring()
Definition poly.cpp:35
Abstract base for the engine's polynomial-ring hierarchy.
Definition polyring.hpp:96
virtual ring_elem divide_by_expvector(const_exponents exp, const ring_elem a) const
Definition ring.cpp:383
void set_non_unit(ring_elem zero_div) const
Definition ring.cpp:88
virtual void monomial_divisor(const ring_elem a, exponents_t exp) const
Definition ring.cpp:349
virtual ring_elem var(int v) const
Definition ring.cpp:97
virtual ring_elem content(ring_elem f) const
Definition ring.cpp:316
virtual bool from_BigReal(gmp_RR a, ring_elem &result) const
Definition ring.cpp:250
void subtract_to(ring_elem &f, const ring_elem &g) const
Definition ring.cpp:206
virtual FreeModule * make_FreeModule() const
Definition ring.cpp:53
void negate_to(ring_elem &f) const
Definition ring.cpp:210
virtual bool from_Interval(gmp_RRi a, ring_elem &result) const
Definition ring.cpp:257
virtual ring_elem divide(const ring_elem f, const ring_elem g) const =0
long mCharacteristic
Definition ring.hpp:105
virtual void increase_maxnorm(gmp_RRmutable norm, const ring_elem f) const
Definition ring.cpp:446
virtual void degree_weights(const ring_elem f, const std::vector< int > &wts, int &lo, int &hi) const
Definition ring.cpp:415
virtual ring_elem subtract(const ring_elem f, const ring_elem g) const =0
virtual std::pair< bool, long > coerceToLongInteger(ring_elem a) const
Definition ring.cpp:236
virtual ring_elem add(const ring_elem f, const ring_elem g) const =0
virtual bool is_homogeneous(const ring_elem f) const
Definition ring.cpp:405
virtual bool from_ComplexInterval(gmp_CCi z, ring_elem &result) const
Definition ring.cpp:264
ring_elem one() const
Definition ring.hpp:357
virtual ring_elem divide_by_given_content(ring_elem f, ring_elem c) const
Definition ring.cpp:329
virtual ring_elem quotient(const ring_elem f, const ring_elem g) const
Definition ring.cpp:217
bool is_field() const
Definition ring.cpp:68
virtual void degree_of_var(int n, const ring_elem a, int &lo, int &hi) const
Definition ring.cpp:368
virtual ~Ring()
Definition ring.cpp:52
virtual bool in_subring(int nslots, const ring_elem a) const
Definition ring.cpp:361
ring_elem minus_oneV
Definition ring.hpp:131
ring_elem zero() const
Definition ring.hpp:359
void initialize_ring(long charac, const PolynomialRing *DR=nullptr, const std::vector< int > &heft_vec={})
Definition ring.cpp:30
ring_elem divide_by_content(ring_elem f) const
Definition ring.cpp:336
virtual ring_elem remainderAndQuotient(const ring_elem f, const ring_elem g, ring_elem &quot) const
Definition ring.cpp:223
virtual ring_elem homogenize(const ring_elem f, int v, int deg, const std::vector< int > &wts) const
Definition ring.cpp:389
virtual bool from_BigComplex(gmp_CC z, ring_elem &result) const
Definition ring.cpp:243
virtual unsigned long get_precision() const
Definition ring.cpp:438
virtual void lower_content(ring_elem &c, ring_elem g) const
Definition ring.cpp:308
virtual ring_elem invert(const ring_elem f) const =0
virtual ring_elem from_long(long n) const =0
virtual ring_elem negate(const ring_elem f) const =0
virtual ring_elem preferred_associate(ring_elem f) const
Definition ring.cpp:290
ring_elem get_non_unit() const
Definition ring.cpp:82
virtual ring_elem copy(const ring_elem f) const =0
virtual bool from_complex_double(double re, double im, ring_elem &result) const
Definition ring.cpp:276
ring_elem oneV
Definition ring.hpp:130
virtual int index_of_var(const ring_elem a) const
Definition ring.cpp:423
virtual bool from_double(double a, ring_elem &result) const
Definition ring.cpp:270
virtual ring_elem divide_by_var(int n, int d, const ring_elem a) const
Definition ring.cpp:376
virtual bool multi_degree(const ring_elem f, monomial d) const
Definition ring.cpp:407
bool declare_field()
Definition ring.cpp:69
virtual ring_elem zeroize_tiny(gmp_RR epsilon, const ring_elem f) const
Definition ring.cpp:439
virtual FreeModule * make_Schreyer_FreeModule() const
Definition ring.cpp:58
virtual bool is_zero(const ring_elem f) const =0
virtual ring_elem diff(ring_elem a, ring_elem b, int use_coeff) const
Definition ring.cpp:355
std::vector< int > mHeftVector
Definition ring.hpp:109
int _isfield
Definition ring.hpp:123
ring_elem _non_unit
Definition ring.hpp:122
virtual ring_elem random() const
Definition ring.cpp:284
const CoefficientRingR * cR
Definition ring.hpp:118
void add_to(ring_elem &f, const ring_elem &g) const
Definition ring.cpp:205
const CoefficientRingR * getCoefficientRingR() const
Definition ring.cpp:24
void mult_to(ring_elem &f, const ring_elem g) const
Definition ring.cpp:204
virtual ring_elem power(const ring_elem f, mpz_srcptr n) const
Exponentiation. This is the default function, if a class doesn't define this.
Definition ring.cpp:109
virtual bool lower_associate_divisor(ring_elem &f, ring_elem g) const
Definition ring.cpp:297
const PolynomialRing * degree_ring
Definition ring.hpp:108
virtual ring_elem mult(const ring_elem f, const ring_elem g) const =0
ring_elem split_off_content(ring_elem f, ring_elem &result) const
Definition ring.cpp:342
virtual ring_elem remainder(const ring_elem f, const ring_elem g) const
Definition ring.cpp:211
virtual M2_arrayint support(const ring_elem a) const
Definition ring.cpp:429
const Monoid * degree_monoid() const
Definition ring.cpp:13
ring_elem zeroV
Definition ring.hpp:129
Ring()
Definition ring.hpp:136
virtual SumCollector * make_SumCollector() const
Definition ring.cpp:486
xxx xxx xxx
Definition ring.hpp:102
static unsigned int mod_ui(mpz_srcptr n, unsigned int p)
Definition ZZ.cpp:55
Engine-side ring of integers, backed by GMP mpz_ptr elements.
Definition ZZ.hpp:77
const Ring * R
Definition ring.cpp:471
SumCollectorDefault(const Ring *R0)
Definition ring.cpp:475
virtual ~SumCollectorDefault()
Definition ring.cpp:476
ring_elem result
Definition ring.cpp:472
virtual void add(ring_elem f)
Definition ring.cpp:477
virtual ring_elem getValue()
Definition ring.cpp:478
Generic SumCollector that accumulates into a single ring_elem via repeated Ring::add_to.
Definition ring.cpp:470
Abstract incremental accumulator that builds a ring_elem from many add(f) calls.
Definition ring.hpp:669
Two SimpleARing-style coefficient adapters: CoefficientRingZZp and CoefficientRingR.
namespace exc — internal C++ exception types and the TRY / CATCH macro pair.
static CanonicalForm base
Definition factory.cpp:289
FreeModule — finite-rank free module R^n, the type-level anchor for every Matrix.
#define monomial
Definition gb-toric.cpp:11
int zero
const int ERROR
Definition m2-mem.cpp:55
VALGRIND_MAKE_MEM_DEFINED & result(result)
M2_arrayint M2_makearrayint(int n)
Definition m2-types.cpp:6
mpfr_srcptr gmp_RR
Definition m2-types.h:148
struct gmp_CC_struct * gmp_CC
Definition m2-types.h:156
mpfr_ptr gmp_RRmutable
Definition m2-types.h:150
mpfi_srcptr gmp_RRi
Definition m2-types.h:153
struct gmp_CCi_struct * gmp_CCi
Definition m2-types.h:162
Monoid — variable count, naming, grading, and monomial order of a polynomial ring.
Concrete commutative PolyRing — standard polynomial ring inheriting from PolyRingFlat.
PolynomialRing — abstract polynomial-ring base, the engine's most-reused class.
RingZZ * makeIntegerRing()
Definition ring.cpp:15
#define ZERO_RINGELEM
Definition ring.hpp:677
Ring — the legacy abstract base class for every coefficient and polynomial ring.