bigdecimal 3.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 rmpd_double_figures() /* figure of double */
81
- #endif
80
+ #define LOG10_2 0.3010299956639812
82
81
 
83
82
  #ifndef RRATIONAL_ZERO_P
84
83
  # define RRATIONAL_ZERO_P(x) (FIXNUM_P(rb_rational_num(x)) && \
@@ -103,54 +102,6 @@ static ID id_half;
103
102
  # define RB_OBJ_STRING(obj) StringValueCStr(obj)
104
103
  #endif
105
104
 
106
- #ifndef HAVE_RB_RATIONAL_NUM
107
- static inline VALUE
108
- rb_rational_num(VALUE rat)
109
- {
110
- #ifdef HAVE_TYPE_STRUCT_RRATIONAL
111
- return RRATIONAL(rat)->num;
112
- #else
113
- return rb_funcall(rat, rb_intern("numerator"), 0);
114
- #endif
115
- }
116
- #endif
117
-
118
- #ifndef HAVE_RB_RATIONAL_DEN
119
- static inline VALUE
120
- rb_rational_den(VALUE rat)
121
- {
122
- #ifdef HAVE_TYPE_STRUCT_RRATIONAL
123
- return RRATIONAL(rat)->den;
124
- #else
125
- return rb_funcall(rat, rb_intern("denominator"), 0);
126
- #endif
127
- }
128
- #endif
129
-
130
- #ifndef HAVE_RB_COMPLEX_REAL
131
- static inline VALUE
132
- rb_complex_real(VALUE cmp)
133
- {
134
- #ifdef HAVE_TYPE_STRUCT_RCOMPLEX
135
- return RCOMPLEX(cmp)->real;
136
- #else
137
- return rb_funcall(cmp, rb_intern("real"), 0);
138
- #endif
139
- }
140
- #endif
141
-
142
- #ifndef HAVE_RB_COMPLEX_IMAG
143
- static inline VALUE
144
- rb_complex_imag(VALUE cmp)
145
- {
146
- #ifdef HAVE_TYPE_STRUCT_RCOMPLEX
147
- return RCOMPLEX(cmp)->imag;
148
- #else
149
- return rb_funcall(cmp, rb_intern("imag"), 0);
150
- #endif
151
- }
152
- #endif
153
-
154
105
  #define BIGDECIMAL_POSITIVE_P(bd) ((bd)->sign > 0)
155
106
  #define BIGDECIMAL_NEGATIVE_P(bd) ((bd)->sign < 0)
156
107
 
@@ -164,7 +115,9 @@ rb_complex_imag(VALUE cmp)
164
115
  */
165
116
  static unsigned short VpGetException(void);
166
117
  static void VpSetException(unsigned short f);
167
- static void VpInternalRound(Real *c, size_t ixDigit, BDIGIT vPrev, BDIGIT v);
118
+ static void VpCheckException(Real *p, bool always);
119
+ static VALUE VpCheckGetValue(Real *p);
120
+ static void VpInternalRound(Real *c, size_t ixDigit, DECDIG vPrev, DECDIG v);
168
121
  static int VpLimitRound(Real *c, size_t ixDigit);
169
122
  static Real *VpCopy(Real *pv, Real const* const x);
170
123
 
@@ -176,6 +129,12 @@ static int VPrint(FILE *fp,const char *cntl_chr,Real *a);
176
129
  * **** BigDecimal part ****
177
130
  */
178
131
 
132
+ static VALUE BigDecimal_nan(void);
133
+ static VALUE BigDecimal_positive_infinity(void);
134
+ static VALUE BigDecimal_negative_infinity(void);
135
+ static VALUE BigDecimal_positive_zero(void);
136
+ static VALUE BigDecimal_negative_zero(void);
137
+
179
138
  static void
180
139
  BigDecimal_delete(void *pv)
181
140
  {
@@ -186,7 +145,7 @@ 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
 
192
151
  #ifndef HAVE_RB_EXT_RACTOR_SAFE
@@ -208,21 +167,6 @@ is_kind_of_BigDecimal(VALUE const v)
208
167
  return rb_typeddata_is_kind_of(v, &BigDecimal_data_type);
209
168
  }
210
169
 
211
- static VALUE
212
- ToValue(Real *p)
213
- {
214
- if (VpIsNaN(p)) {
215
- VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'(Not a Number)", 0);
216
- }
217
- else if (VpIsPosInf(p)) {
218
- VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 0);
219
- }
220
- else if (VpIsNegInf(p)) {
221
- VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 0);
222
- }
223
- return p->obj;
224
- }
225
-
226
170
  NORETURN(static void cannot_be_coerced_into_BigDecimal(VALUE, VALUE));
227
171
 
228
172
  static void
@@ -242,95 +186,67 @@ cannot_be_coerced_into_BigDecimal(VALUE exc_class, VALUE v)
242
186
  }
243
187
 
244
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);
245
194
 
246
195
  static Real*
247
196
  GetVpValueWithPrec(VALUE v, long prec, int must)
248
197
  {
249
- ENTER(1);
250
- Real *pv;
251
- VALUE num, bg;
252
- char szD[128];
253
- VALUE orig = Qundef;
254
- double d;
198
+ const size_t digs = prec < 0 ? SIZE_MAX : (size_t)prec;
255
199
 
256
- again:
257
200
  switch(TYPE(v)) {
258
201
  case T_FLOAT:
259
- if (prec < 0) goto unable_to_coerce_without_prec;
260
- if (prec > (long)DBLE_FIG) goto SomeOneMayDoIt;
261
- d = RFLOAT_VALUE(v);
262
- if (!isfinite(d)) {
263
- pv = VpCreateRbObject(1, NULL);
264
- VpDtoV(pv, d);
265
- return pv;
266
- }
267
- if (d != 0.0) {
268
- v = rb_funcall(v, id_to_r, 0);
269
- goto again;
270
- }
271
- if (1/d < 0.0) {
272
- return VpCreateRbObject(prec, "-0");
273
- }
274
- return VpCreateRbObject(prec, "0");
202
+ v = rb_float_convert_to_BigDecimal(v, digs, must);
203
+ break;
275
204
 
276
205
  case T_RATIONAL:
277
- if (prec < 0) goto unable_to_coerce_without_prec;
278
-
279
- if (orig == Qundef ? (orig = v, 1) : orig != v) {
280
- num = rb_rational_num(v);
281
- pv = GetVpValueWithPrec(num, -1, must);
282
- if (pv == NULL) goto SomeOneMayDoIt;
283
-
284
- v = BigDecimal_div2(ToValue(pv), rb_rational_den(v), LONG2NUM(prec));
285
- goto again;
286
- }
287
-
288
- v = orig;
289
- goto SomeOneMayDoIt;
206
+ v = rb_rational_convert_to_BigDecimal(v, digs, must);
207
+ break;
290
208
 
291
209
  case T_DATA:
292
- if (is_kind_of_BigDecimal(v)) {
293
- pv = DATA_PTR(v);
294
- return pv;
295
- }
296
- else {
297
- goto SomeOneMayDoIt;
298
- }
299
- break;
210
+ if (!is_kind_of_BigDecimal(v)) {
211
+ goto SomeOneMayDoIt;
212
+ }
213
+ break;
300
214
 
301
- case T_FIXNUM:
302
- sprintf(szD, "%ld", FIX2LONG(v));
303
- 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
+ }
304
221
 
305
222
  #ifdef ENABLE_NUMERIC_STRING
306
- case T_STRING:
307
- StringValueCStr(v);
308
- return VpCreateRbObject(RSTRING_LEN(v) + VpBaseFig() + 1,
309
- 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
+ }
310
228
  #endif /* ENABLE_NUMERIC_STRING */
311
229
 
312
- case T_BIGNUM:
313
- bg = rb_big2str(v, 10);
314
- PUSH(bg);
315
- return VpCreateRbObject(strlen(RSTRING_PTR(bg)) + VpBaseFig() + 1,
316
- 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
+
317
237
  default:
318
238
  goto SomeOneMayDoIt;
319
239
  }
320
240
 
241
+ Real *vp;
242
+ TypedData_Get_Struct(v, Real, &BigDecimal_data_type, vp);
243
+ return vp;
244
+
321
245
  SomeOneMayDoIt:
322
246
  if (must) {
323
247
  cannot_be_coerced_into_BigDecimal(rb_eTypeError, v);
324
248
  }
325
249
  return NULL; /* NULL means to coerce */
326
-
327
- unable_to_coerce_without_prec:
328
- if (must) {
329
- rb_raise(rb_eArgError,
330
- "%"PRIsVALUE" can't be coerced into BigDecimal without a precision",
331
- RB_OBJ_CLASSNAME(v));
332
- }
333
- return NULL;
334
250
  }
335
251
 
336
252
  static Real*
@@ -340,11 +256,13 @@ GetVpValue(VALUE v, int must)
340
256
  }
341
257
 
342
258
  /* call-seq:
343
- * 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
344
265
  *
345
- * The BigDecimal.double_fig class method returns the number of digits a
346
- * Float number is allowed to have. The result depends upon the CPU and OS
347
- * in use.
348
266
  */
349
267
  static VALUE
350
268
  BigDecimal_double_fig(VALUE self)
@@ -353,7 +271,7 @@ BigDecimal_double_fig(VALUE self)
353
271
  }
354
272
 
355
273
  /* call-seq:
356
- * big_decimal.precs -> array
274
+ * precs -> array
357
275
  *
358
276
  * Returns an Array of two Integer values that represent platform-dependent
359
277
  * internal storage properties.
@@ -363,7 +281,6 @@ BigDecimal_double_fig(VALUE self)
363
281
  * significant digits in scientific notation, and BigDecimal#precision for
364
282
  * obtaining the number of digits in decimal notation.
365
283
  *
366
- * BigDecimal('5').precs #=> [9, 18]
367
284
  */
368
285
 
369
286
  static VALUE
@@ -383,73 +300,202 @@ BigDecimal_prec(VALUE self)
383
300
  return obj;
384
301
  }
385
302
 
