bigdecimal 1.2.7 → 1.3.0.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
}
|