bigdecimal 1.2.7 → 1.4.3

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
@@ -116,7 +110,7 @@ rb_rational_num(VALUE rat)
116
110
  #ifdef HAVE_TYPE_STRUCT_RRATIONAL
117
111
  return RRATIONAL(rat)->num;
118
112
  #else
119
- return rb_funcall(rat, rb_intern("numerator"));
113
+ return rb_funcall(rat, rb_intern("numerator"), 0);
120
114
  #endif
121
115
  }
122
116
  #endif
@@ -128,30 +122,19 @@ rb_rational_den(VALUE rat)
128
122
  #ifdef HAVE_TYPE_STRUCT_RRATIONAL
129
123
  return RRATIONAL(rat)->den;
130
124
  #else
131
- return rb_funcall(rat, rb_intern("denominator"));
125
+ return rb_funcall(rat, rb_intern("denominator"), 0);
132
126
  #endif
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
  */
139
136
  #define DoSomeOne(x,y,f) rb_num_coerce_bin(x,y,f)
140
137
 
141
- /*
142
- * Returns the BigDecimal version number.
143
- */
144
- static VALUE
145
- BigDecimal_version(VALUE self)
146
- {
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");
153
- }
154
-
155
138
  /*
156
139
  * VP routines used in BigDecimal part
157
140
  */
@@ -179,7 +162,7 @@ static size_t
179
162
  BigDecimal_memsize(const void *ptr)
180
163
  {
181
164
  const Real *pv = ptr;
182
- return pv ? (sizeof(*pv) + pv->MaxPrec * sizeof(BDIGIT)) : 0;
165
+ return (sizeof(*pv) + pv->MaxPrec * sizeof(BDIGIT));
183
166
  }
184
167
 
185
168
  static const rb_data_type_t BigDecimal_data_type = {
@@ -234,6 +217,7 @@ static inline VALUE BigDecimal_div2(VALUE, VALUE, VALUE);
234
217
  static Real*
235
218
  GetVpValueWithPrec(VALUE v, long prec, int must)
236
219
  {
220
+ ENTER(1);
237
221
  Real *pv;
238
222
  VALUE num, bg;
239
223
  char szD[128];
@@ -246,6 +230,11 @@ again:
246
230
  if (prec < 0) goto unable_to_coerce_without_prec;
247
231
  if (prec > DBL_DIG+1) goto SomeOneMayDoIt;
248
232
  d = RFLOAT_VALUE(v);
233
+ if (!isfinite(d)) {
234
+ pv = VpCreateRbObject(1, NULL);
235
+ VpDtoV(pv, d);
236
+ return pv;
237
+ }
249
238
  if (d != 0.0) {
250
239
  v = rb_funcall(v, id_to_r, 0);
251
240
  goto again;
@@ -286,13 +275,15 @@ again:
286
275
 
287
276
  #ifdef ENABLE_NUMERIC_STRING
288
277
  case T_STRING:
289
- SafeStringValue(v);
290
- return VpCreateRbObject(strlen(RSTRING_PTR(v)) + VpBaseFig() + 1,
278
+ StringValueCStr(v);
279
+ rb_check_safe_obj(v);
280
+ return VpCreateRbObject(RSTRING_LEN(v) + VpBaseFig() + 1,
291
281
  RSTRING_PTR(v));
292
282
  #endif /* ENABLE_NUMERIC_STRING */
293
283
 
294
284
  case T_BIGNUM:
295
285
  bg = rb_big2str(v, 10);
286
+ PUSH(bg);
296
287
  return VpCreateRbObject(strlen(RSTRING_PTR(bg)) + VpBaseFig() + 1,
297
288
  RSTRING_PTR(bg));
298
289
  default:
@@ -333,15 +324,18 @@ BigDecimal_double_fig(VALUE self)
333
324
  return INT2FIX(VpDblFig());
334
325
  }
335
326
 
336
- /* call-seq:
337
- * precs
327
+ /* call-seq:
328
+ * big_decimal.precs -> array
329
+ *
330
+ * Returns an Array of two Integer values.
338
331
  *
339
- * Returns an Array of two Integer values.
332
+ * The first value is the current number of significant digits in the
333
+ * BigDecimal. The second value is the maximum number of significant digits
334
+ * for the BigDecimal.
340
335
  *
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.
336
+ * BigDecimal('5').precs #=> [9, 18]
344
337
  */
338
+
345
339
  static VALUE
346
340
  BigDecimal_prec(VALUE self)
347
341
  {
@@ -377,7 +371,7 @@ BigDecimal_hash(VALUE self)
377
371
  hash ^= rb_memhash(p->frac, sizeof(BDIGIT)*p->Prec);
378
372
  hash += p->exponent;
379
373
  }
380
- return INT2FIX(hash);
374
+ return ST2FIX(hash);
381
375
  }
382
376
 
383
377
  /*
@@ -385,10 +379,10 @@ BigDecimal_hash(VALUE self)
385
379
  *
386
380
  * Method used to provide marshalling support.
387
381
  *
388
- * inf = BigDecimal.new('Infinity')
389
- * #=> #<BigDecimal:1e16fa8,'Infinity',9(9)>
382
+ * inf = BigDecimal('Infinity')
383
+ * #=> Infinity
390
384
  * BigDecimal._load(inf._dump)
391
- * #=> #<BigDecimal:1df8dc8,'Infinity',9(9)>
385
+ * #=> Infinity
392
386
  *
393
387
  * See the Marshal module.
394
388
  */
@@ -423,8 +417,8 @@ BigDecimal_load(VALUE self, VALUE str)
423
417
  unsigned char ch;
424
418
  unsigned long m=0;
425
419
 
426
- SafeStringValue(str);
427
- pch = (unsigned char *)RSTRING_PTR(str);
420
+ pch = (unsigned char *)StringValueCStr(str);
421
+ rb_check_safe_obj(str);
428
422
  /* First get max prec */
429
423
  while((*pch) != (unsigned char)'\0' && (ch = *pch++) != (unsigned char)':') {
430
424
  if(!ISDIGIT(ch)) {
@@ -441,6 +435,55 @@ BigDecimal_load(VALUE self, VALUE str)
441
435
  return ToValue(pv);
442
436
  }
443
437
 
438
+ static unsigned short
439
+ check_rounding_mode_option(VALUE const opts)
440
+ {
441
+ VALUE mode;
442
+ char const *s;
443
+ long l;
444
+
445
+ assert(RB_TYPE_P(opts, T_HASH));
446
+
447
+ if (NIL_P(opts))
448
+ goto noopt;
449
+
450
+ mode = rb_hash_lookup2(opts, ID2SYM(id_half), Qundef);
451
+ if (mode == Qundef || NIL_P(mode))
452
+ goto noopt;
453
+
454
+ if (SYMBOL_P(mode))
455
+ mode = rb_sym2str(mode);
456
+ else if (!RB_TYPE_P(mode, T_STRING)) {
457
+ VALUE str_mode = rb_check_string_type(mode);
458
+ if (NIL_P(str_mode)) goto invalid;
459
+ mode = str_mode;
460
+ }
461
+ s = RSTRING_PTR(mode);
462
+ l = RSTRING_LEN(mode);
463
+ switch (l) {
464
+ case 2:
465
+ if (strncasecmp(s, "up", 2) == 0)
466
+ return VP_ROUND_HALF_UP;
467
+ break;
468
+ case 4:
469
+ if (strncasecmp(s, "even", 4) == 0)
470
+ return VP_ROUND_HALF_EVEN;
471
+ else if (strncasecmp(s, "down", 4) == 0)
472
+ return VP_ROUND_HALF_DOWN;
473
+ break;
474
+ default:
475
+ break;
476
+ }
477
+ invalid:
478
+ if (NIL_P(mode))
479
+ rb_raise(rb_eArgError, "invalid rounding mode: nil");
480
+ else
481
+ rb_raise(rb_eArgError, "invalid rounding mode: %"PRIsVALUE, mode);
482
+
483
+ noopt:
484
+ return VpGetRoundMode();
485
+ }
486
+
444
487
  static unsigned short
445
488
  check_rounding_mode(VALUE const v)
446
489
  {
@@ -469,8 +512,7 @@ check_rounding_mode(VALUE const v)
469
512
  break;
470
513
  }
471
514
 
472
- Check_Type(v, T_FIXNUM);
473
- sw = (unsigned short)FIX2UINT(v);
515
+ sw = NUM2USHORT(v);
474
516
  if (!VpIsRoundMode(sw)) {
475
517
  rb_raise(rb_eArgError, "invalid rounding mode");
476
518
  }
@@ -523,8 +565,7 @@ BigDecimal_mode(int argc, VALUE *argv, VALUE self)
523
565
  unsigned long f,fo;
524
566
 
525
567
  rb_scan_args(argc, argv, "11", &which, &val);
526
- Check_Type(which, T_FIXNUM);
527
- f = (unsigned long)FIX2INT(which);
568
+ f = (unsigned long)NUM2INT(which);
528
569
 
529
570
  if (f & VP_EXCEPTION_ALL) {
530
571
  /* Exception mode setting */
@@ -565,7 +606,7 @@ BigDecimal_mode(int argc, VALUE *argv, VALUE self)
565
606
  fo = VpSetRoundMode(sw);
566
607
  return INT2FIX(fo);
567
608
  }
568
- rb_raise(rb_eTypeError, "first argument for BigDecimal#mode invalid");
609
+ rb_raise(rb_eTypeError, "first argument for BigDecimal.mode invalid");
569
610
  return Qnil;
570
611
  }
571
612
 
@@ -591,13 +632,12 @@ GetAddSubPrec(Real *a, Real *b)
591
632
  }
592
633
 
593
634
  static SIGNED_VALUE
594
- GetPositiveInt(VALUE v)
635
+ GetPrecisionInt(VALUE v)
595
636
  {
596
637
  SIGNED_VALUE n;
597
- Check_Type(v, T_FIXNUM);
598
- n = FIX2INT(v);
638
+ n = NUM2INT(v);
599
639
  if (n < 0) {
600
- rb_raise(rb_eArgError, "argument must be positive");
640
+ rb_raise(rb_eArgError, "negative precision");
601
641
  }
602
642
  return n;
603
643
  }
@@ -605,17 +645,18 @@ GetPositiveInt(VALUE v)
605
645
  VP_EXPORT Real *
606
646
  VpNewRbClass(size_t mx, const char *str, VALUE klass)
607
647
  {
608
- Real *pv = VpAlloc(mx,str);
609
- pv->obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, pv);
648
+ VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
649
+ Real *pv = VpAlloc(mx, str, 1, 1);
650
+ RTYPEDDATA_DATA(obj) = pv;
651
+ pv->obj = obj;
652
+ RB_OBJ_FREEZE(obj);
610
653
  return pv;
611
654
  }
612
655
 
613
656
  VP_EXPORT Real *
614
657
  VpCreateRbObject(size_t mx, const char *str)
615
658
  {
616
- Real *pv = VpAlloc(mx,str);
617
- pv->obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, pv);
618
- return pv;
659
+ return VpNewRbClass(mx, str, rb_cBigDecimal);
619
660
  }
620
661
 
621
662
  #define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(BDIGIT))
@@ -684,9 +725,9 @@ BigDecimal_check_num(Real *p)
684
725
 
685
726
  static VALUE BigDecimal_split(VALUE self);
686
727
 
687
- /* Returns the value as an integer (Fixnum or Bignum).
728
+ /* Returns the value as an Integer.
688
729
  *
689
- * If the BigNumber is infinity or NaN, raises FloatDomainError.
730
+ * If the BigDecimal is infinity or NaN, raises FloatDomainError.
690
731
  */
691
732
  static VALUE
692
733
  BigDecimal_to_i(VALUE self)
@@ -706,12 +747,12 @@ BigDecimal_to_i(VALUE self)
706
747
  }