386
- /*
387
- * call-seq:
388
- * big_decimal.precision -> intreger
389
- *
390
- * Returns the number of decimal digits in this number.
391
- *
392
- * Example:
393
- *
394
- * BigDecimal("0").precision # => 0
395
- * BigDecimal("1").precision # => 1
396
- * BigDecimal("-1e20").precision # => 21
397
- * BigDecimal("1e-20").precision # => 20
398
- * BigDecimal("Infinity").precision # => 0
399
- * BigDecimal("-Infinity").precision # => 0
400
- * BigDecimal("NaN").precision # => 0
401
- */
402
- static VALUE
403
- BigDecimal_precision(VALUE self)
303
+ static void
304
+ BigDecimal_count_precision_and_scale(VALUE self, ssize_t *out_precision, ssize_t *out_scale)
404
305
  {
405
306
  ENTER(1);
406
307
 
308
+ if (out_precision == NULL && out_scale == NULL)
309
+ return;
310
+
407
311
  Real *p;
408
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;
409
331
 
410
332
  /*
411
- * The most significant digit is frac[0], and the least significant digit is frac[Prec-1].
412
- * When the exponent is zero, the decimal point is located just before frac[0].
333
+ * Calculate the precision and the scale
334
+ * -------------------------------------
335
+ *
336
+ * The most significant digit is frac[0], and the least significant digit
337
+ * is frac[Prec-1]. When the exponent is zero, the decimal point is
338
+ * located just before frac[0].
339
+ *
413
340
  * When the exponent is negative, the decimal point moves to leftward.
414
- * Conversely, when the exponent is positive, the decimal point moves to rightward.
341
+ * In this case, the precision can be calculated by
342
+ *
343
+ * precision = BASE_FIG * (-exponent + n) - ntz,
344
+ *
345
+ * and the scale is the same as precision.
346
+ *
347
+ * 0 . 0000 0000 | frac[0] ... frac[n-1] |
348
+ * |<----------| exponent == -2 |
349
+ * |---------------------------------->| precision
350
+ * |---------------------------------->| scale
351
+ *
415
352
  *
416
- * | frac[0] frac[1] frac[2] . frac[3] frac[4] ... frac[Prec-1]
417
- * |------------------------> exponent == 3
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
418
366
  */
419
367
 
420
368
  ssize_t ex = p->exponent;
421
- ssize_t precision;
369
+
370
+ /* Count the number of decimal digits before frac[1]. */
371
+ ssize_t n_digits_head = BASE_FIG;
422
372
  if (ex < 0) {
423
- precision = (-ex + 1) * BASE_FIG; /* 1 is for p->frac[0] */
424
- ex = 0;
373
+ n_digits_head += (-ex) * BASE_FIG; /* The number of leading zeros before frac[0]. */
374
+ ex = 0;
425
375
  }
426
- else if (p->Prec > 0) {
427
- BDIGIT x = p->frac[0];
428
- for (precision = 0; x > 0; x /= 10) {
429
- ++precision;
430
- }
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 */
431
381
  }
432
382
 
433
- if (ex > (ssize_t)p->Prec) {
434
- precision += (ex - 1) * BASE_FIG;
383
+ if (out_precision) {
384
+ ssize_t precision = n_digits_head;
385
+
386
+ /* Count the number of decimal digits after frac[0]. */
387
+ if (ex > (ssize_t)n) {
388
+ /* In this case the number is an integer with some trailing zeros. */
389
+ precision += (ex - 1) * BASE_FIG;
390
+ }
391
+ else if (n > 0) {
392
+ precision += (n - 1) * BASE_FIG;
393
+
394
+ if (ex < (ssize_t)n) {
395
+ precision -= ntz;
396
+ }
397
+ }
398
+
399
+ *out_precision = precision;
435
400
  }
436
- else if (p->Prec > 0) {
437
- ssize_t n = (ssize_t)p->Prec - 1;
438
- while (n > 0 && p->frac[n] == 0) --n;
439
401
 
440
- precision += n * BASE_FIG;
402
+ if (out_scale) {
403
+ ssize_t scale = 0;
441
404
 
442
- if (ex < (ssize_t)p->Prec) {
443
- BDIGIT x = p->frac[n];
444
- for (; x > 0 && x % 10 == 0; x /= 10) {
445
- --precision;
446
- }
405
+ if (p->exponent < 0) {
406
+ scale = n_digits_head + (n - 1) * BASE_FIG - ntz;
447
407
  }
408
+ else if (n > p->exponent) {
409
+ scale = (n - p->exponent) * BASE_FIG - ntz;
410
+ }
411
+
412
+ *out_scale = scale;
448
413
  }
414
+ }
449
415
 
416
+ /*
417
+ * call-seq:
418
+ * precision -> integer
419
+ *
420
+ * Returns the number of decimal digits in +self+:
421
+ *
422
+ * BigDecimal("0").precision # => 0
423
+ * BigDecimal("1").precision # => 1
424
+ * BigDecimal("1.1").precision # => 2
425
+ * BigDecimal("3.1415").precision # => 5
426
+ * BigDecimal("-1e20").precision # => 21
427
+ * BigDecimal("1e-20").precision # => 20
428
+ * BigDecimal("Infinity").precision # => 0
429
+ * BigDecimal("-Infinity").precision # => 0
430
+ * BigDecimal("NaN").precision # => 0
431
+ *
432
+ */
433
+ static VALUE
434
+ BigDecimal_precision(VALUE self)
435
+ {
436
+ ssize_t precision;
437
+ BigDecimal_count_precision_and_scale(self, &precision, NULL);
450
438
  return SSIZET2NUM(precision);
451
439
  }
452
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
+ */
453
499
  static VALUE
454
500
  BigDecimal_n_significant_digits(VALUE self)
455
501
  {
@@ -457,32 +503,38 @@ BigDecimal_n_significant_digits(VALUE self)
457
503
 
458
504
  Real *p;
459
505
  GUARD_OBJ(p, GetVpValue(self, 1));
460
-
461
- ssize_t n = p->Prec;
462
- while (n > 0 && p->frac[n-1] == 0) --n;
463
- if (n <= 0) {
506
+ if (VpIsZero(p) || !VpIsDef(p)) {
464
507
  return INT2FIX(0);
465
508
  }
466
509
 
467
- int nlz, ntz;
510
+ ssize_t n = p->Prec; /* The length of frac without trailing zeros. */
511
+ for (n = p->Prec; n > 0 && p->frac[n-1] == 0; --n);
512
+ if (n == 0) return INT2FIX(0);
468
513
 
469
- BDIGIT x = p->frac[0];
470
- for (nlz = BASE_FIG; x > 0; x /= 10) --nlz;
514
+ DECDIG x;
515
+ int nlz = BASE_FIG;
516
+ for (x = p->frac[0]; x > 0; x /= 10) --nlz;
471
517
 
472
- x = p->frac[n-1];
473
- for (ntz = 0; x > 0 && x % 10 == 0; x /= 10) ++ntz;
518
+ int ntz = 0;
519
+ for (x = p->frac[n-1]; x > 0 && x % 10 == 0; x /= 10) ++ntz;
474
520
 
475
- ssize_t n_digits = BASE_FIG * n - nlz - ntz;
476
- return SSIZET2NUM(n_digits);
521
+ ssize_t n_significant_digits = BASE_FIG*n - nlz - ntz;
522
+ return SSIZET2NUM(n_significant_digits);
477
523
  }
478
524
 
479
525
  /*
480
- * call-seq: hash
526
+ * call-seq:
527
+ * hash -> integer
528
+ *
529
+ * Returns the integer hash value for +self+.
481
530
  *
482
- * Creates a hash for this BigDecimal.
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.
483
537
  *
484
- * Two BigDecimals with equal sign,
485
- * fractional part and exponent have the same hash.
486
538
  */
487
539
  static VALUE
488
540
  BigDecimal_hash(VALUE self)
@@ -495,23 +547,23 @@ BigDecimal_hash(VALUE self)
495
547
  hash = (st_index_t)p->sign;
496
548
  /* hash!=2: the case for 0(1),NaN(0) or +-Infinity(3) is sign itself */
497
549
  if(hash == 2 || hash == (st_index_t)-2) {
498
- hash ^= rb_memhash(p->frac, sizeof(BDIGIT)*p->Prec);
499
- hash += p->exponent;
550
+ hash ^= rb_memhash(p->frac, sizeof(DECDIG)*p->Prec);
551
+ hash += p->exponent;
500
552
  }
501
553
  return ST2FIX(hash);
502
554
  }
503
555
 
504
556
  /*
505
- * call-seq: _dump
557
+ * call-seq:
558
+ * _dump -> string
506
559
  *
507
- * Method used to provide marshalling support.
560
+ * Returns a string representing the marshalling of +self+.
561
+ * See module Marshal.
508
562
  *
509
- * inf = BigDecimal('Infinity')
510
- * #=> Infinity
511
- * BigDecimal._load(inf._dump)
512
- * #=> Infinity
563
+ * inf = BigDecimal('Infinity') # => Infinity
564
+ * dumped = inf._dump # => "9:Infinity"
565
+ * BigDecimal._load(dumped) # => Infinity
513
566
  *
514
- * See the Marshal module.
515
567
  */
516
568
  static VALUE
517
569
  BigDecimal_dump(int argc, VALUE *argv, VALUE self)
@@ -553,12 +605,12 @@ BigDecimal_load(VALUE self, VALUE str)
553
605
  m = m*10 + (unsigned long)(ch-'0');
554
606
  }
555
607
  if (m > VpBaseFig()) m -= VpBaseFig();
556
- GUARD_OBJ(pv, VpNewRbClass(m, (char *)pch, self));
608
+ GUARD_OBJ(pv, VpNewRbClass(m, (char *)pch, self, true, true));
557
609
  m /= VpBaseFig();
558
610
  if (m && pv->MaxPrec > m) {
559
611
  pv->MaxPrec = m+1;
560
612
  }
561
- return ToValue(pv);
613
+ return VpCheckGetValue(pv);
562
614
  }
563
615
 
564
616
  static unsigned short
@@ -645,42 +697,166 @@ check_rounding_mode(VALUE const v)
645
697
  return sw;
646
698
  }
647
699
 
648
- /* call-seq:
649
- * BigDecimal.mode(mode, value)
650
- *
651
- * Controls handling of arithmetic exceptions and rounding. If no value
652
- * is supplied, the current value is returned.
653
- *
654
- * Six values of the mode parameter control the handling of arithmetic
655
- * exceptions:
656
- *
657
- * BigDecimal::EXCEPTION_NaN
658
- * BigDecimal::EXCEPTION_INFINITY
659
- * BigDecimal::EXCEPTION_UNDERFLOW
660
- * BigDecimal::EXCEPTION_OVERFLOW
661
- * BigDecimal::EXCEPTION_ZERODIVIDE
662
- * BigDecimal::EXCEPTION_ALL
663
- *
664
- * For each mode parameter above, if the value set is false, computation
665
- * continues after an arithmetic exception of the appropriate type.
666
- * When computation continues, results are as follows:
667
- *
668
- * EXCEPTION_NaN:: NaN
669
- * EXCEPTION_INFINITY:: +Infinity or -Infinity
670
- * EXCEPTION_UNDERFLOW:: 0
671
- * EXCEPTION_OVERFLOW:: +Infinity or -Infinity
672
- * EXCEPTION_ZERODIVIDE:: +Infinity or -Infinity
673
- *
674
- * One value of the mode parameter controls the rounding of numeric values:
675
- * BigDecimal::ROUND_MODE. The values it can take are:
676
- *
677
- * ROUND_UP, :up:: round away from zero
678
- * ROUND_DOWN, :down, :truncate:: round towards zero (truncate)
679
- * ROUND_HALF_UP, :half_up, :default:: round towards the nearest neighbor, unless both neighbors are equidistant, in which case round away from zero. (default)
680
- * ROUND_HALF_DOWN, :half_down:: round towards the nearest neighbor, unless both neighbors are equidistant, in which case round towards zero.
681
- * 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)
682
- * ROUND_CEILING, :ceiling, :ceil:: round towards positive infinity (ceil)
683
- * 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:+.
684
860
  *
685
861
  */
686
862
  static VALUE
@@ -768,25 +944,54 @@ GetPrecisionInt(VALUE v)
768
944
  return n;
769
945
  }
770
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
+
771
965
  VP_EXPORT Real *
772
- 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)
773
967
  {
774
968
  VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
775
- Real *pv = VpAlloc(mx, str, 1, 1);
776
- RTYPEDDATA_DATA(obj) = pv;
777
- pv->obj = obj;
778
- 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);
779
973
  return pv;
780
974
  }
781
975
 
782
976
  VP_EXPORT Real *
783
- VpCreateRbObject(size_t mx, const char *str)
977
+ VpCreateRbObject(size_t mx, const char *str, bool raise_exception)
784
978
  {
785
- return VpNewRbClass(mx, str, rb_cBigDecimal);
979
+ return VpNewRbClass(mx, str, rb_cBigDecimal, true, raise_exception);
786
980
  }
787
981
 
788
- #define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(BDIGIT))
789
- #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
+ }
790
995
 
791
996
  static Real *
792
997
  VpCopy(Real *pv, Real const* const x)
@@ -799,7 +1004,7 @@ VpCopy(Real *pv, Real const* const x)
799
1004
  pv->exponent = x->exponent;
800
1005
  pv->sign = x->sign;
801
1006
  pv->flag = x->flag;
802
- MEMCPY(pv->frac, x->frac, BDIGIT, pv->MaxPrec);
1007
+ MEMCPY(pv->frac, x->frac, DECDIG, pv->MaxPrec);
803
1008
 
804
1009
  return pv;
805
1010
  }
@@ -838,15 +1043,7 @@ BigDecimal_IsFinite(VALUE self)
838
1043
  static void
839
1044
  BigDecimal_check_num(Real *p)
840
1045
  {
841
- if (VpIsNaN(p)) {
842
- VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'(Not a Number)", 1);
843
- }
844
- else if (VpIsPosInf(p)) {
845
- VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 1);
846
- }
847
- else if (VpIsNegInf(p)) {
848
- VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 1);
849
- }
1046
+ VpCheckException(p, true);
850
1047
  }
851
1048
 
852
1049
  static VALUE BigDecimal_split(VALUE self);
@@ -869,7 +1066,7 @@ BigDecimal_to_i(VALUE self)
869
1066
  if (e <= 0) return INT2FIX(0);
870
1067
  nf = VpBaseFig();
871
1068
  if (e <= nf) {
872
- return LONG2NUM((long)(VpGetSign(p) * (BDIGIT_DBL_SIGNED)p->frac[0]));
1069
+ return LONG2NUM((long)(VpGetSign(p) * (DECDIG_DBL_SIGNED)p->frac[0]));
873
1070
  }
874
1071
  else {
875
1072
  VALUE a = BigDecimal_split(self);
@@ -1003,8 +1200,8 @@ BigDecimal_coerce(VALUE self, VALUE other)
1003
1200
  Real *b;
1004
1201
 
1005
1202
  if (RB_TYPE_P(other, T_FLOAT)) {
1006
- GUARD_OBJ(b, GetVpValueWithPrec(other, DBLE_FIG, 1));
1007
- obj = rb_assoc_new(ToValue(b), self);
1203
+ GUARD_OBJ(b, GetVpValueWithPrec(other, 0, 1));
1204
+ obj = rb_assoc_new(VpCheckGetValue(b), self);
1008
1205
  }
1009
1206
  else {
1010
1207
  if (RB_TYPE_P(other, T_RATIONAL)) {
@@ -1021,12 +1218,14 @@ BigDecimal_coerce(VALUE self, VALUE other)
1021
1218
  }
1022
1219
 
1023
1220
  /*
1024
- * call-seq:
1025
- * +big_decimal -> big_decimal
1221
+ * call-seq:
1222
+ * +big_decimal -> self
1026
1223
  *
1027
- * Return self.
1224
+ * Returns +self+:
1225
+ *
1226
+ * +BigDecimal(5) # => 0.5e1
1227
+ * +BigDecimal(-5) # => -0.5e1
1028
1228
  *
1029
- * +BigDecimal('5') #=> 0.5e1
1030
1229
  */
1031
1230
 
1032
1231
  static VALUE
@@ -1036,22 +1235,21 @@ BigDecimal_uplus(VALUE self)
1036
1235
  }
1037
1236
 
1038
1237
  /*
1039
- * Document-method: BigDecimal#add
1040
- * Document-method: BigDecimal#+
1238
+ * call-seq:
1239
+ * self + value -> bigdecimal
1041
1240
  *
1042
- * call-seq:
1043
- * add(value, digits)
1241
+ * Returns the \BigDecimal sum of +self+ and +value+:
1044
1242
  *
1045
- * 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)
1046
1248
  *
1047
- * e.g.
1048
- * c = a.add(b,n)
1049
- * c = a + b
1249
+ * See the {Note About Precision}[BigDecimal.html#class-BigDecimal-label-A+Note+About+Precision].
1050
1250
  *
1051
- * digits:: If specified and less than the number of significant digits of the
1052
- * result, the result is rounded to that number of digits, according
1053
- * to BigDecimal.mode.
1054
1251
  */
1252
+
1055
1253
  static VALUE
1056
1254
  BigDecimal_add(VALUE self, VALUE r)
1057
1255
  {
@@ -1061,7 +1259,7 @@ BigDecimal_add(VALUE self, VALUE r)
1061
1259
 
1062
1260
  GUARD_OBJ(a, GetVpValue(self, 1));
1063
1261
  if (RB_TYPE_P(r, T_FLOAT)) {
1064
- b = GetVpValueWithPrec(r, DBLE_FIG, 1);
1262
+ b = GetVpValueWithPrec(r, 0, 1);
1065
1263
  }
1066
1264
  else if (RB_TYPE_P(r, T_RATIONAL)) {
1067
1265
  b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
@@ -1078,11 +1276,11 @@ BigDecimal_add(VALUE self, VALUE r)
1078
1276
 
1079
1277
  mx = GetAddSubPrec(a, b);
1080
1278
  if (mx == (size_t)-1L) {
1081
- GUARD_OBJ(c,VpCreateRbObject(VpBaseFig() + 1, "0"));
1279
+ GUARD_OBJ(c, VpCreateRbObject(VpBaseFig() + 1, "0", true));
1082
1280
  VpAddSub(c, a, b, 1);
1083
1281
  }
1084
1282
  else {
1085
- GUARD_OBJ(c, VpCreateRbObject(mx * (VpBaseFig() + 1), "0"));
1283
+ GUARD_OBJ(c, VpCreateRbObject(mx * (VpBaseFig() + 1), "0", true));
1086
1284
  if(!mx) {
1087
1285
  VpSetInf(c, VpGetSign(a));
1088
1286
  }
@@ -1090,24 +1288,21 @@ BigDecimal_add(VALUE self, VALUE r)
1090
1288
  VpAddSub(c, a, b, 1);
1091
1289
  }
1092
1290
  }
1093
- return ToValue(c);
1291
+ return VpCheckGetValue(c);
1094
1292
  }
1095
1293
 
1096
- /* call-seq:
1097
- * a - b -> bigdecimal
1098
- *
1099
- * Subtract the specified value.
1100
- *
1101
- * e.g.
1102
- * c = a - b
1294
+ /* call-seq:
1295
+ * self - value -> bigdecimal
1103
1296
  *
1104
- * The precision of the result value depends on the type of +b+.
1297
+ * Returns the \BigDecimal difference of +self+ and +value+:
1105
1298
  *
1106
- * If +b+ is a Float, the precision of the result is Float::DIG+1.
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)
1107
1304
  *
1108
- * If +b+ is a BigDecimal, the precision of the result is +b+'s precision of
1109
- * internal representation from platform. So, it's return value is platform
1110
- * dependent.
1305
+ * See the {Note About Precision}[BigDecimal.html#class-BigDecimal-label-A+Note+About+Precision].
1111
1306
  *
1112
1307
  */
1113
1308
  static VALUE
@@ -1119,7 +1314,7 @@ BigDecimal_sub(VALUE self, VALUE r)
1119
1314
 
1120
1315
  GUARD_OBJ(a, GetVpValue(self,1));
1121
1316
  if (RB_TYPE_P(r, T_FLOAT)) {
1122
- b = GetVpValueWithPrec(r, DBLE_FIG, 1);
1317
+ b = GetVpValueWithPrec(r, 0, 1);
1123
1318
  }
1124
1319
  else if (RB_TYPE_P(r, T_RATIONAL)) {
1125
1320
  b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
@@ -1136,11 +1331,11 @@ BigDecimal_sub(VALUE self, VALUE r)
1136
1331
 
1137
1332
  mx = GetAddSubPrec(a,b);
1138
1333
  if (mx == (size_t)-1L) {
1139
- GUARD_OBJ(c,VpCreateRbObject(VpBaseFig() + 1, "0"));
1334
+ GUARD_OBJ(c, VpCreateRbObject(VpBaseFig() + 1, "0", true));
1140
1335
  VpAddSub(c, a, b, -1);
1141
1336
  }
1142
1337
  else {
1143
- GUARD_OBJ(c,VpCreateRbObject(mx *(VpBaseFig() + 1), "0"));
1338
+ GUARD_OBJ(c,VpCreateRbObject(mx *(VpBaseFig() + 1), "0", true));
1144
1339
  if (!mx) {
1145
1340
  VpSetInf(c,VpGetSign(a));
1146
1341
  }
@@ -1148,7 +1343,7 @@ BigDecimal_sub(VALUE self, VALUE r)
1148
1343
  VpAddSub(c, a, b, -1);
1149
1344
  }
1150
1345
  }
1151
- return ToValue(c);
1346
+ return VpCheckGetValue(c);
1152
1347
  }
