Macaulay2 Engine
Loading...
Searching...
No Matches
RingTest.hpp
Go to the documentation of this file.
1// Copyright 2013 Michael E. Stillman
2
3#ifndef __ring_test_hpp__
4#define __ring_test_hpp__
5
43
44#include <cstdio>
45#include <string>
46#include <iostream>
47//#include <sstream>
48#include <memory>
49#include <gtest/gtest.h>
50//#include <mpfr.h>
51
52#include "interface/random.h"
53#include "ZZ.hpp"
54#include "exceptions.hpp"
55
56const int ntrials = 100; // 5000
57
58template <typename T>
59std::istream& fromStream(std::istream& i,
60 const T& R,
61 typename T::ElementType& result);
62
63template <typename T>
64bool fromStream(std::istream& i, const T& R, ring_elem& result);
65
66template <typename T>
67std::string ringName(const T& R)
68{
69 buffer o;
70 R.text_out(o);
71 std::string result = o.str();
72 return result;
73}
74
75template <typename RingType>
76ring_elem getElement(const RingType& R, int index);
77
78template <typename RingType>
80{
81 public:
82 RingElementGenerator(const RingType& R) : mRing(R), mNext(0) {}
84 void reset() { mNext = 0; }
85 private:
86 const RingType& mRing;
87 int mNext;
88};
89
90template <typename T>
91void testRingCoercions(const T* R, int ntrials)
92{
93 // from int
94 // from mpz
95 // from rational
96}
97template <typename T>
98void testRingNegate(const T* R, int ntrials)
99{
101 for (int i = 0; i < ntrials; i++)
102 {
103 // test: (-a) + (a) == a
104 ring_elem a = gen.nextElement();
105 ring_elem b = R->negate(a);
106 ring_elem c = R->add(a, b);
107 EXPECT_TRUE(R->is_zero(c));
108 }
109}
110template <typename T>
111void testRingAdd(const T* R, int ntrials)
112{
114 for (int i = 0; i < ntrials; i++)
115 {
116 // test: (a+b) + (-b) == a
117 ring_elem a = gen.nextElement();
118 ring_elem b = gen.nextElement();
119 ring_elem c = R->add(a, b);
120 ring_elem d = R->negate(b);
121 ring_elem e = R->add(c, d); // should be a
122 EXPECT_TRUE(R->is_equal(e, a));
123 }
124}
125template <typename T>
126void testRingSubtract(const T* R, int ntrials)
127{
129 for (int i = 0; i < ntrials; i++)
130 {
131 // test: (a-b) + (b) == a
132 ring_elem a = gen.nextElement();
133 ring_elem b = gen.nextElement();
134 ring_elem c = R->subtract(a, b);
135 ring_elem e = R->add(c, b);
136 EXPECT_TRUE(R->is_equal(e, a));
137 }
138}
139template <typename T>
140void testRingDivide(const T* R, int ntrials)
141{
142 auto zero = R->zero();
143 auto a = R->from_long(3);
144 EXPECT_ANY_THROW(R->divide(a, zero));
145
147 for (int i = 0; i < ntrials; i++)
148 {
149 // test: (a*b) // b == a
150 ring_elem a = gen.nextElement();
151 ring_elem b = gen.nextElement();
152 ring_elem c = R->mult(a, b);
153 if (R->is_zero(b))
154 EXPECT_TRUE(R->is_zero(c));
155 else
156 {
157 ring_elem d = R->divide(c, b);
158 EXPECT_TRUE(R->is_equal(d, a));
159 }
160 }
161}
162
163template <typename T>
164void testRingAxioms(const T* R, int ntrials)
165{
167 for (int i = 0; i < ntrials; i++)
168 {
169 ring_elem a = gen.nextElement();
170 ring_elem b = gen.nextElement();
171 ring_elem c = gen.nextElement();
172
173 // Test commutativity
174 // test: a*b = b*a
175 // test: a+b == b+a
176 ring_elem d = R->add(a, b);
177 ring_elem e = R->add(b, a);
178 EXPECT_TRUE(R->is_equal(d, e));
179 d = R->mult(a, b);
180 e = R->mult(b, a);
181 EXPECT_TRUE(R->is_equal(d, e));
182
183 // Test associativity
184 // test: a+(b+c) == (a+b)+c
185 // test: a*(b*c) == (a*b)*c
186 d = R->add(a, R->add(b, c));
187 e = R->add(R->add(a, b), c);
188 EXPECT_TRUE(R->is_equal(d, e));
189 d = R->mult(a, R->mult(b, c));
190 e = R->mult(R->mult(a, b), c);
191 EXPECT_TRUE(R->is_equal(d, e));
192
193 // Test distributivity
194 // test: a*(b+c) == a*b + a*c
195 d = R->mult(a, R->add(b, c));
196 e = R->add(R->mult(a, b), R->mult(a, c));
197 EXPECT_TRUE(R->is_equal(d, e));
198 }
199}
200template <typename T>
201void testRingPower(const T* R, int ntrials)
202{
203 mpz_t gmp1;
204 mpz_init(gmp1);
206 for (int i = 0; i < ntrials; i++)
207 {
208 ring_elem a = gen.nextElement();
209 // TODO: what should the answer here be?
210 // EXPECT_TRUE(R->is_equal(R->power(a, 0), R->one())); // 0^0 == 1 too?
211 EXPECT_TRUE(R->is_equal(R->power(a, 1), a));
212
213 int e1 = rawRandomInt(10) + 1;
214 int e2 = rawRandomInt(10) + 1;
215 // std::cout << "(" << e1 << "," << e2 << ")" << std::endl;
216 ring_elem b = R->power(a, e1);
217 ring_elem c = R->power(a, e2);
218 ring_elem d = R->power(a, e1 + e2);
219 EXPECT_TRUE(R->is_equal(R->mult(b, c), d));
220
221 // Make sure that powers via mpz work (at least for small exponents)
222 mpz_set_si(gmp1, e1);
223 ring_elem b1 = R->power(a, gmp1);
224 EXPECT_TRUE(R->is_equal(b1, b));
225 }
226 mpz_clear(gmp1);
227}
228template <typename T>
229void testRingGCD(const T* R, int ntrials)
230{
232 for (int i = 0; i < ntrials; i++)
233 {
234 ring_elem a = gen.nextElement();
235 ring_elem b = gen.nextElement();
236
237 // (a // gcd(a,b) == 0, b // gcd(a,b) == 0,
238 ring_elem c = R->gcd(a, b);
239 ring_elem u, v;
240 ring_elem d = R->gcd_extended(a, b, u, v);
241
242 EXPECT_TRUE(R->is_equal(c, d));
243 EXPECT_TRUE(R->is_equal(c, R->add(R->mult(a, u), R->mult(b, v))));
244 EXPECT_TRUE(R->is_equal(a, R->mult(R->divide(a, c), c)));
245 }
246}
247template <typename T>
248void testRingRemainder(const T* R, int ntrials)
249{
251 for (int i = 0; i < ntrials; i++)
252 {
253 ring_elem a = gen.nextElement();
254 ring_elem b = gen.nextElement();
255
256#if 0
257 ring_elem c = R->remainder(a, R->zero()); // FAILS!!
258 EXPECT_TRUE(R->is_equal(c,a));
259#endif
260
261 ring_elem r = R->remainder(a, b);
262 ring_elem q = R->quotient(a, b);
263 ring_elem r1, q1;
264 r1 = R->remainderAndQuotient(a, b, q1);
265
266 EXPECT_TRUE(R->is_equal(r, r1));
267 EXPECT_TRUE(R->is_equal(q, q1));
268 ring_elem a1 = R->add(R->mult(q, b), r);
269 EXPECT_TRUE(R->is_equal(a, a1));
270 }
271}
272template <typename T>
273void testRingSyzygy(const T* R, int ntrials)
274{
276 for (int i = 0; i < ntrials; i++)
277 {
278 ring_elem u, v;
279 ring_elem a = gen.nextElement();
280 ring_elem b = gen.nextElement();
281 if (R->is_zero(b)) continue;
282
283 // special cases (note: b != 0 for rest of routine)
284 // syzygy(0,b) returns (1,0)
285 R->syzygy(R->zero(), b, u, v);
286 EXPECT_TRUE(R->is_equal(u, R->one()));
287 EXPECT_TRUE(R->is_equal(v, R->zero()));
288 // syzygy(a,1) returns (1,-a)
289 R->syzygy(a, R->one(), u, v);
290 EXPECT_TRUE(R->is_equal(u, R->one()));
291 EXPECT_TRUE(R->is_equal(v, R->negate(a)));
292 // syzygy(a,-1) returns (1,a)
293 R->syzygy(a, R->minus_one(), u, v);
294 EXPECT_TRUE(R->is_equal(u, R->one()));
295 EXPECT_TRUE(R->is_equal(v, a));
296
297 R->syzygy(a, b, u, v);
298 ring_elem result = R->add(R->mult(a, u), R->mult(b, v));
299#if 0
300 buffer o;
301 o << "a=";
302 R->elem_text_out(o,a);
303 o << " b=";
304 R->elem_text_out(o,b);
305 o << " u=";
306 R->elem_text_out(o,u);
307 o << " v=";
308 R->elem_text_out(o,v);
309 std::cout << o.str() << std::endl;
310#endif
311 EXPECT_TRUE(R->is_zero(result));
312 }
313
314 // over ZZ:
315 // syzygy(a,b) returns (b/c, -a/c), where c = +- gcd(a,b), with same sign as b
316}
317
318#endif
319
320// Local Variables:
321// compile-command: "make -C $M2BUILDDIR/Macaulay2/e/unit-tests check "
322// indent-tabs-mode: nil
323// End:
const int ntrials
Definition ARingTest.hpp:42
void testRingPower(const T *R, int ntrials)
Definition RingTest.hpp:201
void testRingDivide(const T *R, int ntrials)
Definition RingTest.hpp:140
void testRingSyzygy(const T *R, int ntrials)
Definition RingTest.hpp:273
ring_elem getElement(const RingType &R, int index)
void testRingGCD(const T *R, int ntrials)
Definition RingTest.hpp:229
void testRingCoercions(const T *R, int ntrials)
Definition RingTest.hpp:91
void testRingAxioms(const T *R, int ntrials)
Definition RingTest.hpp:164
std::istream & fromStream(std::istream &i, const T &R, typename T::ElementType &result)
void testRingRemainder(const T *R, int ntrials)
Definition RingTest.hpp:248
void testRingAdd(const T *R, int ntrials)
Definition RingTest.hpp:111
std::string ringName(const T &R)
Definition RingTest.hpp:67
void testRingSubtract(const T *R, int ntrials)
Definition RingTest.hpp:126
void testRingNegate(const T *R, int ntrials)
Definition RingTest.hpp:98
Legacy RingZZ — a Ring-derived integer ring backed by GMP mpz_t.
RingElementGenerator(const RingType &R)
Definition RingTest.hpp:82
ring_elem nextElement()
Definition RingTest.hpp:83
const RingType & mRing
Definition RingTest.hpp:86
char * str()
Definition buffer.hpp:72
namespace exc — internal C++ exception types and the TRY / CATCH macro pair.
int zero
VALGRIND_MAKE_MEM_DEFINED & result(result)
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.
#define T
Definition table.c:13