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