1153
1348
 
1154
1349
  static VALUE
@@ -1169,7 +1364,7 @@ BigDecimalCmp(VALUE self, VALUE r,char op)
1169
1364
  break;
1170
1365
 
1171
1366
  case T_FLOAT:
1172
- GUARD_OBJ(b, GetVpValueWithPrec(r, DBLE_FIG, 0));
1367
+ GUARD_OBJ(b, GetVpValueWithPrec(r, 0, 0));
1173
1368
  break;
1174
1369
 
1175
1370
  case T_RATIONAL:
@@ -1286,12 +1481,19 @@ BigDecimal_eq(VALUE self, VALUE r)
1286
1481
  return BigDecimalCmp(self, r, '=');
1287
1482
  }
1288
1483
 
1289
- /* call-seq:
1290
- * a < b
1484
+ /* call-seq:
1485
+ * self < other -> true or false
1486
+ *
1487
+ * Returns +true+ if +self+ is less than +other+, +false+ otherwise:
1291
1488
  *
1292
- * 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.
1293
1496
  *
1294
- * Values may be coerced to perform the comparison (see ==, BigDecimal#coerce).
1295
1497
  */
1296
1498
  static VALUE
1297
1499
  BigDecimal_lt(VALUE self, VALUE r)
@@ -1299,12 +1501,20 @@ BigDecimal_lt(VALUE self, VALUE r)
1299
1501
  return BigDecimalCmp(self, r, '<');
1300
1502
  }
1301
1503
 
1302
- /* call-seq:
1303
- * 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:
1304
1508
  *
1305
- * 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.
1306
1517
  *
1307
- * Values may be coerced to perform the comparison (see ==, BigDecimal#coerce).
1308
1518
  */
1309
1519
  static VALUE
1310
1520
  BigDecimal_le(VALUE self, VALUE r)
@@ -1312,12 +1522,19 @@ BigDecimal_le(VALUE self, VALUE r)
1312
1522
  return BigDecimalCmp(self, r, 'L');
1313
1523
  }
1314
1524
 
1315
- /* call-seq:
1316
- * 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
1317
1535
  *
1318
- * Returns true if a is greater than b.
1536
+ * Raises an exception if the comparison cannot be made.
1319
1537
  *
1320
- * Values may be coerced to perform the comparison (see ==, BigDecimal#coerce).
1321
1538
  */
1322
1539
  static VALUE
1323
1540
  BigDecimal_gt(VALUE self, VALUE r)
@@ -1325,12 +1542,20 @@ BigDecimal_gt(VALUE self, VALUE r)
1325
1542
  return BigDecimalCmp(self, r, '>');
1326
1543
  }
1327
1544
 
1328
- /* call-seq:
1329
- * a >= b
1545
+ /* call-seq:
1546
+ * self >= other -> true or false
1330
1547
  *
1331
- * Returns true if a is greater than or equal to b.
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
1556
+ *
1557
+ * Raises an exception if the comparison cannot be made.
1332
1558
  *
1333
- * Values may be coerced to perform the comparison (see ==, BigDecimal#coerce)
1334
1559
  */
1335
1560
  static VALUE
1336
1561
  BigDecimal_ge(VALUE self, VALUE r)
@@ -1340,11 +1565,14 @@ BigDecimal_ge(VALUE self, VALUE r)
1340
1565
 
1341
1566
  /*
1342
1567
  * call-seq:
1343
- * -big_decimal -> big_decimal
1568
+ * -self -> bigdecimal
1344
1569
  *
1345
- * 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
1346
1575
  *
1347
- * -BigDecimal('5') #=> -0.5e1
1348
1576
  */
1349
1577
 
1350
1578
  static VALUE
@@ -1353,26 +1581,11 @@ BigDecimal_neg(VALUE self)
1353
1581
  ENTER(5);
1354
1582
  Real *c, *a;
1355
1583
  GUARD_OBJ(a, GetVpValue(self, 1));
1356
- GUARD_OBJ(c, VpCreateRbObject(a->Prec *(VpBaseFig() + 1), "0"));
1584
+ GUARD_OBJ(c, VpCreateRbObject(a->Prec *(VpBaseFig() + 1), "0", true));
1357
1585
  VpAsgn(c, a, -1);
1358
- return ToValue(c);
1586
+ return VpCheckGetValue(c);
1359
1587
  }
1360
1588
 
1361
- /*
1362
- * Document-method: BigDecimal#mult
1363
- *
1364
- * call-seq: mult(value, digits)
1365
- *
1366
- * Multiply by the specified value.
1367
- *
1368
- * e.g.
1369
- * c = a.mult(b,n)
1370
- * c = a * b
1371
- *
1372
- * digits:: If specified and less than the number of significant digits of the
1373
- * result, the result is rounded to that number of digits, according
1374
- * to BigDecimal.mode.
1375
- */
1376
1589
  static VALUE
1377
1590
  BigDecimal_mult(VALUE self, VALUE r)
1378
1591
  {
@@ -1382,7 +1595,7 @@ BigDecimal_mult(VALUE self, VALUE r)
1382
1595
 
1383
1596
  GUARD_OBJ(a, GetVpValue(self, 1));
1384
1597
  if (RB_TYPE_P(r, T_FLOAT)) {
1385
- b = GetVpValueWithPrec(r, DBLE_FIG, 1);
1598
+ b = GetVpValueWithPrec(r, 0, 1);
1386
1599
  }
1387
1600
  else if (RB_TYPE_P(r, T_RATIONAL)) {
1388
1601
  b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
@@ -1395,71 +1608,122 @@ BigDecimal_mult(VALUE self, VALUE r)
1395
1608
  SAVE(b);
1396
1609
 
1397
1610
  mx = a->Prec + b->Prec;
1398
- GUARD_OBJ(c, VpCreateRbObject(mx *(VpBaseFig() + 1), "0"));
1611
+ GUARD_OBJ(c, VpCreateRbObject(mx *(VpBaseFig() + 1), "0", true));
1399
1612
  VpMult(c, a, b);
1400
- return ToValue(c);
1613
+ return VpCheckGetValue(c);
1401
1614
  }
1402
1615
 
1403
1616
  static VALUE
1404
- 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)
1405
1618
  /* For c = self.div(r): with round operation */
1406
1619
  {
1407
1620
  ENTER(5);
1408
1621
  Real *a, *b;
1409
1622
  size_t mx;
1410
1623
 
1411
- GUARD_OBJ(a, GetVpValue(self, 1));
1412
- if (RB_TYPE_P(r, T_FLOAT)) {
1413
- b = GetVpValueWithPrec(r, DBLE_FIG, 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);
1414
1636
  }
1415
1637
  else if (RB_TYPE_P(r, T_RATIONAL)) {
1416
- b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
1417
- }
1418
- else {
1419
- b = GetVpValue(r, 0);
1638
+ rr = rb_rational_convert_to_BigDecimal(r, a->Prec*BASE_FIG, true);
1639
+ }
1640
+
1641
+ if (!is_kind_of_BigDecimal(rr)) {
1642
+ return DoSomeOne(self, r, '/');
1420
1643
  }
1421
1644
 
1422
- if (!b) return DoSomeOne(self, r, '/');
1645
+ TypedData_Get_Struct(rr, Real, &BigDecimal_data_type, b);
1423
1646
  SAVE(b);
1424
1647
 
1425
1648
  *div = b;
1426
- mx = a->Prec + vabs(a->exponent);
1427
- if (mx < b->Prec + vabs(b->exponent)) mx = b->Prec + vabs(b->exponent);
1428
- mx++; /* NOTE: An additional digit is needed for the compatibility to
1429
- the version 1.2.1 and the former. */
1430
- mx = (mx + 1) * VpBaseFig();
1431
- GUARD_OBJ((*c), VpCreateRbObject(mx, "#0"));
1432
- 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));
1433
1655
  VpDivd(*c, *res, a, b);
1434
1656
  return Qnil;
1435
1657
  }
1436
1658
 
1437
1659
  /* call-seq:
1438
- * a / b -> bigdecimal
1660
+ * a / b -> bigdecimal
1661
+ *
1662
+ * Divide by the specified value.
1663
+ *
1664
+ * The result precision will be the precision of the larger operand,
1665
+ * but its minimum is 2*Float::DIG.
1666
+ *
1667
+ * See BigDecimal#div.
1668
+ * See BigDecimal#quo.
1669
+ */
1670
+ static VALUE
1671
+ BigDecimal_div(VALUE self, VALUE r)
1672
+ /* For c = self/r: with round operation */
1673
+ {
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:
1439
1693
  * quo(value) -> bigdecimal
1694
+ * quo(value, digits) -> bigdecimal
1440
1695
  *
1441
1696
  * Divide by the specified value.
1442
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#/.
1443
1706
  * See BigDecimal#div.
1444
1707
  */
1445
1708
  static VALUE
1446
- BigDecimal_div(VALUE self, VALUE r)
1447
- /* For c = self/r: with round operation */
1709
+ BigDecimal_quo(int argc, VALUE *argv, VALUE self)
1448
1710
  {
1449
- ENTER(5);
1450
- Real *c=NULL, *res=NULL, *div = NULL;
1451
- r = BigDecimal_divide(&c, &res, &div, self, r);
1452
- if (!NIL_P(r)) return r; /* coerced by other */
1453
- SAVE(c); SAVE(res); SAVE(div);
1454
- /* a/b = c + r/b */
1455
- /* c xxxxx
1456
- r 00000yyyyy ==> (y/b)*BASE >= HALF_BASE
1457
- */
1458
- /* Round */
1459
- if (VpHasVal(div)) { /* frac[0] must be zero for NaN,INF,Zero */
1460
- VpInternalRound(c, 0, c->frac[c->Prec-1], (BDIGIT)(VpBaseVal() * (BDIGIT_DBL)res->frac[0] / div->frac[0]));
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);
1461
1724
  }
1462
- return ToValue(c);
1725
+
1726
+ return result;
1463
1727
  }
1464
1728
 
1465
1729
  /*
@@ -1474,75 +1738,99 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
1474
1738
  Real *a, *b;
1475
1739
  size_t mx;
1476
1740
 
1477
- GUARD_OBJ(a, GetVpValue(self, 1));
1478
- if (RB_TYPE_P(r, T_FLOAT)) {
1479
- b = GetVpValueWithPrec(r, DBLE_FIG, 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);
1480
1753
  }
1481
1754
  else if (RB_TYPE_P(r, T_RATIONAL)) {
1482
- b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
1755
+ rr = rb_rational_convert_to_BigDecimal(r, a->Prec*BASE_FIG, true);
1483
1756
  }
1484
- else {
1485
- b = GetVpValue(r, 0);
1757
+
1758
+ if (!is_kind_of_BigDecimal(rr)) {
1759
+ return Qfalse;
1486
1760
  }
1487
1761
 
1488
- if (!b) return Qfalse;
1762
+ TypedData_Get_Struct(rr, Real, &BigDecimal_data_type, b);
1489
1763
  SAVE(b);
1490
1764
 
1491
1765
  if (VpIsNaN(a) || VpIsNaN(b)) goto NaN;
1492
1766
  if (VpIsInf(a) && VpIsInf(b)) goto NaN;
1493
1767
  if (VpIsZero(b)) {
1494
- rb_raise(rb_eZeroDivError, "divided by 0");
1768
+ rb_raise(rb_eZeroDivError, "divided by 0");
1495
1769
  }
1496
1770
  if (VpIsInf(a)) {
1497
- GUARD_OBJ(d, VpCreateRbObject(1, "0"));
1498
- VpSetInf(d, (SIGNED_VALUE)(VpGetSign(a) == VpGetSign(b) ? 1 : -1));
1499
- GUARD_OBJ(c, VpCreateRbObject(1, "NaN"));
1500
- *div = d;
1501
- *mod = c;
1502
- 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;
1503
1782
  }
1504
1783
  if (VpIsInf(b)) {
1505
- GUARD_OBJ(d, VpCreateRbObject(1, "0"));
1506
- *div = d;
1507
- *mod = a;
1508
- return Qtrue;
1784
+ VALUE zero = BigDecimal_positive_zero();
1785
+ TypedData_Get_Struct(zero, Real, &BigDecimal_data_type, *div);
1786
+ *mod = a;
1787
+ return Qtrue;
1509
1788
  }
1510
1789
  if (VpIsZero(a)) {
1511
- GUARD_OBJ(c, VpCreateRbObject(1, "0"));
1512
- GUARD_OBJ(d, VpCreateRbObject(1, "0"));
1513
- *div = d;
1514
- *mod = c;
1515
- return Qtrue;
1516
- }
1517
-
1518
- mx = a->Prec + vabs(a->exponent);
1519
- if (mx<b->Prec + vabs(b->exponent)) mx = b->Prec + vabs(b->exponent);
1520
- mx = (mx + 1) * VpBaseFig();
1521
- GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
1522
- 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));
1523
1803
  VpDivd(c, res, a, b);
1524
- mx = c->Prec * (VpBaseFig() + 1);
1525
- GUARD_OBJ(d, VpCreateRbObject(mx, "0"));
1804
+
1805
+ mx = c->Prec * BASE_FIG;
1806
+ GUARD_OBJ(d, VpCreateRbObject(mx, "0", true));
1526
1807
  VpActiveRound(d, c, VP_ROUND_DOWN, 0);
1808
+
1527
1809
  VpMult(res, d, b);
1528
1810
  VpAddSub(c, a, res, -1);
1811
+
1529
1812
  if (!VpIsZero(c) && (VpGetSign(a) * VpGetSign(b) < 0)) {
1530
- VpAddSub(res, d, VpOne(), -1);
1531
- GUARD_OBJ(d, VpCreateRbObject(GetAddSubPrec(c, b)*(VpBaseFig() + 1), "0"));
1532
- VpAddSub(d, c, b, 1);
1533
- *div = res;
1534
- *mod = d;
1535
- } else {
1536
- *div = d;
1537
- *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;
1538
1825
  }
1539
1826
  return Qtrue;
1540
1827
 
1541
- NaN:
1542
- GUARD_OBJ(c, VpCreateRbObject(1, "NaN"));
1543
- GUARD_OBJ(d, VpCreateRbObject(1, "NaN"));
1544
- *div = d;
1545
- *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
+ }
1546
1834
  return Qtrue;
1547
1835
  }
1548
1836
 
@@ -1562,7 +1850,7 @@ BigDecimal_mod(VALUE self, VALUE r) /* %: a%b = a - (a.to_f/b).floor * b */
1562
1850
 
