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