bigdecimal 3.0.0 → 3.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -30,14 +30,11 @@
30
30
  #include <ieeefp.h>
31
31
  #endif
32
32
 
33
+ #include "bits.h"
34
+ #include "static_assert.h"
35
+
33
36
  /* #define ENABLE_NUMERIC_STRING */
34
37
 
35
- #define MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max) ( \
36
- (a) == 0 ? 0 : \
37
- (a) == -1 ? (b) < -(max) : \
38
- (a) > 0 ? \
39
- ((b) > 0 ? (max) / (a) < (b) : (min) / (a) > (b)) : \
40
- ((b) > 0 ? (min) / (a) < (b) : (max) / (a) > (b)))
41
38
  #define SIGNED_VALUE_MAX INTPTR_MAX
42
39
  #define SIGNED_VALUE_MIN INTPTR_MIN
43
40
  #define MUL_OVERFLOW_SIGNED_VALUE_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, SIGNED_VALUE_MIN, SIGNED_VALUE_MAX)
@@ -65,20 +62,22 @@ static ID id_eq;
65
62
  static ID id_half;
66
63
 
67
64
  /* MACRO's to guard objects from GC by keeping them in stack */
65
+ #ifdef RBIMPL_ATTR_MAYBE_UNUSED
66
+ #define ENTER(n) RBIMPL_ATTR_MAYBE_UNUSED() volatile VALUE vStack[n];int iStack=0
67
+ #else
68
68
  #define ENTER(n) volatile VALUE RB_UNUSED_VAR(vStack[n]);int iStack=0
69
+ #endif
69
70
  #define PUSH(x) (vStack[iStack++] = (VALUE)(x))
70
71
  #define SAVE(p) PUSH((p)->obj)
71
72
  #define GUARD_OBJ(p,y) ((p)=(y), SAVE(p))
72
73
 
73
- #define BASE_FIG RMPD_COMPONENT_FIGURES
74
- #define BASE RMPD_BASE
74
+ #define BASE_FIG BIGDECIMAL_COMPONENT_FIGURES
75
+ #define BASE BIGDECIMAL_BASE
75
76
 
76
77
  #define HALF_BASE (BASE/2)
77
78
  #define BASE1 (BASE/10)
78
79
 
79
- #ifndef DBLE_FIG
80
- #define DBLE_FIG 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;