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