bigdecimal 1.2.7 → 1.3.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,13 +4,6 @@
4
4
  *
5
5
  * Copyright(C) 2002 by Shigeo Kobayashi(shigeo@tinyforest.gr.jp)
6
6
  *
7
- * You may distribute under the terms of either the GNU General Public
8
- * License or the Artistic License, as specified in the README file
9
- * of this BigDecimal distribution.
10
- *
11
- * NOTE: Change log in this source removed to reduce source code size.
12
- * See rev. 1.25 if needed.
13
- *
14
7
  */
15
8
 
16
9
  /* #define BIGDECIMAL_DEBUG 1 */
@@ -69,6 +62,7 @@ static ID id_ceil;
69
62
  static ID id_floor;
70
63
  static ID id_to_r;
71
64
  static ID id_eq;
65
+ static ID id_half;
72
66
 
73
67
  /* MACRO's to guard objects from GC by keeping them in stack */
74
68
  #define ENTER(n) volatile VALUE RB_UNUSED_VAR(vStack[n]);int iStack=0
@@ -133,6 +127,9 @@ rb_rational_den(VALUE rat)
133
127
  }
134
128
  #endif
135
129
 
130
+ #define BIGDECIMAL_POSITIVE_P(bd) ((bd)->sign > 0)
131
+ #define BIGDECIMAL_NEGATIVE_P(bd) ((bd)->sign < 0)
132
+
136
133
  /*
137
134
  * ================== Ruby Interface part ==========================
138
135
  */
@@ -144,12 +141,16 @@ rb_rational_den(VALUE rat)
144
141
  static VALUE
145
142
  BigDecimal_version(VALUE self)
146
143
  {
147
- /*
148
- * 1.0.0: Ruby 1.8.0
149
- * 1.0.1: Ruby 1.8.1
150
- * 1.1.0: Ruby 1.9.3
151
- */
152
- return rb_str_new2("1.1.0");
144
+ /*
145
+ * 1.0.0: Ruby 1.8.0
146
+ * 1.0.1: Ruby 1.8.1
147
+ * 1.1.0: Ruby 1.9.3
148
+ */
149
+ #ifndef RUBY_BIGDECIMAL_VERSION
150
+ # error RUBY_BIGDECIMAL_VERSION is not defined
151
+ #endif
152
+ rb_warning("BigDecimal.ver is deprecated; use BigDecimal::VERSION instead.");
153
+ return rb_str_new2(RUBY_BIGDECIMAL_VERSION);
153
154
  }
154
155
 
155
156
  /*
@@ -179,7 +180,7 @@ static size_t
179
180
  BigDecimal_memsize(const void *ptr)
180
181
  {
181
182
  const Real *pv = ptr;
182
- return pv ? (sizeof(*pv) + pv->MaxPrec * sizeof(BDIGIT)) : 0;
183
+ return (sizeof(*pv) + pv->MaxPrec * sizeof(BDIGIT));
183
184
  }
184
185
 
185
186
  static const rb_data_type_t BigDecimal_data_type = {
@@ -234,6 +235,7 @@ static inline VALUE BigDecimal_div2(VALUE, VALUE, VALUE);
234
235
  static Real*
235
236
  GetVpValueWithPrec(VALUE v, long prec, int must)
236
237
  {
238
+ ENTER(1);
237
239
  Real *pv;
238
240
  VALUE num, bg;
239
241
  char szD[128];
@@ -246,6 +248,11 @@ again:
246
248
  if (prec < 0) goto unable_to_coerce_without_prec;
247
249
  if (prec > DBL_DIG+1) goto SomeOneMayDoIt;
248
250
  d = RFLOAT_VALUE(v);
251
+ if (!isfinite(d)) {
252
+ pv = VpCreateRbObject(1, NULL);
253
+ VpDtoV(pv, d);
254
+ return pv;
255
+ }
249
256
  if (d != 0.0) {
250
257
  v = rb_funcall(v, id_to_r, 0);
251
258
  goto again;
@@ -286,13 +293,15 @@ again:
286
293
 
287
294
  #ifdef ENABLE_NUMERIC_STRING
288
295
  case T_STRING:
289
- SafeStringValue(v);
290
- return VpCreateRbObject(strlen(RSTRING_PTR(v)) + VpBaseFig() + 1,
296
+ StringValueCStr(v);
297
+ rb_check_safe_obj(v);
298
+ return VpCreateRbObject(RSTRING_LEN(v) + VpBaseFig() + 1,
291
299
  RSTRING_PTR(v));
292
300
  #endif /* ENABLE_NUMERIC_STRING */
293
301
 
294
302
  case T_BIGNUM:
295
303
  bg = rb_big2str(v, 10);
304
+ PUSH(bg);
296
305
  return VpCreateRbObject(strlen(RSTRING_PTR(bg)) + VpBaseFig() + 1,
297
306
  RSTRING_PTR(bg));
298
307
  default:
@@ -333,15 +342,18 @@ BigDecimal_double_fig(VALUE self)
333
342
  return INT2FIX(VpDblFig());
334
343
  }
335
344
 
336
- /* call-seq:
337
- * precs
345
+ /* call-seq:
346
+ * big_decimal.precs -> array
338
347
  *
339
- * Returns an Array of two Integer values.
348
+ * Returns an Array of two Integer values.
340
349
  *
341
- * The first value is the current number of significant digits in the
342
- * BigDecimal. The second value is the maximum number of significant digits
343
- * for the BigDecimal.
350
+ * The first value is the current number of significant digits in the
351
+ * BigDecimal. The second value is the maximum number of significant digits
352
+ * for the BigDecimal.
353
+ *
354
+ * BigDecimal('5').precs #=> [9, 18]
344
355
  */
356
+
345
357
  static VALUE
346
358
  BigDecimal_prec(VALUE self)
347
359
  {
@@ -377,7 +389,7 @@ BigDecimal_hash(VALUE self)
377
389
  hash ^= rb_memhash(p->frac, sizeof(BDIGIT)*p->Prec);
378
390
  hash += p->exponent;
379
391
  }
380
- return INT2FIX(hash);
392
+ return ST2FIX(hash);
381
393
  }
382
394
 
383
395
  /*
@@ -385,10 +397,10 @@ BigDecimal_hash(VALUE self)
385
397
  *
386
398
  * Method used to provide marshalling support.
387
399
  *
388
- * inf = BigDecimal.new('Infinity')
389
- * #=> #<BigDecimal:1e16fa8,'Infinity',9(9)>
400
+ * inf = BigDecimal('Infinity')
401
+ * #=> Infinity
390
402
  * BigDecimal._load(inf._dump)
391
- * #=> #<BigDecimal:1df8dc8,'Infinity',9(9)>
403
+ * #=> Infinity
392
404
  *
393
405
  * See the Marshal module.
394
406
  */
@@ -423,8 +435,8 @@ BigDecimal_load(VALUE self, VALUE str)
423
435
  unsigned char ch;
424
436
  unsigned long m=0;
425
437
 
426
- SafeStringValue(str);
427
- pch = (unsigned char *)RSTRING_PTR(str);
438
+ pch = (unsigned char *)StringValueCStr(str);
439
+ rb_check_safe_obj(str);
428
440
  /* First get max prec */
429
441
  while((*pch) != (unsigned char)'\0' && (ch = *pch++) != (unsigned char)':') {
430
442
  if(!ISDIGIT(ch)) {
@@ -441,6 +453,55 @@ BigDecimal_load(VALUE self, VALUE str)
441
453
  return ToValue(pv);
442
454
  }
443
455
 
456
+ static unsigned short
457
+ check_rounding_mode_option(VALUE const opts)
458
+ {
459
+ VALUE mode;
460
+ char const *s;
461
+ long l;
462
+
463
+ assert(RB_TYPE_P(opts, T_HASH));
464
+
465
+ if (NIL_P(opts))
466
+ goto noopt;
467
+
468
+ mode = rb_hash_lookup2(opts, ID2SYM(id_half), Qundef);
469
+ if (mode == Qundef || NIL_P(mode))
470
+ goto noopt;
471
+
472
+ if (SYMBOL_P(mode))
473
+ mode = rb_sym2str(mode);
474
+ else if (!RB_TYPE_P(mode, T_STRING)) {
475
+ VALUE str_mode = rb_check_string_type(mode);
476
+ if (NIL_P(str_mode)) goto invalid;
477
+ mode = str_mode;
478
+ }
479
+ s = RSTRING_PTR(mode);
480
+ l = RSTRING_LEN(mode);
481
+ switch (l) {
482
+ case 2:
483
+ if (strncasecmp(s, "up", 2) == 0)
484
+ return VP_ROUND_HALF_UP;
485
+ break;
486
+ case 4:
487
+ if (strncasecmp(s, "even", 4) == 0)
488
+ return VP_ROUND_HALF_EVEN;
489
+ else if (strncasecmp(s, "down", 4) == 0)
490
+ return VP_ROUND_HALF_DOWN;
491
+ break;
492
+ default:
493
+ break;
494
+ }
495
+ invalid:
496
+ if (NIL_P(mode))
497
+ rb_raise(rb_eArgError, "invalid rounding mode: nil");
498
+ else
499
+ rb_raise(rb_eArgError, "invalid rounding mode: %"PRIsVALUE, mode);
500
+
501
+ noopt:
502
+ return VpGetRoundMode();
503
+ }
504
+
444
505
  static unsigned short
445
506
  check_rounding_mode(VALUE const v)
446
507
  {
@@ -469,8 +530,7 @@ check_rounding_mode(VALUE const v)
469
530
  break;
470
531
  }
471
532
 
472
- Check_Type(v, T_FIXNUM);
473
- sw = (unsigned short)FIX2UINT(v);
533
+ sw = NUM2USHORT(v);
474
534
  if (!VpIsRoundMode(sw)) {
475
535
  rb_raise(rb_eArgError, "invalid rounding mode");
476
536
  }
@@ -523,8 +583,7 @@ BigDecimal_mode(int argc, VALUE *argv, VALUE self)
523
583
  unsigned long f,fo;
524
584
 
525
585
  rb_scan_args(argc, argv, "11", &which, &val);
526
- Check_Type(which, T_FIXNUM);
527
- f = (unsigned long)FIX2INT(which);
586
+ f = (unsigned long)NUM2INT(which);
528
587
 
529
588
  if (f & VP_EXCEPTION_ALL) {
530
589
  /* Exception mode setting */
@@ -565,7 +624,7 @@ BigDecimal_mode(int argc, VALUE *argv, VALUE self)
565
624
  fo = VpSetRoundMode(sw);
566
625
  return INT2FIX(fo);
567
626
  }
568
- rb_raise(rb_eTypeError, "first argument for BigDecimal#mode invalid");
627
+ rb_raise(rb_eTypeError, "first argument for BigDecimal.mode invalid");
569
628
  return Qnil;
570
629
  }
