bigdecimal 3.0.2 → 3.1.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +56 -0
- data/bigdecimal.gemspec +29 -13
- data/ext/bigdecimal/bigdecimal.c +2274 -1278
- data/ext/bigdecimal/bigdecimal.h +100 -187
- data/ext/bigdecimal/bits.h +141 -0
- data/ext/bigdecimal/extconf.rb +32 -27
- data/ext/bigdecimal/feature.h +68 -0
- data/ext/bigdecimal/missing/dtoa.c +3462 -0
- data/ext/bigdecimal/missing.c +27 -0
- data/ext/bigdecimal/missing.h +196 -0
- data/ext/bigdecimal/static_assert.h +54 -0
- data/lib/bigdecimal/jacobian.rb +3 -3
- data/lib/bigdecimal/util.rb +11 -7
- data/lib/bigdecimal.rb +5 -1
- metadata +16 -64
data/ext/bigdecimal/bigdecimal.h
CHANGED
@@ -10,62 +10,74 @@
|
|
10
10
|
#define RUBY_BIG_DECIMAL_H 1
|
11
11
|
|
12
12
|
#define RUBY_NO_OLD_COMPATIBILITY
|
13
|
-
|
14
13
|
#include "ruby/ruby.h"
|
15
|
-
#include
|
14
|
+
#include "missing.h"
|
16
15
|
|
17
|
-
#
|
18
|
-
#
|
19
|
-
# define RB_UNUSED_VAR(x) x __attribute__ ((unused))
|
20
|
-
# else
|
21
|
-
# define RB_UNUSED_VAR(x) x
|
22
|
-
# endif
|
16
|
+
#ifdef HAVE_FLOAT_H
|
17
|
+
# include <float.h>
|
23
18
|
#endif
|
24
19
|
|
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
20
|
#ifdef HAVE_INT64_T
|
37
|
-
# define
|
38
|
-
# define
|
39
|
-
# define
|
40
|
-
# define
|
41
|
-
# define
|
21
|
+
# define DECDIG uint32_t
|
22
|
+
# define DECDIG_DBL uint64_t
|
23
|
+
# define DECDIG_DBL_SIGNED int64_t
|
24
|
+
# define SIZEOF_DECDIG 4
|
25
|
+
# define PRI_DECDIG_PREFIX ""
|
42
26
|
# ifdef PRI_LL_PREFIX
|
43
|
-
#
|
27
|
+
# define PRI_DECDIG_DBL_PREFIX PRI_LL_PREFIX
|
44
28
|
# else
|
45
|
-
#
|
29
|
+
# define PRI_DECDIG_DBL_PREFIX "l"
|
46
30
|
# endif
|
47
31
|
#else
|
48
|
-
# define
|
49
|
-
# define
|
50
|
-
# define
|
51
|
-
# define
|
52
|
-
# define
|
53
|
-
# define
|
32
|
+
# define DECDIG uint16_t
|
33
|
+
# define DECDIG_DBL uint32_t
|
34
|
+
# define DECDIG_DBL_SIGNED int32_t
|
35
|
+
# define SIZEOF_DECDIG 2
|
36
|
+
# define PRI_DECDIG_PREFIX "h"
|
37
|
+
# define PRI_DECDIG_DBL_PREFIX ""
|
54
38
|
#endif
|
55
39
|
|
56
|
-
#define
|
57
|
-
#define
|
58
|
-
#define
|
59
|
-
#define
|
60
|
-
#define
|
61
|
-
#define
|
40
|
+
#define PRIdDECDIG PRI_DECDIG_PREFIX"d"
|
41
|
+
#define PRIiDECDIG PRI_DECDIG_PREFIX"i"
|
42
|
+
#define PRIoDECDIG PRI_DECDIG_PREFIX"o"
|
43
|
+
#define PRIuDECDIG PRI_DECDIG_PREFIX"u"
|
44
|
+
#define PRIxDECDIG PRI_DECDIG_PREFIX"x"
|
45
|
+
#define PRIXDECDIG PRI_DECDIG_PREFIX"X"
|
46
|
+
|
47
|
+
#define PRIdDECDIG_DBL PRI_DECDIG_DBL_PREFIX"d"
|
48
|
+
#define PRIiDECDIG_DBL PRI_DECDIG_DBL_PREFIX"i"
|
49
|
+
#define PRIoDECDIG_DBL PRI_DECDIG_DBL_PREFIX"o"
|
50
|
+
#define PRIuDECDIG_DBL PRI_DECDIG_DBL_PREFIX"u"
|
51
|
+
#define PRIxDECDIG_DBL PRI_DECDIG_DBL_PREFIX"x"
|
52
|
+
#define PRIXDECDIG_DBL PRI_DECDIG_DBL_PREFIX"X"
|
53
|
+
|
54
|
+
#if SIZEOF_DECDIG == 4
|
55
|
+
# define BIGDECIMAL_BASE ((DECDIG)1000000000U)
|
56
|
+
# define BIGDECIMAL_COMPONENT_FIGURES 9
|
57
|
+
/*
|
58
|
+
* The number of components required for a 64-bit integer.
|
59
|
+
*
|
60
|
+
* INT64_MAX: 9_223372036_854775807
|
61
|
+
* UINT64_MAX: 18_446744073_709551615
|
62
|
+
*/
|
63
|
+
# define BIGDECIMAL_INT64_MAX_LENGTH 3
|
62
64
|
|
63
|
-
#
|
64
|
-
#define
|
65
|
-
#define
|
66
|
-
|
67
|
-
|
68
|
-
|
65
|
+
#elif SIZEOF_DECDIG == 2
|
66
|
+
# define BIGDECIMAL_BASE ((DECDIG)10000U)
|
67
|
+
# define BIGDECIMAL_COMPONENT_FIGURES 4
|
68
|
+
/*
|
69
|
+
* The number of components required for a 64-bit integer.
|
70
|
+
*
|
71
|
+
* INT64_MAX: 922_3372_0368_5477_5807
|
72
|
+
* UINT64_MAX: 1844_6744_0737_0955_1615
|
73
|
+
*/
|
74
|
+
# define BIGDECIMAL_INT64_MAX_LENGTH 5
|
75
|
+
|
76
|
+
#else
|
77
|
+
# error Unknown size of DECDIG
|
78
|
+
#endif
|
79
|
+
|
80
|
+
#define BIGDECIMAL_DOUBLE_FIGURES (1+DBL_DIG)
|
69
81
|
|
70
82
|
#if defined(__cplusplus)
|
71
83
|
extern "C" {
|
@@ -74,115 +86,8 @@ extern "C" {
|
|
74
86
|
#endif
|
75
87
|
#endif
|
76
88
|
|
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
|
-
#if !defined(HAVE_RB_CATEGORY_WARN) || !defined(HAVE_CONST_RB_WARN_CATEGORY_DEPRECATED)
|
163
|
-
# define rb_category_warn(category, ...) rb_warn(__VA_ARGS__)
|
164
|
-
#endif
|
165
|
-
|
166
89
|
extern VALUE rb_cBigDecimal;
|
167
90
|
|
168
|
-
#if 0 || SIZEOF_BDIGITS >= 16
|
169
|
-
# define RMPD_COMPONENT_FIGURES 38
|
170
|
-
# define RMPD_BASE ((BDIGIT)100000000000000000000000000000000000000U)
|
171
|
-
#elif SIZEOF_BDIGITS >= 8
|
172
|
-
# define RMPD_COMPONENT_FIGURES 19
|
173
|
-
# define RMPD_BASE ((BDIGIT)10000000000000000000U)
|
174
|
-
#elif SIZEOF_BDIGITS >= 4
|
175
|
-
# define RMPD_COMPONENT_FIGURES 9
|
176
|
-
# define RMPD_BASE ((BDIGIT)1000000000U)
|
177
|
-
#elif SIZEOF_BDIGITS >= 2
|
178
|
-
# define RMPD_COMPONENT_FIGURES 4
|
179
|
-
# define RMPD_BASE ((BDIGIT)10000U)
|
180
|
-
#else
|
181
|
-
# define RMPD_COMPONENT_FIGURES 2
|
182
|
-
# define RMPD_BASE ((BDIGIT)100U)
|
183
|
-
#endif
|
184
|
-
|
185
|
-
|
186
91
|
/*
|
187
92
|
* NaN & Infinity
|
188
93
|
*/
|
@@ -197,7 +102,7 @@ extern VALUE rb_cBigDecimal;
|
|
197
102
|
*/
|
198
103
|
#define VP_EXPORT static
|
199
104
|
|
200
|
-
/* Exception
|
105
|
+
/* Exception mode */
|
201
106
|
#define VP_EXCEPTION_ALL ((unsigned short)0x00FF)
|
202
107
|
#define VP_EXCEPTION_INFINITY ((unsigned short)0x0001)
|
203
108
|
#define VP_EXCEPTION_NaN ((unsigned short)0x0002)
|
@@ -207,22 +112,39 @@ extern VALUE rb_cBigDecimal;
|
|
207
112
|
|
208
113
|
/* Following 2 exceptions can't controlled by user */
|
209
114
|
#define VP_EXCEPTION_OP ((unsigned short)0x0020)
|
210
|
-
#define VP_EXCEPTION_MEMORY ((unsigned short)0x0040)
|
211
115
|
|
212
|
-
#define
|
116
|
+
#define BIGDECIMAL_EXCEPTION_MODE_DEFAULT 0U
|
213
117
|
|
214
|
-
/*
|
118
|
+
/* This is used in BigDecimal#mode */
|
215
119
|
#define VP_ROUND_MODE ((unsigned short)0x0100)
|
216
|
-
#define VP_ROUND_UP 1
|
217
|
-
#define VP_ROUND_DOWN 2
|
218
|
-
#define VP_ROUND_HALF_UP 3
|
219
|
-
#define VP_ROUND_HALF_DOWN 4
|
220
|
-
#define VP_ROUND_CEIL 5
|
221
|
-
#define VP_ROUND_FLOOR 6
|
222
|
-
#define VP_ROUND_HALF_EVEN 7
|
223
|
-
|
224
|
-
#define RMPD_ROUNDING_MODE_DEFAULT VP_ROUND_HALF_UP
|
225
120
|
|
121
|
+
/* Rounding mode */
|
122
|
+
#define VP_ROUND_UP RBD_ROUND_UP
|
123
|
+
#define VP_ROUND_DOWN RBD_ROUND_DOWN
|
124
|
+
#define VP_ROUND_HALF_UP RBD_ROUND_HALF_UP
|
125
|
+
#define VP_ROUND_HALF_DOWN RBD_ROUND_HALF_DOWN
|
126
|
+
#define VP_ROUND_CEIL RBD_ROUND_CEIL
|
127
|
+
#define VP_ROUND_FLOOR RBD_ROUND_FLOOR
|
128
|
+
#define VP_ROUND_HALF_EVEN RBD_ROUND_HALF_EVEN
|
129
|
+
|
130
|
+
enum rbd_rounding_mode {
|
131
|
+
RBD_ROUND_UP = 1,
|
132
|
+
RBD_ROUND_DOWN = 2,
|
133
|
+
RBD_ROUND_HALF_UP = 3,
|
134
|
+
RBD_ROUND_HALF_DOWN = 4,
|
135
|
+
RBD_ROUND_CEIL = 5,
|
136
|
+
RBD_ROUND_FLOOR = 6,
|
137
|
+
RBD_ROUND_HALF_EVEN = 7,
|
138
|
+
|
139
|
+
RBD_ROUND_DEFAULT = RBD_ROUND_HALF_UP,
|
140
|
+
RBD_ROUND_TRUNCATE = RBD_ROUND_DOWN,
|
141
|
+
RBD_ROUND_BANKER = RBD_ROUND_HALF_EVEN,
|
142
|
+
RBD_ROUND_CEILING = RBD_ROUND_CEIL
|
143
|
+
};
|
144
|
+
|
145
|
+
#define BIGDECIMAL_ROUNDING_MODE_DEFAULT VP_ROUND_HALF_UP
|
146
|
+
|
147
|
+
/* Sign flag */
|
226
148
|
#define VP_SIGN_NaN 0 /* NaN */
|
227
149
|
#define VP_SIGN_POSITIVE_ZERO 1 /* Positive zero */
|
228
150
|
#define VP_SIGN_NEGATIVE_ZERO -1 /* Negative zero */
|
@@ -231,6 +153,7 @@ extern VALUE rb_cBigDecimal;
|
|
231
153
|
#define VP_SIGN_POSITIVE_INFINITE 3 /* Positive infinite number */
|
232
154
|
#define VP_SIGN_NEGATIVE_INFINITE -3 /* Negative infinite number */
|
233
155
|
|
156
|
+
/* The size of fraction part array */
|
234
157
|
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
|
235
158
|
#define FLEXIBLE_ARRAY_SIZE /* */
|
236
159
|
#elif defined(__GNUC__) && !defined(__STRICT_ANSI__)
|
@@ -263,7 +186,7 @@ typedef struct {
|
|
263
186
|
* -3 : Negative infinite number
|
264
187
|
*/
|
265
188
|
short flag; /* Not used in vp_routines,space for user. */
|
266
|
-
|
189
|
+
DECDIG frac[FLEXIBLE_ARRAY_SIZE]; /* Array of fraction part. */
|
267
190
|
} Real;
|
268
191
|
|
269
192
|
/*
|
@@ -272,21 +195,13 @@ typedef struct {
|
|
272
195
|
* ------------------
|
273
196
|
*/
|
274
197
|
|
275
|
-
VP_EXPORT
|
276
|
-
VpNewRbClass(size_t mx, char const *str, VALUE klass);
|
277
|
-
|
278
|
-
VP_EXPORT Real *VpCreateRbObject(size_t mx,const char *str);
|
198
|
+
VP_EXPORT Real *VpNewRbClass(size_t mx, char const *str, VALUE klass, bool strict_p, bool raise_exception);
|
279
199
|
|
280
|
-
|
281
|
-
rmpd_base_value(void) { return RMPD_BASE; }
|
282
|
-
static inline size_t
|
283
|
-
rmpd_component_figures(void) { return RMPD_COMPONENT_FIGURES; }
|
284
|
-
static inline size_t
|
285
|
-
rmpd_double_figures(void) { return 1+DBL_DIG; }
|
200
|
+
VP_EXPORT Real *VpCreateRbObject(size_t mx, const char *str, bool raise_exception);
|
286
201
|
|
287
|
-
#define VpBaseFig()
|
288
|
-
#define VpDblFig()
|
289
|
-
#define VpBaseVal()
|
202
|
+
#define VpBaseFig() BIGDECIMAL_COMPONENT_FIGURES
|
203
|
+
#define VpDblFig() BIGDECIMAL_DOUBLE_FIGURES
|
204
|
+
#define VpBaseVal() BIGDECIMAL_BASE
|
290
205
|
|
291
206
|
/* Zero,Inf,NaN (isinf(),isnan() used to check) */
|
292
207
|
VP_EXPORT double VpGetDoubleNaN(void);
|
@@ -308,10 +223,7 @@ VP_EXPORT int VpException(unsigned short f,const char *str,int always);
|
|
308
223
|
VP_EXPORT int VpIsNegDoubleZero(double v);
|
309
224
|
#endif
|
310
225
|
VP_EXPORT size_t VpNumOfChars(Real *vp,const char *pszFmt);
|
311
|
-
VP_EXPORT size_t VpInit(
|
312
|
-
VP_EXPORT void *VpMemAlloc(size_t mb);
|
313
|
-
VP_EXPORT void *VpMemRealloc(void *ptr, size_t mb);
|
314
|
-
VP_EXPORT void VpFree(Real *pv);
|
226
|
+
VP_EXPORT size_t VpInit(DECDIG BaseVal);
|
315
227
|
VP_EXPORT Real *VpAlloc(size_t mx, const char *szVal, int strict_p, int exc);
|
316
228
|
VP_EXPORT size_t VpAsgn(Real *c, Real *a, int isw);
|
317
229
|
VP_EXPORT size_t VpAddSub(Real *c,Real *a,Real *b,int operation);
|
@@ -319,10 +231,10 @@ VP_EXPORT size_t VpMult(Real *c,Real *a,Real *b);
|
|
319
231
|
VP_EXPORT size_t VpDivd(Real *c,Real *r,Real *a,Real *b);
|
320
232
|
VP_EXPORT int VpComp(Real *a,Real *b);
|
321
233
|
VP_EXPORT ssize_t VpExponent10(Real *a);
|
322
|
-
VP_EXPORT void VpSzMantissa(Real *a,char *
|
323
|
-
VP_EXPORT int VpToSpecialString(Real *a,char *
|
324
|
-
VP_EXPORT void VpToString(Real *a, char *
|
325
|
-
VP_EXPORT void VpToFString(Real *a, char *
|
234
|
+
VP_EXPORT void VpSzMantissa(Real *a, char *buf, size_t bufsize);
|
235
|
+
VP_EXPORT int VpToSpecialString(Real *a, char *buf, size_t bufsize, int fPlus);
|
236
|
+
VP_EXPORT void VpToString(Real *a, char *buf, size_t bufsize, size_t fFmt, int fPlus);
|
237
|
+
VP_EXPORT void VpToFString(Real *a, char *buf, size_t bufsize, size_t fFmt, int fPlus);
|
326
238
|
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);
|
327
239
|
VP_EXPORT int VpVtoD(double *d, SIGNED_VALUE *e, Real *m);
|
328
240
|
VP_EXPORT void VpDtoV(Real *m,double d);
|
@@ -334,7 +246,8 @@ VP_EXPORT int VpActiveRound(Real *y, Real *x, unsigned short f, ssize_t il);
|
|
334
246
|
VP_EXPORT int VpMidRound(Real *y, unsigned short f, ssize_t nf);
|
335
247
|
VP_EXPORT int VpLeftRound(Real *y, unsigned short f, ssize_t nf);
|
336
248
|
VP_EXPORT void VpFrac(Real *y, Real *x);
|
337
|
-
VP_EXPORT int
|
249
|
+
VP_EXPORT int VpPowerByInt(Real *y, Real *x, SIGNED_VALUE n);
|
250
|
+
#define VpPower VpPowerByInt
|
338
251
|
|
339
252
|
/* VP constants */
|
340
253
|
VP_EXPORT Real *VpOne(void);
|
@@ -0,0 +1,141 @@
|
|
1
|
+
#ifndef BIGDECIMAL_BITS_H
|
2
|
+
#define BIGDECIMAL_BITS_H
|
3
|
+
|
4
|
+
#include "feature.h"
|
5
|
+
#include "static_assert.h"
|
6
|
+
|
7
|
+
#if defined(__x86_64__) && defined(HAVE_X86INTRIN_H)
|
8
|
+
# include <x86intrin.h> /* for _lzcnt_u64, etc. */
|
9
|
+
#elif defined(_MSC_VER) && defined(HAVE_INTRIN_H)
|
10
|
+
# include <intrin.h> /* for the following intrinsics */
|
11
|
+
#endif
|
12
|
+
|
13
|
+
#if defined(_MSC_VER) && defined(__AVX2__)
|
14
|
+
# pragma intrinsic(__lzcnt)
|
15
|
+
# pragma intrinsic(__lzcnt64)
|
16
|
+
#endif
|
17
|
+
|
18
|
+
#define numberof(array) ((int)(sizeof(array) / sizeof((array)[0])))
|
19
|
+
#define roomof(x, y) (((x) + (y) - 1) / (y))
|
20
|
+
#define type_roomof(x, y) roomof(sizeof(x), sizeof(y))
|
21
|
+
|
22
|
+
#define MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max) ( \
|
23
|
+
(a) == 0 ? 0 : \
|
24
|
+
(a) == -1 ? (b) < -(max) : \
|
25
|
+
(a) > 0 ? \
|
26
|
+
((b) > 0 ? (max) / (a) < (b) : (min) / (a) > (b)) : \
|
27
|
+
((b) > 0 ? (min) / (a) < (b) : (max) / (a) > (b)))
|
28
|
+
|
29
|
+
#ifdef HAVE_UINT128_T
|
30
|
+
# define bit_length(x) \
|
31
|
+
(unsigned int) \
|
32
|
+
(sizeof(x) <= sizeof(int32_t) ? 32 - nlz_int32((uint32_t)(x)) : \
|
33
|
+
sizeof(x) <= sizeof(int64_t) ? 64 - nlz_int64((uint64_t)(x)) : \
|
34
|
+
128 - nlz_int128((uint128_t)(x)))
|
35
|
+
#else
|
36
|
+
# define bit_length(x) \
|
37
|
+
(unsigned int) \
|
38
|
+
(sizeof(x) <= sizeof(int32_t) ? 32 - nlz_int32((uint32_t)(x)) : \
|
39
|
+
64 - nlz_int64((uint64_t)(x)))
|
40
|
+
#endif
|
41
|
+
|
42
|
+
static inline unsigned nlz_int32(uint32_t x);
|
43
|
+
static inline unsigned nlz_int64(uint64_t x);
|
44
|
+
#ifdef HAVE_UINT128_T
|
45
|
+
static inline unsigned nlz_int128(uint128_t x);
|
46
|
+
#endif
|
47
|
+
|
48
|
+
static inline unsigned int
|
49
|
+
nlz_int32(uint32_t x)
|
50
|
+
{
|
51
|
+
#if defined(_MSC_VER) && defined(__AVX2__) && defined(HAVE___LZCNT)
|
52
|
+
/* Note: It seems there is no such thing like __LZCNT__ predefined in MSVC.
|
53
|
+
* AMD CPUs have had this instruction for decades (since K10) but for
|
54
|
+
* Intel, Haswell is the oldest one. We need to use __AVX2__ for maximum
|
55
|
+
* safety. */
|
56
|
+
return (unsigned int)__lzcnt(x);
|
57
|
+
|
58
|
+
#elif defined(__x86_64__) && defined(__LZCNT__) && defined(HAVE__LZCNT_U32)
|
59
|
+
return (unsigned int)_lzcnt_u32(x);
|
60
|
+
|
61
|
+
#elif defined(_MSC_VER) && defined(HAVE__BITSCANREVERSE)
|
62
|
+
unsigned long r;
|
63
|
+
return _BitScanReverse(&r, x) ? (31 - (int)r) : 32;
|
64
|
+
|
65
|
+
#elif __has_builtin(__builtin_clz)
|
66
|
+
STATIC_ASSERT(sizeof_int, sizeof(int) * CHAR_BIT == 32);
|
67
|
+
return x ? (unsigned int)__builtin_clz(x) : 32;
|
68
|
+
|
69
|
+
#else
|
70
|
+
uint32_t y;
|
71
|
+
unsigned n = 32;
|
72
|
+
y = x >> 16; if (y) {n -= 16; x = y;}
|
73
|
+
y = x >> 8; if (y) {n -= 8; x = y;}
|
74
|
+
y = x >> 4; if (y) {n -= 4; x = y;}
|
75
|
+
y = x >> 2; if (y) {n -= 2; x = y;}
|
76
|
+
y = x >> 1; if (y) {return n - 2;}
|
77
|
+
return (unsigned int)(n - x);
|
78
|
+
#endif
|
79
|
+
}
|
80
|
+
|
81
|
+
static inline unsigned int
|
82
|
+
nlz_int64(uint64_t x)
|
83
|
+
{
|
84
|
+
#if defined(_MSC_VER) && defined(__AVX2__) && defined(HAVE___LZCNT64)
|
85
|
+
return (unsigned int)__lzcnt64(x);
|
86
|
+
|
87
|
+
#elif defined(__x86_64__) && defined(__LZCNT__) && defined(HAVE__LZCNT_U64)
|
88
|
+
return (unsigned int)_lzcnt_u64(x);
|
89
|
+
|
90
|
+
#elif defined(_WIN64) && defined(_MSC_VER) && defined(HAVE__BITSCANREVERSE64)
|
91
|
+
unsigned long r;
|
92
|
+
return _BitScanReverse64(&r, x) ? (63u - (unsigned int)r) : 64;
|
93
|
+
|
94
|
+
#elif __has_builtin(__builtin_clzl) && __has_builtin(__builtin_clzll) && !(defined(__sun) && defined(__sparc))
|
95
|
+
if (x == 0) {
|
96
|
+
return 64;
|
97
|
+
}
|
98
|
+
else if (sizeof(long) * CHAR_BIT == 64) {
|
99
|
+
return (unsigned int)__builtin_clzl((unsigned long)x);
|
100
|
+
}
|
101
|
+
else if (sizeof(long long) * CHAR_BIT == 64) {
|
102
|
+
return (unsigned int)__builtin_clzll((unsigned long long)x);
|
103
|
+
}
|
104
|
+
else {
|
105
|
+
/* :FIXME: Is there a way to make this branch a compile-time error? */
|
106
|
+
__builtin_unreachable();
|
107
|
+
}
|
108
|
+
|
109
|
+
#else
|
110
|
+
uint64_t y;
|
111
|
+
unsigned int n = 64;
|
112
|
+
y = x >> 32; if (y) {n -= 32; x = y;}
|
113
|
+
y = x >> 16; if (y) {n -= 16; x = y;}
|
114
|
+
y = x >> 8; if (y) {n -= 8; x = y;}
|
115
|
+
y = x >> 4; if (y) {n -= 4; x = y;}
|
116
|
+
y = x >> 2; if (y) {n -= 2; x = y;}
|
117
|
+
y = x >> 1; if (y) {return n - 2;}
|
118
|
+
return (unsigned int)(n - x);
|
119
|
+
|
120
|
+
#endif
|
121
|
+
}
|
122
|
+
|
123
|
+
#ifdef HAVE_UINT128_T
|
124
|
+
static inline unsigned int
|
125
|
+
nlz_int128(uint128_t x)
|
126
|
+
{
|
127
|
+
uint64_t y = (uint64_t)(x >> 64);
|
128
|
+
|
129
|
+
if (x == 0) {
|
130
|
+
return 128;
|
131
|
+
}
|
132
|
+
else if (y == 0) {
|
133
|
+
return (unsigned int)nlz_int64(x) + 64;
|
134
|
+
}
|
135
|
+
else {
|
136
|
+
return (unsigned int)nlz_int64(y);
|
137
|
+
}
|
138
|
+
}
|
139
|
+
#endif
|
140
|
+
|
141
|
+
#endif /* BIGDECIMAL_BITS_H */
|
data/ext/bigdecimal/extconf.rb
CHANGED
@@ -1,46 +1,52 @@
|
|
1
1
|
# frozen_string_literal: false
|
2
2
|
require 'mkmf'
|
3
3
|
|
4
|
-
def
|
5
|
-
|
4
|
+
def have_builtin_func(name, check_expr, opt = "", &b)
|
5
|
+
checking_for checking_message(name.funcall_style, nil, opt) do
|
6
|
+
if try_compile(<<SRC, opt, &b)
|
7
|
+
int foo;
|
8
|
+
int main() { #{check_expr}; return 0; }
|
9
|
+
SRC
|
10
|
+
$defs.push(format("-DHAVE_BUILTIN_%s", name.tr_cpp))
|
11
|
+
true
|
12
|
+
else
|
13
|
+
false
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
6
17
|
|
7
|
-
|
8
|
-
|
9
|
-
|
18
|
+
have_builtin_func("__builtin_clz", "__builtin_clz(0)")
|
19
|
+
have_builtin_func("__builtin_clzl", "__builtin_clzl(0)")
|
20
|
+
have_builtin_func("__builtin_clzll", "__builtin_clzll(0)")
|
10
21
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
22
|
+
have_header("float.h")
|
23
|
+
have_header("math.h")
|
24
|
+
have_header("stdbool.h")
|
25
|
+
have_header("stdlib.h")
|
15
26
|
|
16
|
-
|
17
|
-
|
27
|
+
have_header("x86intrin.h")
|
28
|
+
have_func("_lzcnt_u32", "x86intrin.h")
|
29
|
+
have_func("_lzcnt_u64", "x86intrin.h")
|
18
30
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
}
|
25
|
-
$stderr.puts "Unable to find bigdecimal.gemspec"
|
26
|
-
abort
|
27
|
-
end
|
28
|
-
|
29
|
-
check_bigdecimal_version(gemspec_path)
|
31
|
+
have_header("intrin.h")
|
32
|
+
have_func("__lzcnt", "intrin.h")
|
33
|
+
have_func("__lzcnt64", "intrin.h")
|
34
|
+
have_func("_BitScanReverse", "intrin.h")
|
35
|
+
have_func("_BitScanReverse64", "intrin.h")
|
30
36
|
|
31
37
|
have_func("labs", "stdlib.h")
|
32
38
|
have_func("llabs", "stdlib.h")
|
33
39
|
have_func("finite", "math.h")
|
34
40
|
have_func("isfinite", "math.h")
|
35
41
|
|
36
|
-
|
42
|
+
have_header("ruby/atomic.h")
|
43
|
+
have_header("ruby/internal/has/builtin.h")
|
44
|
+
have_header("ruby/internal/static_assert.h")
|
45
|
+
|
37
46
|
have_func("rb_rational_num", "ruby.h")
|
38
47
|
have_func("rb_rational_den", "ruby.h")
|
39
|
-
have_type("struct RComplex", "ruby.h")
|
40
48
|
have_func("rb_complex_real", "ruby.h")
|
41
49
|
have_func("rb_complex_imag", "ruby.h")
|
42
|
-
have_func("rb_array_const_ptr", "ruby.h")
|
43
|
-
have_func("rb_sym2str", "ruby.h")
|
44
50
|
have_func("rb_opts_exception_p", "ruby.h")
|
45
51
|
have_func("rb_category_warn", "ruby.h")
|
46
52
|
have_const("RB_WARN_CATEGORY_DEPRECATED", "ruby.h")
|
@@ -52,6 +58,5 @@ else
|
|
52
58
|
end
|
53
59
|
|
54
60
|
create_makefile('bigdecimal') {|mf|
|
55
|
-
mf << "GEMSPEC = #{gemspec_name}\n"
|
56
61
|
mf << "BIGDECIMAL_RB = #{bigdecimal_rb}\n"
|
57
62
|
}
|
@@ -0,0 +1,68 @@
|
|
1
|
+
#ifndef BIGDECIMAL_HAS_FEATURE_H
|
2
|
+
#define BIGDECIMAL_HAS_FEATURE_H
|
3
|
+
|
4
|
+
/* ======== __has_feature ======== */
|
5
|
+
|
6
|
+
#ifndef __has_feature
|
7
|
+
# define __has_feature(_) 0
|
8
|
+
#endif
|
9
|
+
|
10
|
+
/* ======== __has_extension ======== */
|
11
|
+
|
12
|
+
#ifndef __has_extension
|
13
|
+
# define __has_extension __has_feature
|
14
|
+
#endif
|
15
|
+
|
16
|
+
/* ======== __has_builtin ======== */
|
17
|
+
|
18
|
+
#ifdef HAVE_RUBY_INTERNAL_HAS_BUILTIN_H
|
19
|
+
# include <ruby/internal/has/builtin.h>
|
20
|
+
#endif
|
21
|
+
|
22
|
+
#ifdef RBIMPL_HAS_BUILTIN
|
23
|
+
# define BIGDECIMAL_HAS_BUILTIN(...) RBIMPL_HAS_BUILTIN(__VA_ARGS__)
|
24
|
+
|
25
|
+
#else
|
26
|
+
# /* The following section is copied from CRuby's builtin.h */
|
27
|
+
#
|
28
|
+
# ifdef __has_builtin
|
29
|
+
# if defined(__INTEL_COMPILER)
|
30
|
+
# /* :TODO: Intel C Compiler has __has_builtin (since 19.1 maybe?), and is
|
31
|
+
# * reportedly broken. We have to skip them. However the situation can
|
32
|
+
# * change. They might improve someday. We need to revisit here later. */
|
33
|
+
# elif defined(__GNUC__) && ! __has_builtin(__builtin_alloca)
|
34
|
+
# /* FreeBSD's <sys/cdefs.h> defines its own *broken* version of
|
35
|
+
# * __has_builtin. Cygwin copied that content to be a victim of the
|
36
|
+
# * broken-ness. We don't take them into account. */
|
37
|
+
# else
|
38
|
+
# define HAVE___HAS_BUILTIN 1
|
39
|
+
# endif
|
40
|
+
# endif
|
41
|
+
#
|
42
|
+
# if defined(HAVE___HAS_BUILTIN)
|
43
|
+
# define BIGDECIMAL_HAS_BUILTIN(_) __has_builtin(_)
|
44
|
+
#
|
45
|
+
# elif defined(__GNUC__)
|
46
|
+
# define BIGDECIMAL_HAS_BUILTIN(_) BIGDECIMAL_HAS_BUILTIN_ ## _
|
47
|
+
# if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 6))
|
48
|
+
# define BIGDECIMAL_HAS_BUILTIN___builtin_clz 1
|
49
|
+
# define BIGDECIMAL_HAS_BUILTIN___builtin_clzl 1
|
50
|
+
# else
|
51
|
+
# define BIGDECIMAL_HAS_BUILTIN___builtin_clz 0
|
52
|
+
# define BIGDECIMAL_HAS_BUILTIN___builtin_clzl 0
|
53
|
+
# endif
|
54
|
+
# elif defined(_MSC_VER)
|
55
|
+
# define BIGDECIMAL_HAS_BUILTIN(_) 0
|
56
|
+
#
|
57
|
+
# else
|
58
|
+
# define BIGDECIMAL_HAS_BUILTIN(_) BIGDECIMAL_HAS_BUILTIN_ ## _
|
59
|
+
# define BIGDECIMAL_HAS_BUILTIN___builtin_clz HAVE_BUILTIN___BUILTIN_CLZ
|
60
|
+
# define BIGDECIMAL_HAS_BUILTIN___builtin_clzl HAVE_BUILTIN___BUILTIN_CLZL
|
61
|
+
# endif
|
62
|
+
#endif /* RBIMPL_HAS_BUILTIN */
|
63
|
+
|
64
|
+
#ifndef __has_builtin
|
65
|
+
# define __has_builtin(...) BIGDECIMAL_HAS_BUILTIN(__VA_ARGS__)
|
66
|
+
#endif
|
67
|
+
|
68
|
+
#endif /* BIGDECIMAL_HAS_FEATURE_H */
|