bigdecimal 2.0.3 → 3.1.1

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