571
630
 
@@ -591,13 +650,12 @@ GetAddSubPrec(Real *a, Real *b)
591
650
  }
592
651
 
593
652
  static SIGNED_VALUE
594
- GetPositiveInt(VALUE v)
653
+ GetPrecisionInt(VALUE v)
595
654
  {
596
655
  SIGNED_VALUE n;
597
- Check_Type(v, T_FIXNUM);
598
- n = FIX2INT(v);
656
+ n = NUM2INT(v);
599
657
  if (n < 0) {
600
- rb_raise(rb_eArgError, "argument must be positive");
658
+ rb_raise(rb_eArgError, "negative precision");
601
659
  }
602
660
  return n;
603
661
  }
@@ -605,17 +663,17 @@ GetPositiveInt(VALUE v)
605
663
  VP_EXPORT Real *
606
664
  VpNewRbClass(size_t mx, const char *str, VALUE klass)
607
665
  {
666
+ VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
608
667
  Real *pv = VpAlloc(mx,str);
609
- pv->obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, pv);
668
+ RTYPEDDATA_DATA(obj) = pv;
669
+ pv->obj = obj;
610
670
  return pv;
611
671
  }
612
672
 
613
673
  VP_EXPORT Real *
614
674
  VpCreateRbObject(size_t mx, const char *str)
615
675
  {
616
- Real *pv = VpAlloc(mx,str);
617
- pv->obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, pv);
618
- return pv;
676
+ return VpNewRbClass(mx, str, rb_cBigDecimal);
619
677
  }
620
678
 
621
679
  #define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(BDIGIT))
@@ -684,9 +742,9 @@ BigDecimal_check_num(Real *p)
684
742
 
685
743
  static VALUE BigDecimal_split(VALUE self);
686
744
 
687
- /* Returns the value as an integer (Fixnum or Bignum).
745
+ /* Returns the value as an Integer.
688
746
  *
689
- * If the BigNumber is infinity or NaN, raises FloatDomainError.
747
+ * If the BigDecimal is infinity or NaN, raises FloatDomainError.
690
748
  */
691
749
  static VALUE
692
750
  BigDecimal_to_i(VALUE self)
@@ -706,12 +764,12 @@ BigDecimal_to_i(VALUE self)
706
764
  }
707
765
  else {
708
766
  VALUE a = BigDecimal_split(self);
709
- VALUE digits = RARRAY_PTR(a)[1];
767
+ VALUE digits = RARRAY_AREF(a, 1);
710
768
  VALUE numerator = rb_funcall(digits, rb_intern("to_i"), 0);
711
769
  VALUE ret;
712
770
  ssize_t dpower = e - (ssize_t)RSTRING_LEN(digits);
713
771
 
714
- if (VpGetSign(p) < 0) {
772
+ if (BIGDECIMAL_NEGATIVE_P(p)) {
715
773
  numerator = rb_funcall(numerator, '*', 1, INT2FIX(-1));
716
774
  }
717
775
  if (dpower < 0) {
@@ -766,17 +824,17 @@ BigDecimal_to_f(VALUE self)
766
824
 
767
825
  overflow:
768
826
  VpException(VP_EXCEPTION_OVERFLOW, "BigDecimal to Float conversion", 0);
769
- if (p->sign >= 0)
770
- return rb_float_new(VpGetDoublePosInf());
771
- else
827
+ if (BIGDECIMAL_NEGATIVE_P(p))
772
828
  return rb_float_new(VpGetDoubleNegInf());
829
+ else
830
+ return rb_float_new(VpGetDoublePosInf());
773
831
 
774
832
  underflow:
775
833
  VpException(VP_EXCEPTION_UNDERFLOW, "BigDecimal to Float conversion", 0);
776
- if (p->sign >= 0)
777
- return rb_float_new(0.0);
778
- else
834
+ if (BIGDECIMAL_NEGATIVE_P(p))
779
835
  return rb_float_new(-0.0);
836
+ else
837
+ return rb_float_new(0.0);
780
838
  }
781
839
 
782
840
 
@@ -795,7 +853,7 @@ BigDecimal_to_r(VALUE self)
795
853
  sign = VpGetSign(p);
796
854
  power = VpExponent10(p);
797
855
  a = BigDecimal_split(self);
798
- digits = RARRAY_PTR(a)[1];
856
+ digits = RARRAY_AREF(a, 1);
799
857
  denomi_power = power - RSTRING_LEN(digits);
800
858
  numerator = rb_funcall(digits, rb_intern("to_i"), 0);
801
859
 
@@ -822,7 +880,7 @@ BigDecimal_to_r(VALUE self)
822
880
  * be coerced into a BigDecimal value.
823
881
  *
824
882
  * e.g.
825
- * a = BigDecimal.new("1.0")
883
+ * a = BigDecimal("1.0")
826
884
  * b = a / 2.0 #=> 0.5
827
885
  *
828
886
  * Note that coercing a String to a BigDecimal is not supported by default;
@@ -854,13 +912,14 @@ BigDecimal_coerce(VALUE self, VALUE other)
854
912
  }
855
913
 
856
914
  /*
857
- * call-seq: +@
915
+ * call-seq:
916
+ * +big_decimal -> big_decimal
858
917
  *
859
918
  * Return self.
860
919
  *
861
- * e.g.
862
- * b = +a # b == a
920
+ * +BigDecimal('5') #=> 0.5e1
863
921
  */
922
+
864
923
  static VALUE
865
924
  BigDecimal_uplus(VALUE self)
866
925
  {
@@ -1110,7 +1169,7 @@ BigDecimal_comp(VALUE self, VALUE r)
1110
1169
  *
1111
1170
  * Values may be coerced to perform the comparison:
1112
1171
  *
1113
- * BigDecimal.new('1.0') == 1.0 -> true
1172
+ * BigDecimal('1.0') == 1.0 #=> true
1114
1173
  */
1115
1174
  static VALUE
1116
1175
  BigDecimal_eq(VALUE self, VALUE r)
@@ -1171,14 +1230,14 @@ BigDecimal_ge(VALUE self, VALUE r)
1171
1230
  }
1172
1231
 
1173
1232
  /*
1174
- * call-seq: -@
1233
+ * call-seq:
1234
+ * -big_decimal -> big_decimal
1175
1235
  *
1176
- * Return the negation of self.
1236
+ * Return the negation of self.
1177
1237
  *
1178
- * e.g.
1179
- * b = -a
1180
- * b == a * -1
1238
+ * -BigDecimal('5') #=> -0.5e1
1181
1239
  */
1240
+
1182
1241
  static VALUE
1183
1242
  BigDecimal_neg(VALUE self)
1184
1243
  {
@@ -1266,25 +1325,14 @@ BigDecimal_divide(Real **c, Real **res, Real **div, VALUE self, VALUE r)
1266
1325
  return Qnil;
1267
1326
  }
1268
1327
 
1269
- /* call-seq:
1270
- * div(value, digits)
1271
- * quo(value)
1272
- *
1273
- * Divide by the specified value.
1274
- *
1275
- * e.g.
1276
- * c = a.div(b,n)
1277
- *
1278
- * digits:: If specified and less than the number of significant digits of the
1279
- * result, the result is rounded to that number of digits, according
1280
- * to BigDecimal.mode.
1281
- *
1282
- * If digits is 0, the result is the same as the / operator. If not, the
1283
- * result is an integer BigDecimal, by analogy with Float#div.
1284
- *
1285
- * The alias quo is provided since <code>div(value, 0)</code> is the same as
1286
- * computing the quotient; see BigDecimal#divmod.
1287
- */
1328
+ /* call-seq:
1329
+ * a / b -> bigdecimal
1330
+ * quo(value) -> bigdecimal
1331
+ *
1332
+ * Divide by the specified value.
1333
+ *
1334
+ * See BigDecimal#div.
1335
+ */
1288
1336
  static VALUE
1289
1337
  BigDecimal_div(VALUE self, VALUE r)
1290
1338
  /* For c = self/r: with round operation */
@@ -1483,8 +1531,8 @@ BigDecimal_remainder(VALUE self, VALUE r) /* remainder */
1483
1531
  *
1484
1532
  * require 'bigdecimal'
1485
1533
  *
1486
- * a = BigDecimal.new("42")
1487
- * b = BigDecimal.new("9")
1534
+ * a = BigDecimal("42")
1535
+ * b = BigDecimal("9")
1488
1536
  *
1489
1537
  * q, m = a.divmod(b)
1490
1538
  *
@@ -1527,7 +1575,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
1527
1575
  }
1528
1576
 
1529
1577
  /* div in BigDecimal sense */
1530
- ix = GetPositiveInt(n);
1578
+ ix = GetPrecisionInt(n);
1531
1579
  if (ix == 0) {
1532
1580
  return BigDecimal_div(self, b);
1533
1581
  }
@@ -1537,7 +1585,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
1537
1585
  size_t mx = ix + VpBaseFig()*2;
1538
1586
  size_t pl = VpSetPrecLimit(0);
1539
1587
 
1540
- GUARD_OBJ(cv, VpCreateRbObject(mx, "0"));
1588
+ GUARD_OBJ(cv, VpCreateRbObject(mx + VpBaseFig(), "0"));
1541
1589
  GUARD_OBJ(av, GetVpValue(self, 1));
1542
1590
  GUARD_OBJ(bv, GetVpValue(b, 1));
1543
1591
  mx = av->Prec + bv->Prec + 2;
@@ -1550,6 +1598,37 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
1550
1598
  }
1551
1599
  }
1552
1600
 
