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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 937928a0baf09e4c2e5bf45b2fa608e1aa20601cf7cd27a8ebaf679874e6196f
4
- data.tar.gz: a053c6e868c7e55ad9a35262bfd645314fd908dbae5969935c44530a124cfcc4
3
+ metadata.gz: 922981a841d43e8269ac09725757bd02512ba596903b2da2ab2458e842957833
4
+ data.tar.gz: 34b59473beafbb51888ef2700b0c44ee721025952c1b578c4affa6cb60e91d90
5
5
  SHA512:
6
- metadata.gz: 4a4a41830aab00fd3bef041c64f9f6357891706ca11004696c5d815b7582f6f4f2cbd00a606900cfe4a5bce57585d46523e25da8085c2bf18aa95bbe9afd27ec
7
- data.tar.gz: fe5b587431cca8921613367e236a9844fd3c65f8f53d8b2ae16fe1ed54aac455bfff9a50783256ec2d9e0f5523bc01a3eb9ce0ffc16482cded6026cc03b8c2c0
6
+ metadata.gz: 00e7aedfc9b90c0e82297880c750010e37b8aa427c122343418bbbc3b656a94583a818b0980d2a91b9a7c22aa9c5cc26d621536c33f0d5ec70b87bf9585feed7
7
+ data.tar.gz: 0b54105583917681020ed7d451f9a39c68f9805e9079b48cc83b7031d43ab5e070945dd4899d73e99925022f4a3462c6f9f277062af0281b1455ed16b0a76f49
@@ -33,7 +33,7 @@
33
33
  #include "div.h"
34
34
  #include "static_assert.h"
35
35
 
36
- #define BIGDECIMAL_VERSION "4.1.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
- xfree(p);
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
- snprintf(buf, buflen, "%lu", (unsigned long)nn); /* The leading zero(s) */
5400
- buf += strlen(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
- /* The reading zero(s) */
5496
- size_t n = (size_t)snprintf(p, plen, "%lu", (unsigned long)nn);
5497
- if (n > plen) goto overflow;
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
- snprintf(p, plen, "e%"PRIdSIZE, ex);
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 += start;
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 - div_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 xmalloc
239
+ #define MALLOC malloc
225
240
  #endif
226
241
  #ifdef FREE
227
242
  extern void FREE(void*);
228
243
  #else
229
- #define FREE xfree
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
- #ifndef Omit_Private_Memory
535
- size_t len;
536
- #endif
537
-
538
- rv = 0;
539
- ACQUIRE_DTOA_LOCK(0);
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
- Bfree(Bigint *v)
550
+ Bclear(Bigint **vp)
583
551
  {
584
- Bigint *vn;
585
- if (v) {
586
- if (v->k > Kmax) {
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
- if (!(p5 = p5s)) {
886
- /* first time */
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
- if (!(p51 = p5->next)) {
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, *++s));
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
- if (bd5 > 0)
2036
+ if (!bb) goto retfree;
2037
+ }
2038
+ if (bd5 > 0) {
2051
2039
  bd = pow5mult(bd, bd5);
2052
- if (bd2 > 0)
2040
+ if (!bd) goto retfree;
2041
+ }
2042
+ if (bd2 > 0) {
2053
2043
  bd = lshift(bd, bd2);
2054
- if (bs2 > 0)
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 = ndigits + k + 1;
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 (s5 > 0)
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
- if (s2 > 0)
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 (leftright)
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 (mlo == mhi)
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(sizeof(uint32_t), ntt_size * 9);
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 = (uint32_t)(a_size + b_size - 1); i >= 0; 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;
@@ -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(BigDecimal::Internal.fast_to_f(x)), 0)
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(BigDecimal::Internal.fast_to_f(x)), 0)
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 = BigDecimal::Internal.fast_to_f(x)
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(0) if x > 5000000000 # erfc(5000000000) < 1e-10000000000000000000 (underflow)
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 = BigDecimal::Internal.fast_to_f(x)
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 = BigDecimal::Internal.fast_to_f(x)
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(fast_to_f(x._decimal_shift(-x.exponent))) + x.exponent * Math.log(10)
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(BigDecimal::Internal.fast_to_f(x)), 0)
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
- return x.positive? ? BigDecimal::Internal.infinity_computation_result : BigDecimal(0) if x.infinite?
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)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bigdecimal
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.1
4
+ version: 4.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kenta Murata