707
748
  else {
708
749
  VALUE a = BigDecimal_split(self);
709
- VALUE digits = RARRAY_PTR(a)[1];
750
+ VALUE digits = RARRAY_AREF(a, 1);
710
751
  VALUE numerator = rb_funcall(digits, rb_intern("to_i"), 0);
711
752
  VALUE ret;
712
753
  ssize_t dpower = e - (ssize_t)RSTRING_LEN(digits);
713
754
 
714
- if (VpGetSign(p) < 0) {
755
+ if (BIGDECIMAL_NEGATIVE_P(p)) {
715
756
  numerator = rb_funcall(numerator, '*', 1, INT2FIX(-1));
716
757
  }
717
758
  if (dpower < 0) {
@@ -766,17 +807,17 @@ BigDecimal_to_f(VALUE self)
766
807
 
767
808
  overflow:
768
809
  VpException(VP_EXCEPTION_OVERFLOW, "BigDecimal to Float conversion", 0);
769
- if (p->sign >= 0)
770
- return rb_float_new(VpGetDoublePosInf());
771
- else
810
+ if (BIGDECIMAL_NEGATIVE_P(p))
772
811
  return rb_float_new(VpGetDoubleNegInf());
812
+ else
813
+ return rb_float_new(VpGetDoublePosInf());
773
814
 
774
815
  underflow:
775
816
  VpException(VP_EXCEPTION_UNDERFLOW, "BigDecimal to Float conversion", 0);
776
- if (p->sign >= 0)
777
- return rb_float_new(0.0);
778
- else
817
+ if (BIGDECIMAL_NEGATIVE_P(p))
779
818
  return rb_float_new(-0.0);
819
+ else
820
+ return rb_float_new(0.0);
780
821
  }
781
822
 
782
823
 
@@ -795,7 +836,7 @@ BigDecimal_to_r(VALUE self)
795
836
  sign = VpGetSign(p);
796
837
  power = VpExponent10(p);
797
838
  a = BigDecimal_split(self);
798
- digits = RARRAY_PTR(a)[1];
839
+ digits = RARRAY_AREF(a, 1);
799
840
  denomi_power = power - RSTRING_LEN(digits);
800
841
  numerator = rb_funcall(digits, rb_intern("to_i"), 0);
801
842
 
@@ -822,7 +863,7 @@ BigDecimal_to_r(VALUE self)
822
863
  * be coerced into a BigDecimal value.
823
864
  *
824
865
  * e.g.
825
- * a = BigDecimal.new("1.0")
866
+ * a = BigDecimal("1.0")
826
867
  * b = a / 2.0 #=> 0.5
827
868
  *
828
869
  * Note that coercing a String to a BigDecimal is not supported by default;
@@ -854,13 +895,14 @@ BigDecimal_coerce(VALUE self, VALUE other)
854
895
  }
855
896
 
856
897
  /*
857
- * call-seq: +@
898
+ * call-seq:
899
+ * +big_decimal -> big_decimal
858
900
  *
859
901
  * Return self.
860
902
  *
861
- * e.g.
862
- * b = +a # b == a
903
+ * +BigDecimal('5') #=> 0.5e1
863
904
  */
905
+
864
906
  static VALUE
865
907
  BigDecimal_uplus(VALUE self)
866
908
  {
@@ -1110,7 +1152,7 @@ BigDecimal_comp(VALUE self, VALUE r)
1110
1152
  *
1111
1153
  * Values may be coerced to perform the comparison:
1112
1154
  *
1113
- * BigDecimal.new('1.0') == 1.0 -> true
1155
+ * BigDecimal('1.0') == 1.0 #=> true
1114
1156
  */
1115
1157
  static VALUE
1116
1158
  BigDecimal_eq(VALUE self, VALUE r)
@@ -1171,14 +1213,14 @@ BigDecimal_ge(VALUE self, VALUE r)
1171
1213
  }
1172
1214
 
1173
1215
  /*
1174
- * call-seq: -@
1216
+ * call-seq:
1217
+ * -big_decimal -> big_decimal
1175
1218
  *
1176
- * Return the negation of self.
1219
+ * Return the negation of self.
1177
1220
  *
1178
- * e.g.
1179
- * b = -a
1180
- * b == a * -1
1221
+ * -BigDecimal('5') #=> -0.5e1
1181
1222
  */
1223
+
1182
1224
  static VALUE
1183
1225
  BigDecimal_neg(VALUE self)
1184
1226
  {
@@ -1266,25 +1308,14 @@ BigDecimal_divide(Real **c, Real **res, Real **div, VALUE self, VALUE r)
1266
1308
  return Qnil;
1267
1309
  }
1268
1310
 
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
- */
1311
+ /* call-seq:
1312
+ * a / b -> bigdecimal
1313
+ * quo(value) -> bigdecimal
1314
+ *
1315
+ * Divide by the specified value.
1316
+ *
1317
+ * See BigDecimal#div.
1318
+ */
1288
1319
  static VALUE
1289
1320
  BigDecimal_div(VALUE self, VALUE r)
1290
1321
  /* For c = self/r: with round operation */
@@ -1483,8 +1514,8 @@ BigDecimal_remainder(VALUE self, VALUE r) /* remainder */
1483
1514
  *
1484
1515
  * require 'bigdecimal'
1485
1516
  *
1486
- * a = BigDecimal.new("42")
1487
- * b = BigDecimal.new("9")
1517
+ * a = BigDecimal("42")
1518
+ * b = BigDecimal("9")
1488
1519
  *
1489
1520
  * q, m = a.divmod(b)
1490
1521
  *
@@ -1527,7 +1558,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
1527
1558
  }
1528
1559
 
1529
1560
  /* div in BigDecimal sense */
1530
- ix = GetPositiveInt(n);
1561
+ ix = GetPrecisionInt(n);
1531
1562
  if (ix == 0) {
1532
1563
  return BigDecimal_div(self, b);
1533
1564
  }
@@ -1537,7 +1568,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
1537
1568
  size_t mx = ix + VpBaseFig()*2;
1538
1569
  size_t pl = VpSetPrecLimit(0);
1539
1570
 
1540
- GUARD_OBJ(cv, VpCreateRbObject(mx, "0"));
1571
+ GUARD_OBJ(cv, VpCreateRbObject(mx + VpBaseFig(), "0"));
1541
1572
  GUARD_OBJ(av, GetVpValue(self, 1));
1542
1573
  GUARD_OBJ(bv, GetVpValue(b, 1));
1543
1574
  mx = av->Prec + bv->Prec + 2;
@@ -1550,6 +1581,37 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
1550
1581
  }
1551
1582
  }
1552
1583
 
1584
+ /*
1585
+ * Document-method: BigDecimal#div
1586
+ *
1587
+ * call-seq:
1588
+ * div(value, digits) -> bigdecimal or integer
1589
+ *
1590
+ * Divide by the specified value.
1591
+ *
1592
+ * digits:: If specified and less than the number of significant digits of the
1593
+ * result, the result is rounded to that number of digits, according
1594
+ * to BigDecimal.mode.
1595
+ *
1596
+ * If digits is 0, the result is the same as for the / operator
1597
+ * or #quo.
1598
+ *
1599
+ * If digits is not specified, the result is an integer,
1600
+ * by analogy with Float#div; see also BigDecimal#divmod.
1601
+ *
1602
+ * Examples:
1603
+ *
1604
+ * a = BigDecimal("4")
1605
+ * b = BigDecimal("3")
1606
+ *
1607
+ * a.div(b, 3) # => 0.133e1
1608
+ *
1609
+ * a.div(b, 0) # => 0.1333333333333333333e1
1610
+ * a / b # => 0.1333333333333333333e1
1611
+ * a.quo(b) # => 0.1333333333333333333e1
1612
+ *
1613
+ * a.div(b) # => 1
1614
+ */
1553
1615
  static VALUE
1554
1616
  BigDecimal_div3(int argc, VALUE *argv, VALUE self)
