bigdecimal 3.0.0 → 3.1.2

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.
415
346
  *
416
- * | frac[0] frac[1] frac[2] . frac[3] frac[4] ... frac[Prec-1]
417
- * |------------------------> exponent == 3
347
+ * 0 . 0000 0000 | frac[0] ... frac[n-1] |
348
+ * |<----------| exponent == -2 |
349
+ * |---------------------------------->| precision
350
+ * |---------------------------------->| scale
351
+ *
352
+ *
353
+ * Conversely, when the exponent is positive, the decimal point moves to
354
+ * rightward. In this case, the scale equals to
355
+ *
356
+ * BASE_FIG * (n - exponent) - ntz.
357
+ *
358
+ * the precision equals to
359
+ *
360
+ * scale + BASE_FIG * exponent - nlz.
361
+ *
362
+ * | frac[0] frac[1] . frac[2] ... frac[n-1] |
363
+ * |---------------->| exponent == 2 |
364
+ * | |---------------------->| scale
365
+ * |---------------------------------------->| precision
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+.
530
+ *
531
+ * Two instances of \BigDecimal have the same hash value if and only if
532
+ * they have equal:
481
533
  *
482
- * Creates a hash for this BigDecimal.
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:
1488
+ *
1489
+ * b = BigDecimal('1.5') # => 0.15e1
1490
+ * b < 2 # => true
1491
+ * b < 2.0 # => true
1492
+ * b < Rational(2, 1) # => true
1493
+ * b < 1.5 # => false
1291
1494
  *
1292
- * Returns true if a is less than b.
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:
1317
1529
  *
1318
- * Returns true if a is greater than b.
1530
+ * b = BigDecimal('1.5')
1531
+ * b > 1 # => true
1532
+ * b > 1.0 # => true
1533
+ * b > Rational(1, 1) # => true
1534
+ * b > 2 # => false
1535
+ *
1536
+ * Raises an exception if the comparison cannot be made.
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
1547
+ *
1548
+ * Returns +true+ if +self+ is greater than or equal to +other+, +false+ otherwise:
1330
1549
  *
1331
- * Returns true if a is greater than or equal to b.
1550
+ * b = BigDecimal('1.5')
1551
+ * b >= 1 # => true
1552
+ * b >= 1.0 # => true
1553
+ * b >= Rational(1, 1) # => true
1554
+ * b >= 1.5 # => true
1555
+ * b > 2 # => false
1556
+ *
1557
+ * Raises an exception if the comparison cannot be made.
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
1569
+ *
1570
+ * Returns the \BigDecimal negation of self:
1344
1571
  *
1345
- * Return the negation of self.
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,52 +1608,72 @@ 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;
1622
+ ssize_t a_prec, b_prec;
1409
1623
  size_t mx;
1410
1624
 
1411
- GUARD_OBJ(a, GetVpValue(self, 1));
1412
- if (RB_TYPE_P(r, T_FLOAT)) {
1413
- b = GetVpValueWithPrec(r, DBLE_FIG, 1);
1625
+ TypedData_Get_Struct(self, Real, &BigDecimal_data_type, a);
1626
+ SAVE(a);
1627
+
1628
+ VALUE rr = r;
1629
+ if (is_kind_of_BigDecimal(rr)) {
1630
+ /* do nothing */
1631
+ }
1632
+ else if (RB_INTEGER_TYPE_P(r)) {
1633
+ rr = rb_inum_convert_to_BigDecimal(r, 0, true);
1634
+ }
1635
+ else if (RB_TYPE_P(r, T_FLOAT)) {
1636
+ rr = rb_float_convert_to_BigDecimal(r, 0, true);
1414
1637
  }
1415
1638
  else if (RB_TYPE_P(r, T_RATIONAL)) {
1416
- b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
1417
- }
1418
- else {
1419
- b = GetVpValue(r, 0);
1639
+ rr = rb_rational_convert_to_BigDecimal(r, a->Prec*BASE_FIG, true);
1420
1640
  }
1421
1641
 
1422
- if (!b) return DoSomeOne(self, r, '/');
1423
- SAVE(b);
1642
+ if (!is_kind_of_BigDecimal(rr)) {
1643
+ return DoSomeOne(self, r, '/');
1644
+ }
1424
1645
 
1646
+ TypedData_Get_Struct(rr, Real, &BigDecimal_data_type, b);
1647
+ SAVE(b);
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
+
1650
+ BigDecimal_count_precision_and_scale(self, &a_prec, NULL);
1651
+ BigDecimal_count_precision_and_scale(rr, &b_prec, NULL);
1652
+ mx = (a_prec > b_prec) ? a_prec : b_prec;
1653
+ mx *= 2;
1654
+
1655
+ if (2*BIGDECIMAL_DOUBLE_FIGURES > mx)
1656
+ mx = 2*BIGDECIMAL_DOUBLE_FIGURES;
1657
+
1658
+ GUARD_OBJ((*c), VpCreateRbObject(mx + 2*BASE_FIG, "#0", true));
1659
+ GUARD_OBJ((*res), VpCreateRbObject((mx + 1)*2 + 2*BASE_FIG, "#0", true));
1433
1660
  VpDivd(*c, *res, a, b);
1661
+
1434
1662
  return Qnil;
1435
1663
  }
1436
1664
 
1665
+ static VALUE BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod);
1666
+
1437
1667
  /* call-seq:
1438
- * a / b -> bigdecimal
1439
- * quo(value) -> bigdecimal
1668
+ * a / b -> bigdecimal
1440
1669
  *
1441
1670
  * Divide by the specified value.
1442
1671
  *
1672
+ * The result precision will be the precision of the larger operand,
1673
+ * but its minimum is 2*Float::DIG.
1674
+ *
1443
1675
  * See BigDecimal#div.
1676
+ * See BigDecimal#quo.
1444
1677
  */
1445
1678
  static VALUE
1446
1679
  BigDecimal_div(VALUE self, VALUE r)
@@ -1448,7 +1681,7 @@ BigDecimal_div(VALUE self, VALUE r)
1448
1681
  {
1449
1682
  ENTER(5);
1450
1683
  Real *c=NULL, *res=NULL, *div = NULL;
1451
- r = BigDecimal_divide(&c, &res, &div, self, r);
1684
+ r = BigDecimal_divide(self, r, &c, &res, &div);
1452
1685
  if (!NIL_P(r)) return r; /* coerced by other */
1453
1686
  SAVE(c); SAVE(res); SAVE(div);
1454
1687
  /* a/b = c + r/b */
@@ -1457,9 +1690,48 @@ BigDecimal_div(VALUE self, VALUE r)
1457
1690
  */
1458
1691
  /* Round */
1459
1692
  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]));
1693
+ VpInternalRound(c, 0, c->frac[c->Prec-1], (DECDIG)(VpBaseVal() * (DECDIG_DBL)res->frac[0] / div->frac[0]));
1694
+ }
1695
+ return VpCheckGetValue(c);
1696
+ }
1697
+
1698
+ static VALUE BigDecimal_round(int argc, VALUE *argv, VALUE self);
1699
+
1700
+ /* call-seq:
1701
+ * quo(value) -> bigdecimal
1702
+ * quo(value, digits) -> bigdecimal
1703
+ *
1704
+ * Divide by the specified value.
1705
+ *
1706
+ * digits:: If specified and less than the number of significant digits of
1707
+ * the result, the result is rounded to the given number of digits,
1708
+ * according to the rounding mode indicated by BigDecimal.mode.
1709
+ *
1710
+ * If digits is 0 or omitted, the result is the same as for the
1711
+ * / operator.
1712
+ *
1713
+ * See BigDecimal#/.
1714
+ * See BigDecimal#div.
1715
+ */
1716
+ static VALUE
1717
+ BigDecimal_quo(int argc, VALUE *argv, VALUE self)
1718
+ {
1719
+ VALUE value, digits, result;
1720
+ SIGNED_VALUE n = -1;
1721
+
1722
+ argc = rb_scan_args(argc, argv, "11", &value, &digits);
1723
+ if (argc > 1) {
1724
+ n = GetPrecisionInt(digits);
1725
+ }
1726
+
1727
+ if (n > 0) {
1728
+ result = BigDecimal_div2(self, value, digits);
1729
+ }
1730
+ else {
1731
+ result = BigDecimal_div(self, value);
1461
1732
  }
1462
- return ToValue(c);
1733
+
1734
+ return result;
1463
1735
  }
1464
1736
 
1465
1737
  /*
@@ -1472,77 +1744,106 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
1472
1744
  ENTER(8);
1473
1745
  Real *c=NULL, *d=NULL, *res=NULL;
1474
1746
  Real *a, *b;
1747
+ ssize_t a_prec, b_prec;
1475
1748
  size_t mx;
1476
1749
 
1477
- GUARD_OBJ(a, GetVpValue(self, 1));
1478
- if (RB_TYPE_P(r, T_FLOAT)) {
1479
- b = GetVpValueWithPrec(r, DBLE_FIG, 1);
1750
+ TypedData_Get_Struct(self, Real, &BigDecimal_data_type, a);
1751
+ SAVE(a);
1752
+
1753
+ VALUE rr = r;
1754
+ if (is_kind_of_BigDecimal(rr)) {
1755
+ /* do nothing */
1756
+ }
1757
+ else if (RB_INTEGER_TYPE_P(r)) {
1758
+ rr = rb_inum_convert_to_BigDecimal(r, 0, true);
1759
+ }
1760
+ else if (RB_TYPE_P(r, T_FLOAT)) {
1761
+ rr = rb_float_convert_to_BigDecimal(r, 0, true);
1480
1762
  }
1481
1763
  else if (RB_TYPE_P(r, T_RATIONAL)) {
1482
- b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
1764
+ rr = rb_rational_convert_to_BigDecimal(r, a->Prec*BASE_FIG, true);
1483
1765
  }
1484
- else {
1485
- b = GetVpValue(r, 0);
1766
+
1767
+ if (!is_kind_of_BigDecimal(rr)) {
1768
+ return Qfalse;
1486
1769
  }
1487
1770
 
1488
- if (!b) return Qfalse;
1771
+ TypedData_Get_Struct(rr, Real, &BigDecimal_data_type, b);
1489
1772
  SAVE(b);
1490
1773
 
1491
1774
  if (VpIsNaN(a) || VpIsNaN(b)) goto NaN;
1492
1775
  if (VpIsInf(a) && VpIsInf(b)) goto NaN;
1493
1776
  if (VpIsZero(b)) {
1494
- rb_raise(rb_eZeroDivError, "divided by 0");
1777
+ rb_raise(rb_eZeroDivError, "divided by 0");
1495
1778
  }
1496
1779
  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;
1780
+ if (VpGetSign(a) == VpGetSign(b)) {
1781
+ VALUE inf = BigDecimal_positive_infinity();
1782
+ TypedData_Get_Struct(inf, Real, &BigDecimal_data_type, *div);
1783
+ }
1784
+ else {
1785
+ VALUE inf = BigDecimal_negative_infinity();
1786
+ TypedData_Get_Struct(inf, Real, &BigDecimal_data_type, *div);
1787
+ }
1788
+ VALUE nan = BigDecimal_nan();
1789
+ TypedData_Get_Struct(nan, Real, &BigDecimal_data_type, *mod);
1790
+ return Qtrue;
1503
1791
  }
1504
1792
  if (VpIsInf(b)) {
1505
- GUARD_OBJ(d, VpCreateRbObject(1, "0"));
1506
- *div = d;
1507
- *mod = a;
1508
- return Qtrue;
1793
+ VALUE zero = BigDecimal_positive_zero();
1794
+ TypedData_Get_Struct(zero, Real, &BigDecimal_data_type, *div);
1795
+ *mod = a;
1796
+ return Qtrue;
1509
1797
  }
1510
1798
  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"));
1799
+ VALUE zero = BigDecimal_positive_zero();
1800
+ TypedData_Get_Struct(zero, Real, &BigDecimal_data_type, *div);
1801
+ TypedData_Get_Struct(zero, Real, &BigDecimal_data_type, *mod);
1802
+ return Qtrue;
1803
+ }
1804
+
1805
+ BigDecimal_count_precision_and_scale(self, &a_prec, NULL);
1806
+ BigDecimal_count_precision_and_scale(rr, &b_prec, NULL);
1807
+
1808
+ mx = (a_prec > b_prec) ? a_prec : b_prec;
1809
+ mx *= 2;
1810
+
1811
+ if (2*BIGDECIMAL_DOUBLE_FIGURES > mx)
1812
+ mx = 2*BIGDECIMAL_DOUBLE_FIGURES;
1813
+
1814
+ GUARD_OBJ(c, VpCreateRbObject(mx + 2*BASE_FIG, "0", true));
1815
+ GUARD_OBJ(res, VpCreateRbObject(mx*2 + 2*BASE_FIG, "#0", true));
1523
1816
  VpDivd(c, res, a, b);
1524
- mx = c->Prec * (VpBaseFig() + 1);
1525
- GUARD_OBJ(d, VpCreateRbObject(mx, "0"));
1817
+
1818
+ mx = c->Prec * BASE_FIG;
1819
+ GUARD_OBJ(d, VpCreateRbObject(mx, "0", true));
1526
1820
  VpActiveRound(d, c, VP_ROUND_DOWN, 0);
1821
+
1527
1822
  VpMult(res, d, b);
1528
1823
  VpAddSub(c, a, res, -1);
1824
+
1529
1825
  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;
1826
+ /* result adjustment for negative case */
1827
+ res = VpReallocReal(res, d->MaxPrec);
1828
+ res->MaxPrec = d->MaxPrec;
1829
+ VpAddSub(res, d, VpOne(), -1);
1830
+ GUARD_OBJ(d, VpCreateRbObject(GetAddSubPrec(c, b) * 2*BASE_FIG, "0", true));
1831
+ VpAddSub(d, c, b, 1);
1832
+ *div = res;
1833
+ *mod = d;
1834
+ }
1835
+ else {
1836
+ *div = d;
1837
+ *mod = c;
1538
1838
  }
1539
1839
  return Qtrue;
1540
1840
 
1541
- NaN:
1542
- GUARD_OBJ(c, VpCreateRbObject(1, "NaN"));
1543
- GUARD_OBJ(d, VpCreateRbObject(1, "NaN"));
1544
- *div = d;
1545
- *mod = c;
1841
+ NaN:
1842
+ {
1843
+ VALUE nan = BigDecimal_nan();
1844
+ TypedData_Get_Struct(nan, Real, &BigDecimal_data_type, *div);
1845
+ TypedData_Get_Struct(nan, Real, &BigDecimal_data_type, *mod);
1846
+ }
1546
1847
  return Qtrue;
