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