1555
1617
  {
@@ -1565,7 +1627,7 @@ BigDecimal_add2(VALUE self, VALUE b, VALUE n)
1565
1627
  {
1566
1628
  ENTER(2);
1567
1629
  Real *cv;
1568
- SIGNED_VALUE mx = GetPositiveInt(n);
1630
+ SIGNED_VALUE mx = GetPrecisionInt(n);
1569
1631
  if (mx == 0) return BigDecimal_add(self, b);
1570
1632
  else {
1571
1633
  size_t pl = VpSetPrecLimit(0);
@@ -1595,7 +1657,7 @@ BigDecimal_sub2(VALUE self, VALUE b, VALUE n)
1595
1657
  {
1596
1658
  ENTER(2);
1597
1659
  Real *cv;
1598
- SIGNED_VALUE mx = GetPositiveInt(n);
1660
+ SIGNED_VALUE mx = GetPrecisionInt(n);
1599
1661
  if (mx == 0) return BigDecimal_sub(self, b);
1600
1662
  else {
1601
1663
  size_t pl = VpSetPrecLimit(0);
@@ -1613,7 +1675,7 @@ BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
1613
1675
  {
1614
1676
  ENTER(2);
1615
1677
  Real *cv;
1616
- SIGNED_VALUE mx = GetPositiveInt(n);
1678
+ SIGNED_VALUE mx = GetPrecisionInt(n);
1617
1679
  if (mx == 0) return BigDecimal_mult(self, b);
1618
1680
  else {
1619
1681
  size_t pl = VpSetPrecLimit(0);
@@ -1625,11 +1687,16 @@ BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
1625
1687
  }
1626
1688
  }
1627
1689
 
1628
- /* Returns the absolute value, as a BigDecimal.
1690
+ /*
1691
+ * call-seq:
1692
+ * big_decimal.abs -> big_decimal
1629
1693
  *
1630
- * BigDecimal('5').abs #=> 5
1631
- * BigDecimal('-3').abs #=> 3
1694
+ * Returns the absolute value, as a BigDecimal.
1695
+ *
1696
+ * BigDecimal('5').abs #=> 0.5e1
1697
+ * BigDecimal('-3').abs #=> 0.3e1
1632
1698
  */
1699
+
1633
1700
  static VALUE
1634
1701
  BigDecimal_abs(VALUE self)
1635
1702
  {
@@ -1662,7 +1729,7 @@ BigDecimal_sqrt(VALUE self, VALUE nFig)
1662
1729
  GUARD_OBJ(a, GetVpValue(self, 1));
1663
1730
  mx = a->Prec * (VpBaseFig() + 1);
1664
1731
 
1665
- n = GetPositiveInt(nFig) + VpDblFig() + BASE_FIG;
1732
+ n = GetPrecisionInt(nFig) + VpDblFig() + BASE_FIG;
1666
1733
  if (mx <= n) mx = n;
1667
1734
  GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
1668
1735
  VpSqrt(c, a);
@@ -1724,13 +1791,21 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
1724
1791
  iLoc = 0;
1725
1792
  break;
1726
1793
  case 1:
1727
- Check_Type(vLoc, T_FIXNUM);
1728
- iLoc = FIX2INT(vLoc);
1794
+ if (RB_TYPE_P(vLoc, T_HASH)) {
1795
+ sw = check_rounding_mode_option(vLoc);
1796
+ }
1797
+ else {
1798
+ iLoc = NUM2INT(vLoc);
1799
+ }
1729
1800
  break;
1730
1801
  case 2:
1731
- Check_Type(vLoc, T_FIXNUM);
1732
- iLoc = FIX2INT(vLoc);
1733
- sw = check_rounding_mode(vRound);
1802
+ iLoc = NUM2INT(vLoc);
1803
+ if (RB_TYPE_P(vRound, T_HASH)) {
1804
+ sw = check_rounding_mode_option(vRound);
1805
+ }
1806
+ else {
1807
+ sw = check_rounding_mode(vRound);
1808
+ }
1734
1809
  break;
1735
1810
  default:
1736
1811
  break;
@@ -1780,8 +1855,7 @@ BigDecimal_truncate(int argc, VALUE *argv, VALUE self)
1780
1855
  iLoc = 0;
1781
1856
  }
1782
1857
  else {
1783
- Check_Type(vLoc, T_FIXNUM);
1784
- iLoc = FIX2INT(vLoc);
1858
+ iLoc = NUM2INT(vLoc);
1785
1859
  }
1786
1860
 
1787
1861
  GUARD_OBJ(a, GetVpValue(self, 1));
@@ -1841,8 +1915,7 @@ BigDecimal_floor(int argc, VALUE *argv, VALUE self)
1841
1915
  iLoc = 0;
1842
1916
  }
1843
1917
  else {
1844
- Check_Type(vLoc, T_FIXNUM);
1845
- iLoc = FIX2INT(vLoc);
1918
+ iLoc = NUM2INT(vLoc);
1846
1919
  }
1847
1920
 
1848
1921
  GUARD_OBJ(a, GetVpValue(self, 1));
@@ -1888,8 +1961,7 @@ BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
1888
1961
  if (rb_scan_args(argc, argv, "01", &vLoc) == 0) {
1889
1962
  iLoc = 0;
1890
1963
  } else {
1891
- Check_Type(vLoc, T_FIXNUM);
1892
- iLoc = FIX2INT(vLoc);
1964
+ iLoc = NUM2INT(vLoc);
1893
1965
  }
1894
1966
 
1895
1967
  GUARD_OBJ(a, GetVpValue(self, 1));
@@ -1927,34 +1999,35 @@ BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
1927
1999
  *
1928
2000
  * Examples:
1929
2001
  *
1930
- * BigDecimal.new('-123.45678901234567890').to_s('5F')
2002
+ * BigDecimal('-123.45678901234567890').to_s('5F')
1931
2003
  * #=> '-123.45678 90123 45678 9'
1932
2004
  *
1933
- * BigDecimal.new('123.45678901234567890').to_s('+8F')
2005
+ * BigDecimal('123.45678901234567890').to_s('+8F')
1934
2006
  * #=> '+123.45678901 23456789'
1935
2007
  *
1936
- * BigDecimal.new('123.45678901234567890').to_s(' F')
2008
+ * BigDecimal('123.45678901234567890').to_s(' F')
1937
2009
  * #=> ' 123.4567890123456789'
1938
2010
  */
1939
2011
  static VALUE
1940
2012
  BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
1941
2013
  {
1942
2014
  ENTER(5);
1943
- int fmt = 0; /* 0:E format */
1944
- int fPlus = 0; /* =0:default,=1: set ' ' before digits ,set '+' before digits. */
2015
+ int fmt = 0; /* 0: E format, 1: F format */
2016
+ int fPlus = 0; /* 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
1945
2017
  Real *vp;
1946
2018
  volatile VALUE str;
1947
2019
  char *psz;
1948
2020
  char ch;
1949
2021
  size_t nc, mc = 0;
2022
+ SIGNED_VALUE m;
1950
2023
  VALUE f;
1951
2024
 
1952
2025
  GUARD_OBJ(vp, GetVpValue(self, 1));
1953
2026
 
1954
2027
  if (rb_scan_args(argc, argv, "01", &f) == 1) {
1955
2028
  if (RB_TYPE_P(f, T_STRING)) {
1956
- SafeStringValue(f);
1957
- psz = RSTRING_PTR(f);
2029
+ psz = StringValueCStr(f);
2030
+ rb_check_safe_obj(f);
1958
2031
  if (*psz == ' ') {
1959
2032
  fPlus = 1;
1960
2033
  psz++;
@@ -1977,7 +2050,11 @@ BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
1977
2050
  }
1978
2051
  }
1979
2052
  else {
1980
- mc = (size_t)GetPositiveInt(f);
2053
+ m = NUM2INT(f);
2054
+ if (m <= 0) {
2055
+ rb_raise(rb_eArgError, "argument must be positive");
2056
+ }
2057
+ mc = (size_t)m;
1981
2058
  }
1982
2059
  }
1983
2060
  if (fmt) {
@@ -2071,38 +2148,26 @@ BigDecimal_exponent(VALUE self)
2071
2148
  return INT2NUM(e);
2072
2149
  }
2073
2150
 
2074
- /* Returns debugging information about the value as a string of comma-separated
2075
- * values in angle brackets with a leading #:
2076
- *
2077
- * BigDecimal.new("1234.5678").inspect
2078
- * #=> "#<BigDecimal:b7ea1130,'0.12345678E4',8(12)>"
2151
+ /* Returns a string representation of self.
2079
2152
  *
2080
- * The first part is the address, the second is the value as a string, and
2081
- * the final part ss(mm) is the current number of significant digits and the
2082
- * maximum number of significant digits, respectively.
2153
+ * BigDecimal("1234.5678").inspect
2154
+ * #=> "0.12345678e4"
2083
2155
  */
2084
2156
  static VALUE
2085
2157
  BigDecimal_inspect(VALUE self)
2086
2158
  {
2087
2159
  ENTER(5);
2088
2160
  Real *vp;
2089
- volatile VALUE obj;
2161
+ volatile VALUE str;
2090
2162
  size_t nc;
2091
- char *psz, *tmp;
2092
2163
 
2093
2164
  GUARD_OBJ(vp, GetVpValue(self, 1));
2094
2165
  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;
2166
+
2167
+ str = rb_str_new(0, nc);
2168
+ VpToString(vp, RSTRING_PTR(str), 0, 0);
2169
+ rb_str_resize(str, strlen(RSTRING_PTR(str)));
2170
+ return str;
2106
2171
  }
2107
2172
 
2108
2173
  static VALUE BigMath_s_exp(VALUE, VALUE, VALUE);
@@ -2248,7 +2313,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2248
2313
  n = NIL_P(prec) ? (ssize_t)(x->Prec*VpBaseFig()) : NUM2SSIZET(prec);
2249
2314
 
2250
2315
  if (VpIsNaN(x)) {
2251
- y = VpCreateRbObject(n, "0#");
2316
+ y = VpCreateRbObject(n, "0");
2252
2317
  RB_GC_GUARD(y->obj);
2253
2318
  VpSetNaN(y);
2254
2319
  return ToValue(y);
@@ -2312,7 +2377,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2312
2377
  if (is_negative(vexp)) {
2313
2378
  y = VpCreateRbObject(n, "#0");
2314
2379
  RB_GC_GUARD(y->obj);
2315
- if (VpGetSign(x) < 0) {
2380
+ if (BIGDECIMAL_NEGATIVE_P(x)) {
2316
2381
  if (is_integer(vexp)) {
2317
2382
  if (is_even(vexp)) {
2318
2383
  /* (-0) ** (-even_integer) -> Infinity */
@@ -2351,7 +2416,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2351
2416
 
2352
2417
  if (VpIsInf(x)) {
2353
2418
  if (is_negative(vexp)) {
2354
- if (VpGetSign(x) < 0) {
2419
+ if (BIGDECIMAL_NEGATIVE_P(x)) {
2355
2420
  if (is_integer(vexp)) {
2356
2421
  if (is_even(vexp)) {
2357
2422
  /* (-Infinity) ** (-even_integer) -> +0 */
@@ -2372,8 +2437,8 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2372
2437
  }
2373
2438
  }
2374
2439
  else {
2375
- y = VpCreateRbObject(n, "0#");
2376
- if (VpGetSign(x) < 0) {
2440
+ y = VpCreateRbObject(n, "0");
2441
+ if (BIGDECIMAL_NEGATIVE_P(x)) {
2377
2442
  if (is_integer(vexp)) {
2378
2443
  if (is_even(vexp)) {
2379
2444
  VpSetPosInf(y);
@@ -2405,7 +2470,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2405
2470
  }
2406
2471
  else if (RTEST(rb_funcall(abs_value, '<', 1, INT2FIX(1)))) {
2407
2472
  if (is_negative(vexp)) {
2408
- y = VpCreateRbObject(n, "0#");
2473
+ y = VpCreateRbObject(n, "0");
2409
2474
  if (is_even(vexp)) {
2410
2475
  VpSetInf(y, VpGetSign(x));
2411
2476
  }
@@ -2414,7 +2479,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2414
2479
  }
2415
2480
  return ToValue(y);
2416
2481
  }
2417
- else if (VpGetSign(x) < 0 && is_even(vexp)) {
2482
+ else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
2418
2483
  return ToValue(VpCreateRbObject(n, "-0"));
2419
2484
  }
2420
2485
  else {
@@ -2423,7 +2488,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2423
2488
  }
2424
2489
  else {
2425
2490
  if (is_positive(vexp)) {
2426
- y = VpCreateRbObject(n, "0#");
2491
+ y = VpCreateRbObject(n, "0");
2427
2492
  if (is_even(vexp)) {
2428
2493
  VpSetInf(y, VpGetSign(x));
2429
2494
  }
@@ -2432,7 +2497,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2432
2497
  }
2433
2498
  return ToValue(y);
2434
2499
  }
2435
- else if (VpGetSign(x) < 0 && is_even(vexp)) {
2500
+ else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
2436
2501
  return ToValue(VpCreateRbObject(n, "-0"));
2437
2502
  }
2438
2503
  else {
@@ -2473,93 +2538,82 @@ BigDecimal_power_op(VALUE self, VALUE exp)
2473
2538
  return BigDecimal_power(1, &exp, self);
2474
2539
  }
2475
2540
 
2476
- static VALUE
2477
- BigDecimal_s_allocate(VALUE klass)
2478
- {
2479
- return VpNewRbClass(0, NULL, klass)->obj;
2480
- }
2481
-
2482
- static Real *BigDecimal_new(int argc, VALUE *argv);
2483
-
2484
- /* call-seq:
2485
- * new(initial, digits)
2486
- *
2487
- * Create a new BigDecimal object.
2488
- *
2489
- * initial:: The initial value, as an Integer, a Float, a Rational,
2490
- * a BigDecimal, or a String.
2491
- *
2492
- * If it is a String, spaces are ignored and unrecognized characters
2493
- * terminate the value.
2494
- *
2495
- * digits:: The number of significant digits, as a Fixnum. If omitted or 0,
2496
- * the number of significant digits is determined from the initial
2497
- * value.
2498
- *
2499
- * The actual number of significant digits used in computation is usually
2500
- * larger than the specified number.
2501
- *
2502
- * ==== Exceptions
2503
- *
2504
- * TypeError:: If the +initial+ type is neither Fixnum, Bignum, Float,
2505
- * Rational, nor BigDecimal, this exception is raised.
2506
- *
2507
- * TypeError:: If the +digits+ is not a Fixnum, this exception is raised.
2508
- *
2509
- * ArgumentError:: If +initial+ is a Float, and the +digits+ is larger than
2510
- * Float::DIG + 1, this exception is raised.
2541
+ /* :nodoc:
2511
2542
  *
2512
- * ArgumentError:: If the +initial+ is a Float or Rational, and the +digits+
2513
- * value is omitted, this exception is raised.
2543
+ * private method for dup and clone the provided BigDecimal +other+
2514
2544
  */
2515
2545
  static VALUE
2516
- BigDecimal_initialize(int argc, VALUE *argv, VALUE self)
2546
+ BigDecimal_initialize_copy(VALUE self, VALUE other)
2517
2547
  {
2518
- ENTER(1);
2519
2548
  Real *pv = rb_check_typeddata(self, &BigDecimal_data_type);
2520
- Real *x;
2549
+ Real *x = rb_check_typeddata(other, &BigDecimal_data_type);
2521
2550
 
2522
- GUARD_OBJ(x, BigDecimal_new(argc, argv));
2523
- if (ToValue(x)) {
2524
- pv = VpCopy(pv, x);
2525
- }
2526
- else {
2527
- VpFree(pv);
2528
- pv = x;
2551
+ if (self != other) {
2552
+ DATA_PTR(self) = VpCopy(pv, x);
2529
2553
  }
2530
- DATA_PTR(self) = pv;
2531
- pv->obj = self;
2532
2554
  return self;
2533
2555
  }
2534
2556
 
2535
- /* :nodoc:
2536
- *
2537
- * private method to dup and clone the provided BigDecimal +other+
2538
- */
2539
2557
  static VALUE
2540
- BigDecimal_initialize_copy(VALUE self, VALUE other)
2558
+ BigDecimal_clone(VALUE self)
2541
2559
  {
2542
- Real *pv = rb_check_typeddata(self, &BigDecimal_data_type);
2543
- Real *x = rb_check_typeddata(other, &BigDecimal_data_type);
2560
+ return self;
2561
+ }
2544
2562
 
2545
- if (self != other) {
2546
- DATA_PTR(self) = VpCopy(pv, x);
2563
+ static int
2564
+ opts_exception_p(VALUE opts)
2565
+ {
2566
+ static ID kwds[1];
2567
+ VALUE exception;
2568
+ if (!kwds[0]) {
2569
+ kwds[0] = rb_intern_const("exception");
2547
2570
  }
2548
- return self;
2571
+ rb_get_kwargs(opts, kwds, 0, 1, &exception);
2572
+ return exception != Qfalse;
2549
2573
  }
2550
2574
 
2551
2575
  static Real *
2552
- BigDecimal_new(int argc, VALUE *argv)
2576
+ VpNewVarArgs(int argc, VALUE *argv)
2553
2577
  {
2554
2578
  size_t mf;
2579
+ VALUE opts = Qnil;
2555
2580
  VALUE nFig;
2556
2581
  VALUE iniValue;
2582
+ double d;
2583
+ int exc;
2584
+
2585
+ argc = rb_scan_args(argc, argv, "11:", &iniValue, &nFig, &opts);
2586
+ exc = opts_exception_p(opts);
2557
2587
 
2558
- if (rb_scan_args(argc, argv, "11", &iniValue, &nFig) == 1) {
2588
+ if (argc == 1) {
2559
2589
  mf = 0;
2560
2590
  }
2561
2591
  else {
2562
- mf = GetPositiveInt(nFig);
2592
+ /* expand GetPrecisionInt for exception suppression */
2593
+ ssize_t n = NUM2INT(nFig);
2594
+ if (n < 0) {
2595
+ if (!exc) {
2596
+ return NULL;
2597
+ }
2598
+ rb_raise(rb_eArgError, "negative precision");
2599
+ }
2600
+ mf = (size_t)n;
2601
+ }
2602
+
2603
+ if (SPECIAL_CONST_P(iniValue)) {
2604
+ switch (iniValue) {
2605
+ case Qnil:
2606
+ if (!exc) return NULL;
2607
+ rb_raise(rb_eTypeError, "can't convert nil into BigDecimal");
2608
+ case Qtrue:
2609
+ if (!exc) return NULL;
2610
+ rb_raise(rb_eTypeError, "can't convert true into BigDecimal");
2611
+ case Qfalse:
2612
+ if (!exc) return NULL;
2613
+ rb_raise(rb_eTypeError, "can't convert false into BigDecimal");
2614
+ default:
2615
+ break;
2616
+ }
2563
2617
  }
2564
2618
 
2565
2619
  switch (TYPE(iniValue)) {
@@ -2575,12 +2629,24 @@ BigDecimal_new(int argc, VALUE *argv)
2575
2629
  return GetVpValue(iniValue, 1);
2576
2630
 
2577
2631
  case T_FLOAT:
2632
+ d = RFLOAT_VALUE(iniValue);
2633
+ if (!isfinite(d)) {
2634
+ Real *pv = VpCreateRbObject(1, NULL);
2635
+ VpDtoV(pv, d);
2636
+ return pv;
2637
+ }
2578
2638
  if (mf > DBL_DIG+1) {
2639
+ if (!exc) {
2640
+ return NULL;
2641
+ }
2579
2642
  rb_raise(rb_eArgError, "precision too large.");
2580
2643
  }
2581
2644
  /* fall through */
2582
2645
  case T_RATIONAL:
2583
2646
  if (NIL_P(nFig)) {
2647
+ if (!exc) {
2648
+ return NULL;
2649
+ }
2584
2650
  rb_raise(rb_eArgError,
2585
2651
  "can't omit precision for a %"PRIsVALUE".",
2586
2652
  RB_OBJ_CLASSNAME(iniValue));
@@ -2592,21 +2658,79 @@ BigDecimal_new(int argc, VALUE *argv)
2592
2658
  default:
2593
2659
  break;
2594
2660
  }
2661
+ /* TODO: support to_d */
2662
+ if (!exc) {
2663
+ iniValue = rb_check_convert_type(iniValue, T_STRING, "String", "to_str");
2664
+ if (NIL_P(iniValue)) return NULL;
2665
+ }
2595
2666
  StringValueCStr(iniValue);
2596
- return VpAlloc(mf, RSTRING_PTR(iniValue));
2667
+ return VpAlloc(mf, RSTRING_PTR(iniValue), 1, exc);
2597
2668
  }
2598
2669
 
2599
- /* See also BigDecimal.new */
2600
2670
  static VALUE
2601
- BigDecimal_global_new(int argc, VALUE *argv, VALUE self)
2671
+ BigDecimal_new(int argc, VALUE *argv, VALUE klass)
2602
2672
  {
2603
2673
  ENTER(1);
2604
2674
  Real *pv;
2675
+ VALUE obj;
2605
2676
 
2606
- GUARD_OBJ(pv, BigDecimal_new(argc, argv));
2677
+ obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
2678
+ pv = VpNewVarArgs(argc, argv);
2679
+ if (pv == NULL) return Qnil;
2680
+ SAVE(pv);
2607
2681
  if (ToValue(pv)) pv = VpCopy(NULL, pv);
2608
- pv->obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, pv);
2609
- return pv->obj;
2682
+ RTYPEDDATA_DATA(obj) = pv;
2683
+ RB_OBJ_FREEZE(obj);
2684
+ return pv->obj = obj;
2685
+ }
2686
+
2687
+ /* call-seq:
2688
+ * BigDecimal(initial, digits, exception: true)
2689
+ *
2690
+ * Create a new BigDecimal object.
2691
+ *
2692
+ * initial:: The initial value, as an Integer, a Float, a Rational,
2693
+ * a BigDecimal, or a String.
2694
+ *
2695
+ * If it is a String, spaces are ignored and unrecognized characters
2696
+ * terminate the value.
2697
+ *
2698
+ * digits:: The number of significant digits, as an Integer. If omitted or 0,
2699
+ * the number of significant digits is determined from the initial
2700
+ * value.
2701
+ *
2702
+ * The actual number of significant digits used in computation is
2703
+ * usually larger than the specified number.
2704
+ *
2705
+ * exception:: Whether an exception should be raised on invalid arguments.
2706
+ * +true+ by default, if passed +false+, just returns +nil+
2707
+ * for invalid.
2708
+ *
2709
+ *
2710
+ * ==== Exceptions
2711
+ *
2712
+ * TypeError:: If the +initial+ type is neither Integer, Float,
2713
+ * Rational, nor BigDecimal, this exception is raised.
2714
+ *
2715
+ * TypeError:: If the +digits+ is not an Integer, this exception is raised.
2716
+ *
2717
+ * ArgumentError:: If +initial+ is a Float, and the +digits+ is larger than
2718
+ * Float::DIG + 1, this exception is raised.
2719
+ *
2720
+ * ArgumentError:: If the +initial+ is a Float or Rational, and the +digits+
2721
+ * value is omitted, this exception is raised.
2722
+ */
2723
+ static VALUE
2724
+ f_BigDecimal(int argc, VALUE *argv, VALUE self)
2725
+ {
2726
+ return BigDecimal_new(argc, argv, rb_cBigDecimal);
2727
+ }
2728
+
2729
+ /* DEPRECATED: BigDecimal.new() */
2730
+ static VALUE
2731
+ BigDecimal_s_new(int argc, VALUE *argv, VALUE klass)
2732
+ {
2733
+ return BigDecimal_new(argc, argv, klass);
2610
2734
  }
2611
2735
 
2612
2736
  /* call-seq:
@@ -2630,8 +2754,7 @@ BigDecimal_limit(int argc, VALUE *argv, VALUE self)
2630
2754
  if (rb_scan_args(argc, argv, "01", &nFig) == 1) {
2631
2755
  int nf;
2632
2756
  if (NIL_P(nFig)) return nCur;
2633
- Check_Type(nFig, T_FIXNUM);
2634
- nf = FIX2INT(nFig);
2757
+ nf = NUM2INT(nFig);
2635
2758
  if (nf < 0) {
2636
2759
  rb_raise(rb_eArgError, "argument must be positive");
2637
2760
  }
@@ -2672,9 +2795,9 @@ BigDecimal_sign(VALUE self)
2672
2795
  * BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
2673
2796
  * BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
2674
2797
  *
2675
- * BigDecimal.new(BigDecimal('Infinity'))
2676
- * BigDecimal.new(BigDecimal('-Infinity'))
2677
- * BigDecimal(BigDecimal.new('NaN'))
2798
+ * BigDecimal(BigDecimal('Infinity'))
2799
+ * BigDecimal(BigDecimal('-Infinity'))
2800
+ * BigDecimal(BigDecimal('NaN'))
2678
2801
  * end
2679
2802
  *
2680
2803
  * For use with the BigDecimal::EXCEPTION_*
@@ -2768,13 +2891,13 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
2768
2891
  rb_raise(rb_eArgError, "Zero or negative precision for exp");
2769
2892
  }
2770
2893
 
2771
- /* TODO: the following switch statement is almostly the same as one in the
2894
+ /* TODO: the following switch statement is almost same as one in the
2772
2895
  * BigDecimalCmp function. */
2773
2896
  switch (TYPE(x)) {
2774
2897
  case T_DATA:
2775
2898
  if (!is_kind_of_BigDecimal(x)) break;
2776
2899
  vx = DATA_PTR(x);
2777
- negative = VpGetSign(vx) < 0;
2900
+ negative = BIGDECIMAL_NEGATIVE_P(vx);
2778
2901
  infinite = VpIsPosInf(vx) || VpIsNegInf(vx);
2779
2902
  nan = VpIsNaN(vx);
2780
2903
  break;
@@ -2827,7 +2950,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
2827
2950
  x = vx->obj;
2828
2951
 
2829
2952
  n = prec + rmpd_double_figures();
2830
- negative = VpGetSign(vx) < 0;
2953
+ negative = BIGDECIMAL_NEGATIVE_P(vx);
2831
2954
  if (negative) {
2832
2955
  VpSetSign(vx, 1);
2833
2956
  }
@@ -2906,14 +3029,14 @@ BigMath_s_log(VALUE klass, VALUE x, VALUE vprec)
2906
3029
  rb_raise(rb_eArgError, "Zero or negative precision for exp");
2907
3030
  }
2908
3031
 
2909
- /* TODO: the following switch statement is almostly the same as one in the
3032
+ /* TODO: the following switch statement is almost same as one in the
2910
3033
  * BigDecimalCmp function. */
2911
3034
  switch (TYPE(x)) {
2912
3035
  case T_DATA:
2913
3036
  if (!is_kind_of_BigDecimal(x)) break;
2914
3037
  vx = DATA_PTR(x);
2915
3038
  zero = VpIsZero(vx);
2916
- negative = VpGetSign(vx) < 0;
3039
+ negative = BIGDECIMAL_NEGATIVE_P(vx);
2917
3040
  infinite = VpIsPosInf(vx) || VpIsNegInf(vx);
2918
3041
  nan = VpIsNaN(vx);
2919
3042
  break;
@@ -3030,6 +3153,20 @@ get_vp_value:
3030
3153
  return y;
3031
3154
  }
3032
3155
 
3156
+ VALUE
3157
+ rmpd_util_str_to_d(VALUE str)
3158
+ {
3159
+ ENTER(1);
3160
+ char const *c_str;
3161
+ Real *pv;
3162
+
3163
+ c_str = StringValueCStr(str);
3164
+ GUARD_OBJ(pv, VpAlloc(0, c_str, 0, 1));
3165
+ pv->obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, pv);
3166
+ RB_OBJ_FREEZE(pv->obj);
3167
+ return pv->obj;
3168
+ }
3169
+
3033
3170
  /* Document-class: BigDecimal
3034
3171
  * BigDecimal provides arbitrary-precision floating point decimal arithmetic.
3035
3172
  *
@@ -3061,15 +3198,15 @@ get_vp_value:
3061
3198
  *
3062
3199
  * require 'bigdecimal'
3063
3200
  *
3064
- * sum = BigDecimal.new("0")
3201
+ * sum = BigDecimal("0")
3065
3202
  * 10_000.times do
3066
- * sum = sum + BigDecimal.new("0.0001")
3203
+ * sum = sum + BigDecimal("0.0001")
3067
3204
  * end
3068
3205
  * print sum #=> 0.1E1
3069
3206
  *
3070
3207
  * Similarly:
3071
3208
  *
3072
- * (BigDecimal.new("1.2") - BigDecimal("1.0")) == BigDecimal("0.2") #=> true
3209
+ * (BigDecimal("1.2") - BigDecimal("1.0")) == BigDecimal("0.2") #=> true
3073
3210
  *
3074
3211
  * (1.2 - 1.0) == 0.2 #=> false
3075
3212
  *
@@ -3083,8 +3220,8 @@ get_vp_value:
3083
3220
  * BigDecimal sometimes needs to return infinity, for example if you divide
3084
3221
  * a value by zero.
3085
3222
  *
3086
- * BigDecimal.new("1.0") / BigDecimal.new("0.0") #=> Infinity
3087
- * BigDecimal.new("-1.0") / BigDecimal.new("0.0") #=> -Infinity
3223
+ * BigDecimal("1.0") / BigDecimal("0.0") #=> Infinity
3224
+ * BigDecimal("-1.0") / BigDecimal("0.0") #=> -Infinity
3088
3225
  *
3089
3226
  * You can represent infinite numbers to BigDecimal using the strings
3090
3227
  * <code>'Infinity'</code>, <code>'+Infinity'</code> and
@@ -3097,13 +3234,13 @@ get_vp_value:
3097
3234
  *
3098
3235
  * Example:
3099
3236
  *
3100
- * BigDecimal.new("0.0") / BigDecimal.new("0.0") #=> NaN
3237
+ * BigDecimal("0.0") / BigDecimal("0.0") #=> NaN
3101
3238
  *
3102
3239
  * You can also create undefined values.
3103
3240
  *
3104
3241
  * NaN is never considered to be the same as any other value, even NaN itself:
3105
3242
  *
3106
- * n = BigDecimal.new('NaN')
3243
+ * n = BigDecimal('NaN')
3107
3244
  * n == 0.0 #=> false
3108
3245
  * n == n #=> false
3109
3246
  *
@@ -3116,11 +3253,11 @@ get_vp_value:
3116
3253
  * If the value which is too small to be represented is negative, a BigDecimal
3117
3254
  * value of negative zero is returned.
3118
3255
  *
3119
- * BigDecimal.new("1.0") / BigDecimal.new("-Infinity") #=> -0.0
3256
+ * BigDecimal("1.0") / BigDecimal("-Infinity") #=> -0.0
3120
3257
  *
3121
3258
  * If the value is positive, a value of positive zero is returned.
3122
3259
  *
3123
- * BigDecimal.new("1.0") / BigDecimal.new("Infinity") #=> 0.0
3260
+ * BigDecimal("1.0") / BigDecimal("Infinity") #=> 0.0
3124
3261
  *
3125
3262
  * (See BigDecimal.mode for how to specify limits of precision.)
3126
3263
  *
@@ -3130,13 +3267,25 @@ get_vp_value:
3130
3267
  * Note also that in mathematics, there is no particular concept of negative
3131
3268
  * or positive zero; true mathematical zero has no sign.
3132
3269
  *
3270
+ * == bigdecimal/util
3271
+ *
3272
+ * When you require +bigdecimal/util+, the #to_d method will be
3273
+ * available on BigDecimal and the native Integer, Float, Rational,
3274
+ * and String classes:
3275
+ *
3276
+ * require 'bigdecimal/util'
3277
+ *
3278
+ * 42.to_d # => 0.42e2
3279
+ * 0.5.to_d # => 0.5e0
3280
+ * (2/3r).to_d(3) # => 0.667e0
3281
+ * "0.5".to_d # => 0.5e0
3282
+ *
3133
3283
  * == License
3134
3284
  *
3135
3285
  * Copyright (C) 2002 by Shigeo Kobayashi <shigeo@tinyforest.gr.jp>.
3136
3286
  *
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.
3287
+ * BigDecimal is released under the Ruby and 2-clause BSD licenses.
3288
+ * See LICENSE.txt for details.
3140
3289
  *
3141
3290
  * Maintained by mrkn <mrkn@mrkn.jp> and ruby-core members.
3142
3291
  *
@@ -3157,17 +3306,17 @@ Init_bigdecimal(void)
3157
3306
 
3158
3307
  /* Class and method registration */
3159
3308
  rb_cBigDecimal = rb_define_class("BigDecimal", rb_cNumeric);
3160
- rb_define_alloc_func(rb_cBigDecimal, BigDecimal_s_allocate);
3161
3309
 
3162
3310
  /* Global function */
3163
- rb_define_global_function("BigDecimal", BigDecimal_global_new, -1);
3311
+ rb_define_global_function("BigDecimal", f_BigDecimal, -1);
3164
3312
 
3165
3313
  /* Class methods */
3314
+ rb_undef_method(CLASS_OF(rb_cBigDecimal), "allocate");
3315
+ rb_define_singleton_method(rb_cBigDecimal, "new", BigDecimal_s_new, -1);
3166
3316
  rb_define_singleton_method(rb_cBigDecimal, "mode", BigDecimal_mode, -1);
3167
3317
  rb_define_singleton_method(rb_cBigDecimal, "limit", BigDecimal_limit, -1);
3168
3318
  rb_define_singleton_method(rb_cBigDecimal, "double_fig", BigDecimal_double_fig, 0);
3169
3319
  rb_define_singleton_method(rb_cBigDecimal, "_load", BigDecimal_load, 1);
3170
- rb_define_singleton_method(rb_cBigDecimal, "ver", BigDecimal_version, 0);
3171
3320
 
3172
3321
  rb_define_singleton_method(rb_cBigDecimal, "save_exception_mode", BigDecimal_save_exception_mode, 0);
3173
3322
  rb_define_singleton_method(rb_cBigDecimal, "save_rounding_mode", BigDecimal_save_rounding_mode, 0);
@@ -3175,6 +3324,14 @@ Init_bigdecimal(void)
3175
3324
 
3176
3325
  /* Constants definition */
3177
3326
 
3327
+ #ifndef RUBY_BIGDECIMAL_VERSION
3328
+ # error RUBY_BIGDECIMAL_VERSION is not defined
3329
+ #endif
3330
+ /*
3331
+ * The version of bigdecimal library
3332
+ */
3333
+ rb_define_const(rb_cBigDecimal, "VERSION", rb_str_new2(RUBY_BIGDECIMAL_VERSION));
3334
+
3178
3335
  /*
3179
3336
  * Base value used in internal calculations. On a 32 bit system, BASE
3180
3337
  * is 10000, indicating that calculation is done in groups of 4 digits.
@@ -3217,7 +3374,7 @@ Init_bigdecimal(void)
3217
3374
  rb_define_const(rb_cBigDecimal, "EXCEPTION_OVERFLOW", INT2FIX(VP_EXCEPTION_OVERFLOW));
3218
3375
 
3219
3376
  /*
3220
- * 0x01: Determines what happens when a division by zero is performed.
3377
+ * 0x10: Determines what happens when a division by zero is performed.
3221
3378
  * See BigDecimal.mode.
3222
3379
  */
3223
3380
  rb_define_const(rb_cBigDecimal, "EXCEPTION_ZERODIVIDE", INT2FIX(VP_EXCEPTION_ZERODIVIDE));
@@ -3279,14 +3436,13 @@ Init_bigdecimal(void)
3279
3436
 
3280
3437
  arg = rb_str_new2("+Infinity");
3281
3438
  /* Positive infinity value. */
3282
- rb_define_const(rb_cBigDecimal, "INFINITY", BigDecimal_global_new(1, &arg, rb_cBigDecimal));
3439
+ rb_define_const(rb_cBigDecimal, "INFINITY", f_BigDecimal(1, &arg, rb_cBigDecimal));
3283
3440
  arg = rb_str_new2("NaN");
3284
3441
  /* 'Not a Number' value. */
3285
- rb_define_const(rb_cBigDecimal, "NAN", BigDecimal_global_new(1, &arg, rb_cBigDecimal));
3442
+ rb_define_const(rb_cBigDecimal, "NAN", f_BigDecimal(1, &arg, rb_cBigDecimal));
3286
3443
 
3287
3444
 
3288
3445
  /* instance methods */
3289
- rb_define_method(rb_cBigDecimal, "initialize", BigDecimal_initialize, -1);
3290
3446
  rb_define_method(rb_cBigDecimal, "initialize_copy", BigDecimal_initialize_copy, 1);
3291
3447
  rb_define_method(rb_cBigDecimal, "precs", BigDecimal_prec, 0);
3292
3448
 
@@ -3311,7 +3467,8 @@ Init_bigdecimal(void)
3311
3467
  rb_define_method(rb_cBigDecimal, "modulo", BigDecimal_mod, 1);
3312
3468
  rb_define_method(rb_cBigDecimal, "remainder", BigDecimal_remainder, 1);
3313
3469
  rb_define_method(rb_cBigDecimal, "divmod", BigDecimal_divmod, 1);
3314
- /* rb_define_method(rb_cBigDecimal, "dup", BigDecimal_dup, 0); */
3470
+ rb_define_method(rb_cBigDecimal, "clone", BigDecimal_clone, 0);
3471
+ rb_define_method(rb_cBigDecimal, "dup", BigDecimal_clone, 0);
3315
3472
  rb_define_method(rb_cBigDecimal, "to_f", BigDecimal_to_f, 0);
3316
3473
  rb_define_method(rb_cBigDecimal, "abs", BigDecimal_abs, 0);
3317
3474
  rb_define_method(rb_cBigDecimal, "sqrt", BigDecimal_sqrt, 1);
@@ -3359,6 +3516,7 @@ Init_bigdecimal(void)
3359
3516
  id_floor = rb_intern_const("floor");
3360
3517
  id_to_r = rb_intern_const("to_r");
3361
3518
  id_eq = rb_intern_const("==");
3519
+ id_half = rb_intern_const("half");
3362
3520
  }
3363
3521
 
3364
3522
  /*
@@ -3386,7 +3544,14 @@ static Real *VpPt5; /* constant 0.5 */
3386
3544
  #define MemCmp(x,y,z) memcmp(x,y,z)
3387
3545
  #define StrCmp(x,y) strcmp(x,y)
3388
3546
 
3389
- static int VpIsDefOP(Real *c,Real *a,Real *b,int sw);
3547
+ enum op_sw {
3548
+ OP_SW_ADD = 1, /* + */
3549
+ OP_SW_SUB, /* - */
3550
+ OP_SW_MULT, /* * */
3551
+ OP_SW_DIV /* / */
3552
+ };
3553
+
3554
+ static int VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw);
3390
3555
  static int AddExponent(Real *a, SIGNED_VALUE n);
3391
3556
  static BDIGIT VpAddAbs(Real *a,Real *b,Real *c);
3392
3557
  static BDIGIT VpSubAbs(Real *a,Real *b,Real *c);
@@ -3413,7 +3578,7 @@ VpMemAlloc(size_t mb)
3413
3578
  return p;
3414
3579
  }
3415
3580
 
3416
- VP_EXPORT void *
3581
+ VP_EXPORT void *
3417
3582
  VpMemRealloc(void *ptr, size_t mb)
3418
3583
  {
3419
3584
  void *p = xrealloc(ptr, mb);
@@ -3431,12 +3596,12 @@ VpFree(Real *pv)
3431
3596
  #ifdef BIGDECIMAL_DEBUG
3432
3597
  gnAlloc--; /* Decrement allocation count */
3433
3598
  if (gnAlloc == 0) {
3434
- printf(" *************** All memories allocated freed ****************");
3435
- getchar();
3599
+ printf(" *************** All memories allocated freed ****************\n");
3600
+ /*getchar();*/
3436
3601
  }
3437
3602
  if (gnAlloc < 0) {
3438
3603
  printf(" ??????????? Too many memory free calls(%d) ?????????????\n", gnAlloc);
3439
- getchar();
3604
+ /*getchar();*/
3440
3605
  }
3441
3606
  #endif /* BIGDECIMAL_DEBUG */
3442
3607
  }
@@ -3466,7 +3631,7 @@ VpGetException (void)
3466
3631
  return RMPD_EXCEPTION_MODE_DEFAULT;
3467
3632
  }
3468
3633
 
3469
- return (unsigned short)FIX2UINT(vmode);
3634
+ return NUM2USHORT(vmode);
3470
3635
  }
3471
3636
 
3472
3637
  static void
@@ -3536,7 +3701,7 @@ VpGetRoundMode(void)
3536
3701
  return RMPD_ROUNDING_MODE_DEFAULT;
3537
3702
  }
3538
3703
 
3539
- return (unsigned short)FIX2INT(vmode);
3704
+ return NUM2USHORT(vmode);
3540
3705
  }
3541
3706
 
3542
3707
  VP_EXPORT int
@@ -3576,13 +3741,7 @@ VpSetRoundMode(unsigned short n)
3576
3741
  * (to let the compiler know they may be changed in outside
3577
3742
  * (... but not actually..)).
3578
3743
  */
3579
- volatile const double gZero_ABCED9B1_CE73__00400511F31D = 0.0;
3580
3744
  volatile const double gOne_ABCED9B4_CE73__00400511F31D = 1.0;
3581
- static double
3582
- Zero(void)
3583
- {
3584
- return gZero_ABCED9B1_CE73__00400511F31D;
3585
- }
3586
3745
 
3587
3746
  static double
3588
3747
  One(void)
@@ -3607,25 +3766,19 @@ One(void)
3607
3766
  VP_EXPORT double
3608
3767
  VpGetDoubleNaN(void) /* Returns the value of NaN */
3609
3768
  {
3610
- static double fNaN = 0.0;
3611
- if (fNaN == 0.0) fNaN = Zero()/Zero();
3612
- return fNaN;
3769
+ return nan("");
3613
3770
  }
3614
3771
 
3615
3772
  VP_EXPORT double
3616
3773
  VpGetDoublePosInf(void) /* Returns the value of +Infinity */
3617
3774
  {
3618
- static double fInf = 0.0;
3619
- if (fInf == 0.0) fInf = One()/Zero();
3620
- return fInf;
3775
+ return HUGE_VAL;
3621
3776
  }
3622
3777
 
3623
3778
  VP_EXPORT double
3624
3779
  VpGetDoubleNegInf(void) /* Returns the value of -Infinity */
3625
3780
  {
3626
- static double fInf = 0.0;
3627
- if (fInf == 0.0) fInf = -(One()/Zero());
3628
- return fInf;
3781
+ return -HUGE_VAL;
3629
3782
  }
3630
3783
 
3631
3784
  VP_EXPORT double
@@ -3673,7 +3826,7 @@ VpException(unsigned short f, const char *str,int always)
3673
3826
  /* Throw exception or returns 0,when resulting c is Inf or NaN */
3674
3827
  /* sw=1:+ 2:- 3:* 4:/ */
3675
3828
  static int
3676
- VpIsDefOP(Real *c,Real *a,Real *b,int sw)
3829
+ VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw)
3677
3830
  {
3678
3831
  if (VpIsNaN(a) || VpIsNaN(b)) {
3679
3832
  /* at least a or b is NaN */
@@ -3684,7 +3837,7 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
3684
3837
  if (VpIsInf(a)) {
3685
3838
  if (VpIsInf(b)) {
3686
3839
  switch(sw) {
3687
- case 1: /* + */
3840
+ case OP_SW_ADD: /* + */
3688
3841
  if (VpGetSign(a) == VpGetSign(b)) {
3689
3842
  VpSetInf(c, VpGetSign(a));
3690
3843
  goto Inf;
@@ -3693,7 +3846,7 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
3693
3846
  VpSetNaN(c);
3694
3847
  goto NaN;
3695
3848
  }
3696
- case 2: /* - */
3849
+ case OP_SW_SUB: /* - */
3697
3850
  if (VpGetSign(a) != VpGetSign(b)) {
3698
3851
  VpSetInf(c, VpGetSign(a));
3699
3852
  goto Inf;
@@ -3702,12 +3855,10 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
3702
3855
  VpSetNaN(c);
3703
3856
  goto NaN;
3704
3857
  }
3705
- break;
3706
- case 3: /* * */
3858
+ case OP_SW_MULT: /* * */
3707
3859
  VpSetInf(c, VpGetSign(a)*VpGetSign(b));
3708
3860
  goto Inf;
3709
- break;
3710
- case 4: /* / */
3861
+ case OP_SW_DIV: /* / */
3711
3862
  VpSetNaN(c);
3712
3863
  goto NaN;
3713
3864
  }
@@ -3716,18 +3867,18 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
3716
3867
  }
3717
3868
  /* Inf op Finite */
3718
3869
  switch(sw) {
3719
- case 1: /* + */
3720
- case 2: /* - */
3870
+ case OP_SW_ADD: /* + */
3871
+ case OP_SW_SUB: /* - */
3721
3872
  VpSetInf(c, VpGetSign(a));
3722
3873
  break;
3723
- case 3: /* * */
3874
+ case OP_SW_MULT: /* * */
3724
3875
  if (VpIsZero(b)) {
3725
3876
  VpSetNaN(c);
3726
3877
  goto NaN;
3727
3878
  }
3728
3879
  VpSetInf(c, VpGetSign(a)*VpGetSign(b));
3729
3880
  break;
3730
- case 4: /* / */
3881
+ case OP_SW_DIV: /* / */
3731
3882
  VpSetInf(c, VpGetSign(a)*VpGetSign(b));
3732
3883
  }
3733
3884
  goto Inf;
@@ -3735,20 +3886,20 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
3735
3886
 
3736
3887
  if (VpIsInf(b)) {
3737
3888
  switch(sw) {
3738
- case 1: /* + */
3889
+ case OP_SW_ADD: /* + */
3739
3890
  VpSetInf(c, VpGetSign(b));
3740
3891
  break;
3741
- case 2: /* - */
3892
+ case OP_SW_SUB: /* - */
3742
3893
  VpSetInf(c, -VpGetSign(b));
3743
3894
  break;
3744
- case 3: /* * */
3895
+ case OP_SW_MULT: /* * */
3745
3896
  if (VpIsZero(a)) {
3746
3897
  VpSetNaN(c);
3747
3898
  goto NaN;
3748
3899
  }
3749
3900
  VpSetInf(c, VpGetSign(a)*VpGetSign(b));
3750
3901
  break;
3751
- case 4: /* / */
3902
+ case OP_SW_DIV: /* / */
3752
3903
  VpSetZero(c, VpGetSign(a)*VpGetSign(b));
3753
3904
  }
3754
3905
  goto Inf;
@@ -3756,7 +3907,13 @@ VpIsDefOP(Real *c,Real *a,Real *b,int sw)
3756
3907
  return 1; /* Results OK */
3757
3908
 
3758
3909
  Inf:
3759
- return VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 0);
3910
+ if (VpIsPosInf(c)) {
3911
+ return VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 0);
3912
+ }
3913
+ else {
3914
+ return VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 0);
3915
+ }
3916
+
3760
3917
  NaN:
3761
3918
  return VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'", 0);
3762
3919
  }
@@ -3816,14 +3973,11 @@ VP_EXPORT size_t
3816
3973
  VpInit(BDIGIT BaseVal)
3817
3974
  {
3818
3975
  /* Setup +/- Inf NaN -0 */
3819
- VpGetDoubleNaN();
3820
- VpGetDoublePosInf();
3821
- VpGetDoubleNegInf();
3822
3976
  VpGetDoubleNegZero();
3823
3977
 
3824
3978
  /* Allocates Vp constants. */
3825
- VpConstOne = VpAlloc(1UL, "1");
3826
- VpPt5 = VpAlloc(1UL, ".5");
3979
+ VpConstOne = VpAlloc(1UL, "1", 1, 1);
3980
+ VpPt5 = VpAlloc(1UL, ".5", 1, 1);
3827
3981
 
3828
3982
  #ifdef BIGDECIMAL_DEBUG
3829
3983
  gnAlloc = 0;
@@ -3831,12 +3985,12 @@ VpInit(BDIGIT BaseVal)
3831
3985
 
3832
3986
  #ifdef BIGDECIMAL_DEBUG
3833
3987
  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);
3988
+ printf("VpInit: BaseVal = %"PRIuBDIGIT"\n", BaseVal);
3989
+ printf("\tBASE = %"PRIuBDIGIT"\n", BASE);
3990
+ printf("\tHALF_BASE = %"PRIuBDIGIT"\n", HALF_BASE);
3991
+ printf("\tBASE1 = %"PRIuBDIGIT"\n", BASE1);
3992
+ printf("\tBASE_FIG = %u\n", BASE_FIG);
3993
+ printf("\tDBLE_FIG = %d\n", DBLE_FIG);
3840
3994
  }
3841
3995
  #endif /* BIGDECIMAL_DEBUG */
3842
3996
 
@@ -3863,7 +4017,7 @@ AddExponent(Real *a, SIGNED_VALUE n)
3863
4017
  goto overflow;
3864
4018
  mb = m*(SIGNED_VALUE)BASE_FIG;
3865
4019
  eb = e*(SIGNED_VALUE)BASE_FIG;
3866
- if (mb < eb) goto overflow;
4020
+ if (eb - mb > 0) goto overflow;
3867
4021
  }
3868
4022
  }
3869
4023
  else if (n < 0) {
@@ -3872,7 +4026,7 @@ AddExponent(Real *a, SIGNED_VALUE n)
3872
4026
  goto underflow;
3873
4027
  mb = m*(SIGNED_VALUE)BASE_FIG;
3874
4028
  eb = e*(SIGNED_VALUE)BASE_FIG;
3875
- if (mb > eb) goto underflow;
4029
+ if (mb - eb > 0) goto underflow;
3876
4030
  }
3877
4031
  a->exponent = m;
3878
4032
  return 1;
@@ -3887,6 +4041,52 @@ overflow:
3887
4041
  return VpException(VP_EXCEPTION_OVERFLOW, "Exponent overflow", 0);
3888
4042
  }
3889
4043
 
4044
+ Real *
4045
+ rmpd_parse_special_string(const char *str)
4046
+ {
4047
+ static const struct {
4048
+ const char *str;
4049
+ size_t len;
4050
+ int sign;
4051
+ } table[] = {
4052
+ { SZ_INF, sizeof(SZ_INF) - 1, VP_SIGN_POSITIVE_INFINITE },
4053
+ { SZ_PINF, sizeof(SZ_PINF) - 1, VP_SIGN_POSITIVE_INFINITE },
4054
+ { SZ_NINF, sizeof(SZ_NINF) - 1, VP_SIGN_NEGATIVE_INFINITE },
4055
+ { SZ_NaN, sizeof(SZ_NaN) - 1, VP_SIGN_NaN }
4056
+ };
4057
+ static const size_t table_length = sizeof(table) / sizeof(table[0]);
4058
+ size_t i;
4059
+
4060
+ for (i = 0; i < table_length; ++i) {
4061
+ const char *p;
4062
+ if (strncmp(str, table[i].str, table[i].len) != 0) {
4063
+ continue;
4064
+ }
4065
+
4066
+ p = str + table[i].len;
4067
+ while (*p && ISSPACE(*p)) ++p;
4068
+ if (*p == '\0') {
4069
+ Real *vp = VpAllocReal(1);
4070
+ vp->MaxPrec = 1;
4071
+ switch (table[i].sign) {
4072
+ default:
4073
+ UNREACHABLE; break;
4074
+ case VP_SIGN_POSITIVE_INFINITE:
4075
+ VpSetPosInf(vp);
4076
+ return vp;
4077
+ case VP_SIGN_NEGATIVE_INFINITE:
4078
+ VpSetNegInf(vp);
4079
+ return vp;
4080
+ case VP_SIGN_NaN:
4081
+ VpSetNaN(vp);
4082
+ return vp;
4083
+ }
4084
+ }
4085
+ }
4086
+
4087
+ return NULL;
4088
+ }
4089
+
3890
4090
  /*
3891
4091
  * Allocates variable.
3892
4092
  * [Input]
@@ -3901,9 +4101,10 @@ overflow:
3901
4101
  * NULL be returned if memory allocation is failed,or any error.
3902
4102
  */
3903
4103
  VP_EXPORT Real *
3904
- VpAlloc(size_t mx, const char *szVal)
4104
+ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
3905
4105
  {
3906
- size_t i, ni, ipn, ipf, nf, ipe, ne, nalloc;
4106
+ const char *orig_szVal = szVal;
4107
+ size_t i, j, ni, ipf, nf, ipe, ne, dot_seen, exp_seen, nalloc;
3907
4108
  char v, *psz;
3908
4109
  int sign=1;
3909
4110
  Real *vp = NULL;
@@ -3914,123 +4115,198 @@ VpAlloc(size_t mx, const char *szVal)
3914
4115
  if (mx == 0) ++mx;
3915
4116
 
3916
4117
  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
- }
4118
+ /* Skipping leading spaces */
4119
+ while (ISSPACE(*szVal)) szVal++;
4120
+
4121
+ /* Processing the leading one `#` */
4122
+ if (*szVal != '#') {
4123
+ if (mf) {
4124
+ mf = (mf + BASE_FIG - 1) / BASE_FIG + 2; /* Needs 1 more for div */
4125
+ if (mx > mf) {
4126
+ mx = mf;
4127
+ }
4128
+ }
4129
+ }
4130
+ else {
4131
+ ++szVal;
4132
+ }
3929
4133
  }
3930
4134
  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;
3939
- }
3940
-
3941
- /* Skip all '_' after digit: 2006-6-30 */
3942
- ni = 0;
4135
+ return_zero:
4136
+ /* necessary to be able to store */
4137
+ /* at least mx digits. */
4138
+ /* szVal==NULL ==> allocate zero value. */
4139
+ vp = VpAllocReal(mx);
4140
+ /* xmalloc() alway returns(or throw interruption) */
4141
+ vp->MaxPrec = mx; /* set max precision */
4142
+ VpSetZero(vp, 1); /* initialize vp to zero. */
4143
+ return vp;
4144
+ }
4145
+
4146
+ /* Check on Inf & NaN */
4147
+ if ((vp = rmpd_parse_special_string(szVal)) != NULL) {
4148
+ return vp;
4149
+ }
4150
+
4151
+ /* Scanning digits */
4152
+
4153
+ /* A buffer for keeping scanned digits */
3943
4154
  buf = rb_str_tmp_new(strlen(szVal) + 1);
3944
4155
  psz = RSTRING_PTR(buf);
3945
- i = 0;
3946
- ipn = 0;
3947
- 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;
4156
+
4157
+ /* cursor: i for psz, and j for szVal */
4158
+ i = j = 0;
4159
+
4160
+ /* Scanning: sign part */
4161
+ v = psz[i] = szVal[j];
4162
+ if ((v == '-') || (v == '+')) {
4163
+ sign = -(v == '-');
4164
+ ++i;
4165
+ ++j;
3959
4166
  }
3960
- /* Skip trailing spaces */
3961
- while (--i > 0) {
3962
- if (ISSPACE(psz[i])) psz[i] = 0;
3963
- else break;
4167
+
4168
+ /* Scanning: integer part */
4169
+ ni = 0; /* number of digits in the integer part */
4170
+ while ((v = psz[i] = szVal[j]) != '\0') {
4171
+ if (!strict_p && ISSPACE(v)) {
4172
+ v = psz[i] = '\0';
4173
+ break;
4174
+ }
4175
+ if (v == '_') {
4176
+ if (ni > 0) {
4177
+ v = szVal[j+1];
4178
+ if (v == '\0' || ISSPACE(v) || ISDIGIT(v)) {
4179
+ ++j;
4180
+ continue;
4181
+ }
4182
+ if (!strict_p) {
4183
+ v = psz[i] = '\0';
4184
+ break;
4185
+ }
4186
+ }
4187
+ goto invalid_value;
4188
+ }
4189
+ if (!ISDIGIT(v)) {
4190
+ break;
4191
+ }
4192
+ ++ni;
4193
+ ++i;
4194
+ ++j;
4195
+ }
4196
+
4197
+ /* Scanning: fractional part */
4198
+ nf = 0; /* number of digits in the fractional part */
4199
+ ne = 0; /* number of digits in the exponential part */
4200
+ ipf = 0; /* index of the beginning of the fractional part */
4201
+ ipe = 0; /* index of the beginning of the exponential part */
4202
+ dot_seen = 0;
4203
+ exp_seen = 0;
4204
+
4205
+ if (v != '\0') {
4206
+ /* Scanning fractional part */
4207
+ if ((psz[i] = szVal[j]) == '.') {
4208
+ dot_seen = 1;
4209
+ ++i;
4210
+ ++j;
4211
+ ipf = i;
4212
+ while ((v = psz[i] = szVal[j]) != '\0') {
4213
+ if (!strict_p && ISSPACE(v)) {
4214
+ v = psz[i] = '\0';
4215
+ break;
4216
+ }
4217
+ if (v == '_') {
4218
+ if (nf > 0 && ISDIGIT(szVal[j+1])) {
4219
+ ++j;
4220
+ continue;
4221
+ }
4222
+ if (!strict_p) {
4223
+ v = psz[i] = '\0';
4224
+ if (nf == 0) {
4225
+ dot_seen = 0;
4226
+ }
4227
+ break;
4228
+ }
4229
+ goto invalid_value;
4230
+ }
4231
+ if (!ISDIGIT(v)) break;
4232
+ ++i;
4233
+ ++j;
4234
+ ++nf;
4235
+ }
4236
+ }
4237
+
4238
+ /* Scanning exponential part */
4239
+ if (v != '\0') {
4240
+ switch ((psz[i] = szVal[j])) {
4241
+ case '\0':
4242
+ break;
4243
+ case 'e': case 'E':
4244
+ case 'd': case 'D':
4245
+ exp_seen = 1;
4246
+ ++i;
4247
+ ++j;
4248
+ ipe = i;
4249
+ v = psz[i] = szVal[j];
4250
+ if ((v == '-') || (v == '+')) {
4251
+ ++i;
4252
+ ++j;
4253
+ }
4254
+ while ((v = psz[i] = szVal[j]) != '\0') {
4255
+ if (!strict_p && ISSPACE(v)) {
4256
+ v = psz[i] = '\0';
4257
+ break;
4258
+ }
4259
+ if (v == '_') {
4260
+ if (ne > 0 && ISDIGIT(szVal[j+1])) {
4261
+ ++j;
4262
+ continue;
4263
+ }
4264
+ if (!strict_p) {
4265
+ v = psz[i] = '\0';
4266
+ if (ne == 0) {
4267
+ exp_seen = 0;
4268
+ }
4269
+ break;
4270
+ }
4271
+ goto invalid_value;
4272
+ }
4273
+ if (!ISDIGIT(v)) break;
4274
+ ++i;
4275
+ ++j;
4276
+ ++ne;
4277
+ }
4278
+ break;
4279
+ default:
4280
+ break;
4281
+ }
4282
+ }
4283
+
4284
+ if (v != '\0') {
4285
+ /* Scanning trailing spaces */
4286
+ while (ISSPACE(szVal[j])) ++j;
4287
+
4288
+ /* Invalid character */
4289
+ if (szVal[j] && strict_p) {
4290
+ goto invalid_value;
4291
+ }
4292
+ }
3964
4293
  }
3965
- szVal = psz;
3966
4294
 
3967
- /* Check on Inf & NaN */
3968
- if (StrCmp(szVal, SZ_PINF) == 0 || StrCmp(szVal, SZ_INF) == 0 ) {
3969
- vp = VpAllocReal(1);
3970
- vp->MaxPrec = 1; /* set max precision */
3971
- VpSetPosInf(vp);
3972
- return vp;
3973
- }
3974
- if (StrCmp(szVal, SZ_NINF) == 0) {
3975
- vp = VpAllocReal(1);
3976
- vp->MaxPrec = 1; /* set max precision */
3977
- VpSetNegInf(vp);
3978
- return vp;
3979
- }
3980
- if (StrCmp(szVal, SZ_NaN) == 0) {
3981
- vp = VpAllocReal(1);
3982
- vp->MaxPrec = 1; /* set max precision */
3983
- VpSetNaN(vp);
3984
- return vp;
3985
- }
3986
-
3987
- /* check on number szVal[] */
3988
- ipn = i = 0;
3989
- if (szVal[i] == '-') { sign=-1; ++i; }
3990
- else if (szVal[i] == '+') ++i;
3991
- /* Skip digits */
3992
- ni = 0; /* digits in mantissa */
3993
- while ((v = szVal[i]) != 0) {
3994
- if (!ISDIGIT(v)) break;
3995
- ++i;
3996
- ++ni;
3997
- }
3998
- nf = 0;
3999
- ipf = 0;
4000
- ipe = 0;
4001
- ne = 0;
4002
- 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 */
4295
+ psz[i] = '\0';
4014
4296
 
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
- }
4297
+ if (((ni == 0 || dot_seen) && nf == 0) || (exp_seen && ne == 0)) {
4298
+ VALUE str;
4299
+ invalid_value:
4300
+ if (!strict_p) {
4301
+ goto return_zero;
4302
+ }
4303
+ if (!exc) {
4304
+ return NULL;
4305
+ }
4306
+ str = rb_str_new2(orig_szVal);
4307
+ rb_raise(rb_eArgError, "invalid value for BigDecimal(): \"%"PRIsVALUE"\"", str);
4033
4308
  }
4309
+
4034
4310
  nalloc = (ni + nf + BASE_FIG - 1) / BASE_FIG + 1; /* set effective allocation */
4035
4311
  /* units for szVal[] */
4036
4312
  if (mx == 0) mx = 1;
@@ -4040,7 +4316,7 @@ VpAlloc(size_t mx, const char *szVal)
4040
4316
  /* xmalloc() alway returns(or throw interruption) */
4041
4317
  vp->MaxPrec = mx; /* set max precision */
4042
4318
  VpSetZero(vp, sign);
4043
- VpCtoV(vp, &szVal[ipn], ni, &szVal[ipf], nf, &szVal[ipe], ne);
4319
+ VpCtoV(vp, psz, ni, psz + ipf, nf, psz + ipe, ne);
4044
4320
  rb_str_resize(buf, 0);
4045
4321
  return vp;
4046
4322
  }
@@ -4098,7 +4374,7 @@ VpAsgn(Real *c, Real *a, int isw)
4098
4374
 
4099
4375
  /*
4100
4376
  * c = a + b when operation = 1 or 2
4101
- * = a - b when operation = -1 or -2.
4377
+ * c = a - b when operation = -1 or -2.
4102
4378
  * Returns number of significant digits of c
4103
4379
  */
4104
4380
  VP_EXPORT size_t
@@ -4117,7 +4393,7 @@ VpAddSub(Real *c, Real *a, Real *b, int operation)
4117
4393
  }
4118
4394
  #endif /* BIGDECIMAL_DEBUG */
4119
4395
 
4120
- if (!VpIsDefOP(c, a, b, (operation > 0) ? 1 : 2)) return 0; /* No significant digits */
4396
+ if (!VpIsDefOP(c, a, b, (operation > 0) ? OP_SW_ADD : OP_SW_SUB)) return 0; /* No significant digits */
4121
4397
 
4122
4398
  /* check if a or b is zero */
4123
4399
  if (VpIsZero(a)) {
@@ -4231,7 +4507,7 @@ end_if:
4231
4507
  }
4232
4508
 
4233
4509
  /*
4234
- * Addition of two variable precisional variables
4510
+ * Addition of two values with variable precision
4235
4511
  * a and b assuming abs(a)>abs(b).
4236
4512
  * c = abs(a) + abs(b) ; where |a|>=|b|
4237
4513
  */
@@ -4453,7 +4729,7 @@ VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos,
4453
4729
 
4454
4730
  size_t const round_limit = (VpGetPrecLimit() + BASE_FIG - 1) / BASE_FIG;
4455
4731
 
4456
- assert(a->exponent >= b->expoennt);
4732
+ assert(a->exponent >= b->exponent);
4457
4733
 
4458
4734
  c->frac[0] = 0;
4459
4735
  *av = *bv = 0;
@@ -4573,7 +4849,7 @@ VpMult(Real *c, Real *a, Real *b)
4573
4849
  }
4574
4850
  #endif /* BIGDECIMAL_DEBUG */
4575
4851
 
4576
- if (!VpIsDefOP(c, a, b, 3)) return 0; /* No significant digit */
4852
+ if (!VpIsDefOP(c, a, b, OP_SW_MULT)) return 0; /* No significant digit */
4577
4853
 
4578
4854
  if (VpIsZero(a) || VpIsZero(b)) {
4579
4855
  /* at least a or b is zero */
@@ -4603,7 +4879,7 @@ VpMult(Real *c, Real *a, Real *b)
4603
4879
 
4604
4880
  if (MxIndC < MxIndAB) { /* The Max. prec. of c < Prec(a)+Prec(b) */
4605
4881
  w = c;
4606
- c = VpAlloc((size_t)((MxIndAB + 1) * BASE_FIG), "#0");
4882
+ c = VpAlloc((size_t)((MxIndAB + 1) * BASE_FIG), "#0", 1, 1);
4607
4883
  MxIndC = MxIndAB;
4608
4884
  }
4609
4885
 
@@ -4685,7 +4961,7 @@ Exit:
4685
4961
  /*
4686
4962
  * c = a / b, remainder = r
4687
4963
  */
4688
- VP_EXPORT size_t
4964
+ VP_EXPORT size_t
4689
4965
  VpDivd(Real *c, Real *r, Real *a, Real *b)
4690
4966
  {
4691
4967
  size_t word_a, word_b, word_c, word_r;
@@ -4703,14 +4979,14 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
4703
4979
  #endif /*BIGDECIMAL_DEBUG */
4704
4980
 
4705
4981
  VpSetNaN(r);
4706
- if (!VpIsDefOP(c, a, b, 4)) goto Exit;
4982
+ if (!VpIsDefOP(c, a, b, OP_SW_DIV)) goto Exit;
4707
4983
  if (VpIsZero(a) && VpIsZero(b)) {
4708
4984
  VpSetNaN(c);
4709
- return VpException(VP_EXCEPTION_NaN, "(VpDivd) 0/0 not defined(NaN)", 0);
4985
+ return VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'", 0);
4710
4986
  }
4711
4987
  if (VpIsZero(b)) {
4712
4988
  VpSetInf(c, VpGetSign(a) * VpGetSign(b));
4713
- return VpException(VP_EXCEPTION_ZERODIVIDE, "(VpDivd) Divide by zero", 0);
4989
+ return VpException(VP_EXCEPTION_ZERODIVIDE, "Divide by zero", 0);
4714
4990
  }
4715
4991
  if (VpIsZero(a)) {
4716
4992
  /* numerator a is zero */
@@ -4990,7 +5266,7 @@ VpComp(Real *a, Real *b)
4990
5266
  goto Exit;
4991
5267
  }
4992
5268
 
4993
- /* a and b have same exponent, then compare significand. */
5269
+ /* a and b have same exponent, then compare their significand. */
4994
5270
  mx = (a->Prec < b->Prec) ? a->Prec : b->Prec;
4995
5271
  ind = 0;
4996
5272
  while (ind < mx) {
@@ -5031,8 +5307,8 @@ Exit:
5031
5307
  * % ... VP variable. To print '%', use '%%'.
5032
5308
  * \n ... new line
5033
5309
  * \b ... backspace
5034
- * ... tab
5035
- * Note: % must must not appear more than once
5310
+ * \t ... tab
5311
+ * Note: % must not appear more than once
5036
5312
  * a ... VP variable to be printed
5037
5313
  */
5038
5314
  #ifdef BIGDECIMAL_ENABLE_VPRINT
@@ -5042,24 +5318,6 @@ VPrint(FILE *fp, const char *cntl_chr, Real *a)
5042
5318
  size_t i, j, nc, nd, ZeroSup, sep = 10;
5043
5319
  BDIGIT m, e, nn;
5044
5320
 
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
5321
  j = 0;
5064
5322
  nd = nc = 0; /* nd : number of digits in fraction part(every 10 digits, */
5065
5323
  /* nd<=10). */
@@ -5068,8 +5326,20 @@ VPrint(FILE *fp, const char *cntl_chr, Real *a)
5068
5326
  while (*(cntl_chr + j)) {
5069
5327
  if (*(cntl_chr + j) == '%' && *(cntl_chr + j + 1) != '%') {
5070
5328
  nc = 0;
5071
- if (!VpIsZero(a)) {
5072
- if (VpGetSign(a) < 0) {
5329
+ if (VpIsNaN(a)) {
5330
+ fprintf(fp, SZ_NaN);
5331
+ nc += 8;
5332
+ }
5333
+ else if (VpIsPosInf(a)) {
5334
+ fprintf(fp, SZ_INF);
5335
+ nc += 8;
5336
+ }
5337
+ else if (VpIsNegInf(a)) {
5338
+ fprintf(fp, SZ_NINF);
5339
+ nc += 9;
5340
+ }
5341
+ else if (!VpIsZero(a)) {
5342
+ if (BIGDECIMAL_NEGATIVE_P(a)) {
5073
5343
  fprintf(fp, "-");
5074
5344
  ++nc;
5075
5345
  }
@@ -5158,7 +5428,7 @@ VpFormatSt(char *psz, size_t fFmt)
5158
5428
  if (!ch) break;
5159
5429
  if (ISSPACE(ch) || ch=='-' || ch=='+') continue;
5160
5430
  if (ch == '.') { nf = 0; continue; }
5161
- if (ch == 'E') break;
5431
+ if (ch == 'E' || ch == 'e') break;
5162
5432
 
5163
5433
  if (++nf > fFmt) {
5164
5434
  memmove(psz + i + 1, psz + i, ie - i + 1);
@@ -5207,7 +5477,7 @@ VpSzMantissa(Real *a,char *psz)
5207
5477
 
5208
5478
  ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
5209
5479
  if (!VpIsZero(a)) {
5210
- if (VpGetSign(a) < 0) *psz++ = '-';
5480
+ if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
5211
5481
  n = a->Prec;
5212
5482
  for (i = 0; i < n; ++i) {
5213
5483
  m = BASE1;
@@ -5235,7 +5505,7 @@ VpSzMantissa(Real *a,char *psz)
5235
5505
 
5236
5506
  VP_EXPORT int
5237
5507
  VpToSpecialString(Real *a,char *psz,int fPlus)
5238
- /* fPlus =0:default, =1: set ' ' before digits , =2: set '+' before digits. */
5508
+ /* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
5239
5509
  {
5240
5510
  if (VpIsNaN(a)) {
5241
5511
  sprintf(psz,SZ_NaN);
@@ -5270,7 +5540,7 @@ VpToSpecialString(Real *a,char *psz,int fPlus)
5270
5540
 
5271
5541
  VP_EXPORT void
5272
5542
  VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
5273
- /* fPlus =0:default, =1: set ' ' before digits , =2:set '+' before digits. */
5543
+ /* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
5274
5544
  {
5275
5545
  size_t i, n, ZeroSup;
5276
5546
  BDIGIT shift, m, e, nn;
@@ -5281,7 +5551,7 @@ VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
5281
5551
 
5282
5552
  ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
5283
5553
 
5284
- if (VpGetSign(a) < 0) *psz++ = '-';
5554
+ if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
5285
5555
  else if (fPlus == 1) *psz++ = ' ';
5286
5556
  else if (fPlus == 2) *psz++ = '+';
5287
5557
 
@@ -5312,13 +5582,13 @@ VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
5312
5582
  while (psz[-1] == '0') {
5313
5583
  *(--psz) = 0;
5314
5584
  }
5315
- sprintf(psz, "E%"PRIdSIZE, ex);
5585
+ sprintf(psz, "e%"PRIdSIZE, ex);
5316
5586
  if (fFmt) VpFormatSt(pszSav, fFmt);
5317
5587
  }
5318
5588
 
5319
5589
  VP_EXPORT void
5320
5590
  VpToFString(Real *a, char *psz, size_t fFmt, int fPlus)
5321
- /* fPlus =0:default,=1: set ' ' before digits ,set '+' before digits. */
5591
+ /* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
5322
5592
  {
5323
5593
  size_t i, n;
5324
5594
  BDIGIT m, e, nn;
@@ -5327,7 +5597,7 @@ VpToFString(Real *a, char *psz, size_t fFmt, int fPlus)
5327
5597
 
5328
5598
  if (VpToSpecialString(a, psz, fPlus)) return;
5329
5599
 
5330
- if (VpGetSign(a) < 0) *psz++ = '-';
5600
+ if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
5331
5601
  else if (fPlus == 1) *psz++ = ' ';
5332
5602
  else if (fPlus == 2) *psz++ = '+';
5333
5603
 
@@ -5749,21 +6019,22 @@ VpSqrt(Real *y, Real *x)
5749
6019
  ssize_t nr;
5750
6020
  double val;
5751
6021
 
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);
6022
+ /* Zero or +Infinity ? */
6023
+ if (VpIsZero(x) || VpIsPosInf(x)) {
6024
+ VpAsgn(y,x,1);
5760
6025
  goto Exit;
5761
6026
  }
5762
6027
 
5763
6028
  /* Negative ? */
5764
- if (VpGetSign(x) < 0) {
6029
+ if (BIGDECIMAL_NEGATIVE_P(x)) {
6030
+ VpSetNaN(y);
6031
+ return VpException(VP_EXCEPTION_OP, "sqrt of negative value", 0);
6032
+ }
6033
+
6034
+ /* NaN ? */
6035
+ if (VpIsNaN(x)) {
5765
6036
  VpSetNaN(y);
5766
- return VpException(VP_EXCEPTION_OP, "(VpSqrt) SQRT(negative value)", 0);
6037
+ return VpException(VP_EXCEPTION_OP, "sqrt of 'NaN'(Not a Number)", 0);
5767
6038
  }
5768
6039
 
5769
6040
  /* One ? */
@@ -5776,8 +6047,8 @@ VpSqrt(Real *y, Real *x)
5776
6047
  if (x->MaxPrec > (size_t)n) n = (ssize_t)x->MaxPrec;
5777
6048
 
5778
6049
  /* allocate temporally variables */
5779
- f = VpAlloc(y->MaxPrec * (BASE_FIG + 2), "#1");
5780
- r = VpAlloc((n + n) * (BASE_FIG + 2), "#1");
6050
+ f = VpAlloc(y->MaxPrec * (BASE_FIG + 2), "#1", 1, 1);
6051
+ r = VpAlloc((n + n) * (BASE_FIG + 2), "#1", 1, 1);
5781
6052
 
5782
6053
  nr = 0;
5783
6054
  y_prec = y->MaxPrec;
@@ -5841,18 +6112,13 @@ Exit:
5841
6112
  return 1;
5842
6113
  }
5843
6114
 
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
6115
  /*
5852
6116
  * Round relatively from the decimal point.
5853
6117
  * f: rounding mode
5854
6118
  * nf: digit location to round from the decimal point.
5855
6119
  */
6120
+ VP_EXPORT int
6121
+ VpMidRound(Real *y, unsigned short f, ssize_t nf)
5856
6122
  {
5857
6123
  /* fracf: any positive digit under rounding position? */
5858
6124
  /* fracf_1further: any positive digits under one further than the rounding position? */
@@ -5954,10 +6220,10 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
5954
6220
  if (v > 5 || (v == 5 && fracf_1further)) ++div;
5955
6221
  break;
5956
6222
  case VP_ROUND_CEIL:
5957
- if (fracf && (VpGetSign(y) > 0)) ++div;
6223
+ if (fracf && BIGDECIMAL_POSITIVE_P(y)) ++div;
5958
6224
  break;
5959
6225
  case VP_ROUND_FLOOR:
5960
- if (fracf && (VpGetSign(y) < 0)) ++div;
6226
+ if (fracf && BIGDECIMAL_NEGATIVE_P(y)) ++div;
5961
6227
  break;
5962
6228
  case VP_ROUND_HALF_EVEN: /* Banker's rounding */
5963
6229
  if (v > 5) ++div;
@@ -6076,10 +6342,10 @@ VpInternalRound(Real *c, size_t ixDigit, BDIGIT vPrev, BDIGIT v)
6076
6342
  if (v >= 6) f = 1;
6077
6343
  break;
6078
6344
  case VP_ROUND_CEIL:
6079
- if (v && (VpGetSign(c) > 0)) f = 1;
6345
+ if (v && BIGDECIMAL_POSITIVE_P(c)) f = 1;
6080
6346
  break;
6081
6347
  case VP_ROUND_FLOOR:
6082
- if (v && (VpGetSign(c) < 0)) f = 1;
6348
+ if (v && BIGDECIMAL_NEGATIVE_P(c)) f = 1;
6083
6349
  break;
6084
6350
  case VP_ROUND_HALF_EVEN: /* Banker's rounding */
6085
6351
  /* as per VP_ROUND_HALF_DOWN, because this is the last digit of precision,
@@ -6216,7 +6482,7 @@ VpPower(Real *y, Real *x, SIGNED_VALUE n)
6216
6482
  if (x->exponent == 1 && x->Prec == 1 && x->frac[0] == 1) {
6217
6483
  /* abs(x) = 1 */
6218
6484
  VpSetOne(y);
6219
- if (VpGetSign(x) > 0) goto Exit;
6485
+ if (BIGDECIMAL_POSITIVE_P(x)) goto Exit;
6220
6486
  if ((n % 2) == 0) goto Exit;
6221
6487
  VpSetSign(y, -1);
6222
6488
  goto Exit;
@@ -6234,8 +6500,8 @@ VpPower(Real *y, Real *x, SIGNED_VALUE n)
6234
6500
 
6235
6501
  /* Allocate working variables */
6236
6502
 
6237
- w1 = VpAlloc((y->MaxPrec + 2) * BASE_FIG, "#0");
6238
- w2 = VpAlloc((w1->MaxPrec * 2 + 1) * BASE_FIG, "#0");
6503
+ w1 = VpAlloc((y->MaxPrec + 2) * BASE_FIG, "#0", 1, 1);
6504
+ w2 = VpAlloc((w1->MaxPrec * 2 + 1) * BASE_FIG, "#0", 1, 1);
6239
6505
  /* calculation start */
6240
6506
 
6241
6507
  VpAsgn(y, x, 1);
@@ -6261,7 +6527,7 @@ Exit:
6261
6527
  if (gfDebug) {
6262
6528
  VPrint(stdout, "VpPower y=%\n", y);
6263
6529
  VPrint(stdout, "VpPower x=%\n", x);
6264
- printf(" n=%d\n", n);
6530
+ printf(" n=%"PRIdVALUE"\n", n);
6265
6531
  }
6266
6532
  #endif /* BIGDECIMAL_DEBUG */
6267
6533
  VpFree(w2);
@@ -6296,10 +6562,10 @@ VpVarCheck(Real * v)
6296
6562
  for (i = 0; i < v->Prec; ++i) {
6297
6563
  if (v->frac[i] >= BASE) {
6298
6564
  printf("ERROR(VpVarCheck): Illegal fraction\n");
6299
- printf(" Frac[%"PRIuSIZE"]=%lu\n", i, v->frac[i]);
6565
+ printf(" Frac[%"PRIuSIZE"]=%"PRIuBDIGIT"\n", i, v->frac[i]);
6300
6566
  printf(" Prec. =%"PRIuSIZE"\n", v->Prec);
6301
6567
  printf(" Exp. =%"PRIdVALUE"\n", v->exponent);
6302
- printf(" BASE =%lu\n", BASE);
6568
+ printf(" BASE =%"PRIuBDIGIT"\n", BASE);
6303
6569
  return 3;
6304
6570
  }
6305
6571
  }