1563
1851
  if (BigDecimal_DoDivmod(self, r, &div, &mod)) {
1564
1852
  SAVE(div); SAVE(mod);
1565
- return ToValue(mod);
1853
+ return VpCheckGetValue(mod);
1566
1854
  }
1567
1855
  return DoSomeOne(self, r, '%');
1568
1856
  }
@@ -1577,7 +1865,7 @@ BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv)
1577
1865
 
1578
1866
  GUARD_OBJ(a, GetVpValue(self, 1));
1579
1867
  if (RB_TYPE_P(r, T_FLOAT)) {
1580
- b = GetVpValueWithPrec(r, DBLE_FIG, 1);
1868
+ b = GetVpValueWithPrec(r, 0, 1);
1581
1869
  }
1582
1870
  else if (RB_TYPE_P(r, T_RATIONAL)) {
1583
1871
  b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
@@ -1590,17 +1878,17 @@ BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv)
1590
1878
  SAVE(b);
1591
1879
 
1592
1880
  mx = (a->MaxPrec + b->MaxPrec) *VpBaseFig();
1593
- GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
1594
- GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0"));
1595
- GUARD_OBJ(rr, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0"));
1596
- 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));
1597
1885
 
1598
1886
  VpDivd(c, res, a, b);
1599
1887
 
1600
1888
  mx = c->Prec *(VpBaseFig() + 1);
1601
1889
 
1602
- GUARD_OBJ(d, VpCreateRbObject(mx, "0"));
1603
- GUARD_OBJ(f, VpCreateRbObject(mx, "0"));
1890
+ GUARD_OBJ(d, VpCreateRbObject(mx, "0", true));
1891
+ GUARD_OBJ(f, VpCreateRbObject(mx, "0", true));
1604
1892
 
1605
1893
  VpActiveRound(d, c, VP_ROUND_DOWN, 0); /* 0: round off */
1606
1894
 
@@ -1627,7 +1915,7 @@ BigDecimal_remainder(VALUE self, VALUE r) /* remainder */
1627
1915
  Real *d, *rv = 0;
1628
1916
  f = BigDecimal_divremain(self, r, &d, &rv);
1629
1917
  if (!NIL_P(f)) return f;
1630
- return ToValue(rv);
1918
+ return VpCheckGetValue(rv);
1631
1919
  }
1632
1920
 
1633
1921
  /* call-seq:
@@ -1660,13 +1948,14 @@ BigDecimal_divmod(VALUE self, VALUE r)
1660
1948
 
1661
1949
  if (BigDecimal_DoDivmod(self, r, &div, &mod)) {
1662
1950
  SAVE(div); SAVE(mod);
1663
- return rb_assoc_new(ToValue(div), ToValue(mod));
1951
+ return rb_assoc_new(VpCheckGetValue(div), VpCheckGetValue(mod));
1664
1952
  }
1665
1953
  return DoSomeOne(self,r,rb_intern("divmod"));
1666
1954
  }
1667
1955
 
1668
1956
  /*
1669
- * 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.
1670
1959
  */
1671
1960
  static inline VALUE
1672
1961
  BigDecimal_div2(VALUE self, VALUE b, VALUE n)
@@ -1678,7 +1967,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
1678
1967
  Real *div = NULL;
1679
1968
  Real *mod;
1680
1969
  if (BigDecimal_DoDivmod(self, b, &div, &mod)) {
1681
- return BigDecimal_to_i(ToValue(div));
1970
+ return BigDecimal_to_i(VpCheckGetValue(div));
1682
1971
  }
1683
1972
  return DoSomeOne(self, b, rb_intern("div"));
1684
1973
  }
@@ -1692,18 +1981,25 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
1692
1981
  Real *res = NULL;
1693
1982
  Real *av = NULL, *bv = NULL, *cv = NULL;
1694
1983
  size_t mx = ix + VpBaseFig()*2;
1984
+ size_t b_prec = ix;
1695
1985
  size_t pl = VpSetPrecLimit(0);
1696
1986
 
1697
- GUARD_OBJ(cv, VpCreateRbObject(mx + VpBaseFig(), "0"));
1987
+ GUARD_OBJ(cv, VpCreateRbObject(mx + VpBaseFig(), "0", true));
1698
1988
  GUARD_OBJ(av, GetVpValue(self, 1));
1699
- 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));
1700
1996
  mx = av->Prec + bv->Prec + 2;
1701
1997
  if (mx <= cv->MaxPrec) mx = cv->MaxPrec + 1;
1702
- GUARD_OBJ(res, VpCreateRbObject((mx * 2 + 2)*VpBaseFig(), "#0"));
1998
+ GUARD_OBJ(res, VpCreateRbObject((mx * 2 + 2)*VpBaseFig(), "#0", true));
1703
1999
  VpDivd(cv, res, av, bv);
1704
2000
  VpSetPrecLimit(pl);
1705
2001
  VpLeftRound(cv, VpGetRoundMode(), ix);
1706
- return ToValue(cv);
2002
+ return VpCheckGetValue(cv);
1707
2003
  }
1708
2004
  }
1709
2005
 
@@ -1711,6 +2007,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
1711
2007
  * Document-method: BigDecimal#div
1712
2008
  *
1713
2009
  * call-seq:
2010
+ * div(value) -> integer
1714
2011
  * div(value, digits) -> bigdecimal or integer
1715
2012
  *
1716
2013
  * Divide by the specified value.
@@ -1725,6 +2022,9 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
1725
2022
  * If digits is not specified, the result is an integer,
1726
2023
  * by analogy with Float#div; see also BigDecimal#divmod.
1727
2024
  *
2025
+ * See BigDecimal#/.
2026
+ * See BigDecimal#quo.
2027
+ *
1728
2028
  * Examples:
1729
2029
  *
1730
2030
  * a = BigDecimal("4")
@@ -1748,6 +2048,31 @@ BigDecimal_div3(int argc, VALUE *argv, VALUE self)
1748
2048
  return BigDecimal_div2(self, b, n);
1749
2049
  }
1750
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
+
1751
2076
  static VALUE
1752
2077
  BigDecimal_add2(VALUE self, VALUE b, VALUE n)
1753
2078
  {
@@ -1761,7 +2086,7 @@ BigDecimal_add2(VALUE self, VALUE b, VALUE n)
1761
2086
  VpSetPrecLimit(pl);
1762
2087
  GUARD_OBJ(cv, GetVpValue(c, 1));
1763
2088
  VpLeftRound(cv, VpGetRoundMode(), mx);
1764
- return ToValue(cv);
2089
+ return VpCheckGetValue(cv);
1765
2090
  }
1766
2091
  }
1767
2092
 
@@ -1791,10 +2116,35 @@ BigDecimal_sub2(VALUE self, VALUE b, VALUE n)
1791
2116
  VpSetPrecLimit(pl);
1792
2117
  GUARD_OBJ(cv, GetVpValue(c, 1));
1793
2118
  VpLeftRound(cv, VpGetRoundMode(), mx);
1794
- return ToValue(cv);
2119
+ return VpCheckGetValue(cv);
1795
2120
  }
1796
2121
  }
1797
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
+ */
1798
2148
 
1799
2149
  static VALUE
1800
2150
  BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
@@ -1809,18 +2159,19 @@ BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
1809
2159
  VpSetPrecLimit(pl);
1810
2160
  GUARD_OBJ(cv, GetVpValue(c, 1));
1811
2161
  VpLeftRound(cv, VpGetRoundMode(), mx);
1812
- return ToValue(cv);
2162
+ return VpCheckGetValue(cv);
1813
2163
  }
1814
2164
  }
1815
2165
 
1816
2166
  /*
1817
2167
  * call-seq:
1818
- * big_decimal.abs -> big_decimal
2168
+ * abs -> bigdecimal
1819
2169
  *
1820
- * Returns the absolute value, as a BigDecimal.
2170
+ * Returns the \BigDecimal absolute value of +self+:
2171
+ *
2172
+ * BigDecimal('5').abs # => 0.5e1
2173
+ * BigDecimal('-3').abs # => 0.3e1
1821
2174
  *
1822
- * BigDecimal('5').abs #=> 0.5e1
1823
- * BigDecimal('-3').abs #=> 0.3e1
1824
2175
  */
1825
2176
 
1826
2177
  static VALUE
@@ -1832,10 +2183,10 @@ BigDecimal_abs(VALUE self)
1832
2183
 
1833
2184
  GUARD_OBJ(a, GetVpValue(self, 1));
1834
2185
  mx = a->Prec *(VpBaseFig() + 1);
1835
- GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
2186
+ GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
1836
2187
  VpAsgn(c, a, 1);
1837
2188
  VpChangeSign(c, 1);
1838
- return ToValue(c);
2189
+ return VpCheckGetValue(c);
1839
2190
  }
1840
2191
 
1841
2192
  /* call-seq:
@@ -1857,9 +2208,9 @@ BigDecimal_sqrt(VALUE self, VALUE nFig)
1857
2208
 
1858
2209
  n = GetPrecisionInt(nFig) + VpDblFig() + BASE_FIG;
1859
2210
  if (mx <= n) mx = n;
1860
- GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
2211
+ GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
1861
2212
  VpSqrt(c, a);
1862
- return ToValue(c);
2213
+ return VpCheckGetValue(c);
1863
2214
  }
1864
2215
 
1865
2216
  /* Return the integer part of the number, as a BigDecimal.
@@ -1873,9 +2224,9 @@ BigDecimal_fix(VALUE self)
1873
2224
 
1874
2225
  GUARD_OBJ(a, GetVpValue(self, 1));
1875
2226
  mx = a->Prec *(VpBaseFig() + 1);
1876
- GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
2227
+ GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
1877
2228
  VpActiveRound(c, a, VP_ROUND_DOWN, 0); /* 0: round off */
1878
- return ToValue(c);
2229
+ return VpCheckGetValue(c);
1879
2230
  }
1880
2231
 
1881
2232
  /* call-seq:
@@ -1946,13 +2297,13 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
1946
2297
  pl = VpSetPrecLimit(0);
1947
2298
  GUARD_OBJ(a, GetVpValue(self, 1));
1948
2299
  mx = a->Prec * (VpBaseFig() + 1);
1949
- GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
2300
+ GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
1950
2301
  VpSetPrecLimit(pl);
1951
2302
  VpActiveRound(c, a, sw, iLoc);
1952
2303
  if (round_to_int) {
1953
- return BigDecimal_to_i(ToValue(c));
2304
+ return BigDecimal_to_i(VpCheckGetValue(c));
1954
2305
  }
1955
- return ToValue(c);
2306
+ return VpCheckGetValue(c);
1956
2307
  }
1957
2308
 
1958
2309
  /* call-seq:
@@ -1992,13 +2343,13 @@ BigDecimal_truncate(int argc, VALUE *argv, VALUE self)
1992
2343
 
1993
2344
  GUARD_OBJ(a, GetVpValue(self, 1));
1994
2345
  mx = a->Prec * (VpBaseFig() + 1);
1995
- GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
2346
+ GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
1996
2347
  VpSetPrecLimit(pl);
1997
2348
  VpActiveRound(c, a, VP_ROUND_DOWN, iLoc); /* 0: truncate */
1998
2349
  if (argc == 0) {
1999
- return BigDecimal_to_i(ToValue(c));
2350
+ return BigDecimal_to_i(VpCheckGetValue(c));
2000
2351
  }
2001
- return ToValue(c);
2352
+ return VpCheckGetValue(c);
2002
2353
  }
2003
2354
 
