dec_number 0.0.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/README +20 -0
- data/dec_number.gemspec +13 -0
- data/ext/dec_number/Gemfile +4 -0
- data/ext/dec_number/NOTES +10 -0
- data/ext/dec_number/decNumber/ICU-license.html +45 -0
- data/ext/dec_number/decNumber/Makefile.am +3 -0
- data/ext/dec_number/decNumber/Makefile.in +680 -0
- data/ext/dec_number/decNumber/aclocal.m4 +8988 -0
- data/ext/dec_number/decNumber/autom4te.cache/output.0 +5107 -0
- data/ext/dec_number/decNumber/autom4te.cache/output.1 +6026 -0
- data/ext/dec_number/decNumber/autom4te.cache/output.2 +13468 -0
- data/ext/dec_number/decNumber/autom4te.cache/output.3 +13472 -0
- data/ext/dec_number/decNumber/autom4te.cache/requests +407 -0
- data/ext/dec_number/decNumber/autom4te.cache/traces.0 +352 -0
- data/ext/dec_number/decNumber/autom4te.cache/traces.1 +772 -0
- data/ext/dec_number/decNumber/autom4te.cache/traces.2 +591 -0
- data/ext/dec_number/decNumber/autom4te.cache/traces.3 +2362 -0
- data/ext/dec_number/decNumber/config.guess +1501 -0
- data/ext/dec_number/decNumber/config.h.in +142 -0
- data/ext/dec_number/decNumber/config.sub +1705 -0
- data/ext/dec_number/decNumber/configure +13468 -0
- data/ext/dec_number/decNumber/configure.ac +36 -0
- data/ext/dec_number/decNumber/decBasic.c +3908 -0
- data/ext/dec_number/decNumber/decCommon.c +1835 -0
- data/ext/dec_number/decNumber/decContext.c +437 -0
- data/ext/dec_number/decNumber/decContext.h +254 -0
- data/ext/dec_number/decNumber/decDPD.h +1185 -0
- data/ext/dec_number/decNumber/decDouble.c +140 -0
- data/ext/dec_number/decNumber/decDouble.h +155 -0
- data/ext/dec_number/decNumber/decNumber.c +8141 -0
- data/ext/dec_number/decNumber/decNumber.h +182 -0
- data/ext/dec_number/decNumber/decNumberLocal.h +757 -0
- data/ext/dec_number/decNumber/decPacked.c +220 -0
- data/ext/dec_number/decNumber/decPacked.h +52 -0
- data/ext/dec_number/decNumber/decQuad.c +135 -0
- data/ext/dec_number/decNumber/decQuad.h +177 -0
- data/ext/dec_number/decNumber/decSingle.c +71 -0
- data/ext/dec_number/decNumber/decSingle.h +86 -0
- data/ext/dec_number/decNumber/decimal128.c +553 -0
- data/ext/dec_number/decNumber/decimal128.h +81 -0
- data/ext/dec_number/decNumber/decimal32.c +476 -0
- data/ext/dec_number/decNumber/decimal32.h +81 -0
- data/ext/dec_number/decNumber/decimal64.c +839 -0
- data/ext/dec_number/decNumber/decimal64.h +83 -0
- data/ext/dec_number/decNumber/decnumber.pdf +0 -0
- data/ext/dec_number/decNumber/depcomp +630 -0
- data/ext/dec_number/decNumber/example1.c +38 -0
- data/ext/dec_number/decNumber/example2.c +52 -0
- data/ext/dec_number/decNumber/example3.c +64 -0
- data/ext/dec_number/decNumber/example4.c +61 -0
- data/ext/dec_number/decNumber/example5.c +36 -0
- data/ext/dec_number/decNumber/example6.c +61 -0
- data/ext/dec_number/decNumber/example7.c +35 -0
- data/ext/dec_number/decNumber/example8.c +39 -0
- data/ext/dec_number/decNumber/install-sh +520 -0
- data/ext/dec_number/decNumber/libdecNumber.a +0 -0
- data/ext/dec_number/decNumber/ltmain.sh +8745 -0
- data/ext/dec_number/decNumber/missing +376 -0
- data/ext/dec_number/decNumber/readme.txt +81 -0
- data/ext/dec_number/dec_number.c +464 -0
- data/ext/dec_number/extconf.rb +52 -0
- data/ext/dec_number/extconf2.rb +50 -0
- data/ext/dec_number/recompile.sh +3 -0
- data/ext/dec_number/test_dec_number.rb +236 -0
- data/ext/dec_number/test_numeric.rb +235 -0
- metadata +111 -0
@@ -0,0 +1,464 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
#include "decNumber.h"
|
3
|
+
#include <stdio.h>
|
4
|
+
|
5
|
+
// Backwards compat for old rubies
|
6
|
+
#if !defined(RSTRING_LEN)
|
7
|
+
# define RSTRING_LEN(x) (RSTRING(x)->len)
|
8
|
+
# define RSTRING_PTR(x) (RSTRING(x)->ptr)
|
9
|
+
#endif
|
10
|
+
|
11
|
+
#if !defined(DEBUGPRINT)
|
12
|
+
# define WHERESTR "[file %s, line %d]: "
|
13
|
+
# define WHEREARG __FILE__, __LINE__
|
14
|
+
# define DEBUGPRINT2(...) fprintf(stderr, __VA_ARGS__)
|
15
|
+
# define DEBUGPRINT(_fmt, ...) DEBUGPRINT2(WHERESTR _fmt, WHEREARG, __VA_ARGS__)
|
16
|
+
#endif
|
17
|
+
|
18
|
+
VALUE cDecNumber;
|
19
|
+
VALUE cDecContext;
|
20
|
+
|
21
|
+
#define dec_num_setup( result, self, result_ptr, self_ptr, context_ptr ) \
|
22
|
+
Data_Get_Struct( rb_iv_get(self, "@context"), decContext, context_ptr); \
|
23
|
+
Data_Get_Struct( self, decNumber, self_ptr); \
|
24
|
+
result = rb_funcall( cDecNumber, rb_intern("new"), 0 ); \
|
25
|
+
Data_Get_Struct(result, decNumber, result_ptr)
|
26
|
+
|
27
|
+
#define dec_num_setup_with_new_context( result, self, result_ptr, self_ptr, context, context_ptr ) \
|
28
|
+
context = rb_funcall( cDecContext, rb_intern("new"), 0 ); \
|
29
|
+
Data_Get_Struct( context, decContext, context_ptr); \
|
30
|
+
Data_Get_Struct( self, decNumber, self_ptr); \
|
31
|
+
result = rb_funcall( cDecNumber, rb_intern("new"), 0 ); \
|
32
|
+
Data_Get_Struct(result, decNumber, result_ptr)
|
33
|
+
|
34
|
+
#define dec_num_setup_without_context( result, self, result_ptr, self_ptr ) \
|
35
|
+
Data_Get_Struct( self, decNumber, self_ptr); \
|
36
|
+
result = rb_funcall( cDecNumber, rb_intern("new"), 0 ); \
|
37
|
+
Data_Get_Struct(result, decNumber, result_ptr)
|
38
|
+
|
39
|
+
#define dec_num_setup_rval( result, self, rval, result_ptr, self_ptr, rval_ptr, context_ptr ) \
|
40
|
+
Data_Get_Struct( rb_iv_get(self, "@context"), decContext, context_ptr); \
|
41
|
+
rval = rb_funcall( rval, rb_intern("to_dec_number"), 0 ); \
|
42
|
+
Data_Get_Struct( self, decNumber, self_ptr); \
|
43
|
+
Data_Get_Struct( rval, decNumber, rval_ptr); \
|
44
|
+
result = rb_funcall( cDecNumber, rb_intern("new"), 0 ); \
|
45
|
+
Data_Get_Struct(result, decNumber, result_ptr)
|
46
|
+
|
47
|
+
#define dec_num_setup_rval_with_new_context( result, self, rval, result_ptr, self_ptr, rval_ptr, context, context_ptr ) \
|
48
|
+
context = rb_funcall( cDecContext, rb_intern("new"), 0 ); \
|
49
|
+
Data_Get_Struct( context, decContext, context_ptr); \
|
50
|
+
rval = rb_funcall( rval, rb_intern("to_dec_number"), 0 ); \
|
51
|
+
Data_Get_Struct( self, decNumber, self_ptr); \
|
52
|
+
Data_Get_Struct( rval, decNumber, rval_ptr); \
|
53
|
+
result = rb_funcall( cDecNumber, rb_intern("new"), 0 ); \
|
54
|
+
Data_Get_Struct(result, decNumber, result_ptr)
|
55
|
+
|
56
|
+
static VALUE con_alloc(VALUE klass) {
|
57
|
+
decContext self_struct, *self_ptr;
|
58
|
+
VALUE self;
|
59
|
+
self_ptr = &self_struct;
|
60
|
+
self = Data_Make_Struct(klass, decContext, 0, free, self_ptr);
|
61
|
+
return self;
|
62
|
+
}
|
63
|
+
|
64
|
+
static VALUE con_initialize(int argc, VALUE *argv, VALUE self) {
|
65
|
+
decContext *self_ptr;
|
66
|
+
VALUE from;
|
67
|
+
rb_scan_args( argc, argv, "01", &from );
|
68
|
+
|
69
|
+
Data_Get_Struct(self, decContext, self_ptr);
|
70
|
+
decContextDefault(self_ptr, DEC_INIT_BASE);
|
71
|
+
self_ptr->traps = 0; // no traps TODO: error handling
|
72
|
+
// self_ptr->digits = 34; // WTF
|
73
|
+
|
74
|
+
// TODO: Handle arguments
|
75
|
+
|
76
|
+
return self;
|
77
|
+
}
|
78
|
+
|
79
|
+
static VALUE num_alloc(VALUE klass) {
|
80
|
+
decNumber self_struct, *self_ptr;
|
81
|
+
decContext context;
|
82
|
+
VALUE self;
|
83
|
+
self_ptr = &self_struct;
|
84
|
+
self = Data_Make_Struct(klass, decNumber, 0, free, self_ptr);
|
85
|
+
decContextDefault(&context, DEC_INIT_BASE);
|
86
|
+
|
87
|
+
(*self_ptr).bits = DECNAN;
|
88
|
+
return self;
|
89
|
+
}
|
90
|
+
|
91
|
+
static VALUE num_initialize(int argc, VALUE *argv, VALUE self) {
|
92
|
+
decNumber *self_ptr;
|
93
|
+
decContext *context_ptr;
|
94
|
+
VALUE from, r_str, context;
|
95
|
+
|
96
|
+
rb_scan_args( argc, argv, "01", &from );
|
97
|
+
context = rb_funcall( cDecContext, rb_intern("new"), 0 );
|
98
|
+
rb_iv_set( self, "@context", context );
|
99
|
+
Data_Get_Struct(context, decContext, context_ptr);
|
100
|
+
Data_Get_Struct(self, decNumber, self_ptr);
|
101
|
+
|
102
|
+
if ( NIL_P(from) ) {
|
103
|
+
// decNumberFromString(dec_num_ptr, "0", &dec_context);
|
104
|
+
} else {
|
105
|
+
r_str = rb_funcall(from, rb_intern("to_s"), 0);
|
106
|
+
decNumberFromString(self_ptr, StringValuePtr( r_str ), context_ptr);
|
107
|
+
}
|
108
|
+
|
109
|
+
return self;
|
110
|
+
}
|
111
|
+
|
112
|
+
// TODO: does this work?
|
113
|
+
static VALUE dec_number_from_struct(decNumber source_dec_num) {
|
114
|
+
VALUE new;
|
115
|
+
decNumber *dec_num_ptr;
|
116
|
+
|
117
|
+
new = rb_funcall( cDecNumber, rb_intern("new"), 0 );
|
118
|
+
Data_Get_Struct(new, decNumber, dec_num_ptr);
|
119
|
+
decNumberCopy( dec_num_ptr, &source_dec_num );
|
120
|
+
|
121
|
+
return new;
|
122
|
+
}
|
123
|
+
|
124
|
+
static VALUE dec_number_from_string(VALUE obj, VALUE from) {
|
125
|
+
decNumber *dec_num_ptr;
|
126
|
+
VALUE new, ret, err;
|
127
|
+
|
128
|
+
ret = Qnil;
|
129
|
+
new = rb_funcall( cDecNumber, rb_intern("new"), 1, from );
|
130
|
+
Data_Get_Struct(new, decNumber, dec_num_ptr);
|
131
|
+
|
132
|
+
if ( decNumberIsNaN( dec_num_ptr ) ) {
|
133
|
+
err = rb_funcall( rb_cObject, rb_intern( "sprintf" ), 2, "invalid value for DecNumber: %s", from );
|
134
|
+
rb_raise(rb_eArgError, StringValuePtr( err ) );
|
135
|
+
} else {
|
136
|
+
ret = new;
|
137
|
+
}
|
138
|
+
|
139
|
+
return ret;
|
140
|
+
}
|
141
|
+
|
142
|
+
// TODO: Not sure if this should this return as a NaN when not a number, or as a 0 like nil.to_i
|
143
|
+
static VALUE to_dec_number(VALUE obj) {
|
144
|
+
decNumber *dec_num_ptr;
|
145
|
+
VALUE dec_num;
|
146
|
+
VALUE ret;
|
147
|
+
VALUE err;
|
148
|
+
|
149
|
+
if ( rb_obj_is_kind_of( obj, cDecNumber ) ) {
|
150
|
+
return obj;
|
151
|
+
}
|
152
|
+
|
153
|
+
ret = Qnil;
|
154
|
+
dec_num = rb_funcall( cDecNumber, rb_intern("new"), 1, obj );
|
155
|
+
Data_Get_Struct(dec_num, decNumber, dec_num_ptr);
|
156
|
+
|
157
|
+
if ( decNumberIsNaN( dec_num_ptr ) ) {
|
158
|
+
decNumberZero( dec_num_ptr );
|
159
|
+
ret = dec_num;
|
160
|
+
} else {
|
161
|
+
ret = dec_num;
|
162
|
+
}
|
163
|
+
|
164
|
+
return ret;
|
165
|
+
}
|
166
|
+
|
167
|
+
static VALUE num_coerce( VALUE self, VALUE rhs ) {
|
168
|
+
VALUE result_arr;
|
169
|
+
if ( TYPE(rhs) != TYPE(self) ) {
|
170
|
+
rhs = rb_funcall( rhs, rb_intern("to_dec_number"), 0 );
|
171
|
+
}
|
172
|
+
result_arr = rb_ary_new2(2);
|
173
|
+
rb_ary_store( result_arr, 0, rhs);
|
174
|
+
rb_ary_store( result_arr, 1, self);
|
175
|
+
|
176
|
+
return result_arr;
|
177
|
+
}
|
178
|
+
|
179
|
+
static VALUE num_to_s(VALUE self) {
|
180
|
+
decNumber *dec_num_ptr;
|
181
|
+
VALUE str;
|
182
|
+
char c_str[DECNUMDIGITS+14];
|
183
|
+
|
184
|
+
Data_Get_Struct(self, decNumber, dec_num_ptr);
|
185
|
+
|
186
|
+
decNumberToString( dec_num_ptr, c_str );
|
187
|
+
str = rb_str_new2(c_str);
|
188
|
+
return str;
|
189
|
+
}
|
190
|
+
|
191
|
+
static VALUE num_to_i(VALUE self) {
|
192
|
+
VALUE result, context;
|
193
|
+
decContext *context_ptr;
|
194
|
+
decNumber *self_ptr, *result_ptr;
|
195
|
+
int32_t c_int;
|
196
|
+
dec_num_setup_with_new_context( result, self, result_ptr, self_ptr, context, context_ptr );
|
197
|
+
|
198
|
+
context_ptr->round = DEC_ROUND_DOWN;
|
199
|
+
decNumberToIntegralValue( result_ptr, self_ptr, context_ptr);
|
200
|
+
c_int = decNumberToInt32( result_ptr, context_ptr );
|
201
|
+
|
202
|
+
return INT2NUM(c_int);
|
203
|
+
}
|
204
|
+
|
205
|
+
static VALUE num_to_f(VALUE self) {
|
206
|
+
return rb_funcall(num_to_s(self), rb_intern("to_f"), 0);
|
207
|
+
}
|
208
|
+
|
209
|
+
static VALUE num_zero(VALUE self) {
|
210
|
+
decNumber *dec_num_ptr;
|
211
|
+
Data_Get_Struct(self, decNumber, dec_num_ptr);
|
212
|
+
if ( decNumberIsZero( dec_num_ptr ) ) {
|
213
|
+
return Qtrue;
|
214
|
+
} else {
|
215
|
+
return Qfalse;
|
216
|
+
}
|
217
|
+
}
|
218
|
+
|
219
|
+
static VALUE num_nonzero(VALUE self) {
|
220
|
+
decNumber *dec_num_ptr;
|
221
|
+
Data_Get_Struct(self, decNumber, dec_num_ptr);
|
222
|
+
if ( decNumberIsZero( dec_num_ptr ) ) {
|
223
|
+
return Qfalse;
|
224
|
+
} else {
|
225
|
+
return Qtrue;
|
226
|
+
}
|
227
|
+
}
|
228
|
+
|
229
|
+
static VALUE num_negate(VALUE self) {
|
230
|
+
decNumber *dec_num_ptr;
|
231
|
+
decNumber *new_dec_num_ptr;
|
232
|
+
VALUE new;
|
233
|
+
|
234
|
+
new = rb_funcall( cDecNumber, rb_intern("new"), 0 );
|
235
|
+
Data_Get_Struct(self, decNumber, dec_num_ptr);
|
236
|
+
if ( decNumberIsNaN( dec_num_ptr ) ) {
|
237
|
+
rb_raise(rb_eTypeError, "can't negate that" );
|
238
|
+
return Qnil;
|
239
|
+
}
|
240
|
+
|
241
|
+
Data_Get_Struct(new, decNumber, new_dec_num_ptr);
|
242
|
+
decNumberCopyNegate( new_dec_num_ptr, dec_num_ptr );
|
243
|
+
|
244
|
+
if ( decNumberIsNaN( new_dec_num_ptr ) ) {
|
245
|
+
rb_raise(rb_eTypeError, "negate failed" );
|
246
|
+
return Qnil;
|
247
|
+
}
|
248
|
+
|
249
|
+
return new;
|
250
|
+
}
|
251
|
+
|
252
|
+
// needs to check for things like nil and false, etc, not convert everything. Probably only convert numbers.
|
253
|
+
static VALUE num_compare(VALUE self, VALUE rval) {
|
254
|
+
VALUE ret, result, tmp_obj;
|
255
|
+
int32_t tmp_n, klass;
|
256
|
+
decContext *context_ptr;
|
257
|
+
decNumber *self_ptr, *rval_ptr, *result_ptr;
|
258
|
+
|
259
|
+
ret = Qnil;
|
260
|
+
if ( SYMBOL_P( rval ) ) {
|
261
|
+
return Qnil;
|
262
|
+
}
|
263
|
+
|
264
|
+
dec_num_setup_rval( result, self, rval, result_ptr, self_ptr, rval_ptr, context_ptr );
|
265
|
+
|
266
|
+
decNumberCompare(result_ptr, self_ptr, rval_ptr, context_ptr);
|
267
|
+
|
268
|
+
if ( decNumberIsNaN( result_ptr ) ) {
|
269
|
+
rb_raise(rb_eArgError, "FAIL: TODO: This error (should usually fail earlier)");
|
270
|
+
return Qnil;
|
271
|
+
} else {
|
272
|
+
tmp_n = decNumberToInt32( result_ptr, context_ptr );
|
273
|
+
ret = INT2FIX( tmp_n );
|
274
|
+
}
|
275
|
+
|
276
|
+
return ret;
|
277
|
+
}
|
278
|
+
|
279
|
+
static VALUE num_divide(VALUE self, VALUE rval) {
|
280
|
+
VALUE result;
|
281
|
+
decContext *context_ptr;
|
282
|
+
decNumber *self_ptr, *rval_ptr, *result_ptr;
|
283
|
+
dec_num_setup_rval( result, self, rval, result_ptr, self_ptr, rval_ptr, context_ptr );
|
284
|
+
|
285
|
+
if ( decNumberIsZero(rval_ptr) ) {
|
286
|
+
(*result_ptr).bits = DECNAN;
|
287
|
+
} else {
|
288
|
+
decNumberDivide( result_ptr, self_ptr, rval_ptr, context_ptr);
|
289
|
+
}
|
290
|
+
return result;
|
291
|
+
}
|
292
|
+
|
293
|
+
static VALUE num_div(VALUE self, VALUE rval) {
|
294
|
+
VALUE result;
|
295
|
+
decContext *context_ptr;
|
296
|
+
decNumber *self_ptr, *rval_ptr, *result_ptr;
|
297
|
+
dec_num_setup_rval( result, self, rval, result_ptr, self_ptr, rval_ptr, context_ptr );
|
298
|
+
|
299
|
+
decNumberDivideInteger( result_ptr, self_ptr, rval_ptr, context_ptr);
|
300
|
+
return result;
|
301
|
+
}
|
302
|
+
|
303
|
+
static VALUE num_multiply(VALUE self, VALUE rval) {
|
304
|
+
VALUE result;
|
305
|
+
decContext *context_ptr;
|
306
|
+
decNumber *self_ptr, *rval_ptr, *result_ptr;
|
307
|
+
dec_num_setup_rval( result, self, rval, result_ptr, self_ptr, rval_ptr, context_ptr );
|
308
|
+
|
309
|
+
decNumberMultiply( result_ptr, self_ptr, rval_ptr, context_ptr);
|
310
|
+
return result;
|
311
|
+
}
|
312
|
+
|
313
|
+
static VALUE num_add(VALUE self, VALUE rval) {
|
314
|
+
VALUE result;
|
315
|
+
decContext *context_ptr;
|
316
|
+
decNumber *self_ptr, *rval_ptr, *result_ptr;
|
317
|
+
dec_num_setup_rval( result, self, rval, result_ptr, self_ptr, rval_ptr, context_ptr );
|
318
|
+
|
319
|
+
decNumberAdd( result_ptr, self_ptr, rval_ptr, context_ptr);
|
320
|
+
return result;
|
321
|
+
}
|
322
|
+
|
323
|
+
static VALUE num_subtract(VALUE self, VALUE rval) {
|
324
|
+
VALUE result;
|
325
|
+
decContext *context_ptr;
|
326
|
+
decNumber *self_ptr, *rval_ptr, *result_ptr;
|
327
|
+
dec_num_setup_rval( result, self, rval, result_ptr, self_ptr, rval_ptr, context_ptr );
|
328
|
+
|
329
|
+
decNumberSubtract( result_ptr, self_ptr, rval_ptr, context_ptr);
|
330
|
+
return result;
|
331
|
+
}
|
332
|
+
|
333
|
+
static VALUE num_abs(VALUE self) {
|
334
|
+
VALUE result;
|
335
|
+
decContext *context_ptr;
|
336
|
+
decNumber *self_ptr, *result_ptr;
|
337
|
+
dec_num_setup( result, self, result_ptr, self_ptr, context_ptr );
|
338
|
+
|
339
|
+
decNumberAbs( result_ptr, self_ptr, context_ptr);
|
340
|
+
return result;
|
341
|
+
}
|
342
|
+
|
343
|
+
static VALUE num_ceil(VALUE self) {
|
344
|
+
VALUE result, context;
|
345
|
+
decContext *context_ptr;
|
346
|
+
decNumber *self_ptr, *result_ptr;
|
347
|
+
dec_num_setup_without_context( result, self, result_ptr, self_ptr );
|
348
|
+
context = rb_funcall( cDecContext, rb_intern("new"), 0 );
|
349
|
+
Data_Get_Struct( context, decContext, context_ptr); \
|
350
|
+
|
351
|
+
(*context_ptr).round = DEC_ROUND_CEILING;
|
352
|
+
|
353
|
+
decNumberToIntegralValue( result_ptr, self_ptr, context_ptr);
|
354
|
+
return result;
|
355
|
+
}
|
356
|
+
|
357
|
+
static VALUE num_floor(VALUE self) {
|
358
|
+
VALUE result, context;
|
359
|
+
decContext *context_ptr;
|
360
|
+
decNumber *self_ptr, *result_ptr;
|
361
|
+
dec_num_setup_without_context( result, self, result_ptr, self_ptr );
|
362
|
+
context = rb_funcall( cDecContext, rb_intern("new"), 0 );
|
363
|
+
Data_Get_Struct( context, decContext, context_ptr); \
|
364
|
+
|
365
|
+
(*context_ptr).round = DEC_ROUND_FLOOR;
|
366
|
+
|
367
|
+
decNumberToIntegralValue( result_ptr, self_ptr, context_ptr);
|
368
|
+
return result;
|
369
|
+
}
|
370
|
+
|
371
|
+
static VALUE num_divmod(VALUE self, VALUE rval) {
|
372
|
+
VALUE result_int, result_rem, result_ary;
|
373
|
+
decContext *context_ptr;
|
374
|
+
decNumber *self_ptr, *rval_ptr, *result_int_ptr, *result_rem_ptr;
|
375
|
+
dec_num_setup_rval( result_int, self, rval, result_int_ptr, self_ptr, rval_ptr, context_ptr );
|
376
|
+
result_rem = rb_funcall( cDecNumber, rb_intern("new"), 0 ); \
|
377
|
+
Data_Get_Struct(result_rem, decNumber, result_rem_ptr);
|
378
|
+
|
379
|
+
// There might be a more efficient way to get these
|
380
|
+
decNumberDivideInteger( result_int_ptr, self_ptr, rval_ptr, context_ptr );
|
381
|
+
decNumberRemainder( result_rem_ptr, self_ptr, result_int_ptr, context_ptr);
|
382
|
+
result_ary = rb_ary_new3( 2, result_int, result_rem );
|
383
|
+
return result_ary;
|
384
|
+
}
|
385
|
+
|
386
|
+
static VALUE num_eql(VALUE self, VALUE rval) {
|
387
|
+
VALUE result;
|
388
|
+
decContext *context_ptr;
|
389
|
+
decNumber *self_ptr, *rval_ptr, *result_ptr;
|
390
|
+
|
391
|
+
if ( rb_obj_is_kind_of( rval, cDecNumber ) && FIX2INT( num_compare( self, rval ) ) == 0 ) {
|
392
|
+
return Qtrue;
|
393
|
+
} else {
|
394
|
+
return Qfalse;
|
395
|
+
}
|
396
|
+
}
|
397
|
+
|
398
|
+
static VALUE num_modulo(VALUE self, VALUE rval) {
|
399
|
+
VALUE result, context;
|
400
|
+
decContext *context_ptr;
|
401
|
+
decNumber *self_ptr, *rval_ptr, *result_ptr;
|
402
|
+
dec_num_setup_rval_with_new_context( result, self, rval, result_ptr, self_ptr, rval_ptr, context, context_ptr );
|
403
|
+
|
404
|
+
context_ptr->round = DEC_ROUND_DOWN;
|
405
|
+
|
406
|
+
decNumberRemainder( result_ptr, self_ptr, rval_ptr, context_ptr);
|
407
|
+
return result;
|
408
|
+
}
|
409
|
+
|
410
|
+
static VALUE num_round(VALUE self) {
|
411
|
+
VALUE result;
|
412
|
+
decContext *context_ptr;
|
413
|
+
decNumber *self_ptr, *result_ptr;
|
414
|
+
dec_num_setup( result, self, result_ptr, self_ptr, context_ptr );
|
415
|
+
|
416
|
+
decNumberToIntegralValue( result_ptr, self_ptr, context_ptr);
|
417
|
+
return result;
|
418
|
+
}
|
419
|
+
|
420
|
+
static VALUE num_power(VALUE self, VALUE rval) {
|
421
|
+
VALUE result;
|
422
|
+
decContext *context_ptr;
|
423
|
+
decNumber *self_ptr, *rval_ptr, *result_ptr;
|
424
|
+
dec_num_setup_rval( result, self, rval, result_ptr, self_ptr, rval_ptr, context_ptr );
|
425
|
+
|
426
|
+
decNumberPower( result_ptr, self_ptr, rval_ptr, context_ptr);
|
427
|
+
return result;
|
428
|
+
}
|
429
|
+
|
430
|
+
void Init_dec_number() {
|
431
|
+
cDecContext = rb_define_class("DecContext", rb_cObject);
|
432
|
+
rb_define_alloc_func(cDecContext, con_alloc);
|
433
|
+
rb_define_method(cDecContext, "initialize", con_initialize, -1);
|
434
|
+
cDecNumber = rb_define_class("DecNumber", rb_cNumeric );
|
435
|
+
rb_define_alloc_func(cDecNumber, num_alloc);
|
436
|
+
rb_define_method(cDecNumber, "initialize", num_initialize, -1);
|
437
|
+
rb_define_method(cDecNumber, "to_s", num_to_s, 0);
|
438
|
+
rb_define_method(cDecNumber, "to_i", num_to_i, 0);
|
439
|
+
rb_define_method(cDecNumber, "to_f", num_to_f, 0);
|
440
|
+
rb_define_method(cDecNumber, "-@", num_negate, 0);
|
441
|
+
rb_define_method(cDecNumber, "<=>", num_compare, 1);
|
442
|
+
rb_define_method(cDecNumber, "/", num_divide, 1);
|
443
|
+
rb_define_alias( cDecNumber, "quo", "/");
|
444
|
+
rb_define_method(cDecNumber, "coerce", num_coerce, 1);
|
445
|
+
rb_define_method(cDecNumber, "div", num_div, 1);
|
446
|
+
rb_define_method(cDecNumber, "*", num_multiply, 1);
|
447
|
+
rb_define_method(cDecNumber, "+", num_add, 1);
|
448
|
+
rb_define_method(cDecNumber, "-", num_subtract, 1);
|
449
|
+
rb_define_method(cDecNumber, "abs", num_abs, 0);
|
450
|
+
rb_define_method(cDecNumber, "ceil", num_ceil, 0);
|
451
|
+
rb_define_method(cDecNumber, "floor", num_floor, 0);
|
452
|
+
rb_define_method(cDecNumber, "divmod", num_divmod, 1);
|
453
|
+
rb_define_method(cDecNumber, "eql?", num_eql, 1);
|
454
|
+
rb_define_method(cDecNumber, "%", num_modulo, 1);
|
455
|
+
rb_define_alias( cDecNumber, "modulo", "%");
|
456
|
+
rb_define_method(cDecNumber, "zero?", num_zero, 0);
|
457
|
+
rb_define_method(cDecNumber, "nonzero?", num_nonzero, 0);
|
458
|
+
rb_define_method(cDecNumber, "round", num_round, 0);
|
459
|
+
rb_define_method(cDecNumber, "**", num_power, 1);
|
460
|
+
|
461
|
+
rb_define_method(rb_cObject, "DecNumber", dec_number_from_string, 1);
|
462
|
+
rb_define_method(rb_cObject, "to_dec_number", to_dec_number, 0);
|
463
|
+
// rb_funcall(rb_mKernel,rb_intern("puts"), 1, rb_str_new2("DecNumber loaded"));
|
464
|
+
}
|
@@ -0,0 +1,52 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
require 'mkmf'
|
3
|
+
|
4
|
+
decNumber_dir = './decNumber/'
|
5
|
+
|
6
|
+
if RUBY_VERSION >= "1.9"
|
7
|
+
begin
|
8
|
+
require "ruby_core_source"
|
9
|
+
rescue LoadError
|
10
|
+
require 'rubygems/user_interaction' # for 1.9.1
|
11
|
+
require 'rubygems/dependency_installer'
|
12
|
+
installer = Gem::DependencyInstaller.new
|
13
|
+
installer.install 'ruby_core_source'
|
14
|
+
|
15
|
+
Gem.refresh
|
16
|
+
Gem::Specification.activate('ruby_core_source') # for 1.9.1
|
17
|
+
|
18
|
+
require "ruby_core_source"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Dir.chdir(decNumber_dir) do
|
23
|
+
system('./configure --with-pic=yes') if %w! Makefile decNumber.o decContext.o libdecNumber.a !.find { |fn|not File.exists? fn }
|
24
|
+
|
25
|
+
system("make") and
|
26
|
+
system('ar rs libdecNumber.a decNumber.o decContext.o')
|
27
|
+
end
|
28
|
+
|
29
|
+
$LIBPATH << Dir.pwd
|
30
|
+
$defs += ["-I#{decNumber_dir}"]
|
31
|
+
dir_config('dec_number', decNumber_dir, decNumber_dir)
|
32
|
+
have_library('decNumber','decNumberVersion','decNumber.h') or raise 'decNumber library not found :('
|
33
|
+
|
34
|
+
if RUBY_VERSION >= "1.9"
|
35
|
+
$defs.push("-DRUBY19")
|
36
|
+
hdrs = Proc.new do
|
37
|
+
have_header("vm_core.h")
|
38
|
+
end
|
39
|
+
dir_config("ruby")
|
40
|
+
unless Ruby_core_source::create_makefile_with_core(hdrs, "dec_number")
|
41
|
+
STDERR.puts "\n\nRuby_core_source::create_makefile_with_core ate your cat!"
|
42
|
+
exit(1)
|
43
|
+
end
|
44
|
+
|
45
|
+
else
|
46
|
+
$defs.push("-DRUBY18")
|
47
|
+
unless create_makefile('dec_number')
|
48
|
+
STDERR.puts "\n\ncreate_makefile ate your cat!"
|
49
|
+
exit(1)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
#
|
3
|
+
# This was an attempt to use mkmfmf and core-source but I failed. Thought I'd throw it in anyways.
|
4
|
+
#
|
5
|
+
require "rubygems"
|
6
|
+
require 'mkmfmf'
|
7
|
+
|
8
|
+
decNumber_dir = './decNumber/'
|
9
|
+
|
10
|
+
if RUBY_VERSION >= "1.9"
|
11
|
+
begin
|
12
|
+
require "core-source"
|
13
|
+
rescue LoadError
|
14
|
+
require 'rubygems/user_interaction' # for 1.9.1
|
15
|
+
require 'rubygems/dependency_installer'
|
16
|
+
installer = Gem::DependencyInstaller.new
|
17
|
+
installer.install 'core-source'
|
18
|
+
|
19
|
+
Gem.refresh
|
20
|
+
begin
|
21
|
+
Specification.activate('core-source') # for 1.9.2-p290+
|
22
|
+
rescue NameError
|
23
|
+
Gem.activate('core-source') # 1.9.2-p180
|
24
|
+
end
|
25
|
+
|
26
|
+
require "core-source"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
Dir.chdir(decNumber_dir) do
|
31
|
+
system('./configure --with-pic=yes') if %w! Makefile decNumber.o decContext.o libdecNumber.a !.find { |fn|not File.exists? fn }
|
32
|
+
|
33
|
+
system("make") and
|
34
|
+
system('ar rs libdecNumber.a decNumber.o decContext.o')
|
35
|
+
end
|
36
|
+
|
37
|
+
dir_config('dec_number', decNumber_dir, decNumber_dir)
|
38
|
+
have_library('decNumber','decNumberVersion','decNumber.h') or raise 'decNumber library not found :('
|
39
|
+
|
40
|
+
if RUBY_VERSION >= "1.9"
|
41
|
+
$defs.push("-DRUBY19")
|
42
|
+
ensure_core_headers %w"vm_core.h"
|
43
|
+
else
|
44
|
+
$defs.push("-DRUBY18")
|
45
|
+
end
|
46
|
+
|
47
|
+
unless create_makefile('dec_number')
|
48
|
+
STDERR.puts "\n\ncreate_makefile ate your cat!"
|
49
|
+
exit(1)
|
50
|
+
end
|