bigdecimal 4.1.1 → 4.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/bigdecimal/bigdecimal.c +35 -9
- data/ext/bigdecimal/div.h +13 -13
- data/ext/bigdecimal/missing/dtoa.c +184 -137
- data/ext/bigdecimal/ntt.h +5 -5
- data/lib/bigdecimal/math.rb +6 -6
- data/lib/bigdecimal.rb +20 -12
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 922981a841d43e8269ac09725757bd02512ba596903b2da2ab2458e842957833
|
|
4
|
+
data.tar.gz: 34b59473beafbb51888ef2700b0c44ee721025952c1b578c4affa6cb60e91d90
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 00e7aedfc9b90c0e82297880c750010e37b8aa427c122343418bbbc3b656a94583a818b0980d2a91b9a7c22aa9c5cc26d621536c33f0d5ec70b87bf9585feed7
|
|
7
|
+
data.tar.gz: 0b54105583917681020ed7d451f9a39c68f9805e9079b48cc83b7031d43ab5e070945dd4899d73e99925022f4a3462c6f9f277062af0281b1455ed16b0a76f49
|
data/ext/bigdecimal/bigdecimal.c
CHANGED
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
#include "div.h"
|
|
34
34
|
#include "static_assert.h"
|
|
35
35
|
|
|
36
|
-
#define BIGDECIMAL_VERSION "4.1.
|
|
36
|
+
#define BIGDECIMAL_VERSION "4.1.2"
|
|
37
37
|
|
|
38
38
|
/* Make sure VPMULT_BATCH_SIZE*BASE*BASE does not overflow DECDIG_DBL */
|
|
39
39
|
#define VPMULT_BATCH_SIZE 16
|
|
@@ -2709,7 +2709,7 @@ rb_float_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception)
|
|
|
2709
2709
|
len10 = BIGDECIMAL_DOUBLE_FIGURES;
|
|
2710
2710
|
}
|
|
2711
2711
|
memcpy(buf, p, len10);
|
|
2712
|
-
|
|
2712
|
+
free(p);
|
|
2713
2713
|
|
|
2714
2714
|
VALUE inum;
|
|
2715
2715
|
size_t RB_UNUSED_VAR(prec) = 0;
|
|
@@ -5396,8 +5396,8 @@ VpSzMantissa(Real *a, char *buf, size_t buflen)
|
|
|
5396
5396
|
while (m) {
|
|
5397
5397
|
nn = e / m;
|
|
5398
5398
|
if (!ZeroSup || nn) {
|
|
5399
|
-
|
|
5400
|
-
buf
|
|
5399
|
+
*buf = (char)('0' + nn);
|
|
5400
|
+
buf++;
|
|
5401
5401
|
/* as 0.00xx will be ignored. */
|
|
5402
5402
|
ZeroSup = 0; /* Set to print succeeding zeros */
|
|
5403
5403
|
}
|
|
@@ -5449,10 +5449,22 @@ VpToSpecialString(Real *a, char *buf, size_t buflen, int fPlus)
|
|
|
5449
5449
|
return 0;
|
|
5450
5450
|
}
|
|
5451
5451
|
|
|
5452
|
+
#define ULLTOA_BUFFER_SIZE 20
|
|
5453
|
+
static size_t Vp_ulltoa(unsigned long long number, char *buf)
|
|
5454
|
+
{
|
|
5455
|
+
static const char digits[] = "0123456789";
|
|
5456
|
+
char* tmp = buf;
|
|
5457
|
+
|
|
5458
|
+
do *tmp-- = digits[number % 10]; while (number /= 10);
|
|
5459
|
+
return buf - tmp;
|
|
5460
|
+
}
|
|
5461
|
+
|
|
5452
5462
|
VP_EXPORT void
|
|
5453
5463
|
VpToString(Real *a, char *buf, size_t buflen, size_t fFmt, int fPlus)
|
|
5454
5464
|
/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */
|
|
5455
5465
|
{
|
|
5466
|
+
char ulltoa_buf[ULLTOA_BUFFER_SIZE];
|
|
5467
|
+
char *ulltoa_buf_end = ulltoa_buf + ULLTOA_BUFFER_SIZE;
|
|
5456
5468
|
size_t i, n, ZeroSup;
|
|
5457
5469
|
DECDIG shift, m, e, nn;
|
|
5458
5470
|
char *p = buf;
|
|
@@ -5492,10 +5504,9 @@ VpToString(Real *a, char *buf, size_t buflen, size_t fFmt, int fPlus)
|
|
|
5492
5504
|
while (m) {
|
|
5493
5505
|
nn = e / m;
|
|
5494
5506
|
if (!ZeroSup || nn) {
|
|
5495
|
-
|
|
5496
|
-
|
|
5497
|
-
|
|
5498
|
-
ADVANCE(n);
|
|
5507
|
+
*p = (char)('0' + nn);
|
|
5508
|
+
ADVANCE(1);
|
|
5509
|
+
|
|
5499
5510
|
/* as 0.00xx will be ignored. */
|
|
5500
5511
|
ZeroSup = 0; /* Set to print succeeding zeros */
|
|
5501
5512
|
}
|
|
@@ -5514,7 +5525,22 @@ VpToString(Real *a, char *buf, size_t buflen, size_t fFmt, int fPlus)
|
|
|
5514
5525
|
*(--p) = '\0';
|
|
5515
5526
|
++plen;
|
|
5516
5527
|
}
|
|
5517
|
-
|
|
5528
|
+
*p = 'e';
|
|
5529
|
+
ADVANCE(1);
|
|
5530
|
+
|
|
5531
|
+
if (ex < 0) {
|
|
5532
|
+
*p = '-';
|
|
5533
|
+
ADVANCE(1);
|
|
5534
|
+
ex = -ex;
|
|
5535
|
+
}
|
|
5536
|
+
|
|
5537
|
+
size_t ex_n = Vp_ulltoa(ex, ulltoa_buf_end - 1);
|
|
5538
|
+
if (ex_n > plen) goto overflow;
|
|
5539
|
+
MEMCPY(p, ulltoa_buf_end - ex_n, char, ex_n);
|
|
5540
|
+
ADVANCE(ex_n);
|
|
5541
|
+
*p = '\0';
|
|
5542
|
+
ADVANCE(1);
|
|
5543
|
+
|
|
5518
5544
|
if (fFmt) VpFormatSt(buf, fFmt);
|
|
5519
5545
|
|
|
5520
5546
|
overflow:
|
data/ext/bigdecimal/div.h
CHANGED
|
@@ -59,14 +59,14 @@ divmod_by_inv_mul(VALUE x, VALUE y, VALUE inv, VALUE *res_div, VALUE *res_mod) {
|
|
|
59
59
|
|
|
60
60
|
static void
|
|
61
61
|
slice_copy(DECDIG *dest, Real *src, size_t rshift, size_t length) {
|
|
62
|
-
ssize_t start = src->exponent - rshift - length;
|
|
62
|
+
ssize_t start = src->exponent - (ssize_t)rshift - (ssize_t)length;
|
|
63
63
|
if (start >= (ssize_t)src->Prec) return;
|
|
64
64
|
if (start < 0) {
|
|
65
65
|
dest -= start;
|
|
66
|
-
length
|
|
66
|
+
length -= (size_t)(-start);
|
|
67
67
|
start = 0;
|
|
68
68
|
}
|
|
69
|
-
size_t max_length = src->Prec - start;
|
|
69
|
+
size_t max_length = (size_t)((ssize_t)src->Prec - start);
|
|
70
70
|
memcpy(dest, src->frac + start, Min(length, max_length) * sizeof(DECDIG));
|
|
71
71
|
}
|
|
72
72
|
|
|
@@ -101,28 +101,28 @@ divmod_newton(VALUE x, VALUE y, VALUE *div_out, VALUE *mod_out) {
|
|
|
101
101
|
BDVALUE div_result = NewZeroWrap(1, BIGDECIMAL_COMPONENT_FIGURES * (num_blocks * block_figs + 1));
|
|
102
102
|
BDVALUE bdx = GetBDValueMust(x);
|
|
103
103
|
|
|
104
|
-
VALUE mod = BigDecimal_fix(BigDecimal_decimal_shift(x, SSIZET2NUM(-num_blocks * block_digits)));
|
|
105
|
-
for (ssize_t i = num_blocks - 1; i >= 0; i--) {
|
|
104
|
+
VALUE mod = BigDecimal_fix(BigDecimal_decimal_shift(x, SSIZET2NUM(-(ssize_t)(num_blocks * block_digits))));
|
|
105
|
+
for (ssize_t i = (ssize_t)(num_blocks - 1); i >= 0; i--) {
|
|
106
106
|
memset(divident.real->frac, 0, (y_figs + block_figs) * sizeof(DECDIG));
|
|
107
107
|
|
|
108
108
|
BDVALUE bdmod = GetBDValueMust(mod);
|
|
109
109
|
slice_copy(divident.real->frac, bdmod.real, 0, y_figs);
|
|
110
|
-
slice_copy(divident.real->frac + y_figs, bdx.real, i * block_figs, block_figs);
|
|
110
|
+
slice_copy(divident.real->frac + y_figs, bdx.real, (size_t)i * block_figs, block_figs);
|
|
111
111
|
RB_GC_GUARD(bdmod.bigdecimal);
|
|
112
112
|
|
|
113
113
|
VpSetSign(divident.real, 1);
|
|
114
|
-
divident.real->exponent = y_figs + block_figs;
|
|
114
|
+
divident.real->exponent = (ssize_t)(y_figs + block_figs);
|
|
115
115
|
divident.real->Prec = y_figs + block_figs;
|
|
116
116
|
VpNmlz(divident.real);
|
|
117
117
|
|
|
118
118
|
VALUE div;
|
|
119
119
|
divmod_by_inv_mul(divident.bigdecimal, y, yinv, &div, &mod);
|
|
120
120
|
BDVALUE bddiv = GetBDValueMust(div);
|
|
121
|
-
slice_copy(div_result.real->frac + (num_blocks - i - 1) * block_figs, bddiv.real, 0, block_figs + 1);
|
|
121
|
+
slice_copy(div_result.real->frac + (num_blocks - (size_t)i - 1) * block_figs, bddiv.real, 0, block_figs + 1);
|
|
122
122
|
RB_GC_GUARD(bddiv.bigdecimal);
|
|
123
123
|
}
|
|
124
124
|
VpSetSign(div_result.real, 1);
|
|
125
|
-
div_result.real->exponent = num_blocks * block_figs + 1;
|
|
125
|
+
div_result.real->exponent = (ssize_t)(num_blocks * block_figs + 1);
|
|
126
126
|
div_result.real->Prec = num_blocks * block_figs + 1;
|
|
127
127
|
VpNmlz(div_result.real);
|
|
128
128
|
RB_GC_GUARD(bdx.bigdecimal);
|
|
@@ -148,8 +148,8 @@ VpDivdNewtonInner(VALUE args_ptr)
|
|
|
148
148
|
VpAsgn(b2.real, b, 1);
|
|
149
149
|
VpSetSign(a2.real, 1);
|
|
150
150
|
VpSetSign(b2.real, 1);
|
|
151
|
-
a2.real->exponent = base_prec + div_prec;
|
|
152
|
-
b2.real->exponent = base_prec;
|
|
151
|
+
a2.real->exponent = (ssize_t)(base_prec + div_prec);
|
|
152
|
+
b2.real->exponent = (ssize_t)base_prec;
|
|
153
153
|
|
|
154
154
|
if ((ssize_t)a2.real->Prec > a2.real->exponent) {
|
|
155
155
|
a2_frac = BigDecimal_frac(a2.bigdecimal);
|
|
@@ -164,9 +164,9 @@ VpDivdNewtonInner(VALUE args_ptr)
|
|
|
164
164
|
VpAsgn(r, r2.real, VpGetSign(a));
|
|
165
165
|
AddExponent(c, a->exponent);
|
|
166
166
|
AddExponent(c, -b->exponent);
|
|
167
|
-
AddExponent(c, -div_prec);
|
|
167
|
+
AddExponent(c, -(ssize_t)div_prec);
|
|
168
168
|
AddExponent(r, a->exponent);
|
|
169
|
-
AddExponent(r, -base_prec
|
|
169
|
+
AddExponent(r, -(ssize_t)(base_prec + div_prec));
|
|
170
170
|
RB_GC_GUARD(a2.bigdecimal);
|
|
171
171
|
RB_GC_GUARD(a2.bigdecimal);
|
|
172
172
|
RB_GC_GUARD(c2.bigdecimal);
|
|
@@ -98,17 +98,6 @@
|
|
|
98
98
|
* if memory is available and otherwise does something you deem
|
|
99
99
|
* appropriate. If MALLOC is undefined, malloc will be invoked
|
|
100
100
|
* directly -- and assumed always to succeed.
|
|
101
|
-
* #define Omit_Private_Memory to omit logic (added Jan. 1998) for making
|
|
102
|
-
* memory allocations from a private pool of memory when possible.
|
|
103
|
-
* When used, the private pool is PRIVATE_MEM bytes long: 2304 bytes,
|
|
104
|
-
* unless #defined to be a different length. This default length
|
|
105
|
-
* suffices to get rid of MALLOC calls except for unusual cases,
|
|
106
|
-
* such as decimal-to-binary conversion of a very long string of
|
|
107
|
-
* digits. The longest string dtoa can return is about 751 bytes
|
|
108
|
-
* long. For conversions by strtod of strings of 800 digits and
|
|
109
|
-
* all dtoa conversions in single-threaded executions with 8-byte
|
|
110
|
-
* pointers, PRIVATE_MEM >= 7400 appears to suffice; with 4-byte
|
|
111
|
-
* pointers, PRIVATE_MEM >= 7112 appears adequate.
|
|
112
101
|
* #define INFNAN_CHECK on IEEE systems to cause strtod to check for
|
|
113
102
|
* Infinity and NaN (case insensitively). On some systems (e.g.,
|
|
114
103
|
* some HP systems), it may be necessary to #define NAN_WORD0
|
|
@@ -183,7 +172,10 @@
|
|
|
183
172
|
#undef Long
|
|
184
173
|
#undef ULong
|
|
185
174
|
|
|
175
|
+
#include <assert.h>
|
|
186
176
|
#include <limits.h>
|
|
177
|
+
#include <stddef.h>
|
|
178
|
+
#include <stdint.h>
|
|
187
179
|
|
|
188
180
|
#if (INT_MAX >> 30) && !(INT_MAX >> 31)
|
|
189
181
|
#define Long int
|
|
@@ -195,7 +187,7 @@
|
|
|
195
187
|
#error No 32bit integer
|
|
196
188
|
#endif
|
|
197
189
|
|
|
198
|
-
#if HAVE_LONG_LONG
|
|
190
|
+
#if defined(HAVE_LONG_LONG) && (HAVE_LONG_LONG)
|
|
199
191
|
#define Llong LONG_LONG
|
|
200
192
|
#else
|
|
201
193
|
#define NO_LONG_LONG
|
|
@@ -218,28 +210,43 @@
|
|
|
218
210
|
#include <locale.h>
|
|
219
211
|
#endif
|
|
220
212
|
|
|
213
|
+
#if defined(HAVE_STDCKDINT_H) || !defined(__has_include)
|
|
214
|
+
#elif __has_include(<stdckdint.h>)
|
|
215
|
+
# define HAVE_STDCKDINT_H 1
|
|
216
|
+
#endif
|
|
217
|
+
#ifdef HAVE_STDCKDINT_H
|
|
218
|
+
# include <stdckdint.h>
|
|
219
|
+
#endif
|
|
220
|
+
|
|
221
|
+
#if !defined(ckd_add)
|
|
222
|
+
static inline int /* bool */
|
|
223
|
+
ckd_add(int *result, int x, int y)
|
|
224
|
+
{
|
|
225
|
+
if (x < 0) {
|
|
226
|
+
if (y < INT_MIN - x) return 1;
|
|
227
|
+
}
|
|
228
|
+
else if (x > 0) {
|
|
229
|
+
if (y > INT_MAX - x) return 1;
|
|
230
|
+
}
|
|
231
|
+
*result = x + y;
|
|
232
|
+
return 0;
|
|
233
|
+
}
|
|
234
|
+
#endif
|
|
235
|
+
|
|
221
236
|
#ifdef MALLOC
|
|
222
237
|
extern void *MALLOC(size_t);
|
|
223
238
|
#else
|
|
224
|
-
#define MALLOC
|
|
239
|
+
#define MALLOC malloc
|
|
225
240
|
#endif
|
|
226
241
|
#ifdef FREE
|
|
227
242
|
extern void FREE(void*);
|
|
228
243
|
#else
|
|
229
|
-
#define FREE
|
|
244
|
+
#define FREE free
|
|
230
245
|
#endif
|
|
231
246
|
#ifndef NO_SANITIZE
|
|
232
247
|
#define NO_SANITIZE(x, y) y
|
|
233
248
|
#endif
|
|
234
249
|
|
|
235
|
-
#ifndef Omit_Private_Memory
|
|
236
|
-
#ifndef PRIVATE_MEM
|
|
237
|
-
#define PRIVATE_MEM 2304
|
|
238
|
-
#endif
|
|
239
|
-
#define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
|
|
240
|
-
static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
|
|
241
|
-
#endif
|
|
242
|
-
|
|
243
250
|
#undef IEEE_Arith
|
|
244
251
|
#undef Avoid_Underflow
|
|
245
252
|
#ifdef IEEE_BIG_ENDIAN
|
|
@@ -502,7 +509,7 @@ extern double rnd_prod(double, double), rnd_quot(double, double);
|
|
|
502
509
|
#endif
|
|
503
510
|
|
|
504
511
|
#ifndef ATOMIC_PTR_CAS
|
|
505
|
-
#define ATOMIC_PTR_CAS(var, old, new) ((var) = (new), (old))
|
|
512
|
+
#define ATOMIC_PTR_CAS(var, old, new) ((var) = (new), (void *)(old))
|
|
506
513
|
#endif
|
|
507
514
|
#ifndef LIKELY
|
|
508
515
|
#define LIKELY(x) (x)
|
|
@@ -524,76 +531,29 @@ struct Bigint {
|
|
|
524
531
|
|
|
525
532
|
typedef struct Bigint Bigint;
|
|
526
533
|
|
|
527
|
-
static Bigint *freelist[Kmax+1];
|
|
528
|
-
|
|
529
534
|
static Bigint *
|
|
530
535
|
Balloc(int k)
|
|
531
536
|
{
|
|
532
537
|
int x;
|
|
533
538
|
Bigint *rv;
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
rv =
|
|
539
|
-
|
|
540
|
-
if (k <= Kmax) {
|
|
541
|
-
rv = freelist[k];
|
|
542
|
-
while (rv) {
|
|
543
|
-
Bigint *rvn = rv;
|
|
544
|
-
rv = ATOMIC_PTR_CAS(freelist[k], rv, rv->next);
|
|
545
|
-
if (LIKELY(rvn == rv)) {
|
|
546
|
-
ASSUME(rv);
|
|
547
|
-
break;
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
if (!rv) {
|
|
552
|
-
x = 1 << k;
|
|
553
|
-
#ifdef Omit_Private_Memory
|
|
554
|
-
rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
|
|
555
|
-
#else
|
|
556
|
-
len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
|
|
557
|
-
/sizeof(double);
|
|
558
|
-
if (k <= Kmax) {
|
|
559
|
-
double *pnext = pmem_next;
|
|
560
|
-
while (pnext - private_mem + len <= PRIVATE_mem) {
|
|
561
|
-
double *p = pnext;
|
|
562
|
-
pnext = ATOMIC_PTR_CAS(pmem_next, pnext, pnext + len);
|
|
563
|
-
if (LIKELY(p == pnext)) {
|
|
564
|
-
rv = (Bigint*)pnext;
|
|
565
|
-
ASSUME(rv);
|
|
566
|
-
break;
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
if (!rv)
|
|
571
|
-
rv = (Bigint*)MALLOC(len*sizeof(double));
|
|
572
|
-
#endif
|
|
573
|
-
rv->k = k;
|
|
574
|
-
rv->maxwds = x;
|
|
575
|
-
}
|
|
576
|
-
FREE_DTOA_LOCK(0);
|
|
539
|
+
|
|
540
|
+
x = 1 << k;
|
|
541
|
+
rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
|
|
542
|
+
if (!rv) return NULL;
|
|
543
|
+
rv->k = k;
|
|
544
|
+
rv->maxwds = x;
|
|
577
545
|
rv->sign = rv->wds = 0;
|
|
578
546
|
return rv;
|
|
579
547
|
}
|
|
580
548
|
|
|
581
549
|
static void
|
|
582
|
-
|
|
550
|
+
Bclear(Bigint **vp)
|
|
583
551
|
{
|
|
584
|
-
Bigint *
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
FREE(v);
|
|
588
|
-
return;
|
|
589
|
-
}
|
|
590
|
-
ACQUIRE_DTOA_LOCK(0);
|
|
591
|
-
do {
|
|
592
|
-
vn = v->next = freelist[v->k];
|
|
593
|
-
} while (UNLIKELY(ATOMIC_PTR_CAS(freelist[v->k], vn, v) != vn));
|
|
594
|
-
FREE_DTOA_LOCK(0);
|
|
595
|
-
}
|
|
552
|
+
Bigint *v = *vp;
|
|
553
|
+
*vp = NULL;
|
|
554
|
+
if (v) FREE(v);
|
|
596
555
|
}
|
|
556
|
+
#define Bfree(v) Bclear(&(v))
|
|
597
557
|
|
|
598
558
|
#define Bcopy(x,y) memcpy((char *)&(x)->sign, (char *)&(y)->sign, \
|
|
599
559
|
(y)->wds*sizeof(Long) + 2*sizeof(int))
|
|
@@ -639,6 +599,10 @@ multadd(Bigint *b, int m, int a) /* multiply by m and add a */
|
|
|
639
599
|
if (carry) {
|
|
640
600
|
if (wds >= b->maxwds) {
|
|
641
601
|
b1 = Balloc(b->k+1);
|
|
602
|
+
if (!b1) {
|
|
603
|
+
Bfree(b);
|
|
604
|
+
return NULL;
|
|
605
|
+
}
|
|
642
606
|
Bcopy(b1, b);
|
|
643
607
|
Bfree(b);
|
|
644
608
|
b = b1;
|
|
@@ -660,10 +624,12 @@ s2b(const char *s, int nd0, int nd, ULong y9)
|
|
|
660
624
|
for (k = 0, y = 1; x > y; y <<= 1, k++) ;
|
|
661
625
|
#ifdef Pack_32
|
|
662
626
|
b = Balloc(k);
|
|
627
|
+
if (!b) return NULL;
|
|
663
628
|
b->x[0] = y9;
|
|
664
629
|
b->wds = 1;
|
|
665
630
|
#else
|
|
666
631
|
b = Balloc(k+1);
|
|
632
|
+
if (!b) return NULL;
|
|
667
633
|
b->x[0] = y9 & 0xffff;
|
|
668
634
|
b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
|
|
669
635
|
#endif
|
|
@@ -673,13 +639,16 @@ s2b(const char *s, int nd0, int nd, ULong y9)
|
|
|
673
639
|
s += 9;
|
|
674
640
|
do {
|
|
675
641
|
b = multadd(b, 10, *s++ - '0');
|
|
642
|
+
if (!b) return NULL;
|
|
676
643
|
} while (++i < nd0);
|
|
677
644
|
s++;
|
|
678
645
|
}
|
|
679
646
|
else
|
|
680
647
|
s += 10;
|
|
681
|
-
for (; i < nd; i++)
|
|
648
|
+
for (; i < nd; i++) {
|
|
682
649
|
b = multadd(b, 10, *s++ - '0');
|
|
650
|
+
if (!b) return NULL;
|
|
651
|
+
}
|
|
683
652
|
return b;
|
|
684
653
|
}
|
|
685
654
|
|
|
@@ -761,11 +730,14 @@ i2b(int i)
|
|
|
761
730
|
Bigint *b;
|
|
762
731
|
|
|
763
732
|
b = Balloc(1);
|
|
733
|
+
if (!b) return NULL;
|
|
764
734
|
b->x[0] = i;
|
|
765
735
|
b->wds = 1;
|
|
766
736
|
return b;
|
|
767
737
|
}
|
|
768
738
|
|
|
739
|
+
#define Bzero_p(b) (!(b)->x[0] && (b)->wds <= 1)
|
|
740
|
+
|
|
769
741
|
static Bigint *
|
|
770
742
|
mult(Bigint *a, Bigint *b)
|
|
771
743
|
{
|
|
@@ -782,6 +754,14 @@ mult(Bigint *a, Bigint *b)
|
|
|
782
754
|
#endif
|
|
783
755
|
#endif
|
|
784
756
|
|
|
757
|
+
if (Bzero_p(a) || Bzero_p(b)) {
|
|
758
|
+
c = Balloc(0);
|
|
759
|
+
if (!c) return NULL;
|
|
760
|
+
c->wds = 1;
|
|
761
|
+
c->x[0] = 0;
|
|
762
|
+
return c;
|
|
763
|
+
}
|
|
764
|
+
|
|
785
765
|
if (a->wds < b->wds) {
|
|
786
766
|
c = a;
|
|
787
767
|
a = b;
|
|
@@ -794,6 +774,7 @@ mult(Bigint *a, Bigint *b)
|
|
|
794
774
|
if (wc > a->maxwds)
|
|
795
775
|
k++;
|
|
796
776
|
c = Balloc(k);
|
|
777
|
+
if (!c) return NULL;
|
|
797
778
|
for (x = c->x, xa = x + wc; x < xa; x++)
|
|
798
779
|
*x = 0;
|
|
799
780
|
xa = a->x;
|
|
@@ -873,50 +854,47 @@ static Bigint *
|
|
|
873
854
|
pow5mult(Bigint *b, int k)
|
|
874
855
|
{
|
|
875
856
|
Bigint *b1, *p5, *p51;
|
|
876
|
-
Bigint *p5tmp;
|
|
877
857
|
int i;
|
|
878
858
|
static const int p05[3] = { 5, 25, 125 };
|
|
879
859
|
|
|
880
|
-
if ((i = k & 3) != 0)
|
|
860
|
+
if ((i = k & 3) != 0) {
|
|
881
861
|
b = multadd(b, p05[i-1], 0);
|
|
862
|
+
if (!b) return NULL;
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
#define b_cache(var, addr, new_expr) \
|
|
866
|
+
if ((var = addr) != 0) {} else { \
|
|
867
|
+
Bigint *tmp = 0; \
|
|
868
|
+
ACQUIRE_DTOA_LOCK(1); \
|
|
869
|
+
if (!(var = addr) && (var = (new_expr)) != 0) { \
|
|
870
|
+
var->next = 0; \
|
|
871
|
+
tmp = ATOMIC_PTR_CAS(addr, NULL, var); \
|
|
872
|
+
} \
|
|
873
|
+
FREE_DTOA_LOCK(1); \
|
|
874
|
+
if (UNLIKELY(tmp)) { \
|
|
875
|
+
Bfree(var); \
|
|
876
|
+
var = tmp; \
|
|
877
|
+
} \
|
|
878
|
+
else if (!var) { \
|
|
879
|
+
Bfree(b); \
|
|
880
|
+
return NULL; \
|
|
881
|
+
} \
|
|
882
|
+
}
|
|
882
883
|
|
|
883
884
|
if (!(k >>= 2))
|
|
884
885
|
return b;
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
ACQUIRE_DTOA_LOCK(1);
|
|
888
|
-
if (!(p5 = p5s)) {
|
|
889
|
-
p5 = i2b(625);
|
|
890
|
-
p5->next = 0;
|
|
891
|
-
p5tmp = ATOMIC_PTR_CAS(p5s, NULL, p5);
|
|
892
|
-
if (UNLIKELY(p5tmp)) {
|
|
893
|
-
Bfree(p5);
|
|
894
|
-
p5 = p5tmp;
|
|
895
|
-
}
|
|
896
|
-
}
|
|
897
|
-
FREE_DTOA_LOCK(1);
|
|
898
|
-
}
|
|
886
|
+
/* first time */
|
|
887
|
+
b_cache(p5, p5s, i2b(625));
|
|
899
888
|
for (;;) {
|
|
900
889
|
if (k & 1) {
|
|
901
890
|
b1 = mult(b, p5);
|
|
902
891
|
Bfree(b);
|
|
903
892
|
b = b1;
|
|
893
|
+
if (!b) return NULL;
|
|
904
894
|
}
|
|
905
895
|
if (!(k >>= 1))
|
|
906
896
|
break;
|
|
907
|
-
|
|
908
|
-
ACQUIRE_DTOA_LOCK(1);
|
|
909
|
-
if (!(p51 = p5->next)) {
|
|
910
|
-
p51 = mult(p5,p5);
|
|
911
|
-
p51->next = 0;
|
|
912
|
-
p5tmp = ATOMIC_PTR_CAS(p5->next, NULL, p51);
|
|
913
|
-
if (UNLIKELY(p5tmp)) {
|
|
914
|
-
Bfree(p51);
|
|
915
|
-
p51 = p5tmp;
|
|
916
|
-
}
|
|
917
|
-
}
|
|
918
|
-
FREE_DTOA_LOCK(1);
|
|
919
|
-
}
|
|
897
|
+
b_cache(p51, p5->next, mult(p5, p5));
|
|
920
898
|
p5 = p51;
|
|
921
899
|
}
|
|
922
900
|
return b;
|
|
@@ -929,6 +907,8 @@ lshift(Bigint *b, int k)
|
|
|
929
907
|
Bigint *b1;
|
|
930
908
|
ULong *x, *x1, *xe, z;
|
|
931
909
|
|
|
910
|
+
if (!k || Bzero_p(b)) return b;
|
|
911
|
+
|
|
932
912
|
#ifdef Pack_32
|
|
933
913
|
n = k >> 5;
|
|
934
914
|
#else
|
|
@@ -939,6 +919,10 @@ lshift(Bigint *b, int k)
|
|
|
939
919
|
for (i = b->maxwds; n1 > i; i <<= 1)
|
|
940
920
|
k1++;
|
|
941
921
|
b1 = Balloc(k1);
|
|
922
|
+
if (!b1) {
|
|
923
|
+
Bfree(b);
|
|
924
|
+
return NULL;
|
|
925
|
+
}
|
|
942
926
|
x1 = b1->x;
|
|
943
927
|
for (i = 0; i < n; i++)
|
|
944
928
|
*x1++ = 0;
|
|
@@ -1024,6 +1008,7 @@ diff(Bigint *a, Bigint *b)
|
|
|
1024
1008
|
i = cmp(a,b);
|
|
1025
1009
|
if (!i) {
|
|
1026
1010
|
c = Balloc(0);
|
|
1011
|
+
if (!c) return NULL;
|
|
1027
1012
|
c->wds = 1;
|
|
1028
1013
|
c->x[0] = 0;
|
|
1029
1014
|
return c;
|
|
@@ -1037,6 +1022,7 @@ diff(Bigint *a, Bigint *b)
|
|
|
1037
1022
|
else
|
|
1038
1023
|
i = 0;
|
|
1039
1024
|
c = Balloc(a->k);
|
|
1025
|
+
if (!c) return NULL;
|
|
1040
1026
|
c->sign = i;
|
|
1041
1027
|
wa = a->wds;
|
|
1042
1028
|
xa = a->x;
|
|
@@ -1222,6 +1208,7 @@ d2b(double d_, int *e, int *bits)
|
|
|
1222
1208
|
#else
|
|
1223
1209
|
b = Balloc(2);
|
|
1224
1210
|
#endif
|
|
1211
|
+
if (!b) return NULL;
|
|
1225
1212
|
x = b->x;
|
|
1226
1213
|
|
|
1227
1214
|
z = d0 & Frac_mask;
|
|
@@ -1542,9 +1529,10 @@ break2:
|
|
|
1542
1529
|
aadj = 1.0;
|
|
1543
1530
|
nd0 = -4;
|
|
1544
1531
|
|
|
1545
|
-
if (!*++s || !(s1 = strchr(hexdigit, *s))) goto ret0;
|
|
1532
|
+
if (!*++s || (!(s1 = strchr(hexdigit, *s)) && *s != '.')) goto ret0;
|
|
1546
1533
|
if (*s == '0') {
|
|
1547
1534
|
while (*++s == '0');
|
|
1535
|
+
if (!*s) goto ret;
|
|
1548
1536
|
s1 = strchr(hexdigit, *s);
|
|
1549
1537
|
}
|
|
1550
1538
|
if (s1 != NULL) {
|
|
@@ -1555,9 +1543,7 @@ break2:
|
|
|
1555
1543
|
} while (*++s && (s1 = strchr(hexdigit, *s)));
|
|
1556
1544
|
}
|
|
1557
1545
|
|
|
1558
|
-
if (*s == '.') {
|
|
1559
|
-
dsign = 1;
|
|
1560
|
-
if (!*++s || !(s1 = strchr(hexdigit, *s))) goto ret0;
|
|
1546
|
+
if ((*s == '.') && *++s && (s1 = strchr(hexdigit, *s))) {
|
|
1561
1547
|
if (nd0 < 0) {
|
|
1562
1548
|
while (*s == '0') {
|
|
1563
1549
|
s++;
|
|
@@ -1567,14 +1553,11 @@ break2:
|
|
|
1567
1553
|
for (; *s && (s1 = strchr(hexdigit, *s)); ++s) {
|
|
1568
1554
|
adj += aadj * ((s1 - hexdigit) & 15);
|
|
1569
1555
|
if ((aadj /= 16) == 0.0) {
|
|
1570
|
-
while (strchr(hexdigit,
|
|
1556
|
+
while (*++s && strchr(hexdigit, *s));
|
|
1571
1557
|
break;
|
|
1572
1558
|
}
|
|
1573
1559
|
}
|
|
1574
1560
|
}
|
|
1575
|
-
else {
|
|
1576
|
-
dsign = 0;
|
|
1577
|
-
}
|
|
1578
1561
|
|
|
1579
1562
|
if (*s == 'P' || *s == 'p') {
|
|
1580
1563
|
dsign = 0x2C - *++s; /* +: 2B, -: 2D */
|
|
@@ -1597,9 +1580,6 @@ break2:
|
|
|
1597
1580
|
} while ('0' <= c && c <= '9');
|
|
1598
1581
|
nd0 += nd * dsign;
|
|
1599
1582
|
}
|
|
1600
|
-
else {
|
|
1601
|
-
if (dsign) goto ret0;
|
|
1602
|
-
}
|
|
1603
1583
|
dval(rv) = ldexp(adj, nd0);
|
|
1604
1584
|
goto ret;
|
|
1605
1585
|
}
|
|
@@ -1636,9 +1616,9 @@ break2:
|
|
|
1636
1616
|
}
|
|
1637
1617
|
#endif
|
|
1638
1618
|
if (c == '.') {
|
|
1639
|
-
if (!ISDIGIT(s[1]))
|
|
1640
|
-
goto dig_done;
|
|
1641
1619
|
c = *++s;
|
|
1620
|
+
if (!ISDIGIT(c))
|
|
1621
|
+
goto dig_done;
|
|
1642
1622
|
if (!nd) {
|
|
1643
1623
|
for (; c == '0'; c = *++s)
|
|
1644
1624
|
nz++;
|
|
@@ -1979,12 +1959,16 @@ undfl:
|
|
|
1979
1959
|
/* Put digits into bd: true value = bd * 10^e */
|
|
1980
1960
|
|
|
1981
1961
|
bd0 = s2b(s0, nd0, nd, y);
|
|
1962
|
+
if (!bd0) goto ret;
|
|
1982
1963
|
|
|
1983
1964
|
for (;;) {
|
|
1984
1965
|
bd = Balloc(bd0->k);
|
|
1966
|
+
if (!bd) goto retfree;
|
|
1985
1967
|
Bcopy(bd, bd0);
|
|
1986
1968
|
bb = d2b(dval(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
|
|
1969
|
+
if (!bb) goto retfree;
|
|
1987
1970
|
bs = i2b(1);
|
|
1971
|
+
if (!bs) goto retfree;
|
|
1988
1972
|
|
|
1989
1973
|
if (e >= 0) {
|
|
1990
1974
|
bb2 = bb5 = 0;
|
|
@@ -2041,19 +2025,30 @@ undfl:
|
|
|
2041
2025
|
}
|
|
2042
2026
|
if (bb5 > 0) {
|
|
2043
2027
|
bs = pow5mult(bs, bb5);
|
|
2028
|
+
if (!bs) goto retfree;
|
|
2044
2029
|
bb1 = mult(bs, bb);
|
|
2045
2030
|
Bfree(bb);
|
|
2046
2031
|
bb = bb1;
|
|
2032
|
+
if (!bb) goto retfree;
|
|
2047
2033
|
}
|
|
2048
|
-
if (bb2 > 0)
|
|
2034
|
+
if (bb2 > 0) {
|
|
2049
2035
|
bb = lshift(bb, bb2);
|
|
2050
|
-
|
|
2036
|
+
if (!bb) goto retfree;
|
|
2037
|
+
}
|
|
2038
|
+
if (bd5 > 0) {
|
|
2051
2039
|
bd = pow5mult(bd, bd5);
|
|
2052
|
-
|
|
2040
|
+
if (!bd) goto retfree;
|
|
2041
|
+
}
|
|
2042
|
+
if (bd2 > 0) {
|
|
2053
2043
|
bd = lshift(bd, bd2);
|
|
2054
|
-
|
|
2044
|
+
if (!bd) goto retfree;
|
|
2045
|
+
}
|
|
2046
|
+
if (bs2 > 0) {
|
|
2055
2047
|
bs = lshift(bs, bs2);
|
|
2048
|
+
if (!bs) goto retfree;
|
|
2049
|
+
}
|
|
2056
2050
|
delta = diff(bb, bd);
|
|
2051
|
+
if (!delta) goto retfree;
|
|
2057
2052
|
dsign = delta->sign;
|
|
2058
2053
|
delta->sign = 0;
|
|
2059
2054
|
i = cmp(delta, bs);
|
|
@@ -2086,6 +2081,7 @@ undfl:
|
|
|
2086
2081
|
#endif
|
|
2087
2082
|
{
|
|
2088
2083
|
delta = lshift(delta,Log2P);
|
|
2084
|
+
if (!delta) goto nomem;
|
|
2089
2085
|
if (cmp(delta, bs) <= 0)
|
|
2090
2086
|
adj = -0.5;
|
|
2091
2087
|
}
|
|
@@ -2175,6 +2171,7 @@ apply_adj:
|
|
|
2175
2171
|
break;
|
|
2176
2172
|
}
|
|
2177
2173
|
delta = lshift(delta,Log2P);
|
|
2174
|
+
if (!delta) goto retfree;
|
|
2178
2175
|
if (cmp(delta, bs) > 0)
|
|
2179
2176
|
goto drop_down;
|
|
2180
2177
|
break;
|
|
@@ -2577,6 +2574,7 @@ nrv_alloc(const char *s, char **rve, size_t n)
|
|
|
2577
2574
|
char *rv, *t;
|
|
2578
2575
|
|
|
2579
2576
|
t = rv = rv_alloc(n);
|
|
2577
|
+
if (!rv) return NULL;
|
|
2580
2578
|
while ((*t = *s++) != 0) t++;
|
|
2581
2579
|
if (rve)
|
|
2582
2580
|
*rve = t;
|
|
@@ -2749,6 +2747,7 @@ dtoa(double d_, int mode, int ndigits, int *decpt, int *sign, char **rve)
|
|
|
2749
2747
|
#endif
|
|
2750
2748
|
|
|
2751
2749
|
b = d2b(dval(d), &be, &bbits);
|
|
2750
|
+
if (!b) return NULL;
|
|
2752
2751
|
#ifdef Sudden_Underflow
|
|
2753
2752
|
i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
|
|
2754
2753
|
#else
|
|
@@ -2868,13 +2867,20 @@ dtoa(double d_, int mode, int ndigits, int *decpt, int *sign, char **rve)
|
|
|
2868
2867
|
leftright = 0;
|
|
2869
2868
|
/* no break */
|
|
2870
2869
|
case 5:
|
|
2871
|
-
i
|
|
2870
|
+
if (ckd_add(&i, ndigits, k + 1)) { /* k + 1 should be safe */
|
|
2871
|
+
Bfree(b);
|
|
2872
|
+
return NULL;
|
|
2873
|
+
}
|
|
2872
2874
|
ilim = i;
|
|
2873
2875
|
ilim1 = i - 1;
|
|
2874
2876
|
if (i <= 0)
|
|
2875
2877
|
i = 1;
|
|
2876
2878
|
}
|
|
2877
2879
|
s = s0 = rv_alloc(i+1);
|
|
2880
|
+
if (!s) {
|
|
2881
|
+
Bfree(b);
|
|
2882
|
+
return NULL;
|
|
2883
|
+
}
|
|
2878
2884
|
|
|
2879
2885
|
#ifdef Honor_FLT_ROUNDS
|
|
2880
2886
|
if (mode > 1 && rounding != 1)
|
|
@@ -3055,6 +3061,7 @@ bump_up:
|
|
|
3055
3061
|
b2 += i;
|
|
3056
3062
|
s2 += i;
|
|
3057
3063
|
mhi = i2b(1);
|
|
3064
|
+
if (!mhi) goto nomem;
|
|
3058
3065
|
}
|
|
3059
3066
|
if (m2 > 0 && s2 > 0) {
|
|
3060
3067
|
i = m2 < s2 ? m2 : s2;
|
|
@@ -3066,19 +3073,28 @@ bump_up:
|
|
|
3066
3073
|
if (leftright) {
|
|
3067
3074
|
if (m5 > 0) {
|
|
3068
3075
|
mhi = pow5mult(mhi, m5);
|
|
3076
|
+
if (!mhi) goto nomem;
|
|
3069
3077
|
b1 = mult(mhi, b);
|
|
3070
3078
|
Bfree(b);
|
|
3071
3079
|
b = b1;
|
|
3080
|
+
if (!b) goto nomem;
|
|
3072
3081
|
}
|
|
3073
|
-
if ((j = b5 - m5) != 0)
|
|
3082
|
+
if ((j = b5 - m5) != 0) {
|
|
3074
3083
|
b = pow5mult(b, j);
|
|
3084
|
+
if (!b) goto nomem;
|
|
3085
|
+
}
|
|
3075
3086
|
}
|
|
3076
|
-
else
|
|
3087
|
+
else {
|
|
3077
3088
|
b = pow5mult(b, b5);
|
|
3089
|
+
if (!b) goto nomem;
|
|
3090
|
+
}
|
|
3078
3091
|
}
|
|
3079
3092
|
S = i2b(1);
|
|
3080
|
-
if (
|
|
3093
|
+
if (!S) goto nomem;
|
|
3094
|
+
if (s5 > 0) {
|
|
3081
3095
|
S = pow5mult(S, s5);
|
|
3096
|
+
if (!S) goto nomem;
|
|
3097
|
+
}
|
|
3082
3098
|
|
|
3083
3099
|
/* Check for special case that d is a normalized power of 2. */
|
|
3084
3100
|
|
|
@@ -3126,16 +3142,23 @@ bump_up:
|
|
|
3126
3142
|
m2 += i;
|
|
3127
3143
|
s2 += i;
|
|
3128
3144
|
}
|
|
3129
|
-
if (b2 > 0)
|
|
3145
|
+
if (b2 > 0) {
|
|
3130
3146
|
b = lshift(b, b2);
|
|
3131
|
-
|
|
3147
|
+
if (!b) goto nomem;
|
|
3148
|
+
}
|
|
3149
|
+
if (s2 > 0) {
|
|
3132
3150
|
S = lshift(S, s2);
|
|
3151
|
+
if (!S) goto nomem;
|
|
3152
|
+
}
|
|
3133
3153
|
if (k_check) {
|
|
3134
3154
|
if (cmp(b,S) < 0) {
|
|
3135
3155
|
k--;
|
|
3136
3156
|
b = multadd(b, 10, 0); /* we botched the k estimate */
|
|
3137
|
-
if (
|
|
3157
|
+
if (!b) goto nomem;
|
|
3158
|
+
if (leftright) {
|
|
3138
3159
|
mhi = multadd(mhi, 10, 0);
|
|
3160
|
+
if (!mhi) goto nomem;
|
|
3161
|
+
}
|
|
3139
3162
|
ilim = ilim1;
|
|
3140
3163
|
}
|
|
3141
3164
|
}
|
|
@@ -3152,8 +3175,10 @@ one_digit:
|
|
|
3152
3175
|
goto ret;
|
|
3153
3176
|
}
|
|
3154
3177
|
if (leftright) {
|
|
3155
|
-
if (m2 > 0)
|
|
3178
|
+
if (m2 > 0) {
|
|
3156
3179
|
mhi = lshift(mhi, m2);
|
|
3180
|
+
if (!mhi) goto nomem;
|
|
3181
|
+
}
|
|
3157
3182
|
|
|
3158
3183
|
/* Compute mlo -- check for special case
|
|
3159
3184
|
* that d is a normalized power of 2.
|
|
@@ -3162,8 +3187,10 @@ one_digit:
|
|
|
3162
3187
|
mlo = mhi;
|
|
3163
3188
|
if (spec_case) {
|
|
3164
3189
|
mhi = Balloc(mhi->k);
|
|
3190
|
+
if (!mhi) goto nomem;
|
|
3165
3191
|
Bcopy(mhi, mlo);
|
|
3166
3192
|
mhi = lshift(mhi, Log2P);
|
|
3193
|
+
if (!mhi) goto nomem;
|
|
3167
3194
|
}
|
|
3168
3195
|
|
|
3169
3196
|
for (i = 1;;i++) {
|
|
@@ -3173,6 +3200,7 @@ one_digit:
|
|
|
3173
3200
|
*/
|
|
3174
3201
|
j = cmp(b, mlo);
|
|
3175
3202
|
delta = diff(S, mhi);
|
|
3203
|
+
if (!delta) goto nomem;
|
|
3176
3204
|
j1 = delta->sign ? 1 : cmp(b, delta);
|
|
3177
3205
|
Bfree(delta);
|
|
3178
3206
|
#ifndef ROUND_BIASED
|
|
@@ -3213,6 +3241,7 @@ one_digit:
|
|
|
3213
3241
|
#endif /*Honor_FLT_ROUNDS*/
|
|
3214
3242
|
if (j1 > 0) {
|
|
3215
3243
|
b = lshift(b, 1);
|
|
3244
|
+
if (!b) goto nomem;
|
|
3216
3245
|
j1 = cmp(b, S);
|
|
3217
3246
|
if ((j1 > 0 || (j1 == 0 && (dig & 1))) && dig++ == '9')
|
|
3218
3247
|
goto round_9_up;
|
|
@@ -3241,11 +3270,16 @@ keep_dig:
|
|
|
3241
3270
|
if (i == ilim)
|
|
3242
3271
|
break;
|
|
3243
3272
|
b = multadd(b, 10, 0);
|
|
3244
|
-
if (
|
|
3273
|
+
if (!b) goto nomem;
|
|
3274
|
+
if (mlo == mhi) {
|
|
3245
3275
|
mlo = mhi = multadd(mhi, 10, 0);
|
|
3276
|
+
if (!mlo) goto nomem;
|
|
3277
|
+
}
|
|
3246
3278
|
else {
|
|
3247
3279
|
mlo = multadd(mlo, 10, 0);
|
|
3280
|
+
if (!mlo) goto nomem;
|
|
3248
3281
|
mhi = multadd(mhi, 10, 0);
|
|
3282
|
+
if (!mhi) goto nomem;
|
|
3249
3283
|
}
|
|
3250
3284
|
}
|
|
3251
3285
|
}
|
|
@@ -3261,6 +3295,7 @@ keep_dig:
|
|
|
3261
3295
|
if (i >= ilim)
|
|
3262
3296
|
break;
|
|
3263
3297
|
b = multadd(b, 10, 0);
|
|
3298
|
+
if (!b) goto nomem;
|
|
3264
3299
|
}
|
|
3265
3300
|
|
|
3266
3301
|
/* Round off last digit */
|
|
@@ -3272,6 +3307,7 @@ keep_dig:
|
|
|
3272
3307
|
}
|
|
3273
3308
|
#endif
|
|
3274
3309
|
b = lshift(b, 1);
|
|
3310
|
+
if (!b) goto nomem;
|
|
3275
3311
|
j = cmp(b, S);
|
|
3276
3312
|
if (j > 0 || (j == 0 && (dig & 1))) {
|
|
3277
3313
|
roundoff:
|
|
@@ -3313,6 +3349,16 @@ ret1:
|
|
|
3313
3349
|
if (rve)
|
|
3314
3350
|
*rve = s;
|
|
3315
3351
|
return s0;
|
|
3352
|
+
nomem:
|
|
3353
|
+
if (S) Bfree(S);
|
|
3354
|
+
if (mhi) {
|
|
3355
|
+
if (mlo && mlo != mhi)
|
|
3356
|
+
Bfree(mlo);
|
|
3357
|
+
Bfree(mhi);
|
|
3358
|
+
}
|
|
3359
|
+
if (b) Bfree(b);
|
|
3360
|
+
FREE(s0);
|
|
3361
|
+
return NULL;
|
|
3316
3362
|
}
|
|
3317
3363
|
|
|
3318
3364
|
/*-
|
|
@@ -3421,6 +3467,7 @@ hdtoa(double d, const char *xdigs, int ndigits, int *decpt, int *sign, char **rv
|
|
|
3421
3467
|
*/
|
|
3422
3468
|
bufsize = (ndigits > 0) ? ndigits : SIGFIGS;
|
|
3423
3469
|
s0 = rv_alloc(bufsize+1);
|
|
3470
|
+
if (!s0) return NULL;
|
|
3424
3471
|
|
|
3425
3472
|
/* Round to the desired number of digits. */
|
|
3426
3473
|
if (SIGFIGS > ndigits && ndigits > 0) {
|
data/ext/bigdecimal/ntt.h
CHANGED
|
@@ -68,7 +68,7 @@ ntt(int size_bits, uint32_t *input, uint32_t *output, uint32_t *tmp, int r_base,
|
|
|
68
68
|
|
|
69
69
|
// rmax**(1 << shift) % prime == 1
|
|
70
70
|
// r**size % prime == 1
|
|
71
|
-
uint32_t rmax = mod_pow(r_base, base, prime);
|
|
71
|
+
uint32_t rmax = mod_pow((uint32_t)r_base, (uint32_t)base, prime);
|
|
72
72
|
uint32_t r = mod_pow(rmax, (uint32_t)1 << (shift - size_bits), prime);
|
|
73
73
|
|
|
74
74
|
if (dir < 0) r = mod_pow(r, prime - 2, prime);
|
|
@@ -123,7 +123,7 @@ ntt_multiply(size_t a_size, size_t b_size, uint32_t *a, uint32_t *b, uint32_t *c
|
|
|
123
123
|
return;
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
int ntt_size_bits = bit_length(b_size - 1) + 1;
|
|
126
|
+
int ntt_size_bits = (int)bit_length(b_size - 1) + 1;
|
|
127
127
|
if (ntt_size_bits > MAX_NTT32_BITS) {
|
|
128
128
|
rb_raise(rb_eArgError, "Multiply size too large");
|
|
129
129
|
}
|
|
@@ -133,7 +133,7 @@ ntt_multiply(size_t a_size, size_t b_size, uint32_t *a, uint32_t *b, uint32_t *c
|
|
|
133
133
|
uint32_t batch_size = ntt_size - (uint32_t)b_size;
|
|
134
134
|
uint32_t batch_count = (uint32_t)((a_size + batch_size - 1) / batch_size);
|
|
135
135
|
|
|
136
|
-
uint32_t *mem = ruby_xcalloc(
|
|
136
|
+
uint32_t *mem = ruby_xcalloc(ntt_size * 9, sizeof(uint32_t));
|
|
137
137
|
uint32_t *ntt1 = mem;
|
|
138
138
|
uint32_t *ntt2 = mem + ntt_size;
|
|
139
139
|
uint32_t *ntt3 = mem + ntt_size * 2;
|
|
@@ -177,12 +177,12 @@ ntt_multiply(size_t a_size, size_t b_size, uint32_t *a, uint32_t *b, uint32_t *c
|
|
|
177
177
|
// so this sum doesn't overflow uint32_t.
|
|
178
178
|
for (int j = 0; j < 3; j++) {
|
|
179
179
|
// Index check: if dig[j] is non-zero, assign index is within valid range.
|
|
180
|
-
if (dig[j]) c[idx * batch_size + i + 1 - j] += dig[j];
|
|
180
|
+
if (dig[j]) c[idx * batch_size + i + 1 - (uint32_t)j] += dig[j];
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
184
|
uint32_t carry = 0;
|
|
185
|
-
for (int32_t i = (
|
|
185
|
+
for (int32_t i = (int32_t)(a_size + b_size - 1); i >= 0; i--) {
|
|
186
186
|
uint32_t v = c[i] + carry;
|
|
187
187
|
c[i] = v % NTT_DECDIG_BASE;
|
|
188
188
|
carry = v / NTT_DECDIG_BASE;
|
data/lib/bigdecimal/math.rb
CHANGED
|
@@ -144,7 +144,7 @@ module BigMath
|
|
|
144
144
|
x = -x if neg = x < 0
|
|
145
145
|
ex = x.exponent / 3
|
|
146
146
|
x = x._decimal_shift(-3 * ex)
|
|
147
|
-
y = BigDecimal(Math.cbrt(
|
|
147
|
+
y = BigDecimal(Math.cbrt(x.to_f), 0)
|
|
148
148
|
BigDecimal::Internal.newton_loop(prec + BigDecimal::Internal::EXTRA_PREC) do |p|
|
|
149
149
|
y = (2 * y + x.div(y, p).div(y, p)).div(3, p)
|
|
150
150
|
end
|
|
@@ -304,7 +304,7 @@ module BigMath
|
|
|
304
304
|
|
|
305
305
|
# Solve tan(y) - x = 0 with Newton's method
|
|
306
306
|
# Repeat: y -= (tan(y) - x) * cos(y)**2
|
|
307
|
-
y = BigDecimal(Math.atan(
|
|
307
|
+
y = BigDecimal(Math.atan(x.to_f), 0)
|
|
308
308
|
BigDecimal::Internal.newton_loop(n) do |p|
|
|
309
309
|
s = sin(y, p)
|
|
310
310
|
c = (1 - s * s).sqrt(p)
|
|
@@ -605,7 +605,7 @@ module BigMath
|
|
|
605
605
|
return BigDecimal(1) if x > 5000000000 # erf(5000000000) > 1 - 1e-10000000000000000000
|
|
606
606
|
|
|
607
607
|
if x > 8
|
|
608
|
-
xf =
|
|
608
|
+
xf = x.to_f
|
|
609
609
|
log10_erfc = -xf ** 2 / Math.log(10) - Math.log10(xf * Math::PI ** 0.5)
|
|
610
610
|
erfc_prec = [prec + log10_erfc.ceil, 1].max
|
|
611
611
|
erfc = _erfc_asymptotic(x, erfc_prec)
|
|
@@ -637,7 +637,7 @@ module BigMath
|
|
|
637
637
|
return BigDecimal::Internal.nan_computation_result if x.nan?
|
|
638
638
|
return BigDecimal(1 - x.infinite?) if x.infinite?
|
|
639
639
|
return BigDecimal(1).sub(erf(x, prec + BigDecimal::Internal::EXTRA_PREC), prec) if x < 0.5
|
|
640
|
-
return BigDecimal
|
|
640
|
+
return BigDecimal::Internal.underflow_computation_result if x > 5000000000 # erfc(5000000000) < 1e-10000000000000000000 (underflow)
|
|
641
641
|
|
|
642
642
|
if x >= 8
|
|
643
643
|
y = _erfc_asymptotic(x, prec)
|
|
@@ -647,7 +647,7 @@ module BigMath
|
|
|
647
647
|
# erfc(x) = 1 - erf(x) < exp(-x**2)/x/sqrt(pi)
|
|
648
648
|
# Precision of erf(x) needs about log10(exp(-x**2)/x/sqrt(pi)) extra digits
|
|
649
649
|
log10 = 2.302585092994046
|
|
650
|
-
xf =
|
|
650
|
+
xf = x.to_f
|
|
651
651
|
high_prec = prec + BigDecimal::Internal::EXTRA_PREC + ((xf**2 + Math.log(xf) + Math.log(Math::PI)/2) / log10).ceil
|
|
652
652
|
BigDecimal(1).sub(erf(x, high_prec), prec)
|
|
653
653
|
end
|
|
@@ -698,7 +698,7 @@ module BigMath
|
|
|
698
698
|
# sqrt(2)/2 + k*log(k) - k - 2*k*log(x) < -prec*log(10)
|
|
699
699
|
# and the left side is minimized when k = x**2.
|
|
700
700
|
prec += BigDecimal::Internal::EXTRA_PREC
|
|
701
|
-
xf =
|
|
701
|
+
xf = x.to_f
|
|
702
702
|
kmax = (1..(xf ** 2).floor).bsearch do |k|
|
|
703
703
|
Math.log(2) / 2 + k * Math.log(k) - k - 2 * k * Math.log(xf) < -prec * Math.log(10)
|
|
704
704
|
end
|
data/lib/bigdecimal.rb
CHANGED
|
@@ -57,6 +57,13 @@ class BigDecimal
|
|
|
57
57
|
BigDecimal::INFINITY
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
+
def self.underflow_computation_result # :nodoc:
|
|
61
|
+
if BigDecimal.mode(BigDecimal::EXCEPTION_ALL).anybits?(BigDecimal::EXCEPTION_UNDERFLOW)
|
|
62
|
+
raise FloatDomainError, 'Exponent underflow'
|
|
63
|
+
end
|
|
64
|
+
BigDecimal(0)
|
|
65
|
+
end
|
|
66
|
+
|
|
60
67
|
def self.nan_computation_result # :nodoc:
|
|
61
68
|
if BigDecimal.mode(BigDecimal::EXCEPTION_ALL).anybits?(BigDecimal::EXCEPTION_NaN)
|
|
62
69
|
raise FloatDomainError, "Computation results to 'NaN'"
|
|
@@ -76,18 +83,9 @@ class BigDecimal
|
|
|
76
83
|
end
|
|
77
84
|
end
|
|
78
85
|
|
|
79
|
-
# Fast and rough conversion to float for mathematical calculations.
|
|
80
|
-
# Bigdecimal#to_f is slow when n_significant_digits is large.
|
|
81
|
-
# This is because to_f internally converts BigDecimal to String
|
|
82
|
-
# to get the exact nearest float representation.
|
|
83
|
-
# TODO: Remove this workaround when BigDecimal#to_f is optimized.
|
|
84
|
-
def self.fast_to_f(x) # :nodoc:
|
|
85
|
-
x.n_significant_digits < 40 ? x.to_f : x.mult(1, 20).to_f
|
|
86
|
-
end
|
|
87
|
-
|
|
88
86
|
# Calculates Math.log(x.to_f) considering large or small exponent
|
|
89
87
|
def self.float_log(x) # :nodoc:
|
|
90
|
-
Math.log(
|
|
88
|
+
Math.log(x._decimal_shift(-x.exponent).to_f) + x.exponent * Math.log(10)
|
|
91
89
|
end
|
|
92
90
|
|
|
93
91
|
# Calculating Taylor series sum using binary splitting method
|
|
@@ -277,7 +275,7 @@ class BigDecimal
|
|
|
277
275
|
|
|
278
276
|
ex = exponent / 2
|
|
279
277
|
x = _decimal_shift(-2 * ex)
|
|
280
|
-
y = BigDecimal(Math.sqrt(
|
|
278
|
+
y = BigDecimal(Math.sqrt(x.to_f), 0)
|
|
281
279
|
Internal.newton_loop(prec + BigDecimal::Internal::EXTRA_PREC) do |p|
|
|
282
280
|
y = y.add(x.div(y, p), p).div(2, p)
|
|
283
281
|
end
|
|
@@ -359,7 +357,17 @@ module BigMath
|
|
|
359
357
|
prec = BigDecimal::Internal.coerce_validate_prec(prec, :exp)
|
|
360
358
|
x = BigDecimal::Internal.coerce_to_bigdecimal(x, prec, :exp)
|
|
361
359
|
return BigDecimal::Internal.nan_computation_result if x.nan?
|
|
362
|
-
|
|
360
|
+
if x.infinite? || x.exponent >= 21 # exp(10**20) and exp(-10**20) overflows/underflows 64-bit exponent
|
|
361
|
+
if x.positive?
|
|
362
|
+
return BigDecimal::Internal.infinity_computation_result
|
|
363
|
+
elsif x.infinite?
|
|
364
|
+
# exp(-Infinity) is +0 by definition, this is not an underflow.
|
|
365
|
+
return BigDecimal(0)
|
|
366
|
+
else
|
|
367
|
+
return BigDecimal::Internal.underflow_computation_result
|
|
368
|
+
end
|
|
369
|
+
end
|
|
370
|
+
|
|
363
371
|
return BigDecimal(1) if x.zero?
|
|
364
372
|
|
|
365
373
|
# exp(x * 10**cnt) = exp(x)**(10**cnt)
|