bigdecimal 2.0.3 → 3.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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;