1601
+ /*
1602
+ * Document-method: BigDecimal#div
1603
+ *
1604
+ * call-seq:
1605
+ * div(value, digits) -> bigdecimal or integer
1606
+ *
1607
+ * Divide by the specified value.
1608
+ *
1609
+ * digits:: If specified and less than the number of significant digits of the
1610
+ * result, the result is rounded to that number of digits, according
1611
+ * to BigDecimal.mode.
1612
+ *
1613
+ * If digits is 0, the result is the same as for the / operator
1614
+ * or #quo.
1615
+ *
1616
+ * If digits is not specified, the result is an integer,
1617
+ * by analogy with Float#div; see also BigDecimal#divmod.
1618
+ *
1619
+ * Examples:
1620
+ *
1621
+ * a = BigDecimal("4")
1622
+ * b = BigDecimal("3")
1623
+ *
1624
+ * a.div(b, 3) # => 0.133e1
1625
+ *
1626
+ * a.div(b, 0) # => 0.1333333333333333333e1
1627
+ * a / b # => 0.1333333333333333333e1
1628
+ * a.quo(b) # => 0.1333333333333333333e1
1629
+ *
1630
+ * a.div(b) # => 1
1631
+ */
1553
1632
  static VALUE
1554
1633
  BigDecimal_div3(int argc, VALUE *argv, VALUE self)
