Macaulay2 Engine
Loading...
Searching...
No Matches
ZZ.cpp
Go to the documentation of this file.
1// Copyright 1995 Michael E. Stillman
2
3#include "ZZ.hpp"
4#include "text-io.hpp"
5#include "monoid.hpp"
6#include "relem.hpp"
7#include "ringmap.hpp"
8#include "gbring.hpp"
9
10#include "aring-zz-gmp.hpp"
11#include <utility>
12#include "exceptions.hpp"
13
14unsigned int computeHashValue_mpz(mpz_srcptr a)
15{
16 return static_cast<unsigned int>(mpz_get_si(a));
17}
18
20{
22
23 zeroV = from_long(0);
24 oneV = from_long(1);
26
27 degree_ring = deg_ring;
29 return true;
30}
31
32void RingZZ::text_out(buffer &o) const { o << "ZZ"; }
33
34mpz_ptr RingZZ::new_elem() const
35{
36 mpz_ptr result = getmemstructtype(mpz_ptr);
37 mpz_init(result);
38 return result;
39}
40
41unsigned int RingZZ::computeHashValue(const ring_elem a) const
42{
43 return computeHashValue_mpz(a.get_mpz());
44}
45
46std::pair<bool, int> RingZZ::get_si(mpz_srcptr n)
47{
48 if (not mpz_fits_slong_p(n)) return std::make_pair<bool, int>(false, 0);
49 long a = mpz_get_si(n);
50 int b = static_cast<int>(a);
51 if (a == b) return std::make_pair<bool, int>(true, std::move(b));
52 return std::make_pair<bool, int>(false, 0);
53}
54
55unsigned int RingZZ::mod_ui(mpz_srcptr n, unsigned int p)
56{
57 mpz_t ans;
58 mpz_init(ans);
59 unsigned int exp = static_cast<unsigned int>(mpz_mod_ui(ans, n, p));
60 mpz_clear(ans);
61 return exp;
62}
63
64std::pair<bool, long> RingZZ::coerceToLongInteger(ring_elem a) const
65{
66 return std::pair<bool, long>(mpz_fits_slong_p(a.get_mpz()),
67 mpz_get_si(a.get_mpz()));
68}
69
71 mpz_ptr result = new_elem();
74 return ring_elem(result);
75}
76
78 const ring_elem ap,
79 bool p_one,
80 bool p_plus,
81 bool p_parens) const
82{
83 (void) p_parens;
84 mpz_srcptr a = ap.get_mpz();
85
86 char s[1000];
87 char *str;
88
89 bool is_neg = (mask_mpz_cmp_si(a, 0) == -1);
90 bool is_one = (mask_mpz_cmp_si(a, 1) == 0 || mask_mpz_cmp_si(a, -1) == 0);
91
92 int size = static_cast<int>(mpz_sizeinbase(a, 10)) + 2;
93
94 char *allocstr = (size > 1000 ? newarray_atomic(char, size) : s);
95
96 if (!is_neg && p_plus) o << '+';
97 if (is_one)
98 {
99 if (is_neg) o << '-';
100 if (p_one) o << '1';
101 }
102 else
103 {
104 str = mpz_get_str(allocstr, 10, a);
105 o << str;
106 }
107 if (size > 1000) freemem(allocstr);
108}
109
111{
112 mpz_ptr result = new_elem();
113 mpz_set_si(result, n);
115
116 return ring_elem(result);
117}
118
119ring_elem RingZZ::from_int(mpz_srcptr n) const
120{
121 mpz_ptr result = new_elem();
122 mpz_set(result, n);
124
125 return ring_elem(result);
126}
127
128bool RingZZ::from_rational(mpq_srcptr q, ring_elem &result) const
129{
130 bool ok = mpz_cmp_si(mpq_denref(q), 1) == 0;
131 if (not ok) return false;
132 result = RingZZ::from_int(mpq_numref(q));
133 return true;
134}
135
136bool RingZZ::promote(const Ring *R, const ring_elem a, ring_elem &result) const
137{
138 (void) R;
139 (void) a;
140 (void) result;
141 return false;
142}
143
144bool RingZZ::lift(const Ring *, const ring_elem, ring_elem &) const
145{
146 return false;
147}
148
149bool RingZZ::is_unit(const ring_elem f) const
150{
151 mpz_srcptr a = f.get_mpz();
152 return (mask_mpz_cmp_si(a, 1) == 0 || mask_mpz_cmp_si(a, -1) == 0);
153}
154
155bool RingZZ::is_zero(const ring_elem f) const
156{
157 mpz_srcptr a = f.get_mpz();
158 return mpz_sgn(a) == 0;
159}
160
161bool RingZZ::is_equal(const ring_elem f, const ring_elem g) const
162{
163 mpz_srcptr a = f.get_mpz();
164 mpz_srcptr b = g.get_mpz();
165
166 return mpz_cmp(a, b) == 0;
167}
168int RingZZ::compare_elems(const ring_elem f, const ring_elem g) const
169{
170 mpz_srcptr a = f.get_mpz();
171 mpz_srcptr b = g.get_mpz();
172 int cmp = mpz_cmp(a, b);
173 if (cmp > 0) return 1;
174 if (cmp == 0) return 0;
175 return -1;
176}
178{
179 mpz_srcptr a = f.get_mpz();
180 return mpz_sgn(a) > 0;
181}
182
184{
185 mpz_srcptr a = f.get_mpz();
186
187 mpz_ptr result = new_elem();
188 mpz_set(result, a);
190
191 return ring_elem(result);
192}
193
195{
196 (void) f;
197}
198
200{
201 mpz_srcptr a = f.get_mpz();
202 if (mpz_sgn(a) >= 0) return from_long(1);
203 return from_long(-1);
204}
205
207{
208 // This sets f to either 0, 1 or -1.
209 // if f is 0, do f=sign(g), else f=sign(f)
210 // return whether f is zero
211 mpz_ptr result = RingZZ::new_elem();
212 mpz_srcptr a = f.get_mpz();
213 mpz_srcptr b = g.get_mpz();
214 int sa = mpz_sgn(a);
215 int sb = mpz_sgn(b);
216 int s = (sa == 0 ? sb : sa);
217
218 mpz_set_si(result, s);
220
221 f = ring_elem(result);
222 return !RingZZ::is_zero(f);
223}
224
226// c is a content elem, g is in ring
227{
228 if (is_zero(c))
229 {
230 c = g;
231 return;
232 }
233 mpz_ptr result = RingZZ::new_elem();
234 mpz_srcptr a = c.get_mpz();
235 mpz_srcptr b = g.get_mpz();
236 mpz_gcd(result, a, b);
237 if(mpz_sgn(a) == -1)
238 mpz_neg(result, result);
240 c = ring_elem(result);
241}
242
244{
245 mpz_ptr result = new_elem();
246 mpz_neg(result, f.get_mpz());
248 return ring_elem(result);
249}
250
252{
253 mpz_ptr result = new_elem();
254 mpz_add(result, f.get_mpz(), g.get_mpz());
256 return ring_elem(result);
257}
258
260{
261 mpz_ptr result = new_elem();
262 mpz_sub(result, f.get_mpz(), g.get_mpz());
264 return ring_elem(result);
265}
266
268{
269 mpz_ptr result = new_elem();
270 mpz_mul(result, f.get_mpz(), g.get_mpz());
272 return ring_elem(result);
273}
274
275ring_elem RingZZ::power(const ring_elem f, int n) const
276{
277 mpz_ptr result = new_elem();
278 if (n<0 && !is_unit(f))
279 throw exc::engine_error("can only raise to a nonnegative power");
280 else
281 {
282 mpz_pow_ui(result, f.get_mpz(), n);
284 }
285 return ring_elem(result);
286}
287ring_elem RingZZ::power(const ring_elem f, mpz_srcptr n) const
288{
289 std::pair<bool, int> n1 = RingZZ::get_si(n);
290 if (n1.first)
291 return power(f, n1.second);
292 else
293 throw exc::engine_error("exponent too large");
294}
295
297{
298 if (RingZZ::is_unit(f))
299 return RingZZ::copy(f);
300
301 throw exc::engine_error("division by a non unit attempted");
302}
303
305{
306 if (is_zero(g)) throw exc::division_by_zero_error();
307 mpz_ptr result = new_elem();
308 mpz_t rem;
309 mpz_init(rem);
310 mpz_fdiv_qr(result, rem, f.get_mpz(), g.get_mpz());
311 if (mpz_sgn(rem)) throw exc::engine_error("division not exact");
312 mpz_clear(rem);
314 return ring_elem(result);
315}
316
318 const ring_elem g,
319 ring_elem &quot) const
320{
321 mpz_ptr q = new_elem();
322 mpz_ptr r = new_elem();
323 int gsign = mpz_sgn(g.get_mpz());
324 mpz_t gg, ghalf;
325 mpz_init(gg);
326 mpz_init(ghalf);
327 mpz_abs(gg, g.get_mpz());
328 mpz_fdiv_qr(q, r, f.get_mpz(), gg);
329 mpz_tdiv_q_2exp(ghalf, gg, 1);
330 if (mpz_cmp(r, ghalf) > 0) // r > ghalf
331 {
332 mpz_sub(r, r, gg);
333 mpz_add_ui(q, q, 1);
334 }
335 if (gsign < 0) mpz_neg(q, q);
336
337 mpz_clear(gg);
338 mpz_clear(ghalf);
341 quot = ring_elem(q);
342 return ring_elem(r);
343}
344
346{
347 ring_elem quot;
348 ring_elem rem = RingZZ::remainderAndQuotient(f, g, quot);
349 remove(quot);
350 return rem;
351}
352
354{
355 ring_elem quot;
356 ring_elem rem = RingZZ::remainderAndQuotient(f, g, quot);
357 remove(rem);
358 return quot;
359}
360
362{
363 mpz_ptr result = new_elem();
364 mpz_gcd(result, f.get_mpz(), g.get_mpz());
366 return ring_elem(result);
367}
368
370 const ring_elem g,
371 ring_elem &u,
372 ring_elem &v) const
373{
374 mpz_ptr result = new_elem();
375 mpz_ptr u1 = new_elem();
376 mpz_ptr v1 = new_elem();
377 mpz_gcdext(result, u1, v1, f.get_mpz(), g.get_mpz());
381 u = ring_elem(u1);
382 v = ring_elem(v1);
383 return ring_elem(result);
384}
385
387 const ring_elem b,
388 ring_elem &x,
389 ring_elem &y) const
390{
391 assert(!is_zero(b));
392 // First check the special cases a = 0, b = 1, -1. Other cases: use gcd.
393 if (RingZZ::is_zero(a))
394 {
395 x = RingZZ::from_long(1);
396 y = RingZZ::from_long(0);
397 return;
398 }
399 mpz_srcptr bb = b.get_mpz();
400 if (mpz_cmp_ui(bb, 1) == 0)
401 {
402 x = RingZZ::from_long(1);
403 y = RingZZ::negate(a);
404 return;
405 }
406 if (mask_mpz_cmp_si(bb, -1) == 0)
407 {
408 x = RingZZ::from_long(1);
409 y = RingZZ::copy(a);
410 return;
411 }
412 ring_elem g = RingZZ::gcd(a, b);
413 y = RingZZ::divide(a, g);
414 x = RingZZ::divide(b, g);
416 if (mpz_sgn(x.get_mpz()) > 0)
417 y = RingZZ::negate(y);
418 else
419 x = RingZZ::negate(x);
420}
421
422ring_elem RingZZ::eval(const RingMap *map, const ring_elem f, int) const
423{
424 return map->get_ring()->from_int(f.get_mpz());
425}
426
427// Local Variables:
428// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
429// indent-tabs-mode: nil
430// End:
unsigned int computeHashValue_mpz(mpz_srcptr a)
Definition ZZ.cpp:14
unsigned int computeHashValue_mpz(mpz_srcptr a)
Definition ZZ.cpp:14
int mask_mpz_cmp_si(mpz_srcptr x, long int i)
Definition ZZ.hpp:53
Legacy RingZZ — a Ring-derived integer ring backed by GMP mpz_t.
M2::ARingZZGMP — aring integer ring backed straight by GMP mpz_t.
wrapper for the mpz_struct integer representation
Abstract base for the engine's polynomial-ring hierarchy.
Definition polyring.hpp:96
ring_elem minus_oneV
Definition ring.hpp:131
void initialize_ring(long charac, const PolynomialRing *DR=nullptr, const std::vector< int > &heft_vec={})
Definition ring.cpp:30
ring_elem oneV
Definition ring.hpp:130
virtual ring_elem from_int(mpz_srcptr n) const =0
const PolynomialRing * degree_ring
Definition ring.hpp:108
ring_elem zeroV
Definition ring.hpp:129
Ring()
Definition ring.hpp:136
const Ring * get_ring() const
Definition ringmap.hpp:111
Engine-side ring homomorphism: stores, for each source-ring variable, the target-ring element it maps...
Definition ringmap.hpp:60
virtual ring_elem add(const ring_elem f, const ring_elem g) const
Definition ZZ.cpp:251
virtual bool promote(const Ring *R, const ring_elem f, ring_elem &result) const
Definition ZZ.cpp:136
virtual ring_elem negate(const ring_elem f) const
Definition ZZ.cpp:243
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 ZZ.cpp:287
virtual unsigned int computeHashValue(const ring_elem a) const
Definition ZZ.cpp:41
M2::ARingZZGMP * coeffR
Definition ZZ.hpp:82
virtual ring_elem quotient(const ring_elem f, const ring_elem g) const
Definition ZZ.cpp:353
virtual bool is_unit(const ring_elem f) const
Definition ZZ.cpp:149
virtual bool is_zero(const ring_elem f) const
Definition ZZ.cpp:155
static unsigned int mod_ui(mpz_srcptr n, unsigned int p)
Definition ZZ.cpp:55
virtual void lower_content(ring_elem &c, ring_elem g) const
Definition ZZ.cpp:225
virtual ring_elem from_long(long n) const
Definition ZZ.cpp:110
virtual void syzygy(const ring_elem a, const ring_elem b, ring_elem &x, ring_elem &y) const
Definition ZZ.cpp:386
virtual ring_elem eval(const RingMap *map, const ring_elem f, int first_var) const
Definition ZZ.cpp:422
virtual bool lower_associate_divisor(ring_elem &f, ring_elem g) const
Definition ZZ.cpp:206
virtual bool from_rational(mpq_srcptr q, ring_elem &result) const
Definition ZZ.cpp:128
virtual ring_elem remainderAndQuotient(const ring_elem f, const ring_elem g, ring_elem &quot) const
Definition ZZ.cpp:317
virtual void remove(ring_elem &f) const
Definition ZZ.cpp:194
bool initialize_ZZ(const PolynomialRing *deg_ring)
Definition ZZ.cpp:19
mpz_ptr new_elem() const
Definition ZZ.cpp:34
virtual ring_elem subtract(const ring_elem f, const ring_elem g) const
Definition ZZ.cpp:259
virtual ring_elem random() const
Definition ZZ.cpp:70
virtual ring_elem from_int(mpz_srcptr n) const
Definition ZZ.cpp:119
virtual ring_elem divide(const ring_elem f, const ring_elem g) const
Definition ZZ.cpp:304
virtual int compare_elems(const ring_elem f, const ring_elem g) const
Definition ZZ.cpp:168
static std::pair< bool, int > get_si(mpz_srcptr n)
Definition ZZ.cpp:46
ring_elem gcd(const ring_elem f, const ring_elem g) const
Definition ZZ.cpp:361
int is_positive(const ring_elem a) const
Definition ZZ.cpp:177
virtual bool is_equal(const ring_elem f, const ring_elem g) const
Definition ZZ.cpp:161
virtual ring_elem invert(const ring_elem f) const
Definition ZZ.cpp:296
virtual ring_elem mult(const ring_elem f, const ring_elem g) const
Definition ZZ.cpp:267
virtual ring_elem remainder(const ring_elem f, const ring_elem g) const
Definition ZZ.cpp:345
virtual std::pair< bool, long > coerceToLongInteger(ring_elem a) const
Definition ZZ.cpp:64
virtual void text_out(buffer &o) const
Definition ZZ.cpp:32
ring_elem gcd_extended(const ring_elem f, const ring_elem g, ring_elem &u, ring_elem &v) const
Definition ZZ.cpp:369
virtual ring_elem preferred_associate(ring_elem f) const
Definition ZZ.cpp:199
virtual void elem_text_out(buffer &o, const ring_elem f, bool p_one=true, bool p_plus=false, bool p_parens=false) const
Definition ZZ.cpp:77
virtual ring_elem copy(const ring_elem f) const
Definition ZZ.cpp:183
virtual bool lift(const Ring *R, const ring_elem f, ring_elem &result) const
Definition ZZ.cpp:144
namespace exc — internal C++ exception types and the TRY / CATCH macro pair.
GBRing and gbvector — the GB-tuned polynomial-ring view used by classical Buchberger code.
void mpz_reallocate_limbs(mpz_ptr _z)
Definition gmp-util.h:46
int p
void freemem(void *s)
Definition m2-mem.cpp:103
void size_t s
Definition m2-mem.cpp:271
VALGRIND_MAKE_MEM_DEFINED & result(result)
#define getmemstructtype(S)
Definition m2-mem.h:143
Monoid — variable count, naming, grading, and monomial order of a polynomial ring.
#define newarray_atomic(T, len)
Definition newdelete.hpp:91
volatile int x
void rawSetRandomInteger(mpz_ptr result, gmp_ZZ maxN)
Definition random.cpp:56
RingElement — tagged (Ring*, ring_elem) pair, the engine's universal element type.
RingMap — engine representation of a ring homomorphism.
Text-formatting helpers layered on buffer: bignum print, line wrapping, M2_gbTrace-gated emit.
mpz_srcptr get_mpz() const
Definition ringelem.hpp:127