bigdecimal 1.2.7 → 1.3.4

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