bigdecimal 2.0.2 → 3.1.0

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