Macaulay2 Engine
Loading...
Searching...
No Matches
ARingTest.hpp
Go to the documentation of this file.
1#ifndef __ring_test_hpp__
2#define __ring_test_hpp__
3
39
40#include "interface/random.h"
41
42const int ntrials = 1000;
43// const int ntrials = 1000000; // not good for the ssd - system swaps
44// memory....
45
46template <typename RingType>
47void getElement(const RingType& R,
48 int index,
49 typename RingType::ElementType& result);
50
51template <typename RingType>
53{
54 public:
55 ARingElementGenerator(const RingType& R) : mRing(R), mNext(0) {}
56 void nextElement(typename RingType::ElementType& result)
57 {
59 }
60 void reset() { mNext = 0; }
61 private:
62 const RingType& mRing;
63 int mNext;
64};
65
66template <typename T>
67std::istream& fromStream(std::istream& i,
68 const T& R,
69 typename T::ElementType& result);
70
71template <typename T>
72void testSomeMore(const T& R)
73{
74 typename T::ElementType a, b, c, d;
75 R.init(a);
76 R.init(b);
77 R.init(c);
78 R.init(d);
79
80 R.set_from_long(a, 27);
81 R.set_from_long(b, static_cast<int>(R.characteristic()) - 11);
82 R.set_from_long(c, 16);
83 R.add(d, a, b);
84
85 buffer o;
86 o << "a=";
87 R.elem_text_out(o, a, true);
88 o << " b=";
89 R.elem_text_out(o, b, true);
90 o << " c=";
91 R.elem_text_out(o, c, true);
92 o << " d=a+b=";
93 R.elem_text_out(o, d, true);
94 std::cout << o.str() << std::endl;
95
96 EXPECT_TRUE(R.is_equal(c, d));
97
98 R.clear(a);
99 R.clear(b);
100 R.clear(c);
101 R.clear(d);
102}
103
104template <typename T>
105void testNegate(const T& R, int ntrials)
106{
108 typename T::ElementType a, b;
109 R.init(a);
110 R.init(b);
111 for (int i = 0; i < ntrials; i++)
112 {
113 gen.nextElement(a);
114 R.negate(b, a);
115 R.add(b, a, b);
116 EXPECT_TRUE(R.is_zero(b)); // test: (-a) + a == 0
117 }
118 R.clear(a);
119 R.clear(b);
120}
121
122template <typename T>
123std::string ringName(const T& R)
124{
125 buffer o;
126 R.text_out(o);
127 std::string result = o.str();
128 return result;
129}
130
131template <typename T>
132void testCoercions(const T& R)
133{
134 typename T::ElementType a, b, c;
135 mpz_t m, base;
136 mpq_t n1;
137 R.init(a);
138 R.init(b);
139 R.init(c);
140 mpz_init(m);
141 mpz_init(base);
142 mpq_init(n1);
143
144 // set_from_mpz
145 mpz_set_str(base, "2131236127486324783264782364", 10);
146 R.set_from_mpz(c, base);
147 for (int i = -1000; i < 1000; i++)
148 {
149 mpz_set_si(m, i);
150 mpz_add(m, m, base); // m = base + i
151 R.set_from_mpz(a, m); // a = (base + i) mod charac
152 R.set_from_long(b, i);
153 R.add(b, c, b); // b = (base mod charac) + (i mod charac)
154 EXPECT_TRUE(R.is_equal(a, b)); // a, b should be equal
155 }
156
157 // set_from_mpq
158 for (int i = 1; i < 300; i++)
159 {
160 mpq_set_si(n1, 43999, i);
161 mpq_canonicalize(n1); // n1 = 43999/i
162
163 // check that (43999 mod charac)/(i mod charac) == n1 mod charac
164 // if (i mod charac) is not zero.
165 if (R.characteristic() == 0 or (i % R.characteristic()) == 0) continue;
166 bool ok = R.set_from_mpq(a, n1);
167 EXPECT_TRUE(ok);
168 R.set_from_long(b, 43999);
169 R.set_from_long(c, i);
170 if (!R.is_zero(c))
171 {
172 R.divide(c, b, c);
173 EXPECT_TRUE(R.is_equal(a, c));
174 }
175 }
176
177 R.clear(a);
178 R.clear(b);
179 R.clear(c);
180 mpz_clear(m);
181 mpz_clear(base);
182 mpq_clear(n1);
183}
184
185template <typename T>
186void testAxioms(const T& R, int ntrials)
187{
189 typename T::ElementType a, b, c, d, e, f;
190 R.init(a);
191 R.init(b);
192 R.init(c);
193 R.init(d);
194 R.init(e);
195 R.init(f);
196 for (int i = 0; i < ntrials; i++)
197 {
198 gen.nextElement(a);
199 gen.nextElement(b);
200 gen.nextElement(c);
201
202 // Test commutativity
203 // test: a*b = b*a
204 // test: a+b == b+a
205 R.add(d, a, b);
206 R.add(e, b, a);
207 EXPECT_TRUE(R.is_equal(d, e));
208 R.mult(d, a, b);
209 R.mult(e, b, a);
210 EXPECT_TRUE(R.is_equal(d, e));
211
212 // Test associativity
213 // test: a+(b+c) == (a+b)+c
214 // test: a*(b*c) == (a*b)*c
215 R.add(d, b, c);
216 R.add(d, a, d);
217 R.add(e, a, b);
218 R.add(e, e, c);
219 EXPECT_TRUE(R.is_equal(d, e));
220 R.mult(d, b, c);
221 R.mult(d, a, d);
222 R.mult(e, a, b);
223 R.mult(e, e, c);
224 EXPECT_TRUE(R.is_equal(d, e));
225
226 // Test distributivity
227 // test: a*(b+c) == a*b + a*c
228 R.add(d, b, c);
229 R.mult(d, a, d);
230 R.mult(e, a, b);
231 R.mult(f, a, c);
232 R.add(e, e, f);
233 EXPECT_TRUE(R.is_equal(d, e));
234 }
235 R.clear(a);
236 R.clear(b);
237 R.clear(c);
238 R.clear(d);
239 R.clear(e);
240 R.clear(f);
241}
242
243template <typename T>
244void testAdd(const T& R, int ntrials)
245{
247 typename T::ElementType a, b, c, d;
248 R.init(a);
249 R.init(b);
250 R.init(c);
251 R.init(d);
252 for (int i = 0; i < ntrials; i++)
253 {
254 gen.nextElement(a);
255 gen.nextElement(b);
256 R.add(c, a, b); // c = a+b
257 R.negate(d, b); // d = -b
258
259#if 0
260 buffer o;
261 o << "a=";
262 R.elem_text_out(o, a , true, false, false);
263 o << " b=";
264 R.elem_text_out(o, b , true, false, false);
265 o << " a+b=";
266 R.elem_text_out(o, c , true, false, false);
267 o << " -b=";
268 R.elem_text_out(o, d , true, false, false);
269#endif
270
271 R.add(d, c, d); // d = (a+b) + (-b)
272
273#if 0
274 o << " a=";
275 R.elem_text_out(o, d , true, false, false);
276 std::cout << o.str() << std::endl;
277#endif
278 EXPECT_TRUE(R.is_equal(d, a));
279 }
280 R.clear(a);
281 R.clear(b);
282 R.clear(c);
283 R.clear(d);
284}
285
286template <typename T>
287void testSubtract(const T& R, int ntrials)
288{
290 typename T::ElementType a, b, c, d;
291 R.init(a);
292 R.init(b);
293 R.init(c);
294 R.init(d);
295 for (int i = 0; i < ntrials; i++)
296 {
297 gen.nextElement(a);
298 gen.nextElement(b);
299 gen.nextElement(c);
300 gen.nextElement(d);
301 R.add(c, a, b); // c = a+b
302 R.subtract(d, c, b); // d = (a+b) - b
303 EXPECT_TRUE(R.is_equal(d, a));
304 }
305 R.clear(a);
306 R.clear(b);
307 R.clear(c);
308 R.clear(d);
309}
310
311template <typename T>
312void testMultiply(const T& R, int ntrials)
313{
315 typename T::ElementType a, b, c, d, zero;
316 R.init(a);
317 R.init(b);
318 R.init(c);
319 R.init(d);
320 R.init(zero);
321 R.set_from_long(zero, 0);
322 for (int i = 0; i < ntrials; i++)
323 {
324 gen.nextElement(a);
325 gen.nextElement(b);
326 gen.nextElement(c);
327 gen.nextElement(d);
328 R.mult(c, a, zero);
329 EXPECT_TRUE(R.is_equal(c, zero));
330 // TODO: finish this with more tests
331 }
332 R.clear(a);
333 R.clear(b);
334 R.clear(c);
335 R.clear(d);
336 R.clear(zero);
337}
338
339template <typename T>
340void testDivide(const T& R, int ntrials)
341{
343 typename T::ElementType a, b, c, d, zero;
344 R.init(a);
345 R.init(b);
346 R.init(c);
347 R.init(d);
348 R.init(zero);
349 R.set_from_long(zero, 0);
350 for (int i = 0; i < ntrials; i++)
351 {
352 // c = a*b
353 // c//a == b
354 gen.nextElement(a);
355 gen.nextElement(b);
356 gen.nextElement(c);
357 gen.nextElement(d);
358 if (R.is_zero(a)) continue;
359 R.mult(c, a, b);
360 R.divide(d, c, a);
361 EXPECT_TRUE(R.is_equal(b, d));
362 }
363 R.clear(a);
364 R.clear(b);
365 R.clear(c);
366 R.clear(d);
367 R.clear(zero);
368}
369
370template <typename T>
371void testReciprocal(const T& R, int ntrials)
372{
374 typename T::ElementType a, b, c, one;
375 R.init(a);
376 R.init(b);
377 R.init(c);
378 R.init(one);
379 R.set_from_long(one, 1);
380 for (int i = 0; i < ntrials; i++)
381 {
382 // c = 1/a
383 // 1/a * a == 1
384 gen.nextElement(a);
385 if (R.is_zero(a)) continue;
386 R.invert(b, a);
387 R.mult(c, b, a);
388 EXPECT_TRUE(R.is_equal(c, one));
389 }
390 R.clear(a);
391 R.clear(b);
392 R.clear(c);
393 R.clear(one);
394}
395
396template <typename T>
397void testPower(const T& R, int ntrials)
398{
399 // test the following: (x=generator of the finite field, q = card of field)
400 // check: x^i != x, for 2 <= i <= characteristic-??
401 // x^q == x
402 // x^(q-1) == 1
403 // x^(-1) * x == 1
404 // x^(-2) * x^2 == 1
405
406 // a^2 == a*a, for various a
407 // a^3 == a*a*a
408 // a^0 == 1, what if a == 0?
409 // 1^n == 1, various n
411 typename T::ElementType a, b, c, d, one;
412 int q = static_cast<int>(R.cardinality());
413 R.init(one);
414 R.init(a);
415 R.init(b);
416 R.init(c);
417 R.init(d);
418 R.set_from_long(one, 1);
419 for (int i = 0; i < ntrials; i++)
420 {
421 gen.nextElement(a);
422 gen.nextElement(b);
423
424 R.power(c, a, q);
425 EXPECT_TRUE(R.is_equal(c, a)); // test a^q == a
426
427 if (R.is_zero(a)) continue;
428
429 R.power(c, a, q - 1);
430 EXPECT_TRUE(R.is_equal(c, one)); // test a^(q-1) == 1
431
432 R.power(c, a, -1); // test a^-1 * a == 1
433 R.mult(c, a, c);
434 EXPECT_TRUE(R.is_equal(c, one));
435
436 R.power(c, a, -2); // test a^-2 * a^3 == a
437 R.power(d, a, 3);
438 R.mult(d, c, d);
439 EXPECT_TRUE(R.is_equal(d, a));
440 }
441 R.clear(a);
442 R.clear(b);
443 R.clear(c);
444 R.clear(d);
445 R.clear(one);
446}
447
448template <typename T>
449void testFiniteField(const T& R, int ntrials)
450{
451 testCoercions(R);
453 testAdd(R, ntrials); // fails in char 2, ffpack (negating 1 gives -1)...
454 testSubtract(R, ntrials); // fails in char 2, ffpack
456 testDivide(R, ntrials); // fails in char 2, ffpack
458 testPower(R, ntrials); // fails?
460
461 // TODO: test promote, lift, syzygy(?), (ringmaps)
462 // test random number generation?
463 // get generator
464}
465
466template <typename T>
467void testARingInterface(const T& R)
468{
469 // this test makes sure that all of the interface functions required
470 // actually exist.
471
472 const M2::RingID rid = R.ringID;
473 std::cout << "ring ID: " << rid << std::endl;
474}
475
476#endif
477
478// Local Variables:
479// compile-command: "make -C $M2BUILDDIR/Macaulay2/e/unit-tests check "
480// indent-tabs-mode: nil
481// End:
void testAdd(const T &R, int ntrials)
void testNegate(const T &R, int ntrials)
void testReciprocal(const T &R, int ntrials)
void testPower(const T &R, int ntrials)
void testARingInterface(const T &R)
void testCoercions(const T &R)
std::istream & fromStream(std::istream &i, const T &R, typename T::ElementType &result)
void testAxioms(const T &R, int ntrials)
void testFiniteField(const T &R, int ntrials)
const int ntrials
Definition ARingTest.hpp:42
void getElement(const RingType &R, int index, typename RingType::ElementType &result)
void testSubtract(const T &R, int ntrials)
void testSomeMore(const T &R)
Definition ARingTest.hpp:72
void testMultiply(const T &R, int ntrials)
std::string ringName(const T &R)
void nextElement(typename RingType::ElementType &result)
Definition ARingTest.hpp:56
const RingType & mRing
Definition ARingTest.hpp:62
ARingElementGenerator(const RingType &R)
Definition ARingTest.hpp:55
char * str()
Definition buffer.hpp:72
static CanonicalForm base
Definition factory.cpp:289
void testDivide()
int zero
RingID
Definition aring.hpp:75
VALGRIND_MAKE_MEM_DEFINED & result(result)
Engine-boundary C API for the engine's PRNG and rational / real / complex random draws.
#define T
Definition table.c:13