bigdecimal 2.0.3 → 3.1.1
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 +4 -4
- data/bigdecimal.gemspec +8 -9
- data/ext/bigdecimal/bigdecimal.c +1555 -787
- data/ext/bigdecimal/bigdecimal.h +67 -170
- data/ext/bigdecimal/bits.h +141 -0
- data/ext/bigdecimal/extconf.rb +38 -4
- data/ext/bigdecimal/feature.h +68 -0
- data/ext/bigdecimal/missing/dtoa.c +3462 -0
- data/ext/bigdecimal/missing.c +27 -0
- data/ext/bigdecimal/missing.h +235 -0
- data/ext/bigdecimal/static_assert.h +54 -0
- data/lib/bigdecimal/util.rb +1 -1
- metadata +11 -61
data/ext/bigdecimal/bigdecimal.c
CHANGED
@@ -30,14 +30,11 @@
|
|
30
30
|
#include <ieeefp.h>
|
31
31
|
#endif
|
32
32
|
|
33
|
+
#include "bits.h"
|
34
|
+
#include "static_assert.h"
|
35
|
+
|
33
36
|
/* #define ENABLE_NUMERIC_STRING */
|
34
37
|
|
35
|
-
#define MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max) ( \
|
36
|
-
(a) == 0 ? 0 : \
|
37
|
-
(a) == -1 ? (b) < -(max) : \
|
38
|
-
(a) > 0 ? \
|
39
|
-
((b) > 0 ? (max) / (a) < (b) : (min) / (a) > (b)) : \
|
40
|
-
((b) > 0 ? (min) / (a) < (b) : (max) / (a) > (b)))
|
41
38
|
#define SIGNED_VALUE_MAX INTPTR_MAX
|
42
39
|
#define SIGNED_VALUE_MIN INTPTR_MIN
|
43
40
|
#define MUL_OVERFLOW_SIGNED_VALUE_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, SIGNED_VALUE_MIN, SIGNED_VALUE_MAX)
|
@@ -65,20 +62,22 @@ static ID id_eq;
|
|
65
62
|
static ID id_half;
|
66
63
|
|
67
64
|
/* MACRO's to guard objects from GC by keeping them in stack */
|
65
|
+
#ifdef RBIMPL_ATTR_MAYBE_UNUSED
|
66
|
+
#define ENTER(n) RBIMPL_ATTR_MAYBE_UNUSED() volatile VALUE vStack[n];int iStack=0
|
67
|
+
#else
|
68
68
|
#define ENTER(n) volatile VALUE RB_UNUSED_VAR(vStack[n]);int iStack=0
|
69
|
+
#endif
|
69
70
|
#define PUSH(x) (vStack[iStack++] = (VALUE)(x))
|
70
71
|
#define SAVE(p) PUSH((p)->obj)
|
71
72
|
#define GUARD_OBJ(p,y) ((p)=(y), SAVE(p))
|
72
73
|
|
73
|
-
#define BASE_FIG
|
74
|
-
#define BASE
|
74
|
+
#define BASE_FIG BIGDECIMAL_COMPONENT_FIGURES
|
75
|
+
#define BASE BIGDECIMAL_BASE
|
75
76
|
|
76
77
|
#define HALF_BASE (BASE/2)
|
77
78
|
#define BASE1 (BASE/10)
|
78
79
|
|
79
|
-
#
|
80
|
-
#define DBLE_FIG rmpd_double_figures() /* figure of double */
|
81
|
-
#endif
|
80
|
+
#define LOG10_2 0.3010299956639812
|
82
81
|
|
83
82
|
#ifndef RRATIONAL_ZERO_P
|
84
83
|
# define RRATIONAL_ZERO_P(x) (FIXNUM_P(rb_rational_num(x)) && \
|
@@ -103,54 +102,6 @@ static ID id_half;
|
|
103
102
|
# define RB_OBJ_STRING(obj) StringValueCStr(obj)
|
104
103
|
#endif
|
105
104
|
|
106
|
-
#ifndef HAVE_RB_RATIONAL_NUM
|
107
|
-
static inline VALUE
|
108
|
-
rb_rational_num(VALUE rat)
|
109
|
-
{
|
110
|
-
#ifdef HAVE_TYPE_STRUCT_RRATIONAL
|
111
|
-
return RRATIONAL(rat)->num;
|
112
|
-
#else
|
113
|
-
return rb_funcall(rat, rb_intern("numerator"), 0);
|
114
|
-
#endif
|
115
|
-
}
|
116
|
-
#endif
|
117
|
-
|
118
|
-
#ifndef HAVE_RB_RATIONAL_DEN
|
119
|
-
static inline VALUE
|
120
|
-
rb_rational_den(VALUE rat)
|
121
|
-
{
|
122
|
-
#ifdef HAVE_TYPE_STRUCT_RRATIONAL
|
123
|
-
return RRATIONAL(rat)->den;
|
124
|
-
#else
|
125
|
-
return rb_funcall(rat, rb_intern("denominator"), 0);
|
126
|
-
#endif
|
127
|
-
}
|
128
|
-
#endif
|
129
|
-
|
130
|
-
#ifndef HAVE_RB_COMPLEX_REAL
|
131
|
-
static inline VALUE
|
132
|
-
rb_complex_real(VALUE cmp)
|
133
|
-
{
|
134
|
-
#ifdef HAVE_TYPE_STRUCT_RCOMPLEX
|
135
|
-
return RCOMPLEX(cmp)->real;
|
136
|
-
#else
|
137
|
-
return rb_funcall(cmp, rb_intern("real"), 0);
|
138
|
-
#endif
|
139
|
-
}
|
140
|
-
#endif
|
141
|
-
|
142
|
-
#ifndef HAVE_RB_COMPLEX_IMAG
|
143
|
-
static inline VALUE
|
144
|
-
rb_complex_imag(VALUE cmp)
|
145
|
-
{
|
146
|
-
#ifdef HAVE_TYPE_STRUCT_RCOMPLEX
|
147
|
-
return RCOMPLEX(cmp)->imag;
|
148
|
-
#else
|
149
|
-
return rb_funcall(cmp, rb_intern("imag"), 0);
|
150
|
-
#endif
|
151
|
-
}
|
152
|
-
#endif
|
153
|
-
|
154
105
|
#define BIGDECIMAL_POSITIVE_P(bd) ((bd)->sign > 0)
|
155
106
|
#define BIGDECIMAL_NEGATIVE_P(bd) ((bd)->sign < 0)
|
156
107
|
|
@@ -164,7 +115,9 @@ rb_complex_imag(VALUE cmp)
|
|
164
115
|
*/
|
165
116
|
static unsigned short VpGetException(void);
|
166
117
|
static void VpSetException(unsigned short f);
|
167
|
-
static void
|
118
|
+
static void VpCheckException(Real *p, bool always);
|
119
|
+
static VALUE VpCheckGetValue(Real *p);
|
120
|
+
static void VpInternalRound(Real *c, size_t ixDigit, DECDIG vPrev, DECDIG v);
|
168
121
|
static int VpLimitRound(Real *c, size_t ixDigit);
|
169
122
|
static Real *VpCopy(Real *pv, Real const* const x);
|
170
123
|
|
@@ -176,6 +129,12 @@ static int VPrint(FILE *fp,const char *cntl_chr,Real *a);
|
|
176
129
|
* **** BigDecimal part ****
|
177
130
|
*/
|
178
131
|
|
132
|
+
static VALUE BigDecimal_nan(void);
|
133
|
+
static VALUE BigDecimal_positive_infinity(void);
|
134
|
+
static VALUE BigDecimal_negative_infinity(void);
|
135
|
+
static VALUE BigDecimal_positive_zero(void);
|
136
|
+
static VALUE BigDecimal_negative_zero(void);
|
137
|
+
|
179
138
|
static void
|
180
139
|
BigDecimal_delete(void *pv)
|
181
140
|
{
|
@@ -186,14 +145,19 @@ static size_t
|
|
186
145
|
BigDecimal_memsize(const void *ptr)
|
187
146
|
{
|
188
147
|
const Real *pv = ptr;
|
189
|
-
return (sizeof(*pv) + pv->MaxPrec * sizeof(
|
148
|
+
return (sizeof(*pv) + pv->MaxPrec * sizeof(DECDIG));
|
190
149
|
}
|
191
150
|
|
151
|
+
#ifndef HAVE_RB_EXT_RACTOR_SAFE
|
152
|
+
# undef RUBY_TYPED_FROZEN_SHAREABLE
|
153
|
+
# define RUBY_TYPED_FROZEN_SHAREABLE 0
|
154
|
+
#endif
|
155
|
+
|
192
156
|
static const rb_data_type_t BigDecimal_data_type = {
|
193
157
|
"BigDecimal",
|
194
158
|
{ 0, BigDecimal_delete, BigDecimal_memsize, },
|
195
159
|
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
|
196
|
-
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
|
160
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE
|
197
161
|
#endif
|
198
162
|
};
|
199
163
|
|
@@ -203,21 +167,6 @@ is_kind_of_BigDecimal(VALUE const v)
|
|
203
167
|
return rb_typeddata_is_kind_of(v, &BigDecimal_data_type);
|
204
168
|
}
|
205
169
|
|
206
|
-
static VALUE
|
207
|
-
ToValue(Real *p)
|
208
|
-
{
|
209
|
-
if (VpIsNaN(p)) {
|
210
|
-
VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'(Not a Number)", 0);
|
211
|
-
}
|
212
|
-
else if (VpIsPosInf(p)) {
|
213
|
-
VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 0);
|
214
|
-
}
|
215
|
-
else if (VpIsNegInf(p)) {
|
216
|
-
VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 0);
|
217
|
-
}
|
218
|
-
return p->obj;
|
219
|
-
}
|
220
|
-
|
221
170
|
NORETURN(static void cannot_be_coerced_into_BigDecimal(VALUE, VALUE));
|
222
171
|
|
223
172
|
static void
|
@@ -237,95 +186,67 @@ cannot_be_coerced_into_BigDecimal(VALUE exc_class, VALUE v)
|
|
237
186
|
}
|
238
187
|
|
239
188
|
static inline VALUE BigDecimal_div2(VALUE, VALUE, VALUE);
|
189
|
+
static VALUE rb_inum_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception);
|
190
|
+
static VALUE rb_float_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception);
|
191
|
+
static VALUE rb_rational_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception);
|
192
|
+
static VALUE rb_cstr_convert_to_BigDecimal(const char *c_str, size_t digs, int raise_exception);
|
193
|
+
static VALUE rb_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception);
|
240
194
|
|
241
195
|
static Real*
|
242
196
|
GetVpValueWithPrec(VALUE v, long prec, int must)
|
243
197
|
{
|
244
|
-
|
245
|
-
Real *pv;
|
246
|
-
VALUE num, bg;
|
247
|
-
char szD[128];
|
248
|
-
VALUE orig = Qundef;
|
249
|
-
double d;
|
198
|
+
const size_t digs = prec < 0 ? SIZE_MAX : (size_t)prec;
|
250
199
|
|
251
|
-
again:
|
252
200
|
switch(TYPE(v)) {
|
253
201
|
case T_FLOAT:
|
254
|
-
|
255
|
-
|
256
|
-
d = RFLOAT_VALUE(v);
|
257
|
-
if (!isfinite(d)) {
|
258
|
-
pv = VpCreateRbObject(1, NULL);
|
259
|
-
VpDtoV(pv, d);
|
260
|
-
return pv;
|
261
|
-
}
|
262
|
-
if (d != 0.0) {
|
263
|
-
v = rb_funcall(v, id_to_r, 0);
|
264
|
-
goto again;
|
265
|
-
}
|
266
|
-
if (1/d < 0.0) {
|
267
|
-
return VpCreateRbObject(prec, "-0");
|
268
|
-
}
|
269
|
-
return VpCreateRbObject(prec, "0");
|
202
|
+
v = rb_float_convert_to_BigDecimal(v, digs, must);
|
203
|
+
break;
|
270
204
|
|
271
205
|
case T_RATIONAL:
|
272
|
-
|
273
|
-
|
274
|
-
if (orig == Qundef ? (orig = v, 1) : orig != v) {
|
275
|
-
num = rb_rational_num(v);
|
276
|
-
pv = GetVpValueWithPrec(num, -1, must);
|
277
|
-
if (pv == NULL) goto SomeOneMayDoIt;
|
278
|
-
|
279
|
-
v = BigDecimal_div2(ToValue(pv), rb_rational_den(v), LONG2NUM(prec));
|
280
|
-
goto again;
|
281
|
-
}
|
282
|
-
|
283
|
-
v = orig;
|
284
|
-
goto SomeOneMayDoIt;
|
206
|
+
v = rb_rational_convert_to_BigDecimal(v, digs, must);
|
207
|
+
break;
|
285
208
|
|
286
209
|
case T_DATA:
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
else {
|
292
|
-
goto SomeOneMayDoIt;
|
293
|
-
}
|
294
|
-
break;
|
210
|
+
if (!is_kind_of_BigDecimal(v)) {
|
211
|
+
goto SomeOneMayDoIt;
|
212
|
+
}
|
213
|
+
break;
|
295
214
|
|
296
|
-
case T_FIXNUM:
|
297
|
-
|
298
|
-
|
215
|
+
case T_FIXNUM: {
|
216
|
+
char szD[128];
|
217
|
+
sprintf(szD, "%ld", FIX2LONG(v));
|
218
|
+
v = rb_cstr_convert_to_BigDecimal(szD, VpBaseFig() * 2 + 1, must);
|
219
|
+
break;
|
220
|
+
}
|
299
221
|
|
300
222
|
#ifdef ENABLE_NUMERIC_STRING
|
301
|
-
case T_STRING:
|
302
|
-
|
303
|
-
|
304
|
-
|
223
|
+
case T_STRING: {
|
224
|
+
const char *c_str = StringValueCStr(v);
|
225
|
+
v = rb_cstr_convert_to_BigDecimal(c_str, RSTRING_LEN(v) + VpBaseFig() + 1, must);
|
226
|
+
break;
|
227
|
+
}
|
305
228
|
#endif /* ENABLE_NUMERIC_STRING */
|
306
229
|
|
307
|
-
case T_BIGNUM:
|
308
|
-
bg = rb_big2str(v, 10);
|
309
|
-
|
310
|
-
|
311
|
-
|
230
|
+
case T_BIGNUM: {
|
231
|
+
VALUE bg = rb_big2str(v, 10);
|
232
|
+
v = rb_cstr_convert_to_BigDecimal(RSTRING_PTR(bg), RSTRING_LEN(bg) + VpBaseFig() + 1, must);
|
233
|
+
RB_GC_GUARD(bg);
|
234
|
+
break;
|
235
|
+
}
|
236
|
+
|
312
237
|
default:
|
313
238
|
goto SomeOneMayDoIt;
|
314
239
|
}
|
315
240
|
|
241
|
+
Real *vp;
|
242
|
+
TypedData_Get_Struct(v, Real, &BigDecimal_data_type, vp);
|
243
|
+
return vp;
|
244
|
+
|
316
245
|
SomeOneMayDoIt:
|
317
246
|
if (must) {
|
318
247
|
cannot_be_coerced_into_BigDecimal(rb_eTypeError, v);
|
319
248
|
}
|
320
249
|
return NULL; /* NULL means to coerce */
|
321
|
-
|
322
|
-
unable_to_coerce_without_prec:
|
323
|
-
if (must) {
|
324
|
-
rb_raise(rb_eArgError,
|
325
|
-
"%"PRIsVALUE" can't be coerced into BigDecimal without a precision",
|
326
|
-
RB_OBJ_CLASSNAME(v));
|
327
|
-
}
|
328
|
-
return NULL;
|
329
250
|
}
|
330
251
|
|
331
252
|
static Real*
|
@@ -335,11 +256,13 @@ GetVpValue(VALUE v, int must)
|
|
335
256
|
}
|
336
257
|
|
337
258
|
/* call-seq:
|
338
|
-
*
|
259
|
+
* BigDecimal.double_fig -> integer
|
260
|
+
*
|
261
|
+
* Returns the number of digits a Float object is allowed to have;
|
262
|
+
* the result is system-dependent:
|
263
|
+
*
|
264
|
+
* BigDecimal.double_fig # => 16
|
339
265
|
*
|
340
|
-
* The BigDecimal.double_fig class method returns the number of digits a
|
341
|
-
* Float number is allowed to have. The result depends upon the CPU and OS
|
342
|
-
* in use.
|
343
266
|
*/
|
344
267
|
static VALUE
|
345
268
|
BigDecimal_double_fig(VALUE self)
|
@@ -348,7 +271,7 @@ BigDecimal_double_fig(VALUE self)
|
|
348
271
|
}
|
349
272
|
|
350
273
|
/* call-seq:
|
351
|
-
*
|
274
|
+
* precs -> array
|
352
275
|
*
|
353
276
|
* Returns an Array of two Integer values that represent platform-dependent
|
354
277
|
* internal storage properties.
|
@@ -358,7 +281,6 @@ BigDecimal_double_fig(VALUE self)
|
|
358
281
|
* significant digits in scientific notation, and BigDecimal#precision for
|
359
282
|
* obtaining the number of digits in decimal notation.
|
360
283
|
*
|
361
|
-
* BigDecimal('5').precs #=> [9, 18]
|
362
284
|
*/
|
363
285
|
|
364
286
|
static VALUE
|
@@ -378,73 +300,202 @@ BigDecimal_prec(VALUE self)
|
|
378
300
|
return obj;
|
379
301
|
}
|
380
302
|
|
381
|
-
|
382
|
-
*
|
383
|
-
* big_decimal.precision -> intreger
|
384
|
-
*
|
385
|
-
* Returns the number of decimal digits in this number.
|
386
|
-
*
|
387
|
-
* Example:
|
388
|
-
*
|
389
|
-
* BigDecimal("0").precision # => 0
|
390
|
-
* BigDecimal("1").precision # => 1
|
391
|
-
* BigDecimal("-1e20").precision # => 21
|
392
|
-
* BigDecimal("1e-20").precision # => 20
|
393
|
-
* BigDecimal("Infinity").precision # => 0
|
394
|
-
* BigDecimal("-Infinity").precision # => 0
|
395
|
-
* BigDecimal("NaN").precision # => 0
|
396
|
-
*/
|
397
|
-
static VALUE
|
398
|
-
BigDecimal_precision(VALUE self)
|
303
|
+
static void
|
304
|
+
BigDecimal_count_precision_and_scale(VALUE self, ssize_t *out_precision, ssize_t *out_scale)
|
399
305
|
{
|
400
306
|
ENTER(1);
|
401
307
|
|
308
|
+
if (out_precision == NULL && out_scale == NULL)
|
309
|
+
return;
|
310
|
+
|
402
311
|
Real *p;
|
403
312
|
GUARD_OBJ(p, GetVpValue(self, 1));
|
313
|
+
if (VpIsZero(p) || !VpIsDef(p)) {
|
314
|
+
zero:
|
315
|
+
if (out_precision) *out_precision = 0;
|
316
|
+
if (out_scale) *out_scale = 0;
|
317
|
+
return;
|
318
|
+
}
|
319
|
+
|
320
|
+
DECDIG x;
|
321
|
+
|
322
|
+
ssize_t n = p->Prec; /* The length of frac without zeros. */
|
323
|
+
while (n > 0 && p->frac[n-1] == 0) --n;
|
324
|
+
if (n == 0) goto zero;
|
325
|
+
|
326
|
+
int nlz = BASE_FIG;
|
327
|
+
for (x = p->frac[0]; x > 0; x /= 10) --nlz;
|
328
|
+
|
329
|
+
int ntz = 0;
|
330
|
+
for (x = p->frac[n-1]; x > 0 && x % 10 == 0; x /= 10) ++ntz;
|
404
331
|
|
405
332
|
/*
|
406
|
-
*
|
407
|
-
*
|
333
|
+
* Calculate the precision and the scale
|
334
|
+
* -------------------------------------
|
335
|
+
*
|
336
|
+
* The most significant digit is frac[0], and the least significant digit
|
337
|
+
* is frac[Prec-1]. When the exponent is zero, the decimal point is
|
338
|
+
* located just before frac[0].
|
339
|
+
*
|
408
340
|
* When the exponent is negative, the decimal point moves to leftward.
|
409
|
-
*
|
341
|
+
* In this case, the precision can be calculated by
|
342
|
+
*
|
343
|
+
* precision = BASE_FIG * (-exponent + n) - ntz,
|
344
|
+
*
|
345
|
+
* and the scale is the same as precision.
|
346
|
+
*
|
347
|
+
* 0 . 0000 0000 | frac[0] ... frac[n-1] |
|
348
|
+
* |<----------| exponent == -2 |
|
349
|
+
* |---------------------------------->| precision
|
350
|
+
* |---------------------------------->| scale
|
351
|
+
*
|
352
|
+
*
|
353
|
+
* Conversely, when the exponent is positive, the decimal point moves to
|
354
|
+
* rightward. In this case, the scale equals to
|
355
|
+
*
|
356
|
+
* BASE_FIG * (n - exponent) - ntz.
|
410
357
|
*
|
411
|
-
*
|
412
|
-
*
|
358
|
+
* the precision equals to
|
359
|
+
*
|
360
|
+
* scale + BASE_FIG * exponent - nlz.
|
361
|
+
*
|
362
|
+
* | frac[0] frac[1] . frac[2] ... frac[n-1] |
|
363
|
+
* |---------------->| exponent == 2 |
|
364
|
+
* | |---------------------->| scale
|
365
|
+
* |---------------------------------------->| precision
|
413
366
|
*/
|
414
367
|
|
415
368
|
ssize_t ex = p->exponent;
|
416
|
-
|
369
|
+
|
370
|
+
/* Count the number of decimal digits before frac[1]. */
|
371
|
+
ssize_t n_digits_head = BASE_FIG;
|
417
372
|
if (ex < 0) {
|
418
|
-
|
419
|
-
|
373
|
+
n_digits_head += (-ex) * BASE_FIG; /* The number of leading zeros before frac[0]. */
|
374
|
+
ex = 0;
|
420
375
|
}
|
421
|
-
else if (
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
376
|
+
else if (ex > 0) {
|
377
|
+
/* Count the number of decimal digits without the leading zeros in
|
378
|
+
* the most significant digit in the integral part.
|
379
|
+
*/
|
380
|
+
n_digits_head -= nlz; /* Make the number of digits */
|
426
381
|
}
|
427
382
|
|
428
|
-
if (
|
429
|
-
precision
|
383
|
+
if (out_precision) {
|
384
|
+
ssize_t precision = n_digits_head;
|
385
|
+
|
386
|
+
/* Count the number of decimal digits after frac[0]. */
|
387
|
+
if (ex > (ssize_t)n) {
|
388
|
+
/* In this case the number is an integer with some trailing zeros. */
|
389
|
+
precision += (ex - 1) * BASE_FIG;
|
390
|
+
}
|
391
|
+
else if (n > 0) {
|
392
|
+
precision += (n - 1) * BASE_FIG;
|
393
|
+
|
394
|
+
if (ex < (ssize_t)n) {
|
395
|
+
precision -= ntz;
|
396
|
+
}
|
397
|
+
}
|
398
|
+
|
399
|
+
*out_precision = precision;
|
430
400
|
}
|
431
|
-
else if (p->Prec > 0) {
|
432
|
-
ssize_t n = (ssize_t)p->Prec - 1;
|
433
|
-
while (n > 0 && p->frac[n] == 0) --n;
|
434
401
|
|
435
|
-
|
402
|
+
if (out_scale) {
|
403
|
+
ssize_t scale = 0;
|
436
404
|
|
437
|
-
if (
|
438
|
-
|
439
|
-
for (; x > 0 && x % 10 == 0; x /= 10) {
|
440
|
-
--precision;
|
441
|
-
}
|
405
|
+
if (p->exponent < 0) {
|
406
|
+
scale = n_digits_head + (n - 1) * BASE_FIG - ntz;
|
442
407
|
}
|
408
|
+
else if (n > p->exponent) {
|
409
|
+
scale = (n - p->exponent) * BASE_FIG - ntz;
|
410
|
+
}
|
411
|
+
|
412
|
+
*out_scale = scale;
|
443
413
|
}
|
414
|
+
}
|
444
415
|
|
416
|
+
/*
|
417
|
+
* call-seq:
|
418
|
+
* precision -> integer
|
419
|
+
*
|
420
|
+
* Returns the number of decimal digits in +self+:
|
421
|
+
*
|
422
|
+
* BigDecimal("0").precision # => 0
|
423
|
+
* BigDecimal("1").precision # => 1
|
424
|
+
* BigDecimal("1.1").precision # => 2
|
425
|
+
* BigDecimal("3.1415").precision # => 5
|
426
|
+
* BigDecimal("-1e20").precision # => 21
|
427
|
+
* BigDecimal("1e-20").precision # => 20
|
428
|
+
* BigDecimal("Infinity").precision # => 0
|
429
|
+
* BigDecimal("-Infinity").precision # => 0
|
430
|
+
* BigDecimal("NaN").precision # => 0
|
431
|
+
*
|
432
|
+
*/
|
433
|
+
static VALUE
|
434
|
+
BigDecimal_precision(VALUE self)
|
435
|
+
{
|
436
|
+
ssize_t precision;
|
437
|
+
BigDecimal_count_precision_and_scale(self, &precision, NULL);
|
445
438
|
return SSIZET2NUM(precision);
|
446
439
|
}
|
447
440
|
|
441
|
+
/*
|
442
|
+
* call-seq:
|
443
|
+
* scale -> integer
|
444
|
+
*
|
445
|
+
* Returns the number of decimal digits following the decimal digits in +self+.
|
446
|
+
*
|
447
|
+
* BigDecimal("0").scale # => 0
|
448
|
+
* BigDecimal("1").scale # => 1
|
449
|
+
* BigDecimal("1.1").scale # => 1
|
450
|
+
* BigDecimal("3.1415").scale # => 4
|
451
|
+
* BigDecimal("-1e20").precision # => 0
|
452
|
+
* BigDecimal("1e-20").precision # => 20
|
453
|
+
* BigDecimal("Infinity").scale # => 0
|
454
|
+
* BigDecimal("-Infinity").scale # => 0
|
455
|
+
* BigDecimal("NaN").scale # => 0
|
456
|
+
*/
|
457
|
+
static VALUE
|
458
|
+
BigDecimal_scale(VALUE self)
|
459
|
+
{
|
460
|
+
ssize_t scale;
|
461
|
+
BigDecimal_count_precision_and_scale(self, NULL, &scale);
|
462
|
+
return SSIZET2NUM(scale);
|
463
|
+
}
|
464
|
+
|
465
|
+
/*
|
466
|
+
* call-seq:
|
467
|
+
* precision_scale -> [integer, integer]
|
468
|
+
*
|
469
|
+
* Returns a 2-length array; the first item is the result of
|
470
|
+
* BigDecimal#precision and the second one is of BigDecimal#scale.
|
471
|
+
*
|
472
|
+
* See BigDecimal#precision.
|
473
|
+
* See BigDecimal#scale.
|
474
|
+
*/
|
475
|
+
static VALUE
|
476
|
+
BigDecimal_precision_scale(VALUE self)
|
477
|
+
{
|
478
|
+
ssize_t precision, scale;
|
479
|
+
BigDecimal_count_precision_and_scale(self, &precision, &scale);
|
480
|
+
return rb_assoc_new(SSIZET2NUM(precision), SSIZET2NUM(scale));
|
481
|
+
}
|
482
|
+
|
483
|
+
/*
|
484
|
+
* call-seq:
|
485
|
+
* n_significant_digits -> integer
|
486
|
+
*
|
487
|
+
* Returns the number of decimal significant digits in +self+.
|
488
|
+
*
|
489
|
+
* BigDecimal("0").scale # => 0
|
490
|
+
* BigDecimal("1").scale # => 1
|
491
|
+
* BigDecimal("1.1").scale # => 2
|
492
|
+
* BigDecimal("3.1415").scale # => 5
|
493
|
+
* BigDecimal("-1e20").precision # => 1
|
494
|
+
* BigDecimal("1e-20").precision # => 1
|
495
|
+
* BigDecimal("Infinity").scale # => 0
|
496
|
+
* BigDecimal("-Infinity").scale # => 0
|
497
|
+
* BigDecimal("NaN").scale # => 0
|
498
|
+
*/
|
448
499
|
static VALUE
|
449
500
|
BigDecimal_n_significant_digits(VALUE self)
|
450
501
|
{
|
@@ -452,32 +503,38 @@ BigDecimal_n_significant_digits(VALUE self)
|
|
452
503
|
|
453
504
|
Real *p;
|
454
505
|
GUARD_OBJ(p, GetVpValue(self, 1));
|
455
|
-
|
456
|
-
ssize_t n = p->Prec;
|
457
|
-
while (n > 0 && p->frac[n-1] == 0) --n;
|
458
|
-
if (n <= 0) {
|
506
|
+
if (VpIsZero(p) || !VpIsDef(p)) {
|
459
507
|
return INT2FIX(0);
|
460
508
|
}
|
461
509
|
|
462
|
-
|
510
|
+
ssize_t n = p->Prec; /* The length of frac without trailing zeros. */
|
511
|
+
for (n = p->Prec; n > 0 && p->frac[n-1] == 0; --n);
|
512
|
+
if (n == 0) return INT2FIX(0);
|
463
513
|
|
464
|
-
|
465
|
-
|
514
|
+
DECDIG x;
|
515
|
+
int nlz = BASE_FIG;
|
516
|
+
for (x = p->frac[0]; x > 0; x /= 10) --nlz;
|
466
517
|
|
467
|
-
|
468
|
-
for (
|
518
|
+
int ntz = 0;
|
519
|
+
for (x = p->frac[n-1]; x > 0 && x % 10 == 0; x /= 10) ++ntz;
|
469
520
|
|
470
|
-
ssize_t
|
471
|
-
return SSIZET2NUM(
|
521
|
+
ssize_t n_significant_digits = BASE_FIG*n - nlz - ntz;
|
522
|
+
return SSIZET2NUM(n_significant_digits);
|
472
523
|
}
|
473
524
|
|
474
525
|
/*
|
475
|
-
*
|
526
|
+
* call-seq:
|
527
|
+
* hash -> integer
|
528
|
+
*
|
529
|
+
* Returns the integer hash value for +self+.
|
530
|
+
*
|
531
|
+
* Two instances of \BigDecimal have the same hash value if and only if
|
532
|
+
* they have equal:
|
476
533
|
*
|
477
|
-
*
|
534
|
+
* - Sign.
|
535
|
+
* - Fractional part.
|
536
|
+
* - Exponent.
|
478
537
|
*
|
479
|
-
* Two BigDecimals with equal sign,
|
480
|
-
* fractional part and exponent have the same hash.
|
481
538
|
*/
|
482
539
|
static VALUE
|
483
540
|
BigDecimal_hash(VALUE self)
|
@@ -490,23 +547,23 @@ BigDecimal_hash(VALUE self)
|
|
490
547
|
hash = (st_index_t)p->sign;
|
491
548
|
/* hash!=2: the case for 0(1),NaN(0) or +-Infinity(3) is sign itself */
|
492
549
|
if(hash == 2 || hash == (st_index_t)-2) {
|
493
|
-
|
494
|
-
|
550
|
+
hash ^= rb_memhash(p->frac, sizeof(DECDIG)*p->Prec);
|
551
|
+
hash += p->exponent;
|
495
552
|
}
|
496
553
|
return ST2FIX(hash);
|
497
554
|
}
|
498
555
|
|
499
556
|
/*
|
500
|
-
*
|
557
|
+
* call-seq:
|
558
|
+
* _dump -> string
|
501
559
|
*
|
502
|
-
*
|
560
|
+
* Returns a string representing the marshalling of +self+.
|
561
|
+
* See module Marshal.
|
503
562
|
*
|
504
|
-
*
|
505
|
-
*
|
506
|
-
*
|
507
|
-
* #=> Infinity
|
563
|
+
* inf = BigDecimal('Infinity') # => Infinity
|
564
|
+
* dumped = inf._dump # => "9:Infinity"
|
565
|
+
* BigDecimal._load(dumped) # => Infinity
|
508
566
|
*
|
509
|
-
* See the Marshal module.
|
510
567
|
*/
|
511
568
|
static VALUE
|
512
569
|
BigDecimal_dump(int argc, VALUE *argv, VALUE self)
|
@@ -548,12 +605,12 @@ BigDecimal_load(VALUE self, VALUE str)
|
|
548
605
|
m = m*10 + (unsigned long)(ch-'0');
|
549
606
|
}
|
550
607
|
if (m > VpBaseFig()) m -= VpBaseFig();
|
551
|
-
GUARD_OBJ(pv, VpNewRbClass(m, (char *)pch, self));
|
608
|
+
GUARD_OBJ(pv, VpNewRbClass(m, (char *)pch, self, true, true));
|
552
609
|
m /= VpBaseFig();
|
553
610
|
if (m && pv->MaxPrec > m) {
|
554
611
|
pv->MaxPrec = m+1;
|
555
612
|
}
|
556
|
-
return
|
613
|
+
return VpCheckGetValue(pv);
|
557
614
|
}
|
558
615
|
|
559
616
|
static unsigned short
|
@@ -640,42 +697,166 @@ check_rounding_mode(VALUE const v)
|
|
640
697
|
return sw;
|
641
698
|
}
|
642
699
|
|
643
|
-
/*
|
644
|
-
*
|
645
|
-
*
|
646
|
-
*
|
647
|
-
*
|
648
|
-
*
|
649
|
-
*
|
650
|
-
*
|
651
|
-
*
|
652
|
-
* BigDecimal::
|
653
|
-
* BigDecimal::
|
654
|
-
* BigDecimal::
|
655
|
-
* BigDecimal::
|
656
|
-
* BigDecimal::
|
657
|
-
*
|
658
|
-
*
|
659
|
-
*
|
660
|
-
*
|
661
|
-
*
|
662
|
-
*
|
663
|
-
*
|
664
|
-
*
|
665
|
-
*
|
666
|
-
*
|
667
|
-
*
|
668
|
-
*
|
669
|
-
*
|
670
|
-
*
|
671
|
-
*
|
672
|
-
*
|
673
|
-
*
|
674
|
-
*
|
675
|
-
*
|
676
|
-
*
|
677
|
-
*
|
678
|
-
*
|
700
|
+
/* call-seq:
|
701
|
+
* BigDecimal.mode(mode, setting = nil) -> integer
|
702
|
+
*
|
703
|
+
* Returns an integer representing the mode settings
|
704
|
+
* for exception handling and rounding.
|
705
|
+
*
|
706
|
+
* These modes control exception handling:
|
707
|
+
*
|
708
|
+
* - \BigDecimal::EXCEPTION_NaN.
|
709
|
+
* - \BigDecimal::EXCEPTION_INFINITY.
|
710
|
+
* - \BigDecimal::EXCEPTION_UNDERFLOW.
|
711
|
+
* - \BigDecimal::EXCEPTION_OVERFLOW.
|
712
|
+
* - \BigDecimal::EXCEPTION_ZERODIVIDE.
|
713
|
+
* - \BigDecimal::EXCEPTION_ALL.
|
714
|
+
*
|
715
|
+
* Values for +setting+ for exception handling:
|
716
|
+
*
|
717
|
+
* - +true+: sets the given +mode+ to +true+.
|
718
|
+
* - +false+: sets the given +mode+ to +false+.
|
719
|
+
* - +nil+: does not modify the mode settings.
|
720
|
+
*
|
721
|
+
* You can use method BigDecimal.save_exception_mode
|
722
|
+
* to temporarily change, and then automatically restore, exception modes.
|
723
|
+
*
|
724
|
+
* For clarity, some examples below begin by setting all
|
725
|
+
* exception modes to +false+.
|
726
|
+
*
|
727
|
+
* This mode controls the way rounding is to be performed:
|
728
|
+
*
|
729
|
+
* - \BigDecimal::ROUND_MODE
|
730
|
+
*
|
731
|
+
* You can use method BigDecimal.save_rounding_mode
|
732
|
+
* to temporarily change, and then automatically restore, the rounding mode.
|
733
|
+
*
|
734
|
+
* <b>NaNs</b>
|
735
|
+
*
|
736
|
+
* Mode \BigDecimal::EXCEPTION_NaN controls behavior
|
737
|
+
* when a \BigDecimal NaN is created.
|
738
|
+
*
|
739
|
+
* Settings:
|
740
|
+
*
|
741
|
+
* - +false+ (default): Returns <tt>BigDecimal('NaN')</tt>.
|
742
|
+
* - +true+: Raises FloatDomainError.
|
743
|
+
*
|
744
|
+
* Examples:
|
745
|
+
*
|
746
|
+
* BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0
|
747
|
+
* BigDecimal('NaN') # => NaN
|
748
|
+
* BigDecimal.mode(BigDecimal::EXCEPTION_NaN, true) # => 2
|
749
|
+
* BigDecimal('NaN') # Raises FloatDomainError
|
750
|
+
*
|
751
|
+
* <b>Infinities</b>
|
752
|
+
*
|
753
|
+
* Mode \BigDecimal::EXCEPTION_INFINITY controls behavior
|
754
|
+
* when a \BigDecimal Infinity or -Infinity is created.
|
755
|
+
* Settings:
|
756
|
+
*
|
757
|
+
* - +false+ (default): Returns <tt>BigDecimal('Infinity')</tt>
|
758
|
+
* or <tt>BigDecimal('-Infinity')</tt>.
|
759
|
+
* - +true+: Raises FloatDomainError.
|
760
|
+
*
|
761
|
+
* Examples:
|
762
|
+
*
|
763
|
+
* BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0
|
764
|
+
* BigDecimal('Infinity') # => Infinity
|
765
|
+
* BigDecimal('-Infinity') # => -Infinity
|
766
|
+
* BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, true) # => 1
|
767
|
+
* BigDecimal('Infinity') # Raises FloatDomainError
|
768
|
+
* BigDecimal('-Infinity') # Raises FloatDomainError
|
769
|
+
*
|
770
|
+
* <b>Underflow</b>
|
771
|
+
*
|
772
|
+
* Mode \BigDecimal::EXCEPTION_UNDERFLOW controls behavior
|
773
|
+
* when a \BigDecimal underflow occurs.
|
774
|
+
* Settings:
|
775
|
+
*
|
776
|
+
* - +false+ (default): Returns <tt>BigDecimal('0')</tt>
|
777
|
+
* or <tt>BigDecimal('-Infinity')</tt>.
|
778
|
+
* - +true+: Raises FloatDomainError.
|
779
|
+
*
|
780
|
+
* Examples:
|
781
|
+
*
|
782
|
+
* BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0
|
783
|
+
* def flow_under
|
784
|
+
* x = BigDecimal('0.1')
|
785
|
+
* 100.times { x *= x }
|
786
|
+
* end
|
787
|
+
* flow_under # => 100
|
788
|
+
* BigDecimal.mode(BigDecimal::EXCEPTION_UNDERFLOW, true) # => 4
|
789
|
+
* flow_under # Raises FloatDomainError
|
790
|
+
*
|
791
|
+
* <b>Overflow</b>
|
792
|
+
*
|
793
|
+
* Mode \BigDecimal::EXCEPTION_OVERFLOW controls behavior
|
794
|
+
* when a \BigDecimal overflow occurs.
|
795
|
+
* Settings:
|
796
|
+
*
|
797
|
+
* - +false+ (default): Returns <tt>BigDecimal('Infinity')</tt>
|
798
|
+
* or <tt>BigDecimal('-Infinity')</tt>.
|
799
|
+
* - +true+: Raises FloatDomainError.
|
800
|
+
*
|
801
|
+
* Examples:
|
802
|
+
*
|
803
|
+
* BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0
|
804
|
+
* def flow_over
|
805
|
+
* x = BigDecimal('10')
|
806
|
+
* 100.times { x *= x }
|
807
|
+
* end
|
808
|
+
* flow_over # => 100
|
809
|
+
* BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, true) # => 1
|
810
|
+
* flow_over # Raises FloatDomainError
|
811
|
+
*
|
812
|
+
* <b>Zero Division</b>
|
813
|
+
*
|
814
|
+
* Mode \BigDecimal::EXCEPTION_ZERODIVIDE controls behavior
|
815
|
+
* when a zero-division occurs.
|
816
|
+
* Settings:
|
817
|
+
*
|
818
|
+
* - +false+ (default): Returns <tt>BigDecimal('Infinity')</tt>
|
819
|
+
* or <tt>BigDecimal('-Infinity')</tt>.
|
820
|
+
* - +true+: Raises FloatDomainError.
|
821
|
+
*
|
822
|
+
* Examples:
|
823
|
+
*
|
824
|
+
* BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0
|
825
|
+
* one = BigDecimal('1')
|
826
|
+
* zero = BigDecimal('0')
|
827
|
+
* one / zero # => Infinity
|
828
|
+
* BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, true) # => 16
|
829
|
+
* one / zero # Raises FloatDomainError
|
830
|
+
*
|
831
|
+
* <b>All Exceptions</b>
|
832
|
+
*
|
833
|
+
* Mode \BigDecimal::EXCEPTION_ALL controls all of the above:
|
834
|
+
*
|
835
|
+
* BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0
|
836
|
+
* BigDecimal.mode(BigDecimal::EXCEPTION_ALL, true) # => 23
|
837
|
+
*
|
838
|
+
* <b>Rounding</b>
|
839
|
+
*
|
840
|
+
* Mode \BigDecimal::ROUND_MODE controls the way rounding is to be performed;
|
841
|
+
* its +setting+ values are:
|
842
|
+
*
|
843
|
+
* - +ROUND_UP+: Round away from zero.
|
844
|
+
* Aliased as +:up+.
|
845
|
+
* - +ROUND_DOWN+: Round toward zero.
|
846
|
+
* Aliased as +:down+ and +:truncate+.
|
847
|
+
* - +ROUND_HALF_UP+: Round toward the nearest neighbor;
|
848
|
+
* if the neighbors are equidistant, round away from zero.
|
849
|
+
* Aliased as +:half_up+ and +:default+.
|
850
|
+
* - +ROUND_HALF_DOWN+: Round toward the nearest neighbor;
|
851
|
+
* if the neighbors are equidistant, round toward zero.
|
852
|
+
* Aliased as +:half_down+.
|
853
|
+
* - +ROUND_HALF_EVEN+ (Banker's rounding): Round toward the nearest neighbor;
|
854
|
+
* if the neighbors are equidistant, round toward the even neighbor.
|
855
|
+
* Aliased as +:half_even+ and +:banker+.
|
856
|
+
* - +ROUND_CEILING+: Round toward positive infinity.
|
857
|
+
* Aliased as +:ceiling+ and +:ceil+.
|
858
|
+
* - +ROUND_FLOOR+: Round toward negative infinity.
|
859
|
+
* Aliased as +:floor:+.
|
679
860
|
*
|
680
861
|
*/
|
681
862
|
static VALUE
|
@@ -763,25 +944,54 @@ GetPrecisionInt(VALUE v)
|
|
763
944
|
return n;
|
764
945
|
}
|
765
946
|
|
947
|
+
static VALUE
|
948
|
+
BigDecimal_wrap_struct(VALUE obj, Real *vp)
|
949
|
+
{
|
950
|
+
assert(is_kind_of_BigDecimal(obj));
|
951
|
+
assert(vp != NULL);
|
952
|
+
|
953
|
+
if (vp->obj == obj && RTYPEDDATA_DATA(obj) == vp)
|
954
|
+
return obj;
|
955
|
+
|
956
|
+
assert(RTYPEDDATA_DATA(obj) == NULL);
|
957
|
+
assert(vp->obj == 0);
|
958
|
+
|
959
|
+
RTYPEDDATA_DATA(obj) = vp;
|
960
|
+
vp->obj = obj;
|
961
|
+
RB_OBJ_FREEZE(obj);
|
962
|
+
return obj;
|
963
|
+
}
|
964
|
+
|
766
965
|
VP_EXPORT Real *
|
767
|
-
VpNewRbClass(size_t mx, const char *str, VALUE klass)
|
966
|
+
VpNewRbClass(size_t mx, const char *str, VALUE klass, bool strict_p, bool raise_exception)
|
768
967
|
{
|
769
968
|
VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
|
770
|
-
Real *pv = VpAlloc(mx, str,
|
771
|
-
|
772
|
-
|
773
|
-
|
969
|
+
Real *pv = VpAlloc(mx, str, strict_p, raise_exception);
|
970
|
+
if (!pv)
|
971
|
+
return NULL;
|
972
|
+
BigDecimal_wrap_struct(obj, pv);
|
774
973
|
return pv;
|
775
974
|
}
|
776
975
|
|
777
976
|
VP_EXPORT Real *
|
778
|
-
VpCreateRbObject(size_t mx, const char *str)
|
977
|
+
VpCreateRbObject(size_t mx, const char *str, bool raise_exception)
|
779
978
|
{
|
780
|
-
return VpNewRbClass(mx, str, rb_cBigDecimal);
|
979
|
+
return VpNewRbClass(mx, str, rb_cBigDecimal, true, raise_exception);
|
781
980
|
}
|
782
981
|
|
783
|
-
#define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(
|
784
|
-
|
982
|
+
#define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(DECDIG))
|
983
|
+
|
984
|
+
static Real *
|
985
|
+
VpReallocReal(Real *pv, size_t prec)
|
986
|
+
{
|
987
|
+
VALUE obj = pv ? pv->obj : 0;
|
988
|
+
Real *new_pv = (Real *)VpMemRealloc(pv, offsetof(Real, frac) + prec * sizeof(DECDIG));
|
989
|
+
if (obj) {
|
990
|
+
new_pv->obj = 0;
|
991
|
+
BigDecimal_wrap_struct(obj, new_pv);
|
992
|
+
}
|
993
|
+
return new_pv;
|
994
|
+
}
|
785
995
|
|
786
996
|
static Real *
|
787
997
|
VpCopy(Real *pv, Real const* const x)
|
@@ -794,7 +1004,7 @@ VpCopy(Real *pv, Real const* const x)
|
|
794
1004
|
pv->exponent = x->exponent;
|
795
1005
|
pv->sign = x->sign;
|
796
1006
|
pv->flag = x->flag;
|
797
|
-
MEMCPY(pv->frac, x->frac,
|
1007
|
+
MEMCPY(pv->frac, x->frac, DECDIG, pv->MaxPrec);
|
798
1008
|
|
799
1009
|
return pv;
|
800
1010
|
}
|
@@ -833,15 +1043,7 @@ BigDecimal_IsFinite(VALUE self)
|
|
833
1043
|
static void
|
834
1044
|
BigDecimal_check_num(Real *p)
|
835
1045
|
{
|
836
|
-
|
837
|
-
VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'(Not a Number)", 1);
|
838
|
-
}
|
839
|
-
else if (VpIsPosInf(p)) {
|
840
|
-
VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 1);
|
841
|
-
}
|
842
|
-
else if (VpIsNegInf(p)) {
|
843
|
-
VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 1);
|
844
|
-
}
|
1046
|
+
VpCheckException(p, true);
|
845
1047
|
}
|
846
1048
|
|
847
1049
|
static VALUE BigDecimal_split(VALUE self);
|
@@ -864,7 +1066,7 @@ BigDecimal_to_i(VALUE self)
|
|
864
1066
|
if (e <= 0) return INT2FIX(0);
|
865
1067
|
nf = VpBaseFig();
|
866
1068
|
if (e <= nf) {
|
867
|
-
return LONG2NUM((long)(VpGetSign(p) * (
|
1069
|
+
return LONG2NUM((long)(VpGetSign(p) * (DECDIG_DBL_SIGNED)p->frac[0]));
|
868
1070
|
}
|
869
1071
|
else {
|
870
1072
|
VALUE a = BigDecimal_split(self);
|
@@ -998,8 +1200,8 @@ BigDecimal_coerce(VALUE self, VALUE other)
|
|
998
1200
|
Real *b;
|
999
1201
|
|
1000
1202
|
if (RB_TYPE_P(other, T_FLOAT)) {
|
1001
|
-
GUARD_OBJ(b, GetVpValueWithPrec(other,
|
1002
|
-
|
1203
|
+
GUARD_OBJ(b, GetVpValueWithPrec(other, 0, 1));
|
1204
|
+
obj = rb_assoc_new(VpCheckGetValue(b), self);
|
1003
1205
|
}
|
1004
1206
|
else {
|
1005
1207
|
if (RB_TYPE_P(other, T_RATIONAL)) {
|
@@ -1016,12 +1218,14 @@ BigDecimal_coerce(VALUE self, VALUE other)
|
|
1016
1218
|
}
|
1017
1219
|
|
1018
1220
|
/*
|
1019
|
-
*
|
1020
|
-
* +big_decimal
|
1221
|
+
* call-seq:
|
1222
|
+
* +big_decimal -> self
|
1223
|
+
*
|
1224
|
+
* Returns +self+:
|
1021
1225
|
*
|
1022
|
-
*
|
1226
|
+
* +BigDecimal(5) # => 0.5e1
|
1227
|
+
* +BigDecimal(-5) # => -0.5e1
|
1023
1228
|
*
|
1024
|
-
* +BigDecimal('5') #=> 0.5e1
|
1025
1229
|
*/
|
1026
1230
|
|
1027
1231
|
static VALUE
|
@@ -1031,22 +1235,21 @@ BigDecimal_uplus(VALUE self)
|
|
1031
1235
|
}
|
1032
1236
|
|
1033
1237
|
/*
|
1034
|
-
*
|
1035
|
-
*
|
1238
|
+
* call-seq:
|
1239
|
+
* self + value -> bigdecimal
|
1036
1240
|
*
|
1037
|
-
*
|
1038
|
-
* add(value, digits)
|
1241
|
+
* Returns the \BigDecimal sum of +self+ and +value+:
|
1039
1242
|
*
|
1040
|
-
*
|
1243
|
+
* b = BigDecimal('111111.111') # => 0.111111111e6
|
1244
|
+
* b + 2 # => 0.111113111e6
|
1245
|
+
* b + 2.0 # => 0.111113111e6
|
1246
|
+
* b + Rational(2, 1) # => 0.111113111e6
|
1247
|
+
* b + Complex(2, 0) # => (0.111113111e6+0i)
|
1041
1248
|
*
|
1042
|
-
*
|
1043
|
-
* c = a.add(b,n)
|
1044
|
-
* c = a + b
|
1249
|
+
* See the {Note About Precision}[BigDecimal.html#class-BigDecimal-label-A+Note+About+Precision].
|
1045
1250
|
*
|
1046
|
-
* digits:: If specified and less than the number of significant digits of the
|
1047
|
-
* result, the result is rounded to that number of digits, according
|
1048
|
-
* to BigDecimal.mode.
|
1049
1251
|
*/
|
1252
|
+
|
1050
1253
|
static VALUE
|
1051
1254
|
BigDecimal_add(VALUE self, VALUE r)
|
1052
1255
|
{
|
@@ -1056,7 +1259,7 @@ BigDecimal_add(VALUE self, VALUE r)
|
|
1056
1259
|
|
1057
1260
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1058
1261
|
if (RB_TYPE_P(r, T_FLOAT)) {
|
1059
|
-
b = GetVpValueWithPrec(r,
|
1262
|
+
b = GetVpValueWithPrec(r, 0, 1);
|
1060
1263
|
}
|
1061
1264
|
else if (RB_TYPE_P(r, T_RATIONAL)) {
|
1062
1265
|
b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
|
@@ -1073,11 +1276,11 @@ BigDecimal_add(VALUE self, VALUE r)
|
|
1073
1276
|
|
1074
1277
|
mx = GetAddSubPrec(a, b);
|
1075
1278
|
if (mx == (size_t)-1L) {
|
1076
|
-
|
1279
|
+
GUARD_OBJ(c, VpCreateRbObject(VpBaseFig() + 1, "0", true));
|
1077
1280
|
VpAddSub(c, a, b, 1);
|
1078
1281
|
}
|
1079
1282
|
else {
|
1080
|
-
|
1283
|
+
GUARD_OBJ(c, VpCreateRbObject(mx * (VpBaseFig() + 1), "0", true));
|
1081
1284
|
if(!mx) {
|
1082
1285
|
VpSetInf(c, VpGetSign(a));
|
1083
1286
|
}
|
@@ -1085,24 +1288,21 @@ BigDecimal_add(VALUE self, VALUE r)
|
|
1085
1288
|
VpAddSub(c, a, b, 1);
|
1086
1289
|
}
|
1087
1290
|
}
|
1088
|
-
return
|
1291
|
+
return VpCheckGetValue(c);
|
1089
1292
|
}
|
1090
1293
|
|
1091
|
-
/*
|
1092
|
-
*
|
1093
|
-
*
|
1094
|
-
* Subtract the specified value.
|
1294
|
+
/* call-seq:
|
1295
|
+
* self - value -> bigdecimal
|
1095
1296
|
*
|
1096
|
-
*
|
1097
|
-
* c = a - b
|
1297
|
+
* Returns the \BigDecimal difference of +self+ and +value+:
|
1098
1298
|
*
|
1099
|
-
*
|
1299
|
+
* b = BigDecimal('333333.333') # => 0.333333333e6
|
1300
|
+
* b - 2 # => 0.333331333e6
|
1301
|
+
* b - 2.0 # => 0.333331333e6
|
1302
|
+
* b - Rational(2, 1) # => 0.333331333e6
|
1303
|
+
* b - Complex(2, 0) # => (0.333331333e6+0i)
|
1100
1304
|
*
|
1101
|
-
*
|
1102
|
-
*
|
1103
|
-
* If +b+ is a BigDecimal, the precision of the result is +b+'s precision of
|
1104
|
-
* internal representation from platform. So, it's return value is platform
|
1105
|
-
* dependent.
|
1305
|
+
* See the {Note About Precision}[BigDecimal.html#class-BigDecimal-label-A+Note+About+Precision].
|
1106
1306
|
*
|
1107
1307
|
*/
|
1108
1308
|
static VALUE
|
@@ -1114,7 +1314,7 @@ BigDecimal_sub(VALUE self, VALUE r)
|
|
1114
1314
|
|
1115
1315
|
GUARD_OBJ(a, GetVpValue(self,1));
|
1116
1316
|
if (RB_TYPE_P(r, T_FLOAT)) {
|
1117
|
-
b = GetVpValueWithPrec(r,
|
1317
|
+
b = GetVpValueWithPrec(r, 0, 1);
|
1118
1318
|
}
|
1119
1319
|
else if (RB_TYPE_P(r, T_RATIONAL)) {
|
1120
1320
|
b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
|
@@ -1131,11 +1331,11 @@ BigDecimal_sub(VALUE self, VALUE r)
|
|
1131
1331
|
|
1132
1332
|
mx = GetAddSubPrec(a,b);
|
1133
1333
|
if (mx == (size_t)-1L) {
|
1134
|
-
|
1334
|
+
GUARD_OBJ(c, VpCreateRbObject(VpBaseFig() + 1, "0", true));
|
1135
1335
|
VpAddSub(c, a, b, -1);
|
1136
1336
|
}
|
1137
1337
|
else {
|
1138
|
-
|
1338
|
+
GUARD_OBJ(c,VpCreateRbObject(mx *(VpBaseFig() + 1), "0", true));
|
1139
1339
|
if (!mx) {
|
1140
1340
|
VpSetInf(c,VpGetSign(a));
|
1141
1341
|
}
|
@@ -1143,7 +1343,7 @@ BigDecimal_sub(VALUE self, VALUE r)
|
|
1143
1343
|
VpAddSub(c, a, b, -1);
|
1144
1344
|
}
|
1145
1345
|
}
|
1146
|
-
return
|
1346
|
+
return VpCheckGetValue(c);
|
1147
1347
|
}
|
1148
1348
|
|
1149
1349
|
static VALUE
|
@@ -1164,7 +1364,7 @@ BigDecimalCmp(VALUE self, VALUE r,char op)
|
|
1164
1364
|
break;
|
1165
1365
|
|
1166
1366
|
case T_FLOAT:
|
1167
|
-
GUARD_OBJ(b, GetVpValueWithPrec(r,
|
1367
|
+
GUARD_OBJ(b, GetVpValueWithPrec(r, 0, 0));
|
1168
1368
|
break;
|
1169
1369
|
|
1170
1370
|
case T_RATIONAL:
|
@@ -1281,12 +1481,19 @@ BigDecimal_eq(VALUE self, VALUE r)
|
|
1281
1481
|
return BigDecimalCmp(self, r, '=');
|
1282
1482
|
}
|
1283
1483
|
|
1284
|
-
/*
|
1285
|
-
*
|
1484
|
+
/* call-seq:
|
1485
|
+
* self < other -> true or false
|
1486
|
+
*
|
1487
|
+
* Returns +true+ if +self+ is less than +other+, +false+ otherwise:
|
1488
|
+
*
|
1489
|
+
* b = BigDecimal('1.5') # => 0.15e1
|
1490
|
+
* b < 2 # => true
|
1491
|
+
* b < 2.0 # => true
|
1492
|
+
* b < Rational(2, 1) # => true
|
1493
|
+
* b < 1.5 # => false
|
1286
1494
|
*
|
1287
|
-
*
|
1495
|
+
* Raises an exception if the comparison cannot be made.
|
1288
1496
|
*
|
1289
|
-
* Values may be coerced to perform the comparison (see ==, BigDecimal#coerce).
|
1290
1497
|
*/
|
1291
1498
|
static VALUE
|
1292
1499
|
BigDecimal_lt(VALUE self, VALUE r)
|
@@ -1294,12 +1501,20 @@ BigDecimal_lt(VALUE self, VALUE r)
|
|
1294
1501
|
return BigDecimalCmp(self, r, '<');
|
1295
1502
|
}
|
1296
1503
|
|
1297
|
-
/*
|
1298
|
-
*
|
1504
|
+
/* call-seq:
|
1505
|
+
* self <= other -> true or false
|
1299
1506
|
*
|
1300
|
-
*
|
1507
|
+
* Returns +true+ if +self+ is less or equal to than +other+, +false+ otherwise:
|
1508
|
+
*
|
1509
|
+
* b = BigDecimal('1.5') # => 0.15e1
|
1510
|
+
* b <= 2 # => true
|
1511
|
+
* b <= 2.0 # => true
|
1512
|
+
* b <= Rational(2, 1) # => true
|
1513
|
+
* b <= 1.5 # => true
|
1514
|
+
* b < 1 # => false
|
1515
|
+
*
|
1516
|
+
* Raises an exception if the comparison cannot be made.
|
1301
1517
|
*
|
1302
|
-
* Values may be coerced to perform the comparison (see ==, BigDecimal#coerce).
|
1303
1518
|
*/
|
1304
1519
|
static VALUE
|
1305
1520
|
BigDecimal_le(VALUE self, VALUE r)
|
@@ -1307,12 +1522,19 @@ BigDecimal_le(VALUE self, VALUE r)
|
|
1307
1522
|
return BigDecimalCmp(self, r, 'L');
|
1308
1523
|
}
|
1309
1524
|
|
1310
|
-
/*
|
1311
|
-
*
|
1525
|
+
/* call-seq:
|
1526
|
+
* self > other -> true or false
|
1527
|
+
*
|
1528
|
+
* Returns +true+ if +self+ is greater than +other+, +false+ otherwise:
|
1312
1529
|
*
|
1313
|
-
*
|
1530
|
+
* b = BigDecimal('1.5')
|
1531
|
+
* b > 1 # => true
|
1532
|
+
* b > 1.0 # => true
|
1533
|
+
* b > Rational(1, 1) # => true
|
1534
|
+
* b > 2 # => false
|
1535
|
+
*
|
1536
|
+
* Raises an exception if the comparison cannot be made.
|
1314
1537
|
*
|
1315
|
-
* Values may be coerced to perform the comparison (see ==, BigDecimal#coerce).
|
1316
1538
|
*/
|
1317
1539
|
static VALUE
|
1318
1540
|
BigDecimal_gt(VALUE self, VALUE r)
|
@@ -1320,12 +1542,20 @@ BigDecimal_gt(VALUE self, VALUE r)
|
|
1320
1542
|
return BigDecimalCmp(self, r, '>');
|
1321
1543
|
}
|
1322
1544
|
|
1323
|
-
/*
|
1324
|
-
*
|
1545
|
+
/* call-seq:
|
1546
|
+
* self >= other -> true or false
|
1547
|
+
*
|
1548
|
+
* Returns +true+ if +self+ is greater than or equal to +other+, +false+ otherwise:
|
1325
1549
|
*
|
1326
|
-
*
|
1550
|
+
* b = BigDecimal('1.5')
|
1551
|
+
* b >= 1 # => true
|
1552
|
+
* b >= 1.0 # => true
|
1553
|
+
* b >= Rational(1, 1) # => true
|
1554
|
+
* b >= 1.5 # => true
|
1555
|
+
* b > 2 # => false
|
1556
|
+
*
|
1557
|
+
* Raises an exception if the comparison cannot be made.
|
1327
1558
|
*
|
1328
|
-
* Values may be coerced to perform the comparison (see ==, BigDecimal#coerce)
|
1329
1559
|
*/
|
1330
1560
|
static VALUE
|
1331
1561
|
BigDecimal_ge(VALUE self, VALUE r)
|
@@ -1335,11 +1565,14 @@ BigDecimal_ge(VALUE self, VALUE r)
|
|
1335
1565
|
|
1336
1566
|
/*
|
1337
1567
|
* call-seq:
|
1338
|
-
*
|
1568
|
+
* -self -> bigdecimal
|
1569
|
+
*
|
1570
|
+
* Returns the \BigDecimal negation of self:
|
1339
1571
|
*
|
1340
|
-
*
|
1572
|
+
* b0 = BigDecimal('1.5')
|
1573
|
+
* b1 = -b0 # => -0.15e1
|
1574
|
+
* b2 = -b1 # => 0.15e1
|
1341
1575
|
*
|
1342
|
-
* -BigDecimal('5') #=> -0.5e1
|
1343
1576
|
*/
|
1344
1577
|
|
1345
1578
|
static VALUE
|
@@ -1348,26 +1581,11 @@ BigDecimal_neg(VALUE self)
|
|
1348
1581
|
ENTER(5);
|
1349
1582
|
Real *c, *a;
|
1350
1583
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1351
|
-
GUARD_OBJ(c, VpCreateRbObject(a->Prec *(VpBaseFig() + 1), "0"));
|
1584
|
+
GUARD_OBJ(c, VpCreateRbObject(a->Prec *(VpBaseFig() + 1), "0", true));
|
1352
1585
|
VpAsgn(c, a, -1);
|
1353
|
-
return
|
1586
|
+
return VpCheckGetValue(c);
|
1354
1587
|
}
|
1355
1588
|
|
1356
|
-
/*
|
1357
|
-
* Document-method: BigDecimal#mult
|
1358
|
-
*
|
1359
|
-
* call-seq: mult(value, digits)
|
1360
|
-
*
|
1361
|
-
* Multiply by the specified value.
|
1362
|
-
*
|
1363
|
-
* e.g.
|
1364
|
-
* c = a.mult(b,n)
|
1365
|
-
* c = a * b
|
1366
|
-
*
|
1367
|
-
* digits:: If specified and less than the number of significant digits of the
|
1368
|
-
* result, the result is rounded to that number of digits, according
|
1369
|
-
* to BigDecimal.mode.
|
1370
|
-
*/
|
1371
1589
|
static VALUE
|
1372
1590
|
BigDecimal_mult(VALUE self, VALUE r)
|
1373
1591
|
{
|
@@ -1377,7 +1595,7 @@ BigDecimal_mult(VALUE self, VALUE r)
|
|
1377
1595
|
|
1378
1596
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1379
1597
|
if (RB_TYPE_P(r, T_FLOAT)) {
|
1380
|
-
b = GetVpValueWithPrec(r,
|
1598
|
+
b = GetVpValueWithPrec(r, 0, 1);
|
1381
1599
|
}
|
1382
1600
|
else if (RB_TYPE_P(r, T_RATIONAL)) {
|
1383
1601
|
b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
|
@@ -1390,71 +1608,132 @@ BigDecimal_mult(VALUE self, VALUE r)
|
|
1390
1608
|
SAVE(b);
|
1391
1609
|
|
1392
1610
|
mx = a->Prec + b->Prec;
|
1393
|
-
GUARD_OBJ(c, VpCreateRbObject(mx *(VpBaseFig() + 1), "0"));
|
1611
|
+
GUARD_OBJ(c, VpCreateRbObject(mx *(VpBaseFig() + 1), "0", true));
|
1394
1612
|
VpMult(c, a, b);
|
1395
|
-
return
|
1613
|
+
return VpCheckGetValue(c);
|
1396
1614
|
}
|
1397
1615
|
|
1398
1616
|
static VALUE
|
1399
|
-
BigDecimal_divide(Real **c, Real **res, Real **div
|
1617
|
+
BigDecimal_divide(VALUE self, VALUE r, Real **c, Real **res, Real **div)
|
1400
1618
|
/* For c = self.div(r): with round operation */
|
1401
1619
|
{
|
1402
1620
|
ENTER(5);
|
1403
|
-
Real *a, *b;
|
1621
|
+
Real *a, *b, *d;
|
1622
|
+
ssize_t a_prec, b_prec;
|
1404
1623
|
size_t mx;
|
1405
1624
|
|
1406
|
-
|
1407
|
-
|
1408
|
-
|
1625
|
+
TypedData_Get_Struct(self, Real, &BigDecimal_data_type, a);
|
1626
|
+
SAVE(a);
|
1627
|
+
|
1628
|
+
VALUE rr = r;
|
1629
|
+
if (is_kind_of_BigDecimal(rr)) {
|
1630
|
+
/* do nothing */
|
1631
|
+
}
|
1632
|
+
else if (RB_INTEGER_TYPE_P(r)) {
|
1633
|
+
rr = rb_inum_convert_to_BigDecimal(r, 0, true);
|
1634
|
+
}
|
1635
|
+
else if (RB_TYPE_P(r, T_FLOAT)) {
|
1636
|
+
rr = rb_float_convert_to_BigDecimal(r, 0, true);
|
1409
1637
|
}
|
1410
1638
|
else if (RB_TYPE_P(r, T_RATIONAL)) {
|
1411
|
-
|
1412
|
-
}
|
1413
|
-
else {
|
1414
|
-
b = GetVpValue(r, 0);
|
1639
|
+
rr = rb_rational_convert_to_BigDecimal(r, a->Prec*BASE_FIG, true);
|
1415
1640
|
}
|
1416
1641
|
|
1417
|
-
if (!
|
1418
|
-
|
1642
|
+
if (!is_kind_of_BigDecimal(rr)) {
|
1643
|
+
return DoSomeOne(self, r, '/');
|
1644
|
+
}
|
1419
1645
|
|
1646
|
+
TypedData_Get_Struct(rr, Real, &BigDecimal_data_type, b);
|
1647
|
+
SAVE(b);
|
1420
1648
|
*div = b;
|
1421
|
-
|
1422
|
-
|
1423
|
-
mx
|
1424
|
-
|
1425
|
-
|
1426
|
-
|
1427
|
-
|
1649
|
+
|
1650
|
+
mx = (a->Prec > b->Prec) ? a->Prec : b->Prec;
|
1651
|
+
mx *= BASE_FIG;
|
1652
|
+
|
1653
|
+
BigDecimal_count_precision_and_scale(self, &a_prec, NULL);
|
1654
|
+
BigDecimal_count_precision_and_scale(rr, &b_prec, NULL);
|
1655
|
+
mx = (a_prec > b_prec) ? a_prec : b_prec;
|
1656
|
+
|
1657
|
+
if (2*BIGDECIMAL_DOUBLE_FIGURES > mx)
|
1658
|
+
mx = 2*BIGDECIMAL_DOUBLE_FIGURES;
|
1659
|
+
|
1660
|
+
GUARD_OBJ((*c), VpCreateRbObject(mx + 2*BASE_FIG, "#0", true));
|
1661
|
+
GUARD_OBJ((*res), VpCreateRbObject(mx*2 + 2*BASE_FIG, "#0", true));
|
1428
1662
|
VpDivd(*c, *res, a, b);
|
1663
|
+
|
1429
1664
|
return Qnil;
|
1430
1665
|
}
|
1431
1666
|
|
1667
|
+
static VALUE BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod);
|
1668
|
+
|
1432
1669
|
/* call-seq:
|
1433
|
-
* a / b
|
1434
|
-
* quo(value) -> bigdecimal
|
1670
|
+
* a / b -> bigdecimal
|
1435
1671
|
*
|
1436
1672
|
* Divide by the specified value.
|
1437
1673
|
*
|
1674
|
+
* The result precision will be the precision of the larger operand,
|
1675
|
+
* but its minimum is 2*Float::DIG.
|
1676
|
+
*
|
1438
1677
|
* See BigDecimal#div.
|
1678
|
+
* See BigDecimal#quo.
|
1439
1679
|
*/
|
1440
1680
|
static VALUE
|
1441
1681
|
BigDecimal_div(VALUE self, VALUE r)
|
1442
1682
|
/* For c = self/r: with round operation */
|
1443
1683
|
{
|
1444
|
-
ENTER(5);
|
1445
|
-
Real *c=NULL, *res=NULL, *div = NULL;
|
1446
|
-
r = BigDecimal_divide(&c, &res, &div
|
1447
|
-
if (!NIL_P(r)) return r; /* coerced by other */
|
1448
|
-
SAVE(c); SAVE(res); SAVE(div);
|
1449
|
-
/* a/b = c + r/b */
|
1450
|
-
/* c xxxxx
|
1451
|
-
r 00000yyyyy ==> (y/b)*BASE >= HALF_BASE
|
1452
|
-
*/
|
1453
|
-
/* Round */
|
1454
|
-
if (VpHasVal(div)) { /* frac[0] must be zero for NaN,INF,Zero */
|
1455
|
-
|
1684
|
+
ENTER(5);
|
1685
|
+
Real *c=NULL, *res=NULL, *div = NULL;
|
1686
|
+
r = BigDecimal_divide(self, r, &c, &res, &div);
|
1687
|
+
if (!NIL_P(r)) return r; /* coerced by other */
|
1688
|
+
SAVE(c); SAVE(res); SAVE(div);
|
1689
|
+
/* a/b = c + r/b */
|
1690
|
+
/* c xxxxx
|
1691
|
+
r 00000yyyyy ==> (y/b)*BASE >= HALF_BASE
|
1692
|
+
*/
|
1693
|
+
/* Round */
|
1694
|
+
if (VpHasVal(div)) { /* frac[0] must be zero for NaN,INF,Zero */
|
1695
|
+
VpInternalRound(c, 0, c->frac[c->Prec-1], (DECDIG)(VpBaseVal() * (DECDIG_DBL)res->frac[0] / div->frac[0]));
|
1696
|
+
}
|
1697
|
+
return VpCheckGetValue(c);
|
1698
|
+
}
|
1699
|
+
|
1700
|
+
static VALUE BigDecimal_round(int argc, VALUE *argv, VALUE self);
|
1701
|
+
|
1702
|
+
/* call-seq:
|
1703
|
+
* quo(value) -> bigdecimal
|
1704
|
+
* quo(value, digits) -> bigdecimal
|
1705
|
+
*
|
1706
|
+
* Divide by the specified value.
|
1707
|
+
*
|
1708
|
+
* digits:: If specified and less than the number of significant digits of
|
1709
|
+
* the result, the result is rounded to the given number of digits,
|
1710
|
+
* according to the rounding mode indicated by BigDecimal.mode.
|
1711
|
+
*
|
1712
|
+
* If digits is 0 or omitted, the result is the same as for the
|
1713
|
+
* / operator.
|
1714
|
+
*
|
1715
|
+
* See BigDecimal#/.
|
1716
|
+
* See BigDecimal#div.
|
1717
|
+
*/
|
1718
|
+
static VALUE
|
1719
|
+
BigDecimal_quo(int argc, VALUE *argv, VALUE self)
|
1720
|
+
{
|
1721
|
+
VALUE value, digits, result;
|
1722
|
+
SIGNED_VALUE n = -1;
|
1723
|
+
|
1724
|
+
argc = rb_scan_args(argc, argv, "11", &value, &digits);
|
1725
|
+
if (argc > 1) {
|
1726
|
+
n = GetPrecisionInt(digits);
|
1727
|
+
}
|
1728
|
+
|
1729
|
+
if (n > 0) {
|
1730
|
+
result = BigDecimal_div2(self, value, digits);
|
1731
|
+
}
|
1732
|
+
else {
|
1733
|
+
result = BigDecimal_div(self, value);
|
1456
1734
|
}
|
1457
|
-
|
1735
|
+
|
1736
|
+
return result;
|
1458
1737
|
}
|
1459
1738
|
|
1460
1739
|
/*
|
@@ -1467,77 +1746,104 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
|
|
1467
1746
|
ENTER(8);
|
1468
1747
|
Real *c=NULL, *d=NULL, *res=NULL;
|
1469
1748
|
Real *a, *b;
|
1749
|
+
ssize_t a_prec, b_prec;
|
1470
1750
|
size_t mx;
|
1471
1751
|
|
1472
|
-
|
1473
|
-
|
1474
|
-
|
1752
|
+
TypedData_Get_Struct(self, Real, &BigDecimal_data_type, a);
|
1753
|
+
SAVE(a);
|
1754
|
+
|
1755
|
+
VALUE rr = r;
|
1756
|
+
if (is_kind_of_BigDecimal(rr)) {
|
1757
|
+
/* do nothing */
|
1758
|
+
}
|
1759
|
+
else if (RB_INTEGER_TYPE_P(r)) {
|
1760
|
+
rr = rb_inum_convert_to_BigDecimal(r, 0, true);
|
1761
|
+
}
|
1762
|
+
else if (RB_TYPE_P(r, T_FLOAT)) {
|
1763
|
+
rr = rb_float_convert_to_BigDecimal(r, 0, true);
|
1475
1764
|
}
|
1476
1765
|
else if (RB_TYPE_P(r, T_RATIONAL)) {
|
1477
|
-
|
1766
|
+
rr = rb_rational_convert_to_BigDecimal(r, a->Prec*BASE_FIG, true);
|
1478
1767
|
}
|
1479
|
-
|
1480
|
-
|
1768
|
+
|
1769
|
+
if (!is_kind_of_BigDecimal(rr)) {
|
1770
|
+
return Qfalse;
|
1481
1771
|
}
|
1482
1772
|
|
1483
|
-
|
1773
|
+
TypedData_Get_Struct(rr, Real, &BigDecimal_data_type, b);
|
1484
1774
|
SAVE(b);
|
1485
1775
|
|
1486
1776
|
if (VpIsNaN(a) || VpIsNaN(b)) goto NaN;
|
1487
1777
|
if (VpIsInf(a) && VpIsInf(b)) goto NaN;
|
1488
1778
|
if (VpIsZero(b)) {
|
1489
|
-
|
1779
|
+
rb_raise(rb_eZeroDivError, "divided by 0");
|
1490
1780
|
}
|
1491
1781
|
if (VpIsInf(a)) {
|
1492
|
-
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1496
|
-
|
1497
|
-
|
1782
|
+
if (VpGetSign(a) == VpGetSign(b)) {
|
1783
|
+
VALUE inf = BigDecimal_positive_infinity();
|
1784
|
+
TypedData_Get_Struct(inf, Real, &BigDecimal_data_type, *div);
|
1785
|
+
}
|
1786
|
+
else {
|
1787
|
+
VALUE inf = BigDecimal_negative_infinity();
|
1788
|
+
TypedData_Get_Struct(inf, Real, &BigDecimal_data_type, *div);
|
1789
|
+
}
|
1790
|
+
VALUE nan = BigDecimal_nan();
|
1791
|
+
TypedData_Get_Struct(nan, Real, &BigDecimal_data_type, *mod);
|
1792
|
+
return Qtrue;
|
1498
1793
|
}
|
1499
1794
|
if (VpIsInf(b)) {
|
1500
|
-
|
1501
|
-
|
1502
|
-
|
1503
|
-
|
1795
|
+
VALUE zero = BigDecimal_positive_zero();
|
1796
|
+
TypedData_Get_Struct(zero, Real, &BigDecimal_data_type, *div);
|
1797
|
+
*mod = a;
|
1798
|
+
return Qtrue;
|
1504
1799
|
}
|
1505
1800
|
if (VpIsZero(a)) {
|
1506
|
-
|
1507
|
-
|
1508
|
-
|
1509
|
-
|
1510
|
-
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1514
|
-
|
1515
|
-
mx = (
|
1516
|
-
|
1517
|
-
|
1801
|
+
VALUE zero = BigDecimal_positive_zero();
|
1802
|
+
TypedData_Get_Struct(zero, Real, &BigDecimal_data_type, *div);
|
1803
|
+
TypedData_Get_Struct(zero, Real, &BigDecimal_data_type, *mod);
|
1804
|
+
return Qtrue;
|
1805
|
+
}
|
1806
|
+
|
1807
|
+
BigDecimal_count_precision_and_scale(self, &a_prec, NULL);
|
1808
|
+
BigDecimal_count_precision_and_scale(rr, &b_prec, NULL);
|
1809
|
+
|
1810
|
+
mx = (a_prec > b_prec) ? a_prec : b_prec;
|
1811
|
+
if (2*BIGDECIMAL_DOUBLE_FIGURES > mx)
|
1812
|
+
mx = 2*BIGDECIMAL_DOUBLE_FIGURES;
|
1813
|
+
|
1814
|
+
GUARD_OBJ(c, VpCreateRbObject(mx + 2*BASE_FIG, "0", true));
|
1815
|
+
GUARD_OBJ(res, VpCreateRbObject(mx*2 + 2*BASE_FIG, "#0", true));
|
1518
1816
|
VpDivd(c, res, a, b);
|
1519
|
-
|
1520
|
-
|
1817
|
+
|
1818
|
+
mx = c->Prec * BASE_FIG;
|
1819
|
+
GUARD_OBJ(d, VpCreateRbObject(mx, "0", true));
|
1521
1820
|
VpActiveRound(d, c, VP_ROUND_DOWN, 0);
|
1821
|
+
|
1522
1822
|
VpMult(res, d, b);
|
1523
1823
|
VpAddSub(c, a, res, -1);
|
1824
|
+
|
1524
1825
|
if (!VpIsZero(c) && (VpGetSign(a) * VpGetSign(b) < 0)) {
|
1525
|
-
|
1526
|
-
|
1527
|
-
|
1528
|
-
|
1529
|
-
|
1530
|
-
|
1531
|
-
|
1532
|
-
|
1826
|
+
/* result adjustment for negative case */
|
1827
|
+
res = VpReallocReal(res, d->MaxPrec);
|
1828
|
+
res->MaxPrec = d->MaxPrec;
|
1829
|
+
VpAddSub(res, d, VpOne(), -1);
|
1830
|
+
GUARD_OBJ(d, VpCreateRbObject(GetAddSubPrec(c, b) * 2*BASE_FIG, "0", true));
|
1831
|
+
VpAddSub(d, c, b, 1);
|
1832
|
+
*div = res;
|
1833
|
+
*mod = d;
|
1834
|
+
}
|
1835
|
+
else {
|
1836
|
+
*div = d;
|
1837
|
+
*mod = c;
|
1533
1838
|
}
|
1534
1839
|
return Qtrue;
|
1535
1840
|
|
1536
|
-
NaN:
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1841
|
+
NaN:
|
1842
|
+
{
|
1843
|
+
VALUE nan = BigDecimal_nan();
|
1844
|
+
TypedData_Get_Struct(nan, Real, &BigDecimal_data_type, *div);
|
1845
|
+
TypedData_Get_Struct(nan, Real, &BigDecimal_data_type, *mod);
|
1846
|
+
}
|
1541
1847
|
return Qtrue;
|
1542
1848
|
}
|
1543
1849
|
|
@@ -1557,7 +1863,7 @@ BigDecimal_mod(VALUE self, VALUE r) /* %: a%b = a - (a.to_f/b).floor * b */
|
|
1557
1863
|
|
1558
1864
|
if (BigDecimal_DoDivmod(self, r, &div, &mod)) {
|
1559
1865
|
SAVE(div); SAVE(mod);
|
1560
|
-
|
1866
|
+
return VpCheckGetValue(mod);
|
1561
1867
|
}
|
1562
1868
|
return DoSomeOne(self, r, '%');
|
1563
1869
|
}
|
@@ -1572,7 +1878,7 @@ BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv)
|
|
1572
1878
|
|
1573
1879
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1574
1880
|
if (RB_TYPE_P(r, T_FLOAT)) {
|
1575
|
-
b = GetVpValueWithPrec(r,
|
1881
|
+
b = GetVpValueWithPrec(r, 0, 1);
|
1576
1882
|
}
|
1577
1883
|
else if (RB_TYPE_P(r, T_RATIONAL)) {
|
1578
1884
|
b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
|
@@ -1585,17 +1891,17 @@ BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv)
|
|
1585
1891
|
SAVE(b);
|
1586
1892
|
|
1587
1893
|
mx = (a->MaxPrec + b->MaxPrec) *VpBaseFig();
|
1588
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
1589
|
-
GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0"));
|
1590
|
-
GUARD_OBJ(rr, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0"));
|
1591
|
-
GUARD_OBJ(ff, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0"));
|
1894
|
+
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
1895
|
+
GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0", true));
|
1896
|
+
GUARD_OBJ(rr, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0", true));
|
1897
|
+
GUARD_OBJ(ff, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0", true));
|
1592
1898
|
|
1593
1899
|
VpDivd(c, res, a, b);
|
1594
1900
|
|
1595
1901
|
mx = c->Prec *(VpBaseFig() + 1);
|
1596
1902
|
|
1597
|
-
GUARD_OBJ(d, VpCreateRbObject(mx, "0"));
|
1598
|
-
GUARD_OBJ(f, VpCreateRbObject(mx, "0"));
|
1903
|
+
GUARD_OBJ(d, VpCreateRbObject(mx, "0", true));
|
1904
|
+
GUARD_OBJ(f, VpCreateRbObject(mx, "0", true));
|
1599
1905
|
|
1600
1906
|
VpActiveRound(d, c, VP_ROUND_DOWN, 0); /* 0: round off */
|
1601
1907
|
|
@@ -1622,7 +1928,7 @@ BigDecimal_remainder(VALUE self, VALUE r) /* remainder */
|
|
1622
1928
|
Real *d, *rv = 0;
|
1623
1929
|
f = BigDecimal_divremain(self, r, &d, &rv);
|
1624
1930
|
if (!NIL_P(f)) return f;
|
1625
|
-
return
|
1931
|
+
return VpCheckGetValue(rv);
|
1626
1932
|
}
|
1627
1933
|
|
1628
1934
|
/* call-seq:
|
@@ -1655,13 +1961,14 @@ BigDecimal_divmod(VALUE self, VALUE r)
|
|
1655
1961
|
|
1656
1962
|
if (BigDecimal_DoDivmod(self, r, &div, &mod)) {
|
1657
1963
|
SAVE(div); SAVE(mod);
|
1658
|
-
|
1964
|
+
return rb_assoc_new(VpCheckGetValue(div), VpCheckGetValue(mod));
|
1659
1965
|
}
|
1660
1966
|
return DoSomeOne(self,r,rb_intern("divmod"));
|
1661
1967
|
}
|
1662
1968
|
|
1663
1969
|
/*
|
1664
|
-
*
|
1970
|
+
* Do the same manner as Float#div when n is nil.
|
1971
|
+
* Do the same manner as BigDecimal#quo when n is 0.
|
1665
1972
|
*/
|
1666
1973
|
static inline VALUE
|
1667
1974
|
BigDecimal_div2(VALUE self, VALUE b, VALUE n)
|
@@ -1673,7 +1980,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
|
|
1673
1980
|
Real *div = NULL;
|
1674
1981
|
Real *mod;
|
1675
1982
|
if (BigDecimal_DoDivmod(self, b, &div, &mod)) {
|
1676
|
-
return BigDecimal_to_i(
|
1983
|
+
return BigDecimal_to_i(VpCheckGetValue(div));
|
1677
1984
|
}
|
1678
1985
|
return DoSomeOne(self, b, rb_intern("div"));
|
1679
1986
|
}
|
@@ -1687,18 +1994,25 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
|
|
1687
1994
|
Real *res = NULL;
|
1688
1995
|
Real *av = NULL, *bv = NULL, *cv = NULL;
|
1689
1996
|
size_t mx = ix + VpBaseFig()*2;
|
1997
|
+
size_t b_prec = ix;
|
1690
1998
|
size_t pl = VpSetPrecLimit(0);
|
1691
1999
|
|
1692
|
-
GUARD_OBJ(cv, VpCreateRbObject(mx + VpBaseFig(), "0"));
|
2000
|
+
GUARD_OBJ(cv, VpCreateRbObject(mx + VpBaseFig(), "0", true));
|
1693
2001
|
GUARD_OBJ(av, GetVpValue(self, 1));
|
1694
|
-
|
2002
|
+
/* TODO: I want to refactor this precision control for a float value later
|
2003
|
+
* by introducing an implicit conversion function instead of
|
2004
|
+
* GetVpValueWithPrec. */
|
2005
|
+
if (RB_FLOAT_TYPE_P(b) && b_prec > BIGDECIMAL_DOUBLE_FIGURES) {
|
2006
|
+
b_prec = BIGDECIMAL_DOUBLE_FIGURES;
|
2007
|
+
}
|
2008
|
+
GUARD_OBJ(bv, GetVpValueWithPrec(b, b_prec, 1));
|
1695
2009
|
mx = av->Prec + bv->Prec + 2;
|
1696
2010
|
if (mx <= cv->MaxPrec) mx = cv->MaxPrec + 1;
|
1697
|
-
GUARD_OBJ(res, VpCreateRbObject((mx * 2 + 2)*VpBaseFig(), "#0"));
|
2011
|
+
GUARD_OBJ(res, VpCreateRbObject((mx * 2 + 2)*VpBaseFig(), "#0", true));
|
1698
2012
|
VpDivd(cv, res, av, bv);
|
1699
2013
|
VpSetPrecLimit(pl);
|
1700
2014
|
VpLeftRound(cv, VpGetRoundMode(), ix);
|
1701
|
-
return
|
2015
|
+
return VpCheckGetValue(cv);
|
1702
2016
|
}
|
1703
2017
|
}
|
1704
2018
|
|
@@ -1706,6 +2020,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
|
|
1706
2020
|
* Document-method: BigDecimal#div
|
1707
2021
|
*
|
1708
2022
|
* call-seq:
|
2023
|
+
* div(value) -> integer
|
1709
2024
|
* div(value, digits) -> bigdecimal or integer
|
1710
2025
|
*
|
1711
2026
|
* Divide by the specified value.
|
@@ -1720,6 +2035,9 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
|
|
1720
2035
|
* If digits is not specified, the result is an integer,
|
1721
2036
|
* by analogy with Float#div; see also BigDecimal#divmod.
|
1722
2037
|
*
|
2038
|
+
* See BigDecimal#/.
|
2039
|
+
* See BigDecimal#quo.
|
2040
|
+
*
|
1723
2041
|
* Examples:
|
1724
2042
|
*
|
1725
2043
|
* a = BigDecimal("4")
|
@@ -1743,6 +2061,31 @@ BigDecimal_div3(int argc, VALUE *argv, VALUE self)
|
|
1743
2061
|
return BigDecimal_div2(self, b, n);
|
1744
2062
|
}
|
1745
2063
|
|
2064
|
+
/*
|
2065
|
+
* call-seq:
|
2066
|
+
* add(value, ndigits) -> new_bigdecimal
|
2067
|
+
*
|
2068
|
+
* Returns the \BigDecimal sum of +self+ and +value+
|
2069
|
+
* with a precision of +ndigits+ decimal digits.
|
2070
|
+
*
|
2071
|
+
* When +ndigits+ is less than the number of significant digits
|
2072
|
+
* in the sum, the sum is rounded to that number of digits,
|
2073
|
+
* according to the current rounding mode; see BigDecimal.mode.
|
2074
|
+
*
|
2075
|
+
* Examples:
|
2076
|
+
*
|
2077
|
+
* # Set the rounding mode.
|
2078
|
+
* BigDecimal.mode(BigDecimal::ROUND_MODE, :half_up)
|
2079
|
+
* b = BigDecimal('111111.111')
|
2080
|
+
* b.add(1, 0) # => 0.111112111e6
|
2081
|
+
* b.add(1, 3) # => 0.111e6
|
2082
|
+
* b.add(1, 6) # => 0.111112e6
|
2083
|
+
* b.add(1, 15) # => 0.111112111e6
|
2084
|
+
* b.add(1.0, 15) # => 0.111112111e6
|
2085
|
+
* b.add(Rational(1, 1), 15) # => 0.111112111e6
|
2086
|
+
*
|
2087
|
+
*/
|
2088
|
+
|
1746
2089
|
static VALUE
|
1747
2090
|
BigDecimal_add2(VALUE self, VALUE b, VALUE n)
|
1748
2091
|
{
|
@@ -1756,7 +2099,7 @@ BigDecimal_add2(VALUE self, VALUE b, VALUE n)
|
|
1756
2099
|
VpSetPrecLimit(pl);
|
1757
2100
|
GUARD_OBJ(cv, GetVpValue(c, 1));
|
1758
2101
|
VpLeftRound(cv, VpGetRoundMode(), mx);
|
1759
|
-
|
2102
|
+
return VpCheckGetValue(cv);
|
1760
2103
|
}
|
1761
2104
|
}
|
1762
2105
|
|
@@ -1786,10 +2129,35 @@ BigDecimal_sub2(VALUE self, VALUE b, VALUE n)
|
|
1786
2129
|
VpSetPrecLimit(pl);
|
1787
2130
|
GUARD_OBJ(cv, GetVpValue(c, 1));
|
1788
2131
|
VpLeftRound(cv, VpGetRoundMode(), mx);
|
1789
|
-
|
2132
|
+
return VpCheckGetValue(cv);
|
1790
2133
|
}
|
1791
2134
|
}
|
1792
2135
|
|
2136
|
+
/*
|
2137
|
+
* call-seq:
|
2138
|
+
* mult(other, ndigits) -> bigdecimal
|
2139
|
+
*
|
2140
|
+
* Returns the \BigDecimal product of +self+ and +value+
|
2141
|
+
* with a precision of +ndigits+ decimal digits.
|
2142
|
+
*
|
2143
|
+
* When +ndigits+ is less than the number of significant digits
|
2144
|
+
* in the sum, the sum is rounded to that number of digits,
|
2145
|
+
* according to the current rounding mode; see BigDecimal.mode.
|
2146
|
+
*
|
2147
|
+
* Examples:
|
2148
|
+
*
|
2149
|
+
* # Set the rounding mode.
|
2150
|
+
* BigDecimal.mode(BigDecimal::ROUND_MODE, :half_up)
|
2151
|
+
* b = BigDecimal('555555.555')
|
2152
|
+
* b.mult(3, 0) # => 0.1666666665e7
|
2153
|
+
* b.mult(3, 3) # => 0.167e7
|
2154
|
+
* b.mult(3, 6) # => 0.166667e7
|
2155
|
+
* b.mult(3, 15) # => 0.1666666665e7
|
2156
|
+
* b.mult(3.0, 0) # => 0.1666666665e7
|
2157
|
+
* b.mult(Rational(3, 1), 0) # => 0.1666666665e7
|
2158
|
+
* b.mult(Complex(3, 0), 0) # => (0.1666666665e7+0.0i)
|
2159
|
+
*
|
2160
|
+
*/
|
1793
2161
|
|
1794
2162
|
static VALUE
|
1795
2163
|
BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
|
@@ -1804,18 +2172,19 @@ BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
|
|
1804
2172
|
VpSetPrecLimit(pl);
|
1805
2173
|
GUARD_OBJ(cv, GetVpValue(c, 1));
|
1806
2174
|
VpLeftRound(cv, VpGetRoundMode(), mx);
|
1807
|
-
|
2175
|
+
return VpCheckGetValue(cv);
|
1808
2176
|
}
|
1809
2177
|
}
|
1810
2178
|
|
1811
2179
|
/*
|
1812
2180
|
* call-seq:
|
1813
|
-
*
|
2181
|
+
* abs -> bigdecimal
|
2182
|
+
*
|
2183
|
+
* Returns the \BigDecimal absolute value of +self+:
|
1814
2184
|
*
|
1815
|
-
*
|
2185
|
+
* BigDecimal('5').abs # => 0.5e1
|
2186
|
+
* BigDecimal('-3').abs # => 0.3e1
|
1816
2187
|
*
|
1817
|
-
* BigDecimal('5').abs #=> 0.5e1
|
1818
|
-
* BigDecimal('-3').abs #=> 0.3e1
|
1819
2188
|
*/
|
1820
2189
|
|
1821
2190
|
static VALUE
|
@@ -1827,10 +2196,10 @@ BigDecimal_abs(VALUE self)
|
|
1827
2196
|
|
1828
2197
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1829
2198
|
mx = a->Prec *(VpBaseFig() + 1);
|
1830
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
2199
|
+
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
1831
2200
|
VpAsgn(c, a, 1);
|
1832
2201
|
VpChangeSign(c, 1);
|
1833
|
-
return
|
2202
|
+
return VpCheckGetValue(c);
|
1834
2203
|
}
|
1835
2204
|
|
1836
2205
|
/* call-seq:
|
@@ -1852,9 +2221,9 @@ BigDecimal_sqrt(VALUE self, VALUE nFig)
|
|
1852
2221
|
|
1853
2222
|
n = GetPrecisionInt(nFig) + VpDblFig() + BASE_FIG;
|
1854
2223
|
if (mx <= n) mx = n;
|
1855
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
2224
|
+
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
1856
2225
|
VpSqrt(c, a);
|
1857
|
-
return
|
2226
|
+
return VpCheckGetValue(c);
|
1858
2227
|
}
|
1859
2228
|
|
1860
2229
|
/* Return the integer part of the number, as a BigDecimal.
|
@@ -1868,9 +2237,9 @@ BigDecimal_fix(VALUE self)
|
|
1868
2237
|
|
1869
2238
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1870
2239
|
mx = a->Prec *(VpBaseFig() + 1);
|
1871
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
2240
|
+
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
1872
2241
|
VpActiveRound(c, a, VP_ROUND_DOWN, 0); /* 0: round off */
|
1873
|
-
return
|
2242
|
+
return VpCheckGetValue(c);
|
1874
2243
|
}
|
1875
2244
|
|
1876
2245
|
/* call-seq:
|
@@ -1941,13 +2310,13 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
|
|
1941
2310
|
pl = VpSetPrecLimit(0);
|
1942
2311
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1943
2312
|
mx = a->Prec * (VpBaseFig() + 1);
|
1944
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
2313
|
+
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
1945
2314
|
VpSetPrecLimit(pl);
|
1946
2315
|
VpActiveRound(c, a, sw, iLoc);
|
1947
2316
|
if (round_to_int) {
|
1948
|
-
|
2317
|
+
return BigDecimal_to_i(VpCheckGetValue(c));
|
1949
2318
|
}
|
1950
|
-
return
|
2319
|
+
return VpCheckGetValue(c);
|
1951
2320
|
}
|
1952
2321
|
|
1953
2322
|
/* call-seq:
|
@@ -1987,13 +2356,13 @@ BigDecimal_truncate(int argc, VALUE *argv, VALUE self)
|
|
1987
2356
|
|
1988
2357
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1989
2358
|
mx = a->Prec * (VpBaseFig() + 1);
|
1990
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
2359
|
+
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
1991
2360
|
VpSetPrecLimit(pl);
|
1992
2361
|
VpActiveRound(c, a, VP_ROUND_DOWN, iLoc); /* 0: truncate */
|
1993
2362
|
if (argc == 0) {
|
1994
|
-
|
2363
|
+
return BigDecimal_to_i(VpCheckGetValue(c));
|
1995
2364
|
}
|
1996
|
-
return
|
2365
|
+
return VpCheckGetValue(c);
|
1997
2366
|
}
|
1998
2367
|
|
1999
2368
|
/* Return the fractional part of the number, as a BigDecimal.
|
@@ -2007,9 +2376,9 @@ BigDecimal_frac(VALUE self)
|
|
2007
2376
|
|
2008
2377
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
2009
2378
|
mx = a->Prec * (VpBaseFig() + 1);
|
2010
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
2379
|
+
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
2011
2380
|
VpFrac(c, a);
|
2012
|
-
return
|
2381
|
+
return VpCheckGetValue(c);
|
2013
2382
|
}
|
2014
2383
|
|
2015
2384
|
/* call-seq:
|
@@ -2047,16 +2416,16 @@ BigDecimal_floor(int argc, VALUE *argv, VALUE self)
|
|
2047
2416
|
|
2048
2417
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
2049
2418
|
mx = a->Prec * (VpBaseFig() + 1);
|
2050
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
2419
|
+
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
2051
2420
|
VpSetPrecLimit(pl);
|
2052
2421
|
VpActiveRound(c, a, VP_ROUND_FLOOR, iLoc);
|
2053
2422
|
#ifdef BIGDECIMAL_DEBUG
|
2054
2423
|
VPrint(stderr, "floor: c=%\n", c);
|
2055
2424
|
#endif
|
2056
2425
|
if (argc == 0) {
|
2057
|
-
|
2426
|
+
return BigDecimal_to_i(VpCheckGetValue(c));
|
2058
2427
|
}
|
2059
|
-
return
|
2428
|
+
return VpCheckGetValue(c);
|
2060
2429
|
}
|
2061
2430
|
|
2062
2431
|
/* call-seq:
|
@@ -2093,13 +2462,13 @@ BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
|
|
2093
2462
|
|
2094
2463
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
2095
2464
|
mx = a->Prec * (VpBaseFig() + 1);
|
2096
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
2465
|
+
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
2097
2466
|
VpSetPrecLimit(pl);
|
2098
2467
|
VpActiveRound(c, a, VP_ROUND_CEIL, iLoc);
|
2099
2468
|
if (argc == 0) {
|
2100
|
-
|
2469
|
+
return BigDecimal_to_i(VpCheckGetValue(c));
|
2101
2470
|
}
|
2102
|
-
return
|
2471
|
+
return VpCheckGetValue(c);
|
2103
2472
|
}
|
2104
2473
|
|
2105
2474
|
/* call-seq:
|
@@ -2395,13 +2764,13 @@ is_even(VALUE x)
|
|
2395
2764
|
}
|
2396
2765
|
|
2397
2766
|
static VALUE
|
2398
|
-
|
2767
|
+
bigdecimal_power_by_bigdecimal(Real const* x, Real const* exp, ssize_t const n)
|
2399
2768
|
{
|
2400
2769
|
VALUE log_x, multiplied, y;
|
2401
2770
|
volatile VALUE obj = exp->obj;
|
2402
2771
|
|
2403
2772
|
if (VpIsZero(exp)) {
|
2404
|
-
|
2773
|
+
return VpCheckGetValue(VpCreateRbObject(n, "1", true));
|
2405
2774
|
}
|
2406
2775
|
|
2407
2776
|
log_x = BigMath_log(x->obj, SSIZET2NUM(n+1));
|
@@ -2439,10 +2808,10 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2439
2808
|
n = NIL_P(prec) ? (ssize_t)(x->Prec*VpBaseFig()) : NUM2SSIZET(prec);
|
2440
2809
|
|
2441
2810
|
if (VpIsNaN(x)) {
|
2442
|
-
|
2811
|
+
y = VpCreateRbObject(n, "0", true);
|
2443
2812
|
RB_GC_GUARD(y->obj);
|
2444
2813
|
VpSetNaN(y);
|
2445
|
-
|
2814
|
+
return VpCheckGetValue(y);
|
2446
2815
|
}
|
2447
2816
|
|
2448
2817
|
retry:
|
@@ -2465,9 +2834,9 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2465
2834
|
goto retry;
|
2466
2835
|
}
|
2467
2836
|
if (NIL_P(prec)) {
|
2468
|
-
n +=
|
2837
|
+
n += BIGDECIMAL_DOUBLE_FIGURES;
|
2469
2838
|
}
|
2470
|
-
exp = GetVpValueWithPrec(vexp,
|
2839
|
+
exp = GetVpValueWithPrec(vexp, 0, 1);
|
2471
2840
|
break;
|
2472
2841
|
|
2473
2842
|
case T_RATIONAL:
|
@@ -2511,7 +2880,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2511
2880
|
|
2512
2881
|
if (VpIsZero(x)) {
|
2513
2882
|
if (is_negative(vexp)) {
|
2514
|
-
|
2883
|
+
y = VpCreateRbObject(n, "#0", true);
|
2515
2884
|
RB_GC_GUARD(y->obj);
|
2516
2885
|
if (BIGDECIMAL_NEGATIVE_P(x)) {
|
2517
2886
|
if (is_integer(vexp)) {
|
@@ -2533,18 +2902,18 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2533
2902
|
/* (+0) ** (-num) -> Infinity */
|
2534
2903
|
VpSetPosInf(y);
|
2535
2904
|
}
|
2536
|
-
|
2905
|
+
return VpCheckGetValue(y);
|
2537
2906
|
}
|
2538
2907
|
else if (is_zero(vexp)) {
|
2539
|
-
|
2908
|
+
return VpCheckGetValue(VpCreateRbObject(n, "1", true));
|
2540
2909
|
}
|
2541
2910
|
else {
|
2542
|
-
|
2911
|
+
return VpCheckGetValue(VpCreateRbObject(n, "0", true));
|
2543
2912
|
}
|
2544
2913
|
}
|
2545
2914
|
|
2546
2915
|
if (is_zero(vexp)) {
|
2547
|
-
|
2916
|
+
return VpCheckGetValue(VpCreateRbObject(n, "1", true));
|
2548
2917
|
}
|
2549
2918
|
else if (is_one(vexp)) {
|
2550
2919
|
return self;
|
@@ -2556,24 +2925,24 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2556
2925
|
if (is_integer(vexp)) {
|
2557
2926
|
if (is_even(vexp)) {
|
2558
2927
|
/* (-Infinity) ** (-even_integer) -> +0 */
|
2559
|
-
|
2928
|
+
return VpCheckGetValue(VpCreateRbObject(n, "0", true));
|
2560
2929
|
}
|
2561
2930
|
else {
|
2562
2931
|
/* (-Infinity) ** (-odd_integer) -> -0 */
|
2563
|
-
|
2932
|
+
return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
|
2564
2933
|
}
|
2565
2934
|
}
|
2566
2935
|
else {
|
2567
2936
|
/* (-Infinity) ** (-non_integer) -> -0 */
|
2568
|
-
|
2937
|
+
return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
|
2569
2938
|
}
|
2570
2939
|
}
|
2571
2940
|
else {
|
2572
|
-
|
2941
|
+
return VpCheckGetValue(VpCreateRbObject(n, "0", true));
|
2573
2942
|
}
|
2574
2943
|
}
|
2575
2944
|
else {
|
2576
|
-
|
2945
|
+
y = VpCreateRbObject(n, "0", true);
|
2577
2946
|
if (BIGDECIMAL_NEGATIVE_P(x)) {
|
2578
2947
|
if (is_integer(vexp)) {
|
2579
2948
|
if (is_even(vexp)) {
|
@@ -2592,52 +2961,52 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2592
2961
|
else {
|
2593
2962
|
VpSetPosInf(y);
|
2594
2963
|
}
|
2595
|
-
|
2964
|
+
return VpCheckGetValue(y);
|
2596
2965
|
}
|
2597
2966
|
}
|
2598
2967
|
|
2599
2968
|
if (exp != NULL) {
|
2600
|
-
return
|
2969
|
+
return bigdecimal_power_by_bigdecimal(x, exp, n);
|
2601
2970
|
}
|
2602
2971
|
else if (RB_TYPE_P(vexp, T_BIGNUM)) {
|
2603
2972
|
VALUE abs_value = BigDecimal_abs(self);
|
2604
2973
|
if (is_one(abs_value)) {
|
2605
|
-
|
2974
|
+
return VpCheckGetValue(VpCreateRbObject(n, "1", true));
|
2606
2975
|
}
|
2607
2976
|
else if (RTEST(rb_funcall(abs_value, '<', 1, INT2FIX(1)))) {
|
2608
2977
|
if (is_negative(vexp)) {
|
2609
|
-
|
2978
|
+
y = VpCreateRbObject(n, "0", true);
|
2610
2979
|
if (is_even(vexp)) {
|
2611
2980
|
VpSetInf(y, VpGetSign(x));
|
2612
2981
|
}
|
2613
2982
|
else {
|
2614
2983
|
VpSetInf(y, -VpGetSign(x));
|
2615
2984
|
}
|
2616
|
-
|
2985
|
+
return VpCheckGetValue(y);
|
2617
2986
|
}
|
2618
2987
|
else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
|
2619
|
-
|
2988
|
+
return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
|
2620
2989
|
}
|
2621
2990
|
else {
|
2622
|
-
|
2991
|
+
return VpCheckGetValue(VpCreateRbObject(n, "0", true));
|
2623
2992
|
}
|
2624
2993
|
}
|
2625
2994
|
else {
|
2626
2995
|
if (is_positive(vexp)) {
|
2627
|
-
|
2996
|
+
y = VpCreateRbObject(n, "0", true);
|
2628
2997
|
if (is_even(vexp)) {
|
2629
2998
|
VpSetInf(y, VpGetSign(x));
|
2630
2999
|
}
|
2631
3000
|
else {
|
2632
3001
|
VpSetInf(y, -VpGetSign(x));
|
2633
3002
|
}
|
2634
|
-
|
3003
|
+
return VpCheckGetValue(y);
|
2635
3004
|
}
|
2636
3005
|
else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
|
2637
|
-
|
3006
|
+
return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
|
2638
3007
|
}
|
2639
3008
|
else {
|
2640
|
-
|
3009
|
+
return VpCheckGetValue(VpCreateRbObject(n, "0", true));
|
2641
3010
|
}
|
2642
3011
|
}
|
2643
3012
|
}
|
@@ -2649,24 +3018,30 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2649
3018
|
|
2650
3019
|
if (VpIsDef(x)) {
|
2651
3020
|
mp = x->Prec * (VpBaseFig() + 1);
|
2652
|
-
|
3021
|
+
GUARD_OBJ(y, VpCreateRbObject(mp * (ma + 1), "0", true));
|
2653
3022
|
}
|
2654
3023
|
else {
|
2655
|
-
|
3024
|
+
GUARD_OBJ(y, VpCreateRbObject(1, "0", true));
|
2656
3025
|
}
|
2657
|
-
|
3026
|
+
VpPowerByInt(y, x, int_exp);
|
2658
3027
|
if (!NIL_P(prec) && VpIsDef(y)) {
|
2659
3028
|
VpMidRound(y, VpGetRoundMode(), n);
|
2660
3029
|
}
|
2661
|
-
return
|
3030
|
+
return VpCheckGetValue(y);
|
2662
3031
|
}
|
2663
3032
|
|
2664
|
-
/*
|
2665
|
-
*
|
3033
|
+
/* call-seq:
|
3034
|
+
* self ** other -> bigdecimal
|
2666
3035
|
*
|
2667
|
-
*
|
3036
|
+
* Returns the \BigDecimal value of +self+ raised to power +other+:
|
3037
|
+
*
|
3038
|
+
* b = BigDecimal('3.14')
|
3039
|
+
* b ** 2 # => 0.98596e1
|
3040
|
+
* b ** 2.0 # => 0.98596e1
|
3041
|
+
* b ** Rational(2, 1) # => 0.98596e1
|
3042
|
+
*
|
3043
|
+
* Related: BigDecimal#power.
|
2668
3044
|
*
|
2669
|
-
* See BigDecimal#power.
|
2670
3045
|
*/
|
2671
3046
|
static VALUE
|
2672
3047
|
BigDecimal_power_op(VALUE self, VALUE exp)
|
@@ -2720,182 +3095,483 @@ opts_exception_p(VALUE opts)
|
|
2720
3095
|
}
|
2721
3096
|
#endif
|
2722
3097
|
|
2723
|
-
static
|
2724
|
-
|
3098
|
+
static VALUE
|
3099
|
+
check_exception(VALUE bd)
|
2725
3100
|
{
|
2726
|
-
|
2727
|
-
|
2728
|
-
|
2729
|
-
|
2730
|
-
|
2731
|
-
|
3101
|
+
assert(is_kind_of_BigDecimal(bd));
|
3102
|
+
|
3103
|
+
Real *vp;
|
3104
|
+
TypedData_Get_Struct(bd, Real, &BigDecimal_data_type, vp);
|
3105
|
+
VpCheckGetValue(vp); /* VpCheckGetValue performs exception check */
|
3106
|
+
|
3107
|
+
return bd;
|
3108
|
+
}
|
2732
3109
|
|
2733
|
-
|
2734
|
-
|
3110
|
+
static VALUE
|
3111
|
+
rb_uint64_convert_to_BigDecimal(uint64_t uval, RB_UNUSED_VAR(size_t digs), int raise_exception)
|
3112
|
+
{
|
3113
|
+
VALUE obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0);
|
2735
3114
|
|
2736
|
-
|
2737
|
-
|
3115
|
+
Real *vp;
|
3116
|
+
if (uval == 0) {
|
3117
|
+
vp = VpAllocReal(1);
|
3118
|
+
vp->MaxPrec = 1;
|
3119
|
+
vp->Prec = 1;
|
3120
|
+
vp->exponent = 1;
|
3121
|
+
VpSetZero(vp, 1);
|
3122
|
+
vp->frac[0] = 0;
|
3123
|
+
}
|
3124
|
+
else if (uval < BASE) {
|
3125
|
+
vp = VpAllocReal(1);
|
3126
|
+
vp->MaxPrec = 1;
|
3127
|
+
vp->Prec = 1;
|
3128
|
+
vp->exponent = 1;
|
3129
|
+
VpSetSign(vp, 1);
|
3130
|
+
vp->frac[0] = (DECDIG)uval;
|
2738
3131
|
}
|
2739
3132
|
else {
|
2740
|
-
|
2741
|
-
|
2742
|
-
|
2743
|
-
|
2744
|
-
|
3133
|
+
DECDIG buf[BIGDECIMAL_INT64_MAX_LENGTH] = {0,};
|
3134
|
+
DECDIG r = uval % BASE;
|
3135
|
+
size_t len = 0, ntz = 0;
|
3136
|
+
if (r == 0) {
|
3137
|
+
// Count and skip trailing zeros
|
3138
|
+
for (; r == 0 && uval > 0; ++ntz) {
|
3139
|
+
uval /= BASE;
|
3140
|
+
r = uval % BASE;
|
2745
3141
|
}
|
2746
|
-
rb_raise(rb_eArgError, "negative precision");
|
2747
3142
|
}
|
2748
|
-
|
2749
|
-
|
2750
|
-
|
2751
|
-
|
2752
|
-
|
2753
|
-
case Qnil:
|
2754
|
-
if (!exc) return NULL;
|
2755
|
-
rb_raise(rb_eTypeError, "can't convert nil into BigDecimal");
|
2756
|
-
case Qtrue:
|
2757
|
-
if (!exc) return NULL;
|
2758
|
-
rb_raise(rb_eTypeError, "can't convert true into BigDecimal");
|
2759
|
-
case Qfalse:
|
2760
|
-
if (!exc) return NULL;
|
2761
|
-
rb_raise(rb_eTypeError, "can't convert false into BigDecimal");
|
2762
|
-
default:
|
2763
|
-
break;
|
3143
|
+
for (; uval > 0; ++len) {
|
3144
|
+
// Store digits
|
3145
|
+
buf[BIGDECIMAL_INT64_MAX_LENGTH - len - 1] = r;
|
3146
|
+
uval /= BASE;
|
3147
|
+
r = uval % BASE;
|
2764
3148
|
}
|
3149
|
+
|
3150
|
+
const size_t exp = len + ntz;
|
3151
|
+
vp = VpAllocReal(len);
|
3152
|
+
vp->MaxPrec = len;
|
3153
|
+
vp->Prec = len;
|
3154
|
+
vp->exponent = exp;
|
3155
|
+
VpSetSign(vp, 1);
|
3156
|
+
MEMCPY(vp->frac, buf + BIGDECIMAL_INT64_MAX_LENGTH - len, DECDIG, len);
|
2765
3157
|
}
|
2766
3158
|
|
2767
|
-
|
2768
|
-
|
2769
|
-
case T_DATA:
|
2770
|
-
if (is_kind_of_BigDecimal(iniValue)) {
|
2771
|
-
return DATA_PTR(iniValue);
|
2772
|
-
}
|
2773
|
-
break;
|
3159
|
+
return BigDecimal_wrap_struct(obj, vp);
|
3160
|
+
}
|
2774
3161
|
|
2775
|
-
|
2776
|
-
|
2777
|
-
|
2778
|
-
|
3162
|
+
static VALUE
|
3163
|
+
rb_int64_convert_to_BigDecimal(int64_t ival, size_t digs, int raise_exception)
|
3164
|
+
{
|
3165
|
+
const uint64_t uval = (ival < 0) ? (((uint64_t)-(ival+1))+1) : (uint64_t)ival;
|
3166
|
+
VALUE bd = rb_uint64_convert_to_BigDecimal(uval, digs, raise_exception);
|
3167
|
+
if (ival < 0) {
|
3168
|
+
Real *vp;
|
3169
|
+
TypedData_Get_Struct(bd, Real, &BigDecimal_data_type, vp);
|
3170
|
+
VpSetSign(vp, -1);
|
3171
|
+
}
|
3172
|
+
return bd;
|
3173
|
+
}
|
2779
3174
|
|
2780
|
-
|
2781
|
-
|
2782
|
-
|
2783
|
-
|
2784
|
-
|
2785
|
-
|
3175
|
+
static VALUE
|
3176
|
+
rb_big_convert_to_BigDecimal(VALUE val, RB_UNUSED_VAR(size_t digs), int raise_exception)
|
3177
|
+
{
|
3178
|
+
assert(RB_TYPE_P(val, T_BIGNUM));
|
3179
|
+
|
3180
|
+
int leading_zeros;
|
3181
|
+
size_t size = rb_absint_size(val, &leading_zeros);
|
3182
|
+
int sign = FIX2INT(rb_big_cmp(val, INT2FIX(0)));
|
3183
|
+
if (sign < 0 && leading_zeros == 0) {
|
3184
|
+
size += 1;
|
3185
|
+
}
|
3186
|
+
if (size <= sizeof(long)) {
|
3187
|
+
if (sign < 0) {
|
3188
|
+
return rb_int64_convert_to_BigDecimal(NUM2LONG(val), digs, raise_exception);
|
2786
3189
|
}
|
2787
|
-
|
2788
|
-
|
2789
|
-
|
2790
|
-
|
2791
|
-
|
2792
|
-
|
2793
|
-
|
2794
|
-
|
2795
|
-
|
2796
|
-
|
2797
|
-
|
2798
|
-
|
2799
|
-
|
2800
|
-
|
2801
|
-
|
2802
|
-
|
2803
|
-
|
3190
|
+
else {
|
3191
|
+
return rb_uint64_convert_to_BigDecimal(NUM2ULONG(val), digs, raise_exception);
|
3192
|
+
}
|
3193
|
+
}
|
3194
|
+
#if defined(SIZEOF_LONG_LONG) && SIZEOF_LONG < SIZEOF_LONG_LONG
|
3195
|
+
else if (size <= sizeof(LONG_LONG)) {
|
3196
|
+
if (sign < 0) {
|
3197
|
+
return rb_int64_convert_to_BigDecimal(NUM2LL(val), digs, raise_exception);
|
3198
|
+
}
|
3199
|
+
else {
|
3200
|
+
return rb_uint64_convert_to_BigDecimal(NUM2ULL(val), digs, raise_exception);
|
3201
|
+
}
|
3202
|
+
}
|
3203
|
+
#endif
|
3204
|
+
else {
|
3205
|
+
VALUE str = rb_big2str(val, 10);
|
3206
|
+
Real *vp = VpCreateRbObject(RSTRING_LEN(str) + BASE_FIG + 1,
|
3207
|
+
RSTRING_PTR(str), true);
|
3208
|
+
RB_GC_GUARD(str);
|
3209
|
+
return check_exception(vp->obj);
|
3210
|
+
}
|
3211
|
+
}
|
2804
3212
|
|
2805
|
-
|
2806
|
-
|
2807
|
-
|
2808
|
-
|
2809
|
-
|
2810
|
-
|
2811
|
-
|
2812
|
-
|
2813
|
-
|
2814
|
-
|
3213
|
+
static VALUE
|
3214
|
+
rb_inum_convert_to_BigDecimal(VALUE val, RB_UNUSED_VAR(size_t digs), int raise_exception)
|
3215
|
+
{
|
3216
|
+
assert(RB_INTEGER_TYPE_P(val));
|
3217
|
+
if (FIXNUM_P(val)) {
|
3218
|
+
return rb_int64_convert_to_BigDecimal(FIX2LONG(val), digs, raise_exception);
|
3219
|
+
}
|
3220
|
+
else {
|
3221
|
+
return rb_big_convert_to_BigDecimal(val, digs, raise_exception);
|
3222
|
+
}
|
3223
|
+
}
|
3224
|
+
|
3225
|
+
static VALUE
|
3226
|
+
rb_float_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
|
3227
|
+
{
|
3228
|
+
assert(RB_FLOAT_TYPE_P(val));
|
3229
|
+
|
3230
|
+
double d = RFLOAT_VALUE(val);
|
3231
|
+
|
3232
|
+
if (isnan(d)) {
|
3233
|
+
VALUE obj = BigDecimal_nan();
|
3234
|
+
return check_exception(obj);
|
3235
|
+
}
|
3236
|
+
else if (isinf(d)) {
|
3237
|
+
VALUE obj;
|
3238
|
+
if (d > 0) {
|
3239
|
+
obj = BigDecimal_positive_infinity();
|
3240
|
+
}
|
3241
|
+
else {
|
3242
|
+
obj = BigDecimal_negative_infinity();
|
3243
|
+
}
|
3244
|
+
return check_exception(obj);
|
3245
|
+
}
|
3246
|
+
else if (d == 0.0) {
|
3247
|
+
if (1/d < 0.0) {
|
3248
|
+
return BigDecimal_negative_zero();
|
3249
|
+
}
|
3250
|
+
else {
|
3251
|
+
return BigDecimal_positive_zero();
|
2815
3252
|
}
|
3253
|
+
}
|
3254
|
+
|
3255
|
+
if (digs == SIZE_MAX) {
|
3256
|
+
if (!raise_exception)
|
3257
|
+
return Qnil;
|
3258
|
+
rb_raise(rb_eArgError,
|
3259
|
+
"can't omit precision for a %"PRIsVALUE".",
|
3260
|
+
CLASS_OF(val));
|
3261
|
+
}
|
3262
|
+
else if (digs > BIGDECIMAL_DOUBLE_FIGURES) {
|
3263
|
+
if (!raise_exception)
|
3264
|
+
return Qnil;
|
3265
|
+
rb_raise(rb_eArgError, "precision too large.");
|
3266
|
+
}
|
3267
|
+
|
3268
|
+
/* Use the same logic in flo_to_s to convert a float to a decimal string */
|
3269
|
+
char buf[BIGDECIMAL_DOUBLE_FIGURES + BASE_FIG + 2 + 1]; /* sizeof(buf) == 28 in the typical case */
|
3270
|
+
int decpt, negative_p;
|
3271
|
+
char *e;
|
3272
|
+
const int mode = digs == 0 ? 0 : 2;
|
3273
|
+
char *p = BigDecimal_dtoa(d, mode, (int)digs, &decpt, &negative_p, &e);
|
3274
|
+
int len10 = (int)(e - p);
|
3275
|
+
if (len10 > BIGDECIMAL_DOUBLE_FIGURES) {
|
3276
|
+
/* TODO: Presumably, rounding should be done here. */
|
3277
|
+
len10 = BIGDECIMAL_DOUBLE_FIGURES;
|
3278
|
+
}
|
3279
|
+
memcpy(buf, p, len10);
|
3280
|
+
xfree(p);
|
3281
|
+
|
3282
|
+
VALUE inum;
|
3283
|
+
size_t RB_UNUSED_VAR(prec) = 0;
|
3284
|
+
size_t exp = 0;
|
3285
|
+
if (decpt > 0) {
|
3286
|
+
if (decpt < len10) {
|
3287
|
+
/*
|
3288
|
+
* len10 |---------------|
|
3289
|
+
* : |-------| frac_len10 = len10 - decpt
|
3290
|
+
* decpt |-------| |--| ntz10 = BASE_FIG - frac_len10 % BASE_FIG
|
3291
|
+
* : : :
|
3292
|
+
* 00 dd dddd.dddd dd 00
|
3293
|
+
* prec |-----.----.----.-----| prec = exp + roomof(frac_len, BASE_FIG)
|
3294
|
+
* exp |-----.----| exp = roomof(decpt, BASE_FIG)
|
3295
|
+
*/
|
3296
|
+
const size_t frac_len10 = len10 - decpt;
|
3297
|
+
const size_t ntz10 = BASE_FIG - frac_len10 % BASE_FIG;
|
3298
|
+
memset(buf + len10, '0', ntz10);
|
3299
|
+
buf[len10 + ntz10] = '\0';
|
3300
|
+
inum = rb_cstr_to_inum(buf, 10, false);
|
3301
|
+
|
3302
|
+
exp = roomof(decpt, BASE_FIG);
|
3303
|
+
prec = exp + roomof(frac_len10, BASE_FIG);
|
3304
|
+
}
|
3305
|
+
else {
|
3306
|
+
/*
|
3307
|
+
* decpt |-----------------------|
|
3308
|
+
* len10 |----------| :
|
3309
|
+
* : |------------| exp10
|
3310
|
+
* : : :
|
3311
|
+
* 00 dd dddd dd 00 0000 0000.0
|
3312
|
+
* : : : :
|
3313
|
+
* : |--| ntz10 = exp10 % BASE_FIG
|
3314
|
+
* prec |-----.----.-----| :
|
3315
|
+
* : |----.----| exp10 / BASE_FIG
|
3316
|
+
* exp |-----.----.-----.----.----|
|
3317
|
+
*/
|
3318
|
+
const size_t exp10 = decpt - len10;
|
3319
|
+
const size_t ntz10 = exp10 % BASE_FIG;
|
3320
|
+
|
3321
|
+
memset(buf + len10, '0', ntz10);
|
3322
|
+
buf[len10 + ntz10] = '\0';
|
3323
|
+
inum = rb_cstr_to_inum(buf, 10, false);
|
3324
|
+
|
3325
|
+
prec = roomof(len10 + ntz10, BASE_FIG);
|
3326
|
+
exp = prec + exp10 / BASE_FIG;
|
3327
|
+
}
|
3328
|
+
}
|
3329
|
+
else if (decpt == 0) {
|
3330
|
+
/*
|
3331
|
+
* len10 |------------|
|
3332
|
+
* : :
|
3333
|
+
* 0.dddd dddd dd 00
|
3334
|
+
* : : :
|
3335
|
+
* : |--| ntz10 = prec * BASE_FIG - len10
|
3336
|
+
* prec |----.----.-----| roomof(len10, BASE_FIG)
|
3337
|
+
*/
|
3338
|
+
prec = roomof(len10, BASE_FIG);
|
3339
|
+
const size_t ntz10 = prec * BASE_FIG - len10;
|
3340
|
+
|
3341
|
+
memset(buf + len10, '0', ntz10);
|
3342
|
+
buf[len10 + ntz10] = '\0';
|
3343
|
+
inum = rb_cstr_to_inum(buf, 10, false);
|
3344
|
+
}
|
3345
|
+
else {
|
3346
|
+
/*
|
3347
|
+
* len10 |---------------|
|
3348
|
+
* : :
|
3349
|
+
* decpt |-------| |--| ntz10 = prec * BASE_FIG - nlz10 - len10
|
3350
|
+
* : : :
|
3351
|
+
* 0.0000 00 dd dddd dddd dd 00
|
3352
|
+
* : : :
|
3353
|
+
* nlz10 |--| : decpt % BASE_FIG
|
3354
|
+
* prec |-----.----.----.-----| roomof(decpt + len10, BASE_FIG) - exp
|
3355
|
+
* exp |----| decpt / BASE_FIG
|
3356
|
+
*/
|
3357
|
+
decpt = -decpt;
|
3358
|
+
|
3359
|
+
const size_t nlz10 = decpt % BASE_FIG;
|
3360
|
+
exp = decpt / BASE_FIG;
|
3361
|
+
prec = roomof(decpt + len10, BASE_FIG) - exp;
|
3362
|
+
const size_t ntz10 = prec * BASE_FIG - nlz10 - len10;
|
3363
|
+
|
3364
|
+
if (nlz10 > 0) {
|
3365
|
+
memmove(buf + nlz10, buf, len10);
|
3366
|
+
memset(buf, '0', nlz10);
|
3367
|
+
}
|
3368
|
+
memset(buf + nlz10 + len10, '0', ntz10);
|
3369
|
+
buf[nlz10 + len10 + ntz10] = '\0';
|
3370
|
+
inum = rb_cstr_to_inum(buf, 10, false);
|
3371
|
+
|
3372
|
+
exp = -exp;
|
3373
|
+
}
|
3374
|
+
|
3375
|
+
VALUE bd = rb_inum_convert_to_BigDecimal(inum, SIZE_MAX, raise_exception);
|
3376
|
+
Real *vp;
|
3377
|
+
TypedData_Get_Struct(bd, Real, &BigDecimal_data_type, vp);
|
3378
|
+
assert(vp->Prec == prec);
|
3379
|
+
vp->exponent = exp;
|
3380
|
+
|
3381
|
+
if (negative_p) VpSetSign(vp, -1);
|
3382
|
+
return bd;
|
3383
|
+
}
|
3384
|
+
|
3385
|
+
static VALUE
|
3386
|
+
rb_rational_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
|
3387
|
+
{
|
3388
|
+
assert(RB_TYPE_P(val, T_RATIONAL));
|
3389
|
+
|
3390
|
+
if (digs == SIZE_MAX) {
|
3391
|
+
if (!raise_exception)
|
3392
|
+
return Qnil;
|
3393
|
+
rb_raise(rb_eArgError,
|
3394
|
+
"can't omit precision for a %"PRIsVALUE".",
|
3395
|
+
CLASS_OF(val));
|
3396
|
+
}
|
3397
|
+
|
3398
|
+
VALUE num = rb_inum_convert_to_BigDecimal(rb_rational_num(val), 0, raise_exception);
|
3399
|
+
VALUE d = BigDecimal_div2(num, rb_rational_den(val), SIZET2NUM(digs));
|
3400
|
+
return d;
|
3401
|
+
}
|
3402
|
+
|
3403
|
+
static VALUE
|
3404
|
+
rb_cstr_convert_to_BigDecimal(const char *c_str, size_t digs, int raise_exception)
|
3405
|
+
{
|
3406
|
+
if (digs == SIZE_MAX)
|
3407
|
+
digs = 0;
|
3408
|
+
|
3409
|
+
Real *vp = VpCreateRbObject(digs, c_str, raise_exception);
|
3410
|
+
if (!vp)
|
3411
|
+
return Qnil;
|
3412
|
+
return VpCheckGetValue(vp);
|
3413
|
+
}
|
3414
|
+
|
3415
|
+
static inline VALUE
|
3416
|
+
rb_str_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
|
3417
|
+
{
|
3418
|
+
const char *c_str = StringValueCStr(val);
|
3419
|
+
return rb_cstr_convert_to_BigDecimal(c_str, digs, raise_exception);
|
3420
|
+
}
|
3421
|
+
|
3422
|
+
static VALUE
|
3423
|
+
rb_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
|
3424
|
+
{
|
3425
|
+
switch (val) {
|
3426
|
+
case Qnil:
|
3427
|
+
case Qtrue:
|
3428
|
+
case Qfalse:
|
3429
|
+
if (raise_exception) {
|
3430
|
+
const char *cname = NIL_P(val) ? "nil" :
|
3431
|
+
val == Qtrue ? "true" :
|
3432
|
+
val == Qfalse ? "false" :
|
3433
|
+
NULL;
|
3434
|
+
rb_raise(rb_eTypeError,
|
3435
|
+
"can't convert %s into BigDecimal", cname);
|
3436
|
+
}
|
3437
|
+
return Qnil;
|
2816
3438
|
|
2817
|
-
case T_STRING:
|
2818
|
-
/* fall through */
|
2819
3439
|
default:
|
2820
|
-
|
3440
|
+
break;
|
3441
|
+
}
|
3442
|
+
|
3443
|
+
if (is_kind_of_BigDecimal(val)) {
|
3444
|
+
if (digs == SIZE_MAX)
|
3445
|
+
return check_exception(val);
|
3446
|
+
|
3447
|
+
Real *vp;
|
3448
|
+
TypedData_Get_Struct(val, Real, &BigDecimal_data_type, vp);
|
3449
|
+
|
3450
|
+
VALUE copy = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0);
|
3451
|
+
vp = VpCopy(NULL, vp);
|
3452
|
+
/* TODO: rounding */
|
3453
|
+
BigDecimal_wrap_struct(copy, vp);
|
3454
|
+
return VpCheckGetValue(vp);
|
3455
|
+
}
|
3456
|
+
else if (RB_INTEGER_TYPE_P(val)) {
|
3457
|
+
return rb_inum_convert_to_BigDecimal(val, digs, raise_exception);
|
3458
|
+
}
|
3459
|
+
else if (RB_FLOAT_TYPE_P(val)) {
|
3460
|
+
return rb_float_convert_to_BigDecimal(val, digs, raise_exception);
|
2821
3461
|
}
|
2822
|
-
|
2823
|
-
|
2824
|
-
iniValue = rb_check_convert_type(iniValue, T_STRING, "String", "to_str");
|
2825
|
-
if (NIL_P(iniValue)) return NULL;
|
3462
|
+
else if (RB_TYPE_P(val, T_RATIONAL)) {
|
3463
|
+
return rb_rational_convert_to_BigDecimal(val, digs, raise_exception);
|
2826
3464
|
}
|
2827
|
-
|
2828
|
-
|
3465
|
+
else if (RB_TYPE_P(val, T_COMPLEX)) {
|
3466
|
+
VALUE im = rb_complex_imag(val);
|
3467
|
+
if (!is_zero(im)) {
|
3468
|
+
/* TODO: handle raise_exception */
|
3469
|
+
rb_raise(rb_eArgError,
|
3470
|
+
"Unable to make a BigDecimal from non-zero imaginary number");
|
3471
|
+
}
|
3472
|
+
return rb_convert_to_BigDecimal(rb_complex_real(val), digs, raise_exception);
|
3473
|
+
}
|
3474
|
+
else if (RB_TYPE_P(val, T_STRING)) {
|
3475
|
+
return rb_str_convert_to_BigDecimal(val, digs, raise_exception);
|
3476
|
+
}
|
3477
|
+
|
3478
|
+
/* TODO: chheck to_d */
|
3479
|
+
/* TODO: chheck to_int */
|
3480
|
+
|
3481
|
+
VALUE str = rb_check_convert_type(val, T_STRING, "String", "to_str");
|
3482
|
+
if (!RB_TYPE_P(str, T_STRING)) {
|
3483
|
+
if (raise_exception) {
|
3484
|
+
rb_raise(rb_eTypeError,
|
3485
|
+
"can't convert %"PRIsVALUE" into BigDecimal", rb_obj_class(val));
|
3486
|
+
}
|
3487
|
+
return Qnil;
|
3488
|
+
}
|
3489
|
+
return rb_str_convert_to_BigDecimal(str, digs, raise_exception);
|
2829
3490
|
}
|
2830
3491
|
|
2831
|
-
/*
|
2832
|
-
*
|
3492
|
+
/* call-seq:
|
3493
|
+
* BigDecimal(value, exception: true) -> bigdecimal
|
3494
|
+
* BigDecimal(value, ndigits, exception: true) -> bigdecimal
|
2833
3495
|
*
|
2834
|
-
*
|
3496
|
+
* Returns the \BigDecimal converted from +value+
|
3497
|
+
* with a precision of +ndigits+ decimal digits.
|
2835
3498
|
*
|
2836
|
-
*
|
2837
|
-
*
|
3499
|
+
* When +ndigits+ is less than the number of significant digits
|
3500
|
+
* in the value, the result is rounded to that number of digits,
|
3501
|
+
* according to the current rounding mode; see BigDecimal.mode.
|
2838
3502
|
*
|
2839
|
-
*
|
2840
|
-
* terminate the value.
|
3503
|
+
* Returns +value+ converted to a \BigDecimal, depending on the type of +value+:
|
2841
3504
|
*
|
2842
|
-
*
|
2843
|
-
* the number of significant digits is determined from the initial
|
2844
|
-
* value.
|
3505
|
+
* - Integer, Float, Rational, Complex, or BigDecimal: converted directly:
|
2845
3506
|
*
|
2846
|
-
*
|
2847
|
-
*
|
3507
|
+
* # Integer, Complex, or BigDecimal value does not require ndigits; ignored if given.
|
3508
|
+
* BigDecimal(2) # => 0.2e1
|
3509
|
+
* BigDecimal(Complex(2, 0)) # => 0.2e1
|
3510
|
+
* BigDecimal(BigDecimal(2)) # => 0.2e1
|
3511
|
+
* # Float or Rational value requires ndigits.
|
3512
|
+
* BigDecimal(2.0, 0) # => 0.2e1
|
3513
|
+
* BigDecimal(Rational(2, 1), 0) # => 0.2e1
|
2848
3514
|
*
|
2849
|
-
*
|
2850
|
-
*
|
2851
|
-
* for invalid.
|
3515
|
+
* - String: converted by parsing if it contains an integer or floating-point literal;
|
3516
|
+
* leading and trailing whitespace is ignored:
|
2852
3517
|
*
|
3518
|
+
* # String does not require ndigits; ignored if given.
|
3519
|
+
* BigDecimal('2') # => 0.2e1
|
3520
|
+
* BigDecimal('2.0') # => 0.2e1
|
3521
|
+
* BigDecimal('0.2e1') # => 0.2e1
|
3522
|
+
* BigDecimal(' 2.0 ') # => 0.2e1
|
2853
3523
|
*
|
2854
|
-
*
|
3524
|
+
* - Other type that responds to method <tt>:to_str</tt>:
|
3525
|
+
* first converted to a string, then converted to a \BigDecimal, as above.
|
2855
3526
|
*
|
2856
|
-
*
|
2857
|
-
* Rational, nor BigDecimal, this exception is raised.
|
3527
|
+
* - Other type:
|
2858
3528
|
*
|
2859
|
-
*
|
3529
|
+
* - Raises an exception if keyword argument +exception+ is +true+.
|
3530
|
+
* - Returns +nil+ if keyword argument +exception+ is +true+.
|
2860
3531
|
*
|
2861
|
-
*
|
2862
|
-
*
|
3532
|
+
* Raises an exception if +value+ evaluates to a Float
|
3533
|
+
* and +digits+ is larger than Float::DIG + 1.
|
2863
3534
|
*
|
2864
|
-
* ArgumentError:: If the +initial+ is a Float or Rational, and the +digits+
|
2865
|
-
* value is omitted, this exception is raised.
|
2866
3535
|
*/
|
2867
3536
|
static VALUE
|
2868
3537
|
f_BigDecimal(int argc, VALUE *argv, VALUE self)
|
2869
3538
|
{
|
2870
|
-
|
2871
|
-
|
2872
|
-
|
2873
|
-
|
2874
|
-
|
2875
|
-
|
3539
|
+
VALUE val, digs_v, opts = Qnil;
|
3540
|
+
argc = rb_scan_args(argc, argv, "11:", &val, &digs_v, &opts);
|
3541
|
+
int exception = opts_exception_p(opts);
|
3542
|
+
|
3543
|
+
size_t digs = SIZE_MAX; /* this means digs is omitted */
|
3544
|
+
if (argc > 1) {
|
3545
|
+
digs_v = rb_to_int(digs_v);
|
3546
|
+
if (FIXNUM_P(digs_v)) {
|
3547
|
+
long n = FIX2LONG(digs_v);
|
3548
|
+
if (n < 0)
|
3549
|
+
goto negative_digs;
|
3550
|
+
digs = (size_t)n;
|
3551
|
+
}
|
3552
|
+
else {
|
3553
|
+
if (RBIGNUM_NEGATIVE_P(digs_v)) {
|
3554
|
+
negative_digs:
|
3555
|
+
if (!exception)
|
3556
|
+
return Qnil;
|
3557
|
+
rb_raise(rb_eArgError, "negative precision");
|
3558
|
+
}
|
3559
|
+
digs = NUM2SIZET(digs_v);
|
3560
|
+
}
|
2876
3561
|
}
|
2877
|
-
|
2878
|
-
|
2879
|
-
if (pv == NULL) return Qnil;
|
2880
|
-
SAVE(pv);
|
2881
|
-
if (ToValue(pv)) pv = VpCopy(NULL, pv);
|
2882
|
-
RTYPEDDATA_DATA(obj) = pv;
|
2883
|
-
RB_OBJ_FREEZE(obj);
|
2884
|
-
return pv->obj = obj;
|
3562
|
+
|
3563
|
+
return rb_convert_to_BigDecimal(val, digs, exception);
|
2885
3564
|
}
|
2886
3565
|
|
2887
3566
|
static VALUE
|
2888
3567
|
BigDecimal_s_interpret_loosely(VALUE klass, VALUE str)
|
2889
3568
|
{
|
2890
|
-
|
2891
|
-
|
2892
|
-
|
2893
|
-
|
2894
|
-
|
2895
|
-
|
2896
|
-
pv->obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, pv);
|
2897
|
-
RB_OBJ_FREEZE(pv->obj);
|
2898
|
-
return pv->obj;
|
3569
|
+
char const *c_str = StringValueCStr(str);
|
3570
|
+
Real *vp = VpNewRbClass(0, c_str, klass, false, true);
|
3571
|
+
if (!vp)
|
3572
|
+
return Qnil;
|
3573
|
+
else
|
3574
|
+
return VpCheckGetValue(vp);
|
2899
3575
|
}
|
2900
3576
|
|
2901
3577
|
/* call-seq:
|
@@ -3079,7 +3755,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
|
|
3079
3755
|
infinite = isinf(flo);
|
3080
3756
|
nan = isnan(flo);
|
3081
3757
|
if (!infinite && !nan) {
|
3082
|
-
vx = GetVpValueWithPrec(x,
|
3758
|
+
vx = GetVpValueWithPrec(x, 0, 0);
|
3083
3759
|
}
|
3084
3760
|
break;
|
3085
3761
|
|
@@ -3092,29 +3768,29 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
|
|
3092
3768
|
}
|
3093
3769
|
if (infinite) {
|
3094
3770
|
if (negative) {
|
3095
|
-
|
3771
|
+
return VpCheckGetValue(GetVpValueWithPrec(INT2FIX(0), prec, 1));
|
3096
3772
|
}
|
3097
3773
|
else {
|
3098
3774
|
Real* vy;
|
3099
|
-
|
3775
|
+
vy = VpCreateRbObject(prec, "#0", true);
|
3100
3776
|
VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
|
3101
3777
|
RB_GC_GUARD(vy->obj);
|
3102
|
-
|
3778
|
+
return VpCheckGetValue(vy);
|
3103
3779
|
}
|
3104
3780
|
}
|
3105
3781
|
else if (nan) {
|
3106
3782
|
Real* vy;
|
3107
|
-
|
3783
|
+
vy = VpCreateRbObject(prec, "#0", true);
|
3108
3784
|
VpSetNaN(vy);
|
3109
3785
|
RB_GC_GUARD(vy->obj);
|
3110
|
-
|
3786
|
+
return VpCheckGetValue(vy);
|
3111
3787
|
}
|
3112
3788
|
else if (vx == NULL) {
|
3113
3789
|
cannot_be_coerced_into_BigDecimal(rb_eArgError, x);
|
3114
3790
|
}
|
3115
3791
|
x = vx->obj;
|
3116
3792
|
|
3117
|
-
n = prec +
|
3793
|
+
n = prec + BIGDECIMAL_DOUBLE_FIGURES;
|
3118
3794
|
negative = BIGDECIMAL_NEGATIVE_P(vx);
|
3119
3795
|
if (negative) {
|
3120
3796
|
VALUE x_zero = INT2NUM(1);
|
@@ -3124,7 +3800,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
|
|
3124
3800
|
VpSetSign(vx, 1);
|
3125
3801
|
}
|
3126
3802
|
|
3127
|
-
one =
|
3803
|
+
one = VpCheckGetValue(VpCreateRbObject(1, "1", true));
|
3128
3804
|
y = one;
|
3129
3805
|
d = y;
|
3130
3806
|
i = 1;
|
@@ -3139,8 +3815,8 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
|
|
3139
3815
|
if (m <= 0) {
|
3140
3816
|
break;
|
3141
3817
|
}
|
3142
|
-
else if ((size_t)m <
|
3143
|
-
m =
|
3818
|
+
else if ((size_t)m < BIGDECIMAL_DOUBLE_FIGURES) {
|
3819
|
+
m = BIGDECIMAL_DOUBLE_FIGURES;
|
3144
3820
|
}
|
3145
3821
|
|
3146
3822
|
d = BigDecimal_mult(d, x); /* d <- d * x */
|
@@ -3232,7 +3908,7 @@ get_vp_value:
|
|
3232
3908
|
infinite = isinf(flo);
|
3233
3909
|
nan = isnan(flo);
|
3234
3910
|
if (!zero && !negative && !infinite && !nan) {
|
3235
|
-
vx = GetVpValueWithPrec(x,
|
3911
|
+
vx = GetVpValueWithPrec(x, 0, 1);
|
3236
3912
|
}
|
3237
3913
|
break;
|
3238
3914
|
|
@@ -3252,17 +3928,17 @@ get_vp_value:
|
|
3252
3928
|
}
|
3253
3929
|
if (infinite && !negative) {
|
3254
3930
|
Real* vy;
|
3255
|
-
|
3931
|
+
vy = VpCreateRbObject(prec, "#0", true);
|
3256
3932
|
RB_GC_GUARD(vy->obj);
|
3257
3933
|
VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
|
3258
|
-
|
3934
|
+
return VpCheckGetValue(vy);
|
3259
3935
|
}
|
3260
3936
|
else if (nan) {
|
3261
3937
|
Real* vy;
|
3262
|
-
|
3938
|
+
vy = VpCreateRbObject(prec, "#0", true);
|
3263
3939
|
RB_GC_GUARD(vy->obj);
|
3264
3940
|
VpSetNaN(vy);
|
3265
|
-
|
3941
|
+
return VpCheckGetValue(vy);
|
3266
3942
|
}
|
3267
3943
|
else if (zero || negative) {
|
3268
3944
|
rb_raise(rb_eMathDomainError,
|
@@ -3271,18 +3947,18 @@ get_vp_value:
|
|
3271
3947
|
else if (vx == NULL) {
|
3272
3948
|
cannot_be_coerced_into_BigDecimal(rb_eArgError, x);
|
3273
3949
|
}
|
3274
|
-
x =
|
3950
|
+
x = VpCheckGetValue(vx);
|
3275
3951
|
|
3276
|
-
RB_GC_GUARD(one) =
|
3277
|
-
RB_GC_GUARD(two) =
|
3952
|
+
RB_GC_GUARD(one) = VpCheckGetValue(VpCreateRbObject(1, "1", true));
|
3953
|
+
RB_GC_GUARD(two) = VpCheckGetValue(VpCreateRbObject(1, "2", true));
|
3278
3954
|
|
3279
|
-
n = prec +
|
3955
|
+
n = prec + BIGDECIMAL_DOUBLE_FIGURES;
|
3280
3956
|
RB_GC_GUARD(vn) = SSIZET2NUM(n);
|
3281
3957
|
expo = VpExponent10(vx);
|
3282
3958
|
if (expo < 0 || expo >= 3) {
|
3283
3959
|
char buf[DECIMAL_SIZE_OF_BITS(SIZEOF_VALUE * CHAR_BIT) + 4];
|
3284
3960
|
snprintf(buf, sizeof(buf), "1E%"PRIdVALUE, -expo);
|
3285
|
-
|
3961
|
+
x = BigDecimal_mult2(x, VpCheckGetValue(VpCreateRbObject(1, buf, true)), vn);
|
3286
3962
|
}
|
3287
3963
|
else {
|
3288
3964
|
expo = 0;
|
@@ -3300,8 +3976,8 @@ get_vp_value:
|
|
3300
3976
|
if (m <= 0) {
|
3301
3977
|
break;
|
3302
3978
|
}
|
3303
|
-
else if ((size_t)m <
|
3304
|
-
m =
|
3979
|
+
else if ((size_t)m < BIGDECIMAL_DOUBLE_FIGURES) {
|
3980
|
+
m = BIGDECIMAL_DOUBLE_FIGURES;
|
3305
3981
|
}
|
3306
3982
|
|
3307
3983
|
x = BigDecimal_mult2(x2, x, vn);
|
@@ -3314,7 +3990,7 @@ get_vp_value:
|
|
3314
3990
|
if (expo != 0) {
|
3315
3991
|
VALUE log10, vexpo, dy;
|
3316
3992
|
log10 = BigMath_s_log(klass, INT2FIX(10), vprec);
|
3317
|
-
|
3993
|
+
vexpo = VpCheckGetValue(GetVpValue(SSIZET2NUM(expo), 1));
|
3318
3994
|
dy = BigDecimal_mult(log10, vexpo);
|
3319
3995
|
y = BigDecimal_add(y, dy);
|
3320
3996
|
}
|
@@ -3322,6 +3998,46 @@ get_vp_value:
|
|
3322
3998
|
return y;
|
3323
3999
|
}
|
3324
4000
|
|
4001
|
+
static VALUE BIGDECIMAL_NAN = Qnil;
|
4002
|
+
|
4003
|
+
static VALUE
|
4004
|
+
BigDecimal_nan(void)
|
4005
|
+
{
|
4006
|
+
return BIGDECIMAL_NAN;
|
4007
|
+
}
|
4008
|
+
|
4009
|
+
static VALUE BIGDECIMAL_POSITIVE_INFINITY = Qnil;
|
4010
|
+
|
4011
|
+
static VALUE
|
4012
|
+
BigDecimal_positive_infinity(void)
|
4013
|
+
{
|
4014
|
+
return BIGDECIMAL_POSITIVE_INFINITY;
|
4015
|
+
}
|
4016
|
+
|
4017
|
+
static VALUE BIGDECIMAL_NEGATIVE_INFINITY = Qnil;
|
4018
|
+
|
4019
|
+
static VALUE
|
4020
|
+
BigDecimal_negative_infinity(void)
|
4021
|
+
{
|
4022
|
+
return BIGDECIMAL_NEGATIVE_INFINITY;
|
4023
|
+
}
|
4024
|
+
|
4025
|
+
static VALUE BIGDECIMAL_POSITIVE_ZERO = Qnil;
|
4026
|
+
|
4027
|
+
static VALUE
|
4028
|
+
BigDecimal_positive_zero(void)
|
4029
|
+
{
|
4030
|
+
return BIGDECIMAL_POSITIVE_ZERO;
|
4031
|
+
}
|
4032
|
+
|
4033
|
+
static VALUE BIGDECIMAL_NEGATIVE_ZERO = Qnil;
|
4034
|
+
|
4035
|
+
static VALUE
|
4036
|
+
BigDecimal_negative_zero(void)
|
4037
|
+
{
|
4038
|
+
return BIGDECIMAL_NEGATIVE_ZERO;
|
4039
|
+
}
|
4040
|
+
|
3325
4041
|
/* Document-class: BigDecimal
|
3326
4042
|
* BigDecimal provides arbitrary-precision floating point decimal arithmetic.
|
3327
4043
|
*
|
@@ -3365,6 +4081,18 @@ get_vp_value:
|
|
3365
4081
|
*
|
3366
4082
|
* (1.2 - 1.0) == 0.2 #=> false
|
3367
4083
|
*
|
4084
|
+
* == A Note About Precision
|
4085
|
+
*
|
4086
|
+
* For a calculation using a \BigDecimal and another +value+,
|
4087
|
+
* the precision of the result depends on the type of +value+:
|
4088
|
+
*
|
4089
|
+
* - If +value+ is a \Float,
|
4090
|
+
* the precision is Float::DIG + 1.
|
4091
|
+
* - If +value+ is a \Rational, the precision is larger than Float::DIG + 1.
|
4092
|
+
* - If +value+ is a \BigDecimal, the precision is +value+'s precision in the
|
4093
|
+
* internal representation, which is platform-dependent.
|
4094
|
+
* - If +value+ is other object, the precision is determined by the result of +BigDecimal(value)+.
|
4095
|
+
*
|
3368
4096
|
* == Special features of accurate decimal arithmetic
|
3369
4097
|
*
|
3370
4098
|
* Because BigDecimal is more accurate than normal binary floating point
|
@@ -3450,6 +4178,9 @@ get_vp_value:
|
|
3450
4178
|
void
|
3451
4179
|
Init_bigdecimal(void)
|
3452
4180
|
{
|
4181
|
+
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
4182
|
+
rb_ext_ractor_safe(true);
|
4183
|
+
#endif
|
3453
4184
|
VALUE arg;
|
3454
4185
|
|
3455
4186
|
id_BigDecimal_exception_mode = rb_intern_const("BigDecimal.exception_mode");
|
@@ -3590,17 +4321,40 @@ Init_bigdecimal(void)
|
|
3590
4321
|
/* -3: Indicates that a value is negative and infinite. See BigDecimal.sign. */
|
3591
4322
|
rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_INFINITE", INT2FIX(VP_SIGN_NEGATIVE_INFINITE));
|
3592
4323
|
|
3593
|
-
|
4324
|
+
/* Positive zero value. */
|
4325
|
+
arg = rb_str_new2("+0");
|
4326
|
+
BIGDECIMAL_POSITIVE_ZERO = f_BigDecimal(1, &arg, rb_cBigDecimal);
|
4327
|
+
rb_gc_register_mark_object(BIGDECIMAL_POSITIVE_ZERO);
|
4328
|
+
|
4329
|
+
/* Negative zero value. */
|
4330
|
+
arg = rb_str_new2("-0");
|
4331
|
+
BIGDECIMAL_NEGATIVE_ZERO = f_BigDecimal(1, &arg, rb_cBigDecimal);
|
4332
|
+
rb_gc_register_mark_object(BIGDECIMAL_NEGATIVE_ZERO);
|
4333
|
+
|
3594
4334
|
/* Positive infinity value. */
|
3595
|
-
|
3596
|
-
|
4335
|
+
arg = rb_str_new2("+Infinity");
|
4336
|
+
BIGDECIMAL_POSITIVE_INFINITY = f_BigDecimal(1, &arg, rb_cBigDecimal);
|
4337
|
+
rb_gc_register_mark_object(BIGDECIMAL_POSITIVE_INFINITY);
|
4338
|
+
|
4339
|
+
/* Negative infinity value. */
|
4340
|
+
arg = rb_str_new2("-Infinity");
|
4341
|
+
BIGDECIMAL_NEGATIVE_INFINITY = f_BigDecimal(1, &arg, rb_cBigDecimal);
|
4342
|
+
rb_gc_register_mark_object(BIGDECIMAL_NEGATIVE_INFINITY);
|
4343
|
+
|
3597
4344
|
/* 'Not a Number' value. */
|
3598
|
-
|
4345
|
+
arg = rb_str_new2("NaN");
|
4346
|
+
BIGDECIMAL_NAN = f_BigDecimal(1, &arg, rb_cBigDecimal);
|
4347
|
+
rb_gc_register_mark_object(BIGDECIMAL_NAN);
|
3599
4348
|
|
4349
|
+
/* Special value constants */
|
4350
|
+
rb_define_const(rb_cBigDecimal, "INFINITY", BIGDECIMAL_POSITIVE_INFINITY);
|
4351
|
+
rb_define_const(rb_cBigDecimal, "NAN", BIGDECIMAL_NAN);
|
3600
4352
|
|
3601
4353
|
/* instance methods */
|
3602
4354
|
rb_define_method(rb_cBigDecimal, "precs", BigDecimal_prec, 0);
|
3603
4355
|
rb_define_method(rb_cBigDecimal, "precision", BigDecimal_precision, 0);
|
4356
|
+
rb_define_method(rb_cBigDecimal, "scale", BigDecimal_scale, 0);
|
4357
|
+
rb_define_method(rb_cBigDecimal, "precision_scale", BigDecimal_precision_scale, 0);
|
3604
4358
|
rb_define_method(rb_cBigDecimal, "n_significant_digits", BigDecimal_n_significant_digits, 0);
|
3605
4359
|
|
3606
4360
|
rb_define_method(rb_cBigDecimal, "add", BigDecimal_add2, 2);
|
@@ -3619,7 +4373,7 @@ Init_bigdecimal(void)
|
|
3619
4373
|
rb_define_method(rb_cBigDecimal, "-@", BigDecimal_neg, 0);
|
3620
4374
|
rb_define_method(rb_cBigDecimal, "*", BigDecimal_mult, 1);
|
3621
4375
|
rb_define_method(rb_cBigDecimal, "/", BigDecimal_div, 1);
|
3622
|
-
rb_define_method(rb_cBigDecimal, "quo",
|
4376
|
+
rb_define_method(rb_cBigDecimal, "quo", BigDecimal_quo, -1);
|
3623
4377
|
rb_define_method(rb_cBigDecimal, "%", BigDecimal_mod, 1);
|
3624
4378
|
rb_define_method(rb_cBigDecimal, "modulo", BigDecimal_mod, 1);
|
3625
4379
|
rb_define_method(rb_cBigDecimal, "remainder", BigDecimal_remainder, 1);
|
@@ -3710,14 +4464,17 @@ enum op_sw {
|
|
3710
4464
|
|
3711
4465
|
static int VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw);
|
3712
4466
|
static int AddExponent(Real *a, SIGNED_VALUE n);
|
3713
|
-
static
|
3714
|
-
static
|
3715
|
-
static size_t VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos,
|
4467
|
+
static DECDIG VpAddAbs(Real *a,Real *b,Real *c);
|
4468
|
+
static DECDIG VpSubAbs(Real *a,Real *b,Real *c);
|
4469
|
+
static size_t VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos, DECDIG *av, DECDIG *bv);
|
3716
4470
|
static int VpNmlz(Real *a);
|
3717
4471
|
static void VpFormatSt(char *psz, size_t fFmt);
|
3718
4472
|
static int VpRdup(Real *m, size_t ind_m);
|
3719
4473
|
|
3720
4474
|
#ifdef BIGDECIMAL_DEBUG
|
4475
|
+
# ifdef HAVE_RB_EXT_RACTOR_SAFE
|
4476
|
+
# error Need to make rewiting gnAlloc atomic
|
4477
|
+
# endif
|
3721
4478
|
static int gnAlloc = 0; /* Memory allocation counter */
|
3722
4479
|
#endif /* BIGDECIMAL_DEBUG */
|
3723
4480
|
|
@@ -3725,9 +4482,6 @@ VP_EXPORT void *
|
|
3725
4482
|
VpMemAlloc(size_t mb)
|
3726
4483
|
{
|
3727
4484
|
void *p = xmalloc(mb);
|
3728
|
-
if (!p) {
|
3729
|
-
VpException(VP_EXCEPTION_MEMORY, "failed to allocate memory", 1);
|
3730
|
-
}
|
3731
4485
|
memset(p, 0, mb);
|
3732
4486
|
#ifdef BIGDECIMAL_DEBUG
|
3733
4487
|
gnAlloc++; /* Count allocation call */
|
@@ -3738,11 +4492,7 @@ VpMemAlloc(size_t mb)
|
|
3738
4492
|
VP_EXPORT void *
|
3739
4493
|
VpMemRealloc(void *ptr, size_t mb)
|
3740
4494
|
{
|
3741
|
-
|
3742
|
-
if (!p) {
|
3743
|
-
VpException(VP_EXCEPTION_MEMORY, "failed to allocate memory", 1);
|
3744
|
-
}
|
3745
|
-
return p;
|
4495
|
+
return xrealloc(ptr, mb);
|
3746
4496
|
}
|
3747
4497
|
|
3748
4498
|
VP_EXPORT void
|
@@ -3768,7 +4518,7 @@ VpFree(Real *pv)
|
|
3768
4518
|
* EXCEPTION Handling.
|
3769
4519
|
*/
|
3770
4520
|
|
3771
|
-
#define
|
4521
|
+
#define bigdecimal_set_thread_local_exception_mode(mode) \
|
3772
4522
|
rb_thread_local_aset( \
|
3773
4523
|
rb_thread_current(), \
|
3774
4524
|
id_BigDecimal_exception_mode, \
|
@@ -3784,8 +4534,8 @@ VpGetException (void)
|
|
3784
4534
|
);
|
3785
4535
|
|
3786
4536
|
if (NIL_P(vmode)) {
|
3787
|
-
|
3788
|
-
return
|
4537
|
+
bigdecimal_set_thread_local_exception_mode(BIGDECIMAL_EXCEPTION_MODE_DEFAULT);
|
4538
|
+
return BIGDECIMAL_EXCEPTION_MODE_DEFAULT;
|
3789
4539
|
}
|
3790
4540
|
|
3791
4541
|
return NUM2USHORT(vmode);
|
@@ -3794,20 +4544,41 @@ VpGetException (void)
|
|
3794
4544
|
static void
|
3795
4545
|
VpSetException(unsigned short f)
|
3796
4546
|
{
|
3797
|
-
|
4547
|
+
bigdecimal_set_thread_local_exception_mode(f);
|
4548
|
+
}
|
4549
|
+
|
4550
|
+
static void
|
4551
|
+
VpCheckException(Real *p, bool always)
|
4552
|
+
{
|
4553
|
+
if (VpIsNaN(p)) {
|
4554
|
+
VpException(VP_EXCEPTION_NaN, "Computation results in 'NaN' (Not a Number)", always);
|
4555
|
+
}
|
4556
|
+
else if (VpIsPosInf(p)) {
|
4557
|
+
VpException(VP_EXCEPTION_INFINITY, "Computation results in 'Infinity'", always);
|
4558
|
+
}
|
4559
|
+
else if (VpIsNegInf(p)) {
|
4560
|
+
VpException(VP_EXCEPTION_INFINITY, "Computation results in '-Infinity'", always);
|
4561
|
+
}
|
4562
|
+
}
|
4563
|
+
|
4564
|
+
static VALUE
|
4565
|
+
VpCheckGetValue(Real *p)
|
4566
|
+
{
|
4567
|
+
VpCheckException(p, false);
|
4568
|
+
return p->obj;
|
3798
4569
|
}
|
3799
4570
|
|
3800
4571
|
/*
|
3801
4572
|
* Precision limit.
|
3802
4573
|
*/
|
3803
4574
|
|
3804
|
-
#define
|
4575
|
+
#define bigdecimal_set_thread_local_precision_limit(limit) \
|
3805
4576
|
rb_thread_local_aset( \
|
3806
4577
|
rb_thread_current(), \
|
3807
4578
|
id_BigDecimal_precision_limit, \
|
3808
4579
|
SIZET2NUM(limit) \
|
3809
4580
|
)
|
3810
|
-
#define
|
4581
|
+
#define BIGDECIMAL_PRECISION_LIMIT_DEFAULT ((size_t)0)
|
3811
4582
|
|
3812
4583
|
/* These 2 functions added at v1.1.7 */
|
3813
4584
|
VP_EXPORT size_t
|
@@ -3819,8 +4590,8 @@ VpGetPrecLimit(void)
|
|
3819
4590
|
);
|
3820
4591
|
|
3821
4592
|
if (NIL_P(vlimit)) {
|
3822
|
-
|
3823
|
-
return
|
4593
|
+
bigdecimal_set_thread_local_precision_limit(BIGDECIMAL_PRECISION_LIMIT_DEFAULT);
|
4594
|
+
return BIGDECIMAL_PRECISION_LIMIT_DEFAULT;
|
3824
4595
|
}
|
3825
4596
|
|
3826
4597
|
return NUM2SIZET(vlimit);
|
@@ -3830,7 +4601,7 @@ VP_EXPORT size_t
|
|
3830
4601
|
VpSetPrecLimit(size_t n)
|
3831
4602
|
{
|
3832
4603
|
size_t const s = VpGetPrecLimit();
|
3833
|
-
|
4604
|
+
bigdecimal_set_thread_local_precision_limit(n);
|
3834
4605
|
return s;
|
3835
4606
|
}
|
3836
4607
|
|
@@ -3838,7 +4609,7 @@ VpSetPrecLimit(size_t n)
|
|
3838
4609
|
* Rounding mode.
|
3839
4610
|
*/
|
3840
4611
|
|
3841
|
-
#define
|
4612
|
+
#define bigdecimal_set_thread_local_rounding_mode(mode) \
|
3842
4613
|
rb_thread_local_aset( \
|
3843
4614
|
rb_thread_current(), \
|
3844
4615
|
id_BigDecimal_rounding_mode, \
|
@@ -3854,8 +4625,8 @@ VpGetRoundMode(void)
|
|
3854
4625
|
);
|
3855
4626
|
|
3856
4627
|
if (NIL_P(vmode)) {
|
3857
|
-
|
3858
|
-
return
|
4628
|
+
bigdecimal_set_thread_local_rounding_mode(BIGDECIMAL_ROUNDING_MODE_DEFAULT);
|
4629
|
+
return BIGDECIMAL_ROUNDING_MODE_DEFAULT;
|
3859
4630
|
}
|
3860
4631
|
|
3861
4632
|
return NUM2USHORT(vmode);
|
@@ -3883,7 +4654,7 @@ VP_EXPORT unsigned short
|
|
3883
4654
|
VpSetRoundMode(unsigned short n)
|
3884
4655
|
{
|
3885
4656
|
if (VpIsRoundMode(n)) {
|
3886
|
-
|
4657
|
+
bigdecimal_set_thread_local_rounding_mode(n);
|
3887
4658
|
return n;
|
3888
4659
|
}
|
3889
4660
|
|
@@ -3960,7 +4731,7 @@ VpException(unsigned short f, const char *str,int always)
|
|
3960
4731
|
{
|
3961
4732
|
unsigned short const exception_mode = VpGetException();
|
3962
4733
|
|
3963
|
-
if (f == VP_EXCEPTION_OP
|
4734
|
+
if (f == VP_EXCEPTION_OP) always = 1;
|
3964
4735
|
|
3965
4736
|
if (always || (exception_mode & f)) {
|
3966
4737
|
switch(f) {
|
@@ -3972,7 +4743,6 @@ VpException(unsigned short f, const char *str,int always)
|
|
3972
4743
|
case VP_EXCEPTION_OP:
|
3973
4744
|
rb_raise(rb_eFloatDomainError, "%s", str);
|
3974
4745
|
break;
|
3975
|
-
case VP_EXCEPTION_MEMORY:
|
3976
4746
|
default:
|
3977
4747
|
rb_fatal("%s", str);
|
3978
4748
|
}
|
@@ -4121,13 +4891,13 @@ VpNumOfChars(Real *vp,const char *pszFmt)
|
|
4121
4891
|
* that BASE is as large as possible satisfying the
|
4122
4892
|
* relation MaxVal <= BASE*(BASE+1). Where the value
|
4123
4893
|
* MaxVal is the largest value which can be represented
|
4124
|
-
* by one
|
4894
|
+
* by one DECDIG word in the computer used.
|
4125
4895
|
*
|
4126
4896
|
* [Returns]
|
4127
|
-
*
|
4897
|
+
* BIGDECIMAL_DOUBLE_FIGURES ... OK
|
4128
4898
|
*/
|
4129
4899
|
VP_EXPORT size_t
|
4130
|
-
VpInit(
|
4900
|
+
VpInit(DECDIG BaseVal)
|
4131
4901
|
{
|
4132
4902
|
/* Setup +/- Inf NaN -0 */
|
4133
4903
|
VpGetDoubleNegZero();
|
@@ -4142,16 +4912,16 @@ VpInit(BDIGIT BaseVal)
|
|
4142
4912
|
|
4143
4913
|
#ifdef BIGDECIMAL_DEBUG
|
4144
4914
|
if (gfDebug) {
|
4145
|
-
|
4146
|
-
|
4147
|
-
|
4148
|
-
|
4149
|
-
|
4150
|
-
|
4915
|
+
printf("VpInit: BaseVal = %"PRIuDECDIG"\n", BaseVal);
|
4916
|
+
printf("\tBASE = %"PRIuDECDIG"\n", BASE);
|
4917
|
+
printf("\tHALF_BASE = %"PRIuDECDIG"\n", HALF_BASE);
|
4918
|
+
printf("\tBASE1 = %"PRIuDECDIG"\n", BASE1);
|
4919
|
+
printf("\tBASE_FIG = %u\n", BASE_FIG);
|
4920
|
+
printf("\tBIGDECIMAL_DOUBLE_FIGURES = %d\n", BIGDECIMAL_DOUBLE_FIGURES);
|
4151
4921
|
}
|
4152
4922
|
#endif /* BIGDECIMAL_DEBUG */
|
4153
4923
|
|
4154
|
-
return
|
4924
|
+
return BIGDECIMAL_DOUBLE_FIGURES;
|
4155
4925
|
}
|
4156
4926
|
|
4157
4927
|
VP_EXPORT Real *
|
@@ -4199,7 +4969,7 @@ overflow:
|
|
4199
4969
|
}
|
4200
4970
|
|
4201
4971
|
Real *
|
4202
|
-
|
4972
|
+
bigdecimal_parse_special_string(const char *str)
|
4203
4973
|
{
|
4204
4974
|
static const struct {
|
4205
4975
|
const char *str;
|
@@ -4294,14 +5064,13 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
|
|
4294
5064
|
/* at least mx digits. */
|
4295
5065
|
/* szVal==NULL ==> allocate zero value. */
|
4296
5066
|
vp = VpAllocReal(mx);
|
4297
|
-
/* xmalloc() always returns(or throw interruption) */
|
4298
5067
|
vp->MaxPrec = mx; /* set max precision */
|
4299
5068
|
VpSetZero(vp, 1); /* initialize vp to zero. */
|
4300
5069
|
return vp;
|
4301
5070
|
}
|
4302
5071
|
|
4303
5072
|
/* Check on Inf & NaN */
|
4304
|
-
if ((vp =
|
5073
|
+
if ((vp = bigdecimal_parse_special_string(szVal)) != NULL) {
|
4305
5074
|
return vp;
|
4306
5075
|
}
|
4307
5076
|
|
@@ -4470,7 +5239,6 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
|
|
4470
5239
|
nalloc = Max(nalloc, mx);
|
4471
5240
|
mx = nalloc;
|
4472
5241
|
vp = VpAllocReal(mx);
|
4473
|
-
/* xmalloc() always returns(or throw interruption) */
|
4474
5242
|
vp->MaxPrec = mx; /* set max precision */
|
4475
5243
|
VpSetZero(vp, sign);
|
4476
5244
|
VpCtoV(vp, psz, ni, psz + ipf, nf, psz + ipe, ne);
|
@@ -4509,7 +5277,7 @@ VpAsgn(Real *c, Real *a, int isw)
|
|
4509
5277
|
VpSetSign(c, isw * VpGetSign(a)); /* set sign */
|
4510
5278
|
n = (a->Prec < c->MaxPrec) ? (a->Prec) : (c->MaxPrec);
|
4511
5279
|
c->Prec = n;
|
4512
|
-
|
5280
|
+
memcpy(c->frac, a->frac, n * sizeof(DECDIG));
|
4513
5281
|
/* Needs round ? */
|
4514
5282
|
if (isw != 10) {
|
4515
5283
|
/* Not in ActiveRound */
|
@@ -4540,7 +5308,7 @@ VpAddSub(Real *c, Real *a, Real *b, int operation)
|
|
4540
5308
|
short sw, isw;
|
4541
5309
|
Real *a_ptr, *b_ptr;
|
4542
5310
|
size_t n, na, nb, i;
|
4543
|
-
|
5311
|
+
DECDIG mrv;
|
4544
5312
|
|
4545
5313
|
#ifdef BIGDECIMAL_DEBUG
|
4546
5314
|
if (gfDebug) {
|
@@ -4668,7 +5436,7 @@ end_if:
|
|
4668
5436
|
* a and b assuming abs(a)>abs(b).
|
4669
5437
|
* c = abs(a) + abs(b) ; where |a|>=|b|
|
4670
5438
|
*/
|
4671
|
-
static
|
5439
|
+
static DECDIG
|
4672
5440
|
VpAddAbs(Real *a, Real *b, Real *c)
|
4673
5441
|
{
|
4674
5442
|
size_t word_shift;
|
@@ -4678,7 +5446,7 @@ VpAddAbs(Real *a, Real *b, Real *c)
|
|
4678
5446
|
size_t a_pos;
|
4679
5447
|
size_t b_pos, b_pos_with_word_shift;
|
4680
5448
|
size_t c_pos;
|
4681
|
-
|
5449
|
+
DECDIG av, bv, carry, mrv;
|
4682
5450
|
|
4683
5451
|
#ifdef BIGDECIMAL_DEBUG
|
4684
5452
|
if (gfDebug) {
|
@@ -4763,7 +5531,7 @@ Exit:
|
|
4763
5531
|
/*
|
4764
5532
|
* c = abs(a) - abs(b)
|
4765
5533
|
*/
|
4766
|
-
static
|
5534
|
+
static DECDIG
|
4767
5535
|
VpSubAbs(Real *a, Real *b, Real *c)
|
4768
5536
|
{
|
4769
5537
|
size_t word_shift;
|
@@ -4773,7 +5541,7 @@ VpSubAbs(Real *a, Real *b, Real *c)
|
|
4773
5541
|
size_t a_pos;
|
4774
5542
|
size_t b_pos, b_pos_with_word_shift;
|
4775
5543
|
size_t c_pos;
|
4776
|
-
|
5544
|
+
DECDIG av, bv, borrow, mrv;
|
4777
5545
|
|
4778
5546
|
#ifdef BIGDECIMAL_DEBUG
|
4779
5547
|
if (gfDebug) {
|
@@ -4880,7 +5648,7 @@ Exit:
|
|
4880
5648
|
* c_pos = |
|
4881
5649
|
*/
|
4882
5650
|
static size_t
|
4883
|
-
VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos,
|
5651
|
+
VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos, DECDIG *av, DECDIG *bv)
|
4884
5652
|
{
|
4885
5653
|
size_t left_word, right_word, word_shift;
|
4886
5654
|
|
@@ -4995,8 +5763,8 @@ VpMult(Real *c, Real *a, Real *b)
|
|
4995
5763
|
size_t MxIndA, MxIndB, MxIndAB, MxIndC;
|
4996
5764
|
size_t ind_c, i, ii, nc;
|
4997
5765
|
size_t ind_as, ind_ae, ind_bs;
|
4998
|
-
|
4999
|
-
|
5766
|
+
DECDIG carry;
|
5767
|
+
DECDIG_DBL s;
|
5000
5768
|
Real *w;
|
5001
5769
|
|
5002
5770
|
#ifdef BIGDECIMAL_DEBUG
|
@@ -5050,7 +5818,7 @@ VpMult(Real *c, Real *a, Real *b)
|
|
5050
5818
|
VpSetSign(c, VpGetSign(a) * VpGetSign(b)); /* set sign */
|
5051
5819
|
carry = 0;
|
5052
5820
|
nc = ind_c = MxIndAB;
|
5053
|
-
memset(c->frac, 0, (nc + 1) * sizeof(
|
5821
|
+
memset(c->frac, 0, (nc + 1) * sizeof(DECDIG)); /* Initialize c */
|
5054
5822
|
c->Prec = nc + 1; /* set precision */
|
5055
5823
|
for (nc = 0; nc < MxIndAB; ++nc, --ind_c) {
|
5056
5824
|
if (nc < MxIndB) { /* The left triangle of the Fig. */
|
@@ -5070,15 +5838,15 @@ VpMult(Real *c, Real *a, Real *b)
|
|
5070
5838
|
}
|
5071
5839
|
|
5072
5840
|
for (i = ind_as; i <= ind_ae; ++i) {
|
5073
|
-
|
5074
|
-
|
5075
|
-
|
5076
|
-
|
5077
|
-
|
5078
|
-
|
5079
|
-
|
5080
|
-
|
5081
|
-
|
5841
|
+
s = (DECDIG_DBL)a->frac[i] * b->frac[ind_bs--];
|
5842
|
+
carry = (DECDIG)(s / BASE);
|
5843
|
+
s -= (DECDIG_DBL)carry * BASE;
|
5844
|
+
c->frac[ind_c] += (DECDIG)s;
|
5845
|
+
if (c->frac[ind_c] >= BASE) {
|
5846
|
+
s = c->frac[ind_c] / BASE;
|
5847
|
+
carry += (DECDIG)s;
|
5848
|
+
c->frac[ind_c] -= (DECDIG)(s * BASE);
|
5849
|
+
}
|
5082
5850
|
if (carry) {
|
5083
5851
|
ii = ind_c;
|
5084
5852
|
while (ii-- > 0) {
|
@@ -5124,9 +5892,9 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
|
|
5124
5892
|
size_t word_a, word_b, word_c, word_r;
|
5125
5893
|
size_t i, n, ind_a, ind_b, ind_c, ind_r;
|
5126
5894
|
size_t nLoop;
|
5127
|
-
|
5128
|
-
|
5129
|
-
|
5895
|
+
DECDIG_DBL q, b1, b1p1, b1b2, b1b2p1, r1r2;
|
5896
|
+
DECDIG borrow, borrow1, borrow2;
|
5897
|
+
DECDIG_DBL qb;
|
5130
5898
|
|
5131
5899
|
#ifdef BIGDECIMAL_DEBUG
|
5132
5900
|
if (gfDebug) {
|
@@ -5198,7 +5966,7 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
|
|
5198
5966
|
++ind_c;
|
5199
5967
|
continue;
|
5200
5968
|
}
|
5201
|
-
|
5969
|
+
r1r2 = (DECDIG_DBL)r->frac[ind_c] * BASE + r->frac[ind_c + 1];
|
5202
5970
|
if (r1r2 == b1b2) {
|
5203
5971
|
/* The first two word digits is the same */
|
5204
5972
|
ind_b = 2;
|
@@ -5235,17 +6003,17 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
|
|
5235
6003
|
/* The first two word digits is not the same, */
|
5236
6004
|
/* then compare magnitude, and divide actually. */
|
5237
6005
|
if (r1r2 >= b1b2p1) {
|
5238
|
-
|
5239
|
-
|
5240
|
-
|
5241
|
-
|
6006
|
+
q = r1r2 / b1b2p1; /* q == (DECDIG)q */
|
6007
|
+
c->frac[ind_c] += (DECDIG)q;
|
6008
|
+
ind_r = b->Prec + ind_c - 1;
|
6009
|
+
goto sub_mult;
|
5242
6010
|
}
|
5243
6011
|
|
5244
6012
|
div_b1p1:
|
5245
|
-
|
5246
|
-
|
5247
|
-
|
5248
|
-
|
6013
|
+
if (ind_c + 1 >= word_c) goto out_side;
|
6014
|
+
q = r1r2 / b1p1; /* q == (DECDIG)q */
|
6015
|
+
c->frac[ind_c + 1] += (DECDIG)q;
|
6016
|
+
ind_r = b->Prec + ind_c;
|
5249
6017
|
|
5250
6018
|
sub_mult:
|
5251
6019
|
borrow1 = borrow2 = 0;
|
@@ -5257,16 +6025,16 @@ sub_mult:
|
|
5257
6025
|
qb = q * b->frac[ind_b];
|
5258
6026
|
if (qb < BASE) borrow1 = 0;
|
5259
6027
|
else {
|
5260
|
-
|
5261
|
-
|
6028
|
+
borrow1 = (DECDIG)(qb / BASE);
|
6029
|
+
qb -= (DECDIG_DBL)borrow1 * BASE; /* get qb < BASE */
|
5262
6030
|
}
|
5263
6031
|
if(r->frac[ind_r] < qb) {
|
5264
|
-
|
5265
|
-
|
6032
|
+
r->frac[ind_r] += (DECDIG)(BASE - qb);
|
6033
|
+
borrow2 = borrow2 + borrow1 + 1;
|
5266
6034
|
}
|
5267
6035
|
else {
|
5268
|
-
|
5269
|
-
|
6036
|
+
r->frac[ind_r] -= (DECDIG)qb;
|
6037
|
+
borrow2 += borrow1;
|
5270
6038
|
}
|
5271
6039
|
if (borrow2) {
|
5272
6040
|
if(r->frac[ind_r - 1] < borrow2) {
|
@@ -5348,9 +6116,9 @@ VpNmlz(Real *a)
|
|
5348
6116
|
i = 0;
|
5349
6117
|
while (a->frac[i] == 0) ++i; /* skip the first few zeros */
|
5350
6118
|
if (i) {
|
5351
|
-
|
5352
|
-
|
5353
|
-
|
6119
|
+
a->Prec -= i;
|
6120
|
+
if (!AddExponent(a, -(SIGNED_VALUE)i)) return 0;
|
6121
|
+
memmove(&a->frac[0], &a->frac[i], a->Prec*sizeof(DECDIG));
|
5354
6122
|
}
|
5355
6123
|
return 1;
|
5356
6124
|
}
|
@@ -5473,7 +6241,7 @@ static int
|
|
5473
6241
|
VPrint(FILE *fp, const char *cntl_chr, Real *a)
|
5474
6242
|
{
|
5475
6243
|
size_t i, j, nc, nd, ZeroSup, sep = 10;
|
5476
|
-
|
6244
|
+
DECDIG m, e, nn;
|
5477
6245
|
|
5478
6246
|
j = 0;
|
5479
6247
|
nd = nc = 0; /* nd : number of digits in fraction part(every 10 digits, */
|
@@ -5508,7 +6276,7 @@ VPrint(FILE *fp, const char *cntl_chr, Real *a)
|
|
5508
6276
|
case '0': case 'z':
|
5509
6277
|
ZeroSup = 0;
|
5510
6278
|
++j;
|
5511
|
-
sep = cntl_chr[j] == 'z' ?
|
6279
|
+
sep = cntl_chr[j] == 'z' ? BIGDECIMAL_COMPONENT_FIGURES : 10;
|
5512
6280
|
break;
|
5513
6281
|
}
|
5514
6282
|
for (i = 0; i < a->Prec; ++i) {
|
@@ -5617,7 +6385,7 @@ VP_EXPORT void
|
|
5617
6385
|
VpSzMantissa(Real *a,char *psz)
|
5618
6386
|
{
|
5619
6387
|
size_t i, n, ZeroSup;
|
5620
|
-
|
6388
|
+
DECDIG_DBL m, e, nn;
|
5621
6389
|
|
5622
6390
|
if (VpIsNaN(a)) {
|
5623
6391
|
sprintf(psz, SZ_NaN);
|
@@ -5700,7 +6468,7 @@ VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
|
|
5700
6468
|
/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
|
5701
6469
|
{
|
5702
6470
|
size_t i, n, ZeroSup;
|
5703
|
-
|
6471
|
+
DECDIG shift, m, e, nn;
|
5704
6472
|
char *pszSav = psz;
|
5705
6473
|
ssize_t ex;
|
5706
6474
|
|
@@ -5748,7 +6516,7 @@ VpToFString(Real *a, char *psz, size_t fFmt, int fPlus)
|
|
5748
6516
|
/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
|
5749
6517
|
{
|
5750
6518
|
size_t i, n;
|
5751
|
-
|
6519
|
+
DECDIG m, e, nn;
|
5752
6520
|
char *pszSav = psz;
|
5753
6521
|
ssize_t ex;
|
5754
6522
|
|
@@ -5823,7 +6591,7 @@ VpCtoV(Real *a, const char *int_chr, size_t ni, const char *frac, size_t nf, con
|
|
5823
6591
|
me = ne;
|
5824
6592
|
signe = 1;
|
5825
6593
|
exponent_overflow = 0;
|
5826
|
-
memset(a->frac, 0, ma * sizeof(
|
6594
|
+
memset(a->frac, 0, ma * sizeof(DECDIG));
|
5827
6595
|
if (ne > 0) {
|
5828
6596
|
i = 0;
|
5829
6597
|
if (exp_chr[0] == '-') {
|
@@ -5960,7 +6728,7 @@ Final:
|
|
5960
6728
|
* [Output]
|
5961
6729
|
* *d ... fraction part of m(d = 0.xxxxxxx). where # of 'x's is fig.
|
5962
6730
|
* *e ... exponent of m.
|
5963
|
-
*
|
6731
|
+
* BIGDECIMAL_DOUBLE_FIGURES ... Number of digits in a double variable.
|
5964
6732
|
*
|
5965
6733
|
* m -> d*10**e, 0<d<BASE
|
5966
6734
|
* [Returns]
|
@@ -6007,7 +6775,7 @@ VpVtoD(double *d, SIGNED_VALUE *e, Real *m)
|
|
6007
6775
|
goto Exit;
|
6008
6776
|
}
|
6009
6777
|
/* Normal number */
|
6010
|
-
fig = (
|
6778
|
+
fig = roomof(BIGDECIMAL_DOUBLE_FIGURES, BASE_FIG);
|
6011
6779
|
ind_m = 0;
|
6012
6780
|
mm = Min(fig, m->Prec);
|
6013
6781
|
*d = 0.0;
|
@@ -6024,7 +6792,7 @@ Exit:
|
|
6024
6792
|
if (gfDebug) {
|
6025
6793
|
VPrint(stdout, " VpVtoD: m=%\n", m);
|
6026
6794
|
printf(" d=%e * 10 **%ld\n", *d, *e);
|
6027
|
-
printf("
|
6795
|
+
printf(" BIGDECIMAL_DOUBLE_FIGURES = %d\n", BIGDECIMAL_DOUBLE_FIGURES);
|
6028
6796
|
}
|
6029
6797
|
#endif /*BIGDECIMAL_DEBUG */
|
6030
6798
|
return f;
|
@@ -6038,7 +6806,7 @@ VpDtoV(Real *m, double d)
|
|
6038
6806
|
{
|
6039
6807
|
size_t ind_m, mm;
|
6040
6808
|
SIGNED_VALUE ne;
|
6041
|
-
|
6809
|
+
DECDIG i;
|
6042
6810
|
double val, val2;
|
6043
6811
|
|
6044
6812
|
if (isnan(d)) {
|
@@ -6073,12 +6841,12 @@ VpDtoV(Real *m, double d)
|
|
6073
6841
|
/* Now val = 0.xxxxx*BASE**ne */
|
6074
6842
|
|
6075
6843
|
mm = m->MaxPrec;
|
6076
|
-
memset(m->frac, 0, mm * sizeof(
|
6844
|
+
memset(m->frac, 0, mm * sizeof(DECDIG));
|
6077
6845
|
for (ind_m = 0; val > 0.0 && ind_m < mm; ind_m++) {
|
6078
|
-
|
6079
|
-
|
6080
|
-
|
6081
|
-
|
6846
|
+
val *= (double)BASE;
|
6847
|
+
i = (DECDIG)val;
|
6848
|
+
val -= (double)i;
|
6849
|
+
m->frac[ind_m] = i;
|
6082
6850
|
}
|
6083
6851
|
if (ind_m >= mm) ind_m = mm - 1;
|
6084
6852
|
VpSetSign(m, (d > 0.0) ? 1 : -1);
|
@@ -6086,7 +6854,7 @@ VpDtoV(Real *m, double d)
|
|
6086
6854
|
m->exponent = ne;
|
6087
6855
|
|
6088
6856
|
VpInternalRound(m, 0, (m->Prec > 0) ? m->frac[m->Prec-1] : 0,
|
6089
|
-
|
6857
|
+
(DECDIG)(val*(double)BASE));
|
6090
6858
|
|
6091
6859
|
Exit:
|
6092
6860
|
#ifdef BIGDECIMAL_DEBUG
|
@@ -6225,7 +6993,7 @@ VpSqrt(Real *y, Real *x)
|
|
6225
6993
|
}
|
6226
6994
|
VpDtoV(y, sqrt(val)); /* y <- sqrt(val) */
|
6227
6995
|
y->exponent += n;
|
6228
|
-
n = (SIGNED_VALUE)(
|
6996
|
+
n = (SIGNED_VALUE)roomof(BIGDECIMAL_DOUBLE_FIGURES, BASE_FIG);
|
6229
6997
|
y->MaxPrec = Min((size_t)n , y_prec);
|
6230
6998
|
f->MaxPrec = y->MaxPrec + 1;
|
6231
6999
|
n = (SIGNED_VALUE)(y_prec * BASE_FIG);
|
@@ -6282,8 +7050,8 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
|
|
6282
7050
|
/* exptoadd: number of digits needed to compensate negative nf */
|
6283
7051
|
int fracf, fracf_1further;
|
6284
7052
|
ssize_t n,i,ix,ioffset, exptoadd;
|
6285
|
-
|
6286
|
-
|
7053
|
+
DECDIG v, shifter;
|
7054
|
+
DECDIG div;
|
6287
7055
|
|
6288
7056
|
nf += y->exponent * (ssize_t)BASE_FIG;
|
6289
7057
|
exptoadd=0;
|
@@ -6305,8 +7073,8 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
|
|
6305
7073
|
n = (ssize_t)BASE_FIG - ioffset - 1;
|
6306
7074
|
for (shifter = 1, i = 0; i < n; ++i) shifter *= 10;
|
6307
7075
|
|
6308
|
-
/* so the representation used (in y->frac) is an array of
|
6309
|
-
each
|
7076
|
+
/* so the representation used (in y->frac) is an array of DECDIG, where
|
7077
|
+
each DECDIG contains a value between 0 and BASE-1, consisting of BASE_FIG
|
6310
7078
|
decimal places.
|
6311
7079
|
|
6312
7080
|
(that numbers of decimal places are typed as ssize_t is somewhat confusing)
|
@@ -6314,10 +7082,10 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
|
|
6314
7082
|
nf is now position (in decimal places) of the digit from the start of
|
6315
7083
|
the array.
|
6316
7084
|
|
6317
|
-
ix is the position (in
|
7085
|
+
ix is the position (in DECDIGs) of the DECDIG containing the decimal digit,
|
6318
7086
|
from the start of the array.
|
6319
7087
|
|
6320
|
-
v is the value of this
|
7088
|
+
v is the value of this DECDIG
|
6321
7089
|
|
6322
7090
|
ioffset is the number of extra decimal places along of this decimal digit
|
6323
7091
|
within v.
|
@@ -6343,7 +7111,7 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
|
|
6343
7111
|
now fracf_1further is whether any of the remaining digits within v are non-zero
|
6344
7112
|
*/
|
6345
7113
|
|
6346
|
-
/* now check all the remaining
|
7114
|
+
/* now check all the remaining DECDIGs for zero-ness a whole DECDIG at a time.
|
6347
7115
|
if we spot any non-zeroness, that means that we found a positive digit under
|
6348
7116
|
rounding position, and we also found a positive digit under one further than
|
6349
7117
|
the rounding position, so both searches (to see if any such non-zero digit exists)
|
@@ -6362,7 +7130,7 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
|
|
6362
7130
|
now v = the first digit under the rounding position */
|
6363
7131
|
|
6364
7132
|
/* drop digits after pointed digit */
|
6365
|
-
memset(y->frac + ix + 1, 0, (y->Prec - (ix + 1)) * sizeof(
|
7133
|
+
memset(y->frac + ix + 1, 0, (y->Prec - (ix + 1)) * sizeof(DECDIG));
|
6366
7134
|
|
6367
7135
|
switch (f) {
|
6368
7136
|
case VP_ROUND_DOWN: /* Truncate */
|
@@ -6390,11 +7158,11 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
|
|
6390
7158
|
}
|
6391
7159
|
else {
|
6392
7160
|
if (ioffset == 0) {
|
6393
|
-
|
6394
|
-
|
6395
|
-
|
6396
|
-
|
6397
|
-
|
7161
|
+
/* v is the first decimal digit of its DECDIG;
|
7162
|
+
need to grab the previous DECDIG if present
|
7163
|
+
to check for evenness of the previous decimal
|
7164
|
+
digit (which is same as that of the DECDIG since
|
7165
|
+
base 10 has a factor of 2) */
|
6398
7166
|
if (ix && (y->frac[ix-1] % 2)) ++div;
|
6399
7167
|
}
|
6400
7168
|
else {
|
@@ -6442,7 +7210,7 @@ VpLeftRound(Real *y, unsigned short f, ssize_t nf)
|
|
6442
7210
|
* Round from the left hand side of the digits.
|
6443
7211
|
*/
|
6444
7212
|
{
|
6445
|
-
|
7213
|
+
DECDIG v;
|
6446
7214
|
if (!VpHasVal(y)) return 0; /* Unable to round */
|
6447
7215
|
v = y->frac[0];
|
6448
7216
|
nf -= VpExponent(y) * (ssize_t)BASE_FIG;
|
@@ -6473,7 +7241,7 @@ VpLimitRound(Real *c, size_t ixDigit)
|
|
6473
7241
|
/* If I understand correctly, this is only ever used to round off the final decimal
|
6474
7242
|
digit of precision */
|
6475
7243
|
static void
|
6476
|
-
VpInternalRound(Real *c, size_t ixDigit,
|
7244
|
+
VpInternalRound(Real *c, size_t ixDigit, DECDIG vPrev, DECDIG v)
|
6477
7245
|
{
|
6478
7246
|
int f = 0;
|
6479
7247
|
|
@@ -6523,7 +7291,7 @@ VpInternalRound(Real *c, size_t ixDigit, BDIGIT vPrev, BDIGIT v)
|
|
6523
7291
|
static int
|
6524
7292
|
VpRdup(Real *m, size_t ind_m)
|
6525
7293
|
{
|
6526
|
-
|
7294
|
+
DECDIG carry;
|
6527
7295
|
|
6528
7296
|
if (!ind_m) ind_m = m->Prec;
|
6529
7297
|
|
@@ -6595,7 +7363,7 @@ Exit:
|
|
6595
7363
|
* y = x ** n
|
6596
7364
|
*/
|
6597
7365
|
VP_EXPORT int
|
6598
|
-
|
7366
|
+
VpPowerByInt(Real *y, Real *x, SIGNED_VALUE n)
|
6599
7367
|
{
|
6600
7368
|
size_t s, ss;
|
6601
7369
|
ssize_t sign;
|
@@ -6682,8 +7450,8 @@ VpPower(Real *y, Real *x, SIGNED_VALUE n)
|
|
6682
7450
|
Exit:
|
6683
7451
|
#ifdef BIGDECIMAL_DEBUG
|
6684
7452
|
if (gfDebug) {
|
6685
|
-
VPrint(stdout, "
|
6686
|
-
VPrint(stdout, "
|
7453
|
+
VPrint(stdout, "VpPowerByInt y=%\n", y);
|
7454
|
+
VPrint(stdout, "VpPowerByInt x=%\n", x);
|
6687
7455
|
printf(" n=%"PRIdVALUE"\n", n);
|
6688
7456
|
}
|
6689
7457
|
#endif /* BIGDECIMAL_DEBUG */
|
@@ -6718,12 +7486,12 @@ VpVarCheck(Real * v)
|
|
6718
7486
|
}
|
6719
7487
|
for (i = 0; i < v->Prec; ++i) {
|
6720
7488
|
if (v->frac[i] >= BASE) {
|
6721
|
-
|
6722
|
-
|
6723
|
-
|
6724
|
-
|
6725
|
-
|
6726
|
-
|
7489
|
+
printf("ERROR(VpVarCheck): Illegal fraction\n");
|
7490
|
+
printf(" Frac[%"PRIuSIZE"]=%"PRIuDECDIG"\n", i, v->frac[i]);
|
7491
|
+
printf(" Prec. =%"PRIuSIZE"\n", v->Prec);
|
7492
|
+
printf(" Exp. =%"PRIdVALUE"\n", v->exponent);
|
7493
|
+
printf(" BASE =%"PRIuDECDIG"\n", BASE);
|
7494
|
+
return 3;
|
6727
7495
|
}
|
6728
7496
|
}
|
6729
7497
|
return 0;
|