2004
2355
  /* Return the fractional part of the number, as a BigDecimal.
@@ -2012,9 +2363,9 @@ BigDecimal_frac(VALUE self)
2012
2363
 
2013
2364
  GUARD_OBJ(a, GetVpValue(self, 1));
2014
2365
  mx = a->Prec * (VpBaseFig() + 1);
2015
- GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
2366
+ GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
2016
2367
  VpFrac(c, a);
2017
- return ToValue(c);
2368
+ return VpCheckGetValue(c);
2018
2369
  }
2019
2370
 
2020
2371
  /* call-seq:
@@ -2052,16 +2403,16 @@ BigDecimal_floor(int argc, VALUE *argv, VALUE self)
2052
2403
 
2053
2404
  GUARD_OBJ(a, GetVpValue(self, 1));
2054
2405
  mx = a->Prec * (VpBaseFig() + 1);
2055
- GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
2406
+ GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
2056
2407
  VpSetPrecLimit(pl);
2057
2408
  VpActiveRound(c, a, VP_ROUND_FLOOR, iLoc);
2058
2409
  #ifdef BIGDECIMAL_DEBUG
2059
2410
  VPrint(stderr, "floor: c=%\n", c);
2060
2411
  #endif
2061
2412
  if (argc == 0) {
2062
- return BigDecimal_to_i(ToValue(c));
2413
+ return BigDecimal_to_i(VpCheckGetValue(c));
2063
2414
  }
2064
- return ToValue(c);
2415
+ return VpCheckGetValue(c);
2065
2416
  }
2066
2417
 
2067
2418
  /* call-seq:
@@ -2098,13 +2449,13 @@ BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
2098
2449
 
2099
2450
  GUARD_OBJ(a, GetVpValue(self, 1));
2100
2451
  mx = a->Prec * (VpBaseFig() + 1);
2101
- GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
2452
+ GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
2102
2453
  VpSetPrecLimit(pl);
2103
2454
  VpActiveRound(c, a, VP_ROUND_CEIL, iLoc);
2104
2455
  if (argc == 0) {
2105
- return BigDecimal_to_i(ToValue(c));
2456
+ return BigDecimal_to_i(VpCheckGetValue(c));
2106
2457
  }
2107
- return ToValue(c);
2458
+ return VpCheckGetValue(c);
2108
2459
  }
2109
2460
 
2110
2461
  /* call-seq:
@@ -2400,13 +2751,13 @@ is_even(VALUE x)
2400
2751
  }
2401
2752
 
2402
2753
  static VALUE
2403
- 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)
2404
2755
  {
2405
2756
  VALUE log_x, multiplied, y;
2406
2757
  volatile VALUE obj = exp->obj;
2407
2758
 
2408
2759
  if (VpIsZero(exp)) {
2409
- return ToValue(VpCreateRbObject(n, "1"));
2760
+ return VpCheckGetValue(VpCreateRbObject(n, "1", true));
2410
2761
  }
2411
2762
 
2412
2763
  log_x = BigMath_log(x->obj, SSIZET2NUM(n+1));
@@ -2444,10 +2795,10 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2444
2795
  n = NIL_P(prec) ? (ssize_t)(x->Prec*VpBaseFig()) : NUM2SSIZET(prec);
2445
2796
 
2446
2797
  if (VpIsNaN(x)) {
2447
- y = VpCreateRbObject(n, "0");
2798
+ y = VpCreateRbObject(n, "0", true);
2448
2799
  RB_GC_GUARD(y->obj);
2449
2800
  VpSetNaN(y);
2450
- return ToValue(y);
2801
+ return VpCheckGetValue(y);
2451
2802
  }
2452
2803
 
2453
2804
  retry:
@@ -2470,9 +2821,9 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2470
2821
  goto retry;
2471
2822
  }
2472
2823
  if (NIL_P(prec)) {
2473
- n += DBLE_FIG;
2824
+ n += BIGDECIMAL_DOUBLE_FIGURES;
2474
2825
  }
2475
- exp = GetVpValueWithPrec(vexp, DBLE_FIG, 1);
2826
+ exp = GetVpValueWithPrec(vexp, 0, 1);
2476
2827
  break;
2477
2828
 
2478
2829
  case T_RATIONAL:
@@ -2516,7 +2867,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2516
2867
 
2517
2868
  if (VpIsZero(x)) {
2518
2869
  if (is_negative(vexp)) {
2519
- y = VpCreateRbObject(n, "#0");
2870
+ y = VpCreateRbObject(n, "#0", true);
2520
2871
  RB_GC_GUARD(y->obj);
2521
2872
  if (BIGDECIMAL_NEGATIVE_P(x)) {
2522
2873
  if (is_integer(vexp)) {
@@ -2538,18 +2889,18 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2538
2889
  /* (+0) ** (-num) -> Infinity */
2539
2890
  VpSetPosInf(y);
2540
2891
  }
2541
- return ToValue(y);
2892
+ return VpCheckGetValue(y);
2542
2893
  }
2543
2894
  else if (is_zero(vexp)) {
2544
- return ToValue(VpCreateRbObject(n, "1"));
2895
+ return VpCheckGetValue(VpCreateRbObject(n, "1", true));
2545
2896
  }
2546
2897
  else {
2547
- return ToValue(VpCreateRbObject(n, "0"));
2898
+ return VpCheckGetValue(VpCreateRbObject(n, "0", true));
2548
2899
  }
2549
2900
  }
2550
2901
 
2551
2902
  if (is_zero(vexp)) {
2552
- return ToValue(VpCreateRbObject(n, "1"));
2903
+ return VpCheckGetValue(VpCreateRbObject(n, "1", true));
2553
2904
  }
2554
2905
  else if (is_one(vexp)) {
2555
2906
  return self;
@@ -2561,24 +2912,24 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2561
2912
  if (is_integer(vexp)) {
2562
2913
  if (is_even(vexp)) {
2563
2914
  /* (-Infinity) ** (-even_integer) -> +0 */
2564
- return ToValue(VpCreateRbObject(n, "0"));
2915
+ return VpCheckGetValue(VpCreateRbObject(n, "0", true));
2565
2916
  }
2566
2917
  else {
2567
2918
  /* (-Infinity) ** (-odd_integer) -> -0 */
2568
- return ToValue(VpCreateRbObject(n, "-0"));
2919
+ return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
2569
2920
  }
2570
2921
  }
2571
2922
  else {
2572
2923
  /* (-Infinity) ** (-non_integer) -> -0 */
2573
- return ToValue(VpCreateRbObject(n, "-0"));
2924
+ return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
2574
2925
  }
2575
2926
  }
2576
2927
  else {
2577
- return ToValue(VpCreateRbObject(n, "0"));
2928
+ return VpCheckGetValue(VpCreateRbObject(n, "0", true));
2578
2929
  }
2579
2930
  }
2580
2931
  else {
2581
- y = VpCreateRbObject(n, "0");
2932
+ y = VpCreateRbObject(n, "0", true);
2582
2933
  if (BIGDECIMAL_NEGATIVE_P(x)) {
2583
2934
  if (is_integer(vexp)) {
2584
2935
  if (is_even(vexp)) {
@@ -2597,52 +2948,52 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2597
2948
  else {
2598
2949
  VpSetPosInf(y);
2599
2950
  }
2600
- return ToValue(y);
2951
+ return VpCheckGetValue(y);
2601
2952
  }
2602
2953
  }
2603
2954
 
2604
2955
  if (exp != NULL) {
2605
- return rmpd_power_by_big_decimal(x, exp, n);
2956
+ return bigdecimal_power_by_bigdecimal(x, exp, n);
2606
2957
  }
2607
2958
  else if (RB_TYPE_P(vexp, T_BIGNUM)) {
2608
2959
  VALUE abs_value = BigDecimal_abs(self);
2609
2960
  if (is_one(abs_value)) {
2610
- return ToValue(VpCreateRbObject(n, "1"));
2961
+ return VpCheckGetValue(VpCreateRbObject(n, "1", true));
2611
2962
  }
2612
2963
  else if (RTEST(rb_funcall(abs_value, '<', 1, INT2FIX(1)))) {
2613
2964
  if (is_negative(vexp)) {
2614
- y = VpCreateRbObject(n, "0");
2965
+ y = VpCreateRbObject(n, "0", true);
2615
2966
  if (is_even(vexp)) {
2616
2967
  VpSetInf(y, VpGetSign(x));
2617
2968
  }
2618
2969
  else {
2619
2970
  VpSetInf(y, -VpGetSign(x));
2620
2971
  }
2621
- return ToValue(y);
2972
+ return VpCheckGetValue(y);
2622
2973
  }
2623
2974
  else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
2624
- return ToValue(VpCreateRbObject(n, "-0"));
2975
+ return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
2625
2976
  }
2626
2977
  else {
2627
- return ToValue(VpCreateRbObject(n, "0"));
2978
+ return VpCheckGetValue(VpCreateRbObject(n, "0", true));
2628
2979
  }
2629
2980
  }
2630
2981
  else {
2631
2982
  if (is_positive(vexp)) {
2632
- y = VpCreateRbObject(n, "0");
2983
+ y = VpCreateRbObject(n, "0", true);
2633
2984
  if (is_even(vexp)) {
2634
2985
  VpSetInf(y, VpGetSign(x));
2635
2986
  }
2636
2987
  else {
2637
2988
  VpSetInf(y, -VpGetSign(x));
2638
2989
  }
2639
- return ToValue(y);
2990
+ return VpCheckGetValue(y);
2640
2991
  }
2641
2992
  else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
2642
- return ToValue(VpCreateRbObject(n, "-0"));
2993
+ return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
2643
2994
  }
2644
2995
  else {
2645
- return ToValue(VpCreateRbObject(n, "0"));
2996
+ return VpCheckGetValue(VpCreateRbObject(n, "0", true));
2646
2997
  }
2647
2998
  }
2648
2999
  }
@@ -2654,24 +3005,30 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2654
3005
 
2655
3006
  if (VpIsDef(x)) {
2656
3007
  mp = x->Prec * (VpBaseFig() + 1);
2657
- GUARD_OBJ(y, VpCreateRbObject(mp * (ma + 1), "0"));
3008
+ GUARD_OBJ(y, VpCreateRbObject(mp * (ma + 1), "0", true));
2658
3009
  }
2659
3010
  else {
2660
- GUARD_OBJ(y, VpCreateRbObject(1, "0"));
3011
+ GUARD_OBJ(y, VpCreateRbObject(1, "0", true));
2661
3012
  }
2662
- VpPower(y, x, int_exp);
3013
+ VpPowerByInt(y, x, int_exp);
2663
3014
  if (!NIL_P(prec) && VpIsDef(y)) {
2664
3015
  VpMidRound(y, VpGetRoundMode(), n);
2665
3016
  }
2666
- return ToValue(y);
3017
+ return VpCheckGetValue(y);
2667
3018
  }
2668
3019
 
2669
- /* call-seq:
2670
- * a ** n -> bigdecimal
3020
+ /* call-seq:
3021
+ * self ** other -> bigdecimal
2671
3022
  *
2672
- * 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.
2673
3031
  *
2674
- * See BigDecimal#power.
2675
3032
  */
2676
3033
  static VALUE
2677
3034
  BigDecimal_power_op(VALUE self, VALUE exp)
@@ -2725,182 +3082,483 @@ opts_exception_p(VALUE opts)
2725
3082
  }
2726
3083
  #endif
2727
3084
 
2728
- static Real *
2729
- VpNewVarArg(int argc, VALUE *argv)
3085
+ static VALUE
3086
+ check_exception(VALUE bd)
2730
3087
  {
2731
- size_t mf;
2732
- VALUE opts = Qnil;
2733
- VALUE nFig;
2734
- VALUE iniValue;
2735
- double d;
2736
- 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
+ }
2737
3096
 
2738
- argc = rb_scan_args(argc, argv, "11:", &iniValue, &nFig, &opts);
2739
- 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);
2740
3101
 
2741
- if (argc == 1) {
2742
- 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;
2743
3118
  }
2744
3119
  else {
2745
- /* expand GetPrecisionInt for exception suppression */
2746
- ssize_t n = NUM2INT(nFig);
2747
- if (n < 0) {
2748
- if (!exc) {
2749
- 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;
2750
3128
  }
2751
- rb_raise(rb_eArgError, "negative precision");
2752
3129
  }
2753
- mf = (size_t)n;
2754
- }
2755
-
2756
- if (SPECIAL_CONST_P(iniValue)) {
2757
- switch (iniValue) {
2758
- case Qnil:
2759
- if (!exc) return NULL;
2760
- rb_raise(rb_eTypeError, "can't convert nil into BigDecimal");
2761
- case Qtrue:
2762
- if (!exc) return NULL;
2763
- rb_raise(rb_eTypeError, "can't convert true into BigDecimal");
2764
- case Qfalse:
2765
- if (!exc) return NULL;
2766
- rb_raise(rb_eTypeError, "can't convert false into BigDecimal");
2767
- default:
2768
- 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;
2769
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);
2770
3144
  }
2771
3145
 
2772
- retry:
2773
- switch (TYPE(iniValue)) {
2774
- case T_DATA:
2775
- if (is_kind_of_BigDecimal(iniValue)) {
2776
- return DATA_PTR(iniValue);
2777
- }
2778
- break;
3146
+ return BigDecimal_wrap_struct(obj, vp);
3147
+ }
2779
3148
 
2780
- case T_FIXNUM:
2781
- /* fall through */
2782
- case T_BIGNUM:
2783
- 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
+ }
2784
3161
 
2785
- case T_FLOAT:
2786
- d = RFLOAT_VALUE(iniValue);
2787
- if (!isfinite(d)) {
2788
- Real *pv = VpCreateRbObject(1, NULL);
2789
- VpDtoV(pv, d);
2790
- 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);
2791
3176
  }
2792
- if (mf > DBLE_FIG) {
2793
- if (!exc) {
2794
- return NULL;
2795
- }
2796
- rb_raise(rb_eArgError, "precision too large.");
2797
- }
2798
- /* fall through */
2799
- case T_RATIONAL:
2800
- if (NIL_P(nFig)) {
2801
- if (!exc) {
2802
- return NULL;
2803
- }
2804
- rb_raise(rb_eArgError,
2805
- "can't omit precision for a %"PRIsVALUE".",
2806
- RB_OBJ_CLASSNAME(iniValue));
2807
- }
2808
- 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
+ }
2809
3199
 
2810
- case T_COMPLEX:
2811
- {
2812
- VALUE im;
2813
- im = rb_complex_imag(iniValue);
2814
- if (!is_zero(im)) {
2815
- rb_raise(rb_eArgError,
2816
- "Unable to make a BigDecimal from non-zero imaginary number");
2817
- }
2818
- iniValue = rb_complex_real(iniValue);
2819
- 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();
2820
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();
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;
2821
3425
 
2822
- case T_STRING:
2823
- /* fall through */
2824
3426
  default:
2825
- 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);
2826
3445
  }
2827
- /* TODO: support to_d */
2828
- if (!exc) {
2829
- iniValue = rb_check_convert_type(iniValue, T_STRING, "String", "to_str");
2830
- if (NIL_P(iniValue)) return NULL;
3446
+ else if (RB_FLOAT_TYPE_P(val)) {
3447
+ return rb_float_convert_to_BigDecimal(val, digs, raise_exception);
2831
3448
  }
2832
- StringValueCStr(iniValue);
2833
- return VpAlloc(mf, RSTRING_PTR(iniValue), 1, exc);
3449
+ else if (RB_TYPE_P(val, T_RATIONAL)) {
3450
+ return rb_rational_convert_to_BigDecimal(val, digs, raise_exception);
3451
+ }
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);
2834
3477
  }
2835
3478
 
2836
- /* call-seq:
2837
- * BigDecimal(initial, digits, exception: true)
3479
+ /* call-seq:
3480
+ * BigDecimal(value, exception: true) -> bigdecimal
3481
+ * BigDecimal(value, ndigits, exception: true) -> bigdecimal
2838
3482
  *
2839
- * Create a new BigDecimal object.
3483
+ * Returns the \BigDecimal converted from +value+
3484
+ * with a precision of +ndigits+ decimal digits.
2840
3485
  *
2841
- * initial:: The initial value, as an Integer, a Float, a Rational,
2842
- * 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.
2843
3489
  *
2844
- * If it is a String, spaces are ignored and unrecognized characters
2845
- * terminate the value.
3490
+ * Returns +value+ converted to a \BigDecimal, depending on the type of +value+:
2846
3491
  *
2847
- * digits:: The number of significant digits, as an Integer. If omitted or 0,
2848
- * the number of significant digits is determined from the initial
2849
- * value.
3492
+ * - Integer, Float, Rational, Complex, or BigDecimal: converted directly:
2850
3493
  *
2851
- * The actual number of significant digits used in computation is
2852
- * 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
2853
3501
  *
2854
- * exception:: Whether an exception should be raised on invalid arguments.
2855
- * +true+ by default, if passed +false+, just returns +nil+
2856
- * for invalid.
3502
+ * - String: converted by parsing if it contains an integer or floating-point literal;
3503
+ * leading and trailing whitespace is ignored:
2857
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
2858
3510
  *
2859
- * ==== 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.
2860
3513
  *
2861
- * TypeError:: If the +initial+ type is neither Integer, Float,
2862
- * Rational, nor BigDecimal, this exception is raised.
3514
+ * - Other type:
2863
3515
  *
2864
- * 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+.
2865
3518
  *
2866
- * ArgumentError:: If +initial+ is a Float, and the +digits+ is larger than
2867
- * 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.
2868
3521
  *
2869
- * ArgumentError:: If the +initial+ is a Float or Rational, and the +digits+
2870
- * value is omitted, this exception is raised.
2871
3522
  */
