bigdecimal 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,396 @@
1
+ /*
2
+ *
3
+ * Ruby BigDecimal(Variable decimal precision) extension library.
4
+ *
5
+ * Copyright(C) 2002 by Shigeo Kobayashi(shigeo@tinyforest.gr.jp)
6
+ *
7
+ */
8
+
9
+ #ifndef RUBY_BIG_DECIMAL_H
10
+ #define RUBY_BIG_DECIMAL_H 1
11
+
12
+ #define RUBY_NO_OLD_COMPATIBILITY
13
+
14
+ #include "ruby/ruby.h"
15
+ #include <float.h>
16
+
17
+ #ifndef RB_UNUSED_VAR
18
+ # ifdef __GNUC__
19
+ # define RB_UNUSED_VAR(x) x __attribute__ ((unused))
20
+ # else
21
+ # define RB_UNUSED_VAR(x) x
22
+ # endif
23
+ #endif
24
+
25
+ #ifndef UNREACHABLE
26
+ # define UNREACHABLE /* unreachable */
27
+ #endif
28
+
29
+ #undef BDIGIT
30
+ #undef SIZEOF_BDIGITS
31
+ #undef BDIGIT_DBL
32
+ #undef BDIGIT_DBL_SIGNED
33
+ #undef PRI_BDIGIT_PREFIX
34
+ #undef PRI_BDIGIT_DBL_PREFIX
35
+
36
+ #ifdef HAVE_INT64_T
37
+ # define BDIGIT uint32_t
38
+ # define BDIGIT_DBL uint64_t
39
+ # define BDIGIT_DBL_SIGNED int64_t
40
+ # define SIZEOF_BDIGITS 4
41
+ # define PRI_BDIGIT_PREFIX ""
42
+ # ifdef PRI_LL_PREFIX
43
+ # define PRI_BDIGIT_DBL_PREFIX PRI_LL_PREFIX
44
+ # else
45
+ # define PRI_BDIGIT_DBL_PREFIX "l"
46
+ # endif
47
+ #else
48
+ # define BDIGIT uint16_t
49
+ # define BDIGIT_DBL uint32_t
50
+ # define BDIGIT_DBL_SIGNED int32_t
51
+ # define SIZEOF_BDIGITS 2
52
+ # define PRI_BDIGIT_PREFIX "h"
53
+ # define PRI_BDIGIT_DBL_PREFIX ""
54
+ #endif
55
+
56
+ #define PRIdBDIGIT PRI_BDIGIT_PREFIX"d"
57
+ #define PRIiBDIGIT PRI_BDIGIT_PREFIX"i"
58
+ #define PRIoBDIGIT PRI_BDIGIT_PREFIX"o"
59
+ #define PRIuBDIGIT PRI_BDIGIT_PREFIX"u"
60
+ #define PRIxBDIGIT PRI_BDIGIT_PREFIX"x"
61
+ #define PRIXBDIGIT PRI_BDIGIT_PREFIX"X"
62
+
63
+ #define PRIdBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"d"
64
+ #define PRIiBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"i"
65
+ #define PRIoBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"o"
66
+ #define PRIuBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"u"
67
+ #define PRIxBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"x"
68
+ #define PRIXBDIGIT_DBL PRI_BDIGIT_DBL_PREFIX"X"
69
+
70
+ #if defined(__cplusplus)
71
+ extern "C" {
72
+ #if 0
73
+ } /* satisfy cc-mode */
74
+ #endif
75
+ #endif
76
+
77
+ #ifndef HAVE_LABS
78
+ static inline long
79
+ labs(long const x)
80
+ {
81
+ if (x < 0) return -x;
82
+ return x;
83
+ }
84
+ #endif
85
+
86
+ #ifndef HAVE_LLABS
87
+ static inline LONG_LONG
88
+ llabs(LONG_LONG const x)
89
+ {
90
+ if (x < 0) return -x;
91
+ return x;
92
+ }
93
+ #endif
94
+
95
+ #ifndef HAVE_FINITE
96
+ static int
97
+ finite(double)
98
+ {
99
+ return !isnan(n) && !isinf(n);
100
+ }
101
+ #endif
102
+
103
+ #ifndef isfinite
104
+ # ifndef HAVE_ISFINITE
105
+ # define HAVE_ISFINITE 1
106
+ # define isfinite(x) finite(x)
107
+ # endif
108
+ #endif
109
+
110
+ #ifndef FIX_CONST_VALUE_PTR
111
+ # if defined(__fcc__) || defined(__fcc_version) || \
112
+ defined(__FCC__) || defined(__FCC_VERSION)
113
+ /* workaround for old version of Fujitsu C Compiler (fcc) */
114
+ # define FIX_CONST_VALUE_PTR(x) ((const VALUE *)(x))
115
+ # else
116
+ # define FIX_CONST_VALUE_PTR(x) (x)
117
+ # endif
118
+ #endif
119
+
120
+ #ifndef HAVE_RB_ARRAY_CONST_PTR
121
+ static inline const VALUE *
122
+ rb_array_const_ptr(VALUE a)
123
+ {
124
+ return FIX_CONST_VALUE_PTR((RBASIC(a)->flags & RARRAY_EMBED_FLAG) ?
125
+ RARRAY(a)->as.ary : RARRAY(a)->as.heap.ptr);
126
+ }
127
+ #endif
128
+
129
+ #ifndef RARRAY_CONST_PTR
130
+ # define RARRAY_CONST_PTR(a) rb_array_const_ptr(a)
131
+ #endif
132
+
133
+ #ifndef RARRAY_AREF
134
+ # define RARRAY_AREF(a, i) (RARRAY_CONST_PTR(a)[i])
135
+ #endif
136
+
137
+ #ifndef HAVE_RB_SYM2STR
138
+ static inline VALUE
139
+ rb_sym2str(VALUE sym)
140
+ {
141
+ return rb_id2str(SYM2ID(sym));
142
+ }
143
+ #endif
144
+
145
+ #ifndef ST2FIX
146
+ # undef RB_ST2FIX
147
+ # define RB_ST2FIX(h) LONG2FIX((long)(h))
148
+ # define ST2FIX(h) RB_ST2FIX(h)
149
+ #endif
150
+
151
+ #ifdef vabs
152
+ # undef vabs
153
+ #endif
154
+ #if SIZEOF_VALUE <= SIZEOF_INT
155
+ # define vabs abs
156
+ #elif SIZEOF_VALUE <= SIZEOF_LONG
157
+ # define vabs labs
158
+ #elif SIZEOF_VALUE <= SIZEOF_LONG_LONG
159
+ # define vabs llabs
160
+ #endif
161
+
162
+ extern VALUE rb_cBigDecimal;
163
+
164
+ #if 0 || SIZEOF_BDIGITS >= 16
165
+ # define RMPD_COMPONENT_FIGURES 38
166
+ # define RMPD_BASE ((BDIGIT)100000000000000000000000000000000000000U)
167
+ #elif SIZEOF_BDIGITS >= 8
168
+ # define RMPD_COMPONENT_FIGURES 19
169
+ # define RMPD_BASE ((BDIGIT)10000000000000000000U)
170
+ #elif SIZEOF_BDIGITS >= 4
171
+ # define RMPD_COMPONENT_FIGURES 9
172
+ # define RMPD_BASE ((BDIGIT)1000000000U)
173
+ #elif SIZEOF_BDIGITS >= 2
174
+ # define RMPD_COMPONENT_FIGURES 4
175
+ # define RMPD_BASE ((BDIGIT)10000U)
176
+ #else
177
+ # define RMPD_COMPONENT_FIGURES 2
178
+ # define RMPD_BASE ((BDIGIT)100U)
179
+ #endif
180
+
181
+
182
+ /*
183
+ * NaN & Infinity
184
+ */
185
+ #define SZ_NaN "NaN"
186
+ #define SZ_INF "Infinity"
187
+ #define SZ_PINF "+Infinity"
188
+ #define SZ_NINF "-Infinity"
189
+
190
+ /*
191
+ * #define VP_EXPORT other than static to let VP_ routines
192
+ * be called from outside of this module.
193
+ */
194
+ #define VP_EXPORT static
195
+
196
+ /* Exception codes */
197
+ #define VP_EXCEPTION_ALL ((unsigned short)0x00FF)
198
+ #define VP_EXCEPTION_INFINITY ((unsigned short)0x0001)
199
+ #define VP_EXCEPTION_NaN ((unsigned short)0x0002)
200
+ #define VP_EXCEPTION_UNDERFLOW ((unsigned short)0x0004)
201
+ #define VP_EXCEPTION_OVERFLOW ((unsigned short)0x0001) /* 0x0008) */
202
+ #define VP_EXCEPTION_ZERODIVIDE ((unsigned short)0x0010)
203
+
204
+ /* Following 2 exceptions can't controlled by user */
205
+ #define VP_EXCEPTION_OP ((unsigned short)0x0020)
206
+ #define VP_EXCEPTION_MEMORY ((unsigned short)0x0040)
207
+
208
+ #define RMPD_EXCEPTION_MODE_DEFAULT 0U
209
+
210
+ /* Computation mode */
211
+ #define VP_ROUND_MODE ((unsigned short)0x0100)
212
+ #define VP_ROUND_UP 1
213
+ #define VP_ROUND_DOWN 2
214
+ #define VP_ROUND_HALF_UP 3
215
+ #define VP_ROUND_HALF_DOWN 4
216
+ #define VP_ROUND_CEIL 5
217
+ #define VP_ROUND_FLOOR 6
218
+ #define VP_ROUND_HALF_EVEN 7
219
+
220
+ #define RMPD_ROUNDING_MODE_DEFAULT VP_ROUND_HALF_UP
221
+
222
+ #define VP_SIGN_NaN 0 /* NaN */
223
+ #define VP_SIGN_POSITIVE_ZERO 1 /* Positive zero */
224
+ #define VP_SIGN_NEGATIVE_ZERO -1 /* Negative zero */
225
+ #define VP_SIGN_POSITIVE_FINITE 2 /* Positive finite number */
226
+ #define VP_SIGN_NEGATIVE_FINITE -2 /* Negative finite number */
227
+ #define VP_SIGN_POSITIVE_INFINITE 3 /* Positive infinite number */
228
+ #define VP_SIGN_NEGATIVE_INFINITE -3 /* Negative infinite number */
229
+
230
+ #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
231
+ #define FLEXIBLE_ARRAY_SIZE /* */
232
+ #elif defined(__GNUC__) && !defined(__STRICT_ANSI__)
233
+ #define FLEXIBLE_ARRAY_SIZE 0
234
+ #else
235
+ #define FLEXIBLE_ARRAY_SIZE 1
236
+ #endif
237
+
238
+ /*
239
+ * VP representation
240
+ * r = 0.xxxxxxxxx *BASE**exponent
241
+ */
242
+ typedef struct {
243
+ VALUE obj; /* Back pointer(VALUE) for Ruby object. */
244
+ size_t MaxPrec; /* Maximum precision size */
245
+ /* This is the actual size of frac[] */
246
+ /*(frac[0] to frac[MaxPrec] are available). */
247
+ size_t Prec; /* Current precision size. */
248
+ /* This indicates how much the */
249
+ /* array frac[] is actually used. */
250
+ SIGNED_VALUE exponent; /* Exponent part. */
251
+ short sign; /* Attributes of the value. */
252
+ /*
253
+ * ==0 : NaN
254
+ * 1 : Positive zero
255
+ * -1 : Negative zero
256
+ * 2 : Positive number
257
+ * -2 : Negative number
258
+ * 3 : Positive infinite number
259
+ * -3 : Negative infinite number
260
+ */
261
+ short flag; /* Not used in vp_routines,space for user. */
262
+ BDIGIT frac[FLEXIBLE_ARRAY_SIZE]; /* Array of fraction part. */
263
+ } Real;
264
+
265
+ /*
266
+ * ------------------
267
+ * EXPORTables.
268
+ * ------------------
269
+ */
270
+
271
+ VP_EXPORT Real *
272
+ VpNewRbClass(size_t mx, char const *str, VALUE klass);
273
+
274
+ VP_EXPORT Real *VpCreateRbObject(size_t mx,const char *str);
275
+
276
+ static inline BDIGIT
277
+ rmpd_base_value(void) { return RMPD_BASE; }
278
+ static inline size_t
279
+ rmpd_component_figures(void) { return RMPD_COMPONENT_FIGURES; }
280
+ static inline size_t
281
+ rmpd_double_figures(void) { return 1+DBL_DIG; }
282
+
283
+ #define VpBaseFig() rmpd_component_figures()
284
+ #define VpDblFig() rmpd_double_figures()
285
+ #define VpBaseVal() rmpd_base_value()
286
+
287
+ /* Zero,Inf,NaN (isinf(),isnan() used to check) */
288
+ VP_EXPORT double VpGetDoubleNaN(void);
289
+ VP_EXPORT double VpGetDoublePosInf(void);
290
+ VP_EXPORT double VpGetDoubleNegInf(void);
291
+ VP_EXPORT double VpGetDoubleNegZero(void);
292
+
293
+ /* These 2 functions added at v1.1.7 */
294
+ VP_EXPORT size_t VpGetPrecLimit(void);
295
+ VP_EXPORT size_t VpSetPrecLimit(size_t n);
296
+
297
+ /* Round mode */
298
+ VP_EXPORT int VpIsRoundMode(unsigned short n);
299
+ VP_EXPORT unsigned short VpGetRoundMode(void);
300
+ VP_EXPORT unsigned short VpSetRoundMode(unsigned short n);
301
+
302
+ VP_EXPORT int VpException(unsigned short f,const char *str,int always);
303
+ #if 0 /* unused */
304
+ VP_EXPORT int VpIsNegDoubleZero(double v);
305
+ #endif
306
+ VP_EXPORT size_t VpNumOfChars(Real *vp,const char *pszFmt);
307
+ VP_EXPORT size_t VpInit(BDIGIT BaseVal);
308
+ VP_EXPORT void *VpMemAlloc(size_t mb);
309
+ VP_EXPORT void *VpMemRealloc(void *ptr, size_t mb);
310
+ VP_EXPORT void VpFree(Real *pv);
311
+ VP_EXPORT Real *VpAlloc(size_t mx, const char *szVal, int strict_p, int exc);
312
+ VP_EXPORT size_t VpAsgn(Real *c, Real *a, int isw);
313
+ VP_EXPORT size_t VpAddSub(Real *c,Real *a,Real *b,int operation);
314
+ VP_EXPORT size_t VpMult(Real *c,Real *a,Real *b);
315
+ VP_EXPORT size_t VpDivd(Real *c,Real *r,Real *a,Real *b);
316
+ VP_EXPORT int VpComp(Real *a,Real *b);
317
+ VP_EXPORT ssize_t VpExponent10(Real *a);
318
+ VP_EXPORT void VpSzMantissa(Real *a,char *psz);
319
+ VP_EXPORT int VpToSpecialString(Real *a,char *psz,int fPlus);
320
+ VP_EXPORT void VpToString(Real *a, char *psz, size_t fFmt, int fPlus);
321
+ VP_EXPORT void VpToFString(Real *a, char *psz, size_t fFmt, int fPlus);
322
+ 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);
323
+ VP_EXPORT int VpVtoD(double *d, SIGNED_VALUE *e, Real *m);
324
+ VP_EXPORT void VpDtoV(Real *m,double d);
325
+ #if 0 /* unused */
326
+ VP_EXPORT void VpItoV(Real *m,S_INT ival);
327
+ #endif
328
+ VP_EXPORT int VpSqrt(Real *y,Real *x);
329
+ VP_EXPORT int VpActiveRound(Real *y, Real *x, unsigned short f, ssize_t il);
330
+ VP_EXPORT int VpMidRound(Real *y, unsigned short f, ssize_t nf);
331
+ VP_EXPORT int VpLeftRound(Real *y, unsigned short f, ssize_t nf);
332
+ VP_EXPORT void VpFrac(Real *y, Real *x);
333
+ VP_EXPORT int VpPower(Real *y, Real *x, SIGNED_VALUE n);
334
+
335
+ /* VP constants */
336
+ VP_EXPORT Real *VpOne(void);
337
+
338
+ /*
339
+ * ------------------
340
+ * MACRO definitions.
341
+ * ------------------
342
+ */
343
+ #define Abs(a) (((a)>= 0)?(a):(-(a)))
344
+ #define Max(a, b) (((a)>(b))?(a):(b))
345
+ #define Min(a, b) (((a)>(b))?(b):(a))
346
+
347
+ #define VpMaxPrec(a) ((a)->MaxPrec)
348
+ #define VpPrec(a) ((a)->Prec)
349
+ #define VpGetFlag(a) ((a)->flag)
350
+
351
+ /* Sign */
352
+
353
+ /* VpGetSign(a) returns 1,-1 if a>0,a<0 respectively */
354
+ #define VpGetSign(a) (((a)->sign>0)?1:(-1))
355
+ /* Change sign of a to a>0,a<0 if s = 1,-1 respectively */
356
+ #define VpChangeSign(a,s) {if((s)>0) (a)->sign=(short)Abs((ssize_t)(a)->sign);else (a)->sign=-(short)Abs((ssize_t)(a)->sign);}
357
+ /* Sets sign of a to a>0,a<0 if s = 1,-1 respectively */
358
+ #define VpSetSign(a,s) {if((s)>0) (a)->sign=(short)VP_SIGN_POSITIVE_FINITE;else (a)->sign=(short)VP_SIGN_NEGATIVE_FINITE;}
359
+
360
+ /* 1 */
361
+ #define VpSetOne(a) {(a)->Prec=(a)->exponent=(a)->frac[0]=1;(a)->sign=VP_SIGN_POSITIVE_FINITE;}
362
+
363
+ /* ZEROs */
364
+ #define VpIsPosZero(a) ((a)->sign==VP_SIGN_POSITIVE_ZERO)
365
+ #define VpIsNegZero(a) ((a)->sign==VP_SIGN_NEGATIVE_ZERO)
366
+ #define VpIsZero(a) (VpIsPosZero(a) || VpIsNegZero(a))
367
+ #define VpSetPosZero(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_POSITIVE_ZERO)
368
+ #define VpSetNegZero(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_NEGATIVE_ZERO)
369
+ #define VpSetZero(a,s) (void)(((s)>0)?VpSetPosZero(a):VpSetNegZero(a))
370
+
371
+ /* NaN */
372
+ #define VpIsNaN(a) ((a)->sign==VP_SIGN_NaN)
373
+ #define VpSetNaN(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_NaN)
374
+
375
+ /* Infinity */
376
+ #define VpIsPosInf(a) ((a)->sign==VP_SIGN_POSITIVE_INFINITE)
377
+ #define VpIsNegInf(a) ((a)->sign==VP_SIGN_NEGATIVE_INFINITE)
378
+ #define VpIsInf(a) (VpIsPosInf(a) || VpIsNegInf(a))
379
+ #define VpIsDef(a) ( !(VpIsNaN(a)||VpIsInf(a)) )
380
+ #define VpSetPosInf(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_POSITIVE_INFINITE)
381
+ #define VpSetNegInf(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_NEGATIVE_INFINITE)
382
+ #define VpSetInf(a,s) (void)(((s)>0)?VpSetPosInf(a):VpSetNegInf(a))
383
+ #define VpHasVal(a) (a->frac[0])
384
+ #define VpIsOne(a) ((a->Prec==1)&&(a->frac[0]==1)&&(a->exponent==1))
385
+ #define VpExponent(a) (a->exponent)
386
+ #ifdef BIGDECIMAL_DEBUG
387
+ int VpVarCheck(Real * v);
388
+ #endif /* BIGDECIMAL_DEBUG */
389
+
390
+ #if defined(__cplusplus)
391
+ #if 0
392
+ { /* satisfy cc-mode */
393
+ #endif
394
+ } /* extern "C" { */
395
+ #endif
396
+ #endif /* RUBY_BIG_DECIMAL_H */
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: false
2
+ require 'mkmf'
3
+
4
+ def check_bigdecimal_version(gemspec_path)
5
+ message "checking RUBY_BIGDECIMAL_VERSION... "
6
+
7
+ bigdecimal_version =
8
+ IO.readlines(gemspec_path)
9
+ .grep(/\Abigdecimal_version\s+=\s+/)[0][/\'([^\']+)\'/, 1]
10
+
11
+ version_components = bigdecimal_version.split('.')
12
+ bigdecimal_version = version_components[0, 3].join('.')
13
+ bigdecimal_version << "-#{version_components[3]}" if version_components[3]
14
+ $defs << %Q[-DRUBY_BIGDECIMAL_VERSION=\\"#{bigdecimal_version}\\"]
15
+
16
+ message "#{bigdecimal_version}\n"
17
+ end
18
+
19
+ gemspec_name = gemspec_path = nil
20
+ unless ['', '../../'].any? {|dir|
21
+ gemspec_name = "#{dir}bigdecimal.gemspec"
22
+ gemspec_path = File.expand_path("../#{gemspec_name}", __FILE__)
23
+ File.file?(gemspec_path)
24
+ }
25
+ $stderr.puts "Unable to find bigdecimal.gemspec"
26
+ abort
27
+ end
28
+
29
+ check_bigdecimal_version(gemspec_path)
30
+
31
+ have_func("labs", "stdlib.h")
32
+ have_func("llabs", "stdlib.h")
33
+ have_func("finite", "math.h")
34
+ have_func("isfinite", "math.h")
35
+
36
+ have_type("struct RRational", "ruby.h")
37
+ have_func("rb_rational_num", "ruby.h")
38
+ have_func("rb_rational_den", "ruby.h")
39
+ have_type("struct RComplex", "ruby.h")
40
+ have_func("rb_complex_real", "ruby.h")
41
+ have_func("rb_complex_imag", "ruby.h")
42
+ have_func("rb_array_const_ptr", "ruby.h")
43
+ have_func("rb_sym2str", "ruby.h")
44
+ have_func("rb_opts_exception_p", "ruby.h")
45
+
46
+ if File.file?(File.expand_path('../lib/bigdecimal.rb', __FILE__))
47
+ bigdecimal_rb = "$(srcdir)/lib/bigdecimal.rb"
48
+ else
49
+ bigdecimal_rb = "$(srcdir)/../../lib/bigdecimal.rb"
50
+ end
51
+
52
+ create_makefile('bigdecimal') {|mf|
53
+ mf << "GEMSPEC = #{gemspec_name}\n"
54
+ mf << "BIGDECIMAL_RB = #{bigdecimal_rb}\n"
55
+ }