1555
1634
  {
@@ -1565,7 +1644,7 @@ BigDecimal_add2(VALUE self, VALUE b, VALUE n)
1565
1644
  {
1566
1645
  ENTER(2);
1567
1646
  Real *cv;
1568
- SIGNED_VALUE mx = GetPositiveInt(n);
1647
+ SIGNED_VALUE mx = GetPrecisionInt(n);
1569
1648
  if (mx == 0) return BigDecimal_add(self, b);
1570
1649
  else {
1571
1650
  size_t pl = VpSetPrecLimit(0);
@@ -1595,7 +1674,7 @@ BigDecimal_sub2(VALUE self, VALUE b, VALUE n)
1595
1674
  {
1596
1675
  ENTER(2);
1597
1676
  Real *cv;
1598
- SIGNED_VALUE mx = GetPositiveInt(n);
1677
+ SIGNED_VALUE mx = GetPrecisionInt(n);
1599
1678
  if (mx == 0) return BigDecimal_sub(self, b);
1600
1679
  else {
1601
1680
  size_t pl = VpSetPrecLimit(0);
@@ -1613,7 +1692,7 @@ BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
1613
1692
  {
1614
1693
  ENTER(2);
1615
1694
  Real *cv;
1616
- SIGNED_VALUE mx = GetPositiveInt(n);
1695
+ SIGNED_VALUE mx = GetPrecisionInt(n);
1617
1696
  if (mx == 0) return BigDecimal_mult(self, b);
1618
1697
  else {
1619
1698
  size_t pl = VpSetPrecLimit(0);
@@ -1625,11 +1704,16 @@ BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
1625
1704
  }
1626
1705
  }
1627
1706
 
1628
- /* Returns the absolute value, as a BigDecimal.
1707
+ /*
1708
+ * call-seq:
1709
+ * big_decimal.abs -> big_decimal
1710
+ *
1711
+ * Returns the absolute value, as a BigDecimal.
1629
1712
  *
1630
- * BigDecimal('5').abs #=> 5
1631
- * BigDecimal('-3').abs #=> 3
1713
+ * BigDecimal('5').abs #=> 0.5e1
1714
+ * BigDecimal('-3').abs #=> 0.3e1
1632
1715
  */
1716
+
1633
1717
  static VALUE
1634
1718
  BigDecimal_abs(VALUE self)
1635
1719
  {
@@ -1662,7 +1746,7 @@ BigDecimal_sqrt(VALUE self, VALUE nFig)
1662
1746
  GUARD_OBJ(a, GetVpValue(self, 1));
1663
1747
  mx = a->Prec * (VpBaseFig() + 1);
1664
1748
 
1665
- n = GetPositiveInt(nFig) + VpDblFig() + BASE_FIG;
1749
+ n = GetPrecisionInt(nFig) + VpDblFig() + BASE_FIG;
1666
1750
  if (mx <= n) mx = n;
1667
1751
  GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
1668
1752
  VpSqrt(c, a);
@@ -1724,13 +1808,21 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
1724
1808
  iLoc = 0;
1725
1809
  break;
1726
1810
  case 1:
1727
- Check_Type(vLoc, T_FIXNUM);
1728
- iLoc = FIX2INT(vLoc);
1811
+ if (RB_TYPE_P(vLoc, T_HASH)) {
1812
+ sw = check_rounding_mode_option(vLoc);
1813
+ }
1814
+ else {
1815
+ iLoc = NUM2INT(vLoc);
1816
+ }
1729
1817
  break;
1730
1818
  case 2:
1731
- Check_Type(vLoc, T_FIXNUM);
1732
- iLoc = FIX2INT(vLoc);
1733
- sw = check_rounding_mode(vRound);
1819
+ iLoc = NUM2INT(vLoc);
1820
+ if (RB_TYPE_P(vRound, T_HASH)) {
1821
+ sw = check_rounding_mode_option(vRound);
1822
+ }
1823
+ else {
1824
+ sw = check_rounding_mode(vRound);
1825
+ }
1734
1826
  break;
1735
1827
  default:
1736
1828
  break;
@@ -1780,8 +1872,7 @@ BigDecimal_truncate(int argc, VALUE *argv, VALUE self)
1780
1872
  iLoc = 0;
1781
1873
  }
1782
1874
  else {
1783
- Check_Type(vLoc, T_FIXNUM);
1784
- iLoc = FIX2INT(vLoc);
1875
+ iLoc = NUM2INT(vLoc);
1785
1876
  }
1786
1877
 
1787
1878
  GUARD_OBJ(a, GetVpValue(self, 1));
@@ -1841,8 +1932,7 @@ BigDecimal_floor(int argc, VALUE *argv, VALUE self)
1841
1932
  iLoc = 0;
1842
1933
  }
1843
1934
  else {
1844
- Check_Type(vLoc, T_FIXNUM);
1845
- iLoc = FIX2INT(vLoc);
1935
+ iLoc = NUM2INT(vLoc);
1846
1936
  }
1847
1937
 
1848
1938
  GUARD_OBJ(a, GetVpValue(self, 1));
@@ -1888,8 +1978,7 @@ BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
1888
1978
  if (rb_scan_args(argc, argv, "01", &vLoc) == 0) {
1889
1979
  iLoc = 0;
1890
1980
  } else {
1891
- Check_Type(vLoc, T_FIXNUM);
1892
- iLoc = FIX2INT(vLoc);
1981
+ iLoc = NUM2INT(vLoc);
1893
1982
  }
1894
1983
 
1895
1984
  GUARD_OBJ(a, GetVpValue(self, 1));
@@ -1927,34 +2016,35 @@ BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
1927
2016
  *
1928
2017
  * Examples:
1929
2018
  *
1930
- * BigDecimal.new('-123.45678901234567890').to_s('5F')
2019
+ * BigDecimal('-123.45678901234567890').to_s('5F')
1931
2020
  * #=> '-123.45678 90123 45678 9'
1932
2021
  *
1933
- * BigDecimal.new('123.45678901234567890').to_s('+8F')
2022
+ * BigDecimal('123.45678901234567890').to_s('+8F')
1934
2023
  * #=> '+123.45678901 23456789'
1935
2024
  *
1936
- * BigDecimal.new('123.45678901234567890').to_s(' F')
2025
+ * BigDecimal('123.45678901234567890').to_s(' F')
1937
2026
  * #=> ' 123.4567890123456789'
1938
2027
  */
1939
2028
  static VALUE
1940
2029
  BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
1941
2030
  {
1942
2031
  ENTER(5);
1943
- int fmt = 0; /* 0:E format */
1944
- int fPlus = 0; /* =0:default,=1: set ' ' before digits ,set '+' before digits. */
2032
+ int fmt = 0; /* 0: E format, 1: F format */
2033
+ int fPlus = 0; /* 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
1945
2034
  Real *vp;
1946
2035
  volatile VALUE str;
1947
2036
  char *psz;
1948
2037
  char ch;
1949
2038
  size_t nc, mc = 0;
2039
+ SIGNED_VALUE m;
1950
2040
  VALUE f;
1951
2041
 
1952
2042
  GUARD_OBJ(vp, GetVpValue(self, 1));
1953
2043
 
1954
2044
  if (rb_scan_args(argc, argv, "01", &f) == 1) {
1955
2045
  if (RB_TYPE_P(f, T_STRING)) {
1956
- SafeStringValue(f);
1957
- psz = RSTRING_PTR(f);
2046
+ psz = StringValueCStr(f);
2047
+ rb_check_safe_obj(f);
1958
2048
  if (*psz == ' ') {
1959
2049
  fPlus = 1;
1960
2050
  psz++;
@@ -1977,7 +2067,11 @@ BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
1977
2067
  }
1978
2068
  }
1979
2069
  else {
1980
- mc = (size_t)GetPositiveInt(f);
2070
+ m = NUM2INT(f);
2071
+ if (m <= 0) {
2072
+ rb_raise(rb_eArgError, "argument must be positive");
2073
+ }
2074
+ mc = (size_t)m;
1981
2075
  }
1982
2076
  }
1983
2077
  if (fmt) {
@@ -2074,8 +2168,8 @@ BigDecimal_exponent(VALUE self)
2074
2168
  /* Returns debugging information about the value as a string of comma-separated
2075
2169
  * values in angle brackets with a leading #:
2076
2170
  *
2077
- * BigDecimal.new("1234.5678").inspect
2078
- * #=> "#<BigDecimal:b7ea1130,'0.12345678E4',8(12)>"
2171
+ * BigDecimal("1234.5678").inspect
2172
+ * #=> "0.12345678e4"
2079
2173
  *
2080
2174
  * The first part is the address, the second is the value as a string, and
2081
2175
  * the final part ss(mm) is the current number of significant digits and the
@@ -2086,23 +2180,16 @@ BigDecimal_inspect(VALUE self)
2086
2180
  {
2087
2181
  ENTER(5);
2088
2182
  Real *vp;
2089
- volatile VALUE obj;
2183
+ volatile VALUE str;
2090
2184
  size_t nc;
2091
- char *psz, *tmp;
2092
2185
 
2093
2186
  GUARD_OBJ(vp, GetVpValue(self, 1));
2094
2187
  nc = VpNumOfChars(vp, "E");
2095
- 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;
2188
+
2189
+ str = rb_str_new(0, nc);
2190
+ VpToString(vp, RSTRING_PTR(str), 0, 0);
2191
+ rb_str_resize(str, strlen(RSTRING_PTR(str)));
2192
+ return str;
2106
2193
  }
2107
2194
 
2108
2195
  static VALUE BigMath_s_exp(VALUE, VALUE, VALUE);
@@ -2312,7 +2399,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2312
2399
  if (is_negative(vexp)) {
2313
2400
  y = VpCreateRbObject(n, "#0");
2314
2401
  RB_GC_GUARD(y->obj);
2315
- if (VpGetSign(x) < 0) {
2402
+ if (BIGDECIMAL_NEGATIVE_P(x)) {
2316
2403
  if (is_integer(vexp)) {
2317
2404
  if (is_even(vexp)) {
2318
2405
  /* (-0) ** (-even_integer) -> Infinity */
@@ -2351,7 +2438,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2351
2438
 
2352
2439
  if (VpIsInf(x)) {
2353
2440
  if (is_negative(vexp)) {
2354
- if (VpGetSign(x) < 0) {
2441
+ if (BIGDECIMAL_NEGATIVE_P(x)) {
2355
2442
  if (is_integer(vexp)) {
2356
2443
  if (is_even(vexp)) {
2357
2444
  /* (-Infinity) ** (-even_integer) -> +0 */
@@ -2373,7 +2460,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2373
2460
  }
2374
2461
  else {
2375
2462
  y = VpCreateRbObject(n, "0#");
2376
- if (VpGetSign(x) < 0) {
2463
+ if (BIGDECIMAL_NEGATIVE_P(x)) {
2377
2464
  if (is_integer(vexp)) {
2378
2465
  if (is_even(vexp)) {
2379
2466
  VpSetPosInf(y);
@@ -2414,7 +2501,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2414
2501
  }
2415
2502
  return ToValue(y);
2416
2503
  }
2417
- else if (VpGetSign(x) < 0 && is_even(vexp)) {
2504
+ else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
2418
2505
  return ToValue(VpCreateRbObject(n, "-0"));
2419
2506
  }
2420
2507
  else {
@@ -2432,7 +2519,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2432
2519
  }
2433
2520
  return ToValue(y);
2434
2521
  }
2435
- else if (VpGetSign(x) < 0 && is_even(vexp)) {
2522
+ else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
2436
2523
  return ToValue(VpCreateRbObject(n, "-0"));
2437
2524
  }
2438
2525
  else {
@@ -2492,7 +2579,7 @@ static Real *BigDecimal_new(int argc, VALUE *argv);
2492
2579
  * If it is a String, spaces are ignored and unrecognized characters
2493
2580
  * terminate the value.
2494
2581
  *
2495
- * digits:: The number of significant digits, as a Fixnum. If omitted or 0,
2582
+ * digits:: The number of significant digits, as an Integer. If omitted or 0,
2496
2583
  * the number of significant digits is determined from the initial
2497
2584
  * value.
2498
2585
  *
@@ -2501,10 +2588,10 @@ static Real *BigDecimal_new(int argc, VALUE *argv);
2501
2588
  *
2502
2589
  * ==== Exceptions
2503
2590
  *
2504
- * TypeError:: If the +initial+ type is neither Fixnum, Bignum, Float,
2591
+ * TypeError:: If the +initial+ type is neither Integer, Float,
2505
2592
  * Rational, nor BigDecimal, this exception is raised.
2506
2593
  *
2507
- * TypeError:: If the +digits+ is not a Fixnum, this exception is raised.
2594
+ * TypeError:: If the +digits+ is not an Integer, this exception is raised.
2508
2595
  *
2509
2596
  * ArgumentError:: If +initial+ is a Float, and the +digits+ is larger than
2510
2597
  * Float::DIG + 1, this exception is raised.
@@ -2512,6 +2599,13 @@ static Real *BigDecimal_new(int argc, VALUE *argv);
2512
2599
  * ArgumentError:: If the +initial+ is a Float or Rational, and the +digits+
2513
2600
  * value is omitted, this exception is raised.
2514
2601
  */
2602
+ static VALUE
2603
+ BigDecimal_s_new(int argc, VALUE *argv, VALUE self)
2604
+ {
2605
+ rb_warning("BigDecimal.new is deprecated; use Kernel.BigDecimal method instead.");
2606
+ return rb_call_super(argc, argv);
2607
+ }
2608
+
2515
2609
  static VALUE
2516
2610
  BigDecimal_initialize(int argc, VALUE *argv, VALUE self)
2517
2611
  {
@@ -2534,7 +2628,7 @@ BigDecimal_initialize(int argc, VALUE *argv, VALUE self)
2534
2628
 
2535
2629
  /* :nodoc:
2536
2630
  *
2537
- * private method to dup and clone the provided BigDecimal +other+
2631
+ * private method for dup and clone the provided BigDecimal +other+
2538
2632
  */
2539
2633
  static VALUE
2540
2634
  BigDecimal_initialize_copy(VALUE self, VALUE other)
@@ -2548,18 +2642,25 @@ BigDecimal_initialize_copy(VALUE self, VALUE other)
2548
2642
  return self;
2549
2643
  }
2550
2644
 
2645
+ static VALUE
2646
+ BigDecimal_clone(VALUE self)
2647
+ {
2648
+ return self;
2649
+ }
2650
+
2551
2651
  static Real *
2552
2652
  BigDecimal_new(int argc, VALUE *argv)
2553
2653
  {
2554
2654
  size_t mf;
2555
2655
  VALUE nFig;
2556
2656
  VALUE iniValue;
2657
+ double d;
2557
2658
 
2558
2659
  if (rb_scan_args(argc, argv, "11", &iniValue, &nFig) == 1) {
2559
2660
  mf = 0;
2560
2661
  }
2561
2662
  else {
2562
- mf = GetPositiveInt(nFig);
2663
+ mf = GetPrecisionInt(nFig);
2563
2664
  }
2564
2665
 
2565
2666
  switch (TYPE(iniValue)) {
@@ -2575,6 +2676,12 @@ BigDecimal_new(int argc, VALUE *argv)
2575
2676
  return GetVpValue(iniValue, 1);
2576
2677
 
2577
2678
  case T_FLOAT:
2679
+ d = RFLOAT_VALUE(iniValue);
2680
+ if (!isfinite(d)) {
2681
+ Real *pv = VpCreateRbObject(1, NULL);
2682
+ VpDtoV(pv, d);
2683
+ return pv;
2684
+ }
2578
2685
  if (mf > DBL_DIG+1) {
2579
2686
  rb_raise(rb_eArgError, "precision too large.");
2580
2687
  }
@@ -2602,11 +2709,13 @@ BigDecimal_global_new(int argc, VALUE *argv, VALUE self)
2602
2709
  {
2603
2710
  ENTER(1);
2604
2711
  Real *pv;
2712
+ VALUE obj;
2605
2713
 
2714
+ obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0);
2606
2715
  GUARD_OBJ(pv, BigDecimal_new(argc, argv));
2607
2716
  if (ToValue(pv)) pv = VpCopy(NULL, pv);
2608
- pv->obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, pv);
2609
- return pv->obj;
2717
+ RTYPEDDATA_DATA(obj) = pv;
2718
+ return pv->obj = obj;
2610
2719
  }
2611
2720
 
2612
2721
  /* call-seq:
@@ -2630,8 +2739,7 @@ BigDecimal_limit(int argc, VALUE *argv, VALUE self)
2630
2739
  if (rb_scan_args(argc, argv, "01", &nFig) == 1) {
2631
2740
  int nf;
2632
2741
  if (NIL_P(nFig)) return nCur;
2633
- Check_Type(nFig, T_FIXNUM);
2634
- nf = FIX2INT(nFig);
2742
+ nf = NUM2INT(nFig);
2635
2743
  if (nf < 0) {
2636
2744
  rb_raise(rb_eArgError, "argument must be positive");
2637
2745
  }
@@ -2672,9 +2780,9 @@ BigDecimal_sign(VALUE self)
2672
2780
  * BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
2673
2781
  * BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
2674
2782
  *
2675
- * BigDecimal.new(BigDecimal('Infinity'))
2676
- * BigDecimal.new(BigDecimal('-Infinity'))
2677
- * BigDecimal(BigDecimal.new('NaN'))
2783
+ * BigDecimal(BigDecimal('Infinity'))
2784
+ * BigDecimal(BigDecimal('-Infinity'))
2785
+ * BigDecimal(BigDecimal('NaN'))
2678
2786
  * end
2679
2787
  *
2680
2788
  * For use with the BigDecimal::EXCEPTION_*
@@ -2768,13 +2876,13 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
2768
2876
  rb_raise(rb_eArgError, "Zero or negative precision for exp");
2769
2877
  }
2770
2878
 
2771
- /* TODO: the following switch statement is almostly the same as one in the
2879
+ /* TODO: the following switch statement is almost same as one in the
2772
2880
  * BigDecimalCmp function. */
2773
2881
  switch (TYPE(x)) {
2774
2882
  case T_DATA:
2775
2883
  if (!is_kind_of_BigDecimal(x)) break;
2776
2884
  vx = DATA_PTR(x);
2777
- negative = VpGetSign(vx) < 0;
2885
+ negative = BIGDECIMAL_NEGATIVE_P(vx);
2778
2886
  infinite = VpIsPosInf(vx) || VpIsNegInf(vx);
2779
2887
  nan = VpIsNaN(vx);
2780
2888
  break;
@@ -2827,7 +2935,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
2827
2935
  x = vx->obj;
2828
2936
 
2829
2937
  n = prec + rmpd_double_figures();
2830
- negative = VpGetSign(vx) < 0;
2938
+ negative = BIGDECIMAL_NEGATIVE_P(vx);
2831
2939
  if (negative) {
2832
2940
  VpSetSign(vx, 1);
2833
2941
  }
@@ -2906,14 +3014,14 @@ BigMath_s_log(VALUE klass, VALUE x, VALUE vprec)
2906
3014
  rb_raise(rb_eArgError, "Zero or negative precision for exp");
2907
3015
  }
2908
3016
 
2909
- /* TODO: the following switch statement is almostly the same as one in the
3017
+ /* TODO: the following switch statement is almost same as one in the
2910
3018
  * BigDecimalCmp function. */
2911
3019
  switch (TYPE(x)) {
2912
3020
  case T_DATA:
2913
3021
  if (!is_kind_of_BigDecimal(x)) break;
2914
3022
  vx = DATA_PTR(x);
2915
3023
  zero = VpIsZero(vx);
2916
- negative = VpGetSign(vx) < 0;
3024
+ negative = BIGDECIMAL_NEGATIVE_P(vx);
2917
3025
  infinite = VpIsPosInf(vx) || VpIsNegInf(vx);
2918
3026
  nan = VpIsNaN(vx);
2919
3027
  break;
@@ -3061,15 +3169,15 @@ get_vp_value:
3061
3169
  *
3062
3170
  * require 'bigdecimal'
3063
3171
  *
3064
- * sum = BigDecimal.new("0")
3172
+ * sum = BigDecimal("0")
3065
3173
  * 10_000.times do
3066
- * sum = sum + BigDecimal.new("0.0001")
3174
+ * sum = sum + BigDecimal("0.0001")
3067
3175
  * end
3068
3176
  * print sum #=> 0.1E1
3069
3177
  *
3070
3178
  * Similarly:
3071
3179
  *
3072
- * (BigDecimal.new("1.2") - BigDecimal("1.0")) == BigDecimal("0.2") #=> true
3180
+ * (BigDecimal("1.2") - BigDecimal("1.0")) == BigDecimal("0.2") #=> true
3073
3181
  *
3074
3182
  * (1.2 - 1.0) == 0.2 #=> false
3075
3183
  *
@@ -3083,8 +3191,8 @@ get_vp_value:
3083
3191
  * BigDecimal sometimes needs to return infinity, for example if you divide
3084
3192
  * a value by zero.
3085
3193
  *
3086
- * BigDecimal.new("1.0") / BigDecimal.new("0.0") #=> Infinity
3087
- * BigDecimal.new("-1.0") / BigDecimal.new("0.0") #=> -Infinity
3194
+ * BigDecimal("1.0") / BigDecimal("0.0") #=> Infinity
3195
+ * BigDecimal("-1.0") / BigDecimal("0.0") #=> -Infinity
3088
3196
  *
3089
3197
  * You can represent infinite numbers to BigDecimal using the strings
3090
3198
  * <code>'Infinity'</code>, <code>'+Infinity'</code> and
@@ -3097,13 +3205,13 @@ get_vp_value:
3097
3205
  *
3098
3206
  * Example:
3099
3207
  *
3100
- * BigDecimal.new("0.0") / BigDecimal.new("0.0") #=> NaN
3208
+ * BigDecimal("0.0") / BigDecimal("0.0") #=> NaN
3101
3209
  *
3102
3210
  * You can also create undefined values.
3103
3211
  *
3104
3212
  * NaN is never considered to be the same as any other value, even NaN itself:
3105
3213
  *
3106
- * n = BigDecimal.new('NaN')
3214
+ * n = BigDecimal('NaN')
3107
3215
  * n == 0.0 #=> false
3108
3216
  * n == n #=> false
3109
3217
  *
@@ -3116,11 +3224,11 @@ get_vp_value:
3116
3224
  * If the value which is too small to be represented is negative, a BigDecimal
3117
3225
  * value of negative zero is returned.
3118
3226
  *
3119
- * BigDecimal.new("1.0") / BigDecimal.new("-Infinity") #=> -0.0
3227
+ * BigDecimal("1.0") / BigDecimal("-Infinity") #=> -0.0
3120
3228
  *
3121
3229
  * If the value is positive, a value of positive zero is returned.
3122
3230
  *
3123
- * BigDecimal.new("1.0") / BigDecimal.new("Infinity") #=> 0.0
3231
+ * BigDecimal("1.0") / BigDecimal("Infinity") #=> 0.0
3124
3232
  *
3125
3233
  * (See BigDecimal.mode for how to specify limits of precision.)
3126
3234
  *
@@ -3130,13 +3238,25 @@ get_vp_value:
3130
3238
  * Note also that in mathematics, there is no particular concept of negative
3131
3239
  * or positive zero; true mathematical zero has no sign.
3132
3240
  *
3241
+ * == bigdecimal/util
3242
+ *
3243
+ * When you require +bigdecimal/util+, the #to_d method will be
3244
+ * available on BigDecimal and the native Integer, Float, Rational,
3245
+ * and String classes:
3246
+ *
3247
+ * require 'bigdecimal/util'
3248
+ *
3249
+ * 42.to_d # => 0.42e2
3250
+ * 0.5.to_d # => 0.5e0
3251
+ * (2/3r).to_d(3) # => 0.667e0
3252
+ * "0.5".to_d # => 0.5e0
3253
+ *
3133
3254
  * == License
3134
3255
  *
3135
3256
  * Copyright (C) 2002 by Shigeo Kobayashi <shigeo@tinyforest.gr.jp>.
3136
3257
  *
3137
- * 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.
3258
+ * BigDecimal is released under the Ruby and 2-clause BSD licenses.
3259
+ * See LICENSE.txt for details.
3140
3260
  *
3141
3261
  * Maintained by mrkn <mrkn@mrkn.jp> and ruby-core members.
3142
3262
  *
@@ -3163,6 +3283,7 @@ Init_bigdecimal(void)
3163
3283
  rb_define_global_function("BigDecimal", BigDecimal_global_new, -1);
3164
3284
 
3165
3285
  /* Class methods */
3286
+ rb_define_singleton_method(rb_cBigDecimal, "new", BigDecimal_s_new, -1);
3166
3287
  rb_define_singleton_method(rb_cBigDecimal, "mode", BigDecimal_mode, -1);
3167
3288
  rb_define_singleton_method(rb_cBigDecimal, "limit", BigDecimal_limit, -1);
3168
3289
  rb_define_singleton_method(rb_cBigDecimal, "double_fig", BigDecimal_double_fig, 0);
@@ -3175,6 +3296,14 @@ Init_bigdecimal(void)
3175
3296
 
3176
3297
  /* Constants definition */
3177
3298
 
3299
+ #ifndef RUBY_BIGDECIMAL_VERSION
3300
+ # error RUBY_BIGDECIMAL_VERSION is not defined
3301
+ #endif
3302
+ /*
3303
+ * The version of bigdecimal library
3304
+ */
3305
+ rb_define_const(rb_cBigDecimal, "VERSION", rb_str_new2(RUBY_BIGDECIMAL_VERSION));
3306
+
3178
3307
  /*
3179
3308
  * Base value used in internal calculations. On a 32 bit system, BASE
3180
3309
  * is 10000, indicating that calculation is done in groups of 4 digits.
@@ -3217,7 +3346,7 @@ Init_bigdecimal(void)
3217
3346
  rb_define_const(rb_cBigDecimal, "EXCEPTION_OVERFLOW", INT2FIX(VP_EXCEPTION_OVERFLOW));
3218
3347
 
3219
3348
  /*
3220
- * 0x01: Determines what happens when a division by zero is performed.
3349
+ * 0x10: Determines what happens when a division by zero is performed.
3221
3350
  * See BigDecimal.mode.
3222
3351
  */
3223
3352
  rb_define_const(rb_cBigDecimal, "EXCEPTION_ZERODIVIDE", INT2FIX(VP_EXCEPTION_ZERODIVIDE));
@@ -3311,7 +3440,8 @@ Init_bigdecimal(void)
3311
3440
  rb_define_method(rb_cBigDecimal, "modulo", BigDecimal_mod, 1);
3312
3441
  rb_define_method(rb_cBigDecimal, "remainder", BigDecimal_remainder, 1);
3313
3442
  rb_define_method(rb_cBigDecimal, "divmod", BigDecimal_divmod, 1);
3314
- /* rb_define_method(rb_cBigDecimal, "dup", BigDecimal_dup, 0); */
3443
+ rb_define_method(rb_cBigDecimal, "clone", BigDecimal_clone, 0);
3444
+ rb_define_method(rb_cBigDecimal, "dup", BigDecimal_clone, 0);
3315
3445
  rb_define_method(rb_cBigDecimal, "to_f", BigDecimal_to_f, 0);
3316
3446
  rb_define_method(rb_cBigDecimal, "abs", BigDecimal_abs, 0);
3317
3447
  rb_define_method(rb_cBigDecimal, "sqrt", BigDecimal_sqrt, 1);
@@ -3359,6 +3489,7 @@ Init_bigdecimal(void)
3359
3489
  id_floor = rb_intern_const("floor");
3360
3490
  id_to_r = rb_intern_const("to_r");
3361
3491
  id_eq = rb_intern_const("==");
3492
+ id_half = rb_intern_const("half");
3362
3493
  }
3363
3494
 
3364
3495
  /*
@@ -3386,7 +3517,14 @@ static Real *VpPt5; /* constant 0.5 */
3386
3517
  #define MemCmp(x,y,z) memcmp(x,y,z)
3387
3518
  #define StrCmp(x,y) strcmp(x,y)
3388
3519
 
3389
- static int VpIsDefOP(Real *c,Real *a,Real *b,int sw);
3520
+ enum op_sw {
3521
+ OP_SW_ADD = 1, /* + */
3522
+ OP_SW_SUB, /* - */
3523
+ OP_SW_MULT, /* * */
3524
+ OP_SW_DIV /* / */
3525
+ };
3526
+
3527
+ static int VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw);
3390
3528
  static int AddExponent(Real *a, SIGNED_VALUE n);
3391
3529
  static BDIGIT VpAddAbs(Real *a,Real *b,Real *c);
3392
3530
  static BDIGIT VpSubAbs(Real *a,Real *b,Real *c);
@@ -3413,7 +3551,7 @@ VpMemAlloc(size_t mb)
3413
3551
  return p;
3414
3552
  }
3415
3553
 
3416
- VP_EXPORT void *
3554
+ VP_EXPORT void *
3417
3555
  VpMemRealloc(void *ptr, size_t mb)
3418
3556
  {
3419
3557
  void *p = xrealloc(ptr, mb);
@@ -3431,12 +3569,12 @@ VpFree(Real *pv)
3431
3569
  #ifdef BIGDECIMAL_DEBUG
3432
3570
  gnAlloc--; /* Decrement allocation count */
3433
3571
  if (gnAlloc == 0) {
3434
- printf(" *************** All memories allocated freed ****************");
3435
- getchar();
3572
+ printf(" *************** All memories allocated freed ****************\n");
3573
+ /*getchar();*/
3436
3574
  }
3437
3575
  if (gnAlloc < 0) {
3438
3576
  printf(" ??????????? Too many memory free calls(%d) ?????????????\n", gnAlloc);
3439
- getchar();
3577
+ /*getchar();*/
3440
3578
  }
3441
3579
  #endif /* BIGDECIMAL_DEBUG */
3442
3580
  }
@@ -3466,7 +3604,7 @@ VpGetException (void)
3466
3604
  return RMPD_EXCEPTION_MODE_DEFAULT;
3467
3605
  }
3468
3606
 
3469
- return (unsigned short)FIX2UINT(vmode);
3607
+ return NUM2USHORT(vmode);
3470
3608
  }
3471
3609
 
3472
3610
  static void
@@ -3536,7 +3674,7 @@ VpGetRoundMode(void)
3536
3674
  return RMPD_ROUNDING_MODE_DEFAULT;
3537
3675
  }
3538
3676
 
3539
- return (unsigned short)FIX2INT(vmode);
3677
+ return NUM2USHORT(vmode);
3540
3678
  }
3541
3679
 
3542
3680
  VP_EXPORT int
@@ -3673,7 +3811,7 @@ VpException(unsigned short f, const char *str,int always)
3673
3811
  /* Throw exception or returns 0,when resulting c is Inf or NaN */
3674
3812
  /* sw=1:+ 2:- 3:* 4:/ */
3675
3813
  static int
3676
- VpIsDefOP(Real *c,Real *a,Real *b,int sw)
3814
+ VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw)
3677
3815
  {
3678
3816
  if (VpIsNaN(a) || VpIsNaN(b)) {
3679
3817
  /* at least a or b is NaN */
@@ -3684,7 +3822,7 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
3684
3822
  if (VpIsInf(a)) {
3685
3823
  if (VpIsInf(b)) {
3686
3824
  switch(sw) {
3687
- case 1: /* + */
3825
+ case OP_SW_ADD: /* + */
3688
3826
  if (VpGetSign(a) == VpGetSign(b)) {
3689
3827
  VpSetInf(c, VpGetSign(a));
3690
3828
  goto Inf;
@@ -3693,7 +3831,7 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
3693
3831
  VpSetNaN(c);
3694
3832
  goto NaN;
3695
3833
  }
3696
- case 2: /* - */
3834
+ case OP_SW_SUB: /* - */
3697
3835
  if (VpGetSign(a) != VpGetSign(b)) {
3698
3836
  VpSetInf(c, VpGetSign(a));
3699
3837
  goto Inf;
@@ -3702,12 +3840,10 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
3702
3840
  VpSetNaN(c);
3703
3841
  goto NaN;
3704
3842
  }
3705
- break;
3706
- case 3: /* * */
3843
+ case OP_SW_MULT: /* * */
3707
3844
  VpSetInf(c, VpGetSign(a)*VpGetSign(b));
3708
3845
  goto Inf;
3709
- break;
3710
- case 4: /* / */
3846
+ case OP_SW_DIV: /* / */
3711
3847
  VpSetNaN(c);
3712
3848
  goto NaN;
3713
3849
  }
@@ -3716,18 +3852,18 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
3716
3852
  }
3717
3853
  /* Inf op Finite */
3718
3854
  switch(sw) {
3719
- case 1: /* + */
3720
- case 2: /* - */
3855
+ case OP_SW_ADD: /* + */
3856
+ case OP_SW_SUB: /* - */
3721
3857
  VpSetInf(c, VpGetSign(a));
3722
3858
  break;
3723
- case 3: /* * */
3859
+ case OP_SW_MULT: /* * */
3724
3860
  if (VpIsZero(b)) {
3725
3861
  VpSetNaN(c);
3726
3862
  goto NaN;
3727
3863
  }
3728
3864
  VpSetInf(c, VpGetSign(a)*VpGetSign(b));
3729
3865
  break;
3730
- case 4: /* / */
3866
+ case OP_SW_DIV: /* / */
3731
3867
  VpSetInf(c, VpGetSign(a)*VpGetSign(b));
3732
3868
  }
3733
3869
  goto Inf;
@@ -3735,20 +3871,20 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
3735
3871
 
3736
3872
  if (VpIsInf(b)) {
3737
3873
  switch(sw) {
3738
- case 1: /* + */
3874
+ case OP_SW_ADD: /* + */
3739
3875
  VpSetInf(c, VpGetSign(b));
3740
3876
  break;
3741
- case 2: /* - */
3877
+ case OP_SW_SUB: /* - */
3742
3878
  VpSetInf(c, -VpGetSign(b));
3743
3879
  break;
3744
- case 3: /* * */
3880
+ case OP_SW_MULT: /* * */
3745
3881
  if (VpIsZero(a)) {
3746
3882
  VpSetNaN(c);
3747
3883
  goto NaN;
3748
3884
  }
3749
3885
  VpSetInf(c, VpGetSign(a)*VpGetSign(b));
3750
3886
  break;
3751
- case 4: /* / */
3887
+ case OP_SW_DIV: /* / */
3752
3888
  VpSetZero(c, VpGetSign(a)*VpGetSign(b));
3753
3889
  }
3754
3890
  goto Inf;
@@ -3756,7 +3892,13 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
3756
3892
  return 1; /* Results OK */
3757
3893
 
3758
3894
  Inf:
3759
- return VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 0);
3895
+ if (VpIsPosInf(c)) {
3896
+ return VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 0);
3897
+ }
3898
+ else {
3899
+ return VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 0);
3900
+ }
3901
+
3760
3902
  NaN:
3761
3903
  return VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'", 0);
3762
3904
  }
@@ -3831,12 +3973,12 @@ VpInit(BDIGIT BaseVal)
3831
3973
 
3832
3974
  #ifdef BIGDECIMAL_DEBUG
3833
3975
  if (gfDebug) {
3834
- printf("VpInit: BaseVal = %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);
3976
+ printf("VpInit: BaseVal = %"PRIuBDIGIT"\n", BaseVal);
3977
+ printf("\tBASE = %"PRIuBDIGIT"\n", BASE);
3978
+ printf("\tHALF_BASE = %"PRIuBDIGIT"\n", HALF_BASE);
3979
+ printf("\tBASE1 = %"PRIuBDIGIT"\n", BASE1);
3980
+ printf("\tBASE_FIG = %u\n", BASE_FIG);
3981
+ printf("\tDBLE_FIG = %d\n", DBLE_FIG);
3840
3982
  }
3841
3983
  #endif /* BIGDECIMAL_DEBUG */
3842
3984
 
@@ -3863,7 +4005,7 @@ AddExponent(Real *a, SIGNED_VALUE n)
3863
4005
  goto overflow;
3864
4006
  mb = m*(SIGNED_VALUE)BASE_FIG;
3865
4007
  eb = e*(SIGNED_VALUE)BASE_FIG;
3866
- if (mb < eb) goto overflow;
4008
+ if (eb - mb > 0) goto overflow;
3867
4009
  }
3868
4010
  }
3869
4011
  else if (n < 0) {
@@ -3872,7 +4014,7 @@ AddExponent(Real *a, SIGNED_VALUE n)
3872
4014
  goto underflow;
3873
4015
  mb = m*(SIGNED_VALUE)BASE_FIG;
3874
4016
  eb = e*(SIGNED_VALUE)BASE_FIG;
3875
- if (mb > eb) goto underflow;
4017
+ if (mb - eb > 0) goto underflow;
3876
4018
  }
3877
4019
  a->exponent = m;
3878
4020
  return 1;
@@ -3903,7 +4045,8 @@ overflow:
3903
4045
  VP_EXPORT Real *
3904
4046
  VpAlloc(size_t mx, const char *szVal)
3905
4047
  {
3906
- size_t i, ni, ipn, ipf, nf, ipe, ne, nalloc;
4048
+ const char *orig_szVal = szVal;
4049
+ size_t i, ni, ipn, ipf, nf, ipe, ne, dot_seen, exp_seen, nalloc;
3907
4050
  char v, *psz;
3908
4051
  int sign=1;
3909
4052
  Real *vp = NULL;
@@ -3914,28 +4057,28 @@ VpAlloc(size_t mx, const char *szVal)
3914
4057
  if (mx == 0) ++mx;
3915
4058
 
3916
4059
  if (szVal) {
3917
- 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
- }
4060
+ while (ISSPACE(*szVal)) szVal++;
4061
+ if (*szVal != '#') {
4062
+ if (mf) {
4063
+ mf = (mf + BASE_FIG - 1) / BASE_FIG + 2; /* Needs 1 more for div */
4064
+ if (mx > mf) {
4065
+ mx = mf;
4066
+ }
4067
+ }
4068
+ }
4069
+ else {
4070
+ ++szVal;
4071
+ }
3929
4072
  }
3930
4073
  else {
3931
- /* 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;
4074
+ /* necessary to be able to store */
4075
+ /* at least mx digits. */
4076
+ /* szVal==NULL ==> allocate zero value. */
4077
+ vp = VpAllocReal(mx);
4078
+ /* xmalloc() alway returns(or throw interruption) */
4079
+ vp->MaxPrec = mx; /* set max precision */
4080
+ VpSetZero(vp, 1); /* initialize vp to zero. */
4081
+ return vp;
3939
4082
  }
3940
4083
 
3941
4084
  /* Skip all '_' after digit: 2006-6-30 */
@@ -3945,43 +4088,42 @@ VpAlloc(size_t mx, const char *szVal)
3945
4088
  i = 0;
3946
4089
  ipn = 0;
3947
4090
  while ((psz[i] = szVal[ipn]) != 0) {
3948
- 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;
4091
+ if (ISSPACE(psz[i])) {
4092
+ psz[i] = 0;
4093
+ break;
4094
+ }
4095
+ if (ISDIGIT(psz[i])) ++ni;
4096
+ if (psz[i] == '_') {
4097
+ if (ni > 0) {
4098
+ ipn++;
4099
+ continue;
4100
+ }
4101
+ psz[i] = 0;
4102
+ break;
4103
+ }
4104
+ ++i;
4105
+ ++ipn;
3964
4106
  }
3965
4107
  szVal = psz;
3966
4108
 
3967
4109
  /* Check on Inf & NaN */
3968
4110
  if (StrCmp(szVal, SZ_PINF) == 0 || StrCmp(szVal, SZ_INF) == 0 ) {
3969
- vp = VpAllocReal(1);
3970
- vp->MaxPrec = 1; /* set max precision */
3971
- VpSetPosInf(vp);
3972
- return vp;
4111
+ vp = VpAllocReal(1);
4112
+ vp->MaxPrec = 1; /* set max precision */
4113
+ VpSetPosInf(vp);
4114
+ return vp;
3973
4115
  }
3974
4116
  if (StrCmp(szVal, SZ_NINF) == 0) {
3975
- vp = VpAllocReal(1);
3976
- vp->MaxPrec = 1; /* set max precision */
3977
- VpSetNegInf(vp);
3978
- return vp;
4117
+ vp = VpAllocReal(1);
4118
+ vp->MaxPrec = 1; /* set max precision */
4119
+ VpSetNegInf(vp);
4120
+ return vp;
3979
4121
  }
3980
4122
  if (StrCmp(szVal, SZ_NaN) == 0) {
3981
- vp = VpAllocReal(1);
3982
- vp->MaxPrec = 1; /* set max precision */
3983
- VpSetNaN(vp);
3984
- return vp;
4123
+ vp = VpAllocReal(1);
4124
+ vp->MaxPrec = 1; /* set max precision */
4125
+ VpSetNaN(vp);
4126
+ return vp;
3985
4127
  }
3986
4128
 
3987
4129
  /* check on number szVal[] */
@@ -3991,46 +4133,55 @@ VpAlloc(size_t mx, const char *szVal)
3991
4133
  /* Skip digits */
3992
4134
  ni = 0; /* digits in mantissa */
3993
4135
  while ((v = szVal[i]) != 0) {
3994
- if (!ISDIGIT(v)) break;
3995
- ++i;
3996
- ++ni;
4136
+ if (!ISDIGIT(v)) break;
4137
+ ++i;
4138
+ ++ni;
3997
4139
  }
3998
4140
  nf = 0;
3999
4141
  ipf = 0;
4000
4142
  ipe = 0;
4001
4143
  ne = 0;
4144
+ dot_seen = 0;
4145
+ exp_seen = 0;
4002
4146
  if (v) {
4003
- /* 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
- }
4147
+ /* other than digit nor \0 */
4148
+ if (szVal[i] == '.') { /* xxx. */
4149
+ dot_seen = 1;
4150
+ ++i;
4151
+ ipf = i;
4152
+ while ((v = szVal[i]) != 0) { /* get fraction part. */
4153
+ if (!ISDIGIT(v)) break;
4154
+ ++i;
4155
+ ++nf;
4156
+ }
4157
+ }
4158
+ ipe = 0; /* Exponent */
4159
+
4160
+ switch (szVal[i]) {
4161
+ case '\0':
4162
+ break;
4163
+ case 'e': case 'E':
4164
+ case 'd': case 'D':
4165
+ exp_seen = 1;
4166
+ ++i;
4167
+ ipe = i;
4168
+ v = szVal[i];
4169
+ if ((v == '-') || (v == '+')) ++i;
4170
+ while ((v=szVal[i]) != 0) {
4171
+ if (!ISDIGIT(v)) break;
4172
+ ++i;
4173
+ ++ne;
4174
+ }
4175
+ break;
4176
+ default:
4177
+ break;
4178
+ }
4179
+ }
4180
+ if (((ni == 0 || dot_seen) && nf == 0) || (exp_seen && ne == 0)) {
4181
+ VALUE str = rb_str_new2(orig_szVal);
4182
+ rb_raise(rb_eArgError, "invalid value for BigDecimal(): \"%"PRIsVALUE"\"", str);
4033
4183
  }
4184
+
4034
4185
  nalloc = (ni + nf + BASE_FIG - 1) / BASE_FIG + 1; /* set effective allocation */
4035
4186
  /* units for szVal[] */
4036
4187
  if (mx == 0) mx = 1;
@@ -4098,7 +4249,7 @@ VpAsgn(Real *c, Real *a, int isw)
4098
4249
 
4099
4250
  /*
4100
4251
  * c = a + b when operation = 1 or 2
4101
- * = a - b when operation = -1 or -2.
4252
+ * c = a - b when operation = -1 or -2.
4102
4253
  * Returns number of significant digits of c
4103
4254
  */
4104
4255
  VP_EXPORT size_t
@@ -4117,7 +4268,7 @@ VpAddSub(Real *c, Real *a, Real *b, int operation)
4117
4268
  }
4118
4269
  #endif /* BIGDECIMAL_DEBUG */
4119
4270
 
4120
- if (!VpIsDefOP(c, a, b, (operation > 0) ? 1 : 2)) return 0; /* No significant digits */
4271
+ if (!VpIsDefOP(c, a, b, (operation > 0) ? OP_SW_ADD : OP_SW_SUB)) return 0; /* No significant digits */
4121
4272
 
4122
4273
  /* check if a or b is zero */
4123
4274
  if (VpIsZero(a)) {
@@ -4231,7 +4382,7 @@ end_if:
4231
4382
  }
4232
4383
 
4233
4384
  /*
4234
- * Addition of two variable precisional variables
4385
+ * Addition of two values with variable precision
4235
4386
  * a and b assuming abs(a)>abs(b).
4236
4387
  * c = abs(a) + abs(b) ; where |a|>=|b|
4237
4388
  */
@@ -4453,7 +4604,7 @@ VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos,
4453
4604
 
4454
4605
  size_t const round_limit = (VpGetPrecLimit() + BASE_FIG - 1) / BASE_FIG;
4455
4606
 
4456
- assert(a->exponent >= b->expoennt);
4607
+ assert(a->exponent >= b->exponent);
4457
4608
 
4458
4609
  c->frac[0] = 0;
4459
4610
  *av = *bv = 0;
@@ -4573,7 +4724,7 @@ VpMult(Real *c, Real *a, Real *b)
4573
4724
  }
4574
4725
  #endif /* BIGDECIMAL_DEBUG */
4575
4726
 
4576
- if (!VpIsDefOP(c, a, b, 3)) return 0; /* No significant digit */
4727
+ if (!VpIsDefOP(c, a, b, OP_SW_MULT)) return 0; /* No significant digit */
4577
4728
 
4578
4729
  if (VpIsZero(a) || VpIsZero(b)) {
4579
4730
  /* at least a or b is zero */
@@ -4685,7 +4836,7 @@ Exit:
4685
4836
  /*
4686
4837
  * c = a / b, remainder = r
4687
4838
  */
4688
- VP_EXPORT size_t
4839
+ VP_EXPORT size_t
4689
4840
  VpDivd(Real *c, Real *r, Real *a, Real *b)
4690
4841
  {
4691
4842
  size_t word_a, word_b, word_c, word_r;
@@ -4703,14 +4854,14 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
4703
4854
  #endif /*BIGDECIMAL_DEBUG */
4704
4855
 
4705
4856
  VpSetNaN(r);
4706
- if (!VpIsDefOP(c, a, b, 4)) goto Exit;
4857
+ if (!VpIsDefOP(c, a, b, OP_SW_DIV)) goto Exit;
4707
4858
  if (VpIsZero(a) && VpIsZero(b)) {
4708
4859
  VpSetNaN(c);
4709
- return VpException(VP_EXCEPTION_NaN, "(VpDivd) 0/0 not defined(NaN)", 0);
4860
+ return VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'", 0);
4710
4861
  }
4711
4862
  if (VpIsZero(b)) {
4712
4863
  VpSetInf(c, VpGetSign(a) * VpGetSign(b));
4713
- return VpException(VP_EXCEPTION_ZERODIVIDE, "(VpDivd) Divide by zero", 0);
4864
+ return VpException(VP_EXCEPTION_ZERODIVIDE, "Divide by zero", 0);
4714
4865
  }
4715
4866
  if (VpIsZero(a)) {
4716
4867
  /* numerator a is zero */
@@ -4990,7 +5141,7 @@ VpComp(Real *a, Real *b)
4990
5141
  goto Exit;
4991
5142
  }
4992
5143
 
4993
- /* a and b have same exponent, then compare significand. */
5144
+ /* a and b have same exponent, then compare their significand. */
4994
5145
  mx = (a->Prec < b->Prec) ? a->Prec : b->Prec;
4995
5146
  ind = 0;
4996
5147
  while (ind < mx) {
@@ -5031,8 +5182,8 @@ Exit:
5031
5182
  * % ... VP variable. To print '%', use '%%'.
5032
5183
  * \n ... new line
5033
5184
  * \b ... backspace
5034
- * ... tab
5035
- * Note: % must must not appear more than once
5185
+ * \t ... tab
5186
+ * Note: % must not appear more than once
5036
5187
  * a ... VP variable to be printed
5037
5188
  */
5038
5189
  #ifdef BIGDECIMAL_ENABLE_VPRINT
@@ -5042,24 +5193,6 @@ VPrint(FILE *fp, const char *cntl_chr, Real *a)
5042
5193
  size_t i, j, nc, nd, ZeroSup, sep = 10;
5043
5194
  BDIGIT m, e, nn;
5044
5195
 
5045
- /* Check if NaN & Inf. */
5046
- if (VpIsNaN(a)) {
5047
- fprintf(fp, SZ_NaN);
5048
- return 8;
5049
- }
5050
- if (VpIsPosInf(a)) {
5051
- fprintf(fp, SZ_INF);
5052
- return 8;
5053
- }
5054
- if (VpIsNegInf(a)) {
5055
- fprintf(fp, SZ_NINF);
5056
- return 9;
5057
- }
5058
- if (VpIsZero(a)) {
5059
- fprintf(fp, "0.0");
5060
- return 3;
5061
- }
5062
-
5063
5196
  j = 0;
5064
5197
  nd = nc = 0; /* nd : number of digits in fraction part(every 10 digits, */
5065
5198
  /* nd<=10). */
@@ -5068,8 +5201,20 @@ VPrint(FILE *fp, const char *cntl_chr, Real *a)
5068
5201
  while (*(cntl_chr + j)) {
5069
5202
  if (*(cntl_chr + j) == '%' && *(cntl_chr + j + 1) != '%') {
5070
5203
  nc = 0;
5071
- if (!VpIsZero(a)) {
5072
- if (VpGetSign(a) < 0) {
5204
+ if (VpIsNaN(a)) {
5205
+ fprintf(fp, SZ_NaN);
5206
+ nc += 8;
5207
+ }
5208
+ else if (VpIsPosInf(a)) {
5209
+ fprintf(fp, SZ_INF);
5210
+ nc += 8;
5211
+ }
5212
+ else if (VpIsNegInf(a)) {
5213
+ fprintf(fp, SZ_NINF);
5214
+ nc += 9;
5215
+ }
5216
+ else if (!VpIsZero(a)) {
5217
+ if (BIGDECIMAL_NEGATIVE_P(a)) {
5073
5218
  fprintf(fp, "-");
5074
5219
  ++nc;
5075
5220
  }
@@ -5158,7 +5303,7 @@ VpFormatSt(char *psz, size_t fFmt)
5158
5303
  if (!ch) break;
5159
5304
  if (ISSPACE(ch) || ch=='-' || ch=='+') continue;
5160
5305
  if (ch == '.') { nf = 0; continue; }
5161
- if (ch == 'E') break;
5306
+ if (ch == 'E' || ch == 'e') break;
5162
5307
 
5163
5308
  if (++nf > fFmt) {
5164
5309
  memmove(psz + i + 1, psz + i, ie - i + 1);
@@ -5207,7 +5352,7 @@ VpSzMantissa(Real *a,char *psz)
5207
5352
 
5208
5353
  ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
5209
5354
  if (!VpIsZero(a)) {
5210
- if (VpGetSign(a) < 0) *psz++ = '-';
5355
+ if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
5211
5356
  n = a->Prec;
5212
5357
  for (i = 0; i < n; ++i) {
5213
5358
  m = BASE1;
@@ -5235,7 +5380,7 @@ VpSzMantissa(Real *a,char *psz)
5235
5380
 
5236
5381
  VP_EXPORT int
5237
5382
  VpToSpecialString(Real *a,char *psz,int fPlus)
5238
- /* fPlus =0:default, =1: set ' ' before digits , =2: set '+' before digits. */
5383
+ /* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
5239
5384
  {
5240
5385
  if (VpIsNaN(a)) {
5241
5386
  sprintf(psz,SZ_NaN);
@@ -5270,7 +5415,7 @@ VpToSpecialString(Real *a,char *psz,int fPlus)
5270
5415
 
5271
5416
  VP_EXPORT void
5272
5417
  VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
5273
- /* fPlus =0:default, =1: set ' ' before digits , =2:set '+' before digits. */
5418
+ /* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
5274
5419
  {
5275
5420
  size_t i, n, ZeroSup;
5276
5421
  BDIGIT shift, m, e, nn;
@@ -5281,7 +5426,7 @@ VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
5281
5426
 
5282
5427
  ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
5283
5428
 
5284
- if (VpGetSign(a) < 0) *psz++ = '-';
5429
+ if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
5285
5430
  else if (fPlus == 1) *psz++ = ' ';
5286
5431
  else if (fPlus == 2) *psz++ = '+';
5287
5432
 
@@ -5312,13 +5457,13 @@ VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
5312
5457
  while (psz[-1] == '0') {
5313
5458
  *(--psz) = 0;
5314
5459
  }
5315
- sprintf(psz, "E%"PRIdSIZE, ex);
5460
+ sprintf(psz, "e%"PRIdSIZE, ex);
5316
5461
  if (fFmt) VpFormatSt(pszSav, fFmt);
5317
5462
  }
5318
5463
 
5319
5464
  VP_EXPORT void
5320
5465
  VpToFString(Real *a, char *psz, size_t fFmt, int fPlus)
5321
- /* fPlus =0:default,=1: set ' ' before digits ,set '+' before digits. */
5466
+ /* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
5322
5467
  {
5323
5468
  size_t i, n;
5324
5469
  BDIGIT m, e, nn;
@@ -5327,7 +5472,7 @@ VpToFString(Real *a, char *psz, size_t fFmt, int fPlus)
5327
5472
 
5328
5473
  if (VpToSpecialString(a, psz, fPlus)) return;
5329
5474
 
5330
- if (VpGetSign(a) < 0) *psz++ = '-';
5475
+ if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
5331
5476
  else if (fPlus == 1) *psz++ = ' ';
5332
5477
  else if (fPlus == 2) *psz++ = '+';
5333
5478
 
@@ -5749,21 +5894,22 @@ VpSqrt(Real *y, Real *x)
5749
5894
  ssize_t nr;
5750
5895
  double val;
5751
5896
 
5752
- /* Zero, 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);
5897
+ /* Zero or +Infinity ? */
5898
+ if (VpIsZero(x) || VpIsPosInf(x)) {
5899
+ VpAsgn(y,x,1);
5760
5900
  goto Exit;
5761
5901
  }
5762
5902
 
5763
5903
  /* Negative ? */
5764
- if (VpGetSign(x) < 0) {
5904
+ if (BIGDECIMAL_NEGATIVE_P(x)) {
5905
+ VpSetNaN(y);
5906
+ return VpException(VP_EXCEPTION_OP, "sqrt of negative value", 0);
5907
+ }
5908
+
5909
+ /* NaN ? */
5910
+ if (VpIsNaN(x)) {
5765
5911
  VpSetNaN(y);
5766
- return VpException(VP_EXCEPTION_OP, "(VpSqrt) SQRT(negative value)", 0);
5912
+ return VpException(VP_EXCEPTION_OP, "sqrt of 'NaN'(Not a Number)", 0);
5767
5913
  }
5768
5914
 
5769
5915
  /* One ? */
@@ -5841,18 +5987,13 @@ Exit:
5841
5987
  return 1;
5842
5988
  }
5843
5989
 
5844
- /*
5845
- *
5846
- * nf: digit position for operation.
5847
- *
5848
- */
5849
- VP_EXPORT int
5850
- VpMidRound(Real *y, unsigned short f, ssize_t nf)
5851
5990
  /*
5852
5991
  * Round relatively from the decimal point.
5853
5992
  * f: rounding mode
5854
5993
  * nf: digit location to round from the decimal point.
5855
5994
  */
5995
+ VP_EXPORT int
5996
+ VpMidRound(Real *y, unsigned short f, ssize_t nf)
5856
5997
  {
5857
5998
  /* fracf: any positive digit under rounding position? */
5858
5999
  /* fracf_1further: any positive digits under one further than the rounding position? */
@@ -5954,10 +6095,10 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
5954
6095
  if (v > 5 || (v == 5 && fracf_1further)) ++div;
5955
6096
  break;
5956
6097
  case VP_ROUND_CEIL:
5957
- if (fracf && (VpGetSign(y) > 0)) ++div;
6098
+ if (fracf && BIGDECIMAL_POSITIVE_P(y)) ++div;
5958
6099
  break;
5959
6100
  case VP_ROUND_FLOOR:
5960
- if (fracf && (VpGetSign(y) < 0)) ++div;
6101
+ if (fracf && BIGDECIMAL_NEGATIVE_P(y)) ++div;
5961
6102
  break;
5962
6103
  case VP_ROUND_HALF_EVEN: /* Banker's rounding */
5963
6104
  if (v > 5) ++div;
@@ -6076,10 +6217,10 @@ VpInternalRound(Real *c, size_t ixDigit, BDIGIT vPrev, BDIGIT v)
6076
6217
  if (v >= 6) f = 1;
6077
6218
  break;
6078
6219
  case VP_ROUND_CEIL:
6079
- if (v && (VpGetSign(c) > 0)) f = 1;
6220
+ if (v && BIGDECIMAL_POSITIVE_P(c)) f = 1;
6080
6221
  break;
6081
6222
  case VP_ROUND_FLOOR:
6082
- if (v && (VpGetSign(c) < 0)) f = 1;
6223
+ if (v && BIGDECIMAL_NEGATIVE_P(c)) f = 1;
6083
6224
  break;
6084
6225
  case VP_ROUND_HALF_EVEN: /* Banker's rounding */
6085
6226
  /* as per VP_ROUND_HALF_DOWN, because this is the last digit of precision,
@@ -6216,7 +6357,7 @@ VpPower(Real *y, Real *x, SIGNED_VALUE n)
6216
6357
  if (x->exponent == 1 && x->Prec == 1 && x->frac[0] == 1) {
6217
6358
  /* abs(x) = 1 */
6218
6359
  VpSetOne(y);
6219
- if (VpGetSign(x) > 0) goto Exit;
6360
+ if (BIGDECIMAL_POSITIVE_P(x)) goto Exit;
6220
6361
  if ((n % 2) == 0) goto Exit;
6221
6362
  VpSetSign(y, -1);
6222
6363
  goto Exit;
@@ -6261,7 +6402,7 @@ Exit:
6261
6402
  if (gfDebug) {
6262
6403
  VPrint(stdout, "VpPower y=%\n", y);
6263
6404
  VPrint(stdout, "VpPower x=%\n", x);
6264
- printf(" n=%d\n", n);
6405
+ printf(" n=%"PRIdVALUE"\n", n);
6265
6406
  }
6266
6407
  #endif /* BIGDECIMAL_DEBUG */
6267
6408
  VpFree(w2);
@@ -6296,10 +6437,10 @@ VpVarCheck(Real * v)
6296
6437
  for (i = 0; i < v->Prec; ++i) {
6297
6438
  if (v->frac[i] >= BASE) {
6298
6439
  printf("ERROR(VpVarCheck): Illegal fraction\n");
6299
- printf(" Frac[%"PRIuSIZE"]=%lu\n", i, v->frac[i]);
6440
+ printf(" Frac[%"PRIuSIZE"]=%"PRIuBDIGIT"\n", i, v->frac[i]);
6300
6441
  printf(" Prec. =%"PRIuSIZE"\n", v->Prec);
6301
6442
  printf(" Exp. =%"PRIdVALUE"\n", v->exponent);
6302
- printf(" BASE =%lu\n", BASE);
6443
+ printf(" BASE =%"PRIuBDIGIT"\n", BASE);
6303
6444
  return 3;
6304
6445
  }
6305
6446
  }