1547
1848
  }
1548
1849
 
@@ -1562,7 +1863,7 @@ BigDecimal_mod(VALUE self, VALUE r) /* %: a%b = a - (a.to_f/b).floor * b */
1562
1863
 
1563
1864
  if (BigDecimal_DoDivmod(self, r, &div, &mod)) {
1564
1865
  SAVE(div); SAVE(mod);
1565
- return ToValue(mod);
1866
+ return VpCheckGetValue(mod);
1566
1867
  }
1567
1868
  return DoSomeOne(self, r, '%');
1568
1869
  }
@@ -1577,7 +1878,7 @@ BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv)
1577
1878
 
1578
1879
  GUARD_OBJ(a, GetVpValue(self, 1));
1579
1880
  if (RB_TYPE_P(r, T_FLOAT)) {
1580
- b = GetVpValueWithPrec(r, DBLE_FIG, 1);
1881
+ b = GetVpValueWithPrec(r, 0, 1);
1581
1882
  }
1582
1883
  else if (RB_TYPE_P(r, T_RATIONAL)) {
1583
1884
  b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
@@ -1590,17 +1891,17 @@ BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv)
1590
1891
  SAVE(b);
1591
1892
 
1592
1893
  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"));
1894
+ GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
1895
+ GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0", true));
1896
+ GUARD_OBJ(rr, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0", true));
1897
+ GUARD_OBJ(ff, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0", true));
1597
1898
 
1598
1899
  VpDivd(c, res, a, b);
1599
1900
 
1600
1901
  mx = c->Prec *(VpBaseFig() + 1);
1601
1902
 
1602
- GUARD_OBJ(d, VpCreateRbObject(mx, "0"));
1603
- GUARD_OBJ(f, VpCreateRbObject(mx, "0"));
1903
+ GUARD_OBJ(d, VpCreateRbObject(mx, "0", true));
1904
+ GUARD_OBJ(f, VpCreateRbObject(mx, "0", true));
1604
1905
 
1605
1906
  VpActiveRound(d, c, VP_ROUND_DOWN, 0); /* 0: round off */
1606
1907
 
@@ -1627,7 +1928,7 @@ BigDecimal_remainder(VALUE self, VALUE r) /* remainder */
1627
1928
  Real *d, *rv = 0;
1628
1929
  f = BigDecimal_divremain(self, r, &d, &rv);
1629
1930
  if (!NIL_P(f)) return f;
1630
- return ToValue(rv);
1931
+ return VpCheckGetValue(rv);
1631
1932
  }
1632
1933
 
1633
1934
  /* call-seq:
@@ -1660,13 +1961,14 @@ BigDecimal_divmod(VALUE self, VALUE r)
1660
1961
 
1661
1962
  if (BigDecimal_DoDivmod(self, r, &div, &mod)) {
1662
1963
  SAVE(div); SAVE(mod);
1663
- return rb_assoc_new(ToValue(div), ToValue(mod));
1964
+ return rb_assoc_new(VpCheckGetValue(div), VpCheckGetValue(mod));
1664
1965
  }
1665
1966
  return DoSomeOne(self,r,rb_intern("divmod"));
1666
1967
  }
1667
1968
 
1668
1969
  /*
1669
- * See BigDecimal#quo
1970
+ * Do the same manner as Float#div when n is nil.
1971
+ * Do the same manner as BigDecimal#quo when n is 0.
1670
1972
  */
1671
1973
  static inline VALUE
1672
1974
  BigDecimal_div2(VALUE self, VALUE b, VALUE n)
@@ -1678,7 +1980,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
1678
1980
  Real *div = NULL;
1679
1981
  Real *mod;
1680
1982
  if (BigDecimal_DoDivmod(self, b, &div, &mod)) {
1681
- return BigDecimal_to_i(ToValue(div));
1983
+ return BigDecimal_to_i(VpCheckGetValue(div));
1682
1984
  }
1683
1985
  return DoSomeOne(self, b, rb_intern("div"));
1684
1986
  }
@@ -1692,18 +1994,25 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
1692
1994
  Real *res = NULL;
1693
1995
  Real *av = NULL, *bv = NULL, *cv = NULL;
1694
1996
  size_t mx = ix + VpBaseFig()*2;
1997
+ size_t b_prec = ix;
1695
1998
  size_t pl = VpSetPrecLimit(0);
1696
1999
 
1697
- GUARD_OBJ(cv, VpCreateRbObject(mx + VpBaseFig(), "0"));
2000
+ GUARD_OBJ(cv, VpCreateRbObject(mx + VpBaseFig(), "0", true));
1698
2001
  GUARD_OBJ(av, GetVpValue(self, 1));
1699
- GUARD_OBJ(bv, GetVpValue(b, 1));
2002
+ /* TODO: I want to refactor this precision control for a float value later
2003
+ * by introducing an implicit conversion function instead of
2004
+ * GetVpValueWithPrec. */
2005
+ if (RB_FLOAT_TYPE_P(b) && b_prec > BIGDECIMAL_DOUBLE_FIGURES) {
2006
+ b_prec = BIGDECIMAL_DOUBLE_FIGURES;
2007
+ }
2008
+ GUARD_OBJ(bv, GetVpValueWithPrec(b, b_prec, 1));
1700
2009
  mx = av->Prec + bv->Prec + 2;
1701
2010
  if (mx <= cv->MaxPrec) mx = cv->MaxPrec + 1;
1702
- GUARD_OBJ(res, VpCreateRbObject((mx * 2 + 2)*VpBaseFig(), "#0"));
2011
+ GUARD_OBJ(res, VpCreateRbObject((mx * 2 + 2)*VpBaseFig(), "#0", true));
1703
2012
  VpDivd(cv, res, av, bv);
1704
2013
  VpSetPrecLimit(pl);
1705
2014
  VpLeftRound(cv, VpGetRoundMode(), ix);
1706
- return ToValue(cv);
2015
+ return VpCheckGetValue(cv);
1707
2016
  }
1708
2017
  }
1709
2018
 
@@ -1711,6 +2020,7 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
1711
2020
  * Document-method: BigDecimal#div
1712
2021
  *
1713
2022
  * call-seq:
2023
+ * div(value) -> integer
1714
2024
  * div(value, digits) -> bigdecimal or integer
1715
2025
  *
1716
2026
  * Divide by the specified value.
@@ -1725,6 +2035,9 @@ BigDecimal_div2(VALUE self, VALUE b, VALUE n)
1725
2035
  * If digits is not specified, the result is an integer,
1726
2036
  * by analogy with Float#div; see also BigDecimal#divmod.
1727
2037
  *
2038
+ * See BigDecimal#/.
2039
+ * See BigDecimal#quo.
2040
+ *
1728
2041
  * Examples:
1729
2042
  *
1730
2043
  * a = BigDecimal("4")
@@ -1748,6 +2061,31 @@ BigDecimal_div3(int argc, VALUE *argv, VALUE self)
1748
2061
  return BigDecimal_div2(self, b, n);
1749
2062
  }
1750
2063
 
2064
+ /*
2065
+ * call-seq:
2066
+ * add(value, ndigits) -> new_bigdecimal
2067
+ *
2068
+ * Returns the \BigDecimal sum of +self+ and +value+
2069
+ * with a precision of +ndigits+ decimal digits.
2070
+ *
2071
+ * When +ndigits+ is less than the number of significant digits
2072
+ * in the sum, the sum is rounded to that number of digits,
2073
+ * according to the current rounding mode; see BigDecimal.mode.
2074
+ *
2075
+ * Examples:
2076
+ *
2077
+ * # Set the rounding mode.
2078
+ * BigDecimal.mode(BigDecimal::ROUND_MODE, :half_up)
2079
+ * b = BigDecimal('111111.111')
2080
+ * b.add(1, 0) # => 0.111112111e6
2081
+ * b.add(1, 3) # => 0.111e6
2082
+ * b.add(1, 6) # => 0.111112e6
2083
+ * b.add(1, 15) # => 0.111112111e6
2084
+ * b.add(1.0, 15) # => 0.111112111e6
2085
+ * b.add(Rational(1, 1), 15) # => 0.111112111e6
2086
+ *
2087
+ */
2088
+
1751
2089
  static VALUE
1752
2090
  BigDecimal_add2(VALUE self, VALUE b, VALUE n)
1753
2091
  {
@@ -1761,7 +2099,7 @@ BigDecimal_add2(VALUE self, VALUE b, VALUE n)
1761
2099
  VpSetPrecLimit(pl);
1762
2100
  GUARD_OBJ(cv, GetVpValue(c, 1));
1763
2101
  VpLeftRound(cv, VpGetRoundMode(), mx);
1764
- return ToValue(cv);
2102
+ return VpCheckGetValue(cv);
1765
2103
  }
1766
2104
  }
1767
2105
 
@@ -1791,10 +2129,35 @@ BigDecimal_sub2(VALUE self, VALUE b, VALUE n)
1791
2129
  VpSetPrecLimit(pl);
1792
2130
  GUARD_OBJ(cv, GetVpValue(c, 1));
1793
2131
  VpLeftRound(cv, VpGetRoundMode(), mx);
1794
- return ToValue(cv);
2132
+ return VpCheckGetValue(cv);
1795
2133
  }
1796
2134
  }
1797
2135
 
2136
+ /*
2137
+ * call-seq:
2138
+ * mult(other, ndigits) -> bigdecimal
2139
+ *
2140
+ * Returns the \BigDecimal product of +self+ and +value+
2141
+ * with a precision of +ndigits+ decimal digits.
2142
+ *
2143
+ * When +ndigits+ is less than the number of significant digits
2144
+ * in the sum, the sum is rounded to that number of digits,
2145
+ * according to the current rounding mode; see BigDecimal.mode.
2146
+ *
2147
+ * Examples:
2148
+ *
2149
+ * # Set the rounding mode.
2150
+ * BigDecimal.mode(BigDecimal::ROUND_MODE, :half_up)
2151
+ * b = BigDecimal('555555.555')
2152
+ * b.mult(3, 0) # => 0.1666666665e7
2153
+ * b.mult(3, 3) # => 0.167e7
2154
+ * b.mult(3, 6) # => 0.166667e7
2155
+ * b.mult(3, 15) # => 0.1666666665e7
2156
+ * b.mult(3.0, 0) # => 0.1666666665e7
2157
+ * b.mult(Rational(3, 1), 0) # => 0.1666666665e7
2158
+ * b.mult(Complex(3, 0), 0) # => (0.1666666665e7+0.0i)
2159
+ *
2160
+ */
1798
2161
 
1799
2162
  static VALUE
1800
2163
  BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
@@ -1809,18 +2172,19 @@ BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
1809
2172
  VpSetPrecLimit(pl);
1810
2173
  GUARD_OBJ(cv, GetVpValue(c, 1));
1811
2174
  VpLeftRound(cv, VpGetRoundMode(), mx);
1812
- return ToValue(cv);
2175
+ return VpCheckGetValue(cv);
1813
2176
  }
1814
2177
  }
1815
2178
 
1816
2179
  /*
1817
2180
  * call-seq:
1818
- * big_decimal.abs -> big_decimal
2181
+ * abs -> bigdecimal
2182
+ *
2183
+ * Returns the \BigDecimal absolute value of +self+:
1819
2184
  *
1820
- * Returns the absolute value, as a BigDecimal.
2185
+ * BigDecimal('5').abs # => 0.5e1
2186
+ * BigDecimal('-3').abs # => 0.3e1
1821
2187
  *
1822
- * BigDecimal('5').abs #=> 0.5e1
1823
- * BigDecimal('-3').abs #=> 0.3e1
1824
2188
  */
1825
2189
 
1826
2190
  static VALUE
@@ -1832,10 +2196,10 @@ BigDecimal_abs(VALUE self)
1832
2196
 
1833
2197
  GUARD_OBJ(a, GetVpValue(self, 1));
1834
2198
  mx = a->Prec *(VpBaseFig() + 1);
1835
- GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
2199
+ GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
1836
2200
  VpAsgn(c, a, 1);
1837
2201
  VpChangeSign(c, 1);
1838
- return ToValue(c);
2202
+ return VpCheckGetValue(c);
1839
2203
  }
1840
2204
 
1841
2205
  /* call-seq:
@@ -1857,9 +2221,9 @@ BigDecimal_sqrt(VALUE self, VALUE nFig)
1857
2221
 
1858
2222
  n = GetPrecisionInt(nFig) + VpDblFig() + BASE_FIG;
1859
2223
  if (mx <= n) mx = n;
1860
- GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
2224
+ GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
1861
2225
  VpSqrt(c, a);
1862
- return ToValue(c);
2226
+ return VpCheckGetValue(c);
1863
2227
  }
1864
2228
 
1865
2229
  /* Return the integer part of the number, as a BigDecimal.
@@ -1873,9 +2237,9 @@ BigDecimal_fix(VALUE self)
1873
2237
 
1874
2238
  GUARD_OBJ(a, GetVpValue(self, 1));
1875
2239
  mx = a->Prec *(VpBaseFig() + 1);
1876
- GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
2240
+ GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
1877
2241
  VpActiveRound(c, a, VP_ROUND_DOWN, 0); /* 0: round off */
1878
- return ToValue(c);
2242
+ return VpCheckGetValue(c);
1879
2243
  }
1880
2244
 
1881
2245
  /* call-seq:
@@ -1946,13 +2310,13 @@ BigDecimal_round(int argc, VALUE *argv, VALUE self)
1946
2310
  pl = VpSetPrecLimit(0);
1947
2311
  GUARD_OBJ(a, GetVpValue(self, 1));
1948
2312
  mx = a->Prec * (VpBaseFig() + 1);
1949
- GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
2313
+ GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
1950
2314
  VpSetPrecLimit(pl);
1951
2315
  VpActiveRound(c, a, sw, iLoc);
1952
2316
  if (round_to_int) {
1953
- return BigDecimal_to_i(ToValue(c));
2317
+ return BigDecimal_to_i(VpCheckGetValue(c));
1954
2318
  }
1955
- return ToValue(c);
2319
+ return VpCheckGetValue(c);
1956
2320
  }
1957
2321
 
1958
2322
  /* call-seq:
@@ -1992,13 +2356,13 @@ BigDecimal_truncate(int argc, VALUE *argv, VALUE self)
1992
2356
 
1993
2357
  GUARD_OBJ(a, GetVpValue(self, 1));
1994
2358
  mx = a->Prec * (VpBaseFig() + 1);
1995
- GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
2359
+ GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
1996
2360
  VpSetPrecLimit(pl);
1997
2361
  VpActiveRound(c, a, VP_ROUND_DOWN, iLoc); /* 0: truncate */
