ext/bigdecimal/bigdecimal.c

Go to the documentation of this file.
00001 /*
00002  *
00003  * Ruby BigDecimal(Variable decimal precision) extension library.
00004  *
00005  * Copyright(C) 2002 by Shigeo Kobayashi(shigeo@tinyforest.gr.jp)
00006  *
00007  * You may distribute under the terms of either the GNU General Public
00008  * License or the Artistic License, as specified in the README file
00009  * of this BigDecimal distribution.
00010  *
00011  *  NOTE: Change log in this source removed to reduce source code size.
00012  *        See rev. 1.25 if needed.
00013  *
00014  */
00015 
00016 /* #define BIGDECIMAL_DEBUG 1 */
00017 #ifdef BIGDECIMAL_DEBUG
00018 # define BIGDECIMAL_ENABLE_VPRINT 1
00019 #endif
00020 #include "bigdecimal.h"
00021 
00022 #ifndef BIGDECIMAL_DEBUG
00023 # define NDEBUG
00024 #endif
00025 #include <assert.h>
00026 
00027 #include <ctype.h>
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <string.h>
00031 #include <errno.h>
00032 #include <math.h>
00033 #include "math.h"
00034 
00035 #ifdef HAVE_IEEEFP_H
00036 #include <ieeefp.h>
00037 #endif
00038 
00039 /* #define ENABLE_NUMERIC_STRING */
00040 
00041 #define MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max) ( \
00042     (a) == 0 ? 0 : \
00043     (a) == -1 ? (b) < -(max) : \
00044     (a) > 0 ? \
00045       ((b) > 0 ? (max) / (a) < (b) : (min) / (a) > (b)) : \
00046       ((b) > 0 ? (min) / (a) < (b) : (max) / (a) > (b)))
00047 #define SIGNED_VALUE_MAX INTPTR_MAX
00048 #define SIGNED_VALUE_MIN INTPTR_MIN
00049 #define MUL_OVERFLOW_SIGNED_VALUE_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, SIGNED_VALUE_MIN, SIGNED_VALUE_MAX)
00050 
00051 VALUE rb_cBigDecimal;
00052 VALUE rb_mBigMath;
00053 
00054 static ID id_BigDecimal_exception_mode;
00055 static ID id_BigDecimal_rounding_mode;
00056 static ID id_BigDecimal_precision_limit;
00057 
00058 static ID id_up;
00059 static ID id_down;
00060 static ID id_truncate;
00061 static ID id_half_up;
00062 static ID id_default;
00063 static ID id_half_down;
00064 static ID id_half_even;
00065 static ID id_banker;
00066 static ID id_ceiling;
00067 static ID id_ceil;
00068 static ID id_floor;
00069 static ID id_to_r;
00070 static ID id_eq;
00071 
00072 /* MACRO's to guard objects from GC by keeping them in stack */
00073 #define ENTER(n) volatile VALUE RB_UNUSED_VAR(vStack[n]);int iStack=0
00074 #define PUSH(x)  vStack[iStack++] = (VALUE)(x);
00075 #define SAVE(p)  PUSH(p->obj);
00076 #define GUARD_OBJ(p,y) {p=y;SAVE(p);}
00077 
00078 #define BASE_FIG  RMPD_COMPONENT_FIGURES
00079 #define BASE      RMPD_BASE
00080 
00081 #define HALF_BASE (BASE/2)
00082 #define BASE1 (BASE/10)
00083 
00084 #ifndef DBLE_FIG
00085 #define DBLE_FIG (DBL_DIG+1)    /* figure of double */
00086 #endif
00087 
00088 #ifndef RBIGNUM_ZERO_P
00089 # define RBIGNUM_ZERO_P(x) rb_bigzero_p(x)
00090 #endif
00091 
00092 #ifndef RRATIONAL_ZERO_P
00093 # define RRATIONAL_ZERO_P(x) (FIXNUM_P(RRATIONAL(x)->num) && \
00094                               FIX2LONG(RRATIONAL(x)->num) == 0)
00095 #endif
00096 
00097 #ifndef RRATIONAL_NEGATIVE_P
00098 # define RRATIONAL_NEGATIVE_P(x) RTEST(rb_funcall((x), '<', 1, INT2FIX(0)))
00099 #endif
00100 
00101 /*
00102  * ================== Ruby Interface part ==========================
00103  */
00104 #define DoSomeOne(x,y,f) rb_num_coerce_bin(x,y,f)
00105 
00106 /*
00107  * Returns the BigDecimal version number.
00108  */
00109 static VALUE
00110 BigDecimal_version(VALUE self)
00111 {
00112     /*
00113      * 1.0.0: Ruby 1.8.0
00114      * 1.0.1: Ruby 1.8.1
00115      * 1.1.0: Ruby 1.9.3
00116     */
00117     return rb_str_new2("1.1.0");
00118 }
00119 
00120 /*
00121  *   VP routines used in BigDecimal part
00122  */
00123 static unsigned short VpGetException(void);
00124 static void  VpSetException(unsigned short f);
00125 static void  VpInternalRound(Real *c, size_t ixDigit, BDIGIT vPrev, BDIGIT v);
00126 static int   VpLimitRound(Real *c, size_t ixDigit);
00127 static Real *VpCopy(Real *pv, Real const* const x);
00128 
00129 #ifdef BIGDECIMAL_ENABLE_VPRINT
00130 static int VPrint(FILE *fp,const char *cntl_chr,Real *a);
00131 #endif
00132 
00133 /*
00134  *  **** BigDecimal part ****
00135  */
00136 
00137 static void
00138 BigDecimal_delete(void *pv)
00139 {
00140     VpFree(pv);
00141 }
00142 
00143 static size_t
00144 BigDecimal_memsize(const void *ptr)
00145 {
00146     const Real *pv = ptr;
00147     return pv ? (sizeof(*pv) + pv->MaxPrec * sizeof(BDIGIT)) : 0;
00148 }
00149 
00150 static const rb_data_type_t BigDecimal_data_type = {
00151     "BigDecimal",
00152     { 0, BigDecimal_delete, BigDecimal_memsize, },
00153 #ifdef RUBY_TYPED_FREE_IMMEDIATELY
00154     NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
00155 #endif
00156 };
00157 
00158 static inline int
00159 is_kind_of_BigDecimal(VALUE const v)
00160 {
00161     return rb_typeddata_is_kind_of(v, &BigDecimal_data_type);
00162 }
00163 
00164 static VALUE
00165 ToValue(Real *p)
00166 {
00167     if (VpIsNaN(p)) {
00168         VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'(Not a Number)", 0);
00169     }
00170     else if (VpIsPosInf(p)) {
00171         VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 0);
00172     }
00173     else if (VpIsNegInf(p)) {
00174         VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 0);
00175     }
00176     return p->obj;
00177 }
00178 
00179 NORETURN(static void cannot_be_coerced_into_BigDecimal(VALUE, VALUE));
00180 
00181 static void
00182 cannot_be_coerced_into_BigDecimal(VALUE exc_class, VALUE v)
00183 {
00184     VALUE str;
00185 
00186     if (rb_special_const_p(v)) {
00187         str = rb_inspect(v);
00188     }
00189     else {
00190         str = rb_class_name(rb_obj_class(v));
00191     }
00192 
00193     str = rb_str_cat2(rb_str_dup(str), " can't be coerced into BigDecimal");
00194     rb_exc_raise(rb_exc_new3(exc_class, str));
00195 }
00196 
00197 static inline VALUE BigDecimal_div2(VALUE, VALUE, VALUE);
00198 
00199 static Real*
00200 GetVpValueWithPrec(VALUE v, long prec, int must)
00201 {
00202     Real *pv;
00203     VALUE num, bg;
00204     char szD[128];
00205     VALUE orig = Qundef;
00206     double d;
00207 
00208 again:
00209     switch(TYPE(v)) {
00210       case T_FLOAT:
00211         if (prec < 0) goto unable_to_coerce_without_prec;
00212         if (prec > DBL_DIG+1) goto SomeOneMayDoIt;
00213         d = RFLOAT_VALUE(v);
00214         if (d != 0.0) {
00215             v = rb_funcall(v, id_to_r, 0);
00216             goto again;
00217         }
00218         if (1/d < 0.0) {
00219             return VpCreateRbObject(prec, "-0");
00220         }
00221         return VpCreateRbObject(prec, "0");
00222 
00223       case T_RATIONAL:
00224         if (prec < 0) goto unable_to_coerce_without_prec;
00225 
00226         if (orig == Qundef ? (orig = v, 1) : orig != v) {
00227             num = RRATIONAL(v)->num;
00228             pv = GetVpValueWithPrec(num, -1, must);
00229             if (pv == NULL) goto SomeOneMayDoIt;
00230 
00231             v = BigDecimal_div2(ToValue(pv), RRATIONAL(v)->den, LONG2NUM(prec));
00232             goto again;
00233         }
00234 
00235         v = orig;
00236         goto SomeOneMayDoIt;
00237 
00238       case T_DATA:
00239         if (is_kind_of_BigDecimal(v)) {
00240             pv = DATA_PTR(v);
00241             return pv;
00242         }
00243         else {
00244             goto SomeOneMayDoIt;
00245         }
00246         break;
00247 
00248       case T_FIXNUM:
00249         sprintf(szD, "%ld", FIX2LONG(v));
00250         return VpCreateRbObject(VpBaseFig() * 2 + 1, szD);
00251 
00252 #ifdef ENABLE_NUMERIC_STRING
00253       case T_STRING:
00254         SafeStringValue(v);
00255         return VpCreateRbObject(strlen(RSTRING_PTR(v)) + VpBaseFig() + 1,
00256                                 RSTRING_PTR(v));
00257 #endif /* ENABLE_NUMERIC_STRING */
00258 
00259       case T_BIGNUM:
00260         bg = rb_big2str(v, 10);
00261         return VpCreateRbObject(strlen(RSTRING_PTR(bg)) + VpBaseFig() + 1,
00262                                 RSTRING_PTR(bg));
00263       default:
00264         goto SomeOneMayDoIt;
00265     }
00266 
00267 SomeOneMayDoIt:
00268     if (must) {
00269         cannot_be_coerced_into_BigDecimal(rb_eTypeError, v);
00270     }
00271     return NULL; /* NULL means to coerce */
00272 
00273 unable_to_coerce_without_prec:
00274     if (must) {
00275         rb_raise(rb_eArgError,
00276                  "%s can't be coerced into BigDecimal without a precision",
00277                  rb_obj_classname(v));
00278     }
00279     return NULL;
00280 }
00281 
00282 static Real*
00283 GetVpValue(VALUE v, int must)
00284 {
00285     return GetVpValueWithPrec(v, -1, must);
00286 }
00287 
00288 /* call-seq:
00289  * BigDecimal.double_fig
00290  *
00291  * The BigDecimal.double_fig class method returns the number of digits a
00292  * Float number is allowed to have. The result depends upon the CPU and OS
00293  * in use.
00294  */
00295 static VALUE
00296 BigDecimal_double_fig(VALUE self)
00297 {
00298     return INT2FIX(VpDblFig());
00299 }
00300 
00301 /* call-seq:
00302  * precs
00303  *
00304  * Returns an Array of two Integer values.
00305  *
00306  * The first value is the current number of significant digits in the
00307  * BigDecimal. The second value is the maximum number of significant digits
00308  * for the BigDecimal.
00309  */
00310 static VALUE
00311 BigDecimal_prec(VALUE self)
00312 {
00313     ENTER(1);
00314     Real *p;
00315     VALUE obj;
00316 
00317     GUARD_OBJ(p, GetVpValue(self, 1));
00318     obj = rb_assoc_new(INT2NUM(p->Prec*VpBaseFig()),
00319                        INT2NUM(p->MaxPrec*VpBaseFig()));
00320     return obj;
00321 }
00322 
00323 /*
00324  * call-seq: hash
00325  *
00326  * Creates a hash for this BigDecimal.
00327  *
00328  * Two BigDecimals with equal sign,
00329  * fractional part and exponent have the same hash.
00330  */
00331 static VALUE
00332 BigDecimal_hash(VALUE self)
00333 {
00334     ENTER(1);
00335     Real *p;
00336     st_index_t hash;
00337 
00338     GUARD_OBJ(p, GetVpValue(self, 1));
00339     hash = (st_index_t)p->sign;
00340     /* hash!=2: the case for 0(1),NaN(0) or +-Infinity(3) is sign itself */
00341     if(hash == 2 || hash == (st_index_t)-2) {
00342         hash ^= rb_memhash(p->frac, sizeof(BDIGIT)*p->Prec);
00343         hash += p->exponent;
00344     }
00345     return INT2FIX(hash);
00346 }
00347 
00348 /*
00349  * call-seq: _dump
00350  *
00351  * Method used to provide marshalling support.
00352  *
00353  *      inf = BigDecimal.new('Infinity')
00354  *      => #<BigDecimal:1e16fa8,'Infinity',9(9)>
00355  *      BigDecimal._load(inf._dump)
00356  *      => #<BigDecimal:1df8dc8,'Infinity',9(9)>
00357  *
00358  * See the Marshal module.
00359  */
00360 static VALUE
00361 BigDecimal_dump(int argc, VALUE *argv, VALUE self)
00362 {
00363     ENTER(5);
00364     Real *vp;
00365     char *psz;
00366     VALUE dummy;
00367     volatile VALUE dump;
00368 
00369     rb_scan_args(argc, argv, "01", &dummy);
00370     GUARD_OBJ(vp,GetVpValue(self, 1));
00371     dump = rb_str_new(0, VpNumOfChars(vp, "E")+50);
00372     psz = RSTRING_PTR(dump);
00373     sprintf(psz, "%"PRIuSIZE":", VpMaxPrec(vp)*VpBaseFig());
00374     VpToString(vp, psz+strlen(psz), 0, 0);
00375     rb_str_resize(dump, strlen(psz));
00376     return dump;
00377 }
00378 
00379 /*
00380  * Internal method used to provide marshalling support. See the Marshal module.
00381  */
00382 static VALUE
00383 BigDecimal_load(VALUE self, VALUE str)
00384 {
00385     ENTER(2);
00386     Real *pv;
00387     unsigned char *pch;
00388     unsigned char ch;
00389     unsigned long m=0;
00390 
00391     SafeStringValue(str);
00392     pch = (unsigned char *)RSTRING_PTR(str);
00393     /* First get max prec */
00394     while((*pch) != (unsigned char)'\0' && (ch = *pch++) != (unsigned char)':') {
00395         if(!ISDIGIT(ch)) {
00396             rb_raise(rb_eTypeError, "load failed: invalid character in the marshaled string");
00397         }
00398         m = m*10 + (unsigned long)(ch-'0');
00399     }
00400     if (m > VpBaseFig()) m -= VpBaseFig();
00401     GUARD_OBJ(pv, VpNewRbClass(m, (char *)pch, self));
00402     m /= VpBaseFig();
00403     if (m && pv->MaxPrec > m) {
00404         pv->MaxPrec = m+1;
00405     }
00406     return ToValue(pv);
00407 }
00408 
00409 static unsigned short
00410 check_rounding_mode(VALUE const v)
00411 {
00412     unsigned short sw;
00413     ID id;
00414     switch (TYPE(v)) {
00415       case T_SYMBOL:
00416         id = SYM2ID(v);
00417         if (id == id_up)
00418             return VP_ROUND_UP;
00419         if (id == id_down || id == id_truncate)
00420             return VP_ROUND_DOWN;
00421         if (id == id_half_up || id == id_default)
00422             return VP_ROUND_HALF_UP;
00423         if (id == id_half_down)
00424             return VP_ROUND_HALF_DOWN;
00425         if (id == id_half_even || id == id_banker)
00426             return VP_ROUND_HALF_EVEN;
00427         if (id == id_ceiling || id == id_ceil)
00428             return VP_ROUND_CEIL;
00429         if (id == id_floor)
00430             return VP_ROUND_FLOOR;
00431         rb_raise(rb_eArgError, "invalid rounding mode");
00432 
00433       default:
00434         break;
00435     }
00436 
00437     Check_Type(v, T_FIXNUM);
00438     sw = (unsigned short)FIX2UINT(v);
00439     if (!VpIsRoundMode(sw)) {
00440         rb_raise(rb_eArgError, "invalid rounding mode");
00441     }
00442     return sw;
00443 }
00444 
00445 /* call-seq:
00446  * BigDecimal.mode(mode, value)
00447  *
00448  * Controls handling of arithmetic exceptions and rounding. If no value
00449  * is supplied, the current value is returned.
00450  *
00451  * Six values of the mode parameter control the handling of arithmetic
00452  * exceptions:
00453  *
00454  * BigDecimal::EXCEPTION_NaN
00455  * BigDecimal::EXCEPTION_INFINITY
00456  * BigDecimal::EXCEPTION_UNDERFLOW
00457  * BigDecimal::EXCEPTION_OVERFLOW
00458  * BigDecimal::EXCEPTION_ZERODIVIDE
00459  * BigDecimal::EXCEPTION_ALL
00460  *
00461  * For each mode parameter above, if the value set is false, computation
00462  * continues after an arithmetic exception of the appropriate type.
00463  * When computation continues, results are as follows:
00464  *
00465  * EXCEPTION_NaN:: NaN
00466  * EXCEPTION_INFINITY:: +Infinity or -Infinity
00467  * EXCEPTION_UNDERFLOW:: 0
00468  * EXCEPTION_OVERFLOW:: +Infinity or -Infinity
00469  * EXCEPTION_ZERODIVIDE:: +Infinity or -Infinity
00470  *
00471  * One value of the mode parameter controls the rounding of numeric values:
00472  * BigDecimal::ROUND_MODE. The values it can take are:
00473  *
00474  * ROUND_UP, :up:: round away from zero
00475  * ROUND_DOWN, :down, :truncate:: round towards zero (truncate)
00476  * ROUND_HALF_UP, :half_up, :default:: round towards the nearest neighbor, unless both neighbors are equidistant, in which case round away from zero. (default)
00477  * ROUND_HALF_DOWN, :half_down:: round towards the nearest neighbor, unless both neighbors are equidistant, in which case round towards zero.
00478  * 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)
00479  * ROUND_CEILING, :ceiling, :ceil:: round towards positive infinity (ceil)
00480  * ROUND_FLOOR, :floor:: round towards negative infinity (floor)
00481  *
00482  */
00483 static VALUE
00484 BigDecimal_mode(int argc, VALUE *argv, VALUE self)
00485 {
00486     VALUE which;
00487     VALUE val;
00488     unsigned long f,fo;
00489 
00490     rb_scan_args(argc, argv, "11", &which, &val);
00491     Check_Type(which, T_FIXNUM);
00492     f = (unsigned long)FIX2INT(which);
00493 
00494     if (f & VP_EXCEPTION_ALL) {
00495         /* Exception mode setting */
00496         fo = VpGetException();
00497         if (val == Qnil) return INT2FIX(fo);
00498         if (val != Qfalse && val!=Qtrue) {
00499             rb_raise(rb_eArgError, "second argument must be true or false");
00500             return Qnil; /* Not reached */
00501         }
00502         if (f & VP_EXCEPTION_INFINITY) {
00503             VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_INFINITY) :
00504                         (fo & (~VP_EXCEPTION_INFINITY))));
00505         }
00506         fo = VpGetException();
00507         if (f & VP_EXCEPTION_NaN) {
00508             VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_NaN) :
00509                         (fo & (~VP_EXCEPTION_NaN))));
00510         }
00511         fo = VpGetException();
00512         if (f & VP_EXCEPTION_UNDERFLOW) {
00513             VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_UNDERFLOW) :
00514                         (fo & (~VP_EXCEPTION_UNDERFLOW))));
00515         }
00516         fo = VpGetException();
00517         if(f & VP_EXCEPTION_ZERODIVIDE) {
00518             VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_ZERODIVIDE) :
00519                         (fo & (~VP_EXCEPTION_ZERODIVIDE))));
00520         }
00521         fo = VpGetException();
00522         return INT2FIX(fo);
00523     }
00524     if (VP_ROUND_MODE == f) {
00525         /* Rounding mode setting */
00526         unsigned short sw;
00527         fo = VpGetRoundMode();
00528         if (NIL_P(val)) return INT2FIX(fo);
00529         sw = check_rounding_mode(val);
00530         fo = VpSetRoundMode(sw);
00531         return INT2FIX(fo);
00532     }
00533     rb_raise(rb_eTypeError, "first argument for BigDecimal#mode invalid");
00534     return Qnil;
00535 }
00536 
00537 static size_t
00538 GetAddSubPrec(Real *a, Real *b)
00539 {
00540     size_t mxs;
00541     size_t mx = a->Prec;
00542     SIGNED_VALUE d;
00543 
00544     if (!VpIsDef(a) || !VpIsDef(b)) return (size_t)-1L;
00545     if (mx < b->Prec) mx = b->Prec;
00546     if (a->exponent != b->exponent) {
00547         mxs = mx;
00548         d = a->exponent - b->exponent;
00549         if (d < 0) d = -d;
00550         mx = mx + (size_t)d;
00551         if (mx < mxs) {
00552             return VpException(VP_EXCEPTION_INFINITY, "Exponent overflow", 0);
00553         }
00554     }
00555     return mx;
00556 }
00557 
00558 static SIGNED_VALUE
00559 GetPositiveInt(VALUE v)
00560 {
00561     SIGNED_VALUE n;
00562     Check_Type(v, T_FIXNUM);
00563     n = FIX2INT(v);
00564     if (n < 0) {
00565         rb_raise(rb_eArgError, "argument must be positive");
00566     }
00567     return n;
00568 }
00569 
00570 VP_EXPORT Real *
00571 VpNewRbClass(size_t mx, const char *str, VALUE klass)
00572 {
00573     Real *pv = VpAlloc(mx,str);
00574     pv->obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, pv);
00575     return pv;
00576 }
00577 
00578 VP_EXPORT Real *
00579 VpCreateRbObject(size_t mx, const char *str)
00580 {
00581     Real *pv = VpAlloc(mx,str);
00582     pv->obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, pv);
00583     return pv;
00584 }
00585 
00586 #define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(BDIGIT))
00587 #define VpReallocReal(ptr, prec) (Real *)VpMemRealloc((ptr), offsetof(Real, frac) + (prec) * sizeof(BDIGIT))
00588 
00589 static Real *
00590 VpCopy(Real *pv, Real const* const x)
00591 {
00592     assert(x != NULL);
00593 
00594     pv = VpReallocReal(pv, x->MaxPrec);
00595     pv->MaxPrec = x->MaxPrec;
00596     pv->Prec = x->Prec;
00597     pv->exponent = x->exponent;
00598     pv->sign = x->sign;
00599     pv->flag = x->flag;
00600     MEMCPY(pv->frac, x->frac, BDIGIT, pv->MaxPrec);
00601 
00602     return pv;
00603 }
00604 
00605 /* Returns True if the value is Not a Number */
00606 static VALUE
00607 BigDecimal_IsNaN(VALUE self)
00608 {
00609     Real *p = GetVpValue(self, 1);
00610     if (VpIsNaN(p))  return Qtrue;
00611     return Qfalse;
00612 }
00613 
00614 /* Returns nil, -1, or +1 depending on whether the value is finite,
00615  * -Infinity, or +Infinity.
00616  */
00617 static VALUE
00618 BigDecimal_IsInfinite(VALUE self)
00619 {
00620     Real *p = GetVpValue(self, 1);
00621     if (VpIsPosInf(p)) return INT2FIX(1);
00622     if (VpIsNegInf(p)) return INT2FIX(-1);
00623     return Qnil;
00624 }
00625 
00626 /* Returns True if the value is finite (not NaN or infinite) */
00627 static VALUE
00628 BigDecimal_IsFinite(VALUE self)
00629 {
00630     Real *p = GetVpValue(self, 1);
00631     if (VpIsNaN(p)) return Qfalse;
00632     if (VpIsInf(p)) return Qfalse;
00633     return Qtrue;
00634 }
00635 
00636 static void
00637 BigDecimal_check_num(Real *p)
00638 {
00639     if (VpIsNaN(p)) {
00640         VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'(Not a Number)", 1);
00641     }
00642     else if (VpIsPosInf(p)) {
00643         VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 1);
00644     }
00645     else if (VpIsNegInf(p)) {
00646         VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 1);
00647     }
00648 }
00649 
00650 static VALUE BigDecimal_split(VALUE self);
00651 
00652 /* Returns the value as an integer (Fixnum or Bignum).
00653  *
00654  * If the BigNumber is infinity or NaN, raises FloatDomainError.
00655  */
00656 static VALUE
00657 BigDecimal_to_i(VALUE self)
00658 {
00659     ENTER(5);
00660     ssize_t e, nf;
00661     Real *p;
00662 
00663     GUARD_OBJ(p, GetVpValue(self, 1));
00664     BigDecimal_check_num(p);
00665 
00666     e = VpExponent10(p);
00667     if (e <= 0) return INT2FIX(0);
00668     nf = VpBaseFig();
00669     if (e <= nf) {
00670         return LONG2NUM((long)(VpGetSign(p) * (BDIGIT_DBL_SIGNED)p->frac[0]));
00671     }
00672     else {
00673         VALUE a = BigDecimal_split(self);
00674         VALUE digits = RARRAY_PTR(a)[1];
00675         VALUE numerator = rb_funcall(digits, rb_intern("to_i"), 0);
00676         VALUE ret;
00677         ssize_t dpower = e - (ssize_t)RSTRING_LEN(digits);
00678 
00679         if (VpGetSign(p) < 0) {
00680             numerator = rb_funcall(numerator, '*', 1, INT2FIX(-1));
00681         }
00682         if (dpower < 0) {
00683             ret = rb_funcall(numerator, rb_intern("div"), 1,
00684                               rb_funcall(INT2FIX(10), rb_intern("**"), 1,
00685                                          INT2FIX(-dpower)));
00686         }
00687         else {
00688             ret = rb_funcall(numerator, '*', 1,
00689                              rb_funcall(INT2FIX(10), rb_intern("**"), 1,
00690                                         INT2FIX(dpower)));
00691         }
00692         if (RB_TYPE_P(ret, T_FLOAT)) {
00693             rb_raise(rb_eFloatDomainError, "Infinity");
00694         }
00695         return ret;
00696     }
00697 }
00698 
00699 /* Returns a new Float object having approximately the same value as the
00700  * BigDecimal number. Normal accuracy limits and built-in errors of binary
00701  * Float arithmetic apply.
00702  */
00703 static VALUE
00704 BigDecimal_to_f(VALUE self)
00705 {
00706     ENTER(1);
00707     Real *p;
00708     double d;
00709     SIGNED_VALUE e;
00710     char *buf;
00711     volatile VALUE str;
00712 
00713     GUARD_OBJ(p, GetVpValue(self, 1));
00714     if (VpVtoD(&d, &e, p) != 1)
00715         return rb_float_new(d);
00716     if (e > (SIGNED_VALUE)(DBL_MAX_10_EXP+BASE_FIG))
00717         goto overflow;
00718     if (e < (SIGNED_VALUE)(DBL_MIN_10_EXP-BASE_FIG))
00719         goto underflow;
00720 
00721     str = rb_str_new(0, VpNumOfChars(p, "E"));
00722     buf = RSTRING_PTR(str);
00723     VpToString(p, buf, 0, 0);
00724     errno = 0;
00725     d = strtod(buf, 0);
00726     if (errno == ERANGE) {
00727         if (d == 0.0) goto underflow;
00728         if (fabs(d) >= HUGE_VAL) goto overflow;
00729     }
00730     return rb_float_new(d);
00731 
00732 overflow:
00733     VpException(VP_EXCEPTION_OVERFLOW, "BigDecimal to Float conversion", 0);
00734     if (p->sign >= 0)
00735         return rb_float_new(VpGetDoublePosInf());
00736     else
00737         return rb_float_new(VpGetDoubleNegInf());
00738 
00739 underflow:
00740     VpException(VP_EXCEPTION_UNDERFLOW, "BigDecimal to Float conversion", 0);
00741     if (p->sign >= 0)
00742         return rb_float_new(0.0);
00743     else
00744         return rb_float_new(-0.0);
00745 }
00746 
00747 
00748 /* Converts a BigDecimal to a Rational.
00749  */
00750 static VALUE
00751 BigDecimal_to_r(VALUE self)
00752 {
00753     Real *p;
00754     ssize_t sign, power, denomi_power;
00755     VALUE a, digits, numerator;
00756 
00757     p = GetVpValue(self, 1);
00758     BigDecimal_check_num(p);
00759 
00760     sign = VpGetSign(p);
00761     power = VpExponent10(p);
00762     a = BigDecimal_split(self);
00763     digits = RARRAY_PTR(a)[1];
00764     denomi_power = power - RSTRING_LEN(digits);
00765     numerator = rb_funcall(digits, rb_intern("to_i"), 0);
00766 
00767     if (sign < 0) {
00768         numerator = rb_funcall(numerator, '*', 1, INT2FIX(-1));
00769     }
00770     if (denomi_power < 0) {
00771         return rb_Rational(numerator,
00772                            rb_funcall(INT2FIX(10), rb_intern("**"), 1,
00773                                       INT2FIX(-denomi_power)));
00774     }
00775     else {
00776         return rb_Rational1(rb_funcall(numerator, '*', 1,
00777                                        rb_funcall(INT2FIX(10), rb_intern("**"), 1,
00778                                                   INT2FIX(denomi_power))));
00779     }
00780 }
00781 
00782 /* The coerce method provides support for Ruby type coercion. It is not
00783  * enabled by default.
00784  *
00785  * This means that binary operations like + * / or - can often be performed
00786  * on a BigDecimal and an object of another type, if the other object can
00787  * be coerced into a BigDecimal value.
00788  *
00789  * e.g.
00790  * a = BigDecimal.new("1.0")
00791  * b = a / 2.0  -> 0.5
00792  *
00793  * Note that coercing a String to a BigDecimal is not supported by default;
00794  * it requires a special compile-time option when building Ruby.
00795  */
00796 static VALUE
00797 BigDecimal_coerce(VALUE self, VALUE other)
00798 {
00799     ENTER(2);
00800     VALUE obj;
00801     Real *b;
00802 
00803     if (RB_TYPE_P(other, T_FLOAT)) {
00804         GUARD_OBJ(b, GetVpValueWithPrec(other, DBL_DIG+1, 1));
00805         obj = rb_assoc_new(ToValue(b), self);
00806     }
00807     else {
00808         if (RB_TYPE_P(other, T_RATIONAL)) {
00809             Real* pv = DATA_PTR(self);
00810             GUARD_OBJ(b, GetVpValueWithPrec(other, pv->Prec*VpBaseFig(), 1));
00811         }
00812         else {
00813             GUARD_OBJ(b, GetVpValue(other, 1));
00814         }
00815         obj = rb_assoc_new(b->obj, self);
00816     }
00817 
00818     return obj;
00819 }
00820 
00821 /*
00822  * call-seq: +@
00823  *
00824  * Return self.
00825  *
00826  * e.g.
00827  *   b = +a  # b == a
00828  */
00829 static VALUE
00830 BigDecimal_uplus(VALUE self)
00831 {
00832     return self;
00833 }
00834 
00835  /*
00836   * Document-method: BigDecimal#add
00837   * Document-method: BigDecimal#+
00838   *
00839   * call-seq:
00840   * add(value, digits)
00841   *
00842   * Add the specified value.
00843   *
00844   * e.g.
00845   *   c = a.add(b,n)
00846   *   c = a + b
00847   *
00848   * digits:: If specified and less than the number of significant digits of the
00849   * result, the result is rounded to that number of digits, according to
00850   * BigDecimal.mode.
00851   */
00852 static VALUE
00853 BigDecimal_add(VALUE self, VALUE r)
00854 {
00855     ENTER(5);
00856     Real *c, *a, *b;
00857     size_t mx;
00858 
00859     GUARD_OBJ(a, GetVpValue(self, 1));
00860     if (RB_TYPE_P(r, T_FLOAT)) {
00861         b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
00862     }
00863     else if (RB_TYPE_P(r, T_RATIONAL)) {
00864         b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
00865     }
00866     else {
00867         b = GetVpValue(r, 0);
00868     }
00869 
00870     if (!b) return DoSomeOne(self,r,'+');
00871     SAVE(b);
00872 
00873     if (VpIsNaN(b)) return b->obj;
00874     if (VpIsNaN(a)) return a->obj;
00875 
00876     mx = GetAddSubPrec(a, b);
00877     if (mx == (size_t)-1L) {
00878         GUARD_OBJ(c,VpCreateRbObject(VpBaseFig() + 1, "0"));
00879         VpAddSub(c, a, b, 1);
00880     }
00881     else {
00882         GUARD_OBJ(c, VpCreateRbObject(mx * (VpBaseFig() + 1), "0"));
00883         if(!mx) {
00884             VpSetInf(c, VpGetSign(a));
00885         }
00886         else {
00887             VpAddSub(c, a, b, 1);
00888         }
00889     }
00890     return ToValue(c);
00891 }
00892 
00893  /* call-seq:
00894   * value - digits   -> bigdecimal
00895   *
00896   * Subtract the specified value.
00897   *
00898   * e.g.
00899   *   c = a - b
00900   *
00901   * The precision of the result value depends on the type of +b+.
00902   *
00903   * If +b+ is a Float, the precision of the result is Float::DIG+1.
00904   *
00905   * If +b+ is a BigDecimal, the precision of the result is +b+'s precision of
00906   * internal representation from platform. So, it's return value is platform
00907   * dependent.
00908   *
00909   */
00910 static VALUE
00911 BigDecimal_sub(VALUE self, VALUE r)
00912 {
00913     ENTER(5);
00914     Real *c, *a, *b;
00915     size_t mx;
00916 
00917     GUARD_OBJ(a, GetVpValue(self,1));
00918     if (RB_TYPE_P(r, T_FLOAT)) {
00919         b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
00920     }
00921     else if (RB_TYPE_P(r, T_RATIONAL)) {
00922         b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
00923     }
00924     else {
00925         b = GetVpValue(r,0);
00926     }
00927 
00928     if (!b) return DoSomeOne(self,r,'-');
00929     SAVE(b);
00930 
00931     if (VpIsNaN(b)) return b->obj;
00932     if (VpIsNaN(a)) return a->obj;
00933 
00934     mx = GetAddSubPrec(a,b);
00935     if (mx == (size_t)-1L) {
00936         GUARD_OBJ(c,VpCreateRbObject(VpBaseFig() + 1, "0"));
00937         VpAddSub(c, a, b, -1);
00938     }
00939     else {
00940         GUARD_OBJ(c,VpCreateRbObject(mx *(VpBaseFig() + 1), "0"));
00941         if (!mx) {
00942             VpSetInf(c,VpGetSign(a));
00943         }
00944         else {
00945             VpAddSub(c, a, b, -1);
00946         }
00947     }
00948     return ToValue(c);
00949 }
00950 
00951 static VALUE
00952 BigDecimalCmp(VALUE self, VALUE r,char op)
00953 {
00954     ENTER(5);
00955     SIGNED_VALUE e;
00956     Real *a, *b=0;
00957     GUARD_OBJ(a, GetVpValue(self, 1));
00958     switch (TYPE(r)) {
00959     case T_DATA:
00960         if (!is_kind_of_BigDecimal(r)) break;
00961         /* fall through */
00962     case T_FIXNUM:
00963         /* fall through */
00964     case T_BIGNUM:
00965         GUARD_OBJ(b, GetVpValue(r, 0));
00966         break;
00967 
00968     case T_FLOAT:
00969         GUARD_OBJ(b, GetVpValueWithPrec(r, DBL_DIG+1, 0));
00970         break;
00971 
00972     case T_RATIONAL:
00973         GUARD_OBJ(b, GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 0));
00974         break;
00975 
00976     default:
00977         break;
00978     }
00979     if (b == NULL) {
00980         ID f = 0;
00981 
00982         switch (op) {
00983         case '*':
00984             return rb_num_coerce_cmp(self, r, rb_intern("<=>"));
00985 
00986         case '=':
00987             return RTEST(rb_num_coerce_cmp(self, r, rb_intern("=="))) ? Qtrue : Qfalse;
00988 
00989         case 'G':
00990             f = rb_intern(">=");
00991             break;
00992 
00993         case 'L':
00994             f = rb_intern("<=");
00995             break;
00996 
00997         case '>':
00998             /* fall through */
00999         case '<':
01000             f = (ID)op;
01001             break;
01002 
01003         default:
01004             break;
01005         }
01006         return rb_num_coerce_relop(self, r, f);
01007     }
01008     SAVE(b);
01009     e = VpComp(a, b);
01010     if (e == 999)
01011         return (op == '*') ? Qnil : Qfalse;
01012     switch (op) {
01013     case '*':
01014         return   INT2FIX(e); /* any op */
01015 
01016     case '=':
01017         if (e == 0) return Qtrue;
01018         return Qfalse;
01019 
01020     case 'G':
01021         if (e >= 0) return Qtrue;
01022         return Qfalse;
01023 
01024     case '>':
01025         if (e >  0) return Qtrue;
01026         return Qfalse;
01027 
01028     case 'L':
01029         if (e <= 0) return Qtrue;
01030         return Qfalse;
01031 
01032     case '<':
01033         if (e <  0) return Qtrue;
01034         return Qfalse;
01035 
01036     default:
01037         break;
01038     }
01039 
01040     rb_bug("Undefined operation in BigDecimalCmp()");
01041 
01042     UNREACHABLE;
01043 }
01044 
01045 /* Returns True if the value is zero. */
01046 static VALUE
01047 BigDecimal_zero(VALUE self)
01048 {
01049     Real *a = GetVpValue(self, 1);
01050     return VpIsZero(a) ? Qtrue : Qfalse;
01051 }
01052 
01053 /* Returns self if the value is non-zero, nil otherwise. */
01054 static VALUE
01055 BigDecimal_nonzero(VALUE self)
01056 {
01057     Real *a = GetVpValue(self, 1);
01058     return VpIsZero(a) ? Qnil : self;
01059 }
01060 
01061 /* The comparison operator.
01062  * a <=> b is 0 if a == b, 1 if a > b, -1 if a < b.
01063  */
01064 static VALUE
01065 BigDecimal_comp(VALUE self, VALUE r)
01066 {
01067     return BigDecimalCmp(self, r, '*');
01068 }
01069 
01070 /*
01071  * Tests for value equality; returns true if the values are equal.
01072  *
01073  * The == and === operators and the eql? method have the same implementation
01074  * for BigDecimal.
01075  *
01076  * Values may be coerced to perform the comparison:
01077  *
01078  * BigDecimal.new('1.0') == 1.0  -> true
01079  */
01080 static VALUE
01081 BigDecimal_eq(VALUE self, VALUE r)
01082 {
01083     return BigDecimalCmp(self, r, '=');
01084 }
01085 
01086 /* call-seq:
01087  * a < b
01088  *
01089  * Returns true if a is less than b.
01090  *
01091  * Values may be coerced to perform the comparison (see ==, BigDecimal#coerce).
01092  */
01093 static VALUE
01094 BigDecimal_lt(VALUE self, VALUE r)
01095 {
01096     return BigDecimalCmp(self, r, '<');
01097 }
01098 
01099 /* call-seq:
01100  * a <= b
01101  *
01102  * Returns true if a is less than or equal to b.
01103  *
01104  * Values may be coerced to perform the comparison (see ==, BigDecimal#coerce).
01105  */
01106 static VALUE
01107 BigDecimal_le(VALUE self, VALUE r)
01108 {
01109     return BigDecimalCmp(self, r, 'L');
01110 }
01111 
01112 /* call-seq:
01113  * a > b
01114  *
01115  * Returns true if a is greater than b.
01116  *
01117  * Values may be coerced to perform the comparison (see ==, BigDecimal#coerce).
01118  */
01119 static VALUE
01120 BigDecimal_gt(VALUE self, VALUE r)
01121 {
01122     return BigDecimalCmp(self, r, '>');
01123 }
01124 
01125 /* call-seq:
01126  * a >= b
01127  *
01128  * Returns true if a is greater than or equal to b.
01129  *
01130  * Values may be coerced to perform the comparison (see ==, BigDecimal#coerce)
01131  */
01132 static VALUE
01133 BigDecimal_ge(VALUE self, VALUE r)
01134 {
01135     return BigDecimalCmp(self, r, 'G');
01136 }
01137 
01138 /*
01139  * call-seq: -@
01140  *
01141  * Return the negation of self.
01142  *
01143  * e.g.
01144  *   b = -a
01145  *   b == a * -1
01146  */
01147 static VALUE
01148 BigDecimal_neg(VALUE self)
01149 {
01150     ENTER(5);
01151     Real *c, *a;
01152     GUARD_OBJ(a, GetVpValue(self, 1));
01153     GUARD_OBJ(c, VpCreateRbObject(a->Prec *(VpBaseFig() + 1), "0"));
01154     VpAsgn(c, a, -1);
01155     return ToValue(c);
01156 }
01157 
01158  /*
01159   * Document-method: BigDecimal#mult
01160   *
01161   * call-seq: mult(value, digits)
01162   *
01163   * Multiply by the specified value.
01164   *
01165   * e.g.
01166   *   c = a.mult(b,n)
01167   *   c = a * b
01168   *
01169   * digits:: If specified and less than the number of significant digits of the
01170   * result, the result is rounded to that number of digits, according to
01171   * BigDecimal.mode.
01172   */
01173 static VALUE
01174 BigDecimal_mult(VALUE self, VALUE r)
01175 {
01176     ENTER(5);
01177     Real *c, *a, *b;
01178     size_t mx;
01179 
01180     GUARD_OBJ(a, GetVpValue(self, 1));
01181     if (RB_TYPE_P(r, T_FLOAT)) {
01182         b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
01183     }
01184     else if (RB_TYPE_P(r, T_RATIONAL)) {
01185         b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
01186     }
01187     else {
01188         b = GetVpValue(r,0);
01189     }
01190 
01191     if (!b) return DoSomeOne(self, r, '*');
01192     SAVE(b);
01193 
01194     mx = a->Prec + b->Prec;
01195     GUARD_OBJ(c, VpCreateRbObject(mx *(VpBaseFig() + 1), "0"));
01196     VpMult(c, a, b);
01197     return ToValue(c);
01198 }
01199 
01200 static VALUE
01201 BigDecimal_divide(Real **c, Real **res, Real **div, VALUE self, VALUE r)
01202 /* For c = self.div(r): with round operation */
01203 {
01204     ENTER(5);
01205     Real *a, *b;
01206     size_t mx;
01207 
01208     GUARD_OBJ(a, GetVpValue(self, 1));
01209     if (RB_TYPE_P(r, T_FLOAT)) {
01210         b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
01211     }
01212     else if (RB_TYPE_P(r, T_RATIONAL)) {
01213         b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
01214      }
01215     else {
01216         b = GetVpValue(r, 0);
01217     }
01218 
01219     if (!b) return DoSomeOne(self, r, '/');
01220     SAVE(b);
01221 
01222     *div = b;
01223     mx = a->Prec + vabs(a->exponent);
01224     if (mx < b->Prec + vabs(b->exponent)) mx = b->Prec + vabs(b->exponent);
01225     mx++; /* NOTE: An additional digit is needed for the compatibility to
01226                    the version 1.2.1 and the former.  */
01227     mx = (mx + 1) * VpBaseFig();
01228     GUARD_OBJ((*c), VpCreateRbObject(mx, "#0"));
01229     GUARD_OBJ((*res), VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0"));
01230     VpDivd(*c, *res, a, b);
01231     return Qnil;
01232 }
01233 
01234  /* call-seq:
01235   * div(value, digits)
01236   * quo(value)
01237   *
01238   * Divide by the specified value.
01239   *
01240   * e.g.
01241   *   c = a.div(b,n)
01242   *
01243   * digits:: If specified and less than the number of significant digits of the
01244   * result, the result is rounded to that number of digits, according to
01245   * BigDecimal.mode.
01246   *
01247   * If digits is 0, the result is the same as the / operator. If not, the
01248   * result is an integer BigDecimal, by analogy with Float#div.
01249   *
01250   * The alias quo is provided since <code>div(value, 0)</code> is the same as
01251   * computing the quotient; see BigDecimal#divmod.
01252   */
01253 static VALUE
01254 BigDecimal_div(VALUE self, VALUE r)
01255 /* For c = self/r: with round operation */
01256 {
01257     ENTER(5);
01258     Real *c=NULL, *res=NULL, *div = NULL;
01259     r = BigDecimal_divide(&c, &res, &div, self, r);
01260     if (!NIL_P(r)) return r; /* coerced by other */
01261     SAVE(c); SAVE(res); SAVE(div);
01262     /* a/b = c + r/b */
01263     /* c xxxxx
01264        r 00000yyyyy  ==> (y/b)*BASE >= HALF_BASE
01265      */
01266     /* Round */
01267     if (VpHasVal(div)) { /* frac[0] must be zero for NaN,INF,Zero */
01268         VpInternalRound(c, 0, c->frac[c->Prec-1], (BDIGIT)(VpBaseVal() * (BDIGIT_DBL)res->frac[0] / div->frac[0]));
01269     }
01270     return ToValue(c);
01271 }
01272 
01273 /*
01274  * %: mod = a%b = a - (a.to_f/b).floor * b
01275  * div = (a.to_f/b).floor
01276  */
01277 static VALUE
01278 BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod)
01279 {
01280     ENTER(8);
01281     Real *c=NULL, *d=NULL, *res=NULL;
01282     Real *a, *b;
01283     size_t mx;
01284 
01285     GUARD_OBJ(a, GetVpValue(self, 1));
01286     if (RB_TYPE_P(r, T_FLOAT)) {
01287         b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
01288     }
01289     else if (RB_TYPE_P(r, T_RATIONAL)) {
01290         b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
01291     }
01292     else {
01293         b = GetVpValue(r, 0);
01294     }
01295 
01296     if (!b) return Qfalse;
01297     SAVE(b);
01298 
01299     if (VpIsNaN(a) || VpIsNaN(b)) goto NaN;
01300     if (VpIsInf(a) && VpIsInf(b)) goto NaN;
01301     if (VpIsZero(b)) {
01302         rb_raise(rb_eZeroDivError, "divided by 0");
01303     }
01304     if (VpIsInf(a)) {
01305         GUARD_OBJ(d, VpCreateRbObject(1, "0"));
01306         VpSetInf(d, (SIGNED_VALUE)(VpGetSign(a) == VpGetSign(b) ? 1 : -1));
01307         GUARD_OBJ(c, VpCreateRbObject(1, "NaN"));
01308         *div = d;
01309         *mod = c;
01310         return Qtrue;
01311     }
01312     if (VpIsInf(b)) {
01313         GUARD_OBJ(d, VpCreateRbObject(1, "0"));
01314         *div = d;
01315         *mod = a;
01316         return Qtrue;
01317     }
01318     if (VpIsZero(a)) {
01319         GUARD_OBJ(c, VpCreateRbObject(1, "0"));
01320         GUARD_OBJ(d, VpCreateRbObject(1, "0"));
01321         *div = d;
01322         *mod = c;
01323         return Qtrue;
01324     }
01325 
01326     mx = a->Prec + vabs(a->exponent);
01327     if (mx<b->Prec + vabs(b->exponent)) mx = b->Prec + vabs(b->exponent);
01328     mx = (mx + 1) * VpBaseFig();
01329     GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
01330     GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0"));
01331     VpDivd(c, res, a, b);
01332     mx = c->Prec * (VpBaseFig() + 1);
01333     GUARD_OBJ(d, VpCreateRbObject(mx, "0"));
01334     VpActiveRound(d, c, VP_ROUND_DOWN, 0);
01335     VpMult(res, d, b);
01336     VpAddSub(c, a, res, -1);
01337     if (!VpIsZero(c) && (VpGetSign(a) * VpGetSign(b) < 0)) {
01338         VpAddSub(res, d, VpOne(), -1);
01339         GUARD_OBJ(d, VpCreateRbObject(GetAddSubPrec(c, b)*(VpBaseFig() + 1), "0"));
01340         VpAddSub(d, c, b, 1);
01341         *div = res;
01342         *mod = d;
01343     } else {
01344         *div = d;
01345         *mod = c;
01346     }
01347     return Qtrue;
01348 
01349 NaN:
01350     GUARD_OBJ(c, VpCreateRbObject(1, "NaN"));
01351     GUARD_OBJ(d, VpCreateRbObject(1, "NaN"));
01352     *div = d;
01353     *mod = c;
01354     return Qtrue;
01355 }
01356 
01357 /* call-seq:
01358  * a % b
01359  * a.modulo(b)
01360  *
01361  * Returns the modulus from dividing by b.
01362  *
01363  * See BigDecimal#divmod.
01364  */
01365 static VALUE
01366 BigDecimal_mod(VALUE self, VALUE r) /* %: a%b = a - (a.to_f/b).floor * b */
01367 {
01368     ENTER(3);
01369     Real *div = NULL, *mod = NULL;
01370 
01371     if (BigDecimal_DoDivmod(self, r, &div, &mod)) {
01372         SAVE(div); SAVE(mod);
01373         return ToValue(mod);
01374     }
01375     return DoSomeOne(self, r, '%');
01376 }
01377 
01378 static VALUE
01379 BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv)
01380 {
01381     ENTER(10);
01382     size_t mx;
01383     Real *a = NULL, *b = NULL, *c = NULL, *res = NULL, *d = NULL, *rr = NULL, *ff = NULL;
01384     Real *f = NULL;
01385 
01386     GUARD_OBJ(a, GetVpValue(self, 1));
01387     if (RB_TYPE_P(r, T_FLOAT)) {
01388         b = GetVpValueWithPrec(r, DBL_DIG+1, 1);
01389     }
01390     else if (RB_TYPE_P(r, T_RATIONAL)) {
01391         b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1);
01392     }
01393     else {
01394         b = GetVpValue(r, 0);
01395     }
01396 
01397     if (!b) return DoSomeOne(self, r, rb_intern("remainder"));
01398     SAVE(b);
01399 
01400     mx = (a->MaxPrec + b->MaxPrec) *VpBaseFig();
01401     GUARD_OBJ(c,   VpCreateRbObject(mx, "0"));
01402     GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0"));
01403     GUARD_OBJ(rr,  VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0"));
01404     GUARD_OBJ(ff,  VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0"));
01405 
01406     VpDivd(c, res, a, b);
01407 
01408     mx = c->Prec *(VpBaseFig() + 1);
01409 
01410     GUARD_OBJ(d, VpCreateRbObject(mx, "0"));
01411     GUARD_OBJ(f, VpCreateRbObject(mx, "0"));
01412 
01413     VpActiveRound(d, c, VP_ROUND_DOWN, 0); /* 0: round off */
01414 
01415     VpFrac(f, c);
01416     VpMult(rr, f, b);
01417     VpAddSub(ff, res, rr, 1);
01418 
01419     *dv = d;
01420     *rv = ff;
01421     return Qnil;
01422 }
01423 
01424 /* Returns the remainder from dividing by the value.
01425  *
01426  * x.remainder(y) means x-y*(x/y).truncate
01427  */
01428 static VALUE
01429 BigDecimal_remainder(VALUE self, VALUE r) /* remainder */
01430 {
01431     VALUE  f;
01432     Real  *d, *rv = 0;
01433     f = BigDecimal_divremain(self, r, &d, &rv);
01434     if (!NIL_P(f)) return f;
01435     return ToValue(rv);
01436 }
01437 
01438 /* Divides by the specified value, and returns the quotient and modulus
01439  * as BigDecimal numbers. The quotient is rounded towards negative infinity.
01440  *
01441  * For example:
01442  *
01443  * require 'bigdecimal'
01444  *
01445  * a = BigDecimal.new("42")
01446  * b = BigDecimal.new("9")
01447  *
01448  * q,m = a.divmod(b)
01449  *
01450  * c = q * b + m
01451  *
01452  * a == c  -> true
01453  *
01454  * The quotient q is (a/b).floor, and the modulus is the amount that must be
01455  * added to q * b to get a.
01456  */
01457 static VALUE
01458 BigDecimal_divmod(VALUE self, VALUE r)
01459 {
01460     ENTER(5);
01461     Real *div = NULL, *mod = NULL;
01462 
01463     if (BigDecimal_DoDivmod(self, r, &div, &mod)) {
01464         SAVE(div); SAVE(mod);
01465         return rb_assoc_new(ToValue(div), ToValue(mod));
01466     }
01467     return DoSomeOne(self,r,rb_intern("divmod"));
01468 }
01469 
01470 /*
01471  * See BigDecimal#quo
01472  */
01473 static inline VALUE
01474 BigDecimal_div2(VALUE self, VALUE b, VALUE n)
01475 {
01476     ENTER(5);
01477     SIGNED_VALUE ix;
01478 
01479     if (NIL_P(n)) { /* div in Float sense */
01480         Real *div = NULL;
01481         Real *mod;
01482         if (BigDecimal_DoDivmod(self, b, &div, &mod)) {
01483             return BigDecimal_to_i(ToValue(div));
01484         }
01485         return DoSomeOne(self, b, rb_intern("div"));
01486     }
01487 
01488     /* div in BigDecimal sense */
01489     ix = GetPositiveInt(n);
01490     if (ix == 0) {
01491         return BigDecimal_div(self, b);
01492     }
01493     else {
01494         Real *res = NULL;
01495         Real *av = NULL, *bv = NULL, *cv = NULL;
01496         size_t mx = ix + VpBaseFig()*2;
01497         size_t pl = VpSetPrecLimit(0);
01498 
01499         GUARD_OBJ(cv, VpCreateRbObject(mx, "0"));
01500         GUARD_OBJ(av, GetVpValue(self, 1));
01501         GUARD_OBJ(bv, GetVpValue(b, 1));
01502         mx = av->Prec + bv->Prec + 2;
01503         if (mx <= cv->MaxPrec) mx = cv->MaxPrec + 1;
01504         GUARD_OBJ(res, VpCreateRbObject((mx * 2  + 2)*VpBaseFig(), "#0"));
01505         VpDivd(cv, res, av, bv);
01506         VpSetPrecLimit(pl);
01507         VpLeftRound(cv, VpGetRoundMode(), ix);
01508         return ToValue(cv);
01509     }
01510 }
01511 
01512 static VALUE
01513 BigDecimal_div3(int argc, VALUE *argv, VALUE self)
01514 {
01515     VALUE b,n;
01516 
01517     rb_scan_args(argc, argv, "11", &b, &n);
01518 
01519     return BigDecimal_div2(self, b, n);
01520 }
01521 
01522 static VALUE
01523 BigDecimal_add2(VALUE self, VALUE b, VALUE n)
01524 {
01525     ENTER(2);
01526     Real *cv;
01527     SIGNED_VALUE mx = GetPositiveInt(n);
01528     if (mx == 0) return BigDecimal_add(self, b);
01529     else {
01530         size_t pl = VpSetPrecLimit(0);
01531         VALUE   c = BigDecimal_add(self, b);
01532         VpSetPrecLimit(pl);
01533         GUARD_OBJ(cv, GetVpValue(c, 1));
01534         VpLeftRound(cv, VpGetRoundMode(), mx);
01535         return ToValue(cv);
01536     }
01537 }
01538 
01539 /*
01540  * sub(value, digits)  -> bigdecimal
01541  *
01542  * Subtract the specified value.
01543  *
01544  * e.g.
01545  *   c = a.sub(b,n)
01546  *
01547  * digits:: If specified and less than the number of significant digits of the
01548  * result, the result is rounded to that number of digits, according to
01549  * BigDecimal.mode.
01550  *
01551  */
01552 static VALUE
01553 BigDecimal_sub2(VALUE self, VALUE b, VALUE n)
01554 {
01555     ENTER(2);
01556     Real *cv;
01557     SIGNED_VALUE mx = GetPositiveInt(n);
01558     if (mx == 0) return BigDecimal_sub(self, b);
01559     else {
01560         size_t pl = VpSetPrecLimit(0);
01561         VALUE   c = BigDecimal_sub(self, b);
01562         VpSetPrecLimit(pl);
01563         GUARD_OBJ(cv, GetVpValue(c, 1));
01564         VpLeftRound(cv, VpGetRoundMode(), mx);
01565         return ToValue(cv);
01566     }
01567 }
01568 
01569 
01570 static VALUE
01571 BigDecimal_mult2(VALUE self, VALUE b, VALUE n)
01572 {
01573     ENTER(2);
01574     Real *cv;
01575     SIGNED_VALUE mx = GetPositiveInt(n);
01576     if (mx == 0) return BigDecimal_mult(self, b);
01577     else {
01578         size_t pl = VpSetPrecLimit(0);
01579         VALUE   c = BigDecimal_mult(self, b);
01580         VpSetPrecLimit(pl);
01581         GUARD_OBJ(cv, GetVpValue(c, 1));
01582         VpLeftRound(cv, VpGetRoundMode(), mx);
01583         return ToValue(cv);
01584     }
01585 }
01586 
01587 /* Returns the absolute value.
01588  *
01589  * BigDecimal('5').abs -> 5
01590  *
01591  * BigDecimal('-3').abs -> 3
01592  */
01593 static VALUE
01594 BigDecimal_abs(VALUE self)
01595 {
01596     ENTER(5);
01597     Real *c, *a;
01598     size_t mx;
01599 
01600     GUARD_OBJ(a, GetVpValue(self, 1));
01601     mx = a->Prec *(VpBaseFig() + 1);
01602     GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
01603     VpAsgn(c, a, 1);
01604     VpChangeSign(c, 1);
01605     return ToValue(c);
01606 }
01607 
01608 /* call-seq:
01609  * sqrt(n)
01610  *
01611  * Returns the square root of the value.
01612  *
01613  * Result has at least n significant digits.
01614  */
01615 static VALUE
01616 BigDecimal_sqrt(VALUE self, VALUE nFig)
01617 {
01618     ENTER(5);
01619     Real *c, *a;
01620     size_t mx, n;
01621 
01622     GUARD_OBJ(a, GetVpValue(self, 1));
01623     mx = a->Prec * (VpBaseFig() + 1);
01624 
01625     n = GetPositiveInt(nFig) + VpDblFig() + BASE_FIG;
01626     if (mx <= n) mx = n;
01627     GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
01628     VpSqrt(c, a);
01629     return ToValue(c);
01630 }
01631 
01632 /* Return the integer part of the number.
01633  */
01634 static VALUE
01635 BigDecimal_fix(VALUE self)
01636 {
01637     ENTER(5);
01638     Real *c, *a;
01639     size_t mx;
01640 
01641     GUARD_OBJ(a, GetVpValue(self, 1));
01642     mx = a->Prec *(VpBaseFig() + 1);
01643     GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
01644     VpActiveRound(c, a, VP_ROUND_DOWN, 0); /* 0: round off */
01645     return ToValue(c);
01646 }
01647 
01648 /* call-seq:
01649  * round(n, mode)
01650  *
01651  * Round to the nearest 1 (by default), returning the result as a BigDecimal.
01652  *
01653  *      BigDecimal('3.14159').round #=> 3
01654  *      BigDecimal('8.7').round #=> 9
01655  *
01656  * If n is specified and positive, the fractional part of the result has no
01657  * more than that many digits.
01658  *
01659  * If n is specified and negative, at least that many digits to the left of the
01660  * decimal point will be 0 in the result.
01661  *
01662  *      BigDecimal('3.14159').round(3) #=> 3.142
01663  *      BigDecimal('13345.234').round(-2) #=> 13300.0
01664  *
01665  * The value of the optional mode argument can be used to determine how
01666  * rounding is performed; see BigDecimal.mode.
01667  */
01668 static VALUE
01669 BigDecimal_round(int argc, VALUE *argv, VALUE self)
01670 {
01671     ENTER(5);
01672     Real   *c, *a;
01673     int    iLoc = 0;
01674     VALUE  vLoc;
01675     VALUE  vRound;
01676     size_t mx, pl;
01677 
01678     unsigned short sw = VpGetRoundMode();
01679 
01680     switch (rb_scan_args(argc, argv, "02", &vLoc, &vRound)) {
01681       case 0:
01682         iLoc = 0;
01683         break;
01684       case 1:
01685         Check_Type(vLoc, T_FIXNUM);
01686         iLoc = FIX2INT(vLoc);
01687         break;
01688       case 2:
01689         Check_Type(vLoc, T_FIXNUM);
01690         iLoc = FIX2INT(vLoc);
01691         sw = check_rounding_mode(vRound);
01692         break;
01693       default:
01694         break;
01695     }
01696 
01697     pl = VpSetPrecLimit(0);
01698     GUARD_OBJ(a, GetVpValue(self, 1));
01699     mx = a->Prec * (VpBaseFig() + 1);
01700     GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
01701     VpSetPrecLimit(pl);
01702     VpActiveRound(c, a, sw, iLoc);
01703     if (argc == 0) {
01704         return BigDecimal_to_i(ToValue(c));
01705     }
01706     return ToValue(c);
01707 }
01708 
01709 /* call-seq:
01710  * truncate(n)
01711  *
01712  * Truncate to the nearest 1, returning the result as a BigDecimal.
01713  *
01714  *      BigDecimal('3.14159').truncate #=> 3
01715  *      BigDecimal('8.7').truncate #=> 8
01716  *
01717  * If n is specified and positive, the fractional part of the result has no
01718  * more than that many digits.
01719  *
01720  * If n is specified and negative, at least that many digits to the left of the
01721  * decimal point will be 0 in the result.
01722  *
01723  *      BigDecimal('3.14159').truncate(3) #=> 3.141
01724  *      BigDecimal('13345.234').truncate(-2) #=> 13300.0
01725  */
01726 static VALUE
01727 BigDecimal_truncate(int argc, VALUE *argv, VALUE self)
01728 {
01729     ENTER(5);
01730     Real *c, *a;
01731     int iLoc;
01732     VALUE vLoc;
01733     size_t mx, pl = VpSetPrecLimit(0);
01734 
01735     if (rb_scan_args(argc, argv, "01", &vLoc) == 0) {
01736         iLoc = 0;
01737     }
01738     else {
01739         Check_Type(vLoc, T_FIXNUM);
01740         iLoc = FIX2INT(vLoc);
01741     }
01742 
01743     GUARD_OBJ(a, GetVpValue(self, 1));
01744     mx = a->Prec * (VpBaseFig() + 1);
01745     GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
01746     VpSetPrecLimit(pl);
01747     VpActiveRound(c, a, VP_ROUND_DOWN, iLoc); /* 0: truncate */
01748     if (argc == 0) {
01749         return BigDecimal_to_i(ToValue(c));
01750     }
01751     return ToValue(c);
01752 }
01753 
01754 /* Return the fractional part of the number.
01755  */
01756 static VALUE
01757 BigDecimal_frac(VALUE self)
01758 {
01759     ENTER(5);
01760     Real *c, *a;
01761     size_t mx;
01762 
01763     GUARD_OBJ(a, GetVpValue(self, 1));
01764     mx = a->Prec * (VpBaseFig() + 1);
01765     GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
01766     VpFrac(c, a);
01767     return ToValue(c);
01768 }
01769 
01770 /* call-seq:
01771  * floor(n)
01772  *
01773  * Return the largest integer less than or equal to the value, as a BigDecimal.
01774  *
01775  *      BigDecimal('3.14159').floor #=> 3
01776  *      BigDecimal('-9.1').floor #=> -10
01777  *
01778  * If n is specified and positive, the fractional part of the result has no
01779  * more than that many digits.
01780  *
01781  * If n is specified and negative, at least that
01782  * many digits to the left of the decimal point will be 0 in the result.
01783  *
01784  *      BigDecimal('3.14159').floor(3) #=> 3.141
01785  *      BigDecimal('13345.234').floor(-2) #=> 13300.0
01786  */
01787 static VALUE
01788 BigDecimal_floor(int argc, VALUE *argv, VALUE self)
01789 {
01790     ENTER(5);
01791     Real *c, *a;
01792     int iLoc;
01793     VALUE vLoc;
01794     size_t mx, pl = VpSetPrecLimit(0);
01795 
01796     if (rb_scan_args(argc, argv, "01", &vLoc)==0) {
01797         iLoc = 0;
01798     }
01799     else {
01800         Check_Type(vLoc, T_FIXNUM);
01801         iLoc = FIX2INT(vLoc);
01802     }
01803 
01804     GUARD_OBJ(a, GetVpValue(self, 1));
01805     mx = a->Prec * (VpBaseFig() + 1);
01806     GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
01807     VpSetPrecLimit(pl);
01808     VpActiveRound(c, a, VP_ROUND_FLOOR, iLoc);
01809 #ifdef BIGDECIMAL_DEBUG
01810     VPrint(stderr, "floor: c=%\n", c);
01811 #endif
01812     if (argc == 0) {
01813         return BigDecimal_to_i(ToValue(c));
01814     }
01815     return ToValue(c);
01816 }
01817 
01818 /* call-seq:
01819  * ceil(n)
01820  *
01821  * Return the smallest integer greater than or equal to the value, as a BigDecimal.
01822  *
01823  *      BigDecimal('3.14159').ceil #=> 4
01824  *      BigDecimal('-9.1').ceil #=> -9
01825  *
01826  * If n is specified and positive, the fractional part of the result has no
01827  * more than that many digits.
01828  *
01829  * If n is specified and negative, at least that
01830  * many digits to the left of the decimal point will be 0 in the result.
01831  *
01832  *      BigDecimal('3.14159').ceil(3) #=> 3.142
01833  *      BigDecimal('13345.234').ceil(-2) #=> 13400.0
01834  */
01835 static VALUE
01836 BigDecimal_ceil(int argc, VALUE *argv, VALUE self)
01837 {
01838     ENTER(5);
01839     Real *c, *a;
01840     int iLoc;
01841     VALUE vLoc;
01842     size_t mx, pl = VpSetPrecLimit(0);
01843 
01844     if (rb_scan_args(argc, argv, "01", &vLoc) == 0) {
01845         iLoc = 0;
01846     } else {
01847         Check_Type(vLoc, T_FIXNUM);
01848         iLoc = FIX2INT(vLoc);
01849     }
01850 
01851     GUARD_OBJ(a, GetVpValue(self, 1));
01852     mx = a->Prec * (VpBaseFig() + 1);
01853     GUARD_OBJ(c, VpCreateRbObject(mx, "0"));
01854     VpSetPrecLimit(pl);
01855     VpActiveRound(c, a, VP_ROUND_CEIL, iLoc);
01856     if (argc == 0) {
01857         return BigDecimal_to_i(ToValue(c));
01858     }
01859     return ToValue(c);
01860 }
01861 
01862 /* call-seq:
01863  * to_s(s)
01864  *
01865  * Converts the value to a string.
01866  *
01867  * The default format looks like  0.xxxxEnn.
01868  *
01869  * The optional parameter s consists of either an integer; or an optional '+'
01870  * or ' ', followed by an optional number, followed by an optional 'E' or 'F'.
01871  *
01872  * If there is a '+' at the start of s, positive values are returned with
01873  * a leading '+'.
01874  *
01875  * A space at the start of s returns positive values with a leading space.
01876  *
01877  * If s contains a number, a space is inserted after each group of that many
01878  * fractional digits.
01879  *
01880  * If s ends with an 'E', engineering notation (0.xxxxEnn) is used.
01881  *
01882  * If s ends with an 'F', conventional floating point notation is used.
01883  *
01884  * Examples:
01885  *
01886  *      BigDecimal.new('-123.45678901234567890').to_s('5F')
01887  *          #=> '-123.45678 90123 45678 9'
01888  *
01889  *      BigDecimal.new('123.45678901234567890').to_s('+8F')
01890  *          #=> '+123.45678901 23456789'
01891  *
01892  *      BigDecimal.new('123.45678901234567890').to_s(' F')
01893  *          #=> ' 123.4567890123456789'
01894  */
01895 static VALUE
01896 BigDecimal_to_s(int argc, VALUE *argv, VALUE self)
01897 {
01898     ENTER(5);
01899     int   fmt = 0;   /* 0:E format */
01900     int   fPlus = 0; /* =0:default,=1: set ' ' before digits ,set '+' before digits. */
01901     Real  *vp;
01902     volatile VALUE str;
01903     char  *psz;
01904     char   ch;
01905     size_t nc, mc = 0;
01906     VALUE  f;
01907 
01908     GUARD_OBJ(vp, GetVpValue(self, 1));
01909 
01910     if (rb_scan_args(argc, argv, "01", &f) == 1) {
01911         if (RB_TYPE_P(f, T_STRING)) {
01912             SafeStringValue(f);
01913             psz = RSTRING_PTR(f);
01914             if (*psz == ' ') {
01915                 fPlus = 1;
01916                 psz++;
01917             }
01918             else if (*psz == '+') {
01919                 fPlus = 2;
01920                 psz++;
01921             }
01922             while ((ch = *psz++) != 0) {
01923                 if (ISSPACE(ch)) {
01924                     continue;
01925                 }
01926                 if (!ISDIGIT(ch)) {
01927                     if (ch == 'F' || ch == 'f') {
01928                         fmt = 1; /* F format */
01929                     }
01930                     break;
01931                 }
01932                 mc = mc*10 + ch - '0';
01933             }
01934         }
01935         else {
01936             mc = (size_t)GetPositiveInt(f);
01937         }
01938     }
01939     if (fmt) {
01940         nc = VpNumOfChars(vp, "F");
01941     }
01942     else {
01943         nc = VpNumOfChars(vp, "E");
01944     }
01945     if (mc > 0) {
01946         nc += (nc + mc - 1) / mc + 1;
01947     }
01948 
01949     str = rb_str_new(0, nc);
01950     psz = RSTRING_PTR(str);
01951 
01952     if (fmt) {
01953         VpToFString(vp, psz, mc, fPlus);
01954     }
01955     else {
01956         VpToString (vp, psz, mc, fPlus);
01957     }
01958     rb_str_resize(str, strlen(psz));
01959     return str;
01960 }
01961 
01962 /* Splits a BigDecimal number into four parts, returned as an array of values.
01963  *
01964  * The first value represents the sign of the BigDecimal, and is -1 or 1, or 0
01965  * if the BigDecimal is Not a Number.
01966  *
01967  * The second value is a string representing the significant digits of the
01968  * BigDecimal, with no leading zeros.
01969  *
01970  * The third value is the base used for arithmetic (currently always 10) as an
01971  * Integer.
01972  *
01973  * The fourth value is an Integer exponent.
01974  *
01975  * If the BigDecimal can be represented as 0.xxxxxx*10**n, then xxxxxx is the
01976  * string of significant digits with no leading zeros, and n is the exponent.
01977  *
01978  * From these values, you can translate a BigDecimal to a float as follows:
01979  *
01980  *   sign, significant_digits, base, exponent = a.split
01981  *   f = sign * "0.#{significant_digits}".to_f * (base ** exponent)
01982  *
01983  * (Note that the to_f method is provided as a more convenient way to translate
01984  * a BigDecimal to a Float.)
01985  */
01986 static VALUE
01987 BigDecimal_split(VALUE self)
01988 {
01989     ENTER(5);
01990     Real *vp;
01991     VALUE obj,str;
01992     ssize_t e, s;
01993     char *psz1;
01994 
01995     GUARD_OBJ(vp, GetVpValue(self, 1));
01996     str = rb_str_new(0, VpNumOfChars(vp, "E"));
01997     psz1 = RSTRING_PTR(str);
01998     VpSzMantissa(vp, psz1);
01999     s = 1;
02000     if(psz1[0] == '-') {
02001         size_t len = strlen(psz1 + 1);
02002 
02003         memmove(psz1, psz1 + 1, len);
02004         psz1[len] = '\0';
02005         s = -1;
02006     }
02007     if (psz1[0] == 'N') s = 0; /* NaN */
02008     e = VpExponent10(vp);
02009     obj = rb_ary_new2(4);
02010     rb_ary_push(obj, INT2FIX(s));
02011     rb_ary_push(obj, str);
02012     rb_str_resize(str, strlen(psz1));
02013     rb_ary_push(obj, INT2FIX(10));
02014     rb_ary_push(obj, INT2NUM(e));
02015     return obj;
02016 }
02017 
02018 /* Returns the exponent of the BigDecimal number, as an Integer.
02019  *
02020  * If the number can be represented as 0.xxxxxx*10**n where xxxxxx is a string
02021  * of digits with no leading zeros, then n is the exponent.
02022  */
02023 static VALUE
02024 BigDecimal_exponent(VALUE self)
02025 {
02026     ssize_t e = VpExponent10(GetVpValue(self, 1));
02027     return INT2NUM(e);
02028 }
02029 
02030 /* Returns debugging information about the value as a string of comma-separated
02031  * values in angle brackets with a leading #:
02032  *
02033  * BigDecimal.new("1234.5678").inspect ->
02034  * "#<BigDecimal:b7ea1130,'0.12345678E4',8(12)>"
02035  *
02036  * The first part is the address, the second is the value as a string, and
02037  * the final part ss(mm) is the current number of significant digits and the
02038  * maximum number of significant digits, respectively.
02039  */
02040 static VALUE
02041 BigDecimal_inspect(VALUE self)
02042 {
02043     ENTER(5);
02044     Real *vp;
02045     volatile VALUE obj;
02046     size_t nc;
02047     char *psz, *tmp;
02048 
02049     GUARD_OBJ(vp, GetVpValue(self, 1));
02050     nc = VpNumOfChars(vp, "E");
02051     nc += (nc + 9) / 10;
02052 
02053     obj = rb_str_new(0, nc+256);
02054     psz = RSTRING_PTR(obj);
02055     sprintf(psz, "#<BigDecimal:%"PRIxVALUE",'", self);
02056     tmp = psz + strlen(psz);
02057     VpToString(vp, tmp, 10, 0);
02058     tmp += strlen(tmp);
02059     sprintf(tmp, "',%"PRIuSIZE"(%"PRIuSIZE")>", VpPrec(vp)*VpBaseFig(), VpMaxPrec(vp)*VpBaseFig());
02060     rb_str_resize(obj, strlen(psz));
02061     return obj;
02062 }
02063 
02064 static VALUE BigMath_s_exp(VALUE, VALUE, VALUE);
02065 static VALUE BigMath_s_log(VALUE, VALUE, VALUE);
02066 
02067 #define BigMath_exp(x, n) BigMath_s_exp(rb_mBigMath, (x), (n))
02068 #define BigMath_log(x, n) BigMath_s_log(rb_mBigMath, (x), (n))
02069 
02070 inline static int
02071 is_integer(VALUE x)
02072 {
02073     return (RB_TYPE_P(x, T_FIXNUM) || RB_TYPE_P(x, T_BIGNUM));
02074 }
02075 
02076 inline static int
02077 is_negative(VALUE x)
02078 {
02079     if (FIXNUM_P(x)) {
02080         return FIX2LONG(x) < 0;
02081     }
02082     else if (RB_TYPE_P(x, T_BIGNUM)) {
02083         return RBIGNUM_NEGATIVE_P(x);
02084     }
02085     else if (RB_TYPE_P(x, T_FLOAT)) {
02086         return RFLOAT_VALUE(x) < 0.0;
02087     }
02088     return RTEST(rb_funcall(x, '<', 1, INT2FIX(0)));
02089 }
02090 
02091 #define is_positive(x) (!is_negative(x))
02092 
02093 inline static int
02094 is_zero(VALUE x)
02095 {
02096     VALUE num;
02097 
02098     switch (TYPE(x)) {
02099       case T_FIXNUM:
02100         return FIX2LONG(x) == 0;
02101 
02102       case T_BIGNUM:
02103         return Qfalse;
02104 
02105       case T_RATIONAL:
02106         num = RRATIONAL(x)->num;
02107         return FIXNUM_P(num) && FIX2LONG(num) == 0;
02108 
02109       default:
02110         break;
02111     }
02112 
02113     return RTEST(rb_funcall(x, id_eq, 1, INT2FIX(0)));
02114 }
02115 
02116 inline static int
02117 is_one(VALUE x)
02118 {
02119     VALUE num, den;
02120 
02121     switch (TYPE(x)) {
02122       case T_FIXNUM:
02123         return FIX2LONG(x) == 1;
02124 
02125       case T_BIGNUM:
02126         return Qfalse;
02127 
02128       case T_RATIONAL:
02129         num = RRATIONAL(x)->num;
02130         den = RRATIONAL(x)->den;
02131         return FIXNUM_P(den) && FIX2LONG(den) == 1 &&
02132                FIXNUM_P(num) && FIX2LONG(num) == 1;
02133 
02134       default:
02135         break;
02136     }
02137 
02138     return RTEST(rb_funcall(x, id_eq, 1, INT2FIX(1)));
02139 }
02140 
02141 inline static int
02142 is_even(VALUE x)
02143 {
02144     switch (TYPE(x)) {
02145       case T_FIXNUM:
02146         return (FIX2LONG(x) % 2) == 0;
02147 
02148       case T_BIGNUM:
02149         {
02150             unsigned long l;
02151             rb_big_pack(x, &l, 1);
02152             return l % 2 == 0;
02153         }
02154 
02155       default:
02156         break;
02157     }
02158 
02159     return 0;
02160 }
02161 
02162 static VALUE
02163 rmpd_power_by_big_decimal(Real const* x, Real const* exp, ssize_t const n)
02164 {
02165     VALUE log_x, multiplied, y;
02166     volatile VALUE obj = exp->obj;
02167 
02168     if (VpIsZero(exp)) {
02169         return ToValue(VpCreateRbObject(n, "1"));
02170     }
02171 
02172     log_x = BigMath_log(x->obj, SSIZET2NUM(n+1));
02173     multiplied = BigDecimal_mult2(exp->obj, log_x, SSIZET2NUM(n+1));
02174     y = BigMath_exp(multiplied, SSIZET2NUM(n));
02175     RB_GC_GUARD(obj);
02176 
02177     return y;
02178 }
02179 
02180 /* call-seq:
02181  * power(n)
02182  * power(n, prec)
02183  *
02184  * Returns the value raised to the power of n.
02185  *
02186  * Note that n must be an Integer.
02187  *
02188  * Also available as the operator **
02189  */
02190 static VALUE
02191 BigDecimal_power(int argc, VALUE*argv, VALUE self)
02192 {
02193     ENTER(5);
02194     VALUE vexp, prec;
02195     Real* exp = NULL;
02196     Real *x, *y;
02197     ssize_t mp, ma, n;
02198     SIGNED_VALUE int_exp;
02199     double d;
02200 
02201     rb_scan_args(argc, argv, "11", &vexp, &prec);
02202 
02203     GUARD_OBJ(x, GetVpValue(self, 1));
02204     n = NIL_P(prec) ? (ssize_t)(x->Prec*VpBaseFig()) : NUM2SSIZET(prec);
02205 
02206     if (VpIsNaN(x)) {
02207         y = VpCreateRbObject(n, "0#");
02208         RB_GC_GUARD(y->obj);
02209         VpSetNaN(y);
02210         return ToValue(y);
02211     }
02212 
02213   retry:
02214     switch (TYPE(vexp)) {
02215       case T_FIXNUM:
02216         break;
02217 
02218       case T_BIGNUM:
02219         break;
02220 
02221       case T_FLOAT:
02222         d = RFLOAT_VALUE(vexp);
02223         if (d == round(d)) {
02224             if (FIXABLE(d)) {
02225                 vexp = LONG2FIX((long)d);
02226             }
02227             else {
02228                 vexp = rb_dbl2big(d);
02229             }
02230             goto retry;
02231         }
02232         exp = GetVpValueWithPrec(vexp, DBL_DIG+1, 1);
02233         break;
02234 
02235       case T_RATIONAL:
02236         if (is_zero(RRATIONAL(vexp)->num)) {
02237             if (is_positive(vexp)) {
02238                 vexp = INT2FIX(0);
02239                 goto retry;
02240             }
02241         }
02242         else if (is_one(RRATIONAL(vexp)->den)) {
02243             vexp = RRATIONAL(vexp)->num;
02244             goto retry;
02245         }
02246         exp = GetVpValueWithPrec(vexp, n, 1);
02247         break;
02248 
02249       case T_DATA:
02250         if (is_kind_of_BigDecimal(vexp)) {
02251             VALUE zero = INT2FIX(0);
02252             VALUE rounded = BigDecimal_round(1, &zero, vexp);
02253             if (RTEST(BigDecimal_eq(vexp, rounded))) {
02254                 vexp = BigDecimal_to_i(vexp);
02255                 goto retry;
02256             }
02257             exp = DATA_PTR(vexp);
02258             break;
02259         }
02260         /* fall through */
02261       default:
02262         rb_raise(rb_eTypeError,
02263                  "wrong argument type %s (expected scalar Numeric)",
02264                  rb_obj_classname(vexp));
02265     }
02266 
02267     if (VpIsZero(x)) {
02268         if (is_negative(vexp)) {
02269             y = VpCreateRbObject(n, "#0");
02270             RB_GC_GUARD(y->obj);
02271             if (VpGetSign(x) < 0) {
02272                 if (is_integer(vexp)) {
02273                     if (is_even(vexp)) {
02274                         /* (-0) ** (-even_integer)  -> Infinity */
02275                         VpSetPosInf(y);
02276                     }
02277                     else {
02278                         /* (-0) ** (-odd_integer)  -> -Infinity */
02279                         VpSetNegInf(y);
02280                     }
02281                 }
02282                 else {
02283                     /* (-0) ** (-non_integer)  -> Infinity */
02284                     VpSetPosInf(y);
02285                 }
02286             }
02287             else {
02288                 /* (+0) ** (-num)  -> Infinity */
02289                 VpSetPosInf(y);
02290             }
02291             return ToValue(y);
02292         }
02293         else if (is_zero(vexp)) {
02294             return ToValue(VpCreateRbObject(n, "1"));
02295         }
02296         else {
02297             return ToValue(VpCreateRbObject(n, "0"));
02298         }
02299     }
02300 
02301     if (is_zero(vexp)) {
02302         return ToValue(VpCreateRbObject(n, "1"));
02303     }
02304     else if (is_one(vexp)) {
02305         return self;
02306     }
02307 
02308     if (VpIsInf(x)) {
02309         if (is_negative(vexp)) {
02310             if (VpGetSign(x) < 0) {
02311                 if (is_integer(vexp)) {
02312                     if (is_even(vexp)) {
02313                         /* (-Infinity) ** (-even_integer) -> +0 */
02314                         return ToValue(VpCreateRbObject(n, "0"));
02315                     }
02316                     else {
02317                         /* (-Infinity) ** (-odd_integer) -> -0 */
02318                         return ToValue(VpCreateRbObject(n, "-0"));
02319                     }
02320                 }
02321                 else {
02322                     /* (-Infinity) ** (-non_integer) -> -0 */
02323                     return ToValue(VpCreateRbObject(n, "-0"));
02324                 }
02325             }
02326             else {
02327                 return ToValue(VpCreateRbObject(n, "0"));
02328             }
02329         }
02330         else {
02331             y = VpCreateRbObject(n, "0#");
02332             if (VpGetSign(x) < 0) {
02333                 if (is_integer(vexp)) {
02334                     if (is_even(vexp)) {
02335                         VpSetPosInf(y);
02336                     }
02337                     else {
02338                         VpSetNegInf(y);
02339                     }
02340                 }
02341                 else {
02342                     /* TODO: support complex */
02343                     rb_raise(rb_eMathDomainError,
02344                              "a non-integral exponent for a negative base");
02345                 }
02346             }
02347             else {
02348                 VpSetPosInf(y);
02349             }
02350             return ToValue(y);
02351         }
02352     }
02353 
02354     if (exp != NULL) {
02355         return rmpd_power_by_big_decimal(x, exp, n);
02356     }
02357     else if (RB_TYPE_P(vexp, T_BIGNUM)) {
02358         VALUE abs_value = BigDecimal_abs(self);
02359         if (is_one(abs_value)) {
02360             return ToValue(VpCreateRbObject(n, "1"));
02361         }
02362         else if (RTEST(rb_funcall(abs_value, '<', 1, INT2FIX(1)))) {
02363             if (is_negative(vexp)) {
02364                 y = VpCreateRbObject(n, "0#");
02365                 if (is_even(vexp)) {
02366                     VpSetInf(y, VpGetSign(x));
02367                 }
02368                 else {
02369                     VpSetInf(y, -VpGetSign(x));
02370                 }
02371                 return ToValue(y);
02372             }
02373             else if (VpGetSign(x) < 0 && is_even(vexp)) {
02374                 return ToValue(VpCreateRbObject(n, "-0"));
02375             }
02376             else {
02377                 return ToValue(VpCreateRbObject(n, "0"));
02378             }
02379         }
02380         else {
02381             if (is_positive(vexp)) {
02382                 y = VpCreateRbObject(n, "0#");
02383                 if (is_even(vexp)) {
02384                     VpSetInf(y, VpGetSign(x));
02385                 }
02386                 else {
02387                     VpSetInf(y, -VpGetSign(x));
02388                 }
02389                 return ToValue(y);
02390             }
02391             else if (VpGetSign(x) < 0 && is_even(vexp)) {
02392                 return ToValue(VpCreateRbObject(n, "-0"));
02393             }
02394             else {
02395                 return ToValue(VpCreateRbObject(n, "0"));
02396             }
02397         }
02398     }
02399 
02400     int_exp = FIX2LONG(vexp);
02401     ma = int_exp;
02402     if (ma <  0) ma = -ma;
02403     if (ma == 0) ma = 1;
02404 
02405     if (VpIsDef(x)) {
02406         mp = x->Prec * (VpBaseFig() + 1);
02407         GUARD_OBJ(y, VpCreateRbObject(mp * (ma + 1), "0"));
02408     }
02409     else {
02410         GUARD_OBJ(y, VpCreateRbObject(1, "0"));
02411     }
02412     VpPower(y, x, int_exp);
02413     if (!NIL_P(prec) && VpIsDef(y)) {
02414         VpMidRound(y, VpGetRoundMode(), n);
02415     }
02416     return ToValue(y);
02417 }
02418 
02419 /* call-seq:
02420  *   big_decimal ** exp  -> big_decimal
02421  *
02422  * It is a synonym of BigDecimal#power(exp).
02423  */
02424 static VALUE
02425 BigDecimal_power_op(VALUE self, VALUE exp)
02426 {
02427     return BigDecimal_power(1, &exp, self);
02428 }
02429 
02430 static VALUE
02431 BigDecimal_s_allocate(VALUE klass)
02432 {
02433     return VpNewRbClass(0, NULL, klass)->obj;
02434 }
02435 
02436 static Real *BigDecimal_new(int argc, VALUE *argv);
02437 
02438 /* call-seq:
02439  *   new(initial, digits)
02440  *
02441  * Create a new BigDecimal object.
02442  *
02443  * initial:: The initial value, as an Integer, a Float, a Rational,
02444  *           a BigDecimal, or a String.
02445  *
02446  *           If it is a String, spaces are ignored and unrecognized characters
02447  *           terminate the value.
02448  *
02449  * digits:: The number of significant digits, as a Fixnum. If omitted or 0,
02450  *          the number of significant digits is determined from the initial
02451  *          value.
02452  *
02453  * The actual number of significant digits used in computation is usually
02454  * larger than the specified number.
02455  */
02456 static VALUE
02457 BigDecimal_initialize(int argc, VALUE *argv, VALUE self)
02458 {
02459     ENTER(1);
02460     Real *pv = rb_check_typeddata(self, &BigDecimal_data_type);
02461     Real *x;
02462 
02463     GUARD_OBJ(x, BigDecimal_new(argc, argv));
02464     if (ToValue(x)) {
02465         pv = VpCopy(pv, x);
02466     }
02467     else {
02468         VpFree(pv);
02469         pv = x;
02470     }
02471     DATA_PTR(self) = pv;
02472     pv->obj = self;
02473     return self;
02474 }
02475 
02476 /* :nodoc:
02477  *
02478  * private method to dup and clone the provided BigDecimal +other+
02479  */
02480 static VALUE
02481 BigDecimal_initialize_copy(VALUE self, VALUE other)
02482 {
02483     Real *pv = rb_check_typeddata(self, &BigDecimal_data_type);
02484     Real *x = rb_check_typeddata(other, &BigDecimal_data_type);
02485 
02486     if (self != other) {
02487         DATA_PTR(self) = VpCopy(pv, x);
02488     }
02489     return self;
02490 }
02491 
02492 static Real *
02493 BigDecimal_new(int argc, VALUE *argv)
02494 {
02495     size_t mf;
02496     VALUE  nFig;
02497     VALUE  iniValue;
02498 
02499     if (rb_scan_args(argc, argv, "11", &iniValue, &nFig) == 1) {
02500         mf = 0;
02501     }
02502     else {
02503         mf = GetPositiveInt(nFig);
02504     }
02505 
02506     switch (TYPE(iniValue)) {
02507       case T_DATA:
02508         if (is_kind_of_BigDecimal(iniValue)) {
02509             return DATA_PTR(iniValue);
02510         }
02511         break;
02512 
02513       case T_FIXNUM:
02514         /* fall through */
02515       case T_BIGNUM:
02516         return GetVpValue(iniValue, 1);
02517 
02518       case T_FLOAT:
02519         if (mf > DBL_DIG+1) {
02520             rb_raise(rb_eArgError, "precision too large.");
02521         }
02522         /* fall through */
02523       case T_RATIONAL:
02524         if (NIL_P(nFig)) {
02525             rb_raise(rb_eArgError,
02526                      "can't omit precision for a %"PRIsVALUE".",
02527                      rb_obj_class(iniValue));
02528         }
02529         return GetVpValueWithPrec(iniValue, mf, 1);
02530 
02531       case T_STRING:
02532         /* fall through */
02533       default:
02534         break;
02535     }
02536     StringValueCStr(iniValue);
02537     return VpAlloc(mf, RSTRING_PTR(iniValue));
02538 }
02539 
02540 /* See also BigDecimal::new */
02541 static VALUE
02542 BigDecimal_global_new(int argc, VALUE *argv, VALUE self)
02543 {
02544     ENTER(1);
02545     Real *pv;
02546 
02547     GUARD_OBJ(pv, BigDecimal_new(argc, argv));
02548     if (ToValue(pv)) pv = VpCopy(NULL, pv);
02549     pv->obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, pv);
02550     return pv->obj;
02551 }
02552 
02553  /* call-seq:
02554   * BigDecimal.limit(digits)
02555   *
02556   * Limit the number of significant digits in newly created BigDecimal
02557   * numbers to the specified value. Rounding is performed as necessary,
02558   * as specified by BigDecimal.mode.
02559   *
02560   * A limit of 0, the default, means no upper limit.
02561   *
02562   * The limit specified by this method takes less priority over any limit
02563   * specified to instance methods such as ceil, floor, truncate, or round.
02564   */
02565 static VALUE
02566 BigDecimal_limit(int argc, VALUE *argv, VALUE self)
02567 {
02568     VALUE  nFig;
02569     VALUE  nCur = INT2NUM(VpGetPrecLimit());
02570 
02571     if (rb_scan_args(argc, argv, "01", &nFig) == 1) {
02572         int nf;
02573         if (NIL_P(nFig)) return nCur;
02574         Check_Type(nFig, T_FIXNUM);
02575         nf = FIX2INT(nFig);
02576         if (nf < 0) {
02577             rb_raise(rb_eArgError, "argument must be positive");
02578         }
02579         VpSetPrecLimit(nf);
02580     }
02581     return nCur;
02582 }
02583 
02584 /* Returns the sign of the value.
02585  *
02586  * Returns a positive value if > 0, a negative value if < 0, and a
02587  * zero if == 0.
02588  *
02589  * The specific value returned indicates the type and sign of the BigDecimal,
02590  * as follows:
02591  *
02592  * BigDecimal::SIGN_NaN:: value is Not a Number
02593  * BigDecimal::SIGN_POSITIVE_ZERO:: value is +0
02594  * BigDecimal::SIGN_NEGATIVE_ZERO:: value is -0
02595  * BigDecimal::SIGN_POSITIVE_INFINITE:: value is +Infinity
02596  * BigDecimal::SIGN_NEGATIVE_INFINITE:: value is -Infinity
02597  * BigDecimal::SIGN_POSITIVE_FINITE:: value is positive
02598  * BigDecimal::SIGN_NEGATIVE_FINITE:: value is negative
02599  */
02600 static VALUE
02601 BigDecimal_sign(VALUE self)
02602 { /* sign */
02603     int s = GetVpValue(self, 1)->sign;
02604     return INT2FIX(s);
02605 }
02606 
02607 /*
02608  * call-seq: BigDecimal.save_exception_mode { ... }
02609  *
02610  * Execute the provided block, but preserve the exception mode
02611  *
02612  *     BigDecimal.save_exception_mode do
02613  *       BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
02614  *       BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
02615  *
02616  *       BigDecimal.new(BigDecimal('Infinity'))
02617  *       BigDecimal.new(BigDecimal('-Infinity'))
02618  *       BigDecimal(BigDecimal.new('NaN'))
02619  *     end
02620  *
02621  * For use with the BigDecimal::EXCEPTION_*
02622  *
02623  * See BigDecimal.mode
02624  */
02625 static VALUE
02626 BigDecimal_save_exception_mode(VALUE self)
02627 {
02628     unsigned short const exception_mode = VpGetException();
02629     int state;
02630     VALUE ret = rb_protect(rb_yield, Qnil, &state);
02631     VpSetException(exception_mode);
02632     if (state) rb_jump_tag(state);
02633     return ret;
02634 }
02635 
02636 /*
02637  * call-seq: BigDecimal.save_rounding_mode { ... }
02638  *
02639  * Execute the provided block, but preserve the rounding mode
02640  *
02641  *     BigDecimal.save_rounding_mode do
02642  *       BigDecimal.mode(BigDecimal::ROUND_MODE, :up)
02643  *       puts BigDecimal.mode(BigDecimal::ROUND_MODE)
02644  *     end
02645  *
02646  * For use with the BigDecimal::ROUND_*
02647  *
02648  * See BigDecimal.mode
02649  */
02650 static VALUE
02651 BigDecimal_save_rounding_mode(VALUE self)
02652 {
02653     unsigned short const round_mode = VpGetRoundMode();
02654     int state;
02655     VALUE ret = rb_protect(rb_yield, Qnil, &state);
02656     VpSetRoundMode(round_mode);
02657     if (state) rb_jump_tag(state);
02658     return ret;
02659 }
02660 
02661 /*
02662  * call-seq: BigDecimal.save_limit { ... }
02663  *
02664  * Execute the provided block, but preserve the precision limit
02665  *
02666  *      BigDecimal.limit(100)
02667  *      puts BigDecimal.limit
02668  *      BigDecimal.save_limit do
02669  *          BigDecimal.limit(200)
02670  *          puts BigDecimal.limit
02671  *      end
02672  *      puts BigDecimal.limit
02673  *
02674  */
02675 static VALUE
02676 BigDecimal_save_limit(VALUE self)
02677 {
02678     size_t const limit = VpGetPrecLimit();
02679     int state;
02680     VALUE ret = rb_protect(rb_yield, Qnil, &state);
02681     VpSetPrecLimit(limit);
02682     if (state) rb_jump_tag(state);
02683     return ret;
02684 }
02685 
02686 /* call-seq:
02687  * BigMath.exp(decimal, numeric)    -> BigDecimal
02688  *
02689  * Computes the value of e (the base of natural logarithms) raised to the
02690  * power of +decimal+, to the specified number of digits of precision.
02691  *
02692  * If +decimal+ is infinity, returns Infinity.
02693  *
02694  * If +decimal+ is NaN, returns NaN.
02695  */
02696 static VALUE
02697 BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec)
02698 {
02699     ssize_t prec, n, i;
02700     Real* vx = NULL;
02701     VALUE one, d, y;
02702     int negative = 0;
02703     int infinite = 0;
02704     int nan = 0;
02705     double flo;
02706 
02707     prec = NUM2SSIZET(vprec);
02708     if (prec <= 0) {
02709         rb_raise(rb_eArgError, "Zero or negative precision for exp");
02710     }
02711 
02712     /* TODO: the following switch statement is almostly the same as one in the
02713      *       BigDecimalCmp function. */
02714     switch (TYPE(x)) {
02715       case T_DATA:
02716         if (!is_kind_of_BigDecimal(x)) break;
02717         vx = DATA_PTR(x);
02718         negative = VpGetSign(vx) < 0;
02719         infinite = VpIsPosInf(vx) || VpIsNegInf(vx);
02720         nan = VpIsNaN(vx);
02721         break;
02722 
02723       case T_FIXNUM:
02724         /* fall through */
02725       case T_BIGNUM:
02726         vx = GetVpValue(x, 0);
02727         break;
02728 
02729       case T_FLOAT:
02730         flo = RFLOAT_VALUE(x);
02731         negative = flo < 0;
02732         infinite = isinf(flo);
02733         nan = isnan(flo);
02734         if (!infinite && !nan) {
02735             vx = GetVpValueWithPrec(x, DBL_DIG+1, 0);
02736         }
02737         break;
02738 
02739       case T_RATIONAL:
02740         vx = GetVpValueWithPrec(x, prec, 0);
02741         break;
02742 
02743       default:
02744         break;
02745     }
02746     if (infinite) {
02747         if (negative) {
02748             return ToValue(GetVpValueWithPrec(INT2FIX(0), prec, 1));
02749         }
02750         else {
02751             Real* vy;
02752             vy = VpCreateRbObject(prec, "#0");
02753             VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
02754             RB_GC_GUARD(vy->obj);
02755             return ToValue(vy);
02756         }
02757     }
02758     else if (nan) {
02759         Real* vy;
02760         vy = VpCreateRbObject(prec, "#0");
02761         VpSetNaN(vy);
02762         RB_GC_GUARD(vy->obj);
02763         return ToValue(vy);
02764     }
02765     else if (vx == NULL) {
02766         cannot_be_coerced_into_BigDecimal(rb_eArgError, x);
02767     }
02768     x = vx->obj;
02769 
02770     n = prec + rmpd_double_figures();
02771     negative = VpGetSign(vx) < 0;
02772     if (negative) {
02773         VpSetSign(vx, 1);
02774     }
02775 
02776     one = ToValue(VpCreateRbObject(1, "1"));
02777     y   = one;
02778     d   = y;
02779     i   = 1;
02780 
02781     while (!VpIsZero((Real*)DATA_PTR(d))) {
02782         SIGNED_VALUE const ey = VpExponent10(DATA_PTR(y));
02783         SIGNED_VALUE const ed = VpExponent10(DATA_PTR(d));
02784         ssize_t m = n - vabs(ey - ed);
02785 
02786         rb_thread_check_ints();
02787 
02788         if (m <= 0) {
02789             break;
02790         }
02791         else if ((size_t)m < rmpd_double_figures()) {
02792             m = rmpd_double_figures();
02793         }
02794 
02795         d = BigDecimal_mult(d, x);                             /* d <- d * x */
02796         d = BigDecimal_div2(d, SSIZET2NUM(i), SSIZET2NUM(m));  /* d <- d / i */
02797         y = BigDecimal_add(y, d);                              /* y <- y + d  */
02798         ++i;                                                   /* i  <- i + 1 */
02799     }
02800 
02801     if (negative) {
02802         return BigDecimal_div2(one, y, vprec);
02803     }
02804     else {
02805         vprec = SSIZET2NUM(prec - VpExponent10(DATA_PTR(y)));
02806         return BigDecimal_round(1, &vprec, y);
02807     }
02808 
02809     RB_GC_GUARD(one);
02810     RB_GC_GUARD(x);
02811     RB_GC_GUARD(y);
02812     RB_GC_GUARD(d);
02813 }
02814 
02815 /* call-seq:
02816  * BigMath.log(decimal, numeric)    -> BigDecimal
02817  *
02818  * Computes the natural logarithm of +decimal+ to the specified number of
02819  * digits of precision, +numeric+.
02820  *
02821  * If +decimal+ is zero or negative, raises Math::DomainError.
02822  *
02823  * If +decimal+ is positive infinity, returns Infinity.
02824  *
02825  * If +decimal+ is NaN, returns NaN.
02826  */
02827 static VALUE
02828 BigMath_s_log(VALUE klass, VALUE x, VALUE vprec)
02829 {
02830     ssize_t prec, n, i;
02831     SIGNED_VALUE expo;
02832     Real* vx = NULL;
02833     VALUE vn, one, two, w, x2, y, d;
02834     int zero = 0;
02835     int negative = 0;
02836     int infinite = 0;
02837     int nan = 0;
02838     double flo;
02839     long fix;
02840 
02841     if (!is_integer(vprec)) {
02842         rb_raise(rb_eArgError, "precision must be an Integer");
02843     }
02844 
02845     prec = NUM2SSIZET(vprec);
02846     if (prec <= 0) {
02847         rb_raise(rb_eArgError, "Zero or negative precision for exp");
02848     }
02849 
02850     /* TODO: the following switch statement is almostly the same as one in the
02851      *       BigDecimalCmp function. */
02852     switch (TYPE(x)) {
02853       case T_DATA:
02854           if (!is_kind_of_BigDecimal(x)) break;
02855           vx = DATA_PTR(x);
02856           zero = VpIsZero(vx);
02857           negative = VpGetSign(vx) < 0;
02858           infinite = VpIsPosInf(vx) || VpIsNegInf(vx);
02859           nan = VpIsNaN(vx);
02860           break;
02861 
02862       case T_FIXNUM:
02863         fix = FIX2LONG(x);
02864         zero = fix == 0;
02865         negative = fix < 0;
02866         goto get_vp_value;
02867 
02868       case T_BIGNUM:
02869         zero = RBIGNUM_ZERO_P(x);
02870         negative = RBIGNUM_NEGATIVE_P(x);
02871 get_vp_value:
02872         if (zero || negative) break;
02873         vx = GetVpValue(x, 0);
02874         break;
02875 
02876       case T_FLOAT:
02877         flo = RFLOAT_VALUE(x);
02878         zero = flo == 0;
02879         negative = flo < 0;
02880         infinite = isinf(flo);
02881         nan = isnan(flo);
02882         if (!zero && !negative && !infinite && !nan) {
02883             vx = GetVpValueWithPrec(x, DBL_DIG+1, 1);
02884         }
02885         break;
02886 
02887       case T_RATIONAL:
02888         zero = RRATIONAL_ZERO_P(x);
02889         negative = RRATIONAL_NEGATIVE_P(x);
02890         if (zero || negative) break;
02891         vx = GetVpValueWithPrec(x, prec, 1);
02892         break;
02893 
02894       case T_COMPLEX:
02895         rb_raise(rb_eMathDomainError,
02896                  "Complex argument for BigMath.log");
02897 
02898       default:
02899         break;
02900     }
02901     if (infinite && !negative) {
02902         Real* vy;
02903         vy = VpCreateRbObject(prec, "#0");
02904         RB_GC_GUARD(vy->obj);
02905         VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE);
02906         return ToValue(vy);
02907     }
02908     else if (nan) {
02909         Real* vy;
02910         vy = VpCreateRbObject(prec, "#0");
02911         RB_GC_GUARD(vy->obj);
02912         VpSetNaN(vy);
02913         return ToValue(vy);
02914     }
02915     else if (zero || negative) {
02916         rb_raise(rb_eMathDomainError,
02917                  "Zero or negative argument for log");
02918     }
02919     else if (vx == NULL) {
02920         cannot_be_coerced_into_BigDecimal(rb_eArgError, x);
02921     }
02922     x = ToValue(vx);
02923 
02924     RB_GC_GUARD(one) = ToValue(VpCreateRbObject(1, "1"));
02925     RB_GC_GUARD(two) = ToValue(VpCreateRbObject(1, "2"));
02926 
02927     n = prec + rmpd_double_figures();
02928     RB_GC_GUARD(vn) = SSIZET2NUM(n);
02929     expo = VpExponent10(vx);
02930     if (expo < 0 || expo >= 3) {
02931         char buf[16];
02932         snprintf(buf, 16, "1E%"PRIdVALUE, -expo);
02933         x = BigDecimal_mult2(x, ToValue(VpCreateRbObject(1, buf)), vn);
02934     }
02935     else {
02936         expo = 0;
02937     }
02938     w = BigDecimal_sub(x, one);
02939     x = BigDecimal_div2(w, BigDecimal_add(x, one), vn);
02940     RB_GC_GUARD(x2) = BigDecimal_mult2(x, x, vn);
02941     RB_GC_GUARD(y)  = x;
02942     RB_GC_GUARD(d)  = y;
02943     i = 1;
02944     while (!VpIsZero((Real*)DATA_PTR(d))) {
02945         SIGNED_VALUE const ey = VpExponent10(DATA_PTR(y));
02946         SIGNED_VALUE const ed = VpExponent10(DATA_PTR(d));
02947         ssize_t m = n - vabs(ey - ed);
02948         if (m <= 0) {
02949             break;
02950         }
02951         else if ((size_t)m < rmpd_double_figures()) {
02952             m = rmpd_double_figures();
02953         }
02954 
02955         x = BigDecimal_mult2(x2, x, vn);
02956         i += 2;
02957         d = BigDecimal_div2(x, SSIZET2NUM(i), SSIZET2NUM(m));
02958         y = BigDecimal_add(y, d);
02959     }
02960 
02961     y = BigDecimal_mult(y, two);
02962     if (expo != 0) {
02963         VALUE log10, vexpo, dy;
02964         log10 = BigMath_s_log(klass, INT2FIX(10), vprec);
02965         vexpo = ToValue(GetVpValue(SSIZET2NUM(expo), 1));
02966         dy = BigDecimal_mult(log10, vexpo);
02967         y = BigDecimal_add(y, dy);
02968     }
02969 
02970     return y;
02971 }
02972 
02973 /* Document-class: BigDecimal
02974  * BigDecimal provides arbitrary-precision floating point decimal arithmetic.
02975  *
02976  * == Introduction
02977  *
02978  * Ruby provides built-in support for arbitrary precision integer arithmetic.
02979  *
02980  * For example:
02981  *
02982  *      42**13  #=>   1265437718438866624512
02983  *
02984  * BigDecimal provides similar support for very large or very accurate floating
02985  * point numbers.
02986  *
02987  * Decimal arithmetic is also useful for general calculation, because it
02988  * provides the correct answers people expect--whereas normal binary floating
02989  * point arithmetic often introduces subtle errors because of the conversion
02990  * between base 10 and base 2.
02991  *
02992  * For example, try:
02993  *
02994  *   sum = 0
02995  *   10_000.times do
02996  *     sum = sum + 0.0001
02997  *   end
02998  *   print sum #=> 0.9999999999999062
02999  *
03000  * and contrast with the output from:
03001  *
03002  *   require 'bigdecimal'
03003  *
03004  *   sum = BigDecimal.new("0")
03005  *   10_000.times do
03006  *     sum = sum + BigDecimal.new("0.0001")
03007  *   end
03008  *   print sum #=> 0.1E1
03009  *
03010  * Similarly:
03011  *
03012  *      (BigDecimal.new("1.2") - BigDecimal("1.0")) == BigDecimal("0.2") #=> true
03013  *
03014  *      (1.2 - 1.0) == 0.2 #=> false
03015  *
03016  * == Special features of accurate decimal arithmetic
03017  *
03018  * Because BigDecimal is more accurate than normal binary floating point
03019  * arithmetic, it requires some special values.
03020  *
03021  * === Infinity
03022  *
03023  * BigDecimal sometimes needs to return infinity, for example if you divide
03024  * a value by zero.
03025  *
03026  *      BigDecimal.new("1.0") / BigDecimal.new("0.0")  #=> Infinity
03027  *      BigDecimal.new("-1.0") / BigDecimal.new("0.0")  #=> -Infinity
03028  *
03029  * You can represent infinite numbers to BigDecimal using the strings
03030  * <code>'Infinity'</code>, <code>'+Infinity'</code> and
03031  * <code>'-Infinity'</code> (case-sensitive)
03032  *
03033  * === Not a Number
03034  *
03035  * When a computation results in an undefined value, the special value +NaN+
03036  * (for 'not a number') is returned.
03037  *
03038  * Example:
03039  *
03040  *      BigDecimal.new("0.0") / BigDecimal.new("0.0") #=> NaN
03041  *
03042  * You can also create undefined values.
03043  *
03044  * NaN is never considered to be the same as any other value, even NaN itself:
03045  *
03046  *      n = BigDecimal.new('NaN')
03047  *      n == 0.0 #=> false
03048  *      n == n #=> false
03049  *
03050  * === Positive and negative zero
03051  *
03052  * If a computation results in a value which is too small to be represented as
03053  * a BigDecimal within the currently specified limits of precision, zero must
03054  * be returned.
03055  *
03056  * If the value which is too small to be represented is negative, a BigDecimal
03057  * value of negative zero is returned.
03058  *
03059  *      BigDecimal.new("1.0") / BigDecimal.new("-Infinity") #=> -0.0
03060  *
03061  * If the value is positive, a value of positive zero is returned.
03062  *
03063  *      BigDecimal.new("1.0") / BigDecimal.new("Infinity") #=> 0.0
03064  *
03065  * (See BigDecimal.mode for how to specify limits of precision.)
03066  *
03067  * Note that +-0.0+ and +0.0+ are considered to be the same for the purposes of
03068  * comparison.
03069  *
03070  * Note also that in mathematics, there is no particular concept of negative
03071  * or positive zero; true mathematical zero has no sign.
03072  *
03073  * == License
03074  *
03075  * Copyright (C) 2002 by Shigeo Kobayashi <shigeo@tinyforest.gr.jp>.
03076  *
03077  * You may distribute under the terms of either the GNU General Public
03078  * License or the Artistic License, as specified in the README file
03079  * of the BigDecimal distribution.
03080  *
03081  * Maintained by mrkn <mrkn@mrkn.jp> and ruby-core members.
03082  *
03083  * Documented by zzak <zachary@zacharyscott.net>, mathew <meta@pobox.com>, and
03084  * many other contributors.
03085  */
03086 void
03087 Init_bigdecimal(void)
03088 {
03089     VALUE arg;
03090 
03091     id_BigDecimal_exception_mode = rb_intern_const("BigDecimal.exception_mode");
03092     id_BigDecimal_rounding_mode = rb_intern_const("BigDecimal.rounding_mode");
03093     id_BigDecimal_precision_limit = rb_intern_const("BigDecimal.precision_limit");
03094 
03095     /* Initialize VP routines */
03096     VpInit(0UL);
03097 
03098     /* Class and method registration */
03099     rb_cBigDecimal = rb_define_class("BigDecimal", rb_cNumeric);
03100     rb_define_alloc_func(rb_cBigDecimal, BigDecimal_s_allocate);
03101 
03102     /* Global function */
03103     rb_define_global_function("BigDecimal", BigDecimal_global_new, -1);
03104 
03105     /* Class methods */
03106     rb_define_singleton_method(rb_cBigDecimal, "mode", BigDecimal_mode, -1);
03107     rb_define_singleton_method(rb_cBigDecimal, "limit", BigDecimal_limit, -1);
03108     rb_define_singleton_method(rb_cBigDecimal, "double_fig", BigDecimal_double_fig, 0);
03109     rb_define_singleton_method(rb_cBigDecimal, "_load", BigDecimal_load, 1);
03110     rb_define_singleton_method(rb_cBigDecimal, "ver", BigDecimal_version, 0);
03111 
03112     rb_define_singleton_method(rb_cBigDecimal, "save_exception_mode", BigDecimal_save_exception_mode, 0);
03113     rb_define_singleton_method(rb_cBigDecimal, "save_rounding_mode", BigDecimal_save_rounding_mode, 0);
03114     rb_define_singleton_method(rb_cBigDecimal, "save_limit", BigDecimal_save_limit, 0);
03115 
03116     /* Constants definition */
03117 
03118     /*
03119      * Base value used in internal calculations.  On a 32 bit system, BASE
03120      * is 10000, indicating that calculation is done in groups of 4 digits.
03121      * (If it were larger, BASE**2 wouldn't fit in 32 bits, so you couldn't
03122      * guarantee that two groups could always be multiplied together without
03123      * overflow.)
03124      */
03125     rb_define_const(rb_cBigDecimal, "BASE", INT2FIX((SIGNED_VALUE)VpBaseVal()));
03126 
03127     /* Exceptions */
03128 
03129     /*
03130      * 0xff: Determines whether overflow, underflow or zero divide result in
03131      * an exception being thrown. See BigDecimal.mode.
03132      */
03133     rb_define_const(rb_cBigDecimal, "EXCEPTION_ALL", INT2FIX(VP_EXCEPTION_ALL));
03134 
03135     /*
03136      * 0x02: Determines what happens when the result of a computation is not a
03137      * number (NaN). See BigDecimal.mode.
03138      */
03139     rb_define_const(rb_cBigDecimal, "EXCEPTION_NaN", INT2FIX(VP_EXCEPTION_NaN));
03140 
03141     /*
03142      * 0x01: Determines what happens when the result of a computation is
03143      * infinity.  See BigDecimal.mode.
03144      */
03145     rb_define_const(rb_cBigDecimal, "EXCEPTION_INFINITY", INT2FIX(VP_EXCEPTION_INFINITY));
03146 
03147     /*
03148      * 0x04: Determines what happens when the result of a computation is an
03149      * underflow (a result too small to be represented). See BigDecimal.mode.
03150      */
03151     rb_define_const(rb_cBigDecimal, "EXCEPTION_UNDERFLOW", INT2FIX(VP_EXCEPTION_UNDERFLOW));
03152 
03153     /*
03154      * 0x01: Determines what happens when the result of a computation is an
03155      * overflow (a result too large to be represented). See BigDecimal.mode.
03156      */
03157     rb_define_const(rb_cBigDecimal, "EXCEPTION_OVERFLOW", INT2FIX(VP_EXCEPTION_OVERFLOW));
03158 
03159     /*
03160      * 0x01: Determines what happens when a division by zero is performed.
03161      * See BigDecimal.mode.
03162      */
03163     rb_define_const(rb_cBigDecimal, "EXCEPTION_ZERODIVIDE", INT2FIX(VP_EXCEPTION_ZERODIVIDE));
03164 
03165     /*
03166      * 0x100: Determines what happens when a result must be rounded in order to
03167      * fit in the appropriate number of significant digits. See
03168      * BigDecimal.mode.
03169      */
03170     rb_define_const(rb_cBigDecimal, "ROUND_MODE", INT2FIX(VP_ROUND_MODE));
03171 
03172     /* 1: Indicates that values should be rounded away from zero. See
03173      * BigDecimal.mode.
03174      */
03175     rb_define_const(rb_cBigDecimal, "ROUND_UP", INT2FIX(VP_ROUND_UP));
03176 
03177     /* 2: Indicates that values should be rounded towards zero. See
03178      * BigDecimal.mode.
03179      */
03180     rb_define_const(rb_cBigDecimal, "ROUND_DOWN", INT2FIX(VP_ROUND_DOWN));
03181 
03182     /* 3: Indicates that digits >= 5 should be rounded up, others rounded down.
03183      * See BigDecimal.mode. */
03184     rb_define_const(rb_cBigDecimal, "ROUND_HALF_UP", INT2FIX(VP_ROUND_HALF_UP));
03185 
03186     /* 4: Indicates that digits >= 6 should be rounded up, others rounded down.
03187      * See BigDecimal.mode.
03188      */
03189     rb_define_const(rb_cBigDecimal, "ROUND_HALF_DOWN", INT2FIX(VP_ROUND_HALF_DOWN));
03190     /* 5: Round towards +Infinity. See BigDecimal.mode. */
03191     rb_define_const(rb_cBigDecimal, "ROUND_CEILING", INT2FIX(VP_ROUND_CEIL));
03192 
03193     /* 6: Round towards -Infinity. See BigDecimal.mode. */
03194     rb_define_const(rb_cBigDecimal, "ROUND_FLOOR", INT2FIX(VP_ROUND_FLOOR));
03195 
03196     /* 7: Round towards the even neighbor. See BigDecimal.mode. */
03197     rb_define_const(rb_cBigDecimal, "ROUND_HALF_EVEN", INT2FIX(VP_ROUND_HALF_EVEN));
03198 
03199     /* 0: Indicates that a value is not a number. See BigDecimal.sign. */
03200     rb_define_const(rb_cBigDecimal, "SIGN_NaN", INT2FIX(VP_SIGN_NaN));
03201 
03202     /* 1: Indicates that a value is +0. See BigDecimal.sign. */
03203     rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_ZERO", INT2FIX(VP_SIGN_POSITIVE_ZERO));
03204 
03205     /* -1: Indicates that a value is -0. See BigDecimal.sign. */
03206     rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_ZERO", INT2FIX(VP_SIGN_NEGATIVE_ZERO));
03207 
03208     /* 2: Indicates that a value is positive and finite. See BigDecimal.sign. */
03209     rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_FINITE", INT2FIX(VP_SIGN_POSITIVE_FINITE));
03210 
03211     /* -2: Indicates that a value is negative and finite. See BigDecimal.sign. */
03212     rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_FINITE", INT2FIX(VP_SIGN_NEGATIVE_FINITE));
03213 
03214     /* 3: Indicates that a value is positive and infinite. See BigDecimal.sign. */
03215     rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_INFINITE", INT2FIX(VP_SIGN_POSITIVE_INFINITE));
03216 
03217     /* -3: Indicates that a value is negative and infinite. See BigDecimal.sign. */
03218     rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_INFINITE", INT2FIX(VP_SIGN_NEGATIVE_INFINITE));
03219 
03220     arg = rb_str_new2("+Infinity");
03221     /* Positive infinity value. */
03222     rb_define_const(rb_cBigDecimal, "INFINITY", BigDecimal_global_new(1, &arg, rb_cBigDecimal));
03223     arg = rb_str_new2("NaN");
03224     /* 'Not a Number' value. */
03225     rb_define_const(rb_cBigDecimal, "NAN", BigDecimal_global_new(1, &arg, rb_cBigDecimal));
03226 
03227 
03228     /* instance methods */
03229     rb_define_method(rb_cBigDecimal, "initialize", BigDecimal_initialize, -1);
03230     rb_define_method(rb_cBigDecimal, "initialize_copy", BigDecimal_initialize_copy, 1);
03231     rb_define_method(rb_cBigDecimal, "precs", BigDecimal_prec, 0);
03232 
03233     rb_define_method(rb_cBigDecimal, "add", BigDecimal_add2, 2);
03234     rb_define_method(rb_cBigDecimal, "sub", BigDecimal_sub2, 2);
03235     rb_define_method(rb_cBigDecimal, "mult", BigDecimal_mult2, 2);
03236     rb_define_method(rb_cBigDecimal, "div", BigDecimal_div3, -1);
03237     rb_define_method(rb_cBigDecimal, "hash", BigDecimal_hash, 0);
03238     rb_define_method(rb_cBigDecimal, "to_s", BigDecimal_to_s, -1);
03239     rb_define_method(rb_cBigDecimal, "to_i", BigDecimal_to_i, 0);
03240     rb_define_method(rb_cBigDecimal, "to_int", BigDecimal_to_i, 0);
03241     rb_define_method(rb_cBigDecimal, "to_r", BigDecimal_to_r, 0);
03242     rb_define_method(rb_cBigDecimal, "split", BigDecimal_split, 0);
03243     rb_define_method(rb_cBigDecimal, "+", BigDecimal_add, 1);
03244     rb_define_method(rb_cBigDecimal, "-", BigDecimal_sub, 1);
03245     rb_define_method(rb_cBigDecimal, "+@", BigDecimal_uplus, 0);
03246     rb_define_method(rb_cBigDecimal, "-@", BigDecimal_neg, 0);
03247     rb_define_method(rb_cBigDecimal, "*", BigDecimal_mult, 1);
03248     rb_define_method(rb_cBigDecimal, "/", BigDecimal_div, 1);
03249     rb_define_method(rb_cBigDecimal, "quo", BigDecimal_div, 1);
03250     rb_define_method(rb_cBigDecimal, "%", BigDecimal_mod, 1);
03251     rb_define_method(rb_cBigDecimal, "modulo", BigDecimal_mod, 1);
03252     rb_define_method(rb_cBigDecimal, "remainder", BigDecimal_remainder, 1);
03253     rb_define_method(rb_cBigDecimal, "divmod", BigDecimal_divmod, 1);
03254     /* rb_define_method(rb_cBigDecimal, "dup", BigDecimal_dup, 0); */
03255     rb_define_method(rb_cBigDecimal, "to_f", BigDecimal_to_f, 0);
03256     rb_define_method(rb_cBigDecimal, "abs", BigDecimal_abs, 0);
03257     rb_define_method(rb_cBigDecimal, "sqrt", BigDecimal_sqrt, 1);
03258     rb_define_method(rb_cBigDecimal, "fix", BigDecimal_fix, 0);
03259     rb_define_method(rb_cBigDecimal, "round", BigDecimal_round, -1);
03260     rb_define_method(rb_cBigDecimal, "frac", BigDecimal_frac, 0);
03261     rb_define_method(rb_cBigDecimal, "floor", BigDecimal_floor, -1);
03262     rb_define_method(rb_cBigDecimal, "ceil", BigDecimal_ceil, -1);
03263     rb_define_method(rb_cBigDecimal, "power", BigDecimal_power, -1);
03264     rb_define_method(rb_cBigDecimal, "**", BigDecimal_power_op, 1);
03265     rb_define_method(rb_cBigDecimal, "<=>", BigDecimal_comp, 1);
03266     rb_define_method(rb_cBigDecimal, "==", BigDecimal_eq, 1);
03267     rb_define_method(rb_cBigDecimal, "===", BigDecimal_eq, 1);
03268     rb_define_method(rb_cBigDecimal, "eql?", BigDecimal_eq, 1);
03269     rb_define_method(rb_cBigDecimal, "<", BigDecimal_lt, 1);
03270     rb_define_method(rb_cBigDecimal, "<=", BigDecimal_le, 1);
03271     rb_define_method(rb_cBigDecimal, ">", BigDecimal_gt, 1);
03272     rb_define_method(rb_cBigDecimal, ">=", BigDecimal_ge, 1);
03273     rb_define_method(rb_cBigDecimal, "zero?", BigDecimal_zero, 0);
03274     rb_define_method(rb_cBigDecimal, "nonzero?", BigDecimal_nonzero, 0);
03275     rb_define_method(rb_cBigDecimal, "coerce", BigDecimal_coerce, 1);
03276     rb_define_method(rb_cBigDecimal, "inspect", BigDecimal_inspect, 0);
03277     rb_define_method(rb_cBigDecimal, "exponent", BigDecimal_exponent, 0);
03278     rb_define_method(rb_cBigDecimal, "sign", BigDecimal_sign, 0);
03279     rb_define_method(rb_cBigDecimal, "nan?",      BigDecimal_IsNaN, 0);
03280     rb_define_method(rb_cBigDecimal, "infinite?", BigDecimal_IsInfinite, 0);
03281     rb_define_method(rb_cBigDecimal, "finite?",   BigDecimal_IsFinite, 0);
03282     rb_define_method(rb_cBigDecimal, "truncate",  BigDecimal_truncate, -1);
03283     rb_define_method(rb_cBigDecimal, "_dump", BigDecimal_dump, -1);
03284 
03285     rb_mBigMath = rb_define_module("BigMath");
03286     rb_define_singleton_method(rb_mBigMath, "exp", BigMath_s_exp, 2);
03287     rb_define_singleton_method(rb_mBigMath, "log", BigMath_s_log, 2);
03288 
03289     id_up = rb_intern_const("up");
03290     id_down = rb_intern_const("down");
03291     id_truncate = rb_intern_const("truncate");
03292     id_half_up = rb_intern_const("half_up");
03293     id_default = rb_intern_const("default");
03294     id_half_down = rb_intern_const("half_down");
03295     id_half_even = rb_intern_const("half_even");
03296     id_banker = rb_intern_const("banker");
03297     id_ceiling = rb_intern_const("ceiling");
03298     id_ceil = rb_intern_const("ceil");
03299     id_floor = rb_intern_const("floor");
03300     id_to_r = rb_intern_const("to_r");
03301     id_eq = rb_intern_const("==");
03302 }
03303 
03304 /*
03305  *
03306  *  ============================================================================
03307  *
03308  *  vp_ routines begin from here.
03309  *
03310  *  ============================================================================
03311  *
03312  */
03313 #ifdef BIGDECIMAL_DEBUG
03314 static int gfDebug = 1;         /* Debug switch */
03315 #if 0
03316 static int gfCheckVal = 1;      /* Value checking flag in VpNmlz()  */
03317 #endif
03318 #endif /* BIGDECIMAL_DEBUG */
03319 
03320 static Real *VpConstOne;    /* constant 1.0 */
03321 static Real *VpPt5;        /* constant 0.5 */
03322 #define maxnr 100UL    /* Maximum iterations for calculating sqrt. */
03323                 /* used in VpSqrt() */
03324 
03325 /* ETC */
03326 #define MemCmp(x,y,z) memcmp(x,y,z)
03327 #define StrCmp(x,y)   strcmp(x,y)
03328 
03329 static int VpIsDefOP(Real *c,Real *a,Real *b,int sw);
03330 static int AddExponent(Real *a, SIGNED_VALUE n);
03331 static BDIGIT VpAddAbs(Real *a,Real *b,Real *c);
03332 static BDIGIT VpSubAbs(Real *a,Real *b,Real *c);
03333 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);
03334 static int VpNmlz(Real *a);
03335 static void VpFormatSt(char *psz, size_t fFmt);
03336 static int VpRdup(Real *m, size_t ind_m);
03337 
03338 #ifdef BIGDECIMAL_DEBUG
03339 static int gnAlloc = 0; /* Memory allocation counter */
03340 #endif /* BIGDECIMAL_DEBUG */
03341 
03342 VP_EXPORT void *
03343 VpMemAlloc(size_t mb)
03344 {
03345     void *p = xmalloc(mb);
03346     if (!p) {
03347         VpException(VP_EXCEPTION_MEMORY, "failed to allocate memory", 1);
03348     }
03349     memset(p, 0, mb);
03350 #ifdef BIGDECIMAL_DEBUG
03351     gnAlloc++; /* Count allocation call */
03352 #endif /* BIGDECIMAL_DEBUG */
03353     return p;
03354 }
03355 
03356     VP_EXPORT void *
03357 VpMemRealloc(void *ptr, size_t mb)
03358 {
03359     void *p = xrealloc(ptr, mb);
03360     if (!p) {
03361         VpException(VP_EXCEPTION_MEMORY, "failed to allocate memory", 1);
03362     }
03363     return p;
03364 }
03365 
03366 VP_EXPORT void
03367 VpFree(Real *pv)
03368 {
03369     if (pv != NULL) {
03370         xfree(pv);
03371 #ifdef BIGDECIMAL_DEBUG
03372         gnAlloc--; /* Decrement allocation count */
03373         if (gnAlloc == 0) {
03374             printf(" *************** All memories allocated freed ****************");
03375             getchar();
03376         }
03377         if (gnAlloc <  0) {
03378             printf(" ??????????? Too many memory free calls(%d) ?????????????\n", gnAlloc);
03379             getchar();
03380         }
03381 #endif /* BIGDECIMAL_DEBUG */
03382     }
03383 }
03384 
03385 /*
03386  * EXCEPTION Handling.
03387  */
03388 
03389 #define rmpd_set_thread_local_exception_mode(mode) \
03390     rb_thread_local_aset( \
03391         rb_thread_current(), \
03392         id_BigDecimal_exception_mode, \
03393         INT2FIX((int)(mode)) \
03394     )
03395 
03396 static unsigned short
03397 VpGetException (void)
03398 {
03399     VALUE const vmode = rb_thread_local_aref(
03400         rb_thread_current(),
03401         id_BigDecimal_exception_mode
03402     );
03403 
03404     if (NIL_P(vmode)) {
03405         rmpd_set_thread_local_exception_mode(RMPD_EXCEPTION_MODE_DEFAULT);
03406         return RMPD_EXCEPTION_MODE_DEFAULT;
03407     }
03408 
03409     return (unsigned short)FIX2UINT(vmode);
03410 }
03411 
03412 static void
03413 VpSetException(unsigned short f)
03414 {
03415     rmpd_set_thread_local_exception_mode(f);
03416 }
03417 
03418 /*
03419  * Precision limit.
03420  */
03421 
03422 #define rmpd_set_thread_local_precision_limit(limit) \
03423     rb_thread_local_aset( \
03424         rb_thread_current(), \
03425         id_BigDecimal_precision_limit, \
03426         SIZET2NUM(limit) \
03427     )
03428 #define RMPD_PRECISION_LIMIT_DEFAULT ((size_t)0)
03429 
03430 /* These 2 functions added at v1.1.7 */
03431 VP_EXPORT size_t
03432 VpGetPrecLimit(void)
03433 {
03434     VALUE const vlimit = rb_thread_local_aref(
03435         rb_thread_current(),
03436         id_BigDecimal_precision_limit
03437     );
03438 
03439     if (NIL_P(vlimit)) {
03440         rmpd_set_thread_local_precision_limit(RMPD_PRECISION_LIMIT_DEFAULT);
03441         return RMPD_PRECISION_LIMIT_DEFAULT;
03442     }
03443 
03444     return NUM2SIZET(vlimit);
03445 }
03446 
03447 VP_EXPORT size_t
03448 VpSetPrecLimit(size_t n)
03449 {
03450     size_t const s = VpGetPrecLimit();
03451     rmpd_set_thread_local_precision_limit(n);
03452     return s;
03453 }
03454 
03455 /*
03456  * Rounding mode.
03457  */
03458 
03459 #define rmpd_set_thread_local_rounding_mode(mode) \
03460     rb_thread_local_aset( \
03461         rb_thread_current(), \
03462         id_BigDecimal_rounding_mode, \
03463         INT2FIX((int)(mode)) \
03464     )
03465 
03466 VP_EXPORT unsigned short
03467 VpGetRoundMode(void)
03468 {
03469     VALUE const vmode = rb_thread_local_aref(
03470         rb_thread_current(),
03471         id_BigDecimal_rounding_mode
03472     );
03473 
03474     if (NIL_P(vmode)) {
03475         rmpd_set_thread_local_rounding_mode(RMPD_ROUNDING_MODE_DEFAULT);
03476         return RMPD_ROUNDING_MODE_DEFAULT;
03477     }
03478 
03479     return (unsigned short)FIX2INT(vmode);
03480 }
03481 
03482 VP_EXPORT int
03483 VpIsRoundMode(unsigned short n)
03484 {
03485     switch (n) {
03486       case VP_ROUND_UP:
03487       case VP_ROUND_DOWN:
03488       case VP_ROUND_HALF_UP:
03489       case VP_ROUND_HALF_DOWN:
03490       case VP_ROUND_CEIL:
03491       case VP_ROUND_FLOOR:
03492       case VP_ROUND_HALF_EVEN:
03493         return 1;
03494 
03495       default:
03496         return 0;
03497     }
03498 }
03499 
03500 VP_EXPORT unsigned short
03501 VpSetRoundMode(unsigned short n)
03502 {
03503     if (VpIsRoundMode(n)) {
03504         rmpd_set_thread_local_rounding_mode(n);
03505         return n;
03506     }
03507 
03508     return VpGetRoundMode();
03509 }
03510 
03511 /*
03512  *  0.0 & 1.0 generator
03513  *    These gZero_..... and gOne_..... can be any name
03514  *    referenced from nowhere except Zero() and One().
03515  *    gZero_..... and gOne_..... must have global scope
03516  *    (to let the compiler know they may be changed in outside
03517  *    (... but not actually..)).
03518  */
03519 volatile const double gZero_ABCED9B1_CE73__00400511F31D = 0.0;
03520 volatile const double gOne_ABCED9B4_CE73__00400511F31D  = 1.0;
03521 static double
03522 Zero(void)
03523 {
03524     return gZero_ABCED9B1_CE73__00400511F31D;
03525 }
03526 
03527 static double
03528 One(void)
03529 {
03530     return gOne_ABCED9B4_CE73__00400511F31D;
03531 }
03532 
03533 /*
03534   ----------------------------------------------------------------
03535   Value of sign in Real structure is reserved for future use.
03536   short sign;
03537                     ==0 : NaN
03538                       1 : Positive zero
03539                      -1 : Negative zero
03540                       2 : Positive number
03541                      -2 : Negative number
03542                       3 : Positive infinite number
03543                      -3 : Negative infinite number
03544   ----------------------------------------------------------------
03545 */
03546 
03547 VP_EXPORT double
03548 VpGetDoubleNaN(void) /* Returns the value of NaN */
03549 {
03550     static double fNaN = 0.0;
03551     if (fNaN == 0.0) fNaN = Zero()/Zero();
03552     return fNaN;
03553 }
03554 
03555 VP_EXPORT double
03556 VpGetDoublePosInf(void) /* Returns the value of +Infinity */
03557 {
03558     static double fInf = 0.0;
03559     if (fInf == 0.0) fInf = One()/Zero();
03560     return fInf;
03561 }
03562 
03563 VP_EXPORT double
03564 VpGetDoubleNegInf(void) /* Returns the value of -Infinity */
03565 {
03566     static double fInf = 0.0;
03567     if (fInf == 0.0) fInf = -(One()/Zero());
03568     return fInf;
03569 }
03570 
03571 VP_EXPORT double
03572 VpGetDoubleNegZero(void) /* Returns the value of -0 */
03573 {
03574     static double nzero = 1000.0;
03575     if (nzero != 0.0) nzero = (One()/VpGetDoubleNegInf());
03576     return nzero;
03577 }
03578 
03579 #if 0  /* unused */
03580 VP_EXPORT int
03581 VpIsNegDoubleZero(double v)
03582 {
03583     double z = VpGetDoubleNegZero();
03584     return MemCmp(&v,&z,sizeof(v))==0;
03585 }
03586 #endif
03587 
03588 VP_EXPORT int
03589 VpException(unsigned short f, const char *str,int always)
03590 {
03591     unsigned short const exception_mode = VpGetException();
03592 
03593     if (f == VP_EXCEPTION_OP || f == VP_EXCEPTION_MEMORY) always = 1;
03594 
03595     if (always || (exception_mode & f)) {
03596         switch(f) {
03597           /* case VP_EXCEPTION_OVERFLOW: */
03598           case VP_EXCEPTION_ZERODIVIDE:
03599           case VP_EXCEPTION_INFINITY:
03600           case VP_EXCEPTION_NaN:
03601           case VP_EXCEPTION_UNDERFLOW:
03602           case VP_EXCEPTION_OP:
03603             rb_raise(rb_eFloatDomainError, "%s", str);
03604             break;
03605           case VP_EXCEPTION_MEMORY:
03606           default:
03607             rb_fatal("%s", str);
03608         }
03609     }
03610     return 0; /* 0 Means VpException() raised no exception */
03611 }
03612 
03613 /* Throw exception or returns 0,when resulting c is Inf or NaN */
03614 /*  sw=1:+ 2:- 3:* 4:/ */
03615 static int
03616 VpIsDefOP(Real *c,Real *a,Real *b,int sw)
03617 {
03618     if (VpIsNaN(a) || VpIsNaN(b)) {
03619         /* at least a or b is NaN */
03620         VpSetNaN(c);
03621         goto NaN;
03622     }
03623 
03624     if (VpIsInf(a)) {
03625         if (VpIsInf(b)) {
03626             switch(sw) {
03627               case 1: /* + */
03628                 if (VpGetSign(a) == VpGetSign(b)) {
03629                     VpSetInf(c, VpGetSign(a));
03630                     goto Inf;
03631                 }
03632                 else {
03633                     VpSetNaN(c);
03634                     goto NaN;
03635                 }
03636               case 2: /* - */
03637                 if (VpGetSign(a) != VpGetSign(b)) {
03638                     VpSetInf(c, VpGetSign(a));
03639                     goto Inf;
03640                 }
03641                 else {
03642                     VpSetNaN(c);
03643                     goto NaN;
03644                 }
03645                 break;
03646               case 3: /* * */
03647                 VpSetInf(c, VpGetSign(a)*VpGetSign(b));
03648                 goto Inf;
03649                 break;
03650               case 4: /* / */
03651                 VpSetNaN(c);
03652                 goto NaN;
03653             }
03654             VpSetNaN(c);
03655             goto NaN;
03656         }
03657         /* Inf op Finite */
03658         switch(sw) {
03659           case 1: /* + */
03660           case 2: /* - */
03661             VpSetInf(c, VpGetSign(a));
03662             break;
03663           case 3: /* * */
03664             if (VpIsZero(b)) {
03665                 VpSetNaN(c);
03666                 goto NaN;
03667             }
03668             VpSetInf(c, VpGetSign(a)*VpGetSign(b));
03669             break;
03670           case 4: /* / */
03671             VpSetInf(c, VpGetSign(a)*VpGetSign(b));
03672         }
03673         goto Inf;
03674     }
03675 
03676     if (VpIsInf(b)) {
03677         switch(sw) {
03678           case 1: /* + */
03679             VpSetInf(c, VpGetSign(b));
03680             break;
03681           case 2: /* - */
03682             VpSetInf(c, -VpGetSign(b));
03683             break;
03684           case 3: /* * */
03685             if (VpIsZero(a)) {
03686                 VpSetNaN(c);
03687                 goto NaN;
03688             }
03689             VpSetInf(c, VpGetSign(a)*VpGetSign(b));
03690             break;
03691           case 4: /* / */
03692             VpSetZero(c, VpGetSign(a)*VpGetSign(b));
03693         }
03694         goto Inf;
03695     }
03696     return 1; /* Results OK */
03697 
03698 Inf:
03699     return VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 0);
03700 NaN:
03701     return VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'", 0);
03702 }
03703 
03704 /*
03705   ----------------------------------------------------------------
03706 */
03707 
03708 /*
03709  *    returns number of chars needed to represent vp in specified format.
03710  */
03711 VP_EXPORT size_t
03712 VpNumOfChars(Real *vp,const char *pszFmt)
03713 {
03714     SIGNED_VALUE  ex;
03715     size_t nc;
03716 
03717     if (vp == NULL)   return BASE_FIG*2+6;
03718     if (!VpIsDef(vp)) return 32; /* not sure,may be OK */
03719 
03720     switch(*pszFmt) {
03721       case 'F':
03722         nc = BASE_FIG*(vp->Prec + 1)+2;
03723         ex = vp->exponent;
03724         if (ex < 0) {
03725             nc += BASE_FIG*(size_t)(-ex);
03726         }
03727         else {
03728             if ((size_t)ex > vp->Prec) {
03729                 nc += BASE_FIG*((size_t)ex - vp->Prec);
03730             }
03731         }
03732         break;
03733       case 'E':
03734         /* fall through */
03735       default:
03736         nc = BASE_FIG*(vp->Prec + 2)+6; /* 3: sign + exponent chars */
03737     }
03738     return nc;
03739 }
03740 
03741 /*
03742  * Initializer for Vp routines and constants used.
03743  * [Input]
03744  *   BaseVal: Base value(assigned to BASE) for Vp calculation.
03745  *   It must be the form BaseVal=10**n.(n=1,2,3,...)
03746  *   If Base <= 0L,then the BASE will be calculated so
03747  *   that BASE is as large as possible satisfying the
03748  *   relation MaxVal <= BASE*(BASE+1). Where the value
03749  *   MaxVal is the largest value which can be represented
03750  *   by one BDIGIT word in the computer used.
03751  *
03752  * [Returns]
03753  * 1+DBL_DIG   ... OK
03754  */
03755 VP_EXPORT size_t
03756 VpInit(BDIGIT BaseVal)
03757 {
03758     /* Setup +/- Inf  NaN -0 */
03759     VpGetDoubleNaN();
03760     VpGetDoublePosInf();
03761     VpGetDoubleNegInf();
03762     VpGetDoubleNegZero();
03763 
03764     /* Allocates Vp constants. */
03765     VpConstOne = VpAlloc(1UL, "1");
03766     VpPt5 = VpAlloc(1UL, ".5");
03767 
03768 #ifdef BIGDECIMAL_DEBUG
03769     gnAlloc = 0;
03770 #endif /* BIGDECIMAL_DEBUG */
03771 
03772 #ifdef BIGDECIMAL_DEBUG
03773     if (gfDebug) {
03774         printf("VpInit: BaseVal   = %lu\n", BaseVal);
03775         printf("  BASE   = %lu\n", BASE);
03776         printf("  HALF_BASE = %lu\n", HALF_BASE);
03777         printf("  BASE1  = %lu\n", BASE1);
03778         printf("  BASE_FIG  = %u\n", BASE_FIG);
03779         printf("  DBLE_FIG  = %d\n", DBLE_FIG);
03780     }
03781 #endif /* BIGDECIMAL_DEBUG */
03782 
03783     return rmpd_double_figures();
03784 }
03785 
03786 VP_EXPORT Real *
03787 VpOne(void)
03788 {
03789     return VpConstOne;
03790 }
03791 
03792 /* If exponent overflows,then raise exception or returns 0 */
03793 static int
03794 AddExponent(Real *a, SIGNED_VALUE n)
03795 {
03796     SIGNED_VALUE e = a->exponent;
03797     SIGNED_VALUE m = e+n;
03798     SIGNED_VALUE eb, mb;
03799     if (e > 0) {
03800         if (n > 0) {
03801             if (MUL_OVERFLOW_SIGNED_VALUE_P(m, (SIGNED_VALUE)BASE_FIG) ||
03802                 MUL_OVERFLOW_SIGNED_VALUE_P(e, (SIGNED_VALUE)BASE_FIG))
03803                 goto overflow;
03804             mb = m*(SIGNED_VALUE)BASE_FIG;
03805             eb = e*(SIGNED_VALUE)BASE_FIG;
03806             if (mb < eb) goto overflow;
03807         }
03808     }
03809     else if (n < 0) {
03810         if (MUL_OVERFLOW_SIGNED_VALUE_P(m, (SIGNED_VALUE)BASE_FIG) ||
03811             MUL_OVERFLOW_SIGNED_VALUE_P(e, (SIGNED_VALUE)BASE_FIG))
03812             goto underflow;
03813         mb = m*(SIGNED_VALUE)BASE_FIG;
03814         eb = e*(SIGNED_VALUE)BASE_FIG;
03815         if (mb > eb) goto underflow;
03816     }
03817     a->exponent = m;
03818     return 1;
03819 
03820 /* Overflow/Underflow ==> Raise exception or returns 0 */
03821 underflow:
03822     VpSetZero(a, VpGetSign(a));
03823     return VpException(VP_EXCEPTION_UNDERFLOW, "Exponent underflow", 0);
03824 
03825 overflow:
03826     VpSetInf(a, VpGetSign(a));
03827     return VpException(VP_EXCEPTION_OVERFLOW, "Exponent overflow", 0);
03828 }
03829 
03830 /*
03831  * Allocates variable.
03832  * [Input]
03833  *   mx ... allocation unit, if zero then mx is determined by szVal.
03834  *    The mx is the number of effective digits can to be stored.
03835  *   szVal ... value assigned(char). If szVal==NULL,then zero is assumed.
03836  *            If szVal[0]=='#' then Max. Prec. will not be considered(1.1.7),
03837  *            full precision specified by szVal is allocated.
03838  *
03839  * [Returns]
03840  *   Pointer to the newly allocated variable, or
03841  *   NULL be returned if memory allocation is failed,or any error.
03842  */
03843 VP_EXPORT Real *
03844 VpAlloc(size_t mx, const char *szVal)
03845 {
03846     size_t i, ni, ipn, ipf, nf, ipe, ne, nalloc;
03847     char v, *psz;
03848     int  sign=1;
03849     Real *vp = NULL;
03850     size_t mf = VpGetPrecLimit();
03851     VALUE buf;
03852 
03853     mx = (mx + BASE_FIG - 1) / BASE_FIG;    /* Determine allocation unit. */
03854     if (mx == 0) ++mx;
03855 
03856     if (szVal) {
03857         while (ISSPACE(*szVal)) szVal++;
03858         if (*szVal != '#') {
03859             if (mf) {
03860                 mf = (mf + BASE_FIG - 1) / BASE_FIG + 2; /* Needs 1 more for div */
03861                 if (mx > mf) {
03862                     mx = mf;
03863                 }
03864             }
03865         }
03866         else {
03867             ++szVal;
03868         }
03869     }
03870     else {
03871         /* necessary to be able to store */
03872         /* at least mx digits. */
03873         /* szVal==NULL ==> allocate zero value. */
03874         vp = VpAllocReal(mx);
03875         /* xmalloc() alway returns(or throw interruption) */
03876         vp->MaxPrec = mx;    /* set max precision */
03877         VpSetZero(vp, 1);    /* initialize vp to zero. */
03878         return vp;
03879     }
03880 
03881     /* Skip all '_' after digit: 2006-6-30 */
03882     ni = 0;
03883     buf = rb_str_tmp_new(strlen(szVal) + 1);
03884     psz = RSTRING_PTR(buf);
03885     i   = 0;
03886     ipn = 0;
03887     while ((psz[i] = szVal[ipn]) != 0) {
03888         if (ISDIGIT(psz[i])) ++ni;
03889         if (psz[i] == '_') {
03890             if (ni > 0) {
03891                 ipn++;
03892                 continue;
03893             }
03894             psz[i] = 0;
03895             break;
03896         }
03897         ++i;
03898         ++ipn;
03899     }
03900     /* Skip trailing spaces */
03901     while (--i > 0) {
03902         if (ISSPACE(psz[i])) psz[i] = 0;
03903         else break;
03904     }
03905     szVal = psz;
03906 
03907     /* Check on Inf & NaN */
03908     if (StrCmp(szVal, SZ_PINF) == 0 || StrCmp(szVal, SZ_INF) == 0 ) {
03909         vp = VpAllocReal(1);
03910         vp->MaxPrec = 1;    /* set max precision */
03911         VpSetPosInf(vp);
03912         return vp;
03913     }
03914     if (StrCmp(szVal, SZ_NINF) == 0) {
03915         vp = VpAllocReal(1);
03916         vp->MaxPrec = 1;    /* set max precision */
03917         VpSetNegInf(vp);
03918         return vp;
03919     }
03920     if (StrCmp(szVal, SZ_NaN) == 0) {
03921         vp = VpAllocReal(1);
03922         vp->MaxPrec = 1;    /* set max precision */
03923         VpSetNaN(vp);
03924         return vp;
03925     }
03926 
03927     /* check on number szVal[] */
03928     ipn = i = 0;
03929     if      (szVal[i] == '-') { sign=-1; ++i; }
03930     else if (szVal[i] == '+')            ++i;
03931     /* Skip digits */
03932     ni = 0;            /* digits in mantissa */
03933     while ((v = szVal[i]) != 0) {
03934         if (!ISDIGIT(v)) break;
03935         ++i;
03936         ++ni;
03937     }
03938     nf  = 0;
03939     ipf = 0;
03940     ipe = 0;
03941     ne  = 0;
03942     if (v) {
03943         /* other than digit nor \0 */
03944         if (szVal[i] == '.') {    /* xxx. */
03945             ++i;
03946             ipf = i;
03947             while ((v = szVal[i]) != 0) {    /* get fraction part. */
03948                 if (!ISDIGIT(v)) break;
03949                 ++i;
03950                 ++nf;
03951             }
03952         }
03953         ipe = 0;        /* Exponent */
03954 
03955         switch (szVal[i]) {
03956           case '\0':
03957             break;
03958           case 'e': case 'E':
03959           case 'd': case 'D':
03960             ++i;
03961             ipe = i;
03962             v = szVal[i];
03963             if ((v == '-') || (v == '+')) ++i;
03964             while ((v=szVal[i]) != 0) {
03965                 if (!ISDIGIT(v)) break;
03966                 ++i;
03967                 ++ne;
03968             }
03969             break;
03970           default:
03971             break;
03972         }
03973     }
03974     nalloc = (ni + nf + BASE_FIG - 1) / BASE_FIG + 1;    /* set effective allocation  */
03975     /* units for szVal[]  */
03976     if (mx == 0) mx = 1;
03977     nalloc = Max(nalloc, mx);
03978     mx = nalloc;
03979     vp = VpAllocReal(mx);
03980     /* xmalloc() alway returns(or throw interruption) */
03981     vp->MaxPrec = mx;        /* set max precision */
03982     VpSetZero(vp, sign);
03983     VpCtoV(vp, &szVal[ipn], ni, &szVal[ipf], nf, &szVal[ipe], ne);
03984     rb_str_resize(buf, 0);
03985     return vp;
03986 }
03987 
03988 /*
03989  * Assignment(c=a).
03990  * [Input]
03991  *   a   ... RHSV
03992  *   isw ... switch for assignment.
03993  *    c = a  when isw > 0
03994  *    c = -a when isw < 0
03995  *    if c->MaxPrec < a->Prec,then round operation
03996  *    will be performed.
03997  * [Output]
03998  *  c  ... LHSV
03999  */
04000 VP_EXPORT size_t
04001 VpAsgn(Real *c, Real *a, int isw)
04002 {
04003     size_t n;
04004     if (VpIsNaN(a)) {
04005         VpSetNaN(c);
04006         return 0;
04007     }
04008     if (VpIsInf(a)) {
04009         VpSetInf(c, isw * VpGetSign(a));
04010         return 0;
04011     }
04012 
04013     /* check if the RHS is zero */
04014     if (!VpIsZero(a)) {
04015         c->exponent = a->exponent;    /* store  exponent */
04016         VpSetSign(c, isw * VpGetSign(a));    /* set sign */
04017         n = (a->Prec < c->MaxPrec) ? (a->Prec) : (c->MaxPrec);
04018         c->Prec = n;
04019         memcpy(c->frac, a->frac, n * sizeof(BDIGIT));
04020         /* Needs round ? */
04021         if (isw != 10) {
04022             /* Not in ActiveRound */
04023             if(c->Prec < a->Prec) {
04024                 VpInternalRound(c, n, (n>0) ? a->frac[n-1] : 0, a->frac[n]);
04025             }
04026             else {
04027                 VpLimitRound(c,0);
04028             }
04029         }
04030     }
04031     else {
04032         /* The value of 'a' is zero.  */
04033         VpSetZero(c, isw * VpGetSign(a));
04034         return 1;
04035     }
04036     return c->Prec * BASE_FIG;
04037 }
04038 
04039 /*
04040  *   c = a + b  when operation =  1 or 2
04041  *  = a - b  when operation = -1 or -2.
04042  *   Returns number of significant digits of c
04043  */
04044 VP_EXPORT size_t
04045 VpAddSub(Real *c, Real *a, Real *b, int operation)
04046 {
04047     short sw, isw;
04048     Real *a_ptr, *b_ptr;
04049     size_t n, na, nb, i;
04050     BDIGIT mrv;
04051 
04052 #ifdef BIGDECIMAL_DEBUG
04053     if (gfDebug) {
04054         VPrint(stdout, "VpAddSub(enter) a=% \n", a);
04055         VPrint(stdout, "     b=% \n", b);
04056         printf(" operation=%d\n", operation);
04057     }
04058 #endif /* BIGDECIMAL_DEBUG */
04059 
04060     if (!VpIsDefOP(c, a, b, (operation > 0) ? 1 : 2)) return 0; /* No significant digits */
04061 
04062     /* check if a or b is zero  */
04063     if (VpIsZero(a)) {
04064         /* a is zero,then assign b to c */
04065         if (!VpIsZero(b)) {
04066             VpAsgn(c, b, operation);
04067         }
04068         else {
04069             /* Both a and b are zero. */
04070             if (VpGetSign(a) < 0 && operation * VpGetSign(b) < 0) {
04071                 /* -0 -0 */
04072                 VpSetZero(c, -1);
04073             }
04074             else {
04075                 VpSetZero(c, 1);
04076             }
04077             return 1; /* 0: 1 significant digits */
04078         }
04079         return c->Prec * BASE_FIG;
04080     }
04081     if (VpIsZero(b)) {
04082         /* b is zero,then assign a to c. */
04083         VpAsgn(c, a, 1);
04084         return c->Prec*BASE_FIG;
04085     }
04086 
04087     if (operation < 0) sw = -1;
04088     else               sw =  1;
04089 
04090     /* compare absolute value. As a result,|a_ptr|>=|b_ptr| */
04091     if (a->exponent > b->exponent) {
04092         a_ptr = a;
04093         b_ptr = b;
04094     }         /* |a|>|b| */
04095     else if (a->exponent < b->exponent) {
04096         a_ptr = b;
04097         b_ptr = a;
04098     }                /* |a|<|b| */
04099     else {
04100         /* Exponent part of a and b is the same,then compare fraction */
04101         /* part */
04102         na = a->Prec;
04103         nb = b->Prec;
04104         n  = Min(na, nb);
04105         for (i=0; i < n; ++i) {
04106             if (a->frac[i] > b->frac[i]) {
04107                 a_ptr = a;
04108                 b_ptr = b;
04109                 goto end_if;
04110             }
04111             else if (a->frac[i] < b->frac[i]) {
04112                 a_ptr = b;
04113                 b_ptr = a;
04114                 goto end_if;
04115             }
04116         }
04117         if (na > nb) {
04118             a_ptr = a;
04119             b_ptr = b;
04120             goto end_if;
04121         }
04122         else if (na < nb) {
04123             a_ptr = b;
04124             b_ptr = a;
04125             goto end_if;
04126         }
04127         /* |a| == |b| */
04128         if (VpGetSign(a) + sw *VpGetSign(b) == 0) {
04129             VpSetZero(c, 1);        /* abs(a)=abs(b) and operation = '-'  */
04130             return c->Prec * BASE_FIG;
04131         }
04132         a_ptr = a;
04133         b_ptr = b;
04134     }
04135 
04136 end_if:
04137     isw = VpGetSign(a) + sw *VpGetSign(b);
04138     /*
04139      *  isw = 0 ...( 1)+(-1),( 1)-( 1),(-1)+(1),(-1)-(-1)
04140      *      = 2 ...( 1)+( 1),( 1)-(-1)
04141      *      =-2 ...(-1)+(-1),(-1)-( 1)
04142      *   If isw==0, then c =(Sign a_ptr)(|a_ptr|-|b_ptr|)
04143      *              else c =(Sign ofisw)(|a_ptr|+|b_ptr|)
04144      */
04145     if (isw) {            /* addition */
04146         VpSetSign(c, 1);
04147         mrv = VpAddAbs(a_ptr, b_ptr, c);
04148         VpSetSign(c, isw / 2);
04149     }
04150     else {            /* subtraction */
04151         VpSetSign(c, 1);
04152         mrv = VpSubAbs(a_ptr, b_ptr, c);
04153         if (a_ptr == a) {
04154             VpSetSign(c,VpGetSign(a));
04155         }
04156         else {
04157             VpSetSign(c, VpGetSign(a_ptr) * sw);
04158         }
04159     }
04160     VpInternalRound(c, 0, (c->Prec > 0) ? c->frac[c->Prec-1] : 0, mrv);
04161 
04162 #ifdef BIGDECIMAL_DEBUG
04163     if (gfDebug) {
04164         VPrint(stdout, "VpAddSub(result) c=% \n", c);
04165         VPrint(stdout, "     a=% \n", a);
04166         VPrint(stdout, "     b=% \n", b);
04167         printf(" operation=%d\n", operation);
04168     }
04169 #endif /* BIGDECIMAL_DEBUG */
04170     return c->Prec * BASE_FIG;
04171 }
04172 
04173 /*
04174  * Addition of two variable precisional variables
04175  * a and b assuming abs(a)>abs(b).
04176  *   c = abs(a) + abs(b) ; where |a|>=|b|
04177  */
04178 static BDIGIT
04179 VpAddAbs(Real *a, Real *b, Real *c)
04180 {
04181     size_t word_shift;
04182     size_t ap;
04183     size_t bp;
04184     size_t cp;
04185     size_t a_pos;
04186     size_t b_pos, b_pos_with_word_shift;
04187     size_t c_pos;
04188     BDIGIT av, bv, carry, mrv;
04189 
04190 #ifdef BIGDECIMAL_DEBUG
04191     if (gfDebug) {
04192         VPrint(stdout, "VpAddAbs called: a = %\n", a);
04193         VPrint(stdout, "     b = %\n", b);
04194     }
04195 #endif /* BIGDECIMAL_DEBUG */
04196 
04197     word_shift = VpSetPTR(a, b, c, &ap, &bp, &cp, &av, &bv);
04198     a_pos = ap;
04199     b_pos = bp;
04200     c_pos = cp;
04201 
04202     if (word_shift == (size_t)-1L) return 0; /* Overflow */
04203     if (b_pos == (size_t)-1L) goto Assign_a;
04204 
04205     mrv = av + bv; /* Most right val. Used for round. */
04206 
04207     /* Just assign the last few digits of b to c because a has no  */
04208     /* corresponding digits to be added. */
04209     if (b_pos > 0) {
04210         while (b_pos > 0 && b_pos + word_shift > a_pos) {
04211             c->frac[--c_pos] = b->frac[--b_pos];
04212         }
04213     }
04214     if (b_pos == 0 && word_shift > a_pos) {
04215         while (word_shift-- > a_pos) {
04216             c->frac[--c_pos] = 0;
04217         }
04218     }
04219 
04220     /* Just assign the last few digits of a to c because b has no */
04221     /* corresponding digits to be added. */
04222     b_pos_with_word_shift = b_pos + word_shift;
04223     while (a_pos > b_pos_with_word_shift) {
04224         c->frac[--c_pos] = a->frac[--a_pos];
04225     }
04226     carry = 0;    /* set first carry be zero */
04227 
04228     /* Now perform addition until every digits of b will be */
04229     /* exhausted. */
04230     while (b_pos > 0) {
04231         c->frac[--c_pos] = a->frac[--a_pos] + b->frac[--b_pos] + carry;
04232         if (c->frac[c_pos] >= BASE) {
04233             c->frac[c_pos] -= BASE;
04234             carry = 1;
04235         }
04236         else {
04237             carry = 0;
04238         }
04239     }
04240 
04241     /* Just assign the first few digits of a with considering */
04242     /* the carry obtained so far because b has been exhausted. */
04243     while (a_pos > 0) {
04244         c->frac[--c_pos] = a->frac[--a_pos] + carry;
04245         if (c->frac[c_pos] >= BASE) {
04246             c->frac[c_pos] -= BASE;
04247             carry = 1;
04248         }
04249         else {
04250             carry = 0;
04251         }
04252     }
04253     if (c_pos) c->frac[c_pos - 1] += carry;
04254     goto Exit;
04255 
04256 Assign_a:
04257     VpAsgn(c, a, 1);
04258     mrv = 0;
04259 
04260 Exit:
04261 
04262 #ifdef BIGDECIMAL_DEBUG
04263     if (gfDebug) {
04264         VPrint(stdout, "VpAddAbs exit: c=% \n", c);
04265     }
04266 #endif /* BIGDECIMAL_DEBUG */
04267     return mrv;
04268 }
04269 
04270 /*
04271  * c = abs(a) - abs(b)
04272  */
04273 static BDIGIT
04274 VpSubAbs(Real *a, Real *b, Real *c)
04275 {
04276     size_t word_shift;
04277     size_t ap;
04278     size_t bp;
04279     size_t cp;
04280     size_t a_pos;
04281     size_t b_pos, b_pos_with_word_shift;
04282     size_t c_pos;
04283     BDIGIT av, bv, borrow, mrv;
04284 
04285 #ifdef BIGDECIMAL_DEBUG
04286     if (gfDebug) {
04287         VPrint(stdout, "VpSubAbs called: a = %\n", a);
04288         VPrint(stdout, "     b = %\n", b);
04289     }
04290 #endif /* BIGDECIMAL_DEBUG */
04291 
04292     word_shift = VpSetPTR(a, b, c, &ap, &bp, &cp, &av, &bv);
04293     a_pos = ap;
04294     b_pos = bp;
04295     c_pos = cp;
04296     if (word_shift == (size_t)-1L) return 0; /* Overflow */
04297     if (b_pos == (size_t)-1L) goto Assign_a;
04298 
04299     if (av >= bv) {
04300         mrv = av - bv;
04301         borrow = 0;
04302     }
04303     else {
04304         mrv    = 0;
04305         borrow = 1;
04306     }
04307 
04308     /* Just assign the values which are the BASE subtracted by   */
04309     /* each of the last few digits of the b because the a has no */
04310     /* corresponding digits to be subtracted. */
04311     if (b_pos + word_shift > a_pos) {
04312         while (b_pos > 0 && b_pos + word_shift > a_pos) {
04313             c->frac[--c_pos] = BASE - b->frac[--b_pos] - borrow;
04314             borrow = 1;
04315         }
04316         if (b_pos == 0) {
04317             while (word_shift > a_pos) {
04318                 --word_shift;
04319                 c->frac[--c_pos] = BASE - borrow;
04320                 borrow = 1;
04321             }
04322         }
04323     }
04324     /* Just assign the last few digits of a to c because b has no */
04325     /* corresponding digits to subtract. */
04326 
04327     b_pos_with_word_shift = b_pos + word_shift;
04328     while (a_pos > b_pos_with_word_shift) {
04329         c->frac[--c_pos] = a->frac[--a_pos];
04330     }
04331 
04332     /* Now perform subtraction until every digits of b will be */
04333     /* exhausted. */
04334     while (b_pos > 0) {
04335         --c_pos;
04336         if (a->frac[--a_pos] < b->frac[--b_pos] + borrow) {
04337             c->frac[c_pos] = BASE + a->frac[a_pos] - b->frac[b_pos] - borrow;
04338             borrow = 1;
04339         }
04340         else {
04341             c->frac[c_pos] = a->frac[a_pos] - b->frac[b_pos] - borrow;
04342             borrow = 0;
04343         }
04344     }
04345 
04346     /* Just assign the first few digits of a with considering */
04347     /* the borrow obtained so far because b has been exhausted. */
04348     while (a_pos > 0) {
04349         --c_pos;
04350         if (a->frac[--a_pos] < borrow) {
04351             c->frac[c_pos] = BASE + a->frac[a_pos] - borrow;
04352             borrow = 1;
04353         }
04354         else {
04355             c->frac[c_pos] = a->frac[a_pos] - borrow;
04356             borrow = 0;
04357         }
04358     }
04359     if (c_pos) c->frac[c_pos - 1] -= borrow;
04360     goto Exit;
04361 
04362 Assign_a:
04363     VpAsgn(c, a, 1);
04364     mrv = 0;
04365 
04366 Exit:
04367 #ifdef BIGDECIMAL_DEBUG
04368     if (gfDebug) {
04369         VPrint(stdout, "VpSubAbs exit: c=% \n", c);
04370     }
04371 #endif /* BIGDECIMAL_DEBUG */
04372     return mrv;
04373 }
04374 
04375 /*
04376  * Note: If(av+bv)>= HALF_BASE,then 1 will be added to the least significant
04377  *    digit of c(In case of addition).
04378  * ------------------------- figure of output -----------------------------------
04379  *      a =  xxxxxxxxxxx
04380  *      b =    xxxxxxxxxx
04381  *      c =xxxxxxxxxxxxxxx
04382  *      word_shift =  |   |
04383  *      right_word =  |    | (Total digits in RHSV)
04384  *      left_word  = |   |   (Total digits in LHSV)
04385  *      a_pos      =    |
04386  *      b_pos      =     |
04387  *      c_pos      =      |
04388  */
04389 static size_t
04390 VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos, BDIGIT *av, BDIGIT *bv)
04391 {
04392     size_t left_word, right_word, word_shift;
04393 
04394     size_t const round_limit = (VpGetPrecLimit() + BASE_FIG - 1) / BASE_FIG;
04395 
04396     assert(a->exponent >= b->expoennt);
04397 
04398     c->frac[0] = 0;
04399     *av = *bv = 0;
04400 
04401     word_shift = (a->exponent - b->exponent);
04402     left_word = b->Prec + word_shift;
04403     right_word = Max(a->Prec, left_word);
04404     left_word = c->MaxPrec - 1;    /* -1 ... prepare for round up */
04405 
04406     /*
04407      * check if 'round' is needed.
04408      */
04409     if (right_word > left_word) {    /* round ? */
04410         /*---------------------------------
04411          *  Actual size of a = xxxxxxAxx
04412          *  Actual size of b = xxxBxxxxx
04413          *  Max. size of   c = xxxxxx
04414          *  Round off        =   |-----|
04415          *  c_pos            =   |
04416          *  right_word       =   |
04417          *  a_pos            =    |
04418          */
04419         *c_pos = right_word = left_word + 1;    /* Set resulting precision */
04420         /* be equal to that of c */
04421         if (a->Prec >= c->MaxPrec) {
04422             /*
04423              *   a =  xxxxxxAxxx
04424              *   c =  xxxxxx
04425              *   a_pos =    |
04426              */
04427             *a_pos = left_word;
04428             if (*a_pos <= round_limit) {
04429                 *av = a->frac[*a_pos];    /* av is 'A' shown in above. */
04430             }
04431         }
04432         else {
04433             /*
04434              *   a = xxxxxxx
04435              *   c = xxxxxxxxxx
04436              *  a_pos =     |
04437              */
04438             *a_pos = a->Prec;
04439         }
04440         if (b->Prec + word_shift >= c->MaxPrec) {
04441             /*
04442              *   a = xxxxxxxxx
04443              *   b =  xxxxxxxBxxx
04444              *   c = xxxxxxxxxxx
04445              *  b_pos =   |
04446              */
04447             if (c->MaxPrec >= word_shift + 1) {
04448                 *b_pos = c->MaxPrec - word_shift - 1;
04449                 if (*b_pos + word_shift <= round_limit) {
04450                     *bv = b->frac[*b_pos];
04451                 }
04452             }
04453             else {
04454                 *b_pos = -1L;
04455             }
04456         }
04457         else {
04458             /*
04459              *   a = xxxxxxxxxxxxxxxx
04460              *   b =  xxxxxx
04461              *   c = xxxxxxxxxxxxx
04462              *  b_pos =     |
04463              */
04464             *b_pos = b->Prec;
04465         }
04466     }
04467     else {            /* The MaxPrec of c - 1 > The Prec of a + b  */
04468         /*
04469          *    a =   xxxxxxx
04470          *    b =   xxxxxx
04471          *    c = xxxxxxxxxxx
04472          *   c_pos =   |
04473          */
04474         *b_pos = b->Prec;
04475         *a_pos = a->Prec;
04476         *c_pos = right_word + 1;
04477     }
04478     c->Prec = *c_pos;
04479     c->exponent = a->exponent;
04480     if (!AddExponent(c, 1)) return (size_t)-1L;
04481     return word_shift;
04482 }
04483 
04484 /*
04485  * Return number of significant digits
04486  *       c = a * b , Where a = a0a1a2 ... an
04487  *             b = b0b1b2 ... bm
04488  *             c = c0c1c2 ... cl
04489  *          a0 a1 ... an   * bm
04490  *       a0 a1 ... an   * bm-1
04491  *         .   .    .
04492  *       .   .   .
04493  *        a0 a1 .... an    * b0
04494  *      +_____________________________
04495  *     c0 c1 c2  ......  cl
04496  *     nc      <---|
04497  *     MaxAB |--------------------|
04498  */
04499 VP_EXPORT size_t
04500 VpMult(Real *c, Real *a, Real *b)
04501 {
04502     size_t MxIndA, MxIndB, MxIndAB, MxIndC;
04503     size_t ind_c, i, ii, nc;
04504     size_t ind_as, ind_ae, ind_bs;
04505     BDIGIT carry;
04506     BDIGIT_DBL s;
04507     Real *w;
04508 
04509 #ifdef BIGDECIMAL_DEBUG
04510     if (gfDebug) {
04511         VPrint(stdout, "VpMult(Enter): a=% \n", a);
04512         VPrint(stdout, "      b=% \n", b);
04513     }
04514 #endif /* BIGDECIMAL_DEBUG */
04515 
04516     if (!VpIsDefOP(c, a, b, 3)) return 0; /* No significant digit */
04517 
04518     if (VpIsZero(a) || VpIsZero(b)) {
04519         /* at least a or b is zero */
04520         VpSetZero(c, VpGetSign(a) * VpGetSign(b));
04521         return 1; /* 0: 1 significant digit */
04522     }
04523 
04524     if (VpIsOne(a)) {
04525         VpAsgn(c, b, VpGetSign(a));
04526         goto Exit;
04527     }
04528     if (VpIsOne(b)) {
04529         VpAsgn(c, a, VpGetSign(b));
04530         goto Exit;
04531     }
04532     if (b->Prec > a->Prec) {
04533         /* Adjust so that digits(a)>digits(b) */
04534         w = a;
04535         a = b;
04536         b = w;
04537     }
04538     w = NULL;
04539     MxIndA = a->Prec - 1;
04540     MxIndB = b->Prec - 1;
04541     MxIndC = c->MaxPrec - 1;
04542     MxIndAB = a->Prec + b->Prec - 1;
04543 
04544     if (MxIndC < MxIndAB) {    /* The Max. prec. of c < Prec(a)+Prec(b) */
04545         w = c;
04546         c = VpAlloc((size_t)((MxIndAB + 1) * BASE_FIG), "#0");
04547         MxIndC = MxIndAB;
04548     }
04549 
04550     /* set LHSV c info */
04551 
04552     c->exponent = a->exponent;    /* set exponent */
04553     if (!AddExponent(c, b->exponent)) {
04554         if (w) VpFree(c);
04555         return 0;
04556     }
04557     VpSetSign(c, VpGetSign(a) * VpGetSign(b));    /* set sign  */
04558     carry = 0;
04559     nc = ind_c = MxIndAB;
04560     memset(c->frac, 0, (nc + 1) * sizeof(BDIGIT));        /* Initialize c  */
04561     c->Prec = nc + 1;        /* set precision */
04562     for (nc = 0; nc < MxIndAB; ++nc, --ind_c) {
04563         if (nc < MxIndB) {    /* The left triangle of the Fig. */
04564             ind_as = MxIndA - nc;
04565             ind_ae = MxIndA;
04566             ind_bs = MxIndB;
04567         }
04568         else if (nc <= MxIndA) {    /* The middle rectangular of the Fig. */
04569             ind_as = MxIndA - nc;
04570             ind_ae = MxIndA - (nc - MxIndB);
04571             ind_bs = MxIndB;
04572         }
04573         else /* if (nc > MxIndA) */ {    /*  The right triangle of the Fig. */
04574             ind_as = 0;
04575             ind_ae = MxIndAB - nc - 1;
04576             ind_bs = MxIndB - (nc - MxIndA);
04577         }
04578 
04579         for (i = ind_as; i <= ind_ae; ++i) {
04580             s = (BDIGIT_DBL)a->frac[i] * b->frac[ind_bs--];
04581             carry = (BDIGIT)(s / BASE);
04582             s -= (BDIGIT_DBL)carry * BASE;
04583             c->frac[ind_c] += (BDIGIT)s;
04584             if (c->frac[ind_c] >= BASE) {
04585                 s = c->frac[ind_c] / BASE;
04586                 carry += (BDIGIT)s;
04587                 c->frac[ind_c] -= (BDIGIT)(s * BASE);
04588             }
04589             if (carry) {
04590                 ii = ind_c;
04591                 while (ii-- > 0) {
04592                     c->frac[ii] += carry;
04593                     if (c->frac[ii] >= BASE) {
04594                         carry = c->frac[ii] / BASE;
04595                         c->frac[ii] -= (carry * BASE);
04596                     }
04597                     else {
04598                         break;
04599                     }
04600                 }
04601             }
04602         }
04603     }
04604     if (w != NULL) {        /* free work variable */
04605         VpNmlz(c);
04606         VpAsgn(w, c, 1);
04607         VpFree(c);
04608         c = w;
04609     }
04610     else {
04611         VpLimitRound(c,0);
04612     }
04613 
04614 Exit:
04615 #ifdef BIGDECIMAL_DEBUG
04616     if (gfDebug) {
04617         VPrint(stdout, "VpMult(c=a*b): c=% \n", c);
04618         VPrint(stdout, "      a=% \n", a);
04619         VPrint(stdout, "      b=% \n", b);
04620     }
04621 #endif /*BIGDECIMAL_DEBUG */
04622     return c->Prec*BASE_FIG;
04623 }
04624 
04625 /*
04626  *   c = a / b,  remainder = r
04627  */
04628     VP_EXPORT size_t
04629 VpDivd(Real *c, Real *r, Real *a, Real *b)
04630 {
04631     size_t word_a, word_b, word_c, word_r;
04632     size_t i, n, ind_a, ind_b, ind_c, ind_r;
04633     size_t nLoop;
04634     BDIGIT_DBL q, b1, b1p1, b1b2, b1b2p1, r1r2;
04635     BDIGIT borrow, borrow1, borrow2;
04636     BDIGIT_DBL qb;
04637 
04638 #ifdef BIGDECIMAL_DEBUG
04639     if (gfDebug) {
04640         VPrint(stdout, " VpDivd(c=a/b)  a=% \n", a);
04641         VPrint(stdout, "    b=% \n", b);
04642     }
04643 #endif /*BIGDECIMAL_DEBUG */
04644 
04645     VpSetNaN(r);
04646     if (!VpIsDefOP(c, a, b, 4)) goto Exit;
04647     if (VpIsZero(a) && VpIsZero(b)) {
04648         VpSetNaN(c);
04649         return VpException(VP_EXCEPTION_NaN, "(VpDivd) 0/0 not defined(NaN)", 0);
04650     }
04651     if (VpIsZero(b)) {
04652         VpSetInf(c, VpGetSign(a) * VpGetSign(b));
04653         return VpException(VP_EXCEPTION_ZERODIVIDE, "(VpDivd) Divide by zero", 0);
04654     }
04655     if (VpIsZero(a)) {
04656         /* numerator a is zero  */
04657         VpSetZero(c, VpGetSign(a) * VpGetSign(b));
04658         VpSetZero(r, VpGetSign(a) * VpGetSign(b));
04659         goto Exit;
04660     }
04661     if (VpIsOne(b)) {
04662         /* divide by one  */
04663         VpAsgn(c, a, VpGetSign(b));
04664         VpSetZero(r, VpGetSign(a));
04665         goto Exit;
04666     }
04667 
04668     word_a = a->Prec;
04669     word_b = b->Prec;
04670     word_c = c->MaxPrec;
04671     word_r = r->MaxPrec;
04672 
04673     ind_c = 0;
04674     ind_r = 1;
04675 
04676     if (word_a >= word_r) goto space_error;
04677 
04678     r->frac[0] = 0;
04679     while (ind_r <= word_a) {
04680         r->frac[ind_r] = a->frac[ind_r - 1];
04681         ++ind_r;
04682     }
04683 
04684     while (ind_r < word_r) r->frac[ind_r++] = 0;
04685     while (ind_c < word_c) c->frac[ind_c++] = 0;
04686 
04687     /* initial procedure */
04688     b1 = b1p1 = b->frac[0];
04689     if (b->Prec <= 1) {
04690         b1b2p1 = b1b2 = b1p1 * BASE;
04691     }
04692     else {
04693         b1p1 = b1 + 1;
04694         b1b2p1 = b1b2 = b1 * BASE + b->frac[1];
04695         if (b->Prec > 2) ++b1b2p1;
04696     }
04697 
04698     /* */
04699     /* loop start */
04700     ind_c = word_r - 1;
04701     nLoop = Min(word_c,ind_c);
04702     ind_c = 1;
04703     while (ind_c < nLoop) {
04704         if (r->frac[ind_c] == 0) {
04705             ++ind_c;
04706             continue;
04707         }
04708         r1r2 = (BDIGIT_DBL)r->frac[ind_c] * BASE + r->frac[ind_c + 1];
04709         if (r1r2 == b1b2) {
04710             /* The first two word digits is the same */
04711             ind_b = 2;
04712             ind_a = ind_c + 2;
04713             while (ind_b < word_b) {
04714                 if (r->frac[ind_a] < b->frac[ind_b]) goto div_b1p1;
04715                 if (r->frac[ind_a] > b->frac[ind_b]) break;
04716                 ++ind_a;
04717                 ++ind_b;
04718             }
04719             /* The first few word digits of r and b is the same and */
04720             /* the first different word digit of w is greater than that */
04721             /* of b, so quotient is 1 and just subtract b from r. */
04722             borrow = 0;        /* quotient=1, then just r-b */
04723             ind_b = b->Prec - 1;
04724             ind_r = ind_c + ind_b;
04725             if (ind_r >= word_r) goto space_error;
04726             n = ind_b;
04727             for (i = 0; i <= n; ++i) {
04728                 if (r->frac[ind_r] < b->frac[ind_b] + borrow) {
04729                     r->frac[ind_r] += (BASE - (b->frac[ind_b] + borrow));
04730                     borrow = 1;
04731                 }
04732                 else {
04733                     r->frac[ind_r] = r->frac[ind_r] - b->frac[ind_b] - borrow;
04734                     borrow = 0;
04735                 }
04736                 --ind_r;
04737                 --ind_b;
04738             }
04739             ++c->frac[ind_c];
04740             goto carry;
04741         }
04742         /* The first two word digits is not the same, */
04743         /* then compare magnitude, and divide actually. */
04744         if (r1r2 >= b1b2p1) {
04745             q = r1r2 / b1b2p1;  /* q == (BDIGIT)q  */
04746             c->frac[ind_c] += (BDIGIT)q;
04747             ind_r = b->Prec + ind_c - 1;
04748             goto sub_mult;
04749         }
04750 
04751 div_b1p1:
04752         if (ind_c + 1 >= word_c) goto out_side;
04753         q = r1r2 / b1p1;  /* q == (BDIGIT)q */
04754         c->frac[ind_c + 1] += (BDIGIT)q;
04755         ind_r = b->Prec + ind_c;
04756 
04757 sub_mult:
04758         borrow1 = borrow2 = 0;
04759         ind_b = word_b - 1;
04760         if (ind_r >= word_r) goto space_error;
04761         n = ind_b;
04762         for (i = 0; i <= n; ++i) {
04763             /* now, perform r = r - q * b */
04764             qb = q * b->frac[ind_b];
04765             if (qb < BASE) borrow1 = 0;
04766             else {
04767                 borrow1 = (BDIGIT)(qb / BASE);
04768                 qb -= (BDIGIT_DBL)borrow1 * BASE;       /* get qb < BASE */
04769             }
04770             if(r->frac[ind_r] < qb) {
04771                 r->frac[ind_r] += (BDIGIT)(BASE - qb);
04772                 borrow2 = borrow2 + borrow1 + 1;
04773             }
04774             else {
04775                 r->frac[ind_r] -= (BDIGIT)qb;
04776                 borrow2 += borrow1;
04777             }
04778             if (borrow2) {
04779                 if(r->frac[ind_r - 1] < borrow2) {
04780                     r->frac[ind_r - 1] += (BASE - borrow2);
04781                     borrow2 = 1;
04782                 }
04783                 else {
04784                     r->frac[ind_r - 1] -= borrow2;
04785                     borrow2 = 0;
04786                 }
04787             }
04788             --ind_r;
04789             --ind_b;
04790         }
04791 
04792         r->frac[ind_r] -= borrow2;
04793 carry:
04794         ind_r = ind_c;
04795         while (c->frac[ind_r] >= BASE) {
04796             c->frac[ind_r] -= BASE;
04797             --ind_r;
04798             ++c->frac[ind_r];
04799         }
04800     }
04801     /* End of operation, now final arrangement */
04802 out_side:
04803     c->Prec = word_c;
04804     c->exponent = a->exponent;
04805     if (!AddExponent(c, 2)) return 0;
04806     if (!AddExponent(c, -(b->exponent))) return 0;
04807 
04808     VpSetSign(c, VpGetSign(a) * VpGetSign(b));
04809     VpNmlz(c);            /* normalize c */
04810     r->Prec = word_r;
04811     r->exponent = a->exponent;
04812     if (!AddExponent(r, 1)) return 0;
04813     VpSetSign(r, VpGetSign(a));
04814     VpNmlz(r);            /* normalize r(remainder) */
04815     goto Exit;
04816 
04817 space_error:
04818 #ifdef BIGDECIMAL_DEBUG
04819     if (gfDebug) {
04820         printf("   word_a=%lu\n", word_a);
04821         printf("   word_b=%lu\n", word_b);
04822         printf("   word_c=%lu\n", word_c);
04823         printf("   word_r=%lu\n", word_r);
04824         printf("   ind_r =%lu\n", ind_r);
04825     }
04826 #endif /* BIGDECIMAL_DEBUG */
04827     rb_bug("ERROR(VpDivd): space for remainder too small.");
04828 
04829 Exit:
04830 #ifdef BIGDECIMAL_DEBUG
04831     if (gfDebug) {
04832         VPrint(stdout, " VpDivd(c=a/b), c=% \n", c);
04833         VPrint(stdout, "    r=% \n", r);
04834     }
04835 #endif /* BIGDECIMAL_DEBUG */
04836     return c->Prec * BASE_FIG;
04837 }
04838 
04839 /*
04840  *  Input  a = 00000xxxxxxxx En(5 preceding zeros)
04841  *  Output a = xxxxxxxx En-5
04842  */
04843 static int
04844 VpNmlz(Real *a)
04845 {
04846     size_t ind_a, i;
04847 
04848     if (!VpIsDef(a)) goto NoVal;
04849     if (VpIsZero(a)) goto NoVal;
04850 
04851     ind_a = a->Prec;
04852     while (ind_a--) {
04853         if (a->frac[ind_a]) {
04854             a->Prec = ind_a + 1;
04855             i = 0;
04856             while (a->frac[i] == 0) ++i;        /* skip the first few zeros */
04857             if (i) {
04858                 a->Prec -= i;
04859                 if (!AddExponent(a, -(SIGNED_VALUE)i)) return 0;
04860                 memmove(&a->frac[0], &a->frac[i], a->Prec*sizeof(BDIGIT));
04861             }
04862             return 1;
04863         }
04864     }
04865     /* a is zero(no non-zero digit) */
04866     VpSetZero(a, VpGetSign(a));
04867     return 0;
04868 
04869 NoVal:
04870     a->frac[0] = 0;
04871     a->Prec = 1;
04872     return 0;
04873 }
04874 
04875 /*
04876  *  VpComp = 0  ... if a=b,
04877  *   Pos  ... a>b,
04878  *   Neg  ... a<b.
04879  *   999  ... result undefined(NaN)
04880  */
04881 VP_EXPORT int
04882 VpComp(Real *a, Real *b)
04883 {
04884     int val;
04885     size_t mx, ind;
04886     int e;
04887     val = 0;
04888     if (VpIsNaN(a) || VpIsNaN(b)) return 999;
04889     if (!VpIsDef(a)) {
04890         if (!VpIsDef(b)) e = a->sign - b->sign;
04891         else             e = a->sign;
04892 
04893         if (e > 0)      return  1;
04894         else if (e < 0) return -1;
04895         else            return  0;
04896     }
04897     if (!VpIsDef(b)) {
04898         e = -b->sign;
04899         if (e > 0) return  1;
04900         else       return -1;
04901     }
04902     /* Zero check */
04903     if (VpIsZero(a)) {
04904         if (VpIsZero(b)) return 0; /* both zero */
04905         val = -VpGetSign(b);
04906         goto Exit;
04907     }
04908     if (VpIsZero(b)) {
04909         val = VpGetSign(a);
04910         goto Exit;
04911     }
04912 
04913     /* compare sign */
04914     if (VpGetSign(a) > VpGetSign(b)) {
04915         val = 1;        /* a>b */
04916         goto Exit;
04917     }
04918     if (VpGetSign(a) < VpGetSign(b)) {
04919         val = -1;        /* a<b */
04920         goto Exit;
04921     }
04922 
04923     /* a and b have same sign, && sign!=0,then compare exponent */
04924     if (a->exponent > b->exponent) {
04925         val = VpGetSign(a);
04926         goto Exit;
04927     }
04928     if (a->exponent < b->exponent) {
04929         val = -VpGetSign(b);
04930         goto Exit;
04931     }
04932 
04933     /* a and b have same exponent, then compare significand. */
04934     mx = (a->Prec < b->Prec) ? a->Prec : b->Prec;
04935     ind = 0;
04936     while (ind < mx) {
04937         if (a->frac[ind] > b->frac[ind]) {
04938             val = VpGetSign(a);
04939             goto Exit;
04940         }
04941         if (a->frac[ind] < b->frac[ind]) {
04942             val = -VpGetSign(b);
04943             goto Exit;
04944         }
04945         ++ind;
04946     }
04947     if (a->Prec > b->Prec) {
04948         val = VpGetSign(a);
04949     }
04950     else if (a->Prec < b->Prec) {
04951         val = -VpGetSign(b);
04952     }
04953 
04954 Exit:
04955     if      (val >  1) val =  1;
04956     else if (val < -1) val = -1;
04957 
04958 #ifdef BIGDECIMAL_DEBUG
04959     if (gfDebug) {
04960         VPrint(stdout, " VpComp a=%\n", a);
04961         VPrint(stdout, "  b=%\n", b);
04962         printf("  ans=%d\n", val);
04963     }
04964 #endif /* BIGDECIMAL_DEBUG */
04965     return (int)val;
04966 }
04967 
04968 /*
04969  *    cntl_chr ... ASCIIZ Character, print control characters
04970  *     Available control codes:
04971  *      %  ... VP variable. To print '%', use '%%'.
04972  *      \n ... new line
04973  *      \b ... backspace
04974  *           ... tab
04975  *     Note: % must must not appear more than once
04976  *    a  ... VP variable to be printed
04977  */
04978 #ifdef BIGDECIMAL_ENABLE_VPRINT
04979 static int
04980 VPrint(FILE *fp, const char *cntl_chr, Real *a)
04981 {
04982     size_t i, j, nc, nd, ZeroSup, sep = 10;
04983     BDIGIT m, e, nn;
04984 
04985     /* Check if NaN & Inf. */
04986     if (VpIsNaN(a)) {
04987         fprintf(fp, SZ_NaN);
04988         return 8;
04989     }
04990     if (VpIsPosInf(a)) {
04991         fprintf(fp, SZ_INF);
04992         return 8;
04993     }
04994     if (VpIsNegInf(a)) {
04995         fprintf(fp, SZ_NINF);
04996         return 9;
04997     }
04998     if (VpIsZero(a)) {
04999         fprintf(fp, "0.0");
05000         return 3;
05001     }
05002 
05003     j = 0;
05004     nd = nc = 0;        /*  nd : number of digits in fraction part(every 10 digits, */
05005     /*    nd<=10). */
05006     /*  nc : number of characters printed  */
05007     ZeroSup = 1;        /* Flag not to print the leading zeros as 0.00xxxxEnn */
05008     while (*(cntl_chr + j)) {
05009         if (*(cntl_chr + j) == '%' && *(cntl_chr + j + 1) != '%') {
05010             nc = 0;
05011             if (!VpIsZero(a)) {
05012                 if (VpGetSign(a) < 0) {
05013                     fprintf(fp, "-");
05014                     ++nc;
05015                 }
05016                 nc += fprintf(fp, "0.");
05017                 switch (*(cntl_chr + j + 1)) {
05018                 default:
05019                     break;
05020 
05021                 case '0': case 'z':
05022                     ZeroSup = 0;
05023                     ++j;
05024                     sep = cntl_chr[j] == 'z' ? RMPD_COMPONENT_FIGURES : 10;
05025                     break;
05026                 }
05027                 for (i = 0; i < a->Prec; ++i) {
05028                     m = BASE1;
05029                     e = a->frac[i];
05030                     while (m) {
05031                         nn = e / m;
05032                         if (!ZeroSup || nn) {
05033                             nc += fprintf(fp, "%lu", (unsigned long)nn);    /* The leading zero(s) */
05034                             /* as 0.00xx will not */
05035                             /* be printed. */
05036                             ++nd;
05037                             ZeroSup = 0;    /* Set to print succeeding zeros */
05038                         }
05039                         if (nd >= sep) {    /* print ' ' after every 10 digits */
05040                             nd = 0;
05041                             nc += fprintf(fp, " ");
05042                         }
05043                         e = e - nn * m;
05044                         m /= 10;
05045                     }
05046                 }
05047                 nc += fprintf(fp, "E%"PRIdSIZE, VpExponent10(a));
05048                 nc += fprintf(fp, " (%"PRIdVALUE", %lu, %lu)", a->exponent, a->Prec, a->MaxPrec);
05049             }
05050             else {
05051                 nc += fprintf(fp, "0.0");
05052             }
05053         }
05054         else {
05055             ++nc;
05056             if (*(cntl_chr + j) == '\\') {
05057                 switch (*(cntl_chr + j + 1)) {
05058                   case 'n':
05059                     fprintf(fp, "\n");
05060                     ++j;
05061                     break;
05062                   case 't':
05063                     fprintf(fp, "\t");
05064                     ++j;
05065                     break;
05066                   case 'b':
05067                     fprintf(fp, "\n");
05068                     ++j;
05069                     break;
05070                   default:
05071                     fprintf(fp, "%c", *(cntl_chr + j));
05072                     break;
05073                 }
05074             }
05075             else {
05076                 fprintf(fp, "%c", *(cntl_chr + j));
05077                 if (*(cntl_chr + j) == '%') ++j;
05078             }
05079         }
05080         j++;
05081     }
05082 
05083     return (int)nc;
05084 }
05085 #endif
05086 
05087 static void
05088 VpFormatSt(char *psz, size_t fFmt)
05089 {
05090     size_t ie, i, nf = 0;
05091     char ch;
05092 
05093     if (fFmt == 0) return;
05094 
05095     ie = strlen(psz);
05096     for (i = 0; i < ie; ++i) {
05097         ch = psz[i];
05098         if (!ch) break;
05099         if (ISSPACE(ch) || ch=='-' || ch=='+') continue;
05100         if (ch == '.') { nf = 0; continue; }
05101         if (ch == 'E') break;
05102 
05103         if (++nf > fFmt) {
05104             memmove(psz + i + 1, psz + i, ie - i + 1);
05105             ++ie;
05106             nf = 0;
05107             psz[i] = ' ';
05108         }
05109     }
05110 }
05111 
05112 VP_EXPORT ssize_t
05113 VpExponent10(Real *a)
05114 {
05115     ssize_t ex;
05116     size_t n;
05117 
05118     if (!VpHasVal(a)) return 0;
05119 
05120     ex = a->exponent * (ssize_t)BASE_FIG;
05121     n = BASE1;
05122     while ((a->frac[0] / n) == 0) {
05123         --ex;
05124         n /= 10;
05125     }
05126     return ex;
05127 }
05128 
05129 VP_EXPORT void
05130 VpSzMantissa(Real *a,char *psz)
05131 {
05132     size_t i, n, ZeroSup;
05133     BDIGIT_DBL m, e, nn;
05134 
05135     if (VpIsNaN(a)) {
05136         sprintf(psz, SZ_NaN);
05137         return;
05138     }
05139     if (VpIsPosInf(a)) {
05140         sprintf(psz, SZ_INF);
05141         return;
05142     }
05143     if (VpIsNegInf(a)) {
05144         sprintf(psz, SZ_NINF);
05145         return;
05146     }
05147 
05148     ZeroSup = 1;        /* Flag not to print the leading zeros as 0.00xxxxEnn */
05149     if (!VpIsZero(a)) {
05150         if (VpGetSign(a) < 0) *psz++ = '-';
05151         n = a->Prec;
05152         for (i = 0; i < n; ++i) {
05153             m = BASE1;
05154             e = a->frac[i];
05155             while (m) {
05156                 nn = e / m;
05157                 if (!ZeroSup || nn) {
05158                     sprintf(psz, "%lu", (unsigned long)nn); /* The leading zero(s) */
05159                     psz += strlen(psz);
05160                     /* as 0.00xx will be ignored. */
05161                     ZeroSup = 0; /* Set to print succeeding zeros */
05162                 }
05163                 e = e - nn * m;
05164                 m /= 10;
05165             }
05166         }
05167         *psz = 0;
05168         while (psz[-1] == '0') *(--psz) = 0;
05169     }
05170     else {
05171         if (VpIsPosZero(a)) sprintf(psz, "0");
05172         else                sprintf(psz, "-0");
05173     }
05174 }
05175 
05176 VP_EXPORT int
05177 VpToSpecialString(Real *a,char *psz,int fPlus)
05178     /* fPlus =0:default, =1: set ' ' before digits , =2: set '+' before digits. */
05179 {
05180     if (VpIsNaN(a)) {
05181         sprintf(psz,SZ_NaN);
05182         return 1;
05183     }
05184 
05185     if (VpIsPosInf(a)) {
05186         if (fPlus == 1) {
05187             *psz++ = ' ';
05188         }
05189         else if (fPlus == 2) {
05190             *psz++ = '+';
05191         }
05192         sprintf(psz, SZ_INF);
05193         return 1;
05194     }
05195     if (VpIsNegInf(a)) {
05196         sprintf(psz, SZ_NINF);
05197         return 1;
05198     }
05199     if (VpIsZero(a)) {
05200         if (VpIsPosZero(a)) {
05201             if (fPlus == 1)      sprintf(psz, " 0.0");
05202             else if (fPlus == 2) sprintf(psz, "+0.0");
05203             else                 sprintf(psz,  "0.0");
05204         }
05205         else                     sprintf(psz, "-0.0");
05206         return 1;
05207     }
05208     return 0;
05209 }
05210 
05211 VP_EXPORT void
05212 VpToString(Real *a, char *psz, size_t fFmt, int fPlus)
05213 /* fPlus =0:default, =1: set ' ' before digits , =2:set '+' before digits. */
05214 {
05215     size_t i, n, ZeroSup;
05216     BDIGIT shift, m, e, nn;
05217     char *pszSav = psz;
05218     ssize_t ex;
05219 
05220     if (VpToSpecialString(a, psz, fPlus)) return;
05221 
05222     ZeroSup = 1;    /* Flag not to print the leading zeros as 0.00xxxxEnn */
05223 
05224     if (VpGetSign(a) < 0) *psz++ = '-';
05225     else if (fPlus == 1)  *psz++ = ' ';
05226     else if (fPlus == 2)  *psz++ = '+';
05227 
05228     *psz++ = '0';
05229     *psz++ = '.';
05230     n = a->Prec;
05231     for (i = 0; i < n; ++i) {
05232         m = BASE1;
05233         e = a->frac[i];
05234         while (m) {
05235             nn = e / m;
05236             if (!ZeroSup || nn) {
05237                 sprintf(psz, "%lu", (unsigned long)nn);    /* The reading zero(s) */
05238                 psz += strlen(psz);
05239                 /* as 0.00xx will be ignored. */
05240                 ZeroSup = 0;    /* Set to print succeeding zeros */
05241             }
05242             e = e - nn * m;
05243             m /= 10;
05244         }
05245     }
05246     ex = a->exponent * (ssize_t)BASE_FIG;
05247     shift = BASE1;
05248     while (a->frac[0] / shift == 0) {
05249         --ex;
05250         shift /= 10;
05251     }
05252     while (psz[-1] == '0') {
05253         *(--psz) = 0;
05254     }
05255     sprintf(psz, "E%"PRIdSIZE, ex);
05256     if (fFmt) VpFormatSt(pszSav, fFmt);
05257 }
05258 
05259 VP_EXPORT void
05260 VpToFString(Real *a, char *psz, size_t fFmt, int fPlus)
05261 /* fPlus =0:default,=1: set ' ' before digits ,set '+' before digits. */
05262 {
05263     size_t i, n;
05264     BDIGIT m, e, nn;
05265     char *pszSav = psz;
05266     ssize_t ex;
05267 
05268     if (VpToSpecialString(a, psz, fPlus)) return;
05269 
05270     if (VpGetSign(a) < 0) *psz++ = '-';
05271     else if (fPlus == 1)  *psz++ = ' ';
05272     else if (fPlus == 2)  *psz++ = '+';
05273 
05274     n  = a->Prec;
05275     ex = a->exponent;
05276     if (ex <= 0) {
05277         *psz++ = '0';*psz++ = '.';
05278         while (ex < 0) {
05279             for (i=0; i < BASE_FIG; ++i) *psz++ = '0';
05280             ++ex;
05281         }
05282         ex = -1;
05283     }
05284 
05285     for (i = 0; i < n; ++i) {
05286         --ex;
05287         if (i == 0 && ex >= 0) {
05288             sprintf(psz, "%lu", (unsigned long)a->frac[i]);
05289             psz += strlen(psz);
05290         }
05291         else {
05292             m = BASE1;
05293             e = a->frac[i];
05294             while (m) {
05295                 nn = e / m;
05296                 *psz++ = (char)(nn + '0');
05297                 e = e - nn * m;
05298                 m /= 10;
05299             }
05300         }
05301         if (ex == 0) *psz++ = '.';
05302     }
05303     while (--ex>=0) {
05304         m = BASE;
05305         while (m /= 10) *psz++ = '0';
05306         if (ex == 0)    *psz++ = '.';
05307     }
05308     *psz = 0;
05309     while (psz[-1] == '0') *(--psz) = 0;
05310     if (psz[-1] == '.') sprintf(psz, "0");
05311     if (fFmt) VpFormatSt(pszSav, fFmt);
05312 }
05313 
05314 /*
05315  *  [Output]
05316  *   a[]  ... variable to be assigned the value.
05317  *  [Input]
05318  *   int_chr[]  ... integer part(may include '+/-').
05319  *   ni   ... number of characters in int_chr[],not including '+/-'.
05320  *   frac[]  ... fraction part.
05321  *   nf   ... number of characters in frac[].
05322  *   exp_chr[]  ... exponent part(including '+/-').
05323  *   ne   ... number of characters in exp_chr[],not including '+/-'.
05324  */
05325 VP_EXPORT int
05326 VpCtoV(Real *a, const char *int_chr, size_t ni, const char *frac, size_t nf, const char *exp_chr, size_t ne)
05327 {
05328     size_t i, j, ind_a, ma, mi, me;
05329     SIGNED_VALUE e, es, eb, ef;
05330     int  sign, signe, exponent_overflow;
05331 
05332     /* get exponent part */
05333     e = 0;
05334     ma = a->MaxPrec;
05335     mi = ni;
05336     me = ne;
05337     signe = 1;
05338     exponent_overflow = 0;
05339     memset(a->frac, 0, ma * sizeof(BDIGIT));
05340     if (ne > 0) {
05341         i = 0;
05342         if (exp_chr[0] == '-') {
05343             signe = -1;
05344             ++i;
05345             ++me;
05346         }
05347         else if (exp_chr[0] == '+') {
05348             ++i;
05349             ++me;
05350         }
05351         while (i < me) {
05352             if (MUL_OVERFLOW_SIGNED_VALUE_P(e, (SIGNED_VALUE)BASE_FIG)) {
05353                 es = e;
05354                 goto exp_overflow;
05355             }
05356             es = e * (SIGNED_VALUE)BASE_FIG;
05357             if (MUL_OVERFLOW_SIGNED_VALUE_P(e, 10) ||
05358                 SIGNED_VALUE_MAX - (exp_chr[i] - '0') < e * 10)
05359                 goto exp_overflow;
05360             e = e * 10 + exp_chr[i] - '0';
05361             if (MUL_OVERFLOW_SIGNED_VALUE_P(e, (SIGNED_VALUE)BASE_FIG))
05362                 goto exp_overflow;
05363             if (es > (SIGNED_VALUE)(e * BASE_FIG)) {
05364               exp_overflow:
05365                 exponent_overflow = 1;
05366                 e = es; /* keep sign */
05367                 break;
05368             }
05369             ++i;
05370         }
05371     }
05372 
05373     /* get integer part */
05374     i = 0;
05375     sign = 1;
05376     if (1 /*ni >= 0*/) {
05377         if (int_chr[0] == '-') {
05378             sign = -1;
05379             ++i;
05380             ++mi;
05381         }
05382         else if (int_chr[0] == '+') {
05383             ++i;
05384             ++mi;
05385         }
05386     }
05387 
05388     e = signe * e;        /* e: The value of exponent part. */
05389     e = e + ni;        /* set actual exponent size. */
05390 
05391     if (e > 0) signe = 1;
05392     else       signe = -1;
05393 
05394     /* Adjust the exponent so that it is the multiple of BASE_FIG. */
05395     j = 0;
05396     ef = 1;
05397     while (ef) {
05398         if (e >= 0) eb =  e;
05399         else        eb = -e;
05400         ef = eb / (SIGNED_VALUE)BASE_FIG;
05401         ef = eb - ef * (SIGNED_VALUE)BASE_FIG;
05402         if (ef) {
05403             ++j;        /* Means to add one more preceding zero */
05404             ++e;
05405         }
05406     }
05407 
05408     eb = e / (SIGNED_VALUE)BASE_FIG;
05409 
05410     if (exponent_overflow) {
05411         int zero = 1;
05412         for (     ; i < mi && zero; i++) zero = int_chr[i] == '0';
05413         for (i = 0; i < nf && zero; i++) zero = frac[i] == '0';
05414         if (!zero && signe > 0) {
05415             VpSetInf(a, sign);
05416             VpException(VP_EXCEPTION_INFINITY, "exponent overflow",0);
05417         }
05418         else VpSetZero(a, sign);
05419         return 1;
05420     }
05421 
05422     ind_a = 0;
05423     while (i < mi) {
05424         a->frac[ind_a] = 0;
05425         while (j < BASE_FIG && i < mi) {
05426             a->frac[ind_a] = a->frac[ind_a] * 10 + int_chr[i] - '0';
05427             ++j;
05428             ++i;
05429         }
05430         if (i < mi) {
05431             ++ind_a;
05432             if (ind_a >= ma) goto over_flow;
05433             j = 0;
05434         }
05435     }
05436 
05437     /* get fraction part */
05438 
05439     i = 0;
05440     while (i < nf) {
05441         while (j < BASE_FIG && i < nf) {
05442             a->frac[ind_a] = a->frac[ind_a] * 10 + frac[i] - '0';
05443             ++j;
05444             ++i;
05445         }
05446         if (i < nf) {
05447             ++ind_a;
05448             if (ind_a >= ma) goto over_flow;
05449             j = 0;
05450         }
05451     }
05452     goto Final;
05453 
05454 over_flow:
05455     rb_warn("Conversion from String to BigDecimal overflow (last few digits discarded).");
05456 
05457 Final:
05458     if (ind_a >= ma) ind_a = ma - 1;
05459     while (j < BASE_FIG) {
05460         a->frac[ind_a] = a->frac[ind_a] * 10;
05461         ++j;
05462     }
05463     a->Prec = ind_a + 1;
05464     a->exponent = eb;
05465     VpSetSign(a, sign);
05466     VpNmlz(a);
05467     return 1;
05468 }
05469 
05470 /*
05471  * [Input]
05472  *   *m  ... Real
05473  * [Output]
05474  *   *d  ... fraction part of m(d = 0.xxxxxxx). where # of 'x's is fig.
05475  *   *e  ... exponent of m.
05476  * DBLE_FIG ... Number of digits in a double variable.
05477  *
05478  *  m -> d*10**e, 0<d<BASE
05479  * [Returns]
05480  *   0 ... Zero
05481  *   1 ... Normal
05482  *   2 ... Infinity
05483  *  -1 ... NaN
05484  */
05485 VP_EXPORT int
05486 VpVtoD(double *d, SIGNED_VALUE *e, Real *m)
05487 {
05488     size_t ind_m, mm, fig;
05489     double div;
05490     int    f = 1;
05491 
05492     if (VpIsNaN(m)) {
05493         *d = VpGetDoubleNaN();
05494         *e = 0;
05495         f = -1; /* NaN */
05496         goto Exit;
05497     }
05498     else if (VpIsPosZero(m)) {
05499         *d = 0.0;
05500         *e = 0;
05501         f  = 0;
05502         goto Exit;
05503     }
05504     else if (VpIsNegZero(m)) {
05505         *d = VpGetDoubleNegZero();
05506         *e = 0;
05507         f  = 0;
05508         goto Exit;
05509     }
05510     else if (VpIsPosInf(m)) {
05511         *d = VpGetDoublePosInf();
05512         *e = 0;
05513         f  = 2;
05514         goto Exit;
05515     }
05516     else if (VpIsNegInf(m)) {
05517         *d = VpGetDoubleNegInf();
05518         *e = 0;
05519         f  = 2;
05520         goto Exit;
05521     }
05522     /* Normal number */
05523     fig = (DBLE_FIG + BASE_FIG - 1) / BASE_FIG;
05524     ind_m = 0;
05525     mm = Min(fig, m->Prec);
05526     *d = 0.0;
05527     div = 1.;
05528     while (ind_m < mm) {
05529         div /= (double)BASE;
05530         *d = *d + (double)m->frac[ind_m++] * div;
05531     }
05532     *e = m->exponent * (SIGNED_VALUE)BASE_FIG;
05533     *d *= VpGetSign(m);
05534 
05535 Exit:
05536 #ifdef BIGDECIMAL_DEBUG
05537     if (gfDebug) {
05538         VPrint(stdout, " VpVtoD: m=%\n", m);
05539         printf("   d=%e * 10 **%ld\n", *d, *e);
05540         printf("   DBLE_FIG = %d\n", DBLE_FIG);
05541     }
05542 #endif /*BIGDECIMAL_DEBUG */
05543     return f;
05544 }
05545 
05546 /*
05547  * m <- d
05548  */
05549 VP_EXPORT void
05550 VpDtoV(Real *m, double d)
05551 {
05552     size_t ind_m, mm;
05553     SIGNED_VALUE ne;
05554     BDIGIT i;
05555     double  val, val2;
05556 
05557     if (isnan(d)) {
05558         VpSetNaN(m);
05559         goto Exit;
05560     }
05561     if (isinf(d)) {
05562         if (d > 0.0) VpSetPosInf(m);
05563         else VpSetNegInf(m);
05564         goto Exit;
05565     }
05566 
05567     if (d == 0.0) {
05568         VpSetZero(m, 1);
05569         goto Exit;
05570     }
05571     val = (d > 0.) ? d : -d;
05572     ne = 0;
05573     if (val >= 1.0) {
05574         while (val >= 1.0) {
05575             val /= (double)BASE;
05576             ++ne;
05577         }
05578     }
05579     else {
05580         val2 = 1.0 / (double)BASE;
05581         while (val < val2) {
05582             val *= (double)BASE;
05583             --ne;
05584         }
05585     }
05586     /* Now val = 0.xxxxx*BASE**ne */
05587 
05588     mm = m->MaxPrec;
05589     memset(m->frac, 0, mm * sizeof(BDIGIT));
05590     for (ind_m = 0; val > 0.0 && ind_m < mm; ind_m++) {
05591         val *= (double)BASE;
05592         i = (BDIGIT)val;
05593         val -= (double)i;
05594         m->frac[ind_m] = i;
05595     }
05596     if (ind_m >= mm) ind_m = mm - 1;
05597     VpSetSign(m, (d > 0.0) ? 1 : -1);
05598     m->Prec = ind_m + 1;
05599     m->exponent = ne;
05600 
05601     VpInternalRound(m, 0, (m->Prec > 0) ? m->frac[m->Prec-1] : 0,
05602                     (BDIGIT)(val*(double)BASE));
05603 
05604 Exit:
05605 #ifdef BIGDECIMAL_DEBUG
05606     if (gfDebug) {
05607         printf("VpDtoV d=%30.30e\n", d);
05608         VPrint(stdout, "  m=%\n", m);
05609     }
05610 #endif /* BIGDECIMAL_DEBUG */
05611     return;
05612 }
05613 
05614 /*
05615  *  m <- ival
05616  */
05617 #if 0  /* unused */
05618 VP_EXPORT void
05619 VpItoV(Real *m, SIGNED_VALUE ival)
05620 {
05621     size_t mm, ind_m;
05622     size_t val, v1, v2, v;
05623     int isign;
05624     SIGNED_VALUE ne;
05625 
05626     if (ival == 0) {
05627         VpSetZero(m, 1);
05628         goto Exit;
05629     }
05630     isign = 1;
05631     val = ival;
05632     if (ival < 0) {
05633         isign = -1;
05634         val  =(size_t)(-ival);
05635     }
05636     ne = 0;
05637     ind_m = 0;
05638     mm = m->MaxPrec;
05639     while (ind_m < mm) {
05640         m->frac[ind_m] = 0;
05641         ++ind_m;
05642     }
05643     ind_m = 0;
05644     while (val > 0) {
05645         if (val) {
05646             v1 = val;
05647             v2 = 1;
05648             while (v1 >= BASE) {
05649                 v1 /= BASE;
05650                 v2 *= BASE;
05651             }
05652             val = val - v2 * v1;
05653             v = v1;
05654         }
05655         else {
05656             v = 0;
05657         }
05658         m->frac[ind_m] = v;
05659         ++ind_m;
05660         ++ne;
05661     }
05662     m->Prec = ind_m - 1;
05663     m->exponent = ne;
05664     VpSetSign(m, isign);
05665     VpNmlz(m);
05666 
05667 Exit:
05668 #ifdef BIGDECIMAL_DEBUG
05669     if (gfDebug) {
05670         printf(" VpItoV i=%d\n", ival);
05671         VPrint(stdout, "  m=%\n", m);
05672     }
05673 #endif /* BIGDECIMAL_DEBUG */
05674     return;
05675 }
05676 #endif
05677 
05678 /*
05679  * y = SQRT(x),  y*y - x =>0
05680  */
05681 VP_EXPORT int
05682 VpSqrt(Real *y, Real *x)
05683 {
05684     Real *f = NULL;
05685     Real *r = NULL;
05686     size_t y_prec;
05687     SIGNED_VALUE n, e;
05688     SIGNED_VALUE prec;
05689     ssize_t nr;
05690     double val;
05691 
05692     /* Zero, NaN or Infinity ? */
05693     if (!VpHasVal(x)) {
05694         if (VpIsZero(x) || VpGetSign(x) > 0) {
05695             VpAsgn(y,x,1);
05696             goto Exit;
05697         }
05698         VpSetNaN(y);
05699         return VpException(VP_EXCEPTION_OP, "(VpSqrt) SQRT(NaN or negative value)", 0);
05700         goto Exit;
05701     }
05702 
05703     /* Negative ? */
05704     if (VpGetSign(x) < 0) {
05705         VpSetNaN(y);
05706         return VpException(VP_EXCEPTION_OP, "(VpSqrt) SQRT(negative value)", 0);
05707     }
05708 
05709     /* One ? */
05710     if (VpIsOne(x)) {
05711         VpSetOne(y);
05712         goto Exit;
05713     }
05714 
05715     n = (SIGNED_VALUE)y->MaxPrec;
05716     if (x->MaxPrec > (size_t)n) n = (ssize_t)x->MaxPrec;
05717 
05718     /* allocate temporally variables  */
05719     f = VpAlloc(y->MaxPrec * (BASE_FIG + 2), "#1");
05720     r = VpAlloc((n + n) * (BASE_FIG + 2), "#1");
05721 
05722     nr = 0;
05723     y_prec = y->MaxPrec;
05724 
05725     prec = x->exponent - (ssize_t)y_prec;
05726     if (x->exponent > 0)
05727         ++prec;
05728     else
05729         --prec;
05730 
05731     VpVtoD(&val, &e, x);    /* val <- x  */
05732     e /= (SIGNED_VALUE)BASE_FIG;
05733     n = e / 2;
05734     if (e - n * 2 != 0) {
05735         val /= BASE;
05736         n = (e + 1) / 2;
05737     }
05738     VpDtoV(y, sqrt(val));    /* y <- sqrt(val) */
05739     y->exponent += n;
05740     n = (SIGNED_VALUE)((DBLE_FIG + BASE_FIG - 1) / BASE_FIG);
05741     y->MaxPrec = Min((size_t)n , y_prec);
05742     f->MaxPrec = y->MaxPrec + 1;
05743     n = (SIGNED_VALUE)(y_prec * BASE_FIG);
05744     if (n < (SIGNED_VALUE)maxnr) n = (SIGNED_VALUE)maxnr;
05745     do {
05746         y->MaxPrec *= 2;
05747         if (y->MaxPrec > y_prec) y->MaxPrec = y_prec;
05748         f->MaxPrec = y->MaxPrec;
05749         VpDivd(f, r, x, y);      /* f = x/y    */
05750         VpAddSub(r, f, y, -1);   /* r = f - y  */
05751         VpMult(f, VpPt5, r);     /* f = 0.5*r  */
05752         if (VpIsZero(f))         goto converge;
05753         VpAddSub(r, f, y, 1);    /* r = y + f  */
05754         VpAsgn(y, r, 1);         /* y = r      */
05755     } while (++nr < n);
05756 
05757 #ifdef BIGDECIMAL_DEBUG
05758     if (gfDebug) {
05759         printf("ERROR(VpSqrt): did not converge within %ld iterations.\n", nr);
05760     }
05761 #endif /* BIGDECIMAL_DEBUG */
05762     y->MaxPrec = y_prec;
05763 
05764 converge:
05765     VpChangeSign(y, 1);
05766 #ifdef BIGDECIMAL_DEBUG
05767     if (gfDebug) {
05768         VpMult(r, y, y);
05769         VpAddSub(f, x, r, -1);
05770         printf("VpSqrt: iterations = %"PRIdSIZE"\n", nr);
05771         VPrint(stdout, "  y =% \n", y);
05772         VPrint(stdout, "  x =% \n", x);
05773         VPrint(stdout, "  x-y*y = % \n", f);
05774     }
05775 #endif /* BIGDECIMAL_DEBUG */
05776     y->MaxPrec = y_prec;
05777 
05778 Exit:
05779     VpFree(f);
05780     VpFree(r);
05781     return 1;
05782 }
05783 
05784 /*
05785  *
05786  * nf: digit position for operation.
05787  *
05788  */
05789 VP_EXPORT int
05790 VpMidRound(Real *y, unsigned short f, ssize_t nf)
05791 /*
05792  * Round relatively from the decimal point.
05793  *    f: rounding mode
05794  *   nf: digit location to round from the decimal point.
05795  */
05796 {
05797     /* fracf: any positive digit under rounding position? */
05798     /* fracf_1further: any positive digits under one further than the rounding position? */
05799     /* exptoadd: number of digits needed to compensate negative nf */
05800     int fracf, fracf_1further;
05801     ssize_t n,i,ix,ioffset, exptoadd;
05802     BDIGIT v, shifter;
05803     BDIGIT div;
05804 
05805     nf += y->exponent * (ssize_t)BASE_FIG;
05806     exptoadd=0;
05807     if (nf < 0) {
05808         /* rounding position too left(large). */
05809         if (f != VP_ROUND_CEIL && f != VP_ROUND_FLOOR) {
05810             VpSetZero(y, VpGetSign(y)); /* truncate everything */
05811             return 0;
05812         }
05813         exptoadd = -nf;
05814         nf = 0;
05815     }
05816 
05817     ix = nf / (ssize_t)BASE_FIG;
05818     if ((size_t)ix >= y->Prec) return 0;  /* rounding position too right(small). */
05819     v = y->frac[ix];
05820 
05821     ioffset = nf - ix*(ssize_t)BASE_FIG;
05822     n = (ssize_t)BASE_FIG - ioffset - 1;
05823     for (shifter = 1, i = 0; i < n; ++i) shifter *= 10;
05824 
05825     /* so the representation used (in y->frac) is an array of BDIGIT, where
05826        each BDIGIT contains a value between 0 and BASE-1, consisting of BASE_FIG
05827        decimal places.
05828 
05829        (that numbers of decimal places are typed as ssize_t is somewhat confusing)
05830 
05831        nf is now position (in decimal places) of the digit from the start of
05832        the array.
05833 
05834        ix is the position (in BDIGITS) of the BDIGIT containing the decimal digit,
05835        from the start of the array.
05836 
05837        v is the value of this BDIGIT
05838 
05839        ioffset is the number of extra decimal places along of this decimal digit
05840        within v.
05841 
05842        n is the number of decimal digits remaining within v after this decimal digit
05843        shifter is 10**n,
05844 
05845        v % shifter are the remaining digits within v
05846        v % (shifter * 10) are the digit together with the remaining digits within v
05847        v / shifter are the digit's predecessors together with the digit
05848        div = v / shifter / 10 is just the digit's precessors
05849        (v / shifter) - div*10 is just the digit, which is what v ends up being reassigned to.
05850        */
05851 
05852     fracf = (v % (shifter * 10) > 0);
05853     fracf_1further = ((v % shifter) > 0);
05854 
05855     v /= shifter;
05856     div = v / 10;
05857     v = v - div*10;
05858     /* now v is just the digit required.
05859        now fracf is whether the digit or any of the remaining digits within v are non-zero
05860        now fracf_1further is whether any of the remaining digits within v are non-zero
05861        */
05862 
05863     /* now check all the remaining BDIGITS for zero-ness a whole BDIGIT at a time.
05864        if we spot any non-zeroness, that means that we found a positive digit under
05865        rounding position, and we also found a positive digit under one further than
05866        the rounding position, so both searches (to see if any such non-zero digit exists)
05867        can stop */
05868 
05869     for (i = ix + 1; (size_t)i < y->Prec; i++) {
05870         if (y->frac[i] % BASE) {
05871             fracf = fracf_1further = 1;
05872             break;
05873         }
05874     }
05875 
05876     /* now fracf = does any positive digit exist under the rounding position?
05877        now fracf_1further = does any positive digit exist under one further than the
05878        rounding position?
05879        now v = the first digit under the rounding position */
05880 
05881     /* drop digits after pointed digit */
05882     memset(y->frac + ix + 1, 0, (y->Prec - (ix + 1)) * sizeof(BDIGIT));
05883 
05884     switch (f) {
05885       case VP_ROUND_DOWN: /* Truncate */
05886         break;
05887       case VP_ROUND_UP:   /* Roundup */
05888         if (fracf) ++div;
05889         break;
05890       case VP_ROUND_HALF_UP:
05891         if (v>=5) ++div;
05892         break;
05893       case VP_ROUND_HALF_DOWN:
05894         if (v > 5 || (v == 5 && fracf_1further)) ++div;
05895         break;
05896       case VP_ROUND_CEIL:
05897         if (fracf && (VpGetSign(y) > 0)) ++div;
05898         break;
05899       case VP_ROUND_FLOOR:
05900         if (fracf && (VpGetSign(y) < 0)) ++div;
05901         break;
05902       case VP_ROUND_HALF_EVEN: /* Banker's rounding */
05903         if (v > 5) ++div;
05904         else if (v == 5) {
05905             if (fracf_1further) {
05906                 ++div;
05907             }
05908             else {
05909                 if (ioffset == 0) {
05910                     /* v is the first decimal digit of its BDIGIT;
05911                        need to grab the previous BDIGIT if present
05912                        to check for evenness of the previous decimal
05913                        digit (which is same as that of the BDIGIT since
05914                        base 10 has a factor of 2) */
05915                     if (ix && (y->frac[ix-1] % 2)) ++div;
05916                 }
05917                 else {
05918                     if (div % 2) ++div;
05919                 }
05920             }
05921         }
05922         break;
05923     }
05924     for (i = 0; i <= n; ++i) div *= 10;
05925     if (div >= BASE) {
05926         if (ix) {
05927             y->frac[ix] = 0;
05928             VpRdup(y, ix);
05929         }
05930         else {
05931             short s = VpGetSign(y);
05932             SIGNED_VALUE e = y->exponent;
05933             VpSetOne(y);
05934             VpSetSign(y, s);
05935             y->exponent = e + 1;
05936         }
05937     }
05938     else {
05939         y->frac[ix] = div;
05940         VpNmlz(y);
05941     }
05942     if (exptoadd > 0) {
05943         y->exponent += (SIGNED_VALUE)(exptoadd / BASE_FIG);
05944         exptoadd %= (ssize_t)BASE_FIG;
05945         for (i = 0; i < exptoadd; i++) {
05946             y->frac[0] *= 10;
05947             if (y->frac[0] >= BASE) {
05948                 y->frac[0] /= BASE;
05949                 y->exponent++;
05950             }
05951         }
05952     }
05953     return 1;
05954 }
05955 
05956 VP_EXPORT int
05957 VpLeftRound(Real *y, unsigned short f, ssize_t nf)
05958 /*
05959  * Round from the left hand side of the digits.
05960  */
05961 {
05962     BDIGIT v;
05963     if (!VpHasVal(y)) return 0; /* Unable to round */
05964     v = y->frac[0];
05965     nf -= VpExponent(y) * (ssize_t)BASE_FIG;
05966     while ((v /= 10) != 0) nf--;
05967     nf += (ssize_t)BASE_FIG-1;
05968     return VpMidRound(y, f, nf);
05969 }
05970 
05971 VP_EXPORT int
05972 VpActiveRound(Real *y, Real *x, unsigned short f, ssize_t nf)
05973 {
05974     /* First,assign whole value in truncation mode */
05975     if (VpAsgn(y, x, 10) <= 1) return 0; /* Zero,NaN,or Infinity */
05976     return VpMidRound(y, f, nf);
05977 }
05978 
05979 static int
05980 VpLimitRound(Real *c, size_t ixDigit)
05981 {
05982     size_t ix = VpGetPrecLimit();
05983     if (!VpNmlz(c)) return -1;
05984     if (!ix)        return  0;
05985     if (!ixDigit) ixDigit = c->Prec-1;
05986     if ((ix + BASE_FIG - 1) / BASE_FIG > ixDigit + 1) return 0;
05987     return VpLeftRound(c, VpGetRoundMode(), (ssize_t)ix);
05988 }
05989 
05990 /* If I understand correctly, this is only ever used to round off the final decimal
05991    digit of precision */
05992 static void
05993 VpInternalRound(Real *c, size_t ixDigit, BDIGIT vPrev, BDIGIT v)
05994 {
05995     int f = 0;
05996 
05997     unsigned short const rounding_mode = VpGetRoundMode();
05998 
05999     if (VpLimitRound(c, ixDigit)) return;
06000     if (!v) return;
06001 
06002     v /= BASE1;
06003     switch (rounding_mode) {
06004       case VP_ROUND_DOWN:
06005         break;
06006       case VP_ROUND_UP:
06007         if (v) f = 1;
06008         break;
06009       case VP_ROUND_HALF_UP:
06010         if (v >= 5) f = 1;
06011         break;
06012       case VP_ROUND_HALF_DOWN:
06013         /* this is ok - because this is the last digit of precision,
06014            the case where v == 5 and some further digits are nonzero
06015            will never occur */
06016         if (v >= 6) f = 1;
06017         break;
06018       case VP_ROUND_CEIL:
06019         if (v && (VpGetSign(c) > 0)) f = 1;
06020         break;
06021       case VP_ROUND_FLOOR:
06022         if (v && (VpGetSign(c) < 0)) f = 1;
06023         break;
06024       case VP_ROUND_HALF_EVEN:  /* Banker's rounding */
06025         /* as per VP_ROUND_HALF_DOWN, because this is the last digit of precision,
06026            there is no case to worry about where v == 5 and some further digits are nonzero */
06027         if (v > 5) f = 1;
06028         else if (v == 5 && vPrev % 2) f = 1;
06029         break;
06030     }
06031     if (f) {
06032         VpRdup(c, ixDigit);
06033         VpNmlz(c);
06034     }
06035 }
06036 
06037 /*
06038  *  Rounds up m(plus one to final digit of m).
06039  */
06040 static int
06041 VpRdup(Real *m, size_t ind_m)
06042 {
06043     BDIGIT carry;
06044 
06045     if (!ind_m) ind_m = m->Prec;
06046 
06047     carry = 1;
06048     while (carry > 0 && ind_m--) {
06049         m->frac[ind_m] += carry;
06050         if (m->frac[ind_m] >= BASE) m->frac[ind_m] -= BASE;
06051         else                        carry = 0;
06052     }
06053     if (carry > 0) { /* Overflow,count exponent and set fraction part be 1  */
06054         if (!AddExponent(m, 1)) return 0;
06055         m->Prec = m->frac[0] = 1;
06056     }
06057     else {
06058         VpNmlz(m);
06059     }
06060     return 1;
06061 }
06062 
06063 /*
06064  *  y = x - fix(x)
06065  */
06066 VP_EXPORT void
06067 VpFrac(Real *y, Real *x)
06068 {
06069     size_t my, ind_y, ind_x;
06070 
06071     if (!VpHasVal(x)) {
06072         VpAsgn(y, x, 1);
06073         goto Exit;
06074     }
06075 
06076     if (x->exponent > 0 && (size_t)x->exponent >= x->Prec) {
06077         VpSetZero(y, VpGetSign(x));
06078         goto Exit;
06079     }
06080     else if (x->exponent <= 0) {
06081         VpAsgn(y, x, 1);
06082         goto Exit;
06083     }
06084 
06085     /* satisfy: x->exponent > 0 */
06086 
06087     y->Prec = x->Prec - (size_t)x->exponent;
06088     y->Prec = Min(y->Prec, y->MaxPrec);
06089     y->exponent = 0;
06090     VpSetSign(y, VpGetSign(x));
06091     ind_y = 0;
06092     my = y->Prec;
06093     ind_x = x->exponent;
06094     while (ind_y < my) {
06095         y->frac[ind_y] = x->frac[ind_x];
06096         ++ind_y;
06097         ++ind_x;
06098     }
06099     VpNmlz(y);
06100 
06101 Exit:
06102 #ifdef BIGDECIMAL_DEBUG
06103     if (gfDebug) {
06104         VPrint(stdout, "VpFrac y=%\n", y);
06105         VPrint(stdout, "    x=%\n", x);
06106     }
06107 #endif /* BIGDECIMAL_DEBUG */
06108     return;
06109 }
06110 
06111 /*
06112  *   y = x ** n
06113  */
06114 VP_EXPORT int
06115 VpPower(Real *y, Real *x, SIGNED_VALUE n)
06116 {
06117     size_t s, ss;
06118     ssize_t sign;
06119     Real *w1 = NULL;
06120     Real *w2 = NULL;
06121 
06122     if (VpIsZero(x)) {
06123         if (n == 0) {
06124             VpSetOne(y);
06125             goto Exit;
06126         }
06127         sign = VpGetSign(x);
06128         if (n < 0) {
06129             n = -n;
06130             if (sign < 0) sign = (n % 2) ? -1 : 1;
06131             VpSetInf(y, sign);
06132         }
06133         else {
06134             if (sign < 0) sign = (n % 2) ? -1 : 1;
06135             VpSetZero(y,sign);
06136         }
06137         goto Exit;
06138     }
06139     if (VpIsNaN(x)) {
06140         VpSetNaN(y);
06141         goto Exit;
06142     }
06143     if (VpIsInf(x)) {
06144         if (n == 0) {
06145             VpSetOne(y);
06146             goto Exit;
06147         }
06148         if (n > 0) {
06149             VpSetInf(y, (n % 2 == 0 || VpIsPosInf(x)) ? 1 : -1);
06150             goto Exit;
06151         }
06152         VpSetZero(y, (n % 2 == 0 || VpIsPosInf(x)) ? 1 : -1);
06153         goto Exit;
06154     }
06155 
06156     if (x->exponent == 1 && x->Prec == 1 && x->frac[0] == 1) {
06157         /* abs(x) = 1 */
06158         VpSetOne(y);
06159         if (VpGetSign(x) > 0) goto Exit;
06160         if ((n % 2) == 0) goto Exit;
06161         VpSetSign(y, -1);
06162         goto Exit;
06163     }
06164 
06165     if (n > 0) sign = 1;
06166     else if (n < 0) {
06167         sign = -1;
06168         n = -n;
06169     }
06170     else {
06171         VpSetOne(y);
06172         goto Exit;
06173     }
06174 
06175     /* Allocate working variables  */
06176 
06177     w1 = VpAlloc((y->MaxPrec + 2) * BASE_FIG, "#0");
06178     w2 = VpAlloc((w1->MaxPrec * 2 + 1) * BASE_FIG, "#0");
06179     /* calculation start */
06180 
06181     VpAsgn(y, x, 1);
06182     --n;
06183     while (n > 0) {
06184         VpAsgn(w1, x, 1);
06185         s = 1;
06186         while (ss = s, (s += s) <= (size_t)n) {
06187             VpMult(w2, w1, w1);
06188             VpAsgn(w1, w2, 1);
06189         }
06190         n -= (SIGNED_VALUE)ss;
06191         VpMult(w2, y, w1);
06192         VpAsgn(y, w2, 1);
06193     }
06194     if (sign < 0) {
06195         VpDivd(w1, w2, VpConstOne, y);
06196         VpAsgn(y, w1, 1);
06197     }
06198 
06199 Exit:
06200 #ifdef BIGDECIMAL_DEBUG
06201     if (gfDebug) {
06202         VPrint(stdout, "VpPower y=%\n", y);
06203         VPrint(stdout, "VpPower x=%\n", x);
06204         printf("  n=%d\n", n);
06205     }
06206 #endif /* BIGDECIMAL_DEBUG */
06207     VpFree(w2);
06208     VpFree(w1);
06209     return 1;
06210 }
06211 
06212 #ifdef BIGDECIMAL_DEBUG
06213 int
06214 VpVarCheck(Real * v)
06215 /*
06216  * Checks the validity of the Real variable v.
06217  * [Input]
06218  *   v ... Real *, variable to be checked.
06219  * [Returns]
06220  *   0  ... correct v.
06221  *   other ... error
06222  */
06223 {
06224     size_t i;
06225 
06226     if (v->MaxPrec == 0) {
06227         printf("ERROR(VpVarCheck): Illegal Max. Precision(=%"PRIuSIZE")\n",
06228                v->MaxPrec);
06229         return 1;
06230     }
06231     if (v->Prec == 0 || v->Prec > v->MaxPrec) {
06232         printf("ERROR(VpVarCheck): Illegal Precision(=%"PRIuSIZE")\n", v->Prec);
06233         printf("       Max. Prec.=%"PRIuSIZE"\n", v->MaxPrec);
06234         return 2;
06235     }
06236     for (i = 0; i < v->Prec; ++i) {
06237         if (v->frac[i] >= BASE) {
06238             printf("ERROR(VpVarCheck): Illegal fraction\n");
06239             printf("       Frac[%"PRIuSIZE"]=%lu\n", i, v->frac[i]);
06240             printf("       Prec.   =%"PRIuSIZE"\n", v->Prec);
06241             printf("       Exp. =%"PRIdVALUE"\n", v->exponent);
06242             printf("       BASE =%lu\n", BASE);
06243             return 3;
06244         }
06245     }
06246     return 0;
06247 }
06248 #endif /* BIGDECIMAL_DEBUG */
06249 

Generated on 19 Jul 2016 for Ruby by  doxygen 1.4.7