bigdecimal 1.2.7 → 1.4.3

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