decimal 0.0.2 → 0.0.90.pre

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/decimal.gemspec CHANGED
@@ -1,8 +1,8 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "decimal"
3
3
  s.rubyforge_project = s.name
4
- s.version = "0.0.2"
5
- s.date = "2009-06-18"
4
+ s.version = "0.0.90.pre"
5
+ s.date = "2010-08-11"
6
6
  s.summary = "(yet another) multi-precision decimal arithmetic library"
7
7
  s.homepage = "http://decimal.rubyforge.org/"
8
8
  s.description = <<-EOS.split("\n").map{|l|l.lstrip}.join(" ")
@@ -10,8 +10,12 @@ Gem::Specification.new do |s|
10
10
  provides simple, compact, fast, precise, stable and easy-to-use solution.
11
11
  EOS
12
12
  s.extensions = "extconf.rb"
13
- s.files = %w(COPYING GPL INSTALL README decimal.c decimal.gemspec depend extconf.rb inum18.h)
14
- s.has_rdoc = false
13
+ s.files = %w(COPYING GPL INSTALL README.1st README TODO decimal.c decimal.gemspec
14
+ depend extconf.rb inum18.h inum191.h inum192.h lib/decimal.rb
15
+ lib/decimal/math.rb ruby18compat.h test_decimal.rb)
16
+ s.extra_rdoc_files = %w(README)
17
+ s.has_rdoc = true
15
18
  s.authors = "Tadashi Saito"
16
- s.email = "shiba@mail2.accsnet.ne.jp"
19
+ s.email = "tad.a.digger@gmail.com"
20
+ s.post_install_message = "\n\t\t" << IO.read("README.1st") << "\n"
17
21
  end
data/depend CHANGED
@@ -1,3 +1,3 @@
1
- decimal.o: decimal.c inum18.h \
1
+ decimal.o: decimal.c inum18.h inum191.h inum192.h ruby18compat.h \
2
2
  $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/missing.h \
3
3
  $(hdrdir)/intern.h $(hdrdir)/util.h
data/extconf.rb CHANGED
@@ -1,3 +1,17 @@
1
1
  require "mkmf"
2
+
2
3
  (cflags = arg_config("--cflags")) && $CFLAGS << " #{cflags}"
4
+ version = if have_macro("RUBY_VERSION", "version.h")
5
+ "18"
6
+ elsif try_compile("int rb_str_hash(VALUE);")
7
+ "191"
8
+ else
9
+ "192"
10
+ end
11
+ $CFLAGS << " -DINUM_SOURCE_FILE=" + %(\\"inum#{version}.h\\")
12
+ have_func "rb_big_div"
13
+ have_func "rb_big_modulo"
14
+ have_func "rb_bigzero_p"
15
+ have_func "rb_usascii_str_new"
16
+
3
17
  create_makefile "decimal"
data/inum18.h CHANGED
@@ -1,11 +1,11 @@
1
1
  /*
2
- * Ruby's Integer part from ruby_1_8, r15364.
2
+ * Ruby's Integer part from ruby_1_8, r28324.
3
3
  *
4
- * These are hand copies (with a few modification) taken from original
4
+ * These are hand copies (with few modifications) taken from original
5
5
  * Ruby's code in "numeric.c" and "bignum.c," so the copyrights are
6
6
  * held by matz and other contributors:
7
7
  *
8
- * Copyright (C) 1993-2008 Yukihiro Matsumoto
8
+ * Copyright (C) 1993-2010 Yukihiro Matsumoto
9
9
  *
10
10
  */
11
11
 
@@ -15,6 +15,28 @@
15
15
 
16
16
  #define BDIGITS(x) ((BDIGIT*)RBIGNUM(x)->digits)
17
17
 
18
+ #ifndef HAVE_RB_BIGZERO_P
19
+ #define BIGZEROP(x) (RBIGNUM(x)->len == 0 || \
20
+ (BDIGITS(x)[0] == 0 && \
21
+ (RBIGNUM(x)->len == 1 || bigzero_p(x))))
22
+
23
+ static int
24
+ bigzero_p(VALUE x)
25
+ {
26
+ long i;
27
+ for (i = 0; i < RBIGNUM(x)->len; ++i) {
28
+ if (BDIGITS(x)[i]) return 0;
29
+ }
30
+ return 1;
31
+ }
32
+
33
+ static int
34
+ rb_bigzero_p(VALUE x)
35
+ {
36
+ return BIGZEROP(x);
37
+ }
38
+ #endif /* !HAVE_RB_BIGZERO_P */
39
+
18
40
  static VALUE
