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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5c6add6da22b46504455a11b1c80ee545605a98a
4
- data.tar.gz: 65e574ee88d241c198ea1467d4093e2ca5a21983
3
+ metadata.gz: 2390e0da673ea017af80d3876c848d7bee58d978
4
+ data.tar.gz: 46c3ad1e4b275eef054acf8a3c4336859ac4347d
5
5
  SHA512:
6
- metadata.gz: 5a1d3f5c772c597c5940beaf4ab781eb656038b6ac38173c956b1f45bc83a0786e5e44a5630b52b292505f58b887d298b8b96b4928726302151b02c66920296e
7
- data.tar.gz: 267b4cc7de1fcb5f75c761a599c56b26c4219468a1a04531f2a7aee88bd9b88cdff35d4a1a3695487ae2b9b6e1520f523c5452ff4a635537ec52b931ca9b2c5a
6
+ metadata.gz: fab6b67b03398713ebed08bcec6edee1604824192783ea32ba82fb76f16862fdc5a44398f2fa91fc1a2b1ed357f49a7ec9f7058e23e74cfeae6e1b7d0975bf27
7
+ data.tar.gz: e9129231704307c807b625803341e993c39951cf288b934bb4b26d853868aa9cc9e3a0daab4bcd0267caceee274ebffd24f4113d5c5ac72a2b12e746841f93ec
@@ -1,23 +1,25 @@
1
- # -*- ruby -*-
2
- _VERSION = "1.2.7"
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 = "bigdecimal"
7
- s.version = _VERSION
8
- s.date = date
9
- s.summary = "Arbitrary-precision decimal floating-point number library."
10
- s.homepage = "http://www.ruby-lang.org"
11
- s.email = "mrkn@mrkn.jp"
12
- s.description = "This library provides arbitrary-precision decimal floating-point number class."
13
- s.authors = ["Kenta Murata", "Zachary Scott", "Shigeo Kobayashi"]
14
- s.require_path = %[.]
15
- s.files = %w[
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
- README
20
- depend extconf.rb
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
- s.extensions = %w[extconf.rb]
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 pv ? (sizeof(*pv) + pv->MaxPrec * sizeof(BDIGIT)) : 0;
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
- * #=> #<BigDecimal:1e16fa8,'Infinity',9(9)>
391
+ * #=> Infinity
390
392
  * BigDecimal._load(inf._dump)
391
- * #=> #<BigDecimal:1df8dc8,'Infinity',9(9)>
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
- Check_Type(v, T_FIXNUM);
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
- Check_Type(which, T_FIXNUM);
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#mode invalid");
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
- Check_Type(v, T_FIXNUM);
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
- pv->obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, pv);
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
- Real *pv = VpAlloc(mx,str);
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 integer (Fixnum or Bignum).
734
+ /* Returns the value as an Integer.
688
735
  *
689
- * If the BigNumber is infinity or NaN, raises FloatDomainError.
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 = RARRAY_PTR(a)[1];
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 (VpGetSign(p) < 0) {
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->sign >= 0)
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->sign >= 0)
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 = RARRAY_PTR(a)[1];
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 -> true
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
- Check_Type(vLoc, T_FIXNUM);
1728
- iLoc = FIX2INT(vLoc);
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
- Check_Type(vLoc, T_FIXNUM);
1732
- iLoc = FIX2INT(vLoc);
1733
- sw = check_rounding_mode(vRound);
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
- Check_Type(vLoc, T_FIXNUM);
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
- Check_Type(vLoc, T_FIXNUM);
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
- Check_Type(vLoc, T_FIXNUM);
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
- * #=> "#<BigDecimal:b7ea1130,'0.12345678E4',8(12)>"
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 obj;
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
- nc += (nc + 9) / 10;
2096
-
2097
- obj = rb_str_new(0, nc+256);
2098
- psz = RSTRING_PTR(obj);
2099
- sprintf(psz, "#<BigDecimal:%"PRIxVALUE",'", self);
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 (VpGetSign(x) < 0) {
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 (VpGetSign(x) < 0) {
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 (VpGetSign(x) < 0) {
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 (VpGetSign(x) < 0 && is_even(vexp)) {
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 (VpGetSign(x) < 0 && is_even(vexp)) {
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 a Fixnum. If omitted or 0,
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 Fixnum, Bignum, Float,
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 a Fixnum, this exception is raised.
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 to dup and clone the provided BigDecimal +other+
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
- pv->obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, pv);
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
- Check_Type(nFig, T_FIXNUM);
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 almostly the same as one in the
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 = VpGetSign(vx) < 0;
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 = VpGetSign(vx) < 0;
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 almostly the same as one in the
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 = VpGetSign(vx) < 0;
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
- * You may distribute under the terms of either the GNU General Public
3138
- * License or the Artistic License, as specified in the README file
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
- * 0x01: Determines what happens when a division by zero is performed.
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
- static int VpIsDefOP(Real *c,Real *a,Real *b,int sw);
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
- VP_EXPORT void *
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 (unsigned short)FIX2UINT(vmode);
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 (unsigned short)FIX2INT(vmode);
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,int sw)
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 1: /* + */
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 2: /* - */
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
- break;
3706
- case 3: /* * */
3765
+ case OP_SW_MULT: /* * */
3707
3766
  VpSetInf(c, VpGetSign(a)*VpGetSign(b));
3708
3767
  goto Inf;
3709
- break;
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 1: /* + */
3720
- case 2: /* - */
3777
+ case OP_SW_ADD: /* + */
3778
+ case OP_SW_SUB: /* - */
3721
3779
  VpSetInf(c, VpGetSign(a));
3722
3780
  break;
3723
- case 3: /* * */
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 4: /* / */
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 1: /* + */
3796
+ case OP_SW_ADD: /* + */
3739
3797
  VpSetInf(c, VpGetSign(b));
3740
3798
  break;
3741
- case 2: /* - */
3799
+ case OP_SW_SUB: /* - */
3742
3800
  VpSetInf(c, -VpGetSign(b));
3743
3801
  break;
3744
- case 3: /* * */
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 4: /* / */
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
- return VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 0);
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 = %lu\n", BaseVal);
3835
- printf(" BASE = %lu\n", BASE);
3836
- printf(" HALF_BASE = %lu\n", HALF_BASE);
3837
- printf(" BASE1 = %lu\n", BASE1);
3838
- printf(" BASE_FIG = %u\n", BASE_FIG);
3839
- printf(" DBLE_FIG = %d\n", DBLE_FIG);
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 < eb) goto overflow;
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 > eb) goto underflow;
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
- size_t i, ni, ipn, ipf, nf, ipe, ne, nalloc;
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
- while (ISSPACE(*szVal)) szVal++;
3918
- if (*szVal != '#') {
3919
- if (mf) {
3920
- mf = (mf + BASE_FIG - 1) / BASE_FIG + 2; /* Needs 1 more for div */
3921
- if (mx > mf) {
3922
- mx = mf;
3923
- }
3924
- }
3925
- }
3926
- else {
3927
- ++szVal;
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
- /* necessary to be able to store */
3932
- /* at least mx digits. */
3933
- /* szVal==NULL ==> allocate zero value. */
3934
- vp = VpAllocReal(mx);
3935
- /* xmalloc() alway returns(or throw interruption) */
3936
- vp->MaxPrec = mx; /* set max precision */
3937
- VpSetZero(vp, 1); /* initialize vp to zero. */
3938
- return vp;
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
- if (ISDIGIT(psz[i])) ++ni;
3949
- if (psz[i] == '_') {
3950
- if (ni > 0) {
3951
- ipn++;
3952
- continue;
3953
- }
3954
- psz[i] = 0;
3955
- break;
3956
- }
3957
- ++i;
3958
- ++ipn;
3959
- }
3960
- /* Skip trailing spaces */
3961
- while (--i > 0) {
3962
- if (ISSPACE(psz[i])) psz[i] = 0;
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
- if (!ISDIGIT(v)) break;
3995
- ++i;
3996
- ++ni;
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
- /* other than digit nor \0 */
4004
- if (szVal[i] == '.') { /* xxx. */
4005
- ++i;
4006
- ipf = i;
4007
- while ((v = szVal[i]) != 0) { /* get fraction part. */
4008
- if (!ISDIGIT(v)) break;
4009
- ++i;
4010
- ++nf;
4011
- }
4012
- }
4013
- ipe = 0; /* Exponent */
4014
-
4015
- switch (szVal[i]) {
4016
- case '\0':
4017
- break;
4018
- case 'e': case 'E':
4019
- case 'd': case 'D':
4020
- ++i;
4021
- ipe = i;
4022
- v = szVal[i];
4023
- if ((v == '-') || (v == '+')) ++i;
4024
- while ((v=szVal[i]) != 0) {
4025
- if (!ISDIGIT(v)) break;
4026
- ++i;
4027
- ++ne;
4028
- }
4029
- break;
4030
- default:
4031
- break;
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
- * = a - b when operation = -1 or -2.
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) ? 1 : 2)) return 0; /* No significant digits */
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 precisional variables
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->expoennt);
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, 3)) return 0; /* No significant digit */
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
- VP_EXPORT size_t
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, 4)) goto Exit;
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, "(VpDivd) 0/0 not defined(NaN)", 0);
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, "(VpDivd) Divide by zero", 0);
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
- * ... tab
5035
- * Note: % must must not appear more than once
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 (!VpIsZero(a)) {
5072
- if (VpGetSign(a) < 0) {
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 (VpGetSign(a) < 0) *psz++ = '-';
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 (VpGetSign(a) < 0) *psz++ = '-';
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, "E%"PRIdSIZE, ex);
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 (VpGetSign(a) < 0) *psz++ = '-';
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, NaN or Infinity ? */
5753
- if (!VpHasVal(x)) {
5754
- if (VpIsZero(x) || VpGetSign(x) > 0) {
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 (VpGetSign(x) < 0) {
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, "(VpSqrt) SQRT(negative value)", 0);
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 && (VpGetSign(y) > 0)) ++div;
6025
+ if (fracf && BIGDECIMAL_POSITIVE_P(y)) ++div;
5958
6026
  break;
5959
6027
  case VP_ROUND_FLOOR:
5960
- if (fracf && (VpGetSign(y) < 0)) ++div;
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 && (VpGetSign(c) > 0)) f = 1;
6147
+ if (v && BIGDECIMAL_POSITIVE_P(c)) f = 1;
6080
6148
  break;
6081
6149
  case VP_ROUND_FLOOR:
6082
- if (v && (VpGetSign(c) < 0)) f = 1;
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 (VpGetSign(x) > 0) goto Exit;
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=%d\n", 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"]=%lu\n", i, v->frac[i]);
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 =%lu\n", BASE);
6370
+ printf(" BASE =%"PRIuBDIGIT"\n", BASE);
6303
6371
  return 3;
6304
6372
  }
6305
6373
  }