1998
2362
  if (argc == 0) {
1999
- return BigDecimal_to_i(ToValue(c));
2363
+ return BigDecimal_to_i(VpCheckGetValue(c));
2000
2364
  }
2001
- return ToValue(c);
2365
+ return VpCheckGetValue(c);
2002
2366
  }
2003
2367
 
2004
2368
  /* Return the fractional part of the number, as a BigDecimal.
@@ -2012,9 +2376,9 @@ BigDecimal_frac(VALUE self)
2012
2376
 
2013
2377
  GUARD_OBJ(a, GetVpValue(self, 1));
2014
2378
  mx = a->Prec * (VpBaseFig() + 1);
2015
- GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
2379
+ GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
2016
2380
  VpFrac(c, a);
2017
- return ToValue(c);
2381
+ return VpCheckGetValue(c);
2018
2382
  }
2019
2383
 
2020
2384
  /* call-seq:
@@ -2052,16 +2416,16 @@ BigDecimal_floor(int argc, VALUE *argv, VALUE self)
2052
2416
 
2053
2417
  GUARD_OBJ(a, GetVpValue(self, 1));
2054
2418
  mx = a->Prec * (VpBaseFig() + 1);
2055
- GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
2419
+ GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
2056
2420
  VpSetPrecLimit(pl);
2057
2421
  VpActiveRound(c, a, VP_ROUND_FLOOR, iLoc);
2058
2422
  #ifdef BIGDECIMAL_DEBUG
2059
2423
  VPrint(stderr, "floor: c=%\n", c);
2060
2424
  #endif
2061
2425
  if (argc == 0) {
2062
- return BigDecimal_to_i(ToValue(c));
2426
+ return BigDecimal_to_i(VpCheckGetValue(c));
2063
2427
  }
2064
- return ToValue(c);
2428
+ return VpCheckGetValue(c);
2065
2429
  }
2066
2430
 
2067
2431
  /* call-seq:
@@ -2098,13 +2462,13 @@ BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
2098
2462
 
2099
2463
  GUARD_OBJ(a, GetVpValue(self, 1));
2100
2464
  mx = a->Prec * (VpBaseFig() + 1);
2101
- GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
2465
+ GUARD_OBJ(c, VpCreateRbObject(mx, "0", true));
2102
2466
  VpSetPrecLimit(pl);
2103
2467
  VpActiveRound(c, a, VP_ROUND_CEIL, iLoc);
2104
2468
  if (argc == 0) {
2105
- return BigDecimal_to_i(ToValue(c));
2469
+ return BigDecimal_to_i(VpCheckGetValue(c));
2106
2470
  }
2107
- return ToValue(c);
2471
+ return VpCheckGetValue(c);
2108
2472
  }
2109
2473
 
2110
2474
  /* call-seq:
@@ -2400,13 +2764,13 @@ is_even(VALUE x)
2400
2764
  }
2401
2765
 
2402
2766
  static VALUE
2403
- rmpd_power_by_big_decimal(Real const* x, Real const* exp, ssize_t const n)
2767
+ bigdecimal_power_by_bigdecimal(Real const* x, Real const* exp, ssize_t const n)
2404
2768
  {
2405
2769
  VALUE log_x, multiplied, y;
2406
2770
  volatile VALUE obj = exp->obj;
2407
2771
 
2408
2772
  if (VpIsZero(exp)) {
2409
- return ToValue(VpCreateRbObject(n, "1"));
2773
+ return VpCheckGetValue(VpCreateRbObject(n, "1", true));
2410
2774
  }
2411
2775
 
2412
2776
  log_x = BigMath_log(x->obj, SSIZET2NUM(n+1));
@@ -2444,10 +2808,10 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2444
2808
  n = NIL_P(prec) ? (ssize_t)(x->Prec*VpBaseFig()) : NUM2SSIZET(prec);
2445
2809
 
2446
2810
  if (VpIsNaN(x)) {
2447
- y = VpCreateRbObject(n, "0");
2811
+ y = VpCreateRbObject(n, "0", true);
2448
2812
  RB_GC_GUARD(y->obj);
2449
2813
  VpSetNaN(y);
2450
- return ToValue(y);
2814
+ return VpCheckGetValue(y);
2451
2815
  }
2452
2816
 
2453
2817
  retry:
@@ -2470,9 +2834,9 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2470
2834
  goto retry;
2471
2835
  }
2472
2836
  if (NIL_P(prec)) {
2473
- n += DBLE_FIG;
2837
+ n += BIGDECIMAL_DOUBLE_FIGURES;
2474
2838
  }
2475
- exp = GetVpValueWithPrec(vexp, DBLE_FIG, 1);
2839
+ exp = GetVpValueWithPrec(vexp, 0, 1);
2476
2840
  break;
2477
2841
 
2478
2842
  case T_RATIONAL:
@@ -2516,7 +2880,7 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2516
2880
 
2517
2881
  if (VpIsZero(x)) {
2518
2882
  if (is_negative(vexp)) {
2519
- y = VpCreateRbObject(n, "#0");
2883
+ y = VpCreateRbObject(n, "#0", true);
2520
2884
  RB_GC_GUARD(y->obj);
2521
2885
  if (BIGDECIMAL_NEGATIVE_P(x)) {
2522
2886
  if (is_integer(vexp)) {
@@ -2538,18 +2902,18 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2538
2902
  /* (+0) ** (-num) -> Infinity */
2539
2903
  VpSetPosInf(y);
2540
2904
  }
2541
- return ToValue(y);
2905
+ return VpCheckGetValue(y);
2542
2906
  }
2543
2907
  else if (is_zero(vexp)) {
2544
- return ToValue(VpCreateRbObject(n, "1"));
2908
+ return VpCheckGetValue(VpCreateRbObject(n, "1", true));
2545
2909
  }
2546
2910
  else {
2547
- return ToValue(VpCreateRbObject(n, "0"));
2911
+ return VpCheckGetValue(VpCreateRbObject(n, "0", true));
2548
2912
  }
2549
2913
  }
2550
2914
 
2551
2915
  if (is_zero(vexp)) {
2552
- return ToValue(VpCreateRbObject(n, "1"));
2916
+ return VpCheckGetValue(VpCreateRbObject(n, "1", true));
2553
2917
  }
2554
2918
  else if (is_one(vexp)) {
2555
2919
  return self;
@@ -2561,24 +2925,24 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2561
2925
  if (is_integer(vexp)) {
2562
2926
  if (is_even(vexp)) {
2563
2927
  /* (-Infinity) ** (-even_integer) -> +0 */
2564
- return ToValue(VpCreateRbObject(n, "0"));
2928
+ return VpCheckGetValue(VpCreateRbObject(n, "0", true));
2565
2929
  }
2566
2930
  else {
2567
2931
  /* (-Infinity) ** (-odd_integer) -> -0 */
2568
- return ToValue(VpCreateRbObject(n, "-0"));
2932
+ return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
2569
2933
  }
2570
2934
  }
2571
2935
  else {
2572
2936
  /* (-Infinity) ** (-non_integer) -> -0 */
2573
- return ToValue(VpCreateRbObject(n, "-0"));
2937
+ return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
2574
2938
  }
2575
2939
  }
2576
2940
  else {
2577
- return ToValue(VpCreateRbObject(n, "0"));
2941
+ return VpCheckGetValue(VpCreateRbObject(n, "0", true));
2578
2942
  }
2579
2943
  }
2580
2944
  else {
2581
- y = VpCreateRbObject(n, "0");
2945
+ y = VpCreateRbObject(n, "0", true);
2582
2946
  if (BIGDECIMAL_NEGATIVE_P(x)) {
2583
2947
  if (is_integer(vexp)) {
2584
2948
  if (is_even(vexp)) {
@@ -2597,52 +2961,52 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2597
2961
  else {
2598
2962
  VpSetPosInf(y);
2599
2963
  }
2600
- return ToValue(y);
2964
+ return VpCheckGetValue(y);
2601
2965
  }
2602
2966
  }
2603
2967
 
2604
2968
  if (exp != NULL) {
2605
- return rmpd_power_by_big_decimal(x, exp, n);
2969
+ return bigdecimal_power_by_bigdecimal(x, exp, n);
2606
2970
  }
2607
2971
  else if (RB_TYPE_P(vexp, T_BIGNUM)) {
2608
2972
  VALUE abs_value = BigDecimal_abs(self);
2609
2973
  if (is_one(abs_value)) {
2610
- return ToValue(VpCreateRbObject(n, "1"));
2974
+ return VpCheckGetValue(VpCreateRbObject(n, "1", true));
2611
2975
  }
2612
2976
  else if (RTEST(rb_funcall(abs_value, '<', 1, INT2FIX(1)))) {
2613
2977
  if (is_negative(vexp)) {
2614
- y = VpCreateRbObject(n, "0");
2978
+ y = VpCreateRbObject(n, "0", true);
2615
2979
  if (is_even(vexp)) {
2616
2980
  VpSetInf(y, VpGetSign(x));
2617
2981
  }
2618
2982
  else {
2619
2983
  VpSetInf(y, -VpGetSign(x));
2620
2984
  }
2621
- return ToValue(y);
2985
+ return VpCheckGetValue(y);
2622
2986
  }
2623
2987
  else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
2624
- return ToValue(VpCreateRbObject(n, "-0"));
2988
+ return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
2625
2989
  }
2626
2990
  else {
2627
- return ToValue(VpCreateRbObject(n, "0"));
2991
+ return VpCheckGetValue(VpCreateRbObject(n, "0", true));
2628
2992
  }
2629
2993
  }
2630
2994
  else {
2631
2995
  if (is_positive(vexp)) {
2632
- y = VpCreateRbObject(n, "0");
2996
+ y = VpCreateRbObject(n, "0", true);
2633
2997
  if (is_even(vexp)) {
2634
2998
  VpSetInf(y, VpGetSign(x));
2635
2999
  }
2636
3000
  else {
2637
3001
  VpSetInf(y, -VpGetSign(x));
2638
3002
  }
2639
- return ToValue(y);
3003
+ return VpCheckGetValue(y);
2640
3004
  }
2641
3005
  else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
2642
- return ToValue(VpCreateRbObject(n, "-0"));
3006
+ return VpCheckGetValue(VpCreateRbObject(n, "-0", true));
2643
3007
  }
2644
3008
  else {
2645
- return ToValue(VpCreateRbObject(n, "0"));
3009
+ return VpCheckGetValue(VpCreateRbObject(n, "0", true));
2646
3010
  }
2647
3011
  }
2648
3012
  }
@@ -2654,24 +3018,30 @@ BigDecimal_power(int argc, VALUE*argv, VALUE self)
2654
3018
 
2655
3019
  if (VpIsDef(x)) {
2656
3020
  mp = x->Prec * (VpBaseFig() + 1);
2657
- GUARD_OBJ(y, VpCreateRbObject(mp * (ma + 1), "0"));
3021
+ GUARD_OBJ(y, VpCreateRbObject(mp * (ma + 1), "0", true));
2658
3022
  }
2659
3023
  else {
2660
- GUARD_OBJ(y, VpCreateRbObject(1, "0"));
3024
+ GUARD_OBJ(y, VpCreateRbObject(1, "0", true));
2661
3025
  }
2662
- VpPower(y, x, int_exp);
3026
+ VpPowerByInt(y, x, int_exp);
2663
3027
  if (!NIL_P(prec) && VpIsDef(y)) {
2664
3028
  VpMidRound(y, VpGetRoundMode(), n);
2665
3029
  }
2666
- return ToValue(y);
3030
+ return VpCheckGetValue(y);
2667
3031
  }
2668
3032
 
2669
- /* call-seq:
2670
- * a ** n -> bigdecimal
3033
+ /* call-seq:
3034
+ * self ** other -> bigdecimal
2671
3035
  *
2672
- * Returns the value raised to the power of n.
3036
+ * Returns the \BigDecimal value of +self+ raised to power +other+:
3037
+ *
3038
+ * b = BigDecimal('3.14')
3039
+ * b ** 2 # => 0.98596e1
3040
+ * b ** 2.0 # => 0.98596e1
3041
+ * b ** Rational(2, 1) # => 0.98596e1
3042
+ *
3043
+ * Related: BigDecimal#power.
2673
3044
  *
2674
- * See BigDecimal#power.
2675
3045
  */
2676
3046
  static VALUE
2677
3047
  BigDecimal_power_op(VALUE self, VALUE exp)
@@ -2725,182 +3095,483 @@ opts_exception_p(VALUE opts)
2725
3095
  }
2726
3096
  #endif
2727
3097
 
2728
- static Real *
2729
- VpNewVarArg(int argc, VALUE *argv)
3098
+ static VALUE
3099
+ check_exception(VALUE bd)
2730
3100
  {
2731
- size_t mf;
2732
- VALUE opts = Qnil;
2733
- VALUE nFig;
2734
- VALUE iniValue;
2735
- double d;
2736
- int exc;
3101
+ assert(is_kind_of_BigDecimal(bd));
3102
+
3103
+ Real *vp;
3104
+ TypedData_Get_Struct(bd, Real, &BigDecimal_data_type, vp);
3105
+ VpCheckGetValue(vp); /* VpCheckGetValue performs exception check */
3106
+
3107
+ return bd;
3108
+ }
2737
3109
 
2738
- argc = rb_scan_args(argc, argv, "11:", &iniValue, &nFig, &opts);
2739
- exc = opts_exception_p(opts);
3110
+ static VALUE
3111
+ rb_uint64_convert_to_BigDecimal(uint64_t uval, RB_UNUSED_VAR(size_t digs), int raise_exception)
3112
+ {
3113
+ VALUE obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0);
2740
3114
 