19
41
  rb_big_cmp(VALUE x, VALUE y)
20
42
  {
@@ -65,7 +87,7 @@ rb_big_eq(VALUE x, VALUE y)
65
87
  }
66
88
 
67
89
  static VALUE
68
- big_uminus(VALUE x)
90
+ rb_big_uminus(VALUE x)
69
91
  {
70
92
  VALUE z = rb_big_clone(x);
71
93
 
@@ -87,10 +109,49 @@ rb_big_hash(VALUE x)
87
109
  return LONG2FIX(key);
88
110
  }
89
111
 
112
+ /* specially, copied from ruby_1_9_1 */
113
+ static VALUE
114
+ rb_big_odd_p(VALUE num)
115
+ {
116
+ if (BDIGITS(num)[0] & 1) {
117
+ return Qtrue;
118
+ }
119
+ return Qfalse;
120
+ }
121
+
90
122
  /*
91
123
  * copied from numeric.c
92
124
  */
93
125
 
126
+ static VALUE
127
+ flo_to_s(VALUE flt)
128
+ {
129
+ char buf[32];
130
+ double value = RFLOAT(flt)->value;
131
+ char *p, *e;
132
+
133
+ if (isinf(value))
134
+ return rb_str_new2(value < 0 ? "-Infinity" : "Infinity");
135
+ else if(isnan(value))
136
+ return rb_str_new2("NaN");
137
+
138
+ sprintf(buf, "%#.15g", value); /* ensure to print decimal point */
139
+ if (!(e = strchr(buf, 'e'))) {
140
+ e = buf + strlen(buf);
141
+ }
142
+ if (!ISDIGIT(e[-1])) { /* reformat if ended with decimal point (ex 111111111111111.) */
143
+ sprintf(buf, "%#.14e", value);
144
+ if (!(e = strchr(buf, 'e'))) {
145
+ e = buf + strlen(buf);
146
+ }
147
+ }
148
+ p = e;
149
+ while (p[-1]=='0' && ISDIGIT(p[-2]))
150
+ p--;
151
+ memmove(p, e, strlen(e)+1);
152
+ return rb_str_new2(buf);
153
+ }
154
+
94
155
  static VALUE
95
156
  fix_plus(VALUE x, VALUE y)
96
157
  {
@@ -129,6 +190,10 @@ static VALUE
129
190
  fix_mul(VALUE x, VALUE y)
130
191
  {
131
192
  if (FIXNUM_P(y)) {
193
+ #ifdef __HP_cc
194
+ /* avoids an optimization bug of HP aC++/ANSI C B3910B A.06.05 [Jul 25 2005] */
195
+ volatile
196
+ #endif
132
197
  long a, b, c;
133
198
  VALUE r;
134
199
 
@@ -184,7 +249,7 @@ fix_div(VALUE x, VALUE y)
184
249
  return LONG2NUM(div);
185
250
  }
186
251
  /* modified */
187
- return RARRAY(rb_big_divmod(rb_int2big(FIX2LONG(x)), y))->ptr[0];
252
+ return rb_big_div(rb_int2big(FIX2LONG(x)), y);
188
253
  }
189
254
 
190
255
  static VALUE
@@ -229,7 +294,7 @@ int_pow(long x, unsigned long y)
229
294
  long xz = x * z;
230
295
  if (!POSFIXABLE(xz) || xz / x != z) {
231
296
  goto bignum;
232
- }
297
+ }
233
298
  z = xz;
234
299
  }
235
300
  } while (--y);
@@ -249,7 +314,7 @@ fix_pow(VALUE x, VALUE y)
249
314
  if (b == 1) return x;
250
315
  if (a == 0) {
251
316
  if (b > 0) return INT2FIX(0);
252
- /* modified */
317
+ /* modified */
253
318
  rb_bug("fix_pow(): infinity returned");
254
319
  return Qnil;
255
320
  }
@@ -271,7 +336,7 @@ fix_pow(VALUE x, VALUE y)
271
336
  if (a == 0) return INT2FIX(0);
272
337
  if (a == 1) return INT2FIX(1);
