number 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/bounds.c +116 -0
- data/ext/compare.c +706 -0
- data/ext/complex.c +674 -0
- data/ext/decompose.c +231 -0
- data/ext/extconf.rb +7 -0
- data/ext/interval.c +394 -0
- data/ext/number.c +1651 -0
- data/ext/number.h +92 -0
- data/ext/real.c +877 -0
- data/ext/real_bounds.c +57 -0
- data/ext/round.c +46 -0
- metadata +69 -0
data/ext/complex.c
ADDED
@@ -0,0 +1,674 @@
|
|
1
|
+
#include "number.h"
|
2
|
+
|
3
|
+
/*
|
4
|
+
* Sets the value of num to the complex value represented by re and im.
|
5
|
+
*/
|
6
|
+
void mpc_init_set_r_r (mpc_t num, Real* re, Real* im)
|
7
|
+
{
|
8
|
+
char buf[10000];
|
9
|
+
char tmp_re_buf[10000];
|
10
|
+
char tmp_im_buf[10000];
|
11
|
+
char re_buf[10000];
|
12
|
+
char im_buf[10000];
|
13
|
+
|
14
|
+
if (REAL(re))
|
15
|
+
{
|
16
|
+
gmp_sprintf(tmp_re_buf, "%+Zd", re->num);
|
17
|
+
sprintf(re_buf, "%c0.%se%ld", *tmp_re_buf, tmp_re_buf + 1, re->exp);
|
18
|
+
}
|
19
|
+
else
|
20
|
+
{
|
21
|
+
sprintf(re_buf, "%s", NaN(re) ? "@nan@" : POS_INF(re) ? "@inf@" : "-@inf@");
|
22
|
+
}
|
23
|
+
|
24
|
+
if (REAL(im))
|
25
|
+
{
|
26
|
+
gmp_sprintf(tmp_im_buf, "%+Zd", im->num);
|
27
|
+
sprintf(im_buf, "%c0.%se%ld", *tmp_im_buf, tmp_im_buf + 1, im->exp);
|
28
|
+
}
|
29
|
+
else
|
30
|
+
{
|
31
|
+
sprintf(im_buf, "%s", NaN(im) ? "@nan@" : POS_INF(im) ? "@inf@" : "-@inf@");
|
32
|
+
}
|
33
|
+
|
34
|
+
sprintf(buf, "(%s %s)", re_buf, im_buf);
|
35
|
+
|
36
|
+
mpc_init2(num, PREC);
|
37
|
+
mpc_set_str(num, buf, 10, MPC_RNDNN);
|
38
|
+
}
|
39
|
+
|
40
|
+
/*
|
41
|
+
* Sets the value of num to the floating point value represented by real.
|
42
|
+
*/
|
43
|
+
void mpfr_init_set_r (mpfr_t num, Real* real)
|
44
|
+
{
|
45
|
+
char sign;
|
46
|
+
char buf[10000];
|
47
|
+
char real_buf[10000];
|
48
|
+
|
49
|
+
if (REAL(real))
|
50
|
+
{
|
51
|
+
gmp_sprintf(real_buf, "%+Zd", real->num);
|
52
|
+
sprintf(buf, "%c0.%se%ld", *real_buf, real_buf + 1, real->exp);
|
53
|
+
}
|
54
|
+
else
|
55
|
+
{
|
56
|
+
sprintf(buf, "%s", NaN(real) ? "@nan@" : POS_INF(real) ? "@inf@" : "-@inf@");
|
57
|
+
}
|
58
|
+
|
59
|
+
mpfr_init2(num, PREC);
|
60
|
+
mpfr_set_str(num, buf, 10, MPFR_RNDN);
|
61
|
+
}
|
62
|
+
|
63
|
+
/*
|
64
|
+
* Frees the memory block pointed to by complex.
|
65
|
+
*/
|
66
|
+
void complex_free (Complex* complex)
|
67
|
+
{
|
68
|
+
if (complex)
|
69
|
+
{
|
70
|
+
if (complex->re)
|
71
|
+
{
|
72
|
+
interval_free(complex->re);
|
73
|
+
}
|
74
|
+
|
75
|
+
if (complex->im)
|
76
|
+
{
|
77
|
+
interval_free(complex->im);
|
78
|
+
}
|
79
|
+
|
80
|
+
free(complex);
|
81
|
+
complex = NULL;
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
/*
|
86
|
+
* Returns the maximum size of the string representation of complex as a long.
|
87
|
+
*/
|
88
|
+
long complex_strlen (Complex* complex)
|
89
|
+
{
|
90
|
+
return interval_strlen(complex->re) + interval_strlen(complex->im) + 10;
|
91
|
+
}
|
92
|
+
|
93
|
+
/*
|
94
|
+
* Puts a string representation of complex into the string pointed to by buf.
|
95
|
+
*
|
96
|
+
* complex: ({1:1 < 2:1 < 3:1},{0:1 ≤ 0:1 ≤ 0:1}) => str: "{1:1 < 2:1 < 3:1}, {0:1 ≤ 0:1 ≤ 0:1}i"
|
97
|
+
*/
|
98
|
+
void complex_print (char* buf, Complex* complex)
|
99
|
+
{
|
100
|
+
char rbuf[interval_strlen(complex->re)];
|
101
|
+
char ibuf[interval_strlen(complex->im)];
|
102
|
+
|
103
|
+
if (interval_zero_p(complex->im))
|
104
|
+
{
|
105
|
+
interval_print(rbuf, complex->re);
|
106
|
+
sprintf(buf, "%s", rbuf);
|
107
|
+
}
|
108
|
+
else
|
109
|
+
{
|
110
|
+
interval_print(rbuf, complex->re);
|
111
|
+
interval_print(ibuf, complex->im);
|
112
|
+
|
113
|
+
sprintf(buf, "%s+%si", rbuf, ibuf);
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
117
|
+
/*
|
118
|
+
* Returns a pointer to a newly allocated Complex with the given value. The
|
119
|
+
* given intervals will be referenced by the new complex and must be freed only
|
120
|
+
* when this complex is freed.
|
121
|
+
*
|
122
|
+
* re: {1:1 < 2:1 < 3:1}, im: {0:1 ≤ 0:1 ≤ 0:1} => complex: {1:1 < 2:1 < 3:1}, {0:1 ≤ 0:1 ≤ 0:1}
|
123
|
+
*/
|
124
|
+
Complex* complex_new (Interval* re, Interval* im)
|
125
|
+
{
|
126
|
+
Complex* complex;
|
127
|
+
complex = (Complex*)malloc(sizeof(Complex));
|
128
|
+
|
129
|
+
if (complex == NULL)
|
130
|
+
{
|
131
|
+
return NULL;
|
132
|
+
}
|
133
|
+
|
134
|
+
memset(complex, 0, sizeof(Complex));
|
135
|
+
complex->re = (Interval*)re;
|
136
|
+
complex->im = (Interval*)im;
|
137
|
+
|
138
|
+
return complex;
|
139
|
+
}
|
140
|
+
|
141
|
+
/*
|
142
|
+
* Returns a pointer to a newly allocated Complex with the given real as its
|
143
|
+
* real part and 0 as its imaginary part. The given real is duplicated before
|
144
|
+
* being stored, and therefore must be freed separately.
|
145
|
+
*/
|
146
|
+
Complex* complex_from_real (Real* real)
|
147
|
+
{
|
148
|
+
return complex_new((Interval*)interval_from_real(real), (Interval*)interval_zero());
|
149
|
+
}
|
150
|
+
|
151
|
+
/*
|
152
|
+
* Returns a pointer to a newly allocated Complex with the integer represented
|
153
|
+
* by str as its real part.
|
154
|
+
*/
|
155
|
+
Complex* complex_from_int_str (char* buf)
|
156
|
+
{
|
157
|
+
Real* real;
|
158
|
+
Complex* result;
|
159
|
+
|
160
|
+
real = (Real*)real_from_str(buf, strlen(buf) - (*buf == '-'));
|
161
|
+
result = (Complex*)complex_from_real(real);
|
162
|
+
|
163
|
+
real_free(real);
|
164
|
+
|
165
|
+
return result;
|
166
|
+
}
|
167
|
+
|
168
|
+
/*
|
169
|
+
* Returns a pointer to a newly allocated Complex with the float represented by
|
170
|
+
* str as its real part.
|
171
|
+
*/
|
172
|
+
Complex* complex_from_float_str (char* buf)
|
173
|
+
{
|
174
|
+
mpfr_t num;
|
175
|
+
Real* real;
|
176
|
+
Complex* result;
|
177
|
+
|
178
|
+
mpfr_init2(num, PREC);
|
179
|
+
mpfr_set_str(num, buf, 10, MPFR_RNDN);
|
180
|
+
|
181
|
+
real = (Real*)real_from_mpfr(num, ROUND_NEAREST);
|
182
|
+
result = (Complex*)complex_from_real(real);
|
183
|
+
|
184
|
+
mpfr_clear(num);
|
185
|
+
real_free(real);
|
186
|
+
|
187
|
+
return result;
|
188
|
+
}
|
189
|
+
|
190
|
+
/*
|
191
|
+
* Returns a pointer to a newly allocated Complex containing a NaN value.
|
192
|
+
*/
|
193
|
+
Complex* complex_nan ()
|
194
|
+
{
|
195
|
+
return complex_new((Interval*)interval_nan(), (Interval*)interval_zero());
|
196
|
+
}
|
197
|
+
|
198
|
+
/*
|
199
|
+
* Returns a pointer to a newly allocated Complex containing only +∞.
|
200
|
+
*/
|
201
|
+
Complex* complex_pos_inf ()
|
202
|
+
{
|
203
|
+
return complex_new((Interval*)interval_pos_inf(), (Interval*)interval_zero());
|
204
|
+
}
|
205
|
+
|
206
|
+
/*
|
207
|
+
* Returns a pointer to a newly allocated Complex containing only -∞.
|
208
|
+
*/
|
209
|
+
Complex* complex_neg_inf ()
|
210
|
+
{
|
211
|
+
return complex_new((Interval*)interval_neg_inf(), (Interval*)interval_zero());
|
212
|
+
}
|
213
|
+
|
214
|
+
/*
|
215
|
+
* Returns a pointer to a newly allocated Complex containing only 0.
|
216
|
+
*/
|
217
|
+
Complex* complex_zero ()
|
218
|
+
{
|
219
|
+
return complex_new((Interval*)interval_zero(), (Interval*)interval_zero());
|
220
|
+
}
|
221
|
+
|
222
|
+
/*
|
223
|
+
* Returns a pointer to a newly allocated Complex containing only 1.
|
224
|
+
*/
|
225
|
+
Complex* complex_one ()
|
226
|
+
{
|
227
|
+
return complex_new((Interval*)interval_one(), (Interval*)interval_zero());
|
228
|
+
}
|
229
|
+
|
230
|
+
/*
|
231
|
+
* Returns a pointer to a newly allocated Complex containing π, accurate to
|
232
|
+
* digs digits.
|
233
|
+
*/
|
234
|
+
Complex* complex_pi ()
|
235
|
+
{
|
236
|
+
return complex_new((Interval*)interval_pi(), (Interval*)interval_zero());
|
237
|
+
}
|
238
|
+
|
239
|
+
/*
|
240
|
+
* Returns a pointer to a newly allocated Complex containing e, accurate to
|
241
|
+
* digs digits.
|
242
|
+
*/
|
243
|
+
Complex* complex_e ()
|
244
|
+
{
|
245
|
+
return complex_new((Interval*)interval_e(), (Interval*)interval_zero());
|
246
|
+
}
|
247
|
+
|
248
|
+
/*
|
249
|
+
* Returns a pointer to a newly allocated Complex containing only i.
|
250
|
+
*/
|
251
|
+
Complex* complex_i ()
|
252
|
+
{
|
253
|
+
return complex_new((Interval*)interval_zero(), (Interval*)interval_one());
|
254
|
+
}
|
255
|
+
|
256
|
+
/*
|
257
|
+
* Returns a pointer to a newly allocated Complex with the same value as the
|
258
|
+
* given complex.
|
259
|
+
*/
|
260
|
+
Complex* complex_dup (Complex* complex)
|
261
|
+
{
|
262
|
+
return complex_new((Interval*)interval_dup(complex->re), (Interval*)interval_dup(complex->im));
|
263
|
+
}
|
264
|
+
|
265
|
+
/*
|
266
|
+
* Returns a pointer to a newly allocated Complex containing a + b.
|
267
|
+
*/
|
268
|
+
Complex* complex_add (Complex* a, Complex* b)
|
269
|
+
{
|
270
|
+
Interval* re;
|
271
|
+
Interval* im;
|
272
|
+
|
273
|
+
re = (Interval*)interval_add(a->re, b->re);
|
274
|
+
im = (Interval*)interval_add(a->im, b->im);
|
275
|
+
|
276
|
+
return complex_new(re, im);
|
277
|
+
}
|
278
|
+
|
279
|
+
/*
|
280
|
+
* Returns a pointer to a newly allocated Complex containing a - b.
|
281
|
+
*/
|
282
|
+
Complex* complex_subtract (Complex* a, Complex* b)
|
283
|
+
{
|
284
|
+
Interval* re;
|
285
|
+
Interval* im;
|
286
|
+
|
287
|
+
re = (Interval*)interval_subtract(a->re, b->re);
|
288
|
+
im = (Interval*)interval_subtract(a->im, b->im);
|
289
|
+
|
290
|
+
return complex_new(re, im);
|
291
|
+
}
|
292
|
+
|
293
|
+
/*
|
294
|
+
* Returns a pointer to a newly allocated Complex containing a * b.
|
295
|
+
*/
|
296
|
+
Complex* complex_multiply (Complex* a, Complex* b)
|
297
|
+
{
|
298
|
+
Interval* re_re;
|
299
|
+
Interval* re_im;
|
300
|
+
Interval* im_re;
|
301
|
+
Interval* im_im;
|
302
|
+
Interval* re;
|
303
|
+
Interval* im;
|
304
|
+
|
305
|
+
re_re = (Interval*)interval_multiply(a->re, b->re);
|
306
|
+
re_im = (Interval*)interval_multiply(a->re, b->im);
|
307
|
+
im_re = (Interval*)interval_multiply(a->im, b->re);
|
308
|
+
im_im = (Interval*)interval_multiply(a->im, b->im);
|
309
|
+
|
310
|
+
re = (Interval*)interval_subtract(re_re, im_im);
|
311
|
+
im = (Interval*)interval_add(re_im, im_re);
|
312
|
+
|
313
|
+
interval_free(re_re);
|
314
|
+
interval_free(re_im);
|
315
|
+
interval_free(im_re);
|
316
|
+
interval_free(im_im);
|
317
|
+
|
318
|
+
return (Complex*)complex_new(re, im);
|
319
|
+
}
|
320
|
+
|
321
|
+
/*
|
322
|
+
* Returns a pointer to a newly allocated Complex containing a / b.
|
323
|
+
*/
|
324
|
+
Complex* complex_divide (Complex* a, Complex* b)
|
325
|
+
{
|
326
|
+
mpc_t num_numerator;
|
327
|
+
mpc_t num_denominator;
|
328
|
+
mpc_t num_quotient;
|
329
|
+
mpfr_t num_re;
|
330
|
+
mpfr_t num_im;
|
331
|
+
Interval* denominator_re;
|
332
|
+
Interval* denominator_im;
|
333
|
+
Interval* denominator;
|
334
|
+
Interval* numerator_re;
|
335
|
+
Interval* numerator_im;
|
336
|
+
Interval* re_re;
|
337
|
+
Interval* re_im;
|
338
|
+
Interval* im_re;
|
339
|
+
Interval* im_im;
|
340
|
+
Interval* re;
|
341
|
+
Interval* im;
|
342
|
+
|
343
|
+
denominator_re = (Interval*)interval_multiply(b->re, b->re);
|
344
|
+
denominator_im = (Interval*)interval_multiply(b->im, b->im);
|
345
|
+
denominator = (Interval*)interval_add(denominator_re, denominator_im);
|
346
|
+
|
347
|
+
if (real_zero_p(denominator->l) || real_zero_p(denominator->u) || interval_span_zero_p(denominator))
|
348
|
+
{
|
349
|
+
mpfr_init2(num_re, PREC);
|
350
|
+
mpfr_init2(num_im, PREC);
|
351
|
+
|
352
|
+
mpc_init2(num_quotient, PREC);
|
353
|
+
mpc_init_set_r_r(num_numerator, a->re->n, a->im->n);
|
354
|
+
mpc_init_set_r_r(num_denominator, b->re->n, b->im->n);
|
355
|
+
|
356
|
+
mpc_div(num_quotient, num_numerator, num_denominator, MPC_RNDNN);
|
357
|
+
|
358
|
+
mpc_real(num_re, num_quotient, MPFR_RNDN);
|
359
|
+
mpc_imag(num_im, num_quotient, MPFR_RNDN);
|
360
|
+
|
361
|
+
re = (Interval*)interval_new((Real*)real_neg_inf(), true, (Real*)real_from_mpfr(num_re, ROUND_NEAREST), true, (Real*)real_pos_inf());
|
362
|
+
im = (Interval*)interval_new((Real*)real_neg_inf(), true, (Real*)real_from_mpfr(num_im, ROUND_NEAREST), true, (Real*)real_pos_inf());
|
363
|
+
|
364
|
+
mpc_clear(num_numerator);
|
365
|
+
mpc_clear(num_denominator);
|
366
|
+
mpc_clear(num_quotient);
|
367
|
+
mpfr_clear(num_re);
|
368
|
+
mpfr_clear(num_im);
|
369
|
+
}
|
370
|
+
else
|
371
|
+
{
|
372
|
+
re_re = (Interval*)interval_multiply(a->re, b->re);
|
373
|
+
re_im = (Interval*)interval_multiply(a->re, b->im);
|
374
|
+
im_re = (Interval*)interval_multiply(a->im, b->re);
|
375
|
+
im_im = (Interval*)interval_multiply(a->im, b->im);
|
376
|
+
|
377
|
+
numerator_re = (Interval*)interval_add(re_re, im_im);
|
378
|
+
numerator_im = (Interval*)interval_subtract(im_re, re_im);
|
379
|
+
|
380
|
+
re = (Interval*)interval_divide(numerator_re, denominator);
|
381
|
+
im = (Interval*)interval_divide(numerator_im, denominator);
|
382
|
+
|
383
|
+
interval_free(re_re);
|
384
|
+
interval_free(re_im);
|
385
|
+
interval_free(im_re);
|
386
|
+
interval_free(im_im);
|
387
|
+
interval_free(numerator_re);
|
388
|
+
interval_free(numerator_im);
|
389
|
+
}
|
390
|
+
|
391
|
+
interval_free(denominator_re);
|
392
|
+
interval_free(denominator_im);
|
393
|
+
interval_free(denominator);
|
394
|
+
|
395
|
+
return (Complex*)complex_new(re, im);
|
396
|
+
}
|
397
|
+
|
398
|
+
/*
|
399
|
+
* Returns a pointer to a newly allocated Complex containing a % b.
|
400
|
+
*/
|
401
|
+
Complex* complex_modulo (Complex* a, Complex* b)
|
402
|
+
{
|
403
|
+
Interval* re;
|
404
|
+
Interval* im;
|
405
|
+
|
406
|
+
re = (Interval*)interval_zero();
|
407
|
+
im = (Interval*)interval_zero();
|
408
|
+
|
409
|
+
return (Complex*)complex_new(re, im);
|
410
|
+
}
|
411
|
+
|
412
|
+
/*
|
413
|
+
* Returns a pointer to a newly allocated Complex containing the absolute value
|
414
|
+
* of complex.
|
415
|
+
*/
|
416
|
+
Complex* complex_abs (Complex* complex)
|
417
|
+
{
|
418
|
+
mpfr_t num_n_re;
|
419
|
+
mpfr_t num_ll_re;
|
420
|
+
mpfr_t num_lu_re;
|
421
|
+
mpfr_t num_ul_re;
|
422
|
+
mpfr_t num_uu_re;
|
423
|
+
mpfr_t num_re_abs;
|
424
|
+
mpfr_t num_im_abs;
|
425
|
+
mpc_t num_n;
|
426
|
+
mpc_t num_ll;
|
427
|
+
mpc_t num_lu;
|
428
|
+
mpc_t num_ul;
|
429
|
+
mpc_t num_uu;
|
430
|
+
Real* re_l_abs;
|
431
|
+
Real* re_u_abs;
|
432
|
+
Real* im_l_abs;
|
433
|
+
Real* im_u_abs;
|
434
|
+
|
435
|
+
Bounds* bounds;
|
436
|
+
Interval* re;
|
437
|
+
|
438
|
+
mpfr_init2(num_n_re, PREC);
|
439
|
+
mpfr_init2(num_ll_re, PREC);
|
440
|
+
mpfr_init2(num_lu_re, PREC);
|
441
|
+
mpfr_init2(num_ul_re, PREC);
|
442
|
+
mpfr_init2(num_uu_re, PREC);
|
443
|
+
|
444
|
+
mpc_init_set_r_r(num_n, complex->re->n, complex->im->n);
|
445
|
+
mpc_abs(num_n_re, num_n, MPC_RNDNN);
|
446
|
+
|
447
|
+
mpc_init_set_r_r(num_ll, complex->re->l, complex->im->l);
|
448
|
+
mpc_init_set_r_r(num_lu, complex->re->l, complex->im->u);
|
449
|
+
mpc_init_set_r_r(num_ul, complex->re->u, complex->im->l);
|
450
|
+
mpc_init_set_r_r(num_uu, complex->re->u, complex->im->u);
|
451
|
+
|
452
|
+
mpc_abs(num_ll_re, num_ll, MPC_RNDDD);
|
453
|
+
mpc_abs(num_lu_re, num_lu, MPC_RNDDU);
|
454
|
+
mpc_abs(num_ul_re, num_ul, MPC_RNDUD);
|
455
|
+
mpc_abs(num_uu_re, num_uu, MPC_RNDUU);
|
456
|
+
|
457
|
+
mpc_clear(num_n);
|
458
|
+
mpc_clear(num_ll);
|
459
|
+
mpc_clear(num_lu);
|
460
|
+
mpc_clear(num_ul);
|
461
|
+
mpc_clear(num_uu);
|
462
|
+
|
463
|
+
bounds = (Bounds*)bounds_new();
|
464
|
+
bounds_update_re(bounds, num_ll_re, complex->re->L);
|
465
|
+
bounds_update_re(bounds, num_lu_re, complex->re->L);
|
466
|
+
bounds_update_re(bounds, num_ul_re, complex->re->R);
|
467
|
+
bounds_update_re(bounds, num_uu_re, complex->re->R);
|
468
|
+
|
469
|
+
if (interval_span_zero_p(complex->im))
|
470
|
+
{
|
471
|
+
re_l_abs = (Real*)real_abs(complex->re->l);
|
472
|
+
re_u_abs = (Real*)real_abs(complex->re->u);
|
473
|
+
|
474
|
+
mpfr_init_set_r(num_re_abs, real_lt_p(re_l_abs, re_u_abs) ? re_l_abs : re_u_abs);
|
475
|
+
bounds_update_re(bounds, num_re_abs, true);
|
476
|
+
|
477
|
+
real_free(re_l_abs);
|
478
|
+
real_free(re_u_abs);
|
479
|
+
|
480
|
+
mpfr_clear(num_re_abs);
|
481
|
+
}
|
482
|
+
|
483
|
+
if (interval_span_zero_p(complex->re))
|
484
|
+
{
|
485
|
+
im_l_abs = (Real*)real_abs(complex->im->l);
|
486
|
+
im_u_abs = (Real*)real_abs(complex->im->u);
|
487
|
+
|
488
|
+
mpfr_init_set_r(num_im_abs, real_lt_p(im_l_abs, im_u_abs) ? im_l_abs : im_u_abs);
|
489
|
+
bounds_update_re(bounds, num_im_abs, true);
|
490
|
+
|
491
|
+
real_free(im_l_abs);
|
492
|
+
real_free(im_u_abs);
|
493
|
+
|
494
|
+
mpfr_clear(num_im_abs);
|
495
|
+
}
|
496
|
+
|
497
|
+
if (interval_span_zero_p(complex->re) && interval_span_zero_p(complex->im))
|
498
|
+
{
|
499
|
+
mpfr_set_zero(num_ll_re, 1);
|
500
|
+
bounds_update_re(bounds, num_ll_re, true);
|
501
|
+
}
|
502
|
+
|
503
|
+
re = (Interval*)interval_new(real_from_mpfr(bounds->re_min, ROUND_DOWN), bounds->re_min_closed, real_from_mpfr(num_n_re, ROUND_NEAREST), bounds->re_max_closed, real_from_mpfr(bounds->re_max, ROUND_UP1));
|
504
|
+
|
505
|
+
bounds_free(bounds);
|
506
|
+
|
507
|
+
mpfr_clear(num_n_re);
|
508
|
+
mpfr_clear(num_ll_re);
|
509
|
+
mpfr_clear(num_lu_re);
|
510
|
+
mpfr_clear(num_ul_re);
|
511
|
+
mpfr_clear(num_uu_re);
|
512
|
+
|
513
|
+
return complex_new(re, (Interval*)interval_zero());
|
514
|
+
}
|
515
|
+
|
516
|
+
/*
|
517
|
+
* Returns a pointer to a newly allocated Complex containing the area of the
|
518
|
+
* region in the complex plane enclosed by complex.
|
519
|
+
*/
|
520
|
+
Complex* complex_area (Complex* complex)
|
521
|
+
{
|
522
|
+
Real* re_width;
|
523
|
+
Real* im_width;
|
524
|
+
Real* area;
|
525
|
+
Complex* result;
|
526
|
+
|
527
|
+
re_width = (Real*)real_subtract(complex->re->u, complex->re->l);
|
528
|
+
im_width = (Real*)real_subtract(complex->im->u, complex->im->l);
|
529
|
+
area = (Real*)real_multiply(re_width, im_width);
|
530
|
+
result = (Complex*)complex_from_real(area);
|
531
|
+
|
532
|
+
real_free(re_width);
|
533
|
+
real_free(im_width);
|
534
|
+
real_free(area);
|
535
|
+
|
536
|
+
return result;
|
537
|
+
}
|
538
|
+
|
539
|
+
/*
|
540
|
+
* Returns a pointer to a newly allocated Complex containing the length of the
|
541
|
+
* diagonal of the region in the complex plane enclosed by complex.
|
542
|
+
*/
|
543
|
+
Complex* complex_diagonal (Complex* complex)
|
544
|
+
{
|
545
|
+
mpfr_t num_diag;
|
546
|
+
Real* re_width;
|
547
|
+
Real* im_width;
|
548
|
+
Real* re_width2;
|
549
|
+
Real* im_width2;
|
550
|
+
Real* diag2;
|
551
|
+
Interval* re;
|
552
|
+
Complex* result;
|
553
|
+
|
554
|
+
re_width = (Real*)real_subtract(complex->re->u, complex->re->l);
|
555
|
+
im_width = (Real*)real_subtract(complex->im->u, complex->im->l);
|
556
|
+
|
557
|
+
re_width2 = (Real*)real_multiply(re_width, re_width);
|
558
|
+
im_width2 = (Real*)real_multiply(im_width, im_width);
|
559
|
+
|
560
|
+
diag2 = (Real*)real_add(re_width2, im_width2);
|
561
|
+
|
562
|
+
mpfr_init_set_r(num_diag, diag2);
|
563
|
+
mpfr_sqrt(num_diag, num_diag, MPFR_RNDN);
|
564
|
+
|
565
|
+
re = (Interval*)interval_new((Real*)real_from_mpfr(num_diag, ROUND_DOWN), true, (Real*)real_from_mpfr(num_diag, ROUND_NEAREST), true, (Real*)real_from_mpfr(num_diag, ROUND_UP1));
|
566
|
+
|
567
|
+
real_free(re_width);
|
568
|
+
real_free(im_width);
|
569
|
+
real_free(re_width2);
|
570
|
+
real_free(im_width2);
|
571
|
+
real_free(diag2);
|
572
|
+
|
573
|
+
mpfr_clear(num_diag);
|
574
|
+
|
575
|
+
return (Complex*)complex_new(re, (Interval*)interval_zero());
|
576
|
+
}
|
577
|
+
|
578
|
+
/*
|
579
|
+
* Returns a pointer to a newly allocated Complex containing the conjugate of
|
580
|
+
* complex.
|
581
|
+
*/
|
582
|
+
Complex* complex_conjugate (Complex* complex)
|
583
|
+
{
|
584
|
+
return complex_new((Interval*)interval_dup(complex->re), (Interval*)interval_negate(complex->im));
|
585
|
+
}
|
586
|
+
|
587
|
+
/*
|
588
|
+
* Returns a pointer to a newly allocated Complex containing -complex.
|
589
|
+
*/
|
590
|
+
Complex* complex_negate (Complex* complex)
|
591
|
+
{
|
592
|
+
return complex_new((Interval*)interval_negate(complex->re), (Interval*)interval_negate(complex->im));
|
593
|
+
}
|
594
|
+
|
595
|
+
/*
|
596
|
+
* Returns a pointer to a newly allocated Complex containing the reflection of
|
597
|
+
* complex over the line re == im.
|
598
|
+
*/
|
599
|
+
Complex* complex_reflect (Complex* complex)
|
600
|
+
{
|
601
|
+
return complex_new((Interval*)interval_dup(complex->im), (Interval*)interval_dup(complex->re));
|
602
|
+
}
|
603
|
+
|
604
|
+
/*
|
605
|
+
* Returns a pointer to a newly allocated Complex containing √complex.
|
606
|
+
*/
|
607
|
+
Complex* complex_sqrt (Complex* complex)
|
608
|
+
{
|
609
|
+
mpfr_t num_n_re;
|
610
|
+
mpfr_t num_n_im;
|
611
|
+
mpc_t num_n;
|
612
|
+
mpc_t num_ll;
|
613
|
+
mpc_t num_lu;
|
614
|
+
mpc_t num_ul;
|
615
|
+
mpc_t num_uu;
|
616
|
+
mpc_t num_re_sqrt;
|
617
|
+
Real* zero;
|
618
|
+
Bounds* bounds;
|
619
|
+
Interval* re;
|
620
|
+
Interval* im;
|
621
|
+
|
622
|
+
mpfr_init2(num_n_re, PREC);
|
623
|
+
mpfr_init2(num_n_im, PREC);
|
624
|
+
|
625
|
+
mpc_init_set_r_r(num_n, complex->re->n, complex->im->n);
|
626
|
+
mpc_sqrt(num_n, num_n, MPC_RNDNN);
|
627
|
+
mpc_real(num_n_re, num_n, MPFR_RNDN);
|
628
|
+
mpc_imag(num_n_im, num_n, MPFR_RNDN);
|
629
|
+
|
630
|
+
mpc_init_set_r_r(num_ll, complex->re->l, complex->im->l);
|
631
|
+
mpc_init_set_r_r(num_lu, complex->re->l, complex->im->u);
|
632
|
+
mpc_init_set_r_r(num_ul, complex->re->u, complex->im->l);
|
633
|
+
mpc_init_set_r_r(num_uu, complex->re->u, complex->im->u);
|
634
|
+
|
635
|
+
mpc_sqrt(num_ll, num_ll, MPC_RNDDD);
|
636
|
+
mpc_sqrt(num_lu, num_lu, MPC_RNDDU);
|
637
|
+
mpc_sqrt(num_ul, num_ul, MPC_RNDUD);
|
638
|
+
mpc_sqrt(num_uu, num_uu, MPC_RNDUU);
|
639
|
+
|
640
|
+
bounds = (Bounds*)bounds_new();
|
641
|
+
bounds_update(bounds, num_ll, complex->re->L, complex->im->L);
|
642
|
+
bounds_update(bounds, num_lu, complex->re->L, complex->im->R);
|
643
|
+
bounds_update(bounds, num_ul, complex->re->R, complex->im->L);
|
644
|
+
bounds_update(bounds, num_uu, complex->re->R, complex->im->R);
|
645
|
+
|
646
|
+
if (interval_span_zero_p(complex->im))
|
647
|
+
{
|
648
|
+
zero = (Real*)real_zero();
|
649
|
+
|
650
|
+
mpc_init_set_r_r(num_re_sqrt, complex->re->l, zero);
|
651
|
+
mpc_sqrt(num_re_sqrt, num_re_sqrt, MPC_RNDDD);
|
652
|
+
|
653
|
+
bounds_update(bounds, num_re_sqrt, complex->re->L);
|
654
|
+
|
655
|
+
real_free(zero);
|
656
|
+
mpc_clear(num_re_sqrt);
|
657
|
+
}
|
658
|
+
|
659
|
+
re = (Interval*)interval_new(real_from_mpfr(bounds->re_min, ROUND_DOWN), bounds->re_min_closed, real_from_mpfr(num_n_re, ROUND_NEAREST), bounds->re_max_closed, real_from_mpfr(bounds->re_max, ROUND_UP1));
|
660
|
+
im = (Interval*)interval_new(real_from_mpfr(bounds->im_min, ROUND_DOWN), bounds->im_min_closed, real_from_mpfr(num_n_im, ROUND_NEAREST), bounds->im_max_closed, real_from_mpfr(bounds->im_max, ROUND_UP1));
|
661
|
+
|
662
|
+
bounds_free(bounds);
|
663
|
+
|
664
|
+
mpfr_clear(num_n_re);
|
665
|
+
mpfr_clear(num_n_im);
|
666
|
+
|
667
|
+
mpc_clear(num_n);
|
668
|
+
mpc_clear(num_ll);
|
669
|
+
mpc_clear(num_lu);
|
670
|
+
mpc_clear(num_ul);
|
671
|
+
mpc_clear(num_uu);
|
672
|
+
|
673
|
+
return complex_new(re, im);
|
674
|
+
}
|