number 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }