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 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
  }