273
338
  if (a == -1) {
274
- if ((BDIGITS(y)[0] & 1) == 0) return INT2FIX(1); /* modified */
339
+ if (!rb_big_odd_p(y)) return INT2FIX(1); /* modified */
275
340
  else return INT2FIX(-1);
276
341
  }
277
342
  x = rb_int2big(FIX2LONG(x));
@@ -300,3 +365,12 @@ fix_cmp(VALUE x, VALUE y)
300
365
  return rb_big_cmp(rb_int2big(FIX2LONG(x)), y); /* modified */
301
366
  }
302
367
  }
368
+
369
+ static VALUE
370
+ fix_odd_p(VALUE num)
371
+ {
372
+ if (num & 2) {
373
+ return Qtrue;
374
+ }
375
+ return Qfalse;
376
+ }
data/inum191.h ADDED
@@ -0,0 +1,350 @@
1
+ /*
2
+ * Ruby's Integer part from ruby_1_9_1, r27979.
3
+ *
4
+ * These are hand copies (with few modifications) taken from original
5
+ * Ruby's code in "numeric.c" and "bignum.c," so the copyrights are
6
+ * held by matz and other contributors:
7
+ *
8
+ * Copyright (C) 1993-2010 Yukihiro Matsumoto
9
+ *
10
+ */
11
+
12
+ /*
13
+ * copied from bignum.c
14
+ */
15
+
16
+ #define BDIGITS(x) (RBIGNUM_DIGITS(x))
17
+
18
+ #ifndef HAVE_RB_BIGZERO_P
19
+ #define BIGZEROP(x) (RBIGNUM_LEN(x) == 0 || \
20
+ (BDIGITS(x)[0] == 0 && \
21
+ (RBIGNUM_LEN(x) == 1 || bigzero_p(x))))
22
+
23
+ static int
24
+ bigzero_p(VALUE x)
25
+ {
26
+ long i;
27
+ for (i = RBIGNUM_LEN(x) - 1; 0 <= i; i--) {
28
+ if (BDIGITS(x)[i]) return 0;
29
+ }
30
+ return 1;
31
+ }
32
+
33
+ static int
34
+ rb_bigzero_p(VALUE x)
35
+ {
36
+ return BIGZEROP(x);
37
+ }
38
+ #endif /* !HAVE_RB_BIGZERO_P */
39
+
40
+ static VALUE
41
+ rb_big_uminus(VALUE x)
42
+ {
43
+ VALUE z = rb_big_clone(x);
44
+
45
+ RBIGNUM_SET_SIGN(z, !RBIGNUM_SIGN(x));
46
+
47
+ return rb_big_norm(z); /* modified to use exported one */
48
+ }
49
+
50
+ static VALUE
51
+ rb_big_hash(VALUE x)
52
+ {
53
+ int hash;
54
+
55
+ hash = rb_memhash(BDIGITS(x), sizeof(BDIGIT)*RBIGNUM_LEN(x)) ^ RBIGNUM_SIGN(x);
56
+ return INT2FIX(hash);
57
+ }
58
+
59
+ static VALUE
60
+ rb_big_odd_p(VALUE num)
61
+ {
62
+ if (BDIGITS(num)[0] & 1) {
63
+ return Qtrue;
64
+ }
65
+ return Qfalse;
66
+ }
67
+
68
+ /*
69
+ * copied from numeric.c
70
+ */
71
+
72
+ static VALUE
73
+ flo_to_s(VALUE flt)
74
+ {
75
+ char buf[32];
76
+ double value = RFLOAT_VALUE(flt);
77
+ char *p, *e;
78
+
79
+ if (isinf(value))
80
+ return rb_usascii_str_new2(value < 0 ? "-Infinity" : "Infinity");
81
+ else if(isnan(value))
82
+ return rb_usascii_str_new2("NaN");
83
+
84
+ snprintf(buf, sizeof(buf), "%#.15g", value); /* ensure to print decimal point */
85
+ if (!(e = strchr(buf, 'e'))) {
86
+ e = buf + strlen(buf);
87
+ }
88
+ if (!ISDIGIT(e[-1])) { /* reformat if ended with decimal point (ex 111111111111111.) */
89
+ snprintf(buf, sizeof(buf), "%#.14e", value);
90
+ if (!(e = strchr(buf, 'e'))) {
91
+ e = buf + strlen(buf);
92
+ }
93
+ }
94
+ p = e;
95
+ while (p[-1]=='0' && ISDIGIT(p[-2]))
96
+ p--;
97
+ memmove(p, e, strlen(e)+1);
98
+ return rb_usascii_str_new2(buf);
99
+ }
100
+
101
+ static VALUE
102
+ fix_plus(VALUE x, VALUE y)
103
+ {
104
+ if (FIXNUM_P(y)) {
105
+ long a, b, c;
106
+ VALUE r;
107
+
108
+ a = FIX2LONG(x);
109
+ b = FIX2LONG(y);
110
+ c = a + b;
111
+ r = LONG2NUM(c);
112
+
113
+ return r;
114
+ }
115
+ return rb_big_plus(y, x); /* modified */
116
+ }
117
+
118
+ static VALUE
119
+ fix_minus(VALUE x, VALUE y)
120
+ {
121
+ if (FIXNUM_P(y)) {
122
+ long a, b, c;
123
+ VALUE r;
124
+
125
+ a = FIX2LONG(x);
126
+ b = FIX2LONG(y);
127
+ c = a - b;
128
+ r = LONG2NUM(c);
129
+
130
+ return r;
131
+ }
132
+ /* modified */
133
+ x = rb_int2big(FIX2LONG(x));
134
+ return rb_big_minus(x, y);
135
+ }
136
+
137
+ #define SQRT_LONG_MAX ((SIGNED_VALUE)1<<((SIZEOF_LONG*CHAR_BIT-1)/2))
138
+ /*tests if N*N would overflow*/
139
+ #define FIT_SQRT_LONG(n) (((n)<SQRT_LONG_MAX)&&((n)>=-SQRT_LONG_MAX))
140
+
141
+ static VALUE
142
+ fix_mul(VALUE x, VALUE y)
143
+ {
144
+ if (FIXNUM_P(y)) {
145
+ #ifdef __HP_cc
146
+ /* avoids an optimization bug of HP aC++/ANSI C B3910B A.06.05 [Jul 25 2005] */
147
+ volatile
148
+ #endif
149
+ long a, b;
150
+ #if SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG
151
+ LONG_LONG d;
152
+ #else
153
+ long c;
154
+ VALUE r;
155
+ #endif
156
+
157
+ a = FIX2LONG(x);
158
+ b = FIX2LONG(y);
159
+
160
+ #if SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG
161
+ d = (LONG_LONG)a * b;
162
+ if (FIXABLE(d)) return LONG2FIX(d);
163
+ return rb_ll2inum(d);
164
+ #else
165
+ if (FIT_SQRT_LONG(a) && FIT_SQRT_LONG(b))
166
+ return LONG2FIX(a*b);
167
+ c = a * b;
168
+ r = LONG2FIX(c);
169
+
170
+ if (a == 0) return x;
171
+ if (FIX2LONG(r) != c || c/a != b) {
172
+ r = rb_big_mul(rb_int2big(a), rb_int2big(b));
173
+ }
174
+ return r;
175
+ #endif
176
+ }
177
+ /* modified */
178
+ return rb_big_mul(y, x);
179
+ }
180
+
181
+ static void
182
+ fixdivmod(long x, long y, long *divp, long *modp)
183
+ {
184
+ long div, mod;
185
+
186
+ if (y == 0) rb_bug("fixdivmod(): not reached"); /* modified */
187
+ if (y < 0) {
188
+ if (x < 0)
189
+ div = -x / -y;
190
+ else
191
+ div = - (x / -y);
192
+ }
193
+ else {
194
+ if (x < 0)
195
+ div = - (-x / y);
196
+ else
197
+ div = x / y;
198
+ }
199
+ mod = x - div*y;
200
+ if ((mod < 0 && y > 0) || (mod > 0 && y < 0)) {
201
+ mod += y;
202
+ div -= 1;
203
+ }
204
+ if (divp) *divp = div;
205
+ if (modp) *modp = mod;
206
+ }
207
+
208
+ /* extracted from fix_divide() */
209
+ static VALUE
210
+ fix_div(VALUE x, VALUE y)
211
+ {
212
+ if (FIXNUM_P(y)) {
213
+ long div;
214
+
215
+ fixdivmod(FIX2LONG(x), FIX2LONG(y), &div, 0);
216
+ return LONG2NUM(div);
217
+ }
218
+ /* modified */
219
+ x = rb_int2big(FIX2LONG(x));
220
+ return rb_big_div(x, y);
221
+ }
222
+
223
+ static VALUE
224
+ fix_divmod(VALUE x, VALUE y)
225
+ {
226
+ if (FIXNUM_P(y)) {
227
+ long div, mod;
228
+
229
+ fixdivmod(FIX2LONG(x), FIX2LONG(y), &div, &mod);
230
+
231
+ return rb_assoc_new(LONG2NUM(div), LONG2NUM(mod));
232
+ }
233
+ /* modified */
234
+ x = rb_int2big(FIX2LONG(x));
235
+ return rb_big_divmod(x, y);
236
+ }
237
+
238
+ static VALUE
239
+ int_pow(long x, unsigned long y)
240
+ {
241
+ int neg = x < 0;
242
+ long z = 1;
243
+
244
+ if (neg) x = -x;
245
+ if (y & 1)
246
+ z = x;
247
+ else
248
+ neg = 0;
249
+ y &= ~1;
250
+ do {
251
+ while (y % 2 == 0) {
252
+ if (!FIT_SQRT_LONG(x)) {
253
+ VALUE v;
254
+ bignum:
255
+ v = rb_big_pow(rb_int2big(x), LONG2NUM(y));
256
+ if (z != 1) v = rb_big_mul(rb_int2big(neg ? -z : z), v);
257
+ return v;
258
+ }
259
+ x = x * x;
260
+ y >>= 1;
261
+ }
262
+ {
263
+ long xz = x * z;
264
+ if (!POSFIXABLE(xz) || xz / x != z) {
265
+ goto bignum;
266
+ }
267
+ z = xz;
268
+ }
269
+ } while (--y);
270
+ if (neg) z = -z;
271
+ return LONG2NUM(z);
272
+ }
273
+
274
+ static VALUE fix_odd_p(VALUE num);
275
+
276
+ static VALUE
277
+ fix_pow(VALUE x, VALUE y)
278
+ {
279
+ /* static const double zero = 0.0; */
280
+ long a = FIX2LONG(x);
281
+
282
+ if (FIXNUM_P(y)) {
283
+ long b = FIX2LONG(y);
284
+
285
+ if (b < 0)
286
+ return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
287
+
288
+ if (b == 0) return INT2FIX(1);
289
+ if (b == 1) return x;
290
+ if (a == 0) {
291
+ if (b > 0) return INT2FIX(0);
292
+ /* modified */
293
+ rb_bug("fix_pow(): infinity returned");
294
+ return Qnil;
295
+ }
296
+ if (a == 1) return INT2FIX(1);
297
+ if (a == -1) {
298
+ if (b % 2 == 0)
299
+ return INT2FIX(1);
300
+ else
301
+ return INT2FIX(-1);
302
+ }
303
+ return int_pow(a, b);
304
+ }
305
+ /* modified */
306
+ if (rb_funcall(y, '<', 1, INT2FIX(0)))
307
+ return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
308
+
309
+ if (a == 0) return INT2FIX(0);
310
+ if (a == 1) return INT2FIX(1);
311
+ if (a == -1) {
312
+ /* modified */
313
+ #define int_even_p(x) \
314
+ (FIXNUM_P(x) ? !fix_odd_p(x) : !rb_big_odd_p(x))
315
+ if (int_even_p(y)) return INT2FIX(1);
316
+ #undef int_even_p
317
+ else return INT2FIX(-1);
318
+ }
319
+ x = rb_int2big(FIX2LONG(x));
320
+ return rb_big_pow(x, y);
321
+ }
322
+
323
+ static VALUE
324
+ fix_equal(VALUE x, VALUE y)
325
+ {
326
+ if (x == y) return Qtrue;
327
+ if (FIXNUM_P(y)) return Qfalse;
328
+ return rb_big_eq(y, x); /* modified */
329
+ }
330
+
331
+ static VALUE
332
+ fix_cmp(VALUE x, VALUE y)
333
+ {
334
+ if (x == y) return INT2FIX(0);
335
+ if (FIXNUM_P(y)) {
336
+ if (FIX2LONG(x) > FIX2LONG(y)) return INT2FIX(1);
337
+ return INT2FIX(-1);
338
+ }
339
+ /* modified */
340
+ return rb_big_cmp(rb_int2big(FIX2LONG(x)), y);
341
+ }
342
+
343
+ static VALUE
344
+ fix_odd_p(VALUE num)
345
+ {
346
+ if (num & 2) {
347
+ return Qtrue;
348
+ }
349
+ return Qfalse;
350
+ }