bigdecimal 1.2.7 → 1.4.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/bigdecimal.gemspec +32 -18
- data/{bigdecimal.c → ext/bigdecimal/bigdecimal.c} +748 -482
- data/ext/bigdecimal/bigdecimal.def +3 -0
- data/{bigdecimal.h → ext/bigdecimal/bigdecimal.h} +87 -12
- data/{depend → ext/bigdecimal/depend} +4 -1
- data/ext/bigdecimal/extconf.rb +40 -0
- data/ext/bigdecimal/util/extconf.rb +24 -0
- data/ext/bigdecimal/util/util.c +9 -0
- data/lib/bigdecimal/jacobian.rb +4 -0
- data/lib/bigdecimal/ludcmp.rb +1 -0
- data/lib/bigdecimal/math.rb +10 -9
- data/lib/bigdecimal/newton.rb +1 -0
- data/lib/bigdecimal/util.rb +74 -55
- data/lib/bigdecimal.rb +22 -0
- data/sample/linear.rb +12 -10
- data/sample/nlsolve.rb +6 -5
- data/sample/pi.rb +1 -0
- metadata +91 -16
- data/README +0 -60
- data/extconf.rb +0 -10
@@ -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
|
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
|
-
|
290
|
-
|
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
|
-
/*
|
337
|
-
*
|
327
|
+
/* call-seq:
|
328
|
+
* big_decimal.precs -> array
|
329
|
+
*
|
330
|
+
* Returns an Array of two Integer values.
|
338
331
|
*
|
339
|
-
*
|
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
|
-
*
|
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
|
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
|
389
|
-
* #=>
|
382
|
+
* inf = BigDecimal('Infinity')
|
383
|
+
* #=> Infinity
|
390
384
|
* BigDecimal._load(inf._dump)
|
391
|
-
* #=>
|
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
|
-
|
427
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
635
|
+
GetPrecisionInt(VALUE v)
|
595
636
|
{
|
596
637
|
SIGNED_VALUE n;
|
597
|
-
|
598
|
-
n = FIX2INT(v);
|
638
|
+
n = NUM2INT(v);
|
599
639
|
if (n < 0) {
|
600
|
-
rb_raise(rb_eArgError, "
|
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
|
-
|
609
|
-
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
|
-
|
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
|
728
|
+
/* Returns the value as an Integer.
|
688
729
|
*
|
689
|
-
* If the
|
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 =
|
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 (
|
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
|
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
|
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 =
|
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
|
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
|
-
*
|
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
|
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
|
-
*
|
1216
|
+
* call-seq:
|
1217
|
+
* -big_decimal -> big_decimal
|
1175
1218
|
*
|
1176
|
-
*
|
1219
|
+
* Return the negation of self.
|
1177
1220
|
*
|
1178
|
-
*
|
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
|
-
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
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
|
1487
|
-
* b = BigDecimal
|
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 =
|
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 =
|
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 =
|
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 =
|
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
|
-
/*
|
1690
|
+
/*
|
1691
|
+
* call-seq:
|
1692
|
+
* big_decimal.abs -> big_decimal
|
1629
1693
|
*
|
1630
|
-
*
|
1631
|
-
*
|
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 =
|
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
|
-
|
1728
|
-
|
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
|
-
|
1732
|
-
|
1733
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
2002
|
+
* BigDecimal('-123.45678901234567890').to_s('5F')
|
1931
2003
|
* #=> '-123.45678 90123 45678 9'
|
1932
2004
|
*
|
1933
|
-
* BigDecimal
|
2005
|
+
* BigDecimal('123.45678901234567890').to_s('+8F')
|
1934
2006
|
* #=> '+123.45678901 23456789'
|
1935
2007
|
*
|
1936
|
-
* BigDecimal
|
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; /*
|
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
|
-
|
1957
|
-
|
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
|
-
|
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
|
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
|
-
*
|
2081
|
-
*
|
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
|
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
|
-
|
2096
|
-
|
2097
|
-
|
2098
|
-
|
2099
|
-
|
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 (
|
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 (
|
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 (
|
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 (
|
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 (
|
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
|
-
|
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
|
-
*
|
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
|
-
|
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
|
-
|
2523
|
-
|
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
|
-
|
2558
|
+
BigDecimal_clone(VALUE self)
|
2541
2559
|
{
|
2542
|
-
|
2543
|
-
|
2560
|
+
return self;
|
2561
|
+
}
|
2544
2562
|
|
2545
|
-
|
2546
|
-
|
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
|
-
|
2571
|
+
rb_get_kwargs(opts, kwds, 0, 1, &exception);
|
2572
|
+
return exception != Qfalse;
|
2549
2573
|
}
|
2550
2574
|
|
2551
2575
|
static Real *
|
2552
|
-
|
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 (
|
2588
|
+
if (argc == 1) {
|
2559
2589
|
mf = 0;
|
2560
2590
|
}
|
2561
2591
|
else {
|
2562
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
2609
|
-
|
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
|
-
|
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
|
2676
|
-
* BigDecimal
|
2677
|
-
* BigDecimal(BigDecimal
|
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
|
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 =
|
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 =
|
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
|
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 =
|
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
|
3201
|
+
* sum = BigDecimal("0")
|
3065
3202
|
* 10_000.times do
|
3066
|
-
* sum = sum + BigDecimal
|
3203
|
+
* sum = sum + BigDecimal("0.0001")
|
3067
3204
|
* end
|
3068
3205
|
* print sum #=> 0.1E1
|
3069
3206
|
*
|
3070
3207
|
* Similarly:
|
3071
3208
|
*
|
3072
|
-
* (BigDecimal
|
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
|
3087
|
-
* BigDecimal
|
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
|
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
|
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
|
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
|
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
|
-
*
|
3138
|
-
*
|
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",
|
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
|
-
*
|
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",
|
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",
|
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
|
-
|
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
|
-
|
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
|
-
|
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 (
|
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 (
|
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
|
-
|
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
|
-
|
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
|
-
|
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,
|
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
|
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
|
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
|
-
|
3706
|
-
case 3: /* * */
|
3858
|
+
case OP_SW_MULT: /* * */
|
3707
3859
|
VpSetInf(c, VpGetSign(a)*VpGetSign(b));
|
3708
3860
|
goto Inf;
|
3709
|
-
|
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
|
3720
|
-
case
|
3870
|
+
case OP_SW_ADD: /* + */
|
3871
|
+
case OP_SW_SUB: /* - */
|
3721
3872
|
VpSetInf(c, VpGetSign(a));
|
3722
3873
|
break;
|
3723
|
-
case
|
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
|
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
|
3889
|
+
case OP_SW_ADD: /* + */
|
3739
3890
|
VpSetInf(c, VpGetSign(b));
|
3740
3891
|
break;
|
3741
|
-
case
|
3892
|
+
case OP_SW_SUB: /* - */
|
3742
3893
|
VpSetInf(c, -VpGetSign(b));
|
3743
3894
|
break;
|
3744
|
-
case
|
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
|
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
|
-
|
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 = %
|
3835
|
-
printf("
|
3836
|
-
printf("
|
3837
|
-
printf("
|
3838
|
-
printf("
|
3839
|
-
printf("
|
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
|
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 >
|
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
|
-
|
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
|
-
|
3918
|
-
|
3919
|
-
|
3920
|
-
|
3921
|
-
|
3922
|
-
|
3923
|
-
|
3924
|
-
|
3925
|
-
|
3926
|
-
|
3927
|
-
|
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
|
-
|
3932
|
-
|
3933
|
-
|
3934
|
-
|
3935
|
-
|
3936
|
-
|
3937
|
-
|
3938
|
-
|
3939
|
-
|
3940
|
-
|
3941
|
-
|
3942
|
-
|
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
|
-
|
3946
|
-
|
3947
|
-
|
3948
|
-
|
3949
|
-
|
3950
|
-
|
3951
|
-
|
3952
|
-
|
3953
|
-
|
3954
|
-
|
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
|
-
|
3961
|
-
|
3962
|
-
|
3963
|
-
|
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
|
-
|
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
|
-
|
4016
|
-
|
4017
|
-
|
4018
|
-
|
4019
|
-
|
4020
|
-
|
4021
|
-
|
4022
|
-
|
4023
|
-
|
4024
|
-
|
4025
|
-
|
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,
|
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
|
-
*
|
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) ?
|
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
|
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->
|
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,
|
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
|
-
|
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,
|
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, "
|
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, "
|
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
|
-
*
|
5035
|
-
* Note: % must
|
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 (
|
5072
|
-
|
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 (
|
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
|
-
|
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,
|
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 (
|
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, "
|
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
|
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 (
|
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
|
5753
|
-
if (
|
5754
|
-
|
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 (
|
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, "
|
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 && (
|
6223
|
+
if (fracf && BIGDECIMAL_POSITIVE_P(y)) ++div;
|
5958
6224
|
break;
|
5959
6225
|
case VP_ROUND_FLOOR:
|
5960
|
-
if (fracf && (
|
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 && (
|
6345
|
+
if (v && BIGDECIMAL_POSITIVE_P(c)) f = 1;
|
6080
6346
|
break;
|
6081
6347
|
case VP_ROUND_FLOOR:
|
6082
|
-
if (v && (
|
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 (
|
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=%
|
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"]=%
|
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 =%
|
6568
|
+
printf(" BASE =%"PRIuBDIGIT"\n", BASE);
|
6303
6569
|
return 3;
|
6304
6570
|
}
|
6305
6571
|
}
|