2872
3523
  static VALUE
2873
3524
  f_BigDecimal(int argc, VALUE *argv, VALUE self)
2874
3525
  {
2875
- ENTER(1);
2876
- Real *pv;
2877
- VALUE obj;
2878
-
2879
- if (argc > 0 && CLASS_OF(argv[0]) == rb_cBigDecimal) {
2880
- 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
+ }
2881
3548
  }
2882
- obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0);
2883
- pv = VpNewVarArg(argc, argv);
2884
- if (pv == NULL) return Qnil;
2885
- SAVE(pv);
2886
- if (ToValue(pv)) pv = VpCopy(NULL, pv);
2887
- RTYPEDDATA_DATA(obj) = pv;
2888
- RB_OBJ_FREEZE(obj);
2889
- return pv->obj = obj;
3549
+
3550
+ return rb_convert_to_BigDecimal(val, digs, exception);
2890
3551
  }
2891
3552
 
2892
3553
  static VALUE
2893
3554
  BigDecimal_s_interpret_loosely(VALUE klass, VALUE str)
2894
3555
  {
2895
- ENTER(1);
2896
- char const *c_str;
2897
- Real *pv;
2898
-
2899
- c_str = StringValueCStr(str);
2900
- GUARD_OBJ(pv, VpAlloc(0, c_str, 0, 1));
2901
- pv->obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, pv);
2902
- RB_OBJ_FREEZE(pv->obj);
2903
- 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);
2904
3562
  }
2905
3563
 
2906
3564
  /* call-seq:
@@ -3084,7 +3742,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
3084
3742
  infinite = isinf(flo);
3085
3743
  nan = isnan(flo);
3086
3744
  if (!infinite && !nan) {
3087
- vx = GetVpValueWithPrec(x, DBLE_FIG, 0);
3745
+ vx = GetVpValueWithPrec(x, 0, 0);
3088
3746
  }
3089
3747
  break;
3090
3748
 
@@ -3097,29 +3755,29 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
3097
3755
  }
3098
3756
  if (infinite) {
3099
3757
  if (negative) {
3100
- return ToValue(GetVpValueWithPrec(INT2FIX(0), prec, 1));
3758
+ return VpCheckGetValue(GetVpValueWithPrec(INT2FIX(0), prec, 1));
3101
3759
  }
3102
3760
  else {
3103
3761
  Real* vy;
3104
- vy = VpCreateRbObject(prec, "#0");
3762
+ vy = VpCreateRbObject(prec, "#0", true);
3105
3763
  VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
3106
3764
  RB_GC_GUARD(vy->obj);
3107
- return ToValue(vy);
3765
+ return VpCheckGetValue(vy);
3108
3766
  }
3109
3767
  }
3110
3768
  else if (nan) {
3111
3769
  Real* vy;
3112
- vy = VpCreateRbObject(prec, "#0");
3770
+ vy = VpCreateRbObject(prec, "#0", true);
3113
3771
  VpSetNaN(vy);
3114
3772
  RB_GC_GUARD(vy->obj);
3115
- return ToValue(vy);
3773
+ return VpCheckGetValue(vy);
3116
3774
  }
3117
3775
  else if (vx == NULL) {
3118
3776
  cannot_be_coerced_into_BigDecimal(rb_eArgError, x);
3119
3777
  }
3120
3778
  x = vx->obj;
3121
3779
 
3122
- n = prec + rmpd_double_figures();
3780
+ n = prec + BIGDECIMAL_DOUBLE_FIGURES;
3123
3781
  negative = BIGDECIMAL_NEGATIVE_P(vx);
3124
3782
  if (negative) {
3125
3783
  VALUE x_zero = INT2NUM(1);
@@ -3129,7 +3787,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
3129
3787
  VpSetSign(vx, 1);
3130
3788
  }
3131
3789
 
3132
- one = ToValue(VpCreateRbObject(1, "1"));
3790
+ one = VpCheckGetValue(VpCreateRbObject(1, "1", true));
3133
3791
  y = one;
3134
3792
  d = y;
3135
3793
  i = 1;
@@ -3144,8 +3802,8 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
3144
3802
  if (m <= 0) {
3145
3803
  break;
3146
3804
  }
3147
- else if ((size_t)m < rmpd_double_figures()) {
3148
- m = rmpd_double_figures();
3805
+ else if ((size_t)m < BIGDECIMAL_DOUBLE_FIGURES) {
3806
+ m = BIGDECIMAL_DOUBLE_FIGURES;
3149
3807
  }
3150
3808
 
3151
3809
  d = BigDecimal_mult(d, x); /* d <- d * x */
@@ -3237,7 +3895,7 @@ get_vp_value:
3237
3895
  infinite = isinf(flo);
3238
3896
  nan = isnan(flo);
3239
3897
  if (!zero && !negative && !infinite && !nan) {
3240
- vx = GetVpValueWithPrec(x, DBLE_FIG, 1);
3898
+ vx = GetVpValueWithPrec(x, 0, 1);
3241
3899
  }
3242
3900
  break;
3243
3901
 
@@ -3257,17 +3915,17 @@ get_vp_value:
3257
3915
  }
3258
3916
  if (infinite && !negative) {
3259
3917
  Real* vy;
3260
- vy = VpCreateRbObject(prec, "#0");
3918
+ vy = VpCreateRbObject(prec, "#0", true);
3261
3919
  RB_GC_GUARD(vy->obj);
3262
3920
  VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
3263
- return ToValue(vy);
3921
+ return VpCheckGetValue(vy);
3264
3922
  }
3265
3923
  else if (nan) {
3266
3924
  Real* vy;
3267
- vy = VpCreateRbObject(prec, "#0");
3925
+ vy = VpCreateRbObject(prec, "#0", true);
3268
3926
  RB_GC_GUARD(vy->obj);
3269
3927
  VpSetNaN(vy);
3270
- return ToValue(vy);
3928
+ return VpCheckGetValue(vy);
3271
3929
  }
3272
3930
  else if (zero || negative) {
3273
3931
  rb_raise(rb_eMathDomainError,
@@ -3276,18 +3934,18 @@ get_vp_value:
3276
3934
  else if (vx == NULL) {
3277
3935
  cannot_be_coerced_into_BigDecimal(rb_eArgError, x);
3278
3936
  }
3279
- x = ToValue(vx);
3937
+ x = VpCheckGetValue(vx);
3280
3938
 
3281
- RB_GC_GUARD(one) = ToValue(VpCreateRbObject(1, "1"));
3282
- 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));
3283
3941
 
3284
- n = prec + rmpd_double_figures();
3942
+ n = prec + BIGDECIMAL_DOUBLE_FIGURES;
3285
3943
  RB_GC_GUARD(vn) = SSIZET2NUM(n);
3286
3944
  expo = VpExponent10(vx);
3287
3945
  if (expo < 0 || expo >= 3) {
3288
3946
  char buf[DECIMAL_SIZE_OF_BITS(SIZEOF_VALUE * CHAR_BIT) + 4];
3289
3947
  snprintf(buf, sizeof(buf), "1E%"PRIdVALUE, -expo);
3290
- x = BigDecimal_mult2(x, ToValue(VpCreateRbObject(1, buf)), vn);
3948
+ x = BigDecimal_mult2(x, VpCheckGetValue(VpCreateRbObject(1, buf, true)), vn);
3291
3949
  }
3292
3950
  else {
3293
3951
  expo = 0;
@@ -3305,8 +3963,8 @@ get_vp_value:
3305
3963
  if (m <= 0) {
3306
3964
  break;
3307
3965
  }
3308
- else if ((size_t)m < rmpd_double_figures()) {
3309
- m = rmpd_double_figures();
3966
+ else if ((size_t)m < BIGDECIMAL_DOUBLE_FIGURES) {
3967
+ m = BIGDECIMAL_DOUBLE_FIGURES;
3310
3968
  }
3311
3969
 
3312
3970
  x = BigDecimal_mult2(x2, x, vn);
@@ -3319,7 +3977,7 @@ get_vp_value:
3319
3977
  if (expo != 0) {
3320
3978
  VALUE log10, vexpo, dy;
3321
3979
  log10 = BigMath_s_log(klass, INT2FIX(10), vprec);
3322
- vexpo = ToValue(GetVpValue(SSIZET2NUM(expo), 1));
3980
+ vexpo = VpCheckGetValue(GetVpValue(SSIZET2NUM(expo), 1));
3323
3981
  dy = BigDecimal_mult(log10, vexpo);
3324
3982
  y = BigDecimal_add(y, dy);
3325
3983
  }
@@ -3327,6 +3985,46 @@ get_vp_value:
3327
3985
  return y;
3328
3986
  }
3329
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
+
3330
4028
  /* Document-class: BigDecimal
3331
4029
  * BigDecimal provides arbitrary-precision floating point decimal arithmetic.
3332
4030
  *
@@ -3370,6 +4068,18 @@ get_vp_value:
3370
4068
  *
3371
4069
  * (1.2 - 1.0) == 0.2 #=> false
3372
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
+ *
3373
4083
  * == Special features of accurate decimal arithmetic
3374
4084
  *
3375
4085
  * Because BigDecimal is more accurate than normal binary floating point
@@ -3598,17 +4308,40 @@ Init_bigdecimal(void)
3598
4308
  /* -3: Indicates that a value is negative and infinite. See BigDecimal.sign. */
3599
4309
  rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_INFINITE", INT2FIX(VP_SIGN_NEGATIVE_INFINITE));
3600
4310
 
3601
- 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
+
3602
4321
  /* Positive infinity value. */
3603
- rb_define_const(rb_cBigDecimal, "INFINITY", f_BigDecimal(1, &arg, rb_cBigDecimal));
3604
- 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
+
3605
4331
  /* 'Not a Number' value. */
3606
- 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);
3607
4335
 
4336
+ /* Special value constants */
4337
+ rb_define_const(rb_cBigDecimal, "INFINITY", BIGDECIMAL_POSITIVE_INFINITY);
4338
+ rb_define_const(rb_cBigDecimal, "NAN", BIGDECIMAL_NAN);
3608
4339
 
3609
4340
  /* instance methods */
3610
4341
  rb_define_method(rb_cBigDecimal, "precs", BigDecimal_prec, 0);
3611
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);
3612
4345
  rb_define_method(rb_cBigDecimal, "n_significant_digits", BigDecimal_n_significant_digits, 0);
3613
4346
 
3614
4347
  rb_define_method(rb_cBigDecimal, "add", BigDecimal_add2, 2);
@@ -3627,7 +4360,7 @@ Init_bigdecimal(void)
3627
4360
  rb_define_method(rb_cBigDecimal, "-@", BigDecimal_neg, 0);
3628
4361
  rb_define_method(rb_cBigDecimal, "*", BigDecimal_mult, 1);
3629
4362
  rb_define_method(rb_cBigDecimal, "/", BigDecimal_div, 1);
3630
- rb_define_method(rb_cBigDecimal, "quo", BigDecimal_div, 1);
4363
+ rb_define_method(rb_cBigDecimal, "quo", BigDecimal_quo, -1);
3631
4364
  rb_define_method(rb_cBigDecimal, "%", BigDecimal_mod, 1);
3632
4365
  rb_define_method(rb_cBigDecimal, "modulo", BigDecimal_mod, 1);
3633
4366
  rb_define_method(rb_cBigDecimal, "remainder", BigDecimal_remainder, 1);
@@ -3718,9 +4451,9 @@ enum op_sw {
3718
4451
 
3719
4452
  static int VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw);
3720
4453
  static int AddExponent(Real *a, SIGNED_VALUE n);
3721
- static BDIGIT VpAddAbs(Real *a,Real *b,Real *c);
3722
- static BDIGIT VpSubAbs(Real *a,Real *b,Real *c);
3723
- 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);
3724
4457
  static int VpNmlz(Real *a);
3725
4458
  static void VpFormatSt(char *psz, size_t fFmt);
3726
4459
  static int VpRdup(Real *m, size_t ind_m);
@@ -3736,9 +4469,6 @@ VP_EXPORT void *
3736
4469
  VpMemAlloc(size_t mb)
3737
4470
  {
3738
4471
  void *p = xmalloc(mb);
3739
- if (!p) {
3740
- VpException(VP_EXCEPTION_MEMORY, "failed to allocate memory", 1);
3741
- }
3742
4472
  memset(p, 0, mb);
3743
4473
  #ifdef BIGDECIMAL_DEBUG
3744
4474
  gnAlloc++; /* Count allocation call */
@@ -3749,11 +4479,7 @@ VpMemAlloc(size_t mb)
3749
4479
  VP_EXPORT void *
3750
4480
  VpMemRealloc(void *ptr, size_t mb)
3751
4481
  {
3752
- void *p = xrealloc(ptr, mb);
3753
- if (!p) {
3754
- VpException(VP_EXCEPTION_MEMORY, "failed to allocate memory", 1);
3755
- }
3756
- return p;
4482
+ return xrealloc(ptr, mb);
3757
4483
  }
3758
4484
 
3759
4485
  VP_EXPORT void
@@ -3779,7 +4505,7 @@ VpFree(Real *pv)
3779
4505
  * EXCEPTION Handling.
3780
4506
  */
3781
4507
 
3782
- #define rmpd_set_thread_local_exception_mode(mode) \
4508
+ #define bigdecimal_set_thread_local_exception_mode(mode) \
3783
4509
  rb_thread_local_aset( \
3784
4510
  rb_thread_current(), \
3785
4511
  id_BigDecimal_exception_mode, \
@@ -3795,8 +4521,8 @@ VpGetException (void)
3795
4521
  );
3796
4522
 
3797
4523
  if (NIL_P(vmode)) {
3798
- rmpd_set_thread_local_exception_mode(RMPD_EXCEPTION_MODE_DEFAULT);
3799
- return RMPD_EXCEPTION_MODE_DEFAULT;
4524
+ bigdecimal_set_thread_local_exception_mode(BIGDECIMAL_EXCEPTION_MODE_DEFAULT);
4525
+ return BIGDECIMAL_EXCEPTION_MODE_DEFAULT;
3800
4526
  }
3801
4527
 
3802
4528
  return NUM2USHORT(vmode);
@@ -3805,20 +4531,41 @@ VpGetException (void)
3805
4531
  static void
3806
4532
  VpSetException(unsigned short f)
3807
4533
  {
3808
- 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;
3809
4556
  }
3810
4557
 
3811
4558
  /*
3812
4559
  * Precision limit.
3813
4560
  */
3814
4561
 
3815
- #define rmpd_set_thread_local_precision_limit(limit) \
4562
+ #define bigdecimal_set_thread_local_precision_limit(limit) \
3816
4563
  rb_thread_local_aset( \
3817
4564
  rb_thread_current(), \
3818
4565
  id_BigDecimal_precision_limit, \
3819
4566
  SIZET2NUM(limit) \
3820
4567
  )
3821
- #define RMPD_PRECISION_LIMIT_DEFAULT ((size_t)0)
4568
+ #define BIGDECIMAL_PRECISION_LIMIT_DEFAULT ((size_t)0)
3822
4569
 
3823
4570
  /* These 2 functions added at v1.1.7 */
3824
4571
  VP_EXPORT size_t
@@ -3830,8 +4577,8 @@ VpGetPrecLimit(void)
3830
4577
  );
