Ruby 1.9.3p327(2012-11-10revision37606)
|
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 * NOTES: 00012 * 2003-03-28 V1.0 checked in. 00013 * 00014 */ 00015 00016 #ifndef RUBY_BIG_DECIMAL_H 00017 #define RUBY_BIG_DECIMAL_H 1 00018 00019 #include "ruby/ruby.h" 00020 #include <float.h> 00021 00022 #if defined(__cplusplus) 00023 extern "C" { 00024 #endif 00025 00026 #ifndef HAVE_LABS 00027 static inline long 00028 labs(long const x) 00029 { 00030 if (x < 0) return -x; 00031 return x; 00032 } 00033 #endif 00034 00035 #ifndef HAVE_LLABS 00036 static inline LONG_LONG 00037 llabs(LONG_LONG const x) 00038 { 00039 if (x < 0) return -x; 00040 return x; 00041 } 00042 #endif 00043 00044 #ifdef vabs 00045 # undef vabs 00046 #endif 00047 #if SIZEOF_VALUE <= SIZEOF_INT 00048 # define vabs abs 00049 #elif SIZEOF_VALUE <= SIZEOF_LONG 00050 # define vabs labs 00051 #elif SIZEOF_VALUE <= SIZEOF_LONG_LONG 00052 # define vabs llabs 00053 #endif 00054 00055 extern VALUE rb_cBigDecimal; 00056 00057 #if 0 || SIZEOF_BDIGITS >= 16 00058 # define RMPD_COMPONENT_FIGURES 38 00059 # define RMPD_BASE ((BDIGIT)100000000000000000000000000000000000000U) 00060 #elif SIZEOF_BDIGITS >= 8 00061 # define RMPD_COMPONENT_FIGURES 19 00062 # define RMPD_BASE ((BDIGIT)10000000000000000000U) 00063 #elif SIZEOF_BDIGITS >= 4 00064 # define RMPD_COMPONENT_FIGURES 9 00065 # define RMPD_BASE ((BDIGIT)1000000000U) 00066 #elif SIZEOF_BDIGITS >= 2 00067 # define RMPD_COMPONENT_FIGURES 4 00068 # define RMPD_BASE ((BDIGIT)10000U) 00069 #else 00070 # define RMPD_COMPONENT_FIGURES 2 00071 # define RMPD_BASE ((BDIGIT)100U) 00072 #endif 00073 00074 00075 /* 00076 * NaN & Infinity 00077 */ 00078 #define SZ_NaN "NaN" 00079 #define SZ_INF "Infinity" 00080 #define SZ_PINF "+Infinity" 00081 #define SZ_NINF "-Infinity" 00082 00083 /* 00084 * #define VP_EXPORT other than static to let VP_ routines 00085 * be called from outside of this module. 00086 */ 00087 #define VP_EXPORT static 00088 00089 /* Exception codes */ 00090 #define VP_EXCEPTION_ALL ((unsigned short)0x00FF) 00091 #define VP_EXCEPTION_INFINITY ((unsigned short)0x0001) 00092 #define VP_EXCEPTION_NaN ((unsigned short)0x0002) 00093 #define VP_EXCEPTION_UNDERFLOW ((unsigned short)0x0004) 00094 #define VP_EXCEPTION_OVERFLOW ((unsigned short)0x0001) /* 0x0008) */ 00095 #define VP_EXCEPTION_ZERODIVIDE ((unsigned short)0x0010) 00096 00097 /* Following 2 exceptions cann't controlled by user */ 00098 #define VP_EXCEPTION_OP ((unsigned short)0x0020) 00099 #define VP_EXCEPTION_MEMORY ((unsigned short)0x0040) 00100 00101 #define RMPD_EXCEPTION_MODE_DEFAULT 0U 00102 00103 /* Computation mode */ 00104 #define VP_ROUND_MODE ((unsigned short)0x0100) 00105 #define VP_ROUND_UP 1 00106 #define VP_ROUND_DOWN 2 00107 #define VP_ROUND_HALF_UP 3 00108 #define VP_ROUND_HALF_DOWN 4 00109 #define VP_ROUND_CEIL 5 00110 #define VP_ROUND_FLOOR 6 00111 #define VP_ROUND_HALF_EVEN 7 00112 00113 #define RMPD_ROUNDING_MODE_DEFAULT VP_ROUND_HALF_UP 00114 00115 #define VP_SIGN_NaN 0 /* NaN */ 00116 #define VP_SIGN_POSITIVE_ZERO 1 /* Positive zero */ 00117 #define VP_SIGN_NEGATIVE_ZERO -1 /* Negative zero */ 00118 #define VP_SIGN_POSITIVE_FINITE 2 /* Positive finite number */ 00119 #define VP_SIGN_NEGATIVE_FINITE -2 /* Negative finite number */ 00120 #define VP_SIGN_POSITIVE_INFINITE 3 /* Positive infinite number */ 00121 #define VP_SIGN_NEGATIVE_INFINITE -3 /* Negative infinite number */ 00122 00123 /* 00124 * VP representation 00125 * r = 0.xxxxxxxxx *BASE**exponent 00126 */ 00127 typedef struct { 00128 VALUE obj; /* Back pointer(VALUE) for Ruby object. */ 00129 size_t MaxPrec; /* Maximum precision size */ 00130 /* This is the actual size of pfrac[] */ 00131 /*(frac[0] to frac[MaxPrec] are available). */ 00132 size_t Prec; /* Current precision size. */ 00133 /* This indicates how much the. */ 00134 /* the array frac[] is actually used. */ 00135 SIGNED_VALUE exponent; /* Exponent part. */ 00136 short sign; /* Attributes of the value. */ 00137 /* 00138 * ==0 : NaN 00139 * 1 : Positive zero 00140 * -1 : Negative zero 00141 * 2 : Positive number 00142 * -2 : Negative number 00143 * 3 : Positive infinite number 00144 * -3 : Negative infinite number 00145 */ 00146 short flag; /* Not used in vp_routines,space for user. */ 00147 BDIGIT frac[1]; /* Pointer to array of fraction part. */ 00148 } Real; 00149 00150 /* 00151 * ------------------ 00152 * EXPORTables. 00153 * ------------------ 00154 */ 00155 00156 VP_EXPORT Real * 00157 VpNewRbClass(size_t mx, char const *str, VALUE klass); 00158 00159 VP_EXPORT Real *VpCreateRbObject(size_t mx,const char *str); 00160 00161 static inline BDIGIT 00162 rmpd_base_value(void) { return RMPD_BASE; } 00163 static inline size_t 00164 rmpd_component_figures(void) { return RMPD_COMPONENT_FIGURES; } 00165 static inline size_t 00166 rmpd_double_figures(void) { return 1+DBL_DIG; } 00167 00168 #define VpBaseFig() rmpd_component_figures() 00169 #define VpDblFig() rmpd_double_figures() 00170 #define VpBaseVal() rmpd_base_value() 00171 00172 /* Zero,Inf,NaN (isinf(),isnan() used to check) */ 00173 VP_EXPORT double VpGetDoubleNaN(void); 00174 VP_EXPORT double VpGetDoublePosInf(void); 00175 VP_EXPORT double VpGetDoubleNegInf(void); 00176 VP_EXPORT double VpGetDoubleNegZero(void); 00177 00178 /* These 2 functions added at v1.1.7 */ 00179 VP_EXPORT size_t VpGetPrecLimit(void); 00180 VP_EXPORT size_t VpSetPrecLimit(size_t n); 00181 00182 /* Round mode */ 00183 VP_EXPORT int VpIsRoundMode(unsigned short n); 00184 VP_EXPORT unsigned short VpGetRoundMode(void); 00185 VP_EXPORT unsigned short VpSetRoundMode(unsigned short n); 00186 00187 VP_EXPORT int VpException(unsigned short f,const char *str,int always); 00188 #if 0 /* unused */ 00189 VP_EXPORT int VpIsNegDoubleZero(double v); 00190 #endif 00191 VP_EXPORT size_t VpNumOfChars(Real *vp,const char *pszFmt); 00192 VP_EXPORT size_t VpInit(BDIGIT BaseVal); 00193 VP_EXPORT void *VpMemAlloc(size_t mb); 00194 VP_EXPORT void VpFree(Real *pv); 00195 VP_EXPORT Real *VpAlloc(size_t mx, const char *szVal); 00196 VP_EXPORT size_t VpAsgn(Real *c, Real *a, int isw); 00197 VP_EXPORT size_t VpAddSub(Real *c,Real *a,Real *b,int operation); 00198 VP_EXPORT size_t VpMult(Real *c,Real *a,Real *b); 00199 VP_EXPORT size_t VpDivd(Real *c,Real *r,Real *a,Real *b); 00200 VP_EXPORT int VpComp(Real *a,Real *b); 00201 VP_EXPORT ssize_t VpExponent10(Real *a); 00202 VP_EXPORT void VpSzMantissa(Real *a,char *psz); 00203 VP_EXPORT int VpToSpecialString(Real *a,char *psz,int fPlus); 00204 VP_EXPORT void VpToString(Real *a, char *psz, size_t fFmt, int fPlus); 00205 VP_EXPORT void VpToFString(Real *a, char *psz, size_t fFmt, int fPlus); 00206 VP_EXPORT int VpCtoV(Real *a, const char *int_chr, size_t ni, const char *frac, size_t nf, const char *exp_chr, size_t ne); 00207 VP_EXPORT int VpVtoD(double *d, SIGNED_VALUE *e, Real *m); 00208 VP_EXPORT void VpDtoV(Real *m,double d); 00209 #if 0 /* unused */ 00210 VP_EXPORT void VpItoV(Real *m,S_INT ival); 00211 #endif 00212 VP_EXPORT int VpSqrt(Real *y,Real *x); 00213 VP_EXPORT int VpActiveRound(Real *y, Real *x, unsigned short f, ssize_t il); 00214 VP_EXPORT int VpMidRound(Real *y, unsigned short f, ssize_t nf); 00215 VP_EXPORT int VpLeftRound(Real *y, unsigned short f, ssize_t nf); 00216 VP_EXPORT void VpFrac(Real *y, Real *x); 00217 VP_EXPORT int VpPower(Real *y, Real *x, SIGNED_VALUE n); 00218 00219 /* VP constants */ 00220 VP_EXPORT Real *VpOne(void); 00221 00222 /* 00223 * ------------------ 00224 * MACRO definitions. 00225 * ------------------ 00226 */ 00227 #define Abs(a) (((a)>= 0)?(a):(-(a))) 00228 #define Max(a, b) (((a)>(b))?(a):(b)) 00229 #define Min(a, b) (((a)>(b))?(b):(a)) 00230 00231 #define VpMaxPrec(a) ((a)->MaxPrec) 00232 #define VpPrec(a) ((a)->Prec) 00233 #define VpGetFlag(a) ((a)->flag) 00234 00235 /* Sign */ 00236 00237 /* VpGetSign(a) returns 1,-1 if a>0,a<0 respectively */ 00238 #define VpGetSign(a) (((a)->sign>0)?1:(-1)) 00239 /* Change sign of a to a>0,a<0 if s = 1,-1 respectively */ 00240 #define VpChangeSign(a,s) {if((s)>0) (a)->sign=(short)Abs((ssize_t)(a)->sign);else (a)->sign=-(short)Abs((ssize_t)(a)->sign);} 00241 /* Sets sign of a to a>0,a<0 if s = 1,-1 respectively */ 00242 #define VpSetSign(a,s) {if((s)>0) (a)->sign=(short)VP_SIGN_POSITIVE_FINITE;else (a)->sign=(short)VP_SIGN_NEGATIVE_FINITE;} 00243 00244 /* 1 */ 00245 #define VpSetOne(a) {(a)->Prec=(a)->exponent=(a)->frac[0]=1;(a)->sign=VP_SIGN_POSITIVE_FINITE;} 00246 00247 /* ZEROs */ 00248 #define VpIsPosZero(a) ((a)->sign==VP_SIGN_POSITIVE_ZERO) 00249 #define VpIsNegZero(a) ((a)->sign==VP_SIGN_NEGATIVE_ZERO) 00250 #define VpIsZero(a) (VpIsPosZero(a) || VpIsNegZero(a)) 00251 #define VpSetPosZero(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_POSITIVE_ZERO) 00252 #define VpSetNegZero(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_NEGATIVE_ZERO) 00253 #define VpSetZero(a,s) ( ((s)>0)?VpSetPosZero(a):VpSetNegZero(a) ) 00254 00255 /* NaN */ 00256 #define VpIsNaN(a) ((a)->sign==VP_SIGN_NaN) 00257 #define VpSetNaN(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_NaN) 00258 00259 /* Infinity */ 00260 #define VpIsPosInf(a) ((a)->sign==VP_SIGN_POSITIVE_INFINITE) 00261 #define VpIsNegInf(a) ((a)->sign==VP_SIGN_NEGATIVE_INFINITE) 00262 #define VpIsInf(a) (VpIsPosInf(a) || VpIsNegInf(a)) 00263 #define VpIsDef(a) ( !(VpIsNaN(a)||VpIsInf(a)) ) 00264 #define VpSetPosInf(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_POSITIVE_INFINITE) 00265 #define VpSetNegInf(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_NEGATIVE_INFINITE) 00266 #define VpSetInf(a,s) ( ((s)>0)?VpSetPosInf(a):VpSetNegInf(a) ) 00267 #define VpHasVal(a) (a->frac[0]) 00268 #define VpIsOne(a) ((a->Prec==1)&&(a->frac[0]==1)&&(a->exponent==1)) 00269 #define VpExponent(a) (a->exponent) 00270 #ifdef BIGDECIMAL_DEBUG 00271 int VpVarCheck(Real * v); 00272 VP_EXPORT int VPrint(FILE *fp,const char *cntl_chr,Real *a); 00273 #endif /* BIGDECIMAL_DEBUG */ 00274 00275 #if defined(__cplusplus) 00276 } /* extern "C" { */ 00277 #endif 00278 #endif /* RUBY_BIG_DECIMAL_H */ 00279