bigdecimal 2.0.2 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -30,14 +30,11 @@
30
30
  #include <ieeefp.h>
31
31
  #endif
32
32
 
33
+ #include "bits.h"
34
+ #include "static_assert.h"
35
+
33
36
  /* #define ENABLE_NUMERIC_STRING */
34
37
 
35
- #define MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max) ( \
36
- (a) == 0 ? 0 : \
37
- (a) == -1 ? (b) < -(max) : \
38
- (a) > 0 ? \
39
- ((b) > 0 ? (max) / (a) < (b) : (min) / (a) > (b)) : \
40
- ((b) > 0 ? (min) / (a) < (b) : (max) / (a) > (b)))
41
38
  #define SIGNED_VALUE_MAX INTPTR_MAX
42
39
  #define SIGNED_VALUE_MIN INTPTR_MIN
43
40
  #define MUL_OVERFLOW_SIGNED_VALUE_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, SIGNED_VALUE_MIN, SIGNED_VALUE_MAX)
@@ -65,20 +62,22 @@ static ID id_eq;
65
62
  static ID id_half;
66
63
 
67
64
  /* MACRO's to guard objects from GC by keeping them in stack */
65
+ #ifdef RBIMPL_ATTR_MAYBE_UNUSED
66
+ #define ENTER(n) RBIMPL_ATTR_MAYBE_UNUSED() volatile VALUE vStack[n];int iStack=0
67
+ #else
68
68
  #define ENTER(n) volatile VALUE RB_UNUSED_VAR(vStack[n]);int iStack=0
69
+ #endif
69
70
  #define PUSH(x) (vStack[iStack++] = (VALUE)(x))
70
71
  #define SAVE(p) PUSH((p)->obj)
71
72
  #define GUARD_OBJ(p,y) ((p)=(y), SAVE(p))
72
73
 
73
- #define BASE_FIG RMPD_COMPONENT_FIGURES
74
- #define BASE RMPD_BASE
74
+ #define BASE_FIG BIGDECIMAL_COMPONENT_FIGURES
75
+ #define BASE BIGDECIMAL_BASE
75
76
 
76
77
  #define HALF_BASE (BASE/2)
77
78
  #define BASE1 (BASE/10)
78
79
 
79
- #ifndef DBLE_FIG
80
- #define DBLE_FIG (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;