2741
- if (argc == 1) {
2742
- mf = 0;
3115
+ Real *vp;
3116
+ if (uval == 0) {
3117
+ vp = VpAllocReal(1);
3118
+ vp->MaxPrec = 1;
3119
+ vp->Prec = 1;
3120
+ vp->exponent = 1;
3121
+ VpSetZero(vp, 1);
3122
+ vp->frac[0] = 0;
3123
+ }
3124
+ else if (uval < BASE) {
3125
+ vp = VpAllocReal(1);
3126
+ vp->MaxPrec = 1;
3127
+ vp->Prec = 1;
3128
+ vp->exponent = 1;
3129
+ VpSetSign(vp, 1);
3130
+ vp->frac[0] = (DECDIG)uval;
2743
3131
  }
2744
3132
  else {
2745
- /* expand GetPrecisionInt for exception suppression */
2746
- ssize_t n = NUM2INT(nFig);
2747
- if (n < 0) {
2748
- if (!exc) {
2749
- return NULL;
3133
+ DECDIG buf[BIGDECIMAL_INT64_MAX_LENGTH] = {0,};
3134
+ DECDIG r = uval % BASE;
3135
+ size_t len = 0, ntz = 0;
3136
+ if (r == 0) {
3137
+ // Count and skip trailing zeros
3138
+ for (; r == 0 && uval > 0; ++ntz) {
3139
+ uval /= BASE;
3140
+ r = uval % BASE;
2750
3141
  }
2751
- rb_raise(rb_eArgError, "negative precision");
2752
3142
  }
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;
3143
+ for (; uval > 0; ++len) {
3144
+ // Store digits
3145
+ buf[BIGDECIMAL_INT64_MAX_LENGTH - len - 1] = r;
3146
+ uval /= BASE;
3147
+ r = uval % BASE;
2769
3148
  }
3149
+
3150
+ const size_t exp = len + ntz;
3151
+ vp = VpAllocReal(len);
3152
+ vp->MaxPrec = len;
3153
+ vp->Prec = len;
3154
+ vp->exponent = exp;
3155
+ VpSetSign(vp, 1);
3156
+ MEMCPY(vp->frac, buf + BIGDECIMAL_INT64_MAX_LENGTH - len, DECDIG, len);
2770
3157
  }
2771
3158
 
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;
3159
+ return BigDecimal_wrap_struct(obj, vp);
3160
+ }
2779
3161
 
2780
- case T_FIXNUM:
2781
- /* fall through */
2782
- case T_BIGNUM:
2783
- return GetVpValue(iniValue, 1);
3162
+ static VALUE
3163
+ rb_int64_convert_to_BigDecimal(int64_t ival, size_t digs, int raise_exception)
3164
+ {
3165
+ const uint64_t uval = (ival < 0) ? (((uint64_t)-(ival+1))+1) : (uint64_t)ival;
3166
+ VALUE bd = rb_uint64_convert_to_BigDecimal(uval, digs, raise_exception);
3167
+ if (ival < 0) {
3168
+ Real *vp;
3169
+ TypedData_Get_Struct(bd, Real, &BigDecimal_data_type, vp);
3170
+ VpSetSign(vp, -1);
3171
+ }
3172
+ return bd;
3173
+ }
2784
3174
 
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;
3175
+ static VALUE
3176
+ rb_big_convert_to_BigDecimal(VALUE val, RB_UNUSED_VAR(size_t digs), int raise_exception)
3177
+ {
3178
+ assert(RB_TYPE_P(val, T_BIGNUM));
3179
+
3180
+ int leading_zeros;
3181
+ size_t size = rb_absint_size(val, &leading_zeros);
3182
+ int sign = FIX2INT(rb_big_cmp(val, INT2FIX(0)));
3183
+ if (sign < 0 && leading_zeros == 0) {
3184
+ size += 1;
3185
+ }
3186
+ if (size <= sizeof(long)) {
3187
+ if (sign < 0) {
3188
+ return rb_int64_convert_to_BigDecimal(NUM2LONG(val), digs, raise_exception);
2791
3189
  }
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);
3190
+ else {
3191
+ return rb_uint64_convert_to_BigDecimal(NUM2ULONG(val), digs, raise_exception);
3192
+ }
3193
+ }
3194
+ #if defined(SIZEOF_LONG_LONG) && SIZEOF_LONG < SIZEOF_LONG_LONG
3195
+ else if (size <= sizeof(LONG_LONG)) {
3196
+ if (sign < 0) {
3197
+ return rb_int64_convert_to_BigDecimal(NUM2LL(val), digs, raise_exception);
3198
+ }
3199
+ else {
3200
+ return rb_uint64_convert_to_BigDecimal(NUM2ULL(val), digs, raise_exception);
3201
+ }
3202
+ }
3203
+ #endif
3204
+ else {
3205
+ VALUE str = rb_big2str(val, 10);
3206
+ Real *vp = VpCreateRbObject(RSTRING_LEN(str) + BASE_FIG + 1,
3207
+ RSTRING_PTR(str), true);
3208
+ RB_GC_GUARD(str);
3209
+ return check_exception(vp->obj);
3210
+ }
3211
+ }
2809
3212
 
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;
3213
+ static VALUE
3214
+ rb_inum_convert_to_BigDecimal(VALUE val, RB_UNUSED_VAR(size_t digs), int raise_exception)
3215
+ {
3216
+ assert(RB_INTEGER_TYPE_P(val));
3217
+ if (FIXNUM_P(val)) {
3218
+ return rb_int64_convert_to_BigDecimal(FIX2LONG(val), digs, raise_exception);
3219
+ }
3220
+ else {
3221
+ return rb_big_convert_to_BigDecimal(val, digs, raise_exception);
3222
+ }
3223
+ }
3224
+
3225
+ static VALUE
3226
+ rb_float_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
3227
+ {
3228
+ assert(RB_FLOAT_TYPE_P(val));
3229
+
3230
+ double d = RFLOAT_VALUE(val);
3231
+
3232
+ if (isnan(d)) {
3233
+ VALUE obj = BigDecimal_nan();
3234
+ return check_exception(obj);
3235
+ }
3236
+ else if (isinf(d)) {
3237
+ VALUE obj;
3238
+ if (d > 0) {
3239
+ obj = BigDecimal_positive_infinity();
3240
+ }
3241
+ else {
3242
+ obj = BigDecimal_negative_infinity();
3243
+ }
3244
+ return check_exception(obj);
3245
+ }
3246
+ else if (d == 0.0) {
3247
+ if (1/d < 0.0) {
3248
+ return BigDecimal_negative_zero();
3249
+ }
3250
+ else {
3251
+ return BigDecimal_positive_zero();
3252
+ }
3253
+ }
3254
+
3255
+ if (digs == SIZE_MAX) {
3256
+ if (!raise_exception)
3257
+ return Qnil;
3258
+ rb_raise(rb_eArgError,
3259
+ "can't omit precision for a %"PRIsVALUE".",
3260
+ CLASS_OF(val));
3261
+ }
3262
+ else if (digs > BIGDECIMAL_DOUBLE_FIGURES) {
3263
+ if (!raise_exception)
3264
+ return Qnil;
3265
+ rb_raise(rb_eArgError, "precision too large.");
3266
+ }
3267
+
3268
+ /* Use the same logic in flo_to_s to convert a float to a decimal string */
3269
+ char buf[BIGDECIMAL_DOUBLE_FIGURES + BASE_FIG + 2 + 1]; /* sizeof(buf) == 28 in the typical case */
3270
+ int decpt, negative_p;
3271
+ char *e;
3272
+ const int mode = digs == 0 ? 0 : 2;
3273
+ char *p = BigDecimal_dtoa(d, mode, (int)digs, &decpt, &negative_p, &e);
3274
+ int len10 = (int)(e - p);
3275
+ if (len10 > BIGDECIMAL_DOUBLE_FIGURES) {
3276
+ /* TODO: Presumably, rounding should be done here. */
3277
+ len10 = BIGDECIMAL_DOUBLE_FIGURES;
3278
+ }
3279
+ memcpy(buf, p, len10);
3280
+ xfree(p);
3281
+
3282
+ VALUE inum;
3283
+ size_t RB_UNUSED_VAR(prec) = 0;
3284
+ size_t exp = 0;
3285
+ if (decpt > 0) {
3286
+ if (decpt < len10) {
3287
+ /*
3288
+ * len10 |---------------|
3289
+ * : |-------| frac_len10 = len10 - decpt
3290
+ * decpt |-------| |--| ntz10 = BASE_FIG - frac_len10 % BASE_FIG
3291
+ * : : :
3292
+ * 00 dd dddd.dddd dd 00
3293
+ * prec |-----.----.----.-----| prec = exp + roomof(frac_len, BASE_FIG)
3294
+ * exp |-----.----| exp = roomof(decpt, BASE_FIG)
3295
+ */
3296
+ const size_t frac_len10 = len10 - decpt;
3297
+ const size_t ntz10 = BASE_FIG - frac_len10 % BASE_FIG;
3298
+ memset(buf + len10, '0', ntz10);
3299
+ buf[len10 + ntz10] = '\0';
3300
+ inum = rb_cstr_to_inum(buf, 10, false);
3301
+
3302
+ exp = roomof(decpt, BASE_FIG);
3303
+ prec = exp + roomof(frac_len10, BASE_FIG);
3304
+ }
3305
+ else {
3306
+ /*
3307
+ * decpt |-----------------------|
3308
+ * len10 |----------| :
3309
+ * : |------------| exp10
3310
+ * : : :
3311
+ * 00 dd dddd dd 00 0000 0000.0
3312
+ * : : : :
3313
+ * : |--| ntz10 = exp10 % BASE_FIG
3314
+ * prec |-----.----.-----| :
3315
+ * : |----.----| exp10 / BASE_FIG
3316
+ * exp |-----.----.-----.----.----|
3317
+ */
3318
+ const size_t exp10 = decpt - len10;
3319
+ const size_t ntz10 = exp10 % BASE_FIG;
3320
+
3321
+ memset(buf + len10, '0', ntz10);
3322
+ buf[len10 + ntz10] = '\0';
3323
+ inum = rb_cstr_to_inum(buf, 10, false);
3324
+
3325
+ prec = roomof(len10 + ntz10, BASE_FIG);
3326
+ exp = prec + exp10 / BASE_FIG;
3327
+ }
3328
+ }
3329
+ else if (decpt == 0) {
3330
+ /*
3331
+ * len10 |------------|
3332
+ * : :
3333
+ * 0.dddd dddd dd 00
3334
+ * : : :
3335
+ * : |--| ntz10 = prec * BASE_FIG - len10
3336
+ * prec |----.----.-----| roomof(len10, BASE_FIG)
3337
+ */
3338
+ prec = roomof(len10, BASE_FIG);
3339
+ const size_t ntz10 = prec * BASE_FIG - len10;
3340
+
3341
+ memset(buf + len10, '0', ntz10);
3342
+ buf[len10 + ntz10] = '\0';
3343
+ inum = rb_cstr_to_inum(buf, 10, false);
3344
+ }
3345
+ else {
3346
+ /*
3347
+ * len10 |---------------|
3348
+ * : :
3349
+ * decpt |-------| |--| ntz10 = prec * BASE_FIG - nlz10 - len10
3350
+ * : : :
3351
+ * 0.0000 00 dd dddd dddd dd 00
3352
+ * : : :
3353
+ * nlz10 |--| : decpt % BASE_FIG
3354
+ * prec |-----.----.----.-----| roomof(decpt + len10, BASE_FIG) - exp
3355
+ * exp |----| decpt / BASE_FIG
3356
+ */
3357
+ decpt = -decpt;
3358
+
3359
+ const size_t nlz10 = decpt % BASE_FIG;
3360
+ exp = decpt / BASE_FIG;
3361
+ prec = roomof(decpt + len10, BASE_FIG) - exp;
3362
+ const size_t ntz10 = prec * BASE_FIG - nlz10 - len10;
3363
+
3364
+ if (nlz10 > 0) {
3365
+ memmove(buf + nlz10, buf, len10);
3366
+ memset(buf, '0', nlz10);
2820
3367
  }
3368
+ memset(buf + nlz10 + len10, '0', ntz10);
3369
+ buf[nlz10 + len10 + ntz10] = '\0';
3370
+ inum = rb_cstr_to_inum(buf, 10, false);
3371
+
3372
+ exp = -exp;
3373
+ }
3374
+
3375
+ VALUE bd = rb_inum_convert_to_BigDecimal(inum, SIZE_MAX, raise_exception);
3376
+ Real *vp;
3377
+ TypedData_Get_Struct(bd, Real, &BigDecimal_data_type, vp);
3378
+ assert(vp->Prec == prec);
3379
+ vp->exponent = exp;
3380
+
3381
+ if (negative_p) VpSetSign(vp, -1);
3382
+ return bd;
3383
+ }
3384
+
3385
+ static VALUE
3386
+ rb_rational_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
3387
+ {
3388
+ assert(RB_TYPE_P(val, T_RATIONAL));
3389
+
3390
+ if (digs == SIZE_MAX) {
3391
+ if (!raise_exception)
3392
+ return Qnil;
3393
+ rb_raise(rb_eArgError,
3394
+ "can't omit precision for a %"PRIsVALUE".",
3395
+ CLASS_OF(val));
3396
+ }
3397
+
3398
+ VALUE num = rb_inum_convert_to_BigDecimal(rb_rational_num(val), 0, raise_exception);
3399
+ VALUE d = BigDecimal_div2(num, rb_rational_den(val), SIZET2NUM(digs));
3400
+ return d;
3401
+ }
3402
+
3403
+ static VALUE
3404
+ rb_cstr_convert_to_BigDecimal(const char *c_str, size_t digs, int raise_exception)
3405
+ {
3406
+ if (digs == SIZE_MAX)
3407
+ digs = 0;
3408
+
3409
+ Real *vp = VpCreateRbObject(digs, c_str, raise_exception);
3410
+ if (!vp)
3411
+ return Qnil;
3412
+ return VpCheckGetValue(vp);
3413
+ }
3414
+
3415
+ static inline VALUE
3416
+ rb_str_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
3417
+ {
3418
+ const char *c_str = StringValueCStr(val);
3419
+ return rb_cstr_convert_to_BigDecimal(c_str, digs, raise_exception);
3420
+ }
3421
+
3422
+ static VALUE
3423
+ rb_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
3424
+ {
3425
+ switch (val) {
3426
+ case Qnil:
3427
+ case Qtrue:
3428
+ case Qfalse:
3429
+ if (raise_exception) {
3430
+ const char *cname = NIL_P(val) ? "nil" :
3431
+ val == Qtrue ? "true" :
3432
+ val == Qfalse ? "false" :
3433
+ NULL;
3434
+ rb_raise(rb_eTypeError,
3435
+ "can't convert %s into BigDecimal", cname);
3436
+ }
3437
+ return Qnil;
2821
3438
 
2822
- case T_STRING:
2823
- /* fall through */
2824
3439
  default:
2825
- break;
3440
+ break;
3441
+ }
3442
+
3443
+ if (is_kind_of_BigDecimal(val)) {
3444
+ if (digs == SIZE_MAX)
3445
+ return check_exception(val);
3446
+
3447
+ Real *vp;
3448
+ TypedData_Get_Struct(val, Real, &BigDecimal_data_type, vp);
3449
+
3450
+ VALUE copy = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0);
3451
+ vp = VpCopy(NULL, vp);
3452
+ /* TODO: rounding */
3453
+ BigDecimal_wrap_struct(copy, vp);
3454
+ return VpCheckGetValue(vp);
2826
3455
  }
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;
3456
+ else if (RB_INTEGER_TYPE_P(val)) {
3457
+ return rb_inum_convert_to_BigDecimal(val, digs, raise_exception);
3458
+ }
3459
+ else if (RB_FLOAT_TYPE_P(val)) {
3460
+ return rb_float_convert_to_BigDecimal(val, digs, raise_exception);
3461
+ }
3462
+ else if (RB_TYPE_P(val, T_RATIONAL)) {
3463
+ return rb_rational_convert_to_BigDecimal(val, digs, raise_exception);
3464
+ }
3465
+ else if (RB_TYPE_P(val, T_COMPLEX)) {
3466
+ VALUE im = rb_complex_imag(val);
3467
+ if (!is_zero(im)) {
3468
+ /* TODO: handle raise_exception */
3469
+ rb_raise(rb_eArgError,
3470
+ "Unable to make a BigDecimal from non-zero imaginary number");
3471
+ }
3472
+ return rb_convert_to_BigDecimal(rb_complex_real(val), digs, raise_exception);
3473
+ }
3474
+ else if (RB_TYPE_P(val, T_STRING)) {
3475
+ return rb_str_convert_to_BigDecimal(val, digs, raise_exception);
3476
+ }
3477
+
3478
+ /* TODO: chheck to_d */
3479
+ /* TODO: chheck to_int */
3480
+
3481
+ VALUE str = rb_check_convert_type(val, T_STRING, "String", "to_str");
3482
+ if (!RB_TYPE_P(str, T_STRING)) {
3483
+ if (raise_exception) {
3484
+ rb_raise(rb_eTypeError,
3485
+ "can't convert %"PRIsVALUE" into BigDecimal", rb_obj_class(val));
3486
+ }
3487
+ return Qnil;
2831
3488
  }
2832
- StringValueCStr(iniValue);
2833
- return VpAlloc(mf, RSTRING_PTR(iniValue), 1, exc);
3489
+ return rb_str_convert_to_BigDecimal(str, digs, raise_exception);
2834
3490
  }
