bigdecimal 2.0.2 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bigdecimal.gemspec +8 -9
- data/ext/bigdecimal/bigdecimal.c +1593 -737
- data/ext/bigdecimal/bigdecimal.h +67 -166
- data/ext/bigdecimal/bits.h +141 -0
- data/ext/bigdecimal/extconf.rb +40 -4
- 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 +235 -0
- data/ext/bigdecimal/static_assert.h +54 -0
- data/lib/bigdecimal/util.rb +1 -1
- metadata +11 -61
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
|
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
|
14
|
+
#include "missing.h"
|
24
15
|
|
25
|
-
#
|
26
|
-
#
|
16
|
+
#ifdef HAVE_FLOAT_H
|
17
|
+
# include <float.h>
|
27
18
|
#endif
|
28
19
|
|
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
|
64
|
+
|
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
|
62
79
|
|
63
|
-
#define
|
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"
|
80
|
+
#define BIGDECIMAL_DOUBLE_FIGURES (1+DBL_DIG)
|
69
81
|
|
70
82
|
#if defined(__cplusplus)
|
71
83
|
extern "C" {
|
@@ -74,111 +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
89
|
extern VALUE rb_cBigDecimal;
|
163
90
|
|
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
91
|
/*
|
183
92
|
* NaN & Infinity
|
184
93
|
*/
|
@@ -203,9 +112,8 @@ extern VALUE rb_cBigDecimal;
|
|
203
112
|
|
204
113
|
/* Following 2 exceptions can't controlled by user */
|
205
114
|
#define VP_EXCEPTION_OP ((unsigned short)0x0020)
|
206
|
-
#define VP_EXCEPTION_MEMORY ((unsigned short)0x0040)
|
207
115
|
|
208
|
-
#define
|
116
|
+
#define BIGDECIMAL_EXCEPTION_MODE_DEFAULT 0U
|
209
117
|
|
210
118
|
/* Computation mode */
|
211
119
|
#define VP_ROUND_MODE ((unsigned short)0x0100)
|
@@ -217,7 +125,7 @@ extern VALUE rb_cBigDecimal;
|
|
217
125
|
#define VP_ROUND_FLOOR 6
|
218
126
|
#define VP_ROUND_HALF_EVEN 7
|
219
127
|
|
220
|
-
#define
|
128
|
+
#define BIGDECIMAL_ROUNDING_MODE_DEFAULT VP_ROUND_HALF_UP
|
221
129
|
|
222
130
|
#define VP_SIGN_NaN 0 /* NaN */
|
223
131
|
#define VP_SIGN_POSITIVE_ZERO 1 /* Positive zero */
|
@@ -259,7 +167,7 @@ typedef struct {
|
|
259
167
|
* -3 : Negative infinite number
|
260
168
|
*/
|
261
169
|
short flag; /* Not used in vp_routines,space for user. */
|
262
|
-
|
170
|
+
DECDIG frac[FLEXIBLE_ARRAY_SIZE]; /* Array of fraction part. */
|
263
171
|
} Real;
|
264
172
|
|
265
173
|
/*
|
@@ -268,21 +176,13 @@ typedef struct {
|
|
268
176
|
* ------------------
|
269
177
|
*/
|
270
178
|
|
271
|
-
VP_EXPORT
|
272
|
-
VpNewRbClass(size_t mx, char const *str, VALUE klass);
|
273
|
-
|
274
|
-
VP_EXPORT Real *VpCreateRbObject(size_t mx,const char *str);
|
179
|
+
VP_EXPORT Real *VpNewRbClass(size_t mx, char const *str, VALUE klass, bool strict_p, bool raise_exception);
|
275
180
|
|
276
|
-
|
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; }
|
181
|
+
VP_EXPORT Real *VpCreateRbObject(size_t mx, const char *str, bool raise_exception);
|
282
182
|
|
283
|
-
#define VpBaseFig()
|
284
|
-
#define VpDblFig()
|
285
|
-
#define VpBaseVal()
|
183
|
+
#define VpBaseFig() BIGDECIMAL_COMPONENT_FIGURES
|
184
|
+
#define VpDblFig() BIGDECIMAL_DOUBLE_FIGURES
|
185
|
+
#define VpBaseVal() BIGDECIMAL_BASE
|
286
186
|
|
287
187
|
/* Zero,Inf,NaN (isinf(),isnan() used to check) */
|
288
188
|
VP_EXPORT double VpGetDoubleNaN(void);
|
@@ -304,7 +204,7 @@ VP_EXPORT int VpException(unsigned short f,const char *str,int always);
|
|
304
204
|
VP_EXPORT int VpIsNegDoubleZero(double v);
|
305
205
|
#endif
|
306
206
|
VP_EXPORT size_t VpNumOfChars(Real *vp,const char *pszFmt);
|
307
|
-
VP_EXPORT size_t VpInit(
|
207
|
+
VP_EXPORT size_t VpInit(DECDIG BaseVal);
|
308
208
|
VP_EXPORT void *VpMemAlloc(size_t mb);
|
309
209
|
VP_EXPORT void *VpMemRealloc(void *ptr, size_t mb);
|
310
210
|
VP_EXPORT void VpFree(Real *pv);
|
@@ -330,7 +230,8 @@ VP_EXPORT int VpActiveRound(Real *y, Real *x, unsigned short f, ssize_t il);
|
|
330
230
|
VP_EXPORT int VpMidRound(Real *y, unsigned short f, ssize_t nf);
|
331
231
|
VP_EXPORT int VpLeftRound(Real *y, unsigned short f, ssize_t nf);
|
332
232
|
VP_EXPORT void VpFrac(Real *y, Real *x);
|
333
|
-
VP_EXPORT int
|
233
|
+
VP_EXPORT int VpPowerByInt(Real *y, Real *x, SIGNED_VALUE n);
|
234
|
+
#define VpPower VpPowerByInt
|
334
235
|
|
335
236
|
/* VP constants */
|
336
237
|
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
@@ -3,10 +3,7 @@ require 'mkmf'
|
|
3
3
|
|
4
4
|
def check_bigdecimal_version(gemspec_path)
|
5
5
|
message "checking RUBY_BIGDECIMAL_VERSION... "
|
6
|
-
|
7
|
-
bigdecimal_version =
|
8
|
-
IO.readlines(gemspec_path)
|
9
|
-
.grep(/\Abigdecimal_version\s+=\s+/)[0][/\'([^\']+)\'/, 1]
|
6
|
+
bigdecimal_version = File.read(gemspec_path).match(/^\s*s\.version\s+=\s+['"]([^'"]+)['"]\s*$/)[1]
|
10
7
|
|
11
8
|
version_components = bigdecimal_version.split('.')
|
12
9
|
bigdecimal_version = version_components[0, 3].join('.')
|
@@ -16,6 +13,20 @@ def check_bigdecimal_version(gemspec_path)
|
|
16
13
|
message "#{bigdecimal_version}\n"
|
17
14
|
end
|
18
15
|
|
16
|
+
def have_builtin_func(name, check_expr, opt = "", &b)
|
17
|
+
checking_for checking_message(name.funcall_style, nil, opt) do
|
18
|
+
if try_compile(<<SRC, opt, &b)
|
19
|
+
int foo;
|
20
|
+
int main() { #{check_expr}; return 0; }
|
21
|
+
SRC
|
22
|
+
$defs.push(format("-DHAVE_BUILTIN_%s", name.tr_cpp))
|
23
|
+
true
|
24
|
+
else
|
25
|
+
false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
19
30
|
gemspec_name = gemspec_path = nil
|
20
31
|
unless ['', '../../'].any? {|dir|
|
21
32
|
gemspec_name = "#{dir}bigdecimal.gemspec"
|
@@ -28,11 +39,34 @@ end
|
|
28
39
|
|
29
40
|
check_bigdecimal_version(gemspec_path)
|
30
41
|
|
42
|
+
have_builtin_func("__builtin_clz", "__builtin_clz(0)")
|
43
|
+
have_builtin_func("__builtin_clzl", "__builtin_clzl(0)")
|
44
|
+
have_builtin_func("__builtin_clzll", "__builtin_clzll(0)")
|
45
|
+
|
46
|
+
have_header("float.h")
|
47
|
+
have_header("math.h")
|
48
|
+
have_header("stdbool.h")
|
49
|
+
have_header("stdlib.h")
|
50
|
+
|
51
|
+
have_header("x86intrin.h")
|
52
|
+
have_func("_lzcnt_u32", "x86intrin.h")
|
53
|
+
have_func("_lzcnt_u64", "x86intrin.h")
|
54
|
+
|
55
|
+
have_header("intrin.h")
|
56
|
+
have_func("__lzcnt", "intrin.h")
|
57
|
+
have_func("__lzcnt64", "intrin.h")
|
58
|
+
have_func("_BitScanReverse", "intrin.h")
|
59
|
+
have_func("_BitScanReverse64", "intrin.h")
|
60
|
+
|
31
61
|
have_func("labs", "stdlib.h")
|
32
62
|
have_func("llabs", "stdlib.h")
|
33
63
|
have_func("finite", "math.h")
|
34
64
|
have_func("isfinite", "math.h")
|
35
65
|
|
66
|
+
have_header("ruby/atomic.h")
|
67
|
+
have_header("ruby/internal/has/builtin.h")
|
68
|
+
have_header("ruby/internal/static_assert.h")
|
69
|
+
|
36
70
|
have_type("struct RRational", "ruby.h")
|
37
71
|
have_func("rb_rational_num", "ruby.h")
|
38
72
|
have_func("rb_rational_den", "ruby.h")
|
@@ -42,6 +76,8 @@ have_func("rb_complex_imag", "ruby.h")
|
|
42
76
|
have_func("rb_array_const_ptr", "ruby.h")
|
43
77
|
have_func("rb_sym2str", "ruby.h")
|
44
78
|
have_func("rb_opts_exception_p", "ruby.h")
|
79
|
+
have_func("rb_category_warn", "ruby.h")
|
80
|
+
have_const("RB_WARN_CATEGORY_DEPRECATED", "ruby.h")
|
45
81
|
|
46
82
|
if File.file?(File.expand_path('../lib/bigdecimal.rb', __FILE__))
|
47
83
|
bigdecimal_rb = "$(srcdir)/lib/bigdecimal.rb"
|
@@ -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 */
|