1/* 2 * 3 * Ruby BigDecimal(Variable decimal precision) extension library. 4 * 5 * Copyright(C) 2002 by Shigeo Kobayashi(shigeo@tinyforest.gr.jp) 6 * 7 * You may distribute under the terms of either the GNU General Public 8 * License or the Artistic License, as specified in the README file 9 * of this BigDecimal distribution. 10 * 11 * NOTES: 12 * 2003-03-28 V1.0 checked in. 13 * 14 */ 15 16#ifndef RUBY_BIG_DECIMAL_H 17#define RUBY_BIG_DECIMAL_H 1 18 19#include "ruby/ruby.h" 20#include <float.h> 21 22#if defined(__cplusplus) 23extern "C" { 24#if 0 25} /* satisfy cc-mode */ 26#endif 27#endif 28 29#ifndef HAVE_LABS 30static inline long 31labs(long const x) 32{ 33 if (x < 0) return -x; 34 return x; 35} 36#endif 37 38#ifndef HAVE_LLABS 39static inline LONG_LONG 40llabs(LONG_LONG const x) 41{ 42 if (x < 0) return -x; 43 return x; 44} 45#endif 46 47#ifdef vabs 48# undef vabs 49#endif 50#if SIZEOF_VALUE <= SIZEOF_INT 51# define vabs abs 52#elif SIZEOF_VALUE <= SIZEOF_LONG 53# define vabs labs 54#elif SIZEOF_VALUE <= SIZEOF_LONG_LONG 55# define vabs llabs 56#endif 57 58extern VALUE rb_cBigDecimal; 59 60#if 0 || SIZEOF_BDIGITS >= 16 61# define RMPD_COMPONENT_FIGURES 38 62# define RMPD_BASE ((BDIGIT)100000000000000000000000000000000000000U) 63#elif SIZEOF_BDIGITS >= 8 64# define RMPD_COMPONENT_FIGURES 19 65# define RMPD_BASE ((BDIGIT)10000000000000000000U) 66#elif SIZEOF_BDIGITS >= 4 67# define RMPD_COMPONENT_FIGURES 9 68# define RMPD_BASE ((BDIGIT)1000000000U) 69#elif SIZEOF_BDIGITS >= 2 70# define RMPD_COMPONENT_FIGURES 4 71# define RMPD_BASE ((BDIGIT)10000U) 72#else 73# define RMPD_COMPONENT_FIGURES 2 74# define RMPD_BASE ((BDIGIT)100U) 75#endif 76 77 78/* 79 * NaN & Infinity 80 */ 81#define SZ_NaN "NaN" 82#define SZ_INF "Infinity" 83#define SZ_PINF "+Infinity" 84#define SZ_NINF "-Infinity" 85 86/* 87 * #define VP_EXPORT other than static to let VP_ routines 88 * be called from outside of this module. 89 */ 90#define VP_EXPORT static 91 92/* Exception codes */ 93#define VP_EXCEPTION_ALL ((unsigned short)0x00FF) 94#define VP_EXCEPTION_INFINITY ((unsigned short)0x0001) 95#define VP_EXCEPTION_NaN ((unsigned short)0x0002) 96#define VP_EXCEPTION_UNDERFLOW ((unsigned short)0x0004) 97#define VP_EXCEPTION_OVERFLOW ((unsigned short)0x0001) /* 0x0008) */ 98#define VP_EXCEPTION_ZERODIVIDE ((unsigned short)0x0010) 99 100/* Following 2 exceptions cann't controlled by user */ 101#define VP_EXCEPTION_OP ((unsigned short)0x0020) 102#define VP_EXCEPTION_MEMORY ((unsigned short)0x0040) 103 104#define RMPD_EXCEPTION_MODE_DEFAULT 0U 105 106/* Computation mode */ 107#define VP_ROUND_MODE ((unsigned short)0x0100) 108#define VP_ROUND_UP 1 109#define VP_ROUND_DOWN 2 110#define VP_ROUND_HALF_UP 3 111#define VP_ROUND_HALF_DOWN 4 112#define VP_ROUND_CEIL 5 113#define VP_ROUND_FLOOR 6 114#define VP_ROUND_HALF_EVEN 7 115 116#define RMPD_ROUNDING_MODE_DEFAULT VP_ROUND_HALF_UP 117 118#define VP_SIGN_NaN 0 /* NaN */ 119#define VP_SIGN_POSITIVE_ZERO 1 /* Positive zero */ 120#define VP_SIGN_NEGATIVE_ZERO -1 /* Negative zero */ 121#define VP_SIGN_POSITIVE_FINITE 2 /* Positive finite number */ 122#define VP_SIGN_NEGATIVE_FINITE -2 /* Negative finite number */ 123#define VP_SIGN_POSITIVE_INFINITE 3 /* Positive infinite number */ 124#define VP_SIGN_NEGATIVE_INFINITE -3 /* Negative infinite number */ 125 126#ifdef __GNUC__ 127#define FLEXIBLE_ARRAY_SIZE 0 128#else 129#define FLEXIBLE_ARRAY_SIZE 1 130#endif 131 132/* 133 * VP representation 134 * r = 0.xxxxxxxxx *BASE**exponent 135 */ 136typedef struct { 137 VALUE obj; /* Back pointer(VALUE) for Ruby object. */ 138 size_t MaxPrec; /* Maximum precision size */ 139 /* This is the actual size of pfrac[] */ 140 /*(frac[0] to frac[MaxPrec] are available). */ 141 size_t Prec; /* Current precision size. */ 142 /* This indicates how much the. */ 143 /* the array frac[] is actually used. */ 144 SIGNED_VALUE exponent; /* Exponent part. */ 145 short sign; /* Attributes of the value. */ 146 /* 147 * ==0 : NaN 148 * 1 : Positive zero 149 * -1 : Negative zero 150 * 2 : Positive number 151 * -2 : Negative number 152 * 3 : Positive infinite number 153 * -3 : Negative infinite number 154 */ 155 short flag; /* Not used in vp_routines,space for user. */ 156 BDIGIT frac[FLEXIBLE_ARRAY_SIZE]; /* Array of fraction part. */ 157} Real; 158 159/* 160 * ------------------ 161 * EXPORTables. 162 * ------------------ 163 */ 164 165VP_EXPORT Real * 166VpNewRbClass(size_t mx, char const *str, VALUE klass); 167 168VP_EXPORT Real *VpCreateRbObject(size_t mx,const char *str); 169 170static inline BDIGIT 171rmpd_base_value(void) { return RMPD_BASE; } 172static inline size_t 173rmpd_component_figures(void) { return RMPD_COMPONENT_FIGURES; } 174static inline size_t 175rmpd_double_figures(void) { return 1+DBL_DIG; } 176 177#define VpBaseFig() rmpd_component_figures() 178#define VpDblFig() rmpd_double_figures() 179#define VpBaseVal() rmpd_base_value() 180 181/* Zero,Inf,NaN (isinf(),isnan() used to check) */ 182VP_EXPORT double VpGetDoubleNaN(void); 183VP_EXPORT double VpGetDoublePosInf(void); 184VP_EXPORT double VpGetDoubleNegInf(void); 185VP_EXPORT double VpGetDoubleNegZero(void); 186 187/* These 2 functions added at v1.1.7 */ 188VP_EXPORT size_t VpGetPrecLimit(void); 189VP_EXPORT size_t VpSetPrecLimit(size_t n); 190 191/* Round mode */ 192VP_EXPORT int VpIsRoundMode(unsigned short n); 193VP_EXPORT unsigned short VpGetRoundMode(void); 194VP_EXPORT unsigned short VpSetRoundMode(unsigned short n); 195 196VP_EXPORT int VpException(unsigned short f,const char *str,int always); 197#if 0 /* unused */ 198VP_EXPORT int VpIsNegDoubleZero(double v); 199#endif 200VP_EXPORT size_t VpNumOfChars(Real *vp,const char *pszFmt); 201VP_EXPORT size_t VpInit(BDIGIT BaseVal); 202VP_EXPORT void *VpMemAlloc(size_t mb); 203VP_EXPORT void *VpMemRealloc(void *ptr, size_t mb); 204VP_EXPORT void VpFree(Real *pv); 205VP_EXPORT Real *VpAlloc(size_t mx, const char *szVal); 206VP_EXPORT size_t VpAsgn(Real *c, Real *a, int isw); 207VP_EXPORT size_t VpAddSub(Real *c,Real *a,Real *b,int operation); 208VP_EXPORT size_t VpMult(Real *c,Real *a,Real *b); 209VP_EXPORT size_t VpDivd(Real *c,Real *r,Real *a,Real *b); 210VP_EXPORT int VpComp(Real *a,Real *b); 211VP_EXPORT ssize_t VpExponent10(Real *a); 212VP_EXPORT void VpSzMantissa(Real *a,char *psz); 213VP_EXPORT int VpToSpecialString(Real *a,char *psz,int fPlus); 214VP_EXPORT void VpToString(Real *a, char *psz, size_t fFmt, int fPlus); 215VP_EXPORT void VpToFString(Real *a, char *psz, size_t fFmt, int fPlus); 216VP_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); 217VP_EXPORT int VpVtoD(double *d, SIGNED_VALUE *e, Real *m); 218VP_EXPORT void VpDtoV(Real *m,double d); 219#if 0 /* unused */ 220VP_EXPORT void VpItoV(Real *m,S_INT ival); 221#endif 222VP_EXPORT int VpSqrt(Real *y,Real *x); 223VP_EXPORT int VpActiveRound(Real *y, Real *x, unsigned short f, ssize_t il); 224VP_EXPORT int VpMidRound(Real *y, unsigned short f, ssize_t nf); 225VP_EXPORT int VpLeftRound(Real *y, unsigned short f, ssize_t nf); 226VP_EXPORT void VpFrac(Real *y, Real *x); 227VP_EXPORT int VpPower(Real *y, Real *x, SIGNED_VALUE n); 228 229/* VP constants */ 230VP_EXPORT Real *VpOne(void); 231 232/* 233 * ------------------ 234 * MACRO definitions. 235 * ------------------ 236 */ 237#define Abs(a) (((a)>= 0)?(a):(-(a))) 238#define Max(a, b) (((a)>(b))?(a):(b)) 239#define Min(a, b) (((a)>(b))?(b):(a)) 240 241#define VpMaxPrec(a) ((a)->MaxPrec) 242#define VpPrec(a) ((a)->Prec) 243#define VpGetFlag(a) ((a)->flag) 244 245/* Sign */ 246 247/* VpGetSign(a) returns 1,-1 if a>0,a<0 respectively */ 248#define VpGetSign(a) (((a)->sign>0)?1:(-1)) 249/* Change sign of a to a>0,a<0 if s = 1,-1 respectively */ 250#define VpChangeSign(a,s) {if((s)>0) (a)->sign=(short)Abs((ssize_t)(a)->sign);else (a)->sign=-(short)Abs((ssize_t)(a)->sign);} 251/* Sets sign of a to a>0,a<0 if s = 1,-1 respectively */ 252#define VpSetSign(a,s) {if((s)>0) (a)->sign=(short)VP_SIGN_POSITIVE_FINITE;else (a)->sign=(short)VP_SIGN_NEGATIVE_FINITE;} 253 254/* 1 */ 255#define VpSetOne(a) {(a)->Prec=(a)->exponent=(a)->frac[0]=1;(a)->sign=VP_SIGN_POSITIVE_FINITE;} 256 257/* ZEROs */ 258#define VpIsPosZero(a) ((a)->sign==VP_SIGN_POSITIVE_ZERO) 259#define VpIsNegZero(a) ((a)->sign==VP_SIGN_NEGATIVE_ZERO) 260#define VpIsZero(a) (VpIsPosZero(a) || VpIsNegZero(a)) 261#define VpSetPosZero(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_POSITIVE_ZERO) 262#define VpSetNegZero(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_NEGATIVE_ZERO) 263#define VpSetZero(a,s) ( ((s)>0)?VpSetPosZero(a):VpSetNegZero(a) ) 264 265/* NaN */ 266#define VpIsNaN(a) ((a)->sign==VP_SIGN_NaN) 267#define VpSetNaN(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_NaN) 268 269/* Infinity */ 270#define VpIsPosInf(a) ((a)->sign==VP_SIGN_POSITIVE_INFINITE) 271#define VpIsNegInf(a) ((a)->sign==VP_SIGN_NEGATIVE_INFINITE) 272#define VpIsInf(a) (VpIsPosInf(a) || VpIsNegInf(a)) 273#define VpIsDef(a) ( !(VpIsNaN(a)||VpIsInf(a)) ) 274#define VpSetPosInf(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_POSITIVE_INFINITE) 275#define VpSetNegInf(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_NEGATIVE_INFINITE) 276#define VpSetInf(a,s) ( ((s)>0)?VpSetPosInf(a):VpSetNegInf(a) ) 277#define VpHasVal(a) (a->frac[0]) 278#define VpIsOne(a) ((a->Prec==1)&&(a->frac[0]==1)&&(a->exponent==1)) 279#define VpExponent(a) (a->exponent) 280#ifdef BIGDECIMAL_DEBUG 281int VpVarCheck(Real * v); 282VP_EXPORT int VPrint(FILE *fp,const char *cntl_chr,Real *a); 283#endif /* BIGDECIMAL_DEBUG */ 284 285#if defined(__cplusplus) 286#if 0 287{ /* satisfy cc-mode */ 288#endif 289} /* extern "C" { */ 290#endif 291#endif /* RUBY_BIG_DECIMAL_H */ 292