2835
3491
 
2836
- /* call-seq:
2837
- * BigDecimal(initial, digits, exception: true)
3492
+ /* call-seq:
3493
+ * BigDecimal(value, exception: true) -> bigdecimal
3494
+ * BigDecimal(value, ndigits, exception: true) -> bigdecimal
2838
3495
  *
2839
- * Create a new BigDecimal object.
3496
+ * Returns the \BigDecimal converted from +value+
3497
+ * with a precision of +ndigits+ decimal digits.
2840
3498
  *
2841
- * initial:: The initial value, as an Integer, a Float, a Rational,
2842
- * a BigDecimal, or a String.
3499
+ * When +ndigits+ is less than the number of significant digits
3500
+ * in the value, the result is rounded to that number of digits,
3501
+ * according to the current rounding mode; see BigDecimal.mode.
2843
3502
  *
2844
- * If it is a String, spaces are ignored and unrecognized characters
2845
- * terminate the value.
3503
+ * Returns +value+ converted to a \BigDecimal, depending on the type of +value+:
2846
3504
  *
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.
3505
+ * - Integer, Float, Rational, Complex, or BigDecimal: converted directly:
2850
3506
  *
2851
- * The actual number of significant digits used in computation is
2852
- * usually larger than the specified number.
3507
+ * # Integer, Complex, or BigDecimal value does not require ndigits; ignored if given.
3508
+ * BigDecimal(2) # => 0.2e1
3509
+ * BigDecimal(Complex(2, 0)) # => 0.2e1
3510
+ * BigDecimal(BigDecimal(2)) # => 0.2e1
3511
+ * # Float or Rational value requires ndigits.
3512
+ * BigDecimal(2.0, 0) # => 0.2e1
3513
+ * BigDecimal(Rational(2, 1), 0) # => 0.2e1
2853
3514
  *
2854
- * exception:: Whether an exception should be raised on invalid arguments.
2855
- * +true+ by default, if passed +false+, just returns +nil+
2856
- * for invalid.
3515
+ * - String: converted by parsing if it contains an integer or floating-point literal;
3516
+ * leading and trailing whitespace is ignored:
2857
3517
  *
3518
+ * # String does not require ndigits; ignored if given.
3519
+ * BigDecimal('2') # => 0.2e1
3520
+ * BigDecimal('2.0') # => 0.2e1
3521
+ * BigDecimal('0.2e1') # => 0.2e1
3522
+ * BigDecimal(' 2.0 ') # => 0.2e1
2858
3523
  *
2859
- * ==== Exceptions
3524
+ * - Other type that responds to method <tt>:to_str</tt>:
3525
+ * first converted to a string, then converted to a \BigDecimal, as above.
2860
3526
  *
2861
- * TypeError:: If the +initial+ type is neither Integer, Float,
2862
- * Rational, nor BigDecimal, this exception is raised.
3527
+ * - Other type:
2863
3528
  *
2864
- * TypeError:: If the +digits+ is not an Integer, this exception is raised.
3529
+ * - Raises an exception if keyword argument +exception+ is +true+.
3530
+ * - Returns +nil+ if keyword argument +exception+ is +true+.
2865
3531
  *
2866
- * ArgumentError:: If +initial+ is a Float, and the +digits+ is larger than
2867
- * Float::DIG + 1, this exception is raised.
3532
+ * Raises an exception if +value+ evaluates to a Float
3533
+ * and +digits+ is larger than Float::DIG + 1.
2868
3534
  *
2869
- * ArgumentError:: If the +initial+ is a Float or Rational, and the +digits+
2870
- * value is omitted, this exception is raised.
2871
3535
  */
2872
3536
  static VALUE
2873
3537
  f_BigDecimal(int argc, VALUE *argv, VALUE self)
2874
3538
  {
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];
3539
+ VALUE val, digs_v, opts = Qnil;
3540
+ argc = rb_scan_args(argc, argv, "11:", &val, &digs_v, &opts);
3541
+ int exception = opts_exception_p(opts);
3542
+
3543
+ size_t digs = SIZE_MAX; /* this means digs is omitted */
3544
+ if (argc > 1) {
3545
+ digs_v = rb_to_int(digs_v);
3546
+ if (FIXNUM_P(digs_v)) {
3547
+ long n = FIX2LONG(digs_v);
3548
+ if (n < 0)
3549
+ goto negative_digs;
3550
+ digs = (size_t)n;
3551
+ }
3552
+ else {
3553
+ if (RBIGNUM_NEGATIVE_P(digs_v)) {
3554
+ negative_digs:
3555
+ if (!exception)
3556
+ return Qnil;
3557
+ rb_raise(rb_eArgError, "negative precision");
3558
+ }
3559
+ digs = NUM2SIZET(digs_v);
3560
+ }
2881
3561
  }
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;
3562
+
3563
+ return rb_convert_to_BigDecimal(val, digs, exception);
2890
3564
  }
2891
3565
 
2892
3566
  static VALUE
2893
3567
  BigDecimal_s_interpret_loosely(VALUE klass, VALUE str)
2894
3568
  {
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;
3569
+ char const *c_str = StringValueCStr(str);
3570
+ Real *vp = VpNewRbClass(0, c_str, klass, false, true);
3571
+ if (!vp)
3572
+ return Qnil;
3573
+ else
3574
+ return VpCheckGetValue(vp);
2904
3575
  }
2905
3576
 
2906
3577
  /* call-seq:
@@ -3084,7 +3755,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
3084
3755
  infinite = isinf(flo);
3085
3756
  nan = isnan(flo);
3086
3757
  if (!infinite && !nan) {
3087
- vx = GetVpValueWithPrec(x, DBLE_FIG, 0);
3758
+ vx = GetVpValueWithPrec(x, 0, 0);
3088
3759
  }
3089
3760
  break;
3090
3761
 
@@ -3097,29 +3768,29 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
3097
3768
  }
3098
3769
  if (infinite) {
3099
3770
  if (negative) {
3100
- return ToValue(GetVpValueWithPrec(INT2FIX(0), prec, 1));
3771
+ return VpCheckGetValue(GetVpValueWithPrec(INT2FIX(0), prec, 1));
3101
3772
  }
3102
3773
  else {
3103
3774
  Real* vy;
3104
- vy = VpCreateRbObject(prec, "#0");
3775
+ vy = VpCreateRbObject(prec, "#0", true);
3105
3776
  VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
3106
3777
  RB_GC_GUARD(vy->obj);
3107
- return ToValue(vy);
3778
+ return VpCheckGetValue(vy);
3108
3779
  }
3109
3780
  }
3110
3781
  else if (nan) {
3111
3782
  Real* vy;
3112
- vy = VpCreateRbObject(prec, "#0");
3783
+ vy = VpCreateRbObject(prec, "#0", true);
3113
3784
  VpSetNaN(vy);
3114
3785
  RB_GC_GUARD(vy->obj);
3115
- return ToValue(vy);
3786
+ return VpCheckGetValue(vy);
3116
3787
  }
3117
3788
  else if (vx == NULL) {
3118
3789
  cannot_be_coerced_into_BigDecimal(rb_eArgError, x);
3119
3790
  }
3120
3791
  x = vx->obj;
3121
3792
 
3122
- n = prec + rmpd_double_figures();
3793
+ n = prec + BIGDECIMAL_DOUBLE_FIGURES;
3123
3794
  negative = BIGDECIMAL_NEGATIVE_P(vx);
3124
3795
  if (negative) {
3125
3796
  VALUE x_zero = INT2NUM(1);
@@ -3129,7 +3800,7 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
3129
3800
  VpSetSign(vx, 1);
3130
3801
  }
3131
3802
 
3132
- one = ToValue(VpCreateRbObject(1, "1"));
3803
+ one = VpCheckGetValue(VpCreateRbObject(1, "1", true));
3133
3804
  y = one;
3134
3805
  d = y;
3135
3806
  i = 1;
@@ -3144,8 +3815,8 @@ BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
3144
3815
  if (m <= 0) {
3145
3816
  break;
3146
3817
  }
3147
- else if ((size_t)m < rmpd_double_figures()) {
3148
- m = rmpd_double_figures();
3818
+ else if ((size_t)m < BIGDECIMAL_DOUBLE_FIGURES) {
3819
+ m = BIGDECIMAL_DOUBLE_FIGURES;
3149
3820
  }
3150
3821
 
3151
3822
  d = BigDecimal_mult(d, x); /* d <- d * x */
@@ -3237,7 +3908,7 @@ get_vp_value:
3237
3908
  infinite = isinf(flo);
3238
3909
  nan = isnan(flo);
3239
3910
  if (!zero && !negative && !infinite && !nan) {
3240
- vx = GetVpValueWithPrec(x, DBLE_FIG, 1);
3911
+ vx = GetVpValueWithPrec(x, 0, 1);
3241
3912
  }
3242
3913
  break;
3243
3914
 
@@ -3257,17 +3928,17 @@ get_vp_value:
3257
3928
  }
3258
3929
  if (infinite && !negative) {
3259
3930
  Real* vy;
3260
- vy = VpCreateRbObject(prec, "#0");
3931
+ vy = VpCreateRbObject(prec, "#0", true);
3261
3932
  RB_GC_GUARD(vy->obj);
3262
3933
  VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
3263
- return ToValue(vy);
3934
+ return VpCheckGetValue(vy);
3264
3935
  }
3265
3936
  else if (nan) {
3266
3937
  Real* vy;
3267
- vy = VpCreateRbObject(prec, "#0");
3938
+ vy = VpCreateRbObject(prec, "#0", true);
3268
3939
  RB_GC_GUARD(vy->obj);
3269
3940
  VpSetNaN(vy);
3270
- return ToValue(vy);
3941
+ return VpCheckGetValue(vy);
3271
3942
  }