3831
4578
 
3832
4579
  if (NIL_P(vlimit)) {
3833
- rmpd_set_thread_local_precision_limit(RMPD_PRECISION_LIMIT_DEFAULT);
3834
- return RMPD_PRECISION_LIMIT_DEFAULT;
4580
+ bigdecimal_set_thread_local_precision_limit(BIGDECIMAL_PRECISION_LIMIT_DEFAULT);
4581
+ return BIGDECIMAL_PRECISION_LIMIT_DEFAULT;
3835
4582
  }
3836
4583
 
3837
4584
  return NUM2SIZET(vlimit);
@@ -3841,7 +4588,7 @@ VP_EXPORT size_t
3841
4588
  VpSetPrecLimit(size_t n)
3842
4589
  {
3843
4590
  size_t const s = VpGetPrecLimit();
3844
- rmpd_set_thread_local_precision_limit(n);
4591
+ bigdecimal_set_thread_local_precision_limit(n);
3845
4592
  return s;
3846
4593
  }
3847
4594
 
@@ -3849,7 +4596,7 @@ VpSetPrecLimit(size_t n)
3849
4596
  * Rounding mode.
3850
4597
  */
3851
4598
 
3852
- #define rmpd_set_thread_local_rounding_mode(mode) \
4599
+ #define bigdecimal_set_thread_local_rounding_mode(mode) \
3853
4600
  rb_thread_local_aset( \
3854
4601
  rb_thread_current(), \
3855
4602
  id_BigDecimal_rounding_mode, \
@@ -3865,8 +4612,8 @@ VpGetRoundMode(void)
3865
4612
  );
3866
4613
 
3867
4614
  if (NIL_P(vmode)) {
3868
- rmpd_set_thread_local_rounding_mode(RMPD_ROUNDING_MODE_DEFAULT);
3869
- return RMPD_ROUNDING_MODE_DEFAULT;
4615
+ bigdecimal_set_thread_local_rounding_mode(BIGDECIMAL_ROUNDING_MODE_DEFAULT);
4616
+ return BIGDECIMAL_ROUNDING_MODE_DEFAULT;
3870
4617
  }
3871
4618
 
3872
4619
  return NUM2USHORT(vmode);
@@ -3894,7 +4641,7 @@ VP_EXPORT unsigned short
3894
4641
  VpSetRoundMode(unsigned short n)
