Macaulay2 Engine
Loading...
Searching...
No Matches
aring-CCC.hpp
Go to the documentation of this file.
1// Copyright 2012 Michael E. Stillman
2
3#ifndef _aring_CCC_hpp_
4#define _aring_CCC_hpp_
5
43
44#include "interface/gmp-util.h" // for mpfr_reallocate_limbs, moveTo_gmpCC
45#include "interface/random.h" // for randomMpfr
46
47#include "aring.hpp"
48#include "buffer.hpp"
49#include "ringelem.hpp"
50#include "ringmap.hpp"
51
52#include "aring-RRR.hpp"
53
54class RingMap;
55
56namespace M2 {
70class ARingCCC : public SimpleARing<ARingCCC>
71{
72 // complex numbers represented as pairs of MPFRs.
73
74 private:
75 const ARingRRR mRRR; // reals with the same precision
76 public:
77 static const RingID ringID = ring_CCC;
78
79 typedef cc_struct elem; // ??? staighten this out!!!
83
84 ARingCCC(unsigned long precision) : mRRR(precision) {}
85 ARingCCC() : mRRR(53) {}
86 // ring informational
87 size_t characteristic() const { return 0; }
88 unsigned long get_precision() const { return mRRR.get_precision(); }
89 void text_out(buffer& o) const;
90
91 const RealRingType& real_ring() const { return mRRR; }
92 unsigned int computeHashValue(const ElementType& a) const
93 {
94 double a1 = mpfr_get_d(&a.re, MPFR_RNDN);
95 double b1 = mpfr_get_d(&a.im, MPFR_RNDN);
96 return static_cast<unsigned int>(12347. * a1 + 865800. * b1);
97 }
98
100 // ElementType informational ////
102
103 bool is_unit(const ElementType& f) const { return !is_zero(f); }
104 bool is_zero(const ElementType& f) const
105 {
106 return mpfr_cmp_si(&f.re, 0) == 0 && mpfr_cmp_si(&f.im, 0) == 0;
107 }
108
109 bool is_equal(const ElementType& f, const ElementType& g) const
110 {
111 return mpfr_cmp(&f.re, &g.re) == 0 && mpfr_cmp(&f.im, &g.im) == 0;
112 }
113
114 int compare_elems(const ElementType& f, const ElementType& g) const
115 {
116 int cmp_re = mpfr_cmp(&f.re, &g.re);
117 if (cmp_re < 0) return -1;
118 if (cmp_re > 0) return 1;
119 int cmp_im = mpfr_cmp(&f.im, &g.im);
120 if (cmp_im < 0) return -1;
121 if (cmp_im > 0) return 1;
122 return 0;
123 }
124
126 // to/from ringelem ////////
129 {
131 init(*res);
132 set(*res, a);
135 result = ring_elem(res);
136 }
137
139 {
140 set(result, *a.get_cc());
141 }
142
144 {
145 return *a.get_cc();
146 }
147
148 // 'init', 'init_set' functions
149
151 {
152 mpfr_init2(&result.re, get_precision());
153 mpfr_init2(&result.im, get_precision());
154 }
155
156 void init_set(ElementType& result, const ElementType& a) const
157 {
158 init(result);
159 mpfr_set(&result.re, &a.re, MPFR_RNDN);
160 mpfr_set(&result.im, &a.im, MPFR_RNDN);
161 }
162
163 void set(ElementType& result, const ElementType& a) const
164 {
165 mpfr_set(&result.re, &a.re, MPFR_RNDN);
166 mpfr_set(&result.im, &a.im, MPFR_RNDN);
167 }
168
170 {
171 mpfr_set_si(&result.re, 0, MPFR_RNDN);
172 mpfr_set_si(&result.im, 0, MPFR_RNDN);
173 }
174
176 {
177 mpfr_clear(&result.re);
178 mpfr_clear(&result.im);
179 }
180
181 void copy(ElementType& result, const ElementType& a) const { set(result, a); }
182 void set_from_long(ElementType& result, long a) const
183 {
184 mpfr_set_si(&result.re, a, MPFR_RNDN);
185 mpfr_set_si(&result.im, 0, MPFR_RNDN);
186 }
187
188 void set_var(ElementType& result, int v) const
189 {
190 (void) v;
192 }
193
194 void set_from_mpz(ElementType& result, mpz_srcptr a) const
195 {
196 mpfr_set_z(&result.re, a, MPFR_RNDN);
197 mpfr_set_si(&result.im, 0, MPFR_RNDN);
198 }
199
200 bool set_from_mpq(ElementType& result, mpq_srcptr a) const
201 {
202 mpfr_set_q(&result.re, a, MPFR_RNDN);
203 mpfr_set_si(&result.im, 0, MPFR_RNDN);
204 return true;
205 }
206
208 {
209 mpfr_set(&result.re, a, MPFR_RNDN);
210 mpfr_set_si(&result.im, 0, MPFR_RNDN);
211 return true;
212 }
214 { //???
215 mpfr_set(&result.re, a->re, MPFR_RNDN);
216 mpfr_set(&result.im, a->im, MPFR_RNDN);
217 return true;
218 }
219 bool set_from_double(ElementType& result, double a) const
220 {
221 mpfr_set_d(&result.re, a, MPFR_RNDN);
222 mpfr_set_si(&result.im, 0, MPFR_RNDN);
223 return true;
224 }
225 bool set_from_complex_double(ElementType& result, double re, double im) const
226 {
227 mpfr_set_d(&result.re, re, MPFR_RNDN);
228 mpfr_set_d(&result.im, im, MPFR_RNDN);
229 return true;
230 }
231 bool set_from_complex_mpfr(ElementType& result, mpfr_srcptr re, const mpfr_srcptr im) const
232 {
233 mpfr_set(&result.re, re, MPFR_RNDN);
234 mpfr_set(&result.im, im, MPFR_RNDN);
235 return true;
236 }
237
238 // arithmetic
239 void negate(ElementType& result, const ElementType& a) const
240 {
241 mpfr_neg(&result.re, &a.re, MPFR_RNDN);
242 mpfr_neg(&result.im, &a.im, MPFR_RNDN);
243 }
244
245 void invert(ElementType& result, const ElementType& a) const
246 // we silently assume that a != 0. If it is, result is set to a^0, i.e. 1
247 {
248 mpfr_t p, denom;
249 mpfr_init2(p, get_precision());
250 mpfr_init2(denom, get_precision());
251
252 if (mpfr_cmpabs(&a.re, &a.im) >= 0)
253 {
254 // double p = &a.im/&a.re;
255 // double denom = &a.re + p * &a.im;
256 // &result.re = 1.0/denom;
257 // &result.im = - p/denom;
258
259 mpfr_div(p, &a.im, &a.re, MPFR_RNDN);
260 mpfr_mul(denom, p, &a.im, MPFR_RNDN);
261 mpfr_add(denom, denom, &a.re, MPFR_RNDN);
262 mpfr_si_div(&result.re, 1, denom, MPFR_RNDN);
263 mpfr_div(&result.im, p, denom, MPFR_RNDN);
264 mpfr_neg(&result.im, &result.im, MPFR_RNDN);
265 }
266 else
267 {
268 // double p = &a.re/&a.im;
269 // double denom = &a.im + p * &a.re;
270 // &result.re = p/denom;
271 // &result.im = -1.0/denom;
272
273 mpfr_div(p, &a.re, &a.im, MPFR_RNDN);
274 mpfr_mul(denom, p, &a.re, MPFR_RNDN);
275 mpfr_add(denom, denom, &a.im, MPFR_RNDN);
276 mpfr_si_div(&result.im, 1, denom, MPFR_RNDN);
277 mpfr_neg(&result.im, &result.im, MPFR_RNDN);
278 mpfr_div(&result.re, p, denom, MPFR_RNDN);
279 }
280
281 mpfr_clear(p);
282 mpfr_clear(denom);
283 }
284
286 const ElementType& a,
287 const ElementType& b) const
288 {
289 mpfr_add(&result.re, &a.re, &b.re, MPFR_RNDN);
290 mpfr_add(&result.im, &a.im, &b.im, MPFR_RNDN);
291 }
292
294 const RealElementType& a,
295 const ElementType& b) const
296 {
297 mRRR.addMultipleTo(result.re, a, b.re);
298 mRRR.addMultipleTo(result.im, a, b.im);
299 }
300
302 const ElementType& a,
303 const ElementType& b) const
304 {
305 Element ab(*this);
306 mult(ab, a, b);
307 add(result, result, ab);
308 }
309
311 const ElementType& a,
312 const ElementType& b) const
313 {
314 mpfr_sub(&result.re, &a.re, &b.re, MPFR_RNDN);
315 mpfr_sub(&result.im, &a.im, &b.im, MPFR_RNDN);
316 }
317
319 const ElementType& a,
320 const ElementType& b) const
321 {
322 // result -= a*b
323 Element ab(*this);
324 mult(ab, a, b);
325 subtract(result, result, ab);
326 }
327
328 void mult(ElementType& res,
329 const ElementType& a,
330 const RealElementType& b) const
331 {
332 mpfr_t tmp;
333 Element result(*this);
334 mpfr_init2(tmp, get_precision());
335
336 // &result.re = &a.re*&b;
337 mpfr_mul(tmp, &a.re, &b, MPFR_RNDN);
338 mpfr_set(&result.value().re, tmp, MPFR_RNDN);
339
340 // &result.im = &a.im*&b;
341 mpfr_mul(tmp, &a.im, &b, MPFR_RNDN);
342 mpfr_set(&result.value().im, tmp, MPFR_RNDN);
343
344 set(res, result);
345 mpfr_clear(tmp);
346 }
347
348 void mult(ElementType& res, const ElementType& a, const ElementType& b) const
349 {
350 mpfr_t tmp;
351 Element result(*this);
352 mpfr_init2(tmp, get_precision());
353
354 // &result.re = &a.re*&b.re - &a.im*&b.im;
355 mpfr_mul(tmp, &a.re, &b.re, MPFR_RNDN);
356 mpfr_set(&result.value().re, tmp, MPFR_RNDN);
357 mpfr_mul(tmp, &a.im, &b.im, MPFR_RNDN);
358 mpfr_sub(&result.value().re, &result.value().re, tmp, MPFR_RNDN);
359
360 // &result.im = &a.re*&b.im + &a.im*&b.re;
361 mpfr_mul(tmp, &a.re, &b.im, MPFR_RNDN);
362 mpfr_set(&result.value().im, tmp, MPFR_RNDN);
363 mpfr_mul(tmp, &a.im, &b.re, MPFR_RNDN);
364 mpfr_add(&result.value().im, &result.value().im, tmp, MPFR_RNDN);
365
366 set(res, result);
367 mpfr_clear(tmp);
368 }
369
371 const ElementType& a,
372 const RealElementType& b) const
373 {
374 mpfr_t tmp;
375 Element result(*this);
376 mpfr_init2(tmp, get_precision());
377
378 mpfr_div(tmp, &a.re, &b, MPFR_RNDN);
379 mpfr_set(&result.value().re, tmp, MPFR_RNDN);
380
381 mpfr_div(tmp, &a.im, &b, MPFR_RNDN);
382 mpfr_set(&result.value().im, tmp, MPFR_RNDN);
383
384 set(res, result);
385 mpfr_clear(tmp);
386 }
387
389 const ElementType& a,
390 const ElementType& b) const
391 {
392 mpfr_t p, denom;
393 mpfr_init2(p, get_precision());
394 mpfr_init2(denom, get_precision());
395 Element result(*this);
396
397 if (mpfr_cmpabs(&b.re, &b.im) >= 0)
398 {
399 // for v = c + d*i,
400 // p = d/c
401 // c+di = c(1+p*i), so denom is c(1+p^2)
402 // which is c + d*p
403
404 // double p = v.im/v.re;
405 // double denom = v.re + p * v.im;
406 // result.re = (u.re + p*u.im)/denom;
407 // result.im = (u.im - p*u.re)/denom;
408
409 mpfr_div(p, &b.im, &b.re, MPFR_RNDN);
410 mpfr_mul(denom, p, &b.im, MPFR_RNDN);
411 mpfr_add(denom, denom, &b.re, MPFR_RNDN);
412
413 mpfr_mul(&result.value().re, p, &a.im, MPFR_RNDN);
414 mpfr_add(&result.value().re, &result.value().re, &a.re, MPFR_RNDN);
415 mpfr_div(&result.value().re, &result.value().re, denom, MPFR_RNDN);
416
417 mpfr_mul(&result.value().im, p, &a.re, MPFR_RNDN);
418 mpfr_neg(&result.value().im, &result.value().im, MPFR_RNDN);
419 mpfr_add(&result.value().im, &result.value().im, &a.im, MPFR_RNDN);
420 mpfr_div(&result.value().im, &result.value().im, denom, MPFR_RNDN);
421 }
422 else
423 {
424 // double p = v.re/v.im;
425 // double denom = v.im + p * v.re;
426 // result.re = (u.re * p + u.im)/denom;
427 // result.im = (-u.re + p * u.im)/denom;
428
429 mpfr_div(p, &b.re, &b.im, MPFR_RNDN);
430 mpfr_mul(denom, p, &b.re, MPFR_RNDN);
431 mpfr_add(denom, denom, &b.im, MPFR_RNDN);
432
433 mpfr_mul(&result.value().re, p, &a.re, MPFR_RNDN);
434 mpfr_add(&result.value().re, &result.value().re, &a.im, MPFR_RNDN);
435 mpfr_div(&result.value().re, &result.value().re, denom, MPFR_RNDN);
436
437 mpfr_mul(&result.value().im, p, &a.im, MPFR_RNDN);
438 mpfr_sub(&result.value().im, &result.value().im, &a.re, MPFR_RNDN);
439 mpfr_div(&result.value().im, &result.value().im, denom, MPFR_RNDN);
440 }
441 mpfr_clear(p);
442 mpfr_clear(denom);
443 set(res, result);
444 }
445
447 {
449 ARingRRR::Element s(mRRR);
451 mRRR.add(result, result, s);
452 }
453
455 {
457 mpfr_sqrt(&result, &result, MPFR_RNDN); // should we have ARingRRR::sqrt ???
458 }
459
460 void power(ElementType& result, const ElementType& a, int n) const
461 {
462 ElementType curr_pow;
463 init(curr_pow);
465 if (n == 0)
466 {
467 }
468 else if (n < 0)
469 {
470 n = -n;
471 invert(curr_pow, a);
472 }
473 else
474 {
475 set(curr_pow, a);
476 }
477 while (n > 0)
478 {
479 if (n % 2)
480 {
481 mult(result, result, curr_pow);
482 }
483 n = n / 2;
484 mult(curr_pow, curr_pow, curr_pow);
485 }
486 clear(curr_pow);
487 }
488
489 void power_mpz(ElementType& result, const ElementType& a, mpz_srcptr n) const
490 {
491 std::pair<bool, int> n1 = RingZZ::get_si(n);
492 if (n1.first)
493 power(result, a, n1.second);
494 else
495 throw exc::engine_error("exponent too large");
496 }
497
498 void swap(ElementType& a, ElementType& b) const
499 {
500 mpfr_swap(&a.re, &b.re);
501 mpfr_swap(&a.im, &b.im);
502 }
503
504 void elem_text_out(buffer& o,
505 const ElementType& a,
506 bool p_one = true,
507 bool p_plus = false,
508 bool p_parens = false) const;
509
510 void syzygy(const ElementType& a,
511 const ElementType& b,
512 ElementType& x,
513 ElementType& y) const // remove?
514 // returns x,y s.y. x*a + y*b == 0.
515 // if possible, x is set to 1.
516 // no need to consider the case a==0 or b==0.
517 {
518 set_var(x, 0); // set x=1
519 if (!is_zero(b))
520 {
521 set(y, a);
522 negate(y, y);
523 divide(y, y, b);
524 }
525 }
526
527 void random(ElementType& result) const // redo?
528 {
529 randomMpfr(&result.re);
530 randomMpfr(&result.im);
531 }
532
533 void eval(const RingMap* map,
534 ElementType& f,
535 int first_var,
536 ring_elem& result) const
537 {
538 gmp_CC_struct g;
539 (void) first_var;
540 g.re = &f.re;
541 g.im = &f.im;
542 if (!map->get_ring()->from_BigComplex(&g, result))
543 {
544 result = map->get_ring()->from_long(0);
545 ERROR("cannot map CC value to ring type");
546 }
547 }
548
550 {
554 mpfr_init2(result->re, get_precision());
555 mpfr_init2(result->im, get_precision());
556 mpfr_set(result->re, &a.re, MPFR_RNDN);
557 mpfr_set(result->im, &a.im, MPFR_RNDN);
558 return moveTo_gmpCC(result);
559 }
560
562 {
563 mpfr_set(&result.re, &a, MPFR_RNDN);
564 mpfr_set_si(&result.im, 0, MPFR_RNDN);
565 return true;
566 }
567
569 {
570 return a.re;
571 }
573 const ElementType& a) const
574 {
575 return a.im;
576 }
578 {
579 mpfr_set(&c.re, &a, MPFR_RNDN);
580 }
582 {
583 mpfr_set(&c.im, &a, MPFR_RNDN);
584 }
586 {
587 mpfr_set(&result.re, re, MPFR_RNDN);
588 mpfr_set(&result.im, im, MPFR_RNDN);
589 }
590 void set_from_doubles(ElementType& result, double re, double im) const
591 {
592 mRRR.set_from_double(result.re, re);
593 mRRR.set_from_double(result.im, im);
594 }
595
596 void zeroize_tiny(gmp_RR epsilon, ElementType& a) const
597 {
598 mRRR.zeroize_tiny(epsilon, a.re);
599 mRRR.zeroize_tiny(epsilon, a.im);
600 }
601 void increase_norm(gmp_RRmutable norm, const ElementType& a) const
602 {
603 ARingRRR::Element n(mRRR);
604 abs(n, a);
605 if (mpfr_cmp(&n.value(), norm) > 0) mRRR.set(*norm, n);
606 }
607};
608
609}; // end namespace M2
610
611#endif
612
613// Local Variables:
614// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
615// indent-tabs-mode: nil
616// End:
M2::ARingRRR — arbitrary-precision real numbers backed by MPFR.
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.
void addMultipleTo(ElementType &result, const RealElementType &a, const ElementType &b) const
void set_from_long(ElementType &result, long a) const
bool is_zero(const ElementType &f) const
void add(ElementType &result, const ElementType &a, const ElementType &b) const
const ARingRRR mRRR
Definition aring-CCC.hpp:75
bool set_from_BigReal(ElementType &result, gmp_RR a) const
cc_struct elem
Definition aring-CCC.hpp:79
bool set_from_complex_mpfr(ElementType &result, mpfr_srcptr re, const mpfr_srcptr im) const
void abs(ARingRRR::ElementType &result, const ElementType &a) const
gmp_CC toBigComplex(const ElementType &a) const
bool is_unit(const ElementType &f) const
unsigned int computeHashValue(const ElementType &a) const
Definition aring-CCC.hpp:92
ARingCCC(unsigned long precision)
Definition aring-CCC.hpp:84
size_t characteristic() const
Definition aring-CCC.hpp:87
void subtract(ElementType &result, const ElementType &a, const ElementType &b) const
void text_out(buffer &o) const
Definition aring-CCC.cpp:6
void set_from_BigReals(ElementType &result, gmp_RR re, gmp_RR im) const
void random(ElementType &result) const
bool set_from_complex_double(ElementType &result, double re, double im) const
void init(ElementType &result) const
void negate(ElementType &result, const ElementType &a) const
bool is_equal(const ElementType &f, const ElementType &g) const
void increase_norm(gmp_RRmutable norm, const ElementType &a) const
void set_from_mpz(ElementType &result, mpz_srcptr a) const
RealRingType::ElementType RealElementType
Definition aring-CCC.hpp:82
unsigned long get_precision() const
Definition aring-CCC.hpp:88
int compare_elems(const ElementType &f, const ElementType &g) const
void eval(const RingMap *map, ElementType &f, int first_var, ring_elem &result) const
const RealRingType & real_ring() const
Definition aring-CCC.hpp:91
void mult(ElementType &res, const ElementType &a, const RealElementType &b) const
bool set_from_RRR(ElementType &result, const ARingRRR::ElementType &a) const
const ElementType & from_ring_elem_const(const ring_elem &a) const
bool set_from_mpq(ElementType &result, mpq_srcptr a) const
void swap(ElementType &a, ElementType &b) const
static const RingID ringID
Definition aring-CCC.hpp:77
void power_mpz(ElementType &result, const ElementType &a, mpz_srcptr n) const
void mult(ElementType &res, const ElementType &a, const ElementType &b) const
void from_ring_elem(ElementType &result, const ring_elem &a) const
void subtract_multiple(ElementType &result, const ElementType &a, const ElementType &b) const
void power(ElementType &result, const ElementType &a, int n) const
void set_zero(ElementType &result) const
static void clear(ElementType &result)
void elem_text_out(buffer &o, const ElementType &a, bool p_one=true, bool p_plus=false, bool p_parens=false) const
Definition aring-CCC.cpp:7
void init_set(ElementType &result, const ElementType &a) const
void divide(ElementType &res, const ElementType &a, const ElementType &b) const
void set_imaginary_part(ElementType &c, ARingRRR::ElementType &a) const
ARingRRR RealRingType
Definition aring-CCC.hpp:81
bool set_from_double(ElementType &result, double a) const
const ARingRRR::ElementType & realPartReference(const ElementType &a) const
void zeroize_tiny(gmp_RR epsilon, ElementType &a) const
void set_from_doubles(ElementType &result, double re, double im) const
void syzygy(const ElementType &a, const ElementType &b, ElementType &x, ElementType &y) const
void copy(ElementType &result, const ElementType &a) const
const ARingRRR::ElementType & imaginaryPartReference(const ElementType &a) const
bool set_from_BigComplex(ElementType &result, gmp_CC a) const
void set(ElementType &result, const ElementType &a) const
void to_ring_elem(ring_elem &result, const ElementType &a) const
void set_real_part(ElementType &c, ARingRRR::ElementType &a) const
void abs_squared(ARingRRR::ElementType &result, const ElementType &a) const
void addMultipleTo(ElementType &result, const ElementType &a, const ElementType &b) const
void set_var(ElementType &result, int v) const
void divide(ElementType &res, const ElementType &a, const RealElementType &b) const
void invert(ElementType &result, const ElementType &a) const
aring-style adapter for arbitrary-precision real numbers, backed by MPFR.
Definition aring-RRR.hpp:70
A base class for simple ARings.
Definition aring.hpp:147
virtual bool from_BigComplex(gmp_CC z, ring_elem &result) const
Definition ring.cpp:243
virtual ring_elem from_long(long n) const =0
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
static std::pair< bool, int > get_si(mpz_srcptr n)
Definition ZZ.cpp:46
gmp_CC moveTo_gmpCC(gmp_CCmutable _z)
Definition gmp-util.h:166
void mpfr_reallocate_limbs(mpfr_ptr _z)
Definition gmp-util.h:65
Inline helpers that move GMP / MPFR / MPFI limbs from malloc-managed storage into the bdwgc heap.
int p
RingID
Definition aring.hpp:75
@ ring_CCC
Definition aring.hpp:90
void size_t s
Definition m2-mem.cpp:271
const int ERROR
Definition m2-mem.cpp:55
VALGRIND_MAKE_MEM_DEFINED & result(result)
#define getmemstructtype(S)
Definition m2-mem.h:143
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
struct gmp_CCmutable_struct * gmp_CCmutable
Definition m2-types.h:159
Definition aring-CC.cpp:3
volatile int x
#define abs(x)
Definition polyroots.cpp:51
void randomMpfr(mpfr_t result)
Definition random.cpp:240
Engine-boundary C API for the engine's PRNG and rational / real / complex random draws.
cc_struct * cc_ptr
Definition ringelem.hpp:60
ring_elem — the universal value type carried by every Ring* in the engine.
RingMap — engine representation of a ring homomorphism.
__mpfr_struct im
Definition ringelem.hpp:58
__mpfr_struct re
Definition ringelem.hpp:57
cc_srcptr get_cc() const
Definition ringelem.hpp:133