bigdecimal 1.2.7 → 1.3.4
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.
- 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
|
}
|