Macaulay2 Engine
Loading...
Searching...
No Matches
aring-CCi.hpp
Go to the documentation of this file.
1// Copyright 2012 Michael E. Stillman
2
3#ifndef _aring_CCi_hpp_
4#define _aring_CCi_hpp_
5
42
43#include <iostream>
44
45#include <mpfi.h>
46#include "interface/random.h"
47#include "interface/gmp-util.h"
48#include "aring.hpp"
49#include "buffer.hpp"
50#include "ringelem.hpp"
51#include "ringmap.hpp"
52#include "aring-RRR.hpp"
53#include "aring-RRi.hpp"
54#include "aring-CCC.hpp"
55
56class CCi;
57class RingMap;
58
59namespace M2 {
73class ARingCCi : public SimpleARing<ARingCCi>
74{
75 // Higher precision real intervals
76
77 public:
78 static const RingID ringID = ring_CCi;
79
82
83 ARingCCi(unsigned long precision) : mPrecision(precision) {}
84 // ring informational
85 size_t characteristic() const { return 0; }
86 unsigned long get_precision() const { return mPrecision; }
87 void text_out(buffer &o) const;
88
89 unsigned int computeHashValue(const elem &a) const
90 {
91 double d1 = mpfr_get_d(&a.re.left, MPFR_RNDN);
92 double d2 = mpfr_get_d(&(a.re.right), MPFR_RNDN);
93 double d3 = mpfr_get_d(&(a.im.left), MPFR_RNDN);
94 double d4 = mpfr_get_d(&(a.im.right), MPFR_RNDN);
95 double d = 12347. * d1 + 865800. * d2 + 72158. * d3 + 86429. * d4;
96 return static_cast<unsigned int>(d);
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 { return mpfr_cmp_si(&(f.im.left), 0) == 0 and mpfr_cmp_si(&(f.im.right), 0) == 0 and
105 mpfr_cmp_si(&(f.re.left), 0) == 0 and
106 mpfr_cmp_si(&(f.re.right), 0) == 0; }
107 bool is_equal(const ElementType &f, const ElementType &g) const
108 { return
109 mpfr_cmp(&(f.re.left), &(g.re.left)) == 0 and mpfr_cmp(&(f.re.right), &(g.re.right)) == 0 and
110 mpfr_cmp(&(f.im.left), &(g.im.left)) == 0 and mpfr_cmp(&(f.im.right), &(g.im.right)) == 0;
111 }
112
113 int compare_elems(const ElementType &f, const ElementType &g) const
114 {
115 int cmp = mpfi_cmp(&f.re, &g.re);
116 if (cmp < 0) return -1;
117 if (cmp > 0) return 1;
118 cmp = mpfi_cmp(&f.im, &g.im);
119 if (cmp < 0) return -1;
120 if (cmp > 0) return 1;
121 return 0;
122 }
123
124 bool is_empty(const ElementType &f) const { return mpfi_is_empty(&f.re)>0 || mpfi_is_empty(&f.im)>0; }
125 bool is_member(const ARingCCC::ElementType &a, const ElementType &f) const { return mpfi_cmp_fr(&f.re,&a.re) == 0 && mpfi_cmp_fr(&f.im,&a.im) == 0; }
126 bool is_member(const ARingRRi::ElementType &a, const ElementType &f) const { return mpfi_cmp(&f.re,&a) == 0 && mpfi_cmp_si(&f.im,0); }
127 bool is_member(const ARingRRR::ElementType &a, const ElementType &f) const { return mpfi_cmp_fr(&f.re,&a) == 0 && mpfi_cmp_si(&f.im,0); }
128 bool is_member(mpq_srcptr a, const ElementType &f) const { return mpfi_cmp_q(&f.re,a) == 0 && mpfi_cmp_si(&f.im,0); }
129 bool is_member(mpz_srcptr a, const ElementType &f) const { return mpfi_cmp_z(&f.re,a) == 0 && mpfi_cmp_si(&f.im,0); }
130 bool is_member(long a, const ElementType &f) const { return mpfi_cmp_si(&f.re,a) == 0 && mpfi_cmp_si(&f.im,0); }
131 bool is_member(double a, const ElementType &f) const { return mpfi_cmp_d(&f.re,a) == 0 && mpfi_cmp_si(&f.im,0); }
132
133 bool is_subset(const ElementType &g, const ElementType &f) const { return mpfi_cmp_fr(&f.re,&(g.re.left)) == 0 and mpfi_cmp_fr(&f.re,&(g.re.right)) == 0 and mpfi_cmp_fr(&f.im,&(g.im.left)) == 0 and mpfi_cmp_fr(&f.im,&(g.im.right)) == 0; }
134
136 // to/from ringelem ////////
138 // These simply repackage the element as either a ringelem or an
139 // 'ElementType'.
140 // No reinitialization is done.
141 // Do not take the same element and store it as two different ring_elem's!!
143 {
145 mpfi_init2(&res->re,mPrecision);
146 mpfi_init2(&res->im,mPrecision);
147 mpfi_set(&res->re,&a.re);
148 mpfi_set(&res->im,&a.im);
151 result = ring_elem(res);
152 }
153
155 {
156 mpfi_set(&result.re, &a.get_cci()->re);
157 mpfi_set(&result.im, &a.get_cci()->im);
158 }
159
161 {
162 return *a.get_cci();
163 }
164 // 'init', 'init_set' functions
165
166 void init(ElementType &result) const {
167 mpfi_init2(&result.re, mPrecision);
168 mpfi_init2(&result.im, mPrecision);
169 }
170 void init_set(ElementType &result, const ElementType &a) const
171 {
172 init(result);
173 mpfi_set(&result.re, &a.re);
174 mpfi_set(&result.im, &a.im);
175 }
176
177 void set(ElementType &result, const ElementType &a) const
178 {
179 mpfi_set(&result.re, &a.re);
180 mpfi_set(&result.im, &a.im);
181 }
182
183 void set(ElementType &result, const gmp_CCi a) const
184 {
185 mpfi_set(&result.re, a->re);
186 mpfi_set(&result.im, a->im);
187 }
188
190 {
191 mpfi_set_si(&result.re, 0);
192 mpfi_set_si(&result.im, 0);
193 }
194
195 static void clear(ElementType &result) {
196 mpfi_clear(&result.re);
197 mpfi_clear(&result.im);
198 }
199 void copy(ElementType &result, const ElementType &a) const
200 {
201 mpfi_set(&result.re, &a.re);
202 mpfi_set(&result.im, &a.im);
203 }
204
205 void set_from_long(ElementType &result, long a) const
206 {
207 mpfi_set_si(&result.re, a);
208 mpfi_set_si(&result.im, 0);
209 }
210
211 void set_var(ElementType &result, int v) const
212 {
213 mpfi_set_si(&result.re, v);
214 mpfi_set_si(&result.im, 0);
215 }
216
217 void set_from_mpz(ElementType &result, mpz_srcptr a) const
218 {
219 mpfi_set_z(&result.re, a);
220 mpfi_set_si(&result.im, 0);
221 }
222
223 bool set_from_mpq(ElementType &result, mpq_srcptr a) const
224 {
225 mpfi_set_q(&result.re, a);
226 mpfi_set_si(&result.im, 0);
227 return true;
228 }
229
230 bool set_from_double(ElementType &result, double a) const
231 {
232 mpfi_set_d(&result.re, a);
233 mpfi_set_si(&result.im, 0);
234 return true;
235 }
236
238 {
239 mpfi_set_fr(&result.re, a);
240 mpfi_set_si(&result.im, 0);
241 return true;
242 }
243
245 {
246 mpfi_set(&result.re, a);
247 mpfi_set_si(&result.im, 0);
248 return true;
249 }
250
252 {
253 mpfi_set_fr(&result.re, a->re);
254 mpfi_set_fr(&result.im, a->im);
255 return true;
256 }
257
259 {
260 mpfi_set_fr(&result.re, &a->re);
261 mpfi_set_fr(&result.im, &a->im);
262 return true;
263 }
264
265 bool set_from_complex_double(ElementType &result, double re, double im) const
266 {
267 mpfi_set_d(&result.re, re);
268 mpfi_set_d(&result.im, im);
269 return true;
270 }
271
273 {
274 mpfi_set(&result.re, a->re);
275 mpfi_set(&result.im, a->im);
276 return true;
277 }
278
280 {
281 mpfi_set(&result.re, &a.re);
282 mpfi_set(&result.im, &a.im);
283 return true;
284 }
285
287 {
288 mpfi_set_fr(&result.re, re);
289 mpfi_set_fr(&result.im, im);
290 }
291 void set_from_doubles(ElementType& result, double re, double im) const
292 {
293 mpfi_set_d(&result.re, re);
294 mpfi_set_d(&result.im, im);
295 }
296
298 {
299 return a.re;
300 }
302 const ElementType& a) const
303 {
304 return a.im;
305 }
307 {
308 mpfi_set(&c.re, &a);
309 }
311 {
312 mpfi_set(&c.im, &a);
313 }
314
315 // arithmetic
316 void negate(ElementType &result, const ElementType &a) const
317 {
318 mpfi_mul_si(&result.re, &a.re, -1);
319 mpfi_mul_si(&result.im, &a.im, -1);
320 }
321
322 void invert(ElementType &result, const ElementType &a) const
323 // we silently assume that a != 0. If it is, result is set to a^0, i.e. 1
324 {
325 mpfi_t norm, temp;
326 mpfi_init2(norm,get_precision());
327 mpfi_init2(temp,get_precision());
328 mpfi_set(norm,&a.re);
329 mpfi_mul(norm,norm,norm);
330 mpfi_set(temp,&a.im);
331 mpfi_mul(temp,temp,temp);
332 mpfi_add(norm,norm,temp);
333 mpfi_set(&result.re,&a.re);
334 mpfi_mul_si(&result.im,&a.im,-1);
335 mpfi_div(&result.re,&result.re,norm);
336 mpfi_div(&result.im,&result.im,norm);
337 }
338
340 const ElementType &a,
341 const ElementType &b) const
342 {
343 mpfi_add(&result.re, &a.re, &b.re);
344 mpfi_add(&result.im, &a.im, &b.im);
345 }
346
347
349 const ElementType &a,
350 const ElementType &b) const
351 {
352 ElementType ab;
353 init(ab);
354 mult(ab,a,b);
355 add(result,result,ab);
356 }
357
358
360 const ElementType &a,
361 const ElementType &b) const
362 {
363 mpfi_sub(&result.re, &a.re, &b.re);
364 mpfi_sub(&result.im, &a.im, &b.im);
365 }
366
368 const ElementType &a,
369 const ElementType &b) const
370 {
371 // result -= a*b
372 ElementType ab;
373 init(ab);
374 mult(ab, a, b);
375 subtract(result, result, ab);
376 clear(ab);
377 }
378
380 const ElementType &a,
381 const ElementType &b) const
382 {
383 mpfi_t temp, retemp, imtemp;
384 mpfi_init2(temp,get_precision());
385 mpfi_init2(retemp,get_precision());
386 mpfi_init2(imtemp,get_precision());
387 mpfi_mul(retemp,&a.re,&b.re);
388 mpfi_mul(temp,&a.im,&b.im);
389 mpfi_sub(retemp,retemp,temp);
390 mpfi_mul(temp,&a.re,&b.im);
391 mpfi_mul(imtemp,&a.im,&b.re);
392 mpfi_add(&result.im,imtemp,temp);
393 mpfi_set(&result.re,retemp);
394 }
395
397 const ElementType &a,
398 const ElementType &b) const
399 {
400 // result -= a*b
401 ElementType b_inv;
402 init(b_inv);
403 invert(b_inv,b);
404 mult(result,a,b_inv);
405 clear(b_inv);
406 }
407
408 void power(ElementType &result, const ElementType &a, int n) const
409 {
410 if (n >= 2)
411 {
412 ElementType b;
413 init(b);
414 if (n%2 == 0)
415 {
416 power(b,a,n/2);
417 mult(result,b,b);
418 }
419 else
420 {
421 power(b,a,n-1);
422 mult(result,a,b);
423 }
424 }
425 else if (n == 1)
426 {
427 mpfi_set(&result.re,&a.re);
428 mpfi_set(&result.im,&a.im);
429 }
430 else if (n == 0)
431 {
432 mpfi_set_si(&result.re,1);
433 mpfi_set_si(&result.im,0);
434 }
435 else if (n<0)
436 throw 20;
437 }
438
439 /* Not entirely sure how to deal with this one. */
440 void power_mpz(ElementType &result, const ElementType &a, mpz_srcptr n) const
441 {
442 if (mpz_cmp_si(n,2)>=0)
443 {
444 mpz_t r;
445 mpz_init(r);
446 mpz_fdiv_r_ui(r,n,2);
447
448 ElementType b;
449 init(b);
450
451 mpz_t m;
452 mpz_init(m);
453
454 if (mpz_cmp_si(r,0) == 0)
455 {
456 mpz_cdiv_q_ui(m,n,2);
457
458 power_mpz(b,a,m);
459 mult(result,b,b);
460 }
461 else
462 {
463 mpz_sub_ui(m,n,1);
464
465 power_mpz(b,a,m);
466 mult(result,a,b);
467 }
468 mpz_clear(r);
469 mpz_clear(m);
470 }
471 else if (mpz_cmp_si(n,1)==0)
472 {
473 mpfi_set(&result.re,&a.re);
474 mpfi_set(&result.im,&a.im);
475 }
476 else if (mpz_cmp_si(n,0)==0)
477 {
478 mpfi_set_si(&result.re,1);
479 mpfi_set_si(&result.im,0);
480 }
481 else if (mpz_cmp_si(n,0)<0)
482 throw 20;
483 }
484
485 void swap(ElementType &a, ElementType &b) const {
486 mpfi_swap(&a.re, &b.re);
487 mpfi_swap(&a.im, &b.im);
488 }
489
490 void midpoint(ARingCCC::ElementType &a, const ElementType &b) const {
491 mpfi_mid(&a.re,&b.re);
492 mpfi_mid(&a.im,&b.im);
493 }
494
495 void diameter(ARingRRi::ElementType &a, const ElementType &b) const {
496 mpfi_t temp;
497 mpfi_set(&a,&b.re);
498 mpfi_sqr(&a,&a);
499 mpfi_set(temp,&b.im);
500 mpfi_sqr(temp,temp);
501 mpfi_add(&a,&a,temp);
502 mpfi_sqrt(&a,&a);
503 }
504
505 void elem_text_out(buffer &o,
506 const ElementType &a,
507 bool p_one,
508 bool p_plus,
509 bool p_parens) const;
510
511 void syzygy(const ElementType &a,
512 const ElementType &b,
513 ElementType &x,
514 ElementType &y) const // remove?
515 // returns x,y s.y. x*a + y*b == 0.
516 // if possible, x is set to 1.
517 // no need to consider the case a==0 or b==0.
518 {
519 set_var(x, 0); // set x=1
520 if (!is_zero(b))
521 {
522 set(y, a);
523 negate(y, y);
524 divide(y, y, b);
525 }
526 }
527
528 /* rewrite this (in rand.cpp or just copy over?) */
529 void random(ElementType &result) const // redo?
530 {
531 mpfr_t val;
532 mpfr_init2(val, mPrecision);
533 randomMpfr(val);
534 mpfi_set_fr(&result.re,val);
535
536 randomMpfr(val);
537 mpfi_put_fr(&result.re,val);
538
539 randomMpfr(val);
540 mpfi_set_fr(&result.im,val);
541
542 randomMpfr(val);
543 mpfi_put_fr(&result.im,val);
544 mpfr_clear(val);
545 }
546
547 /* Needs to be redone. */
548 void eval(const RingMap *map,
549 const ElementType &f,
550 int first_var,
551 ring_elem &result) const
552 {
553 gmp_CCi_struct g;
554 g.re = &f.re;
555 g.im = &f.im;
556 if (!map->get_ring()->from_ComplexInterval(&g, result))
557 {
558 result = map->get_ring()->from_long(0);
559 ERROR("cannot coerce RRi value to ring type");
560 }
561 }
562
563/* Not ready */
564 void zeroize_tiny(gmp_RR epsilon, ElementType &a) const
565 {
566 throw 20;
567 //if (mpfr_cmpabs(&a, epsilon) < 0) set_zero(a);
568 }
569 /* Not ready */
570 void increase_norm(gmp_RRmutable norm, const ElementType &a) const
571 {
572 throw 20;
573 /* if (mpfr_cmpabs(&a, norm) > 0)
574 {
575 set(*norm, a);
576 abs(*norm, *norm);
577 }*/
578 }
579
580 void abs(ElementType &result, const ElementType &a) const
581 {
582 mpfi_t temp;
583 mpfi_set(&result.re,&a.re);
584 mpfi_sqr(&result.re,&result.re);
585 mpfi_set(temp,&a.im);
586 mpfi_sqr(temp,temp);
587 mpfi_add(&result.re,&result.re,temp);
588 mpfi_sqrt(&result.re,&result.re);
589 mpfi_set_si(&result.im,0);
590 }
591
593 {
594 abs(result,a);
596 }
597
599 {
603 mpfr_init2(result->re, get_precision());
604 mpfr_init2(result->im, get_precision());
605 mpfi_get_fr(result->re, &a.re);
606 mpfi_get_fr(result->im, &a.im);
607 return moveTo_gmpCC(result);
608 }
609
610 private:
611 unsigned long mPrecision;
612};
613
614}; // end namespace M2
615
616#endif
617
618// Local Variables:
619// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
620// indent-tabs-mode: nil
621// End:
M2::ARingCCC — arbitrary-precision complex numbers (pair of MPFR floats).
M2::ARingRRR — arbitrary-precision real numbers backed by MPFR.
M2::ARingRRi — certified real intervals [a, b] with MPFR endpoints, MPFI arithmetic.
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 abs(ElementType &result, const ElementType &a) const
static const RingID ringID
Definition aring-CCi.hpp:78
void zeroize_tiny(gmp_RR epsilon, ElementType &a) const
unsigned long get_precision() const
Definition aring-CCi.hpp:86
void set_imaginary_part(ElementType &c, ARingRRi::ElementType &a) const
void invert(ElementType &result, const ElementType &a) const
void power_mpz(ElementType &result, const ElementType &a, mpz_srcptr n) const
void syzygy(const ElementType &a, const ElementType &b, ElementType &x, ElementType &y) const
void add(ElementType &result, const ElementType &a, const ElementType &b) const
void set_from_mpz(ElementType &result, mpz_srcptr a) const
void eval(const RingMap *map, const ElementType &f, int first_var, ring_elem &result) const
void set_from_BigReals(ElementType &result, gmp_RR re, gmp_RR im) const
void set_var(ElementType &result, int v) const
void init_set(ElementType &result, const ElementType &a) const
bool is_member(mpq_srcptr a, const ElementType &f) const
void elem_text_out(buffer &o, const ElementType &a, bool p_one, bool p_plus, bool p_parens) const
Definition aring-CCi.cpp:6
bool is_member(double a, const ElementType &f) const
void to_ring_elem(ring_elem &result, const ElementType &a) const
void subtract(ElementType &result, const ElementType &a, const ElementType &b) const
void set(ElementType &result, const ElementType &a) const
void midpoint(ARingCCC::ElementType &a, const ElementType &b) const
bool set_from_BigComplex(ElementType &result, gmp_CC a) const
unsigned long mPrecision
bool is_member(const ARingRRR::ElementType &a, const ElementType &f) const
void set_from_long(ElementType &result, long a) const
void set(ElementType &result, const gmp_CCi a) const
bool set_from_BigComplex(ElementType &result, const cc_struct *a) const
void negate(ElementType &result, const ElementType &a) const
void addMultipleTo(ElementType &result, const ElementType &a, const ElementType &b) const
bool set_from_complex_double(ElementType &result, double re, double im) const
void random(ElementType &result) const
void mult(ElementType &result, const ElementType &a, const ElementType &b) const
void copy(ElementType &result, const ElementType &a) const
bool is_equal(const ElementType &f, const ElementType &g) const
void subtract_multiple(ElementType &result, const ElementType &a, const ElementType &b) const
void swap(ElementType &a, ElementType &b) const
bool is_empty(const ElementType &f) const
int compare_elems(const ElementType &f, const ElementType &g) const
bool is_subset(const ElementType &g, const ElementType &f) const
const ARingRRi::ElementType & realPartReference(const ElementType &a) const
unsigned int computeHashValue(const elem &a) const
Definition aring-CCi.hpp:89
static void clear(ElementType &result)
size_t characteristic() const
Definition aring-CCi.hpp:85
void from_ring_elem(ElementType &result, const ring_elem &a) const
void diameter(ARingRRi::ElementType &a, const ElementType &b) const
void increase_norm(gmp_RRmutable norm, const ElementType &a) const
bool set_from_ComplexInterval(ElementType &result, ElementType &a) const
void set_from_doubles(ElementType &result, double re, double im) const
void set_real_part(ElementType &c, ARingRRi::ElementType &a) const
bool set_from_double(ElementType &result, double a) const
bool is_member(const ARingCCC::ElementType &a, const ElementType &f) const
bool is_member(long a, const ElementType &f) const
void abs_squared(ElementType &result, const ElementType &a) const
void divide(ElementType &result, const ElementType &a, const ElementType &b) const
gmp_CC toBigComplex(const ElementType &a) const
bool is_member(mpz_srcptr a, const ElementType &f) const
bool set_from_BigReal(ElementType &result, gmp_RR a) const
bool set_from_mpq(ElementType &result, mpq_srcptr a) const
ARingCCi(unsigned long precision)
Definition aring-CCi.hpp:83
void init(ElementType &result) const
bool is_unit(const ElementType &f) const
bool is_zero(const ElementType &f) const
bool set_from_Interval(ElementType &result, gmp_RRi a) const
const ARingRRi::ElementType & imaginaryPartReference(const ElementType &a) const
void set_zero(ElementType &result) const
bool set_from_ComplexInterval(ElementType &result, gmp_CCi a) const
void power(ElementType &result, const ElementType &a, int n) const
cci_struct elem
Definition aring-CCi.hpp:80
const ElementType & from_ring_elem_const(const ring_elem &a) const
bool is_member(const ARingRRi::ElementType &a, const ElementType &f) const
void text_out(buffer &o) const
Definition aring-CCi.cpp:5
A base class for simple ARings.
Definition aring.hpp:147
virtual bool from_ComplexInterval(gmp_CCi z, ring_elem &result) const
Definition ring.cpp:264
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
void mpfi_reallocate_limbs(mpfi_ptr _z)
Definition gmp-util.h:79
gmp_CC moveTo_gmpCC(gmp_CCmutable _z)
Definition gmp-util.h:166
Inline helpers that move GMP / MPFR / MPFI limbs from malloc-managed storage into the bdwgc heap.
RingID
Definition aring.hpp:75
@ ring_CCi
Definition aring.hpp:92
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
mpfi_srcptr gmp_RRi
Definition m2-types.h:153
struct gmp_CCi_struct * gmp_CCi
Definition m2-types.h:162
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.
cci_struct * cci_ptr
Definition ringelem.hpp:76
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
__mpfi_struct im
Definition ringelem.hpp:74
__mpfi_struct re
Definition ringelem.hpp:73
cci_srcptr get_cci() const
Definition ringelem.hpp:134