bigdecimal 2.0.2 → 3.1.0
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 +1593 -737
- data/ext/bigdecimal/bigdecimal.h +67 -166
- data/ext/bigdecimal/bits.h +141 -0
- data/ext/bigdecimal/extconf.rb +40 -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 (DBL_DIG+1) /* figure of double */
|
81
|
-
#endif
|
80
|
+
#define LOG10_2 0.3010299956639812
|
82
81
|
|
83
82
|
#ifndef RRATIONAL_ZERO_P
|
84
83
|
# define RRATIONAL_ZERO_P(x) (FIXNUM_P(rb_rational_num(x)) && \
|
@@ -103,54 +102,6 @@ static ID id_half;
|
|
103
102
|
# define RB_OBJ_STRING(obj) StringValueCStr(obj)
|
104
103
|
#endif
|
105
104
|
|
106
|
-
#ifndef HAVE_RB_RATIONAL_NUM
|
107
|
-
static inline VALUE
|
108
|
-
rb_rational_num(VALUE rat)
|
109
|
-
{
|
110
|
-
#ifdef HAVE_TYPE_STRUCT_RRATIONAL
|
111
|
-
return RRATIONAL(rat)->num;
|
112
|
-
#else
|
113
|
-
return rb_funcall(rat, rb_intern("numerator"), 0);
|
114
|
-
#endif
|
115
|
-
}
|
116
|
-
#endif
|
117
|
-
|
118
|
-
#ifndef HAVE_RB_RATIONAL_DEN
|
119
|
-
static inline VALUE
|
120
|
-
rb_rational_den(VALUE rat)
|
121
|
-
{
|
122
|
-
#ifdef HAVE_TYPE_STRUCT_RRATIONAL
|
123
|
-
return RRATIONAL(rat)->den;
|
124
|
-
#else
|
125
|
-
return rb_funcall(rat, rb_intern("denominator"), 0);
|
126
|
-
#endif
|
127
|
-
}
|
128
|
-
#endif
|
129
|
-
|
130
|
-
#ifndef HAVE_RB_COMPLEX_REAL
|
131
|
-
static inline VALUE
|
132
|
-
rb_complex_real(VALUE cmp)
|
133
|
-
{
|
134
|
-
#ifdef HAVE_TYPE_STRUCT_RCOMPLEX
|
135
|
-
return RCOMPLEX(cmp)->real;
|
136
|
-
#else
|
137
|
-
return rb_funcall(cmp, rb_intern("real"), 0);
|
138
|
-
#endif
|
139
|
-
}
|
140
|
-
#endif
|
141
|
-
|
142
|
-
#ifndef HAVE_RB_COMPLEX_IMAG
|
143
|
-
static inline VALUE
|
144
|
-
rb_complex_imag(VALUE cmp)
|
145
|
-
{
|
146
|
-
#ifdef HAVE_TYPE_STRUCT_RCOMPLEX
|
147
|
-
return RCOMPLEX(cmp)->imag;
|
148
|
-
#else
|
149
|
-
return rb_funcall(cmp, rb_intern("imag"), 0);
|
150
|
-
#endif
|
151
|
-
}
|
152
|
-
#endif
|
153
|
-
|
154
105
|
#define BIGDECIMAL_POSITIVE_P(bd) ((bd)->sign > 0)
|
155
106
|
#define BIGDECIMAL_NEGATIVE_P(bd) ((bd)->sign < 0)
|
156
107
|
|
@@ -164,7 +115,9 @@ rb_complex_imag(VALUE cmp)
|
|
164
115
|
*/
|
165
116
|
static unsigned short VpGetException(void);
|
166
117
|
static void VpSetException(unsigned short f);
|
167
|
-
static void
|
118
|
+
static void VpCheckException(Real *p, bool always);
|
119
|
+
static VALUE VpCheckGetValue(Real *p);
|
120
|
+
static void VpInternalRound(Real *c, size_t ixDigit, DECDIG vPrev, DECDIG v);
|
168
121
|
static int VpLimitRound(Real *c, size_t ixDigit);
|
169
122
|
static Real *VpCopy(Real *pv, Real const* const x);
|
170
123
|
|
@@ -176,6 +129,12 @@ static int VPrint(FILE *fp,const char *cntl_chr,Real *a);
|
|
176
129
|
* **** BigDecimal part ****
|
177
130
|
*/
|
178
131
|
|
132
|
+
static VALUE BigDecimal_nan(void);
|
133
|
+
static VALUE BigDecimal_positive_infinity(void);
|
134
|
+
static VALUE BigDecimal_negative_infinity(void);
|
135
|
+
static VALUE BigDecimal_positive_zero(void);
|
136
|
+
static VALUE BigDecimal_negative_zero(void);
|
137
|
+
|
179
138
|
static void
|
180
139
|
BigDecimal_delete(void *pv)
|
181
140
|
{
|
@@ -186,14 +145,19 @@ static size_t
|
|
186
145
|
BigDecimal_memsize(const void *ptr)
|
187
146
|
{
|
188
147
|
const Real *pv = ptr;
|
189
|
-
return (sizeof(*pv) + pv->MaxPrec * sizeof(
|
148
|
+
return (sizeof(*pv) + pv->MaxPrec * sizeof(DECDIG));
|
190
149
|
}
|
191
150
|
|
151
|
+
#ifndef HAVE_RB_EXT_RACTOR_SAFE
|
152
|
+
# undef RUBY_TYPED_FROZEN_SHAREABLE
|
153
|
+
# define RUBY_TYPED_FROZEN_SHAREABLE 0
|
154
|
+
#endif
|
155
|
+
|
192
156
|
static const rb_data_type_t BigDecimal_data_type = {
|
193
157
|
"BigDecimal",
|
194
158
|
{ 0, BigDecimal_delete, BigDecimal_memsize, },
|
195
159
|
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
|
196
|
-
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
|
160
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE
|
197
161
|
#endif
|
198
162
|
};
|
199
163
|
|
@@ -203,21 +167,6 @@ is_kind_of_BigDecimal(VALUE const v)
|
|
203
167
|
return rb_typeddata_is_kind_of(v, &BigDecimal_data_type);
|
204
168
|
}
|
205
169
|
|
206
|
-
static VALUE
|
207
|
-
ToValue(Real *p)
|
208
|
-
{
|
209
|
-
if (VpIsNaN(p)) {
|
210
|
-
VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'(Not a Number)", 0);
|
211
|
-
}
|
212
|
-
else if (VpIsPosInf(p)) {
|
213
|
-
VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 0);
|
214
|
-
}
|
215
|
-
else if (VpIsNegInf(p)) {
|
216
|
-
VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 0);
|
217
|
-
}
|
218
|
-
return p->obj;
|
219
|
-
}
|
220
|
-
|
221
170
|
NORETURN(static void cannot_be_coerced_into_BigDecimal(VALUE, VALUE));
|
222
171
|
|
223
172
|
static void
|
@@ -237,95 +186,67 @@ cannot_be_coerced_into_BigDecimal(VALUE exc_class, VALUE v)
|
|
237
186
|
}
|
238
187
|
|
239
188
|
static inline VALUE BigDecimal_div2(VALUE, VALUE, VALUE);
|
189
|
+
static VALUE rb_inum_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception);
|
190
|
+
static VALUE rb_float_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception);
|
191
|
+
static VALUE rb_rational_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception);
|
192
|
+
static VALUE rb_cstr_convert_to_BigDecimal(const char *c_str, size_t digs, int raise_exception);
|
193
|
+
static VALUE rb_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception);
|
240
194
|
|
241
195
|
static Real*
|
242
196
|
GetVpValueWithPrec(VALUE v, long prec, int must)
|
243
197
|
{
|
244
|
-
|
245
|
-
Real *pv;
|
246
|
-
VALUE num, bg;
|
247
|
-
char szD[128];
|
248
|
-
VALUE orig = Qundef;
|
249
|
-
double d;
|
198
|
+
const size_t digs = prec < 0 ? SIZE_MAX : (size_t)prec;
|
250
199
|
|
251
|
-
again:
|
252
200
|
switch(TYPE(v)) {
|
253
201
|
case T_FLOAT:
|
254
|
-
|
255
|
-
|
256
|
-
d = RFLOAT_VALUE(v);
|
257
|
-
if (!isfinite(d)) {
|
258
|
-
pv = VpCreateRbObject(1, NULL);
|
259
|
-
VpDtoV(pv, d);
|
260
|
-
return pv;
|
261
|
-
}
|
262
|
-
if (d != 0.0) {
|
263
|
-
v = rb_funcall(v, id_to_r, 0);
|
264
|
-
goto again;
|
265
|
-
}
|
266
|
-
if (1/d < 0.0) {
|
267
|
-
return VpCreateRbObject(prec, "-0");
|
268
|
-
}
|
269
|
-
return VpCreateRbObject(prec, "0");
|
202
|
+
v = rb_float_convert_to_BigDecimal(v, digs, must);
|
203
|
+
break;
|
270
204
|
|
271
205
|
case T_RATIONAL:
|
272
|
-
|
273
|
-
|
274
|
-
if (orig == Qundef ? (orig = v, 1) : orig != v) {
|
275
|
-
num = rb_rational_num(v);
|
276
|
-
pv = GetVpValueWithPrec(num, -1, must);
|
277
|
-
if (pv == NULL) goto SomeOneMayDoIt;
|
278
|
-
|
279
|
-
v = BigDecimal_div2(ToValue(pv), rb_rational_den(v), LONG2NUM(prec));
|
280
|
-
goto again;
|
281
|
-
}
|
282
|
-
|
283
|
-
v = orig;
|
284
|
-
goto SomeOneMayDoIt;
|
206
|
+
v = rb_rational_convert_to_BigDecimal(v, digs, must);
|
207
|
+
break;
|
285
208
|
|
286
209
|
case T_DATA:
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
else {
|
292
|
-
goto SomeOneMayDoIt;
|
293
|
-
}
|
294
|
-
break;
|
210
|
+
if (!is_kind_of_BigDecimal(v)) {
|
211
|
+
goto SomeOneMayDoIt;
|
212
|
+
}
|
213
|
+
break;
|
295
214
|
|
296
|
-
case T_FIXNUM:
|
297
|
-
|
298
|
-
|
215
|
+
case T_FIXNUM: {
|
216
|
+
char szD[128];
|
217
|
+
sprintf(szD, "%ld", FIX2LONG(v));
|
218
|
+
v = rb_cstr_convert_to_BigDecimal(szD, VpBaseFig() * 2 + 1, must);
|
219
|
+
break;
|
220
|
+
}
|
299
221
|
|
300
222
|
#ifdef ENABLE_NUMERIC_STRING
|
301
|
-
case T_STRING:
|
302
|
-
|
303
|
-
|
304
|
-
|
223
|
+
case T_STRING: {
|
224
|
+
const char *c_str = StringValueCStr(v);
|
225
|
+
v = rb_cstr_convert_to_BigDecimal(c_str, RSTRING_LEN(v) + VpBaseFig() + 1, must);
|
226
|
+
break;
|
227
|
+
}
|
305
228
|
#endif /* ENABLE_NUMERIC_STRING */
|
306
229
|
|
307
|
-
case T_BIGNUM:
|
308
|
-
bg = rb_big2str(v, 10);
|
309
|
-
|
310
|
-
|
311
|
-
|
230
|
+
case T_BIGNUM: {
|
231
|
+
VALUE bg = rb_big2str(v, 10);
|
232
|
+
v = rb_cstr_convert_to_BigDecimal(RSTRING_PTR(bg), RSTRING_LEN(bg) + VpBaseFig() + 1, must);
|
233
|
+
RB_GC_GUARD(bg);
|
234
|
+
break;
|
235
|
+
}
|
236
|
+
|
312
237
|
default:
|
313
238
|
goto SomeOneMayDoIt;
|
314
239
|
}
|
315
240
|
|
241
|
+
Real *vp;
|
242
|
+
TypedData_Get_Struct(v, Real, &BigDecimal_data_type, vp);
|
243
|
+
return vp;
|
244
|
+
|
316
245
|
SomeOneMayDoIt:
|
317
246
|
if (must) {
|
318
247
|
cannot_be_coerced_into_BigDecimal(rb_eTypeError, v);
|
319
248
|
}
|
320
249
|
return NULL; /* NULL means to coerce */
|
321
|
-
|
322
|
-
unable_to_coerce_without_prec:
|
323
|
-
if (must) {
|
324
|
-
rb_raise(rb_eArgError,
|
325
|
-
"%"PRIsVALUE" can't be coerced into BigDecimal without a precision",
|
326
|
-
RB_OBJ_CLASSNAME(v));
|
327
|
-
}
|
328
|
-
return NULL;
|
329
250
|
}
|
330
251
|
|
331
252
|
static Real*
|
@@ -335,11 +256,13 @@ GetVpValue(VALUE v, int must)
|
|
335
256
|
}
|
336
257
|
|
337
258
|
/* call-seq:
|
338
|
-
*
|
259
|
+
* BigDecimal.double_fig -> integer
|
260
|
+
*
|
261
|
+
* Returns the number of digits a Float object is allowed to have;
|
262
|
+
* the result is system-dependent:
|
263
|
+
*
|
264
|
+
* BigDecimal.double_fig # => 16
|
339
265
|
*
|
340
|
-
* The BigDecimal.double_fig class method returns the number of digits a
|
341
|
-
* Float number is allowed to have. The result depends upon the CPU and OS
|
342
|
-
* in use.
|
343
266
|
*/
|
344
267
|
static VALUE
|
345
268
|
BigDecimal_double_fig(VALUE self)
|
@@ -348,15 +271,16 @@ BigDecimal_double_fig(VALUE self)
|
|
348
271
|
}
|
349
272
|
|
350
273
|
/* call-seq:
|
351
|
-
*
|
274
|
+
* precs -> array
|
352
275
|
*
|
353
|
-
* Returns an Array of two Integer values
|
276
|
+
* Returns an Array of two Integer values that represent platform-dependent
|
277
|
+
* internal storage properties.
|
354
278
|
*
|
355
|
-
*
|
356
|
-
*
|
357
|
-
*
|
279
|
+
* This method is deprecated and will be removed in the future.
|
280
|
+
* Instead, use BigDecimal#n_significant_digits for obtaining the number of
|
281
|
+
* significant digits in scientific notation, and BigDecimal#precision for
|
282
|
+
* obtaining the number of digits in decimal notation.
|
358
283
|
*
|
359
|
-
* BigDecimal('5').precs #=> [9, 18]
|
360
284
|
*/
|
361
285
|
|
362
286
|
static VALUE
|
@@ -366,19 +290,251 @@ BigDecimal_prec(VALUE self)
|
|
366
290
|
Real *p;
|
367
291
|
VALUE obj;
|
368
292
|
|
293
|
+
rb_category_warn(RB_WARN_CATEGORY_DEPRECATED,
|
294
|
+
"BigDecimal#precs is deprecated and will be removed in the future; "
|
295
|
+
"use BigDecimal#precision instead.");
|
296
|
+
|
369
297
|
GUARD_OBJ(p, GetVpValue(self, 1));
|
370
298
|
obj = rb_assoc_new(SIZET2NUM(p->Prec*VpBaseFig()),
|
371
299
|
SIZET2NUM(p->MaxPrec*VpBaseFig()));
|
372
300
|
return obj;
|
373
301
|
}
|
374
302
|
|
303
|
+
static void
|
304
|
+
BigDecimal_count_precision_and_scale(VALUE self, ssize_t *out_precision, ssize_t *out_scale)
|
305
|
+
{
|
306
|
+
ENTER(1);
|
307
|
+
|
308
|
+
if (out_precision == NULL && out_scale == NULL)
|
309
|
+
return;
|
310
|
+
|
311
|
+
Real *p;
|
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;
|
331
|
+
|
332
|
+
/*
|
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
|
+
*
|
340
|
+
* When the exponent is negative, the decimal point moves to leftward.
|
341
|
+
* In this case, the precision can be calculated by
|
342
|
+
*
|
343
|
+
* precision = BASE_FIG * (-exponent + n) - ntz,
|
344
|
+
*
|
345
|
+
* and the scale is the same as precision.
|
346
|
+
*
|
347
|
+
* 0 . 0000 0000 | frac[0] ... frac[n-1] |
|
348
|
+
* |<----------| exponent == -2 |
|
349
|
+
* |---------------------------------->| precision
|
350
|
+
* |---------------------------------->| scale
|
351
|
+
*
|
352
|
+
*
|
353
|
+
* Conversely, when the exponent is positive, the decimal point moves to
|
354
|
+
* rightward. In this case, the scale equals to
|
355
|
+
*
|
356
|
+
* BASE_FIG * (n - exponent) - ntz.
|
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
|
366
|
+
*/
|
367
|
+
|
368
|
+
ssize_t ex = p->exponent;
|
369
|
+
|
370
|
+
/* Count the number of decimal digits before frac[1]. */
|
371
|
+
ssize_t n_digits_head = BASE_FIG;
|
372
|
+
if (ex < 0) {
|
373
|
+
n_digits_head += (-ex) * BASE_FIG; /* The number of leading zeros before frac[0]. */
|
374
|
+
ex = 0;
|
375
|
+
}
|
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 */
|
381
|
+
}
|
382
|
+
|
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;
|
400
|
+
}
|
401
|
+
|
402
|
+
if (out_scale) {
|
403
|
+
ssize_t scale = 0;
|
404
|
+
|
405
|
+
if (p->exponent < 0) {
|
406
|
+
scale = n_digits_head + (n - 1) * BASE_FIG - ntz;
|
407
|
+
}
|
408
|
+
else if (n > p->exponent) {
|
409
|
+
scale = (n - p->exponent) * BASE_FIG - ntz;
|
410
|
+
}
|
411
|
+
|
412
|
+
*out_scale = scale;
|
413
|
+
}
|
414
|
+
}
|
415
|
+
|
375
416
|
/*
|
376
|
-
*
|
417
|
+
* call-seq:
|
418
|
+
* precision -> integer
|
419
|
+
*
|
420
|
+
* Returns the number of decimal digits in +self+:
|
377
421
|
*
|
378
|
-
*
|
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);
|
438
|
+
return SSIZET2NUM(precision);
|
439
|
+
}
|
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
|
+
*/
|
499
|
+
static VALUE
|
500
|
+
BigDecimal_n_significant_digits(VALUE self)
|
501
|
+
{
|
502
|
+
ENTER(1);
|
503
|
+
|
504
|
+
Real *p;
|
505
|
+
GUARD_OBJ(p, GetVpValue(self, 1));
|
506
|
+
if (VpIsZero(p) || !VpIsDef(p)) {
|
507
|
+
return INT2FIX(0);
|
508
|
+
}
|
509
|
+
|
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);
|
513
|
+
|
514
|
+
DECDIG x;
|
515
|
+
int nlz = BASE_FIG;
|
516
|
+
for (x = p->frac[0]; x > 0; x /= 10) --nlz;
|
517
|
+
|
518
|
+
int ntz = 0;
|
519
|
+
for (x = p->frac[n-1]; x > 0 && x % 10 == 0; x /= 10) ++ntz;
|
520
|
+
|
521
|
+
ssize_t n_significant_digits = BASE_FIG*n - nlz - ntz;
|
522
|
+
return SSIZET2NUM(n_significant_digits);
|
523
|
+
}
|
524
|
+
|
525
|
+
/*
|
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:
|
533
|
+
*
|
534
|
+
* - Sign.
|
535
|
+
* - Fractional part.
|
536
|
+
* - Exponent.
|
379
537
|
*
|
380
|
-
* Two BigDecimals with equal sign,
|
381
|
-
* fractional part and exponent have the same hash.
|
382
538
|
*/
|
383
539
|
static VALUE
|
384
540
|
BigDecimal_hash(VALUE self)
|
@@ -391,23 +547,23 @@ BigDecimal_hash(VALUE self)
|
|
391
547
|
hash = (st_index_t)p->sign;
|
392
548
|
/* hash!=2: the case for 0(1),NaN(0) or +-Infinity(3) is sign itself */
|
393
549
|
if(hash == 2 || hash == (st_index_t)-2) {
|
394
|
-
|
395
|
-
|
550
|
+
hash ^= rb_memhash(p->frac, sizeof(DECDIG)*p->Prec);
|
551
|
+
hash += p->exponent;
|
396
552
|
}
|
397
553
|
return ST2FIX(hash);
|
398
554
|
}
|
399
555
|
|
400
556
|
/*
|
401
|
-
*
|
557
|
+
* call-seq:
|
558
|
+
* _dump -> string
|
402
559
|
*
|
403
|
-
*
|
560
|
+
* Returns a string representing the marshalling of +self+.
|
561
|
+
* See module Marshal.
|
404
562
|
*
|
405
|
-
*
|
406
|
-
*
|
407
|
-
*
|
408
|
-
* #=> Infinity
|
563
|
+
* inf = BigDecimal('Infinity') # => Infinity
|
564
|
+
* dumped = inf._dump # => "9:Infinity"
|
565
|
+
* BigDecimal._load(dumped) # => Infinity
|
409
566
|
*
|
410
|
-
* See the Marshal module.
|
411
567
|
*/
|
412
568
|
static VALUE
|
413
569
|
BigDecimal_dump(int argc, VALUE *argv, VALUE self)
|
@@ -449,12 +605,12 @@ BigDecimal_load(VALUE self, VALUE str)
|
|
449
605
|
m = m*10 + (unsigned long)(ch-'0');
|
450
606
|
}
|
451
607
|
if (m > VpBaseFig()) m -= VpBaseFig();
|
452
|
-
GUARD_OBJ(pv, VpNewRbClass(m, (char *)pch, self));
|
608
|
+
GUARD_OBJ(pv, VpNewRbClass(m, (char *)pch, self, true, true));
|
453
609
|
m /= VpBaseFig();
|
454
610
|
if (m && pv->MaxPrec > m) {
|
455
611
|
pv->MaxPrec = m+1;
|
456
612
|
}
|
457
|
-
return
|
613
|
+
return VpCheckGetValue(pv);
|
458
614
|
}
|
459
615
|
|
460
616
|
static unsigned short
|
@@ -541,42 +697,166 @@ check_rounding_mode(VALUE const v)
|
|
541
697
|
return sw;
|
542
698
|
}
|
543
699
|
|
544
|
-
/*
|
545
|
-
*
|
546
|
-
*
|
547
|
-
*
|
548
|
-
*
|
549
|
-
*
|
550
|
-
*
|
551
|
-
*
|
552
|
-
*
|
553
|
-
* BigDecimal::
|
554
|
-
* BigDecimal::
|
555
|
-
* BigDecimal::
|
556
|
-
* BigDecimal::
|
557
|
-
* BigDecimal::
|
558
|
-
*
|
559
|
-
*
|
560
|
-
*
|
561
|
-
*
|
562
|
-
*
|
563
|
-
*
|
564
|
-
*
|
565
|
-
*
|
566
|
-
*
|
567
|
-
*
|
568
|
-
*
|
569
|
-
*
|
570
|
-
*
|
571
|
-
*
|
572
|
-
*
|
573
|
-
*
|
574
|
-
*
|
575
|
-
*
|
576
|
-
*
|
577
|
-
*
|
578
|
-
*
|
579
|
-
*
|
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:+.
|
580
860
|
*
|
581
861
|
*/
|
582
862
|
static VALUE
|
@@ -664,25 +944,54 @@ GetPrecisionInt(VALUE v)
|
|
664
944
|
return n;
|
665
945
|
}
|
666
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
|
+
|
667
965
|
VP_EXPORT Real *
|
668
|
-
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)
|
669
967
|
{
|
670
968
|
VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
|
671
|
-
Real *pv = VpAlloc(mx, str,
|
672
|
-
|
673
|
-
|
674
|
-
|
969
|
+
Real *pv = VpAlloc(mx, str, strict_p, raise_exception);
|
970
|
+
if (!pv)
|
971
|
+
return NULL;
|
972
|
+
BigDecimal_wrap_struct(obj, pv);
|
675
973
|
return pv;
|
676
974
|
}
|
677
975
|
|
678
976
|
VP_EXPORT Real *
|
679
|
-
VpCreateRbObject(size_t mx, const char *str)
|
977
|
+
VpCreateRbObject(size_t mx, const char *str, bool raise_exception)
|
680
978
|
{
|
681
|
-
return VpNewRbClass(mx, str, rb_cBigDecimal);
|
979
|
+
return VpNewRbClass(mx, str, rb_cBigDecimal, true, raise_exception);
|
682
980
|
}
|
683
981
|
|
684
|
-
#define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(
|
685
|
-
|
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
|
+
}
|
686
995
|
|
687
996
|
static Real *
|
688
997
|
VpCopy(Real *pv, Real const* const x)
|
@@ -695,7 +1004,7 @@ VpCopy(Real *pv, Real const* const x)
|
|
695
1004
|
pv->exponent = x->exponent;
|
696
1005
|
pv->sign = x->sign;
|
697
1006
|
pv->flag = x->flag;
|
698
|
-
MEMCPY(pv->frac, x->frac,
|
1007
|
+
MEMCPY(pv->frac, x->frac, DECDIG, pv->MaxPrec);
|
699
1008
|
|
700
1009
|
return pv;
|
701
1010
|
}
|
@@ -734,15 +1043,7 @@ BigDecimal_IsFinite(VALUE self)
|
|
734
1043
|
static void
|
735
1044
|
BigDecimal_check_num(Real *p)
|
736
1045
|
{
|
737
|
-
|
738
|
-
VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'(Not a Number)", 1);
|
739
|
-
}
|
740
|
-
else if (VpIsPosInf(p)) {
|
741
|
-
VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 1);
|
742
|
-
}
|
743
|
-
else if (VpIsNegInf(p)) {
|
744
|
-
VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 1);
|
745
|
-
}
|
1046
|
+
VpCheckException(p, true);
|
746
1047
|
}
|
747
1048
|
|
748
1049
|
static VALUE BigDecimal_split(VALUE self);
|
@@ -765,7 +1066,7 @@ BigDecimal_to_i(VALUE self)
|
|
765
1066
|
if (e <= 0) return INT2FIX(0);
|
766
1067
|
nf = VpBaseFig();
|
767
1068
|
if (e <= nf) {
|
768
|
-
return LONG2NUM((long)(VpGetSign(p) * (
|
1069
|
+
return LONG2NUM((long)(VpGetSign(p) * (DECDIG_DBL_SIGNED)p->frac[0]));
|
769
1070
|
}
|
770
1071
|
else {
|
771
1072
|
VALUE a = BigDecimal_split(self);
|
@@ -899,8 +1200,8 @@ BigDecimal_coerce(VALUE self, VALUE other)
|
|
899
1200
|
Real *b;
|
900
1201
|
|
901
1202
|
if (RB_TYPE_P(other, T_FLOAT)) {
|
902
|
-
GUARD_OBJ(b, GetVpValueWithPrec(other,
|
903
|
-
|
1203
|
+
GUARD_OBJ(b, GetVpValueWithPrec(other, 0, 1));
|
1204
|
+
obj = rb_assoc_new(VpCheckGetValue(b), self);
|
904
1205
|
}
|
905
1206
|
else {
|
906
1207
|
if (RB_TYPE_P(other, T_RATIONAL)) {
|
@@ -917,12 +1218,14 @@ BigDecimal_coerce(VALUE self, VALUE other)
|
|
917
1218
|
}
|
918
1219
|
|
919
1220
|
/*
|
920
|
-
*
|
921
|
-
* +big_decimal
|
1221
|
+
* call-seq:
|
1222
|
+
* +big_decimal -> self
|
922
1223
|
*
|
923
|
-
*
|
1224
|
+
* Returns +self+:
|
1225
|
+
*
|
1226
|
+
* +BigDecimal(5) # => 0.5e1
|
1227
|
+
* +BigDecimal(-5) # => -0.5e1
|
924
1228
|
*
|
925
|
-
* +BigDecimal('5') #=> 0.5e1
|
926
1229
|
*/
|
927
1230
|
|
928
1231
|
static VALUE
|
@@ -932,22 +1235,21 @@ BigDecimal_uplus(VALUE self)
|
|
932
1235
|
}
|
933
1236
|
|
934
1237
|
/*
|
935
|
-
*
|
936
|
-
*
|
1238
|
+
* call-seq:
|
1239
|
+
* self + value -> bigdecimal
|
937
1240
|
*
|
938
|
-
*
|
939
|
-
* add(value, digits)
|
1241
|
+
* Returns the \BigDecimal sum of +self+ and +value+:
|
940
1242
|
*
|
941
|
-
*
|
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)
|
942
1248
|
*
|
943
|
-
*
|
944
|
-
* c = a.add(b,n)
|
945
|
-
* c = a + b
|
1249
|
+
* See the {Note About Precision}[BigDecimal.html#class-BigDecimal-label-A+Note+About+Precision].
|
946
1250
|
*
|
947
|
-
* digits:: If specified and less than the number of significant digits of the
|
948
|
-
* result, the result is rounded to that number of digits, according
|
949
|
-
* to BigDecimal.mode.
|
950
1251
|
*/
|
1252
|
+
|
951
1253
|
static VALUE
|
952
1254
|
BigDecimal_add(VALUE self, VALUE r)
|
953
1255
|
{
|
@@ -957,7 +1259,7 @@ BigDecimal_add(VALUE self, VALUE r)
|
|
957
1259
|
|
958
1260
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
959
1261
|
if (RB_TYPE_P(r, T_FLOAT)) {
|
960
|
-
b = GetVpValueWithPrec(r,
|
1262
|
+
b = GetVpValueWithPrec(r, 0, 1);
|
961
1263
|
}
|
962
1264
|
else if (RB_TYPE_P(r, T_RATIONAL)) {
|
963
1265
|
b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
|
@@ -974,11 +1276,11 @@ BigDecimal_add(VALUE self, VALUE r)
|
|
974
1276
|
|
975
1277
|
mx = GetAddSubPrec(a, b);
|
976
1278
|
if (mx == (size_t)-1L) {
|
977
|
-
|
1279
|
+
GUARD_OBJ(c, VpCreateRbObject(VpBaseFig() + 1, "0", true));
|
978
1280
|
VpAddSub(c, a, b, 1);
|
979
1281
|
}
|
980
1282
|
else {
|
981
|
-
|
1283
|
+
GUARD_OBJ(c, VpCreateRbObject(mx * (VpBaseFig() + 1), "0", true));
|
982
1284
|
if(!mx) {
|
983
1285
|
VpSetInf(c, VpGetSign(a));
|
984
1286
|
}
|
@@ -986,24 +1288,21 @@ BigDecimal_add(VALUE self, VALUE r)
|
|
986
1288
|
VpAddSub(c, a, b, 1);
|
987
1289
|
}
|
988
1290
|
}
|
989
|
-
return
|
1291
|
+
return VpCheckGetValue(c);
|
990
1292
|
}
|
991
1293
|
|
992
|
-
/*
|
993
|
-
*
|
1294
|
+
/* call-seq:
|
1295
|
+
* self - value -> bigdecimal
|
994
1296
|
*
|
995
|
-
*
|
1297
|
+
* Returns the \BigDecimal difference of +self+ and +value+:
|
996
1298
|
*
|
997
|
-
*
|
998
|
-
*
|
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)
|
999
1304
|
*
|
1000
|
-
*
|
1001
|
-
*
|
1002
|
-
* If +b+ is a Float, the precision of the result is Float::DIG+1.
|
1003
|
-
*
|
1004
|
-
* If +b+ is a BigDecimal, the precision of the result is +b+'s precision of
|
1005
|
-
* internal representation from platform. So, it's return value is platform
|
1006
|
-
* dependent.
|
1305
|
+
* See the {Note About Precision}[BigDecimal.html#class-BigDecimal-label-A+Note+About+Precision].
|
1007
1306
|
*
|
1008
1307
|
*/
|
1009
1308
|
static VALUE
|
@@ -1015,7 +1314,7 @@ BigDecimal_sub(VALUE self, VALUE r)
|
|
1015
1314
|
|
1016
1315
|
GUARD_OBJ(a, GetVpValue(self,1));
|
1017
1316
|
if (RB_TYPE_P(r, T_FLOAT)) {
|
1018
|
-
b = GetVpValueWithPrec(r,
|
1317
|
+
b = GetVpValueWithPrec(r, 0, 1);
|
1019
1318
|
}
|
1020
1319
|
else if (RB_TYPE_P(r, T_RATIONAL)) {
|
1021
1320
|
b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
|
@@ -1032,11 +1331,11 @@ BigDecimal_sub(VALUE self, VALUE r)
|
|
1032
1331
|
|
1033
1332
|
mx = GetAddSubPrec(a,b);
|
1034
1333
|
if (mx == (size_t)-1L) {
|
1035
|
-
|
1334
|
+
GUARD_OBJ(c, VpCreateRbObject(VpBaseFig() + 1, "0", true));
|
1036
1335
|
VpAddSub(c, a, b, -1);
|
1037
1336
|
}
|
1038
1337
|
else {
|
1039
|
-
|
1338
|
+
GUARD_OBJ(c,VpCreateRbObject(mx *(VpBaseFig() + 1), "0", true));
|
1040
1339
|
if (!mx) {
|
1041
1340
|
VpSetInf(c,VpGetSign(a));
|
1042
1341
|
}
|
@@ -1044,7 +1343,7 @@ BigDecimal_sub(VALUE self, VALUE r)
|
|
1044
1343
|
VpAddSub(c, a, b, -1);
|
1045
1344
|
}
|
1046
1345
|
}
|
1047
|
-
return
|
1346
|
+
return VpCheckGetValue(c);
|
1048
1347
|
}
|
1049
1348
|
|
1050
1349
|
static VALUE
|
@@ -1065,7 +1364,7 @@ BigDecimalCmp(VALUE self, VALUE r,char op)
|
|
1065
1364
|
break;
|
1066
1365
|
|
1067
1366
|
case T_FLOAT:
|
1068
|
-
GUARD_OBJ(b, GetVpValueWithPrec(r,
|
1367
|
+
GUARD_OBJ(b, GetVpValueWithPrec(r, 0, 0));
|
1069
1368
|
break;
|
1070
1369
|
|
1071
1370
|
case T_RATIONAL:
|
@@ -1182,12 +1481,19 @@ BigDecimal_eq(VALUE self, VALUE r)
|
|
1182
1481
|
return BigDecimalCmp(self, r, '=');
|
1183
1482
|
}
|
1184
1483
|
|
1185
|
-
/*
|
1186
|
-
*
|
1484
|
+
/* call-seq:
|
1485
|
+
* self < other -> true or false
|
1486
|
+
*
|
1487
|
+
* Returns +true+ if +self+ is less than +other+, +false+ otherwise:
|
1187
1488
|
*
|
1188
|
-
*
|
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
|
1494
|
+
*
|
1495
|
+
* Raises an exception if the comparison cannot be made.
|
1189
1496
|
*
|
1190
|
-
* Values may be coerced to perform the comparison (see ==, BigDecimal#coerce).
|
1191
1497
|
*/
|
1192
1498
|
static VALUE
|
1193
1499
|
BigDecimal_lt(VALUE self, VALUE r)
|
@@ -1195,12 +1501,20 @@ BigDecimal_lt(VALUE self, VALUE r)
|
|
1195
1501
|
return BigDecimalCmp(self, r, '<');
|
1196
1502
|
}
|
1197
1503
|
|
1198
|
-
/*
|
1199
|
-
*
|
1504
|
+
/* call-seq:
|
1505
|
+
* self <= other -> true or false
|
1506
|
+
*
|
1507
|
+
* Returns +true+ if +self+ is less or equal to than +other+, +false+ otherwise:
|
1200
1508
|
*
|
1201
|
-
*
|
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.
|
1202
1517
|
*
|
1203
|
-
* Values may be coerced to perform the comparison (see ==, BigDecimal#coerce).
|
1204
1518
|
*/
|
1205
1519
|
static VALUE
|
1206
1520
|
BigDecimal_le(VALUE self, VALUE r)
|
@@ -1208,12 +1522,19 @@ BigDecimal_le(VALUE self, VALUE r)
|
|
1208
1522
|
return BigDecimalCmp(self, r, 'L');
|
1209
1523
|
}
|
1210
1524
|
|
1211
|
-
/*
|
1212
|
-
*
|
1525
|
+
/* call-seq:
|
1526
|
+
* self > other -> true or false
|
1527
|
+
*
|
1528
|
+
* Returns +true+ if +self+ is greater than +other+, +false+ otherwise:
|
1529
|
+
*
|
1530
|
+
* b = BigDecimal('1.5')
|
1531
|
+
* b > 1 # => true
|
1532
|
+
* b > 1.0 # => true
|
1533
|
+
* b > Rational(1, 1) # => true
|
1534
|
+
* b > 2 # => false
|
1213
1535
|
*
|
1214
|
-
*
|
1536
|
+
* Raises an exception if the comparison cannot be made.
|
1215
1537
|
*
|
1216
|
-
* Values may be coerced to perform the comparison (see ==, BigDecimal#coerce).
|
1217
1538
|
*/
|
1218
1539
|
static VALUE
|
1219
1540
|
BigDecimal_gt(VALUE self, VALUE r)
|
@@ -1221,12 +1542,20 @@ BigDecimal_gt(VALUE self, VALUE r)
|
|
1221
1542
|
return BigDecimalCmp(self, r, '>');
|
1222
1543
|
}
|
1223
1544
|
|
1224
|
-
/*
|
1225
|
-
*
|
1545
|
+
/* call-seq:
|
1546
|
+
* self >= other -> true or false
|
1547
|
+
*
|
1548
|
+
* Returns +true+ if +self+ is greater than or equal to +other+, +false+ otherwise:
|
1549
|
+
*
|
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
|
1226
1556
|
*
|
1227
|
-
*
|
1557
|
+
* Raises an exception if the comparison cannot be made.
|
1228
1558
|
*
|
1229
|
-
* Values may be coerced to perform the comparison (see ==, BigDecimal#coerce)
|
1230
1559
|
*/
|
1231
1560
|
static VALUE
|
1232
1561
|
BigDecimal_ge(VALUE self, VALUE r)
|
@@ -1236,11 +1565,14 @@ BigDecimal_ge(VALUE self, VALUE r)
|
|
1236
1565
|
|
1237
1566
|
/*
|
1238
1567
|
* call-seq:
|
1239
|
-
*
|
1568
|
+
* -self -> bigdecimal
|
1240
1569
|
*
|
1241
|
-
*
|
1570
|
+
* Returns the \BigDecimal negation of self:
|
1571
|
+
*
|
1572
|
+
* b0 = BigDecimal('1.5')
|
1573
|
+
* b1 = -b0 # => -0.15e1
|
1574
|
+
* b2 = -b1 # => 0.15e1
|
1242
1575
|
*
|
1243
|
-
* -BigDecimal('5') #=> -0.5e1
|
1244
1576
|
*/
|
1245
1577
|
|
1246
1578
|
static VALUE
|
@@ -1249,26 +1581,11 @@ BigDecimal_neg(VALUE self)
|
|
1249
1581
|
ENTER(5);
|
1250
1582
|
Real *c, *a;
|
1251
1583
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1252
|
-
GUARD_OBJ(c, VpCreateRbObject(a->Prec *(VpBaseFig() + 1), "0"));
|
1584
|
+
GUARD_OBJ(c, VpCreateRbObject(a->Prec *(VpBaseFig() + 1), "0", true));
|
1253
1585
|
VpAsgn(c, a, -1);
|
1254
|
-
return
|
1586
|
+
return VpCheckGetValue(c);
|
1255
1587
|
}
|
1256
1588
|
|
1257
|
-
/*
|
1258
|
-
* Document-method: BigDecimal#mult
|
1259
|
-
*
|
1260
|
-
* call-seq: mult(value, digits)
|
1261
|
-
*
|
1262
|
-
* Multiply by the specified value.
|
1263
|
-
*
|
1264
|
-
* e.g.
|
1265
|
-
* c = a.mult(b,n)
|
1266
|
-
* c = a * b
|
1267
|
-
*
|
1268
|
-
* digits:: If specified and less than the number of significant digits of the
|
1269
|
-
* result, the result is rounded to that number of digits, according
|
1270
|
-
* to BigDecimal.mode.
|
1271
|
-
*/
|
1272
1589
|
static VALUE
|
1273
1590
|
BigDecimal_mult(VALUE self, VALUE r)
|
1274
1591
|
{
|
@@ -1278,7 +1595,7 @@ BigDecimal_mult(VALUE self, VALUE r)
|
|
1278
1595
|
|
1279
1596
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1280
1597
|
if (RB_TYPE_P(r, T_FLOAT)) {
|
1281
|
-
|
1598
|
+
b = GetVpValueWithPrec(r, 0, 1);
|
1282
1599
|
}
|
1283
1600
|
else if (RB_TYPE_P(r, T_RATIONAL)) {
|
1284
1601
|
b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
|
@@ -1291,71 +1608,122 @@ BigDecimal_mult(VALUE self, VALUE r)
|
|
1291
1608
|
SAVE(b);
|
1292
1609
|
|
1293
1610
|
mx = a->Prec + b->Prec;
|
1294
|
-
GUARD_OBJ(c, VpCreateRbObject(mx *(VpBaseFig() + 1), "0"));
|
1611
|
+
GUARD_OBJ(c, VpCreateRbObject(mx *(VpBaseFig() + 1), "0", true));
|
1295
1612
|
VpMult(c, a, b);
|
1296
|
-
return
|
1613
|
+
return VpCheckGetValue(c);
|
1297
1614
|
}
|
1298
1615
|
|
1299
1616
|
static VALUE
|
1300
|
-
BigDecimal_divide(Real **c, Real **res, Real **div
|
1617
|
+
BigDecimal_divide(VALUE self, VALUE r, Real **c, Real **res, Real **div)
|
1301
1618
|
/* For c = self.div(r): with round operation */
|
1302
1619
|
{
|
1303
1620
|
ENTER(5);
|
1304
1621
|
Real *a, *b;
|
1305
1622
|
size_t mx;
|
1306
1623
|
|
1307
|
-
|
1308
|
-
|
1309
|
-
|
1624
|
+
TypedData_Get_Struct(self, Real, &BigDecimal_data_type, a);
|
1625
|
+
SAVE(a);
|
1626
|
+
|
1627
|
+
VALUE rr = r;
|
1628
|
+
if (is_kind_of_BigDecimal(rr)) {
|
1629
|
+
/* do nothing */
|
1630
|
+
}
|
1631
|
+
else if (RB_INTEGER_TYPE_P(r)) {
|
1632
|
+
rr = rb_inum_convert_to_BigDecimal(r, 0, true);
|
1633
|
+
}
|
1634
|
+
else if (RB_TYPE_P(r, T_FLOAT)) {
|
1635
|
+
rr = rb_float_convert_to_BigDecimal(r, 0, true);
|
1310
1636
|
}
|
1311
1637
|
else if (RB_TYPE_P(r, T_RATIONAL)) {
|
1312
|
-
|
1313
|
-
}
|
1314
|
-
else {
|
1315
|
-
b = GetVpValue(r, 0);
|
1638
|
+
rr = rb_rational_convert_to_BigDecimal(r, a->Prec*BASE_FIG, true);
|
1316
1639
|
}
|
1317
1640
|
|
1318
|
-
if (!
|
1641
|
+
if (!is_kind_of_BigDecimal(rr)) {
|
1642
|
+
return DoSomeOne(self, r, '/');
|
1643
|
+
}
|
1644
|
+
|
1645
|
+
TypedData_Get_Struct(rr, Real, &BigDecimal_data_type, b);
|
1319
1646
|
SAVE(b);
|
1320
1647
|
|
1321
1648
|
*div = b;
|
1322
|
-
mx = a->Prec
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
GUARD_OBJ((*
|
1328
|
-
GUARD_OBJ((*res), VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0"));
|
1649
|
+
mx = (a->Prec > b->Prec) ? a->Prec : b->Prec;
|
1650
|
+
mx *= BASE_FIG;
|
1651
|
+
if (2*BIGDECIMAL_DOUBLE_FIGURES > mx)
|
1652
|
+
mx = 2*BIGDECIMAL_DOUBLE_FIGURES;
|
1653
|
+
GUARD_OBJ((*c), VpCreateRbObject(mx + 2*BASE_FIG, "#0", true));
|
1654
|
+
GUARD_OBJ((*res), VpCreateRbObject(mx*2 + 2*BASE_FIG, "#0", true));
|
1329
1655
|
VpDivd(*c, *res, a, b);
|
1330
1656
|
return Qnil;
|
1331
1657
|
}
|
1332
1658
|
|
1333
1659
|
/* call-seq:
|
1334
|
-
* a / b
|
1335
|
-
* quo(value) -> bigdecimal
|
1660
|
+
* a / b -> bigdecimal
|
1336
1661
|
*
|
1337
1662
|
* Divide by the specified value.
|
1338
1663
|
*
|
1664
|
+
* The result precision will be the precision of the larger operand,
|
1665
|
+
* but its minimum is 2*Float::DIG.
|
1666
|
+
*
|
1339
1667
|
* See BigDecimal#div.
|
1668
|
+
* See BigDecimal#quo.
|
1340
1669
|
*/
|
1341
1670
|
static VALUE
|
1342
1671
|
BigDecimal_div(VALUE self, VALUE r)
|
1343
1672
|
/* For c = self/r: with round operation */
|
1344
1673
|
{
|
1345
|
-
ENTER(5);
|
1346
|
-
Real *c=NULL, *res=NULL, *div = NULL;
|
1347
|
-
r = BigDecimal_divide(&c, &res, &div
|
1348
|
-
if (!NIL_P(r)) return r; /* coerced by other */
|
1349
|
-
SAVE(c); SAVE(res); SAVE(div);
|
1350
|
-
/* a/b = c + r/b */
|
1351
|
-
/* c xxxxx
|
1352
|
-
r 00000yyyyy ==> (y/b)*BASE >= HALF_BASE
|
1353
|
-
*/
|
1354
|
-
/* Round */
|
1355
|
-
if (VpHasVal(div)) { /* frac[0] must be zero for NaN,INF,Zero */
|
1356
|
-
|
1674
|
+
ENTER(5);
|
1675
|
+
Real *c=NULL, *res=NULL, *div = NULL;
|
1676
|
+
r = BigDecimal_divide(self, r, &c, &res, &div);
|
1677
|
+
if (!NIL_P(r)) return r; /* coerced by other */
|
1678
|
+
SAVE(c); SAVE(res); SAVE(div);
|
1679
|
+
/* a/b = c + r/b */
|
1680
|
+
/* c xxxxx
|
1681
|
+
r 00000yyyyy ==> (y/b)*BASE >= HALF_BASE
|
1682
|
+
*/
|
1683
|
+
/* Round */
|
1684
|
+
if (VpHasVal(div)) { /* frac[0] must be zero for NaN,INF,Zero */
|
1685
|
+
VpInternalRound(c, 0, c->frac[c->Prec-1], (DECDIG)(VpBaseVal() * (DECDIG_DBL)res->frac[0] / div->frac[0]));
|
1686
|
+
}
|
1687
|
+
return VpCheckGetValue(c);
|
1688
|
+
}
|
1689
|
+
|
1690
|
+
static VALUE BigDecimal_round(int argc, VALUE *argv, VALUE self);
|
1691
|
+
|
1692
|
+
/* call-seq:
|
1693
|
+
* quo(value) -> bigdecimal
|
1694
|
+
* quo(value, digits) -> bigdecimal
|
1695
|
+
*
|
1696
|
+
* Divide by the specified value.
|
1697
|
+
*
|
1698
|
+
* digits:: If specified and less than the number of significant digits of
|
1699
|
+
* the result, the result is rounded to the given number of digits,
|
1700
|
+
* according to the rounding mode indicated by BigDecimal.mode.
|
1701
|
+
*
|
1702
|
+
* If digits is 0 or omitted, the result is the same as for the
|
1703
|
+
* / operator.
|
1704
|
+
*
|
1705
|
+
* See BigDecimal#/.
|
1706
|
+
* See BigDecimal#div.
|
1707
|
+
*/
|
1708
|
+
static VALUE
|
1709
|
+
BigDecimal_quo(int argc, VALUE *argv, VALUE self)
|
1710
|
+
{
|
1711
|
+
VALUE value, digits, result;
|
1712
|
+
SIGNED_VALUE n = -1;
|
1713
|
+
|
1714
|
+
argc = rb_scan_args(argc, argv, "11", &value, &digits);
|
1715
|
+
if (argc > 1) {
|
1716
|
+
n = GetPrecisionInt(digits);
|
1717
|
+
}
|
1718
|
+
|
1719
|
+
if (n > 0) {
|
1720
|
+
result = BigDecimal_div2(self, value, digits);
|
1721
|
+
}
|
1722
|
+
else {
|
1723
|
+
result = BigDecimal_div(self, value);
|
1357
1724
|
}
|
1358
|
-
|
1725
|
+
|
1726
|
+
return result;
|
1359
1727
|
}
|
1360
1728
|
|
1361
1729
|
/*
|
@@ -1370,75 +1738,99 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
|
|
1370
1738
|
Real *a, *b;
|
1371
1739
|
size_t mx;
|
1372
1740
|
|
1373
|
-
|
1374
|
-
|
1375
|
-
|
1741
|
+
TypedData_Get_Struct(self, Real, &BigDecimal_data_type, a);
|
1742
|
+
SAVE(a);
|
1743
|
+
|
1744
|
+
VALUE rr = r;
|
1745
|
+
if (is_kind_of_BigDecimal(rr)) {
|
1746
|
+
/* do nothing */
|
1747
|
+
}
|
1748
|
+
else if (RB_INTEGER_TYPE_P(r)) {
|
1749
|
+
rr = rb_inum_convert_to_BigDecimal(r, 0, true);
|
1750
|
+
}
|
1751
|
+
else if (RB_TYPE_P(r, T_FLOAT)) {
|
1752
|
+
rr = rb_float_convert_to_BigDecimal(r, 0, true);
|
1376
1753
|
}
|
1377
1754
|
else if (RB_TYPE_P(r, T_RATIONAL)) {
|
1378
|
-
|
1755
|
+
rr = rb_rational_convert_to_BigDecimal(r, a->Prec*BASE_FIG, true);
|
1379
1756
|
}
|
1380
|
-
|
1381
|
-
|
1757
|
+
|
1758
|
+
if (!is_kind_of_BigDecimal(rr)) {
|
1759
|
+
return Qfalse;
|
1382
1760
|
}
|
1383
1761
|
|
1384
|
-
|
1762
|
+
TypedData_Get_Struct(rr, Real, &BigDecimal_data_type, b);
|
1385
1763
|
SAVE(b);
|
1386
1764
|
|
1387
1765
|
if (VpIsNaN(a) || VpIsNaN(b)) goto NaN;
|
1388
1766
|
if (VpIsInf(a) && VpIsInf(b)) goto NaN;
|
1389
1767
|
if (VpIsZero(b)) {
|
1390
|
-
|
1768
|
+
rb_raise(rb_eZeroDivError, "divided by 0");
|
1391
1769
|
}
|
1392
1770
|
if (VpIsInf(a)) {
|
1393
|
-
|
1394
|
-
|
1395
|
-
|
1396
|
-
|
1397
|
-
|
1398
|
-
|
1771
|
+
if (VpGetSign(a) == VpGetSign(b)) {
|
1772
|
+
VALUE inf = BigDecimal_positive_infinity();
|
1773
|
+
TypedData_Get_Struct(inf, Real, &BigDecimal_data_type, *div);
|
1774
|
+
}
|
1775
|
+
else {
|
1776
|
+
VALUE inf = BigDecimal_negative_infinity();
|
1777
|
+
TypedData_Get_Struct(inf, Real, &BigDecimal_data_type, *div);
|
1778
|
+
}
|
1779
|
+
VALUE nan = BigDecimal_nan();
|
1780
|
+
TypedData_Get_Struct(nan, Real, &BigDecimal_data_type, *mod);
|
1781
|
+
return Qtrue;
|
1399
1782
|
}
|
1400
1783
|
if (VpIsInf(b)) {
|
1401
|
-
|
1402
|
-
|
1403
|
-
|
1404
|
-
|
1784
|
+
VALUE zero = BigDecimal_positive_zero();
|
1785
|
+
TypedData_Get_Struct(zero, Real, &BigDecimal_data_type, *div);
|
1786
|
+
*mod = a;
|
1787
|
+
return Qtrue;
|
1405
1788
|
}
|
1406
1789
|
if (VpIsZero(a)) {
|
1407
|
-
|
1408
|
-
|
1409
|
-
|
1410
|
-
|
1411
|
-
|
1412
|
-
|
1413
|
-
|
1414
|
-
mx
|
1415
|
-
if (
|
1416
|
-
|
1417
|
-
|
1418
|
-
GUARD_OBJ(
|
1790
|
+
VALUE zero = BigDecimal_positive_zero();
|
1791
|
+
TypedData_Get_Struct(zero, Real, &BigDecimal_data_type, *div);
|
1792
|
+
TypedData_Get_Struct(zero, Real, &BigDecimal_data_type, *mod);
|
1793
|
+
return Qtrue;
|
1794
|
+
}
|
1795
|
+
|
1796
|
+
mx = (a->Prec > b->Prec) ? a->Prec : b->Prec;
|
1797
|
+
mx *= BASE_FIG;
|
1798
|
+
if (2*BIGDECIMAL_DOUBLE_FIGURES > mx)
|
1799
|
+
mx = 2*BIGDECIMAL_DOUBLE_FIGURES;
|
1800
|
+
|
1801
|
+
GUARD_OBJ(c, VpCreateRbObject(mx + 2*BASE_FIG, "0", true));
|
1802
|
+
GUARD_OBJ(res, VpCreateRbObject(mx*2 + 2*BASE_FIG, "#0", true));
|
1419
1803
|
VpDivd(c, res, a, b);
|
1420
|
-
|
1421
|
-
|
1804
|
+
|
1805
|
+
mx = c->Prec * BASE_FIG;
|
1806
|
+
GUARD_OBJ(d, VpCreateRbObject(mx, "0", true));
|
1422
1807
|
VpActiveRound(d, c, VP_ROUND_DOWN, 0);
|
1808
|
+
|
1423
1809
|
VpMult(res, d, b);
|
1424
1810
|
VpAddSub(c, a, res, -1);
|
1811
|
+
|
1425
1812
|
if (!VpIsZero(c) && (VpGetSign(a) * VpGetSign(b) < 0)) {
|
1426
|
-
|
1427
|
-
|
1428
|
-
|
1429
|
-
|
1430
|
-
|
1431
|
-
|
1432
|
-
|
1433
|
-
|
1813
|
+
/* result adjustment for negative case */
|
1814
|
+
res = VpReallocReal(res, d->MaxPrec);
|
1815
|
+
res->MaxPrec = d->MaxPrec;
|
1816
|
+
VpAddSub(res, d, VpOne(), -1);
|
1817
|
+
GUARD_OBJ(d, VpCreateRbObject(GetAddSubPrec(c, b) * 2*BASE_FIG, "0", true));
|
1818
|
+
VpAddSub(d, c, b, 1);
|
1819
|
+
*div = res;
|
1820
|
+
*mod = d;
|
1821
|
+
}
|
1822
|
+
else {
|
1823
|
+
*div = d;
|
1824
|
+
*mod = c;
|
1434
1825
|
}
|
1435
1826
|
return Qtrue;
|
1436
1827
|
|
1437
|
-
NaN:
|
1438
|
-
|
1439
|
-
|
1440
|
-
|
1441
|
-
|
1828
|
+
NaN:
|
1829
|
+
{
|
1830
|
+
VALUE nan = BigDecimal_nan();
|
1831
|
+
TypedData_Get_Struct(nan, Real, &BigDecimal_data_type, *div);
|
1832
|
+
TypedData_Get_Struct(nan, Real, &BigDecimal_data_type, *mod);
|
1833
|
+
}
|
1442
1834
|
return Qtrue;
|
1443
1835
|
}
|
1444
1836
|
|
@@ -1458,7 +1850,7 @@ BigDecimal_mod(VALUE self, VALUE r) /* %: a%b = a - (a.to_f/b).floor * b */
|
|
1458
1850
|
|
1459
1851
|
if (BigDecimal_DoDivmod(self, r, &div, &mod)) {
|
1460
1852
|
SAVE(div); SAVE(mod);
|
1461
|
-
|
1853
|
+
return VpCheckGetValue(mod);
|
1462
1854
|
}
|
1463
1855
|
return DoSomeOne(self, r, '%');
|
1464
1856
|
}
|
@@ -1473,7 +1865,7 @@ BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv)
|
|
1473
1865
|
|
1474
1866
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1475
1867
|
if (RB_TYPE_P(r, T_FLOAT)) {
|
1476
|
-
b = GetVpValueWithPrec(r,
|
1868
|
+
b = GetVpValueWithPrec(r, 0, 1);
|
1477
1869
|
}
|
1478
1870
|
else if (RB_TYPE_P(r, T_RATIONAL)) {
|
1479
1871
|
b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
|
@@ -1486,17 +1878,17 @@ BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv)
|
|
1486
1878
|
SAVE(b);
|
1487
1879
|
|
1488
1880
|
mx = (a->MaxPrec + b->MaxPrec) *VpBaseFig();
|
1489
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
1490
|
-
GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0"));
|
1491
|
-
GUARD_OBJ(rr, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0"));
|
1492
|
-
GUARD_OBJ(ff, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0"));
|
1881
|
+
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
1882
|
+
GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0", true));
|
1883
|
+
GUARD_OBJ(rr, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0", true));
|
1884
|
+
GUARD_OBJ(ff, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0", true));
|
1493
1885
|
|
1494
1886
|
VpDivd(c, res, a, b);
|
1495
1887
|
|
1496
1888
|
mx = c->Prec *(VpBaseFig() + 1);
|
1497
1889
|
|
1498
|
-
GUARD_OBJ(d, VpCreateRbObject(mx, "0"));
|
1499
|
-
GUARD_OBJ(f, VpCreateRbObject(mx, "0"));
|
1890
|
+
GUARD_OBJ(d, VpCreateRbObject(mx, "0", true));
|
1891
|
+
GUARD_OBJ(f, VpCreateRbObject(mx, "0", true));
|
1500
1892
|
|
1501
1893
|
VpActiveRound(d, c, VP_ROUND_DOWN, 0); /* 0: round off */
|
1502
1894
|
|
@@ -1523,7 +1915,7 @@ BigDecimal_remainder(VALUE self, VALUE r) /* remainder */
|
|
1523
1915
|
Real *d, *rv = 0;
|
1524
1916
|
f = BigDecimal_divremain(self, r, &d, &rv);
|
1525
1917
|
if (!NIL_P(f)) return f;
|
1526
|
-
return
|
1918
|
+
return VpCheckGetValue(rv);
|
1527
1919
|
}
|
1528
1920
|
|
1529
1921
|
/* call-seq:
|
@@ -1556,13 +1948,14 @@ BigDecimal_divmod(VALUE self, VALUE r)
|
|
1556
1948
|
|
1557
1949
|
if (BigDecimal_DoDivmod(self, r, &div, &mod)) {
|
1558
1950
|
SAVE(div); SAVE(mod);
|
1559
|
-
|
1951
|
+
return rb_assoc_new(VpCheckGetValue(div), VpCheckGetValue(mod));
|
1560
1952
|
}
|
1561
1953
|
return DoSomeOne(self,r,rb_intern("divmod"));
|
1562
1954
|
}
|
1563
1955
|
|
1564
1956
|
/*
|
1565
|
-
*
|
1957
|
+
* Do the same manner as Float#div when n is nil.
|
1958
|
+
* Do the same manner as BigDecimal#quo when n is 0.
|
1566
1959
|
*/
|
1567
1960
|
static inline VALUE
|
1568
1961
|
BigDecimal_div2(VALUE self, VALUE b, VALUE n)
|
@@ -1574,7 +1967,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
|
|
1574
1967
|
Real *div = NULL;
|
1575
1968
|
Real *mod;
|
1576
1969
|
if (BigDecimal_DoDivmod(self, b, &div, &mod)) {
|
1577
|
-
return BigDecimal_to_i(
|
1970
|
+
return BigDecimal_to_i(VpCheckGetValue(div));
|
1578
1971
|
}
|
1579
1972
|
return DoSomeOne(self, b, rb_intern("div"));
|
1580
1973
|
}
|
@@ -1588,18 +1981,25 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
|
|
1588
1981
|
Real *res = NULL;
|
1589
1982
|
Real *av = NULL, *bv = NULL, *cv = NULL;
|
1590
1983
|
size_t mx = ix + VpBaseFig()*2;
|
1984
|
+
size_t b_prec = ix;
|
1591
1985
|
size_t pl = VpSetPrecLimit(0);
|
1592
1986
|
|
1593
|
-
GUARD_OBJ(cv, VpCreateRbObject(mx + VpBaseFig(), "0"));
|
1987
|
+
GUARD_OBJ(cv, VpCreateRbObject(mx + VpBaseFig(), "0", true));
|
1594
1988
|
GUARD_OBJ(av, GetVpValue(self, 1));
|
1595
|
-
|
1989
|
+
/* TODO: I want to refactor this precision control for a float value later
|
1990
|
+
* by introducing an implicit conversion function instead of
|
1991
|
+
* GetVpValueWithPrec. */
|
1992
|
+
if (RB_FLOAT_TYPE_P(b) && b_prec > BIGDECIMAL_DOUBLE_FIGURES) {
|
1993
|
+
b_prec = BIGDECIMAL_DOUBLE_FIGURES;
|
1994
|
+
}
|
1995
|
+
GUARD_OBJ(bv, GetVpValueWithPrec(b, b_prec, 1));
|
1596
1996
|
mx = av->Prec + bv->Prec + 2;
|
1597
1997
|
if (mx <= cv->MaxPrec) mx = cv->MaxPrec + 1;
|
1598
|
-
GUARD_OBJ(res, VpCreateRbObject((mx * 2 + 2)*VpBaseFig(), "#0"));
|
1998
|
+
GUARD_OBJ(res, VpCreateRbObject((mx * 2 + 2)*VpBaseFig(), "#0", true));
|
1599
1999
|
VpDivd(cv, res, av, bv);
|
1600
2000
|
VpSetPrecLimit(pl);
|
1601
2001
|
VpLeftRound(cv, VpGetRoundMode(), ix);
|
1602
|
-
return
|
2002
|
+
return VpCheckGetValue(cv);
|
1603
2003
|
}
|
1604
2004
|
}
|
1605
2005
|
|
@@ -1607,6 +2007,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
|
|
1607
2007
|
* Document-method: BigDecimal#div
|
1608
2008
|
*
|
1609
2009
|
* call-seq:
|
2010
|
+
* div(value) -> integer
|
1610
2011
|
* div(value, digits) -> bigdecimal or integer
|
1611
2012
|
*
|
1612
2013
|
* Divide by the specified value.
|
@@ -1621,6 +2022,9 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
|
|
1621
2022
|
* If digits is not specified, the result is an integer,
|
1622
2023
|
* by analogy with Float#div; see also BigDecimal#divmod.
|
1623
2024
|
*
|
2025
|
+
* See BigDecimal#/.
|
2026
|
+
* See BigDecimal#quo.
|
2027
|
+
*
|
1624
2028
|
* Examples:
|
1625
2029
|
*
|
1626
2030
|
* a = BigDecimal("4")
|
@@ -1644,6 +2048,31 @@ BigDecimal_div3(int argc, VALUE *argv, VALUE self)
|
|
1644
2048
|
return BigDecimal_div2(self, b, n);
|
1645
2049
|
}
|
1646
2050
|
|
2051
|
+
/*
|
2052
|
+
* call-seq:
|
2053
|
+
* add(value, ndigits) -> new_bigdecimal
|
2054
|
+
*
|
2055
|
+
* Returns the \BigDecimal sum of +self+ and +value+
|
2056
|
+
* with a precision of +ndigits+ decimal digits.
|
2057
|
+
*
|
2058
|
+
* When +ndigits+ is less than the number of significant digits
|
2059
|
+
* in the sum, the sum is rounded to that number of digits,
|
2060
|
+
* according to the current rounding mode; see BigDecimal.mode.
|
2061
|
+
*
|
2062
|
+
* Examples:
|
2063
|
+
*
|
2064
|
+
* # Set the rounding mode.
|
2065
|
+
* BigDecimal.mode(BigDecimal::ROUND_MODE, :half_up)
|
2066
|
+
* b = BigDecimal('111111.111')
|
2067
|
+
* b.add(1, 0) # => 0.111112111e6
|
2068
|
+
* b.add(1, 3) # => 0.111e6
|
2069
|
+
* b.add(1, 6) # => 0.111112e6
|
2070
|
+
* b.add(1, 15) # => 0.111112111e6
|
2071
|
+
* b.add(1.0, 15) # => 0.111112111e6
|
2072
|
+
* b.add(Rational(1, 1), 15) # => 0.111112111e6
|
2073
|
+
*
|
2074
|
+
*/
|
2075
|
+
|
1647
2076
|
static VALUE
|
1648
2077
|
BigDecimal_add2(VALUE self, VALUE b, VALUE n)
|
1649
2078
|
{
|
@@ -1657,7 +2086,7 @@ BigDecimal_add2(VALUE self, VALUE b, VALUE n)
|
|
1657
2086
|
VpSetPrecLimit(pl);
|
1658
2087
|
GUARD_OBJ(cv, GetVpValue(c, 1));
|
1659
2088
|
VpLeftRound(cv, VpGetRoundMode(), mx);
|
1660
|
-
|
2089
|
+
return VpCheckGetValue(cv);
|
1661
2090
|
}
|
1662
2091
|
}
|
1663
2092
|
|
@@ -1687,10 +2116,35 @@ BigDecimal_sub2(VALUE self, VALUE b, VALUE n)
|
|
1687
2116
|
VpSetPrecLimit(pl);
|
1688
2117
|
GUARD_OBJ(cv, GetVpValue(c, 1));
|
1689
2118
|
VpLeftRound(cv, VpGetRoundMode(), mx);
|
1690
|
-
|
2119
|
+
return VpCheckGetValue(cv);
|
1691
2120
|
}
|
1692
2121
|
}
|
1693
2122
|
|
2123
|
+
/*
|
2124
|
+
* call-seq:
|
2125
|
+
* mult(other, ndigits) -> bigdecimal
|
2126
|
+
*
|
2127
|
+
* Returns the \BigDecimal product of +self+ and +value+
|
2128
|
+
* with a precision of +ndigits+ decimal digits.
|
2129
|
+
*
|
2130
|
+
* When +ndigits+ is less than the number of significant digits
|
2131
|
+
* in the sum, the sum is rounded to that number of digits,
|
2132
|
+
* according to the current rounding mode; see BigDecimal.mode.
|
2133
|
+
*
|
2134
|
+
* Examples:
|
2135
|
+
*
|
2136
|
+
* # Set the rounding mode.
|
2137
|
+
* BigDecimal.mode(BigDecimal::ROUND_MODE, :half_up)
|
2138
|
+
* b = BigDecimal('555555.555')
|
2139
|
+
* b.mult(3, 0) # => 0.1666666665e7
|
2140
|
+
* b.mult(3, 3) # => 0.167e7
|
2141
|
+
* b.mult(3, 6) # => 0.166667e7
|
2142
|
+
* b.mult(3, 15) # => 0.1666666665e7
|
2143
|
+
* b.mult(3.0, 0) # => 0.1666666665e7
|
2144
|
+
* b.mult(Rational(3, 1), 0) # => 0.1666666665e7
|
2145
|
+
* b.mult(Complex(3, 0), 0) # => (0.1666666665e7+0.0i)
|
2146
|
+
*
|
2147
|
+
*/
|
1694
2148
|
|
1695
2149
|
static VALUE
|
1696
2150
|
BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
|
@@ -1705,18 +2159,19 @@ BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
|
|
1705
2159
|
VpSetPrecLimit(pl);
|
1706
2160
|
GUARD_OBJ(cv, GetVpValue(c, 1));
|
1707
2161
|
VpLeftRound(cv, VpGetRoundMode(), mx);
|
1708
|
-
|
2162
|
+
return VpCheckGetValue(cv);
|
1709
2163
|
}
|
1710
2164
|
}
|
1711
2165
|
|
1712
2166
|
/*
|
1713
2167
|
* call-seq:
|
1714
|
-
*
|
2168
|
+
* abs -> bigdecimal
|
2169
|
+
*
|
2170
|
+
* Returns the \BigDecimal absolute value of +self+:
|
1715
2171
|
*
|
1716
|
-
*
|
2172
|
+
* BigDecimal('5').abs # => 0.5e1
|
2173
|
+
* BigDecimal('-3').abs # => 0.3e1
|
1717
2174
|
*
|
1718
|
-
* BigDecimal('5').abs #=> 0.5e1
|
1719
|
-
* BigDecimal('-3').abs #=> 0.3e1
|
1720
2175
|
*/
|
1721
2176
|
|
1722
2177
|
static VALUE
|
@@ -1728,10 +2183,10 @@ BigDecimal_abs(VALUE self)
|
|
1728
2183
|
|
1729
2184
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1730
2185
|
mx = a->Prec *(VpBaseFig() + 1);
|
1731
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
2186
|
+
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
1732
2187
|
VpAsgn(c, a, 1);
|
1733
2188
|
VpChangeSign(c, 1);
|
1734
|
-
return
|
2189
|
+
return VpCheckGetValue(c);
|
1735
2190
|
}
|
1736
2191
|
|
1737
2192
|
/* call-seq:
|
@@ -1753,9 +2208,9 @@ BigDecimal_sqrt(VALUE self, VALUE nFig)
|
|
1753
2208
|
|
1754
2209
|
n = GetPrecisionInt(nFig) + VpDblFig() + BASE_FIG;
|
1755
2210
|
if (mx <= n) mx = n;
|
1756
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
2211
|
+
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
1757
2212
|
VpSqrt(c, a);
|
1758
|
-
return
|
2213
|
+
return VpCheckGetValue(c);
|
1759
2214
|
}
|
1760
2215
|
|
1761
2216
|
/* Return the integer part of the number, as a BigDecimal.
|
@@ -1769,9 +2224,9 @@ BigDecimal_fix(VALUE self)
|
|
1769
2224
|
|
1770
2225
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1771
2226
|
mx = a->Prec *(VpBaseFig() + 1);
|
1772
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
2227
|
+
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
1773
2228
|
VpActiveRound(c, a, VP_ROUND_DOWN, 0); /* 0: round off */
|
1774
|
-
return
|
2229
|
+
return VpCheckGetValue(c);
|
1775
2230
|
}
|
1776
2231
|
|
1777
2232
|
/* call-seq:
|
@@ -1842,13 +2297,13 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
|
|
1842
2297
|
pl = VpSetPrecLimit(0);
|
1843
2298
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1844
2299
|
mx = a->Prec * (VpBaseFig() + 1);
|
1845
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
2300
|
+
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
1846
2301
|
VpSetPrecLimit(pl);
|
1847
2302
|
VpActiveRound(c, a, sw, iLoc);
|
1848
2303
|
if (round_to_int) {
|
1849
|
-
|
2304
|
+
return BigDecimal_to_i(VpCheckGetValue(c));
|
1850
2305
|
}
|
1851
|
-
return
|
2306
|
+
return VpCheckGetValue(c);
|
1852
2307
|
}
|
1853
2308
|
|
1854
2309
|
/* call-seq:
|
@@ -1888,13 +2343,13 @@ BigDecimal_truncate(int argc, VALUE *argv, VALUE self)
|
|
1888
2343
|
|
1889
2344
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1890
2345
|
mx = a->Prec * (VpBaseFig() + 1);
|
1891
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
2346
|
+
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
1892
2347
|
VpSetPrecLimit(pl);
|
1893
2348
|
VpActiveRound(c, a, VP_ROUND_DOWN, iLoc); /* 0: truncate */
|
1894
2349
|
if (argc == 0) {
|
1895
|
-
|
2350
|
+
return BigDecimal_to_i(VpCheckGetValue(c));
|
1896
2351
|
}
|
1897
|
-
return
|
2352
|
+
return VpCheckGetValue(c);
|
1898
2353
|
}
|
1899
2354
|
|
1900
2355
|
/* Return the fractional part of the number, as a BigDecimal.
|
@@ -1908,9 +2363,9 @@ BigDecimal_frac(VALUE self)
|
|
1908
2363
|
|
1909
2364
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1910
2365
|
mx = a->Prec * (VpBaseFig() + 1);
|
1911
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
2366
|
+
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
1912
2367
|
VpFrac(c, a);
|
1913
|
-
return
|
2368
|
+
return VpCheckGetValue(c);
|
1914
2369
|
}
|
1915
2370
|
|
1916
2371
|
/* call-seq:
|
@@ -1948,16 +2403,16 @@ BigDecimal_floor(int argc, VALUE *argv, VALUE self)
|
|
1948
2403
|
|
1949
2404
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1950
2405
|
mx = a->Prec * (VpBaseFig() + 1);
|
1951
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
2406
|
+
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
1952
2407
|
VpSetPrecLimit(pl);
|
1953
2408
|
VpActiveRound(c, a, VP_ROUND_FLOOR, iLoc);
|
1954
2409
|
#ifdef BIGDECIMAL_DEBUG
|
1955
2410
|
VPrint(stderr, "floor: c=%\n", c);
|
1956
2411
|
#endif
|
1957
2412
|
if (argc == 0) {
|
1958
|
-
|
2413
|
+
return BigDecimal_to_i(VpCheckGetValue(c));
|
1959
2414
|
}
|
1960
|
-
return
|
2415
|
+
return VpCheckGetValue(c);
|
1961
2416
|
}
|
1962
2417
|
|
1963
2418
|
/* call-seq:
|
@@ -1994,13 +2449,13 @@ BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
|
|
1994
2449
|
|
1995
2450
|
GUARD_OBJ(a, GetVpValue(self, 1));
|
1996
2451
|
mx = a->Prec * (VpBaseFig() + 1);
|
1997
|
-
GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
|
2452
|
+
GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
|
1998
2453
|
VpSetPrecLimit(pl);
|
1999
2454
|
VpActiveRound(c, a, VP_ROUND_CEIL, iLoc);
|
2000
2455
|
if (argc == 0) {
|
2001
|
-
|
2456
|
+
return BigDecimal_to_i(VpCheckGetValue(c));
|
2002
2457
|
}
|
2003
|
-
return
|
2458
|
+
return VpCheckGetValue(c);
|
2004
2459
|
}
|
2005
2460
|
|
2006
2461
|
/* call-seq:
|
@@ -2296,13 +2751,13 @@ is_even(VALUE x)
|
|
2296
2751
|
}
|
2297
2752
|
|
2298
2753
|
static VALUE
|
2299
|
-
|
2754
|
+
bigdecimal_power_by_bigdecimal(Real const* x, Real const* exp, ssize_t const n)
|
2300
2755
|
{
|
2301
2756
|
VALUE log_x, multiplied, y;
|
2302
2757
|
volatile VALUE obj = exp->obj;
|
2303
2758
|
|
2304
2759
|
if (VpIsZero(exp)) {
|
2305
|
-
|
2760
|
+
return VpCheckGetValue(VpCreateRbObject(n, "1", true));
|
2306
2761
|
}
|
2307
2762
|
|
2308
2763
|
log_x = BigMath_log(x->obj, SSIZET2NUM(n+1));
|
@@ -2340,10 +2795,10 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2340
2795
|
n = NIL_P(prec) ? (ssize_t)(x->Prec*VpBaseFig()) : NUM2SSIZET(prec);
|
2341
2796
|
|
2342
2797
|
if (VpIsNaN(x)) {
|
2343
|
-
|
2798
|
+
y = VpCreateRbObject(n, "0", true);
|
2344
2799
|
RB_GC_GUARD(y->obj);
|
2345
2800
|
VpSetNaN(y);
|
2346
|
-
|
2801
|
+
return VpCheckGetValue(y);
|
2347
2802
|
}
|
2348
2803
|
|
2349
2804
|
retry:
|
@@ -2366,9 +2821,9 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2366
2821
|
goto retry;
|
2367
2822
|
}
|
2368
2823
|
if (NIL_P(prec)) {
|
2369
|
-
n +=
|
2824
|
+
n += BIGDECIMAL_DOUBLE_FIGURES;
|
2370
2825
|
}
|
2371
|
-
exp = GetVpValueWithPrec(vexp,
|
2826
|
+
exp = GetVpValueWithPrec(vexp, 0, 1);
|
2372
2827
|
break;
|
2373
2828
|
|
2374
2829
|
case T_RATIONAL:
|
@@ -2412,7 +2867,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2412
2867
|
|
2413
2868
|
if (VpIsZero(x)) {
|
2414
2869
|
if (is_negative(vexp)) {
|
2415
|
-
|
2870
|
+
y = VpCreateRbObject(n, "#0", true);
|
2416
2871
|
RB_GC_GUARD(y->obj);
|
2417
2872
|
if (BIGDECIMAL_NEGATIVE_P(x)) {
|
2418
2873
|
if (is_integer(vexp)) {
|
@@ -2434,18 +2889,18 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2434
2889
|
/* (+0) ** (-num) -> Infinity */
|
2435
2890
|
VpSetPosInf(y);
|
2436
2891
|
}
|
2437
|
-
|
2892
|
+
return VpCheckGetValue(y);
|
2438
2893
|
}
|
2439
2894
|
else if (is_zero(vexp)) {
|
2440
|
-
|
2895
|
+
return VpCheckGetValue(VpCreateRbObject(n, "1", true));
|
2441
2896
|
}
|
2442
2897
|
else {
|
2443
|
-
|
2898
|
+
return VpCheckGetValue(VpCreateRbObject(n, "0", true));
|
2444
2899
|
}
|
2445
2900
|
}
|
2446
2901
|
|
2447
2902
|
if (is_zero(vexp)) {
|
2448
|
-
|
2903
|
+
return VpCheckGetValue(VpCreateRbObject(n, "1", true));
|
2449
2904
|
}
|
2450
2905
|
else if (is_one(vexp)) {
|
2451
2906
|
return self;
|
@@ -2457,24 +2912,24 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2457
2912
|
if (is_integer(vexp)) {
|
2458
2913
|
if (is_even(vexp)) {
|
2459
2914
|
/* (-Infinity) ** (-even_integer) -> +0 */
|
2460
|
-
|
2915
|
+
return VpCheckGetValue(VpCreateRbObject(n, "0", true));
|
2461
2916
|
}
|
2462
2917
|
else {
|
2463
2918
|
/* (-Infinity) ** (-odd_integer) -> -0 */
|
2464
|
-
|
2919
|
+
return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
|
2465
2920
|
}
|
2466
2921
|
}
|
2467
2922
|
else {
|
2468
2923
|
/* (-Infinity) ** (-non_integer) -> -0 */
|
2469
|
-
|
2924
|
+
return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
|
2470
2925
|
}
|
2471
2926
|
}
|
2472
2927
|
else {
|
2473
|
-
|
2928
|
+
return VpCheckGetValue(VpCreateRbObject(n, "0", true));
|
2474
2929
|
}
|
2475
2930
|
}
|
2476
2931
|
else {
|
2477
|
-
|
2932
|
+
y = VpCreateRbObject(n, "0", true);
|
2478
2933
|
if (BIGDECIMAL_NEGATIVE_P(x)) {
|
2479
2934
|
if (is_integer(vexp)) {
|
2480
2935
|
if (is_even(vexp)) {
|
@@ -2493,52 +2948,52 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2493
2948
|
else {
|
2494
2949
|
VpSetPosInf(y);
|
2495
2950
|
}
|
2496
|
-
|
2951
|
+
return VpCheckGetValue(y);
|
2497
2952
|
}
|
2498
2953
|
}
|
2499
2954
|
|
2500
2955
|
if (exp != NULL) {
|
2501
|
-
return
|
2956
|
+
return bigdecimal_power_by_bigdecimal(x, exp, n);
|
2502
2957
|
}
|
2503
2958
|
else if (RB_TYPE_P(vexp, T_BIGNUM)) {
|
2504
2959
|
VALUE abs_value = BigDecimal_abs(self);
|
2505
2960
|
if (is_one(abs_value)) {
|
2506
|
-
|
2961
|
+
return VpCheckGetValue(VpCreateRbObject(n, "1", true));
|
2507
2962
|
}
|
2508
2963
|
else if (RTEST(rb_funcall(abs_value, '<', 1, INT2FIX(1)))) {
|
2509
2964
|
if (is_negative(vexp)) {
|
2510
|
-
|
2965
|
+
y = VpCreateRbObject(n, "0", true);
|
2511
2966
|
if (is_even(vexp)) {
|
2512
2967
|
VpSetInf(y, VpGetSign(x));
|
2513
2968
|
}
|
2514
2969
|
else {
|
2515
2970
|
VpSetInf(y, -VpGetSign(x));
|
2516
2971
|
}
|
2517
|
-
|
2972
|
+
return VpCheckGetValue(y);
|
2518
2973
|
}
|
2519
2974
|
else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
|
2520
|
-
|
2975
|
+
return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
|
2521
2976
|
}
|
2522
2977
|
else {
|
2523
|
-
|
2978
|
+
return VpCheckGetValue(VpCreateRbObject(n, "0", true));
|
2524
2979
|
}
|
2525
2980
|
}
|
2526
2981
|
else {
|
2527
2982
|
if (is_positive(vexp)) {
|
2528
|
-
|
2983
|
+
y = VpCreateRbObject(n, "0", true);
|
2529
2984
|
if (is_even(vexp)) {
|
2530
2985
|
VpSetInf(y, VpGetSign(x));
|
2531
2986
|
}
|
2532
2987
|
else {
|
2533
2988
|
VpSetInf(y, -VpGetSign(x));
|
2534
2989
|
}
|
2535
|
-
|
2990
|
+
return VpCheckGetValue(y);
|
2536
2991
|
}
|
2537
2992
|
else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
|
2538
|
-
|
2993
|
+
return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
|
2539
2994
|
}
|
2540
2995
|
else {
|
2541
|
-
|
2996
|
+
return VpCheckGetValue(VpCreateRbObject(n, "0", true));
|
2542
2997
|
}
|
2543
2998
|
}
|
2544
2999
|
}
|
@@ -2550,24 +3005,30 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
|
|
2550
3005
|
|
2551
3006
|
if (VpIsDef(x)) {
|
2552
3007
|
mp = x->Prec * (VpBaseFig() + 1);
|
2553
|
-
|
3008
|
+
GUARD_OBJ(y, VpCreateRbObject(mp * (ma + 1), "0", true));
|
2554
3009
|
}
|
2555
3010
|
else {
|
2556
|
-
|
3011
|
+
GUARD_OBJ(y, VpCreateRbObject(1, "0", true));
|
2557
3012
|
}
|
2558
|
-
|
3013
|
+
VpPowerByInt(y, x, int_exp);
|
2559
3014
|
if (!NIL_P(prec) && VpIsDef(y)) {
|
2560
3015
|
VpMidRound(y, VpGetRoundMode(), n);
|
2561
3016
|
}
|
2562
|
-
return
|
3017
|
+
return VpCheckGetValue(y);
|
2563
3018
|
}
|
2564
3019
|
|
2565
|
-
/*
|
2566
|
-
*
|
3020
|
+
/* call-seq:
|
3021
|
+
* self ** other -> bigdecimal
|
2567
3022
|
*
|
2568
|
-
*
|
3023
|
+
* Returns the \BigDecimal value of +self+ raised to power +other+:
|
3024
|
+
*
|
3025
|
+
* b = BigDecimal('3.14')
|
3026
|
+
* b ** 2 # => 0.98596e1
|
3027
|
+
* b ** 2.0 # => 0.98596e1
|
3028
|
+
* b ** Rational(2, 1) # => 0.98596e1
|
3029
|
+
*
|
3030
|
+
* Related: BigDecimal#power.
|
2569
3031
|
*
|
2570
|
-
* See BigDecimal#power.
|
2571
3032
|
*/
|
2572
3033
|
static VALUE
|
2573
3034
|
BigDecimal_power_op(VALUE self, VALUE exp)
|
@@ -2621,182 +3082,483 @@ opts_exception_p(VALUE opts)
|
|
2621
3082
|
}
|
2622
3083
|
#endif
|
2623
3084
|
|
2624
|
-
static
|
2625
|
-
|
3085
|
+
static VALUE
|
3086
|
+
check_exception(VALUE bd)
|
2626
3087
|
{
|
2627
|
-
|
2628
|
-
|
2629
|
-
|
2630
|
-
|
2631
|
-
|
2632
|
-
|
3088
|
+
assert(is_kind_of_BigDecimal(bd));
|
3089
|
+
|
3090
|
+
Real *vp;
|
3091
|
+
TypedData_Get_Struct(bd, Real, &BigDecimal_data_type, vp);
|
3092
|
+
VpCheckGetValue(vp); /* VpCheckGetValue performs exception check */
|
3093
|
+
|
3094
|
+
return bd;
|
3095
|
+
}
|
2633
3096
|
|
2634
|
-
|
2635
|
-
|
3097
|
+
static VALUE
|
3098
|
+
rb_uint64_convert_to_BigDecimal(uint64_t uval, RB_UNUSED_VAR(size_t digs), int raise_exception)
|
3099
|
+
{
|
3100
|
+
VALUE obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0);
|
2636
3101
|
|
2637
|
-
|
2638
|
-
|
3102
|
+
Real *vp;
|
3103
|
+
if (uval == 0) {
|
3104
|
+
vp = VpAllocReal(1);
|
3105
|
+
vp->MaxPrec = 1;
|
3106
|
+
vp->Prec = 1;
|
3107
|
+
vp->exponent = 1;
|
3108
|
+
VpSetZero(vp, 1);
|
3109
|
+
vp->frac[0] = 0;
|
3110
|
+
}
|
3111
|
+
else if (uval < BASE) {
|
3112
|
+
vp = VpAllocReal(1);
|
3113
|
+
vp->MaxPrec = 1;
|
3114
|
+
vp->Prec = 1;
|
3115
|
+
vp->exponent = 1;
|
3116
|
+
VpSetSign(vp, 1);
|
3117
|
+
vp->frac[0] = (DECDIG)uval;
|
2639
3118
|
}
|
2640
3119
|
else {
|
2641
|
-
|
2642
|
-
|
2643
|
-
|
2644
|
-
|
2645
|
-
|
3120
|
+
DECDIG buf[BIGDECIMAL_INT64_MAX_LENGTH] = {0,};
|
3121
|
+
DECDIG r = uval % BASE;
|
3122
|
+
size_t len = 0, ntz = 0;
|
3123
|
+
if (r == 0) {
|
3124
|
+
// Count and skip trailing zeros
|
3125
|
+
for (; r == 0 && uval > 0; ++ntz) {
|
3126
|
+
uval /= BASE;
|
3127
|
+
r = uval % BASE;
|
2646
3128
|
}
|
2647
|
-
rb_raise(rb_eArgError, "negative precision");
|
2648
3129
|
}
|
2649
|
-
|
2650
|
-
|
2651
|
-
|
2652
|
-
|
2653
|
-
|
2654
|
-
case Qnil:
|
2655
|
-
if (!exc) return NULL;
|
2656
|
-
rb_raise(rb_eTypeError, "can't convert nil into BigDecimal");
|
2657
|
-
case Qtrue:
|
2658
|
-
if (!exc) return NULL;
|
2659
|
-
rb_raise(rb_eTypeError, "can't convert true into BigDecimal");
|
2660
|
-
case Qfalse:
|
2661
|
-
if (!exc) return NULL;
|
2662
|
-
rb_raise(rb_eTypeError, "can't convert false into BigDecimal");
|
2663
|
-
default:
|
2664
|
-
break;
|
3130
|
+
for (; uval > 0; ++len) {
|
3131
|
+
// Store digits
|
3132
|
+
buf[BIGDECIMAL_INT64_MAX_LENGTH - len - 1] = r;
|
3133
|
+
uval /= BASE;
|
3134
|
+
r = uval % BASE;
|
2665
3135
|
}
|
3136
|
+
|
3137
|
+
const size_t exp = len + ntz;
|
3138
|
+
vp = VpAllocReal(len);
|
3139
|
+
vp->MaxPrec = len;
|
3140
|
+
vp->Prec = len;
|
3141
|
+
vp->exponent = exp;
|
3142
|
+
VpSetSign(vp, 1);
|
3143
|
+
MEMCPY(vp->frac, buf + BIGDECIMAL_INT64_MAX_LENGTH - len, DECDIG, len);
|
2666
3144
|
}
|
2667
3145
|
|
2668
|
-
|
2669
|
-
|
2670
|
-
case T_DATA:
|
2671
|
-
if (is_kind_of_BigDecimal(iniValue)) {
|
2672
|
-
return DATA_PTR(iniValue);
|
2673
|
-
}
|
2674
|
-
break;
|
3146
|
+
return BigDecimal_wrap_struct(obj, vp);
|
3147
|
+
}
|
2675
3148
|
|
2676
|
-
|
2677
|
-
|
2678
|
-
|
2679
|
-
|
3149
|
+
static VALUE
|
3150
|
+
rb_int64_convert_to_BigDecimal(int64_t ival, size_t digs, int raise_exception)
|
3151
|
+
{
|
3152
|
+
const uint64_t uval = (ival < 0) ? (((uint64_t)-(ival+1))+1) : (uint64_t)ival;
|
3153
|
+
VALUE bd = rb_uint64_convert_to_BigDecimal(uval, digs, raise_exception);
|
3154
|
+
if (ival < 0) {
|
3155
|
+
Real *vp;
|
3156
|
+
TypedData_Get_Struct(bd, Real, &BigDecimal_data_type, vp);
|
3157
|
+
VpSetSign(vp, -1);
|
3158
|
+
}
|
3159
|
+
return bd;
|
3160
|
+
}
|
2680
3161
|
|
2681
|
-
|
2682
|
-
|
2683
|
-
|
2684
|
-
|
2685
|
-
|
2686
|
-
|
3162
|
+
static VALUE
|
3163
|
+
rb_big_convert_to_BigDecimal(VALUE val, RB_UNUSED_VAR(size_t digs), int raise_exception)
|
3164
|
+
{
|
3165
|
+
assert(RB_TYPE_P(val, T_BIGNUM));
|
3166
|
+
|
3167
|
+
int leading_zeros;
|
3168
|
+
size_t size = rb_absint_size(val, &leading_zeros);
|
3169
|
+
int sign = FIX2INT(rb_big_cmp(val, INT2FIX(0)));
|
3170
|
+
if (sign < 0 && leading_zeros == 0) {
|
3171
|
+
size += 1;
|
3172
|
+
}
|
3173
|
+
if (size <= sizeof(long)) {
|
3174
|
+
if (sign < 0) {
|
3175
|
+
return rb_int64_convert_to_BigDecimal(NUM2LONG(val), digs, raise_exception);
|
2687
3176
|
}
|
2688
|
-
|
2689
|
-
|
2690
|
-
|
2691
|
-
|
2692
|
-
|
2693
|
-
|
2694
|
-
|
2695
|
-
|
2696
|
-
|
2697
|
-
|
2698
|
-
|
2699
|
-
|
2700
|
-
|
2701
|
-
|
2702
|
-
|
2703
|
-
|
2704
|
-
|
3177
|
+
else {
|
3178
|
+
return rb_uint64_convert_to_BigDecimal(NUM2ULONG(val), digs, raise_exception);
|
3179
|
+
}
|
3180
|
+
}
|
3181
|
+
#if defined(SIZEOF_LONG_LONG) && SIZEOF_LONG < SIZEOF_LONG_LONG
|
3182
|
+
else if (size <= sizeof(LONG_LONG)) {
|
3183
|
+
if (sign < 0) {
|
3184
|
+
return rb_int64_convert_to_BigDecimal(NUM2LL(val), digs, raise_exception);
|
3185
|
+
}
|
3186
|
+
else {
|
3187
|
+
return rb_uint64_convert_to_BigDecimal(NUM2ULL(val), digs, raise_exception);
|
3188
|
+
}
|
3189
|
+
}
|
3190
|
+
#endif
|
3191
|
+
else {
|
3192
|
+
VALUE str = rb_big2str(val, 10);
|
3193
|
+
Real *vp = VpCreateRbObject(RSTRING_LEN(str) + BASE_FIG + 1,
|
3194
|
+
RSTRING_PTR(str), true);
|
3195
|
+
RB_GC_GUARD(str);
|
3196
|
+
return check_exception(vp->obj);
|
3197
|
+
}
|
3198
|
+
}
|
2705
3199
|
|
2706
|
-
|
2707
|
-
|
2708
|
-
|
2709
|
-
|
2710
|
-
|
2711
|
-
|
2712
|
-
|
2713
|
-
|
2714
|
-
|
2715
|
-
|
3200
|
+
static VALUE
|
3201
|
+
rb_inum_convert_to_BigDecimal(VALUE val, RB_UNUSED_VAR(size_t digs), int raise_exception)
|
3202
|
+
{
|
3203
|
+
assert(RB_INTEGER_TYPE_P(val));
|
3204
|
+
if (FIXNUM_P(val)) {
|
3205
|
+
return rb_int64_convert_to_BigDecimal(FIX2LONG(val), digs, raise_exception);
|
3206
|
+
}
|
3207
|
+
else {
|
3208
|
+
return rb_big_convert_to_BigDecimal(val, digs, raise_exception);
|
3209
|
+
}
|
3210
|
+
}
|
3211
|
+
|
3212
|
+
static VALUE
|
3213
|
+
rb_float_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
|
3214
|
+
{
|
3215
|
+
assert(RB_FLOAT_TYPE_P(val));
|
3216
|
+
|
3217
|
+
double d = RFLOAT_VALUE(val);
|
3218
|
+
|
3219
|
+
if (isnan(d)) {
|
3220
|
+
VALUE obj = BigDecimal_nan();
|
3221
|
+
return check_exception(obj);
|
3222
|
+
}
|
3223
|
+
else if (isinf(d)) {
|
3224
|
+
VALUE obj;
|
3225
|
+
if (d > 0) {
|
3226
|
+
obj = BigDecimal_positive_infinity();
|
3227
|
+
}
|
3228
|
+
else {
|
3229
|
+
obj = BigDecimal_negative_infinity();
|
3230
|
+
}
|
3231
|
+
return check_exception(obj);
|
3232
|
+
}
|
3233
|
+
else if (d == 0.0) {
|
3234
|
+
if (1/d < 0.0) {
|
3235
|
+
return BigDecimal_negative_zero();
|
3236
|
+
}
|
3237
|
+
else {
|
3238
|
+
return BigDecimal_positive_zero();
|
2716
3239
|
}
|
3240
|
+
}
|
3241
|
+
|
3242
|
+
if (digs == SIZE_MAX) {
|
3243
|
+
if (!raise_exception)
|
3244
|
+
return Qnil;
|
3245
|
+
rb_raise(rb_eArgError,
|
3246
|
+
"can't omit precision for a %"PRIsVALUE".",
|
3247
|
+
CLASS_OF(val));
|
3248
|
+
}
|
3249
|
+
else if (digs > BIGDECIMAL_DOUBLE_FIGURES) {
|
3250
|
+
if (!raise_exception)
|
3251
|
+
return Qnil;
|
3252
|
+
rb_raise(rb_eArgError, "precision too large.");
|
3253
|
+
}
|
3254
|
+
|
3255
|
+
/* Use the same logic in flo_to_s to convert a float to a decimal string */
|
3256
|
+
char buf[BIGDECIMAL_DOUBLE_FIGURES + BASE_FIG + 2 + 1]; /* sizeof(buf) == 28 in the typical case */
|
3257
|
+
int decpt, negative_p;
|
3258
|
+
char *e;
|
3259
|
+
const int mode = digs == 0 ? 0 : 2;
|
3260
|
+
char *p = BigDecimal_dtoa(d, mode, (int)digs, &decpt, &negative_p, &e);
|
3261
|
+
int len10 = (int)(e - p);
|
3262
|
+
if (len10 > BIGDECIMAL_DOUBLE_FIGURES) {
|
3263
|
+
/* TODO: Presumably, rounding should be done here. */
|
3264
|
+
len10 = BIGDECIMAL_DOUBLE_FIGURES;
|
3265
|
+
}
|
3266
|
+
memcpy(buf, p, len10);
|
3267
|
+
xfree(p);
|
3268
|
+
|
3269
|
+
VALUE inum;
|
3270
|
+
size_t RB_UNUSED_VAR(prec) = 0;
|
3271
|
+
size_t exp = 0;
|
3272
|
+
if (decpt > 0) {
|
3273
|
+
if (decpt < len10) {
|
3274
|
+
/*
|
3275
|
+
* len10 |---------------|
|
3276
|
+
* : |-------| frac_len10 = len10 - decpt
|
3277
|
+
* decpt |-------| |--| ntz10 = BASE_FIG - frac_len10 % BASE_FIG
|
3278
|
+
* : : :
|
3279
|
+
* 00 dd dddd.dddd dd 00
|
3280
|
+
* prec |-----.----.----.-----| prec = exp + roomof(frac_len, BASE_FIG)
|
3281
|
+
* exp |-----.----| exp = roomof(decpt, BASE_FIG)
|
3282
|
+
*/
|
3283
|
+
const size_t frac_len10 = len10 - decpt;
|
3284
|
+
const size_t ntz10 = BASE_FIG - frac_len10 % BASE_FIG;
|
3285
|
+
memset(buf + len10, '0', ntz10);
|
3286
|
+
buf[len10 + ntz10] = '\0';
|
3287
|
+
inum = rb_cstr_to_inum(buf, 10, false);
|
3288
|
+
|
3289
|
+
exp = roomof(decpt, BASE_FIG);
|
3290
|
+
prec = exp + roomof(frac_len10, BASE_FIG);
|
3291
|
+
}
|
3292
|
+
else {
|
3293
|
+
/*
|
3294
|
+
* decpt |-----------------------|
|
3295
|
+
* len10 |----------| :
|
3296
|
+
* : |------------| exp10
|
3297
|
+
* : : :
|
3298
|
+
* 00 dd dddd dd 00 0000 0000.0
|
3299
|
+
* : : : :
|
3300
|
+
* : |--| ntz10 = exp10 % BASE_FIG
|
3301
|
+
* prec |-----.----.-----| :
|
3302
|
+
* : |----.----| exp10 / BASE_FIG
|
3303
|
+
* exp |-----.----.-----.----.----|
|
3304
|
+
*/
|
3305
|
+
const size_t exp10 = decpt - len10;
|
3306
|
+
const size_t ntz10 = exp10 % BASE_FIG;
|
3307
|
+
|
3308
|
+
memset(buf + len10, '0', ntz10);
|
3309
|
+
buf[len10 + ntz10] = '\0';
|
3310
|
+
inum = rb_cstr_to_inum(buf, 10, false);
|
3311
|
+
|
3312
|
+
prec = roomof(len10 + ntz10, BASE_FIG);
|
3313
|
+
exp = prec + exp10 / BASE_FIG;
|
3314
|
+
}
|
3315
|
+
}
|
3316
|
+
else if (decpt == 0) {
|
3317
|
+
/*
|
3318
|
+
* len10 |------------|
|
3319
|
+
* : :
|
3320
|
+
* 0.dddd dddd dd 00
|
3321
|
+
* : : :
|
3322
|
+
* : |--| ntz10 = prec * BASE_FIG - len10
|
3323
|
+
* prec |----.----.-----| roomof(len10, BASE_FIG)
|
3324
|
+
*/
|
3325
|
+
prec = roomof(len10, BASE_FIG);
|
3326
|
+
const size_t ntz10 = prec * BASE_FIG - len10;
|
3327
|
+
|
3328
|
+
memset(buf + len10, '0', ntz10);
|
3329
|
+
buf[len10 + ntz10] = '\0';
|
3330
|
+
inum = rb_cstr_to_inum(buf, 10, false);
|
3331
|
+
}
|
3332
|
+
else {
|
3333
|
+
/*
|
3334
|
+
* len10 |---------------|
|
3335
|
+
* : :
|
3336
|
+
* decpt |-------| |--| ntz10 = prec * BASE_FIG - nlz10 - len10
|
3337
|
+
* : : :
|
3338
|
+
* 0.0000 00 dd dddd dddd dd 00
|
3339
|
+
* : : :
|
3340
|
+
* nlz10 |--| : decpt % BASE_FIG
|
3341
|
+
* prec |-----.----.----.-----| roomof(decpt + len10, BASE_FIG) - exp
|
3342
|
+
* exp |----| decpt / BASE_FIG
|
3343
|
+
*/
|
3344
|
+
decpt = -decpt;
|
3345
|
+
|
3346
|
+
const size_t nlz10 = decpt % BASE_FIG;
|
3347
|
+
exp = decpt / BASE_FIG;
|
3348
|
+
prec = roomof(decpt + len10, BASE_FIG) - exp;
|
3349
|
+
const size_t ntz10 = prec * BASE_FIG - nlz10 - len10;
|
3350
|
+
|
3351
|
+
if (nlz10 > 0) {
|
3352
|
+
memmove(buf + nlz10, buf, len10);
|
3353
|
+
memset(buf, '0', nlz10);
|
3354
|
+
}
|
3355
|
+
memset(buf + nlz10 + len10, '0', ntz10);
|
3356
|
+
buf[nlz10 + len10 + ntz10] = '\0';
|
3357
|
+
inum = rb_cstr_to_inum(buf, 10, false);
|
3358
|
+
|
3359
|
+
exp = -exp;
|
3360
|
+
}
|
3361
|
+
|
3362
|
+
VALUE bd = rb_inum_convert_to_BigDecimal(inum, SIZE_MAX, raise_exception);
|
3363
|
+
Real *vp;
|
3364
|
+
TypedData_Get_Struct(bd, Real, &BigDecimal_data_type, vp);
|
3365
|
+
assert(vp->Prec == prec);
|
3366
|
+
vp->exponent = exp;
|
3367
|
+
|
3368
|
+
if (negative_p) VpSetSign(vp, -1);
|
3369
|
+
return bd;
|
3370
|
+
}
|
3371
|
+
|
3372
|
+
static VALUE
|
3373
|
+
rb_rational_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
|
3374
|
+
{
|
3375
|
+
assert(RB_TYPE_P(val, T_RATIONAL));
|
3376
|
+
|
3377
|
+
if (digs == SIZE_MAX) {
|
3378
|
+
if (!raise_exception)
|
3379
|
+
return Qnil;
|
3380
|
+
rb_raise(rb_eArgError,
|
3381
|
+
"can't omit precision for a %"PRIsVALUE".",
|
3382
|
+
CLASS_OF(val));
|
3383
|
+
}
|
3384
|
+
|
3385
|
+
VALUE num = rb_inum_convert_to_BigDecimal(rb_rational_num(val), 0, raise_exception);
|
3386
|
+
VALUE d = BigDecimal_div2(num, rb_rational_den(val), SIZET2NUM(digs));
|
3387
|
+
return d;
|
3388
|
+
}
|
3389
|
+
|
3390
|
+
static VALUE
|
3391
|
+
rb_cstr_convert_to_BigDecimal(const char *c_str, size_t digs, int raise_exception)
|
3392
|
+
{
|
3393
|
+
if (digs == SIZE_MAX)
|
3394
|
+
digs = 0;
|
3395
|
+
|
3396
|
+
Real *vp = VpCreateRbObject(digs, c_str, raise_exception);
|
3397
|
+
if (!vp)
|
3398
|
+
return Qnil;
|
3399
|
+
return VpCheckGetValue(vp);
|
3400
|
+
}
|
3401
|
+
|
3402
|
+
static inline VALUE
|
3403
|
+
rb_str_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
|
3404
|
+
{
|
3405
|
+
const char *c_str = StringValueCStr(val);
|
3406
|
+
return rb_cstr_convert_to_BigDecimal(c_str, digs, raise_exception);
|
3407
|
+
}
|
3408
|
+
|
3409
|
+
static VALUE
|
3410
|
+
rb_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
|
3411
|
+
{
|
3412
|
+
switch (val) {
|
3413
|
+
case Qnil:
|
3414
|
+
case Qtrue:
|
3415
|
+
case Qfalse:
|
3416
|
+
if (raise_exception) {
|
3417
|
+
const char *cname = NIL_P(val) ? "nil" :
|
3418
|
+
val == Qtrue ? "true" :
|
3419
|
+
val == Qfalse ? "false" :
|
3420
|
+
NULL;
|
3421
|
+
rb_raise(rb_eTypeError,
|
3422
|
+
"can't convert %s into BigDecimal", cname);
|
3423
|
+
}
|
3424
|
+
return Qnil;
|
2717
3425
|
|
2718
|
-
case T_STRING:
|
2719
|
-
/* fall through */
|
2720
3426
|
default:
|
2721
|
-
|
3427
|
+
break;
|
3428
|
+
}
|
3429
|
+
|
3430
|
+
if (is_kind_of_BigDecimal(val)) {
|
3431
|
+
if (digs == SIZE_MAX)
|
3432
|
+
return check_exception(val);
|
3433
|
+
|
3434
|
+
Real *vp;
|
3435
|
+
TypedData_Get_Struct(val, Real, &BigDecimal_data_type, vp);
|
3436
|
+
|
3437
|
+
VALUE copy = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0);
|
3438
|
+
vp = VpCopy(NULL, vp);
|
3439
|
+
/* TODO: rounding */
|
3440
|
+
BigDecimal_wrap_struct(copy, vp);
|
3441
|
+
return VpCheckGetValue(vp);
|
3442
|
+
}
|
3443
|
+
else if (RB_INTEGER_TYPE_P(val)) {
|
3444
|
+
return rb_inum_convert_to_BigDecimal(val, digs, raise_exception);
|
3445
|
+
}
|
3446
|
+
else if (RB_FLOAT_TYPE_P(val)) {
|
3447
|
+
return rb_float_convert_to_BigDecimal(val, digs, raise_exception);
|
2722
3448
|
}
|
2723
|
-
|
2724
|
-
|
2725
|
-
iniValue = rb_check_convert_type(iniValue, T_STRING, "String", "to_str");
|
2726
|
-
if (NIL_P(iniValue)) return NULL;
|
3449
|
+
else if (RB_TYPE_P(val, T_RATIONAL)) {
|
3450
|
+
return rb_rational_convert_to_BigDecimal(val, digs, raise_exception);
|
2727
3451
|
}
|
2728
|
-
|
2729
|
-
|
3452
|
+
else if (RB_TYPE_P(val, T_COMPLEX)) {
|
3453
|
+
VALUE im = rb_complex_imag(val);
|
3454
|
+
if (!is_zero(im)) {
|
3455
|
+
/* TODO: handle raise_exception */
|
3456
|
+
rb_raise(rb_eArgError,
|
3457
|
+
"Unable to make a BigDecimal from non-zero imaginary number");
|
3458
|
+
}
|
3459
|
+
return rb_convert_to_BigDecimal(rb_complex_real(val), digs, raise_exception);
|
3460
|
+
}
|
3461
|
+
else if (RB_TYPE_P(val, T_STRING)) {
|
3462
|
+
return rb_str_convert_to_BigDecimal(val, digs, raise_exception);
|
3463
|
+
}
|
3464
|
+
|
3465
|
+
/* TODO: chheck to_d */
|
3466
|
+
/* TODO: chheck to_int */
|
3467
|
+
|
3468
|
+
VALUE str = rb_check_convert_type(val, T_STRING, "String", "to_str");
|
3469
|
+
if (!RB_TYPE_P(str, T_STRING)) {
|
3470
|
+
if (raise_exception) {
|
3471
|
+
rb_raise(rb_eTypeError,
|
3472
|
+
"can't convert %"PRIsVALUE" into BigDecimal", rb_obj_class(val));
|
3473
|
+
}
|
3474
|
+
return Qnil;
|
3475
|
+
}
|
3476
|
+
return rb_str_convert_to_BigDecimal(str, digs, raise_exception);
|
2730
3477
|
}
|
2731
3478
|
|
2732
|
-
/*
|
2733
|
-
*
|
3479
|
+
/* call-seq:
|
3480
|
+
* BigDecimal(value, exception: true) -> bigdecimal
|
3481
|
+
* BigDecimal(value, ndigits, exception: true) -> bigdecimal
|
2734
3482
|
*
|
2735
|
-
*
|
3483
|
+
* Returns the \BigDecimal converted from +value+
|
3484
|
+
* with a precision of +ndigits+ decimal digits.
|
2736
3485
|
*
|
2737
|
-
*
|
2738
|
-
*
|
3486
|
+
* When +ndigits+ is less than the number of significant digits
|
3487
|
+
* in the value, the result is rounded to that number of digits,
|
3488
|
+
* according to the current rounding mode; see BigDecimal.mode.
|
2739
3489
|
*
|
2740
|
-
*
|
2741
|
-
* terminate the value.
|
3490
|
+
* Returns +value+ converted to a \BigDecimal, depending on the type of +value+:
|
2742
3491
|
*
|
2743
|
-
*
|
2744
|
-
* the number of significant digits is determined from the initial
|
2745
|
-
* value.
|
3492
|
+
* - Integer, Float, Rational, Complex, or BigDecimal: converted directly:
|
2746
3493
|
*
|
2747
|
-
*
|
2748
|
-
*
|
3494
|
+
* # Integer, Complex, or BigDecimal value does not require ndigits; ignored if given.
|
3495
|
+
* BigDecimal(2) # => 0.2e1
|
3496
|
+
* BigDecimal(Complex(2, 0)) # => 0.2e1
|
3497
|
+
* BigDecimal(BigDecimal(2)) # => 0.2e1
|
3498
|
+
* # Float or Rational value requires ndigits.
|
3499
|
+
* BigDecimal(2.0, 0) # => 0.2e1
|
3500
|
+
* BigDecimal(Rational(2, 1), 0) # => 0.2e1
|
2749
3501
|
*
|
2750
|
-
*
|
2751
|
-
*
|
2752
|
-
* for invalid.
|
3502
|
+
* - String: converted by parsing if it contains an integer or floating-point literal;
|
3503
|
+
* leading and trailing whitespace is ignored:
|
2753
3504
|
*
|
3505
|
+
* # String does not require ndigits; ignored if given.
|
3506
|
+
* BigDecimal('2') # => 0.2e1
|
3507
|
+
* BigDecimal('2.0') # => 0.2e1
|
3508
|
+
* BigDecimal('0.2e1') # => 0.2e1
|
3509
|
+
* BigDecimal(' 2.0 ') # => 0.2e1
|
2754
3510
|
*
|
2755
|
-
*
|
3511
|
+
* - Other type that responds to method <tt>:to_str</tt>:
|
3512
|
+
* first converted to a string, then converted to a \BigDecimal, as above.
|
2756
3513
|
*
|
2757
|
-
*
|
2758
|
-
* Rational, nor BigDecimal, this exception is raised.
|
3514
|
+
* - Other type:
|
2759
3515
|
*
|
2760
|
-
*
|
3516
|
+
* - Raises an exception if keyword argument +exception+ is +true+.
|
3517
|
+
* - Returns +nil+ if keyword argument +exception+ is +true+.
|
2761
3518
|
*
|
2762
|
-
*
|
2763
|
-
*
|
3519
|
+
* Raises an exception if +value+ evaluates to a Float
|
3520
|
+
* and +digits+ is larger than Float::DIG + 1.
|
2764
3521
|
*
|
2765
|
-
* ArgumentError:: If the +initial+ is a Float or Rational, and the +digits+
|
2766
|
-
* value is omitted, this exception is raised.
|
2767
3522
|
*/
|
2768
3523
|
static VALUE
|
2769
3524
|
f_BigDecimal(int argc, VALUE *argv, VALUE self)
|
2770
3525
|
{
|
2771
|
-
|
2772
|
-
|
2773
|
-
|
2774
|
-
|
2775
|
-
|
2776
|
-
|
3526
|
+
VALUE val, digs_v, opts = Qnil;
|
3527
|
+
argc = rb_scan_args(argc, argv, "11:", &val, &digs_v, &opts);
|
3528
|
+
int exception = opts_exception_p(opts);
|
3529
|
+
|
3530
|
+
size_t digs = SIZE_MAX; /* this means digs is omitted */
|
3531
|
+
if (argc > 1) {
|
3532
|
+
digs_v = rb_to_int(digs_v);
|
3533
|
+
if (FIXNUM_P(digs_v)) {
|
3534
|
+
long n = FIX2LONG(digs_v);
|
3535
|
+
if (n < 0)
|
3536
|
+
goto negative_digs;
|
3537
|
+
digs = (size_t)n;
|
3538
|
+
}
|
3539
|
+
else {
|
3540
|
+
if (RBIGNUM_NEGATIVE_P(digs_v)) {
|
3541
|
+
negative_digs:
|
3542
|
+
if (!exception)
|
3543
|
+
return Qnil;
|
3544
|
+
rb_raise(rb_eArgError, "negative precision");
|
3545
|
+
}
|
3546
|
+
digs = NUM2SIZET(digs_v);
|
3547
|
+
}
|
2777
3548
|
}
|
2778
|
-
|
2779
|
-
|
2780
|
-
if (pv == NULL) return Qnil;
|
2781
|
-
SAVE(pv);
|
2782
|
-
if (ToValue(pv)) pv = VpCopy(NULL, pv);
|
2783
|
-
RTYPEDDATA_DATA(obj) = pv;
|
2784
|
-
RB_OBJ_FREEZE(obj);
|
2785
|
-
return pv->obj = obj;
|
3549
|
+
|
3550
|
+
return rb_convert_to_BigDecimal(val, digs, exception);
|
2786
3551
|
}
|
2787
3552
|
|
2788
3553
|
static VALUE
|
2789
3554
|
BigDecimal_s_interpret_loosely(VALUE klass, VALUE str)
|
2790
3555
|
{
|
2791
|
-
|
2792
|
-
|
2793
|
-
|
2794
|
-
|
2795
|
-
|
2796
|
-
|
2797
|
-
pv->obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, pv);
|
2798
|
-
RB_OBJ_FREEZE(pv->obj);
|
2799
|
-
return pv->obj;
|
3556
|
+
char const *c_str = StringValueCStr(str);
|
3557
|
+
Real *vp = VpNewRbClass(0, c_str, klass, false, true);
|
3558
|
+
if (!vp)
|
3559
|
+
return Qnil;
|
3560
|
+
else
|
3561
|
+
return VpCheckGetValue(vp);
|
2800
3562
|
}
|
2801
3563
|
|
2802
3564
|
/* call-seq:
|
@@ -2980,7 +3742,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
|
|
2980
3742
|
infinite = isinf(flo);
|
2981
3743
|
nan = isnan(flo);
|
2982
3744
|
if (!infinite && !nan) {
|
2983
|
-
vx = GetVpValueWithPrec(x,
|
3745
|
+
vx = GetVpValueWithPrec(x, 0, 0);
|
2984
3746
|
}
|
2985
3747
|
break;
|
2986
3748
|
|
@@ -2993,29 +3755,29 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
|
|
2993
3755
|
}
|
2994
3756
|
if (infinite) {
|
2995
3757
|
if (negative) {
|
2996
|
-
|
3758
|
+
return VpCheckGetValue(GetVpValueWithPrec(INT2FIX(0), prec, 1));
|
2997
3759
|
}
|
2998
3760
|
else {
|
2999
3761
|
Real* vy;
|
3000
|
-
|
3762
|
+
vy = VpCreateRbObject(prec, "#0", true);
|
3001
3763
|
VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
|
3002
3764
|
RB_GC_GUARD(vy->obj);
|
3003
|
-
|
3765
|
+
return VpCheckGetValue(vy);
|
3004
3766
|
}
|
3005
3767
|
}
|
3006
3768
|
else if (nan) {
|
3007
3769
|
Real* vy;
|
3008
|
-
|
3770
|
+
vy = VpCreateRbObject(prec, "#0", true);
|
3009
3771
|
VpSetNaN(vy);
|
3010
3772
|
RB_GC_GUARD(vy->obj);
|
3011
|
-
|
3773
|
+
return VpCheckGetValue(vy);
|
3012
3774
|
}
|
3013
3775
|
else if (vx == NULL) {
|
3014
3776
|
cannot_be_coerced_into_BigDecimal(rb_eArgError, x);
|
3015
3777
|
}
|
3016
3778
|
x = vx->obj;
|
3017
3779
|
|
3018
|
-
n = prec +
|
3780
|
+
n = prec + BIGDECIMAL_DOUBLE_FIGURES;
|
3019
3781
|
negative = BIGDECIMAL_NEGATIVE_P(vx);
|
3020
3782
|
if (negative) {
|
3021
3783
|
VALUE x_zero = INT2NUM(1);
|
@@ -3025,7 +3787,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
|
|
3025
3787
|
VpSetSign(vx, 1);
|
3026
3788
|
}
|
3027
3789
|
|
3028
|
-
one =
|
3790
|
+
one = VpCheckGetValue(VpCreateRbObject(1, "1", true));
|
3029
3791
|
y = one;
|
3030
3792
|
d = y;
|
3031
3793
|
i = 1;
|
@@ -3040,8 +3802,8 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
|
|
3040
3802
|
if (m <= 0) {
|
3041
3803
|
break;
|
3042
3804
|
}
|
3043
|
-
else if ((size_t)m <
|
3044
|
-
m =
|
3805
|
+
else if ((size_t)m < BIGDECIMAL_DOUBLE_FIGURES) {
|
3806
|
+
m = BIGDECIMAL_DOUBLE_FIGURES;
|
3045
3807
|
}
|
3046
3808
|
|
3047
3809
|
d = BigDecimal_mult(d, x); /* d <- d * x */
|
@@ -3133,7 +3895,7 @@ get_vp_value:
|
|
3133
3895
|
infinite = isinf(flo);
|
3134
3896
|
nan = isnan(flo);
|
3135
3897
|
if (!zero && !negative && !infinite && !nan) {
|
3136
|
-
vx = GetVpValueWithPrec(x,
|
3898
|
+
vx = GetVpValueWithPrec(x, 0, 1);
|
3137
3899
|
}
|
3138
3900
|
break;
|
3139
3901
|
|
@@ -3153,17 +3915,17 @@ get_vp_value:
|
|
3153
3915
|
}
|
3154
3916
|
if (infinite && !negative) {
|
3155
3917
|
Real* vy;
|
3156
|
-
|
3918
|
+
vy = VpCreateRbObject(prec, "#0", true);
|
3157
3919
|
RB_GC_GUARD(vy->obj);
|
3158
3920
|
VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
|
3159
|
-
|
3921
|
+
return VpCheckGetValue(vy);
|
3160
3922
|
}
|
3161
3923
|
else if (nan) {
|
3162
3924
|
Real* vy;
|
3163
|
-
|
3925
|
+
vy = VpCreateRbObject(prec, "#0", true);
|
3164
3926
|
RB_GC_GUARD(vy->obj);
|
3165
3927
|
VpSetNaN(vy);
|
3166
|
-
|
3928
|
+
return VpCheckGetValue(vy);
|
3167
3929
|
}
|
3168
3930
|
else if (zero || negative) {
|
3169
3931
|
rb_raise(rb_eMathDomainError,
|
@@ -3172,18 +3934,18 @@ get_vp_value:
|
|
3172
3934
|
else if (vx == NULL) {
|
3173
3935
|
cannot_be_coerced_into_BigDecimal(rb_eArgError, x);
|
3174
3936
|
}
|
3175
|
-
x =
|
3937
|
+
x = VpCheckGetValue(vx);
|
3176
3938
|
|
3177
|
-
RB_GC_GUARD(one) =
|
3178
|
-
RB_GC_GUARD(two) =
|
3939
|
+
RB_GC_GUARD(one) = VpCheckGetValue(VpCreateRbObject(1, "1", true));
|
3940
|
+
RB_GC_GUARD(two) = VpCheckGetValue(VpCreateRbObject(1, "2", true));
|
3179
3941
|
|
3180
|
-
n = prec +
|
3942
|
+
n = prec + BIGDECIMAL_DOUBLE_FIGURES;
|
3181
3943
|
RB_GC_GUARD(vn) = SSIZET2NUM(n);
|
3182
3944
|
expo = VpExponent10(vx);
|
3183
3945
|
if (expo < 0 || expo >= 3) {
|
3184
3946
|
char buf[DECIMAL_SIZE_OF_BITS(SIZEOF_VALUE * CHAR_BIT) + 4];
|
3185
3947
|
snprintf(buf, sizeof(buf), "1E%"PRIdVALUE, -expo);
|
3186
|
-
|
3948
|
+
x = BigDecimal_mult2(x, VpCheckGetValue(VpCreateRbObject(1, buf, true)), vn);
|
3187
3949
|
}
|
3188
3950
|
else {
|
3189
3951
|
expo = 0;
|
@@ -3201,8 +3963,8 @@ get_vp_value:
|
|
3201
3963
|
if (m <= 0) {
|
3202
3964
|
break;
|
3203
3965
|
}
|
3204
|
-
else if ((size_t)m <
|
3205
|
-
m =
|
3966
|
+
else if ((size_t)m < BIGDECIMAL_DOUBLE_FIGURES) {
|
3967
|
+
m = BIGDECIMAL_DOUBLE_FIGURES;
|
3206
3968
|
}
|
3207
3969
|
|
3208
3970
|
x = BigDecimal_mult2(x2, x, vn);
|
@@ -3215,7 +3977,7 @@ get_vp_value:
|
|
3215
3977
|
if (expo != 0) {
|
3216
3978
|
VALUE log10, vexpo, dy;
|
3217
3979
|
log10 = BigMath_s_log(klass, INT2FIX(10), vprec);
|
3218
|
-
|
3980
|
+
vexpo = VpCheckGetValue(GetVpValue(SSIZET2NUM(expo), 1));
|
3219
3981
|
dy = BigDecimal_mult(log10, vexpo);
|
3220
3982
|
y = BigDecimal_add(y, dy);
|
3221
3983
|
}
|
@@ -3223,6 +3985,46 @@ get_vp_value:
|
|
3223
3985
|
return y;
|
3224
3986
|
}
|
3225
3987
|
|
3988
|
+
static VALUE BIGDECIMAL_NAN = Qnil;
|
3989
|
+
|
3990
|
+
static VALUE
|
3991
|
+
BigDecimal_nan(void)
|
3992
|
+
{
|
3993
|
+
return BIGDECIMAL_NAN;
|
3994
|
+
}
|
3995
|
+
|
3996
|
+
static VALUE BIGDECIMAL_POSITIVE_INFINITY = Qnil;
|
3997
|
+
|
3998
|
+
static VALUE
|
3999
|
+
BigDecimal_positive_infinity(void)
|
4000
|
+
{
|
4001
|
+
return BIGDECIMAL_POSITIVE_INFINITY;
|
4002
|
+
}
|
4003
|
+
|
4004
|
+
static VALUE BIGDECIMAL_NEGATIVE_INFINITY = Qnil;
|
4005
|
+
|
4006
|
+
static VALUE
|
4007
|
+
BigDecimal_negative_infinity(void)
|
4008
|
+
{
|
4009
|
+
return BIGDECIMAL_NEGATIVE_INFINITY;
|
4010
|
+
}
|
4011
|
+
|
4012
|
+
static VALUE BIGDECIMAL_POSITIVE_ZERO = Qnil;
|
4013
|
+
|
4014
|
+
static VALUE
|
4015
|
+
BigDecimal_positive_zero(void)
|
4016
|
+
{
|
4017
|
+
return BIGDECIMAL_POSITIVE_ZERO;
|
4018
|
+
}
|
4019
|
+
|
4020
|
+
static VALUE BIGDECIMAL_NEGATIVE_ZERO = Qnil;
|
4021
|
+
|
4022
|
+
static VALUE
|
4023
|
+
BigDecimal_negative_zero(void)
|
4024
|
+
{
|
4025
|
+
return BIGDECIMAL_NEGATIVE_ZERO;
|
4026
|
+
}
|
4027
|
+
|
3226
4028
|
/* Document-class: BigDecimal
|
3227
4029
|
* BigDecimal provides arbitrary-precision floating point decimal arithmetic.
|
3228
4030
|
*
|
@@ -3266,6 +4068,18 @@ get_vp_value:
|
|
3266
4068
|
*
|
3267
4069
|
* (1.2 - 1.0) == 0.2 #=> false
|
3268
4070
|
*
|
4071
|
+
* == A Note About Precision
|
4072
|
+
*
|
4073
|
+
* For a calculation using a \BigDecimal and another +value+,
|
4074
|
+
* the precision of the result depends on the type of +value+:
|
4075
|
+
*
|
4076
|
+
* - If +value+ is a \Float,
|
4077
|
+
* the precision is Float::DIG + 1.
|
4078
|
+
* - If +value+ is a \Rational, the precision is larger than Float::DIG + 1.
|
4079
|
+
* - If +value+ is a \BigDecimal, the precision is +value+'s precision in the
|
4080
|
+
* internal representation, which is platform-dependent.
|
4081
|
+
* - If +value+ is other object, the precision is determined by the result of +BigDecimal(value)+.
|
4082
|
+
*
|
3269
4083
|
* == Special features of accurate decimal arithmetic
|
3270
4084
|
*
|
3271
4085
|
* Because BigDecimal is more accurate than normal binary floating point
|
@@ -3351,6 +4165,9 @@ get_vp_value:
|
|
3351
4165
|
void
|
3352
4166
|
Init_bigdecimal(void)
|
3353
4167
|
{
|
4168
|
+
#ifdef HAVE_RB_EXT_RACTOR_SAFE
|
4169
|
+
rb_ext_ractor_safe(true);
|
4170
|
+
#endif
|
3354
4171
|
VALUE arg;
|
3355
4172
|
|
3356
4173
|
id_BigDecimal_exception_mode = rb_intern_const("BigDecimal.exception_mode");
|
@@ -3367,7 +4184,7 @@ Init_bigdecimal(void)
|
|
3367
4184
|
rb_define_global_function("BigDecimal", f_BigDecimal, -1);
|
3368
4185
|
|
3369
4186
|
/* Class methods */
|
3370
|
-
|
4187
|
+
rb_undef_alloc_func(rb_cBigDecimal);
|
3371
4188
|
rb_undef_method(CLASS_OF(rb_cBigDecimal), "new");
|
3372
4189
|
rb_define_singleton_method(rb_cBigDecimal, "interpret_loosely", BigDecimal_s_interpret_loosely, 1);
|
3373
4190
|
rb_define_singleton_method(rb_cBigDecimal, "mode", BigDecimal_mode, -1);
|
@@ -3491,16 +4308,41 @@ Init_bigdecimal(void)
|
|
3491
4308
|
/* -3: Indicates that a value is negative and infinite. See BigDecimal.sign. */
|
3492
4309
|
rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_INFINITE", INT2FIX(VP_SIGN_NEGATIVE_INFINITE));
|
3493
4310
|
|
3494
|
-
|
4311
|
+
/* Positive zero value. */
|
4312
|
+
arg = rb_str_new2("+0");
|
4313
|
+
BIGDECIMAL_POSITIVE_ZERO = f_BigDecimal(1, &arg, rb_cBigDecimal);
|
4314
|
+
rb_gc_register_mark_object(BIGDECIMAL_POSITIVE_ZERO);
|
4315
|
+
|
4316
|
+
/* Negative zero value. */
|
4317
|
+
arg = rb_str_new2("-0");
|
4318
|
+
BIGDECIMAL_NEGATIVE_ZERO = f_BigDecimal(1, &arg, rb_cBigDecimal);
|
4319
|
+
rb_gc_register_mark_object(BIGDECIMAL_NEGATIVE_ZERO);
|
4320
|
+
|
3495
4321
|
/* Positive infinity value. */
|
3496
|
-
|
3497
|
-
|
4322
|
+
arg = rb_str_new2("+Infinity");
|
4323
|
+
BIGDECIMAL_POSITIVE_INFINITY = f_BigDecimal(1, &arg, rb_cBigDecimal);
|
4324
|
+
rb_gc_register_mark_object(BIGDECIMAL_POSITIVE_INFINITY);
|
4325
|
+
|
4326
|
+
/* Negative infinity value. */
|
4327
|
+
arg = rb_str_new2("-Infinity");
|
4328
|
+
BIGDECIMAL_NEGATIVE_INFINITY = f_BigDecimal(1, &arg, rb_cBigDecimal);
|
4329
|
+
rb_gc_register_mark_object(BIGDECIMAL_NEGATIVE_INFINITY);
|
4330
|
+
|
3498
4331
|
/* 'Not a Number' value. */
|
3499
|
-
|
4332
|
+
arg = rb_str_new2("NaN");
|
4333
|
+
BIGDECIMAL_NAN = f_BigDecimal(1, &arg, rb_cBigDecimal);
|
4334
|
+
rb_gc_register_mark_object(BIGDECIMAL_NAN);
|
3500
4335
|
|
4336
|
+
/* Special value constants */
|
4337
|
+
rb_define_const(rb_cBigDecimal, "INFINITY", BIGDECIMAL_POSITIVE_INFINITY);
|
4338
|
+
rb_define_const(rb_cBigDecimal, "NAN", BIGDECIMAL_NAN);
|
3501
4339
|
|
3502
4340
|
/* instance methods */
|
3503
4341
|
rb_define_method(rb_cBigDecimal, "precs", BigDecimal_prec, 0);
|
4342
|
+
rb_define_method(rb_cBigDecimal, "precision", BigDecimal_precision, 0);
|
4343
|
+
rb_define_method(rb_cBigDecimal, "scale", BigDecimal_scale, 0);
|
4344
|
+
rb_define_method(rb_cBigDecimal, "precision_scale", BigDecimal_precision_scale, 0);
|
4345
|
+
rb_define_method(rb_cBigDecimal, "n_significant_digits", BigDecimal_n_significant_digits, 0);
|
3504
4346
|
|
3505
4347
|
rb_define_method(rb_cBigDecimal, "add", BigDecimal_add2, 2);
|
3506
4348
|
rb_define_method(rb_cBigDecimal, "sub", BigDecimal_sub2, 2);
|
@@ -3518,7 +4360,7 @@ Init_bigdecimal(void)
|
|
3518
4360
|
rb_define_method(rb_cBigDecimal, "-@", BigDecimal_neg, 0);
|
3519
4361
|
rb_define_method(rb_cBigDecimal, "*", BigDecimal_mult, 1);
|
3520
4362
|
rb_define_method(rb_cBigDecimal, "/", BigDecimal_div, 1);
|
3521
|
-
rb_define_method(rb_cBigDecimal, "quo",
|
4363
|
+
rb_define_method(rb_cBigDecimal, "quo", BigDecimal_quo, -1);
|
3522
4364
|
rb_define_method(rb_cBigDecimal, "%", BigDecimal_mod, 1);
|
3523
4365
|
rb_define_method(rb_cBigDecimal, "modulo", BigDecimal_mod, 1);
|
3524
4366
|
rb_define_method(rb_cBigDecimal, "remainder", BigDecimal_remainder, 1);
|
@@ -3609,14 +4451,17 @@ enum op_sw {
|
|
3609
4451
|
|
3610
4452
|
static int VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw);
|
3611
4453
|
static int AddExponent(Real *a, SIGNED_VALUE n);
|
3612
|
-
static
|
3613
|
-
static
|
3614
|
-
static size_t VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos,
|
4454
|
+
static DECDIG VpAddAbs(Real *a,Real *b,Real *c);
|
4455
|
+
static DECDIG VpSubAbs(Real *a,Real *b,Real *c);
|
4456
|
+
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);
|
3615
4457
|
static int VpNmlz(Real *a);
|
3616
4458
|
static void VpFormatSt(char *psz, size_t fFmt);
|
3617
4459
|
static int VpRdup(Real *m, size_t ind_m);
|
3618
4460
|
|
3619
4461
|
#ifdef BIGDECIMAL_DEBUG
|
4462
|
+
# ifdef HAVE_RB_EXT_RACTOR_SAFE
|
4463
|
+
# error Need to make rewiting gnAlloc atomic
|
4464
|
+
# endif
|
3620
4465
|
static int gnAlloc = 0; /* Memory allocation counter */
|
3621
4466
|
#endif /* BIGDECIMAL_DEBUG */
|
3622
4467
|
|
@@ -3624,9 +4469,6 @@ VP_EXPORT void *
|
|
3624
4469
|
VpMemAlloc(size_t mb)
|
3625
4470
|
{
|
3626
4471
|
void *p = xmalloc(mb);
|
3627
|
-
if (!p) {
|
3628
|
-
VpException(VP_EXCEPTION_MEMORY, "failed to allocate memory", 1);
|
3629
|
-
}
|
3630
4472
|
memset(p, 0, mb);
|
3631
4473
|
#ifdef BIGDECIMAL_DEBUG
|
3632
4474
|
gnAlloc++; /* Count allocation call */
|
@@ -3637,11 +4479,7 @@ VpMemAlloc(size_t mb)
|
|
3637
4479
|
VP_EXPORT void *
|
3638
4480
|
VpMemRealloc(void *ptr, size_t mb)
|
3639
4481
|
{
|
3640
|
-
|
3641
|
-
if (!p) {
|
3642
|
-
VpException(VP_EXCEPTION_MEMORY, "failed to allocate memory", 1);
|
3643
|
-
}
|
3644
|
-
return p;
|
4482
|
+
return xrealloc(ptr, mb);
|
3645
4483
|
}
|
3646
4484
|
|
3647
4485
|
VP_EXPORT void
|
@@ -3667,7 +4505,7 @@ VpFree(Real *pv)
|
|
3667
4505
|
* EXCEPTION Handling.
|
3668
4506
|
*/
|
3669
4507
|
|
3670
|
-
#define
|
4508
|
+
#define bigdecimal_set_thread_local_exception_mode(mode) \
|
3671
4509
|
rb_thread_local_aset( \
|
3672
4510
|
rb_thread_current(), \
|
3673
4511
|
id_BigDecimal_exception_mode, \
|
@@ -3683,8 +4521,8 @@ VpGetException (void)
|
|
3683
4521
|
);
|
3684
4522
|
|
3685
4523
|
if (NIL_P(vmode)) {
|
3686
|
-
|
3687
|
-
return
|
4524
|
+
bigdecimal_set_thread_local_exception_mode(BIGDECIMAL_EXCEPTION_MODE_DEFAULT);
|
4525
|
+
return BIGDECIMAL_EXCEPTION_MODE_DEFAULT;
|
3688
4526
|
}
|
3689
4527
|
|
3690
4528
|
return NUM2USHORT(vmode);
|
@@ -3693,20 +4531,41 @@ VpGetException (void)
|
|
3693
4531
|
static void
|
3694
4532
|
VpSetException(unsigned short f)
|
3695
4533
|
{
|
3696
|
-
|
4534
|
+
bigdecimal_set_thread_local_exception_mode(f);
|
4535
|
+
}
|
4536
|
+
|
4537
|
+
static void
|
4538
|
+
VpCheckException(Real *p, bool always)
|
4539
|
+
{
|
4540
|
+
if (VpIsNaN(p)) {
|
4541
|
+
VpException(VP_EXCEPTION_NaN, "Computation results in 'NaN' (Not a Number)", always);
|
4542
|
+
}
|
4543
|
+
else if (VpIsPosInf(p)) {
|
4544
|
+
VpException(VP_EXCEPTION_INFINITY, "Computation results in 'Infinity'", always);
|
4545
|
+
}
|
4546
|
+
else if (VpIsNegInf(p)) {
|
4547
|
+
VpException(VP_EXCEPTION_INFINITY, "Computation results in '-Infinity'", always);
|
4548
|
+
}
|
4549
|
+
}
|
4550
|
+
|
4551
|
+
static VALUE
|
4552
|
+
VpCheckGetValue(Real *p)
|
4553
|
+
{
|
4554
|
+
VpCheckException(p, false);
|
4555
|
+
return p->obj;
|
3697
4556
|
}
|
3698
4557
|
|
3699
4558
|
/*
|
3700
4559
|
* Precision limit.
|
3701
4560
|
*/
|
3702
4561
|
|
3703
|
-
#define
|
4562
|
+
#define bigdecimal_set_thread_local_precision_limit(limit) \
|
3704
4563
|
rb_thread_local_aset( \
|
3705
4564
|
rb_thread_current(), \
|
3706
4565
|
id_BigDecimal_precision_limit, \
|
3707
4566
|
SIZET2NUM(limit) \
|
3708
4567
|
)
|
3709
|
-
#define
|
4568
|
+
#define BIGDECIMAL_PRECISION_LIMIT_DEFAULT ((size_t)0)
|
3710
4569
|
|
3711
4570
|
/* These 2 functions added at v1.1.7 */
|
3712
4571
|
VP_EXPORT size_t
|
@@ -3718,8 +4577,8 @@ VpGetPrecLimit(void)
|
|
3718
4577
|
);
|
3719
4578
|
|
3720
4579
|
if (NIL_P(vlimit)) {
|
3721
|
-
|
3722
|
-
return
|
4580
|
+
bigdecimal_set_thread_local_precision_limit(BIGDECIMAL_PRECISION_LIMIT_DEFAULT);
|
4581
|
+
return BIGDECIMAL_PRECISION_LIMIT_DEFAULT;
|
3723
4582
|
}
|
3724
4583
|
|
3725
4584
|
return NUM2SIZET(vlimit);
|
@@ -3729,7 +4588,7 @@ VP_EXPORT size_t
|
|
3729
4588
|
VpSetPrecLimit(size_t n)
|
3730
4589
|
{
|
3731
4590
|
size_t const s = VpGetPrecLimit();
|
3732
|
-
|
4591
|
+
bigdecimal_set_thread_local_precision_limit(n);
|
3733
4592
|
return s;
|
3734
4593
|
}
|
3735
4594
|
|
@@ -3737,7 +4596,7 @@ VpSetPrecLimit(size_t n)
|
|
3737
4596
|
* Rounding mode.
|
3738
4597
|
*/
|
3739
4598
|
|
3740
|
-
#define
|
4599
|
+
#define bigdecimal_set_thread_local_rounding_mode(mode) \
|
3741
4600
|
rb_thread_local_aset( \
|
3742
4601
|
rb_thread_current(), \
|
3743
4602
|
id_BigDecimal_rounding_mode, \
|
@@ -3753,8 +4612,8 @@ VpGetRoundMode(void)
|
|
3753
4612
|
);
|
3754
4613
|
|
3755
4614
|
if (NIL_P(vmode)) {
|
3756
|
-
|
3757
|
-
return
|
4615
|
+
bigdecimal_set_thread_local_rounding_mode(BIGDECIMAL_ROUNDING_MODE_DEFAULT);
|
4616
|
+
return BIGDECIMAL_ROUNDING_MODE_DEFAULT;
|
3758
4617
|
}
|
3759
4618
|
|
3760
4619
|
return NUM2USHORT(vmode);
|
@@ -3782,7 +4641,7 @@ VP_EXPORT unsigned short
|
|
3782
4641
|
VpSetRoundMode(unsigned short n)
|
3783
4642
|
{
|
3784
4643
|
if (VpIsRoundMode(n)) {
|
3785
|
-
|
4644
|
+
bigdecimal_set_thread_local_rounding_mode(n);
|
3786
4645
|
return n;
|
3787
4646
|
}
|
3788
4647
|
|
@@ -3859,7 +4718,7 @@ VpException(unsigned short f, const char *str,int always)
|
|
3859
4718
|
{
|
3860
4719
|
unsigned short const exception_mode = VpGetException();
|
3861
4720
|
|
3862
|
-
if (f == VP_EXCEPTION_OP
|
4721
|
+
if (f == VP_EXCEPTION_OP) always = 1;
|
3863
4722
|
|
3864
4723
|
if (always || (exception_mode & f)) {
|
3865
4724
|
switch(f) {
|
@@ -3871,7 +4730,6 @@ VpException(unsigned short f, const char *str,int always)
|
|
3871
4730
|
case VP_EXCEPTION_OP:
|
3872
4731
|
rb_raise(rb_eFloatDomainError, "%s", str);
|
3873
4732
|
break;
|
3874
|
-
case VP_EXCEPTION_MEMORY:
|
3875
4733
|
default:
|
3876
4734
|
rb_fatal("%s", str);
|
3877
4735
|
}
|
@@ -4020,13 +4878,13 @@ VpNumOfChars(Real *vp,const char *pszFmt)
|
|
4020
4878
|
* that BASE is as large as possible satisfying the
|
4021
4879
|
* relation MaxVal <= BASE*(BASE+1). Where the value
|
4022
4880
|
* MaxVal is the largest value which can be represented
|
4023
|
-
* by one
|
4881
|
+
* by one DECDIG word in the computer used.
|
4024
4882
|
*
|
4025
4883
|
* [Returns]
|
4026
|
-
*
|
4884
|
+
* BIGDECIMAL_DOUBLE_FIGURES ... OK
|
4027
4885
|
*/
|
4028
4886
|
VP_EXPORT size_t
|
4029
|
-
VpInit(
|
4887
|
+
VpInit(DECDIG BaseVal)
|
4030
4888
|
{
|
4031
4889
|
/* Setup +/- Inf NaN -0 */
|
4032
4890
|
VpGetDoubleNegZero();
|
@@ -4041,16 +4899,16 @@ VpInit(BDIGIT BaseVal)
|
|
4041
4899
|
|
4042
4900
|
#ifdef BIGDECIMAL_DEBUG
|
4043
4901
|
if (gfDebug) {
|
4044
|
-
|
4045
|
-
|
4046
|
-
|
4047
|
-
|
4048
|
-
|
4049
|
-
|
4902
|
+
printf("VpInit: BaseVal = %"PRIuDECDIG"\n", BaseVal);
|
4903
|
+
printf("\tBASE = %"PRIuDECDIG"\n", BASE);
|
4904
|
+
printf("\tHALF_BASE = %"PRIuDECDIG"\n", HALF_BASE);
|
4905
|
+
printf("\tBASE1 = %"PRIuDECDIG"\n", BASE1);
|
4906
|
+
printf("\tBASE_FIG = %u\n", BASE_FIG);
|
4907
|
+
printf("\tBIGDECIMAL_DOUBLE_FIGURES = %d\n", BIGDECIMAL_DOUBLE_FIGURES);
|
4050
4908
|
}
|
4051
4909
|
#endif /* BIGDECIMAL_DEBUG */
|
4052
4910
|
|
4053
|
-
return
|
4911
|
+
return BIGDECIMAL_DOUBLE_FIGURES;
|
4054
4912
|
}
|
4055
4913
|
|
4056
4914
|
VP_EXPORT Real *
|
@@ -4098,7 +4956,7 @@ overflow:
|
|
4098
4956
|
}
|
4099
4957
|
|
4100
4958
|
Real *
|
4101
|
-
|
4959
|
+
bigdecimal_parse_special_string(const char *str)
|
4102
4960
|
{
|
4103
4961
|
static const struct {
|
4104
4962
|
const char *str;
|
@@ -4193,14 +5051,13 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
|
|
4193
5051
|
/* at least mx digits. */
|
4194
5052
|
/* szVal==NULL ==> allocate zero value. */
|
4195
5053
|
vp = VpAllocReal(mx);
|
4196
|
-
/* xmalloc() always returns(or throw interruption) */
|
4197
5054
|
vp->MaxPrec = mx; /* set max precision */
|
4198
5055
|
VpSetZero(vp, 1); /* initialize vp to zero. */
|
4199
5056
|
return vp;
|
4200
5057
|
}
|
4201
5058
|
|
4202
5059
|
/* Check on Inf & NaN */
|
4203
|
-
if ((vp =
|
5060
|
+
if ((vp = bigdecimal_parse_special_string(szVal)) != NULL) {
|
4204
5061
|
return vp;
|
4205
5062
|
}
|
4206
5063
|
|
@@ -4369,7 +5226,6 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
|
|
4369
5226
|
nalloc = Max(nalloc, mx);
|
4370
5227
|
mx = nalloc;
|
4371
5228
|
vp = VpAllocReal(mx);
|
4372
|
-
/* xmalloc() always returns(or throw interruption) */
|
4373
5229
|
vp->MaxPrec = mx; /* set max precision */
|
4374
5230
|
VpSetZero(vp, sign);
|
4375
5231
|
VpCtoV(vp, psz, ni, psz + ipf, nf, psz + ipe, ne);
|
@@ -4408,7 +5264,7 @@ VpAsgn(Real *c, Real *a, int isw)
|
|
4408
5264
|
VpSetSign(c, isw * VpGetSign(a)); /* set sign */
|
4409
5265
|
n = (a->Prec < c->MaxPrec) ? (a->Prec) : (c->MaxPrec);
|
4410
5266
|
c->Prec = n;
|
4411
|
-
|
5267
|
+
memcpy(c->frac, a->frac, n * sizeof(DECDIG));
|
4412
5268
|
/* Needs round ? */
|
4413
5269
|
if (isw != 10) {
|
4414
5270
|
/* Not in ActiveRound */
|
@@ -4439,7 +5295,7 @@ VpAddSub(Real *c, Real *a, Real *b, int operation)
|
|
4439
5295
|
short sw, isw;
|
4440
5296
|
Real *a_ptr, *b_ptr;
|
4441
5297
|
size_t n, na, nb, i;
|
4442
|
-
|
5298
|
+
DECDIG mrv;
|
4443
5299
|
|
4444
5300
|
#ifdef BIGDECIMAL_DEBUG
|
4445
5301
|
if (gfDebug) {
|
@@ -4567,7 +5423,7 @@ end_if:
|
|
4567
5423
|
* a and b assuming abs(a)>abs(b).
|
4568
5424
|
* c = abs(a) + abs(b) ; where |a|>=|b|
|
4569
5425
|
*/
|
4570
|
-
static
|
5426
|
+
static DECDIG
|
4571
5427
|
VpAddAbs(Real *a, Real *b, Real *c)
|
4572
5428
|
{
|
4573
5429
|
size_t word_shift;
|
@@ -4577,7 +5433,7 @@ VpAddAbs(Real *a, Real *b, Real *c)
|
|
4577
5433
|
size_t a_pos;
|
4578
5434
|
size_t b_pos, b_pos_with_word_shift;
|
4579
5435
|
size_t c_pos;
|
4580
|
-
|
5436
|
+
DECDIG av, bv, carry, mrv;
|
4581
5437
|
|
4582
5438
|
#ifdef BIGDECIMAL_DEBUG
|
4583
5439
|
if (gfDebug) {
|
@@ -4662,7 +5518,7 @@ Exit:
|
|
4662
5518
|
/*
|
4663
5519
|
* c = abs(a) - abs(b)
|
4664
5520
|
*/
|
4665
|
-
static
|
5521
|
+
static DECDIG
|
4666
5522
|
VpSubAbs(Real *a, Real *b, Real *c)
|
4667
5523
|
{
|
4668
5524
|
size_t word_shift;
|
@@ -4672,7 +5528,7 @@ VpSubAbs(Real *a, Real *b, Real *c)
|
|
4672
5528
|
size_t a_pos;
|
4673
5529
|
size_t b_pos, b_pos_with_word_shift;
|
4674
5530
|
size_t c_pos;
|
4675
|
-
|
5531
|
+
DECDIG av, bv, borrow, mrv;
|
4676
5532
|
|
4677
5533
|
#ifdef BIGDECIMAL_DEBUG
|
4678
5534
|
if (gfDebug) {
|
@@ -4779,7 +5635,7 @@ Exit:
|
|
4779
5635
|
* c_pos = |
|
4780
5636
|
*/
|
4781
5637
|
static size_t
|
4782
|
-
VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos,
|
5638
|
+
VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos, DECDIG *av, DECDIG *bv)
|
4783
5639
|
{
|
4784
5640
|
size_t left_word, right_word, word_shift;
|
4785
5641
|
|
@@ -4894,8 +5750,8 @@ VpMult(Real *c, Real *a, Real *b)
|
|
4894
5750
|
size_t MxIndA, MxIndB, MxIndAB, MxIndC;
|
4895
5751
|
size_t ind_c, i, ii, nc;
|
4896
5752
|
size_t ind_as, ind_ae, ind_bs;
|
4897
|
-
|
4898
|
-
|
5753
|
+
DECDIG carry;
|
5754
|
+
DECDIG_DBL s;
|
4899
5755
|
Real *w;
|
4900
5756
|
|
4901
5757
|
#ifdef BIGDECIMAL_DEBUG
|
@@ -4949,7 +5805,7 @@ VpMult(Real *c, Real *a, Real *b)
|
|
4949
5805
|
VpSetSign(c, VpGetSign(a) * VpGetSign(b)); /* set sign */
|
4950
5806
|
carry = 0;
|
4951
5807
|
nc = ind_c = MxIndAB;
|
4952
|
-
memset(c->frac, 0, (nc + 1) * sizeof(
|
5808
|
+
memset(c->frac, 0, (nc + 1) * sizeof(DECDIG)); /* Initialize c */
|
4953
5809
|
c->Prec = nc + 1; /* set precision */
|
4954
5810
|
for (nc = 0; nc < MxIndAB; ++nc, --ind_c) {
|
4955
5811
|
if (nc < MxIndB) { /* The left triangle of the Fig. */
|
@@ -4969,15 +5825,15 @@ VpMult(Real *c, Real *a, Real *b)
|
|
4969
5825
|
}
|
4970
5826
|
|
4971
5827
|
for (i = ind_as; i <= ind_ae; ++i) {
|
4972
|
-
|
4973
|
-
|
4974
|
-
|
4975
|
-
|
4976
|
-
|
4977
|
-
|
4978
|
-
|
4979
|
-
|
4980
|
-
|
5828
|
+
s = (DECDIG_DBL)a->frac[i] * b->frac[ind_bs--];
|
5829
|
+
carry = (DECDIG)(s / BASE);
|
5830
|
+
s -= (DECDIG_DBL)carry * BASE;
|
5831
|
+
c->frac[ind_c] += (DECDIG)s;
|
5832
|
+
if (c->frac[ind_c] >= BASE) {
|
5833
|
+
s = c->frac[ind_c] / BASE;
|
5834
|
+
carry += (DECDIG)s;
|
5835
|
+
c->frac[ind_c] -= (DECDIG)(s * BASE);
|
5836
|
+
}
|
4981
5837
|
if (carry) {
|
4982
5838
|
ii = ind_c;
|
4983
5839
|
while (ii-- > 0) {
|
@@ -5023,9 +5879,9 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
|
|
5023
5879
|
size_t word_a, word_b, word_c, word_r;
|
5024
5880
|
size_t i, n, ind_a, ind_b, ind_c, ind_r;
|
5025
5881
|
size_t nLoop;
|
5026
|
-
|
5027
|
-
|
5028
|
-
|
5882
|
+
DECDIG_DBL q, b1, b1p1, b1b2, b1b2p1, r1r2;
|
5883
|
+
DECDIG borrow, borrow1, borrow2;
|
5884
|
+
DECDIG_DBL qb;
|
5029
5885
|
|
5030
5886
|
#ifdef BIGDECIMAL_DEBUG
|
5031
5887
|
if (gfDebug) {
|
@@ -5097,7 +5953,7 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
|
|
5097
5953
|
++ind_c;
|
5098
5954
|
continue;
|
5099
5955
|
}
|
5100
|
-
|
5956
|
+
r1r2 = (DECDIG_DBL)r->frac[ind_c] * BASE + r->frac[ind_c + 1];
|
5101
5957
|
if (r1r2 == b1b2) {
|
5102
5958
|
/* The first two word digits is the same */
|
5103
5959
|
ind_b = 2;
|
@@ -5134,17 +5990,17 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
|
|
5134
5990
|
/* The first two word digits is not the same, */
|
5135
5991
|
/* then compare magnitude, and divide actually. */
|
5136
5992
|
if (r1r2 >= b1b2p1) {
|
5137
|
-
|
5138
|
-
|
5139
|
-
|
5140
|
-
|
5993
|
+
q = r1r2 / b1b2p1; /* q == (DECDIG)q */
|
5994
|
+
c->frac[ind_c] += (DECDIG)q;
|
5995
|
+
ind_r = b->Prec + ind_c - 1;
|
5996
|
+
goto sub_mult;
|
5141
5997
|
}
|
5142
5998
|
|
5143
5999
|
div_b1p1:
|
5144
|
-
|
5145
|
-
|
5146
|
-
|
5147
|
-
|
6000
|
+
if (ind_c + 1 >= word_c) goto out_side;
|
6001
|
+
q = r1r2 / b1p1; /* q == (DECDIG)q */
|
6002
|
+
c->frac[ind_c + 1] += (DECDIG)q;
|
6003
|
+
ind_r = b->Prec + ind_c;
|
5148
6004
|
|
5149
6005
|
sub_mult:
|
5150
6006
|
borrow1 = borrow2 = 0;
|
@@ -5156,16 +6012,16 @@ sub_mult:
|
|
5156
6012
|
qb = q * b->frac[ind_b];
|
5157
6013
|
if (qb < BASE) borrow1 = 0;
|
5158
6014
|
else {
|
5159
|
-
|
5160
|
-
|
6015
|
+
borrow1 = (DECDIG)(qb / BASE);
|
6016
|
+
qb -= (DECDIG_DBL)borrow1 * BASE; /* get qb < BASE */
|
5161
6017
|
}
|
5162
6018
|
if(r->frac[ind_r] < qb) {
|
5163
|
-
|
5164
|
-
|
6019
|
+
r->frac[ind_r] += (DECDIG)(BASE - qb);
|
6020
|
+
borrow2 = borrow2 + borrow1 + 1;
|
5165
6021
|
}
|
5166
6022
|
else {
|
5167
|
-
|
5168
|
-
|
6023
|
+
r->frac[ind_r] -= (DECDIG)qb;
|
6024
|
+
borrow2 += borrow1;
|
5169
6025
|
}
|
5170
6026
|
if (borrow2) {
|
5171
6027
|
if(r->frac[ind_r - 1] < borrow2) {
|
@@ -5247,9 +6103,9 @@ VpNmlz(Real *a)
|
|
5247
6103
|
i = 0;
|
5248
6104
|
while (a->frac[i] == 0) ++i; /* skip the first few zeros */
|
5249
6105
|
if (i) {
|
5250
|
-
|
5251
|
-
|
5252
|
-
|
6106
|
+
a->Prec -= i;
|
6107
|
+
if (!AddExponent(a, -(SIGNED_VALUE)i)) return 0;
|
6108
|
+
memmove(&a->frac[0], &a->frac[i], a->Prec*sizeof(DECDIG));
|
5253
6109
|
}
|
5254
6110
|
return 1;
|
5255
6111
|
}
|
@@ -5372,7 +6228,7 @@ static int
|
|
5372
6228
|
VPrint(FILE *fp, const char *cntl_chr, Real *a)
|
5373
6229
|
{
|
5374
6230
|
size_t i, j, nc, nd, ZeroSup, sep = 10;
|
5375
|
-
|
6231
|
+
DECDIG m, e, nn;
|
5376
6232
|
|
5377
6233
|
j = 0;
|
5378
6234
|
nd = nc = 0; /* nd : number of digits in fraction part(every 10 digits, */
|
@@ -5407,7 +6263,7 @@ VPrint(FILE *fp, const char *cntl_chr, Real *a)
|
|
5407
6263
|
case '0': case 'z':
|
5408
6264
|
ZeroSup = 0;
|
5409
6265
|
++j;
|
5410
|
-
sep = cntl_chr[j] == 'z' ?
|
6266
|
+
sep = cntl_chr[j] == 'z' ? BIGDECIMAL_COMPONENT_FIGURES : 10;
|
5411
6267
|
break;
|
5412
6268
|
}
|
5413
6269
|
for (i = 0; i < a->Prec; ++i) {
|
@@ -5516,7 +6372,7 @@ VP_EXPORT void
|
|
5516
6372
|
VpSzMantissa(Real *a,char *psz)
|
5517
6373
|
{
|
5518
6374
|
size_t i, n, ZeroSup;
|
5519
|
-
|
6375
|
+
DECDIG_DBL m, e, nn;
|
5520
6376
|
|
5521
6377
|
if (VpIsNaN(a)) {
|
5522
6378
|
sprintf(psz, SZ_NaN);
|
@@ -5599,7 +6455,7 @@ VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
|
|
5599
6455
|
/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
|
5600
6456
|
{
|
5601
6457
|
size_t i, n, ZeroSup;
|
5602
|
-
|
6458
|
+
DECDIG shift, m, e, nn;
|
5603
6459
|
char *pszSav = psz;
|
5604
6460
|
ssize_t ex;
|
5605
6461
|
|
@@ -5647,7 +6503,7 @@ VpToFString(Real *a, char *psz, size_t fFmt, int fPlus)
|
|
5647
6503
|
/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
|
5648
6504
|
{
|
5649
6505
|
size_t i, n;
|
5650
|
-
|
6506
|
+
DECDIG m, e, nn;
|
5651
6507
|
char *pszSav = psz;
|
5652
6508
|
ssize_t ex;
|
5653
6509
|
|
@@ -5722,7 +6578,7 @@ VpCtoV(Real *a, const char *int_chr, size_t ni, const char *frac, size_t nf, con
|
|
5722
6578
|
me = ne;
|
5723
6579
|
signe = 1;
|
5724
6580
|
exponent_overflow = 0;
|
5725
|
-
memset(a->frac, 0, ma * sizeof(
|
6581
|
+
memset(a->frac, 0, ma * sizeof(DECDIG));
|
5726
6582
|
if (ne > 0) {
|
5727
6583
|
i = 0;
|
5728
6584
|
if (exp_chr[0] == '-') {
|
@@ -5859,7 +6715,7 @@ Final:
|
|
5859
6715
|
* [Output]
|
5860
6716
|
* *d ... fraction part of m(d = 0.xxxxxxx). where # of 'x's is fig.
|
5861
6717
|
* *e ... exponent of m.
|
5862
|
-
*
|
6718
|
+
* BIGDECIMAL_DOUBLE_FIGURES ... Number of digits in a double variable.
|
5863
6719
|
*
|
5864
6720
|
* m -> d*10**e, 0<d<BASE
|
5865
6721
|
* [Returns]
|
@@ -5906,7 +6762,7 @@ VpVtoD(double *d, SIGNED_VALUE *e, Real *m)
|
|
5906
6762
|
goto Exit;
|
5907
6763
|
}
|
5908
6764
|
/* Normal number */
|
5909
|
-
fig = (
|
6765
|
+
fig = roomof(BIGDECIMAL_DOUBLE_FIGURES, BASE_FIG);
|
5910
6766
|
ind_m = 0;
|
5911
6767
|
mm = Min(fig, m->Prec);
|
5912
6768
|
*d = 0.0;
|
@@ -5923,7 +6779,7 @@ Exit:
|
|
5923
6779
|
if (gfDebug) {
|
5924
6780
|
VPrint(stdout, " VpVtoD: m=%\n", m);
|
5925
6781
|
printf(" d=%e * 10 **%ld\n", *d, *e);
|
5926
|
-
printf("
|
6782
|
+
printf(" BIGDECIMAL_DOUBLE_FIGURES = %d\n", BIGDECIMAL_DOUBLE_FIGURES);
|
5927
6783
|
}
|
5928
6784
|
#endif /*BIGDECIMAL_DEBUG */
|
5929
6785
|
return f;
|
@@ -5937,7 +6793,7 @@ VpDtoV(Real *m, double d)
|
|
5937
6793
|
{
|
5938
6794
|
size_t ind_m, mm;
|
5939
6795
|
SIGNED_VALUE ne;
|
5940
|
-
|
6796
|
+
DECDIG i;
|
5941
6797
|
double val, val2;
|
5942
6798
|
|
5943
6799
|
if (isnan(d)) {
|
@@ -5972,12 +6828,12 @@ VpDtoV(Real *m, double d)
|
|
5972
6828
|
/* Now val = 0.xxxxx*BASE**ne */
|
5973
6829
|
|
5974
6830
|
mm = m->MaxPrec;
|
5975
|
-
memset(m->frac, 0, mm * sizeof(
|
6831
|
+
memset(m->frac, 0, mm * sizeof(DECDIG));
|
5976
6832
|
for (ind_m = 0; val > 0.0 && ind_m < mm; ind_m++) {
|
5977
|
-
|
5978
|
-
|
5979
|
-
|
5980
|
-
|
6833
|
+
val *= (double)BASE;
|
6834
|
+
i = (DECDIG)val;
|
6835
|
+
val -= (double)i;
|
6836
|
+
m->frac[ind_m] = i;
|
5981
6837
|
}
|
5982
6838
|
if (ind_m >= mm) ind_m = mm - 1;
|
5983
6839
|
VpSetSign(m, (d > 0.0) ? 1 : -1);
|
@@ -5985,7 +6841,7 @@ VpDtoV(Real *m, double d)
|
|
5985
6841
|
m->exponent = ne;
|
5986
6842
|
|
5987
6843
|
VpInternalRound(m, 0, (m->Prec > 0) ? m->frac[m->Prec-1] : 0,
|
5988
|
-
|
6844
|
+
(DECDIG)(val*(double)BASE));
|
5989
6845
|
|
5990
6846
|
Exit:
|
5991
6847
|
#ifdef BIGDECIMAL_DEBUG
|
@@ -6124,7 +6980,7 @@ VpSqrt(Real *y, Real *x)
|
|
6124
6980
|
}
|
6125
6981
|
VpDtoV(y, sqrt(val)); /* y <- sqrt(val) */
|
6126
6982
|
y->exponent += n;
|
6127
|
-
n = (SIGNED_VALUE)(
|
6983
|
+
n = (SIGNED_VALUE)roomof(BIGDECIMAL_DOUBLE_FIGURES, BASE_FIG);
|
6128
6984
|
y->MaxPrec = Min((size_t)n , y_prec);
|
6129
6985
|
f->MaxPrec = y->MaxPrec + 1;
|
6130
6986
|
n = (SIGNED_VALUE)(y_prec * BASE_FIG);
|
@@ -6181,8 +7037,8 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
|
|
6181
7037
|
/* exptoadd: number of digits needed to compensate negative nf */
|
6182
7038
|
int fracf, fracf_1further;
|
6183
7039
|
ssize_t n,i,ix,ioffset, exptoadd;
|
6184
|
-
|
6185
|
-
|
7040
|
+
DECDIG v, shifter;
|
7041
|
+
DECDIG div;
|
6186
7042
|
|
6187
7043
|
nf += y->exponent * (ssize_t)BASE_FIG;
|
6188
7044
|
exptoadd=0;
|
@@ -6204,8 +7060,8 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
|
|
6204
7060
|
n = (ssize_t)BASE_FIG - ioffset - 1;
|
6205
7061
|
for (shifter = 1, i = 0; i < n; ++i) shifter *= 10;
|
6206
7062
|
|
6207
|
-
/* so the representation used (in y->frac) is an array of
|
6208
|
-
each
|
7063
|
+
/* so the representation used (in y->frac) is an array of DECDIG, where
|
7064
|
+
each DECDIG contains a value between 0 and BASE-1, consisting of BASE_FIG
|
6209
7065
|
decimal places.
|
6210
7066
|
|
6211
7067
|
(that numbers of decimal places are typed as ssize_t is somewhat confusing)
|
@@ -6213,10 +7069,10 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
|
|
6213
7069
|
nf is now position (in decimal places) of the digit from the start of
|
6214
7070
|
the array.
|
6215
7071
|
|
6216
|
-
ix is the position (in
|
7072
|
+
ix is the position (in DECDIGs) of the DECDIG containing the decimal digit,
|
6217
7073
|
from the start of the array.
|
6218
7074
|
|
6219
|
-
v is the value of this
|
7075
|
+
v is the value of this DECDIG
|
6220
7076
|
|
6221
7077
|
ioffset is the number of extra decimal places along of this decimal digit
|
6222
7078
|
within v.
|
@@ -6242,7 +7098,7 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
|
|
6242
7098
|
now fracf_1further is whether any of the remaining digits within v are non-zero
|
6243
7099
|
*/
|
6244
7100
|
|
6245
|
-
/* now check all the remaining
|
7101
|
+
/* now check all the remaining DECDIGs for zero-ness a whole DECDIG at a time.
|
6246
7102
|
if we spot any non-zeroness, that means that we found a positive digit under
|
6247
7103
|
rounding position, and we also found a positive digit under one further than
|
6248
7104
|
the rounding position, so both searches (to see if any such non-zero digit exists)
|
@@ -6261,7 +7117,7 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
|
|
6261
7117
|
now v = the first digit under the rounding position */
|
6262
7118
|
|
6263
7119
|
/* drop digits after pointed digit */
|
6264
|
-
memset(y->frac + ix + 1, 0, (y->Prec - (ix + 1)) * sizeof(
|
7120
|
+
memset(y->frac + ix + 1, 0, (y->Prec - (ix + 1)) * sizeof(DECDIG));
|
6265
7121
|
|
6266
7122
|
switch (f) {
|
6267
7123
|
case VP_ROUND_DOWN: /* Truncate */
|
@@ -6289,11 +7145,11 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
|
|
6289
7145
|
}
|
6290
7146
|
else {
|
6291
7147
|
if (ioffset == 0) {
|
6292
|
-
|
6293
|
-
|
6294
|
-
|
6295
|
-
|
6296
|
-
|
7148
|
+
/* v is the first decimal digit of its DECDIG;
|
7149
|
+
need to grab the previous DECDIG if present
|
7150
|
+
to check for evenness of the previous decimal
|
7151
|
+
digit (which is same as that of the DECDIG since
|
7152
|
+
base 10 has a factor of 2) */
|
6297
7153
|
if (ix && (y->frac[ix-1] % 2)) ++div;
|
6298
7154
|
}
|
6299
7155
|
else {
|
@@ -6341,7 +7197,7 @@ VpLeftRound(Real *y, unsigned short f, ssize_t nf)
|
|
6341
7197
|
* Round from the left hand side of the digits.
|
6342
7198
|
*/
|
6343
7199
|
{
|
6344
|
-
|
7200
|
+
DECDIG v;
|
6345
7201
|
if (!VpHasVal(y)) return 0; /* Unable to round */
|
6346
7202
|
v = y->frac[0];
|
6347
7203
|
nf -= VpExponent(y) * (ssize_t)BASE_FIG;
|
@@ -6372,7 +7228,7 @@ VpLimitRound(Real *c, size_t ixDigit)
|
|
6372
7228
|
/* If I understand correctly, this is only ever used to round off the final decimal
|
6373
7229
|
digit of precision */
|
6374
7230
|
static void
|
6375
|
-
VpInternalRound(Real *c, size_t ixDigit,
|
7231
|
+
VpInternalRound(Real *c, size_t ixDigit, DECDIG vPrev, DECDIG v)
|
6376
7232
|
{
|
6377
7233
|
int f = 0;
|
6378
7234
|
|
@@ -6422,7 +7278,7 @@ VpInternalRound(Real *c, size_t ixDigit, BDIGIT vPrev, BDIGIT v)
|
|
6422
7278
|
static int
|
6423
7279
|
VpRdup(Real *m, size_t ind_m)
|
6424
7280
|
{
|
6425
|
-
|
7281
|
+
DECDIG carry;
|
6426
7282
|
|
6427
7283
|
if (!ind_m) ind_m = m->Prec;
|
6428
7284
|
|
@@ -6494,7 +7350,7 @@ Exit:
|
|
6494
7350
|
* y = x ** n
|
6495
7351
|
*/
|
6496
7352
|
VP_EXPORT int
|
6497
|
-
|
7353
|
+
VpPowerByInt(Real *y, Real *x, SIGNED_VALUE n)
|
6498
7354
|
{
|
6499
7355
|
size_t s, ss;
|
6500
7356
|
ssize_t sign;
|
@@ -6581,8 +7437,8 @@ VpPower(Real *y, Real *x, SIGNED_VALUE n)
|
|
6581
7437
|
Exit:
|
6582
7438
|
#ifdef BIGDECIMAL_DEBUG
|
6583
7439
|
if (gfDebug) {
|
6584
|
-
VPrint(stdout, "
|
6585
|
-
VPrint(stdout, "
|
7440
|
+
VPrint(stdout, "VpPowerByInt y=%\n", y);
|
7441
|
+
VPrint(stdout, "VpPowerByInt x=%\n", x);
|
6586
7442
|
printf(" n=%"PRIdVALUE"\n", n);
|
6587
7443
|
}
|
6588
7444
|
#endif /* BIGDECIMAL_DEBUG */
|
@@ -6617,12 +7473,12 @@ VpVarCheck(Real * v)
|
|
6617
7473
|
}
|
6618
7474
|
for (i = 0; i < v->Prec; ++i) {
|
6619
7475
|
if (v->frac[i] >= BASE) {
|
6620
|
-
|
6621
|
-
|
6622
|
-
|
6623
|
-
|
6624
|
-
|
6625
|
-
|
7476
|
+
printf("ERROR(VpVarCheck): Illegal fraction\n");
|
7477
|
+
printf(" Frac[%"PRIuSIZE"]=%"PRIuDECDIG"\n", i, v->frac[i]);
|
7478
|
+
printf(" Prec. =%"PRIuSIZE"\n", v->Prec);
|
7479
|
+
printf(" Exp. =%"PRIdVALUE"\n", v->exponent);
|
7480
|
+
printf(" BASE =%"PRIuDECDIG"\n", BASE);
|
7481
|
+
return 3;
|
6626
7482
|
}
|
6627
7483
|
}
|
6628
7484
|
return 0;
|