number 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/ext/decompose.c ADDED
@@ -0,0 +1,231 @@
1
+ #include "number.h"
2
+
3
+ Complex* complex_im (Complex* complex)
4
+ {
5
+ return (Complex*)complex_new((Interval*)interval_dup(complex->im), (Interval*)interval_zero());
6
+ }
7
+
8
+ Complex* complex_im_l (Complex* complex)
9
+ {
10
+ return (Complex*)complex_from_real(complex->im->l);
11
+ }
12
+
13
+ Complex* complex_im_n (Complex* complex)
14
+ {
15
+ return (Complex*)complex_from_real(complex->im->n);
16
+ }
17
+
18
+ Complex* complex_im_u (Complex* complex)
19
+ {
20
+ return (Complex*)complex_from_real(complex->im->u);
21
+ }
22
+
23
+ Complex* complex_im_magnitude (Complex* complex)
24
+ {
25
+ Real* l_abs;
26
+ Real* u_abs;
27
+ Complex* result;
28
+
29
+ l_abs = (Real*)real_abs(complex->im->l);
30
+ u_abs = (Real*)real_abs(complex->im->u);
31
+
32
+ result = (Complex*)complex_from_real(real_gt_p(l_abs, u_abs) ? l_abs : u_abs);
33
+
34
+ real_free(l_abs);
35
+ real_free(u_abs);
36
+
37
+ return result;
38
+ }
39
+
40
+ Complex* complex_im_mignitude (Complex* complex)
41
+ {
42
+ Real* l_abs;
43
+ Real* u_abs;
44
+ Real* zero;
45
+ Complex* result;
46
+
47
+ l_abs = (Real*)real_abs(complex->im->l);
48
+ u_abs = (Real*)real_abs(complex->im->u);
49
+ zero = (Real*)real_zero();
50
+
51
+ result = (Complex*)complex_from_real(interval_span_zero_p(complex->im) ? zero : (real_lt_p(l_abs, u_abs) ? l_abs : u_abs));
52
+
53
+ real_free(l_abs);
54
+ real_free(u_abs);
55
+ real_free(zero);
56
+
57
+ return result;
58
+ }
59
+
60
+ Complex* complex_im_width (Complex* complex)
61
+ {
62
+ Real* width;
63
+ Complex* result;
64
+
65
+ width = (Real*)real_subtract(complex->im->u, complex->im->l);
66
+ result = (Complex*)complex_from_real(width);
67
+
68
+ real_free(width);
69
+
70
+ return result;
71
+ }
72
+
73
+ Complex* complex_re (Complex* complex)
74
+ {
75
+ return (Complex*)complex_new((Interval*)interval_dup(complex->re), (Interval*)interval_zero());
76
+ }
77
+
78
+ Complex* complex_re_l (Complex* complex)
79
+ {
80
+ return (Complex*)complex_from_real(complex->re->l);
81
+ }
82
+
83
+ Complex* complex_re_n (Complex* complex)
84
+ {
85
+ return (Complex*)complex_from_real(complex->re->n);
86
+ }
87
+
88
+ Complex* complex_re_u (Complex* complex)
89
+ {
90
+ return (Complex*)complex_from_real(complex->re->u);
91
+ }
92
+
93
+ Complex* complex_re_magnitude (Complex* complex)
94
+ {
95
+ Real* l_abs;
96
+ Real* u_abs;
97
+ Complex* result;
98
+
99
+ l_abs = (Real*)real_abs(complex->re->l);
100
+ u_abs = (Real*)real_abs(complex->re->u);
101
+
102
+ result = (Complex*)complex_from_real(real_gt_p(l_abs, u_abs) ? l_abs : u_abs);
103
+
104
+ real_free(l_abs);
105
+ real_free(u_abs);
106
+
107
+ return result;
108
+ }
109
+
110
+ Complex* complex_re_mignitude (Complex* complex)
111
+ {
112
+ Real* l_abs;
113
+ Real* u_abs;
114
+ Real* zero;
115
+ Complex* result;
116
+
117
+ l_abs = (Real*)real_abs(complex->re->l);
118
+ u_abs = (Real*)real_abs(complex->re->u);
119
+ zero = (Real*)real_zero();
120
+
121
+ result = (Complex*)complex_from_real(interval_span_zero_p(complex->re) ? zero : (real_lt_p(l_abs, u_abs) ? l_abs : u_abs));
122
+
123
+ real_free(l_abs);
124
+ real_free(u_abs);
125
+ real_free(zero);
126
+
127
+ return result;
128
+ }
129
+
130
+ Complex* complex_re_width (Complex* complex)
131
+ {
132
+ Real* width;
133
+ Complex* result;
134
+
135
+ width = (Real*)real_subtract(complex->re->u, complex->re->l);
136
+ result = (Complex*)complex_from_real(width);
137
+
138
+ real_free(width);
139
+
140
+ return result;
141
+ }
142
+
143
+ Complex* complex_ll (Complex* complex)
144
+ {
145
+ return (Complex*)complex_new((Interval*)interval_from_real(complex->re->l), (Interval*)interval_from_real(complex->im->l));
146
+ }
147
+
148
+ Complex* complex_lu (Complex* complex)
149
+ {
150
+ return (Complex*)complex_new((Interval*)interval_from_real(complex->re->l), (Interval*)interval_from_real(complex->im->u));
151
+ }
152
+
153
+ Complex* complex_n (Complex* complex)
154
+ {
155
+ return (Complex*)complex_new((Interval*)interval_from_real(complex->re->n), (Interval*)interval_from_real(complex->im->n));
156
+ }
157
+
158
+ Complex* complex_ul (Complex* complex)
159
+ {
160
+ return (Complex*)complex_new((Interval*)interval_from_real(complex->re->u), (Interval*)interval_from_real(complex->im->l));
161
+ }
162
+
163
+ Complex* complex_uu (Complex* complex)
164
+ {
165
+ return (Complex*)complex_new((Interval*)interval_from_real(complex->re->u), (Interval*)interval_from_real(complex->im->u));
166
+ }
167
+
168
+ Complex* complex_magnitude (Complex* complex)
169
+ {
170
+ Real* re_l_abs;
171
+ Real* re_u_abs;
172
+ Real* im_l_abs;
173
+ Real* im_u_abs;
174
+ Complex* result;
175
+
176
+ re_l_abs = (Real*)real_abs(complex->re->l);
177
+ re_u_abs = (Real*)real_abs(complex->re->u);
178
+ im_l_abs = (Real*)real_abs(complex->im->l);
179
+ im_u_abs = (Real*)real_abs(complex->im->u);
180
+
181
+ result = (Complex*)complex_new((Interval*)interval_from_real(real_gt_p(re_l_abs, re_u_abs) ? re_l_abs : re_u_abs), (Interval*)interval_from_real(real_gt_p(im_l_abs, im_u_abs) ? im_l_abs : im_u_abs));
182
+
183
+ real_free(re_l_abs);
184
+ real_free(re_u_abs);
185
+ real_free(im_l_abs);
186
+ real_free(im_u_abs);
187
+
188
+ return result;
189
+ }
190
+
191
+ Complex* complex_mignitude (Complex* complex)
192
+ {
193
+ Real* re_l_abs;
194
+ Real* re_u_abs;
195
+ Real* im_l_abs;
196
+ Real* im_u_abs;
197
+ Real* zero;
198
+ Complex* result;
199
+
200
+ re_l_abs = (Real*)real_abs(complex->re->l);
201
+ re_u_abs = (Real*)real_abs(complex->re->u);
202
+ im_l_abs = (Real*)real_abs(complex->im->l);
203
+ im_u_abs = (Real*)real_abs(complex->im->u);
204
+
205
+ zero = (Real*)real_zero();
206
+ result = (Complex*)complex_new((Interval*)interval_from_real(interval_span_zero_p(complex->re) ? zero : (real_lt_p(re_l_abs, re_u_abs) ? re_l_abs : re_u_abs)), (Interval*)interval_from_real(interval_span_zero_p(complex->im) ? zero : (real_lt_p(im_l_abs, im_u_abs) ? im_l_abs : im_u_abs)));
207
+
208
+ real_free(re_l_abs);
209
+ real_free(re_u_abs);
210
+ real_free(im_l_abs);
211
+ real_free(im_u_abs);
212
+ real_free(zero);
213
+
214
+ return result;
215
+ }
216
+
217
+ Complex* complex_width (Complex* complex)
218
+ {
219
+ Real* re_width;
220
+ Real* im_width;
221
+ Complex* result;
222
+
223
+ re_width = (Real*)real_subtract(complex->re->u, complex->re->l);
224
+ im_width = (Real*)real_subtract(complex->im->u, complex->im->l);
225
+ result = (Complex*)complex_new((Interval*)interval_from_real(re_width), (Interval*)interval_from_real(im_width));
226
+
227
+ real_free(re_width);
228
+ real_free(im_width);
229
+
230
+ return result;
231
+ }
data/ext/extconf.rb ADDED
@@ -0,0 +1,7 @@
1
+ #encoding: UTF-8
2
+ require 'mkmf'
3
+
4
+ have_library('gmp')
5
+ have_library('mpfr')
6
+ have_library('mpc')
7
+ create_makefile('number')
data/ext/interval.c ADDED
@@ -0,0 +1,394 @@
1
+ #include "number.h"
2
+
3
+ /*
4
+ * Frees the memory block pointed to by interval.
5
+ */
6
+ void interval_free (Interval* interval)
7
+ {
8
+ if (interval)
9
+ {
10
+ if (interval->n)
11
+ {
12
+ real_free(interval->n);
13
+ }
14
+
15
+ if (interval->l)
16
+ {
17
+ real_free(interval->l);
18
+ }
19
+
20
+ if (interval->u)
21
+ {
22
+ real_free(interval->u);
23
+ }
24
+
25
+ free(interval);
26
+ interval = NULL;
27
+ }
28
+ }
29
+
30
+ /*
31
+ * Returns the maximum size of the string representation of interval as a long.
32
+ */
33
+ long interval_strlen (Interval* interval)
34
+ {
35
+ return real_strlen(interval->l) + real_strlen(interval->n) + real_strlen(interval->u) + 10;
36
+ }
37
+
38
+ /*
39
+ * Puts a string representation of interval into the string pointed to by buf.
40
+ *
41
+ * interval: {1:1 < 2:1 < 3:1} => str: "{1:1 < 2:1 < 3:1}"
42
+ * interval: {0:1 ≤ 0:1 ≤ 0:1} => str: "{0:1 ≤ 0:1 ≤ 0:1}"
43
+ */
44
+ void interval_print(char* buf, Interval* interval)
45
+ {
46
+ char n_str[real_strlen(interval->n)];
47
+ char l_str[real_strlen(interval->l)];
48
+ char u_str[real_strlen(interval->u)];
49
+
50
+ if (interval_degenerate_p(interval))
51
+ {
52
+ real_print(n_str, interval->n);
53
+ sprintf(buf, "%s", n_str);
54
+ }
55
+ else
56
+ {
57
+ real_print(n_str, interval->n);
58
+ real_print(l_str, interval->l);
59
+ real_print(u_str, interval->u);
60
+
61
+ sprintf(buf, "[%s %s (%s) %s %s]", l_str, interval->L ? "≤" : "<", n_str, interval->R ? "≤" : "<", u_str);
62
+ }
63
+ }
64
+
65
+ /*
66
+ * Returns 1 if interval contains real, 0 otherwise.
67
+ */
68
+ int interval_span_p (Interval* interval, Real* real)
69
+ {
70
+ return !(real_gt_p(interval->l, real) || real_lt_p(interval->u, real) || (real_eq_p(interval->l, real) && !interval->L) || (real_eq_p(interval->u, real) && !interval->R));
71
+ }
72
+
73
+ /*
74
+ * Returns 1 if interval contains zero, 0 otherwise.
75
+ */
76
+ int interval_span_zero_p (Interval* interval)
77
+ {
78
+ int result;
79
+ Real* zero;
80
+
81
+ zero = (Real*)real_zero();
82
+ result = interval_span_p(interval, zero);
83
+
84
+ real_free(zero);
85
+
86
+ return result;
87
+ }
88
+
89
+ /*
90
+ * Returns 1 if interval contains only zero, 0 otherwise.
91
+ */
92
+ int interval_zero_p (Interval* interval)
93
+ {
94
+ int result;
95
+ Real* zero;
96
+
97
+ zero = (Real*)real_zero();
98
+ result = real_eq_p(interval->l, zero) && real_eq_p(interval->u, zero);
99
+
100
+ real_free(zero);
101
+
102
+ return result;
103
+ }
104
+
105
+ /*
106
+ * Returns 1 if interval contains exactly one real number, 0 otherwise.
107
+ */
108
+ int interval_degenerate_p (Interval* interval)
109
+ {
110
+ return real_eq_p(interval->l, interval->u);
111
+ }
112
+
113
+ /*
114
+ * Returns a pointer to a newly allocated Interval with the given value. The
115
+ * given reals will be referenced by the new interval and must be freed only
116
+ * when this interval is freed.
117
+ *
118
+ * l: (1:1), L: 0, n: (2:1), R: 1, u: (3:1) => interval: {1:1 < 2:1 ≤ 3:1}
119
+ */
120
+ Interval* interval_new (Real* l, int L, Real* n, int R, Real* u)
121
+ {
122
+ Interval* interval;
123
+ interval = (Interval*)malloc(sizeof(Interval));
124
+
125
+ if (interval == NULL)
126
+ {
127
+ return NULL;
128
+ }
129
+
130
+ memset(interval, 0, sizeof(Interval));
131
+
132
+ if (NaN(l) || NaN(n) || NaN(u))
133
+ {
134
+ interval->n = (Real*)real_nan();
135
+ interval->l = (Real*)real_neg_inf();
136
+ interval->u = (Real*)real_pos_inf();
137
+
138
+ interval->L = true;
139
+ interval->R = true;
140
+
141
+ real_free(n);
142
+ real_free(l);
143
+ real_free(u);
144
+ }
145
+ else
146
+ {
147
+ interval->n = (Real*)n;
148
+ interval->l = (Real*)l;
149
+ interval->u = (Real*)u;
150
+
151
+ interval->L = real_eq_p(interval->l, interval->u) || real_eq_p(interval->n, interval->l) || L;
152
+ interval->R = real_eq_p(interval->l, interval->u) || real_eq_p(interval->n, interval->u) || R;
153
+ }
154
+
155
+ return interval;
156
+ }
157
+
158
+ /*
159
+ * Returns a pointer to a newly allocated Interval containing only the given
160
+ * real. The given real is duplicated before being stored, and therefore must
161
+ * be freed separately.
162
+ */
163
+ Interval* interval_from_real (Real* real)
164
+ {
165
+ return interval_new((Real*)real_dup(real), true, (Real*)real_dup(real), true, (Real*)real_dup(real));
166
+ }
167
+
168
+ /*
169
+ * Returns a pointer to a newly allocated Interval containing a NaN value.
170
+ */
171
+ Interval* interval_nan ()
172
+ {
173
+ return interval_new((Real*)real_neg_inf(), true, (Real*)real_nan(), true, (Real*)real_pos_inf());
174
+ }
175
+
176
+ /*
177
+ * Returns a pointer to a newly allocated Interval containing only +∞.
178
+ */
179
+ Interval* interval_pos_inf ()
180
+ {
181
+ return interval_new((Real*)real_pos_inf(), true, (Real*)real_pos_inf(), true, (Real*)real_pos_inf());
182
+ }
183
+
184
+ /*
185
+ * Returns a pointer to a newly allocated Interval containing only -∞.
186
+ */
187
+ Interval* interval_neg_inf ()
188
+ {
189
+ return interval_new((Real*)real_neg_inf(), true, (Real*)real_neg_inf(), true, (Real*)real_neg_inf());
190
+ }
191
+
192
+ /*
193
+ * Returns a pointer to a newly allocated Interval containing only 0.
194
+ */
195
+ Interval* interval_zero ()
196
+ {
197
+ return interval_new((Real*)real_zero(), true, (Real*)real_zero(), true, (Real*)real_zero());
198
+ }
199
+
200
+ /*
201
+ * Returns a pointer to a newly allocated Interval containing only 1.
202
+ */
203
+ Interval* interval_one ()
204
+ {
205
+ return interval_new((Real*)real_one(), true, (Real*)real_one(), true, (Real*)real_one());
206
+ }
207
+
208
+ /*
209
+ * Returns a pointer to a newly allocated Interval containing π, accurate to
210
+ * digs digits.
211
+ */
212
+ Interval* interval_pi ()
213
+ {
214
+ return (Interval*)interval_new((Real*)real_pi(ROUND_DOWN), false, (Real*)real_pi(ROUND_NEAREST), false, (Real*)real_pi(ROUND_UP1));
215
+ }
216
+
217
+ /*
218
+ * Returns a pointer to a newly allocated Interval containing e, accurate to
219
+ * digs digits.
220
+ */
221
+ Interval* interval_e ()
222
+ {
223
+ return (Interval*)interval_new((Real*)real_e(ROUND_DOWN), false, (Real*)real_e(ROUND_NEAREST), false, (Real*)real_e(ROUND_UP1));
224
+ }
225
+
226
+ /*
227
+ * Returns a pointer to a newly allocated Interval with the same value as the
228
+ * given interval.
229
+ */
230
+ Interval* interval_dup (Interval* interval)
231
+ {
232
+ return interval_new((Real*)real_dup(interval->l), interval->L, (Real*)real_dup(interval->n), interval->R, (Real*)real_dup(interval->u));
233
+ }
234
+
235
+ /*
236
+ * Returns a pointer to a newly allocated Interval containing a + b.
237
+ */
238
+ Interval* interval_add (Interval* a, Interval* b)
239
+ {
240
+ int L;
241
+ int R;
242
+ Real* n;
243
+ Real* l;
244
+ Real* u;
245
+
246
+ n = (Real*)real_add(a->n, b->n);
247
+ l = (Real*)real_add(a->l, b->l);
248
+ u = (Real*)real_add(a->u, b->u);
249
+
250
+ L = a->L && b->L;
251
+ R = a->R && b->R;
252
+
253
+ return interval_new(l, L, n, R, u);
254
+ }
255
+
256
+ /*
257
+ * Returns a pointer to a newly allocated Interval containing a - b.
258
+ */
259
+ Interval* interval_subtract (Interval* a, Interval* b)
260
+ {
261
+ int L;
262
+ int R;
263
+ Real* n;
264
+ Real* l;
265
+ Real* u;
266
+
267
+ n = (Real*)real_subtract(a->n, b->n);
268
+ l = (Real*)real_subtract(a->l, b->u);
269
+ u = (Real*)real_subtract(a->u, b->l);
270
+
271
+ L = a->L && b->R;
272
+ R = a->R && b->L;
273
+
274
+ return interval_new(l, L, n, R, u);
275
+ }
276
+
277
+ /*
278
+ * Returns a pointer to a newly allocated Interval containing a * b.
279
+ */
280
+ Interval* interval_multiply (Interval* a, Interval* b)
281
+ {
282
+ int L;
283
+ int R;
284
+ Real* n;
285
+ Real* l;
286
+ Real* u;
287
+ RealBounds* bounds;
288
+ Interval* interval;
289
+
290
+ bounds = (RealBounds*)real_bounds_new();
291
+ real_bounds_update(bounds, (Real*)real_multiply(a->l, b->l), a->L && b->L);
292
+ real_bounds_update(bounds, (Real*)real_multiply(a->l, b->u), a->L && b->R);
293
+ real_bounds_update(bounds, (Real*)real_multiply(a->u, b->l), a->R && b->L);
294
+ real_bounds_update(bounds, (Real*)real_multiply(a->u, b->u), a->R && b->R);
295
+
296
+ L = bounds->min_closed;
297
+ R = bounds->max_closed;
298
+
299
+ n = (Real*)real_multiply(a->n, b->n);
300
+ l = (Real*)real_dup(bounds->min);
301
+ u = (Real*)real_dup(bounds->max);
302
+
303
+ real_bounds_free(bounds);
304
+
305
+ return interval_new(l, L, n, R, u);
306
+ }
307
+
308
+ /*
309
+ * Returns a pointer to a newly allocated Interval containing a / b.
310
+ */
311
+ Interval* interval_divide (Interval* a, Interval* b)
312
+ {
313
+ int L;
314
+ int R;
315
+ Real* n;
316
+ Real* l;
317
+ Real* u;
318
+ RealBounds* bounds;
319
+ Interval* interval;
320
+
321
+ bounds = (RealBounds*)real_bounds_new();
322
+ real_bounds_update(bounds, (Real*)real_divide(a->l, b->l, ROUND_NEAREST), a->L && b->L);
323
+ real_bounds_update(bounds, (Real*)real_divide(a->l, b->u, ROUND_NEAREST), a->L && b->R);
324
+ real_bounds_update(bounds, (Real*)real_divide(a->u, b->l, ROUND_NEAREST), a->R && b->L);
325
+ real_bounds_update(bounds, (Real*)real_divide(a->u, b->u, ROUND_NEAREST), a->R && b->R);
326
+
327
+ L = bounds->min_closed;
328
+ R = bounds->max_closed;
329
+
330
+ n = (Real*)real_divide(a->n, b->n);
331
+ l = (Real*)real_dup(bounds->min);
332
+ u = (Real*)real_dup(bounds->max);
333
+
334
+ real_bounds_free(bounds);
335
+
336
+ return interval_new(l, L, n, R, u);
337
+ }
338
+
339
+ /*
340
+ * Returns a pointer to a newly allocated Interval containing -interval.
341
+ */
342
+ Interval* interval_negate (Interval* interval)
343
+ {
344
+ return interval_new((Real*)real_negate(interval->u), interval->R, (Real*)real_negate(interval->n), interval->L, (Real*)real_negate(interval->l));
345
+ }
346
+
347
+ /*
348
+ * Returns a pointer to a newly allocated Interval containing the elements of
349
+ * interval rounded to the nearest integer values.
350
+ */
351
+ Interval* interval_round (Interval* interval)
352
+ {
353
+ return interval_new((Real*)real_round(interval->l), true, (Real*)real_round(interval->n), true, (Real*)real_round(interval->u));
354
+ }
355
+
356
+ /*
357
+ * Returns a pointer to a newly allocated Interval containing the elements of
358
+ * interval rounded to the next closest integer values in the direction of
359
+ * positive infinity.
360
+ */
361
+ Interval* interval_round_ceiling (Interval* interval)
362
+ {
363
+ return interval_new((Real*)real_ceil(interval->l), true, (Real*)real_ceil(interval->n), true, (Real*)real_ceil(interval->u));
364
+ }
365
+
366
+ /*
367
+ * Returns a pointer to a newly allocated Interval containing the elements of
368
+ * interval rounded to the next closest integer values in the direction of
369
+ * negative infinity.
370
+ */
371
+ Interval* interval_round_floor (Interval* interval)
372
+ {
373
+ return interval_new((Real*)real_floor(interval->l), true, (Real*)real_floor(interval->n), true, (Real*)real_floor(interval->u));
374
+ }
375
+
376
+ /*
377
+ * Returns a pointer to a newly allocated Interval containing the elements of
378
+ * interval rounded to the next closest integer values in the direction away
379
+ * from the origin.
380
+ */
381
+ Interval* interval_round_infinity (Interval* interval)
382
+ {
383
+ return interval_new((Real*)real_round_infinity(interval->l), true, (Real*)real_round_infinity(interval->n), true, (Real*)real_round_infinity(interval->u));
384
+ }
385
+
386
+ /*
387
+ * Returns a pointer to a newly allocated Interval containing the elements of
388
+ * interval rounded to the next closest integer values in the direction of the
389
+ * origin.
390
+ */
391
+ Interval* interval_round_origin (Interval* interval)
392
+ {
393
+ return interval_new((Real*)real_round_origin(interval->l), true, (Real*)real_round_origin(interval->n), true, (Real*)real_round_origin(interval->u));
394
+ }