Macaulay2 Engine
Loading...
Searching...
No Matches
complex.c
Go to the documentation of this file.
1// Copyright 2007 Michael E. Stillman
2
3#include "complex.h"
5#include "interface/m2-mem.h"
6#include <stdio.h>
7
9{
12 mpfr_init_set(result->re, a->re, MPFR_RNDN);
13 mpfr_init_set(result->im, a->im, MPFR_RNDN);
14}
15
16void mpfc_init(gmp_CCmutable result, long precision)
17{
20 mpfr_init2(result->re, precision);
21 mpfr_init2(result->im, precision);
22}
24{
25 mpfr_set(result->re, a->re, MPFR_RNDN);
26 mpfr_set(result->im, a->im, MPFR_RNDN);
27}
28
30{
31 mpfr_clear(result->re);
32 mpfr_clear(result->im);
33 freemem(result->re);
34 freemem(result->im);
35 // GC_FREE(result->re);
36 // GC_FREE(result->im);
37}
39{
40 mpfr_set_si(result->re, re, MPFR_RNDN);
41 mpfr_set_si(result->im, 0, MPFR_RNDN);
42}
44{
45 return mpfr_cmp_si(a->re, 0) == 0 && mpfr_cmp_si(a->im, 0) == 0;
46}
47
49{
50 return mpfr_cmp(a->re, b->re) == 0 && mpfr_cmp(a->im, b->im) == 0;
51}
53{
54 mpfr_add(result->re, a->re, b->re, MPFR_RNDN);
55 mpfr_add(result->im, a->im, b->im, MPFR_RNDN);
56}
58{
59 mpfr_neg(result->re, a->re, MPFR_RNDN);
60 mpfr_neg(result->im, a->im, MPFR_RNDN);
61}
63{
64 mpfr_sub(result->re, a->re, b->re, MPFR_RNDN);
65 mpfr_sub(result->im, a->im, b->im, MPFR_RNDN);
66}
68{
69 mpfr_t tmp;
70 mpfr_init2(tmp, mpfr_get_prec(a->re));
71
72 // result->re = a->re*b->re - a->im*b->im;
73 mpfr_mul(tmp, a->re, b->re, MPFR_RNDN);
74 mpfr_set(result->re, tmp, MPFR_RNDN);
75 mpfr_mul(tmp, a->im, b->im, MPFR_RNDN);
76 mpfr_sub(result->re, result->re, tmp, MPFR_RNDN);
77
78 // result->im = a->re*b->im + a->im*b->re;
79 mpfr_mul(tmp, a->re, b->im, MPFR_RNDN);
80 mpfr_set(result->im, tmp, MPFR_RNDN);
81 mpfr_mul(tmp, a->im, b->re, MPFR_RNDN);
82 mpfr_add(result->im, result->im, tmp, MPFR_RNDN);
83
84 mpfr_clear(tmp);
85}
87{
88 mpfr_t p, denom;
89 mpfr_init2(p, mpfr_get_prec(v->re));
90 mpfr_init2(denom, mpfr_get_prec(v->re));
91
92 if (mpfr_cmpabs(v->re, v->im) >= 0)
93 {
94 // double p = v->im/v->re;
95 // double denom = v->re + p * v->im;
96 // result->re = 1.0/denom;
97 // result->im = - p/denom;
98
99 mpfr_div(p, v->im, v->re, MPFR_RNDN);
100 mpfr_mul(denom, p, v->im, MPFR_RNDN);
101 mpfr_add(denom, denom, v->re, MPFR_RNDN);
102 mpfr_si_div(result->re, 1, denom, MPFR_RNDN);
103 mpfr_div(result->im, p, denom, MPFR_RNDN);
104 mpfr_neg(result->im, result->im, MPFR_RNDN);
105 }
106 else
107 {
108 // double p = v->re/v->im;
109 // double denom = v->im + p * v->re;
110 // result->re = p/denom;
111 // result->im = -1.0/denom;
112
113 mpfr_div(p, v->re, v->im, MPFR_RNDN);
114 mpfr_mul(denom, p, v->re, MPFR_RNDN);
115 mpfr_add(denom, denom, v->im, MPFR_RNDN);
116 mpfr_si_div(result->im, 1, denom, MPFR_RNDN);
117 mpfr_neg(result->im, result->im, MPFR_RNDN);
118 mpfr_div(result->re, p, denom, MPFR_RNDN);
119 }
120
121 mpfr_clear(p);
122 mpfr_clear(denom);
123}
125{
126 mpfr_t p, denom;
127 mpfr_init2(p, mpfr_get_prec(u->re));
128 mpfr_init2(denom, mpfr_get_prec(u->re));
129
130 printf("not expected to be used -- we have a bug here\n");
131 abort();
132 if (mpfr_cmpabs(v->re, v->im) >= 0)
133 {
134 // for v = c + d*i,
135 // p = d/c
136 // c+di = c(1+p*i), so denom is c(1+p^2)
137 // which is c + d*p
138
139 // double p = v.im/v.re;
140 // double denom = v.re + p * v.im;
141 // result.re = (u.re + p*u.im)/denom;
142 // result.im = (u.im - p*u.re)/denom;
143
144 mpfr_div(p, v->im, v->re, MPFR_RNDN);
145 mpfr_mul(denom, p, v->im, MPFR_RNDN);
146 mpfr_add(denom, denom, v->re, MPFR_RNDN);
147
148 mpfr_mul(result->re, p, u->im, MPFR_RNDN);
149 mpfr_add(result->re, result->re, u->re, MPFR_RNDN);
150 mpfr_div(result->re, result->re, denom, MPFR_RNDN);
151
152 mpfr_mul(result->im, p, u->re, MPFR_RNDN);
153 mpfr_neg(result->im, result->re, MPFR_RNDN);
154 mpfr_add(result->im, result->re, u->im, MPFR_RNDN);
155 mpfr_div(result->im, result->re, denom, MPFR_RNDN);
156 }
157 else
158 {
159 // double p = v.re/v.im;
160 // double denom = v.im + p * v.re;
161 // result.re = (u.re * p + u.im)/denom;
162 // result.im = (-u.re + p * u.im)/denom;
163
164 mpfr_div(p, v->re, v->im, MPFR_RNDN);
165 mpfr_mul(denom, p, v->re, MPFR_RNDN);
166 mpfr_add(denom, denom, v->im, MPFR_RNDN);
167
168 mpfr_mul(result->re, p, u->re, MPFR_RNDN);
169 mpfr_add(result->re, result->re, u->im, MPFR_RNDN);
170 mpfr_div(result->re, result->re, denom, MPFR_RNDN);
171
172 mpfr_mul(result->im, p, u->im, MPFR_RNDN);
173 mpfr_sub(result->im, result->re, u->re, MPFR_RNDN);
174 mpfr_div(result->im, result->re, denom, MPFR_RNDN);
175 }
176
177 mpfr_clear(p);
178 mpfr_clear(denom);
179#if 0
180 if (fabs(v.re) >= fabs(v.im))
181 {
182 // for u = c + d*i,
183 // p = d/c
184 // c+di = c(1+p*i), so denom is c(1+p^2)
185 // which is c + d*p
186 double p = v.im/v.re;
187 double denom = v.re + p * v.im;
188 result.re = (u.re + p*u.im)/denom;
189 result.im = (u.im - p*u.re)/denom;
190 }
191 else
192 {
193 double p = v.re/v.im;
194 double denom = v.im + p * v.re;
195 result.re = (u.re * p + u.im)/denom;
196 result.im = (-u.re + p * u.im)/denom;
197 }
198#endif
199}
201{
202 // result->re -= a->re*b->re - a->im*b->im;
203 // result->im -= a->re*b->im + a->im*b->re;
204
205 mpfr_t tmp;
206 mpfr_init2(tmp, mpfr_get_prec(a->re));
207
208 mpfr_mul(tmp, a->re, b->re, MPFR_RNDN);
209 mpfr_add(result->re, result->re, tmp, MPFR_RNDN);
210 mpfr_mul(tmp, a->im, b->im, MPFR_RNDN);
211 mpfr_sub(result->re, result->re, tmp, MPFR_RNDN);
212
213 mpfr_mul(tmp, a->re, b->im, MPFR_RNDN);
214 mpfr_add(result->im, result->im, tmp, MPFR_RNDN);
215 mpfr_mul(tmp, a->im, b->re, MPFR_RNDN);
216 mpfr_add(result->im, result->im, tmp, MPFR_RNDN);
217
218 mpfr_clear(tmp);
219}
221{
222 mpfr_set(result->re, a->re, MPFR_RNDN);
223 mpfr_neg(result->im, a->im, MPFR_RNDN);
224}
226{
227 mpfr_t a, b;
228
229 mpfr_init2(a, mpfr_get_prec(c->re));
230 mpfr_init2(b, mpfr_get_prec(c->re));
231 mpfr_abs(a, c->re, MPFR_RNDN);
232 mpfr_abs(b, c->im, MPFR_RNDN);
233 if (mpfr_zero_p(a))
234 mpfr_set(result, b, MPFR_RNDN);
235 else if (mpfr_zero_p(b))
236 mpfr_set(result, a, MPFR_RNDN);
237 else if (mpfr_greater_p(a, b))
238 {
239 // double d = b/a;
240 // But use b for d, as it is not needed later.
241 // result = a * ::sqrt(1.0 + d*d);
242 mpfr_div(b, b, a, MPFR_RNDN);
243 mpfr_sqr(b, b, MPFR_RNDN);
244 mpfr_add_si(b, b, 1, MPFR_RNDN);
245 mpfr_sqrt(b, b, MPFR_RNDN);
246 mpfr_mul(result, a, b, MPFR_RNDN);
247 }
248 else
249 {
250 // double d = a/b;
251 // But use a for d, as it is not needed later.
252 // result = b * ::sqrt(1.0 + d*d);
253 mpfr_div(a, a, b, MPFR_RNDN);
254 mpfr_sqr(a, a, MPFR_RNDN);
255 mpfr_add_si(a, a, 1, MPFR_RNDN);
256 mpfr_sqrt(a, a, MPFR_RNDN);
257 mpfr_mul(result, b, a, MPFR_RNDN);
258 }
259 mpfr_clear(a);
260 mpfr_clear(b);
261
262#if 0
263 static void abs(double &result, elem c)
264 {
265 double a = fabs(c.re);
266 double b = fabs(c.im);
267 if (a == 0.0) result = b;
268 else if (b == 0.0) result = a;
269 else if (a > b)
270 {
271 double d = b/a;
272 result = a * ::sqrt(1.0 + d*d);
273 }
274 else
275 {
276 double d = a/b;
277 result = b * ::sqrt(1.0 + d*d);
278 }
279 }
280#endif
281}
283{
284 // The idea is: write a = a1 + i * a2
285 // first make it numerically more stable by dividing by the larger
286 // answer will be multiplied by larger afterwards, if needed
287 // To take the square root of 1+di, or -1+di
288 // it is enough to solve (if sqrt is e+fi), e^2+f^2 = sqrt(1+d^2),
289 // and e^2-f^2 = 1 (or -1).
290
291 if (mpfr_zero_p(a->re) && mpfr_zero_p(a->im))
292 {
293 mpfr_set_si(result->re, 0, MPFR_RNDN);
294 mpfr_set_si(result->im, 0, MPFR_RNDN);
295 return;
296 }
297
298 mpfr_t b, c, d, d2;
299
300 unsigned long p = mpfr_get_prec(a->re);
301 mpfr_init2(b, p);
302 mpfr_init2(c, p);
303 mpfr_init2(d, p);
304 mpfr_init2(d2, p);
305
306 // b = fabs(a.re);
307 // c = fabs(a.im);
308 mpfr_abs(b, a->re, MPFR_RNDN);
309 mpfr_abs(c, a->im, MPFR_RNDN);
310 if (mpfr_greater_p(b, c))
311 {
312 // d = c/b;
313 // e = ::sqrt(b) * ::sqrt(0.5 * (1.0 + ::sqrt(1.0 + d*d)));
314 // but use c as d, and also as e
315 mpfr_div(d, c, b, MPFR_RNDN);
316 mpfr_sqr(d, d, MPFR_RNDN);
317 mpfr_add_si(d, d, 1, MPFR_RNDN);
318 mpfr_sqrt(d, d, MPFR_RNDN);
319 mpfr_add_si(d, d, 1, MPFR_RNDN);
320 mpfr_div_2ui(d, d, 1, MPFR_RNDN);
321 mpfr_sqrt(d, d, MPFR_RNDN);
322 mpfr_sqrt(b, b, MPFR_RNDN);
323 mpfr_mul(d, d, b, MPFR_RNDN); /* this is now e ! */
324 }
325 else
326 {
327 // d = b/c;
328 // e = ::sqrt(c) * ::sqrt(0.5 * (d + ::sqrt(1.0 + d*d)));
329 mpfr_div(d, b, c, MPFR_RNDN);
330 mpfr_sqr(d2, d, MPFR_RNDN);
331 mpfr_add_si(d2, d2, 1, MPFR_RNDN);
332 mpfr_sqrt(d2, d2, MPFR_RNDN);
333 mpfr_add(d, d2, d, MPFR_RNDN);
334 mpfr_div_2ui(d, d, 1, MPFR_RNDN);
335 mpfr_sqrt(d, d, MPFR_RNDN);
336 mpfr_sqrt(c, c, MPFR_RNDN);
337 mpfr_mul(d, d, c, MPFR_RNDN); /* this is now e ! */
338 }
339 if (mpfr_sgn(a->re) >= 0)
340 {
341 // result.re = e;
342 // result.im = a.im/(2.0 * e);
343 mpfr_set(result->re, d, MPFR_RNDN);
344 mpfr_mul_2ui(d, d, 1, MPFR_RNDN);
345 mpfr_div(result->im, a->im, d, MPFR_RNDN);
346 }
347 else
348 {
349 // result.im = (a.im >= 0.0 ? e : -e);
350 // result.re = a.re/(2.0*result.im);
351 mpfr_set(result->im, d, MPFR_RNDN);
352 if (mpfr_sgn(a->im) < 0) mpfr_neg(result->im, result->im, MPFR_RNDN);
353 mpfr_mul_2ui(d, result->im, 1, MPFR_RNDN);
354 mpfr_div(result->re, a->im, d, MPFR_RNDN);
355 }
356
357 mpfr_clear(b);
358 mpfr_clear(c);
359 mpfr_clear(d);
360 mpfr_clear(d2);
361
362#if 0
363 static void sqrt(elem &result, elem a)
364 {
365 double b,c,d,e;
366 if (a.re == 0.0 && a.im == 0.0)
367 {
368 result.re = 0.0;
369 result.im = 0.0;
370 }
371 else
372 {
373 b = fabs(a.re);
374 c = fabs(a.im);
375 if (b > c)
376 {
377 d = c/b;
378 e = ::sqrt(b) * ::sqrt(0.5 * (1.0 + ::sqrt(1.0 + d*d)));
379 }
380 else
381 {
382 d = b/c;
383 e = ::sqrt(c) * ::sqrt(0.5 * (d + ::sqrt(1.0 + d*d)));
384 }
385 // Now be careful with the signs:
386 if (a.re >= 0.0)
387 {
388 result.re = e;
389 result.im = a.im/(2.0 * e);
390 }
391 else
392 {
393 result.im = (a.im >= 0.0 ? e : -e);
394 result.re = a.re/(2.0*result.im);
395 }
396 }
397 }
398#endif
399}
400
401// Local Variables:
402// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
403// indent-tabs-mode: nil
404// End:
int mpfc_is_equal(gmp_CCmutable a, gmp_CCmutable b)
Definition complex.c:48
void mpfc_conj(gmp_CCmutable result, gmp_CCmutable a)
Definition complex.c:220
void mpfc_add(gmp_CCmutable result, gmp_CCmutable a, gmp_CCmutable b)
Definition complex.c:52
void mpfc_init(gmp_CCmutable result, long precision)
Definition complex.c:16
void mpfc_set_si(gmp_CCmutable result, long re)
Definition complex.c:38
void mpfc_init_set(gmp_CCmutable result, gmp_CCmutable a)
Definition complex.c:8
void mpfc_mul(gmp_CCmutable result, gmp_CCmutable a, gmp_CCmutable b)
Definition complex.c:67
void mpfc_sqrt(gmp_CCmutable result, gmp_CC a)
Definition complex.c:282
void mpfc_neg(gmp_CCmutable result, gmp_CCmutable a)
Definition complex.c:57
void mpfc_abs(gmp_RRmutable result, gmp_CCmutable c)
Definition complex.c:225
void mpfc_invert(gmp_CCmutable result, gmp_CCmutable v)
Definition complex.c:86
void mpfc_div(gmp_CCmutable result, gmp_CCmutable u, gmp_CCmutable v)
Definition complex.c:124
void mpfc_sub(gmp_CCmutable result, gmp_CCmutable a, gmp_CCmutable b)
Definition complex.c:62
int mpfc_is_zero(gmp_CCmutable a)
Definition complex.c:43
void mpfc_sub_mult(gmp_CCmutable result, gmp_CCmutable a, gmp_CCmutable b)
Definition complex.c:200
void mpfc_clear(gmp_CCmutable result)
Definition complex.c:29
void mpfc_set(gmp_CCmutable result, gmp_CCmutable a)
Definition complex.c:23
gmp_CC C primitives: arithmetic on arbitrary-precision complex values (pair of MPFR reals).
int p
void freemem(void *s)
Definition m2-mem.cpp:103
VALGRIND_MAKE_MEM_DEFINED & result(result)
#define getmemstructtype(S)
Definition m2-mem.h:143
Engine-wide GC allocator surface (getmem / getmem_atomic) and debug-allocation trap.
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
Engine-to-interpreter type vocabulary across the C++ / .dd boundary.
#define abs(x)
Definition polyroots.cpp:51