bigdecimal 3.0.0 → 3.1.2
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 +1535 -779
- 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,7 +145,7 @@ 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
|
|
192
151
|
#ifndef HAVE_RB_EXT_RACTOR_SAFE
|
@@ -208,21 +167,6 @@ is_kind_of_BigDecimal(VALUE const v)
|
|
208
167
|
return rb_typeddata_is_kind_of(v, &BigDecimal_data_type);
|
209
168
|
}
|
210
169
|
|
211
|
-
static VALUE
|
212
|
-
ToValue(Real *p)
|
213
|
-
{
|
214
|
-
if (VpIsNaN(p)) {
|
215
|
-
VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'(Not a Number)", 0);
|
216
|
-
}
|
217
|
-
else if (VpIsPosInf(p)) {
|
218
|
-
VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 0);
|
219
|
-
}
|
220
|
-
else if (VpIsNegInf(p)) {
|
221
|
-
VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 0);
|
222
|
-
}
|
223
|
-
return p->obj;
|
224
|
-
}
|
225
|
-
|
226
170
|
NORETURN(static void cannot_be_coerced_into_BigDecimal(VALUE, VALUE));
|
227
171
|
|
228
172
|
static void
|
@@ -242,95 +186,67 @@ cannot_be_coerced_into_BigDecimal(VALUE exc_class, VALUE v)
|
|
242
186
|
}
|
243
187
|
|
244
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);
|
245
194
|
|
246
195
|
static Real*
|
247
196
|
GetVpValueWithPrec(VALUE v, long prec, int must)
|
248
197
|
{
|
249
|
-
|
250
|
-
Real *pv;
|
251
|
-
VALUE num, bg;
|
252
|
-
char szD[128];
|
253
|
-
VALUE orig = Qundef;
|
254
|
-
double d;
|
198
|
+
const size_t digs = prec < 0 ? SIZE_MAX : (size_t)prec;
|
255
199
|
|
256
|
-
again:
|
257
200
|
switch(TYPE(v)) {
|
258
201
|
case T_FLOAT:
|
259
|
-
|
260
|
-
|
261
|
-
d = RFLOAT_VALUE(v);
|
262
|
-
if (!isfinite(d)) {
|
263
|
-
pv = VpCreateRbObject(1, NULL);
|
264
|
-
VpDtoV(pv, d);
|
265
|
-
return pv;
|
266
|
-
}
|
267
|
-
if (d != 0.0) {
|
268
|
-
v = rb_funcall(v, id_to_r, 0);
|
269
|
-
goto again;
|
270
|
-
}
|
271
|
-
if (1/d < 0.0) {
|
272
|
-
return VpCreateRbObject(prec, "-0");
|
273
|
-
}
|
274
|
-
return VpCreateRbObject(prec, "0");
|
202
|
+
v = rb_float_convert_to_BigDecimal(v, digs, must);
|
203
|
+
break;
|
275
204
|
|
276
205
|
case T_RATIONAL:
|
277
|
-
|
278
|
-
|
279
|
-
if (orig == Qundef ? (orig = v, 1) : orig != v) {
|
280
|
-
num = rb_rational_num(v);
|
281
|
-
pv = GetVpValueWithPrec(num, -1, must);
|
282
|
-
if (pv == NULL) goto SomeOneMayDoIt;
|
283
|
-
|
284
|
-
v = BigDecimal_div2(ToValue(pv), rb_rational_den(v), LONG2NUM(prec));
|
285
|
-
goto again;
|
286
|
-
}
|
287
|
-
|
288
|
-
v = orig;
|
289
|
-
goto SomeOneMayDoIt;
|
206
|
+
v = rb_rational_convert_to_BigDecimal(v, digs, must);
|
207
|
+
break;
|
290
208
|
|
291
209
|
case T_DATA:
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
else {
|
297
|
-
goto SomeOneMayDoIt;
|
298
|
-
}
|
299
|
-
break;
|
210
|
+
if (!is_kind_of_BigDecimal(v)) {
|
211
|
+
goto SomeOneMayDoIt;
|
212
|
+
}
|
213
|
+
break;
|
300
214
|
|
301
|
-
case T_FIXNUM:
|
302
|
-
|
303
|
-
|
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
|
+
}
|
304
221
|
|
305
222
|
#ifdef ENABLE_NUMERIC_STRING
|
306
|
-
case T_STRING:
|
307
|
-
|
308
|
-
|
309
|
-
|
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
|
+
}
|
310
228
|
#endif /* ENABLE_NUMERIC_STRING */
|
311
229
|
|
312
|
-
case T_BIGNUM:
|
313
|
-
bg = rb_big2str(v, 10);
|
314
|
-
|
315
|
-
|
316
|
-
|
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
|
+
|
317
237
|
default:
|
318
238
|
goto SomeOneMayDoIt;
|
319
239
|
}
|
320
240
|
|
241
|
+
Real *vp;
|
242
|
+
TypedData_Get_Struct(v, Real, &BigDecimal_data_type, vp);
|
243
|
+
return vp;
|
244
|
+
|
321
245
|
SomeOneMayDoIt:
|
322
246
|
if (must) {
|
323
247
|
cannot_be_coerced_into_BigDecimal(rb_eTypeError, v);
|
324
248
|
}
|
325
249
|
return NULL; /* NULL means to coerce */
|
326
|
-
|
327
|
-
unable_to_coerce_without_prec:
|
328
|
-
if (must) {
|
329
|
-
rb_raise(rb_eArgError,
|
330
|
-
"%"PRIsVALUE" can't be coerced into BigDecimal without a precision",
|
331
|
-
RB_OBJ_CLASSNAME(v));
|
332
|
-
}
|
333
|
-
return NULL;
|
334
250
|
}
|
335
251
|
|
336
252
|
static Real*
|
@@ -340,11 +256,13 @@ GetVpValue(VALUE v, int must)
|
|
340
256
|
}
|
341
257
|
|
342
258
|
/* call-seq:
|
343
|
-
*
|
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
|
344
265
|
*
|
345
|
-
* The BigDecimal.double_fig class method returns the number of digits a
|
346
|
-
* Float number is allowed to have. The result depends upon the CPU and OS
|
347
|
-
* in use.
|
348
266
|
*/
|
349
267
|
static VALUE
|
350
268
|
BigDecimal_double_fig(VALUE self)
|
@@ -353,7 +271,7 @@ BigDecimal_double_fig(VALUE self)
|
|
353
271
|
}
|
354
272
|
|
355
273
|
/* call-seq:
|
356
|
-
*
|
274
|
+
* precs -> array
|
357
275
|
*
|
358
276
|
* Returns an Array of two Integer values that represent platform-dependent
|
359
277
|
* internal storage properties.
|
@@ -363,7 +281,6 @@ BigDecimal_double_fig(VALUE self)
|
|
363
281
|
* significant digits in scientific notation, and BigDecimal#precision for
|
364
282
|
* obtaining the number of digits in decimal notation.
|
365
283
|
*
|
366
|
-
* BigDecimal('5').precs #=> [9, 18]
|
367
284
|
*/
|
368
285
|
|
369
286
|
static VALUE
|
@@ -383,73 +300,202 @@ BigDecimal_prec(VALUE self)
|
|
383
300
|
return obj;
|
384
301
|
}
|
385
302
|
|
386
|
-
|
387
|
-
*
|
388
|
-
* big_decimal.precision -> intreger
|
389
|
-
*
|
390
|
-
* Returns the number of decimal digits in this number.
|
391
|
-
*
|
392
|
-
* Example:
|
393
|
-
*
|
394
|
-
* BigDecimal("0").precision # => 0
|
395
|
-
* BigDecimal("1").precision # => 1
|
396
|
-
* BigDecimal("-1e20").precision # => 21
|
397
|
-
* BigDecimal("1e-20").precision # => 20
|
398
|
-
* BigDecimal("Infinity").precision # => 0
|
399
|
-
* BigDecimal("-Infinity").precision # => 0
|
400
|
-
* BigDecimal("NaN").precision # => 0
|
401
|
-
*/
|
402
|
-
static VALUE
|
403
|
-
BigDecimal_precision(VALUE self)
|
303
|
+
static void
|
304
|
+
BigDecimal_count_precision_and_scale(VALUE self, ssize_t *out_precision, ssize_t *out_scale)
|
404
305
|
{
|
405
306
|
ENTER(1);
|
406
307
|
|
308
|
+
if (out_precision == NULL && out_scale == NULL)
|
309
|
+
return;
|
310
|
+
|
407
311
|
Real *p;
|
408
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;
|
409
331
|
|
410
332
|
/*
|
411
|
-
*
|
412
|
-
*
|
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
|
+
*
|
413
340
|
* When the exponent is negative, the decimal point moves to leftward.
|
414
|
-
*
|
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.
|
415
346
|
*
|
416
|
-
*
|
417
|
-
*
|
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.
|
357
|
+
*
|
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
|
418
366
|
*/
|
419
367
|
|
420
368
|
ssize_t ex = p->exponent;
|
421
|
-
|
369
|
+
|
370
|
+
/* Count the number of decimal digits before frac[1]. */
|
371
|
+
ssize_t n_digits_head = BASE_FIG;
|
422
372
|
if (ex < 0) {
|
423
|
-
|
424
|
-
|
373
|
+
n_digits_head += (-ex) * BASE_FIG; /* The number of leading zeros before frac[0]. */
|
374
|
+
ex = 0;
|
425
375
|
}
|
426
|
-
else if (
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
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 */
|
431
381
|
}
|
432
382
|
|
433
|
-
if (
|
434
|
-
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;
|
435
400
|
}
|
436
|
-
else if (p->Prec > 0) {
|
437
|
-
ssize_t n = (ssize_t)p->Prec - 1;
|
438
|
-
while (n > 0 && p->frac[n] == 0) --n;
|
439
401
|
|
440
|
-
|
402
|
+
if (out_scale) {
|
403
|
+
ssize_t scale = 0;
|
441
404
|
|
442
|
-
if (
|
443
|
-
|
444
|
-
for (; x > 0 && x % 10 == 0; x /= 10) {
|
445
|
-
--precision;
|
446
|
-
}
|
405
|
+
if (p->exponent < 0) {
|
406
|
+
scale = n_digits_head + (n - 1) * BASE_FIG - ntz;
|
447
407
|
}
|
408
|
+
else if (n > p->exponent) {
|
409
|
+
scale = (n - p->exponent) * BASE_FIG - ntz;
|
410
|
+
}
|
411
|
+
|
412
|
+
*out_scale = scale;
|
448
413
|
}
|
414
|
+
}
|
449
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);
|
450
438
|
return SSIZET2NUM(precision);
|
451
439
|
}
|
452
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
|
+
*/
|
453
499
|
static VALUE
|
454
500
|
BigDecimal_n_significant_digits(VALUE self)
|
455
501
|
{
|
@@ -457,32 +503,38 @@ BigDecimal_n_significant_digits(VALUE self)
|
|
457
503
|
|
458
504
|
Real *p;
|
459
505
|
GUARD_OBJ(p, GetVpValue(self, 1));
|
460
|
-
|
461
|
-
ssize_t n = p->Prec;
|
462
|
-
while (n > 0 && p->frac[n-1] == 0) --n;
|
463
|
-
if (n <= 0) {
|
506
|
+
if (VpIsZero(p) || !VpIsDef(p)) {
|
464
507
|
return INT2FIX(0);
|
465
508
|
}
|
466
509
|
|
467
|
-
|
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);
|
468
513
|
|
469
|
-
|
470
|
-
|
514
|
+
DECDIG x;
|
515
|
+
int nlz = BASE_FIG;
|
516
|
+
for (x = p->frac[0]; x > 0; x /= 10) --nlz;
|
471
517
|
|
472
|
-
|
473
|
-
for (
|
518
|
+
int ntz = 0;
|
519
|
+
for (x = p->frac[n-1]; x > 0 && x % 10 == 0; x /= 10) ++ntz;
|
474
520
|
|
475
|
-
ssize_t
|
476
|
-
return SSIZET2NUM(
|
521
|
+
ssize_t n_significant_digits = BASE_FIG*n - nlz - ntz;
|
522
|
+
return SSIZET2NUM(n_significant_digits);
|
477
523
|
}
|
478
524
|
|
479
525
|
/*
|
480
|
-
*
|
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:
|
481
533
|
*
|
482
|
-
*
|
534
|
+
* - Sign.
|
535
|
+
* - Fractional part.
|
536
|
+
* - Exponent.
|
483
537
|
*
|
484
|
-
* Two BigDecimals with equal sign,
|
485
|
-
* fractional part and exponent have the same hash.
|
486
538
|
*/
|
487
539
|
static VALUE
|
488
540
|
BigDecimal_hash(VALUE self)
|
@@ -495,23 +547,23 @@ BigDecimal_hash(VALUE self)
|
|
495
547
|
hash = (st_index_t)p->sign;
|
496
548
|
/* hash!=2: the case for 0(1),NaN(0) or +-Infinity(3) is sign itself */
|
497
549
|
if(hash == 2 || hash == (st_index_t)-2) {
|
498
|
-
|
499
|
-
|
550
|
+
hash ^= rb_memhash(p->frac, sizeof(DECDIG)*p->Prec);
|
551
|
+
hash += p->exponent;
|
500
552
|
}
|
501
553
|
return ST2FIX(hash);
|
502
554
|
}
|
503
555
|
|
504
556
|
/*
|
505
|
-
*
|
557
|
+
* call-seq:
|
558
|
+
* _dump -> string
|
506
559
|
*
|
507
|
-
*
|
560
|
+
* Returns a string representing the marshalling of +self+.
|
561
|
+
* See module Marshal.
|
508
562
|
*
|
509
|
-
*
|
510
|
-
*
|
511
|
-
*
|
512
|
-
* #=> Infinity
|
563
|
+
* inf = BigDecimal('Infinity') # => Infinity
|
564
|
+
* dumped = inf._dump # => "9:Infinity"
|
565
|
+
* BigDecimal._load(dumped) # => Infinity
|
513
566
|
*
|
514
|
-
* See the Marshal module.
|
515
567
|
*/
|
516
568
|
static VALUE
|
517
569
|
BigDecimal_dump(int argc, VALUE *argv, VALUE self)
|
@@ -553,12 +605,12 @@ BigDecimal_load(VALUE self, VALUE str)
|
|
553
605
|
m = m*10 + (unsigned long)(ch-'0');
|
554
606
|
}
|
555
607
|
if (m > VpBaseFig()) m -= VpBaseFig();
|
556
|
-
GUARD_OBJ(pv, VpNewRbClass(m, (char *)pch, self));
|
608
|
+
GUARD_OBJ(pv, VpNewRbClass(m, (char *)pch, self, true, true));
|
557
609
|
m /= VpBaseFig();
|
558
610
|
if (m && pv->MaxPrec > m) {
|
559
611
|
pv->MaxPrec = m+1;
|
560
612
|
}
|
561
|
-
return
|
613
|
+
return VpCheckGetValue(pv);
|
562
614
|
}
|
563
615
|
|
564
616
|
static unsigned short
|
@@ -645,42 +697,166 @@ check_rounding_mode(VALUE const v)
|
|
645
697
|
return sw;
|
646
698
|
}
|
647
699
|
|
648
|
-
/*
|
649
|
-
*
|
650
|
-
*
|
651
|
-
*
|
652
|
-
*
|
653
|
-
*
|
654
|
-
*
|
655
|
-
*
|
656
|
-
*
|
657
|
-
* BigDecimal::
|
658
|
-
* BigDecimal::
|
659
|
-
* BigDecimal::
|
660
|
-
* BigDecimal::
|
661
|
-
* BigDecimal::
|
662
|
-
*
|
663
|
-
*
|
664
|
-
*
|
665
|
-
*
|
666
|
-
*
|
667
|
-
*
|
668
|
-
*
|
669
|
-
*
|
670
|
-
*
|
671
|
-
*
|
672
|
-
*
|
673
|
-
*
|
674
|
-
*
|
675
|
-
*
|
676
|
-
*
|
677
|
-
*
|
678
|
-
*
|
679
|
-
*
|
680
|
-
*
|
681
|
-
*
|
682
|
-
*
|
683
|
-
*
|
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:+.
|
684
860
|
*
|
685
861
|
*/
|
686
862
|
static VALUE
|
@@ -768,25 +944,54 @@ GetPrecisionInt(VALUE v)
|
|
768
944
|
return n;
|
769
945
|
}
|
770
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
|
+
|
771
965
|
VP_EXPORT Real *
|
772
|
-
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)
|
773
967
|
{
|
774
968
|
VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
|
775
|
-
Real *pv = VpAlloc(mx, str,
|
776
|
-
|
777
|
-
|
778
|
-
|
969
|
+
Real *pv = VpAlloc(mx, str, strict_p, raise_exception);
|
970
|
+
if (!pv)
|
971
|
+
return NULL;
|
972
|
+
BigDecimal_wrap_struct(obj, pv);
|
779
973
|
return pv;
|
780
974
|
}
|
781
975
|
|
782
976
|
VP_EXPORT Real *
|
783
|
-
VpCreateRbObject(size_t mx, const char *str)
|
977
|
+
VpCreateRbObject(size_t mx, const char *str, bool raise_exception)
|
784
978
|
{
|
785
|
-
return VpNewRbClass(mx, str, rb_cBigDecimal);
|
979
|
+
return VpNewRbClass(mx, str, rb_cBigDecimal, true, raise_exception);
|
786
980
|
}
|
787
981
|
|
788
|
-
#define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(
|
789
|
-
|
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
|
+
}
|
790
995
|
|
791
996
|
static Real *
|
792
997
|
VpCopy(Real *pv, Real const* const x)
|
@@ -799,7 +1004,7 @@ VpCopy(Real *pv, Real const* const x)
|
|
799
1004
|
pv->exponent = x->exponent;
|
800
1005
|
pv->sign = x->sign;
|
801
1006
|
pv->flag = x->flag;
|
802
|
-
MEMCPY(pv->frac, x->frac,
|
1007
|
+
MEMCPY(pv->frac, x->frac, DECDIG, pv->MaxPrec);
|
803
1008
|
|
804
1009
|
return pv;
|
805
1010
|
}
|
@@ -838,15 +1043,7 @@ BigDecimal_IsFinite(VALUE self)
|
|
838
1043
|
static void
|
839
1044
|
BigDecimal_check_num(Real *p)
|
840
1045
|
{
|
841
|
-
|
842
|
-
VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'(Not a Number)", 1);
|
843
|
-
}
|
844
|
-
else if (VpIsPosInf(p)) {
|
845
|
-
VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 1);
|
846
|
-
}
|
847
|
-
else if (VpIsNegInf(p)) {
|
848
|
-
VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 1);
|
849
|
-
}
|
1046
|
+
VpCheckException(p, true);
|
850
1047
|
}
|
851
1048
|
|
852
1049
|
static VALUE BigDecimal_split(VALUE self);
|
@@ -869,7 +1066,7 @@ BigDecimal_to_i(VALUE self)
|
|
869
1066
|
if (e <= 0) return INT2FIX(0);
|
870
1067
|
nf = VpBaseFig();
|
871
1068
|
if (e <= nf) {
|
872
|
-
return LONG2NUM((long)(VpGetSign(p) * (
|
1069
|
+
return LONG2NUM((long)(VpGetSign(p) * (DECDIG_DBL_SIGNED)p->frac[0]));
|
873
1070
|
}
|
874
1071
|
else {
|
875
1072
|
VALUE a = BigDecimal_split(self);
|
@@ -1003,8 +1200,8 @@ BigDecimal_coerce(VALUE self, VALUE other)
|
|
1003
1200
|
Real *b;
|
1004
1201
|
|
1005
1202
|
if (RB_TYPE_P(other, T_FLOAT)) {
|
1006
|
-
GUARD_OBJ(b, GetVpValueWithPrec(other,
|
1007
|
-
|
1203
|
+
GUARD_OBJ(b, GetVpValueWithPrec(other, 0, 1));
|
1204
|
+
obj = rb_assoc_new(VpCheckGetValue(b), self);
|
1008
1205
|
}
|
1009
1206
|
else {
|
1010
1207
|
if (RB_TYPE_P(other, T_RATIONAL)) {
|
@@ -1021,12 +1218,14 @@ BigDecimal_coerce(VALUE self, VALUE other)
|
|
1021
1218
|
}
|
1022
1219
|
|
1023
1220
|
/*
|
1024
|
-
*
|
1025
|
-
* +big_decimal
|
1221
|
+
* call-seq:
|
1222
|
+
* +big_decimal -> self
|
1026
1223
|
*
|
1027
|
-
*
|
1224
|
+
* Returns +self+:
|
1225
|
+
*
|
1226
|
+
* +BigDecimal(5) # => 0.5e1
|
1227
|
+
* +BigDecimal(-5) # => -0.5e1
|
1028
1228
|
*
|
1029
|
-
* +BigDecimal('5') #=> 0.5e1
|
1030
1229
|
*/
|
1031
1230
|
|
1032
1231
|
static VALUE
|
@@ -1036,22 +1235,21 @@ BigDecimal_uplus(VALUE self)
|
|
1036
1235
|
}
|
1037
1236
|
|
1038
1237
|
/*
|
1039
|
-
*
|
1040
|
-
*
|
1238
|
+
* call-seq:
|
1239
|
+
* self + value -> bigdecimal
|
1041
1240
|
*
|
1042
|
-
*
|
1043
|
-
* add(value, digits)
|
1241
|
+
* Returns the \BigDecimal sum of +self+ and +value+:
|
1044
1242
|
*
|
1045
|
-
*
|
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)
|
1046
1248
|
*
|
1047
|
-
*
|
1048
|
-
* c = a.add(b,n)
|
1049
|
-
* c = a + b
|
1249
|
+
* See the {Note About Precision}[BigDecimal.html#class-BigDecimal-label-A+Note+About+Precision].
|
1050
1250
|
*
|
1051
|
-
* digits:: If specified and less than the number of significant digits of the
|
1052
|
-
* result, the result is rounded to that number of digits, according
|
1053
|
-
* to BigDecimal.mode.
|
1054
1251
|
*/
|
1252
|
+
|
1055
1253
|
static VALUE
|
1056
1254
|
BigDecimal_add(VALUE self, VALUE r)
|
1057
1255
|
{
|
@@ -1061,7 +1259,7 @@ BigDecimal_add(VALUE self, VALUE r)
|
|
1061
1259
|
|
1062
1260
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1063
1261
|
if (RB_TYPE_P(r, T_FLOAT)) {
|
1064
|
-
b = GetVpValueWithPrec(r,
|
1262
|
+
b = GetVpValueWithPrec(r, 0, 1);
|
1065
1263
|
}
|
1066
1264
|
else if (RB_TYPE_P(r, T_RATIONAL)) {
|
1067
1265
|
b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
|
@@ -1078,11 +1276,11 @@ BigDecimal_add(VALUE self, VALUE r)
|
|
1078
1276
|
|
1079
1277
|
mx = GetAddSubPrec(a, b);
|
1080
1278
|
if (mx == (size_t)-1L) {
|
1081
|
-
|
1279
|
+
GUARD_OBJ(c, VpCreateRbObject(VpBaseFig() + 1, "0", true));
|
1082
1280
|
VpAddSub(c, a, b, 1);
|
1083
1281
|
}
|
1084
1282
|
else {
|
1085
|
-
|
1283
|
+
GUARD_OBJ(c, VpCreateRbObject(mx * (VpBaseFig() + 1), "0", true));
|
1086
1284
|
if(!mx) {
|
1087
1285
|
VpSetInf(c, VpGetSign(a));
|
1088
1286
|
}
|
@@ -1090,24 +1288,21 @@ BigDecimal_add(VALUE self, VALUE r)
|
|
1090
1288
|
VpAddSub(c, a, b, 1);
|
1091
1289
|
}
|
1092
1290
|
}
|
1093
|
-
return
|
1291
|
+
return VpCheckGetValue(c);
|
1094
1292
|
}
|
1095
1293
|
|
1096
|
-
/*
|
1097
|
-
*
|
1098
|
-
*
|
1099
|
-
* Subtract the specified value.
|
1100
|
-
*
|
1101
|
-
* e.g.
|
1102
|
-
* c = a - b
|
1294
|
+
/* call-seq:
|
1295
|
+
* self - value -> bigdecimal
|
1103
1296
|
*
|
1104
|
-
*
|
1297
|
+
* Returns the \BigDecimal difference of +self+ and +value+:
|
1105
1298
|
*
|
1106
|
-
*
|
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)
|
1107
1304
|
*
|
1108
|
-
*
|
1109
|
-
* internal representation from platform. So, it's return value is platform
|
1110
|
-
* dependent.
|
1305
|
+
* See the {Note About Precision}[BigDecimal.html#class-BigDecimal-label-A+Note+About+Precision].
|
1111
1306
|
*
|
1112
1307
|
*/
|
1113
1308
|
static VALUE
|
@@ -1119,7 +1314,7 @@ BigDecimal_sub(VALUE self, VALUE r)
|
|
1119
1314
|
|
1120
1315
|
GUARD_OBJ(a, GetVpValue(self,1));
|
1121
1316
|
if (RB_TYPE_P(r, T_FLOAT)) {
|
1122
|
-
b = GetVpValueWithPrec(r,
|
1317
|
+
b = GetVpValueWithPrec(r, 0, 1);
|
1123
1318
|
}
|
1124
1319
|
else if (RB_TYPE_P(r, T_RATIONAL)) {
|
1125
1320
|
b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
|
@@ -1136,11 +1331,11 @@ BigDecimal_sub(VALUE self, VALUE r)
|
|
1136
1331
|
|
1137
1332
|
mx = GetAddSubPrec(a,b);
|
1138
1333
|
if (mx == (size_t)-1L) {
|
1139
|
-
|
1334
|
+
GUARD_OBJ(c, VpCreateRbObject(VpBaseFig() + 1, "0", true));
|
1140
1335
|
VpAddSub(c, a, b, -1);
|
1141
1336
|
}
|
1142
1337
|
else {
|
1143
|
-
|
1338
|
+
GUARD_OBJ(c,VpCreateRbObject(mx *(VpBaseFig() + 1), "0", true));
|
1144
1339
|
if (!mx) {
|
1145
1340
|
VpSetInf(c,VpGetSign(a));
|
1146
1341
|
}
|
@@ -1148,7 +1343,7 @@ BigDecimal_sub(VALUE self, VALUE r)
|
|
1148
1343
|
VpAddSub(c, a, b, -1);
|
1149
1344
|
}
|
1150
1345
|
}
|
1151
|
-
return
|
1346
|
+
return VpCheckGetValue(c);
|
1152
1347
|
}
|
1153
1348
|
|
1154
1349
|
static VALUE
|
@@ -1169,7 +1364,7 @@ BigDecimalCmp(VALUE self, VALUE r,char op)
|
|
1169
1364
|
break;
|
1170
1365
|
|
1171
1366
|
case T_FLOAT:
|
1172
|
-
GUARD_OBJ(b, GetVpValueWithPrec(r,
|
1367
|
+
GUARD_OBJ(b, GetVpValueWithPrec(r, 0, 0));
|
1173
1368
|
break;
|
1174
1369
|
|
1175
1370
|
case T_RATIONAL:
|
@@ -1286,12 +1481,19 @@ BigDecimal_eq(VALUE self, VALUE r)
|
|
1286
1481
|
return BigDecimalCmp(self, r, '=');
|
1287
1482
|
}
|
1288
1483
|
|
1289
|
-
/*
|
1290
|
-
*
|
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
|
1291
1494
|
*
|
1292
|
-
*
|
1495
|
+
* Raises an exception if the comparison cannot be made.
|
1293
1496
|
*
|
1294
|
-
* Values may be coerced to perform the comparison (see ==, BigDecimal#coerce).
|
1295
1497
|
*/
|
1296
1498
|
static VALUE
|
1297
1499
|
BigDecimal_lt(VALUE self, VALUE r)
|
@@ -1299,12 +1501,20 @@ BigDecimal_lt(VALUE self, VALUE r)
|
|
1299
1501
|
return BigDecimalCmp(self, r, '<');
|
1300
1502
|
}
|
1301
1503
|
|
1302
|
-
/*
|
1303
|
-
*
|
1504
|
+
/* call-seq:
|
1505
|
+
* self <= other -> true or false
|
1506
|
+
*
|
1507
|
+
* Returns +true+ if +self+ is less or equal to than +other+, +false+ otherwise:
|
1304
1508
|
*
|
1305
|
-
*
|
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.
|
1306
1517
|
*
|
1307
|
-
* Values may be coerced to perform the comparison (see ==, BigDecimal#coerce).
|
1308
1518
|
*/
|
1309
1519
|
static VALUE
|
1310
1520
|
BigDecimal_le(VALUE self, VALUE r)
|
@@ -1312,12 +1522,19 @@ BigDecimal_le(VALUE self, VALUE r)
|
|
1312
1522
|
return BigDecimalCmp(self, r, 'L');
|
1313
1523
|
}
|
1314
1524
|
|
1315
|
-
/*
|
1316
|
-
*
|
1525
|
+
/* call-seq:
|
1526
|
+
* self > other -> true or false
|
1527
|
+
*
|
1528
|
+
* Returns +true+ if +self+ is greater than +other+, +false+ otherwise:
|
1317
1529
|
*
|
1318
|
-
*
|
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.
|
1319
1537
|
*
|
1320
|
-
* Values may be coerced to perform the comparison (see ==, BigDecimal#coerce).
|
1321
1538
|
*/
|
1322
1539
|
static VALUE
|
1323
1540
|
BigDecimal_gt(VALUE self, VALUE r)
|
@@ -1325,12 +1542,20 @@ BigDecimal_gt(VALUE self, VALUE r)
|
|
1325
1542
|
return BigDecimalCmp(self, r, '>');
|
1326
1543
|
}
|
1327
1544
|
|
1328
|
-
/*
|
1329
|
-
*
|
1545
|
+
/* call-seq:
|
1546
|
+
* self >= other -> true or false
|
1547
|
+
*
|
1548
|
+
* Returns +true+ if +self+ is greater than or equal to +other+, +false+ otherwise:
|
1330
1549
|
*
|
1331
|
-
*
|
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.
|
1332
1558
|
*
|
1333
|
-
* Values may be coerced to perform the comparison (see ==, BigDecimal#coerce)
|
1334
1559
|
*/
|
1335
1560
|
static VALUE
|
1336
1561
|
BigDecimal_ge(VALUE self, VALUE r)
|
@@ -1340,11 +1565,14 @@ BigDecimal_ge(VALUE self, VALUE r)
|
|
1340
1565
|
|
1341
1566
|
/*
|
1342
1567
|
* call-seq:
|
1343
|
-
*
|
1568
|
+
* -self -> bigdecimal
|
1569
|
+
*
|
1570
|
+
* Returns the \BigDecimal negation of self:
|
1344
1571
|
*
|
1345
|
-
*
|
1572
|
+
* b0 = BigDecimal('1.5')
|
1573
|
+
* b1 = -b0 # => -0.15e1
|
1574
|
+
* b2 = -b1 # => 0.15e1
|
1346
1575
|
*
|
1347
|
-
* -BigDecimal('5') #=> -0.5e1
|
1348
1576
|
*/
|
1349
1577
|
|
1350
1578
|
static VALUE
|
@@ -1353,26 +1581,11 @@ BigDecimal_neg(VALUE self)
|
|
1353
1581
|
ENTER(5);
|
1354
1582
|
Real *c, *a;
|
1355
1583
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1356
|
-
GUARD_OBJ(c, VpCreateRbObject(a->Prec *(VpBaseFig() + 1), "0"));
|
1584
|
+
GUARD_OBJ(c, VpCreateRbObject(a->Prec *(VpBaseFig() + 1), "0", true));
|
1357
1585
|
VpAsgn(c, a, -1);
|
1358
|
-
return
|
1586
|
+
return VpCheckGetValue(c);
|
1359
1587
|
}
|
1360
1588
|
|
1361
|
-
/*
|
1362
|
-
* Document-method: BigDecimal#mult
|
1363
|
-
*
|
1364
|
-
* call-seq: mult(value, digits)
|
1365
|
-
*
|
1366
|
-
* Multiply by the specified value.
|
1367
|
-
*
|
1368
|
-
* e.g.
|
1369
|
-
* c = a.mult(b,n)
|
1370
|
-
* c = a * b
|
1371
|
-
*
|
1372
|
-
* digits:: If specified and less than the number of significant digits of the
|
1373
|
-
* result, the result is rounded to that number of digits, according
|
1374
|
-
* to BigDecimal.mode.
|
1375
|
-
*/
|
1376
1589
|
static VALUE
|
1377
1590
|
BigDecimal_mult(VALUE self, VALUE r)
|
1378
1591
|
{
|
@@ -1382,7 +1595,7 @@ BigDecimal_mult(VALUE self, VALUE r)
|
|
1382
1595
|
|
1383
1596
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1384
1597
|
if (RB_TYPE_P(r, T_FLOAT)) {
|
1385
|
-
b = GetVpValueWithPrec(r,
|
1598
|
+
b = GetVpValueWithPrec(r, 0, 1);
|
1386
1599
|
}
|
1387
1600
|
else if (RB_TYPE_P(r, T_RATIONAL)) {
|
1388
1601
|
b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
|
@@ -1395,52 +1608,72 @@ BigDecimal_mult(VALUE self, VALUE r)
|
|
1395
1608
|
SAVE(b);
|
1396
1609
|
|
1397
1610
|
mx = a->Prec + b->Prec;
|
1398
|
-
GUARD_OBJ(c, VpCreateRbObject(mx *(VpBaseFig() + 1), "0"));
|
1611
|
+
GUARD_OBJ(c, VpCreateRbObject(mx *(VpBaseFig() + 1), "0", true));
|
1399
1612
|
VpMult(c, a, b);
|
1400
|
-
return
|
1613
|
+
return VpCheckGetValue(c);
|
1401
1614
|
}
|
1402
1615
|
|
1403
1616
|
static VALUE
|
1404
|
-
BigDecimal_divide(Real **c, Real **res, Real **div
|
1617
|
+
BigDecimal_divide(VALUE self, VALUE r, Real **c, Real **res, Real **div)
|
1405
1618
|
/* For c = self.div(r): with round operation */
|
1406
1619
|
{
|
1407
1620
|
ENTER(5);
|
1408
1621
|
Real *a, *b;
|
1622
|
+
ssize_t a_prec, b_prec;
|
1409
1623
|
size_t mx;
|
1410
1624
|
|
1411
|
-
|
1412
|
-
|
1413
|
-
|
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);
|
1414
1637
|
}
|
1415
1638
|
else if (RB_TYPE_P(r, T_RATIONAL)) {
|
1416
|
-
|
1417
|
-
}
|
1418
|
-
else {
|
1419
|
-
b = GetVpValue(r, 0);
|
1639
|
+
rr = rb_rational_convert_to_BigDecimal(r, a->Prec*BASE_FIG, true);
|
1420
1640
|
}
|
1421
1641
|
|
1422
|
-
if (!
|
1423
|
-
|
1642
|
+
if (!is_kind_of_BigDecimal(rr)) {
|
1643
|
+
return DoSomeOne(self, r, '/');
|
1644
|
+
}
|
1424
1645
|
|
1646
|
+
TypedData_Get_Struct(rr, Real, &BigDecimal_data_type, b);
|
1647
|
+
SAVE(b);
|
1425
1648
|
*div = b;
|
1426
|
-
|
1427
|
-
|
1428
|
-
|
1429
|
-
|
1430
|
-
mx
|
1431
|
-
|
1432
|
-
|
1649
|
+
|
1650
|
+
BigDecimal_count_precision_and_scale(self, &a_prec, NULL);
|
1651
|
+
BigDecimal_count_precision_and_scale(rr, &b_prec, NULL);
|
1652
|
+
mx = (a_prec > b_prec) ? a_prec : b_prec;
|
1653
|
+
mx *= 2;
|
1654
|
+
|
1655
|
+
if (2*BIGDECIMAL_DOUBLE_FIGURES > mx)
|
1656
|
+
mx = 2*BIGDECIMAL_DOUBLE_FIGURES;
|
1657
|
+
|
1658
|
+
GUARD_OBJ((*c), VpCreateRbObject(mx + 2*BASE_FIG, "#0", true));
|
1659
|
+
GUARD_OBJ((*res), VpCreateRbObject((mx + 1)*2 + 2*BASE_FIG, "#0", true));
|
1433
1660
|
VpDivd(*c, *res, a, b);
|
1661
|
+
|
1434
1662
|
return Qnil;
|
1435
1663
|
}
|
1436
1664
|
|
1665
|
+
static VALUE BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod);
|
1666
|
+
|
1437
1667
|
/* call-seq:
|
1438
|
-
* a / b
|
1439
|
-
* quo(value) -> bigdecimal
|
1668
|
+
* a / b -> bigdecimal
|
1440
1669
|
*
|
1441
1670
|
* Divide by the specified value.
|
1442
1671
|
*
|
1672
|
+
* The result precision will be the precision of the larger operand,
|
1673
|
+
* but its minimum is 2*Float::DIG.
|
1674
|
+
*
|
1443
1675
|
* See BigDecimal#div.
|
1676
|
+
* See BigDecimal#quo.
|
1444
1677
|
*/
|
1445
1678
|
static VALUE
|
1446
1679
|
BigDecimal_div(VALUE self, VALUE r)
|
@@ -1448,7 +1681,7 @@ BigDecimal_div(VALUE self, VALUE r)
|
|
1448
1681
|
{
|
1449
1682
|
ENTER(5);
|
1450
1683
|
Real *c=NULL, *res=NULL, *div = NULL;
|
1451
|
-
r = BigDecimal_divide(&c, &res, &div
|
1684
|
+
r = BigDecimal_divide(self, r, &c, &res, &div);
|
1452
1685
|
if (!NIL_P(r)) return r; /* coerced by other */
|
1453
1686
|
SAVE(c); SAVE(res); SAVE(div);
|
1454
1687
|
/* a/b = c + r/b */
|
@@ -1457,9 +1690,48 @@ BigDecimal_div(VALUE self, VALUE r)
|
|
1457
1690
|
*/
|
1458
1691
|
/* Round */
|
1459
1692
|
if (VpHasVal(div)) { /* frac[0] must be zero for NaN,INF,Zero */
|
1460
|
-
|
1693
|
+
VpInternalRound(c, 0, c->frac[c->Prec-1], (DECDIG)(VpBaseVal() * (DECDIG_DBL)res->frac[0] / div->frac[0]));
|
1694
|
+
}
|
1695
|
+
return VpCheckGetValue(c);
|
1696
|
+
}
|
1697
|
+
|
1698
|
+
static VALUE BigDecimal_round(int argc, VALUE *argv, VALUE self);
|
1699
|
+
|
1700
|
+
/* call-seq:
|
1701
|
+
* quo(value) -> bigdecimal
|
1702
|
+
* quo(value, digits) -> bigdecimal
|
1703
|
+
*
|
1704
|
+
* Divide by the specified value.
|
1705
|
+
*
|
1706
|
+
* digits:: If specified and less than the number of significant digits of
|
1707
|
+
* the result, the result is rounded to the given number of digits,
|
1708
|
+
* according to the rounding mode indicated by BigDecimal.mode.
|
1709
|
+
*
|
1710
|
+
* If digits is 0 or omitted, the result is the same as for the
|
1711
|
+
* / operator.
|
1712
|
+
*
|
1713
|
+
* See BigDecimal#/.
|
1714
|
+
* See BigDecimal#div.
|
1715
|
+
*/
|
1716
|
+
static VALUE
|
1717
|
+
BigDecimal_quo(int argc, VALUE *argv, VALUE self)
|
1718
|
+
{
|
1719
|
+
VALUE value, digits, result;
|
1720
|
+
SIGNED_VALUE n = -1;
|
1721
|
+
|
1722
|
+
argc = rb_scan_args(argc, argv, "11", &value, &digits);
|
1723
|
+
if (argc > 1) {
|
1724
|
+
n = GetPrecisionInt(digits);
|
1725
|
+
}
|
1726
|
+
|
1727
|
+
if (n > 0) {
|
1728
|
+
result = BigDecimal_div2(self, value, digits);
|
1729
|
+
}
|
1730
|
+
else {
|
1731
|
+
result = BigDecimal_div(self, value);
|
1461
1732
|
}
|
1462
|
-
|
1733
|
+
|
1734
|
+
return result;
|
1463
1735
|
}
|
1464
1736
|
|
1465
1737
|
/*
|
@@ -1472,77 +1744,106 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
|
|
1472
1744
|
ENTER(8);
|
1473
1745
|
Real *c=NULL, *d=NULL, *res=NULL;
|
1474
1746
|
Real *a, *b;
|
1747
|
+
ssize_t a_prec, b_prec;
|
1475
1748
|
size_t mx;
|
1476
1749
|
|
1477
|
-
|
1478
|
-
|
1479
|
-
|
1750
|
+
TypedData_Get_Struct(self, Real, &BigDecimal_data_type, a);
|
1751
|
+
SAVE(a);
|
1752
|
+
|
1753
|
+
VALUE rr = r;
|
1754
|
+
if (is_kind_of_BigDecimal(rr)) {
|
1755
|
+
/* do nothing */
|
1756
|
+
}
|
1757
|
+
else if (RB_INTEGER_TYPE_P(r)) {
|
1758
|
+
rr = rb_inum_convert_to_BigDecimal(r, 0, true);
|
1759
|
+
}
|
1760
|
+
else if (RB_TYPE_P(r, T_FLOAT)) {
|
1761
|
+
rr = rb_float_convert_to_BigDecimal(r, 0, true);
|
1480
1762
|
}
|
1481
1763
|
else if (RB_TYPE_P(r, T_RATIONAL)) {
|
1482
|
-
|
1764
|
+
rr = rb_rational_convert_to_BigDecimal(r, a->Prec*BASE_FIG, true);
|
1483
1765
|
}
|
1484
|
-
|
1485
|
-
|
1766
|
+
|
1767
|
+
if (!is_kind_of_BigDecimal(rr)) {
|
1768
|
+
return Qfalse;
|
1486
1769
|
}
|
1487
1770
|
|
1488
|
-
|
1771
|
+
TypedData_Get_Struct(rr, Real, &BigDecimal_data_type, b);
|
1489
1772
|
SAVE(b);
|
1490
1773
|
|
1491
1774
|
if (VpIsNaN(a) || VpIsNaN(b)) goto NaN;
|
1492
1775
|
if (VpIsInf(a) && VpIsInf(b)) goto NaN;
|
1493
1776
|
if (VpIsZero(b)) {
|
1494
|
-
|
1777
|
+
rb_raise(rb_eZeroDivError, "divided by 0");
|
1495
1778
|
}
|
1496
1779
|
if (VpIsInf(a)) {
|
1497
|
-
|
1498
|
-
|
1499
|
-
|
1500
|
-
|
1501
|
-
|
1502
|
-
|
1780
|
+
if (VpGetSign(a) == VpGetSign(b)) {
|
1781
|
+
VALUE inf = BigDecimal_positive_infinity();
|
1782
|
+
TypedData_Get_Struct(inf, Real, &BigDecimal_data_type, *div);
|
1783
|
+
}
|
1784
|
+
else {
|
1785
|
+
VALUE inf = BigDecimal_negative_infinity();
|
1786
|
+
TypedData_Get_Struct(inf, Real, &BigDecimal_data_type, *div);
|
1787
|
+
}
|
1788
|
+
VALUE nan = BigDecimal_nan();
|
1789
|
+
TypedData_Get_Struct(nan, Real, &BigDecimal_data_type, *mod);
|
1790
|
+
return Qtrue;
|
1503
1791
|
}
|
1504
1792
|
if (VpIsInf(b)) {
|
1505
|
-
|
1506
|
-
|
1507
|
-
|
1508
|
-
|
1793
|
+
VALUE zero = BigDecimal_positive_zero();
|
1794
|
+
TypedData_Get_Struct(zero, Real, &BigDecimal_data_type, *div);
|
1795
|
+
*mod = a;
|
1796
|
+
return Qtrue;
|
1509
1797
|
}
|
1510
1798
|
if (VpIsZero(a)) {
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1514
|
-
|
1515
|
-
|
1516
|
-
|
1517
|
-
|
1518
|
-
|
1519
|
-
|
1520
|
-
mx = (
|
1521
|
-
|
1522
|
-
|
1799
|
+
VALUE zero = BigDecimal_positive_zero();
|
1800
|
+
TypedData_Get_Struct(zero, Real, &BigDecimal_data_type, *div);
|
1801
|
+
TypedData_Get_Struct(zero, Real, &BigDecimal_data_type, *mod);
|
1802
|
+
return Qtrue;
|
1803
|
+
}
|
1804
|
+
|
1805
|
+
BigDecimal_count_precision_and_scale(self, &a_prec, NULL);
|
1806
|
+
BigDecimal_count_precision_and_scale(rr, &b_prec, NULL);
|
1807
|
+
|
1808
|
+
mx = (a_prec > b_prec) ? a_prec : b_prec;
|
1809
|
+
mx *= 2;
|
1810
|
+
|
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));
|
1523
1816
|
VpDivd(c, res, a, b);
|
1524
|
-
|
1525
|
-
|
1817
|
+
|
1818
|
+
mx = c->Prec * BASE_FIG;
|
1819
|
+
GUARD_OBJ(d, VpCreateRbObject(mx, "0", true));
|
1526
1820
|
VpActiveRound(d, c, VP_ROUND_DOWN, 0);
|
1821
|
+
|
1527
1822
|
VpMult(res, d, b);
|
1528
1823
|
VpAddSub(c, a, res, -1);
|
1824
|
+
|
1529
1825
|
if (!VpIsZero(c) && (VpGetSign(a) * VpGetSign(b) < 0)) {
|
1530
|
-
|
1531
|
-
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
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;
|
1538
1838
|
}
|
1539
1839
|
return Qtrue;
|
1540
1840
|
|
1541
|
-
NaN:
|
1542
|
-
|
1543
|
-
|
1544
|
-
|
1545
|
-
|
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
|
+
}
|
1546
1847
|
return Qtrue;
|
1547
1848
|
}
|
1548
1849
|
|
@@ -1562,7 +1863,7 @@ BigDecimal_mod(VALUE self, VALUE r) /* %: a%b = a - (a.to_f/b).floor * b */
|
|
1562
1863
|
|
1563
1864
|
if (BigDecimal_DoDivmod(self, r, &div, &mod)) {
|
1564
1865
|
SAVE(div); SAVE(mod);
|
1565
|
-
|
1866
|
+
return VpCheckGetValue(mod);
|
1566
1867
|
}
|
1567
1868
|
return DoSomeOne(self, r, '%');
|
1568
1869
|
}
|
@@ -1577,7 +1878,7 @@ BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv)
|
|
1577
1878
|
|
1578
1879
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1579
1880
|
if (RB_TYPE_P(r, T_FLOAT)) {
|
1580
|
-
b = GetVpValueWithPrec(r,
|
1881
|
+
b = GetVpValueWithPrec(r, 0, 1);
|
1581
1882
|
}
|
1582
1883
|
else if (RB_TYPE_P(r, T_RATIONAL)) {
|
1583
1884
|
b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
|
@@ -1590,17 +1891,17 @@ BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv)
|
|
1590
1891
|
SAVE(b);
|
1591
1892
|
|
1592
1893
|
mx = (a->MaxPrec + b->MaxPrec) *VpBaseFig();
|
1593
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
1594
|
-
GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0"));
|
1595
|
-
GUARD_OBJ(rr, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0"));
|
1596
|
-
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));
|
1597
1898
|
|
1598
1899
|
VpDivd(c, res, a, b);
|
1599
1900
|
|
1600
1901
|
mx = c->Prec *(VpBaseFig() + 1);
|
1601
1902
|
|
1602
|
-
GUARD_OBJ(d, VpCreateRbObject(mx, "0"));
|
1603
|
-
GUARD_OBJ(f, VpCreateRbObject(mx, "0"));
|
1903
|
+
GUARD_OBJ(d, VpCreateRbObject(mx, "0", true));
|
1904
|
+
GUARD_OBJ(f, VpCreateRbObject(mx, "0", true));
|
1604
1905
|
|
1605
1906
|
VpActiveRound(d, c, VP_ROUND_DOWN, 0); /* 0: round off */
|
1606
1907
|
|
@@ -1627,7 +1928,7 @@ BigDecimal_remainder(VALUE self, VALUE r) /* remainder */
|
|
1627
1928
|
Real *d, *rv = 0;
|
1628
1929
|
f = BigDecimal_divremain(self, r, &d, &rv);
|
1629
1930
|
if (!NIL_P(f)) return f;
|
1630
|
-
return
|
1931
|
+
return VpCheckGetValue(rv);
|
1631
1932
|
}
|
1632
1933
|
|
1633
1934
|
/* call-seq:
|
@@ -1660,13 +1961,14 @@ BigDecimal_divmod(VALUE self, VALUE r)
|
|
1660
1961
|
|
1661
1962
|
if (BigDecimal_DoDivmod(self, r, &div, &mod)) {
|
1662
1963
|
SAVE(div); SAVE(mod);
|
1663
|
-
|
1964
|
+
return rb_assoc_new(VpCheckGetValue(div), VpCheckGetValue(mod));
|
1664
1965
|
}
|
1665
1966
|
return DoSomeOne(self,r,rb_intern("divmod"));
|
1666
1967
|
}
|
1667
1968
|
|
1668
1969
|
/*
|
1669
|
-
*
|
1970
|
+
* Do the same manner as Float#div when n is nil.
|
1971
|
+
* Do the same manner as BigDecimal#quo when n is 0.
|
1670
1972
|
*/
|
1671
1973
|
static inline VALUE
|
1672
1974
|
BigDecimal_div2(VALUE self, VALUE b, VALUE n)
|
@@ -1678,7 +1980,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
|
|
1678
1980
|
Real *div = NULL;
|
1679
1981
|
Real *mod;
|
1680
1982
|
if (BigDecimal_DoDivmod(self, b, &div, &mod)) {
|
1681
|
-
return BigDecimal_to_i(
|
1983
|
+
return BigDecimal_to_i(VpCheckGetValue(div));
|
1682
1984
|
}
|
1683
1985
|
return DoSomeOne(self, b, rb_intern("div"));
|
1684
1986
|
}
|
@@ -1692,18 +1994,25 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
|
|
1692
1994
|
Real *res = NULL;
|
1693
1995
|
Real *av = NULL, *bv = NULL, *cv = NULL;
|
1694
1996
|
size_t mx = ix + VpBaseFig()*2;
|
1997
|
+
size_t b_prec = ix;
|
1695
1998
|
size_t pl = VpSetPrecLimit(0);
|
1696
1999
|
|
1697
|
-
GUARD_OBJ(cv, VpCreateRbObject(mx + VpBaseFig(), "0"));
|
2000
|
+
GUARD_OBJ(cv, VpCreateRbObject(mx + VpBaseFig(), "0", true));
|
1698
2001
|
GUARD_OBJ(av, GetVpValue(self, 1));
|
1699
|
-
|
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));
|
1700
2009
|
mx = av->Prec + bv->Prec + 2;
|
1701
2010
|
if (mx <= cv->MaxPrec) mx = cv->MaxPrec + 1;
|
1702
|
-
GUARD_OBJ(res, VpCreateRbObject((mx * 2 + 2)*VpBaseFig(), "#0"));
|
2011
|
+
GUARD_OBJ(res, VpCreateRbObject((mx * 2 + 2)*VpBaseFig(), "#0", true));
|
1703
2012
|
VpDivd(cv, res, av, bv);
|
1704
2013
|
VpSetPrecLimit(pl);
|
1705
2014
|
VpLeftRound(cv, VpGetRoundMode(), ix);
|
1706
|
-
return
|
2015
|
+
return VpCheckGetValue(cv);
|
1707
2016
|
}
|
1708
2017
|
}
|
1709
2018
|
|
@@ -1711,6 +2020,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
|
|
1711
2020
|
* Document-method: BigDecimal#div
|
1712
2021
|
*
|
1713
2022
|
* call-seq:
|
2023
|
+
* div(value) -> integer
|
1714
2024
|
* div(value, digits) -> bigdecimal or integer
|
1715
2025
|
*
|
1716
2026
|
* Divide by the specified value.
|
@@ -1725,6 +2035,9 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
|
|
1725
2035
|
* If digits is not specified, the result is an integer,
|
1726
2036
|
* by analogy with Float#div; see also BigDecimal#divmod.
|
1727
2037
|
*
|
2038
|
+
* See BigDecimal#/.
|
2039
|
+
* See BigDecimal#quo.
|
2040
|
+
*
|
1728
2041
|
* Examples:
|
1729
2042
|
*
|
1730
2043
|
* a = BigDecimal("4")
|
@@ -1748,6 +2061,31 @@ BigDecimal_div3(int argc, VALUE *argv, VALUE self)
|
|
1748
2061
|
return BigDecimal_div2(self, b, n);
|
1749
2062
|
}
|
1750
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
|
+
|
1751
2089
|
static VALUE
|
1752
2090
|
BigDecimal_add2(VALUE self, VALUE b, VALUE n)
|
1753
2091
|
{
|
@@ -1761,7 +2099,7 @@ BigDecimal_add2(VALUE self, VALUE b, VALUE n)
|
|
1761
2099
|
VpSetPrecLimit(pl);
|
1762
2100
|
GUARD_OBJ(cv, GetVpValue(c, 1));
|
1763
2101
|
VpLeftRound(cv, VpGetRoundMode(), mx);
|
1764
|
-
|
2102
|
+
return VpCheckGetValue(cv);
|
1765
2103
|
}
|
1766
2104
|
}
|
1767
2105
|
|
@@ -1791,10 +2129,35 @@ BigDecimal_sub2(VALUE self, VALUE b, VALUE n)
|
|
1791
2129
|
VpSetPrecLimit(pl);
|
1792
2130
|
GUARD_OBJ(cv, GetVpValue(c, 1));
|
1793
2131
|
VpLeftRound(cv, VpGetRoundMode(), mx);
|
1794
|
-
|
2132
|
+
return VpCheckGetValue(cv);
|
1795
2133
|
}
|
1796
2134
|
}
|
1797
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
|
+
*/
|
1798
2161
|
|
1799
2162
|
static VALUE
|
1800
2163
|
BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
|
@@ -1809,18 +2172,19 @@ BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
|
|
1809
2172
|
VpSetPrecLimit(pl);
|
1810
2173
|
GUARD_OBJ(cv, GetVpValue(c, 1));
|
1811
2174
|
VpLeftRound(cv, VpGetRoundMode(), mx);
|
1812
|
-
|
2175
|
+
return VpCheckGetValue(cv);
|
1813
2176
|
}
|
1814
2177
|
}
|
1815
2178
|
|
1816
2179
|
/*
|
1817
2180
|
* call-seq:
|
1818
|
-
*
|
2181
|
+
* abs -> bigdecimal
|
2182
|
+
*
|
2183
|
+
* Returns the \BigDecimal absolute value of +self+:
|
1819
2184
|
*
|
1820
|
-
*
|
2185
|
+
* BigDecimal('5').abs # => 0.5e1
|
2186
|
+
* BigDecimal('-3').abs # => 0.3e1
|
1821
2187
|
*
|
1822
|
-
* BigDecimal('5').abs #=> 0.5e1
|
1823
|
-
* BigDecimal('-3').abs #=> 0.3e1
|
1824
2188
|
*/
|
1825
2189
|
|
1826
2190
|
static VALUE
|
@@ -1832,10 +2196,10 @@ BigDecimal_abs(VALUE self)
|
|
1832
2196
|
|
1833
2197
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1834
2198
|
mx = a->Prec *(VpBaseFig() + 1);
|
1835
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
2199
|
+
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
1836
2200
|
VpAsgn(c, a, 1);
|
1837
2201
|
VpChangeSign(c, 1);
|
1838
|
-
return
|
2202
|
+
return VpCheckGetValue(c);
|
1839
2203
|
}
|
1840
2204
|
|
1841
2205
|
/* call-seq:
|
@@ -1857,9 +2221,9 @@ BigDecimal_sqrt(VALUE self, VALUE nFig)
|
|
1857
2221
|
|
1858
2222
|
n = GetPrecisionInt(nFig) + VpDblFig() + BASE_FIG;
|
1859
2223
|
if (mx <= n) mx = n;
|
1860
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
2224
|
+
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
1861
2225
|
VpSqrt(c, a);
|
1862
|
-
return
|
2226
|
+
return VpCheckGetValue(c);
|
1863
2227
|
}
|
1864
2228
|
|
1865
2229
|
/* Return the integer part of the number, as a BigDecimal.
|
@@ -1873,9 +2237,9 @@ BigDecimal_fix(VALUE self)
|
|
1873
2237
|
|
1874
2238
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1875
2239
|
mx = a->Prec *(VpBaseFig() + 1);
|
1876
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
2240
|
+
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
1877
2241
|
VpActiveRound(c, a, VP_ROUND_DOWN, 0); /* 0: round off */
|
1878
|
-
return
|
2242
|
+
return VpCheckGetValue(c);
|
1879
2243
|
}
|
1880
2244
|
|
1881
2245
|
/* call-seq:
|
@@ -1946,13 +2310,13 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
|
|
1946
2310
|
pl = VpSetPrecLimit(0);
|
1947
2311
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1948
2312
|
mx = a->Prec * (VpBaseFig() + 1);
|
1949
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
2313
|
+
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
1950
2314
|
VpSetPrecLimit(pl);
|
1951
2315
|
VpActiveRound(c, a, sw, iLoc);
|
1952
2316
|
if (round_to_int) {
|
1953
|
-
|
2317
|
+
return BigDecimal_to_i(VpCheckGetValue(c));
|
1954
2318
|
}
|
1955
|
-
return
|
2319
|
+
return VpCheckGetValue(c);
|
1956
2320
|
}
|
1957
2321
|
|
1958
2322
|
/* call-seq:
|
@@ -1992,13 +2356,13 @@ BigDecimal_truncate(int argc, VALUE *argv, VALUE self)
|
|
1992
2356
|
|
1993
2357
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1994
2358
|
mx = a->Prec * (VpBaseFig() + 1);
|
1995
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
2359
|
+
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
1996
2360
|
VpSetPrecLimit(pl);
|
1997
2361
|
VpActiveRound(c, a, VP_ROUND_DOWN, iLoc); /* 0: truncate */
|
1998
2362
|
if (argc == 0) {
|
1999
|
-
|
2363
|
+
return BigDecimal_to_i(VpCheckGetValue(c));
|
2000
2364
|
}
|
2001
|
-
return
|
2365
|
+
return VpCheckGetValue(c);
|
2002
2366
|
}
|
2003
2367
|
|
2004
2368
|
/* Return the fractional part of the number, as a BigDecimal.
|
@@ -2012,9 +2376,9 @@ BigDecimal_frac(VALUE self)
|
|
2012
2376
|
|
2013
2377
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
2014
2378
|
mx = a->Prec * (VpBaseFig() + 1);
|
2015
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
2379
|
+
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
2016
2380
|
VpFrac(c, a);
|
2017
|
-
return
|
2381
|
+
return VpCheckGetValue(c);
|
2018
2382
|
}
|
2019
2383
|
|
2020
2384
|
/* call-seq:
|
@@ -2052,16 +2416,16 @@ BigDecimal_floor(int argc, VALUE *argv, VALUE self)
|
|
2052
2416
|
|
2053
2417
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
2054
2418
|
mx = a->Prec * (VpBaseFig() + 1);
|
2055
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
2419
|
+
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
2056
2420
|
VpSetPrecLimit(pl);
|
2057
2421
|
VpActiveRound(c, a, VP_ROUND_FLOOR, iLoc);
|
2058
2422
|
#ifdef BIGDECIMAL_DEBUG
|
2059
2423
|
VPrint(stderr, "floor: c=%\n", c);
|
2060
2424
|
#endif
|
2061
2425
|
if (argc == 0) {
|
2062
|
-
|
2426
|
+
return BigDecimal_to_i(VpCheckGetValue(c));
|
2063
2427
|
}
|
2064
|
-
return
|
2428
|
+
return VpCheckGetValue(c);
|
2065
2429
|
}
|
2066
2430
|
|
2067
2431
|
/* call-seq:
|
@@ -2098,13 +2462,13 @@ BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
|
|
2098
2462
|
|
2099
2463
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
2100
2464
|
mx = a->Prec * (VpBaseFig() + 1);
|
2101
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
2465
|
+
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
2102
2466
|
VpSetPrecLimit(pl);
|
2103
2467
|
VpActiveRound(c, a, VP_ROUND_CEIL, iLoc);
|
2104
2468
|
if (argc == 0) {
|
2105
|
-
|
2469
|
+
return BigDecimal_to_i(VpCheckGetValue(c));
|
2106
2470
|
}
|
2107
|
-
return
|
2471
|
+
return VpCheckGetValue(c);
|
2108
2472
|
}
|
2109
2473
|
|
2110
2474
|
/* call-seq:
|
@@ -2400,13 +2764,13 @@ is_even(VALUE x)
|
|
2400
2764
|
}
|
2401
2765
|
|
2402
2766
|
static VALUE
|
2403
|
-
|
2767
|
+
bigdecimal_power_by_bigdecimal(Real const* x, Real const* exp, ssize_t const n)
|
2404
2768
|
{
|
2405
2769
|
VALUE log_x, multiplied, y;
|
2406
2770
|
volatile VALUE obj = exp->obj;
|
2407
2771
|
|
2408
2772
|
if (VpIsZero(exp)) {
|
2409
|
-
|
2773
|
+
return VpCheckGetValue(VpCreateRbObject(n, "1", true));
|
2410
2774
|
}
|
2411
2775
|
|
2412
2776
|
log_x = BigMath_log(x->obj, SSIZET2NUM(n+1));
|
@@ -2444,10 +2808,10 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2444
2808
|
n = NIL_P(prec) ? (ssize_t)(x->Prec*VpBaseFig()) : NUM2SSIZET(prec);
|
2445
2809
|
|
2446
2810
|
if (VpIsNaN(x)) {
|
2447
|
-
|
2811
|
+
y = VpCreateRbObject(n, "0", true);
|
2448
2812
|
RB_GC_GUARD(y->obj);
|
2449
2813
|
VpSetNaN(y);
|
2450
|
-
|
2814
|
+
return VpCheckGetValue(y);
|
2451
2815
|
}
|
2452
2816
|
|
2453
2817
|
retry:
|
@@ -2470,9 +2834,9 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2470
2834
|
goto retry;
|
2471
2835
|
}
|
2472
2836
|
if (NIL_P(prec)) {
|
2473
|
-
n +=
|
2837
|
+
n += BIGDECIMAL_DOUBLE_FIGURES;
|
2474
2838
|
}
|
2475
|
-
exp = GetVpValueWithPrec(vexp,
|
2839
|
+
exp = GetVpValueWithPrec(vexp, 0, 1);
|
2476
2840
|
break;
|
2477
2841
|
|
2478
2842
|
case T_RATIONAL:
|
@@ -2516,7 +2880,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2516
2880
|
|
2517
2881
|
if (VpIsZero(x)) {
|
2518
2882
|
if (is_negative(vexp)) {
|
2519
|
-
|
2883
|
+
y = VpCreateRbObject(n, "#0", true);
|
2520
2884
|
RB_GC_GUARD(y->obj);
|
2521
2885
|
if (BIGDECIMAL_NEGATIVE_P(x)) {
|
2522
2886
|
if (is_integer(vexp)) {
|
@@ -2538,18 +2902,18 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2538
2902
|
/* (+0) ** (-num) -> Infinity */
|
2539
2903
|
VpSetPosInf(y);
|
2540
2904
|
}
|
2541
|
-
|
2905
|
+
return VpCheckGetValue(y);
|
2542
2906
|
}
|
2543
2907
|
else if (is_zero(vexp)) {
|
2544
|
-
|
2908
|
+
return VpCheckGetValue(VpCreateRbObject(n, "1", true));
|
2545
2909
|
}
|
2546
2910
|
else {
|
2547
|
-
|
2911
|
+
return VpCheckGetValue(VpCreateRbObject(n, "0", true));
|
2548
2912
|
}
|
2549
2913
|
}
|
2550
2914
|
|
2551
2915
|
if (is_zero(vexp)) {
|
2552
|
-
|
2916
|
+
return VpCheckGetValue(VpCreateRbObject(n, "1", true));
|
2553
2917
|
}
|
2554
2918
|
else if (is_one(vexp)) {
|
2555
2919
|
return self;
|
@@ -2561,24 +2925,24 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2561
2925
|
if (is_integer(vexp)) {
|
2562
2926
|
if (is_even(vexp)) {
|
2563
2927
|
/* (-Infinity) ** (-even_integer) -> +0 */
|
2564
|
-
|
2928
|
+
return VpCheckGetValue(VpCreateRbObject(n, "0", true));
|
2565
2929
|
}
|
2566
2930
|
else {
|
2567
2931
|
/* (-Infinity) ** (-odd_integer) -> -0 */
|
2568
|
-
|
2932
|
+
return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
|
2569
2933
|
}
|
2570
2934
|
}
|
2571
2935
|
else {
|
2572
2936
|
/* (-Infinity) ** (-non_integer) -> -0 */
|
2573
|
-
|
2937
|
+
return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
|
2574
2938
|
}
|
2575
2939
|
}
|
2576
2940
|
else {
|
2577
|
-
|
2941
|
+
return VpCheckGetValue(VpCreateRbObject(n, "0", true));
|
2578
2942
|
}
|
2579
2943
|
}
|
2580
2944
|
else {
|
2581
|
-
|
2945
|
+
y = VpCreateRbObject(n, "0", true);
|
2582
2946
|
if (BIGDECIMAL_NEGATIVE_P(x)) {
|
2583
2947
|
if (is_integer(vexp)) {
|
2584
2948
|
if (is_even(vexp)) {
|
@@ -2597,52 +2961,52 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2597
2961
|
else {
|
2598
2962
|
VpSetPosInf(y);
|
2599
2963
|
}
|
2600
|
-
|
2964
|
+
return VpCheckGetValue(y);
|
2601
2965
|
}
|
2602
2966
|
}
|
2603
2967
|
|
2604
2968
|
if (exp != NULL) {
|
2605
|
-
return
|
2969
|
+
return bigdecimal_power_by_bigdecimal(x, exp, n);
|
2606
2970
|
}
|
2607
2971
|
else if (RB_TYPE_P(vexp, T_BIGNUM)) {
|
2608
2972
|
VALUE abs_value = BigDecimal_abs(self);
|
2609
2973
|
if (is_one(abs_value)) {
|
2610
|
-
|
2974
|
+
return VpCheckGetValue(VpCreateRbObject(n, "1", true));
|
2611
2975
|
}
|
2612
2976
|
else if (RTEST(rb_funcall(abs_value, '<', 1, INT2FIX(1)))) {
|
2613
2977
|
if (is_negative(vexp)) {
|
2614
|
-
|
2978
|
+
y = VpCreateRbObject(n, "0", true);
|
2615
2979
|
if (is_even(vexp)) {
|
2616
2980
|
VpSetInf(y, VpGetSign(x));
|
2617
2981
|
}
|
2618
2982
|
else {
|
2619
2983
|
VpSetInf(y, -VpGetSign(x));
|
2620
2984
|
}
|
2621
|
-
|
2985
|
+
return VpCheckGetValue(y);
|
2622
2986
|
}
|
2623
2987
|
else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
|
2624
|
-
|
2988
|
+
return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
|
2625
2989
|
}
|
2626
2990
|
else {
|
2627
|
-
|
2991
|
+
return VpCheckGetValue(VpCreateRbObject(n, "0", true));
|
2628
2992
|
}
|
2629
2993
|
}
|
2630
2994
|
else {
|
2631
2995
|
if (is_positive(vexp)) {
|
2632
|
-
|
2996
|
+
y = VpCreateRbObject(n, "0", true);
|
2633
2997
|
if (is_even(vexp)) {
|
2634
2998
|
VpSetInf(y, VpGetSign(x));
|
2635
2999
|
}
|
2636
3000
|
else {
|
2637
3001
|
VpSetInf(y, -VpGetSign(x));
|
2638
3002
|
}
|
2639
|
-
|
3003
|
+
return VpCheckGetValue(y);
|
2640
3004
|
}
|
2641
3005
|
else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
|
2642
|
-
|
3006
|
+
return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
|
2643
3007
|
}
|
2644
3008
|
else {
|
2645
|
-
|
3009
|
+
return VpCheckGetValue(VpCreateRbObject(n, "0", true));
|
2646
3010
|
}
|
2647
3011
|
}
|
2648
3012
|
}
|
@@ -2654,24 +3018,30 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2654
3018
|
|
2655
3019
|
if (VpIsDef(x)) {
|
2656
3020
|
mp = x->Prec * (VpBaseFig() + 1);
|
2657
|
-
|
3021
|
+
GUARD_OBJ(y, VpCreateRbObject(mp * (ma + 1), "0", true));
|
2658
3022
|
}
|
2659
3023
|
else {
|
2660
|
-
|
3024
|
+
GUARD_OBJ(y, VpCreateRbObject(1, "0", true));
|
2661
3025
|
}
|
2662
|
-
|
3026
|
+
VpPowerByInt(y, x, int_exp);
|
2663
3027
|
if (!NIL_P(prec) && VpIsDef(y)) {
|
2664
3028
|
VpMidRound(y, VpGetRoundMode(), n);
|
2665
3029
|
}
|
2666
|
-
return
|
3030
|
+
return VpCheckGetValue(y);
|
2667
3031
|
}
|
2668
3032
|
|
2669
|
-
/*
|
2670
|
-
*
|
3033
|
+
/* call-seq:
|
3034
|
+
* self ** other -> bigdecimal
|
2671
3035
|
*
|
2672
|
-
*
|
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.
|
2673
3044
|
*
|
2674
|
-
* See BigDecimal#power.
|
2675
3045
|
*/
|
2676
3046
|
static VALUE
|
2677
3047
|
BigDecimal_power_op(VALUE self, VALUE exp)
|
@@ -2725,182 +3095,483 @@ opts_exception_p(VALUE opts)
|
|
2725
3095
|
}
|
2726
3096
|
#endif
|
2727
3097
|
|
2728
|
-
static
|
2729
|
-
|
3098
|
+
static VALUE
|
3099
|
+
check_exception(VALUE bd)
|
2730
3100
|
{
|
2731
|
-
|
2732
|
-
|
2733
|
-
|
2734
|
-
|
2735
|
-
|
2736
|
-
|
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
|
+
}
|
2737
3109
|
|
2738
|
-
|
2739
|
-
|
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);
|
2740
3114
|
|
2741
|
-
|
2742
|
-
|
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;
|
2743
3131
|
}
|
2744
3132
|
else {
|
2745
|
-
|
2746
|
-
|
2747
|
-
|
2748
|
-
|
2749
|
-
|
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;
|
2750
3141
|
}
|
2751
|
-
rb_raise(rb_eArgError, "negative precision");
|
2752
3142
|
}
|
2753
|
-
|
2754
|
-
|
2755
|
-
|
2756
|
-
|
2757
|
-
|
2758
|
-
case Qnil:
|
2759
|
-
if (!exc) return NULL;
|
2760
|
-
rb_raise(rb_eTypeError, "can't convert nil into BigDecimal");
|
2761
|
-
case Qtrue:
|
2762
|
-
if (!exc) return NULL;
|
2763
|
-
rb_raise(rb_eTypeError, "can't convert true into BigDecimal");
|
2764
|
-
case Qfalse:
|
2765
|
-
if (!exc) return NULL;
|
2766
|
-
rb_raise(rb_eTypeError, "can't convert false into BigDecimal");
|
2767
|
-
default:
|
2768
|
-
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;
|
2769
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);
|
2770
3157
|
}
|
2771
3158
|
|
2772
|
-
|
2773
|
-
|
2774
|
-
case T_DATA:
|
2775
|
-
if (is_kind_of_BigDecimal(iniValue)) {
|
2776
|
-
return DATA_PTR(iniValue);
|
2777
|
-
}
|
2778
|
-
break;
|
3159
|
+
return BigDecimal_wrap_struct(obj, vp);
|
3160
|
+
}
|
2779
3161
|
|
2780
|
-
|
2781
|
-
|
2782
|
-
|
2783
|
-
|
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
|
+
}
|
2784
3174
|
|
2785
|
-
|
2786
|
-
|
2787
|
-
|
2788
|
-
|
2789
|
-
|
2790
|
-
|
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);
|
2791
3189
|
}
|
2792
|
-
|
2793
|
-
|
2794
|
-
|
2795
|
-
|
2796
|
-
|
2797
|
-
|
2798
|
-
|
2799
|
-
|
2800
|
-
|
2801
|
-
|
2802
|
-
|
2803
|
-
|
2804
|
-
|
2805
|
-
|
2806
|
-
|
2807
|
-
|
2808
|
-
|
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
|
+
}
|
2809
3212
|
|
2810
|
-
|
2811
|
-
|
2812
|
-
|
2813
|
-
|
2814
|
-
|
2815
|
-
|
2816
|
-
|
2817
|
-
|
2818
|
-
|
2819
|
-
|
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();
|
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);
|
2820
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;
|
2821
3438
|
|
2822
|
-
case T_STRING:
|
2823
|
-
/* fall through */
|
2824
3439
|
default:
|
2825
|
-
|
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);
|
2826
3455
|
}
|
2827
|
-
|
2828
|
-
|
2829
|
-
|
2830
|
-
|
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);
|
3461
|
+
}
|
3462
|
+
else if (RB_TYPE_P(val, T_RATIONAL)) {
|
3463
|
+
return rb_rational_convert_to_BigDecimal(val, digs, raise_exception);
|
3464
|
+
}
|
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;
|
2831
3488
|
}
|
2832
|
-
|
2833
|
-
return VpAlloc(mf, RSTRING_PTR(iniValue), 1, exc);
|
3489
|
+
return rb_str_convert_to_BigDecimal(str, digs, raise_exception);
|
2834
3490
|
}
|
2835
3491
|
|
2836
|
-
/*
|
2837
|
-
*
|
3492
|
+
/* call-seq:
|
3493
|
+
* BigDecimal(value, exception: true) -> bigdecimal
|
3494
|
+
* BigDecimal(value, ndigits, exception: true) -> bigdecimal
|
2838
3495
|
*
|
2839
|
-
*
|
3496
|
+
* Returns the \BigDecimal converted from +value+
|
3497
|
+
* with a precision of +ndigits+ decimal digits.
|
2840
3498
|
*
|
2841
|
-
*
|
2842
|
-
*
|
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.
|
2843
3502
|
*
|
2844
|
-
*
|
2845
|
-
* terminate the value.
|
3503
|
+
* Returns +value+ converted to a \BigDecimal, depending on the type of +value+:
|
2846
3504
|
*
|
2847
|
-
*
|
2848
|
-
* the number of significant digits is determined from the initial
|
2849
|
-
* value.
|
3505
|
+
* - Integer, Float, Rational, Complex, or BigDecimal: converted directly:
|
2850
3506
|
*
|
2851
|
-
*
|
2852
|
-
*
|
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
|
2853
3514
|
*
|
2854
|
-
*
|
2855
|
-
*
|
2856
|
-
* for invalid.
|
3515
|
+
* - String: converted by parsing if it contains an integer or floating-point literal;
|
3516
|
+
* leading and trailing whitespace is ignored:
|
2857
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
|
2858
3523
|
*
|
2859
|
-
*
|
3524
|
+
* - Other type that responds to method <tt>:to_str</tt>:
|
3525
|
+
* first converted to a string, then converted to a \BigDecimal, as above.
|
2860
3526
|
*
|
2861
|
-
*
|
2862
|
-
* Rational, nor BigDecimal, this exception is raised.
|
3527
|
+
* - Other type:
|
2863
3528
|
*
|
2864
|
-
*
|
3529
|
+
* - Raises an exception if keyword argument +exception+ is +true+.
|
3530
|
+
* - Returns +nil+ if keyword argument +exception+ is +true+.
|
2865
3531
|
*
|
2866
|
-
*
|
2867
|
-
*
|
3532
|
+
* Raises an exception if +value+ evaluates to a Float
|
3533
|
+
* and +digits+ is larger than Float::DIG + 1.
|
2868
3534
|
*
|
2869
|
-
* ArgumentError:: If the +initial+ is a Float or Rational, and the +digits+
|
2870
|
-
* value is omitted, this exception is raised.
|
2871
3535
|
*/
|
2872
3536
|
static VALUE
|
2873
3537
|
f_BigDecimal(int argc, VALUE *argv, VALUE self)
|
2874
3538
|
{
|
2875
|
-
|
2876
|
-
|
2877
|
-
|
2878
|
-
|
2879
|
-
|
2880
|
-
|
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
|
+
}
|
2881
3561
|
}
|
2882
|
-
|
2883
|
-
|
2884
|
-
if (pv == NULL) return Qnil;
|
2885
|
-
SAVE(pv);
|
2886
|
-
if (ToValue(pv)) pv = VpCopy(NULL, pv);
|
2887
|
-
RTYPEDDATA_DATA(obj) = pv;
|
2888
|
-
RB_OBJ_FREEZE(obj);
|
2889
|
-
return pv->obj = obj;
|
3562
|
+
|
3563
|
+
return rb_convert_to_BigDecimal(val, digs, exception);
|
2890
3564
|
}
|
2891
3565
|
|
2892
3566
|
static VALUE
|
2893
3567
|
BigDecimal_s_interpret_loosely(VALUE klass, VALUE str)
|
2894
3568
|
{
|
2895
|
-
|
2896
|
-
|
2897
|
-
|
2898
|
-
|
2899
|
-
|
2900
|
-
|
2901
|
-
pv->obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, pv);
|
2902
|
-
RB_OBJ_FREEZE(pv->obj);
|
2903
|
-
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);
|
2904
3575
|
}
|
2905
3576
|
|
2906
3577
|
/* call-seq:
|
@@ -3084,7 +3755,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
|
|
3084
3755
|
infinite = isinf(flo);
|
3085
3756
|
nan = isnan(flo);
|
3086
3757
|
if (!infinite && !nan) {
|
3087
|
-
vx = GetVpValueWithPrec(x,
|
3758
|
+
vx = GetVpValueWithPrec(x, 0, 0);
|
3088
3759
|
}
|
3089
3760
|
break;
|
3090
3761
|
|
@@ -3097,29 +3768,29 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
|
|
3097
3768
|
}
|
3098
3769
|
if (infinite) {
|
3099
3770
|
if (negative) {
|
3100
|
-
|
3771
|
+
return VpCheckGetValue(GetVpValueWithPrec(INT2FIX(0), prec, 1));
|
3101
3772
|
}
|
3102
3773
|
else {
|
3103
3774
|
Real* vy;
|
3104
|
-
|
3775
|
+
vy = VpCreateRbObject(prec, "#0", true);
|
3105
3776
|
VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
|
3106
3777
|
RB_GC_GUARD(vy->obj);
|
3107
|
-
|
3778
|
+
return VpCheckGetValue(vy);
|
3108
3779
|
}
|
3109
3780
|
}
|
3110
3781
|
else if (nan) {
|
3111
3782
|
Real* vy;
|
3112
|
-
|
3783
|
+
vy = VpCreateRbObject(prec, "#0", true);
|
3113
3784
|
VpSetNaN(vy);
|
3114
3785
|
RB_GC_GUARD(vy->obj);
|
3115
|
-
|
3786
|
+
return VpCheckGetValue(vy);
|
3116
3787
|
}
|
3117
3788
|
else if (vx == NULL) {
|
3118
3789
|
cannot_be_coerced_into_BigDecimal(rb_eArgError, x);
|
3119
3790
|
}
|
3120
3791
|
x = vx->obj;
|
3121
3792
|
|
3122
|
-
n = prec +
|
3793
|
+
n = prec + BIGDECIMAL_DOUBLE_FIGURES;
|
3123
3794
|
negative = BIGDECIMAL_NEGATIVE_P(vx);
|
3124
3795
|
if (negative) {
|
3125
3796
|
VALUE x_zero = INT2NUM(1);
|
@@ -3129,7 +3800,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
|
|
3129
3800
|
VpSetSign(vx, 1);
|
3130
3801
|
}
|
3131
3802
|
|
3132
|
-
one =
|
3803
|
+
one = VpCheckGetValue(VpCreateRbObject(1, "1", true));
|
3133
3804
|
y = one;
|
3134
3805
|
d = y;
|
3135
3806
|
i = 1;
|
@@ -3144,8 +3815,8 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
|
|
3144
3815
|
if (m <= 0) {
|
3145
3816
|
break;
|
3146
3817
|
}
|
3147
|
-
else if ((size_t)m <
|
3148
|
-
m =
|
3818
|
+
else if ((size_t)m < BIGDECIMAL_DOUBLE_FIGURES) {
|
3819
|
+
m = BIGDECIMAL_DOUBLE_FIGURES;
|
3149
3820
|
}
|
3150
3821
|
|
3151
3822
|
d = BigDecimal_mult(d, x); /* d <- d * x */
|
@@ -3237,7 +3908,7 @@ get_vp_value:
|
|
3237
3908
|
infinite = isinf(flo);
|
3238
3909
|
nan = isnan(flo);
|
3239
3910
|
if (!zero && !negative && !infinite && !nan) {
|
3240
|
-
vx = GetVpValueWithPrec(x,
|
3911
|
+
vx = GetVpValueWithPrec(x, 0, 1);
|
3241
3912
|
}
|
3242
3913
|
break;
|
3243
3914
|
|
@@ -3257,17 +3928,17 @@ get_vp_value:
|
|
3257
3928
|
}
|
3258
3929
|
if (infinite && !negative) {
|
3259
3930
|
Real* vy;
|
3260
|
-
|
3931
|
+
vy = VpCreateRbObject(prec, "#0", true);
|
3261
3932
|
RB_GC_GUARD(vy->obj);
|
3262
3933
|
VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
|
3263
|
-
|
3934
|
+
return VpCheckGetValue(vy);
|
3264
3935
|
}
|
3265
3936
|
else if (nan) {
|
3266
3937
|
Real* vy;
|
3267
|
-
|
3938
|
+
vy = VpCreateRbObject(prec, "#0", true);
|
3268
3939
|
RB_GC_GUARD(vy->obj);
|
3269
3940
|
VpSetNaN(vy);
|
3270
|
-
|
3941
|
+
return VpCheckGetValue(vy);
|
3271
3942
|
}
|
3272
3943
|
else if (zero || negative) {
|
3273
3944
|
rb_raise(rb_eMathDomainError,
|
@@ -3276,18 +3947,18 @@ get_vp_value:
|
|
3276
3947
|
else if (vx == NULL) {
|
3277
3948
|
cannot_be_coerced_into_BigDecimal(rb_eArgError, x);
|
3278
3949
|
}
|
3279
|
-
x =
|
3950
|
+
x = VpCheckGetValue(vx);
|
3280
3951
|
|
3281
|
-
RB_GC_GUARD(one) =
|
3282
|
-
RB_GC_GUARD(two) =
|
3952
|
+
RB_GC_GUARD(one) = VpCheckGetValue(VpCreateRbObject(1, "1", true));
|
3953
|
+
RB_GC_GUARD(two) = VpCheckGetValue(VpCreateRbObject(1, "2", true));
|
3283
3954
|
|
3284
|
-
n = prec +
|
3955
|
+
n = prec + BIGDECIMAL_DOUBLE_FIGURES;
|
3285
3956
|
RB_GC_GUARD(vn) = SSIZET2NUM(n);
|
3286
3957
|
expo = VpExponent10(vx);
|
3287
3958
|
if (expo < 0 || expo >= 3) {
|
3288
3959
|
char buf[DECIMAL_SIZE_OF_BITS(SIZEOF_VALUE * CHAR_BIT) + 4];
|
3289
3960
|
snprintf(buf, sizeof(buf), "1E%"PRIdVALUE, -expo);
|
3290
|
-
|
3961
|
+
x = BigDecimal_mult2(x, VpCheckGetValue(VpCreateRbObject(1, buf, true)), vn);
|
3291
3962
|
}
|
3292
3963
|
else {
|
3293
3964
|
expo = 0;
|
@@ -3305,8 +3976,8 @@ get_vp_value:
|
|
3305
3976
|
if (m <= 0) {
|
3306
3977
|
break;
|
3307
3978
|
}
|
3308
|
-
else if ((size_t)m <
|
3309
|
-
m =
|
3979
|
+
else if ((size_t)m < BIGDECIMAL_DOUBLE_FIGURES) {
|
3980
|
+
m = BIGDECIMAL_DOUBLE_FIGURES;
|
3310
3981
|
}
|
3311
3982
|
|
3312
3983
|
x = BigDecimal_mult2(x2, x, vn);
|
@@ -3319,7 +3990,7 @@ get_vp_value:
|
|
3319
3990
|
if (expo != 0) {
|
3320
3991
|
VALUE log10, vexpo, dy;
|
3321
3992
|
log10 = BigMath_s_log(klass, INT2FIX(10), vprec);
|
3322
|
-
|
3993
|
+
vexpo = VpCheckGetValue(GetVpValue(SSIZET2NUM(expo), 1));
|
3323
3994
|
dy = BigDecimal_mult(log10, vexpo);
|
3324
3995
|
y = BigDecimal_add(y, dy);
|
3325
3996
|
}
|
@@ -3327,6 +3998,46 @@ get_vp_value:
|
|
3327
3998
|
return y;
|
3328
3999
|
}
|
3329
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
|
+
|
3330
4041
|
/* Document-class: BigDecimal
|
3331
4042
|
* BigDecimal provides arbitrary-precision floating point decimal arithmetic.
|
3332
4043
|
*
|
@@ -3370,6 +4081,18 @@ get_vp_value:
|
|
3370
4081
|
*
|
3371
4082
|
* (1.2 - 1.0) == 0.2 #=> false
|
3372
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
|
+
*
|
3373
4096
|
* == Special features of accurate decimal arithmetic
|
3374
4097
|
*
|
3375
4098
|
* Because BigDecimal is more accurate than normal binary floating point
|
@@ -3598,17 +4321,40 @@ Init_bigdecimal(void)
|
|
3598
4321
|
/* -3: Indicates that a value is negative and infinite. See BigDecimal.sign. */
|
3599
4322
|
rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_INFINITE", INT2FIX(VP_SIGN_NEGATIVE_INFINITE));
|
3600
4323
|
|
3601
|
-
|
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
|
+
|
3602
4334
|
/* Positive infinity value. */
|
3603
|
-
|
3604
|
-
|
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
|
+
|
3605
4344
|
/* 'Not a Number' value. */
|
3606
|
-
|
4345
|
+
arg = rb_str_new2("NaN");
|
4346
|
+
BIGDECIMAL_NAN = f_BigDecimal(1, &arg, rb_cBigDecimal);
|
4347
|
+
rb_gc_register_mark_object(BIGDECIMAL_NAN);
|
3607
4348
|
|
4349
|
+
/* Special value constants */
|
4350
|
+
rb_define_const(rb_cBigDecimal, "INFINITY", BIGDECIMAL_POSITIVE_INFINITY);
|
4351
|
+
rb_define_const(rb_cBigDecimal, "NAN", BIGDECIMAL_NAN);
|
3608
4352
|
|
3609
4353
|
/* instance methods */
|
3610
4354
|
rb_define_method(rb_cBigDecimal, "precs", BigDecimal_prec, 0);
|
3611
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);
|
3612
4358
|
rb_define_method(rb_cBigDecimal, "n_significant_digits", BigDecimal_n_significant_digits, 0);
|
3613
4359
|
|
3614
4360
|
rb_define_method(rb_cBigDecimal, "add", BigDecimal_add2, 2);
|
@@ -3627,7 +4373,7 @@ Init_bigdecimal(void)
|
|
3627
4373
|
rb_define_method(rb_cBigDecimal, "-@", BigDecimal_neg, 0);
|
3628
4374
|
rb_define_method(rb_cBigDecimal, "*", BigDecimal_mult, 1);
|
3629
4375
|
rb_define_method(rb_cBigDecimal, "/", BigDecimal_div, 1);
|
3630
|
-
rb_define_method(rb_cBigDecimal, "quo",
|
4376
|
+
rb_define_method(rb_cBigDecimal, "quo", BigDecimal_quo, -1);
|
3631
4377
|
rb_define_method(rb_cBigDecimal, "%", BigDecimal_mod, 1);
|
3632
4378
|
rb_define_method(rb_cBigDecimal, "modulo", BigDecimal_mod, 1);
|
3633
4379
|
rb_define_method(rb_cBigDecimal, "remainder", BigDecimal_remainder, 1);
|
@@ -3718,9 +4464,9 @@ enum op_sw {
|
|
3718
4464
|
|
3719
4465
|
static int VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw);
|
3720
4466
|
static int AddExponent(Real *a, SIGNED_VALUE n);
|
3721
|
-
static
|
3722
|
-
static
|
3723
|
-
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);
|
3724
4470
|
static int VpNmlz(Real *a);
|
3725
4471
|
static void VpFormatSt(char *psz, size_t fFmt);
|
3726
4472
|
static int VpRdup(Real *m, size_t ind_m);
|
@@ -3736,9 +4482,6 @@ VP_EXPORT void *
|
|
3736
4482
|
VpMemAlloc(size_t mb)
|
3737
4483
|
{
|
3738
4484
|
void *p = xmalloc(mb);
|
3739
|
-
if (!p) {
|
3740
|
-
VpException(VP_EXCEPTION_MEMORY, "failed to allocate memory", 1);
|
3741
|
-
}
|
3742
4485
|
memset(p, 0, mb);
|
3743
4486
|
#ifdef BIGDECIMAL_DEBUG
|
3744
4487
|
gnAlloc++; /* Count allocation call */
|
@@ -3749,11 +4492,7 @@ VpMemAlloc(size_t mb)
|
|
3749
4492
|
VP_EXPORT void *
|
3750
4493
|
VpMemRealloc(void *ptr, size_t mb)
|
3751
4494
|
{
|
3752
|
-
|
3753
|
-
if (!p) {
|
3754
|
-
VpException(VP_EXCEPTION_MEMORY, "failed to allocate memory", 1);
|
3755
|
-
}
|
3756
|
-
return p;
|
4495
|
+
return xrealloc(ptr, mb);
|
3757
4496
|
}
|
3758
4497
|
|
3759
4498
|
VP_EXPORT void
|
@@ -3779,7 +4518,7 @@ VpFree(Real *pv)
|
|
3779
4518
|
* EXCEPTION Handling.
|
3780
4519
|
*/
|
3781
4520
|
|
3782
|
-
#define
|
4521
|
+
#define bigdecimal_set_thread_local_exception_mode(mode) \
|
3783
4522
|
rb_thread_local_aset( \
|
3784
4523
|
rb_thread_current(), \
|
3785
4524
|
id_BigDecimal_exception_mode, \
|
@@ -3795,8 +4534,8 @@ VpGetException (void)
|
|
3795
4534
|
);
|
3796
4535
|
|
3797
4536
|
if (NIL_P(vmode)) {
|
3798
|
-
|
3799
|
-
return
|
4537
|
+
bigdecimal_set_thread_local_exception_mode(BIGDECIMAL_EXCEPTION_MODE_DEFAULT);
|
4538
|
+
return BIGDECIMAL_EXCEPTION_MODE_DEFAULT;
|
3800
4539
|
}
|
3801
4540
|
|
3802
4541
|
return NUM2USHORT(vmode);
|
@@ -3805,20 +4544,41 @@ VpGetException (void)
|
|
3805
4544
|
static void
|
3806
4545
|
VpSetException(unsigned short f)
|
3807
4546
|
{
|
3808
|
-
|
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;
|
3809
4569
|
}
|
3810
4570
|
|
3811
4571
|
/*
|
3812
4572
|
* Precision limit.
|
3813
4573
|
*/
|
3814
4574
|
|
3815
|
-
#define
|
4575
|
+
#define bigdecimal_set_thread_local_precision_limit(limit) \
|
3816
4576
|
rb_thread_local_aset( \
|
3817
4577
|
rb_thread_current(), \
|
3818
4578
|
id_BigDecimal_precision_limit, \
|
3819
4579
|
SIZET2NUM(limit) \
|
3820
4580
|
)
|
3821
|
-
#define
|
4581
|
+
#define BIGDECIMAL_PRECISION_LIMIT_DEFAULT ((size_t)0)
|
3822
4582
|
|
3823
4583
|
/* These 2 functions added at v1.1.7 */
|
3824
4584
|
VP_EXPORT size_t
|
@@ -3830,8 +4590,8 @@ VpGetPrecLimit(void)
|
|
3830
4590
|
);
|
3831
4591
|
|
3832
4592
|
if (NIL_P(vlimit)) {
|
3833
|
-
|
3834
|
-
return
|
4593
|
+
bigdecimal_set_thread_local_precision_limit(BIGDECIMAL_PRECISION_LIMIT_DEFAULT);
|
4594
|
+
return BIGDECIMAL_PRECISION_LIMIT_DEFAULT;
|
3835
4595
|
}
|
3836
4596
|
|
3837
4597
|
return NUM2SIZET(vlimit);
|
@@ -3841,7 +4601,7 @@ VP_EXPORT size_t
|
|
3841
4601
|
VpSetPrecLimit(size_t n)
|
3842
4602
|
{
|
3843
4603
|
size_t const s = VpGetPrecLimit();
|
3844
|
-
|
4604
|
+
bigdecimal_set_thread_local_precision_limit(n);
|
3845
4605
|
return s;
|
3846
4606
|
}
|
3847
4607
|
|
@@ -3849,7 +4609,7 @@ VpSetPrecLimit(size_t n)
|
|
3849
4609
|
* Rounding mode.
|
3850
4610
|
*/
|
3851
4611
|
|
3852
|
-
#define
|
4612
|
+
#define bigdecimal_set_thread_local_rounding_mode(mode) \
|
3853
4613
|
rb_thread_local_aset( \
|
3854
4614
|
rb_thread_current(), \
|
3855
4615
|
id_BigDecimal_rounding_mode, \
|
@@ -3865,8 +4625,8 @@ VpGetRoundMode(void)
|
|
3865
4625
|
);
|
3866
4626
|
|
3867
4627
|
if (NIL_P(vmode)) {
|
3868
|
-
|
3869
|
-
return
|
4628
|
+
bigdecimal_set_thread_local_rounding_mode(BIGDECIMAL_ROUNDING_MODE_DEFAULT);
|
4629
|
+
return BIGDECIMAL_ROUNDING_MODE_DEFAULT;
|
3870
4630
|
}
|
3871
4631
|
|
3872
4632
|
return NUM2USHORT(vmode);
|
@@ -3894,7 +4654,7 @@ VP_EXPORT unsigned short
|
|
3894
4654
|
VpSetRoundMode(unsigned short n)
|
3895
4655
|
{
|
3896
4656
|
if (VpIsRoundMode(n)) {
|
3897
|
-
|
4657
|
+
bigdecimal_set_thread_local_rounding_mode(n);
|
3898
4658
|
return n;
|
3899
4659
|
}
|
3900
4660
|
|
@@ -3971,7 +4731,7 @@ VpException(unsigned short f, const char *str,int always)
|
|
3971
4731
|
{
|
3972
4732
|
unsigned short const exception_mode = VpGetException();
|
3973
4733
|
|
3974
|
-
if (f == VP_EXCEPTION_OP
|
4734
|
+
if (f == VP_EXCEPTION_OP) always = 1;
|
3975
4735
|
|
3976
4736
|
if (always || (exception_mode & f)) {
|
3977
4737
|
switch(f) {
|
@@ -3983,7 +4743,6 @@ VpException(unsigned short f, const char *str,int always)
|
|
3983
4743
|
case VP_EXCEPTION_OP:
|
3984
4744
|
rb_raise(rb_eFloatDomainError, "%s", str);
|
3985
4745
|
break;
|
3986
|
-
case VP_EXCEPTION_MEMORY:
|
3987
4746
|
default:
|
3988
4747
|
rb_fatal("%s", str);
|
3989
4748
|
}
|
@@ -4132,13 +4891,13 @@ VpNumOfChars(Real *vp,const char *pszFmt)
|
|
4132
4891
|
* that BASE is as large as possible satisfying the
|
4133
4892
|
* relation MaxVal <= BASE*(BASE+1). Where the value
|
4134
4893
|
* MaxVal is the largest value which can be represented
|
4135
|
-
* by one
|
4894
|
+
* by one DECDIG word in the computer used.
|
4136
4895
|
*
|
4137
4896
|
* [Returns]
|
4138
|
-
*
|
4897
|
+
* BIGDECIMAL_DOUBLE_FIGURES ... OK
|
4139
4898
|
*/
|
4140
4899
|
VP_EXPORT size_t
|
4141
|
-
VpInit(
|
4900
|
+
VpInit(DECDIG BaseVal)
|
4142
4901
|
{
|
4143
4902
|
/* Setup +/- Inf NaN -0 */
|
4144
4903
|
VpGetDoubleNegZero();
|
@@ -4153,16 +4912,16 @@ VpInit(BDIGIT BaseVal)
|
|
4153
4912
|
|
4154
4913
|
#ifdef BIGDECIMAL_DEBUG
|
4155
4914
|
if (gfDebug) {
|
4156
|
-
|
4157
|
-
|
4158
|
-
|
4159
|
-
|
4160
|
-
|
4161
|
-
|
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);
|
4162
4921
|
}
|
4163
4922
|
#endif /* BIGDECIMAL_DEBUG */
|
4164
4923
|
|
4165
|
-
return
|
4924
|
+
return BIGDECIMAL_DOUBLE_FIGURES;
|
4166
4925
|
}
|
4167
4926
|
|
4168
4927
|
VP_EXPORT Real *
|
@@ -4210,7 +4969,7 @@ overflow:
|
|
4210
4969
|
}
|
4211
4970
|
|
4212
4971
|
Real *
|
4213
|
-
|
4972
|
+
bigdecimal_parse_special_string(const char *str)
|
4214
4973
|
{
|
4215
4974
|
static const struct {
|
4216
4975
|
const char *str;
|
@@ -4305,14 +5064,13 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
|
|
4305
5064
|
/* at least mx digits. */
|
4306
5065
|
/* szVal==NULL ==> allocate zero value. */
|
4307
5066
|
vp = VpAllocReal(mx);
|
4308
|
-
/* xmalloc() always returns(or throw interruption) */
|
4309
5067
|
vp->MaxPrec = mx; /* set max precision */
|
4310
5068
|
VpSetZero(vp, 1); /* initialize vp to zero. */
|
4311
5069
|
return vp;
|
4312
5070
|
}
|
4313
5071
|
|
4314
5072
|
/* Check on Inf & NaN */
|
4315
|
-
if ((vp =
|
5073
|
+
if ((vp = bigdecimal_parse_special_string(szVal)) != NULL) {
|
4316
5074
|
return vp;
|
4317
5075
|
}
|
4318
5076
|
|
@@ -4481,7 +5239,6 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
|
|
4481
5239
|
nalloc = Max(nalloc, mx);
|
4482
5240
|
mx = nalloc;
|
4483
5241
|
vp = VpAllocReal(mx);
|
4484
|
-
/* xmalloc() always returns(or throw interruption) */
|
4485
5242
|
vp->MaxPrec = mx; /* set max precision */
|
4486
5243
|
VpSetZero(vp, sign);
|
4487
5244
|
VpCtoV(vp, psz, ni, psz + ipf, nf, psz + ipe, ne);
|
@@ -4520,7 +5277,7 @@ VpAsgn(Real *c, Real *a, int isw)
|
|
4520
5277
|
VpSetSign(c, isw * VpGetSign(a)); /* set sign */
|
4521
5278
|
n = (a->Prec < c->MaxPrec) ? (a->Prec) : (c->MaxPrec);
|
4522
5279
|
c->Prec = n;
|
4523
|
-
|
5280
|
+
memcpy(c->frac, a->frac, n * sizeof(DECDIG));
|
4524
5281
|
/* Needs round ? */
|
4525
5282
|
if (isw != 10) {
|
4526
5283
|
/* Not in ActiveRound */
|
@@ -4551,7 +5308,7 @@ VpAddSub(Real *c, Real *a, Real *b, int operation)
|
|
4551
5308
|
short sw, isw;
|
4552
5309
|
Real *a_ptr, *b_ptr;
|
4553
5310
|
size_t n, na, nb, i;
|
4554
|
-
|
5311
|
+
DECDIG mrv;
|
4555
5312
|
|
4556
5313
|
#ifdef BIGDECIMAL_DEBUG
|
4557
5314
|
if (gfDebug) {
|
@@ -4679,7 +5436,7 @@ end_if:
|
|
4679
5436
|
* a and b assuming abs(a)>abs(b).
|
4680
5437
|
* c = abs(a) + abs(b) ; where |a|>=|b|
|
4681
5438
|
*/
|
4682
|
-
static
|
5439
|
+
static DECDIG
|
4683
5440
|
VpAddAbs(Real *a, Real *b, Real *c)
|
4684
5441
|
{
|
4685
5442
|
size_t word_shift;
|
@@ -4689,7 +5446,7 @@ VpAddAbs(Real *a, Real *b, Real *c)
|
|
4689
5446
|
size_t a_pos;
|
4690
5447
|
size_t b_pos, b_pos_with_word_shift;
|
4691
5448
|
size_t c_pos;
|
4692
|
-
|
5449
|
+
DECDIG av, bv, carry, mrv;
|
4693
5450
|
|
4694
5451
|
#ifdef BIGDECIMAL_DEBUG
|
4695
5452
|
if (gfDebug) {
|
@@ -4774,7 +5531,7 @@ Exit:
|
|
4774
5531
|
/*
|
4775
5532
|
* c = abs(a) - abs(b)
|
4776
5533
|
*/
|
4777
|
-
static
|
5534
|
+
static DECDIG
|
4778
5535
|
VpSubAbs(Real *a, Real *b, Real *c)
|
4779
5536
|
{
|
4780
5537
|
size_t word_shift;
|
@@ -4784,7 +5541,7 @@ VpSubAbs(Real *a, Real *b, Real *c)
|
|
4784
5541
|
size_t a_pos;
|
4785
5542
|
size_t b_pos, b_pos_with_word_shift;
|
4786
5543
|
size_t c_pos;
|
4787
|
-
|
5544
|
+
DECDIG av, bv, borrow, mrv;
|
4788
5545
|
|
4789
5546
|
#ifdef BIGDECIMAL_DEBUG
|
4790
5547
|
if (gfDebug) {
|
@@ -4891,7 +5648,7 @@ Exit:
|
|
4891
5648
|
* c_pos = |
|
4892
5649
|
*/
|
4893
5650
|
static size_t
|
4894
|
-
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)
|
4895
5652
|
{
|
4896
5653
|
size_t left_word, right_word, word_shift;
|
4897
5654
|
|
@@ -5006,8 +5763,8 @@ VpMult(Real *c, Real *a, Real *b)
|
|
5006
5763
|
size_t MxIndA, MxIndB, MxIndAB, MxIndC;
|
5007
5764
|
size_t ind_c, i, ii, nc;
|
5008
5765
|
size_t ind_as, ind_ae, ind_bs;
|
5009
|
-
|
5010
|
-
|
5766
|
+
DECDIG carry;
|
5767
|
+
DECDIG_DBL s;
|
5011
5768
|
Real *w;
|
5012
5769
|
|
5013
5770
|
#ifdef BIGDECIMAL_DEBUG
|
@@ -5061,7 +5818,7 @@ VpMult(Real *c, Real *a, Real *b)
|
|
5061
5818
|
VpSetSign(c, VpGetSign(a) * VpGetSign(b)); /* set sign */
|
5062
5819
|
carry = 0;
|
5063
5820
|
nc = ind_c = MxIndAB;
|
5064
|
-
memset(c->frac, 0, (nc + 1) * sizeof(
|
5821
|
+
memset(c->frac, 0, (nc + 1) * sizeof(DECDIG)); /* Initialize c */
|
5065
5822
|
c->Prec = nc + 1; /* set precision */
|
5066
5823
|
for (nc = 0; nc < MxIndAB; ++nc, --ind_c) {
|
5067
5824
|
if (nc < MxIndB) { /* The left triangle of the Fig. */
|
@@ -5081,15 +5838,15 @@ VpMult(Real *c, Real *a, Real *b)
|
|
5081
5838
|
}
|
5082
5839
|
|
5083
5840
|
for (i = ind_as; i <= ind_ae; ++i) {
|
5084
|
-
|
5085
|
-
|
5086
|
-
|
5087
|
-
|
5088
|
-
|
5089
|
-
|
5090
|
-
|
5091
|
-
|
5092
|
-
|
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
|
+
}
|
5093
5850
|
if (carry) {
|
5094
5851
|
ii = ind_c;
|
5095
5852
|
while (ii-- > 0) {
|
@@ -5135,9 +5892,9 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
|
|
5135
5892
|
size_t word_a, word_b, word_c, word_r;
|
5136
5893
|
size_t i, n, ind_a, ind_b, ind_c, ind_r;
|
5137
5894
|
size_t nLoop;
|
5138
|
-
|
5139
|
-
|
5140
|
-
|
5895
|
+
DECDIG_DBL q, b1, b1p1, b1b2, b1b2p1, r1r2;
|
5896
|
+
DECDIG borrow, borrow1, borrow2;
|
5897
|
+
DECDIG_DBL qb;
|
5141
5898
|
|
5142
5899
|
#ifdef BIGDECIMAL_DEBUG
|
5143
5900
|
if (gfDebug) {
|
@@ -5174,18 +5931,17 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
|
|
5174
5931
|
word_c = c->MaxPrec;
|
5175
5932
|
word_r = r->MaxPrec;
|
5176
5933
|
|
5177
|
-
ind_c = 0;
|
5178
|
-
ind_r = 1;
|
5179
|
-
|
5180
5934
|
if (word_a >= word_r) goto space_error;
|
5181
5935
|
|
5936
|
+
ind_r = 1;
|
5182
5937
|
r->frac[0] = 0;
|
5183
5938
|
while (ind_r <= word_a) {
|
5184
5939
|
r->frac[ind_r] = a->frac[ind_r - 1];
|
5185
5940
|
++ind_r;
|
5186
5941
|
}
|
5187
|
-
|
5188
5942
|
while (ind_r < word_r) r->frac[ind_r++] = 0;
|
5943
|
+
|
5944
|
+
ind_c = 0;
|
5189
5945
|
while (ind_c < word_c) c->frac[ind_c++] = 0;
|
5190
5946
|
|
5191
5947
|
/* initial procedure */
|
@@ -5209,7 +5965,7 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
|
|
5209
5965
|
++ind_c;
|
5210
5966
|
continue;
|
5211
5967
|
}
|
5212
|
-
|
5968
|
+
r1r2 = (DECDIG_DBL)r->frac[ind_c] * BASE + r->frac[ind_c + 1];
|
5213
5969
|
if (r1r2 == b1b2) {
|
5214
5970
|
/* The first two word digits is the same */
|
5215
5971
|
ind_b = 2;
|
@@ -5246,17 +6002,17 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
|
|
5246
6002
|
/* The first two word digits is not the same, */
|
5247
6003
|
/* then compare magnitude, and divide actually. */
|
5248
6004
|
if (r1r2 >= b1b2p1) {
|
5249
|
-
|
5250
|
-
|
5251
|
-
|
5252
|
-
|
6005
|
+
q = r1r2 / b1b2p1; /* q == (DECDIG)q */
|
6006
|
+
c->frac[ind_c] += (DECDIG)q;
|
6007
|
+
ind_r = b->Prec + ind_c - 1;
|
6008
|
+
goto sub_mult;
|
5253
6009
|
}
|
5254
6010
|
|
5255
6011
|
div_b1p1:
|
5256
|
-
|
5257
|
-
|
5258
|
-
|
5259
|
-
|
6012
|
+
if (ind_c + 1 >= word_c) goto out_side;
|
6013
|
+
q = r1r2 / b1p1; /* q == (DECDIG)q */
|
6014
|
+
c->frac[ind_c + 1] += (DECDIG)q;
|
6015
|
+
ind_r = b->Prec + ind_c;
|
5260
6016
|
|
5261
6017
|
sub_mult:
|
5262
6018
|
borrow1 = borrow2 = 0;
|
@@ -5268,16 +6024,16 @@ sub_mult:
|
|
5268
6024
|
qb = q * b->frac[ind_b];
|
5269
6025
|
if (qb < BASE) borrow1 = 0;
|
5270
6026
|
else {
|
5271
|
-
|
5272
|
-
|
6027
|
+
borrow1 = (DECDIG)(qb / BASE);
|
6028
|
+
qb -= (DECDIG_DBL)borrow1 * BASE; /* get qb < BASE */
|
5273
6029
|
}
|
5274
6030
|
if(r->frac[ind_r] < qb) {
|
5275
|
-
|
5276
|
-
|
6031
|
+
r->frac[ind_r] += (DECDIG)(BASE - qb);
|
6032
|
+
borrow2 = borrow2 + borrow1 + 1;
|
5277
6033
|
}
|
5278
6034
|
else {
|
5279
|
-
|
5280
|
-
|
6035
|
+
r->frac[ind_r] -= (DECDIG)qb;
|
6036
|
+
borrow2 += borrow1;
|
5281
6037
|
}
|
5282
6038
|
if (borrow2) {
|
5283
6039
|
if(r->frac[ind_r - 1] < borrow2) {
|
@@ -5359,9 +6115,9 @@ VpNmlz(Real *a)
|
|
5359
6115
|
i = 0;
|
5360
6116
|
while (a->frac[i] == 0) ++i; /* skip the first few zeros */
|
5361
6117
|
if (i) {
|
5362
|
-
|
5363
|
-
|
5364
|
-
|
6118
|
+
a->Prec -= i;
|
6119
|
+
if (!AddExponent(a, -(SIGNED_VALUE)i)) return 0;
|
6120
|
+
memmove(&a->frac[0], &a->frac[i], a->Prec*sizeof(DECDIG));
|
5365
6121
|
}
|
5366
6122
|
return 1;
|
5367
6123
|
}
|
@@ -5484,7 +6240,7 @@ static int
|
|
5484
6240
|
VPrint(FILE *fp, const char *cntl_chr, Real *a)
|
5485
6241
|
{
|
5486
6242
|
size_t i, j, nc, nd, ZeroSup, sep = 10;
|
5487
|
-
|
6243
|
+
DECDIG m, e, nn;
|
5488
6244
|
|
5489
6245
|
j = 0;
|
5490
6246
|
nd = nc = 0; /* nd : number of digits in fraction part(every 10 digits, */
|
@@ -5519,7 +6275,7 @@ VPrint(FILE *fp, const char *cntl_chr, Real *a)
|
|
5519
6275
|
case '0': case 'z':
|
5520
6276
|
ZeroSup = 0;
|
5521
6277
|
++j;
|
5522
|
-
sep = cntl_chr[j] == 'z' ?
|
6278
|
+
sep = cntl_chr[j] == 'z' ? BIGDECIMAL_COMPONENT_FIGURES : 10;
|
5523
6279
|
break;
|
5524
6280
|
}
|
5525
6281
|
for (i = 0; i < a->Prec; ++i) {
|
@@ -5628,7 +6384,7 @@ VP_EXPORT void
|
|
5628
6384
|
VpSzMantissa(Real *a,char *psz)
|
5629
6385
|
{
|
5630
6386
|
size_t i, n, ZeroSup;
|
5631
|
-
|
6387
|
+
DECDIG_DBL m, e, nn;
|
5632
6388
|
|
5633
6389
|
if (VpIsNaN(a)) {
|
5634
6390
|
sprintf(psz, SZ_NaN);
|
@@ -5711,7 +6467,7 @@ VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
|
|
5711
6467
|
/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
|
5712
6468
|
{
|
5713
6469
|
size_t i, n, ZeroSup;
|
5714
|
-
|
6470
|
+
DECDIG shift, m, e, nn;
|
5715
6471
|
char *pszSav = psz;
|
5716
6472
|
ssize_t ex;
|
5717
6473
|
|
@@ -5759,7 +6515,7 @@ VpToFString(Real *a, char *psz, size_t fFmt, int fPlus)
|
|
5759
6515
|
/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
|
5760
6516
|
{
|
5761
6517
|
size_t i, n;
|
5762
|
-
|
6518
|
+
DECDIG m, e, nn;
|
5763
6519
|
char *pszSav = psz;
|
5764
6520
|
ssize_t ex;
|
5765
6521
|
|
@@ -5834,7 +6590,7 @@ VpCtoV(Real *a, const char *int_chr, size_t ni, const char *frac, size_t nf, con
|
|
5834
6590
|
me = ne;
|
5835
6591
|
signe = 1;
|
5836
6592
|
exponent_overflow = 0;
|
5837
|
-
memset(a->frac, 0, ma * sizeof(
|
6593
|
+
memset(a->frac, 0, ma * sizeof(DECDIG));
|
5838
6594
|
if (ne > 0) {
|
5839
6595
|
i = 0;
|
5840
6596
|
if (exp_chr[0] == '-') {
|
@@ -5971,7 +6727,7 @@ Final:
|
|
5971
6727
|
* [Output]
|
5972
6728
|
* *d ... fraction part of m(d = 0.xxxxxxx). where # of 'x's is fig.
|
5973
6729
|
* *e ... exponent of m.
|
5974
|
-
*
|
6730
|
+
* BIGDECIMAL_DOUBLE_FIGURES ... Number of digits in a double variable.
|
5975
6731
|
*
|
5976
6732
|
* m -> d*10**e, 0<d<BASE
|
5977
6733
|
* [Returns]
|
@@ -6018,7 +6774,7 @@ VpVtoD(double *d, SIGNED_VALUE *e, Real *m)
|
|
6018
6774
|
goto Exit;
|
6019
6775
|
}
|
6020
6776
|
/* Normal number */
|
6021
|
-
fig = (
|
6777
|
+
fig = roomof(BIGDECIMAL_DOUBLE_FIGURES, BASE_FIG);
|
6022
6778
|
ind_m = 0;
|
6023
6779
|
mm = Min(fig, m->Prec);
|
6024
6780
|
*d = 0.0;
|
@@ -6035,7 +6791,7 @@ Exit:
|
|
6035
6791
|
if (gfDebug) {
|
6036
6792
|
VPrint(stdout, " VpVtoD: m=%\n", m);
|
6037
6793
|
printf(" d=%e * 10 **%ld\n", *d, *e);
|
6038
|
-
printf("
|
6794
|
+
printf(" BIGDECIMAL_DOUBLE_FIGURES = %d\n", BIGDECIMAL_DOUBLE_FIGURES);
|
6039
6795
|
}
|
6040
6796
|
#endif /*BIGDECIMAL_DEBUG */
|
6041
6797
|
return f;
|
@@ -6049,7 +6805,7 @@ VpDtoV(Real *m, double d)
|
|
6049
6805
|
{
|
6050
6806
|
size_t ind_m, mm;
|
6051
6807
|
SIGNED_VALUE ne;
|
6052
|
-
|
6808
|
+
DECDIG i;
|
6053
6809
|
double val, val2;
|
6054
6810
|
|
6055
6811
|
if (isnan(d)) {
|
@@ -6084,12 +6840,12 @@ VpDtoV(Real *m, double d)
|
|
6084
6840
|
/* Now val = 0.xxxxx*BASE**ne */
|
6085
6841
|
|
6086
6842
|
mm = m->MaxPrec;
|
6087
|
-
memset(m->frac, 0, mm * sizeof(
|
6843
|
+
memset(m->frac, 0, mm * sizeof(DECDIG));
|
6088
6844
|
for (ind_m = 0; val > 0.0 && ind_m < mm; ind_m++) {
|
6089
|
-
|
6090
|
-
|
6091
|
-
|
6092
|
-
|
6845
|
+
val *= (double)BASE;
|
6846
|
+
i = (DECDIG)val;
|
6847
|
+
val -= (double)i;
|
6848
|
+
m->frac[ind_m] = i;
|
6093
6849
|
}
|
6094
6850
|
if (ind_m >= mm) ind_m = mm - 1;
|
6095
6851
|
VpSetSign(m, (d > 0.0) ? 1 : -1);
|
@@ -6097,7 +6853,7 @@ VpDtoV(Real *m, double d)
|
|
6097
6853
|
m->exponent = ne;
|
6098
6854
|
|
6099
6855
|
VpInternalRound(m, 0, (m->Prec > 0) ? m->frac[m->Prec-1] : 0,
|
6100
|
-
|
6856
|
+
(DECDIG)(val*(double)BASE));
|
6101
6857
|
|
6102
6858
|
Exit:
|
6103
6859
|
#ifdef BIGDECIMAL_DEBUG
|
@@ -6236,7 +6992,7 @@ VpSqrt(Real *y, Real *x)
|
|
6236
6992
|
}
|
6237
6993
|
VpDtoV(y, sqrt(val)); /* y <- sqrt(val) */
|
6238
6994
|
y->exponent += n;
|
6239
|
-
n = (SIGNED_VALUE)(
|
6995
|
+
n = (SIGNED_VALUE)roomof(BIGDECIMAL_DOUBLE_FIGURES, BASE_FIG);
|
6240
6996
|
y->MaxPrec = Min((size_t)n , y_prec);
|
6241
6997
|
f->MaxPrec = y->MaxPrec + 1;
|
6242
6998
|
n = (SIGNED_VALUE)(y_prec * BASE_FIG);
|
@@ -6293,8 +7049,8 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
|
|
6293
7049
|
/* exptoadd: number of digits needed to compensate negative nf */
|
6294
7050
|
int fracf, fracf_1further;
|
6295
7051
|
ssize_t n,i,ix,ioffset, exptoadd;
|
6296
|
-
|
6297
|
-
|
7052
|
+
DECDIG v, shifter;
|
7053
|
+
DECDIG div;
|
6298
7054
|
|
6299
7055
|
nf += y->exponent * (ssize_t)BASE_FIG;
|
6300
7056
|
exptoadd=0;
|
@@ -6316,8 +7072,8 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
|
|
6316
7072
|
n = (ssize_t)BASE_FIG - ioffset - 1;
|
6317
7073
|
for (shifter = 1, i = 0; i < n; ++i) shifter *= 10;
|
6318
7074
|
|
6319
|
-
/* so the representation used (in y->frac) is an array of
|
6320
|
-
each
|
7075
|
+
/* so the representation used (in y->frac) is an array of DECDIG, where
|
7076
|
+
each DECDIG contains a value between 0 and BASE-1, consisting of BASE_FIG
|
6321
7077
|
decimal places.
|
6322
7078
|
|
6323
7079
|
(that numbers of decimal places are typed as ssize_t is somewhat confusing)
|
@@ -6325,10 +7081,10 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
|
|
6325
7081
|
nf is now position (in decimal places) of the digit from the start of
|
6326
7082
|
the array.
|
6327
7083
|
|
6328
|
-
ix is the position (in
|
7084
|
+
ix is the position (in DECDIGs) of the DECDIG containing the decimal digit,
|
6329
7085
|
from the start of the array.
|
6330
7086
|
|
6331
|
-
v is the value of this
|
7087
|
+
v is the value of this DECDIG
|
6332
7088
|
|
6333
7089
|
ioffset is the number of extra decimal places along of this decimal digit
|
6334
7090
|
within v.
|
@@ -6354,7 +7110,7 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
|
|
6354
7110
|
now fracf_1further is whether any of the remaining digits within v are non-zero
|
6355
7111
|
*/
|
6356
7112
|
|
6357
|
-
/* now check all the remaining
|
7113
|
+
/* now check all the remaining DECDIGs for zero-ness a whole DECDIG at a time.
|
6358
7114
|
if we spot any non-zeroness, that means that we found a positive digit under
|
6359
7115
|
rounding position, and we also found a positive digit under one further than
|
6360
7116
|
the rounding position, so both searches (to see if any such non-zero digit exists)
|
@@ -6373,7 +7129,7 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
|
|
6373
7129
|
now v = the first digit under the rounding position */
|
6374
7130
|
|
6375
7131
|
/* drop digits after pointed digit */
|
6376
|
-
memset(y->frac + ix + 1, 0, (y->Prec - (ix + 1)) * sizeof(
|
7132
|
+
memset(y->frac + ix + 1, 0, (y->Prec - (ix + 1)) * sizeof(DECDIG));
|
6377
7133
|
|
6378
7134
|
switch (f) {
|
6379
7135
|
case VP_ROUND_DOWN: /* Truncate */
|
@@ -6401,11 +7157,11 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
|
|
6401
7157
|
}
|
6402
7158
|
else {
|
6403
7159
|
if (ioffset == 0) {
|
6404
|
-
|
6405
|
-
|
6406
|
-
|
6407
|
-
|
6408
|
-
|
7160
|
+
/* v is the first decimal digit of its DECDIG;
|
7161
|
+
need to grab the previous DECDIG if present
|
7162
|
+
to check for evenness of the previous decimal
|
7163
|
+
digit (which is same as that of the DECDIG since
|
7164
|
+
base 10 has a factor of 2) */
|
6409
7165
|
if (ix && (y->frac[ix-1] % 2)) ++div;
|
6410
7166
|
}
|
6411
7167
|
else {
|
@@ -6453,7 +7209,7 @@ VpLeftRound(Real *y, unsigned short f, ssize_t nf)
|
|
6453
7209
|
* Round from the left hand side of the digits.
|
6454
7210
|
*/
|
6455
7211
|
{
|
6456
|
-
|
7212
|
+
DECDIG v;
|
6457
7213
|
if (!VpHasVal(y)) return 0; /* Unable to round */
|
6458
7214
|
v = y->frac[0];
|
6459
7215
|
nf -= VpExponent(y) * (ssize_t)BASE_FIG;
|
@@ -6484,7 +7240,7 @@ VpLimitRound(Real *c, size_t ixDigit)
|
|
6484
7240
|
/* If I understand correctly, this is only ever used to round off the final decimal
|
6485
7241
|
digit of precision */
|
6486
7242
|
static void
|
6487
|
-
VpInternalRound(Real *c, size_t ixDigit,
|
7243
|
+
VpInternalRound(Real *c, size_t ixDigit, DECDIG vPrev, DECDIG v)
|
6488
7244
|
{
|
6489
7245
|
int f = 0;
|
6490
7246
|
|
@@ -6534,7 +7290,7 @@ VpInternalRound(Real *c, size_t ixDigit, BDIGIT vPrev, BDIGIT v)
|
|
6534
7290
|
static int
|
6535
7291
|
VpRdup(Real *m, size_t ind_m)
|
6536
7292
|
{
|
6537
|
-
|
7293
|
+
DECDIG carry;
|
6538
7294
|
|
6539
7295
|
if (!ind_m) ind_m = m->Prec;
|
6540
7296
|
|
@@ -6606,7 +7362,7 @@ Exit:
|
|
6606
7362
|
* y = x ** n
|
6607
7363
|
*/
|
6608
7364
|
VP_EXPORT int
|
6609
|
-
|
7365
|
+
VpPowerByInt(Real *y, Real *x, SIGNED_VALUE n)
|
6610
7366
|
{
|
6611
7367
|
size_t s, ss;
|
6612
7368
|
ssize_t sign;
|
@@ -6693,8 +7449,8 @@ VpPower(Real *y, Real *x, SIGNED_VALUE n)
|
|
6693
7449
|
Exit:
|
6694
7450
|
#ifdef BIGDECIMAL_DEBUG
|
6695
7451
|
if (gfDebug) {
|
6696
|
-
VPrint(stdout, "
|
6697
|
-
VPrint(stdout, "
|
7452
|
+
VPrint(stdout, "VpPowerByInt y=%\n", y);
|
7453
|
+
VPrint(stdout, "VpPowerByInt x=%\n", x);
|
6698
7454
|
printf(" n=%"PRIdVALUE"\n", n);
|
6699
7455
|
}
|
6700
7456
|
#endif /* BIGDECIMAL_DEBUG */
|
@@ -6729,12 +7485,12 @@ VpVarCheck(Real * v)
|
|
6729
7485
|
}
|
6730
7486
|
for (i = 0; i < v->Prec; ++i) {
|
6731
7487
|
if (v->frac[i] >= BASE) {
|
6732
|
-
|
6733
|
-
|
6734
|
-
|
6735
|
-
|
6736
|
-
|
6737
|
-
|
7488
|
+
printf("ERROR(VpVarCheck): Illegal fraction\n");
|
7489
|
+
printf(" Frac[%"PRIuSIZE"]=%"PRIuDECDIG"\n", i, v->frac[i]);
|
7490
|
+
printf(" Prec. =%"PRIuSIZE"\n", v->Prec);
|
7491
|
+
printf(" Exp. =%"PRIdVALUE"\n", v->exponent);
|
7492
|
+
printf(" BASE =%"PRIuDECDIG"\n", BASE);
|
7493
|
+
return 3;
|
6738
7494
|
}
|
6739
7495
|
}
|
6740
7496
|
return 0;
|