3272
3943
  else if (zero || negative) {
3273
3944
  rb_raise(rb_eMathDomainError,
@@ -3276,18 +3947,18 @@ get_vp_value:
3276
3947
  else if (vx == NULL) {
3277
3948
  cannot_be_coerced_into_BigDecimal(rb_eArgError, x);
3278
3949
  }
3279
- x = ToValue(vx);
3950
+ x = VpCheckGetValue(vx);
3280
3951
 
3281
- RB_GC_GUARD(one) = ToValue(VpCreateRbObject(1, "1"));
3282
- RB_GC_GUARD(two) = ToValue(VpCreateRbObject(1, "2"));
3952
+ RB_GC_GUARD(one) = VpCheckGetValue(VpCreateRbObject(1, "1", true));
3953
+ RB_GC_GUARD(two) = VpCheckGetValue(VpCreateRbObject(1, "2", true));
3283
3954
 
3284
- n = prec + rmpd_double_figures();
3955
+ n = prec + BIGDECIMAL_DOUBLE_FIGURES;
3285
3956
  RB_GC_GUARD(vn) = SSIZET2NUM(n);
3286
3957
  expo = VpExponent10(vx);
3287
3958
  if (expo < 0 || expo >= 3) {
3288
3959
  char buf[DECIMAL_SIZE_OF_BITS(SIZEOF_VALUE * CHAR_BIT) + 4];
3289
3960
  snprintf(buf, sizeof(buf), "1E%"PRIdVALUE, -expo);
3290
- x = BigDecimal_mult2(x, ToValue(VpCreateRbObject(1, buf)), vn);
3961
+ x = BigDecimal_mult2(x, VpCheckGetValue(VpCreateRbObject(1, buf, true)), vn);
3291
3962
  }
3292
3963
  else {
3293
3964
  expo = 0;
@@ -3305,8 +3976,8 @@ get_vp_value:
3305
3976
  if (m <= 0) {
3306
3977
  break;
3307
3978
  }
3308
- else if ((size_t)m < rmpd_double_figures()) {
3309
- m = rmpd_double_figures();
3979
+ else if ((size_t)m < BIGDECIMAL_DOUBLE_FIGURES) {
3980
+ m = BIGDECIMAL_DOUBLE_FIGURES;
3310
3981
  }
3311
3982
 
3312
3983
  x = BigDecimal_mult2(x2, x, vn);
@@ -3319,7 +3990,7 @@ get_vp_value:
3319
3990
  if (expo != 0) {
3320
3991
  VALUE log10, vexpo, dy;
3321
3992
  log10 = BigMath_s_log(klass, INT2FIX(10), vprec);
3322
- vexpo = ToValue(GetVpValue(SSIZET2NUM(expo), 1));
3993
+ vexpo = VpCheckGetValue(GetVpValue(SSIZET2NUM(expo), 1));
3323
3994
  dy = BigDecimal_mult(log10, vexpo);
3324
3995
  y = BigDecimal_add(y, dy);
3325
3996
  }
@@ -3327,6 +3998,46 @@ get_vp_value:
3327
3998
  return y;
3328
3999
  }
3329
4000
 
4001
+ static VALUE BIGDECIMAL_NAN = Qnil;
4002
+
4003
+ static VALUE
4004
+ BigDecimal_nan(void)
4005
+ {
4006
+ return BIGDECIMAL_NAN;
4007
+ }
4008
+
4009
+ static VALUE BIGDECIMAL_POSITIVE_INFINITY = Qnil;
4010
+
4011
+ static VALUE
4012
+ BigDecimal_positive_infinity(void)
4013
+ {
4014
+ return BIGDECIMAL_POSITIVE_INFINITY;
4015
+ }
4016
+
4017
+ static VALUE BIGDECIMAL_NEGATIVE_INFINITY = Qnil;
4018
+
4019
+ static VALUE
4020
+ BigDecimal_negative_infinity(void)
4021
+ {
4022
+ return BIGDECIMAL_NEGATIVE_INFINITY;
4023
+ }
4024
+
4025
+ static VALUE BIGDECIMAL_POSITIVE_ZERO = Qnil;
4026
+
4027
+ static VALUE
4028
+ BigDecimal_positive_zero(void)
4029
+ {
4030
+ return BIGDECIMAL_POSITIVE_ZERO;
4031
+ }
4032
+
4033
+ static VALUE BIGDECIMAL_NEGATIVE_ZERO = Qnil;
4034
+
4035
+ static VALUE
4036
+ BigDecimal_negative_zero(void)
4037
+ {
4038
+ return BIGDECIMAL_NEGATIVE_ZERO;
4039
+ }
4040
+
3330
4041
  /* Document-class: BigDecimal
3331
4042
  * BigDecimal provides arbitrary-precision floating point decimal arithmetic.
3332
4043
  *
@@ -3370,6 +4081,18 @@ get_vp_value:
3370
4081
  *
3371
4082
  * (1.2 - 1.0) == 0.2 #=> false
3372
4083
  *
4084
+ * == A Note About Precision
4085
+ *
4086
+ * For a calculation using a \BigDecimal and another +value+,
4087
+ * the precision of the result depends on the type of +value+:
4088
+ *
4089
+ * - If +value+ is a \Float,
4090
+ * the precision is Float::DIG + 1.
4091
+ * - If +value+ is a \Rational, the precision is larger than Float::DIG + 1.
4092
+ * - If +value+ is a \BigDecimal, the precision is +value+'s precision in the
4093
+ * internal representation, which is platform-dependent.
4094
+ * - If +value+ is other object, the precision is determined by the result of +BigDecimal(value)+.
4095
+ *
3373
4096
  * == Special features of accurate decimal arithmetic
3374
4097
  *
3375
4098
  * Because BigDecimal is more accurate than normal binary floating point
@@ -3598,17 +4321,40 @@ Init_bigdecimal(void)
3598
4321
  /* -3: Indicates that a value is negative and infinite. See BigDecimal.sign. */
3599
4322
  rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_INFINITE", INT2FIX(VP_SIGN_NEGATIVE_INFINITE));
3600
4323
 
3601
- arg = rb_str_new2("+Infinity");
4324
+ /* Positive zero value. */
4325
+ arg = rb_str_new2("+0");
4326
+ BIGDECIMAL_POSITIVE_ZERO = f_BigDecimal(1, &arg, rb_cBigDecimal);
4327
+ rb_gc_register_mark_object(BIGDECIMAL_POSITIVE_ZERO);
4328
+
4329
+ /* Negative zero value. */
4330
+ arg = rb_str_new2("-0");
4331
+ BIGDECIMAL_NEGATIVE_ZERO = f_BigDecimal(1, &arg, rb_cBigDecimal);
4332
+ rb_gc_register_mark_object(BIGDECIMAL_NEGATIVE_ZERO);
4333
+
3602
4334
  /* Positive infinity value. */
3603
- rb_define_const(rb_cBigDecimal, "INFINITY", f_BigDecimal(1, &arg, rb_cBigDecimal));
3604
- arg = rb_str_new2("NaN");
4335
+ arg = rb_str_new2("+Infinity");
4336
+ BIGDECIMAL_POSITIVE_INFINITY = f_BigDecimal(1, &arg, rb_cBigDecimal);
4337
+ rb_gc_register_mark_object(BIGDECIMAL_POSITIVE_INFINITY);
4338
+
4339
+ /* Negative infinity value. */
4340
+ arg = rb_str_new2("-Infinity");
4341
+ BIGDECIMAL_NEGATIVE_INFINITY = f_BigDecimal(1, &arg, rb_cBigDecimal);
4342
+ rb_gc_register_mark_object(BIGDECIMAL_NEGATIVE_INFINITY);
4343
+
3605
4344
  /* 'Not a Number' value. */
3606
- rb_define_const(rb_cBigDecimal, "NAN", f_BigDecimal(1, &arg, rb_cBigDecimal));
4345
+ arg = rb_str_new2("NaN");
4346
+ BIGDECIMAL_NAN = f_BigDecimal(1, &arg, rb_cBigDecimal);
4347
+ rb_gc_register_mark_object(BIGDECIMAL_NAN);
3607
4348
 
4349
+ /* Special value constants */
4350
+ rb_define_const(rb_cBigDecimal, "INFINITY", BIGDECIMAL_POSITIVE_INFINITY);
4351
+ rb_define_const(rb_cBigDecimal, "NAN", BIGDECIMAL_NAN);
3608
4352
 
3609
4353
  /* instance methods */
3610
4354
  rb_define_method(rb_cBigDecimal, "precs", BigDecimal_prec, 0);
3611
4355
  rb_define_method(rb_cBigDecimal, "precision", BigDecimal_precision, 0);
4356
+ rb_define_method(rb_cBigDecimal, "scale", BigDecimal_scale, 0);
4357
+ rb_define_method(rb_cBigDecimal, "precision_scale", BigDecimal_precision_scale, 0);
3612
4358
  rb_define_method(rb_cBigDecimal, "n_significant_digits", BigDecimal_n_significant_digits, 0);
3613
4359
 
3614
4360
  rb_define_method(rb_cBigDecimal, "add", BigDecimal_add2, 2);
@@ -3627,7 +4373,7 @@ Init_bigdecimal(void)
3627
4373
  rb_define_method(rb_cBigDecimal, "-@", BigDecimal_neg, 0);
3628
4374
  rb_define_method(rb_cBigDecimal, "*", BigDecimal_mult, 1);
3629
4375
  rb_define_method(rb_cBigDecimal, "/", BigDecimal_div, 1);
3630
- rb_define_method(rb_cBigDecimal, "quo", BigDecimal_div, 1);
4376
+ rb_define_method(rb_cBigDecimal, "quo", BigDecimal_quo, -1);
3631
4377
  rb_define_method(rb_cBigDecimal, "%", BigDecimal_mod, 1);
3632
4378
  rb_define_method(rb_cBigDecimal, "modulo", BigDecimal_mod, 1);
3633
4379
  rb_define_method(rb_cBigDecimal, "remainder", BigDecimal_remainder, 1);
@@ -3718,9 +4464,9 @@ enum op_sw {
3718
4464
 
3719
4465
  static int VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw);
3720
4466
  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);
4467
+ static DECDIG VpAddAbs(Real *a,Real *b,Real *c);
4468
+ static DECDIG VpSubAbs(Real *a,Real *b,Real *c);
4469
+ static size_t VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos, DECDIG *av, DECDIG *bv);
3724
4470
  static int VpNmlz(Real *a);
3725
4471
  static void VpFormatSt(char *psz, size_t fFmt);
3726
4472
  static int VpRdup(Real *m, size_t ind_m);
@@ -3736,9 +4482,6 @@ VP_EXPORT void *
3736
4482
  VpMemAlloc(size_t mb)
3737
4483
  {
3738
4484
  void *p = xmalloc(mb);
3739
- if (!p) {
3740
- VpException(VP_EXCEPTION_MEMORY, "failed to allocate memory", 1);
3741
- }
3742
4485
  memset(p, 0, mb);
3743
4486
  #ifdef BIGDECIMAL_DEBUG
3744
4487
  gnAlloc++; /* Count allocation call */
@@ -3749,11 +4492,7 @@ VpMemAlloc(size_t mb)
3749
4492
  VP_EXPORT void *
3750
4493
  VpMemRealloc(void *ptr, size_t mb)
3751
4494
  {
3752
- void *p = xrealloc(ptr, mb);
3753
- if (!p) {
3754
- VpException(VP_EXCEPTION_MEMORY, "failed to allocate memory", 1);
3755
- }
3756
- return p;
4495
+ return xrealloc(ptr, mb);
3757
4496
  }
3758
4497
 
3759
4498
  VP_EXPORT void
@@ -3779,7 +4518,7 @@ VpFree(Real *pv)
3779
4518
  * EXCEPTION Handling.
3780
4519
  */
3781
4520
 
3782
- #define rmpd_set_thread_local_exception_mode(mode) \
4521
+ #define bigdecimal_set_thread_local_exception_mode(mode) \
3783
4522
  rb_thread_local_aset( \
3784
4523
  rb_thread_current(), \
3785
4524
  id_BigDecimal_exception_mode, \
@@ -3795,8 +4534,8 @@ VpGetException (void)
3795
4534
  );
3796
4535
 
3797
4536
  if (NIL_P(vmode)) {
3798
- rmpd_set_thread_local_exception_mode(RMPD_EXCEPTION_MODE_DEFAULT);
3799
- return RMPD_EXCEPTION_MODE_DEFAULT;
4537
+ bigdecimal_set_thread_local_exception_mode(BIGDECIMAL_EXCEPTION_MODE_DEFAULT);
4538
+ return BIGDECIMAL_EXCEPTION_MODE_DEFAULT;
3800
4539
  }
3801
4540
 
3802
4541
  return NUM2USHORT(vmode);
@@ -3805,20 +4544,41 @@ VpGetException (void)
3805
4544
  static void
3806
4545
  VpSetException(unsigned short f)
3807
4546
  {
3808
- rmpd_set_thread_local_exception_mode(f);
4547
+ bigdecimal_set_thread_local_exception_mode(f);
4548
+ }
4549
+
4550
+ static void
4551
+ VpCheckException(Real *p, bool always)
4552
+ {
4553
+ if (VpIsNaN(p)) {
4554
+ VpException(VP_EXCEPTION_NaN, "Computation results in 'NaN' (Not a Number)", always);
4555
+ }
4556
+ else if (VpIsPosInf(p)) {
4557
+ VpException(VP_EXCEPTION_INFINITY, "Computation results in 'Infinity'", always);
4558
+ }
4559
+ else if (VpIsNegInf(p)) {
4560
+ VpException(VP_EXCEPTION_INFINITY, "Computation results in '-Infinity'", always);
4561
+ }
4562
+ }
4563
+
4564
+ static VALUE
4565
+ VpCheckGetValue(Real *p)
4566
+ {
4567
+ VpCheckException(p, false);
4568
+ return p->obj;
3809
4569
  }
3810
4570
 
3811
4571
  /*
3812
4572
  * Precision limit.
3813
4573
  */
3814
4574
 
3815
- #define rmpd_set_thread_local_precision_limit(limit) \
4575
+ #define bigdecimal_set_thread_local_precision_limit(limit) \
3816
4576
  rb_thread_local_aset( \
3817
4577
  rb_thread_current(), \
3818
4578
  id_BigDecimal_precision_limit, \
3819
4579
  SIZET2NUM(limit) \
3820
4580
  )
3821
- #define RMPD_PRECISION_LIMIT_DEFAULT ((size_t)0)
4581
+ #define BIGDECIMAL_PRECISION_LIMIT_DEFAULT ((size_t)0)
3822
4582
 
3823
4583
  /* These 2 functions added at v1.1.7 */
3824
4584
  VP_EXPORT size_t
@@ -3830,8 +4590,8 @@ VpGetPrecLimit(void)
3830
4590
  );
3831
4591
 
3832
4592
  if (NIL_P(vlimit)) {
3833
- rmpd_set_thread_local_precision_limit(RMPD_PRECISION_LIMIT_DEFAULT);
3834
- return RMPD_PRECISION_LIMIT_DEFAULT;
4593
+ bigdecimal_set_thread_local_precision_limit(BIGDECIMAL_PRECISION_LIMIT_DEFAULT);
4594
+ return BIGDECIMAL_PRECISION_LIMIT_DEFAULT;
3835
4595
  }
3836
4596
 
3837
4597
  return NUM2SIZET(vlimit);
@@ -3841,7 +4601,7 @@ VP_EXPORT size_t
3841
4601
  VpSetPrecLimit(size_t n)
3842
4602
  {
3843
4603
  size_t const s = VpGetPrecLimit();
3844
- rmpd_set_thread_local_precision_limit(n);
4604
+ bigdecimal_set_thread_local_precision_limit(n);
3845
4605
  return s;
3846
4606
  }
3847
4607
 
@@ -3849,7 +4609,7 @@ VpSetPrecLimit(size_t n)
3849
4609
  * Rounding mode.
3850
4610
  */
3851
4611
 
3852
- #define rmpd_set_thread_local_rounding_mode(mode) \
4612
+ #define bigdecimal_set_thread_local_rounding_mode(mode) \
3853
4613
  rb_thread_local_aset( \
3854
4614
  rb_thread_current(), \
3855
4615
  id_BigDecimal_rounding_mode, \
@@ -3865,8 +4625,8 @@ VpGetRoundMode(void)
3865
4625
  );
3866
4626
 
3867
4627
  if (NIL_P(vmode)) {
3868
- rmpd_set_thread_local_rounding_mode(RMPD_ROUNDING_MODE_DEFAULT);
3869
- return RMPD_ROUNDING_MODE_DEFAULT;
4628
+ bigdecimal_set_thread_local_rounding_mode(BIGDECIMAL_ROUNDING_MODE_DEFAULT);
4629
+ return BIGDECIMAL_ROUNDING_MODE_DEFAULT;
3870
4630
  }
3871
4631
 
3872
4632
  return NUM2USHORT(vmode);
@@ -3894,7 +4654,7 @@ VP_EXPORT unsigned short
3894
4654
  VpSetRoundMode(unsigned short n)
3895
4655
  {
3896
4656
  if (VpIsRoundMode(n)) {
3897
- rmpd_set_thread_local_rounding_mode(n);
4657
+ bigdecimal_set_thread_local_rounding_mode(n);
3898
4658
  return n;
3899
4659
  }
3900
4660
 
@@ -3971,7 +4731,7 @@ VpException(unsigned short f, const char *str,int always)
3971
4731
  {
3972
4732
  unsigned short const exception_mode = VpGetException();
3973
4733
 
3974
- if (f == VP_EXCEPTION_OP || f == VP_EXCEPTION_MEMORY) always = 1;
4734
+ if (f == VP_EXCEPTION_OP) always = 1;
3975
4735
 
3976
4736
  if (always || (exception_mode & f)) {
3977
4737
  switch(f) {
@@ -3983,7 +4743,6 @@ VpException(unsigned short f, const char *str,int always)
3983
4743
  case VP_EXCEPTION_OP:
3984
4744
  rb_raise(rb_eFloatDomainError, "%s", str);
3985
4745
  break;
3986
- case VP_EXCEPTION_MEMORY:
3987
4746
  default:
3988
4747
  rb_fatal("%s", str);
3989
4748
  }
@@ -4132,13 +4891,13 @@ VpNumOfChars(Real *vp,const char *pszFmt)
4132
4891
  * that BASE is as large as possible satisfying the
4133
4892
  * relation MaxVal <= BASE*(BASE+1). Where the value
4134
4893
  * MaxVal is the largest value which can be represented
4135
- * by one BDIGIT word in the computer used.
4894
+ * by one DECDIG word in the computer used.
4136
4895
  *
4137
4896
  * [Returns]
4138
- * DBLE_FIG ... OK
4897
+ * BIGDECIMAL_DOUBLE_FIGURES ... OK
4139
4898
  */
4140
4899
  VP_EXPORT size_t
4141
- VpInit(BDIGIT BaseVal)
4900
+ VpInit(DECDIG BaseVal)
4142
4901
  {
4143
4902
  /* Setup +/- Inf NaN -0 */
4144
4903
  VpGetDoubleNegZero();
@@ -4153,16 +4912,16 @@ VpInit(BDIGIT BaseVal)
4153
4912
 
4154
4913
  #ifdef BIGDECIMAL_DEBUG
4155
4914
  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);
4915
+ printf("VpInit: BaseVal = %"PRIuDECDIG"\n", BaseVal);
4916
+ printf("\tBASE = %"PRIuDECDIG"\n", BASE);
4917
+ printf("\tHALF_BASE = %"PRIuDECDIG"\n", HALF_BASE);
4918
+ printf("\tBASE1 = %"PRIuDECDIG"\n", BASE1);
4919
+ printf("\tBASE_FIG = %u\n", BASE_FIG);
4920
+ printf("\tBIGDECIMAL_DOUBLE_FIGURES = %d\n", BIGDECIMAL_DOUBLE_FIGURES);
4162
4921
  }
4163
4922
  #endif /* BIGDECIMAL_DEBUG */
4164
4923
 
4165
- return rmpd_double_figures();
4924
+ return BIGDECIMAL_DOUBLE_FIGURES;
4166
4925
  }
4167
4926
 
4168
4927
  VP_EXPORT Real *
@@ -4210,7 +4969,7 @@ overflow:
4210
4969
  }
4211
4970
 
4212
4971
  Real *
4213
- rmpd_parse_special_string(const char *str)
4972
+ bigdecimal_parse_special_string(const char *str)
4214
4973
  {
4215
4974
  static const struct {
4216
4975
  const char *str;
@@ -4305,14 +5064,13 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
4305
5064
  /* at least mx digits. */
4306
5065
  /* szVal==NULL ==> allocate zero value. */
4307
5066
  vp = VpAllocReal(mx);
4308
- /* xmalloc() always returns(or throw interruption) */
4309
5067
  vp->MaxPrec = mx; /* set max precision */
4310
5068
  VpSetZero(vp, 1); /* initialize vp to zero. */
4311
5069
  return vp;
4312
5070
  }
4313
5071
 
4314
5072
  /* Check on Inf & NaN */
4315
- if ((vp = rmpd_parse_special_string(szVal)) != NULL) {
5073
+ if ((vp = bigdecimal_parse_special_string(szVal)) != NULL) {
4316
5074
  return vp;
4317
5075
  }
4318
5076
 
@@ -4481,7 +5239,6 @@ VpAlloc(size_t mx, const char *szVal, int strict_p, int exc)
4481
5239
  nalloc = Max(nalloc, mx);
4482
5240
  mx = nalloc;
4483
5241
  vp = VpAllocReal(mx);
4484
- /* xmalloc() always returns(or throw interruption) */
4485
5242
  vp->MaxPrec = mx; /* set max precision */
4486
5243
  VpSetZero(vp, sign);
4487
5244
  VpCtoV(vp, psz, ni, psz + ipf, nf, psz + ipe, ne);
@@ -4520,7 +5277,7 @@ VpAsgn(Real *c, Real *a, int isw)
4520
5277
  VpSetSign(c, isw * VpGetSign(a)); /* set sign */
4521
5278
  n = (a->Prec < c->MaxPrec) ? (a->Prec) : (c->MaxPrec);
4522
5279
  c->Prec = n;
4523
- memcpy(c->frac, a->frac, n * sizeof(BDIGIT));
5280
+ memcpy(c->frac, a->frac, n * sizeof(DECDIG));
4524
5281
  /* Needs round ? */
4525
5282
  if (isw != 10) {
4526
5283
  /* Not in ActiveRound */
@@ -4551,7 +5308,7 @@ VpAddSub(Real *c, Real *a, Real *b, int operation)
4551
5308
  short sw, isw;
4552
5309
  Real *a_ptr, *b_ptr;
4553
5310
  size_t n, na, nb, i;
4554
- BDIGIT mrv;
5311
+ DECDIG mrv;
4555
5312
 
4556
5313
  #ifdef BIGDECIMAL_DEBUG
4557
5314
  if (gfDebug) {
@@ -4679,7 +5436,7 @@ end_if:
4679
5436
  * a and b assuming abs(a)>abs(b).
4680
5437
  * c = abs(a) + abs(b) ; where |a|>=|b|
4681
5438
  */
4682
- static BDIGIT
5439
+ static DECDIG
4683
5440
  VpAddAbs(Real *a, Real *b, Real *c)
4684
5441
  {
4685
5442
  size_t word_shift;
@@ -4689,7 +5446,7 @@ VpAddAbs(Real *a, Real *b, Real *c)
4689
5446
  size_t a_pos;
4690
5447
  size_t b_pos, b_pos_with_word_shift;
4691
5448
  size_t c_pos;
4692
- BDIGIT av, bv, carry, mrv;
5449
+ DECDIG av, bv, carry, mrv;
4693
5450
 
4694
5451
  #ifdef BIGDECIMAL_DEBUG
4695
5452
  if (gfDebug) {
@@ -4774,7 +5531,7 @@ Exit:
4774
5531
  /*
4775
5532
  * c = abs(a) - abs(b)
4776
5533
  */
4777
- static BDIGIT
5534
+ static DECDIG
4778
5535
  VpSubAbs(Real *a, Real *b, Real *c)
4779
5536
  {
4780
5537
  size_t word_shift;
@@ -4784,7 +5541,7 @@ VpSubAbs(Real *a, Real *b, Real *c)
4784
5541
  size_t a_pos;
4785
5542
  size_t b_pos, b_pos_with_word_shift;
4786
5543
  size_t c_pos;
4787
- BDIGIT av, bv, borrow, mrv;
5544
+ DECDIG av, bv, borrow, mrv;
4788
5545
 
4789
5546
  #ifdef BIGDECIMAL_DEBUG
4790
5547
  if (gfDebug) {
@@ -4891,7 +5648,7 @@ Exit:
4891
5648
  * c_pos = |
4892
5649
  */
4893
5650
  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)
5651
+ VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos, DECDIG *av, DECDIG *bv)
4895
5652
  {
4896
5653
  size_t left_word, right_word, word_shift;
4897
5654
 
@@ -5006,8 +5763,8 @@ VpMult(Real *c, Real *a, Real *b)
5006
5763
  size_t MxIndA, MxIndB, MxIndAB, MxIndC;
5007
5764
  size_t ind_c, i, ii, nc;
5008
5765
  size_t ind_as, ind_ae, ind_bs;
5009
- BDIGIT carry;
5010
- BDIGIT_DBL s;
5766
+ DECDIG carry;
5767
+ DECDIG_DBL s;
5011
5768
  Real *w;
5012
5769
 
5013
5770
  #ifdef BIGDECIMAL_DEBUG
@@ -5061,7 +5818,7 @@ VpMult(Real *c, Real *a, Real *b)
5061
5818
  VpSetSign(c, VpGetSign(a) * VpGetSign(b)); /* set sign */
5062
5819
  carry = 0;
5063
5820
  nc = ind_c = MxIndAB;
5064
- memset(c->frac, 0, (nc + 1) * sizeof(BDIGIT)); /* Initialize c */
5821
+ memset(c->frac, 0, (nc + 1) * sizeof(DECDIG)); /* Initialize c */
5065
5822
  c->Prec = nc + 1; /* set precision */
5066
5823
  for (nc = 0; nc < MxIndAB; ++nc, --ind_c) {
5067
5824
  if (nc < MxIndB) { /* The left triangle of the Fig. */
@@ -5081,15 +5838,15 @@ VpMult(Real *c, Real *a, Real *b)
5081
5838
  }
5082
5839
 
5083
5840
  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
- }
5841
+ s = (DECDIG_DBL)a->frac[i] * b->frac[ind_bs--];
5842
+ carry = (DECDIG)(s / BASE);
5843
+ s -= (DECDIG_DBL)carry * BASE;
5844
+ c->frac[ind_c] += (DECDIG)s;
5845
+ if (c->frac[ind_c] >= BASE) {
5846
+ s = c->frac[ind_c] / BASE;
5847
+ carry += (DECDIG)s;
5848
+ c->frac[ind_c] -= (DECDIG)(s * BASE);
5849
+ }
5093
5850
  if (carry) {
5094
5851
  ii = ind_c;
5095
5852
  while (ii-- > 0) {
@@ -5135,9 +5892,9 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
5135
5892
  size_t word_a, word_b, word_c, word_r;
5136
5893
  size_t i, n, ind_a, ind_b, ind_c, ind_r;
5137
5894
  size_t nLoop;
5138
- BDIGIT_DBL q, b1, b1p1, b1b2, b1b2p1, r1r2;
5139
- BDIGIT borrow, borrow1, borrow2;
5140
- BDIGIT_DBL qb;
5895
+ DECDIG_DBL q, b1, b1p1, b1b2, b1b2p1, r1r2;
5896
+ DECDIG borrow, borrow1, borrow2;
5897
+ DECDIG_DBL qb;
5141
5898
 
5142
5899
  #ifdef BIGDECIMAL_DEBUG
5143
5900
  if (gfDebug) {
@@ -5174,18 +5931,17 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
5174
5931
  word_c = c->MaxPrec;
5175
5932
  word_r = r->MaxPrec;
5176
5933
 
5177
- ind_c = 0;
5178
- ind_r = 1;
5179
-
5180
5934
  if (word_a >= word_r) goto space_error;
5181
5935
 
5936
+ ind_r = 1;
5182
5937
  r->frac[0] = 0;
5183
5938
  while (ind_r <= word_a) {
5184
5939
  r->frac[ind_r] = a->frac[ind_r - 1];
5185
5940
  ++ind_r;
5186
5941
  }
5187
-
5188
5942
  while (ind_r < word_r) r->frac[ind_r++] = 0;
5943
+
5944
+ ind_c = 0;
5189
5945
  while (ind_c < word_c) c->frac[ind_c++] = 0;
5190
5946
 
5191
5947
  /* initial procedure */
@@ -5209,7 +5965,7 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
5209
5965
  ++ind_c;
5210
5966
  continue;
5211
5967
  }
5212
- r1r2 = (BDIGIT_DBL)r->frac[ind_c] * BASE + r->frac[ind_c + 1];
5968
+ r1r2 = (DECDIG_DBL)r->frac[ind_c] * BASE + r->frac[ind_c + 1];
5213
5969
  if (r1r2 == b1b2) {
5214
5970
  /* The first two word digits is the same */
5215
5971
  ind_b = 2;
@@ -5246,17 +6002,17 @@ VpDivd(Real *c, Real *r, Real *a, Real *b)
5246
6002
  /* The first two word digits is not the same, */
5247
6003
  /* then compare magnitude, and divide actually. */
5248
6004
  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;
6005
+ q = r1r2 / b1b2p1; /* q == (DECDIG)q */
6006
+ c->frac[ind_c] += (DECDIG)q;
6007
+ ind_r = b->Prec + ind_c - 1;
6008
+ goto sub_mult;
5253
6009
  }
5254
6010
 
5255
6011
  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;
6012
+ if (ind_c + 1 >= word_c) goto out_side;
6013
+ q = r1r2 / b1p1; /* q == (DECDIG)q */
6014
+ c->frac[ind_c + 1] += (DECDIG)q;
6015
+ ind_r = b->Prec + ind_c;
5260
6016
 
5261
6017
  sub_mult:
5262
6018
  borrow1 = borrow2 = 0;
@@ -5268,16 +6024,16 @@ sub_mult:
5268
6024
  qb = q * b->frac[ind_b];
5269
6025
  if (qb < BASE) borrow1 = 0;
5270
6026
  else {
5271
- borrow1 = (BDIGIT)(qb / BASE);
5272
- qb -= (BDIGIT_DBL)borrow1 * BASE; /* get qb < BASE */
6027
+ borrow1 = (DECDIG)(qb / BASE);
6028
+ qb -= (DECDIG_DBL)borrow1 * BASE; /* get qb < BASE */
5273
6029
  }
5274
6030
  if(r->frac[ind_r] < qb) {
5275
- r->frac[ind_r] += (BDIGIT)(BASE - qb);
5276
- borrow2 = borrow2 + borrow1 + 1;
6031
+ r->frac[ind_r] += (DECDIG)(BASE - qb);
6032
+ borrow2 = borrow2 + borrow1 + 1;
5277
6033
  }
5278
6034
  else {
5279
- r->frac[ind_r] -= (BDIGIT)qb;
5280
- borrow2 += borrow1;
6035
+ r->frac[ind_r] -= (DECDIG)qb;
6036
+ borrow2 += borrow1;
5281
6037
  }
5282
6038
  if (borrow2) {
5283
6039
  if(r->frac[ind_r - 1] < borrow2) {
@@ -5359,9 +6115,9 @@ VpNmlz(Real *a)
5359
6115
  i = 0;
5360
6116
  while (a->frac[i] == 0) ++i; /* skip the first few zeros */
5361
6117
  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));
6118
+ a->Prec -= i;
6119
+ if (!AddExponent(a, -(SIGNED_VALUE)i)) return 0;
6120
+ memmove(&a->frac[0], &a->frac[i], a->Prec*sizeof(DECDIG));
5365
6121
  }
5366
6122
  return 1;
5367
6123
  }
@@ -5484,7 +6240,7 @@ static int
5484
6240
  VPrint(FILE *fp, const char *cntl_chr, Real *a)
5485
6241
  {
5486
6242
  size_t i, j, nc, nd, ZeroSup, sep = 10;
5487
- BDIGIT m, e, nn;
6243
+ DECDIG m, e, nn;
5488
6244
 
5489
6245
  j = 0;
5490
6246
  nd = nc = 0; /* nd : number of digits in fraction part(every 10 digits, */
@@ -5519,7 +6275,7 @@ VPrint(FILE *fp, const char *cntl_chr, Real *a)
5519
6275
  case '0': case 'z':
5520
6276
  ZeroSup = 0;
5521
6277
  ++j;
5522
- sep = cntl_chr[j] == 'z' ? RMPD_COMPONENT_FIGURES : 10;
6278
+ sep = cntl_chr[j] == 'z' ? BIGDECIMAL_COMPONENT_FIGURES : 10;
5523
6279
  break;
5524
6280
  }
5525
6281
  for (i = 0; i < a->Prec; ++i) {
@@ -5628,7 +6384,7 @@ VP_EXPORT void
5628
6384
  VpSzMantissa(Real *a,char *psz)
5629
6385
  {
5630
6386
  size_t i, n, ZeroSup;
5631
- BDIGIT_DBL m, e, nn;
6387
+ DECDIG_DBL m, e, nn;
5632
6388
 
5633
6389
  if (VpIsNaN(a)) {
5634
6390
  sprintf(psz, SZ_NaN);
@@ -5711,7 +6467,7 @@ VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
5711
6467
  /* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
5712
6468
  {
5713
6469
  size_t i, n, ZeroSup;
5714
- BDIGIT shift, m, e, nn;
6470
+ DECDIG shift, m, e, nn;
5715
6471
  char *pszSav = psz;
5716
6472
  ssize_t ex;
5717
6473
 
@@ -5759,7 +6515,7 @@ VpToFString(Real *a, char *psz, size_t fFmt, int fPlus)
5759
6515
  /* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
5760
6516
  {
5761
6517
  size_t i, n;
5762
- BDIGIT m, e, nn;
6518
+ DECDIG m, e, nn;
5763
6519
  char *pszSav = psz;
5764
6520
  ssize_t ex;
5765
6521
 
@@ -5834,7 +6590,7 @@ VpCtoV(Real *a, const char *int_chr, size_t ni, const char *frac, size_t nf, con
5834
6590
  me = ne;
5835
6591
  signe = 1;
5836
6592
  exponent_overflow = 0;
5837
- memset(a->frac, 0, ma * sizeof(BDIGIT));
6593
+ memset(a->frac, 0, ma * sizeof(DECDIG));
5838
6594
  if (ne > 0) {
5839
6595
  i = 0;
5840
6596
  if (exp_chr[0] == '-') {
@@ -5971,7 +6727,7 @@ Final:
5971
6727
  * [Output]
5972
6728
  * *d ... fraction part of m(d = 0.xxxxxxx). where # of 'x's is fig.
5973
6729
  * *e ... exponent of m.
5974
- * DBLE_FIG ... Number of digits in a double variable.
6730
+ * BIGDECIMAL_DOUBLE_FIGURES ... Number of digits in a double variable.
5975
6731
  *
5976
6732
  * m -> d*10**e, 0<d<BASE
5977
6733
  * [Returns]
@@ -6018,7 +6774,7 @@ VpVtoD(double *d, SIGNED_VALUE *e, Real *m)
6018
6774
  goto Exit;
6019
6775
  }
6020
6776
  /* Normal number */
6021
- fig = (DBLE_FIG + BASE_FIG - 1) / BASE_FIG;
6777
+ fig = roomof(BIGDECIMAL_DOUBLE_FIGURES, BASE_FIG);
6022
6778
  ind_m = 0;
6023
6779
  mm = Min(fig, m->Prec);
6024
6780
  *d = 0.0;
@@ -6035,7 +6791,7 @@ Exit:
6035
6791
  if (gfDebug) {
6036
6792
  VPrint(stdout, " VpVtoD: m=%\n", m);
6037
6793
  printf(" d=%e * 10 **%ld\n", *d, *e);
6038
- printf(" DBLE_FIG = %d\n", DBLE_FIG);
6794
+ printf(" BIGDECIMAL_DOUBLE_FIGURES = %d\n", BIGDECIMAL_DOUBLE_FIGURES);
6039
6795
  }
6040
6796
  #endif /*BIGDECIMAL_DEBUG */
6041
6797
  return f;
@@ -6049,7 +6805,7 @@ VpDtoV(Real *m, double d)
6049
6805
  {
6050
6806
  size_t ind_m, mm;
6051
6807
  SIGNED_VALUE ne;
6052
- BDIGIT i;
6808
+ DECDIG i;
6053
6809
  double val, val2;
6054
6810
 
6055
6811
  if (isnan(d)) {
@@ -6084,12 +6840,12 @@ VpDtoV(Real *m, double d)
6084
6840
  /* Now val = 0.xxxxx*BASE**ne */
6085
6841
 
6086
6842
  mm = m->MaxPrec;
6087
- memset(m->frac, 0, mm * sizeof(BDIGIT));
6843
+ memset(m->frac, 0, mm * sizeof(DECDIG));
6088
6844
  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;
6845
+ val *= (double)BASE;
6846
+ i = (DECDIG)val;
6847
+ val -= (double)i;
6848
+ m->frac[ind_m] = i;
6093
6849
  }
6094
6850
  if (ind_m >= mm) ind_m = mm - 1;
6095
6851
  VpSetSign(m, (d > 0.0) ? 1 : -1);
@@ -6097,7 +6853,7 @@ VpDtoV(Real *m, double d)
6097
6853
  m->exponent = ne;
6098
6854
 
6099
6855
  VpInternalRound(m, 0, (m->Prec > 0) ? m->frac[m->Prec-1] : 0,
6100
- (BDIGIT)(val*(double)BASE));
6856
+ (DECDIG)(val*(double)BASE));
6101
6857
 
6102
6858
  Exit:
6103
6859
  #ifdef BIGDECIMAL_DEBUG
@@ -6236,7 +6992,7 @@ VpSqrt(Real *y, Real *x)
6236
6992
  }
6237
6993
  VpDtoV(y, sqrt(val)); /* y <- sqrt(val) */
6238
6994
  y->exponent += n;
6239
- n = (SIGNED_VALUE)((DBLE_FIG + BASE_FIG - 1) / BASE_FIG);
6995
+ n = (SIGNED_VALUE)roomof(BIGDECIMAL_DOUBLE_FIGURES, BASE_FIG);
6240
6996
  y->MaxPrec = Min((size_t)n , y_prec);
6241
6997
  f->MaxPrec = y->MaxPrec + 1;
6242
6998
  n = (SIGNED_VALUE)(y_prec * BASE_FIG);
@@ -6293,8 +7049,8 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
6293
7049
  /* exptoadd: number of digits needed to compensate negative nf */
6294
7050
  int fracf, fracf_1further;
6295
7051
  ssize_t n,i,ix,ioffset, exptoadd;
6296
- BDIGIT v, shifter;
6297
- BDIGIT div;
7052
+ DECDIG v, shifter;
7053
+ DECDIG div;
6298
7054
 
6299
7055
  nf += y->exponent * (ssize_t)BASE_FIG;
6300
7056
  exptoadd=0;
@@ -6316,8 +7072,8 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
6316
7072
  n = (ssize_t)BASE_FIG - ioffset - 1;
6317
7073
  for (shifter = 1, i = 0; i < n; ++i) shifter *= 10;
6318
7074
 
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
7075
+ /* so the representation used (in y->frac) is an array of DECDIG, where
7076
+ each DECDIG contains a value between 0 and BASE-1, consisting of BASE_FIG
6321
7077
  decimal places.
6322
7078
 
6323
7079
  (that numbers of decimal places are typed as ssize_t is somewhat confusing)
@@ -6325,10 +7081,10 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
6325
7081
  nf is now position (in decimal places) of the digit from the start of
6326
7082
  the array.
6327
7083
 
6328
- ix is the position (in BDIGITS) of the BDIGIT containing the decimal digit,
7084
+ ix is the position (in DECDIGs) of the DECDIG containing the decimal digit,
6329
7085
  from the start of the array.
6330
7086
 
6331
- v is the value of this BDIGIT
7087
+ v is the value of this DECDIG
6332
7088
 
6333
7089
  ioffset is the number of extra decimal places along of this decimal digit
6334
7090
  within v.
@@ -6354,7 +7110,7 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
6354
7110
  now fracf_1further is whether any of the remaining digits within v are non-zero
6355
7111
  */
6356
7112
 
6357
- /* now check all the remaining BDIGITS for zero-ness a whole BDIGIT at a time.
7113
+ /* now check all the remaining DECDIGs for zero-ness a whole DECDIG at a time.
6358
7114
  if we spot any non-zeroness, that means that we found a positive digit under
6359
7115
  rounding position, and we also found a positive digit under one further than
6360
7116
  the rounding position, so both searches (to see if any such non-zero digit exists)
@@ -6373,7 +7129,7 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
6373
7129
  now v = the first digit under the rounding position */
6374
7130
 
6375
7131
  /* drop digits after pointed digit */
6376
- memset(y->frac + ix + 1, 0, (y->Prec - (ix + 1)) * sizeof(BDIGIT));
7132
+ memset(y->frac + ix + 1, 0, (y->Prec - (ix + 1)) * sizeof(DECDIG));
6377
7133
 
6378
7134
  switch (f) {
6379
7135
  case VP_ROUND_DOWN: /* Truncate */
@@ -6401,11 +7157,11 @@ VpMidRound(Real *y, unsigned short f, ssize_t nf)
6401
7157
  }
6402
7158
  else {
6403
7159
  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) */
7160
+ /* v is the first decimal digit of its DECDIG;
7161
+ need to grab the previous DECDIG if present
7162
+ to check for evenness of the previous decimal
7163
+ digit (which is same as that of the DECDIG since
7164
+ base 10 has a factor of 2) */
6409
7165
  if (ix && (y->frac[ix-1] % 2)) ++div;
6410
7166
  }
6411
7167
  else {
@@ -6453,7 +7209,7 @@ VpLeftRound(Real *y, unsigned short f, ssize_t nf)
6453
7209
  * Round from the left hand side of the digits.
6454
7210
  */
6455
7211
  {
6456
- BDIGIT v;
7212
+ DECDIG v;
6457
7213
  if (!VpHasVal(y)) return 0; /* Unable to round */
6458
7214
  v = y->frac[0];
6459
7215
  nf -= VpExponent(y) * (ssize_t)BASE_FIG;
@@ -6484,7 +7240,7 @@ VpLimitRound(Real *c, size_t ixDigit)
6484
7240
  /* If I understand correctly, this is only ever used to round off the final decimal
6485
7241
  digit of precision */
6486
7242
  static void
6487
- VpInternalRound(Real *c, size_t ixDigit, BDIGIT vPrev, BDIGIT v)
7243
+ VpInternalRound(Real *c, size_t ixDigit, DECDIG vPrev, DECDIG v)
6488
7244
  {
6489
7245
  int f = 0;
6490
7246
 
@@ -6534,7 +7290,7 @@ VpInternalRound(Real *c, size_t ixDigit, BDIGIT vPrev, BDIGIT v)
6534
7290
  static int
6535
7291
  VpRdup(Real *m, size_t ind_m)
6536
7292
  {
6537
- BDIGIT carry;
7293
+ DECDIG carry;
6538
7294
 
6539
7295
  if (!ind_m) ind_m = m->Prec;
6540
7296
 
@@ -6606,7 +7362,7 @@ Exit:
6606
7362
  * y = x ** n
6607
7363
  */
6608
7364
  VP_EXPORT int
6609
- VpPower(Real *y, Real *x, SIGNED_VALUE n)
7365
+ VpPowerByInt(Real *y, Real *x, SIGNED_VALUE n)
6610
7366
  {
6611
7367
  size_t s, ss;
6612
7368
  ssize_t sign;
@@ -6693,8 +7449,8 @@ VpPower(Real *y, Real *x, SIGNED_VALUE n)
6693
7449
  Exit:
6694
7450
  #ifdef BIGDECIMAL_DEBUG
6695
7451
  if (gfDebug) {
6696
- VPrint(stdout, "VpPower y=%\n", y);
6697
- VPrint(stdout, "VpPower x=%\n", x);
7452
+ VPrint(stdout, "VpPowerByInt y=%\n", y);
7453
+ VPrint(stdout, "VpPowerByInt x=%\n", x);
6698
7454
  printf(" n=%"PRIdVALUE"\n", n);
6699
7455
  }
6700
7456
  #endif /* BIGDECIMAL_DEBUG */
@@ -6729,12 +7485,12 @@ VpVarCheck(Real * v)
6729
7485
  }
6730
7486
  for (i = 0; i < v->Prec; ++i) {
6731
7487
  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;
7488
+ printf("ERROR(VpVarCheck): Illegal fraction\n");
7489
+ printf(" Frac[%"PRIuSIZE"]=%"PRIuDECDIG"\n", i, v->frac[i]);
7490
+ printf(" Prec. =%"PRIuSIZE"\n", v->Prec);
7491
+ printf(" Exp. =%"PRIdVALUE"\n", v->exponent);
7492
+ printf(" BASE =%"PRIuDECDIG"\n", BASE);
7493
+ return 3;
6738
7494
  }
6739
7495
  }
6740
7496
  return 0;