Ruby  2.5.0dev(2017-10-22revision60238)
bigdecimal.c
Go to the documentation of this file.
1 /*
2  *
3  * Ruby BigDecimal(Variable decimal precision) extension library.
4  *
5  * Copyright(C) 2002 by Shigeo Kobayashi(shigeo@tinyforest.gr.jp)
6  *
7  */
8 
9 /* #define BIGDECIMAL_DEBUG 1 */
10 #ifdef BIGDECIMAL_DEBUG
11 # define BIGDECIMAL_ENABLE_VPRINT 1
12 #endif
13 #include "bigdecimal.h"
14 #include "ruby/util.h"
15 
16 #ifndef BIGDECIMAL_DEBUG
17 # define NDEBUG
18 #endif
19 #include <assert.h>
20 
21 #include <ctype.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <math.h>
27 #include "math.h"
28 
29 #ifdef HAVE_IEEEFP_H
30 #include <ieeefp.h>
31 #endif
32 
33 /* #define ENABLE_NUMERIC_STRING */
34 
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 #define SIGNED_VALUE_MAX INTPTR_MAX
42 #define SIGNED_VALUE_MIN INTPTR_MIN
43 #define MUL_OVERFLOW_SIGNED_VALUE_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, SIGNED_VALUE_MIN, SIGNED_VALUE_MAX)
44 
47 
48 static ID id_BigDecimal_exception_mode;
49 static ID id_BigDecimal_rounding_mode;
50 static ID id_BigDecimal_precision_limit;
51 
52 static ID id_up;
53 static ID id_down;
54 static ID id_truncate;
55 static ID id_half_up;
56 static ID id_default;
57 static ID id_half_down;
58 static ID id_half_even;
59 static ID id_banker;
60 static ID id_ceiling;
61 static ID id_ceil;
62 static ID id_floor;
63 static ID id_to_r;
64 static ID id_eq;
65 static ID id_half;
66 
67 /* MACRO's to guard objects from GC by keeping them in stack */
68 #define ENTER(n) volatile VALUE RB_UNUSED_VAR(vStack[n]);int iStack=0
69 #define PUSH(x) (vStack[iStack++] = (VALUE)(x))
70 #define SAVE(p) PUSH((p)->obj)
71 #define GUARD_OBJ(p,y) ((p)=(y), SAVE(p))
72 
73 #define BASE_FIG RMPD_COMPONENT_FIGURES
74 #define BASE RMPD_BASE
75 
76 #define HALF_BASE (BASE/2)
77 #define BASE1 (BASE/10)
78 
79 #ifndef DBLE_FIG
80 #define DBLE_FIG (DBL_DIG+1) /* figure of double */
81 #endif
82 
83 #ifndef RRATIONAL_ZERO_P
84 # define RRATIONAL_ZERO_P(x) (FIXNUM_P(rb_rational_num(x)) && \
85  FIX2LONG(rb_rational_num(x)) == 0)
86 #endif
87 
88 #ifndef RRATIONAL_NEGATIVE_P
89 # define RRATIONAL_NEGATIVE_P(x) RTEST(rb_funcall((x), '<', 1, INT2FIX(0)))
90 #endif
91 
92 #ifndef DECIMAL_SIZE_OF_BITS
93 #define DECIMAL_SIZE_OF_BITS(n) (((n) * 3010 + 9998) / 9999)
94 /* an approximation of ceil(n * log10(2)), upto 65536 at least */
95 #endif
96 
97 #ifdef PRIsVALUE
98 # define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj)
99 # define RB_OBJ_STRING(obj) (obj)
100 #else
101 # define PRIsVALUE "s"
102 # define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj)
103 # define RB_OBJ_STRING(obj) StringValueCStr(obj)
104 #endif
105 
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"));
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"));
126 #endif
127 }
128 #endif
129 
130 #define BIGDECIMAL_POSITIVE_P(bd) ((bd)->sign > 0)
131 #define BIGDECIMAL_NEGATIVE_P(bd) ((bd)->sign < 0)
132 
133 /*
134  * ================== Ruby Interface part ==========================
135  */
136 #define DoSomeOne(x,y,f) rb_num_coerce_bin(x,y,f)
137 
138 /*
139  * Returns the BigDecimal version number.
140  */
141 static VALUE
142 BigDecimal_version(VALUE self)
143 {
144  /*
145  * 1.0.0: Ruby 1.8.0
146  * 1.0.1: Ruby 1.8.1
147  * 1.1.0: Ruby 1.9.3
148  */
149  return rb_str_new2("1.1.0");
150 }
151 
152 /*
153  * VP routines used in BigDecimal part
154  */
155 static unsigned short VpGetException(void);
156 static void VpSetException(unsigned short f);
157 static void VpInternalRound(Real *c, size_t ixDigit, BDIGIT vPrev, BDIGIT v);
158 static int VpLimitRound(Real *c, size_t ixDigit);
159 static Real *VpCopy(Real *pv, Real const* const x);
160 
161 #ifdef BIGDECIMAL_ENABLE_VPRINT
162 static int VPrint(FILE *fp,const char *cntl_chr,Real *a);
163 #endif
164 
165 /*
166  * **** BigDecimal part ****
167  */
168 
169 static void
170 BigDecimal_delete(void *pv)
171 {
172  VpFree(pv);
173 }
174 
175 static size_t
176 BigDecimal_memsize(const void *ptr)
177 {
178  const Real *pv = ptr;
179  return (sizeof(*pv) + pv->MaxPrec * sizeof(BDIGIT));
180 }
181 
182 static const rb_data_type_t BigDecimal_data_type = {
183  "BigDecimal",
184  { 0, BigDecimal_delete, BigDecimal_memsize, },
185 #ifdef RUBY_TYPED_FREE_IMMEDIATELY
187 #endif
188 };
189 
190 static inline int
191 is_kind_of_BigDecimal(VALUE const v)
192 {
193  return rb_typeddata_is_kind_of(v, &BigDecimal_data_type);
194 }
195 
196 static VALUE
197 ToValue(Real *p)
198 {
199  if (VpIsNaN(p)) {
200  VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'(Not a Number)", 0);
201  }
202  else if (VpIsPosInf(p)) {
203  VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 0);
204  }
205  else if (VpIsNegInf(p)) {
206  VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 0);
207  }
208  return p->obj;
209 }
210 
211 NORETURN(static void cannot_be_coerced_into_BigDecimal(VALUE, VALUE));
212 
213 static void
214 cannot_be_coerced_into_BigDecimal(VALUE exc_class, VALUE v)
215 {
216  VALUE str;
217 
218  if (rb_special_const_p(v)) {
219  str = rb_inspect(v);
220  }
221  else {
222  str = rb_class_name(rb_obj_class(v));
223  }
224 
225  str = rb_str_cat2(rb_str_dup(str), " can't be coerced into BigDecimal");
226  rb_exc_raise(rb_exc_new3(exc_class, str));
227 }
228 
229 static inline VALUE BigDecimal_div2(VALUE, VALUE, VALUE);
230 
231 static Real*
232 GetVpValueWithPrec(VALUE v, long prec, int must)
233 {
234  ENTER(1);
235  Real *pv;
236  VALUE num, bg;
237  char szD[128];
238  VALUE orig = Qundef;
239  double d;
240 
241 again:
242  switch(TYPE(v)) {
243  case T_FLOAT:
244  if (prec < 0) goto unable_to_coerce_without_prec;
245  if (prec > DBL_DIG+1) goto SomeOneMayDoIt;
246  d = RFLOAT_VALUE(v);
247  if (!isfinite(d)) {
248  pv = VpCreateRbObject(1, NULL);
249  VpDtoV(pv, d);
250  return pv;
251  }
252  if (d != 0.0) {
253  v = rb_funcall(v, id_to_r, 0);
254  goto again;
255  }
256  if (1/d < 0.0) {
257  return VpCreateRbObject(prec, "-0");
258  }
259  return VpCreateRbObject(prec, "0");
260 
261  case T_RATIONAL:
262  if (prec < 0) goto unable_to_coerce_without_prec;
263 
264  if (orig == Qundef ? (orig = v, 1) : orig != v) {
265  num = rb_rational_num(v);
266  pv = GetVpValueWithPrec(num, -1, must);
267  if (pv == NULL) goto SomeOneMayDoIt;
268 
269  v = BigDecimal_div2(ToValue(pv), rb_rational_den(v), LONG2NUM(prec));
270  goto again;
271  }
272 
273  v = orig;
274  goto SomeOneMayDoIt;
275 
276  case T_DATA:
277  if (is_kind_of_BigDecimal(v)) {
278  pv = DATA_PTR(v);
279  return pv;
280  }
281  else {
282  goto SomeOneMayDoIt;
283  }
284  break;
285 
286  case T_FIXNUM:
287  sprintf(szD, "%ld", FIX2LONG(v));
288  return VpCreateRbObject(VpBaseFig() * 2 + 1, szD);
289 
290 #ifdef ENABLE_NUMERIC_STRING
291  case T_STRING:
292  StringValueCStr(v);
294  return VpCreateRbObject(RSTRING_LEN(v) + VpBaseFig() + 1,
295  RSTRING_PTR(v));
296 #endif /* ENABLE_NUMERIC_STRING */
297 
298  case T_BIGNUM:
299  bg = rb_big2str(v, 10);
300  PUSH(bg);
301  return VpCreateRbObject(strlen(RSTRING_PTR(bg)) + VpBaseFig() + 1,
302  RSTRING_PTR(bg));
303  default:
304  goto SomeOneMayDoIt;
305  }
306 
307 SomeOneMayDoIt:
308  if (must) {
309  cannot_be_coerced_into_BigDecimal(rb_eTypeError, v);
310  }
311  return NULL; /* NULL means to coerce */
312 
313 unable_to_coerce_without_prec:
314  if (must) {
316  "%"PRIsVALUE" can't be coerced into BigDecimal without a precision",
317  RB_OBJ_CLASSNAME(v));
318  }
319  return NULL;
320 }
321 
322 static Real*
323 GetVpValue(VALUE v, int must)
324 {
325  return GetVpValueWithPrec(v, -1, must);
326 }
327 
328 /* call-seq:
329  * BigDecimal.double_fig
330  *
331  * The BigDecimal.double_fig class method returns the number of digits a
332  * Float number is allowed to have. The result depends upon the CPU and OS
333  * in use.
334  */
335 static VALUE
336 BigDecimal_double_fig(VALUE self)
337 {
338  return INT2FIX(VpDblFig());
339 }
340 
341 /* call-seq:
342  * big_decimal.precs -> array
343  *
344  * Returns an Array of two Integer values.
345  *
346  * The first value is the current number of significant digits in the
347  * BigDecimal. The second value is the maximum number of significant digits
348  * for the BigDecimal.
349  *
350  * BigDecimal('5').precs #=> [9, 18]
351  */
352 
353 static VALUE
354 BigDecimal_prec(VALUE self)
355 {
356  ENTER(1);
357  Real *p;
358  VALUE obj;
359 
360  GUARD_OBJ(p, GetVpValue(self, 1));
361  obj = rb_assoc_new(INT2NUM(p->Prec*VpBaseFig()),
362  INT2NUM(p->MaxPrec*VpBaseFig()));
363  return obj;
364 }
365 
366 /*
367  * call-seq: hash
368  *
369  * Creates a hash for this BigDecimal.
370  *
371  * Two BigDecimals with equal sign,
372  * fractional part and exponent have the same hash.
373  */
374 static VALUE
375 BigDecimal_hash(VALUE self)
376 {
377  ENTER(1);
378  Real *p;
379  st_index_t hash;
380 
381  GUARD_OBJ(p, GetVpValue(self, 1));
382  hash = (st_index_t)p->sign;
383  /* hash!=2: the case for 0(1),NaN(0) or +-Infinity(3) is sign itself */
384  if(hash == 2 || hash == (st_index_t)-2) {
385  hash ^= rb_memhash(p->frac, sizeof(BDIGIT)*p->Prec);
386  hash += p->exponent;
387  }
388  return ST2FIX(hash);
389 }
390 
391 /*
392  * call-seq: _dump
393  *
394  * Method used to provide marshalling support.
395  *
396  * inf = BigDecimal.new('Infinity')
397  * #=> Infinity
398  * BigDecimal._load(inf._dump)
399  * #=> Infinity
400  *
401  * See the Marshal module.
402  */
403 static VALUE
404 BigDecimal_dump(int argc, VALUE *argv, VALUE self)
405 {
406  ENTER(5);
407  Real *vp;
408  char *psz;
409  VALUE dummy;
410  volatile VALUE dump;
411 
412  rb_scan_args(argc, argv, "01", &dummy);
413  GUARD_OBJ(vp,GetVpValue(self, 1));
414  dump = rb_str_new(0, VpNumOfChars(vp, "E")+50);
415  psz = RSTRING_PTR(dump);
416  sprintf(psz, "%"PRIuSIZE":", VpMaxPrec(vp)*VpBaseFig());
417  VpToString(vp, psz+strlen(psz), 0, 0);
418  rb_str_resize(dump, strlen(psz));
419  return dump;
420 }
421 
422 /*
423  * Internal method used to provide marshalling support. See the Marshal module.
424  */
425 static VALUE
426 BigDecimal_load(VALUE self, VALUE str)
427 {
428  ENTER(2);
429  Real *pv;
430  unsigned char *pch;
431  unsigned char ch;
432  unsigned long m=0;
433 
434  pch = (unsigned char *)StringValueCStr(str);
435  rb_check_safe_obj(str);
436  /* First get max prec */
437  while((*pch) != (unsigned char)'\0' && (ch = *pch++) != (unsigned char)':') {
438  if(!ISDIGIT(ch)) {
439  rb_raise(rb_eTypeError, "load failed: invalid character in the marshaled string");
440  }
441  m = m*10 + (unsigned long)(ch-'0');
442  }
443  if (m > VpBaseFig()) m -= VpBaseFig();
444  GUARD_OBJ(pv, VpNewRbClass(m, (char *)pch, self));
445  m /= VpBaseFig();
446  if (m && pv->MaxPrec > m) {
447  pv->MaxPrec = m+1;
448  }
449  return ToValue(pv);
450 }
451 
452 static unsigned short
453 check_rounding_mode_option(VALUE const opts)
454 {
455  VALUE mode;
456  char const *s;
457  long l;
458 
459  assert(RB_TYPE_P(opts, T_HASH));
460 
461  if (NIL_P(opts))
462  goto noopt;
463 
464  mode = rb_hash_lookup2(opts, ID2SYM(id_half), Qundef);
465  if (mode == Qundef || NIL_P(mode))
466  goto noopt;
467 
468  if (SYMBOL_P(mode))
469  mode = rb_sym2str(mode);
470  else if (!RB_TYPE_P(mode, T_STRING)) {
471  VALUE str_mode = rb_check_string_type(mode);
472  if (NIL_P(str_mode)) goto invalid;
473  mode = str_mode;
474  }
475  s = RSTRING_PTR(mode);
476  l = RSTRING_LEN(mode);
477  switch (l) {
478  case 2:
479  if (strncasecmp(s, "up", 2) == 0)
480  return VP_ROUND_HALF_UP;
481  break;
482  case 4:
483  if (strncasecmp(s, "even", 4) == 0)
484  return VP_ROUND_HALF_EVEN;
485  else if (strncasecmp(s, "down", 4) == 0)
486  return VP_ROUND_HALF_DOWN;
487  break;
488  default:
489  break;
490  }
491  invalid:
492  if (NIL_P(mode))
493  rb_raise(rb_eArgError, "invalid rounding mode: nil");
494  else
495  rb_raise(rb_eArgError, "invalid rounding mode: %"PRIsVALUE, mode);
496 
497  noopt:
498  return VpGetRoundMode();
499 }
500 
501 static unsigned short
502 check_rounding_mode(VALUE const v)
503 {
504  unsigned short sw;
505  ID id;
506  switch (TYPE(v)) {
507  case T_SYMBOL:
508  id = SYM2ID(v);
509  if (id == id_up)
510  return VP_ROUND_UP;
511  if (id == id_down || id == id_truncate)
512  return VP_ROUND_DOWN;
513  if (id == id_half_up || id == id_default)
514  return VP_ROUND_HALF_UP;
515  if (id == id_half_down)
516  return VP_ROUND_HALF_DOWN;
517  if (id == id_half_even || id == id_banker)
518  return VP_ROUND_HALF_EVEN;
519  if (id == id_ceiling || id == id_ceil)
520  return VP_ROUND_CEIL;
521  if (id == id_floor)
522  return VP_ROUND_FLOOR;
523  rb_raise(rb_eArgError, "invalid rounding mode");
524 
525  default:
526  break;
527  }
528 
529  sw = NUM2USHORT(v);
530  if (!VpIsRoundMode(sw)) {
531  rb_raise(rb_eArgError, "invalid rounding mode");
532  }
533  return sw;
534 }
535 
536 /* call-seq:
537  * BigDecimal.mode(mode, value)
538  *
539  * Controls handling of arithmetic exceptions and rounding. If no value
540  * is supplied, the current value is returned.
541  *
542  * Six values of the mode parameter control the handling of arithmetic
543  * exceptions:
544  *
545  * BigDecimal::EXCEPTION_NaN
546  * BigDecimal::EXCEPTION_INFINITY
547  * BigDecimal::EXCEPTION_UNDERFLOW
548  * BigDecimal::EXCEPTION_OVERFLOW
549  * BigDecimal::EXCEPTION_ZERODIVIDE
550  * BigDecimal::EXCEPTION_ALL
551  *
552  * For each mode parameter above, if the value set is false, computation
553  * continues after an arithmetic exception of the appropriate type.
554  * When computation continues, results are as follows:
555  *
556  * EXCEPTION_NaN:: NaN
557  * EXCEPTION_INFINITY:: +Infinity or -Infinity
558  * EXCEPTION_UNDERFLOW:: 0
559  * EXCEPTION_OVERFLOW:: +Infinity or -Infinity
560  * EXCEPTION_ZERODIVIDE:: +Infinity or -Infinity
561  *
562  * One value of the mode parameter controls the rounding of numeric values:
563  * BigDecimal::ROUND_MODE. The values it can take are:
564  *
565  * ROUND_UP, :up:: round away from zero
566  * ROUND_DOWN, :down, :truncate:: round towards zero (truncate)
567  * ROUND_HALF_UP, :half_up, :default:: round towards the nearest neighbor, unless both neighbors are equidistant, in which case round away from zero. (default)
568  * ROUND_HALF_DOWN, :half_down:: round towards the nearest neighbor, unless both neighbors are equidistant, in which case round towards zero.
569  * 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)
570  * ROUND_CEILING, :ceiling, :ceil:: round towards positive infinity (ceil)
571  * ROUND_FLOOR, :floor:: round towards negative infinity (floor)
572  *
573  */
574 static VALUE
575 BigDecimal_mode(int argc, VALUE *argv, VALUE self)
576 {
577  VALUE which;
578  VALUE val;
579  unsigned long f,fo;
580 
581  rb_scan_args(argc, argv, "11", &which, &val);
582  f = (unsigned long)NUM2INT(which);
583 
584  if (f & VP_EXCEPTION_ALL) {
585  /* Exception mode setting */
586  fo = VpGetException();
587  if (val == Qnil) return INT2FIX(fo);
588  if (val != Qfalse && val!=Qtrue) {
589  rb_raise(rb_eArgError, "second argument must be true or false");
590  return Qnil; /* Not reached */
591  }
592  if (f & VP_EXCEPTION_INFINITY) {
593  VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_INFINITY) :
594  (fo & (~VP_EXCEPTION_INFINITY))));
595  }
596  fo = VpGetException();
597  if (f & VP_EXCEPTION_NaN) {
598  VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_NaN) :
599  (fo & (~VP_EXCEPTION_NaN))));
600  }
601  fo = VpGetException();
602  if (f & VP_EXCEPTION_UNDERFLOW) {
603  VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_UNDERFLOW) :
604  (fo & (~VP_EXCEPTION_UNDERFLOW))));
605  }
606  fo = VpGetException();
607  if(f & VP_EXCEPTION_ZERODIVIDE) {
608  VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_ZERODIVIDE) :
609  (fo & (~VP_EXCEPTION_ZERODIVIDE))));
610  }
611  fo = VpGetException();
612  return INT2FIX(fo);
613  }
614  if (VP_ROUND_MODE == f) {
615  /* Rounding mode setting */
616  unsigned short sw;
617  fo = VpGetRoundMode();
618  if (NIL_P(val)) return INT2FIX(fo);
619  sw = check_rounding_mode(val);
620  fo = VpSetRoundMode(sw);
621  return INT2FIX(fo);
622  }
623  rb_raise(rb_eTypeError, "first argument for BigDecimal.mode invalid");
624  return Qnil;
625 }
626 
627 static size_t
628 GetAddSubPrec(Real *a, Real *b)
629 {
630  size_t mxs;
631  size_t mx = a->Prec;
632  SIGNED_VALUE d;
633 
634  if (!VpIsDef(a) || !VpIsDef(b)) return (size_t)-1L;
635  if (mx < b->Prec) mx = b->Prec;
636  if (a->exponent != b->exponent) {
637  mxs = mx;
638  d = a->exponent - b->exponent;
639  if (d < 0) d = -d;
640  mx = mx + (size_t)d;
641  if (mx < mxs) {
642  return VpException(VP_EXCEPTION_INFINITY, "Exponent overflow", 0);
643  }
644  }
645  return mx;
646 }
647 
648 static SIGNED_VALUE
649 GetPositiveInt(VALUE v)
650 {
651  SIGNED_VALUE n;
652  n = NUM2INT(v);
653  if (n < 0) {
654  rb_raise(rb_eArgError, "argument must be positive");
655  }
656  return n;
657 }
658 
659 VP_EXPORT Real *
660 VpNewRbClass(size_t mx, const char *str, VALUE klass)
661 {
662  VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0);
663  Real *pv = VpAlloc(mx,str);
664  RTYPEDDATA_DATA(obj) = pv;
665  pv->obj = obj;
666  return pv;
667 }
668 
669 VP_EXPORT Real *
670 VpCreateRbObject(size_t mx, const char *str)
671 {
672  return VpNewRbClass(mx, str, rb_cBigDecimal);
673 }
674 
675 #define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(BDIGIT))
676 #define VpReallocReal(ptr, prec) (Real *)VpMemRealloc((ptr), offsetof(Real, frac) + (prec) * sizeof(BDIGIT))
677 
678 static Real *
679 VpCopy(Real *pv, Real const* const x)
680 {
681  assert(x != NULL);
682 
683  pv = VpReallocReal(pv, x->MaxPrec);
684  pv->MaxPrec = x->MaxPrec;
685  pv->Prec = x->Prec;
686  pv->exponent = x->exponent;
687  pv->sign = x->sign;
688  pv->flag = x->flag;
689  MEMCPY(pv->frac, x->frac, BDIGIT, pv->MaxPrec);
690 
691  return pv;
692 }
693 
694 /* Returns True if the value is Not a Number. */
695 static VALUE
696 BigDecimal_IsNaN(VALUE self)
697 {
698  Real *p = GetVpValue(self, 1);
699  if (VpIsNaN(p)) return Qtrue;
700  return Qfalse;
701 }
702 
703 /* Returns nil, -1, or +1 depending on whether the value is finite,
704  * -Infinity, or +Infinity.
705  */
706 static VALUE
707 BigDecimal_IsInfinite(VALUE self)
708 {
709  Real *p = GetVpValue(self, 1);
710  if (VpIsPosInf(p)) return INT2FIX(1);
711  if (VpIsNegInf(p)) return INT2FIX(-1);
712  return Qnil;
713 }
714 
715 /* Returns True if the value is finite (not NaN or infinite). */
716 static VALUE
717 BigDecimal_IsFinite(VALUE self)
718 {
719  Real *p = GetVpValue(self, 1);
720  if (VpIsNaN(p)) return Qfalse;
721  if (VpIsInf(p)) return Qfalse;
722  return Qtrue;
723 }
724 
725 static void
726 BigDecimal_check_num(Real *p)
727 {
728  if (VpIsNaN(p)) {
729  VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'(Not a Number)", 1);
730  }
731  else if (VpIsPosInf(p)) {
732  VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 1);
733  }
734  else if (VpIsNegInf(p)) {
735  VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 1);
736  }
737 }
738 
739 static VALUE BigDecimal_split(VALUE self);
740 
741 /* Returns the value as an Integer.
742  *
743  * If the BigDecimal is infinity or NaN, raises FloatDomainError.
744  */
745 static VALUE
746 BigDecimal_to_i(VALUE self)
747 {
748  ENTER(5);
749  ssize_t e, nf;
750  Real *p;
751 
752  GUARD_OBJ(p, GetVpValue(self, 1));
753  BigDecimal_check_num(p);
754 
755  e = VpExponent10(p);
756  if (e <= 0) return INT2FIX(0);
757  nf = VpBaseFig();
758  if (e <= nf) {
759  return LONG2NUM((long)(VpGetSign(p) * (BDIGIT_DBL_SIGNED)p->frac[0]));
760  }
761  else {
762  VALUE a = BigDecimal_split(self);
763  VALUE digits = RARRAY_AREF(a, 1);
764  VALUE numerator = rb_funcall(digits, rb_intern("to_i"), 0);
765  VALUE ret;
766  ssize_t dpower = e - (ssize_t)RSTRING_LEN(digits);
767 
768  if (BIGDECIMAL_NEGATIVE_P(p)) {
769  numerator = rb_funcall(numerator, '*', 1, INT2FIX(-1));
770  }
771  if (dpower < 0) {
772  ret = rb_funcall(numerator, rb_intern("div"), 1,
773  rb_funcall(INT2FIX(10), rb_intern("**"), 1,
774  INT2FIX(-dpower)));
775  }
776  else {
777  ret = rb_funcall(numerator, '*', 1,
778  rb_funcall(INT2FIX(10), rb_intern("**"), 1,
779  INT2FIX(dpower)));
780  }
781  if (RB_TYPE_P(ret, T_FLOAT)) {
782  rb_raise(rb_eFloatDomainError, "Infinity");
783  }
784  return ret;
785  }
786 }
787 
788 /* Returns a new Float object having approximately the same value as the
789  * BigDecimal number. Normal accuracy limits and built-in errors of binary
790  * Float arithmetic apply.
791  */
792 static VALUE
793 BigDecimal_to_f(VALUE self)
794 {
795  ENTER(1);
796  Real *p;
797  double d;
798  SIGNED_VALUE e;
799  char *buf;
800  volatile VALUE str;
801 
802  GUARD_OBJ(p, GetVpValue(self, 1));
803  if (VpVtoD(&d, &e, p) != 1)
804  return rb_float_new(d);
806  goto overflow;
808  goto underflow;
809 
810  str = rb_str_new(0, VpNumOfChars(p, "E"));
811  buf = RSTRING_PTR(str);
812  VpToString(p, buf, 0, 0);
813  errno = 0;
814  d = strtod(buf, 0);
815  if (errno == ERANGE) {
816  if (d == 0.0) goto underflow;
817  if (fabs(d) >= HUGE_VAL) goto overflow;
818  }
819  return rb_float_new(d);
820 
821 overflow:
822  VpException(VP_EXCEPTION_OVERFLOW, "BigDecimal to Float conversion", 0);
823  if (BIGDECIMAL_NEGATIVE_P(p))
825  else
827 
828 underflow:
829  VpException(VP_EXCEPTION_UNDERFLOW, "BigDecimal to Float conversion", 0);
830  if (BIGDECIMAL_NEGATIVE_P(p))
831  return rb_float_new(-0.0);
832  else
833  return rb_float_new(0.0);
834 }
835 
836 
837 /* Converts a BigDecimal to a Rational.
838  */
839 static VALUE
840 BigDecimal_to_r(VALUE self)
841 {
842  Real *p;
843  ssize_t sign, power, denomi_power;
844  VALUE a, digits, numerator;
845 
846  p = GetVpValue(self, 1);
847  BigDecimal_check_num(p);
848 
849  sign = VpGetSign(p);
850  power = VpExponent10(p);
851  a = BigDecimal_split(self);
852  digits = RARRAY_AREF(a, 1);
853  denomi_power = power - RSTRING_LEN(digits);
854  numerator = rb_funcall(digits, rb_intern("to_i"), 0);
855 
856  if (sign < 0) {
857  numerator = rb_funcall(numerator, '*', 1, INT2FIX(-1));
858  }
859  if (denomi_power < 0) {
860  return rb_Rational(numerator,
861  rb_funcall(INT2FIX(10), rb_intern("**"), 1,
862  INT2FIX(-denomi_power)));
863  }
864  else {
865  return rb_Rational1(rb_funcall(numerator, '*', 1,
866  rb_funcall(INT2FIX(10), rb_intern("**"), 1,
867  INT2FIX(denomi_power))));
868  }
869 }
870 
871 /* The coerce method provides support for Ruby type coercion. It is not
872  * enabled by default.
873  *
874  * This means that binary operations like + * / or - can often be performed
875  * on a BigDecimal and an object of another type, if the other object can
876  * be coerced into a BigDecimal value.
877  *
878  * e.g.
879  * a = BigDecimal.new("1.0")
880  * b = a / 2.0 #=> 0.5
881  *
882  * Note that coercing a String to a BigDecimal is not supported by default;
883  * it requires a special compile-time option when building Ruby.
884  */
885 static VALUE
886 BigDecimal_coerce(VALUE self, VALUE other)
887 {
888  ENTER(2);
889  VALUE obj;
890  Real *b;
891 
892  if (RB_TYPE_P(other, T_FLOAT)) {
893  GUARD_OBJ(b, GetVpValueWithPrec(other, DBL_DIG+1, 1));
894  obj = rb_assoc_new(ToValue(b), self);
895  }
896  else {
897  if (RB_TYPE_P(other, T_RATIONAL)) {
898  Real* pv = DATA_PTR(self);
899  GUARD_OBJ(b, GetVpValueWithPrec(other, pv->Prec*VpBaseFig(), 1));
900  }
901  else {
902  GUARD_OBJ(b, GetVpValue(other, 1));
903  }
904  obj = rb_assoc_new(b->obj, self);
905  }
906 
907  return obj;
908 }
909 
910 /*
911  * call-seq:
912  * +big_decimal -> big_decimal
913  *
914  * Return self.
915  *
916  * +BigDecimal('5') #=> 0.5e1
917  */
918 
919 static VALUE
920 BigDecimal_uplus(VALUE self)
921 {
922  return self;
923 }
924 
925  /*
926  * Document-method: BigDecimal#add
927  * Document-method: BigDecimal#+
928  *
929  * call-seq:
930  * add(value, digits)
931  *
932  * Add the specified value.
933  *
934  * e.g.
935  * c = a.add(b,n)
936  * c = a + b
937  *
938  * digits:: If specified and less than the number of significant digits of the
939  * result, the result is rounded to that number of digits, according
940  * to BigDecimal.mode.
941  */
942 static VALUE
943 BigDecimal_add(VALUE self, VALUE r)
944 {
945  ENTER(5);
946  Real *c, *a, *b;
947  size_t mx;
948 
949  GUARD_OBJ(a, GetVpValue(self, 1));
950  if (RB_TYPE_P(r, T_FLOAT)) {
951  b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
952  }
953  else if (RB_TYPE_P(r, T_RATIONAL)) {
954  b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
955  }
956  else {
957  b = GetVpValue(r, 0);
958  }
959 
960  if (!b) return DoSomeOne(self,r,'+');
961  SAVE(b);
962 
963  if (VpIsNaN(b)) return b->obj;
964  if (VpIsNaN(a)) return a->obj;
965 
966  mx = GetAddSubPrec(a, b);
967  if (mx == (size_t)-1L) {
968  GUARD_OBJ(c,VpCreateRbObject(VpBaseFig() + 1, "0"));
969  VpAddSub(c, a, b, 1);
970  }
971  else {
972  GUARD_OBJ(c, VpCreateRbObject(mx * (VpBaseFig() + 1), "0"));
973  if(!mx) {
974  VpSetInf(c, VpGetSign(a));
975  }
976  else {
977  VpAddSub(c, a, b, 1);
978  }
979  }
980  return ToValue(c);
981 }
982 
983  /* call-seq:
984  * a - b -> bigdecimal
985  *
986  * Subtract the specified value.
987  *
988  * e.g.
989  * c = a - b
990  *
991  * The precision of the result value depends on the type of +b+.
992  *
993  * If +b+ is a Float, the precision of the result is Float::DIG+1.
994  *
995  * If +b+ is a BigDecimal, the precision of the result is +b+'s precision of
996  * internal representation from platform. So, it's return value is platform
997  * dependent.
998  *
999  */
1000 static VALUE
1001 BigDecimal_sub(VALUE self, VALUE r)
1002 {
1003  ENTER(5);
1004  Real *c, *a, *b;
1005  size_t mx;
1006 
1007  GUARD_OBJ(a, GetVpValue(self,1));
1008  if (RB_TYPE_P(r, T_FLOAT)) {
1009  b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
1010  }
1011  else if (RB_TYPE_P(r, T_RATIONAL)) {
1012  b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
1013  }
1014  else {
1015  b = GetVpValue(r,0);
1016  }
1017 
1018  if (!b) return DoSomeOne(self,r,'-');
1019  SAVE(b);
1020 
1021  if (VpIsNaN(b)) return b->obj;
1022  if (VpIsNaN(a)) return a->obj;
1023 
1024  mx = GetAddSubPrec(a,b);
1025  if (mx == (size_t)-1L) {
1026  GUARD_OBJ(c,VpCreateRbObject(VpBaseFig() + 1, "0"));
1027  VpAddSub(c, a, b, -1);
1028  }
1029  else {
1030  GUARD_OBJ(c,VpCreateRbObject(mx *(VpBaseFig() + 1), "0"));
1031  if (!mx) {
1032  VpSetInf(c,VpGetSign(a));
1033  }
1034  else {
1035  VpAddSub(c, a, b, -1);
1036  }
1037  }
1038  return ToValue(c);
1039 }
1040 
1041 static VALUE
1042 BigDecimalCmp(VALUE self, VALUE r,char op)
1043 {
1044  ENTER(5);
1045  SIGNED_VALUE e;
1046  Real *a, *b=0;
1047  GUARD_OBJ(a, GetVpValue(self, 1));
1048  switch (TYPE(r)) {
1049  case T_DATA:
1050  if (!is_kind_of_BigDecimal(r)) break;
1051  /* fall through */
1052  case T_FIXNUM:
1053  /* fall through */
1054  case T_BIGNUM:
1055  GUARD_OBJ(b, GetVpValue(r, 0));
1056  break;
1057 
1058  case T_FLOAT:
1059  GUARD_OBJ(b, GetVpValueWithPrec(r, DBL_DIG+1, 0));
1060  break;
1061 
1062  case T_RATIONAL:
1063  GUARD_OBJ(b, GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 0));
1064  break;
1065 
1066  default:
1067  break;
1068  }
1069  if (b == NULL) {
1070  ID f = 0;
1071 
1072  switch (op) {
1073  case '*':
1074  return rb_num_coerce_cmp(self, r, rb_intern("<=>"));
1075 
1076  case '=':
1077  return RTEST(rb_num_coerce_cmp(self, r, rb_intern("=="))) ? Qtrue : Qfalse;
1078 
1079  case 'G':
1080  f = rb_intern(">=");
1081  break;
1082 
1083  case 'L':
1084  f = rb_intern("<=");
1085  break;
1086 
1087  case '>':
1088  /* fall through */
1089  case '<':
1090  f = (ID)op;
1091  break;
1092 
1093  default:
1094  break;
1095  }
1096  return rb_num_coerce_relop(self, r, f);
1097  }
1098  SAVE(b);
1099  e = VpComp(a, b);
1100  if (e == 999)
1101  return (op == '*') ? Qnil : Qfalse;
1102  switch (op) {
1103  case '*':
1104  return INT2FIX(e); /* any op */
1105 
1106  case '=':
1107  if (e == 0) return Qtrue;
1108  return Qfalse;
1109 
1110  case 'G':
1111  if (e >= 0) return Qtrue;
1112  return Qfalse;
1113 
1114  case '>':
1115  if (e > 0) return Qtrue;
1116  return Qfalse;
1117 
1118  case 'L':
1119  if (e <= 0) return Qtrue;
1120  return Qfalse;
1121 
1122  case '<':
1123  if (e < 0) return Qtrue;
1124  return Qfalse;
1125 
1126  default:
1127  break;
1128  }
1129 
1130  rb_bug("Undefined operation in BigDecimalCmp()");
1131 
1132  UNREACHABLE;
1133 }
1134 
1135 /* Returns True if the value is zero. */
1136 static VALUE
1137 BigDecimal_zero(VALUE self)
1138 {
1139  Real *a = GetVpValue(self, 1);
1140  return VpIsZero(a) ? Qtrue : Qfalse;
1141 }
1142 
1143 /* Returns self if the value is non-zero, nil otherwise. */
1144 static VALUE
1145 BigDecimal_nonzero(VALUE self)
1146 {
1147  Real *a = GetVpValue(self, 1);
1148  return VpIsZero(a) ? Qnil : self;
1149 }
1150 
1151 /* The comparison operator.
1152  * a <=> b is 0 if a == b, 1 if a > b, -1 if a < b.
1153  */
1154 static VALUE
1155 BigDecimal_comp(VALUE self, VALUE r)
1156 {
1157  return BigDecimalCmp(self, r, '*');
1158 }
1159 
1160 /*
1161  * Tests for value equality; returns true if the values are equal.
1162  *
1163  * The == and === operators and the eql? method have the same implementation
1164  * for BigDecimal.
1165  *
1166  * Values may be coerced to perform the comparison:
1167  *
1168  * BigDecimal.new('1.0') == 1.0 #=> true
1169  */
1170 static VALUE
1171 BigDecimal_eq(VALUE self, VALUE r)
1172 {
1173  return BigDecimalCmp(self, r, '=');
1174 }
1175 
1176 /* call-seq:
1177  * a < b
1178  *
1179  * Returns true if a is less than b.
1180  *
1181  * Values may be coerced to perform the comparison (see ==, BigDecimal#coerce).
1182  */
1183 static VALUE
1184 BigDecimal_lt(VALUE self, VALUE r)
1185 {
1186  return BigDecimalCmp(self, r, '<');
1187 }
1188 
1189 /* call-seq:
1190  * a <= b
1191  *
1192  * Returns true if a is less than or equal to b.
1193  *
1194  * Values may be coerced to perform the comparison (see ==, BigDecimal#coerce).
1195  */
1196 static VALUE
1197 BigDecimal_le(VALUE self, VALUE r)
1198 {
1199  return BigDecimalCmp(self, r, 'L');
1200 }
1201 
1202 /* call-seq:
1203  * a > b
1204  *
1205  * Returns true if a is greater than b.
1206  *
1207  * Values may be coerced to perform the comparison (see ==, BigDecimal#coerce).
1208  */
1209 static VALUE
1210 BigDecimal_gt(VALUE self, VALUE r)
1211 {
1212  return BigDecimalCmp(self, r, '>');
1213 }
1214 
1215 /* call-seq:
1216  * a >= b
1217  *
1218  * Returns true if a is greater than or equal to b.
1219  *
1220  * Values may be coerced to perform the comparison (see ==, BigDecimal#coerce)
1221  */
1222 static VALUE
1223 BigDecimal_ge(VALUE self, VALUE r)
1224 {
1225  return BigDecimalCmp(self, r, 'G');
1226 }
1227 
1228 /*
1229  * call-seq:
1230  * -big_decimal -> big_decimal
1231  *
1232  * Return the negation of self.
1233  *
1234  * -BigDecimal('5') #=> -0.5e1
1235  */
1236 
1237 static VALUE
1238 BigDecimal_neg(VALUE self)
1239 {
1240  ENTER(5);
1241  Real *c, *a;
1242  GUARD_OBJ(a, GetVpValue(self, 1));
1243  GUARD_OBJ(c, VpCreateRbObject(a->Prec *(VpBaseFig() + 1), "0"));
1244  VpAsgn(c, a, -1);
1245  return ToValue(c);
1246 }
1247 
1248  /*
1249  * Document-method: BigDecimal#mult
1250  *
1251  * call-seq: mult(value, digits)
1252  *
1253  * Multiply by the specified value.
1254  *
1255  * e.g.
1256  * c = a.mult(b,n)
1257  * c = a * b
1258  *
1259  * digits:: If specified and less than the number of significant digits of the
1260  * result, the result is rounded to that number of digits, according
1261  * to BigDecimal.mode.
1262  */
1263 static VALUE
1264 BigDecimal_mult(VALUE self, VALUE r)
1265 {
1266  ENTER(5);
1267  Real *c, *a, *b;
1268  size_t mx;
1269 
1270  GUARD_OBJ(a, GetVpValue(self, 1));
1271  if (RB_TYPE_P(r, T_FLOAT)) {
1272  b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
1273  }
1274  else if (RB_TYPE_P(r, T_RATIONAL)) {
1275  b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
1276  }
1277  else {
1278  b = GetVpValue(r,0);
1279  }
1280 
1281  if (!b) return DoSomeOne(self, r, '*');
1282  SAVE(b);
1283 
1284  mx = a->Prec + b->Prec;
1285  GUARD_OBJ(c, VpCreateRbObject(mx *(VpBaseFig() + 1), "0"));
1286  VpMult(c, a, b);
1287  return ToValue(c);
1288 }
1289 
1290 static VALUE
1291 BigDecimal_divide(Real **c, Real **res, Real **div, VALUE self, VALUE r)
1292 /* For c = self.div(r): with round operation */
1293 {
1294  ENTER(5);
1295  Real *a, *b;
1296  size_t mx;
1297 
1298  GUARD_OBJ(a, GetVpValue(self, 1));
1299  if (RB_TYPE_P(r, T_FLOAT)) {
1300  b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
1301  }
1302  else if (RB_TYPE_P(r, T_RATIONAL)) {
1303  b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
1304  }
1305  else {
1306  b = GetVpValue(r, 0);
1307  }
1308 
1309  if (!b) return DoSomeOne(self, r, '/');
1310  SAVE(b);
1311 
1312  *div = b;
1313  mx = a->Prec + vabs(a->exponent);
1314  if (mx < b->Prec + vabs(b->exponent)) mx = b->Prec + vabs(b->exponent);
1315  mx++; /* NOTE: An additional digit is needed for the compatibility to
1316  the version 1.2.1 and the former. */
1317  mx = (mx + 1) * VpBaseFig();
1318  GUARD_OBJ((*c), VpCreateRbObject(mx, "#0"));
1319  GUARD_OBJ((*res), VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0"));
1320  VpDivd(*c, *res, a, b);
1321  return Qnil;
1322 }
1323 
1324 /* call-seq:
1325  * a / b -> bigdecimal
1326  * quo(value) -> bigdecimal
1327  *
1328  * Divide by the specified value.
1329  *
1330  * See BigDecimal#div.
1331  */
1332 static VALUE
1333 BigDecimal_div(VALUE self, VALUE r)
1334 /* For c = self/r: with round operation */
1335 {
1336  ENTER(5);
1337  Real *c=NULL, *res=NULL, *div = NULL;
1338  r = BigDecimal_divide(&c, &res, &div, self, r);
1339  if (!NIL_P(r)) return r; /* coerced by other */
1340  SAVE(c); SAVE(res); SAVE(div);
1341  /* a/b = c + r/b */
1342  /* c xxxxx
1343  r 00000yyyyy ==> (y/b)*BASE >= HALF_BASE
1344  */
1345  /* Round */
1346  if (VpHasVal(div)) { /* frac[0] must be zero for NaN,INF,Zero */
1347  VpInternalRound(c, 0, c->frac[c->Prec-1], (BDIGIT)(VpBaseVal() * (BDIGIT_DBL)res->frac[0] / div->frac[0]));
1348  }
1349  return ToValue(c);
1350 }
1351 
1352 /*
1353  * %: mod = a%b = a - (a.to_f/b).floor * b
1354  * div = (a.to_f/b).floor
1355  */
1356 static VALUE
1357 BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
1358 {
1359  ENTER(8);
1360  Real *c=NULL, *d=NULL, *res=NULL;
1361  Real *a, *b;
1362  size_t mx;
1363 
1364  GUARD_OBJ(a, GetVpValue(self, 1));
1365  if (RB_TYPE_P(r, T_FLOAT)) {
1366  b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
1367  }
1368  else if (RB_TYPE_P(r, T_RATIONAL)) {
1369  b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
1370  }
1371  else {
1372  b = GetVpValue(r, 0);
1373  }
1374 
1375  if (!b) return Qfalse;
1376  SAVE(b);
1377 
1378  if (VpIsNaN(a) || VpIsNaN(b)) goto NaN;
1379  if (VpIsInf(a) && VpIsInf(b)) goto NaN;
1380  if (VpIsZero(b)) {
1381  rb_raise(rb_eZeroDivError, "divided by 0");
1382  }
1383  if (VpIsInf(a)) {
1384  GUARD_OBJ(d, VpCreateRbObject(1, "0"));
1385  VpSetInf(d, (SIGNED_VALUE)(VpGetSign(a) == VpGetSign(b) ? 1 : -1));
1386  GUARD_OBJ(c, VpCreateRbObject(1, "NaN"));
1387  *div = d;
1388  *mod = c;
1389  return Qtrue;
1390  }
1391  if (VpIsInf(b)) {
1392  GUARD_OBJ(d, VpCreateRbObject(1, "0"));
1393  *div = d;
1394  *mod = a;
1395  return Qtrue;
1396  }
1397  if (VpIsZero(a)) {
1398  GUARD_OBJ(c, VpCreateRbObject(1, "0"));
1399  GUARD_OBJ(d, VpCreateRbObject(1, "0"));
1400  *div = d;
1401  *mod = c;
1402  return Qtrue;
1403  }
1404 
1405  mx = a->Prec + vabs(a->exponent);
1406  if (mx<b->Prec + vabs(b->exponent)) mx = b->Prec + vabs(b->exponent);
1407  mx = (mx + 1) * VpBaseFig();
1408  GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
1409  GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0"));
1410  VpDivd(c, res, a, b);
1411  mx = c->Prec * (VpBaseFig() + 1);
1412  GUARD_OBJ(d, VpCreateRbObject(mx, "0"));
1413  VpActiveRound(d, c, VP_ROUND_DOWN, 0);
1414  VpMult(res, d, b);
1415  VpAddSub(c, a, res, -1);
1416  if (!VpIsZero(c) && (VpGetSign(a) * VpGetSign(b) < 0)) {
1417  VpAddSub(res, d, VpOne(), -1);
1418  GUARD_OBJ(d, VpCreateRbObject(GetAddSubPrec(c, b)*(VpBaseFig() + 1), "0"));
1419  VpAddSub(d, c, b, 1);
1420  *div = res;
1421  *mod = d;
1422  } else {
1423  *div = d;
1424  *mod = c;
1425  }
1426  return Qtrue;
1427 
1428 NaN:
1429  GUARD_OBJ(c, VpCreateRbObject(1, "NaN"));
1430  GUARD_OBJ(d, VpCreateRbObject(1, "NaN"));
1431  *div = d;
1432  *mod = c;
1433  return Qtrue;
1434 }
1435 
1436 /* call-seq:
1437  * a % b
1438  * a.modulo(b)
1439  *
1440  * Returns the modulus from dividing by b.
1441  *
1442  * See BigDecimal#divmod.
1443  */
1444 static VALUE
1445 BigDecimal_mod(VALUE self, VALUE r) /* %: a%b = a - (a.to_f/b).floor * b */
1446 {
1447  ENTER(3);
1448  Real *div = NULL, *mod = NULL;
1449 
1450  if (BigDecimal_DoDivmod(self, r, &div, &mod)) {
1451  SAVE(div); SAVE(mod);
1452  return ToValue(mod);
1453  }
1454  return DoSomeOne(self, r, '%');
1455 }
1456 
1457 static VALUE
1458 BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv)
1459 {
1460  ENTER(10);
1461  size_t mx;
1462  Real *a = NULL, *b = NULL, *c = NULL, *res = NULL, *d = NULL, *rr = NULL, *ff = NULL;
1463  Real *f = NULL;
1464 
1465  GUARD_OBJ(a, GetVpValue(self, 1));
1466  if (RB_TYPE_P(r, T_FLOAT)) {
1467  b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
1468  }
1469  else if (RB_TYPE_P(r, T_RATIONAL)) {
1470  b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
1471  }
1472  else {
1473  b = GetVpValue(r, 0);
1474  }
1475 
1476  if (!b) return DoSomeOne(self, r, rb_intern("remainder"));
1477  SAVE(b);
1478 
1479  mx = (a->MaxPrec + b->MaxPrec) *VpBaseFig();
1480  GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
1481  GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0"));
1482  GUARD_OBJ(rr, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0"));
1483  GUARD_OBJ(ff, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0"));
1484 
1485  VpDivd(c, res, a, b);
1486 
1487  mx = c->Prec *(VpBaseFig() + 1);
1488 
1489  GUARD_OBJ(d, VpCreateRbObject(mx, "0"));
1490  GUARD_OBJ(f, VpCreateRbObject(mx, "0"));
1491 
1492  VpActiveRound(d, c, VP_ROUND_DOWN, 0); /* 0: round off */
1493 
1494  VpFrac(f, c);
1495  VpMult(rr, f, b);
1496  VpAddSub(ff, res, rr, 1);
1497 
1498  *dv = d;
1499  *rv = ff;
1500  return Qnil;
1501 }
1502 
1503 /* call-seq:
1504  * remainder(value)
1505  *
1506  * Returns the remainder from dividing by the value.
1507  *
1508  * x.remainder(y) means x-y*(x/y).truncate
1509  */
1510 static VALUE
1511 BigDecimal_remainder(VALUE self, VALUE r) /* remainder */
1512 {
1513  VALUE f;
1514  Real *d, *rv = 0;
1515  f = BigDecimal_divremain(self, r, &d, &rv);
1516  if (!NIL_P(f)) return f;
1517  return ToValue(rv);
1518 }
1519 
1520 /* call-seq:
1521  * divmod(value)
1522  *
1523  * Divides by the specified value, and returns the quotient and modulus
1524  * as BigDecimal numbers. The quotient is rounded towards negative infinity.
1525  *
1526  * For example:
1527  *
1528  * require 'bigdecimal'
1529  *
1530  * a = BigDecimal.new("42")
1531  * b = BigDecimal.new("9")
1532  *
1533  * q, m = a.divmod(b)
1534  *
1535  * c = q * b + m
1536  *
1537  * a == c #=> true
1538  *
1539  * The quotient q is (a/b).floor, and the modulus is the amount that must be
1540  * added to q * b to get a.
1541  */
1542 static VALUE
1543 BigDecimal_divmod(VALUE self, VALUE r)
1544 {
1545  ENTER(5);
1546  Real *div = NULL, *mod = NULL;
1547 
1548  if (BigDecimal_DoDivmod(self, r, &div, &mod)) {
1549  SAVE(div); SAVE(mod);
1550  return rb_assoc_new(ToValue(div), ToValue(mod));
1551  }
1552  return DoSomeOne(self,r,rb_intern("divmod"));
1553 }
1554 
1555 /*
1556  * See BigDecimal#quo
1557  */
1558 static inline VALUE
1559 BigDecimal_div2(VALUE self, VALUE b, VALUE n)
1560 {
1561  ENTER(5);
1562  SIGNED_VALUE ix;
1563 
1564  if (NIL_P(n)) { /* div in Float sense */
1565  Real *div = NULL;
1566  Real *mod;
1567  if (BigDecimal_DoDivmod(self, b, &div, &mod)) {
1568  return BigDecimal_to_i(ToValue(div));
1569  }
1570  return DoSomeOne(self, b, rb_intern("div"));
1571  }
1572 
1573  /* div in BigDecimal sense */
1574  ix = GetPositiveInt(n);
1575  if (ix == 0) {
1576  return BigDecimal_div(self, b);
1577  }
1578  else {
1579  Real *res = NULL;
1580  Real *av = NULL, *bv = NULL, *cv = NULL;
1581  size_t mx = ix + VpBaseFig()*2;
1582  size_t pl = VpSetPrecLimit(0);
1583 
1584  GUARD_OBJ(cv, VpCreateRbObject(mx + VpBaseFig(), "0"));
1585  GUARD_OBJ(av, GetVpValue(self, 1));
1586  GUARD_OBJ(bv, GetVpValue(b, 1));
1587  mx = av->Prec + bv->Prec + 2;
1588  if (mx <= cv->MaxPrec) mx = cv->MaxPrec + 1;
1589  GUARD_OBJ(res, VpCreateRbObject((mx * 2 + 2)*VpBaseFig(), "#0"));
1590  VpDivd(cv, res, av, bv);
1591  VpSetPrecLimit(pl);
1592  VpLeftRound(cv, VpGetRoundMode(), ix);
1593  return ToValue(cv);
1594  }
1595 }
1596 
1597  /*
1598  * Document-method: BigDecimal#div
1599  *
1600  * call-seq:
1601  * div(value, digits) -> bigdecimal or integer
1602  *
1603  * Divide by the specified value.
1604  *
1605  * digits:: If specified and less than the number of significant digits of the
1606  * result, the result is rounded to that number of digits, according
1607  * to BigDecimal.mode.
1608  *
1609  * If digits is 0, the result is the same as for the / operator
1610  * or #quo.
1611  *
1612  * If digits is not specified, the result is an integer,
1613  * by analogy with Float#div; see also BigDecimal#divmod.
1614  *
1615  * Examples:
1616  *
1617  * a = BigDecimal("4")
1618  * b = BigDecimal("3")
1619  *
1620  * a.div(b, 3) # => 0.133e1
1621  *
1622  * a.div(b, 0) # => 0.1333333333333333333e1
1623  * a / b # => 0.1333333333333333333e1
1624  * a.quo(b) # => 0.1333333333333333333e1
1625  *
1626  * a.div(b) # => 1
1627  */
1628 static VALUE
1629 BigDecimal_div3(int argc, VALUE *argv, VALUE self)
1630 {
1631  VALUE b,n;
1632 
1633  rb_scan_args(argc, argv, "11", &b, &n);
1634 
1635  return BigDecimal_div2(self, b, n);
1636 }
1637 
1638 static VALUE
1639 BigDecimal_add2(VALUE self, VALUE b, VALUE n)
1640 {
1641  ENTER(2);
1642  Real *cv;
1643  SIGNED_VALUE mx = GetPositiveInt(n);
1644  if (mx == 0) return BigDecimal_add(self, b);
1645  else {
1646  size_t pl = VpSetPrecLimit(0);
1647  VALUE c = BigDecimal_add(self, b);
1648  VpSetPrecLimit(pl);
1649  GUARD_OBJ(cv, GetVpValue(c, 1));
1650  VpLeftRound(cv, VpGetRoundMode(), mx);
1651  return ToValue(cv);
1652  }
1653 }
1654 
1655 /* call-seq:
1656  * sub(value, digits) -> bigdecimal
1657  *
1658  * Subtract the specified value.
1659  *
1660  * e.g.
1661  * c = a.sub(b,n)
1662  *
1663  * digits:: If specified and less than the number of significant digits of the
1664  * result, the result is rounded to that number of digits, according
1665  * to BigDecimal.mode.
1666  *
1667  */
1668 static VALUE
1669 BigDecimal_sub2(VALUE self, VALUE b, VALUE n)
1670 {
1671  ENTER(2);
1672  Real *cv;
1673  SIGNED_VALUE mx = GetPositiveInt(n);
1674  if (mx == 0) return BigDecimal_sub(self, b);
1675  else {
1676  size_t pl = VpSetPrecLimit(0);
1677  VALUE c = BigDecimal_sub(self, b);
1678  VpSetPrecLimit(pl);
1679  GUARD_OBJ(cv, GetVpValue(c, 1));
1680  VpLeftRound(cv, VpGetRoundMode(), mx);
1681  return ToValue(cv);
1682  }
1683 }
1684 
1685 
1686 static VALUE
1687 BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
1688 {
1689  ENTER(2);
1690  Real *cv;
1691  SIGNED_VALUE mx = GetPositiveInt(n);
1692  if (mx == 0) return BigDecimal_mult(self, b);
1693  else {
1694  size_t pl = VpSetPrecLimit(0);
1695  VALUE c = BigDecimal_mult(self, b);
1696  VpSetPrecLimit(pl);
1697  GUARD_OBJ(cv, GetVpValue(c, 1));
1698  VpLeftRound(cv, VpGetRoundMode(), mx);
1699  return ToValue(cv);
1700  }
1701 }
1702 
1703 /*
1704  * call-seq:
1705  * big_decimal.abs -> big_decimal
1706  *
1707  * Returns the absolute value, as a BigDecimal.
1708  *
1709  * BigDecimal('5').abs #=> 0.5e1
1710  * BigDecimal('-3').abs #=> 0.3e1
1711  */
1712 
1713 static VALUE
1714 BigDecimal_abs(VALUE self)
1715 {
1716  ENTER(5);
1717  Real *c, *a;
1718  size_t mx;
1719 
1720  GUARD_OBJ(a, GetVpValue(self, 1));
1721  mx = a->Prec *(VpBaseFig() + 1);
1722  GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
1723  VpAsgn(c, a, 1);
1724  VpChangeSign(c, 1);
1725  return ToValue(c);
1726 }
1727 
1728 /* call-seq:
1729  * sqrt(n)
1730  *
1731  * Returns the square root of the value.
1732  *
1733  * Result has at least n significant digits.
1734  */
1735 static VALUE
1736 BigDecimal_sqrt(VALUE self, VALUE nFig)
1737 {
1738  ENTER(5);
1739  Real *c, *a;
1740  size_t mx, n;
1741 
1742  GUARD_OBJ(a, GetVpValue(self, 1));
1743  mx = a->Prec * (VpBaseFig() + 1);
1744 
1745  n = GetPositiveInt(nFig) + VpDblFig() + BASE_FIG;
1746  if (mx <= n) mx = n;
1747  GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
1748  VpSqrt(c, a);
1749  return ToValue(c);
1750 }
1751 
1752 /* Return the integer part of the number, as a BigDecimal.
1753  */
1754 static VALUE
1755 BigDecimal_fix(VALUE self)
1756 {
1757  ENTER(5);
1758  Real *c, *a;
1759  size_t mx;
1760 
1761  GUARD_OBJ(a, GetVpValue(self, 1));
1762  mx = a->Prec *(VpBaseFig() + 1);
1763  GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
1764  VpActiveRound(c, a, VP_ROUND_DOWN, 0); /* 0: round off */
1765  return ToValue(c);
1766 }
1767 
1768 /* call-seq:
1769  * round(n, mode)
1770  *
1771  * Round to the nearest integer (by default), returning the result as a
1772  * BigDecimal.
1773  *
1774  * BigDecimal('3.14159').round #=> 3
1775  * BigDecimal('8.7').round #=> 9
1776  * BigDecimal('-9.9').round #=> -10
1777  *
1778  * If n is specified and positive, the fractional part of the result has no
1779  * more than that many digits.
1780  *
1781  * If n is specified and negative, at least that many digits to the left of the
1782  * decimal point will be 0 in the result.
1783  *
1784  * BigDecimal('3.14159').round(3) #=> 3.142
1785  * BigDecimal('13345.234').round(-2) #=> 13300.0
1786  *
1787  * The value of the optional mode argument can be used to determine how
1788  * rounding is performed; see BigDecimal.mode.
1789  */
1790 static VALUE
1791 BigDecimal_round(int argc, VALUE *argv, VALUE self)
1792 {
1793  ENTER(5);
1794  Real *c, *a;
1795  int iLoc = 0;
1796  VALUE vLoc;
1797  VALUE vRound;
1798  size_t mx, pl;
1799 
1800  unsigned short sw = VpGetRoundMode();
1801 
1802  switch (rb_scan_args(argc, argv, "02", &vLoc, &vRound)) {
1803  case 0:
1804  iLoc = 0;
1805  break;
1806  case 1:
1807  if (RB_TYPE_P(vLoc, T_HASH)) {
1808  sw = check_rounding_mode_option(vLoc);
1809  }
1810  else {
1811  iLoc = NUM2INT(vLoc);
1812  }
1813  break;
1814  case 2:
1815  iLoc = NUM2INT(vLoc);
1816  if (RB_TYPE_P(vRound, T_HASH)) {
1817  sw = check_rounding_mode_option(vRound);
1818  }
1819  else {
1820  sw = check_rounding_mode(vRound);
1821  }
1822  break;
1823  default:
1824  break;
1825  }
1826 
1827  pl = VpSetPrecLimit(0);
1828  GUARD_OBJ(a, GetVpValue(self, 1));
1829  mx = a->Prec * (VpBaseFig() + 1);
1830  GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
1831  VpSetPrecLimit(pl);
1832  VpActiveRound(c, a, sw, iLoc);
1833  if (argc == 0) {
1834  return BigDecimal_to_i(ToValue(c));
1835  }
1836  return ToValue(c);
1837 }
1838 
1839 /* call-seq:
1840  * truncate(n)
1841  *
1842  * Truncate to the nearest integer (by default), returning the result as a
1843  * BigDecimal.
1844  *
1845  * BigDecimal('3.14159').truncate #=> 3
1846  * BigDecimal('8.7').truncate #=> 8
1847  * BigDecimal('-9.9').truncate #=> -9
1848  *
1849  * If n is specified and positive, the fractional part of the result has no
1850  * more than that many digits.
1851  *
1852  * If n is specified and negative, at least that many digits to the left of the
1853  * decimal point will be 0 in the result.
1854  *
1855  * BigDecimal('3.14159').truncate(3) #=> 3.141
1856  * BigDecimal('13345.234').truncate(-2) #=> 13300.0
1857  */
1858 static VALUE
1859 BigDecimal_truncate(int argc, VALUE *argv, VALUE self)
1860 {
1861  ENTER(5);
1862  Real *c, *a;
1863  int iLoc;
1864  VALUE vLoc;
1865  size_t mx, pl = VpSetPrecLimit(0);
1866 
1867  if (rb_scan_args(argc, argv, "01", &vLoc) == 0) {
1868  iLoc = 0;
1869  }
1870  else {
1871  iLoc = NUM2INT(vLoc);
1872  }
1873 
1874  GUARD_OBJ(a, GetVpValue(self, 1));
1875  mx = a->Prec * (VpBaseFig() + 1);
1876  GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
1877  VpSetPrecLimit(pl);
1878  VpActiveRound(c, a, VP_ROUND_DOWN, iLoc); /* 0: truncate */
1879  if (argc == 0) {
1880  return BigDecimal_to_i(ToValue(c));
1881  }
1882  return ToValue(c);
1883 }
1884 
1885 /* Return the fractional part of the number, as a BigDecimal.
1886  */
1887 static VALUE
1888 BigDecimal_frac(VALUE self)
1889 {
1890  ENTER(5);
1891  Real *c, *a;
1892  size_t mx;
1893 
1894  GUARD_OBJ(a, GetVpValue(self, 1));
1895  mx = a->Prec * (VpBaseFig() + 1);
1896  GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
1897  VpFrac(c, a);
1898  return ToValue(c);
1899 }
1900 
1901 /* call-seq:
1902  * floor(n)
1903  *
1904  * Return the largest integer less than or equal to the value, as a BigDecimal.
1905  *
1906  * BigDecimal('3.14159').floor #=> 3
1907  * BigDecimal('-9.1').floor #=> -10
1908  *
1909  * If n is specified and positive, the fractional part of the result has no
1910  * more than that many digits.
1911  *
1912  * If n is specified and negative, at least that
1913  * many digits to the left of the decimal point will be 0 in the result.
1914  *
1915  * BigDecimal('3.14159').floor(3) #=> 3.141
1916  * BigDecimal('13345.234').floor(-2) #=> 13300.0
1917  */
1918 static VALUE
1919 BigDecimal_floor(int argc, VALUE *argv, VALUE self)
1920 {
1921  ENTER(5);
1922  Real *c, *a;
1923  int iLoc;
1924  VALUE vLoc;
1925  size_t mx, pl = VpSetPrecLimit(0);
1926 
1927  if (rb_scan_args(argc, argv, "01", &vLoc)==0) {
1928  iLoc = 0;
1929  }
1930  else {
1931  iLoc = NUM2INT(vLoc);
1932  }
1933 
1934  GUARD_OBJ(a, GetVpValue(self, 1));
1935  mx = a->Prec * (VpBaseFig() + 1);
1936  GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
1937  VpSetPrecLimit(pl);
1938  VpActiveRound(c, a, VP_ROUND_FLOOR, iLoc);
1939 #ifdef BIGDECIMAL_DEBUG
1940  VPrint(stderr, "floor: c=%\n", c);
1941 #endif
1942  if (argc == 0) {
1943  return BigDecimal_to_i(ToValue(c));
1944  }
1945  return ToValue(c);
1946 }
1947 
1948 /* call-seq:
1949  * ceil(n)
1950  *
1951  * Return the smallest integer greater than or equal to the value, as a BigDecimal.
1952  *
1953  * BigDecimal('3.14159').ceil #=> 4
1954  * BigDecimal('-9.1').ceil #=> -9
1955  *
1956  * If n is specified and positive, the fractional part of the result has no
1957  * more than that many digits.
1958  *
1959  * If n is specified and negative, at least that
1960  * many digits to the left of the decimal point will be 0 in the result.
1961  *
1962  * BigDecimal('3.14159').ceil(3) #=> 3.142
1963  * BigDecimal('13345.234').ceil(-2) #=> 13400.0
1964  */
1965 static VALUE
1966 BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
1967 {
1968  ENTER(5);
1969  Real *c, *a;
1970  int iLoc;
1971  VALUE vLoc;
1972  size_t mx, pl = VpSetPrecLimit(0);
1973 
1974  if (rb_scan_args(argc, argv, "01", &vLoc) == 0) {
1975  iLoc = 0;
1976  } else {
1977  iLoc = NUM2INT(vLoc);
1978  }
1979 
1980  GUARD_OBJ(a, GetVpValue(self, 1));
1981  mx = a->Prec * (VpBaseFig() + 1);
1982  GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
1983  VpSetPrecLimit(pl);
1984  VpActiveRound(c, a, VP_ROUND_CEIL, iLoc);
1985  if (argc == 0) {
1986  return BigDecimal_to_i(ToValue(c));
1987  }
1988  return ToValue(c);
1989 }
1990 
1991 /* call-seq:
1992  * to_s(s)
1993  *
1994  * Converts the value to a string.
1995  *
1996  * The default format looks like 0.xxxxEnn.
1997  *
1998  * The optional parameter s consists of either an integer; or an optional '+'
1999  * or ' ', followed by an optional number, followed by an optional 'E' or 'F'.
2000  *
2001  * If there is a '+' at the start of s, positive values are returned with
2002  * a leading '+'.
2003  *
2004  * A space at the start of s returns positive values with a leading space.
2005  *
2006  * If s contains a number, a space is inserted after each group of that many
2007  * fractional digits.
2008  *
2009  * If s ends with an 'E', engineering notation (0.xxxxEnn) is used.
2010  *
2011  * If s ends with an 'F', conventional floating point notation is used.
2012  *
2013  * Examples:
2014  *
2015  * BigDecimal.new('-123.45678901234567890').to_s('5F')
2016  * #=> '-123.45678 90123 45678 9'
2017  *
2018  * BigDecimal.new('123.45678901234567890').to_s('+8F')
2019  * #=> '+123.45678901 23456789'
2020  *
2021  * BigDecimal.new('123.45678901234567890').to_s(' F')
2022  * #=> ' 123.4567890123456789'
2023  */
2024 static VALUE
2025 BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
2026 {
2027  ENTER(5);
2028  int fmt = 0; /* 0:E format */
2029  int fPlus = 0; /* =0:default,=1: set ' ' before digits ,set '+' before digits. */
2030  Real *vp;
2031  volatile VALUE str;
2032  char *psz;
2033  char ch;
2034  size_t nc, mc = 0;
2035  VALUE f;
2036 
2037  GUARD_OBJ(vp, GetVpValue(self, 1));
2038 
2039  if (rb_scan_args(argc, argv, "01", &f) == 1) {
2040  if (RB_TYPE_P(f, T_STRING)) {
2041  psz = StringValueCStr(f);
2042  rb_check_safe_obj(f);
2043  if (*psz == ' ') {
2044  fPlus = 1;
2045  psz++;
2046  }
2047  else if (*psz == '+') {
2048  fPlus = 2;
2049  psz++;
2050  }
2051  while ((ch = *psz++) != 0) {
2052  if (ISSPACE(ch)) {
2053  continue;
2054  }
2055  if (!ISDIGIT(ch)) {
2056  if (ch == 'F' || ch == 'f') {
2057  fmt = 1; /* F format */
2058  }
2059  break;
2060  }
2061  mc = mc*10 + ch - '0';
2062  }
2063  }
2064  else {
2065  mc = (size_t)GetPositiveInt(f);
2066  }
2067  }
2068  if (fmt) {
2069  nc = VpNumOfChars(vp, "F");
2070  }
2071  else {
2072  nc = VpNumOfChars(vp, "E");
2073  }
2074  if (mc > 0) {
2075  nc += (nc + mc - 1) / mc + 1;
2076  }
2077 
2078  str = rb_str_new(0, nc);
2079  psz = RSTRING_PTR(str);
2080 
2081  if (fmt) {
2082  VpToFString(vp, psz, mc, fPlus);
2083  }
2084  else {
2085  VpToString (vp, psz, mc, fPlus);
2086  }
2087  rb_str_resize(str, strlen(psz));
2088  return str;
2089 }
2090 
2091 /* Splits a BigDecimal number into four parts, returned as an array of values.
2092  *
2093  * The first value represents the sign of the BigDecimal, and is -1 or 1, or 0
2094  * if the BigDecimal is Not a Number.
2095  *
2096  * The second value is a string representing the significant digits of the
2097  * BigDecimal, with no leading zeros.
2098  *
2099  * The third value is the base used for arithmetic (currently always 10) as an
2100  * Integer.
2101  *
2102  * The fourth value is an Integer exponent.
2103  *
2104  * If the BigDecimal can be represented as 0.xxxxxx*10**n, then xxxxxx is the
2105  * string of significant digits with no leading zeros, and n is the exponent.
2106  *
2107  * From these values, you can translate a BigDecimal to a float as follows:
2108  *
2109  * sign, significant_digits, base, exponent = a.split
2110  * f = sign * "0.#{significant_digits}".to_f * (base ** exponent)
2111  *
2112  * (Note that the to_f method is provided as a more convenient way to translate
2113  * a BigDecimal to a Float.)
2114  */
2115 static VALUE
2116 BigDecimal_split(VALUE self)
2117 {
2118  ENTER(5);
2119  Real *vp;
2120  VALUE obj,str;
2121  ssize_t e, s;
2122  char *psz1;
2123 
2124  GUARD_OBJ(vp, GetVpValue(self, 1));
2125  str = rb_str_new(0, VpNumOfChars(vp, "E"));
2126  psz1 = RSTRING_PTR(str);
2127  VpSzMantissa(vp, psz1);
2128  s = 1;
2129  if(psz1[0] == '-') {
2130  size_t len = strlen(psz1 + 1);
2131 
2132  memmove(psz1, psz1 + 1, len);
2133  psz1[len] = '\0';
2134  s = -1;
2135  }
2136  if (psz1[0] == 'N') s = 0; /* NaN */
2137  e = VpExponent10(vp);
2138  obj = rb_ary_new2(4);
2139  rb_ary_push(obj, INT2FIX(s));
2140  rb_ary_push(obj, str);
2141  rb_str_resize(str, strlen(psz1));
2142  rb_ary_push(obj, INT2FIX(10));
2143  rb_ary_push(obj, INT2NUM(e));
2144  return obj;
2145 }
2146 
2147 /* Returns the exponent of the BigDecimal number, as an Integer.
2148  *
2149  * If the number can be represented as 0.xxxxxx*10**n where xxxxxx is a string
2150  * of digits with no leading zeros, then n is the exponent.
2151  */
2152 static VALUE
2153 BigDecimal_exponent(VALUE self)
2154 {
2155  ssize_t e = VpExponent10(GetVpValue(self, 1));
2156  return INT2NUM(e);
2157 }
2158 
2159 /* Returns debugging information about the value as a string of comma-separated
2160  * values in angle brackets with a leading #:
2161  *
2162  * BigDecimal.new("1234.5678").inspect
2163  * #=> "0.12345678e4"
2164  *
2165  * The first part is the address, the second is the value as a string, and
2166  * the final part ss(mm) is the current number of significant digits and the
2167  * maximum number of significant digits, respectively.
2168  */
2169 static VALUE
2170 BigDecimal_inspect(VALUE self)
2171 {
2172  ENTER(5);
2173  Real *vp;
2174  volatile VALUE str;
2175  size_t nc;
2176 
2177  GUARD_OBJ(vp, GetVpValue(self, 1));
2178  nc = VpNumOfChars(vp, "E");
2179 
2180  str = rb_str_new(0, nc);
2181  VpToString(vp, RSTRING_PTR(str), 0, 0);
2182  rb_str_resize(str, strlen(RSTRING_PTR(str)));
2183  return str;
2184 }
2185 
2186 static VALUE BigMath_s_exp(VALUE, VALUE, VALUE);
2187 static VALUE BigMath_s_log(VALUE, VALUE, VALUE);
2188 
2189 #define BigMath_exp(x, n) BigMath_s_exp(rb_mBigMath, (x), (n))
2190 #define BigMath_log(x, n) BigMath_s_log(rb_mBigMath, (x), (n))
2191 
2192 inline static int
2193 is_integer(VALUE x)
2194 {
2195  return (RB_TYPE_P(x, T_FIXNUM) || RB_TYPE_P(x, T_BIGNUM));
2196 }
2197 
2198 inline static int
2199 is_negative(VALUE x)
2200 {
2201  if (FIXNUM_P(x)) {
2202  return FIX2LONG(x) < 0;
2203  }
2204  else if (RB_TYPE_P(x, T_BIGNUM)) {
2205  return FIX2INT(rb_big_cmp(x, INT2FIX(0))) < 0;
2206  }
2207  else if (RB_TYPE_P(x, T_FLOAT)) {
2208  return RFLOAT_VALUE(x) < 0.0;
2209  }
2210  return RTEST(rb_funcall(x, '<', 1, INT2FIX(0)));
2211 }
2212 
2213 #define is_positive(x) (!is_negative(x))
2214 
2215 inline static int
2216 is_zero(VALUE x)
2217 {
2218  VALUE num;
2219 
2220  switch (TYPE(x)) {
2221  case T_FIXNUM:
2222  return FIX2LONG(x) == 0;
2223 
2224  case T_BIGNUM:
2225  return Qfalse;
2226 
2227  case T_RATIONAL:
2228  num = rb_rational_num(x);
2229  return FIXNUM_P(num) && FIX2LONG(num) == 0;
2230 
2231  default:
2232  break;
2233  }
2234 
2235  return RTEST(rb_funcall(x, id_eq, 1, INT2FIX(0)));
2236 }
2237 
2238 inline static int
2239 is_one(VALUE x)
2240 {
2241  VALUE num, den;
2242 
2243  switch (TYPE(x)) {
2244  case T_FIXNUM:
2245  return FIX2LONG(x) == 1;
2246 
2247  case T_BIGNUM:
2248  return Qfalse;
2249 
2250  case T_RATIONAL:
2251  num = rb_rational_num(x);
2252  den = rb_rational_den(x);
2253  return FIXNUM_P(den) && FIX2LONG(den) == 1 &&
2254  FIXNUM_P(num) && FIX2LONG(num) == 1;
2255 
2256  default:
2257  break;
2258  }
2259 
2260  return RTEST(rb_funcall(x, id_eq, 1, INT2FIX(1)));
2261 }
2262 
2263 inline static int
2264 is_even(VALUE x)
2265 {
2266  switch (TYPE(x)) {
2267  case T_FIXNUM:
2268  return (FIX2LONG(x) % 2) == 0;
2269 
2270  case T_BIGNUM:
2271  {
2272  unsigned long l;
2273  rb_big_pack(x, &l, 1);
2274  return l % 2 == 0;
2275  }
2276 
2277  default:
2278  break;
2279  }
2280 
2281  return 0;
2282 }
2283 
2284 static VALUE
2285 rmpd_power_by_big_decimal(Real const* x, Real const* exp, ssize_t const n)
2286 {
2287  VALUE log_x, multiplied, y;
2288  volatile VALUE obj = exp->obj;
2289 
2290  if (VpIsZero(exp)) {
2291  return ToValue(VpCreateRbObject(n, "1"));
2292  }
2293 
2294  log_x = BigMath_log(x->obj, SSIZET2NUM(n+1));
2295  multiplied = BigDecimal_mult2(exp->obj, log_x, SSIZET2NUM(n+1));
2296  y = BigMath_exp(multiplied, SSIZET2NUM(n));
2297  RB_GC_GUARD(obj);
2298 
2299  return y;
2300 }
2301 
2302 /* call-seq:
2303  * power(n)
2304  * power(n, prec)
2305  *
2306  * Returns the value raised to the power of n.
2307  *
2308  * Note that n must be an Integer.
2309  *
2310  * Also available as the operator **.
2311  */
2312 static VALUE
2313 BigDecimal_power(int argc, VALUE*argv, VALUE self)
2314 {
2315  ENTER(5);
2316  VALUE vexp, prec;
2317  Real* exp = NULL;
2318  Real *x, *y;
2319  ssize_t mp, ma, n;
2320  SIGNED_VALUE int_exp;
2321  double d;
2322 
2323  rb_scan_args(argc, argv, "11", &vexp, &prec);
2324 
2325  GUARD_OBJ(x, GetVpValue(self, 1));
2326  n = NIL_P(prec) ? (ssize_t)(x->Prec*VpBaseFig()) : NUM2SSIZET(prec);
2327 
2328  if (VpIsNaN(x)) {
2329  y = VpCreateRbObject(n, "0#");
2330  RB_GC_GUARD(y->obj);
2331  VpSetNaN(y);
2332  return ToValue(y);
2333  }
2334 
2335  retry:
2336  switch (TYPE(vexp)) {
2337  case T_FIXNUM:
2338  break;
2339 
2340  case T_BIGNUM:
2341  break;
2342 
2343  case T_FLOAT:
2344  d = RFLOAT_VALUE(vexp);
2345  if (d == round(d)) {
2346  if (FIXABLE(d)) {
2347  vexp = LONG2FIX((long)d);
2348  }
2349  else {
2350  vexp = rb_dbl2big(d);
2351  }
2352  goto retry;
2353  }
2354  exp = GetVpValueWithPrec(vexp, DBL_DIG+1, 1);
2355  break;
2356 
2357  case T_RATIONAL:
2358  if (is_zero(rb_rational_num(vexp))) {
2359  if (is_positive(vexp)) {
2360  vexp = INT2FIX(0);
2361  goto retry;
2362  }
2363  }
2364  else if (is_one(rb_rational_den(vexp))) {
2365  vexp = rb_rational_num(vexp);
2366  goto retry;
2367  }
2368  exp = GetVpValueWithPrec(vexp, n, 1);
2369  break;
2370 
2371  case T_DATA:
2372  if (is_kind_of_BigDecimal(vexp)) {
2373  VALUE zero = INT2FIX(0);
2374  VALUE rounded = BigDecimal_round(1, &zero, vexp);
2375  if (RTEST(BigDecimal_eq(vexp, rounded))) {
2376  vexp = BigDecimal_to_i(vexp);
2377  goto retry;
2378  }
2379  exp = DATA_PTR(vexp);
2380  break;
2381  }
2382  /* fall through */
2383  default:
2385  "wrong argument type %"PRIsVALUE" (expected scalar Numeric)",
2386  RB_OBJ_CLASSNAME(vexp));
2387  }
2388 
2389  if (VpIsZero(x)) {
2390  if (is_negative(vexp)) {
2391  y = VpCreateRbObject(n, "#0");
2392  RB_GC_GUARD(y->obj);
2393  if (BIGDECIMAL_NEGATIVE_P(x)) {
2394  if (is_integer(vexp)) {
2395  if (is_even(vexp)) {
2396  /* (-0) ** (-even_integer) -> Infinity */
2397  VpSetPosInf(y);
2398  }
2399  else {
2400  /* (-0) ** (-odd_integer) -> -Infinity */
2401  VpSetNegInf(y);
2402  }
2403  }
2404  else {
2405  /* (-0) ** (-non_integer) -> Infinity */
2406  VpSetPosInf(y);
2407  }
2408  }
2409  else {
2410  /* (+0) ** (-num) -> Infinity */
2411  VpSetPosInf(y);
2412  }
2413  return ToValue(y);
2414  }
2415  else if (is_zero(vexp)) {
2416  return ToValue(VpCreateRbObject(n, "1"));
2417  }
2418  else {
2419  return ToValue(VpCreateRbObject(n, "0"));
2420  }
2421  }
2422 
2423  if (is_zero(vexp)) {
2424  return ToValue(VpCreateRbObject(n, "1"));
2425  }
2426  else if (is_one(vexp)) {
2427  return self;
2428  }
2429 
2430  if (VpIsInf(x)) {
2431  if (is_negative(vexp)) {
2432  if (BIGDECIMAL_NEGATIVE_P(x)) {
2433  if (is_integer(vexp)) {
2434  if (is_even(vexp)) {
2435  /* (-Infinity) ** (-even_integer) -> +0 */
2436  return ToValue(VpCreateRbObject(n, "0"));
2437  }
2438  else {
2439  /* (-Infinity) ** (-odd_integer) -> -0 */
2440  return ToValue(VpCreateRbObject(n, "-0"));
2441  }
2442  }
2443  else {
2444  /* (-Infinity) ** (-non_integer) -> -0 */
2445  return ToValue(VpCreateRbObject(n, "-0"));
2446  }
2447  }
2448  else {
2449  return ToValue(VpCreateRbObject(n, "0"));
2450  }
2451  }
2452  else {
2453  y = VpCreateRbObject(n, "0#");
2454  if (BIGDECIMAL_NEGATIVE_P(x)) {
2455  if (is_integer(vexp)) {
2456  if (is_even(vexp)) {
2457  VpSetPosInf(y);
2458  }
2459  else {
2460  VpSetNegInf(y);
2461  }
2462  }
2463  else {
2464  /* TODO: support complex */
2466  "a non-integral exponent for a negative base");
2467  }
2468  }
2469  else {
2470  VpSetPosInf(y);
2471  }
2472  return ToValue(y);
2473  }
2474  }
2475 
2476  if (exp != NULL) {
2477  return rmpd_power_by_big_decimal(x, exp, n);
2478  }
2479  else if (RB_TYPE_P(vexp, T_BIGNUM)) {
2480  VALUE abs_value = BigDecimal_abs(self);
2481  if (is_one(abs_value)) {
2482  return ToValue(VpCreateRbObject(n, "1"));
2483  }
2484  else if (RTEST(rb_funcall(abs_value, '<', 1, INT2FIX(1)))) {
2485  if (is_negative(vexp)) {
2486  y = VpCreateRbObject(n, "0#");
2487  if (is_even(vexp)) {
2488  VpSetInf(y, VpGetSign(x));
2489  }
2490  else {
2491  VpSetInf(y, -VpGetSign(x));
2492  }
2493  return ToValue(y);
2494  }
2495  else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
2496  return ToValue(VpCreateRbObject(n, "-0"));
2497  }
2498  else {
2499  return ToValue(VpCreateRbObject(n, "0"));
2500  }
2501  }
2502  else {
2503  if (is_positive(vexp)) {
2504  y = VpCreateRbObject(n, "0#");
2505  if (is_even(vexp)) {
2506  VpSetInf(y, VpGetSign(x));
2507  }
2508  else {
2509  VpSetInf(y, -VpGetSign(x));
2510  }
2511  return ToValue(y);
2512  }
2513  else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) {
2514  return ToValue(VpCreateRbObject(n, "-0"));
2515  }
2516  else {
2517  return ToValue(VpCreateRbObject(n, "0"));
2518  }
2519  }
2520  }
2521 
2522  int_exp = FIX2LONG(vexp);
2523  ma = int_exp;
2524  if (ma < 0) ma = -ma;
2525  if (ma == 0) ma = 1;
2526 
2527  if (VpIsDef(x)) {
2528  mp = x->Prec * (VpBaseFig() + 1);
2529  GUARD_OBJ(y, VpCreateRbObject(mp * (ma + 1), "0"));
2530  }
2531  else {
2532  GUARD_OBJ(y, VpCreateRbObject(1, "0"));
2533  }
2534  VpPower(y, x, int_exp);
2535  if (!NIL_P(prec) && VpIsDef(y)) {
2536  VpMidRound(y, VpGetRoundMode(), n);
2537  }
2538  return ToValue(y);
2539 }
2540 
2541 /* call-seq:
2542  * a ** n -> bigdecimal
2543  *
2544  * Returns the value raised to the power of n.
2545  *
2546  * See BigDecimal#power.
2547  */
2548 static VALUE
2549 BigDecimal_power_op(VALUE self, VALUE exp)
2550 {
2551  return BigDecimal_power(1, &exp, self);
2552 }
2553 
2554 static VALUE
2555 BigDecimal_s_allocate(VALUE klass)
2556 {
2557  return VpNewRbClass(0, NULL, klass)->obj;
2558 }
2559 
2560 static Real *BigDecimal_new(int argc, VALUE *argv);
2561 
2562 /* call-seq:
2563  * new(initial, digits)
2564  *
2565  * Create a new BigDecimal object.
2566  *
2567  * initial:: The initial value, as an Integer, a Float, a Rational,
2568  * a BigDecimal, or a String.
2569  *
2570  * If it is a String, spaces are ignored and unrecognized characters
2571  * terminate the value.
2572  *
2573  * digits:: The number of significant digits, as an Integer. If omitted or 0,
2574  * the number of significant digits is determined from the initial
2575  * value.
2576  *
2577  * The actual number of significant digits used in computation is usually
2578  * larger than the specified number.
2579  *
2580  * ==== Exceptions
2581  *
2582  * TypeError:: If the +initial+ type is neither Integer, Float,
2583  * Rational, nor BigDecimal, this exception is raised.
2584  *
2585  * TypeError:: If the +digits+ is not an Integer, this exception is raised.
2586  *
2587  * ArgumentError:: If +initial+ is a Float, and the +digits+ is larger than
2588  * Float::DIG + 1, this exception is raised.
2589  *
2590  * ArgumentError:: If the +initial+ is a Float or Rational, and the +digits+
2591  * value is omitted, this exception is raised.
2592  */
2593 static VALUE
2594 BigDecimal_initialize(int argc, VALUE *argv, VALUE self)
2595 {
2596  ENTER(1);
2597  Real *pv = rb_check_typeddata(self, &BigDecimal_data_type);
2598  Real *x;
2599 
2600  GUARD_OBJ(x, BigDecimal_new(argc, argv));
2601  if (ToValue(x)) {
2602  pv = VpCopy(pv, x);
2603  }
2604  else {
2605  VpFree(pv);
2606  pv = x;
2607  }
2608  DATA_PTR(self) = pv;
2609  pv->obj = self;
2610  return self;
2611 }
2612 
2613 /* :nodoc:
2614  *
2615  * private method for dup and clone the provided BigDecimal +other+
2616  */
2617 static VALUE
2618 BigDecimal_initialize_copy(VALUE self, VALUE other)
2619 {
2620  Real *pv = rb_check_typeddata(self, &BigDecimal_data_type);
2621  Real *x = rb_check_typeddata(other, &BigDecimal_data_type);
2622 
2623  if (self != other) {
2624  DATA_PTR(self) = VpCopy(pv, x);
2625  }
2626  return self;
2627 }
2628 
2629 static Real *
2630 BigDecimal_new(int argc, VALUE *argv)
2631 {
2632  size_t mf;
2633  VALUE nFig;
2634  VALUE iniValue;
2635  double d;
2636 
2637  if (rb_scan_args(argc, argv, "11", &iniValue, &nFig) == 1) {
2638  mf = 0;
2639  }
2640  else {
2641  mf = GetPositiveInt(nFig);
2642  }
2643 
2644  switch (TYPE(iniValue)) {
2645  case T_DATA:
2646  if (is_kind_of_BigDecimal(iniValue)) {
2647  return DATA_PTR(iniValue);
2648  }
2649  break;
2650 
2651  case T_FIXNUM:
2652  /* fall through */
2653  case T_BIGNUM:
2654  return GetVpValue(iniValue, 1);
2655 
2656  case T_FLOAT:
2657  d = RFLOAT_VALUE(iniValue);
2658  if (!isfinite(d)) {
2659  Real *pv = VpCreateRbObject(1, NULL);
2660  VpDtoV(pv, d);
2661  return pv;
2662  }
2663  if (mf > DBL_DIG+1) {
2664  rb_raise(rb_eArgError, "precision too large.");
2665  }
2666  /* fall through */
2667  case T_RATIONAL:
2668  if (NIL_P(nFig)) {
2670  "can't omit precision for a %"PRIsVALUE".",
2671  RB_OBJ_CLASSNAME(iniValue));
2672  }
2673  return GetVpValueWithPrec(iniValue, mf, 1);
2674 
2675  case T_STRING:
2676  /* fall through */
2677  default:
2678  break;
2679  }
2680  StringValueCStr(iniValue);
2681  return VpAlloc(mf, RSTRING_PTR(iniValue));
2682 }
2683 
2684 /* See also BigDecimal.new */
2685 static VALUE
2686 BigDecimal_global_new(int argc, VALUE *argv, VALUE self)
2687 {
2688  ENTER(1);
2689  Real *pv;
2690  VALUE obj;
2691 
2692  obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0);
2693  GUARD_OBJ(pv, BigDecimal_new(argc, argv));
2694  if (ToValue(pv)) pv = VpCopy(NULL, pv);
2695  RTYPEDDATA_DATA(obj) = pv;
2696  return pv->obj = obj;
2697 }
2698 
2699  /* call-seq:
2700  * BigDecimal.limit(digits)
2701  *
2702  * Limit the number of significant digits in newly created BigDecimal
2703  * numbers to the specified value. Rounding is performed as necessary,
2704  * as specified by BigDecimal.mode.
2705  *
2706  * A limit of 0, the default, means no upper limit.
2707  *
2708  * The limit specified by this method takes less priority over any limit
2709  * specified to instance methods such as ceil, floor, truncate, or round.
2710  */
2711 static VALUE
2712 BigDecimal_limit(int argc, VALUE *argv, VALUE self)
2713 {
2714  VALUE nFig;
2715  VALUE nCur = INT2NUM(VpGetPrecLimit());
2716 
2717  if (rb_scan_args(argc, argv, "01", &nFig) == 1) {
2718  int nf;
2719  if (NIL_P(nFig)) return nCur;
2720  nf = NUM2INT(nFig);
2721  if (nf < 0) {
2722  rb_raise(rb_eArgError, "argument must be positive");
2723  }
2724  VpSetPrecLimit(nf);
2725  }
2726  return nCur;
2727 }
2728 
2729 /* Returns the sign of the value.
2730  *
2731  * Returns a positive value if > 0, a negative value if < 0, and a
2732  * zero if == 0.
2733  *
2734  * The specific value returned indicates the type and sign of the BigDecimal,
2735  * as follows:
2736  *
2737  * BigDecimal::SIGN_NaN:: value is Not a Number
2738  * BigDecimal::SIGN_POSITIVE_ZERO:: value is +0
2739  * BigDecimal::SIGN_NEGATIVE_ZERO:: value is -0
2740  * BigDecimal::SIGN_POSITIVE_INFINITE:: value is +Infinity
2741  * BigDecimal::SIGN_NEGATIVE_INFINITE:: value is -Infinity
2742  * BigDecimal::SIGN_POSITIVE_FINITE:: value is positive
2743  * BigDecimal::SIGN_NEGATIVE_FINITE:: value is negative
2744  */
2745 static VALUE
2746 BigDecimal_sign(VALUE self)
2747 { /* sign */
2748  int s = GetVpValue(self, 1)->sign;
2749  return INT2FIX(s);
2750 }
2751 
2752 /*
2753  * call-seq: BigDecimal.save_exception_mode { ... }
2754  *
2755  * Execute the provided block, but preserve the exception mode
2756  *
2757  * BigDecimal.save_exception_mode do
2758  * BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
2759  * BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
2760  *
2761  * BigDecimal.new(BigDecimal('Infinity'))
2762  * BigDecimal.new(BigDecimal('-Infinity'))
2763  * BigDecimal(BigDecimal.new('NaN'))
2764  * end
2765  *
2766  * For use with the BigDecimal::EXCEPTION_*
2767  *
2768  * See BigDecimal.mode
2769  */
2770 static VALUE
2771 BigDecimal_save_exception_mode(VALUE self)
2772 {
2773  unsigned short const exception_mode = VpGetException();
2774  int state;
2775  VALUE ret = rb_protect(rb_yield, Qnil, &state);
2776  VpSetException(exception_mode);
2777  if (state) rb_jump_tag(state);
2778  return ret;
2779 }
2780 
2781 /*
2782  * call-seq: BigDecimal.save_rounding_mode { ... }
2783  *
2784  * Execute the provided block, but preserve the rounding mode
2785  *
2786  * BigDecimal.save_rounding_mode do
2787  * BigDecimal.mode(BigDecimal::ROUND_MODE, :up)
2788  * puts BigDecimal.mode(BigDecimal::ROUND_MODE)
2789  * end
2790  *
2791  * For use with the BigDecimal::ROUND_*
2792  *
2793  * See BigDecimal.mode
2794  */
2795 static VALUE
2796 BigDecimal_save_rounding_mode(VALUE self)
2797 {
2798  unsigned short const round_mode = VpGetRoundMode();
2799  int state;
2800  VALUE ret = rb_protect(rb_yield, Qnil, &state);
2801  VpSetRoundMode(round_mode);
2802  if (state) rb_jump_tag(state);
2803  return ret;
2804 }
2805 
2806 /*
2807  * call-seq: BigDecimal.save_limit { ... }
2808  *
2809  * Execute the provided block, but preserve the precision limit
2810  *
2811  * BigDecimal.limit(100)
2812  * puts BigDecimal.limit
2813  * BigDecimal.save_limit do
2814  * BigDecimal.limit(200)
2815  * puts BigDecimal.limit
2816  * end
2817  * puts BigDecimal.limit
2818  *
2819  */
2820 static VALUE
2821 BigDecimal_save_limit(VALUE self)
2822 {
2823  size_t const limit = VpGetPrecLimit();
2824  int state;
2825  VALUE ret = rb_protect(rb_yield, Qnil, &state);
2826  VpSetPrecLimit(limit);
2827  if (state) rb_jump_tag(state);
2828  return ret;
2829 }
2830 
2831 /* call-seq:
2832  * BigMath.exp(decimal, numeric) -> BigDecimal
2833  *
2834  * Computes the value of e (the base of natural logarithms) raised to the
2835  * power of +decimal+, to the specified number of digits of precision.
2836  *
2837  * If +decimal+ is infinity, returns Infinity.
2838  *
2839  * If +decimal+ is NaN, returns NaN.
2840  */
2841 static VALUE
2842 BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
2843 {
2844  ssize_t prec, n, i;
2845  Real* vx = NULL;
2846  VALUE one, d, y;
2847  int negative = 0;
2848  int infinite = 0;
2849  int nan = 0;
2850  double flo;
2851 
2852  prec = NUM2SSIZET(vprec);
2853  if (prec <= 0) {
2854  rb_raise(rb_eArgError, "Zero or negative precision for exp");
2855  }
2856 
2857  /* TODO: the following switch statement is almost same as one in the
2858  * BigDecimalCmp function. */
2859  switch (TYPE(x)) {
2860  case T_DATA:
2861  if (!is_kind_of_BigDecimal(x)) break;
2862  vx = DATA_PTR(x);
2863  negative = BIGDECIMAL_NEGATIVE_P(vx);
2864  infinite = VpIsPosInf(vx) || VpIsNegInf(vx);
2865  nan = VpIsNaN(vx);
2866  break;
2867 
2868  case T_FIXNUM:
2869  /* fall through */
2870  case T_BIGNUM:
2871  vx = GetVpValue(x, 0);
2872  break;
2873 
2874  case T_FLOAT:
2875  flo = RFLOAT_VALUE(x);
2876  negative = flo < 0;
2877  infinite = isinf(flo);
2878  nan = isnan(flo);
2879  if (!infinite && !nan) {
2880  vx = GetVpValueWithPrec(x, DBL_DIG+1, 0);
2881  }
2882  break;
2883 
2884  case T_RATIONAL:
2885  vx = GetVpValueWithPrec(x, prec, 0);
2886  break;
2887 
2888  default:
2889  break;
2890  }
2891  if (infinite) {
2892  if (negative) {
2893  return ToValue(GetVpValueWithPrec(INT2FIX(0), prec, 1));
2894  }
2895  else {
2896  Real* vy;
2897  vy = VpCreateRbObject(prec, "#0");
2899  RB_GC_GUARD(vy->obj);
2900  return ToValue(vy);
2901  }
2902  }
2903  else if (nan) {
2904  Real* vy;
2905  vy = VpCreateRbObject(prec, "#0");
2906  VpSetNaN(vy);
2907  RB_GC_GUARD(vy->obj);
2908  return ToValue(vy);
2909  }
2910  else if (vx == NULL) {
2911  cannot_be_coerced_into_BigDecimal(rb_eArgError, x);
2912  }
2913  x = vx->obj;
2914 
2915  n = prec + rmpd_double_figures();
2916  negative = BIGDECIMAL_NEGATIVE_P(vx);
2917  if (negative) {
2918  VpSetSign(vx, 1);
2919  }
2920 
2921  one = ToValue(VpCreateRbObject(1, "1"));
2922  y = one;
2923  d = y;
2924  i = 1;
2925 
2926  while (!VpIsZero((Real*)DATA_PTR(d))) {
2927  SIGNED_VALUE const ey = VpExponent10(DATA_PTR(y));
2928  SIGNED_VALUE const ed = VpExponent10(DATA_PTR(d));
2929  ssize_t m = n - vabs(ey - ed);
2930 
2932 
2933  if (m <= 0) {
2934  break;
2935  }
2936  else if ((size_t)m < rmpd_double_figures()) {
2937  m = rmpd_double_figures();
2938  }
2939 
2940  d = BigDecimal_mult(d, x); /* d <- d * x */
2941  d = BigDecimal_div2(d, SSIZET2NUM(i), SSIZET2NUM(m)); /* d <- d / i */
2942  y = BigDecimal_add(y, d); /* y <- y + d */
2943  ++i; /* i <- i + 1 */
2944  }
2945 
2946  if (negative) {
2947  return BigDecimal_div2(one, y, vprec);
2948  }
2949  else {
2950  vprec = SSIZET2NUM(prec - VpExponent10(DATA_PTR(y)));
2951  return BigDecimal_round(1, &vprec, y);
2952  }
2953 
2954  RB_GC_GUARD(one);
2955  RB_GC_GUARD(x);
2956  RB_GC_GUARD(y);
2957  RB_GC_GUARD(d);
2958 }
2959 
2960 /* call-seq:
2961  * BigMath.log(decimal, numeric) -> BigDecimal
2962  *
2963  * Computes the natural logarithm of +decimal+ to the specified number of
2964  * digits of precision, +numeric+.
2965  *
2966  * If +decimal+ is zero or negative, raises Math::DomainError.
2967  *
2968  * If +decimal+ is positive infinity, returns Infinity.
2969  *
2970  * If +decimal+ is NaN, returns NaN.
2971  */
2972 static VALUE
2973 BigMath_s_log(VALUE klass, VALUE x, VALUE vprec)
2974 {
2975  ssize_t prec, n, i;
2976  SIGNED_VALUE expo;
2977  Real* vx = NULL;
2978  VALUE vn, one, two, w, x2, y, d;
2979  int zero = 0;
2980  int negative = 0;
2981  int infinite = 0;
2982  int nan = 0;
2983  double flo;
2984  long fix;
2985 
2986  if (!is_integer(vprec)) {
2987  rb_raise(rb_eArgError, "precision must be an Integer");
2988  }
2989 
2990  prec = NUM2SSIZET(vprec);
2991  if (prec <= 0) {
2992  rb_raise(rb_eArgError, "Zero or negative precision for exp");
2993  }
2994 
2995  /* TODO: the following switch statement is almost same as one in the
2996  * BigDecimalCmp function. */
2997  switch (TYPE(x)) {
2998  case T_DATA:
2999  if (!is_kind_of_BigDecimal(x)) break;
3000  vx = DATA_PTR(x);
3001  zero = VpIsZero(vx);
3002  negative = BIGDECIMAL_NEGATIVE_P(vx);
3003  infinite = VpIsPosInf(vx) || VpIsNegInf(vx);
3004  nan = VpIsNaN(vx);
3005  break;
3006 
3007  case T_FIXNUM:
3008  fix = FIX2LONG(x);
3009  zero = fix == 0;
3010  negative = fix < 0;
3011  goto get_vp_value;
3012 
3013  case T_BIGNUM:
3014  i = FIX2INT(rb_big_cmp(x, INT2FIX(0)));
3015  zero = i == 0;
3016  negative = i < 0;
3017 get_vp_value:
3018  if (zero || negative) break;
3019  vx = GetVpValue(x, 0);
3020  break;
3021 
3022  case T_FLOAT:
3023  flo = RFLOAT_VALUE(x);
3024  zero = flo == 0;
3025  negative = flo < 0;
3026  infinite = isinf(flo);
3027  nan = isnan(flo);
3028  if (!zero && !negative && !infinite && !nan) {
3029  vx = GetVpValueWithPrec(x, DBL_DIG+1, 1);
3030  }
3031  break;
3032 
3033  case T_RATIONAL:
3034  zero = RRATIONAL_ZERO_P(x);
3035  negative = RRATIONAL_NEGATIVE_P(x);
3036  if (zero || negative) break;
3037  vx = GetVpValueWithPrec(x, prec, 1);
3038  break;
3039 
3040  case T_COMPLEX:
3042  "Complex argument for BigMath.log");
3043 
3044  default:
3045  break;
3046  }
3047  if (infinite && !negative) {
3048  Real* vy;
3049  vy = VpCreateRbObject(prec, "#0");
3050  RB_GC_GUARD(vy->obj);
3052  return ToValue(vy);
3053  }
3054  else if (nan) {
3055  Real* vy;
3056  vy = VpCreateRbObject(prec, "#0");
3057  RB_GC_GUARD(vy->obj);
3058  VpSetNaN(vy);
3059  return ToValue(vy);
3060  }
3061  else if (zero || negative) {
3063  "Zero or negative argument for log");
3064  }
3065  else if (vx == NULL) {
3066  cannot_be_coerced_into_BigDecimal(rb_eArgError, x);
3067  }
3068  x = ToValue(vx);
3069 
3070  RB_GC_GUARD(one) = ToValue(VpCreateRbObject(1, "1"));
3071  RB_GC_GUARD(two) = ToValue(VpCreateRbObject(1, "2"));
3072 
3073  n = prec + rmpd_double_figures();
3074  RB_GC_GUARD(vn) = SSIZET2NUM(n);
3075  expo = VpExponent10(vx);
3076  if (expo < 0 || expo >= 3) {
3078  snprintf(buf, sizeof(buf), "1E%"PRIdVALUE, -expo);
3079  x = BigDecimal_mult2(x, ToValue(VpCreateRbObject(1, buf)), vn);
3080  }
3081  else {
3082  expo = 0;
3083  }
3084  w = BigDecimal_sub(x, one);
3085  x = BigDecimal_div2(w, BigDecimal_add(x, one), vn);
3086  RB_GC_GUARD(x2) = BigDecimal_mult2(x, x, vn);
3087  RB_GC_GUARD(y) = x;
3088  RB_GC_GUARD(d) = y;
3089  i = 1;
3090  while (!VpIsZero((Real*)DATA_PTR(d))) {
3091  SIGNED_VALUE const ey = VpExponent10(DATA_PTR(y));
3092  SIGNED_VALUE const ed = VpExponent10(DATA_PTR(d));
3093  ssize_t m = n - vabs(ey - ed);
3094  if (m <= 0) {
3095  break;
3096  }
3097  else if ((size_t)m < rmpd_double_figures()) {
3098  m = rmpd_double_figures();
3099  }
3100 
3101  x = BigDecimal_mult2(x2, x, vn);
3102  i += 2;
3103  d = BigDecimal_div2(x, SSIZET2NUM(i), SSIZET2NUM(m));
3104  y = BigDecimal_add(y, d);
3105  }
3106 
3107  y = BigDecimal_mult(y, two);
3108  if (expo != 0) {
3109  VALUE log10, vexpo, dy;
3110  log10 = BigMath_s_log(klass, INT2FIX(10), vprec);
3111  vexpo = ToValue(GetVpValue(SSIZET2NUM(expo), 1));
3112  dy = BigDecimal_mult(log10, vexpo);
3113  y = BigDecimal_add(y, dy);
3114  }
3115 
3116  return y;
3117 }
3118 
3119 /* Document-class: BigDecimal
3120  * BigDecimal provides arbitrary-precision floating point decimal arithmetic.
3121  *
3122  * == Introduction
3123  *
3124  * Ruby provides built-in support for arbitrary precision integer arithmetic.
3125  *
3126  * For example:
3127  *
3128  * 42**13 #=> 1265437718438866624512
3129  *
3130  * BigDecimal provides similar support for very large or very accurate floating
3131  * point numbers.
3132  *
3133  * Decimal arithmetic is also useful for general calculation, because it
3134  * provides the correct answers people expect--whereas normal binary floating
3135  * point arithmetic often introduces subtle errors because of the conversion
3136  * between base 10 and base 2.
3137  *
3138  * For example, try:
3139  *
3140  * sum = 0
3141  * 10_000.times do
3142  * sum = sum + 0.0001
3143  * end
3144  * print sum #=> 0.9999999999999062
3145  *
3146  * and contrast with the output from:
3147  *
3148  * require 'bigdecimal'
3149  *
3150  * sum = BigDecimal.new("0")
3151  * 10_000.times do
3152  * sum = sum + BigDecimal.new("0.0001")
3153  * end
3154  * print sum #=> 0.1E1
3155  *
3156  * Similarly:
3157  *
3158  * (BigDecimal.new("1.2") - BigDecimal("1.0")) == BigDecimal("0.2") #=> true
3159  *
3160  * (1.2 - 1.0) == 0.2 #=> false
3161  *
3162  * == Special features of accurate decimal arithmetic
3163  *
3164  * Because BigDecimal is more accurate than normal binary floating point
3165  * arithmetic, it requires some special values.
3166  *
3167  * === Infinity
3168  *
3169  * BigDecimal sometimes needs to return infinity, for example if you divide
3170  * a value by zero.
3171  *
3172  * BigDecimal.new("1.0") / BigDecimal.new("0.0") #=> Infinity
3173  * BigDecimal.new("-1.0") / BigDecimal.new("0.0") #=> -Infinity
3174  *
3175  * You can represent infinite numbers to BigDecimal using the strings
3176  * <code>'Infinity'</code>, <code>'+Infinity'</code> and
3177  * <code>'-Infinity'</code> (case-sensitive)
3178  *
3179  * === Not a Number
3180  *
3181  * When a computation results in an undefined value, the special value +NaN+
3182  * (for 'not a number') is returned.
3183  *
3184  * Example:
3185  *
3186  * BigDecimal.new("0.0") / BigDecimal.new("0.0") #=> NaN
3187  *
3188  * You can also create undefined values.
3189  *
3190  * NaN is never considered to be the same as any other value, even NaN itself:
3191  *
3192  * n = BigDecimal.new('NaN')
3193  * n == 0.0 #=> false
3194  * n == n #=> false
3195  *
3196  * === Positive and negative zero
3197  *
3198  * If a computation results in a value which is too small to be represented as
3199  * a BigDecimal within the currently specified limits of precision, zero must
3200  * be returned.
3201  *
3202  * If the value which is too small to be represented is negative, a BigDecimal
3203  * value of negative zero is returned.
3204  *
3205  * BigDecimal.new("1.0") / BigDecimal.new("-Infinity") #=> -0.0
3206  *
3207  * If the value is positive, a value of positive zero is returned.
3208  *
3209  * BigDecimal.new("1.0") / BigDecimal.new("Infinity") #=> 0.0
3210  *
3211  * (See BigDecimal.mode for how to specify limits of precision.)
3212  *
3213  * Note that +-0.0+ and +0.0+ are considered to be the same for the purposes of
3214  * comparison.
3215  *
3216  * Note also that in mathematics, there is no particular concept of negative
3217  * or positive zero; true mathematical zero has no sign.
3218  *
3219  * == bigdecimal/util
3220  *
3221  * When you require +bigdecimal/util+, the #to_d method will be
3222  * available on BigDecimal and the native Integer, Float, Rational,
3223  * and String classes:
3224  *
3225  * require 'bigdecimal/util'
3226  *
3227  * 42.to_d # => 0.42e2
3228  * 0.5.to_d # => 0.5e0
3229  * (2/3r).to_d(3) # => 0.667e0
3230  * "0.5".to_d # => 0.5e0
3231  *
3232  * == License
3233  *
3234  * Copyright (C) 2002 by Shigeo Kobayashi <shigeo@tinyforest.gr.jp>.
3235  *
3236  * BigDecimal is released under the Ruby and 2-clause BSD licenses.
3237  * See LICENSE.txt for details.
3238  *
3239  * Maintained by mrkn <mrkn@mrkn.jp> and ruby-core members.
3240  *
3241  * Documented by zzak <zachary@zacharyscott.net>, mathew <meta@pobox.com>, and
3242  * many other contributors.
3243  */
3244 void
3246 {
3247  VALUE arg;
3248 
3249  id_BigDecimal_exception_mode = rb_intern_const("BigDecimal.exception_mode");
3250  id_BigDecimal_rounding_mode = rb_intern_const("BigDecimal.rounding_mode");
3251  id_BigDecimal_precision_limit = rb_intern_const("BigDecimal.precision_limit");
3252 
3253  /* Initialize VP routines */
3254  VpInit(0UL);
3255 
3256  /* Class and method registration */
3257  rb_cBigDecimal = rb_define_class("BigDecimal", rb_cNumeric);
3258  rb_define_alloc_func(rb_cBigDecimal, BigDecimal_s_allocate);
3259 
3260  /* Global function */
3261  rb_define_global_function("BigDecimal", BigDecimal_global_new, -1);
3262 
3263  /* Class methods */
3264  rb_define_singleton_method(rb_cBigDecimal, "mode", BigDecimal_mode, -1);
3265  rb_define_singleton_method(rb_cBigDecimal, "limit", BigDecimal_limit, -1);
3266  rb_define_singleton_method(rb_cBigDecimal, "double_fig", BigDecimal_double_fig, 0);
3267  rb_define_singleton_method(rb_cBigDecimal, "_load", BigDecimal_load, 1);
3268  rb_define_singleton_method(rb_cBigDecimal, "ver", BigDecimal_version, 0);
3269 
3270  rb_define_singleton_method(rb_cBigDecimal, "save_exception_mode", BigDecimal_save_exception_mode, 0);
3271  rb_define_singleton_method(rb_cBigDecimal, "save_rounding_mode", BigDecimal_save_rounding_mode, 0);
3272  rb_define_singleton_method(rb_cBigDecimal, "save_limit", BigDecimal_save_limit, 0);
3273 
3274  /* Constants definition */
3275 
3276  /*
3277  * Base value used in internal calculations. On a 32 bit system, BASE
3278  * is 10000, indicating that calculation is done in groups of 4 digits.
3279  * (If it were larger, BASE**2 wouldn't fit in 32 bits, so you couldn't
3280  * guarantee that two groups could always be multiplied together without
3281  * overflow.)
3282  */
3284 
3285  /* Exceptions */
3286 
3287  /*
3288  * 0xff: Determines whether overflow, underflow or zero divide result in
3289  * an exception being thrown. See BigDecimal.mode.
3290  */
3292 
3293  /*
3294  * 0x02: Determines what happens when the result of a computation is not a
3295  * number (NaN). See BigDecimal.mode.
3296  */
3298 
3299  /*
3300  * 0x01: Determines what happens when the result of a computation is
3301  * infinity. See BigDecimal.mode.
3302  */
3304 
3305  /*
3306  * 0x04: Determines what happens when the result of a computation is an
3307  * underflow (a result too small to be represented). See BigDecimal.mode.
3308  */
3310 
3311  /*
3312  * 0x01: Determines what happens when the result of a computation is an
3313  * overflow (a result too large to be represented). See BigDecimal.mode.
3314  */
3316 
3317  /*
3318  * 0x10: Determines what happens when a division by zero is performed.
3319  * See BigDecimal.mode.
3320  */
3322 
3323  /*
3324  * 0x100: Determines what happens when a result must be rounded in order to
3325  * fit in the appropriate number of significant digits. See
3326  * BigDecimal.mode.
3327  */
3329 
3330  /* 1: Indicates that values should be rounded away from zero. See
3331  * BigDecimal.mode.
3332  */
3334 
3335  /* 2: Indicates that values should be rounded towards zero. See
3336  * BigDecimal.mode.
3337  */
3339 
3340  /* 3: Indicates that digits >= 5 should be rounded up, others rounded down.
3341  * See BigDecimal.mode. */
3343 
3344  /* 4: Indicates that digits >= 6 should be rounded up, others rounded down.
3345  * See BigDecimal.mode.
3346  */
3348  /* 5: Round towards +Infinity. See BigDecimal.mode. */
3350 
3351  /* 6: Round towards -Infinity. See BigDecimal.mode. */
3353 
3354  /* 7: Round towards the even neighbor. See BigDecimal.mode. */
3356 
3357  /* 0: Indicates that a value is not a number. See BigDecimal.sign. */
3359 
3360  /* 1: Indicates that a value is +0. See BigDecimal.sign. */
3362 
3363  /* -1: Indicates that a value is -0. See BigDecimal.sign. */
3365 
3366  /* 2: Indicates that a value is positive and finite. See BigDecimal.sign. */
3368 
3369  /* -2: Indicates that a value is negative and finite. See BigDecimal.sign. */
3371 
3372  /* 3: Indicates that a value is positive and infinite. See BigDecimal.sign. */
3373  rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_INFINITE", INT2FIX(VP_SIGN_POSITIVE_INFINITE));
3374 
3375  /* -3: Indicates that a value is negative and infinite. See BigDecimal.sign. */
3376  rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_INFINITE", INT2FIX(VP_SIGN_NEGATIVE_INFINITE));
3377 
3378  arg = rb_str_new2("+Infinity");
3379  /* Positive infinity value. */
3380  rb_define_const(rb_cBigDecimal, "INFINITY", BigDecimal_global_new(1, &arg, rb_cBigDecimal));
3381  arg = rb_str_new2("NaN");
3382  /* 'Not a Number' value. */
3383  rb_define_const(rb_cBigDecimal, "NAN", BigDecimal_global_new(1, &arg, rb_cBigDecimal));
3384 
3385 
3386  /* instance methods */
3387  rb_define_method(rb_cBigDecimal, "initialize", BigDecimal_initialize, -1);
3388  rb_define_method(rb_cBigDecimal, "initialize_copy", BigDecimal_initialize_copy, 1);
3389  rb_define_method(rb_cBigDecimal, "precs", BigDecimal_prec, 0);
3390 
3391  rb_define_method(rb_cBigDecimal, "add", BigDecimal_add2, 2);
3392  rb_define_method(rb_cBigDecimal, "sub", BigDecimal_sub2, 2);
3393  rb_define_method(rb_cBigDecimal, "mult", BigDecimal_mult2, 2);
3394  rb_define_method(rb_cBigDecimal, "div", BigDecimal_div3, -1);
3395  rb_define_method(rb_cBigDecimal, "hash", BigDecimal_hash, 0);
3396  rb_define_method(rb_cBigDecimal, "to_s", BigDecimal_to_s, -1);
3397  rb_define_method(rb_cBigDecimal, "to_i", BigDecimal_to_i, 0);
3398  rb_define_method(rb_cBigDecimal, "to_int", BigDecimal_to_i, 0);
3399  rb_define_method(rb_cBigDecimal, "to_r", BigDecimal_to_r, 0);
3400  rb_define_method(rb_cBigDecimal, "split", BigDecimal_split, 0);
3401  rb_define_method(rb_cBigDecimal, "+", BigDecimal_add, 1);
3402  rb_define_method(rb_cBigDecimal, "-", BigDecimal_sub, 1);
3403  rb_define_method(rb_cBigDecimal, "+@", BigDecimal_uplus, 0);
3404  rb_define_method(rb_cBigDecimal, "-@", BigDecimal_neg, 0);
3405  rb_define_method(rb_cBigDecimal, "*", BigDecimal_mult, 1);
3406  rb_define_method(rb_cBigDecimal, "/", BigDecimal_div, 1);
3407  rb_define_method(rb_cBigDecimal, "quo", BigDecimal_div, 1);
3408  rb_define_method(rb_cBigDecimal, "%", BigDecimal_mod, 1);
3409  rb_define_method(rb_cBigDecimal, "modulo", BigDecimal_mod, 1);
3410  rb_define_method(rb_cBigDecimal, "remainder", BigDecimal_remainder, 1);
3411  rb_define_method(rb_cBigDecimal, "divmod", BigDecimal_divmod, 1);
3412  /* rb_define_method(rb_cBigDecimal, "dup", BigDecimal_dup, 0); */
3413  rb_define_method(rb_cBigDecimal, "to_f", BigDecimal_to_f, 0);
3414  rb_define_method(rb_cBigDecimal, "abs", BigDecimal_abs, 0);
3415  rb_define_method(rb_cBigDecimal, "sqrt", BigDecimal_sqrt, 1);
3416  rb_define_method(rb_cBigDecimal, "fix", BigDecimal_fix, 0);
3417  rb_define_method(rb_cBigDecimal, "round", BigDecimal_round, -1);
3418  rb_define_method(rb_cBigDecimal, "frac", BigDecimal_frac, 0);
3419  rb_define_method(rb_cBigDecimal, "floor", BigDecimal_floor, -1);
3420  rb_define_method(rb_cBigDecimal, "ceil", BigDecimal_ceil, -1);
3421  rb_define_method(rb_cBigDecimal, "power", BigDecimal_power, -1);
3422  rb_define_method(rb_cBigDecimal, "**", BigDecimal_power_op, 1);
3423  rb_define_method(rb_cBigDecimal, "<=>", BigDecimal_comp, 1);
3424  rb_define_method(rb_cBigDecimal, "==", BigDecimal_eq, 1);
3425  rb_define_method(rb_cBigDecimal, "===", BigDecimal_eq, 1);
3426  rb_define_method(rb_cBigDecimal, "eql?", BigDecimal_eq, 1);
3427  rb_define_method(rb_cBigDecimal, "<", BigDecimal_lt, 1);
3428  rb_define_method(rb_cBigDecimal, "<=", BigDecimal_le, 1);
3429  rb_define_method(rb_cBigDecimal, ">", BigDecimal_gt, 1);
3430  rb_define_method(rb_cBigDecimal, ">=", BigDecimal_ge, 1);
3431  rb_define_method(rb_cBigDecimal, "zero?", BigDecimal_zero, 0);
3432  rb_define_method(rb_cBigDecimal, "nonzero?", BigDecimal_nonzero, 0);
3433  rb_define_method(rb_cBigDecimal, "coerce", BigDecimal_coerce, 1);
3434  rb_define_method(rb_cBigDecimal, "inspect", BigDecimal_inspect, 0);
3435  rb_define_method(rb_cBigDecimal, "exponent", BigDecimal_exponent, 0);
3436  rb_define_method(rb_cBigDecimal, "sign", BigDecimal_sign, 0);
3437  rb_define_method(rb_cBigDecimal, "nan?", BigDecimal_IsNaN, 0);
3438  rb_define_method(rb_cBigDecimal, "infinite?", BigDecimal_IsInfinite, 0);
3439  rb_define_method(rb_cBigDecimal, "finite?", BigDecimal_IsFinite, 0);
3440  rb_define_method(rb_cBigDecimal, "truncate", BigDecimal_truncate, -1);
3441  rb_define_method(rb_cBigDecimal, "_dump", BigDecimal_dump, -1);
3442 
3443  rb_mBigMath = rb_define_module("BigMath");
3444  rb_define_singleton_method(rb_mBigMath, "exp", BigMath_s_exp, 2);
3445  rb_define_singleton_method(rb_mBigMath, "log", BigMath_s_log, 2);
3446 
3447  id_up = rb_intern_const("up");
3448  id_down = rb_intern_const("down");
3449  id_truncate = rb_intern_const("truncate");
3450  id_half_up = rb_intern_const("half_up");
3451  id_default = rb_intern_const("default");
3452  id_half_down = rb_intern_const("half_down");
3453  id_half_even = rb_intern_const("half_even");
3454  id_banker = rb_intern_const("banker");
3455  id_ceiling = rb_intern_const("ceiling");
3456  id_ceil = rb_intern_const("ceil");
3457  id_floor = rb_intern_const("floor");
3458  id_to_r = rb_intern_const("to_r");
3459  id_eq = rb_intern_const("==");
3460  id_half = rb_intern_const("half");
3461 }
3462 
3463 /*
3464  *
3465  * ============================================================================
3466  *
3467  * vp_ routines begin from here.
3468  *
3469  * ============================================================================
3470  *
3471  */
3472 #ifdef BIGDECIMAL_DEBUG
3473 static int gfDebug = 1; /* Debug switch */
3474 #if 0
3475 static int gfCheckVal = 1; /* Value checking flag in VpNmlz() */
3476 #endif
3477 #endif /* BIGDECIMAL_DEBUG */
3478 
3479 static Real *VpConstOne; /* constant 1.0 */
3480 static Real *VpPt5; /* constant 0.5 */
3481 #define maxnr 100UL /* Maximum iterations for calculating sqrt. */
3482  /* used in VpSqrt() */
3483 
3484 /* ETC */
3485 #define MemCmp(x,y,z) memcmp(x,y,z)
3486 #define StrCmp(x,y) strcmp(x,y)
3487 
3488 enum op_sw {
3489  OP_SW_ADD = 1, /* + */
3490  OP_SW_SUB, /* - */
3491  OP_SW_MULT, /* * */
3492  OP_SW_DIV /* / */
3493 };
3494 
3495 static int VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw);
3496 static int AddExponent(Real *a, SIGNED_VALUE n);
3497 static BDIGIT VpAddAbs(Real *a,Real *b,Real *c);
3498 static BDIGIT VpSubAbs(Real *a,Real *b,Real *c);
3499 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);
3500 static int VpNmlz(Real *a);
3501 static void VpFormatSt(char *psz, size_t fFmt);
3502 static int VpRdup(Real *m, size_t ind_m);
3503 
3504 #ifdef BIGDECIMAL_DEBUG
3505 static int gnAlloc = 0; /* Memory allocation counter */
3506 #endif /* BIGDECIMAL_DEBUG */
3507 
3508 VP_EXPORT void *
3509 VpMemAlloc(size_t mb)
3510 {
3511  void *p = xmalloc(mb);
3512  if (!p) {
3513  VpException(VP_EXCEPTION_MEMORY, "failed to allocate memory", 1);
3514  }
3515  memset(p, 0, mb);
3516 #ifdef BIGDECIMAL_DEBUG
3517  gnAlloc++; /* Count allocation call */
3518 #endif /* BIGDECIMAL_DEBUG */
3519  return p;
3520 }
3521 
3522 VP_EXPORT void *
3523 VpMemRealloc(void *ptr, size_t mb)
3524 {
3525  void *p = xrealloc(ptr, mb);
3526  if (!p) {
3527  VpException(VP_EXCEPTION_MEMORY, "failed to allocate memory", 1);
3528  }
3529  return p;
3530 }
3531 
3532 VP_EXPORT void
3534 {
3535  if (pv != NULL) {
3536  xfree(pv);
3537 #ifdef BIGDECIMAL_DEBUG
3538  gnAlloc--; /* Decrement allocation count */
3539  if (gnAlloc == 0) {
3540  printf(" *************** All memories allocated freed ****************\n");
3541  /*getchar();*/
3542  }
3543  if (gnAlloc < 0) {
3544  printf(" ??????????? Too many memory free calls(%d) ?????????????\n", gnAlloc);
3545  /*getchar();*/
3546  }
3547 #endif /* BIGDECIMAL_DEBUG */
3548  }
3549 }
3550 
3551 /*
3552  * EXCEPTION Handling.
3553  */
3554 
3555 #define rmpd_set_thread_local_exception_mode(mode) \
3556  rb_thread_local_aset( \
3557  rb_thread_current(), \
3558  id_BigDecimal_exception_mode, \
3559  INT2FIX((int)(mode)) \
3560  )
3561 
3562 static unsigned short
3563 VpGetException (void)
3564 {
3565  VALUE const vmode = rb_thread_local_aref(
3567  id_BigDecimal_exception_mode
3568  );
3569 
3570  if (NIL_P(vmode)) {
3573  }
3574 
3575  return NUM2USHORT(vmode);
3576 }
3577 
3578 static void
3579 VpSetException(unsigned short f)
3580 {
3582 }
3583 
3584 /*
3585  * Precision limit.
3586  */
3587 
3588 #define rmpd_set_thread_local_precision_limit(limit) \
3589  rb_thread_local_aset( \
3590  rb_thread_current(), \
3591  id_BigDecimal_precision_limit, \
3592  SIZET2NUM(limit) \
3593  )
3594 #define RMPD_PRECISION_LIMIT_DEFAULT ((size_t)0)
3595 
3596 /* These 2 functions added at v1.1.7 */
3597 VP_EXPORT size_t
3599 {
3600  VALUE const vlimit = rb_thread_local_aref(
3602  id_BigDecimal_precision_limit
3603  );
3604 
3605  if (NIL_P(vlimit)) {
3608  }
3609 
3610  return NUM2SIZET(vlimit);
3611 }
3612 
3613 VP_EXPORT size_t
3615 {
3616  size_t const s = VpGetPrecLimit();
3618  return s;
3619 }
3620 
3621 /*
3622  * Rounding mode.
3623  */
3624 
3625 #define rmpd_set_thread_local_rounding_mode(mode) \
3626  rb_thread_local_aset( \
3627  rb_thread_current(), \
3628  id_BigDecimal_rounding_mode, \
3629  INT2FIX((int)(mode)) \
3630  )
3631 
3632 VP_EXPORT unsigned short
3634 {
3635  VALUE const vmode = rb_thread_local_aref(
3637  id_BigDecimal_rounding_mode
3638  );
3639 
3640  if (NIL_P(vmode)) {
3643  }
3644 
3645  return NUM2USHORT(vmode);
3646 }
3647 
3648 VP_EXPORT int
3649 VpIsRoundMode(unsigned short n)
3650 {
3651  switch (n) {
3652  case VP_ROUND_UP:
3653  case VP_ROUND_DOWN:
3654  case VP_ROUND_HALF_UP:
3655  case VP_ROUND_HALF_DOWN:
3656  case VP_ROUND_CEIL:
3657  case VP_ROUND_FLOOR:
3658  case VP_ROUND_HALF_EVEN:
3659  return 1;
3660 
3661  default:
3662  return 0;
3663  }
3664 }
3665 
3666 VP_EXPORT unsigned short
3667 VpSetRoundMode(unsigned short n)
3668 {
3669  if (VpIsRoundMode(n)) {
3671  return n;
3672  }
3673 
3674  return VpGetRoundMode();
3675 }
3676 
3677 /*
3678  * 0.0 & 1.0 generator
3679  * These gZero_..... and gOne_..... can be any name
3680  * referenced from nowhere except Zero() and One().
3681  * gZero_..... and gOne_..... must have global scope
3682  * (to let the compiler know they may be changed in outside
3683  * (... but not actually..)).
3684  */
3685 volatile const double gZero_ABCED9B1_CE73__00400511F31D = 0.0;
3686 volatile const double gOne_ABCED9B4_CE73__00400511F31D = 1.0;
3687 static double
3688 Zero(void)
3689 {
3691 }
3692 
3693 static double
3694 One(void)
3695 {
3697 }
3698 
3699 /*
3700  ----------------------------------------------------------------
3701  Value of sign in Real structure is reserved for future use.
3702  short sign;
3703  ==0 : NaN
3704  1 : Positive zero
3705  -1 : Negative zero
3706  2 : Positive number
3707  -2 : Negative number
3708  3 : Positive infinite number
3709  -3 : Negative infinite number
3710  ----------------------------------------------------------------
3711 */
3712 
3713 VP_EXPORT double
3714 VpGetDoubleNaN(void) /* Returns the value of NaN */
3715 {
3716  static double fNaN = 0.0;
3717  if (fNaN == 0.0) fNaN = Zero()/Zero();
3718  return fNaN;
3719 }
3720 
3721 VP_EXPORT double
3722 VpGetDoublePosInf(void) /* Returns the value of +Infinity */
3723 {
3724  static double fInf = 0.0;
3725  if (fInf == 0.0) fInf = One()/Zero();
3726  return fInf;
3727 }
3728 
3729 VP_EXPORT double
3730 VpGetDoubleNegInf(void) /* Returns the value of -Infinity */
3731 {
3732  static double fInf = 0.0;
3733  if (fInf == 0.0) fInf = -(One()/Zero());
3734  return fInf;
3735 }
3736 
3737 VP_EXPORT double
3738 VpGetDoubleNegZero(void) /* Returns the value of -0 */
3739 {
3740  static double nzero = 1000.0;
3741  if (nzero != 0.0) nzero = (One()/VpGetDoubleNegInf());
3742  return nzero;
3743 }
3744 
3745 #if 0 /* unused */
3746 VP_EXPORT int
3747 VpIsNegDoubleZero(double v)
3748 {
3749  double z = VpGetDoubleNegZero();
3750  return MemCmp(&v,&z,sizeof(v))==0;
3751 }
3752 #endif
3753 
3754 VP_EXPORT int
3755 VpException(unsigned short f, const char *str,int always)
3756 {
3757  unsigned short const exception_mode = VpGetException();
3758 
3759  if (f == VP_EXCEPTION_OP || f == VP_EXCEPTION_MEMORY) always = 1;
3760 
3761  if (always || (exception_mode & f)) {
3762  switch(f) {
3763  /* case VP_EXCEPTION_OVERFLOW: */
3765  case VP_EXCEPTION_INFINITY:
3766  case VP_EXCEPTION_NaN:
3768  case VP_EXCEPTION_OP:
3769  rb_raise(rb_eFloatDomainError, "%s", str);
3770  break;
3771  case VP_EXCEPTION_MEMORY:
3772  default:
3773  rb_fatal("%s", str);
3774  }
3775  }
3776  return 0; /* 0 Means VpException() raised no exception */
3777 }
3778 
3779 /* Throw exception or returns 0,when resulting c is Inf or NaN */
3780 /* sw=1:+ 2:- 3:* 4:/ */
3781 static int
3782 VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw)
3783 {
3784  if (VpIsNaN(a) || VpIsNaN(b)) {
3785  /* at least a or b is NaN */
3786  VpSetNaN(c);
3787  goto NaN;
3788  }
3789 
3790  if (VpIsInf(a)) {
3791  if (VpIsInf(b)) {
3792  switch(sw) {
3793  case OP_SW_ADD: /* + */
3794  if (VpGetSign(a) == VpGetSign(b)) {
3795  VpSetInf(c, VpGetSign(a));
3796  goto Inf;
3797  }
3798  else {
3799  VpSetNaN(c);
3800  goto NaN;
3801  }
3802  case OP_SW_SUB: /* - */
3803  if (VpGetSign(a) != VpGetSign(b)) {
3804  VpSetInf(c, VpGetSign(a));
3805  goto Inf;
3806  }
3807  else {
3808  VpSetNaN(c);
3809  goto NaN;
3810  }
3811  case OP_SW_MULT: /* * */
3812  VpSetInf(c, VpGetSign(a)*VpGetSign(b));
3813  goto Inf;
3814  case OP_SW_DIV: /* / */
3815  VpSetNaN(c);
3816  goto NaN;
3817  }
3818  VpSetNaN(c);
3819  goto NaN;
3820  }
3821  /* Inf op Finite */
3822  switch(sw) {
3823  case OP_SW_ADD: /* + */
3824  case OP_SW_SUB: /* - */
3825  VpSetInf(c, VpGetSign(a));
3826  break;
3827  case OP_SW_MULT: /* * */
3828  if (VpIsZero(b)) {
3829  VpSetNaN(c);
3830  goto NaN;
3831  }
3832  VpSetInf(c, VpGetSign(a)*VpGetSign(b));
3833  break;
3834  case OP_SW_DIV: /* / */
3835  VpSetInf(c, VpGetSign(a)*VpGetSign(b));
3836  }
3837  goto Inf;
3838  }
3839 
3840  if (VpIsInf(b)) {
3841  switch(sw) {
3842  case OP_SW_ADD: /* + */
3843  VpSetInf(c, VpGetSign(b));
3844  break;
3845  case OP_SW_SUB: /* - */
3846  VpSetInf(c, -VpGetSign(b));
3847  break;
3848  case OP_SW_MULT: /* * */
3849  if (VpIsZero(a)) {
3850  VpSetNaN(c);
3851  goto NaN;
3852  }
3853  VpSetInf(c, VpGetSign(a)*VpGetSign(b));
3854  break;
3855  case OP_SW_DIV: /* / */
3856  VpSetZero(c, VpGetSign(a)*VpGetSign(b));
3857  }
3858  goto Inf;
3859  }
3860  return 1; /* Results OK */
3861 
3862 Inf:
3863  if (VpIsPosInf(c)) {
3864  return VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 0);
3865  }
3866  else {
3867  return VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 0);
3868  }
3869 
3870 NaN:
3871  return VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'", 0);
3872 }
3873 
3874 /*
3875  ----------------------------------------------------------------
3876 */
3877 
3878 /*
3879  * returns number of chars needed to represent vp in specified format.
3880  */
3881 VP_EXPORT size_t
3882 VpNumOfChars(Real *vp,const char *pszFmt)
3883 {
3884  SIGNED_VALUE ex;
3885  size_t nc;
3886 
3887  if (vp == NULL) return BASE_FIG*2+6;
3888  if (!VpIsDef(vp)) return 32; /* not sure,may be OK */
3889 
3890  switch(*pszFmt) {
3891  case 'F':
3892  nc = BASE_FIG*(vp->Prec + 1)+2;
3893  ex = vp->exponent;
3894  if (ex < 0) {
3895  nc += BASE_FIG*(size_t)(-ex);
3896  }
3897  else {
3898  if ((size_t)ex > vp->Prec) {
3899  nc += BASE_FIG*((size_t)ex - vp->Prec);
3900  }
3901  }
3902  break;
3903  case 'E':
3904  /* fall through */
3905  default:
3906  nc = BASE_FIG*(vp->Prec + 2)+6; /* 3: sign + exponent chars */
3907  }
3908  return nc;
3909 }
3910 
3911 /*
3912  * Initializer for Vp routines and constants used.
3913  * [Input]
3914  * BaseVal: Base value(assigned to BASE) for Vp calculation.
3915  * It must be the form BaseVal=10**n.(n=1,2,3,...)
3916  * If Base <= 0L,then the BASE will be calculated so
3917  * that BASE is as large as possible satisfying the
3918  * relation MaxVal <= BASE*(BASE+1). Where the value
3919  * MaxVal is the largest value which can be represented
3920  * by one BDIGIT word in the computer used.
3921  *
3922  * [Returns]
3923  * 1+DBL_DIG ... OK
3924  */
3925 VP_EXPORT size_t
3926 VpInit(BDIGIT BaseVal)
3927 {
3928  /* Setup +/- Inf NaN -0 */
3929  VpGetDoubleNaN();
3933 
3934  /* Allocates Vp constants. */
3935  VpConstOne = VpAlloc(1UL, "1");
3936  VpPt5 = VpAlloc(1UL, ".5");
3937 
3938 #ifdef BIGDECIMAL_DEBUG
3939  gnAlloc = 0;
3940 #endif /* BIGDECIMAL_DEBUG */
3941 
3942 #ifdef BIGDECIMAL_DEBUG
3943  if (gfDebug) {
3944  printf("VpInit: BaseVal = %"PRIuBDIGIT"\n", BaseVal);
3945  printf("\tBASE = %"PRIuBDIGIT"\n", BASE);
3946  printf("\tHALF_BASE = %"PRIuBDIGIT"\n", HALF_BASE);
3947  printf("\tBASE1 = %"PRIuBDIGIT"\n", BASE1);
3948  printf("\tBASE_FIG = %u\n", BASE_FIG);
3949  printf("\tDBLE_FIG = %d\n", DBLE_FIG);
3950  }
3951 #endif /* BIGDECIMAL_DEBUG */
3952 
3953  return rmpd_double_figures();
3954 }
3955 
3956 VP_EXPORT Real *
3957 VpOne(void)
3958 {
3959  return VpConstOne;
3960 }
3961 
3962 /* If exponent overflows,then raise exception or returns 0 */
3963 static int
3964 AddExponent(Real *a, SIGNED_VALUE n)
3965 {
3966  SIGNED_VALUE e = a->exponent;
3967  SIGNED_VALUE m = e+n;
3968  SIGNED_VALUE eb, mb;
3969  if (e > 0) {
3970  if (n > 0) {
3973  goto overflow;
3974  mb = m*(SIGNED_VALUE)BASE_FIG;
3975  eb = e*(SIGNED_VALUE)BASE_FIG;
3976  if (eb - mb > 0) goto overflow;
3977  }
3978  }
3979  else if (n < 0) {
3982  goto underflow;
3983  mb = m*(SIGNED_VALUE)BASE_FIG;
3984  eb = e*(SIGNED_VALUE)BASE_FIG;
3985  if (mb - eb > 0) goto underflow;
3986  }
3987  a->exponent = m;
3988  return 1;
3989 
3990 /* Overflow/Underflow ==> Raise exception or returns 0 */
3991 underflow:
3992  VpSetZero(a, VpGetSign(a));
3993  return VpException(VP_EXCEPTION_UNDERFLOW, "Exponent underflow", 0);
3994 
3995 overflow:
3996  VpSetInf(a, VpGetSign(a));
3997  return VpException(VP_EXCEPTION_OVERFLOW, "Exponent overflow", 0);
3998 }
3999 
4000 /*
4001  * Allocates variable.
4002  * [Input]
4003  * mx ... allocation unit, if zero then mx is determined by szVal.
4004  * The mx is the number of effective digits can to be stored.
4005  * szVal ... value assigned(char). If szVal==NULL,then zero is assumed.
4006  * If szVal[0]=='#' then Max. Prec. will not be considered(1.1.7),
4007  * full precision specified by szVal is allocated.
4008  *
4009  * [Returns]
4010  * Pointer to the newly allocated variable, or
4011  * NULL be returned if memory allocation is failed,or any error.
4012  */
4013 VP_EXPORT Real *
4014 VpAlloc(size_t mx, const char *szVal)
4015 {
4016  const char *orig_szVal = szVal;
4017  size_t i, ni, ipn, ipf, nf, ipe, ne, dot_seen, exp_seen, nalloc;
4018  char v, *psz;
4019  int sign=1;
4020  Real *vp = NULL;
4021  size_t mf = VpGetPrecLimit();
4022  VALUE buf;
4023 
4024  mx = (mx + BASE_FIG - 1) / BASE_FIG; /* Determine allocation unit. */
4025  if (mx == 0) ++mx;
4026 
4027  if (szVal) {
4028  while (ISSPACE(*szVal)) szVal++;
4029  if (*szVal != '#') {
4030  if (mf) {
4031  mf = (mf + BASE_FIG - 1) / BASE_FIG + 2; /* Needs 1 more for div */
4032  if (mx > mf) {
4033  mx = mf;
4034  }
4035  }
4036  }
4037  else {
4038  ++szVal;
4039  }
4040  }
4041  else {
4042  /* necessary to be able to store */
4043  /* at least mx digits. */
4044  /* szVal==NULL ==> allocate zero value. */
4045  vp = VpAllocReal(mx);
4046  /* xmalloc() alway returns(or throw interruption) */
4047  vp->MaxPrec = mx; /* set max precision */
4048  VpSetZero(vp, 1); /* initialize vp to zero. */
4049  return vp;
4050  }
4051 
4052  /* Skip all '_' after digit: 2006-6-30 */
4053  ni = 0;
4054  buf = rb_str_tmp_new(strlen(szVal) + 1);
4055  psz = RSTRING_PTR(buf);
4056  i = 0;
4057  ipn = 0;
4058  while ((psz[i] = szVal[ipn]) != 0) {
4059  if (ISSPACE(psz[i])) {
4060  psz[i] = 0;
4061  break;
4062  }
4063  if (ISDIGIT(psz[i])) ++ni;
4064  if (psz[i] == '_') {
4065  if (ni > 0) {
4066  ipn++;
4067  continue;
4068  }
4069  psz[i] = 0;
4070  break;
4071  }
4072  ++i;
4073  ++ipn;
4074  }
4075  szVal = psz;
4076 
4077  /* Check on Inf & NaN */
4078  if (StrCmp(szVal, SZ_PINF) == 0 || StrCmp(szVal, SZ_INF) == 0 ) {
4079  vp = VpAllocReal(1);
4080  vp->MaxPrec = 1; /* set max precision */
4081  VpSetPosInf(vp);
4082  return vp;
4083  }
4084  if (StrCmp(szVal, SZ_NINF) == 0) {
4085  vp = VpAllocReal(1);
4086  vp->MaxPrec = 1; /* set max precision */
4087  VpSetNegInf(vp);
4088  return vp;
4089  }
4090  if (StrCmp(szVal, SZ_NaN) == 0) {
4091  vp = VpAllocReal(1);
4092  vp->MaxPrec = 1; /* set max precision */
4093  VpSetNaN(vp);
4094  return vp;
4095  }
4096 
4097  /* check on number szVal[] */
4098  ipn = i = 0;
4099  if (szVal[i] == '-') { sign=-1; ++i; }
4100  else if (szVal[i] == '+') ++i;
4101  /* Skip digits */
4102  ni = 0; /* digits in mantissa */
4103  while ((v = szVal[i]) != 0) {
4104  if (!ISDIGIT(v)) break;
4105  ++i;
4106  ++ni;
4107  }
4108  nf = 0;
4109  ipf = 0;
4110  ipe = 0;
4111  ne = 0;
4112  dot_seen = 0;
4113  exp_seen = 0;
4114  if (v) {
4115  /* other than digit nor \0 */
4116  if (szVal[i] == '.') { /* xxx. */
4117  dot_seen = 1;
4118  ++i;
4119  ipf = i;
4120  while ((v = szVal[i]) != 0) { /* get fraction part. */
4121  if (!ISDIGIT(v)) break;
4122  ++i;
4123  ++nf;
4124  }
4125  }
4126  ipe = 0; /* Exponent */
4127 
4128  switch (szVal[i]) {
4129  case '\0':
4130  break;
4131  case 'e': case 'E':
4132  case 'd': case 'D':
4133  exp_seen = 1;
4134  ++i;
4135  ipe = i;
4136  v = szVal[i];
4137  if ((v == '-') || (v == '+')) ++i;
4138  while ((v=szVal[i]) != 0) {
4139  if (!ISDIGIT(v)) break;
4140  ++i;
4141  ++ne;
4142  }
4143  break;
4144  default:
4145  break;
4146  }
4147  }
4148  if (((ni == 0 || dot_seen) && nf == 0) || (exp_seen && ne == 0)) {
4149  VALUE str = rb_str_new2(orig_szVal);
4150  rb_raise(rb_eArgError, "invalid value for BigDecimal(): \"%"PRIsVALUE"\"", str);
4151  }
4152 
4153  nalloc = (ni + nf + BASE_FIG - 1) / BASE_FIG + 1; /* set effective allocation */
4154  /* units for szVal[] */
4155  if (mx == 0) mx = 1;
4156  nalloc = Max(nalloc, mx);
4157  mx = nalloc;
4158  vp = VpAllocReal(mx);
4159  /* xmalloc() alway returns(or throw interruption) */
4160  vp->MaxPrec = mx; /* set max precision */
4161  VpSetZero(vp, sign);
4162  VpCtoV(vp, &szVal[ipn], ni, &szVal[ipf], nf, &szVal[ipe], ne);
4163  rb_str_resize(buf, 0);
4164  return vp;
4165 }
4166 
4167 /*
4168  * Assignment(c=a).
4169  * [Input]
4170  * a ... RHSV
4171  * isw ... switch for assignment.
4172  * c = a when isw > 0
4173  * c = -a when isw < 0
4174  * if c->MaxPrec < a->Prec,then round operation
4175  * will be performed.
4176  * [Output]
4177  * c ... LHSV
4178  */
4179 VP_EXPORT size_t
4180 VpAsgn(Real *c, Real *a, int isw)
4181 {
4182  size_t n;
4183  if (VpIsNaN(a)) {
4184  VpSetNaN(c);
4185  return 0;
4186  }
4187  if (VpIsInf(a)) {
4188  VpSetInf(c, isw * VpGetSign(a));
4189  return 0;
4190  }
4191 
4192  /* check if the RHS is zero */
4193  if (!VpIsZero(a)) {
4194  c->exponent = a->exponent; /* store exponent */
4195  VpSetSign(c, isw * VpGetSign(a)); /* set sign */
4196  n = (a->Prec < c->MaxPrec) ? (a->Prec) : (c->MaxPrec);
4197  c->Prec = n;
4198  memcpy(c->frac, a->frac, n * sizeof(BDIGIT));
4199  /* Needs round ? */
4200  if (isw != 10) {
4201  /* Not in ActiveRound */
4202  if(c->Prec < a->Prec) {
4203  VpInternalRound(c, n, (n>0) ? a->frac[n-1] : 0, a->frac[n]);
4204  }
4205  else {
4206  VpLimitRound(c,0);
4207  }
4208  }
4209  }
4210  else {
4211  /* The value of 'a' is zero. */
4212  VpSetZero(c, isw * VpGetSign(a));
4213  return 1;
4214  }
4215  return c->Prec * BASE_FIG;
4216 }
4217 
4218 /*
4219  * c = a + b when operation = 1 or 2
4220  * c = a - b when operation = -1 or -2.
4221  * Returns number of significant digits of c
4222  */
4223 VP_EXPORT size_t
4224 VpAddSub(Real *c, Real *a, Real *b, int operation)
4225 {
4226  short sw, isw;
4227  Real *a_ptr, *b_ptr;
4228  size_t n, na, nb, i;
4229  BDIGIT mrv;
4230 
4231 #ifdef BIGDECIMAL_DEBUG
4232  if (gfDebug) {
4233  VPrint(stdout, "VpAddSub(enter) a=% \n", a);
4234  VPrint(stdout, " b=% \n", b);
4235  printf(" operation=%d\n", operation);
4236  }
4237 #endif /* BIGDECIMAL_DEBUG */
4238 
4239  if (!VpIsDefOP(c, a, b, (operation > 0) ? OP_SW_ADD : OP_SW_SUB)) return 0; /* No significant digits */
4240 
4241  /* check if a or b is zero */
4242  if (VpIsZero(a)) {
4243  /* a is zero,then assign b to c */
4244  if (!VpIsZero(b)) {
4245  VpAsgn(c, b, operation);
4246  }
4247  else {
4248  /* Both a and b are zero. */
4249  if (VpGetSign(a) < 0 && operation * VpGetSign(b) < 0) {
4250  /* -0 -0 */
4251  VpSetZero(c, -1);
4252  }
4253  else {
4254  VpSetZero(c, 1);
4255  }
4256  return 1; /* 0: 1 significant digits */
4257  }
4258  return c->Prec * BASE_FIG;
4259  }
4260  if (VpIsZero(b)) {
4261  /* b is zero,then assign a to c. */
4262  VpAsgn(c, a, 1);
4263  return c->Prec*BASE_FIG;
4264  }
4265 
4266  if (operation < 0) sw = -1;
4267  else sw = 1;
4268 
4269  /* compare absolute value. As a result,|a_ptr|>=|b_ptr| */
4270  if (a->exponent > b->exponent) {
4271  a_ptr = a;
4272  b_ptr = b;
4273  } /* |a|>|b| */
4274  else if (a->exponent < b->exponent) {
4275  a_ptr = b;
4276  b_ptr = a;
4277  } /* |a|<|b| */
4278  else {
4279  /* Exponent part of a and b is the same,then compare fraction */
4280  /* part */
4281  na = a->Prec;
4282  nb = b->Prec;
4283  n = Min(na, nb);
4284  for (i=0; i < n; ++i) {
4285  if (a->frac[i] > b->frac[i]) {
4286  a_ptr = a;
4287  b_ptr = b;
4288  goto end_if;
4289  }
4290  else if (a->frac[i] < b->frac[i]) {
4291  a_ptr = b;
4292  b_ptr = a;
4293  goto end_if;
4294  }
4295  }
4296  if (na > nb) {
4297  a_ptr = a;
4298  b_ptr = b;
4299  goto end_if;
4300  }
4301  else if (na < nb) {
4302  a_ptr = b;
4303  b_ptr = a;
4304  goto end_if;
4305  }
4306  /* |a| == |b| */
4307  if (VpGetSign(a) + sw *VpGetSign(b) == 0) {
4308  VpSetZero(c, 1); /* abs(a)=abs(b) and operation = '-' */
4309  return c->Prec * BASE_FIG;
4310  }
4311  a_ptr = a;
4312  b_ptr = b;
4313  }
4314 
4315 end_if:
4316  isw = VpGetSign(a) + sw *VpGetSign(b);
4317  /*
4318  * isw = 0 ...( 1)+(-1),( 1)-( 1),(-1)+(1),(-1)-(-1)
4319  * = 2 ...( 1)+( 1),( 1)-(-1)
4320  * =-2 ...(-1)+(-1),(-1)-( 1)
4321  * If isw==0, then c =(Sign a_ptr)(|a_ptr|-|b_ptr|)
4322  * else c =(Sign ofisw)(|a_ptr|+|b_ptr|)
4323  */
4324  if (isw) { /* addition */
4325  VpSetSign(c, 1);
4326  mrv = VpAddAbs(a_ptr, b_ptr, c);
4327  VpSetSign(c, isw / 2);
4328  }
4329  else { /* subtraction */
4330  VpSetSign(c, 1);
4331  mrv = VpSubAbs(a_ptr, b_ptr, c);
4332  if (a_ptr == a) {
4333  VpSetSign(c,VpGetSign(a));
4334  }
4335  else {
4336  VpSetSign(c, VpGetSign(a_ptr) * sw);
4337  }
4338  }
4339  VpInternalRound(c, 0, (c->Prec > 0) ? c->frac[c->Prec-1] : 0, mrv);
4340 
4341 #ifdef BIGDECIMAL_DEBUG
4342  if (gfDebug) {
4343  VPrint(stdout, "VpAddSub(result) c=% \n", c);
4344  VPrint(stdout, " a=% \n", a);
4345  VPrint(stdout, " b=% \n", b);
4346  printf(" operation=%d\n", operation);
4347  }
4348 #endif /* BIGDECIMAL_DEBUG */
4349  return c->Prec * BASE_FIG;
4350 }
4351 
4352 /*
4353  * Addition of two values with variable precision
4354  * a and b assuming abs(a)>abs(b).
4355  * c = abs(a) + abs(b) ; where |a|>=|b|
4356  */
4357 static BDIGIT
4358 VpAddAbs(Real *a, Real *b, Real *c)
4359 {
4360  size_t word_shift;
4361  size_t ap;
4362  size_t bp;
4363  size_t cp;
4364  size_t a_pos;
4365  size_t b_pos, b_pos_with_word_shift;
4366  size_t c_pos;
4367  BDIGIT av, bv, carry, mrv;
4368 
4369 #ifdef BIGDECIMAL_DEBUG
4370  if (gfDebug) {
4371  VPrint(stdout, "VpAddAbs called: a = %\n", a);
4372  VPrint(stdout, " b = %\n", b);
4373  }
4374 #endif /* BIGDECIMAL_DEBUG */
4375 
4376  word_shift = VpSetPTR(a, b, c, &ap, &bp, &cp, &av, &bv);
4377  a_pos = ap;
4378  b_pos = bp;
4379  c_pos = cp;
4380 
4381  if (word_shift == (size_t)-1L) return 0; /* Overflow */
4382  if (b_pos == (size_t)-1L) goto Assign_a;
4383 
4384  mrv = av + bv; /* Most right val. Used for round. */
4385 
4386  /* Just assign the last few digits of b to c because a has no */
4387  /* corresponding digits to be added. */
4388  if (b_pos > 0) {
4389  while (b_pos > 0 && b_pos + word_shift > a_pos) {
4390  c->frac[--c_pos] = b->frac[--b_pos];
4391  }
4392  }
4393  if (b_pos == 0 && word_shift > a_pos) {
4394  while (word_shift-- > a_pos) {
4395  c->frac[--c_pos] = 0;
4396  }
4397  }
4398 
4399  /* Just assign the last few digits of a to c because b has no */
4400  /* corresponding digits to be added. */
4401  b_pos_with_word_shift = b_pos + word_shift;
4402  while (a_pos > b_pos_with_word_shift) {
4403  c->frac[--c_pos] = a->frac[--a_pos];
4404  }
4405  carry = 0; /* set first carry be zero */
4406 
4407  /* Now perform addition until every digits of b will be */
4408  /* exhausted. */
4409  while (b_pos > 0) {
4410  c->frac[--c_pos] = a->frac[--a_pos] + b->frac[--b_pos] + carry;
4411  if (c->frac[c_pos] >= BASE) {
4412  c->frac[c_pos] -= BASE;
4413  carry = 1;
4414  }
4415  else {
4416  carry = 0;
4417  }
4418  }
4419 
4420  /* Just assign the first few digits of a with considering */
4421  /* the carry obtained so far because b has been exhausted. */
4422  while (a_pos > 0) {
4423  c->frac[--c_pos] = a->frac[--a_pos] + carry;
4424  if (c->frac[c_pos] >= BASE) {
4425  c->frac[c_pos] -= BASE;
4426  carry = 1;
4427  }
4428  else {
4429  carry = 0;
4430  }
4431  }
4432  if (c_pos) c->frac[c_pos - 1] += carry;
4433  goto Exit;
4434 
4435 Assign_a:
4436  VpAsgn(c, a, 1);
4437  mrv = 0;
4438 
4439 Exit:
4440 
4441 #ifdef BIGDECIMAL_DEBUG
4442  if (gfDebug) {
4443  VPrint(stdout, "VpAddAbs exit: c=% \n", c);
4444  }
4445 #endif /* BIGDECIMAL_DEBUG */
4446  return mrv;
4447 }
4448 
4449 /*
4450  * c = abs(a) - abs(b)
4451  */
4452 static BDIGIT
4453 VpSubAbs(Real *a, Real *b, Real *c)
4454 {
4455  size_t word_shift;
4456  size_t ap;
4457  size_t bp;
4458  size_t cp;
4459  size_t a_pos;
4460  size_t b_pos, b_pos_with_word_shift;
4461  size_t c_pos;
4462  BDIGIT av, bv, borrow, mrv;
4463 
4464 #ifdef BIGDECIMAL_DEBUG
4465  if (gfDebug) {
4466  VPrint(stdout, "VpSubAbs called: a = %\n", a);
4467  VPrint(stdout, " b = %\n", b);
4468  }
4469 #endif /* BIGDECIMAL_DEBUG */
4470 
4471  word_shift = VpSetPTR(a, b, c, &ap, &bp, &cp, &av, &bv);
4472  a_pos = ap;
4473  b_pos = bp;
4474  c_pos = cp;
4475  if (word_shift == (size_t)-1L) return 0; /* Overflow */
4476  if (b_pos == (size_t)-1L) goto Assign_a;
4477 
4478  if (av >= bv) {
4479  mrv = av - bv;
4480  borrow = 0;
4481  }
4482  else {
4483  mrv = 0;
4484  borrow = 1;
4485  }
4486 
4487  /* Just assign the values which are the BASE subtracted by */
4488  /* each of the last few digits of the b because the a has no */
4489  /* corresponding digits to be subtracted. */
4490  if (b_pos + word_shift > a_pos) {
4491  while (b_pos > 0 && b_pos + word_shift > a_pos) {
4492  c->frac[--c_pos] = BASE - b->frac[--b_pos] - borrow;
4493  borrow = 1;
4494  }
4495  if (b_pos == 0) {
4496  while (word_shift > a_pos) {
4497  --word_shift;
4498  c->frac[--c_pos] = BASE - borrow;
4499  borrow = 1;
4500  }
4501  }
4502  }
4503  /* Just assign the last few digits of a to c because b has no */
4504  /* corresponding digits to subtract. */
4505 
4506  b_pos_with_word_shift = b_pos + word_shift;
4507  while (a_pos > b_pos_with_word_shift) {
4508  c->frac[--c_pos] = a->frac[--a_pos];
4509  }
4510 
4511  /* Now perform subtraction until every digits of b will be */
4512  /* exhausted. */
4513  while (b_pos > 0) {
4514  --c_pos;
4515  if (a->frac[--a_pos] < b->frac[--b_pos] + borrow) {
4516  c->frac[c_pos] = BASE + a->frac[a_pos] - b->frac[b_pos] - borrow;
4517  borrow = 1;
4518  }
4519  else {
4520  c->frac[c_pos] = a->frac[a_pos] - b->frac[b_pos] - borrow;
4521  borrow = 0;
4522  }
4523  }
4524 
4525  /* Just assign the first few digits of a with considering */
4526  /* the borrow obtained so far because b has been exhausted. */
4527  while (a_pos > 0) {
4528  --c_pos;
4529  if (a->frac[--a_pos] < borrow) {
4530  c->frac[c_pos] = BASE + a->frac[a_pos] - borrow;
4531  borrow = 1;
4532  }
4533  else {
4534  c->frac[c_pos] = a->frac[a_pos] - borrow;
4535  borrow = 0;
4536  }
4537  }
4538  if (c_pos) c->frac[c_pos - 1] -= borrow;
4539  goto Exit;
4540 
4541 Assign_a:
4542  VpAsgn(c, a, 1);
4543  mrv = 0;
4544 
4545 Exit:
4546 #ifdef BIGDECIMAL_DEBUG
4547  if (gfDebug) {
4548  VPrint(stdout, "VpSubAbs exit: c=% \n", c);
4549  }
4550 #endif /* BIGDECIMAL_DEBUG */
4551  return mrv;
4552 }
4553 
4554 /*
4555  * Note: If(av+bv)>= HALF_BASE,then 1 will be added to the least significant
4556  * digit of c(In case of addition).
4557  * ------------------------- figure of output -----------------------------------
4558  * a = xxxxxxxxxxx
4559  * b = xxxxxxxxxx
4560  * c =xxxxxxxxxxxxxxx
4561  * word_shift = | |
4562  * right_word = | | (Total digits in RHSV)
4563  * left_word = | | (Total digits in LHSV)
4564  * a_pos = |
4565  * b_pos = |
4566  * c_pos = |
4567  */
4568 static size_t
4569 VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos, BDIGIT *av, BDIGIT *bv)
4570 {
4571  size_t left_word, right_word, word_shift;
4572 
4573  size_t const round_limit = (VpGetPrecLimit() + BASE_FIG - 1) / BASE_FIG;
4574 
4575  assert(a->exponent >= b->exponent);
4576 
4577  c->frac[0] = 0;
4578  *av = *bv = 0;
4579 
4580  word_shift = (a->exponent - b->exponent);
4581  left_word = b->Prec + word_shift;
4582  right_word = Max(a->Prec, left_word);
4583  left_word = c->MaxPrec - 1; /* -1 ... prepare for round up */
4584 
4585  /*
4586  * check if 'round' is needed.
4587  */
4588  if (right_word > left_word) { /* round ? */
4589  /*---------------------------------
4590  * Actual size of a = xxxxxxAxx
4591  * Actual size of b = xxxBxxxxx
4592  * Max. size of c = xxxxxx
4593  * Round off = |-----|
4594  * c_pos = |
4595  * right_word = |
4596  * a_pos = |
4597  */
4598  *c_pos = right_word = left_word + 1; /* Set resulting precision */
4599  /* be equal to that of c */
4600  if (a->Prec >= c->MaxPrec) {
4601  /*
4602  * a = xxxxxxAxxx
4603  * c = xxxxxx
4604  * a_pos = |
4605  */
4606  *a_pos = left_word;
4607  if (*a_pos <= round_limit) {
4608  *av = a->frac[*a_pos]; /* av is 'A' shown in above. */
4609  }
4610  }
4611  else {
4612  /*
4613  * a = xxxxxxx
4614  * c = xxxxxxxxxx
4615  * a_pos = |
4616  */
4617  *a_pos = a->Prec;
4618  }
4619  if (b->Prec + word_shift >= c->MaxPrec) {
4620  /*
4621  * a = xxxxxxxxx
4622  * b = xxxxxxxBxxx
4623  * c = xxxxxxxxxxx
4624  * b_pos = |
4625  */
4626  if (c->MaxPrec >= word_shift + 1) {
4627  *b_pos = c->MaxPrec - word_shift - 1;
4628  if (*b_pos + word_shift <= round_limit) {
4629  *bv = b->frac[*b_pos];
4630  }
4631  }
4632  else {
4633  *b_pos = -1L;
4634  }
4635  }
4636  else {
4637  /*
4638  * a = xxxxxxxxxxxxxxxx
4639  * b = xxxxxx
4640  * c = xxxxxxxxxxxxx
4641  * b_pos = |
4642  */
4643  *b_pos = b->Prec;
4644  }
4645  }
4646  else { /* The MaxPrec of c - 1 > The Prec of a + b */
4647  /*
4648  * a = xxxxxxx
4649  * b = xxxxxx
4650  * c = xxxxxxxxxxx
4651  * c_pos = |
4652  */
4653  *b_pos = b->Prec;
4654  *a_pos = a->Prec;
4655  *c_pos = right_word + 1;
4656  }
4657  c->Prec = *c_pos;
4658  c->exponent = a->exponent;
4659  if (!AddExponent(c, 1)) return (size_t)-1L;
4660  return word_shift;
4661 }
4662 
4663 /*
4664  * Return number of significant digits
4665  * c = a * b , Where a = a0a1a2 ... an
4666  * b = b0b1b2 ... bm
4667  * c = c0c1c2 ... cl
4668  * a0 a1 ... an * bm
4669  * a0 a1 ... an * bm-1
4670  * . . .
4671  * . . .
4672  * a0 a1 .... an * b0
4673  * +_____________________________
4674  * c0 c1 c2 ...... cl
4675  * nc <---|
4676  * MaxAB |--------------------|
4677  */
4678 VP_EXPORT size_t
4679 VpMult(Real *c, Real *a, Real *b)
4680 {
4681  size_t MxIndA, MxIndB, MxIndAB, MxIndC;
4682  size_t ind_c, i, ii, nc;
4683  size_t ind_as, ind_ae, ind_bs;
4684  BDIGIT carry;
4685  BDIGIT_DBL s;
4686  Real *w;
4687 
4688 #ifdef BIGDECIMAL_DEBUG
4689  if (gfDebug) {
4690  VPrint(stdout, "VpMult(Enter): a=% \n", a);
4691  VPrint(stdout, " b=% \n", b);
4692  }
4693 #endif /* BIGDECIMAL_DEBUG */
4694 
4695  if (!VpIsDefOP(c, a, b, OP_SW_MULT)) return 0; /* No significant digit */
4696 
4697  if (VpIsZero(a) || VpIsZero(b)) {
4698  /* at least a or b is zero */
4699  VpSetZero(c, VpGetSign(a) * VpGetSign(b));
4700  return 1; /* 0: 1 significant digit */
4701  }
4702 
4703  if (VpIsOne(a)) {
4704  VpAsgn(c, b, VpGetSign(a));
4705  goto Exit;
4706  }
4707  if (VpIsOne(b)) {
4708  VpAsgn(c, a, VpGetSign(b));
4709  goto Exit;
4710  }
4711  if (b->Prec > a->Prec) {
4712  /* Adjust so that digits(a)>digits(b) */
4713  w = a;
4714  a = b;
4715  b = w;
4716  }
4717  w = NULL;
4718  MxIndA = a->Prec - 1;
4719  MxIndB = b->Prec - 1;
4720  MxIndC = c->MaxPrec - 1;
4721  MxIndAB = a->Prec + b->Prec - 1;
4722 
4723  if (MxIndC < MxIndAB) { /* The Max. prec. of c < Prec(a)+Prec(b) */
4724  w = c;
4725  c = VpAlloc((size_t)((MxIndAB + 1) * BASE_FIG), "#0");
4726  MxIndC = MxIndAB;
4727  }
4728 
4729  /* set LHSV c info */
4730 
4731  c->exponent = a->exponent; /* set exponent */
4732  if (!AddExponent(c, b->exponent)) {
4733  if (w) VpFree(c);
4734  return 0;
4735  }
4736  VpSetSign(c, VpGetSign(a) * VpGetSign(b)); /* set sign */
4737  carry = 0;
4738  nc = ind_c = MxIndAB;
4739  memset(c->frac, 0, (nc + 1) * sizeof(BDIGIT)); /* Initialize c */
4740  c->Prec = nc + 1; /* set precision */
4741  for (nc = 0; nc < MxIndAB; ++nc, --ind_c) {
4742  if (nc < MxIndB) { /* The left triangle of the Fig. */
4743  ind_as = MxIndA - nc;
4744  ind_ae = MxIndA;
4745  ind_bs = MxIndB;
4746  }
4747  else if (nc <= MxIndA) { /* The middle rectangular of the Fig. */
4748  ind_as = MxIndA - nc;
4749  ind_ae = MxIndA - (nc - MxIndB);
4750  ind_bs = MxIndB;
4751  }
4752  else /* if (nc > MxIndA) */ { /* The right triangle of the Fig. */
4753  ind_as = 0;
4754  ind_ae = MxIndAB - nc - 1;
4755  ind_bs = MxIndB - (nc - MxIndA);
4756  }
4757 
4758  for (i = ind_as; i <= ind_ae; ++i) {
4759  s = (BDIGIT_DBL)a->frac[i] * b->frac[ind_bs--];
4760  carry = (BDIGIT)(s / BASE);
4761  s -= (BDIGIT_DBL)carry * BASE;
4762  c->frac[ind_c] += (BDIGIT)s;
4763  if (c->frac[ind_c] >= BASE) {
4764  s = c->frac[ind_c] / BASE;
4765  carry += (BDIGIT)s;
4766  c->frac[ind_c] -= (BDIGIT)(s * BASE);
4767  }
4768  if (carry) {
4769  ii = ind_c;
4770  while (ii-- > 0) {
4771  c->frac[ii] += carry;
4772  if (c->frac[ii] >= BASE) {
4773  carry = c->frac[ii] / BASE;
4774  c->frac[ii] -= (carry * BASE);
4775  }
4776  else {
4777  break;
4778  }
4779  }
4780  }
4781  }
4782  }
4783  if (w != NULL) { /* free work variable */
4784  VpNmlz(c);
4785  VpAsgn(w, c, 1);
4786  VpFree(c);
4787  c = w;
4788  }
4789  else {
4790  VpLimitRound(c,0);
4791  }
4792 
4793 Exit:
4794 #ifdef BIGDECIMAL_DEBUG
4795  if (gfDebug) {
4796  VPrint(stdout, "VpMult(c=a*b): c=% \n", c);
4797  VPrint(stdout, " a=% \n", a);
4798  VPrint(stdout, " b=% \n", b);
4799  }
4800 #endif /*BIGDECIMAL_DEBUG */
4801  return c->Prec*BASE_FIG;
4802 }
4803 
4804 /*
4805  * c = a / b, remainder = r
4806  */
4807 VP_EXPORT size_t
4808 VpDivd(Real *c, Real *r, Real *a, Real *b)
4809 {
4810  size_t word_a, word_b, word_c, word_r;
4811  size_t i, n, ind_a, ind_b, ind_c, ind_r;
4812  size_t nLoop;
4813  BDIGIT_DBL q, b1, b1p1, b1b2, b1b2p1, r1r2;
4814  BDIGIT borrow, borrow1, borrow2;
4815  BDIGIT_DBL qb;
4816 
4817 #ifdef BIGDECIMAL_DEBUG
4818  if (gfDebug) {
4819  VPrint(stdout, " VpDivd(c=a/b) a=% \n", a);
4820  VPrint(stdout, " b=% \n", b);
4821  }
4822 #endif /*BIGDECIMAL_DEBUG */
4823 
4824  VpSetNaN(r);
4825  if (!VpIsDefOP(c, a, b, OP_SW_DIV)) goto Exit;
4826  if (VpIsZero(a) && VpIsZero(b)) {
4827  VpSetNaN(c);
4828  return VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'", 0);
4829  }
4830  if (VpIsZero(b)) {
4831  VpSetInf(c, VpGetSign(a) * VpGetSign(b));
4832  return VpException(VP_EXCEPTION_ZERODIVIDE, "Divide by zero", 0);
4833  }
4834  if (VpIsZero(a)) {
4835  /* numerator a is zero */
4836  VpSetZero(c, VpGetSign(a) * VpGetSign(b));
4837  VpSetZero(r, VpGetSign(a) * VpGetSign(b));
4838  goto Exit;
4839  }
4840  if (VpIsOne(b)) {
4841  /* divide by one */
4842  VpAsgn(c, a, VpGetSign(b));
4843  VpSetZero(r, VpGetSign(a));
4844  goto Exit;
4845  }
4846 
4847  word_a = a->Prec;
4848  word_b = b->Prec;
4849  word_c = c->MaxPrec;
4850  word_r = r->MaxPrec;
4851 
4852  ind_c = 0;
4853  ind_r = 1;
4854 
4855  if (word_a >= word_r) goto space_error;
4856 
4857  r->frac[0] = 0;
4858  while (ind_r <= word_a) {
4859  r->frac[ind_r] = a->frac[ind_r - 1];
4860  ++ind_r;
4861  }
4862 
4863  while (ind_r < word_r) r->frac[ind_r++] = 0;
4864  while (ind_c < word_c) c->frac[ind_c++] = 0;
4865 
4866  /* initial procedure */
4867  b1 = b1p1 = b->frac[0];
4868  if (b->Prec <= 1) {
4869  b1b2p1 = b1b2 = b1p1 * BASE;
4870  }
4871  else {
4872  b1p1 = b1 + 1;
4873  b1b2p1 = b1b2 = b1 * BASE + b->frac[1];
4874  if (b->Prec > 2) ++b1b2p1;
4875  }
4876 
4877  /* */
4878  /* loop start */
4879  ind_c = word_r - 1;
4880  nLoop = Min(word_c,ind_c);
4881  ind_c = 1;
4882  while (ind_c < nLoop) {
4883  if (r->frac[ind_c] == 0) {
4884  ++ind_c;
4885  continue;
4886  }
4887  r1r2 = (BDIGIT_DBL)r->frac[ind_c] * BASE + r->frac[ind_c + 1];
4888  if (r1r2 == b1b2) {
4889  /* The first two word digits is the same */
4890  ind_b = 2;
4891  ind_a = ind_c + 2;
4892  while (ind_b < word_b) {
4893  if (r->frac[ind_a] < b->frac[ind_b]) goto div_b1p1;
4894  if (r->frac[ind_a] > b->frac[ind_b]) break;
4895  ++ind_a;
4896  ++ind_b;
4897  }
4898  /* The first few word digits of r and b is the same and */
4899  /* the first different word digit of w is greater than that */
4900  /* of b, so quotient is 1 and just subtract b from r. */
4901  borrow = 0; /* quotient=1, then just r-b */
4902  ind_b = b->Prec - 1;
4903  ind_r = ind_c + ind_b;
4904  if (ind_r >= word_r) goto space_error;
4905  n = ind_b;
4906  for (i = 0; i <= n; ++i) {
4907  if (r->frac[ind_r] < b->frac[ind_b] + borrow) {
4908  r->frac[ind_r] += (BASE - (b->frac[ind_b] + borrow));
4909  borrow = 1;
4910  }
4911  else {
4912  r->frac[ind_r] = r->frac[ind_r] - b->frac[ind_b] - borrow;
4913  borrow = 0;
4914  }
4915  --ind_r;
4916  --ind_b;
4917  }
4918  ++c->frac[ind_c];
4919  goto carry;
4920  }
4921  /* The first two word digits is not the same, */
4922  /* then compare magnitude, and divide actually. */
4923  if (r1r2 >= b1b2p1) {
4924  q = r1r2 / b1b2p1; /* q == (BDIGIT)q */
4925  c->frac[ind_c] += (BDIGIT)q;
4926  ind_r = b->Prec + ind_c - 1;
4927  goto sub_mult;
4928  }
4929 
4930 div_b1p1:
4931  if (ind_c + 1 >= word_c) goto out_side;
4932  q = r1r2 / b1p1; /* q == (BDIGIT)q */
4933  c->frac[ind_c + 1] += (BDIGIT)q;
4934  ind_r = b->Prec + ind_c;
4935 
4936 sub_mult:
4937  borrow1 = borrow2 = 0;
4938  ind_b = word_b - 1;
4939  if (ind_r >= word_r) goto space_error;
4940  n = ind_b;
4941  for (i = 0; i <= n; ++i) {
4942  /* now, perform r = r - q * b */
4943  qb = q * b->frac[ind_b];
4944  if (qb < BASE) borrow1 = 0;
4945  else {
4946  borrow1 = (BDIGIT)(qb / BASE);
4947  qb -= (BDIGIT_DBL)borrow1 * BASE; /* get qb < BASE */
4948  }
4949  if(r->frac[ind_r] < qb) {
4950  r->frac[ind_r] += (BDIGIT)(BASE - qb);
4951  borrow2 = borrow2 + borrow1 + 1;
4952  }
4953  else {
4954  r->frac[ind_r] -= (BDIGIT)qb;
4955  borrow2 += borrow1;
4956  }
4957  if (borrow2) {
4958  if(r->frac[ind_r - 1] < borrow2) {
4959  r->frac[ind_r - 1] += (BASE - borrow2);
4960  borrow2 = 1;
4961  }
4962  else {
4963  r->frac[ind_r - 1] -= borrow2;
4964  borrow2 = 0;
4965  }
4966  }
4967  --ind_r;
4968  --ind_b;
4969  }
4970 
4971  r->frac[ind_r] -= borrow2;
4972 carry:
4973  ind_r = ind_c;
4974  while (c->frac[ind_r] >= BASE) {
4975  c->frac[ind_r] -= BASE;
4976  --ind_r;
4977  ++c->frac[ind_r];
4978  }
4979  }
4980  /* End of operation, now final arrangement */
4981 out_side:
4982  c->Prec = word_c;
4983  c->exponent = a->exponent;
4984  if (!AddExponent(c, 2)) return 0;
4985  if (!AddExponent(c, -(b->exponent))) return 0;
4986 
4987  VpSetSign(c, VpGetSign(a) * VpGetSign(b));
4988  VpNmlz(c); /* normalize c */
4989  r->Prec = word_r;
4990  r->exponent = a->exponent;
4991  if (!AddExponent(r, 1)) return 0;
4992  VpSetSign(r, VpGetSign(a));
4993  VpNmlz(r); /* normalize r(remainder) */
4994  goto Exit;
4995 
4996 space_error:
4997 #ifdef BIGDECIMAL_DEBUG
4998  if (gfDebug) {
4999  printf(" word_a=%"PRIuSIZE"\n", word_a);
5000  printf(" word_b=%"PRIuSIZE"\n", word_b);
5001  printf(" word_c=%"PRIuSIZE"\n", word_c);
5002  printf(" word_r=%"PRIuSIZE"\n", word_r);
5003  printf(" ind_r =%"PRIuSIZE"\n", ind_r);
5004  }
5005 #endif /* BIGDECIMAL_DEBUG */
5006  rb_bug("ERROR(VpDivd): space for remainder too small.");
5007 
5008 Exit:
5009 #ifdef BIGDECIMAL_DEBUG
5010  if (gfDebug) {
5011  VPrint(stdout, " VpDivd(c=a/b), c=% \n", c);
5012  VPrint(stdout, " r=% \n", r);
5013  }
5014 #endif /* BIGDECIMAL_DEBUG */
5015  return c->Prec * BASE_FIG;
5016 }
5017 
5018 /*
5019  * Input a = 00000xxxxxxxx En(5 preceding zeros)
5020  * Output a = xxxxxxxx En-5
5021  */
5022 static int
5023 VpNmlz(Real *a)
5024 {
5025  size_t ind_a, i;
5026 
5027  if (!VpIsDef(a)) goto NoVal;
5028  if (VpIsZero(a)) goto NoVal;
5029 
5030  ind_a = a->Prec;
5031  while (ind_a--) {
5032  if (a->frac[ind_a]) {
5033  a->Prec = ind_a + 1;
5034  i = 0;
5035  while (a->frac[i] == 0) ++i; /* skip the first few zeros */
5036  if (i) {
5037  a->Prec -= i;
5038  if (!AddExponent(a, -(SIGNED_VALUE)i)) return 0;
5039  memmove(&a->frac[0], &a->frac[i], a->Prec*sizeof(BDIGIT));
5040  }
5041  return 1;
5042  }
5043  }
5044  /* a is zero(no non-zero digit) */
5045  VpSetZero(a, VpGetSign(a));
5046  return 0;
5047 
5048 NoVal:
5049  a->frac[0] = 0;
5050  a->Prec = 1;
5051  return 0;
5052 }
5053 
5054 /*
5055  * VpComp = 0 ... if a=b,
5056  * Pos ... a>b,
5057  * Neg ... a<b.
5058  * 999 ... result undefined(NaN)
5059  */
5060 VP_EXPORT int
5062 {
5063  int val;
5064  size_t mx, ind;
5065  int e;
5066  val = 0;
5067  if (VpIsNaN(a) || VpIsNaN(b)) return 999;
5068  if (!VpIsDef(a)) {
5069  if (!VpIsDef(b)) e = a->sign - b->sign;
5070  else e = a->sign;
5071 
5072  if (e > 0) return 1;
5073  else if (e < 0) return -1;
5074  else return 0;
5075  }
5076  if (!VpIsDef(b)) {
5077  e = -b->sign;
5078  if (e > 0) return 1;
5079  else return -1;
5080  }
5081  /* Zero check */
5082  if (VpIsZero(a)) {
5083  if (VpIsZero(b)) return 0; /* both zero */
5084  val = -VpGetSign(b);
5085  goto Exit;
5086  }
5087  if (VpIsZero(b)) {
5088  val = VpGetSign(a);
5089  goto Exit;
5090  }
5091 
5092  /* compare sign */
5093  if (VpGetSign(a) > VpGetSign(b)) {
5094  val = 1; /* a>b */
5095  goto Exit;
5096  }
5097  if (VpGetSign(a) < VpGetSign(b)) {
5098  val = -1; /* a<b */
5099  goto Exit;
5100  }
5101 
5102  /* a and b have same sign, && sign!=0,then compare exponent */
5103  if (a->exponent > b->exponent) {
5104  val = VpGetSign(a);
5105  goto Exit;
5106  }
5107  if (a->exponent < b->exponent) {
5108  val = -VpGetSign(b);
5109  goto Exit;
5110  }
5111 
5112  /* a and b have same exponent, then compare their significand. */
5113  mx = (a->Prec < b->Prec) ? a->Prec : b->Prec;
5114  ind = 0;
5115  while (ind < mx) {
5116  if (a->frac[ind] > b->frac[ind]) {
5117  val = VpGetSign(a);
5118  goto Exit;
5119  }
5120  if (a->frac[ind] < b->frac[ind]) {
5121  val = -VpGetSign(b);
5122  goto Exit;
5123  }
5124  ++ind;
5125  }
5126  if (a->Prec > b->Prec) {
5127  val = VpGetSign(a);
5128  }
5129  else if (a->Prec < b->Prec) {
5130  val = -VpGetSign(b);
5131  }
5132 
5133 Exit:
5134  if (val > 1) val = 1;
5135  else if (val < -1) val = -1;
5136 
5137 #ifdef BIGDECIMAL_DEBUG
5138  if (gfDebug) {
5139  VPrint(stdout, " VpComp a=%\n", a);
5140  VPrint(stdout, " b=%\n", b);
5141  printf(" ans=%d\n", val);
5142  }
5143 #endif /* BIGDECIMAL_DEBUG */
5144  return (int)val;
5145 }
5146 
5147 /*
5148  * cntl_chr ... ASCIIZ Character, print control characters
5149  * Available control codes:
5150  * % ... VP variable. To print '%', use '%%'.
5151  * \n ... new line
5152  * \b ... backspace
5153  * \t ... tab
5154  * Note: % must not appear more than once
5155  * a ... VP variable to be printed
5156  */
5157 #ifdef BIGDECIMAL_ENABLE_VPRINT
5158 static int
5159 VPrint(FILE *fp, const char *cntl_chr, Real *a)
5160 {
5161  size_t i, j, nc, nd, ZeroSup, sep = 10;
5162  BDIGIT m, e, nn;
5163 
5164  j = 0;
5165  nd = nc = 0; /* nd : number of digits in fraction part(every 10 digits, */
5166  /* nd<=10). */
5167  /* nc : number of characters printed */
5168  ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
5169  while (*(cntl_chr + j)) {
5170  if (*(cntl_chr + j) == '%' && *(cntl_chr + j + 1) != '%') {
5171  nc = 0;
5172  if (VpIsNaN(a)) {
5173  fprintf(fp, SZ_NaN);
5174  nc += 8;
5175  }
5176  else if (VpIsPosInf(a)) {
5177  fprintf(fp, SZ_INF);
5178  nc += 8;
5179  }
5180  else if (VpIsNegInf(a)) {
5181  fprintf(fp, SZ_NINF);
5182  nc += 9;
5183  }
5184  else if (!VpIsZero(a)) {
5185  if (BIGDECIMAL_NEGATIVE_P(a)) {
5186  fprintf(fp, "-");
5187  ++nc;
5188  }
5189  nc += fprintf(fp, "0.");
5190  switch (*(cntl_chr + j + 1)) {
5191  default:
5192  break;
5193 
5194  case '0': case 'z':
5195  ZeroSup = 0;
5196  ++j;
5197  sep = cntl_chr[j] == 'z' ? RMPD_COMPONENT_FIGURES : 10;
5198  break;
5199  }
5200  for (i = 0; i < a->Prec; ++i) {
5201  m = BASE1;
5202  e = a->frac[i];
5203  while (m) {
5204  nn = e / m;
5205  if (!ZeroSup || nn) {
5206  nc += fprintf(fp, "%lu", (unsigned long)nn); /* The leading zero(s) */
5207  /* as 0.00xx will not */
5208  /* be printed. */
5209  ++nd;
5210  ZeroSup = 0; /* Set to print succeeding zeros */
5211  }
5212  if (nd >= sep) { /* print ' ' after every 10 digits */
5213  nd = 0;
5214  nc += fprintf(fp, " ");
5215  }
5216  e = e - nn * m;
5217  m /= 10;
5218  }
5219  }
5220  nc += fprintf(fp, "E%"PRIdSIZE, VpExponent10(a));
5221  nc += fprintf(fp, " (%"PRIdVALUE", %lu, %lu)", a->exponent, a->Prec, a->MaxPrec);
5222  }
5223  else {
5224  nc += fprintf(fp, "0.0");
5225  }
5226  }
5227  else {
5228  ++nc;
5229  if (*(cntl_chr + j) == '\\') {
5230  switch (*(cntl_chr + j + 1)) {
5231  case 'n':
5232  fprintf(fp, "\n");
5233  ++j;
5234  break;
5235  case 't':
5236  fprintf(fp, "\t");
5237  ++j;
5238  break;
5239  case 'b':
5240  fprintf(fp, "\n");
5241  ++j;
5242  break;
5243  default:
5244  fprintf(fp, "%c", *(cntl_chr + j));
5245  break;
5246  }
5247  }
5248  else {
5249  fprintf(fp, "%c", *(cntl_chr + j));
5250  if (*(cntl_chr + j) == '%') ++j;
5251  }
5252  }
5253  j++;
5254  }
5255 
5256  return (int)nc;
5257 }
5258 #endif
5259 
5260 static void
5261 VpFormatSt(char *psz, size_t fFmt)
5262 {
5263  size_t ie, i, nf = 0;
5264  char ch;
5265 
5266  if (fFmt == 0) return;
5267 
5268  ie = strlen(psz);
5269  for (i = 0; i < ie; ++i) {
5270  ch = psz[i];
5271  if (!ch) break;
5272  if (ISSPACE(ch) || ch=='-' || ch=='+') continue;
5273  if (ch == '.') { nf = 0; continue; }
5274  if (ch == 'E' || ch == 'e') break;
5275 
5276  if (++nf > fFmt) {
5277  memmove(psz + i + 1, psz + i, ie - i + 1);
5278  ++ie;
5279  nf = 0;
5280  psz[i] = ' ';
5281  }
5282  }
5283 }
5284 
5285 VP_EXPORT ssize_t
5287 {
5288  ssize_t ex;
5289  size_t n;
5290 
5291  if (!VpHasVal(a)) return 0;
5292 
5293  ex = a->exponent * (ssize_t)BASE_FIG;
5294  n = BASE1;
5295  while ((a->frac[0] / n) == 0) {
5296  --ex;
5297  n /= 10;
5298  }
5299  return ex;
5300 }
5301 
5302 VP_EXPORT void
5303 VpSzMantissa(Real *a,char *psz)
5304 {
5305  size_t i, n, ZeroSup;
5306  BDIGIT_DBL m, e, nn;
5307 
5308  if (VpIsNaN(a)) {
5309  sprintf(psz, SZ_NaN);
5310  return;
5311  }
5312  if (VpIsPosInf(a)) {
5313  sprintf(psz, SZ_INF);
5314  return;
5315  }
5316  if (VpIsNegInf(a)) {
5317  sprintf(psz, SZ_NINF);
5318  return;
5319  }
5320 
5321  ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
5322  if (!VpIsZero(a)) {
5323  if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
5324  n = a->Prec;
5325  for (i = 0; i < n; ++i) {
5326  m = BASE1;
5327  e = a->frac[i];
5328  while (m) {
5329  nn = e / m;
5330  if (!ZeroSup || nn) {
5331  sprintf(psz, "%lu", (unsigned long)nn); /* The leading zero(s) */
5332  psz += strlen(psz);
5333  /* as 0.00xx will be ignored. */
5334  ZeroSup = 0; /* Set to print succeeding zeros */
5335  }
5336  e = e - nn * m;
5337  m /= 10;
5338  }
5339  }
5340  *psz = 0;
5341  while (psz[-1] == '0') *(--psz) = 0;
5342  }
5343  else {
5344  if (VpIsPosZero(a)) sprintf(psz, "0");
5345  else sprintf(psz, "-0");
5346  }
5347 }
5348 
5349 VP_EXPORT int
5350 VpToSpecialString(Real *a,char *psz,int fPlus)
5351  /* fPlus =0:default, =1: set ' ' before digits , =2: set '+' before digits. */
5352 {
5353  if (VpIsNaN(a)) {
5354  sprintf(psz,SZ_NaN);
5355  return 1;
5356  }
5357 
5358  if (VpIsPosInf(a)) {
5359  if (fPlus == 1) {
5360  *psz++ = ' ';
5361  }
5362  else if (fPlus == 2) {
5363  *psz++ = '+';
5364  }
5365  sprintf(psz, SZ_INF);
5366  return 1;
5367  }
5368  if (VpIsNegInf(a)) {
5369  sprintf(psz, SZ_NINF);
5370  return 1;
5371  }
5372  if (VpIsZero(a)) {
5373  if (VpIsPosZero(a)) {
5374  if (fPlus == 1) sprintf(psz, " 0.0");
5375  else if (fPlus == 2) sprintf(psz, "+0.0");
5376  else sprintf(psz, "0.0");
5377  }
5378  else sprintf(psz, "-0.0");
5379  return 1;
5380  }
5381  return 0;
5382 }
5383 
5384 VP_EXPORT void
5385 VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
5386 /* fPlus =0:default, =1: set ' ' before digits , =2:set '+' before digits. */
5387 {
5388  size_t i, n, ZeroSup;
5389  BDIGIT shift, m, e, nn;
5390  char *pszSav = psz;
5391  ssize_t ex;
5392 
5393  if (VpToSpecialString(a, psz, fPlus)) return;
5394 
5395  ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */
5396 
5397  if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
5398  else if (fPlus == 1) *psz++ = ' ';
5399  else if (fPlus == 2) *psz++ = '+';
5400 
5401  *psz++ = '0';
5402  *psz++ = '.';
5403  n = a->Prec;
5404  for (i = 0; i < n; ++i) {
5405  m = BASE1;
5406  e = a->frac[i];
5407  while (m) {
5408  nn = e / m;
5409  if (!ZeroSup || nn) {
5410  sprintf(psz, "%lu", (unsigned long)nn); /* The reading zero(s) */
5411  psz += strlen(psz);
5412  /* as 0.00xx will be ignored. */
5413  ZeroSup = 0; /* Set to print succeeding zeros */
5414  }
5415  e = e - nn * m;
5416  m /= 10;
5417  }
5418  }
5419  ex = a->exponent * (ssize_t)BASE_FIG;
5420  shift = BASE1;
5421  while (a->frac[0] / shift == 0) {
5422  --ex;
5423  shift /= 10;
5424  }
5425  while (psz[-1] == '0') {
5426  *(--psz) = 0;
5427  }
5428  sprintf(psz, "e%"PRIdSIZE, ex);
5429  if (fFmt) VpFormatSt(pszSav, fFmt);
5430 }
5431 
5432 VP_EXPORT void
5433 VpToFString(Real *a, char *psz, size_t fFmt, int fPlus)
5434 /* fPlus =0:default,=1: set ' ' before digits ,set '+' before digits. */
5435 {
5436  size_t i, n;
5437  BDIGIT m, e, nn;
5438  char *pszSav = psz;
5439  ssize_t ex;
5440 
5441  if (VpToSpecialString(a, psz, fPlus)) return;
5442 
5443  if (BIGDECIMAL_NEGATIVE_P(a)) *psz++ = '-';
5444  else if (fPlus == 1) *psz++ = ' ';
5445  else if (fPlus == 2) *psz++ = '+';
5446 
5447  n = a->Prec;
5448  ex = a->exponent;
5449  if (ex <= 0) {
5450  *psz++ = '0';*psz++ = '.';
5451  while (ex < 0) {
5452  for (i=0; i < BASE_FIG; ++i) *psz++ = '0';
5453  ++ex;
5454  }
5455  ex = -1;
5456  }
5457 
5458  for (i = 0; i < n; ++i) {
5459  --ex;
5460  if (i == 0 && ex >= 0) {
5461  sprintf(psz, "%lu", (unsigned long)a->frac[i]);
5462  psz += strlen(psz);
5463  }
5464  else {
5465  m = BASE1;
5466  e = a->frac[i];
5467  while (m) {
5468  nn = e / m;
5469  *psz++ = (char)(nn + '0');
5470  e = e - nn * m;
5471  m /= 10;
5472  }
5473  }
5474  if (ex == 0) *psz++ = '.';
5475  }
5476  while (--ex>=0) {
5477  m = BASE;
5478  while (m /= 10) *psz++ = '0';
5479  if (ex == 0) *psz++ = '.';
5480  }
5481  *psz = 0;
5482  while (psz[-1] == '0') *(--psz) = 0;
5483  if (psz[-1] == '.') sprintf(psz, "0");
5484  if (fFmt) VpFormatSt(pszSav, fFmt);
5485 }
5486 
5487 /*
5488  * [Output]
5489  * a[] ... variable to be assigned the value.
5490  * [Input]
5491  * int_chr[] ... integer part(may include '+/-').
5492  * ni ... number of characters in int_chr[],not including '+/-'.
5493  * frac[] ... fraction part.
5494  * nf ... number of characters in frac[].
5495  * exp_chr[] ... exponent part(including '+/-').
5496  * ne ... number of characters in exp_chr[],not including '+/-'.
5497  */
5498 VP_EXPORT int
5499 VpCtoV(Real *a, const char *int_chr, size_t ni, const char *frac, size_t nf, const char *exp_chr, size_t ne)
5500 {
5501  size_t i, j, ind_a, ma, mi, me;
5502  SIGNED_VALUE e, es, eb, ef;
5503  int sign, signe, exponent_overflow;
5504 
5505  /* get exponent part */
5506  e = 0;
5507  ma = a->MaxPrec;
5508  mi = ni;
5509  me = ne;
5510  signe = 1;
5511  exponent_overflow = 0;
5512  memset(a->frac, 0, ma * sizeof(BDIGIT));
5513  if (ne > 0) {
5514  i = 0;
5515  if (exp_chr[0] == '-') {
5516  signe = -1;
5517  ++i;
5518  ++me;
5519  }
5520  else if (exp_chr[0] == '+') {
5521  ++i;
5522  ++me;
5523  }
5524  while (i < me) {
5526  es = e;
5527  goto exp_overflow;
5528  }
5529  es = e * (SIGNED_VALUE)BASE_FIG;
5530  if (MUL_OVERFLOW_SIGNED_VALUE_P(e, 10) ||
5531  SIGNED_VALUE_MAX - (exp_chr[i] - '0') < e * 10)
5532  goto exp_overflow;
5533  e = e * 10 + exp_chr[i] - '0';
5535  goto exp_overflow;
5536  if (es > (SIGNED_VALUE)(e * BASE_FIG)) {
5537  exp_overflow:
5538  exponent_overflow = 1;
5539  e = es; /* keep sign */
5540  break;
5541  }
5542  ++i;
5543  }
5544  }
5545 
5546  /* get integer part */
5547  i = 0;
5548  sign = 1;
5549  if (1 /*ni >= 0*/) {
5550  if (int_chr[0] == '-') {
5551  sign = -1;
5552  ++i;
5553  ++mi;
5554  }
5555  else if (int_chr[0] == '+') {
5556  ++i;
5557  ++mi;
5558  }
5559  }
5560 
5561  e = signe * e; /* e: The value of exponent part. */
5562  e = e + ni; /* set actual exponent size. */
5563 
5564  if (e > 0) signe = 1;
5565  else signe = -1;
5566 
5567  /* Adjust the exponent so that it is the multiple of BASE_FIG. */
5568  j = 0;
5569  ef = 1;
5570  while (ef) {
5571  if (e >= 0) eb = e;
5572  else eb = -e;
5573  ef = eb / (SIGNED_VALUE)BASE_FIG;
5574  ef = eb - ef * (SIGNED_VALUE)BASE_FIG;
5575  if (ef) {
5576  ++j; /* Means to add one more preceding zero */
5577  ++e;
5578  }
5579  }
5580 
5581  eb = e / (SIGNED_VALUE)BASE_FIG;
5582 
5583  if (exponent_overflow) {
5584  int zero = 1;
5585  for ( ; i < mi && zero; i++) zero = int_chr[i] == '0';
5586  for (i = 0; i < nf && zero; i++) zero = frac[i] == '0';
5587  if (!zero && signe > 0) {
5588  VpSetInf(a, sign);
5589  VpException(VP_EXCEPTION_INFINITY, "exponent overflow",0);
5590  }
5591  else VpSetZero(a, sign);
5592  return 1;
5593  }
5594 
5595  ind_a = 0;
5596  while (i < mi) {
5597  a->frac[ind_a] = 0;
5598  while (j < BASE_FIG && i < mi) {
5599  a->frac[ind_a] = a->frac[ind_a] * 10 + int_chr[i] - '0';
5600  ++j;
5601  ++i;
5602  }
5603  if (i < mi) {
5604  ++ind_a;
5605  if (ind_a >= ma) goto over_flow;
5606  j = 0;
5607  }
5608  }
5609 
5610  /* get fraction part */
5611 
5612  i = 0;
5613  while (i < nf) {
5614  while (j < BASE_FIG && i < nf) {
5615  a->frac[ind_a] = a->frac[ind_a] * 10 + frac[i] - '0';
5616  ++j;
5617  ++i;
5618  }
5619  if (i < nf) {
5620  ++ind_a;
5621  if (ind_a >= ma) goto over_flow;
5622  j = 0;
5623  }
5624  }
5625  goto Final;
5626 
5627 over_flow:
5628  rb_warn("Conversion from String to BigDecimal overflow (last few digits discarded).");
5629 
5630 Final:
5631  if (ind_a >= ma) ind_a = ma - 1;
5632  while (j < BASE_FIG) {
5633  a->frac[ind_a] = a->frac[ind_a] * 10;
5634  ++j;
5635  }
5636  a->Prec = ind_a + 1;
5637  a->exponent = eb;
5638  VpSetSign(a, sign);
5639  VpNmlz(a);
5640  return 1;
5641 }
5642 
5643 /*
5644  * [Input]
5645  * *m ... Real
5646  * [Output]
5647  * *d ... fraction part of m(d = 0.xxxxxxx). where # of 'x's is fig.
5648  * *e ... exponent of m.
5649  * DBLE_FIG ... Number of digits in a double variable.
5650  *
5651  * m -> d*10**e, 0<d<BASE
5652  * [Returns]
5653  * 0 ... Zero
5654  * 1 ... Normal
5655  * 2 ... Infinity
5656  * -1 ... NaN
5657  */
5658 VP_EXPORT int
5659 VpVtoD(double *d, SIGNED_VALUE *e, Real *m)
5660 {
5661  size_t ind_m, mm, fig;
5662  double div;
5663  int f = 1;
5664 
5665  if (VpIsNaN(m)) {
5666  *d = VpGetDoubleNaN();
5667  *e = 0;
5668  f = -1; /* NaN */
5669  goto Exit;
5670  }
5671  else if (VpIsPosZero(m)) {
5672  *d = 0.0;
5673  *e = 0;
5674  f = 0;
5675  goto Exit;
5676  }
5677  else if (VpIsNegZero(m)) {
5678  *d = VpGetDoubleNegZero();
5679  *e = 0;
5680  f = 0;
5681  goto Exit;
5682  }
5683  else if (VpIsPosInf(m)) {
5684  *d = VpGetDoublePosInf();
5685  *e = 0;
5686  f = 2;
5687  goto Exit;
5688  }
5689  else if (VpIsNegInf(m)) {
5690  *d = VpGetDoubleNegInf();
5691  *e = 0;
5692  f = 2;
5693  goto Exit;
5694  }
5695  /* Normal number */
5696  fig = (DBLE_FIG + BASE_FIG - 1) / BASE_FIG;
5697  ind_m = 0;
5698  mm = Min(fig, m->Prec);
5699  *d = 0.0;
5700  div = 1.;
5701  while (ind_m < mm) {
5702  div /= (double)BASE;
5703  *d = *d + (double)m->frac[ind_m++] * div;
5704  }
5705  *e = m->exponent * (SIGNED_VALUE)BASE_FIG;
5706  *d *= VpGetSign(m);
5707 
5708 Exit:
5709 #ifdef BIGDECIMAL_DEBUG
5710  if (gfDebug) {
5711  VPrint(stdout, " VpVtoD: m=%\n", m);
5712  printf(" d=%e * 10 **%ld\n", *d, *e);
5713  printf(" DBLE_FIG = %d\n", DBLE_FIG);
5714  }
5715 #endif /*BIGDECIMAL_DEBUG */
5716  return f;
5717 }
5718 
5719 /*
5720  * m <- d
5721  */
5722 VP_EXPORT void
5723 VpDtoV(Real *m, double d)
5724 {
5725  size_t ind_m, mm;
5726  SIGNED_VALUE ne;
5727  BDIGIT i;
5728  double val, val2;
5729 
5730  if (isnan(d)) {
5731  VpSetNaN(m);
5732  goto Exit;
5733  }
5734  if (isinf(d)) {
5735  if (d > 0.0) VpSetPosInf(m);
5736  else VpSetNegInf(m);
5737  goto Exit;
5738  }
5739 
5740  if (d == 0.0) {
5741  VpSetZero(m, 1);
5742  goto Exit;
5743  }
5744  val = (d > 0.) ? d : -d;
5745  ne = 0;
5746  if (val >= 1.0) {
5747  while (val >= 1.0) {
5748  val /= (double)BASE;
5749  ++ne;
5750  }
5751  }
5752  else {
5753  val2 = 1.0 / (double)BASE;
5754  while (val < val2) {
5755  val *= (double)BASE;
5756  --ne;
5757  }
5758  }
5759  /* Now val = 0.xxxxx*BASE**ne */
5760 
5761  mm = m->MaxPrec;
5762  memset(m->frac, 0, mm * sizeof(BDIGIT));
5763  for (ind_m = 0; val > 0.0 && ind_m < mm; ind_m++) {
5764  val *= (double)BASE;
5765  i = (BDIGIT)val;
5766  val -= (double)i;
5767  m->frac[ind_m] = i;
5768  }
5769  if (ind_m >= mm) ind_m = mm - 1;
5770  VpSetSign(m, (d > 0.0) ? 1 : -1);
5771  m->Prec = ind_m + 1;
5772  m->exponent = ne;
5773 
5774  VpInternalRound(m, 0, (m->Prec > 0) ? m->frac[m->Prec-1] : 0,
5775  (BDIGIT)(val*(double)BASE));
5776 
5777 Exit:
5778 #ifdef BIGDECIMAL_DEBUG
5779  if (gfDebug) {
5780  printf("VpDtoV d=%30.30e\n", d);
5781  VPrint(stdout, " m=%\n", m);
5782  }
5783 #endif /* BIGDECIMAL_DEBUG */
5784  return;
5785 }
5786 
5787 /*
5788  * m <- ival
5789  */
5790 #if 0 /* unused */
5791 VP_EXPORT void
5792 VpItoV(Real *m, SIGNED_VALUE ival)
5793 {
5794  size_t mm, ind_m;
5795  size_t val, v1, v2, v;
5796  int isign;
5797  SIGNED_VALUE ne;
5798 
5799  if (ival == 0) {
5800  VpSetZero(m, 1);
5801  goto Exit;
5802  }
5803  isign = 1;
5804  val = ival;
5805  if (ival < 0) {
5806  isign = -1;
5807  val =(size_t)(-ival);
5808  }
5809  ne = 0;
5810  ind_m = 0;
5811  mm = m->MaxPrec;
5812  while (ind_m < mm) {
5813  m->frac[ind_m] = 0;
5814  ++ind_m;
5815  }
5816  ind_m = 0;
5817  while (val > 0) {
5818  if (val) {
5819  v1 = val;
5820  v2 = 1;
5821  while (v1 >= BASE) {
5822  v1 /= BASE;
5823  v2 *= BASE;
5824  }
5825  val = val - v2 * v1;
5826  v = v1;
5827  }
5828  else {
5829  v = 0;
5830  }
5831  m->frac[ind_m] = v;
5832  ++ind_m;
5833  ++ne;
5834  }
5835  m->Prec = ind_m - 1;
5836  m->exponent = ne;
5837  VpSetSign(m, isign);
5838  VpNmlz(m);
5839 
5840 Exit:
5841 #ifdef BIGDECIMAL_DEBUG
5842  if (gfDebug) {
5843  printf(" VpItoV i=%d\n", ival);
5844  VPrint(stdout, " m=%\n", m);
5845  }
5846 #endif /* BIGDECIMAL_DEBUG */
5847  return;
5848 }
5849 #endif
5850 
5851 /*
5852  * y = SQRT(x), y*y - x =>0
5853  */
5854 VP_EXPORT int
5856 {
5857  Real *f = NULL;
5858  Real *r = NULL;
5859  size_t y_prec;
5860  SIGNED_VALUE n, e;
5861  SIGNED_VALUE prec;
5862  ssize_t nr;
5863  double val;
5864 
5865  /* Zero or +Infinity ? */
5866  if (VpIsZero(x) || VpIsPosInf(x)) {
5867  VpAsgn(y,x,1);
5868  goto Exit;
5869  }
5870 
5871  /* Negative ? */
5872  if (BIGDECIMAL_NEGATIVE_P(x)) {
5873  VpSetNaN(y);
5874  return VpException(VP_EXCEPTION_OP, "sqrt of negative value", 0);
5875  }
5876 
5877  /* NaN ? */
5878  if (VpIsNaN(x)) {
5879  VpSetNaN(y);
5880  return VpException(VP_EXCEPTION_OP, "sqrt of 'NaN'(Not a Number)", 0);
5881  }
5882 
5883  /* One ? */
5884  if (VpIsOne(x)) {
5885  VpSetOne(y);
5886  goto Exit;
5887  }
5888 
5889  n = (SIGNED_VALUE)y->MaxPrec;
5890  if (x->MaxPrec > (size_t)n) n = (ssize_t)x->MaxPrec;
5891 
5892  /* allocate temporally variables */
5893  f = VpAlloc(y->MaxPrec * (BASE_FIG + 2), "#1");
5894  r = VpAlloc((n + n) * (BASE_FIG + 2), "#1");
5895 
5896  nr = 0;
5897  y_prec = y->MaxPrec;
5898 
5899  prec = x->exponent - (ssize_t)y_prec;
5900  if (x->exponent > 0)
5901  ++prec;
5902  else
5903  --prec;
5904 
5905  VpVtoD(&val, &e, x); /* val <- x */
5906  e /= (SIGNED_VALUE)BASE_FIG;
5907  n = e / 2;
5908  if (e - n * 2 != 0) {
5909  val /= BASE;
5910  n = (e + 1) / 2;
5911  }
5912  VpDtoV(y, sqrt(val)); /* y <- sqrt(val) */
5913  y->exponent += n;
5914  n = (SIGNED_VALUE)((DBLE_FIG + BASE_FIG - 1) / BASE_FIG);
5915  y->MaxPrec = Min((size_t)n , y_prec);
5916  f->MaxPrec = y->MaxPrec + 1;
5917  n = (SIGNED_VALUE)(y_prec * BASE_FIG);
5918  if (n < (SIGNED_VALUE)maxnr) n = (SIGNED_VALUE)maxnr;
5919  do {
5920  y->MaxPrec *= 2;
5921  if (y->MaxPrec > y_prec) y->MaxPrec = y_prec;
5922  f->MaxPrec = y->MaxPrec;
5923  VpDivd(f, r, x, y); /* f = x/y */
5924  VpAddSub(r, f, y, -1); /* r = f - y */
5925  VpMult(f, VpPt5, r); /* f = 0.5*r */
5926  if (VpIsZero(f)) goto converge;
5927  VpAddSub(r, f, y, 1); /* r = y + f */
5928  VpAsgn(y, r, 1); /* y = r */
5929  } while (++nr < n);
5930 
5931 #ifdef BIGDECIMAL_DEBUG
5932  if (gfDebug) {
5933  printf("ERROR(VpSqrt): did not converge within %ld iterations.\n", nr);
5934  }
5935 #endif /* BIGDECIMAL_DEBUG */
5936  y->MaxPrec = y_prec;
5937 
5938 converge:
5939  VpChangeSign(y, 1);
5940 #ifdef BIGDECIMAL_DEBUG
5941  if (gfDebug) {
5942  VpMult(r, y, y);
5943  VpAddSub(f, x, r, -1);
5944  printf("VpSqrt: iterations = %"PRIdSIZE"\n", nr);
5945  VPrint(stdout, " y =% \n", y);
5946  VPrint(stdout, " x =% \n", x);
5947  VPrint(stdout, " x-y*y = % \n", f);
5948  }
5949 #endif /* BIGDECIMAL_DEBUG */
5950  y->MaxPrec = y_prec;
5951 
5952 Exit:
5953  VpFree(f);
5954  VpFree(r);
5955  return 1;
5956 }
5957 
5958 /*
5959  * Round relatively from the decimal point.
5960  * f: rounding mode
5961  * nf: digit location to round from the decimal point.
5962  */
5963 VP_EXPORT int
5964 VpMidRound(Real *y, unsigned short f, ssize_t nf)
5965 {
5966  /* fracf: any positive digit under rounding position? */
5967  /* fracf_1further: any positive digits under one further than the rounding position? */
5968  /* exptoadd: number of digits needed to compensate negative nf */
5969  int fracf, fracf_1further;
5970  ssize_t n,i,ix,ioffset, exptoadd;
5971  BDIGIT v, shifter;
5972  BDIGIT div;
5973 
5974  nf += y->exponent * (ssize_t)BASE_FIG;
5975  exptoadd=0;
5976  if (nf < 0) {
5977  /* rounding position too left(large). */
5978  if (f != VP_ROUND_CEIL && f != VP_ROUND_FLOOR) {
5979  VpSetZero(y, VpGetSign(y)); /* truncate everything */
5980  return 0;
5981  }
5982  exptoadd = -nf;
5983  nf = 0;
5984  }
5985 
5986  ix = nf / (ssize_t)BASE_FIG;
5987  if ((size_t)ix >= y->Prec) return 0; /* rounding position too right(small). */
5988  v = y->frac[ix];
5989 
5990  ioffset = nf - ix*(ssize_t)BASE_FIG;
5991  n = (ssize_t)BASE_FIG - ioffset - 1;
5992  for (shifter = 1, i = 0; i < n; ++i) shifter *= 10;
5993 
5994  /* so the representation used (in y->frac) is an array of BDIGIT, where
5995  each BDIGIT contains a value between 0 and BASE-1, consisting of BASE_FIG
5996  decimal places.
5997 
5998  (that numbers of decimal places are typed as ssize_t is somewhat confusing)
5999 
6000  nf is now position (in decimal places) of the digit from the start of
6001  the array.
6002 
6003  ix is the position (in BDIGITS) of the BDIGIT containing the decimal digit,
6004  from the start of the array.
6005 
6006  v is the value of this BDIGIT
6007 
6008  ioffset is the number of extra decimal places along of this decimal digit
6009  within v.
6010 
6011  n is the number of decimal digits remaining within v after this decimal digit
6012  shifter is 10**n,
6013 
6014  v % shifter are the remaining digits within v
6015  v % (shifter * 10) are the digit together with the remaining digits within v
6016  v / shifter are the digit's predecessors together with the digit
6017  div = v / shifter / 10 is just the digit's precessors
6018  (v / shifter) - div*10 is just the digit, which is what v ends up being reassigned to.
6019  */
6020 
6021  fracf = (v % (shifter * 10) > 0);
6022  fracf_1further = ((v % shifter) > 0);
6023 
6024  v /= shifter;
6025  div = v / 10;
6026  v = v - div*10;
6027  /* now v is just the digit required.
6028  now fracf is whether the digit or any of the remaining digits within v are non-zero
6029  now fracf_1further is whether any of the remaining digits within v are non-zero
6030  */
6031 
6032  /* now check all the remaining BDIGITS for zero-ness a whole BDIGIT at a time.
6033  if we spot any non-zeroness, that means that we found a positive digit under
6034  rounding position, and we also found a positive digit under one further than
6035  the rounding position, so both searches (to see if any such non-zero digit exists)
6036  can stop */
6037 
6038  for (i = ix + 1; (size_t)i < y->Prec; i++) {
6039  if (y->frac[i] % BASE) {
6040  fracf = fracf_1further = 1;
6041  break;
6042  }
6043  }
6044 
6045  /* now fracf = does any positive digit exist under the rounding position?
6046  now fracf_1further = does any positive digit exist under one further than the
6047  rounding position?
6048  now v = the first digit under the rounding position */
6049 
6050  /* drop digits after pointed digit */
6051  memset(y->frac + ix + 1, 0, (y->Prec - (ix + 1)) * sizeof(BDIGIT));
6052 
6053  switch (f) {
6054  case VP_ROUND_DOWN: /* Truncate */
6055  break;
6056  case VP_ROUND_UP: /* Roundup */
6057  if (fracf) ++div;
6058  break;
6059  case VP_ROUND_HALF_UP:
6060  if (v>=5) ++div;
6061  break;
6062  case VP_ROUND_HALF_DOWN:
6063  if (v > 5 || (v == 5 && fracf_1further)) ++div;
6064  break;
6065  case VP_ROUND_CEIL:
6066  if (fracf && BIGDECIMAL_POSITIVE_P(y)) ++div;
6067  break;
6068  case VP_ROUND_FLOOR:
6069  if (fracf && BIGDECIMAL_NEGATIVE_P(y)) ++div;
6070  break;
6071  case VP_ROUND_HALF_EVEN: /* Banker's rounding */
6072  if (v > 5) ++div;
6073  else if (v == 5) {
6074  if (fracf_1further) {
6075  ++div;
6076  }
6077  else {
6078  if (ioffset == 0) {
6079  /* v is the first decimal digit of its BDIGIT;
6080  need to grab the previous BDIGIT if present
6081  to check for evenness of the previous decimal
6082  digit (which is same as that of the BDIGIT since
6083  base 10 has a factor of 2) */
6084  if (ix && (y->frac[ix-1] % 2)) ++div;
6085  }
6086  else {
6087  if (div % 2) ++div;
6088  }
6089  }
6090  }
6091  break;
6092  }
6093  for (i = 0; i <= n; ++i) div *= 10;
6094  if (div >= BASE) {
6095  if (ix) {
6096  y->frac[ix] = 0;
6097  VpRdup(y, ix);
6098  }
6099  else {
6100  short s = VpGetSign(y);
6101  SIGNED_VALUE e = y->exponent;
6102  VpSetOne(y);
6103  VpSetSign(y, s);
6104  y->exponent = e + 1;
6105  }
6106  }
6107  else {
6108  y->frac[ix] = div;
6109  VpNmlz(y);
6110  }
6111  if (exptoadd > 0) {
6112  y->exponent += (SIGNED_VALUE)(exptoadd / BASE_FIG);
6113  exptoadd %= (ssize_t)BASE_FIG;
6114  for (i = 0; i < exptoadd; i++) {
6115  y->frac[0] *= 10;
6116  if (y->frac[0] >= BASE) {
6117  y->frac[0] /= BASE;
6118  y->exponent++;
6119  }
6120  }
6121  }
6122  return 1;
6123 }
6124 
6125 VP_EXPORT int
6126 VpLeftRound(Real *y, unsigned short f, ssize_t nf)
6127 /*
6128  * Round from the left hand side of the digits.
6129  */
6130 {
6131  BDIGIT v;
6132  if (!VpHasVal(y)) return 0; /* Unable to round */
6133  v = y->frac[0];
6134  nf -= VpExponent(y) * (ssize_t)BASE_FIG;
6135  while ((v /= 10) != 0) nf--;
6136  nf += (ssize_t)BASE_FIG-1;
6137  return VpMidRound(y, f, nf);
6138 }
6139 
6140 VP_EXPORT int
6141 VpActiveRound(Real *y, Real *x, unsigned short f, ssize_t nf)
6142 {
6143  /* First,assign whole value in truncation mode */
6144  if (VpAsgn(y, x, 10) <= 1) return 0; /* Zero,NaN,or Infinity */
6145  return VpMidRound(y, f, nf);
6146 }
6147 
6148 static int
6149 VpLimitRound(Real *c, size_t ixDigit)
6150 {
6151  size_t ix = VpGetPrecLimit();
6152  if (!VpNmlz(c)) return -1;
6153  if (!ix) return 0;
6154  if (!ixDigit) ixDigit = c->Prec-1;
6155  if ((ix + BASE_FIG - 1) / BASE_FIG > ixDigit + 1) return 0;
6156  return VpLeftRound(c, VpGetRoundMode(), (ssize_t)ix);
6157 }
6158 
6159 /* If I understand correctly, this is only ever used to round off the final decimal
6160  digit of precision */
6161 static void
6162 VpInternalRound(Real *c, size_t ixDigit, BDIGIT vPrev, BDIGIT v)
6163 {
6164  int f = 0;
6165 
6166  unsigned short const rounding_mode = VpGetRoundMode();
6167 
6168  if (VpLimitRound(c, ixDigit)) return;
6169  if (!v) return;
6170 
6171  v /= BASE1;
6172  switch (rounding_mode) {
6173  case VP_ROUND_DOWN:
6174  break;
6175  case VP_ROUND_UP:
6176  if (v) f = 1;
6177  break;
6178  case VP_ROUND_HALF_UP:
6179  if (v >= 5) f = 1;
6180  break;
6181  case VP_ROUND_HALF_DOWN:
6182  /* this is ok - because this is the last digit of precision,
6183  the case where v == 5 and some further digits are nonzero
6184  will never occur */
6185  if (v >= 6) f = 1;
6186  break;
6187  case VP_ROUND_CEIL:
6188  if (v && BIGDECIMAL_POSITIVE_P(c)) f = 1;
6189  break;
6190  case VP_ROUND_FLOOR:
6191  if (v && BIGDECIMAL_NEGATIVE_P(c)) f = 1;
6192  break;
6193  case VP_ROUND_HALF_EVEN: /* Banker's rounding */
6194  /* as per VP_ROUND_HALF_DOWN, because this is the last digit of precision,
6195  there is no case to worry about where v == 5 and some further digits are nonzero */
6196  if (v > 5) f = 1;
6197  else if (v == 5 && vPrev % 2) f = 1;
6198  break;
6199  }
6200  if (f) {
6201  VpRdup(c, ixDigit);
6202  VpNmlz(c);
6203  }
6204 }
6205 
6206 /*
6207  * Rounds up m(plus one to final digit of m).
6208  */
6209 static int
6210 VpRdup(Real *m, size_t ind_m)
6211 {
6212  BDIGIT carry;
6213 
6214  if (!ind_m) ind_m = m->Prec;
6215 
6216  carry = 1;
6217  while (carry > 0 && ind_m--) {
6218  m->frac[ind_m] += carry;
6219  if (m->frac[ind_m] >= BASE) m->frac[ind_m] -= BASE;
6220  else carry = 0;
6221  }
6222  if (carry > 0) { /* Overflow,count exponent and set fraction part be 1 */
6223  if (!AddExponent(m, 1)) return 0;
6224  m->Prec = m->frac[0] = 1;
6225  }
6226  else {
6227  VpNmlz(m);
6228  }
6229  return 1;
6230 }
6231 
6232 /*
6233  * y = x - fix(x)
6234  */
6235 VP_EXPORT void
6237 {
6238  size_t my, ind_y, ind_x;
6239 
6240  if (!VpHasVal(x)) {
6241  VpAsgn(y, x, 1);
6242  goto Exit;
6243  }
6244 
6245  if (x->exponent > 0 && (size_t)x->exponent >= x->Prec) {
6246  VpSetZero(y, VpGetSign(x));
6247  goto Exit;
6248  }
6249  else if (x->exponent <= 0) {
6250  VpAsgn(y, x, 1);
6251  goto Exit;
6252  }
6253 
6254  /* satisfy: x->exponent > 0 */
6255 
6256  y->Prec = x->Prec - (size_t)x->exponent;
6257  y->Prec = Min(y->Prec, y->MaxPrec);
6258  y->exponent = 0;
6259  VpSetSign(y, VpGetSign(x));
6260  ind_y = 0;
6261  my = y->Prec;
6262  ind_x = x->exponent;
6263  while (ind_y < my) {
6264  y->frac[ind_y] = x->frac[ind_x];
6265  ++ind_y;
6266  ++ind_x;
6267  }
6268  VpNmlz(y);
6269 
6270 Exit:
6271 #ifdef BIGDECIMAL_DEBUG
6272  if (gfDebug) {
6273  VPrint(stdout, "VpFrac y=%\n", y);
6274  VPrint(stdout, " x=%\n", x);
6275  }
6276 #endif /* BIGDECIMAL_DEBUG */
6277  return;
6278 }
6279 
6280 /*
6281  * y = x ** n
6282  */
6283 VP_EXPORT int
6285 {
6286  size_t s, ss;
6287  ssize_t sign;
6288  Real *w1 = NULL;
6289  Real *w2 = NULL;
6290 
6291  if (VpIsZero(x)) {
6292  if (n == 0) {
6293  VpSetOne(y);
6294  goto Exit;
6295  }
6296  sign = VpGetSign(x);
6297  if (n < 0) {
6298  n = -n;
6299  if (sign < 0) sign = (n % 2) ? -1 : 1;
6300  VpSetInf(y, sign);
6301  }
6302  else {
6303  if (sign < 0) sign = (n % 2) ? -1 : 1;
6304  VpSetZero(y,sign);
6305  }
6306  goto Exit;
6307  }
6308  if (VpIsNaN(x)) {
6309  VpSetNaN(y);
6310  goto Exit;
6311  }
6312  if (VpIsInf(x)) {
6313  if (n == 0) {
6314  VpSetOne(y);
6315  goto Exit;
6316  }
6317  if (n > 0) {
6318  VpSetInf(y, (n % 2 == 0 || VpIsPosInf(x)) ? 1 : -1);
6319  goto Exit;
6320  }
6321  VpSetZero(y, (n % 2 == 0 || VpIsPosInf(x)) ? 1 : -1);
6322  goto Exit;
6323  }
6324 
6325  if (x->exponent == 1 && x->Prec == 1 && x->frac[0] == 1) {
6326  /* abs(x) = 1 */
6327  VpSetOne(y);
6328  if (BIGDECIMAL_POSITIVE_P(x)) goto Exit;
6329  if ((n % 2) == 0) goto Exit;
6330  VpSetSign(y, -1);
6331  goto Exit;
6332  }
6333 
6334  if (n > 0) sign = 1;
6335  else if (n < 0) {
6336  sign = -1;
6337  n = -n;
6338  }
6339  else {
6340  VpSetOne(y);
6341  goto Exit;
6342  }
6343 
6344  /* Allocate working variables */
6345 
6346  w1 = VpAlloc((y->MaxPrec + 2) * BASE_FIG, "#0");
6347  w2 = VpAlloc((w1->MaxPrec * 2 + 1) * BASE_FIG, "#0");
6348  /* calculation start */
6349 
6350  VpAsgn(y, x, 1);
6351  --n;
6352  while (n > 0) {
6353  VpAsgn(w1, x, 1);
6354  s = 1;
6355  while (ss = s, (s += s) <= (size_t)n) {
6356  VpMult(w2, w1, w1);
6357  VpAsgn(w1, w2, 1);
6358  }
6359  n -= (SIGNED_VALUE)ss;
6360  VpMult(w2, y, w1);
6361  VpAsgn(y, w2, 1);
6362  }
6363  if (sign < 0) {
6364  VpDivd(w1, w2, VpConstOne, y);
6365  VpAsgn(y, w1, 1);
6366  }
6367 
6368 Exit:
6369 #ifdef BIGDECIMAL_DEBUG
6370  if (gfDebug) {
6371  VPrint(stdout, "VpPower y=%\n", y);
6372  VPrint(stdout, "VpPower x=%\n", x);
6373  printf(" n=%"PRIdVALUE"\n", n);
6374  }
6375 #endif /* BIGDECIMAL_DEBUG */
6376  VpFree(w2);
6377  VpFree(w1);
6378  return 1;
6379 }
6380 
6381 #ifdef BIGDECIMAL_DEBUG
6382 int
6383 VpVarCheck(Real * v)
6384 /*
6385  * Checks the validity of the Real variable v.
6386  * [Input]
6387  * v ... Real *, variable to be checked.
6388  * [Returns]
6389  * 0 ... correct v.
6390  * other ... error
6391  */
6392 {
6393  size_t i;
6394 
6395  if (v->MaxPrec == 0) {
6396  printf("ERROR(VpVarCheck): Illegal Max. Precision(=%"PRIuSIZE")\n",
6397  v->MaxPrec);
6398  return 1;
6399  }
6400  if (v->Prec == 0 || v->Prec > v->MaxPrec) {
6401  printf("ERROR(VpVarCheck): Illegal Precision(=%"PRIuSIZE")\n", v->Prec);
6402  printf(" Max. Prec.=%"PRIuSIZE"\n", v->MaxPrec);
6403  return 2;
6404  }
6405  for (i = 0; i < v->Prec; ++i) {
6406  if (v->frac[i] >= BASE) {
6407  printf("ERROR(VpVarCheck): Illegal fraction\n");
6408  printf(" Frac[%"PRIuSIZE"]=%"PRIuBDIGIT"\n", i, v->frac[i]);
6409  printf(" Prec. =%"PRIuSIZE"\n", v->Prec);
6410  printf(" Exp. =%"PRIdVALUE"\n", v->exponent);
6411  printf(" BASE =%"PRIuBDIGIT"\n", BASE);
6412  return 3;
6413  }
6414  }
6415  return 0;
6416 }
6417 #endif /* BIGDECIMAL_DEBUG */
VP_EXPORT size_t VpDivd(Real *c, Real *r, Real *a, Real *b)
Definition: bigdecimal.c:4808
VP_EXPORT void VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
Definition: bigdecimal.c:5385
void rb_fatal(const char *fmt,...)
Definition: error.c:2338
VP_EXPORT double VpGetDoublePosInf(void)
Definition: bigdecimal.c:3722
#define T_SYMBOL
Definition: ruby.h:508
#define ISDIGIT(c)
Definition: ruby.h:2150
#define Max(a, b)
Definition: bigdecimal.h:336
#define RMPD_EXCEPTION_MODE_DEFAULT
Definition: bigdecimal.h:202
#define PUSH(x)
Definition: bigdecimal.c:69
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *pstate)
Protects a function call from potential global escapes from the function.
Definition: eval.c:992
SIGNED_VALUE exponent
Definition: bigdecimal.h:242
void rb_warn(const char *fmt,...)
Definition: error.c:246
void rb_bug(const char *fmt,...)
Definition: error.c:521
VP_EXPORT int VpException(unsigned short f, const char *str, int always)
Definition: bigdecimal.c:3755
#define id_ceil
Definition: rational.c:1638
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1138
#define Min(a, b)
Definition: bigdecimal.h:337
size_t strlen(const char *)
#define INT2NUM(x)
Definition: ruby.h:1538
#define VP_ROUND_HALF_UP
Definition: bigdecimal.h:208
#define T_FIXNUM
Definition: ruby.h:503
VALUE rb_Rational(VALUE, VALUE)
Definition: rational.c:1979
#define SAVE(p)
Definition: bigdecimal.c:70
#define NUM2INT(x)
Definition: ruby.h:684
#define BigMath_exp(x, n)
Definition: bigdecimal.c:2189
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1716
#define VP_ROUND_DOWN
Definition: bigdecimal.h:207
#define DBL_DIG
Definition: numeric.c:54
VALUE obj
Definition: bigdecimal.h:235
VP_EXPORT int VpIsRoundMode(unsigned short n)
Definition: bigdecimal.c:3649
#define VP_ROUND_FLOOR
Definition: bigdecimal.h:211
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2284
#define VpIsInf(a)
Definition: bigdecimal.h:370
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
Definition: eval.c:821
#define VP_SIGN_POSITIVE_FINITE
Definition: bigdecimal.h:219
#define VpIsDef(a)
Definition: bigdecimal.h:371
#define Qtrue
Definition: ruby.h:437
void rb_big_pack(VALUE val, unsigned long *buf, long num_longs)
Definition: bignum.c:3197
#define VP_SIGN_NEGATIVE_ZERO
Definition: bigdecimal.h:218
#define TypedData_Wrap_Struct(klass, data_type, sval)
Definition: ruby.h:1162
const int id
Definition: nkf.c:209
#define DECIMAL_SIZE_OF_BITS(n)
Definition: util.h:50
#define T_RATIONAL
Definition: ruby.h:509
#define UNREACHABLE
Definition: ruby.h:46
#define isfinite(x)
Definition: missing.h:180
#define VpMaxPrec(a)
Definition: bigdecimal.h:339
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:924
#define VpSetNaN(a)
Definition: bigdecimal.h:365
size_t Prec
Definition: bigdecimal.h:239
if(len<=MAX_WORD_LENGTH &&len >=MIN_WORD_LENGTH)
Definition: zonetab.h:883
RUBY_EXTERN VALUE rb_eMathDomainError
Definition: ruby.h:1969
#define SYM2ID(x)
Definition: ruby.h:384
st_index_t rb_memhash(const void *ptr, long len)
Definition: random.c:1512
VP_EXPORT unsigned short VpGetRoundMode(void)
Definition: bigdecimal.c:3633
VP_EXPORT unsigned short VpSetRoundMode(unsigned short n)
Definition: bigdecimal.c:3667
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:774
VP_EXPORT void VpDtoV(Real *m, double d)
Definition: bigdecimal.c:5723
#define is_positive(x)
Definition: bigdecimal.c:2213
VP_EXPORT void VpFrac(Real *y, Real *x)
Definition: bigdecimal.c:6236
#define VP_SIGN_POSITIVE_ZERO
Definition: bigdecimal.h:217
#define RB_GC_GUARD(v)
Definition: ruby.h:552
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
#define T_HASH
Definition: ruby.h:499
#define DATA_PTR(dta)
Definition: ruby.h:1106
#define VP_ROUND_HALF_DOWN
Definition: bigdecimal.h:209
#define VP_SIGN_POSITIVE_INFINITE
Definition: bigdecimal.h:221
#define VP_EXCEPTION_OVERFLOW
Definition: bigdecimal.h:195
#define VpIsPosInf(a)
Definition: bigdecimal.h:368
#define RRATIONAL_NEGATIVE_P(x)
Definition: bigdecimal.c:89
st_data_t st_index_t
Definition: st.h:50
VP_EXPORT Real * VpCreateRbObject(size_t mx, const char *str)
Definition: bigdecimal.c:670
VP_EXPORT int VpVtoD(double *d, SIGNED_VALUE *e, Real *m)
Definition: bigdecimal.c:5659
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:1745
#define FIXNUM_P(f)
Definition: ruby.h:365
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:656
#define SSIZET2NUM(v)
Definition: ruby.h:265
#define strncasecmp
Definition: win32.h:192
VALUE rb_str_tmp_new(long)
Definition: string.c:1310
RUBY_EXTERN VALUE rb_eZeroDivError
Definition: ruby.h:1953
#define DoSomeOne(x, y, f)
Definition: bigdecimal.c:136
VP_EXPORT int VpComp(Real *a, Real *b)
Definition: bigdecimal.c:5061
#define NUM2USHORT(x)
Definition: ruby.h:707
#define VpIsPosZero(a)
Definition: bigdecimal.h:356
#define rb_ary_new2
Definition: intern.h:90
VP_EXPORT int VpMidRound(Real *y, unsigned short f, ssize_t nf)
Definition: bigdecimal.c:5964
VP_EXPORT int VpCtoV(Real *a, const char *int_chr, size_t ni, const char *frac, size_t nf, const char *exp_chr, size_t ne)
Definition: bigdecimal.c:5499
VP_EXPORT int VpActiveRound(Real *y, Real *x, unsigned short f, ssize_t nf)
Definition: bigdecimal.c:6141
RUBY_EXTERN void * memmove(void *, const void *, size_t)
Definition: memmove.c:7
#define VpBaseVal()
Definition: bigdecimal.h:277
#define VP_EXCEPTION_INFINITY
Definition: bigdecimal.h:192
VALUE rb_thread_local_aref(VALUE, ID)
Definition: thread.c:3013
VALUE rb_eArgError
Definition: error.c:802
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:759
#define SZ_INF
Definition: bigdecimal.h:180
VP_EXPORT Real * VpNewRbClass(size_t mx, const char *str, VALUE klass)
Definition: bigdecimal.c:660
#define DBL_MAX_10_EXP
Definition: numeric.c:51
#define strtod(s, e)
Definition: util.h:77
#define VP_SIGN_NEGATIVE_FINITE
Definition: bigdecimal.h:220
VALUE rb_obj_class(VALUE)
call-seq: obj.class -> class
Definition: object.c:277
#define RB_TYPE_P(obj, type)
Definition: ruby.h:527
#define MUL_OVERFLOW_SIGNED_VALUE_P(a, b)
Definition: bigdecimal.c:43
#define VpIsNaN(a)
Definition: bigdecimal.h:364
#define div(x, y)
Definition: date_strftime.c:27
VALUE rb_class_name(VALUE)
Definition: variable.c:444
VALUE rb_dbl2big(double d)
Definition: bignum.c:5214
#define RMPD_COMPONENT_FIGURES
Definition: bigdecimal.h:168
NORETURN(static void cannot_be_coerced_into_BigDecimal(VALUE, VALUE))
#define val
#define VP_EXCEPTION_UNDERFLOW
Definition: bigdecimal.h:194
#define ne(x, y)
Definition: time.c:72
#define rb_float_new(d)
Definition: internal.h:1449
#define SZ_NINF
Definition: bigdecimal.h:182
#define PRIdVALUE
Definition: ruby.h:130
#define VpExponent(a)
Definition: bigdecimal.h:377
VALUE rb_str_cat2(VALUE, const char *)
VALUE rb_big_cmp(VALUE x, VALUE y)
Definition: bignum.c:5367
#define VP_EXPORT
Definition: bigdecimal.h:188
#define rmpd_set_thread_local_exception_mode(mode)
Definition: bigdecimal.c:3555
#define snprintf
Definition: subst.h:6
VALUE rb_thread_current(void)
Definition: thread.c:2494
#define RRATIONAL(obj)
Definition: internal.h:630
#define HALF_BASE
Definition: bigdecimal.c:76
#define NIL_P(v)
Definition: ruby.h:451
VP_EXPORT double VpGetDoubleNaN(void)
Definition: bigdecimal.c:3714
VP_EXPORT size_t VpGetPrecLimit(void)
Definition: bigdecimal.c:3598
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:646
#define VpIsOne(a)
Definition: bigdecimal.h:376
VP_EXPORT void * VpMemAlloc(size_t mb)
Definition: bigdecimal.c:3509
#define BDIGIT_DBL_SIGNED
Definition: bigdecimal.h:50
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2691
#define VpAllocReal(prec)
Definition: bigdecimal.c:675
VP_EXPORT size_t VpMult(Real *c, Real *a, Real *b)
Definition: bigdecimal.c:4679
#define ENTER(n)
Definition: bigdecimal.c:68
#define T_FLOAT
Definition: ruby.h:495
#define TYPE(x)
Definition: ruby.h:521
int argc
Definition: ruby.c:187
volatile const double gOne_ABCED9B4_CE73__00400511F31D
Definition: bigdecimal.c:3686
#define Qfalse
Definition: ruby.h:436
VP_EXPORT void VpToFString(Real *a, char *psz, size_t fFmt, int fPlus)
Definition: bigdecimal.c:5433
#define T_BIGNUM
Definition: ruby.h:501
#define MEMCPY(p1, p2, type, n)
Definition: ruby.h:1661
RUBY_EXTERN int isinf(double)
Definition: isinf.c:56
VP_EXPORT Real * VpOne(void)
Definition: bigdecimal.c:3957
#define rb_str_new2
Definition: intern.h:835
#define BIGDECIMAL_POSITIVE_P(bd)
Definition: bigdecimal.c:130
VP_EXPORT void VpSzMantissa(Real *a, char *psz)
Definition: bigdecimal.c:5303
#define T_COMPLEX
Definition: ruby.h:510
#define VpDblFig()
Definition: bigdecimal.h:276
VALUE rb_big2str(VALUE x, int base)
Definition: bignum.c:5062
#define id_to_r
Definition: rational.c:2005
short flag
Definition: bigdecimal.h:253
VP_EXPORT void VpFree(Real *pv)
Definition: bigdecimal.c:3533
void Init_bigdecimal(void)
Definition: bigdecimal.c:3245
VALUE rb_str_resize(VALUE, long)
Definition: string.c:2644
#define VpSetInf(a, s)
Definition: bigdecimal.h:374
#define VpSetSign(a, s)
Definition: bigdecimal.h:350
#define VP_EXCEPTION_ZERODIVIDE
Definition: bigdecimal.h:196
volatile const double gZero_ABCED9B1_CE73__00400511F31D
Definition: bigdecimal.c:3685
#define RSTRING_LEN(str)
Definition: ruby.h:971
VALUE rb_yield(VALUE)
Definition: vm_eval.c:973
#define VpSetPosInf(a)
Definition: bigdecimal.h:372
int errno
#define T_DATA
Definition: ruby.h:506
#define vabs
Definition: bigdecimal.h:149
#define VpBaseFig()
Definition: bigdecimal.h:275
#define VP_SIGN_NEGATIVE_INFINITE
Definition: bigdecimal.h:222
#define rb_Rational1(x)
Definition: intern.h:169
#define id_eq
Definition: numeric.c:176
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1908
VP_EXPORT Real * VpAlloc(size_t mx, const char *szVal)
Definition: bigdecimal.c:4014
#define rmpd_set_thread_local_rounding_mode(mode)
Definition: bigdecimal.c:3625
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4309
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:639
#define PRIsVALUE
Definition: ruby.h:135
unsigned long ID
Definition: ruby.h:86
#define Qnil
Definition: ruby.h:438
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition: eval.c:615
#define VP_ROUND_UP
Definition: bigdecimal.h:206
#define VP_EXCEPTION_MEMORY
Definition: bigdecimal.h:200
#define MemCmp(x, y, z)
Definition: bigdecimal.c:3485
unsigned long VALUE
Definition: ruby.h:85
#define VP_SIGN_NaN
Definition: bigdecimal.h:216
#define BIGDECIMAL_NEGATIVE_P(bd)
Definition: bigdecimal.c:131
#define StrCmp(x, y)
Definition: bigdecimal.c:3486
VP_EXPORT size_t VpInit(BDIGIT BaseVal)
Definition: bigdecimal.c:3926
VALUE rb_eTypeError
Definition: error.c:801
#define FIX2INT(x)
Definition: ruby.h:686
VALUE rb_num_coerce_relop(VALUE, VALUE, ID)
Definition: numeric.c:488
#define maxnr
Definition: bigdecimal.c:3481
#define isnan(x)
Definition: win32.h:346
RUBY_EXTERN VALUE rb_cNumeric
Definition: ruby.h:1919
short sign
Definition: bigdecimal.h:243
VALUE rb_str_dup(VALUE)
Definition: string.c:1488
#define FIXABLE(f)
Definition: ruby.h:368
VP_EXPORT double VpGetDoubleNegInf(void)
Definition: bigdecimal.c:3730
#define CHAR_BIT
Definition: ruby.h:196
#define LONG2NUM(x)
Definition: ruby.h:1573
register unsigned int len
Definition: zonetab.h:51
#define StringValueCStr(v)
Definition: ruby.h:571
#define VpIsNegInf(a)
Definition: bigdecimal.h:369
VP_EXPORT size_t VpAsgn(Real *c, Real *a, int isw)
Definition: bigdecimal.c:4180
#define RSTRING_PTR(str)
Definition: ruby.h:975
VALUE rb_cBigDecimal
Definition: bigdecimal.c:45
#define rb_exc_new3
Definition: intern.h:244
#define VP_EXCEPTION_NaN
Definition: bigdecimal.h:193
BDIGIT frac[FLEXIBLE_ARRAY_SIZE]
Definition: bigdecimal.h:254
#define RMPD_PRECISION_LIMIT_DEFAULT
Definition: bigdecimal.c:3594
#define rmpd_set_thread_local_precision_limit(limit)
Definition: bigdecimal.c:3588
#define RFLOAT_VALUE(v)
Definition: ruby.h:933
#define f
VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
Definition: hash.c:842
#define INT2FIX(i)
Definition: ruby.h:232
#define VpChangeSign(a, s)
Definition: bigdecimal.h:348
#define RARRAY_AREF(a, i)
Definition: ruby.h:1033
#define NUM2SSIZET(x)
Definition: ruby.h:739
RUBY_EXTERN double round(double)
Definition: numeric.c:79
#define RB_OBJ_CLASSNAME(obj)
Definition: bigdecimal.c:98
#define xmalloc
Definition: defines.h:183
#define NUM2SIZET(x)
Definition: ruby.h:738
VP_EXPORT int VpToSpecialString(Real *a, char *psz, int fPlus)
Definition: bigdecimal.c:5350
#define RMPD_ROUNDING_MODE_DEFAULT
Definition: bigdecimal.h:214
#define VpIsNegZero(a)
Definition: bigdecimal.h:357
#define VpGetSign(a)
Definition: bigdecimal.h:346
VP_EXPORT int VpLeftRound(Real *y, unsigned short f, ssize_t nf)
Definition: bigdecimal.c:6126
VP_EXPORT size_t VpAddSub(Real *c, Real *a, Real *b, int operation)
Definition: bigdecimal.c:4224
#define VpIsZero(a)
Definition: bigdecimal.h:358
#define DBL_MIN_10_EXP
Definition: numeric.c:48
VALUE rb_check_string_type(VALUE)
Definition: string.c:2246
#define LONG2FIX(i)
Definition: ruby.h:234
#define VpSetOne(a)
Definition: bigdecimal.h:353
#define SZ_NaN
Definition: bigdecimal.h:179
#define SIZEOF_VALUE
Definition: ruby.h:88
#define BDIGIT_DBL
Definition: bigdecimal.h:49
#define RTEST(v)
Definition: ruby.h:450
void rb_thread_check_ints(void)
Definition: thread.c:1219
#define T_STRING
Definition: ruby.h:496
#define DBLE_FIG
Definition: bigdecimal.c:80
#define PRIuSIZE
Definition: ruby.h:177
void rb_check_safe_obj(VALUE)
Definition: safe.c:117
op_sw
Definition: bigdecimal.c:3488
VP_EXPORT int VpPower(Real *y, Real *x, SIGNED_VALUE n)
Definition: bigdecimal.c:6284
#define assert
Definition: ruby_assert.h:37
#define SIGNED_VALUE_MAX
Definition: bigdecimal.c:41
#define BASE_FIG
Definition: bigdecimal.c:73
#define BASE1
Definition: bigdecimal.c:77
#define PRIdSIZE
Definition: ruby.h:174
#define VpSetZero(a, s)
Definition: bigdecimal.h:361
#define VpSetNegInf(a)
Definition: bigdecimal.h:373
#define xrealloc
Definition: defines.h:186
#define ID2SYM(x)
Definition: ruby.h:383
#define VP_ROUND_HALF_EVEN
Definition: bigdecimal.h:212
VP_EXPORT size_t VpSetPrecLimit(size_t n)
Definition: bigdecimal.c:3614
RUBY_EXTERN VALUE rb_eFloatDomainError
Definition: ruby.h:1957
#define RRATIONAL_ZERO_P(x)
Definition: bigdecimal.c:84
#define BigMath_log(x, n)
Definition: bigdecimal.c:2190
#define BASE
Definition: bigdecimal.c:74
#define SZ_PINF
Definition: bigdecimal.h:181
#define RTYPEDDATA_DATA(v)
Definition: ruby.h:1110
VP_EXPORT size_t VpNumOfChars(Real *vp, const char *pszFmt)
Definition: bigdecimal.c:3882
#define VpHasVal(a)
Definition: bigdecimal.h:375
#define rb_intern_const(str)
Definition: ruby.h:1777
void void xfree(void *)
#define VP_EXCEPTION_OP
Definition: bigdecimal.h:199
VALUE rb_define_module(const char *name)
Definition: class.c:768
#define rb_intern(str)
#define PRIuBDIGIT
Definition: bigdecimal.h:59
#define VP_ROUND_MODE
Definition: bigdecimal.h:205
#define SYMBOL_P(x)
Definition: ruby.h:382
#define mod(x, y)
Definition: date_strftime.c:28
VP_EXPORT double VpGetDoubleNegZero(void)
Definition: bigdecimal.c:3738
VALUE rb_mBigMath
Definition: bigdecimal.c:46
#define NULL
Definition: _sdbm.c:102
#define FIX2LONG(x)
Definition: ruby.h:363
#define Qundef
Definition: ruby.h:439
#define VpReallocReal(ptr, prec)
Definition: bigdecimal.c:676
#define VP_EXCEPTION_ALL
Definition: bigdecimal.h:191
#define ST2FIX(h)
Definition: ruby_missing.h:21
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1515
VP_EXPORT void * VpMemRealloc(void *ptr, size_t mb)
Definition: bigdecimal.c:3523
#define bp()
Definition: vm_debug.h:25
VP_EXPORT ssize_t VpExponent10(Real *a)
Definition: bigdecimal.c:5286
#define BDIGIT
Definition: bigdecimal.h:48
#define VP_ROUND_CEIL
Definition: bigdecimal.h:210
size_t MaxPrec
Definition: bigdecimal.h:236
void * rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type)
Definition: error.c:769
char ** argv
Definition: ruby.c:188
#define ISSPACE(c)
Definition: ruby.h:2145
VALUE rb_num_coerce_cmp(VALUE, VALUE, ID)
Definition: numeric.c:480
#define rb_sym2str(sym)
Definition: console.c:107
VALUE rb_str_new(const char *, long)
Definition: string.c:737
#define SIGNED_VALUE
Definition: ruby.h:87
#define GUARD_OBJ(p, y)
Definition: bigdecimal.c:71
VP_EXPORT int VpSqrt(Real *y, Real *x)
Definition: bigdecimal.c:5855