bigdecimal 1.2.7 → 1.3.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bigdecimal.gemspec +26 -18
- data/{bigdecimal.c → ext/bigdecimal/bigdecimal.c} +481 -340
- data/{bigdecimal.h → ext/bigdecimal/bigdecimal.h} +83 -10
- data/ext/bigdecimal/extconf.rb +35 -0
- data/lib/bigdecimal/jacobian.rb +1 -0
- data/lib/bigdecimal/ludcmp.rb +1 -0
- data/lib/bigdecimal/math.rb +10 -9
- data/lib/bigdecimal/newton.rb +1 -0
- data/lib/bigdecimal/util.rb +58 -51
- data/sample/linear.rb +12 -10
- data/sample/nlsolve.rb +6 -5
- data/sample/pi.rb +1 -0
- metadata +85 -14
- data/README +0 -60
- data/extconf.rb +0 -10
- data/{depend → ext/bigdecimal/depend} +1 -1
@@ -4,13 +4,6 @@
|
|
4
4
|
*
|
5
5
|
* Copyright(C) 2002 by Shigeo Kobayashi(shigeo@tinyforest.gr.jp)
|
6
6
|
*
|
7
|
-
* You may distribute under the terms of either the GNU General Public
|
8
|
-
* License or the Artistic License, as specified in the README file
|
9
|
-
* of this BigDecimal distribution.
|
10
|
-
*
|
11
|
-
* NOTE: Change log in this source removed to reduce source code size.
|
12
|
-
* See rev. 1.25 if needed.
|
13
|
-
*
|
14
7
|
*/
|
15
8
|
|
16
9
|
/* #define BIGDECIMAL_DEBUG 1 */
|
@@ -69,6 +62,7 @@ static ID id_ceil;
|
|
69
62
|
static ID id_floor;
|
70
63
|
static ID id_to_r;
|
71
64
|
static ID id_eq;
|
65
|
+
static ID id_half;
|
72
66
|
|
73
67
|
/* MACRO's to guard objects from GC by keeping them in stack */
|
74
68
|
#define ENTER(n) volatile VALUE RB_UNUSED_VAR(vStack[n]);int iStack=0
|
@@ -133,6 +127,9 @@ rb_rational_den(VALUE rat)
|
|
133
127
|
}
|
134
128
|
#endif
|
135
129
|
|
130
|
+
#define BIGDECIMAL_POSITIVE_P(bd) ((bd)->sign > 0)
|
131
|
+
#define BIGDECIMAL_NEGATIVE_P(bd) ((bd)->sign < 0)
|
132
|
+
|
136
133
|
/*
|
137
134
|
* ================== Ruby Interface part ==========================
|
138
135
|
*/
|
@@ -144,12 +141,16 @@ rb_rational_den(VALUE rat)
|
|
144
141
|
static VALUE
|
145
142
|
BigDecimal_version(VALUE self)
|
146
143
|
{
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
144
|
+
/*
|
145
|
+
* 1.0.0: Ruby 1.8.0
|
146
|
+
* 1.0.1: Ruby 1.8.1
|
147
|
+
* 1.1.0: Ruby 1.9.3
|
148
|
+
*/
|
149
|
+
#ifndef RUBY_BIGDECIMAL_VERSION
|
150
|
+
# error RUBY_BIGDECIMAL_VERSION is not defined
|
151
|
+
#endif
|
152
|
+
rb_warning("BigDecimal.ver is deprecated; use BigDecimal::VERSION instead.");
|
153
|
+
return rb_str_new2(RUBY_BIGDECIMAL_VERSION);
|
153
154
|
}
|
154
155
|
|
155
156
|
/*
|
@@ -179,7 +180,7 @@ static size_t
|
|
179
180
|
BigDecimal_memsize(const void *ptr)
|
180
181
|
{
|
181
182
|
const Real *pv = ptr;
|
182
|
-
return
|
183
|
+
return (sizeof(*pv) + pv->MaxPrec * sizeof(BDIGIT));
|
183
184
|
}
|
184
185
|
|
185
186
|
static const rb_data_type_t BigDecimal_data_type = {
|
@@ -234,6 +235,7 @@ static inline VALUE BigDecimal_div2(VALUE, VALUE, VALUE);
|
|
234
235
|
static Real*
|
235
236
|
GetVpValueWithPrec(VALUE v, long prec, int must)
|
236
237
|
{
|
238
|
+
ENTER(1);
|
237
239
|
Real *pv;
|
238
240
|
VALUE num, bg;
|
239
241
|
char szD[128];
|
@@ -246,6 +248,11 @@ again:
|
|
246
248
|
if (prec < 0) goto unable_to_coerce_without_prec;
|
247
249
|
if (prec > DBL_DIG+1) goto SomeOneMayDoIt;
|
248
250
|
d = RFLOAT_VALUE(v);
|
251
|
+
if (!isfinite(d)) {
|
252
|
+
pv = VpCreateRbObject(1, NULL);
|
253
|
+
VpDtoV(pv, d);
|
254
|
+
return pv;
|
255
|
+
}
|
249
256
|
if (d != 0.0) {
|
250
257
|
v = rb_funcall(v, id_to_r, 0);
|
251
258
|
goto again;
|
@@ -286,13 +293,15 @@ again:
|
|
286
293
|
|
287
294
|
#ifdef ENABLE_NUMERIC_STRING
|
288
295
|
case T_STRING:
|
289
|
-
|
290
|
-
|
296
|
+
StringValueCStr(v);
|
297
|
+
rb_check_safe_obj(v);
|
298
|
+
return VpCreateRbObject(RSTRING_LEN(v) + VpBaseFig() + 1,
|
291
299
|
RSTRING_PTR(v));
|
292
300
|
#endif /* ENABLE_NUMERIC_STRING */
|
293
301
|
|
294
302
|
case T_BIGNUM:
|
295
303
|
bg = rb_big2str(v, 10);
|
304
|
+
PUSH(bg);
|
296
305
|
return VpCreateRbObject(strlen(RSTRING_PTR(bg)) + VpBaseFig() + 1,
|
297
306
|
RSTRING_PTR(bg));
|
298
307
|
default:
|
@@ -333,15 +342,18 @@ BigDecimal_double_fig(VALUE self)
|
|
333
342
|
return INT2FIX(VpDblFig());
|
334
343
|
}
|
335
344
|
|
336
|
-
/*
|
337
|
-
*
|
345
|
+
/* call-seq:
|
346
|
+
* big_decimal.precs -> array
|
338
347
|
*
|
339
|
-
*
|
348
|
+
* Returns an Array of two Integer values.
|
340
349
|
*
|
341
|
-
*
|
342
|
-
*
|
343
|
-
*
|
350
|
+
* The first value is the current number of significant digits in the
|
351
|
+
* BigDecimal. The second value is the maximum number of significant digits
|
352
|
+
* for the BigDecimal.
|
353
|
+
*
|
354
|
+
* BigDecimal('5').precs #=> [9, 18]
|
344
355
|
*/
|
356
|
+
|
345
357
|
static VALUE
|
346
358
|
BigDecimal_prec(VALUE self)
|
347
359
|
{
|
@@ -377,7 +389,7 @@ BigDecimal_hash(VALUE self)
|
|
377
389
|
hash ^= rb_memhash(p->frac, sizeof(BDIGIT)*p->Prec);
|
378
390
|
hash += p->exponent;
|
379
391
|
}
|
380
|
-
return
|
392
|
+
return ST2FIX(hash);
|
381
393
|
}
|
382
394
|
|
383
395
|
/*
|
@@ -385,10 +397,10 @@ BigDecimal_hash(VALUE self)
|
|
385
397
|
*
|
386
398
|
* Method used to provide marshalling support.
|
387
399
|
*
|
388
|
-
* inf = BigDecimal
|
389
|
-
* #=>
|
400
|
+
* inf = BigDecimal('Infinity')
|
401
|
+
* #=> Infinity
|
390
402
|
* BigDecimal._load(inf._dump)
|
391
|
-
* #=>
|
403
|
+
* #=> Infinity
|
392
404
|
*
|
393
405
|
* See the Marshal module.
|
394
406
|
*/
|
@@ -423,8 +435,8 @@ BigDecimal_load(VALUE self, VALUE str)
|
|
423
435
|
unsigned char ch;
|
424
436
|
unsigned long m=0;
|
425
437
|
|
426
|
-
|
427
|
-
|
438
|
+
pch = (unsigned char *)StringValueCStr(str);
|
439
|
+
rb_check_safe_obj(str);
|
428
440
|
/* First get max prec */
|
429
441
|
while((*pch) != (unsigned char)'\0' && (ch = *pch++) != (unsigned char)':') {
|
430
442
|
if(!ISDIGIT(ch)) {
|
@@ -441,6 +453,55 @@ BigDecimal_load(VALUE self, VALUE str)
|
|
441
453
|
return ToValue(pv);
|
442
454
|
}
|
443
455
|
|
456
|
+
static unsigned short
|
457
|
+
check_rounding_mode_option(VALUE const opts)
|
458
|
+
{
|
459
|
+
VALUE mode;
|
460
|
+
char const *s;
|
461
|
+
long l;
|
462
|
+
|
463
|
+
assert(RB_TYPE_P(opts, T_HASH));
|
464
|
+
|
465
|
+
if (NIL_P(opts))
|
466
|
+
goto noopt;
|
467
|
+
|
468
|
+
mode = rb_hash_lookup2(opts, ID2SYM(id_half), Qundef);
|
469
|
+
if (mode == Qundef || NIL_P(mode))
|
470
|
+
goto noopt;
|
471
|
+
|
472
|
+
if (SYMBOL_P(mode))
|
473
|
+
mode = rb_sym2str(mode);
|
474
|
+
else if (!RB_TYPE_P(mode, T_STRING)) {
|
475
|
+
VALUE str_mode = rb_check_string_type(mode);
|
476
|
+
if (NIL_P(str_mode)) goto invalid;
|
477
|
+
mode = str_mode;
|
478
|
+
}
|
479
|
+
s = RSTRING_PTR(mode);
|
480
|
+
l = RSTRING_LEN(mode);
|
481
|
+
switch (l) {
|
482
|
+
case 2:
|
483
|
+
if (strncasecmp(s, "up", 2) == 0)
|
484
|
+
return VP_ROUND_HALF_UP;
|
485
|
+
break;
|
486
|
+
case 4:
|
487
|
+
if (strncasecmp(s, "even", 4) == 0)
|
488
|
+
return VP_ROUND_HALF_EVEN;
|
489
|
+
else if (strncasecmp(s, "down", 4) == 0)
|
490
|
+
return VP_ROUND_HALF_DOWN;
|
491
|
+
break;
|
492
|
+
default:
|
493
|
+
break;
|
494
|
+
}
|
495
|
+
invalid:
|
496
|
+
if (NIL_P(mode))
|
497
|
+
rb_raise(rb_eArgError, "invalid rounding mode: nil");
|
498
|
+
else
|
499
|
+
rb_raise(rb_eArgError, "invalid rounding mode: %"PRIsVALUE, mode);
|
500
|
+
|
501
|
+
noopt:
|
502
|
+
return VpGetRoundMode();
|
503
|
+
}
|
504
|
+
|
444
505
|
static unsigned short
|
445
506
|
check_rounding_mode(VALUE const v)
|
446
507
|
{
|
@@ -469,8 +530,7 @@ check_rounding_mode(VALUE const v)
|
|
469
530
|
break;
|
470
531
|
}
|
471
532
|
|
472
|
-
|
473
|
-
sw = (unsigned short)FIX2UINT(v);
|
533
|
+
sw = NUM2USHORT(v);
|
474
534
|
if (!VpIsRoundMode(sw)) {
|
475
535
|
rb_raise(rb_eArgError, "invalid rounding mode");
|
476
536
|
}
|
@@ -523,8 +583,7 @@ BigDecimal_mode(int argc, VALUE *argv, VALUE self)
|
|
523
583
|
unsigned long f,fo;
|
524
584
|
|
525
585
|
rb_scan_args(argc, argv, "11", &which, &val);
|
526
|
-
|
527
|
-
f = (unsigned long)FIX2INT(which);
|
586
|
+
f = (unsigned long)NUM2INT(which);
|
528
587
|
|
529
588
|
if (f & VP_EXCEPTION_ALL) {
|
530
589
|
/* Exception mode setting */
|
@@ -565,7 +624,7 @@ BigDecimal_mode(int argc, VALUE *argv, VALUE self)
|
|
565
624
|
fo = VpSetRoundMode(sw);
|
566
625
|
return INT2FIX(fo);
|
567
626
|
}
|
568
|
-
rb_raise(rb_eTypeError, "first argument for BigDecimal
|
627
|
+
rb_raise(rb_eTypeError, "first argument for BigDecimal.mode invalid");
|
569
628
|
return Qnil;
|
570
629
|
}
|
571
630
|
|
@@ -591,13 +650,12 @@ GetAddSubPrec(Real *a, Real *b)
|
|
591
650
|
}
|
592
651
|
|
593
652
|
static SIGNED_VALUE
|
594
|
-
|
653
|
+
GetPrecisionInt(VALUE v)
|
595
654
|
{
|
596
655
|
SIGNED_VALUE n;
|
597
|
-
|
598
|
-
n = FIX2INT(v);
|
656
|
+
n = NUM2INT(v);
|
599
657
|
if (n < 0) {
|
600
|
-
rb_raise(rb_eArgError, "
|
658
|
+
rb_raise(rb_eArgError, "negative precision");
|
601
659
|
}
|
602
660
|
return n;
|
603
661
|
}
|
@@ -605,17 +663,17 @@ GetPositiveInt(VALUE v)
|
|
605
663
|
VP_EXPORT Real *
|
606
664
|
VpNewRbClass(size_t mx, const char *str, VALUE klass)
|
607
665
|
{
|
666
|
+
VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
|
608
667
|
Real *pv = VpAlloc(mx,str);
|
609
|
-
|
668
|
+
RTYPEDDATA_DATA(obj) = pv;
|
669
|
+
pv->obj = obj;
|
610
670
|
return pv;
|
611
671
|
}
|
612
672
|
|
613
673
|
VP_EXPORT Real *
|
614
674
|
VpCreateRbObject(size_t mx, const char *str)
|
615
675
|
{
|
616
|
-
|
617
|
-
pv->obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, pv);
|
618
|
-
return pv;
|
676
|
+
return VpNewRbClass(mx, str, rb_cBigDecimal);
|
619
677
|
}
|
620
678
|
|
621
679
|
#define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(BDIGIT))
|
@@ -684,9 +742,9 @@ BigDecimal_check_num(Real *p)
|
|
684
742
|
|
685
743
|
static VALUE BigDecimal_split(VALUE self);
|
686
744
|
|
687
|
-
/* Returns the value as an
|
745
|
+
/* Returns the value as an Integer.
|
688
746
|
*
|
689
|
-
* If the
|
747
|
+
* If the BigDecimal is infinity or NaN, raises FloatDomainError.
|
690
748
|
*/
|
691
749
|
static VALUE
|
692
750
|
BigDecimal_to_i(VALUE self)
|
@@ -706,12 +764,12 @@ BigDecimal_to_i(VALUE self)
|
|
706
764
|
}
|
707
765
|
else {
|
708
766
|
VALUE a = BigDecimal_split(self);
|
709
|
-
VALUE digits =
|
767
|
+
VALUE digits = RARRAY_AREF(a, 1);
|
710
768
|
VALUE numerator = rb_funcall(digits, rb_intern("to_i"), 0);
|
711
769
|
VALUE ret;
|
712
770
|
ssize_t dpower = e - (ssize_t)RSTRING_LEN(digits);
|
713
771
|
|
714
|
-
if (
|
772
|
+
if (BIGDECIMAL_NEGATIVE_P(p)) {
|
715
773
|
numerator = rb_funcall(numerator, '*', 1, INT2FIX(-1));
|
716
774
|
}
|
717
775
|
if (dpower < 0) {
|
@@ -766,17 +824,17 @@ BigDecimal_to_f(VALUE self)
|
|
766
824
|
|
767
825
|
overflow:
|
768
826
|
VpException(VP_EXCEPTION_OVERFLOW, "BigDecimal to Float conversion", 0);
|
769
|
-
if (p
|
770
|
-
return rb_float_new(VpGetDoublePosInf());
|
771
|
-
else
|
827
|
+
if (BIGDECIMAL_NEGATIVE_P(p))
|
772
828
|
return rb_float_new(VpGetDoubleNegInf());
|
829
|
+
else
|
830
|
+
return rb_float_new(VpGetDoublePosInf());
|
773
831
|
|
774
832
|
underflow:
|
775
833
|
VpException(VP_EXCEPTION_UNDERFLOW, "BigDecimal to Float conversion", 0);
|
776
|
-
if (p
|
777
|
-
return rb_float_new(0.0);
|
778
|
-
else
|
834
|
+
if (BIGDECIMAL_NEGATIVE_P(p))
|
779
835
|
return rb_float_new(-0.0);
|
836
|
+
else
|
837
|
+
return rb_float_new(0.0);
|
780
838
|
}
|
781
839
|
|
782
840
|
|
@@ -795,7 +853,7 @@ BigDecimal_to_r(VALUE self)
|
|
795
853
|
sign = VpGetSign(p);
|
796
854
|
power = VpExponent10(p);
|
797
855
|
a = BigDecimal_split(self);
|
798
|
-
digits =
|
856
|
+
digits = RARRAY_AREF(a, 1);
|
799
857
|
denomi_power = power - RSTRING_LEN(digits);
|
800
858
|
numerator = rb_funcall(digits, rb_intern("to_i"), 0);
|
801
859
|
|
@@ -822,7 +880,7 @@ BigDecimal_to_r(VALUE self)
|
|
822
880
|
* be coerced into a BigDecimal value.
|
823
881
|
*
|
824
882
|
* e.g.
|
825
|
-
* a = BigDecimal
|
883
|
+
* a = BigDecimal("1.0")
|
826
884
|
* b = a / 2.0 #=> 0.5
|
827
885
|
*
|
828
886
|
* Note that coercing a String to a BigDecimal is not supported by default;
|
@@ -854,13 +912,14 @@ BigDecimal_coerce(VALUE self, VALUE other)
|
|
854
912
|
}
|
855
913
|
|
856
914
|
/*
|
857
|
-
* call-seq:
|
915
|
+
* call-seq:
|
916
|
+
* +big_decimal -> big_decimal
|
858
917
|
*
|
859
918
|
* Return self.
|
860
919
|
*
|
861
|
-
*
|
862
|
-
* b = +a # b == a
|
920
|
+
* +BigDecimal('5') #=> 0.5e1
|
863
921
|
*/
|
922
|
+
|
864
923
|
static VALUE
|
865
924
|
BigDecimal_uplus(VALUE self)
|
866
925
|
{
|
@@ -1110,7 +1169,7 @@ BigDecimal_comp(VALUE self, VALUE r)
|
|
1110
1169
|
*
|
1111
1170
|
* Values may be coerced to perform the comparison:
|
1112
1171
|
*
|
1113
|
-
* BigDecimal
|
1172
|
+
* BigDecimal('1.0') == 1.0 #=> true
|
1114
1173
|
*/
|
1115
1174
|
static VALUE
|
1116
1175
|
BigDecimal_eq(VALUE self, VALUE r)
|
@@ -1171,14 +1230,14 @@ BigDecimal_ge(VALUE self, VALUE r)
|
|
1171
1230
|
}
|
1172
1231
|
|
1173
1232
|
/*
|
1174
|
-
*
|
1233
|
+
* call-seq:
|
1234
|
+
* -big_decimal -> big_decimal
|
1175
1235
|
*
|
1176
|
-
*
|
1236
|
+
* Return the negation of self.
|
1177
1237
|
*
|
1178
|
-
*
|
1179
|
-
* b = -a
|
1180
|
-
* b == a * -1
|
1238
|
+
* -BigDecimal('5') #=> -0.5e1
|
1181
1239
|
*/
|
1240
|
+
|
1182
1241
|
static VALUE
|
1183
1242
|
BigDecimal_neg(VALUE self)
|
1184
1243
|
{
|
@@ -1266,25 +1325,14 @@ BigDecimal_divide(Real **c, Real **res, Real **div, VALUE self, VALUE r)
|
|
1266
1325
|
return Qnil;
|
1267
1326
|
}
|
1268
1327
|
|
1269
|
-
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
*
|
1278
|
-
* digits:: If specified and less than the number of significant digits of the
|
1279
|
-
* result, the result is rounded to that number of digits, according
|
1280
|
-
* to BigDecimal.mode.
|
1281
|
-
*
|
1282
|
-
* If digits is 0, the result is the same as the / operator. If not, the
|
1283
|
-
* result is an integer BigDecimal, by analogy with Float#div.
|
1284
|
-
*
|
1285
|
-
* The alias quo is provided since <code>div(value, 0)</code> is the same as
|
1286
|
-
* computing the quotient; see BigDecimal#divmod.
|
1287
|
-
*/
|
1328
|
+
/* call-seq:
|
1329
|
+
* a / b -> bigdecimal
|
1330
|
+
* quo(value) -> bigdecimal
|
1331
|
+
*
|
1332
|
+
* Divide by the specified value.
|
1333
|
+
*
|
1334
|
+
* See BigDecimal#div.
|
1335
|
+
*/
|
1288
1336
|
static VALUE
|
1289
1337
|
BigDecimal_div(VALUE self, VALUE r)
|
1290
1338
|
/* For c = self/r: with round operation */
|
@@ -1483,8 +1531,8 @@ BigDecimal_remainder(VALUE self, VALUE r) /* remainder */
|
|
1483
1531
|
*
|
1484
1532
|
* require 'bigdecimal'
|
1485
1533
|
*
|
1486
|
-
* a = BigDecimal
|
1487
|
-
* b = BigDecimal
|
1534
|
+
* a = BigDecimal("42")
|
1535
|
+
* b = BigDecimal("9")
|
1488
1536
|
*
|
1489
1537
|
* q, m = a.divmod(b)
|
1490
1538
|
*
|
@@ -1527,7 +1575,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
|
|
1527
1575
|
}
|
1528
1576
|
|
1529
1577
|
/* div in BigDecimal sense */
|
1530
|
-
ix =
|
1578
|
+
ix = GetPrecisionInt(n);
|
1531
1579
|
if (ix == 0) {
|
1532
1580
|
return BigDecimal_div(self, b);
|
1533
1581
|
}
|
@@ -1537,7 +1585,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
|
|
1537
1585
|
size_t mx = ix + VpBaseFig()*2;
|
1538
1586
|
size_t pl = VpSetPrecLimit(0);
|
1539
1587
|
|
1540
|
-
GUARD_OBJ(cv, VpCreateRbObject(mx, "0"));
|
1588
|
+
GUARD_OBJ(cv, VpCreateRbObject(mx + VpBaseFig(), "0"));
|
1541
1589
|
GUARD_OBJ(av, GetVpValue(self, 1));
|
1542
1590
|
GUARD_OBJ(bv, GetVpValue(b, 1));
|
1543
1591
|
mx = av->Prec + bv->Prec + 2;
|
@@ -1550,6 +1598,37 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
|
|
1550
1598
|
}
|
1551
1599
|
}
|
1552
1600
|
|
1601
|
+
/*
|
1602
|
+
* Document-method: BigDecimal#div
|
1603
|
+
*
|
1604
|
+
* call-seq:
|
1605
|
+
* div(value, digits) -> bigdecimal or integer
|
1606
|
+
*
|
1607
|
+
* Divide by the specified value.
|
1608
|
+
*
|
1609
|
+
* digits:: If specified and less than the number of significant digits of the
|
1610
|
+
* result, the result is rounded to that number of digits, according
|
1611
|
+
* to BigDecimal.mode.
|
1612
|
+
*
|
1613
|
+
* If digits is 0, the result is the same as for the / operator
|
1614
|
+
* or #quo.
|
1615
|
+
*
|
1616
|
+
* If digits is not specified, the result is an integer,
|
1617
|
+
* by analogy with Float#div; see also BigDecimal#divmod.
|
1618
|
+
*
|
1619
|
+
* Examples:
|
1620
|
+
*
|
1621
|
+
* a = BigDecimal("4")
|
1622
|
+
* b = BigDecimal("3")
|
1623
|
+
*
|
1624
|
+
* a.div(b, 3) # => 0.133e1
|
1625
|
+
*
|
1626
|
+
* a.div(b, 0) # => 0.1333333333333333333e1
|
1627
|
+
* a / b # => 0.1333333333333333333e1
|
1628
|
+
* a.quo(b) # => 0.1333333333333333333e1
|
1629
|
+
*
|
1630
|
+
* a.div(b) # => 1
|
1631
|
+
*/
|
1553
1632
|
static VALUE
|
1554
1633
|
BigDecimal_div3(int argc, VALUE *argv, VALUE self)
|
1555
1634
|
{
|
@@ -1565,7 +1644,7 @@ BigDecimal_add2(VALUE self, VALUE b, VALUE n)
|
|
1565
1644
|
{
|
1566
1645
|
ENTER(2);
|
1567
1646
|
Real *cv;
|
1568
|
-
SIGNED_VALUE mx =
|
1647
|
+
SIGNED_VALUE mx = GetPrecisionInt(n);
|
1569
1648
|
if (mx == 0) return BigDecimal_add(self, b);
|
1570
1649
|
else {
|
1571
1650
|
size_t pl = VpSetPrecLimit(0);
|
@@ -1595,7 +1674,7 @@ BigDecimal_sub2(VALUE self, VALUE b, VALUE n)
|
|
1595
1674
|
{
|
1596
1675
|
ENTER(2);
|
1597
1676
|
Real *cv;
|
1598
|
-
SIGNED_VALUE mx =
|
1677
|
+
SIGNED_VALUE mx = GetPrecisionInt(n);
|
1599
1678
|
if (mx == 0) return BigDecimal_sub(self, b);
|
1600
1679
|
else {
|
1601
1680
|
size_t pl = VpSetPrecLimit(0);
|
@@ -1613,7 +1692,7 @@ BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
|
|
1613
1692
|
{
|
1614
1693
|
ENTER(2);
|
1615
1694
|
Real *cv;
|
1616
|
-
SIGNED_VALUE mx =
|
1695
|
+
SIGNED_VALUE mx = GetPrecisionInt(n);
|
1617
1696
|
if (mx == 0) return BigDecimal_mult(self, b);
|
1618
1697
|
else {
|
1619
1698
|
size_t pl = VpSetPrecLimit(0);
|
@@ -1625,11 +1704,16 @@ BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
|
|
1625
1704
|
}
|
1626
1705
|
}
|
1627
1706
|
|
1628
|
-
/*
|
1707
|
+
/*
|
1708
|
+
* call-seq:
|
1709
|
+
* big_decimal.abs -> big_decimal
|
1710
|
+
*
|
1711
|
+
* Returns the absolute value, as a BigDecimal.
|
1629
1712
|
*
|
1630
|
-
*
|
1631
|
-
*
|
1713
|
+
* BigDecimal('5').abs #=> 0.5e1
|
1714
|
+
* BigDecimal('-3').abs #=> 0.3e1
|
1632
1715
|
*/
|
1716
|
+
|
1633
1717
|
static VALUE
|
1634
1718
|
BigDecimal_abs(VALUE self)
|
1635
1719
|
{
|
@@ -1662,7 +1746,7 @@ BigDecimal_sqrt(VALUE self, VALUE nFig)
|
|
1662
1746
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1663
1747
|
mx = a->Prec * (VpBaseFig() + 1);
|
1664
1748
|
|
1665
|
-
n =
|
1749
|
+
n = GetPrecisionInt(nFig) + VpDblFig() + BASE_FIG;
|
1666
1750
|
if (mx <= n) mx = n;
|
1667
1751
|
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
1668
1752
|
VpSqrt(c, a);
|
@@ -1724,13 +1808,21 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
|
|
1724
1808
|
iLoc = 0;
|
1725
1809
|
break;
|
1726
1810
|
case 1:
|
1727
|
-
|
1728
|
-
|
1811
|
+
if (RB_TYPE_P(vLoc, T_HASH)) {
|
1812
|
+
sw = check_rounding_mode_option(vLoc);
|
1813
|
+
}
|
1814
|
+
else {
|
1815
|
+
iLoc = NUM2INT(vLoc);
|
1816
|
+
}
|
1729
1817
|
break;
|
1730
1818
|
case 2:
|
1731
|
-
|
1732
|
-
|
1733
|
-
|
1819
|
+
iLoc = NUM2INT(vLoc);
|
1820
|
+
if (RB_TYPE_P(vRound, T_HASH)) {
|
1821
|
+
sw = check_rounding_mode_option(vRound);
|
1822
|
+
}
|
1823
|
+
else {
|
1824
|
+
sw = check_rounding_mode(vRound);
|
1825
|
+
}
|
1734
1826
|
break;
|
1735
1827
|
default:
|
1736
1828
|
break;
|
@@ -1780,8 +1872,7 @@ BigDecimal_truncate(int argc, VALUE *argv, VALUE self)
|
|
1780
1872
|
iLoc = 0;
|
1781
1873
|
}
|
1782
1874
|
else {
|
1783
|
-
|
1784
|
-
iLoc = FIX2INT(vLoc);
|
1875
|
+
iLoc = NUM2INT(vLoc);
|
1785
1876
|
}
|
1786
1877
|
|
1787
1878
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
@@ -1841,8 +1932,7 @@ BigDecimal_floor(int argc, VALUE *argv, VALUE self)
|
|
1841
1932
|
iLoc = 0;
|
1842
1933
|
}
|
1843
1934
|
else {
|
1844
|
-
|
1845
|
-
iLoc = FIX2INT(vLoc);
|
1935
|
+
iLoc = NUM2INT(vLoc);
|
1846
1936
|
}
|
1847
1937
|
|
1848
1938
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
@@ -1888,8 +1978,7 @@ BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
|
|
1888
1978
|
if (rb_scan_args(argc, argv, "01", &vLoc) == 0) {
|
1889
1979
|
iLoc = 0;
|
1890
1980
|
} else {
|
1891
|
-
|
1892
|
-
iLoc = FIX2INT(vLoc);
|
1981
|
+
iLoc = NUM2INT(vLoc);
|
1893
1982
|
}
|
1894
1983
|
|
1895
1984
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
@@ -1927,34 +2016,35 @@ BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
|
|
1927
2016
|
*
|
1928
2017
|
* Examples:
|
1929
2018
|
*
|
1930
|
-
* BigDecimal
|
2019
|
+
* BigDecimal('-123.45678901234567890').to_s('5F')
|
1931
2020
|
* #=> '-123.45678 90123 45678 9'
|
1932
2021
|
*
|
1933
|
-
* BigDecimal
|
2022
|
+
* BigDecimal('123.45678901234567890').to_s('+8F')
|
1934
2023
|
* #=> '+123.45678901 23456789'
|
1935
2024
|
*
|
1936
|
-
* BigDecimal
|
2025
|
+
* BigDecimal('123.45678901234567890').to_s(' F')
|
1937
2026
|
* #=> ' 123.4567890123456789'
|
1938
2027
|
*/
|
1939
2028
|
static VALUE
|
1940
2029
|
BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
|
1941
2030
|
{
|
1942
2031
|
ENTER(5);
|
1943
|
-
int fmt = 0; /* 0:E format */
|
1944
|
-
int fPlus = 0; /*
|
2032
|
+
int fmt = 0; /* 0: E format, 1: F format */
|
2033
|
+
int fPlus = 0; /* 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
|
1945
2034
|
Real *vp;
|
1946
2035
|
volatile VALUE str;
|
1947
2036
|
char *psz;
|
1948
2037
|
char ch;
|
1949
2038
|
size_t nc, mc = 0;
|
2039
|
+
SIGNED_VALUE m;
|
1950
2040
|
VALUE f;
|
1951
2041
|
|
1952
2042
|
GUARD_OBJ(vp, GetVpValue(self, 1));
|
1953
2043
|
|
1954
2044
|
if (rb_scan_args(argc, argv, "01", &f) == 1) {
|
1955
2045
|
if (RB_TYPE_P(f, T_STRING)) {
|
1956
|
-
|
1957
|
-
|
2046
|
+
psz = StringValueCStr(f);
|
2047
|
+
rb_check_safe_obj(f);
|
1958
2048
|
if (*psz == ' ') {
|
1959
2049
|
fPlus = 1;
|
1960
2050
|
psz++;
|
@@ -1977,7 +2067,11 @@ BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
|
|
1977
2067
|
}
|
1978
2068
|
}
|
1979
2069
|
else {
|
1980
|
-
|
2070
|
+
m = NUM2INT(f);
|
2071
|
+
if (m <= 0) {
|
2072
|
+
rb_raise(rb_eArgError, "argument must be positive");
|
2073
|
+
}
|
2074
|
+
mc = (size_t)m;
|
1981
2075
|
}
|
1982
2076
|
}
|
1983
2077
|
if (fmt) {
|
@@ -2074,8 +2168,8 @@ BigDecimal_exponent(VALUE self)
|
|
2074
2168
|
/* Returns debugging information about the value as a string of comma-separated
|
2075
2169
|
* values in angle brackets with a leading #:
|
2076
2170
|
*
|
2077
|
-
* BigDecimal
|
2078
|
-
* #=> "
|
2171
|
+
* BigDecimal("1234.5678").inspect
|
2172
|
+
* #=> "0.12345678e4"
|
2079
2173
|
*
|
2080
2174
|
* The first part is the address, the second is the value as a string, and
|
2081
2175
|
* the final part ss(mm) is the current number of significant digits and the
|
@@ -2086,23 +2180,16 @@ BigDecimal_inspect(VALUE self)
|
|
2086
2180
|
{
|
2087
2181
|
ENTER(5);
|
2088
2182
|
Real *vp;
|
2089
|
-
volatile VALUE
|
2183
|
+
volatile VALUE str;
|
2090
2184
|
size_t nc;
|
2091
|
-
char *psz, *tmp;
|
2092
2185
|
|
2093
2186
|
GUARD_OBJ(vp, GetVpValue(self, 1));
|
2094
2187
|
nc = VpNumOfChars(vp, "E");
|
2095
|
-
|
2096
|
-
|
2097
|
-
|
2098
|
-
|
2099
|
-
|
2100
|
-
tmp = psz + strlen(psz);
|
2101
|
-
VpToString(vp, tmp, 10, 0);
|
2102
|
-
tmp += strlen(tmp);
|
2103
|
-
sprintf(tmp, "',%"PRIuSIZE"(%"PRIuSIZE")>", VpPrec(vp)*VpBaseFig(), VpMaxPrec(vp)*VpBaseFig());
|
2104
|
-
rb_str_resize(obj, strlen(psz));
|
2105
|
-
return obj;
|
2188
|
+
|
2189
|
+
str = rb_str_new(0, nc);
|
2190
|
+
VpToString(vp, RSTRING_PTR(str), 0, 0);
|
2191
|
+
rb_str_resize(str, strlen(RSTRING_PTR(str)));
|
2192
|
+
return str;
|
2106
2193
|
}
|
2107
2194
|
|
2108
2195
|
static VALUE BigMath_s_exp(VALUE, VALUE, VALUE);
|
@@ -2312,7 +2399,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2312
2399
|
if (is_negative(vexp)) {
|
2313
2400
|
y = VpCreateRbObject(n, "#0");
|
2314
2401
|
RB_GC_GUARD(y->obj);
|
2315
|
-
if (
|
2402
|
+
if (BIGDECIMAL_NEGATIVE_P(x)) {
|
2316
2403
|
if (is_integer(vexp)) {
|
2317
2404
|
if (is_even(vexp)) {
|
2318
2405
|
/* (-0) ** (-even_integer) -> Infinity */
|
@@ -2351,7 +2438,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2351
2438
|
|
2352
2439
|
if (VpIsInf(x)) {
|
2353
2440
|
if (is_negative(vexp)) {
|
2354
|
-
if (
|
2441
|
+
if (BIGDECIMAL_NEGATIVE_P(x)) {
|
2355
2442
|
if (is_integer(vexp)) {
|
2356
2443
|
if (is_even(vexp)) {
|
2357
2444
|
/* (-Infinity) ** (-even_integer) -> +0 */
|
@@ -2373,7 +2460,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2373
2460
|
}
|
2374
2461
|
else {
|
2375
2462
|
y = VpCreateRbObject(n, "0#");
|
2376
|
-
if (
|
2463
|
+
if (BIGDECIMAL_NEGATIVE_P(x)) {
|
2377
2464
|
if (is_integer(vexp)) {
|
2378
2465
|
if (is_even(vexp)) {
|
2379
2466
|
VpSetPosInf(y);
|
@@ -2414,7 +2501,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2414
2501
|
}
|
2415
2502
|
return ToValue(y);
|
2416
2503
|
}
|
2417
|
-
else if (
|
2504
|
+
else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
|
2418
2505
|
return ToValue(VpCreateRbObject(n, "-0"));
|
2419
2506
|
}
|
2420
2507
|
else {
|
@@ -2432,7 +2519,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2432
2519
|
}
|
2433
2520
|
return ToValue(y);
|
2434
2521
|
}
|
2435
|
-
else if (
|
2522
|
+
else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
|
2436
2523
|
return ToValue(VpCreateRbObject(n, "-0"));
|
2437
2524
|
}
|
2438
2525
|
else {
|
@@ -2492,7 +2579,7 @@ static Real *BigDecimal_new(int argc, VALUE *argv);
|
|
2492
2579
|
* If it is a String, spaces are ignored and unrecognized characters
|
2493
2580
|
* terminate the value.
|
2494
2581
|
*
|
2495
|
-
* digits:: The number of significant digits, as
|
2582
|
+
* digits:: The number of significant digits, as an Integer. If omitted or 0,
|
2496
2583
|
* the number of significant digits is determined from the initial
|
2497
2584
|
* value.
|
2498
2585
|
*
|
@@ -2501,10 +2588,10 @@ static Real *BigDecimal_new(int argc, VALUE *argv);
|
|
2501
2588
|
*
|
2502
2589
|
* ==== Exceptions
|
2503
2590
|
*
|
2504
|
-
* TypeError:: If the +initial+ type is neither
|
2591
|
+
* TypeError:: If the +initial+ type is neither Integer, Float,
|
2505
2592
|
* Rational, nor BigDecimal, this exception is raised.
|
2506
2593
|
*
|
2507
|
-
* TypeError:: If the +digits+ is not
|
2594
|
+
* TypeError:: If the +digits+ is not an Integer, this exception is raised.
|
2508
2595
|
*
|
2509
2596
|
* ArgumentError:: If +initial+ is a Float, and the +digits+ is larger than
|
2510
2597
|
* Float::DIG + 1, this exception is raised.
|
@@ -2512,6 +2599,13 @@ static Real *BigDecimal_new(int argc, VALUE *argv);
|
|
2512
2599
|
* ArgumentError:: If the +initial+ is a Float or Rational, and the +digits+
|
2513
2600
|
* value is omitted, this exception is raised.
|
2514
2601
|
*/
|
2602
|
+
static VALUE
|
2603
|
+
BigDecimal_s_new(int argc, VALUE *argv, VALUE self)
|
2604
|
+
{
|
2605
|
+
rb_warning("BigDecimal.new is deprecated; use Kernel.BigDecimal method instead.");
|
2606
|
+
return rb_call_super(argc, argv);
|
2607
|
+
}
|
2608
|
+
|
2515
2609
|
static VALUE
|
2516
2610
|
BigDecimal_initialize(int argc, VALUE *argv, VALUE self)
|
2517
2611
|
{
|
@@ -2534,7 +2628,7 @@ BigDecimal_initialize(int argc, VALUE *argv, VALUE self)
|
|
2534
2628
|
|
2535
2629
|
/* :nodoc:
|
2536
2630
|
*
|
2537
|
-
* private method
|
2631
|
+
* private method for dup and clone the provided BigDecimal +other+
|
2538
2632
|
*/
|
2539
2633
|
static VALUE
|
2540
2634
|
BigDecimal_initialize_copy(VALUE self, VALUE other)
|
@@ -2548,18 +2642,25 @@ BigDecimal_initialize_copy(VALUE self, VALUE other)
|
|
2548
2642
|
return self;
|
2549
2643
|
}
|
2550
2644
|
|
2645
|
+
static VALUE
|
2646
|
+
BigDecimal_clone(VALUE self)
|
2647
|
+
{
|
2648
|
+
return self;
|
2649
|
+
}
|
2650
|
+
|
2551
2651
|
static Real *
|
2552
2652
|
BigDecimal_new(int argc, VALUE *argv)
|
2553
2653
|
{
|
2554
2654
|
size_t mf;
|
2555
2655
|
VALUE nFig;
|
2556
2656
|
VALUE iniValue;
|
2657
|
+
double d;
|
2557
2658
|
|
2558
2659
|
if (rb_scan_args(argc, argv, "11", &iniValue, &nFig) == 1) {
|
2559
2660
|
mf = 0;
|
2560
2661
|
}
|
2561
2662
|
else {
|
2562
|
-
mf =
|
2663
|
+
mf = GetPrecisionInt(nFig);
|
2563
2664
|
}
|
2564
2665
|
|
2565
2666
|
switch (TYPE(iniValue)) {
|
@@ -2575,6 +2676,12 @@ BigDecimal_new(int argc, VALUE *argv)
|
|
2575
2676
|
return GetVpValue(iniValue, 1);
|
2576
2677
|
|
2577
2678
|
case T_FLOAT:
|
2679
|
+
d = RFLOAT_VALUE(iniValue);
|
2680
|
+
if (!isfinite(d)) {
|
2681
|
+
Real *pv = VpCreateRbObject(1, NULL);
|
2682
|
+
VpDtoV(pv, d);
|
2683
|
+
return pv;
|
2684
|
+
}
|
2578
2685
|
if (mf > DBL_DIG+1) {
|
2579
2686
|
rb_raise(rb_eArgError, "precision too large.");
|
2580
2687
|
}
|
@@ -2602,11 +2709,13 @@ BigDecimal_global_new(int argc, VALUE *argv, VALUE self)
|
|
2602
2709
|
{
|
2603
2710
|
ENTER(1);
|
2604
2711
|
Real *pv;
|
2712
|
+
VALUE obj;
|
2605
2713
|
|
2714
|
+
obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0);
|
2606
2715
|
GUARD_OBJ(pv, BigDecimal_new(argc, argv));
|
2607
2716
|
if (ToValue(pv)) pv = VpCopy(NULL, pv);
|
2608
|
-
|
2609
|
-
return pv->obj;
|
2717
|
+
RTYPEDDATA_DATA(obj) = pv;
|
2718
|
+
return pv->obj = obj;
|
2610
2719
|
}
|
2611
2720
|
|
2612
2721
|
/* call-seq:
|
@@ -2630,8 +2739,7 @@ BigDecimal_limit(int argc, VALUE *argv, VALUE self)
|
|
2630
2739
|
if (rb_scan_args(argc, argv, "01", &nFig) == 1) {
|
2631
2740
|
int nf;
|
2632
2741
|
if (NIL_P(nFig)) return nCur;
|
2633
|
-
|
2634
|
-
nf = FIX2INT(nFig);
|
2742
|
+
nf = NUM2INT(nFig);
|
2635
2743
|
if (nf < 0) {
|
2636
2744
|
rb_raise(rb_eArgError, "argument must be positive");
|
2637
2745
|
}
|
@@ -2672,9 +2780,9 @@ BigDecimal_sign(VALUE self)
|
|
2672
2780
|
* BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
|
2673
2781
|
* BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
|
2674
2782
|
*
|
2675
|
-
* BigDecimal
|
2676
|
-
* BigDecimal
|
2677
|
-
* BigDecimal(BigDecimal
|
2783
|
+
* BigDecimal(BigDecimal('Infinity'))
|
2784
|
+
* BigDecimal(BigDecimal('-Infinity'))
|
2785
|
+
* BigDecimal(BigDecimal('NaN'))
|
2678
2786
|
* end
|
2679
2787
|
*
|
2680
2788
|
* For use with the BigDecimal::EXCEPTION_*
|
@@ -2768,13 +2876,13 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
|
|
2768
2876
|
rb_raise(rb_eArgError, "Zero or negative precision for exp");
|
2769
2877
|
}
|
2770
2878
|
|
2771
|
-
/* TODO: the following switch statement is
|
2879
|
+
/* TODO: the following switch statement is almost same as one in the
|
2772
2880
|
* BigDecimalCmp function. */
|
2773
2881
|
switch (TYPE(x)) {
|
2774
2882
|
case T_DATA:
|
2775
2883
|
if (!is_kind_of_BigDecimal(x)) break;
|
2776
2884
|
vx = DATA_PTR(x);
|
2777
|
-
negative =
|
2885
|
+
negative = BIGDECIMAL_NEGATIVE_P(vx);
|
2778
2886
|
infinite = VpIsPosInf(vx) || VpIsNegInf(vx);
|
2779
2887
|
nan = VpIsNaN(vx);
|
2780
2888
|
break;
|
@@ -2827,7 +2935,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
|
|
2827
2935
|
x = vx->obj;
|
2828
2936
|
|
2829
2937
|
n = prec + rmpd_double_figures();
|
2830
|
-
negative =
|
2938
|
+
negative = BIGDECIMAL_NEGATIVE_P(vx);
|
2831
2939
|
if (negative) {
|
2832
2940
|
VpSetSign(vx, 1);
|
2833
2941
|
}
|
@@ -2906,14 +3014,14 @@ BigMath_s_log(VALUE klass, VALUE x, VALUE vprec)
|
|
2906
3014
|
rb_raise(rb_eArgError, "Zero or negative precision for exp");
|
2907
3015
|
}
|
2908
3016
|
|
2909
|
-
/* TODO: the following switch statement is
|
3017
|
+
/* TODO: the following switch statement is almost same as one in the
|
2910
3018
|
* BigDecimalCmp function. */
|
2911
3019
|
switch (TYPE(x)) {
|
2912
3020
|
case T_DATA:
|
2913
3021
|
if (!is_kind_of_BigDecimal(x)) break;
|
2914
3022
|
vx = DATA_PTR(x);
|
2915
3023
|
zero = VpIsZero(vx);
|
2916
|
-
negative =
|
3024
|
+
negative = BIGDECIMAL_NEGATIVE_P(vx);
|
2917
3025
|
infinite = VpIsPosInf(vx) || VpIsNegInf(vx);
|
2918
3026
|
nan = VpIsNaN(vx);
|
2919
3027
|
break;
|
@@ -3061,15 +3169,15 @@ get_vp_value:
|
|
3061
3169
|
*
|
3062
3170
|
* require 'bigdecimal'
|
3063
3171
|
*
|
3064
|
-
* sum = BigDecimal
|
3172
|
+
* sum = BigDecimal("0")
|
3065
3173
|
* 10_000.times do
|
3066
|
-
* sum = sum + BigDecimal
|
3174
|
+
* sum = sum + BigDecimal("0.0001")
|
3067
3175
|
* end
|
3068
3176
|
* print sum #=> 0.1E1
|
3069
3177
|
*
|
3070
3178
|
* Similarly:
|
3071
3179
|
*
|
3072
|
-
* (BigDecimal
|
3180
|
+
* (BigDecimal("1.2") - BigDecimal("1.0")) == BigDecimal("0.2") #=> true
|
3073
3181
|
*
|
3074
3182
|
* (1.2 - 1.0) == 0.2 #=> false
|
3075
3183
|
*
|
@@ -3083,8 +3191,8 @@ get_vp_value:
|
|
3083
3191
|
* BigDecimal sometimes needs to return infinity, for example if you divide
|
3084
3192
|
* a value by zero.
|
3085
3193
|
*
|
3086
|
-
* BigDecimal
|
3087
|
-
* BigDecimal
|
3194
|
+
* BigDecimal("1.0") / BigDecimal("0.0") #=> Infinity
|
3195
|
+
* BigDecimal("-1.0") / BigDecimal("0.0") #=> -Infinity
|
3088
3196
|
*
|
3089
3197
|
* You can represent infinite numbers to BigDecimal using the strings
|
3090
3198
|
* <code>'Infinity'</code>, <code>'+Infinity'</code> and
|
@@ -3097,13 +3205,13 @@ get_vp_value:
|
|
3097
3205
|
*
|
3098
3206
|
* Example:
|
3099
3207
|
*
|
3100
|
-
* BigDecimal
|
3208
|
+
* BigDecimal("0.0") / BigDecimal("0.0") #=> NaN
|
3101
3209
|
*
|
3102
3210
|
* You can also create undefined values.
|
3103
3211
|
*
|
3104
3212
|
* NaN is never considered to be the same as any other value, even NaN itself:
|
3105
3213
|
*
|
3106
|
-
* n = BigDecimal
|
3214
|
+
* n = BigDecimal('NaN')
|
3107
3215
|
* n == 0.0 #=> false
|
3108
3216
|
* n == n #=> false
|
3109
3217
|
*
|
@@ -3116,11 +3224,11 @@ get_vp_value:
|
|
3116
3224
|
* If the value which is too small to be represented is negative, a BigDecimal
|
3117
3225
|
* value of negative zero is returned.
|
3118
3226
|
*
|
3119
|
-
* BigDecimal
|
3227
|
+
* BigDecimal("1.0") / BigDecimal("-Infinity") #=> -0.0
|
3120
3228
|
*
|
3121
3229
|
* If the value is positive, a value of positive zero is returned.
|
3122
3230
|
*
|
3123
|
-
* BigDecimal
|
3231
|
+
* BigDecimal("1.0") / BigDecimal("Infinity") #=> 0.0
|
3124
3232
|
*
|
3125
3233
|
* (See BigDecimal.mode for how to specify limits of precision.)
|
3126
3234
|
*
|
@@ -3130,13 +3238,25 @@ get_vp_value:
|
|
3130
3238
|
* Note also that in mathematics, there is no particular concept of negative
|
3131
3239
|
* or positive zero; true mathematical zero has no sign.
|
3132
3240
|
*
|
3241
|
+
* == bigdecimal/util
|
3242
|
+
*
|
3243
|
+
* When you require +bigdecimal/util+, the #to_d method will be
|
3244
|
+
* available on BigDecimal and the native Integer, Float, Rational,
|
3245
|
+
* and String classes:
|
3246
|
+
*
|
3247
|
+
* require 'bigdecimal/util'
|
3248
|
+
*
|
3249
|
+
* 42.to_d # => 0.42e2
|
3250
|
+
* 0.5.to_d # => 0.5e0
|
3251
|
+
* (2/3r).to_d(3) # => 0.667e0
|
3252
|
+
* "0.5".to_d # => 0.5e0
|
3253
|
+
*
|
3133
3254
|
* == License
|
3134
3255
|
*
|
3135
3256
|
* Copyright (C) 2002 by Shigeo Kobayashi <shigeo@tinyforest.gr.jp>.
|
3136
3257
|
*
|
3137
|
-
*
|
3138
|
-
*
|
3139
|
-
* of the BigDecimal distribution.
|
3258
|
+
* BigDecimal is released under the Ruby and 2-clause BSD licenses.
|
3259
|
+
* See LICENSE.txt for details.
|
3140
3260
|
*
|
3141
3261
|
* Maintained by mrkn <mrkn@mrkn.jp> and ruby-core members.
|
3142
3262
|
*
|
@@ -3163,6 +3283,7 @@ Init_bigdecimal(void)
|
|
3163
3283
|
rb_define_global_function("BigDecimal", BigDecimal_global_new, -1);
|
3164
3284
|
|
3165
3285
|
/* Class methods */
|
3286
|
+
rb_define_singleton_method(rb_cBigDecimal, "new", BigDecimal_s_new, -1);
|
3166
3287
|
rb_define_singleton_method(rb_cBigDecimal, "mode", BigDecimal_mode, -1);
|
3167
3288
|
rb_define_singleton_method(rb_cBigDecimal, "limit", BigDecimal_limit, -1);
|
3168
3289
|
rb_define_singleton_method(rb_cBigDecimal, "double_fig", BigDecimal_double_fig, 0);
|
@@ -3175,6 +3296,14 @@ Init_bigdecimal(void)
|
|
3175
3296
|
|
3176
3297
|
/* Constants definition */
|
3177
3298
|
|
3299
|
+
#ifndef RUBY_BIGDECIMAL_VERSION
|
3300
|
+
# error RUBY_BIGDECIMAL_VERSION is not defined
|
3301
|
+
#endif
|
3302
|
+
/*
|
3303
|
+
* The version of bigdecimal library
|
3304
|
+
*/
|
3305
|
+
rb_define_const(rb_cBigDecimal, "VERSION", rb_str_new2(RUBY_BIGDECIMAL_VERSION));
|
3306
|
+
|
3178
3307
|
/*
|
3179
3308
|
* Base value used in internal calculations. On a 32 bit system, BASE
|
3180
3309
|
* is 10000, indicating that calculation is done in groups of 4 digits.
|
@@ -3217,7 +3346,7 @@ Init_bigdecimal(void)
|
|
3217
3346
|
rb_define_const(rb_cBigDecimal, "EXCEPTION_OVERFLOW", INT2FIX(VP_EXCEPTION_OVERFLOW));
|
3218
3347
|
|
3219
3348
|
/*
|
3220
|
-
*
|
3349
|
+
* 0x10: Determines what happens when a division by zero is performed.
|
3221
3350
|
* See BigDecimal.mode.
|
3222
3351
|
*/
|
3223
3352
|
rb_define_const(rb_cBigDecimal, "EXCEPTION_ZERODIVIDE", INT2FIX(VP_EXCEPTION_ZERODIVIDE));
|
@@ -3311,7 +3440,8 @@ Init_bigdecimal(void)
|
|
3311
3440
|
rb_define_method(rb_cBigDecimal, "modulo", BigDecimal_mod, 1);
|
3312
3441
|
rb_define_method(rb_cBigDecimal, "remainder", BigDecimal_remainder, 1);
|
3313
3442
|
rb_define_method(rb_cBigDecimal, "divmod", BigDecimal_divmod, 1);
|
3314
|
-
|
3443
|
+
rb_define_method(rb_cBigDecimal, "clone", BigDecimal_clone, 0);
|
3444
|
+
rb_define_method(rb_cBigDecimal, "dup", BigDecimal_clone, 0);
|
3315
3445
|
rb_define_method(rb_cBigDecimal, "to_f", BigDecimal_to_f, 0);
|
3316
3446
|
rb_define_method(rb_cBigDecimal, "abs", BigDecimal_abs, 0);
|
3317
3447
|
rb_define_method(rb_cBigDecimal, "sqrt", BigDecimal_sqrt, 1);
|
@@ -3359,6 +3489,7 @@ Init_bigdecimal(void)
|
|
3359
3489
|
id_floor = rb_intern_const("floor");
|
3360
3490
|
id_to_r = rb_intern_const("to_r");
|
3361
3491
|
id_eq = rb_intern_const("==");
|
3492
|
+
id_half = rb_intern_const("half");
|
3362
3493
|
}
|
3363
3494
|
|
3364
3495
|
/*
|
@@ -3386,7 +3517,14 @@ static Real *VpPt5; /* constant 0.5 */
|
|
3386
3517
|
#define MemCmp(x,y,z) memcmp(x,y,z)
|
3387
3518
|
#define StrCmp(x,y) strcmp(x,y)
|
3388
3519
|
|
3389
|
-
|
3520
|
+
enum op_sw {
|
3521
|
+
OP_SW_ADD = 1, /* + */
|
3522
|
+
OP_SW_SUB, /* - */
|
3523
|
+
OP_SW_MULT, /* * */
|
3524
|
+
OP_SW_DIV /* / */
|
3525
|
+
};
|
3526
|
+
|
3527
|
+
static int VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw);
|
3390
3528
|
static int AddExponent(Real *a, SIGNED_VALUE n);
|
3391
3529
|
static BDIGIT VpAddAbs(Real *a,Real *b,Real *c);
|
3392
3530
|
static BDIGIT VpSubAbs(Real *a,Real *b,Real *c);
|
@@ -3413,7 +3551,7 @@ VpMemAlloc(size_t mb)
|
|
3413
3551
|
return p;
|
3414
3552
|
}
|
3415
3553
|
|
3416
|
-
|
3554
|
+
VP_EXPORT void *
|
3417
3555
|
VpMemRealloc(void *ptr, size_t mb)
|
3418
3556
|
{
|
3419
3557
|
void *p = xrealloc(ptr, mb);
|
@@ -3431,12 +3569,12 @@ VpFree(Real *pv)
|
|
3431
3569
|
#ifdef BIGDECIMAL_DEBUG
|
3432
3570
|
gnAlloc--; /* Decrement allocation count */
|
3433
3571
|
if (gnAlloc == 0) {
|
3434
|
-
printf(" *************** All memories allocated freed
|
3435
|
-
getchar()
|
3572
|
+
printf(" *************** All memories allocated freed ****************\n");
|
3573
|
+
/*getchar();*/
|
3436
3574
|
}
|
3437
3575
|
if (gnAlloc < 0) {
|
3438
3576
|
printf(" ??????????? Too many memory free calls(%d) ?????????????\n", gnAlloc);
|
3439
|
-
getchar()
|
3577
|
+
/*getchar();*/
|
3440
3578
|
}
|
3441
3579
|
#endif /* BIGDECIMAL_DEBUG */
|
3442
3580
|
}
|
@@ -3466,7 +3604,7 @@ VpGetException (void)
|
|
3466
3604
|
return RMPD_EXCEPTION_MODE_DEFAULT;
|
3467
3605
|
}
|
3468
3606
|
|
3469
|
-
return (
|
3607
|
+
return NUM2USHORT(vmode);
|
3470
3608
|
}
|
3471
3609
|
|
3472
3610
|
static void
|
@@ -3536,7 +3674,7 @@ VpGetRoundMode(void)
|
|
3536
3674
|
return RMPD_ROUNDING_MODE_DEFAULT;
|
3537
3675
|
}
|
3538
3676
|
|
3539
|
-
return (
|
3677
|
+
return NUM2USHORT(vmode);
|
3540
3678
|
}
|
3541
3679
|
|
3542
3680
|
VP_EXPORT int
|
@@ -3673,7 +3811,7 @@ VpException(unsigned short f, const char *str,int always)
|
|
3673
3811
|
/* Throw exception or returns 0,when resulting c is Inf or NaN */
|
3674
3812
|
/* sw=1:+ 2:- 3:* 4:/ */
|
3675
3813
|
static int
|
3676
|
-
VpIsDefOP(Real *c,Real *a,Real *b,
|
3814
|
+
VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw)
|
3677
3815
|
{
|
3678
3816
|
if (VpIsNaN(a) || VpIsNaN(b)) {
|
3679
3817
|
/* at least a or b is NaN */
|
@@ -3684,7 +3822,7 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
|
|
3684
3822
|
if (VpIsInf(a)) {
|
3685
3823
|
if (VpIsInf(b)) {
|
3686
3824
|
switch(sw) {
|
3687
|
-
case
|
3825
|
+
case OP_SW_ADD: /* + */
|
3688
3826
|
if (VpGetSign(a) == VpGetSign(b)) {
|
3689
3827
|
VpSetInf(c, VpGetSign(a));
|
3690
3828
|
goto Inf;
|
@@ -3693,7 +3831,7 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
|
|
3693
3831
|
VpSetNaN(c);
|
3694
3832
|
goto NaN;
|
3695
3833
|
}
|
3696
|
-
case
|
3834
|
+
case OP_SW_SUB: /* - */
|
3697
3835
|
if (VpGetSign(a) != VpGetSign(b)) {
|
3698
3836
|
VpSetInf(c, VpGetSign(a));
|
3699
3837
|
goto Inf;
|
@@ -3702,12 +3840,10 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
|
|
3702
3840
|
VpSetNaN(c);
|
3703
3841
|
goto NaN;
|
3704
3842
|
}
|
3705
|
-
|
3706
|
-
case 3: /* * */
|
3843
|
+
case OP_SW_MULT: /* * */
|
3707
3844
|
VpSetInf(c, VpGetSign(a)*VpGetSign(b));
|
3708
3845
|
goto Inf;
|
3709
|
-
|
3710
|
-
case 4: /* / */
|
3846
|
+
case OP_SW_DIV: /* / */
|
3711
3847
|
VpSetNaN(c);
|
3712
3848
|
goto NaN;
|
3713
3849
|
}
|
@@ -3716,18 +3852,18 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
|
|
3716
3852
|
}
|
3717
3853
|
/* Inf op Finite */
|
3718
3854
|
switch(sw) {
|
3719
|
-
case
|
3720
|
-
case
|
3855
|
+
case OP_SW_ADD: /* + */
|
3856
|
+
case OP_SW_SUB: /* - */
|
3721
3857
|
VpSetInf(c, VpGetSign(a));
|
3722
3858
|
break;
|
3723
|
-
case
|
3859
|
+
case OP_SW_MULT: /* * */
|
3724
3860
|
if (VpIsZero(b)) {
|
3725
3861
|
VpSetNaN(c);
|
3726
3862
|
goto NaN;
|
3727
3863
|
}
|
3728
3864
|
VpSetInf(c, VpGetSign(a)*VpGetSign(b));
|
3729
3865
|
break;
|
3730
|
-
case
|
3866
|
+
case OP_SW_DIV: /* / */
|
3731
3867
|
VpSetInf(c, VpGetSign(a)*VpGetSign(b));
|
3732
3868
|
}
|
3733
3869
|
goto Inf;
|
@@ -3735,20 +3871,20 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
|
|
3735
3871
|
|
3736
3872
|
if (VpIsInf(b)) {
|
3737
3873
|
switch(sw) {
|
3738
|
-
case
|
3874
|
+
case OP_SW_ADD: /* + */
|
3739
3875
|
VpSetInf(c, VpGetSign(b));
|
3740
3876
|
break;
|
3741
|
-
case
|
3877
|
+
case OP_SW_SUB: /* - */
|
3742
3878
|
VpSetInf(c, -VpGetSign(b));
|
3743
3879
|
break;
|
3744
|
-
case
|
3880
|
+
case OP_SW_MULT: /* * */
|
3745
3881
|
if (VpIsZero(a)) {
|
3746
3882
|
VpSetNaN(c);
|
3747
3883
|
goto NaN;
|
3748
3884
|
}
|
3749
3885
|
VpSetInf(c, VpGetSign(a)*VpGetSign(b));
|
3750
3886
|
break;
|
3751
|
-
case
|
3887
|
+
case OP_SW_DIV: /* / */
|
3752
3888
|
VpSetZero(c, VpGetSign(a)*VpGetSign(b));
|
3753
3889
|
}
|
3754
3890
|
goto Inf;
|
@@ -3756,7 +3892,13 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
|
|
3756
3892
|
return 1; /* Results OK */
|
3757
3893
|
|
3758
3894
|
Inf:
|
3759
|
-
|
3895
|
+
if (VpIsPosInf(c)) {
|
3896
|
+
return VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 0);
|
3897
|
+
}
|
3898
|
+
else {
|
3899
|
+
return VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 0);
|
3900
|
+
}
|
3901
|
+
|
3760
3902
|
NaN:
|
3761
3903
|
return VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'", 0);
|
3762
3904
|
}
|
@@ -3831,12 +3973,12 @@ VpInit(BDIGIT BaseVal)
|
|
3831
3973
|
|
3832
3974
|
#ifdef BIGDECIMAL_DEBUG
|
3833
3975
|
if (gfDebug) {
|
3834
|
-
printf("VpInit: BaseVal = %
|
3835
|
-
printf("
|
3836
|
-
printf("
|
3837
|
-
printf("
|
3838
|
-
printf("
|
3839
|
-
printf("
|
3976
|
+
printf("VpInit: BaseVal = %"PRIuBDIGIT"\n", BaseVal);
|
3977
|
+
printf("\tBASE = %"PRIuBDIGIT"\n", BASE);
|
3978
|
+
printf("\tHALF_BASE = %"PRIuBDIGIT"\n", HALF_BASE);
|
3979
|
+
printf("\tBASE1 = %"PRIuBDIGIT"\n", BASE1);
|
3980
|
+
printf("\tBASE_FIG = %u\n", BASE_FIG);
|
3981
|
+
printf("\tDBLE_FIG = %d\n", DBLE_FIG);
|
3840
3982
|
}
|
3841
3983
|
#endif /* BIGDECIMAL_DEBUG */
|
3842
3984
|
|
@@ -3863,7 +4005,7 @@ AddExponent(Real *a, SIGNED_VALUE n)
|
|
3863
4005
|
goto overflow;
|
3864
4006
|
mb = m*(SIGNED_VALUE)BASE_FIG;
|
3865
4007
|
eb = e*(SIGNED_VALUE)BASE_FIG;
|
3866
|
-
if (mb
|
4008
|
+
if (eb - mb > 0) goto overflow;
|
3867
4009
|
}
|
3868
4010
|
}
|
3869
4011
|
else if (n < 0) {
|
@@ -3872,7 +4014,7 @@ AddExponent(Real *a, SIGNED_VALUE n)
|
|
3872
4014
|
goto underflow;
|
3873
4015
|
mb = m*(SIGNED_VALUE)BASE_FIG;
|
3874
4016
|
eb = e*(SIGNED_VALUE)BASE_FIG;
|
3875
|
-
if (mb >
|
4017
|
+
if (mb - eb > 0) goto underflow;
|
3876
4018
|
}
|
3877
4019
|
a->exponent = m;
|
3878
4020
|
return 1;
|
@@ -3903,7 +4045,8 @@ overflow:
|
|
3903
4045
|
VP_EXPORT Real *
|
3904
4046
|
VpAlloc(size_t mx, const char *szVal)
|
3905
4047
|
{
|
3906
|
-
|
4048
|
+
const char *orig_szVal = szVal;
|
4049
|
+
size_t i, ni, ipn, ipf, nf, ipe, ne, dot_seen, exp_seen, nalloc;
|
3907
4050
|
char v, *psz;
|
3908
4051
|
int sign=1;
|
3909
4052
|
Real *vp = NULL;
|
@@ -3914,28 +4057,28 @@ VpAlloc(size_t mx, const char *szVal)
|
|
3914
4057
|
if (mx == 0) ++mx;
|
3915
4058
|
|
3916
4059
|
if (szVal) {
|
3917
|
-
|
3918
|
-
|
3919
|
-
|
3920
|
-
|
3921
|
-
|
3922
|
-
|
3923
|
-
|
3924
|
-
|
3925
|
-
|
3926
|
-
|
3927
|
-
|
3928
|
-
|
4060
|
+
while (ISSPACE(*szVal)) szVal++;
|
4061
|
+
if (*szVal != '#') {
|
4062
|
+
if (mf) {
|
4063
|
+
mf = (mf + BASE_FIG - 1) / BASE_FIG + 2; /* Needs 1 more for div */
|
4064
|
+
if (mx > mf) {
|
4065
|
+
mx = mf;
|
4066
|
+
}
|
4067
|
+
}
|
4068
|
+
}
|
4069
|
+
else {
|
4070
|
+
++szVal;
|
4071
|
+
}
|
3929
4072
|
}
|
3930
4073
|
else {
|
3931
|
-
|
3932
|
-
|
3933
|
-
|
3934
|
-
|
3935
|
-
|
3936
|
-
|
3937
|
-
|
3938
|
-
|
4074
|
+
/* necessary to be able to store */
|
4075
|
+
/* at least mx digits. */
|
4076
|
+
/* szVal==NULL ==> allocate zero value. */
|
4077
|
+
vp = VpAllocReal(mx);
|
4078
|
+
/* xmalloc() alway returns(or throw interruption) */
|
4079
|
+
vp->MaxPrec = mx; /* set max precision */
|
4080
|
+
VpSetZero(vp, 1); /* initialize vp to zero. */
|
4081
|
+
return vp;
|
3939
4082
|
}
|
3940
4083
|
|
3941
4084
|
/* Skip all '_' after digit: 2006-6-30 */
|
@@ -3945,43 +4088,42 @@ VpAlloc(size_t mx, const char *szVal)
|
|
3945
4088
|
i = 0;
|
3946
4089
|
ipn = 0;
|
3947
4090
|
while ((psz[i] = szVal[ipn]) != 0) {
|
3948
|
-
|
3949
|
-
|
3950
|
-
|
3951
|
-
|
3952
|
-
|
3953
|
-
|
3954
|
-
|
3955
|
-
|
3956
|
-
|
3957
|
-
|
3958
|
-
|
3959
|
-
|
3960
|
-
|
3961
|
-
|
3962
|
-
|
3963
|
-
else break;
|
4091
|
+
if (ISSPACE(psz[i])) {
|
4092
|
+
psz[i] = 0;
|
4093
|
+
break;
|
4094
|
+
}
|
4095
|
+
if (ISDIGIT(psz[i])) ++ni;
|
4096
|
+
if (psz[i] == '_') {
|
4097
|
+
if (ni > 0) {
|
4098
|
+
ipn++;
|
4099
|
+
continue;
|
4100
|
+
}
|
4101
|
+
psz[i] = 0;
|
4102
|
+
break;
|
4103
|
+
}
|
4104
|
+
++i;
|
4105
|
+
++ipn;
|
3964
4106
|
}
|
3965
4107
|
szVal = psz;
|
3966
4108
|
|
3967
4109
|
/* Check on Inf & NaN */
|
3968
4110
|
if (StrCmp(szVal, SZ_PINF) == 0 || StrCmp(szVal, SZ_INF) == 0 ) {
|
3969
|
-
|
3970
|
-
|
3971
|
-
|
3972
|
-
|
4111
|
+
vp = VpAllocReal(1);
|
4112
|
+
vp->MaxPrec = 1; /* set max precision */
|
4113
|
+
VpSetPosInf(vp);
|
4114
|
+
return vp;
|
3973
4115
|
}
|
3974
4116
|
if (StrCmp(szVal, SZ_NINF) == 0) {
|
3975
|
-
|
3976
|
-
|
3977
|
-
|
3978
|
-
|
4117
|
+
vp = VpAllocReal(1);
|
4118
|
+
vp->MaxPrec = 1; /* set max precision */
|
4119
|
+
VpSetNegInf(vp);
|
4120
|
+
return vp;
|
3979
4121
|
}
|
3980
4122
|
if (StrCmp(szVal, SZ_NaN) == 0) {
|
3981
|
-
|
3982
|
-
|
3983
|
-
|
3984
|
-
|
4123
|
+
vp = VpAllocReal(1);
|
4124
|
+
vp->MaxPrec = 1; /* set max precision */
|
4125
|
+
VpSetNaN(vp);
|
4126
|
+
return vp;
|
3985
4127
|
}
|
3986
4128
|
|
3987
4129
|
/* check on number szVal[] */
|
@@ -3991,46 +4133,55 @@ VpAlloc(size_t mx, const char *szVal)
|
|
3991
4133
|
/* Skip digits */
|
3992
4134
|
ni = 0; /* digits in mantissa */
|
3993
4135
|
while ((v = szVal[i]) != 0) {
|
3994
|
-
|
3995
|
-
|
3996
|
-
|
4136
|
+
if (!ISDIGIT(v)) break;
|
4137
|
+
++i;
|
4138
|
+
++ni;
|
3997
4139
|
}
|
3998
4140
|
nf = 0;
|
3999
4141
|
ipf = 0;
|
4000
4142
|
ipe = 0;
|
4001
4143
|
ne = 0;
|
4144
|
+
dot_seen = 0;
|
4145
|
+
exp_seen = 0;
|
4002
4146
|
if (v) {
|
4003
|
-
|
4004
|
-
|
4005
|
-
|
4006
|
-
|
4007
|
-
|
4008
|
-
|
4009
|
-
|
4010
|
-
|
4011
|
-
|
4012
|
-
|
4013
|
-
|
4014
|
-
|
4015
|
-
|
4016
|
-
|
4017
|
-
|
4018
|
-
|
4019
|
-
|
4020
|
-
|
4021
|
-
|
4022
|
-
|
4023
|
-
|
4024
|
-
|
4025
|
-
|
4026
|
-
|
4027
|
-
|
4028
|
-
|
4029
|
-
|
4030
|
-
|
4031
|
-
|
4032
|
-
|
4147
|
+
/* other than digit nor \0 */
|
4148
|
+
if (szVal[i] == '.') { /* xxx. */
|
4149
|
+
dot_seen = 1;
|
4150
|
+
++i;
|
4151
|
+
ipf = i;
|
4152
|
+
while ((v = szVal[i]) != 0) { /* get fraction part. */
|
4153
|
+
if (!ISDIGIT(v)) break;
|
4154
|
+
++i;
|
4155
|
+
++nf;
|
4156
|
+
}
|
4157
|
+
}
|
4158
|
+
ipe = 0; /* Exponent */
|
4159
|
+
|
4160
|
+
switch (szVal[i]) {
|
4161
|
+
case '\0':
|
4162
|
+
break;
|
4163
|
+
case 'e': case 'E':
|
4164
|
+
case 'd': case 'D':
|
4165
|
+
exp_seen = 1;
|
4166
|
+
++i;
|
4167
|
+
ipe = i;
|
4168
|
+
v = szVal[i];
|
4169
|
+
if ((v == '-') || (v == '+')) ++i;
|
4170
|
+
while ((v=szVal[i]) != 0) {
|
4171
|
+
if (!ISDIGIT(v)) break;
|
4172
|
+
++i;
|
4173
|
+
++ne;
|
4174
|
+
}
|
4175
|
+
break;
|
4176
|
+
default:
|
4177
|
+
break;
|
4178
|
+
}
|
4179
|
+
}
|
4180
|
+
if (((ni == 0 || dot_seen) && nf == 0) || (exp_seen && ne == 0)) {
|
4181
|
+
VALUE str = rb_str_new2(orig_szVal);
|
4182
|
+
rb_raise(rb_eArgError, "invalid value for BigDecimal(): \"%"PRIsVALUE"\"", str);
|
4033
4183
|
}
|
4184
|
+
|
4034
4185
|
nalloc = (ni + nf + BASE_FIG - 1) / BASE_FIG + 1; /* set effective allocation */
|
4035
4186
|
/* units for szVal[] */
|
4036
4187
|
if (mx == 0) mx = 1;
|
@@ -4098,7 +4249,7 @@ VpAsgn(Real *c, Real *a, int isw)
|
|
4098
4249
|
|
4099
4250
|
/*
|
4100
4251
|
* c = a + b when operation = 1 or 2
|
4101
|
-
*
|
4252
|
+
* c = a - b when operation = -1 or -2.
|
4102
4253
|
* Returns number of significant digits of c
|
4103
4254
|
*/
|
4104
4255
|
VP_EXPORT size_t
|
@@ -4117,7 +4268,7 @@ VpAddSub(Real *c, Real *a, Real *b, int operation)
|
|
4117
4268
|
}
|
4118
4269
|
#endif /* BIGDECIMAL_DEBUG */
|
4119
4270
|
|
4120
|
-
if (!VpIsDefOP(c, a, b, (operation > 0) ?
|
4271
|
+
if (!VpIsDefOP(c, a, b, (operation > 0) ? OP_SW_ADD : OP_SW_SUB)) return 0; /* No significant digits */
|
4121
4272
|
|
4122
4273
|
/* check if a or b is zero */
|
4123
4274
|
if (VpIsZero(a)) {
|
@@ -4231,7 +4382,7 @@ end_if:
|
|
4231
4382
|
}
|
4232
4383
|
|
4233
4384
|
/*
|
4234
|
-
* Addition of two variable
|
4385
|
+
* Addition of two values with variable precision
|
4235
4386
|
* a and b assuming abs(a)>abs(b).
|
4236
4387
|
* c = abs(a) + abs(b) ; where |a|>=|b|
|
4237
4388
|
*/
|
@@ -4453,7 +4604,7 @@ VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos,
|
|
4453
4604
|
|
4454
4605
|
size_t const round_limit = (VpGetPrecLimit() + BASE_FIG - 1) / BASE_FIG;
|
4455
4606
|
|
4456
|
-
assert(a->exponent >= b->
|
4607
|
+
assert(a->exponent >= b->exponent);
|
4457
4608
|
|
4458
4609
|
c->frac[0] = 0;
|
4459
4610
|
*av = *bv = 0;
|
@@ -4573,7 +4724,7 @@ VpMult(Real *c, Real *a, Real *b)
|
|
4573
4724
|
}
|
4574
4725
|
#endif /* BIGDECIMAL_DEBUG */
|
4575
4726
|
|
4576
|
-
if (!VpIsDefOP(c, a, b,
|
4727
|
+
if (!VpIsDefOP(c, a, b, OP_SW_MULT)) return 0; /* No significant digit */
|
4577
4728
|
|
4578
4729
|
if (VpIsZero(a) || VpIsZero(b)) {
|
4579
4730
|
/* at least a or b is zero */
|
@@ -4685,7 +4836,7 @@ Exit:
|
|
4685
4836
|
/*
|
4686
4837
|
* c = a / b, remainder = r
|
4687
4838
|
*/
|
4688
|
-
|
4839
|
+
VP_EXPORT size_t
|
4689
4840
|
VpDivd(Real *c, Real *r, Real *a, Real *b)
|
4690
4841
|
{
|
4691
4842
|
size_t word_a, word_b, word_c, word_r;
|
@@ -4703,14 +4854,14 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
|
|
4703
4854
|
#endif /*BIGDECIMAL_DEBUG */
|
4704
4855
|
|
4705
4856
|
VpSetNaN(r);
|
4706
|
-
if (!VpIsDefOP(c, a, b,
|
4857
|
+
if (!VpIsDefOP(c, a, b, OP_SW_DIV)) goto Exit;
|
4707
4858
|
if (VpIsZero(a) && VpIsZero(b)) {
|
4708
4859
|
VpSetNaN(c);
|
4709
|
-
return VpException(VP_EXCEPTION_NaN, "
|
4860
|
+
return VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'", 0);
|
4710
4861
|
}
|
4711
4862
|
if (VpIsZero(b)) {
|
4712
4863
|
VpSetInf(c, VpGetSign(a) * VpGetSign(b));
|
4713
|
-
return VpException(VP_EXCEPTION_ZERODIVIDE, "
|
4864
|
+
return VpException(VP_EXCEPTION_ZERODIVIDE, "Divide by zero", 0);
|
4714
4865
|
}
|
4715
4866
|
if (VpIsZero(a)) {
|
4716
4867
|
/* numerator a is zero */
|
@@ -4990,7 +5141,7 @@ VpComp(Real *a, Real *b)
|
|
4990
5141
|
goto Exit;
|
4991
5142
|
}
|
4992
5143
|
|
4993
|
-
/* a and b have same exponent, then compare significand. */
|
5144
|
+
/* a and b have same exponent, then compare their significand. */
|
4994
5145
|
mx = (a->Prec < b->Prec) ? a->Prec : b->Prec;
|
4995
5146
|
ind = 0;
|
4996
5147
|
while (ind < mx) {
|
@@ -5031,8 +5182,8 @@ Exit:
|
|
5031
5182
|
* % ... VP variable. To print '%', use '%%'.
|
5032
5183
|
* \n ... new line
|
5033
5184
|
* \b ... backspace
|
5034
|
-
*
|
5035
|
-
* Note: % must
|
5185
|
+
* \t ... tab
|
5186
|
+
* Note: % must not appear more than once
|
5036
5187
|
* a ... VP variable to be printed
|
5037
5188
|
*/
|
5038
5189
|
#ifdef BIGDECIMAL_ENABLE_VPRINT
|
@@ -5042,24 +5193,6 @@ VPrint(FILE *fp, const char *cntl_chr, Real *a)
|
|
5042
5193
|
size_t i, j, nc, nd, ZeroSup, sep = 10;
|
5043
5194
|
BDIGIT m, e, nn;
|
5044
5195
|
|
5045
|
-
/* Check if NaN & Inf. */
|
5046
|
-
if (VpIsNaN(a)) {
|
5047
|
-
fprintf(fp, SZ_NaN);
|
5048
|
-
return 8;
|
5049
|
-
}
|
5050
|
-
if (VpIsPosInf(a)) {
|
5051
|
-
fprintf(fp, SZ_INF);
|
5052
|
-
return 8;
|
5053
|
-
}
|
5054
|
-
if (VpIsNegInf(a)) {
|
5055
|
-
fprintf(fp, SZ_NINF);
|
5056
|
-
return 9;
|
5057
|
-
}
|
5058
|
-
if (VpIsZero(a)) {
|
5059
|
-
fprintf(fp, "0.0");
|
5060
|
-
return 3;
|
5061
|
-
}
|
5062
|
-
|
5063
5196
|
j = 0;
|
5064
5197
|
nd = nc = 0; /* nd : number of digits in fraction part(every 10 digits, */
|
5065
5198
|
/* nd<=10). */
|
@@ -5068,8 +5201,20 @@ VPrint(FILE *fp, const char *cntl_chr, Real *a)
|
|
5068
5201
|
while (*(cntl_chr + j)) {
|
5069
5202
|
if (*(cntl_chr + j) == '%' && *(cntl_chr + j + 1) != '%') {
|
5070
5203
|
nc = 0;
|
5071
|
-
if (
|
5072
|
-
|
5204
|
+
if (VpIsNaN(a)) {
|
5205
|
+
fprintf(fp, SZ_NaN);
|
5206
|
+
nc += 8;
|
5207
|
+
}
|
5208
|
+
else if (VpIsPosInf(a)) {
|
5209
|
+
fprintf(fp, SZ_INF);
|
5210
|
+
nc += 8;
|
5211
|
+
}
|
5212
|
+
else if (VpIsNegInf(a)) {
|
5213
|
+
fprintf(fp, SZ_NINF);
|
5214
|
+
nc += 9;
|
5215
|
+
}
|
5216
|
+
else if (!VpIsZero(a)) {
|
5217
|
+
if (BIGDECIMAL_NEGATIVE_P(a)) {
|
5073
5218
|
fprintf(fp, "-");
|
5074
5219
|
++nc;
|
5075
5220
|
}
|
@@ -5158,7 +5303,7 @@ VpFormatSt(char *psz, size_t fFmt)
|
|
5158
5303
|
if (!ch) break;
|
5159
5304
|
if (ISSPACE(ch) || ch=='-' || ch=='+') continue;
|
5160
5305
|
if (ch == '.') { nf = 0; continue; }
|
5161
|
-
if (ch == 'E') break;
|
5306
|
+
if (ch == 'E' || ch == 'e') break;
|
5162
5307
|
|
5163
5308
|
if (++nf > fFmt) {
|
5164
5309
|
memmove(psz + i + 1, psz + i, ie - i + 1);
|
@@ -5207,7 +5352,7 @@ VpSzMantissa(Real *a,char *psz)
|
|
5207
5352
|
|
5208
5353
|
ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
|
5209
5354
|
if (!VpIsZero(a)) {
|
5210
|
-
if (
|
5355
|
+
if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
|
5211
5356
|
n = a->Prec;
|
5212
5357
|
for (i = 0; i < n; ++i) {
|
5213
5358
|
m = BASE1;
|
@@ -5235,7 +5380,7 @@ VpSzMantissa(Real *a,char *psz)
|
|
5235
5380
|
|
5236
5381
|
VP_EXPORT int
|
5237
5382
|
VpToSpecialString(Real *a,char *psz,int fPlus)
|
5238
|
-
|
5383
|
+
/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
|
5239
5384
|
{
|
5240
5385
|
if (VpIsNaN(a)) {
|
5241
5386
|
sprintf(psz,SZ_NaN);
|
@@ -5270,7 +5415,7 @@ VpToSpecialString(Real *a,char *psz,int fPlus)
|
|
5270
5415
|
|
5271
5416
|
VP_EXPORT void
|
5272
5417
|
VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
|
5273
|
-
/* fPlus =0:default,
|
5418
|
+
/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
|
5274
5419
|
{
|
5275
5420
|
size_t i, n, ZeroSup;
|
5276
5421
|
BDIGIT shift, m, e, nn;
|
@@ -5281,7 +5426,7 @@ VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
|
|
5281
5426
|
|
5282
5427
|
ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
|
5283
5428
|
|
5284
|
-
if (
|
5429
|
+
if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
|
5285
5430
|
else if (fPlus == 1) *psz++ = ' ';
|
5286
5431
|
else if (fPlus == 2) *psz++ = '+';
|
5287
5432
|
|
@@ -5312,13 +5457,13 @@ VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
|
|
5312
5457
|
while (psz[-1] == '0') {
|
5313
5458
|
*(--psz) = 0;
|
5314
5459
|
}
|
5315
|
-
sprintf(psz, "
|
5460
|
+
sprintf(psz, "e%"PRIdSIZE, ex);
|
5316
5461
|
if (fFmt) VpFormatSt(pszSav, fFmt);
|
5317
5462
|
}
|
5318
5463
|
|
5319
5464
|
VP_EXPORT void
|
5320
5465
|
VpToFString(Real *a, char *psz, size_t fFmt, int fPlus)
|
5321
|
-
/* fPlus =0:default
|
5466
|
+
/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
|
5322
5467
|
{
|
5323
5468
|
size_t i, n;
|
5324
5469
|
BDIGIT m, e, nn;
|
@@ -5327,7 +5472,7 @@ VpToFString(Real *a, char *psz, size_t fFmt, int fPlus)
|
|
5327
5472
|
|
5328
5473
|
if (VpToSpecialString(a, psz, fPlus)) return;
|
5329
5474
|
|
5330
|
-
if (
|
5475
|
+
if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
|
5331
5476
|
else if (fPlus == 1) *psz++ = ' ';
|
5332
5477
|
else if (fPlus == 2) *psz++ = '+';
|
5333
5478
|
|
@@ -5749,21 +5894,22 @@ VpSqrt(Real *y, Real *x)
|
|
5749
5894
|
ssize_t nr;
|
5750
5895
|
double val;
|
5751
5896
|
|
5752
|
-
/* Zero
|
5753
|
-
if (
|
5754
|
-
|
5755
|
-
VpAsgn(y,x,1);
|
5756
|
-
goto Exit;
|
5757
|
-
}
|
5758
|
-
VpSetNaN(y);
|
5759
|
-
return VpException(VP_EXCEPTION_OP, "(VpSqrt) SQRT(NaN or negative value)", 0);
|
5897
|
+
/* Zero or +Infinity ? */
|
5898
|
+
if (VpIsZero(x) || VpIsPosInf(x)) {
|
5899
|
+
VpAsgn(y,x,1);
|
5760
5900
|
goto Exit;
|
5761
5901
|
}
|
5762
5902
|
|
5763
5903
|
/* Negative ? */
|
5764
|
-
if (
|
5904
|
+
if (BIGDECIMAL_NEGATIVE_P(x)) {
|
5905
|
+
VpSetNaN(y);
|
5906
|
+
return VpException(VP_EXCEPTION_OP, "sqrt of negative value", 0);
|
5907
|
+
}
|
5908
|
+
|
5909
|
+
/* NaN ? */
|
5910
|
+
if (VpIsNaN(x)) {
|
5765
5911
|
VpSetNaN(y);
|
5766
|
-
return VpException(VP_EXCEPTION_OP, "
|
5912
|
+
return VpException(VP_EXCEPTION_OP, "sqrt of 'NaN'(Not a Number)", 0);
|
5767
5913
|
}
|
5768
5914
|
|
5769
5915
|
/* One ? */
|
@@ -5841,18 +5987,13 @@ Exit:
|
|
5841
5987
|
return 1;
|
5842
5988
|
}
|
5843
5989
|
|
5844
|
-
/*
|
5845
|
-
*
|
5846
|
-
* nf: digit position for operation.
|
5847
|
-
*
|
5848
|
-
*/
|
5849
|
-
VP_EXPORT int
|
5850
|
-
VpMidRound(Real *y, unsigned short f, ssize_t nf)
|
5851
5990
|
/*
|
5852
5991
|
* Round relatively from the decimal point.
|
5853
5992
|
* f: rounding mode
|
5854
5993
|
* nf: digit location to round from the decimal point.
|
5855
5994
|
*/
|
5995
|
+
VP_EXPORT int
|
5996
|
+
VpMidRound(Real *y, unsigned short f, ssize_t nf)
|
5856
5997
|
{
|
5857
5998
|
/* fracf: any positive digit under rounding position? */
|
5858
5999
|
/* fracf_1further: any positive digits under one further than the rounding position? */
|
@@ -5954,10 +6095,10 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
|
|
5954
6095
|
if (v > 5 || (v == 5 && fracf_1further)) ++div;
|
5955
6096
|
break;
|
5956
6097
|
case VP_ROUND_CEIL:
|
5957
|
-
if (fracf && (
|
6098
|
+
if (fracf && BIGDECIMAL_POSITIVE_P(y)) ++div;
|
5958
6099
|
break;
|
5959
6100
|
case VP_ROUND_FLOOR:
|
5960
|
-
if (fracf && (
|
6101
|
+
if (fracf && BIGDECIMAL_NEGATIVE_P(y)) ++div;
|
5961
6102
|
break;
|
5962
6103
|
case VP_ROUND_HALF_EVEN: /* Banker's rounding */
|
5963
6104
|
if (v > 5) ++div;
|
@@ -6076,10 +6217,10 @@ VpInternalRound(Real *c, size_t ixDigit, BDIGIT vPrev, BDIGIT v)
|
|
6076
6217
|
if (v >= 6) f = 1;
|
6077
6218
|
break;
|
6078
6219
|
case VP_ROUND_CEIL:
|
6079
|
-
if (v && (
|
6220
|
+
if (v && BIGDECIMAL_POSITIVE_P(c)) f = 1;
|
6080
6221
|
break;
|
6081
6222
|
case VP_ROUND_FLOOR:
|
6082
|
-
if (v && (
|
6223
|
+
if (v && BIGDECIMAL_NEGATIVE_P(c)) f = 1;
|
6083
6224
|
break;
|
6084
6225
|
case VP_ROUND_HALF_EVEN: /* Banker's rounding */
|
6085
6226
|
/* as per VP_ROUND_HALF_DOWN, because this is the last digit of precision,
|
@@ -6216,7 +6357,7 @@ VpPower(Real *y, Real *x, SIGNED_VALUE n)
|
|
6216
6357
|
if (x->exponent == 1 && x->Prec == 1 && x->frac[0] == 1) {
|
6217
6358
|
/* abs(x) = 1 */
|
6218
6359
|
VpSetOne(y);
|
6219
|
-
if (
|
6360
|
+
if (BIGDECIMAL_POSITIVE_P(x)) goto Exit;
|
6220
6361
|
if ((n % 2) == 0) goto Exit;
|
6221
6362
|
VpSetSign(y, -1);
|
6222
6363
|
goto Exit;
|
@@ -6261,7 +6402,7 @@ Exit:
|
|
6261
6402
|
if (gfDebug) {
|
6262
6403
|
VPrint(stdout, "VpPower y=%\n", y);
|
6263
6404
|
VPrint(stdout, "VpPower x=%\n", x);
|
6264
|
-
printf(" n=%
|
6405
|
+
printf(" n=%"PRIdVALUE"\n", n);
|
6265
6406
|
}
|
6266
6407
|
#endif /* BIGDECIMAL_DEBUG */
|
6267
6408
|
VpFree(w2);
|
@@ -6296,10 +6437,10 @@ VpVarCheck(Real * v)
|
|
6296
6437
|
for (i = 0; i < v->Prec; ++i) {
|
6297
6438
|
if (v->frac[i] >= BASE) {
|
6298
6439
|
printf("ERROR(VpVarCheck): Illegal fraction\n");
|
6299
|
-
printf(" Frac[%"PRIuSIZE"]=%
|
6440
|
+
printf(" Frac[%"PRIuSIZE"]=%"PRIuBDIGIT"\n", i, v->frac[i]);
|
6300
6441
|
printf(" Prec. =%"PRIuSIZE"\n", v->Prec);
|
6301
6442
|
printf(" Exp. =%"PRIdVALUE"\n", v->exponent);
|
6302
|
-
printf(" BASE =%
|
6443
|
+
printf(" BASE =%"PRIuBDIGIT"\n", BASE);
|
6303
6444
|
return 3;
|
6304
6445
|
}
|
6305
6446
|
}
|