3895
4642
  {
3896
4643
  if (VpIsRoundMode(n)) {
3897
- rmpd_set_thread_local_rounding_mode(n);
4644
+ bigdecimal_set_thread_local_rounding_mode(n);
3898
4645
  return n;
3899
4646
  }
3900
4647
 
@@ -3971,7 +4718,7 @@ VpException(unsigned short f, const char *str,int always)
3971
4718
  {
3972
4719
  unsigned short const exception_mode = VpGetException();
3973
4720
 
3974
- if (f == VP_EXCEPTION_OP || f == VP_EXCEPTION_MEMORY) always = 1;
4721
+ if (f == VP_EXCEPTION_OP) always = 1;
3975
4722
 
3976
4723
  if (always || (exception_mode & f)) {
3977
4724
  switch(f) {
@@ -3983,7 +4730,6 @@ VpException(unsigned short f, const char *str,int always)
3983
4730
  case VP_EXCEPTION_OP:
3984
4731
  rb_raise(rb_eFloatDomainError, "%s", str);
3985
4732
  break;
3986
- case VP_EXCEPTION_MEMORY:
3987
4733
  default:
3988
4734
  rb_fatal("%s", str);
3989
4735
  }
@@ -4132,13 +4878,13 @@ VpNumOfChars(Real *vp,const char *pszFmt)
4132
4878
  * that BASE is as large as possible satisfying the
4133
4879
  * relation MaxVal <= BASE*(BASE+1). Where the value
4134
4880
  * MaxVal is the largest value which can be represented
4135
- * by one BDIGIT word in the computer used.
4881
+ * by one DECDIG word in the computer used.
4136
4882
  *
4137
4883
  * [Returns]
4138
- * DBLE_FIG ... OK
4884
+ * BIGDECIMAL_DOUBLE_FIGURES ... OK
4139
4885
  */
4140
4886
  VP_EXPORT size_t
4141
- VpInit(BDIGIT BaseVal)
4887
+ VpInit(DECDIG BaseVal)
4142
4888
  {
4143
4889
  /* Setup +/- Inf NaN -0 */
4144
4890
  VpGetDoubleNegZero();
@@ -4153,16 +4899,16 @@ VpInit(BDIGIT BaseVal)
4153
4899
 
4154
4900
  #ifdef BIGDECIMAL_DEBUG
4155
4901
  if (gfDebug) {
4156
- printf("VpInit: BaseVal = %"PRIuBDIGIT"\n", BaseVal);
4157
- printf("\tBASE = %"PRIuBDIGIT"\n", BASE);
4158
- printf("\tHALF_BASE = %"PRIuBDIGIT"\n", HALF_BASE);
4159
- printf("\tBASE1 = %"PRIuBDIGIT"\n", BASE1);
4160
- printf("\tBASE_FIG = %u\n", BASE_FIG);
4161
- 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);
4162
4908
  }
4163
4909
  #endif /* BIGDECIMAL_DEBUG */
4164
4910
 
4165
- return rmpd_double_figures();
4911
+ return BIGDECIMAL_DOUBLE_FIGURES;
4166
4912
  }
4167
4913
 
4168
4914
  VP_EXPORT Real *
@@ -4210,7 +4956,7 @@ overflow:
4210
4956
  }
4211
4957
 
4212
4958
  Real *
4213
- rmpd_parse_special_string(const char *str)
4959
+ bigdecimal_parse_special_string(const char *str)
4214
4960
  {
4215
4961
  static const struct {
4216
4962
  const char *str;
@@ -4305,14 +5051,13 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
4305
5051
  /* at least mx digits. */
4306
5052
  /* szVal==NULL ==> allocate zero value. */
4307
5053
  vp = VpAllocReal(mx);
4308
- /* xmalloc() always returns(or throw interruption) */
4309
5054
  vp->MaxPrec = mx; /* set max precision */
4310
5055
  VpSetZero(vp, 1); /* initialize vp to zero. */
4311
5056
  return vp;
4312
5057
  }
4313
5058
 
4314
5059
  /* Check on Inf & NaN */
4315
- if ((vp = rmpd_parse_special_string(szVal)) != NULL) {
5060
+ if ((vp = bigdecimal_parse_special_string(szVal)) != NULL) {
4316
5061
  return vp;
4317
5062
  }
4318
5063
 
@@ -4481,7 +5226,6 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
4481
5226
  nalloc = Max(nalloc, mx);
4482
5227
  mx = nalloc;
4483
5228
  vp = VpAllocReal(mx);
4484
- /* xmalloc() always returns(or throw interruption) */
4485
5229
  vp->MaxPrec = mx; /* set max precision */
4486
5230
  VpSetZero(vp, sign);
4487
5231
  VpCtoV(vp, psz, ni, psz + ipf, nf, psz + ipe, ne);
@@ -4520,7 +5264,7 @@ VpAsgn(Real *c, Real *a, int isw)
4520
5264
  VpSetSign(c, isw * VpGetSign(a)); /* set sign */
4521
5265
  n = (a->Prec < c->MaxPrec) ? (a->Prec) : (c->MaxPrec);
4522
5266
  c->Prec = n;
4523
- memcpy(c->frac, a->frac, n * sizeof(BDIGIT));
5267
+ memcpy(c->frac, a->frac, n * sizeof(DECDIG));
4524
5268
  /* Needs round ? */
4525
5269
  if (isw != 10) {
4526
5270
  /* Not in ActiveRound */
@@ -4551,7 +5295,7 @@ VpAddSub(Real *c, Real *a, Real *b, int operation)
4551
5295
  short sw, isw;
4552
5296
  Real *a_ptr, *b_ptr;
4553
5297
  size_t n, na, nb, i;
4554
- BDIGIT mrv;
5298
+ DECDIG mrv;
4555
5299
 
4556
5300
  #ifdef BIGDECIMAL_DEBUG
4557
5301
  if (gfDebug) {
@@ -4679,7 +5423,7 @@ end_if:
4679
5423
  * a and b assuming abs(a)>abs(b).
4680
5424
  * c = abs(a) + abs(b) ; where |a|>=|b|
4681
5425
  */
4682
- static BDIGIT
5426
+ static DECDIG
4683
5427
  VpAddAbs(Real *a, Real *b, Real *c)
4684
5428
  {
4685
5429
  size_t word_shift;
@@ -4689,7 +5433,7 @@ VpAddAbs(Real *a, Real *b, Real *c)
4689
5433
  size_t a_pos;
4690
5434
  size_t b_pos, b_pos_with_word_shift;
4691
5435
  size_t c_pos;
4692
- BDIGIT av, bv, carry, mrv;
5436
+ DECDIG av, bv, carry, mrv;
4693
5437
 
4694
5438
  #ifdef BIGDECIMAL_DEBUG
4695
5439
  if (gfDebug) {
@@ -4774,7 +5518,7 @@ Exit:
4774
5518
  /*
4775
5519
  * c = abs(a) - abs(b)
4776
5520
  */
4777
- static BDIGIT
5521
+ static DECDIG
4778
5522
  VpSubAbs(Real *a, Real *b, Real *c)
4779
5523
  {
4780
5524
  size_t word_shift;
@@ -4784,7 +5528,7 @@ VpSubAbs(Real *a, Real *b, Real *c)
4784
5528
  size_t a_pos;
4785
5529
  size_t b_pos, b_pos_with_word_shift;
4786
5530
  size_t c_pos;
4787
- BDIGIT av, bv, borrow, mrv;
5531
+ DECDIG av, bv, borrow, mrv;
4788
5532
 
4789
5533
  #ifdef BIGDECIMAL_DEBUG
4790
5534
  if (gfDebug) {
@@ -4891,7 +5635,7 @@ Exit:
4891
5635
  * c_pos = |
4892
5636
  */
4893
5637
  static size_t
4894
- 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)
4895
5639
  {
4896
5640
  size_t left_word, right_word, word_shift;
4897
5641
 
@@ -5006,8 +5750,8 @@ VpMult(Real *c, Real *a, Real *b)
5006
5750
  size_t MxIndA, MxIndB, MxIndAB, MxIndC;
5007
5751
  size_t ind_c, i, ii, nc;
5008
5752
  size_t ind_as, ind_ae, ind_bs;
5009
- BDIGIT carry;
5010
- BDIGIT_DBL s;
5753
+ DECDIG carry;
5754
+ DECDIG_DBL s;
5011
5755
  Real *w;
5012
5756
 
5013
5757
  #ifdef BIGDECIMAL_DEBUG
@@ -5061,7 +5805,7 @@ VpMult(Real *c, Real *a, Real *b)
5061
5805
  VpSetSign(c, VpGetSign(a) * VpGetSign(b)); /* set sign */
5062
5806
  carry = 0;
5063
5807
  nc = ind_c = MxIndAB;
5064
- memset(c->frac, 0, (nc + 1) * sizeof(BDIGIT)); /* Initialize c */
5808
+ memset(c->frac, 0, (nc + 1) * sizeof(DECDIG)); /* Initialize c */
5065
5809
  c->Prec = nc + 1; /* set precision */
5066
5810
  for (nc = 0; nc < MxIndAB; ++nc, --ind_c) {
5067
5811
  if (nc < MxIndB) { /* The left triangle of the Fig. */
@@ -5081,15 +5825,15 @@ VpMult(Real *c, Real *a, Real *b)
5081
5825
  }
5082
5826
 
5083
5827
  for (i = ind_as; i <= ind_ae; ++i) {
5084
- s = (BDIGIT_DBL)a->frac[i] * b->frac[ind_bs--];
5085
- carry = (BDIGIT)(s / BASE);
5086
- s -= (BDIGIT_DBL)carry * BASE;
5087
- c->frac[ind_c] += (BDIGIT)s;
5088
- if (c->frac[ind_c] >= BASE) {
5089
- s = c->frac[ind_c] / BASE;
5090
- carry += (BDIGIT)s;
5091
- c->frac[ind_c] -= (BDIGIT)(s * BASE);
5092
- }
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
+ }
5093
5837
  if (carry) {
5094
5838
  ii = ind_c;
5095
5839
  while (ii-- > 0) {
@@ -5135,9 +5879,9 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
5135
5879
  size_t word_a, word_b, word_c, word_r;
5136
5880
  size_t i, n, ind_a, ind_b, ind_c, ind_r;
5137
5881
  size_t nLoop;
5138
- BDIGIT_DBL q, b1, b1p1, b1b2, b1b2p1, r1r2;
5139
- BDIGIT borrow, borrow1, borrow2;
5140
- BDIGIT_DBL qb;
5882
+ DECDIG_DBL q, b1, b1p1, b1b2, b1b2p1, r1r2;
5883
+ DECDIG borrow, borrow1, borrow2;
5884
+ DECDIG_DBL qb;
5141
5885
 
5142
5886
  #ifdef BIGDECIMAL_DEBUG
5143
5887
  if (gfDebug) {
@@ -5209,7 +5953,7 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
5209
5953
  ++ind_c;
5210
5954
  continue;
5211
5955
  }
5212
- 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];
5213
5957
  if (r1r2 == b1b2) {
5214
5958
  /* The first two word digits is the same */
5215
5959
  ind_b = 2;
@@ -5246,17 +5990,17 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
5246
5990
  /* The first two word digits is not the same, */
5247
5991
  /* then compare magnitude, and divide actually. */
5248
5992
  if (r1r2 >= b1b2p1) {
5249
- q = r1r2 / b1b2p1; /* q == (BDIGIT)q */
5250
- c->frac[ind_c] += (BDIGIT)q;
5251
- ind_r = b->Prec + ind_c - 1;
5252
- 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;
5253
5997
  }
5254
5998
 
5255
5999
  div_b1p1:
5256
- if (ind_c + 1 >= word_c) goto out_side;
5257
- q = r1r2 / b1p1; /* q == (BDIGIT)q */
5258
- c->frac[ind_c + 1] += (BDIGIT)q;
5259
- 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;
5260
6004
 
5261
6005
  sub_mult:
5262
6006
  borrow1 = borrow2 = 0;
@@ -5268,16 +6012,16 @@ sub_mult:
5268
6012
  qb = q * b->frac[ind_b];
5269
6013
  if (qb < BASE) borrow1 = 0;
5270
6014
  else {
5271
- borrow1 = (BDIGIT)(qb / BASE);
5272
- qb -= (BDIGIT_DBL)borrow1 * BASE; /* get qb < BASE */
6015
+ borrow1 = (DECDIG)(qb / BASE);
6016
+ qb -= (DECDIG_DBL)borrow1 * BASE; /* get qb < BASE */
5273
6017
  }
5274
6018
  if(r->frac[ind_r] < qb) {
5275
- r->frac[ind_r] += (BDIGIT)(BASE - qb);
5276
- borrow2 = borrow2 + borrow1 + 1;
6019
+ r->frac[ind_r] += (DECDIG)(BASE - qb);
6020
+ borrow2 = borrow2 + borrow1 + 1;
5277
6021
  }
5278
6022
  else {
5279
- r->frac[ind_r] -= (BDIGIT)qb;
5280
- borrow2 += borrow1;
6023
+ r->frac[ind_r] -= (DECDIG)qb;
6024
+ borrow2 += borrow1;
5281
6025
  }
5282
6026
  if (borrow2) {
5283
6027
  if(r->frac[ind_r - 1] < borrow2) {
@@ -5359,9 +6103,9 @@ VpNmlz(Real *a)
5359
6103
  i = 0;
5360
6104
  while (a->frac[i] == 0) ++i; /* skip the first few zeros */
5361
6105
  if (i) {
5362
- a->Prec -= i;
5363
- if (!AddExponent(a, -(SIGNED_VALUE)i)) return 0;
5364
- 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));
5365
6109
  }
5366
6110
  return 1;
5367
6111
  }
@@ -5484,7 +6228,7 @@ static int
5484
6228
  VPrint(FILE *fp, const char *cntl_chr, Real *a)
5485
6229
  {
5486
6230
  size_t i, j, nc, nd, ZeroSup, sep = 10;
5487
- BDIGIT m, e, nn;
6231
+ DECDIG m, e, nn;
5488
6232
 
5489
6233
  j = 0;
5490
6234
  nd = nc = 0; /* nd : number of digits in fraction part(every 10 digits, */
@@ -5519,7 +6263,7 @@ VPrint(FILE *fp, const char *cntl_chr, Real *a)
5519
6263
  case '0': case 'z':
5520
6264
  ZeroSup = 0;
5521
6265
  ++j;
5522
- sep = cntl_chr[j] == 'z' ? RMPD_COMPONENT_FIGURES : 10;
6266
+ sep = cntl_chr[j] == 'z' ? BIGDECIMAL_COMPONENT_FIGURES : 10;
5523
6267
  break;
5524
6268
  }
5525
6269
  for (i = 0; i < a->Prec; ++i) {
@@ -5628,7 +6372,7 @@ VP_EXPORT void
5628
6372
  VpSzMantissa(Real *a,char *psz)
5629
6373
  {
5630
6374
  size_t i, n, ZeroSup;
5631
- BDIGIT_DBL m, e, nn;
6375
+ DECDIG_DBL m, e, nn;
5632
6376
 
5633
6377
  if (VpIsNaN(a)) {
5634
6378
  sprintf(psz, SZ_NaN);
@@ -5711,7 +6455,7 @@ VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
5711
6455
  /* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
5712
6456
  {
5713
6457
  size_t i, n, ZeroSup;
5714
- BDIGIT shift, m, e, nn;
6458
+ DECDIG shift, m, e, nn;
5715
6459
  char *pszSav = psz;
5716
6460
  ssize_t ex;
5717
6461
 
@@ -5759,7 +6503,7 @@ VpToFString(Real *a, char *psz, size_t fFmt, int fPlus)
5759
6503
  /* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
5760
6504
  {
5761
6505
  size_t i, n;
5762
- BDIGIT m, e, nn;
6506
+ DECDIG m, e, nn;
5763
6507
  char *pszSav = psz;
5764
6508
  ssize_t ex;
5765
6509
 
@@ -5834,7 +6578,7 @@ VpCtoV(Real *a, const char *int_chr, size_t ni, const char *frac, size_t nf, con
5834
6578
  me = ne;
5835
6579
  signe = 1;
5836
6580
  exponent_overflow = 0;
5837
- memset(a->frac, 0, ma * sizeof(BDIGIT));
6581
+ memset(a->frac, 0, ma * sizeof(DECDIG));
5838
6582
  if (ne > 0) {
5839
6583
  i = 0;
5840
6584
  if (exp_chr[0] == '-') {
@@ -5971,7 +6715,7 @@ Final:
5971
6715
  * [Output]
5972
6716
  * *d ... fraction part of m(d = 0.xxxxxxx). where # of 'x's is fig.
5973
6717
  * *e ... exponent of m.
5974
- * DBLE_FIG ... Number of digits in a double variable.
6718
+ * BIGDECIMAL_DOUBLE_FIGURES ... Number of digits in a double variable.
5975
6719
  *
5976
6720
  * m -> d*10**e, 0<d<BASE
5977
6721
  * [Returns]
@@ -6018,7 +6762,7 @@ VpVtoD(double *d, SIGNED_VALUE *e, Real *m)
6018
6762
  goto Exit;
6019
6763
  }
6020
6764
  /* Normal number */
6021
- fig = (DBLE_FIG + BASE_FIG - 1) / BASE_FIG;
6765
+ fig = roomof(BIGDECIMAL_DOUBLE_FIGURES, BASE_FIG);
6022
6766
  ind_m = 0;
6023
6767
  mm = Min(fig, m->Prec);
6024
6768
  *d = 0.0;
@@ -6035,7 +6779,7 @@ Exit:
6035
6779
  if (gfDebug) {
6036
6780
  VPrint(stdout, " VpVtoD: m=%\n", m);
6037
6781
  printf(" d=%e * 10 **%ld\n", *d, *e);
6038
- printf(" DBLE_FIG = %d\n", DBLE_FIG);
6782
+ printf(" BIGDECIMAL_DOUBLE_FIGURES = %d\n", BIGDECIMAL_DOUBLE_FIGURES);
6039
6783
  }
6040
6784
  #endif /*BIGDECIMAL_DEBUG */
6041
6785
  return f;
@@ -6049,7 +6793,7 @@ VpDtoV(Real *m, double d)
6049
6793
  {
6050
6794
  size_t ind_m, mm;
6051
6795
  SIGNED_VALUE ne;
6052
- BDIGIT i;
6796
+ DECDIG i;
6053
6797
  double val, val2;
6054
6798
 
6055
6799
  if (isnan(d)) {
@@ -6084,12 +6828,12 @@ VpDtoV(Real *m, double d)
6084
6828
  /* Now val = 0.xxxxx*BASE**ne */
6085
6829
 
6086
6830
  mm = m->MaxPrec;
6087
- memset(m->frac, 0, mm * sizeof(BDIGIT));
6831
+ memset(m->frac, 0, mm * sizeof(DECDIG));
6088
6832
  for (ind_m = 0; val > 0.0 && ind_m < mm; ind_m++) {
6089
- val *= (double)BASE;
6090
- i = (BDIGIT)val;
6091
- val -= (double)i;
6092
- m->frac[ind_m] = i;
6833
+ val *= (double)BASE;
6834
+ i = (DECDIG)val;
6835
+ val -= (double)i;
6836
+ m->frac[ind_m] = i;
6093
6837
  }
6094
6838
  if (ind_m >= mm) ind_m = mm - 1;
6095
6839
  VpSetSign(m, (d > 0.0) ? 1 : -1);
@@ -6097,7 +6841,7 @@ VpDtoV(Real *m, double d)
6097
6841
  m->exponent = ne;
6098
6842
 
6099
6843
  VpInternalRound(m, 0, (m->Prec > 0) ? m->frac[m->Prec-1] : 0,
6100
- (BDIGIT)(val*(double)BASE));
6844
+ (DECDIG)(val*(double)BASE));
6101
6845
 
6102
6846
  Exit:
6103
6847
  #ifdef BIGDECIMAL_DEBUG
@@ -6236,7 +6980,7 @@ VpSqrt(Real *y, Real *x)
6236
6980
  }
6237
6981
  VpDtoV(y, sqrt(val)); /* y <- sqrt(val) */
6238
6982
  y->exponent += n;
6239
- n = (SIGNED_VALUE)((DBLE_FIG + BASE_FIG - 1) / BASE_FIG);
6983
+ n = (SIGNED_VALUE)roomof(BIGDECIMAL_DOUBLE_FIGURES, BASE_FIG);
6240
6984
  y->MaxPrec = Min((size_t)n , y_prec);
6241
6985
  f->MaxPrec = y->MaxPrec + 1;
6242
6986
  n = (SIGNED_VALUE)(y_prec * BASE_FIG);
@@ -6293,8 +7037,8 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
6293
7037
  /* exptoadd: number of digits needed to compensate negative nf */
6294
7038
  int fracf, fracf_1further;
6295
7039
  ssize_t n,i,ix,ioffset, exptoadd;
6296
- BDIGIT v, shifter;
6297
- BDIGIT div;
7040
+ DECDIG v, shifter;
7041
+ DECDIG div;
6298
7042
 
6299
7043
  nf += y->exponent * (ssize_t)BASE_FIG;
6300
7044
  exptoadd=0;
@@ -6316,8 +7060,8 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
6316
7060
  n = (ssize_t)BASE_FIG - ioffset - 1;
6317
7061
  for (shifter = 1, i = 0; i < n; ++i) shifter *= 10;
6318
7062
 
6319
- /* so the representation used (in y->frac) is an array of BDIGIT, where
6320
- 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
6321
7065
  decimal places.
6322
7066
 
6323
7067
  (that numbers of decimal places are typed as ssize_t is somewhat confusing)
@@ -6325,10 +7069,10 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
6325
7069
  nf is now position (in decimal places) of the digit from the start of
6326
7070
  the array.
6327
7071
 
6328
- 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,
6329
7073
  from the start of the array.
6330
7074
 
6331
- v is the value of this BDIGIT
7075
+ v is the value of this DECDIG
6332
7076
 
6333
7077
  ioffset is the number of extra decimal places along of this decimal digit
6334
7078
  within v.
@@ -6354,7 +7098,7 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
6354
7098
  now fracf_1further is whether any of the remaining digits within v are non-zero
6355
7099
  */
6356
7100
 
6357
- /* 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.
6358
7102
  if we spot any non-zeroness, that means that we found a positive digit under
6359
7103
  rounding position, and we also found a positive digit under one further than
6360
7104
  the rounding position, so both searches (to see if any such non-zero digit exists)
@@ -6373,7 +7117,7 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
6373
7117
  now v = the first digit under the rounding position */
6374
7118
 
6375
7119
  /* drop digits after pointed digit */
6376
- 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));
6377
7121
 
6378
7122
  switch (f) {
6379
7123
  case VP_ROUND_DOWN: /* Truncate */
@@ -6401,11 +7145,11 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
6401
7145
  }
6402
7146
  else {
6403
7147
  if (ioffset == 0) {
6404
- /* v is the first decimal digit of its BDIGIT;
6405
- need to grab the previous BDIGIT if present
6406
- to check for evenness of the previous decimal
6407
- digit (which is same as that of the BDIGIT since
6408
- 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) */
6409
7153
  if (ix && (y->frac[ix-1] % 2)) ++div;
6410
7154
  }
6411
7155
  else {
@@ -6453,7 +7197,7 @@ VpLeftRound(Real *y, unsigned short f, ssize_t nf)
6453
7197
  * Round from the left hand side of the digits.
6454
7198
  */
6455
7199
  {
6456
- BDIGIT v;
7200
+ DECDIG v;
6457
7201
  if (!VpHasVal(y)) return 0; /* Unable to round */
6458
7202
  v = y->frac[0];
6459
7203
  nf -= VpExponent(y) * (ssize_t)BASE_FIG;
@@ -6484,7 +7228,7 @@ VpLimitRound(Real *c, size_t ixDigit)
6484
7228
  /* If I understand correctly, this is only ever used to round off the final decimal
6485
7229
  digit of precision */
6486
7230
  static void
6487
- VpInternalRound(Real *c, size_t ixDigit, BDIGIT vPrev, BDIGIT v)
7231
+ VpInternalRound(Real *c, size_t ixDigit, DECDIG vPrev, DECDIG v)
6488
7232
  {
6489
7233
  int f = 0;
6490
7234
 
@@ -6534,7 +7278,7 @@ VpInternalRound(Real *c, size_t ixDigit, BDIGIT vPrev, BDIGIT v)
6534
7278
  static int
6535
7279
  VpRdup(Real *m, size_t ind_m)
6536
7280
  {
6537
- BDIGIT carry;
7281
+ DECDIG carry;
6538
7282
 
6539
7283
  if (!ind_m) ind_m = m->Prec;
6540
7284
 
@@ -6606,7 +7350,7 @@ Exit:
6606
7350
  * y = x ** n
6607
7351
  */
6608
7352
  VP_EXPORT int
6609
- VpPower(Real *y, Real *x, SIGNED_VALUE n)
7353
+ VpPowerByInt(Real *y, Real *x, SIGNED_VALUE n)
6610
7354
  {
6611
7355
  size_t s, ss;
6612
7356
  ssize_t sign;
@@ -6693,8 +7437,8 @@ VpPower(Real *y, Real *x, SIGNED_VALUE n)
6693
7437
  Exit:
6694
7438
  #ifdef BIGDECIMAL_DEBUG
6695
7439
  if (gfDebug) {
6696
- VPrint(stdout, "VpPower y=%\n", y);
6697
- VPrint(stdout, "VpPower x=%\n", x);
7440
+ VPrint(stdout, "VpPowerByInt y=%\n", y);
7441
+ VPrint(stdout, "VpPowerByInt x=%\n", x);
6698
7442
  printf(" n=%"PRIdVALUE"\n", n);
6699
7443
  }
6700
7444
  #endif /* BIGDECIMAL_DEBUG */
@@ -6729,12 +7473,12 @@ VpVarCheck(Real * v)
6729
7473
  }
6730
7474
  for (i = 0; i < v->Prec; ++i) {
6731
7475
  if (v->frac[i] >= BASE) {
6732
- printf("ERROR(VpVarCheck): Illegal fraction\n");
6733
- printf(" Frac[%"PRIuSIZE"]=%"PRIuBDIGIT"\n", i, v->frac[i]);
6734
- printf(" Prec. =%"PRIuSIZE"\n", v->Prec);
6735
- printf(" Exp. =%"PRIdVALUE"\n", v->exponent);
6736
- printf(" BASE =%"PRIuBDIGIT"\n", BASE);
6737
- 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;
6738
7482
  }
6739
7483
  }
6740
7484
  return 0;