bigdecimal 1.2.7 → 1.3.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bigdecimal.gemspec +23 -18
- data/{bigdecimal.c → ext/bigdecimal/bigdecimal.c} +325 -257
- data/{bigdecimal.h → ext/bigdecimal/bigdecimal.h} +75 -10
- data/{depend → ext/bigdecimal/depend} +1 -1
- data/ext/bigdecimal/extconf.rb +30 -0
- data/lib/bigdecimal/jacobian.rb +1 -0
- data/lib/bigdecimal/ludcmp.rb +1 -0
- data/lib/bigdecimal/math.rb +1 -0
- data/lib/bigdecimal/newton.rb +1 -0
- data/lib/bigdecimal/util.rb +2 -1
- data/sample/linear.rb +1 -0
- data/sample/nlsolve.rb +1 -0
- data/sample/pi.rb +1 -0
- metadata +59 -16
- data/README +0 -60
- data/extconf.rb +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2390e0da673ea017af80d3876c848d7bee58d978
|
4
|
+
data.tar.gz: 46c3ad1e4b275eef054acf8a3c4336859ac4347d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fab6b67b03398713ebed08bcec6edee1604824192783ea32ba82fb76f16862fdc5a44398f2fa91fc1a2b1ed357f49a7ec9f7058e23e74cfeae6e1b7d0975bf27
|
7
|
+
data.tar.gz: e9129231704307c807b625803341e993c39951cf288b934bb4b26d853868aa9cc9e3a0daab4bcd0267caceee274ebffd24f4113d5c5ac72a2b12e746841f93ec
|
data/bigdecimal.gemspec
CHANGED
@@ -1,23 +1,25 @@
|
|
1
|
-
#
|
2
|
-
_VERSION =
|
3
|
-
date = %w$Date:: $[1]
|
1
|
+
# coding: utf-8
|
2
|
+
_VERSION = '1.3.0.pre'
|
4
3
|
|
5
4
|
Gem::Specification.new do |s|
|
6
|
-
s.name
|
7
|
-
s.version
|
8
|
-
s.
|
9
|
-
s.
|
10
|
-
|
11
|
-
s.
|
12
|
-
s.description
|
13
|
-
s.
|
14
|
-
s.
|
15
|
-
|
5
|
+
s.name = "bigdecimal"
|
6
|
+
s.version = _VERSION
|
7
|
+
s.authors = ["Kenta Murata", "Zachary Scott", "Shigeo Kobayashi"]
|
8
|
+
s.email = ["mrkn@mrkn.jp"]
|
9
|
+
|
10
|
+
s.summary = "Arbitrary-precision decimal floating-point number library."
|
11
|
+
s.description = "This library provides arbitrary-precision decimal floating-point number class."
|
12
|
+
s.homepage = "https://github.com/ruby/bigdecimal"
|
13
|
+
s.license = "ruby"
|
14
|
+
|
15
|
+
s.require_paths = %w[lib]
|
16
|
+
s.extensions = %w[ext/bigdecimal/extconf.rb]
|
17
|
+
s.files = %w[
|
16
18
|
bigdecimal.gemspec
|
17
|
-
bigdecimal.c
|
18
|
-
bigdecimal.h
|
19
|
-
|
20
|
-
|
19
|
+
ext/bigdecimal/bigdecimal.c
|
20
|
+
ext/bigdecimal/bigdecimal.h
|
21
|
+
ext/bigdecimal/depend
|
22
|
+
ext/bigdecimal/extconf.rb
|
21
23
|
lib/bigdecimal/jacobian.rb
|
22
24
|
lib/bigdecimal/ludcmp.rb
|
23
25
|
lib/bigdecimal/math.rb
|
@@ -27,5 +29,8 @@ Gem::Specification.new do |s|
|
|
27
29
|
sample/nlsolve.rb
|
28
30
|
sample/pi.rb
|
29
31
|
]
|
30
|
-
|
32
|
+
|
33
|
+
s.add_development_dependency "rake", "~> 10.0"
|
34
|
+
s.add_development_dependency "rake-compiler", "~> 0.9"
|
35
|
+
s.add_development_dependency "minitest", "~> 4.7.5"
|
31
36
|
end
|
@@ -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
|
*/
|
@@ -179,7 +176,7 @@ static size_t
|
|
179
176
|
BigDecimal_memsize(const void *ptr)
|
180
177
|
{
|
181
178
|
const Real *pv = ptr;
|
182
|
-
return
|
179
|
+
return (sizeof(*pv) + pv->MaxPrec * sizeof(BDIGIT));
|
183
180
|
}
|
184
181
|
|
185
182
|
static const rb_data_type_t BigDecimal_data_type = {
|
@@ -246,6 +243,11 @@ again:
|
|
246
243
|
if (prec < 0) goto unable_to_coerce_without_prec;
|
247
244
|
if (prec > DBL_DIG+1) goto SomeOneMayDoIt;
|
248
245
|
d = RFLOAT_VALUE(v);
|
246
|
+
if (!isfinite(d)) {
|
247
|
+
pv = VpCreateRbObject(1, NULL);
|
248
|
+
VpDtoV(pv, d);
|
249
|
+
return pv;
|
250
|
+
}
|
249
251
|
if (d != 0.0) {
|
250
252
|
v = rb_funcall(v, id_to_r, 0);
|
251
253
|
goto again;
|
@@ -386,9 +388,9 @@ BigDecimal_hash(VALUE self)
|
|
386
388
|
* Method used to provide marshalling support.
|
387
389
|
*
|
388
390
|
* inf = BigDecimal.new('Infinity')
|
389
|
-
* #=>
|
391
|
+
* #=> Infinity
|
390
392
|
* BigDecimal._load(inf._dump)
|
391
|
-
* #=>
|
393
|
+
* #=> Infinity
|
392
394
|
*
|
393
395
|
* See the Marshal module.
|
394
396
|
*/
|
@@ -441,6 +443,54 @@ BigDecimal_load(VALUE self, VALUE str)
|
|
441
443
|
return ToValue(pv);
|
442
444
|
}
|
443
445
|
|
446
|
+
static unsigned short
|
447
|
+
check_rounding_mode_option(VALUE const opts)
|
448
|
+
{
|
449
|
+
VALUE mode;
|
450
|
+
char const *s;
|
451
|
+
long l;
|
452
|
+
|
453
|
+
assert(RB_TYPE_P(opts, T_HASH));
|
454
|
+
|
455
|
+
if (NIL_P(opts))
|
456
|
+
goto noopt;
|
457
|
+
|
458
|
+
mode = rb_hash_lookup2(opts, ID2SYM(id_half), Qundef);
|
459
|
+
if (mode == Qundef)
|
460
|
+
goto noopt;
|
461
|
+
|
462
|
+
if (SYMBOL_P(mode))
|
463
|
+
mode = rb_sym2str(mode);
|
464
|
+
else if (!RB_TYPE_P(mode, T_STRING)) {
|
465
|
+
VALUE str_mode = rb_check_string_type(mode);
|
466
|
+
if (NIL_P(str_mode)) goto invalid;
|
467
|
+
mode = str_mode;
|
468
|
+
}
|
469
|
+
s = RSTRING_PTR(mode);
|
470
|
+
l = RSTRING_LEN(mode);
|
471
|
+
switch (l) {
|
472
|
+
case 2:
|
473
|
+
if (strncasecmp(s, "up", 2) == 0)
|
474
|
+
return VP_ROUND_HALF_UP;
|
475
|
+
break;
|
476
|
+
case 4:
|
477
|
+
if (strncasecmp(s, "even", 4) == 0)
|
478
|
+
return VP_ROUND_HALF_EVEN;
|
479
|
+
else if (strncasecmp(s, "down", 4) == 0)
|
480
|
+
return VP_ROUND_HALF_DOWN;
|
481
|
+
default:
|
482
|
+
break;
|
483
|
+
}
|
484
|
+
invalid:
|
485
|
+
if (NIL_P(mode))
|
486
|
+
rb_raise(rb_eArgError, "invalid rounding mode: nil");
|
487
|
+
else
|
488
|
+
rb_raise(rb_eArgError, "invalid rounding mode: %"PRIsVALUE, mode);
|
489
|
+
|
490
|
+
noopt:
|
491
|
+
return VpGetRoundMode();
|
492
|
+
}
|
493
|
+
|
444
494
|
static unsigned short
|
445
495
|
check_rounding_mode(VALUE const v)
|
446
496
|
{
|
@@ -469,8 +519,7 @@ check_rounding_mode(VALUE const v)
|
|
469
519
|
break;
|
470
520
|
}
|
471
521
|
|
472
|
-
|
473
|
-
sw = (unsigned short)FIX2UINT(v);
|
522
|
+
sw = NUM2USHORT(v);
|
474
523
|
if (!VpIsRoundMode(sw)) {
|
475
524
|
rb_raise(rb_eArgError, "invalid rounding mode");
|
476
525
|
}
|
@@ -523,8 +572,7 @@ BigDecimal_mode(int argc, VALUE *argv, VALUE self)
|
|
523
572
|
unsigned long f,fo;
|
524
573
|
|
525
574
|
rb_scan_args(argc, argv, "11", &which, &val);
|
526
|
-
|
527
|
-
f = (unsigned long)FIX2INT(which);
|
575
|
+
f = (unsigned long)NUM2INT(which);
|
528
576
|
|
529
577
|
if (f & VP_EXCEPTION_ALL) {
|
530
578
|
/* Exception mode setting */
|
@@ -565,7 +613,7 @@ BigDecimal_mode(int argc, VALUE *argv, VALUE self)
|
|
565
613
|
fo = VpSetRoundMode(sw);
|
566
614
|
return INT2FIX(fo);
|
567
615
|
}
|
568
|
-
rb_raise(rb_eTypeError, "first argument for BigDecimal
|
616
|
+
rb_raise(rb_eTypeError, "first argument for BigDecimal.mode invalid");
|
569
617
|
return Qnil;
|
570
618
|
}
|
571
619
|
|
@@ -594,8 +642,7 @@ static SIGNED_VALUE
|
|
594
642
|
GetPositiveInt(VALUE v)
|
595
643
|
{
|
596
644
|
SIGNED_VALUE n;
|
597
|
-
|
598
|
-
n = FIX2INT(v);
|
645
|
+
n = NUM2INT(v);
|
599
646
|
if (n < 0) {
|
600
647
|
rb_raise(rb_eArgError, "argument must be positive");
|
601
648
|
}
|
@@ -605,17 +652,17 @@ GetPositiveInt(VALUE v)
|
|
605
652
|
VP_EXPORT Real *
|
606
653
|
VpNewRbClass(size_t mx, const char *str, VALUE klass)
|
607
654
|
{
|
655
|
+
VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
|
608
656
|
Real *pv = VpAlloc(mx,str);
|
609
|
-
|
657
|
+
RTYPEDDATA_DATA(obj) = pv;
|
658
|
+
pv->obj = obj;
|
610
659
|
return pv;
|
611
660
|
}
|
612
661
|
|
613
662
|
VP_EXPORT Real *
|
614
663
|
VpCreateRbObject(size_t mx, const char *str)
|
615
664
|
{
|
616
|
-
|
617
|
-
pv->obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, pv);
|
618
|
-
return pv;
|
665
|
+
return VpNewRbClass(mx, str, rb_cBigDecimal);
|
619
666
|
}
|
620
667
|
|
621
668
|
#define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(BDIGIT))
|
@@ -684,9 +731,9 @@ BigDecimal_check_num(Real *p)
|
|
684
731
|
|
685
732
|
static VALUE BigDecimal_split(VALUE self);
|
686
733
|
|
687
|
-
/* Returns the value as an
|
734
|
+
/* Returns the value as an Integer.
|
688
735
|
*
|
689
|
-
* If the
|
736
|
+
* If the BigDecimal is infinity or NaN, raises FloatDomainError.
|
690
737
|
*/
|
691
738
|
static VALUE
|
692
739
|
BigDecimal_to_i(VALUE self)
|
@@ -706,12 +753,12 @@ BigDecimal_to_i(VALUE self)
|
|
706
753
|
}
|
707
754
|
else {
|
708
755
|
VALUE a = BigDecimal_split(self);
|
709
|
-
VALUE digits =
|
756
|
+
VALUE digits = RARRAY_AREF(a, 1);
|
710
757
|
VALUE numerator = rb_funcall(digits, rb_intern("to_i"), 0);
|
711
758
|
VALUE ret;
|
712
759
|
ssize_t dpower = e - (ssize_t)RSTRING_LEN(digits);
|
713
760
|
|
714
|
-
if (
|
761
|
+
if (BIGDECIMAL_NEGATIVE_P(p)) {
|
715
762
|
numerator = rb_funcall(numerator, '*', 1, INT2FIX(-1));
|
716
763
|
}
|
717
764
|
if (dpower < 0) {
|
@@ -766,17 +813,17 @@ BigDecimal_to_f(VALUE self)
|
|
766
813
|
|
767
814
|
overflow:
|
768
815
|
VpException(VP_EXCEPTION_OVERFLOW, "BigDecimal to Float conversion", 0);
|
769
|
-
if (p
|
770
|
-
return rb_float_new(VpGetDoublePosInf());
|
771
|
-
else
|
816
|
+
if (BIGDECIMAL_NEGATIVE_P(p))
|
772
817
|
return rb_float_new(VpGetDoubleNegInf());
|
818
|
+
else
|
819
|
+
return rb_float_new(VpGetDoublePosInf());
|
773
820
|
|
774
821
|
underflow:
|
775
822
|
VpException(VP_EXCEPTION_UNDERFLOW, "BigDecimal to Float conversion", 0);
|
776
|
-
if (p
|
777
|
-
return rb_float_new(0.0);
|
778
|
-
else
|
823
|
+
if (BIGDECIMAL_NEGATIVE_P(p))
|
779
824
|
return rb_float_new(-0.0);
|
825
|
+
else
|
826
|
+
return rb_float_new(0.0);
|
780
827
|
}
|
781
828
|
|
782
829
|
|
@@ -795,7 +842,7 @@ BigDecimal_to_r(VALUE self)
|
|
795
842
|
sign = VpGetSign(p);
|
796
843
|
power = VpExponent10(p);
|
797
844
|
a = BigDecimal_split(self);
|
798
|
-
digits =
|
845
|
+
digits = RARRAY_AREF(a, 1);
|
799
846
|
denomi_power = power - RSTRING_LEN(digits);
|
800
847
|
numerator = rb_funcall(digits, rb_intern("to_i"), 0);
|
801
848
|
|
@@ -1110,7 +1157,7 @@ BigDecimal_comp(VALUE self, VALUE r)
|
|
1110
1157
|
*
|
1111
1158
|
* Values may be coerced to perform the comparison:
|
1112
1159
|
*
|
1113
|
-
* BigDecimal.new('1.0') == 1.0
|
1160
|
+
* BigDecimal.new('1.0') == 1.0 #=> true
|
1114
1161
|
*/
|
1115
1162
|
static VALUE
|
1116
1163
|
BigDecimal_eq(VALUE self, VALUE r)
|
@@ -1537,7 +1584,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
|
|
1537
1584
|
size_t mx = ix + VpBaseFig()*2;
|
1538
1585
|
size_t pl = VpSetPrecLimit(0);
|
1539
1586
|
|
1540
|
-
GUARD_OBJ(cv, VpCreateRbObject(mx, "0"));
|
1587
|
+
GUARD_OBJ(cv, VpCreateRbObject(mx + VpBaseFig(), "0"));
|
1541
1588
|
GUARD_OBJ(av, GetVpValue(self, 1));
|
1542
1589
|
GUARD_OBJ(bv, GetVpValue(b, 1));
|
1543
1590
|
mx = av->Prec + bv->Prec + 2;
|
@@ -1724,13 +1771,21 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
|
|
1724
1771
|
iLoc = 0;
|
1725
1772
|
break;
|
1726
1773
|
case 1:
|
1727
|
-
|
1728
|
-
|
1774
|
+
if (RB_TYPE_P(vLoc, T_HASH)) {
|
1775
|
+
sw = check_rounding_mode_option(vLoc);
|
1776
|
+
}
|
1777
|
+
else {
|
1778
|
+
iLoc = NUM2INT(vLoc);
|
1779
|
+
}
|
1729
1780
|
break;
|
1730
1781
|
case 2:
|
1731
|
-
|
1732
|
-
|
1733
|
-
|
1782
|
+
iLoc = NUM2INT(vLoc);
|
1783
|
+
if (RB_TYPE_P(vRound, T_HASH)) {
|
1784
|
+
sw = check_rounding_mode_option(vRound);
|
1785
|
+
}
|
1786
|
+
else {
|
1787
|
+
sw = check_rounding_mode(vRound);
|
1788
|
+
}
|
1734
1789
|
break;
|
1735
1790
|
default:
|
1736
1791
|
break;
|
@@ -1780,8 +1835,7 @@ BigDecimal_truncate(int argc, VALUE *argv, VALUE self)
|
|
1780
1835
|
iLoc = 0;
|
1781
1836
|
}
|
1782
1837
|
else {
|
1783
|
-
|
1784
|
-
iLoc = FIX2INT(vLoc);
|
1838
|
+
iLoc = NUM2INT(vLoc);
|
1785
1839
|
}
|
1786
1840
|
|
1787
1841
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
@@ -1841,8 +1895,7 @@ BigDecimal_floor(int argc, VALUE *argv, VALUE self)
|
|
1841
1895
|
iLoc = 0;
|
1842
1896
|
}
|
1843
1897
|
else {
|
1844
|
-
|
1845
|
-
iLoc = FIX2INT(vLoc);
|
1898
|
+
iLoc = NUM2INT(vLoc);
|
1846
1899
|
}
|
1847
1900
|
|
1848
1901
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
@@ -1888,8 +1941,7 @@ BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
|
|
1888
1941
|
if (rb_scan_args(argc, argv, "01", &vLoc) == 0) {
|
1889
1942
|
iLoc = 0;
|
1890
1943
|
} else {
|
1891
|
-
|
1892
|
-
iLoc = FIX2INT(vLoc);
|
1944
|
+
iLoc = NUM2INT(vLoc);
|
1893
1945
|
}
|
1894
1946
|
|
1895
1947
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
@@ -2075,7 +2127,7 @@ BigDecimal_exponent(VALUE self)
|
|
2075
2127
|
* values in angle brackets with a leading #:
|
2076
2128
|
*
|
2077
2129
|
* BigDecimal.new("1234.5678").inspect
|
2078
|
-
* #=> "
|
2130
|
+
* #=> "0.12345678e4"
|
2079
2131
|
*
|
2080
2132
|
* The first part is the address, the second is the value as a string, and
|
2081
2133
|
* the final part ss(mm) is the current number of significant digits and the
|
@@ -2086,23 +2138,16 @@ BigDecimal_inspect(VALUE self)
|
|
2086
2138
|
{
|
2087
2139
|
ENTER(5);
|
2088
2140
|
Real *vp;
|
2089
|
-
volatile VALUE
|
2141
|
+
volatile VALUE str;
|
2090
2142
|
size_t nc;
|
2091
|
-
char *psz, *tmp;
|
2092
2143
|
|
2093
2144
|
GUARD_OBJ(vp, GetVpValue(self, 1));
|
2094
2145
|
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;
|
2146
|
+
|
2147
|
+
str = rb_str_new(0, nc);
|
2148
|
+
VpToString(vp, RSTRING_PTR(str), 0, 0);
|
2149
|
+
rb_str_resize(str, strlen(RSTRING_PTR(str)));
|
2150
|
+
return str;
|
2106
2151
|
}
|
2107
2152
|
|
2108
2153
|
static VALUE BigMath_s_exp(VALUE, VALUE, VALUE);
|
@@ -2312,7 +2357,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2312
2357
|
if (is_negative(vexp)) {
|
2313
2358
|
y = VpCreateRbObject(n, "#0");
|
2314
2359
|
RB_GC_GUARD(y->obj);
|
2315
|
-
if (
|
2360
|
+
if (BIGDECIMAL_NEGATIVE_P(x)) {
|
2316
2361
|
if (is_integer(vexp)) {
|
2317
2362
|
if (is_even(vexp)) {
|
2318
2363
|
/* (-0) ** (-even_integer) -> Infinity */
|
@@ -2351,7 +2396,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2351
2396
|
|
2352
2397
|
if (VpIsInf(x)) {
|
2353
2398
|
if (is_negative(vexp)) {
|
2354
|
-
if (
|
2399
|
+
if (BIGDECIMAL_NEGATIVE_P(x)) {
|
2355
2400
|
if (is_integer(vexp)) {
|
2356
2401
|
if (is_even(vexp)) {
|
2357
2402
|
/* (-Infinity) ** (-even_integer) -> +0 */
|
@@ -2373,7 +2418,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2373
2418
|
}
|
2374
2419
|
else {
|
2375
2420
|
y = VpCreateRbObject(n, "0#");
|
2376
|
-
if (
|
2421
|
+
if (BIGDECIMAL_NEGATIVE_P(x)) {
|
2377
2422
|
if (is_integer(vexp)) {
|
2378
2423
|
if (is_even(vexp)) {
|
2379
2424
|
VpSetPosInf(y);
|
@@ -2414,7 +2459,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2414
2459
|
}
|
2415
2460
|
return ToValue(y);
|
2416
2461
|
}
|
2417
|
-
else if (
|
2462
|
+
else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
|
2418
2463
|
return ToValue(VpCreateRbObject(n, "-0"));
|
2419
2464
|
}
|
2420
2465
|
else {
|
@@ -2432,7 +2477,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2432
2477
|
}
|
2433
2478
|
return ToValue(y);
|
2434
2479
|
}
|
2435
|
-
else if (
|
2480
|
+
else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
|
2436
2481
|
return ToValue(VpCreateRbObject(n, "-0"));
|
2437
2482
|
}
|
2438
2483
|
else {
|
@@ -2492,7 +2537,7 @@ static Real *BigDecimal_new(int argc, VALUE *argv);
|
|
2492
2537
|
* If it is a String, spaces are ignored and unrecognized characters
|
2493
2538
|
* terminate the value.
|
2494
2539
|
*
|
2495
|
-
* digits:: The number of significant digits, as
|
2540
|
+
* digits:: The number of significant digits, as an Integer. If omitted or 0,
|
2496
2541
|
* the number of significant digits is determined from the initial
|
2497
2542
|
* value.
|
2498
2543
|
*
|
@@ -2501,10 +2546,10 @@ static Real *BigDecimal_new(int argc, VALUE *argv);
|
|
2501
2546
|
*
|
2502
2547
|
* ==== Exceptions
|
2503
2548
|
*
|
2504
|
-
* TypeError:: If the +initial+ type is neither
|
2549
|
+
* TypeError:: If the +initial+ type is neither Integer, Float,
|
2505
2550
|
* Rational, nor BigDecimal, this exception is raised.
|
2506
2551
|
*
|
2507
|
-
* TypeError:: If the +digits+ is not
|
2552
|
+
* TypeError:: If the +digits+ is not an Integer, this exception is raised.
|
2508
2553
|
*
|
2509
2554
|
* ArgumentError:: If +initial+ is a Float, and the +digits+ is larger than
|
2510
2555
|
* Float::DIG + 1, this exception is raised.
|
@@ -2534,7 +2579,7 @@ BigDecimal_initialize(int argc, VALUE *argv, VALUE self)
|
|
2534
2579
|
|
2535
2580
|
/* :nodoc:
|
2536
2581
|
*
|
2537
|
-
* private method
|
2582
|
+
* private method for dup and clone the provided BigDecimal +other+
|
2538
2583
|
*/
|
2539
2584
|
static VALUE
|
2540
2585
|
BigDecimal_initialize_copy(VALUE self, VALUE other)
|
@@ -2554,6 +2599,7 @@ BigDecimal_new(int argc, VALUE *argv)
|
|
2554
2599
|
size_t mf;
|
2555
2600
|
VALUE nFig;
|
2556
2601
|
VALUE iniValue;
|
2602
|
+
double d;
|
2557
2603
|
|
2558
2604
|
if (rb_scan_args(argc, argv, "11", &iniValue, &nFig) == 1) {
|
2559
2605
|
mf = 0;
|
@@ -2575,6 +2621,12 @@ BigDecimal_new(int argc, VALUE *argv)
|
|
2575
2621
|
return GetVpValue(iniValue, 1);
|
2576
2622
|
|
2577
2623
|
case T_FLOAT:
|
2624
|
+
d = RFLOAT_VALUE(iniValue);
|
2625
|
+
if (!isfinite(d)) {
|
2626
|
+
Real *pv = VpCreateRbObject(1, NULL);
|
2627
|
+
VpDtoV(pv, d);
|
2628
|
+
return pv;
|
2629
|
+
}
|
2578
2630
|
if (mf > DBL_DIG+1) {
|
2579
2631
|
rb_raise(rb_eArgError, "precision too large.");
|
2580
2632
|
}
|
@@ -2602,11 +2654,13 @@ BigDecimal_global_new(int argc, VALUE *argv, VALUE self)
|
|
2602
2654
|
{
|
2603
2655
|
ENTER(1);
|
2604
2656
|
Real *pv;
|
2657
|
+
VALUE obj;
|
2605
2658
|
|
2659
|
+
obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0);
|
2606
2660
|
GUARD_OBJ(pv, BigDecimal_new(argc, argv));
|
2607
2661
|
if (ToValue(pv)) pv = VpCopy(NULL, pv);
|
2608
|
-
|
2609
|
-
return pv->obj;
|
2662
|
+
RTYPEDDATA_DATA(obj) = pv;
|
2663
|
+
return pv->obj = obj;
|
2610
2664
|
}
|
2611
2665
|
|
2612
2666
|
/* call-seq:
|
@@ -2630,8 +2684,7 @@ BigDecimal_limit(int argc, VALUE *argv, VALUE self)
|
|
2630
2684
|
if (rb_scan_args(argc, argv, "01", &nFig) == 1) {
|
2631
2685
|
int nf;
|
2632
2686
|
if (NIL_P(nFig)) return nCur;
|
2633
|
-
|
2634
|
-
nf = FIX2INT(nFig);
|
2687
|
+
nf = NUM2INT(nFig);
|
2635
2688
|
if (nf < 0) {
|
2636
2689
|
rb_raise(rb_eArgError, "argument must be positive");
|
2637
2690
|
}
|
@@ -2768,13 +2821,13 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
|
|
2768
2821
|
rb_raise(rb_eArgError, "Zero or negative precision for exp");
|
2769
2822
|
}
|
2770
2823
|
|
2771
|
-
/* TODO: the following switch statement is
|
2824
|
+
/* TODO: the following switch statement is almost same as one in the
|
2772
2825
|
* BigDecimalCmp function. */
|
2773
2826
|
switch (TYPE(x)) {
|
2774
2827
|
case T_DATA:
|
2775
2828
|
if (!is_kind_of_BigDecimal(x)) break;
|
2776
2829
|
vx = DATA_PTR(x);
|
2777
|
-
negative =
|
2830
|
+
negative = BIGDECIMAL_NEGATIVE_P(vx);
|
2778
2831
|
infinite = VpIsPosInf(vx) || VpIsNegInf(vx);
|
2779
2832
|
nan = VpIsNaN(vx);
|
2780
2833
|
break;
|
@@ -2827,7 +2880,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
|
|
2827
2880
|
x = vx->obj;
|
2828
2881
|
|
2829
2882
|
n = prec + rmpd_double_figures();
|
2830
|
-
negative =
|
2883
|
+
negative = BIGDECIMAL_NEGATIVE_P(vx);
|
2831
2884
|
if (negative) {
|
2832
2885
|
VpSetSign(vx, 1);
|
2833
2886
|
}
|
@@ -2906,14 +2959,14 @@ BigMath_s_log(VALUE klass, VALUE x, VALUE vprec)
|
|
2906
2959
|
rb_raise(rb_eArgError, "Zero or negative precision for exp");
|
2907
2960
|
}
|
2908
2961
|
|
2909
|
-
/* TODO: the following switch statement is
|
2962
|
+
/* TODO: the following switch statement is almost same as one in the
|
2910
2963
|
* BigDecimalCmp function. */
|
2911
2964
|
switch (TYPE(x)) {
|
2912
2965
|
case T_DATA:
|
2913
2966
|
if (!is_kind_of_BigDecimal(x)) break;
|
2914
2967
|
vx = DATA_PTR(x);
|
2915
2968
|
zero = VpIsZero(vx);
|
2916
|
-
negative =
|
2969
|
+
negative = BIGDECIMAL_NEGATIVE_P(vx);
|
2917
2970
|
infinite = VpIsPosInf(vx) || VpIsNegInf(vx);
|
2918
2971
|
nan = VpIsNaN(vx);
|
2919
2972
|
break;
|
@@ -3134,9 +3187,8 @@ get_vp_value:
|
|
3134
3187
|
*
|
3135
3188
|
* Copyright (C) 2002 by Shigeo Kobayashi <shigeo@tinyforest.gr.jp>.
|
3136
3189
|
*
|
3137
|
-
*
|
3138
|
-
*
|
3139
|
-
* of the BigDecimal distribution.
|
3190
|
+
* BigDecimal is released under the Ruby and 2-clause BSD licenses.
|
3191
|
+
* See LICENSE.txt for details.
|
3140
3192
|
*
|
3141
3193
|
* Maintained by mrkn <mrkn@mrkn.jp> and ruby-core members.
|
3142
3194
|
*
|
@@ -3217,7 +3269,7 @@ Init_bigdecimal(void)
|
|
3217
3269
|
rb_define_const(rb_cBigDecimal, "EXCEPTION_OVERFLOW", INT2FIX(VP_EXCEPTION_OVERFLOW));
|
3218
3270
|
|
3219
3271
|
/*
|
3220
|
-
*
|
3272
|
+
* 0x10: Determines what happens when a division by zero is performed.
|
3221
3273
|
* See BigDecimal.mode.
|
3222
3274
|
*/
|
3223
3275
|
rb_define_const(rb_cBigDecimal, "EXCEPTION_ZERODIVIDE", INT2FIX(VP_EXCEPTION_ZERODIVIDE));
|
@@ -3359,6 +3411,7 @@ Init_bigdecimal(void)
|
|
3359
3411
|
id_floor = rb_intern_const("floor");
|
3360
3412
|
id_to_r = rb_intern_const("to_r");
|
3361
3413
|
id_eq = rb_intern_const("==");
|
3414
|
+
id_half = rb_intern_const("half");
|
3362
3415
|
}
|
3363
3416
|
|
3364
3417
|
/*
|
@@ -3386,7 +3439,14 @@ static Real *VpPt5; /* constant 0.5 */
|
|
3386
3439
|
#define MemCmp(x,y,z) memcmp(x,y,z)
|
3387
3440
|
#define StrCmp(x,y) strcmp(x,y)
|
3388
3441
|
|
3389
|
-
|
3442
|
+
enum op_sw {
|
3443
|
+
OP_SW_ADD = 1, /* + */
|
3444
|
+
OP_SW_SUB, /* - */
|
3445
|
+
OP_SW_MULT, /* * */
|
3446
|
+
OP_SW_DIV /* / */
|
3447
|
+
};
|
3448
|
+
|
3449
|
+
static int VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw);
|
3390
3450
|
static int AddExponent(Real *a, SIGNED_VALUE n);
|
3391
3451
|
static BDIGIT VpAddAbs(Real *a,Real *b,Real *c);
|
3392
3452
|
static BDIGIT VpSubAbs(Real *a,Real *b,Real *c);
|
@@ -3413,7 +3473,7 @@ VpMemAlloc(size_t mb)
|
|
3413
3473
|
return p;
|
3414
3474
|
}
|
3415
3475
|
|
3416
|
-
|
3476
|
+
VP_EXPORT void *
|
3417
3477
|
VpMemRealloc(void *ptr, size_t mb)
|
3418
3478
|
{
|
3419
3479
|
void *p = xrealloc(ptr, mb);
|
@@ -3431,12 +3491,12 @@ VpFree(Real *pv)
|
|
3431
3491
|
#ifdef BIGDECIMAL_DEBUG
|
3432
3492
|
gnAlloc--; /* Decrement allocation count */
|
3433
3493
|
if (gnAlloc == 0) {
|
3434
|
-
printf(" *************** All memories allocated freed
|
3435
|
-
getchar()
|
3494
|
+
printf(" *************** All memories allocated freed ****************\n");
|
3495
|
+
/*getchar();*/
|
3436
3496
|
}
|
3437
3497
|
if (gnAlloc < 0) {
|
3438
3498
|
printf(" ??????????? Too many memory free calls(%d) ?????????????\n", gnAlloc);
|
3439
|
-
getchar()
|
3499
|
+
/*getchar();*/
|
3440
3500
|
}
|
3441
3501
|
#endif /* BIGDECIMAL_DEBUG */
|
3442
3502
|
}
|
@@ -3466,7 +3526,7 @@ VpGetException (void)
|
|
3466
3526
|
return RMPD_EXCEPTION_MODE_DEFAULT;
|
3467
3527
|
}
|
3468
3528
|
|
3469
|
-
return (
|
3529
|
+
return NUM2USHORT(vmode);
|
3470
3530
|
}
|
3471
3531
|
|
3472
3532
|
static void
|
@@ -3536,7 +3596,7 @@ VpGetRoundMode(void)
|
|
3536
3596
|
return RMPD_ROUNDING_MODE_DEFAULT;
|
3537
3597
|
}
|
3538
3598
|
|
3539
|
-
return (
|
3599
|
+
return NUM2USHORT(vmode);
|
3540
3600
|
}
|
3541
3601
|
|
3542
3602
|
VP_EXPORT int
|
@@ -3673,7 +3733,7 @@ VpException(unsigned short f, const char *str,int always)
|
|
3673
3733
|
/* Throw exception or returns 0,when resulting c is Inf or NaN */
|
3674
3734
|
/* sw=1:+ 2:- 3:* 4:/ */
|
3675
3735
|
static int
|
3676
|
-
VpIsDefOP(Real *c,Real *a,Real *b,
|
3736
|
+
VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw)
|
3677
3737
|
{
|
3678
3738
|
if (VpIsNaN(a) || VpIsNaN(b)) {
|
3679
3739
|
/* at least a or b is NaN */
|
@@ -3684,7 +3744,7 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
|
|
3684
3744
|
if (VpIsInf(a)) {
|
3685
3745
|
if (VpIsInf(b)) {
|
3686
3746
|
switch(sw) {
|
3687
|
-
case
|
3747
|
+
case OP_SW_ADD: /* + */
|
3688
3748
|
if (VpGetSign(a) == VpGetSign(b)) {
|
3689
3749
|
VpSetInf(c, VpGetSign(a));
|
3690
3750
|
goto Inf;
|
@@ -3693,7 +3753,7 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
|
|
3693
3753
|
VpSetNaN(c);
|
3694
3754
|
goto NaN;
|
3695
3755
|
}
|
3696
|
-
case
|
3756
|
+
case OP_SW_SUB: /* - */
|
3697
3757
|
if (VpGetSign(a) != VpGetSign(b)) {
|
3698
3758
|
VpSetInf(c, VpGetSign(a));
|
3699
3759
|
goto Inf;
|
@@ -3702,12 +3762,10 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
|
|
3702
3762
|
VpSetNaN(c);
|
3703
3763
|
goto NaN;
|
3704
3764
|
}
|
3705
|
-
|
3706
|
-
case 3: /* * */
|
3765
|
+
case OP_SW_MULT: /* * */
|
3707
3766
|
VpSetInf(c, VpGetSign(a)*VpGetSign(b));
|
3708
3767
|
goto Inf;
|
3709
|
-
|
3710
|
-
case 4: /* / */
|
3768
|
+
case OP_SW_DIV: /* / */
|
3711
3769
|
VpSetNaN(c);
|
3712
3770
|
goto NaN;
|
3713
3771
|
}
|
@@ -3716,18 +3774,18 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
|
|
3716
3774
|
}
|
3717
3775
|
/* Inf op Finite */
|
3718
3776
|
switch(sw) {
|
3719
|
-
case
|
3720
|
-
case
|
3777
|
+
case OP_SW_ADD: /* + */
|
3778
|
+
case OP_SW_SUB: /* - */
|
3721
3779
|
VpSetInf(c, VpGetSign(a));
|
3722
3780
|
break;
|
3723
|
-
case
|
3781
|
+
case OP_SW_MULT: /* * */
|
3724
3782
|
if (VpIsZero(b)) {
|
3725
3783
|
VpSetNaN(c);
|
3726
3784
|
goto NaN;
|
3727
3785
|
}
|
3728
3786
|
VpSetInf(c, VpGetSign(a)*VpGetSign(b));
|
3729
3787
|
break;
|
3730
|
-
case
|
3788
|
+
case OP_SW_DIV: /* / */
|
3731
3789
|
VpSetInf(c, VpGetSign(a)*VpGetSign(b));
|
3732
3790
|
}
|
3733
3791
|
goto Inf;
|
@@ -3735,20 +3793,20 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
|
|
3735
3793
|
|
3736
3794
|
if (VpIsInf(b)) {
|
3737
3795
|
switch(sw) {
|
3738
|
-
case
|
3796
|
+
case OP_SW_ADD: /* + */
|
3739
3797
|
VpSetInf(c, VpGetSign(b));
|
3740
3798
|
break;
|
3741
|
-
case
|
3799
|
+
case OP_SW_SUB: /* - */
|
3742
3800
|
VpSetInf(c, -VpGetSign(b));
|
3743
3801
|
break;
|
3744
|
-
case
|
3802
|
+
case OP_SW_MULT: /* * */
|
3745
3803
|
if (VpIsZero(a)) {
|
3746
3804
|
VpSetNaN(c);
|
3747
3805
|
goto NaN;
|
3748
3806
|
}
|
3749
3807
|
VpSetInf(c, VpGetSign(a)*VpGetSign(b));
|
3750
3808
|
break;
|
3751
|
-
case
|
3809
|
+
case OP_SW_DIV: /* / */
|
3752
3810
|
VpSetZero(c, VpGetSign(a)*VpGetSign(b));
|
3753
3811
|
}
|
3754
3812
|
goto Inf;
|
@@ -3756,7 +3814,13 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
|
|
3756
3814
|
return 1; /* Results OK */
|
3757
3815
|
|
3758
3816
|
Inf:
|
3759
|
-
|
3817
|
+
if (VpIsPosInf(c)) {
|
3818
|
+
return VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 0);
|
3819
|
+
}
|
3820
|
+
else {
|
3821
|
+
return VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 0);
|
3822
|
+
}
|
3823
|
+
|
3760
3824
|
NaN:
|
3761
3825
|
return VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'", 0);
|
3762
3826
|
}
|
@@ -3831,12 +3895,12 @@ VpInit(BDIGIT BaseVal)
|
|
3831
3895
|
|
3832
3896
|
#ifdef BIGDECIMAL_DEBUG
|
3833
3897
|
if (gfDebug) {
|
3834
|
-
printf("VpInit: BaseVal = %
|
3835
|
-
printf("
|
3836
|
-
printf("
|
3837
|
-
printf("
|
3838
|
-
printf("
|
3839
|
-
printf("
|
3898
|
+
printf("VpInit: BaseVal = %"PRIuBDIGIT"\n", BaseVal);
|
3899
|
+
printf("\tBASE = %"PRIuBDIGIT"\n", BASE);
|
3900
|
+
printf("\tHALF_BASE = %"PRIuBDIGIT"\n", HALF_BASE);
|
3901
|
+
printf("\tBASE1 = %"PRIuBDIGIT"\n", BASE1);
|
3902
|
+
printf("\tBASE_FIG = %u\n", BASE_FIG);
|
3903
|
+
printf("\tDBLE_FIG = %d\n", DBLE_FIG);
|
3840
3904
|
}
|
3841
3905
|
#endif /* BIGDECIMAL_DEBUG */
|
3842
3906
|
|
@@ -3863,7 +3927,7 @@ AddExponent(Real *a, SIGNED_VALUE n)
|
|
3863
3927
|
goto overflow;
|
3864
3928
|
mb = m*(SIGNED_VALUE)BASE_FIG;
|
3865
3929
|
eb = e*(SIGNED_VALUE)BASE_FIG;
|
3866
|
-
if (mb
|
3930
|
+
if (eb - mb > 0) goto overflow;
|
3867
3931
|
}
|
3868
3932
|
}
|
3869
3933
|
else if (n < 0) {
|
@@ -3872,7 +3936,7 @@ AddExponent(Real *a, SIGNED_VALUE n)
|
|
3872
3936
|
goto underflow;
|
3873
3937
|
mb = m*(SIGNED_VALUE)BASE_FIG;
|
3874
3938
|
eb = e*(SIGNED_VALUE)BASE_FIG;
|
3875
|
-
if (mb >
|
3939
|
+
if (mb - eb > 0) goto underflow;
|
3876
3940
|
}
|
3877
3941
|
a->exponent = m;
|
3878
3942
|
return 1;
|
@@ -3903,7 +3967,8 @@ overflow:
|
|
3903
3967
|
VP_EXPORT Real *
|
3904
3968
|
VpAlloc(size_t mx, const char *szVal)
|
3905
3969
|
{
|
3906
|
-
|
3970
|
+
const char *orig_szVal = szVal;
|
3971
|
+
size_t i, ni, ipn, ipf, nf, ipe, ne, dot_seen, exp_seen, nalloc;
|
3907
3972
|
char v, *psz;
|
3908
3973
|
int sign=1;
|
3909
3974
|
Real *vp = NULL;
|
@@ -3914,28 +3979,48 @@ VpAlloc(size_t mx, const char *szVal)
|
|
3914
3979
|
if (mx == 0) ++mx;
|
3915
3980
|
|
3916
3981
|
if (szVal) {
|
3917
|
-
|
3918
|
-
|
3919
|
-
|
3920
|
-
|
3921
|
-
|
3922
|
-
|
3923
|
-
|
3924
|
-
|
3925
|
-
|
3926
|
-
|
3927
|
-
|
3928
|
-
|
3982
|
+
while (ISSPACE(*szVal)) szVal++;
|
3983
|
+
if (*szVal != '#') {
|
3984
|
+
if (mf) {
|
3985
|
+
mf = (mf + BASE_FIG - 1) / BASE_FIG + 2; /* Needs 1 more for div */
|
3986
|
+
if (mx > mf) {
|
3987
|
+
mx = mf;
|
3988
|
+
}
|
3989
|
+
}
|
3990
|
+
}
|
3991
|
+
else {
|
3992
|
+
++szVal;
|
3993
|
+
}
|
3929
3994
|
}
|
3930
3995
|
else {
|
3931
|
-
|
3932
|
-
|
3933
|
-
|
3934
|
-
|
3935
|
-
|
3936
|
-
|
3937
|
-
|
3938
|
-
|
3996
|
+
/* necessary to be able to store */
|
3997
|
+
/* at least mx digits. */
|
3998
|
+
/* szVal==NULL ==> allocate zero value. */
|
3999
|
+
vp = VpAllocReal(mx);
|
4000
|
+
/* xmalloc() alway returns(or throw interruption) */
|
4001
|
+
vp->MaxPrec = mx; /* set max precision */
|
4002
|
+
VpSetZero(vp, 1); /* initialize vp to zero. */
|
4003
|
+
return vp;
|
4004
|
+
}
|
4005
|
+
|
4006
|
+
/* Check on Inf & NaN */
|
4007
|
+
if (StrCmp(szVal, SZ_PINF) == 0 || StrCmp(szVal, SZ_INF) == 0 ) {
|
4008
|
+
vp = VpAllocReal(1);
|
4009
|
+
vp->MaxPrec = 1; /* set max precision */
|
4010
|
+
VpSetPosInf(vp);
|
4011
|
+
return vp;
|
4012
|
+
}
|
4013
|
+
if (StrCmp(szVal, SZ_NINF) == 0) {
|
4014
|
+
vp = VpAllocReal(1);
|
4015
|
+
vp->MaxPrec = 1; /* set max precision */
|
4016
|
+
VpSetNegInf(vp);
|
4017
|
+
return vp;
|
4018
|
+
}
|
4019
|
+
if (StrCmp(szVal, SZ_NaN) == 0) {
|
4020
|
+
vp = VpAllocReal(1);
|
4021
|
+
vp->MaxPrec = 1; /* set max precision */
|
4022
|
+
VpSetNaN(vp);
|
4023
|
+
return vp;
|
3939
4024
|
}
|
3940
4025
|
|
3941
4026
|
/* Skip all '_' after digit: 2006-6-30 */
|
@@ -3945,45 +4030,24 @@ VpAlloc(size_t mx, const char *szVal)
|
|
3945
4030
|
i = 0;
|
3946
4031
|
ipn = 0;
|
3947
4032
|
while ((psz[i] = szVal[ipn]) != 0) {
|
3948
|
-
|
3949
|
-
|
3950
|
-
|
3951
|
-
|
3952
|
-
|
3953
|
-
|
3954
|
-
|
3955
|
-
|
3956
|
-
|
3957
|
-
|
3958
|
-
|
3959
|
-
|
3960
|
-
|
3961
|
-
|
3962
|
-
|
3963
|
-
else break;
|
4033
|
+
if (ISSPACE(psz[i])) {
|
4034
|
+
psz[i] = 0;
|
4035
|
+
break;
|
4036
|
+
}
|
4037
|
+
if (ISDIGIT(psz[i])) ++ni;
|
4038
|
+
if (psz[i] == '_') {
|
4039
|
+
if (ni > 0) {
|
4040
|
+
ipn++;
|
4041
|
+
continue;
|
4042
|
+
}
|
4043
|
+
psz[i] = 0;
|
4044
|
+
break;
|
4045
|
+
}
|
4046
|
+
++i;
|
4047
|
+
++ipn;
|
3964
4048
|
}
|
3965
4049
|
szVal = psz;
|
3966
4050
|
|
3967
|
-
/* Check on Inf & NaN */
|
3968
|
-
if (StrCmp(szVal, SZ_PINF) == 0 || StrCmp(szVal, SZ_INF) == 0 ) {
|
3969
|
-
vp = VpAllocReal(1);
|
3970
|
-
vp->MaxPrec = 1; /* set max precision */
|
3971
|
-
VpSetPosInf(vp);
|
3972
|
-
return vp;
|
3973
|
-
}
|
3974
|
-
if (StrCmp(szVal, SZ_NINF) == 0) {
|
3975
|
-
vp = VpAllocReal(1);
|
3976
|
-
vp->MaxPrec = 1; /* set max precision */
|
3977
|
-
VpSetNegInf(vp);
|
3978
|
-
return vp;
|
3979
|
-
}
|
3980
|
-
if (StrCmp(szVal, SZ_NaN) == 0) {
|
3981
|
-
vp = VpAllocReal(1);
|
3982
|
-
vp->MaxPrec = 1; /* set max precision */
|
3983
|
-
VpSetNaN(vp);
|
3984
|
-
return vp;
|
3985
|
-
}
|
3986
|
-
|
3987
4051
|
/* check on number szVal[] */
|
3988
4052
|
ipn = i = 0;
|
3989
4053
|
if (szVal[i] == '-') { sign=-1; ++i; }
|
@@ -3991,46 +4055,55 @@ VpAlloc(size_t mx, const char *szVal)
|
|
3991
4055
|
/* Skip digits */
|
3992
4056
|
ni = 0; /* digits in mantissa */
|
3993
4057
|
while ((v = szVal[i]) != 0) {
|
3994
|
-
|
3995
|
-
|
3996
|
-
|
4058
|
+
if (!ISDIGIT(v)) break;
|
4059
|
+
++i;
|
4060
|
+
++ni;
|
3997
4061
|
}
|
3998
4062
|
nf = 0;
|
3999
4063
|
ipf = 0;
|
4000
4064
|
ipe = 0;
|
4001
4065
|
ne = 0;
|
4066
|
+
dot_seen = 0;
|
4067
|
+
exp_seen = 0;
|
4002
4068
|
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
|
-
|
4069
|
+
/* other than digit nor \0 */
|
4070
|
+
if (szVal[i] == '.') { /* xxx. */
|
4071
|
+
dot_seen = 1;
|
4072
|
+
++i;
|
4073
|
+
ipf = i;
|
4074
|
+
while ((v = szVal[i]) != 0) { /* get fraction part. */
|
4075
|
+
if (!ISDIGIT(v)) break;
|
4076
|
+
++i;
|
4077
|
+
++nf;
|
4078
|
+
}
|
4079
|
+
}
|
4080
|
+
ipe = 0; /* Exponent */
|
4081
|
+
|
4082
|
+
switch (szVal[i]) {
|
4083
|
+
case '\0':
|
4084
|
+
break;
|
4085
|
+
case 'e': case 'E':
|
4086
|
+
case 'd': case 'D':
|
4087
|
+
exp_seen = 1;
|
4088
|
+
++i;
|
4089
|
+
ipe = i;
|
4090
|
+
v = szVal[i];
|
4091
|
+
if ((v == '-') || (v == '+')) ++i;
|
4092
|
+
while ((v=szVal[i]) != 0) {
|
4093
|
+
if (!ISDIGIT(v)) break;
|
4094
|
+
++i;
|
4095
|
+
++ne;
|
4096
|
+
}
|
4097
|
+
break;
|
4098
|
+
default:
|
4099
|
+
break;
|
4100
|
+
}
|
4101
|
+
}
|
4102
|
+
if (((ni == 0 || dot_seen) && nf == 0) || (exp_seen && ne == 0)) {
|
4103
|
+
VALUE str = rb_str_new2(orig_szVal);
|
4104
|
+
rb_raise(rb_eArgError, "invalid value for BigDecimal(): \"%"PRIsVALUE"\"", str);
|
4033
4105
|
}
|
4106
|
+
|
4034
4107
|
nalloc = (ni + nf + BASE_FIG - 1) / BASE_FIG + 1; /* set effective allocation */
|
4035
4108
|
/* units for szVal[] */
|
4036
4109
|
if (mx == 0) mx = 1;
|
@@ -4098,7 +4171,7 @@ VpAsgn(Real *c, Real *a, int isw)
|
|
4098
4171
|
|
4099
4172
|
/*
|
4100
4173
|
* c = a + b when operation = 1 or 2
|
4101
|
-
*
|
4174
|
+
* c = a - b when operation = -1 or -2.
|
4102
4175
|
* Returns number of significant digits of c
|
4103
4176
|
*/
|
4104
4177
|
VP_EXPORT size_t
|
@@ -4117,7 +4190,7 @@ VpAddSub(Real *c, Real *a, Real *b, int operation)
|
|
4117
4190
|
}
|
4118
4191
|
#endif /* BIGDECIMAL_DEBUG */
|
4119
4192
|
|
4120
|
-
if (!VpIsDefOP(c, a, b, (operation > 0) ?
|
4193
|
+
if (!VpIsDefOP(c, a, b, (operation > 0) ? OP_SW_ADD : OP_SW_SUB)) return 0; /* No significant digits */
|
4121
4194
|
|
4122
4195
|
/* check if a or b is zero */
|
4123
4196
|
if (VpIsZero(a)) {
|
@@ -4231,7 +4304,7 @@ end_if:
|
|
4231
4304
|
}
|
4232
4305
|
|
4233
4306
|
/*
|
4234
|
-
* Addition of two variable
|
4307
|
+
* Addition of two values with variable precision
|
4235
4308
|
* a and b assuming abs(a)>abs(b).
|
4236
4309
|
* c = abs(a) + abs(b) ; where |a|>=|b|
|
4237
4310
|
*/
|
@@ -4453,7 +4526,7 @@ VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos,
|
|
4453
4526
|
|
4454
4527
|
size_t const round_limit = (VpGetPrecLimit() + BASE_FIG - 1) / BASE_FIG;
|
4455
4528
|
|
4456
|
-
assert(a->exponent >= b->
|
4529
|
+
assert(a->exponent >= b->exponent);
|
4457
4530
|
|
4458
4531
|
c->frac[0] = 0;
|
4459
4532
|
*av = *bv = 0;
|
@@ -4573,7 +4646,7 @@ VpMult(Real *c, Real *a, Real *b)
|
|
4573
4646
|
}
|
4574
4647
|
#endif /* BIGDECIMAL_DEBUG */
|
4575
4648
|
|
4576
|
-
if (!VpIsDefOP(c, a, b,
|
4649
|
+
if (!VpIsDefOP(c, a, b, OP_SW_MULT)) return 0; /* No significant digit */
|
4577
4650
|
|
4578
4651
|
if (VpIsZero(a) || VpIsZero(b)) {
|
4579
4652
|
/* at least a or b is zero */
|
@@ -4685,7 +4758,7 @@ Exit:
|
|
4685
4758
|
/*
|
4686
4759
|
* c = a / b, remainder = r
|
4687
4760
|
*/
|
4688
|
-
|
4761
|
+
VP_EXPORT size_t
|
4689
4762
|
VpDivd(Real *c, Real *r, Real *a, Real *b)
|
4690
4763
|
{
|
4691
4764
|
size_t word_a, word_b, word_c, word_r;
|
@@ -4703,14 +4776,14 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
|
|
4703
4776
|
#endif /*BIGDECIMAL_DEBUG */
|
4704
4777
|
|
4705
4778
|
VpSetNaN(r);
|
4706
|
-
if (!VpIsDefOP(c, a, b,
|
4779
|
+
if (!VpIsDefOP(c, a, b, OP_SW_DIV)) goto Exit;
|
4707
4780
|
if (VpIsZero(a) && VpIsZero(b)) {
|
4708
4781
|
VpSetNaN(c);
|
4709
|
-
return VpException(VP_EXCEPTION_NaN, "
|
4782
|
+
return VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'", 0);
|
4710
4783
|
}
|
4711
4784
|
if (VpIsZero(b)) {
|
4712
4785
|
VpSetInf(c, VpGetSign(a) * VpGetSign(b));
|
4713
|
-
return VpException(VP_EXCEPTION_ZERODIVIDE, "
|
4786
|
+
return VpException(VP_EXCEPTION_ZERODIVIDE, "Divide by zero", 0);
|
4714
4787
|
}
|
4715
4788
|
if (VpIsZero(a)) {
|
4716
4789
|
/* numerator a is zero */
|
@@ -4990,7 +5063,7 @@ VpComp(Real *a, Real *b)
|
|
4990
5063
|
goto Exit;
|
4991
5064
|
}
|
4992
5065
|
|
4993
|
-
/* a and b have same exponent, then compare significand. */
|
5066
|
+
/* a and b have same exponent, then compare their significand. */
|
4994
5067
|
mx = (a->Prec < b->Prec) ? a->Prec : b->Prec;
|
4995
5068
|
ind = 0;
|
4996
5069
|
while (ind < mx) {
|
@@ -5031,8 +5104,8 @@ Exit:
|
|
5031
5104
|
* % ... VP variable. To print '%', use '%%'.
|
5032
5105
|
* \n ... new line
|
5033
5106
|
* \b ... backspace
|
5034
|
-
*
|
5035
|
-
* Note: % must
|
5107
|
+
* \t ... tab
|
5108
|
+
* Note: % must not appear more than once
|
5036
5109
|
* a ... VP variable to be printed
|
5037
5110
|
*/
|
5038
5111
|
#ifdef BIGDECIMAL_ENABLE_VPRINT
|
@@ -5042,24 +5115,6 @@ VPrint(FILE *fp, const char *cntl_chr, Real *a)
|
|
5042
5115
|
size_t i, j, nc, nd, ZeroSup, sep = 10;
|
5043
5116
|
BDIGIT m, e, nn;
|
5044
5117
|
|
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
5118
|
j = 0;
|
5064
5119
|
nd = nc = 0; /* nd : number of digits in fraction part(every 10 digits, */
|
5065
5120
|
/* nd<=10). */
|
@@ -5068,8 +5123,20 @@ VPrint(FILE *fp, const char *cntl_chr, Real *a)
|
|
5068
5123
|
while (*(cntl_chr + j)) {
|
5069
5124
|
if (*(cntl_chr + j) == '%' && *(cntl_chr + j + 1) != '%') {
|
5070
5125
|
nc = 0;
|
5071
|
-
if (
|
5072
|
-
|
5126
|
+
if (VpIsNaN(a)) {
|
5127
|
+
fprintf(fp, SZ_NaN);
|
5128
|
+
nc += 8;
|
5129
|
+
}
|
5130
|
+
else if (VpIsPosInf(a)) {
|
5131
|
+
fprintf(fp, SZ_INF);
|
5132
|
+
nc += 8;
|
5133
|
+
}
|
5134
|
+
else if (VpIsNegInf(a)) {
|
5135
|
+
fprintf(fp, SZ_NINF);
|
5136
|
+
nc += 9;
|
5137
|
+
}
|
5138
|
+
else if (!VpIsZero(a)) {
|
5139
|
+
if (BIGDECIMAL_NEGATIVE_P(a)) {
|
5073
5140
|
fprintf(fp, "-");
|
5074
5141
|
++nc;
|
5075
5142
|
}
|
@@ -5158,7 +5225,7 @@ VpFormatSt(char *psz, size_t fFmt)
|
|
5158
5225
|
if (!ch) break;
|
5159
5226
|
if (ISSPACE(ch) || ch=='-' || ch=='+') continue;
|
5160
5227
|
if (ch == '.') { nf = 0; continue; }
|
5161
|
-
if (ch == 'E') break;
|
5228
|
+
if (ch == 'E' || ch == 'e') break;
|
5162
5229
|
|
5163
5230
|
if (++nf > fFmt) {
|
5164
5231
|
memmove(psz + i + 1, psz + i, ie - i + 1);
|
@@ -5207,7 +5274,7 @@ VpSzMantissa(Real *a,char *psz)
|
|
5207
5274
|
|
5208
5275
|
ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
|
5209
5276
|
if (!VpIsZero(a)) {
|
5210
|
-
if (
|
5277
|
+
if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
|
5211
5278
|
n = a->Prec;
|
5212
5279
|
for (i = 0; i < n; ++i) {
|
5213
5280
|
m = BASE1;
|
@@ -5281,7 +5348,7 @@ VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
|
|
5281
5348
|
|
5282
5349
|
ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
|
5283
5350
|
|
5284
|
-
if (
|
5351
|
+
if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
|
5285
5352
|
else if (fPlus == 1) *psz++ = ' ';
|
5286
5353
|
else if (fPlus == 2) *psz++ = '+';
|
5287
5354
|
|
@@ -5312,7 +5379,7 @@ VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
|
|
5312
5379
|
while (psz[-1] == '0') {
|
5313
5380
|
*(--psz) = 0;
|
5314
5381
|
}
|
5315
|
-
sprintf(psz, "
|
5382
|
+
sprintf(psz, "e%"PRIdSIZE, ex);
|
5316
5383
|
if (fFmt) VpFormatSt(pszSav, fFmt);
|
5317
5384
|
}
|
5318
5385
|
|
@@ -5327,7 +5394,7 @@ VpToFString(Real *a, char *psz, size_t fFmt, int fPlus)
|
|
5327
5394
|
|
5328
5395
|
if (VpToSpecialString(a, psz, fPlus)) return;
|
5329
5396
|
|
5330
|
-
if (
|
5397
|
+
if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
|
5331
5398
|
else if (fPlus == 1) *psz++ = ' ';
|
5332
5399
|
else if (fPlus == 2) *psz++ = '+';
|
5333
5400
|
|
@@ -5749,21 +5816,22 @@ VpSqrt(Real *y, Real *x)
|
|
5749
5816
|
ssize_t nr;
|
5750
5817
|
double val;
|
5751
5818
|
|
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);
|
5819
|
+
/* Zero or +Infinity ? */
|
5820
|
+
if (VpIsZero(x) || VpIsPosInf(x)) {
|
5821
|
+
VpAsgn(y,x,1);
|
5760
5822
|
goto Exit;
|
5761
5823
|
}
|
5762
5824
|
|
5763
5825
|
/* Negative ? */
|
5764
|
-
if (
|
5826
|
+
if (BIGDECIMAL_NEGATIVE_P(x)) {
|
5827
|
+
VpSetNaN(y);
|
5828
|
+
return VpException(VP_EXCEPTION_OP, "sqrt of negative value", 0);
|
5829
|
+
}
|
5830
|
+
|
5831
|
+
/* NaN ? */
|
5832
|
+
if (VpIsNaN(x)) {
|
5765
5833
|
VpSetNaN(y);
|
5766
|
-
return VpException(VP_EXCEPTION_OP, "
|
5834
|
+
return VpException(VP_EXCEPTION_OP, "sqrt of 'NaN'(Not a Number)", 0);
|
5767
5835
|
}
|
5768
5836
|
|
5769
5837
|
/* One ? */
|
@@ -5954,10 +6022,10 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
|
|
5954
6022
|
if (v > 5 || (v == 5 && fracf_1further)) ++div;
|
5955
6023
|
break;
|
5956
6024
|
case VP_ROUND_CEIL:
|
5957
|
-
if (fracf && (
|
6025
|
+
if (fracf && BIGDECIMAL_POSITIVE_P(y)) ++div;
|
5958
6026
|
break;
|
5959
6027
|
case VP_ROUND_FLOOR:
|
5960
|
-
if (fracf && (
|
6028
|
+
if (fracf && BIGDECIMAL_NEGATIVE_P(y)) ++div;
|
5961
6029
|
break;
|
5962
6030
|
case VP_ROUND_HALF_EVEN: /* Banker's rounding */
|
5963
6031
|
if (v > 5) ++div;
|
@@ -6076,10 +6144,10 @@ VpInternalRound(Real *c, size_t ixDigit, BDIGIT vPrev, BDIGIT v)
|
|
6076
6144
|
if (v >= 6) f = 1;
|
6077
6145
|
break;
|
6078
6146
|
case VP_ROUND_CEIL:
|
6079
|
-
if (v && (
|
6147
|
+
if (v && BIGDECIMAL_POSITIVE_P(c)) f = 1;
|
6080
6148
|
break;
|
6081
6149
|
case VP_ROUND_FLOOR:
|
6082
|
-
if (v && (
|
6150
|
+
if (v && BIGDECIMAL_NEGATIVE_P(c)) f = 1;
|
6083
6151
|
break;
|
6084
6152
|
case VP_ROUND_HALF_EVEN: /* Banker's rounding */
|
6085
6153
|
/* as per VP_ROUND_HALF_DOWN, because this is the last digit of precision,
|
@@ -6216,7 +6284,7 @@ VpPower(Real *y, Real *x, SIGNED_VALUE n)
|
|
6216
6284
|
if (x->exponent == 1 && x->Prec == 1 && x->frac[0] == 1) {
|
6217
6285
|
/* abs(x) = 1 */
|
6218
6286
|
VpSetOne(y);
|
6219
|
-
if (
|
6287
|
+
if (BIGDECIMAL_POSITIVE_P(x)) goto Exit;
|
6220
6288
|
if ((n % 2) == 0) goto Exit;
|
6221
6289
|
VpSetSign(y, -1);
|
6222
6290
|
goto Exit;
|
@@ -6261,7 +6329,7 @@ Exit:
|
|
6261
6329
|
if (gfDebug) {
|
6262
6330
|
VPrint(stdout, "VpPower y=%\n", y);
|
6263
6331
|
VPrint(stdout, "VpPower x=%\n", x);
|
6264
|
-
printf(" n=%
|
6332
|
+
printf(" n=%"PRIdVALUE"\n", n);
|
6265
6333
|
}
|
6266
6334
|
#endif /* BIGDECIMAL_DEBUG */
|
6267
6335
|
VpFree(w2);
|
@@ -6296,10 +6364,10 @@ VpVarCheck(Real * v)
|
|
6296
6364
|
for (i = 0; i < v->Prec; ++i) {
|
6297
6365
|
if (v->frac[i] >= BASE) {
|
6298
6366
|
printf("ERROR(VpVarCheck): Illegal fraction\n");
|
6299
|
-
printf(" Frac[%"PRIuSIZE"]=%
|
6367
|
+
printf(" Frac[%"PRIuSIZE"]=%"PRIuBDIGIT"\n", i, v->frac[i]);
|
6300
6368
|
printf(" Prec. =%"PRIuSIZE"\n", v->Prec);
|
6301
6369
|
printf(" Exp. =%"PRIdVALUE"\n", v->exponent);
|
6302
|
-
printf(" BASE =%
|
6370
|
+
printf(" BASE =%"PRIuBDIGIT"\n", BASE);
|
6303
6371
|
return 3;
|
6304
6372
|
}
|
6305
6373
|
}
|