diff options
Diffstat (limited to '')
| -rw-r--r-- | src/lib/libc/stdlib/strtod.c | 106 |
1 files changed, 75 insertions, 31 deletions
diff --git a/src/lib/libc/stdlib/strtod.c b/src/lib/libc/stdlib/strtod.c index a8a52e02c5..253bc4ddc0 100644 --- a/src/lib/libc/stdlib/strtod.c +++ b/src/lib/libc/stdlib/strtod.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: strtod.c,v 1.28 2006/10/13 03:50:14 deraadt Exp $ */ | 1 | /* $OpenBSD: strtod.c,v 1.29 2006/10/29 18:45:56 deraadt Exp $ */ |
| 2 | /**************************************************************** | 2 | /**************************************************************** |
| 3 | * | 3 | * |
| 4 | * The author of this software is David M. Gay. | 4 | * The author of this software is David M. Gay. |
| @@ -125,6 +125,11 @@ | |||
| 125 | #define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);} | 125 | #define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);} |
| 126 | #endif | 126 | #endif |
| 127 | 127 | ||
| 128 | #include "thread_private.h" | ||
| 129 | |||
| 130 | _THREAD_PRIVATE_KEY(dtoa); | ||
| 131 | _THREAD_PRIVATE_KEY(pow5mult); | ||
| 132 | |||
| 128 | #ifdef __cplusplus | 133 | #ifdef __cplusplus |
| 129 | #include "malloc.h" | 134 | #include "malloc.h" |
| 130 | #include "memory.h" | 135 | #include "memory.h" |
| @@ -365,21 +370,35 @@ Bigint { | |||
| 365 | 370 | ||
| 366 | static Bigint *freelist[Kmax+1]; | 371 | static Bigint *freelist[Kmax+1]; |
| 367 | 372 | ||
| 373 | #define PRIVATE_MEM 2304 | ||
| 374 | #define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double)) | ||
| 375 | static double private_mem[PRIVATE_mem], *pmem_next = private_mem; | ||
| 376 | |||
| 368 | static Bigint * | 377 | static Bigint * |
| 369 | Balloc(int k) | 378 | Balloc(int k) |
| 370 | { | 379 | { |
| 371 | int x; | 380 | int x; |
| 381 | unsigned int len; | ||
| 372 | Bigint *rv; | 382 | Bigint *rv; |
| 373 | 383 | ||
| 384 | _THREAD_PRIVATE_MUTEX_LOCK(dtoa); | ||
| 374 | if ((rv = freelist[k])) { | 385 | if ((rv = freelist[k])) { |
| 375 | freelist[k] = rv->next; | 386 | freelist[k] = rv->next; |
| 376 | } | 387 | } |
| 377 | else { | 388 | else { |
| 378 | x = 1 << k; | 389 | x = 1 << k; |
| 379 | rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(Long)); | 390 | len = (sizeof(Bigint) + (x-1)*sizeof(Long) + sizeof(double) - 1) |
| 391 | /sizeof(double); | ||
| 392 | if (pmem_next - private_mem + len <= PRIVATE_mem) { | ||
| 393 | rv = (Bigint *)pmem_next; | ||
| 394 | pmem_next += len; | ||
| 395 | } | ||
| 396 | else | ||
| 397 | rv = (Bigint *)MALLOC(len *sizeof(double)); | ||
| 380 | rv->k = k; | 398 | rv->k = k; |
| 381 | rv->maxwds = x; | 399 | rv->maxwds = x; |
| 382 | } | 400 | } |
| 401 | _THREAD_PRIVATE_MUTEX_UNLOCK(dtoa); | ||
| 383 | rv->sign = rv->wds = 0; | 402 | rv->sign = rv->wds = 0; |
| 384 | return rv; | 403 | return rv; |
| 385 | } | 404 | } |
| @@ -388,14 +407,55 @@ Balloc(int k) | |||
| 388 | Bfree(Bigint *v) | 407 | Bfree(Bigint *v) |
| 389 | { | 408 | { |
| 390 | if (v) { | 409 | if (v) { |
| 410 | _THREAD_PRIVATE_MUTEX_LOCK(dtoa); | ||
| 391 | v->next = freelist[v->k]; | 411 | v->next = freelist[v->k]; |
| 392 | freelist[v->k] = v; | 412 | freelist[v->k] = v; |
| 413 | _THREAD_PRIVATE_MUTEX_UNLOCK(dtoa); | ||
| 393 | } | 414 | } |
| 394 | } | 415 | } |
| 395 | 416 | ||
| 396 | #define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \ | 417 | #define Bcopy(x,y) memcpy((char *)&x->sign, (char *)&y->sign, \ |
| 397 | y->wds*sizeof(Long) + 2*sizeof(int)) | 418 | y->wds*sizeof(Long) + 2*sizeof(int)) |
| 398 | 419 | ||
| 420 | /* return value is only used as a simple string, so mis-aligned parts | ||
| 421 | * inside the Bigint are not at risk on strict align architectures | ||
| 422 | */ | ||
| 423 | static char * | ||
| 424 | rv_alloc(int i) | ||
| 425 | { | ||
| 426 | int j, k, *r; | ||
| 427 | |||
| 428 | j = sizeof(ULong); | ||
| 429 | for(k = 0; | ||
| 430 | sizeof(Bigint) - sizeof(ULong) - sizeof(int) + j <= i; | ||
| 431 | j <<= 1) | ||
| 432 | k++; | ||
| 433 | r = (int*)Balloc(k); | ||
| 434 | *r = k; | ||
| 435 | return (char *)(r+1); | ||
| 436 | } | ||
| 437 | |||
| 438 | static char * | ||
| 439 | nrv_alloc(char *s, char **rve, int n) | ||
| 440 | { | ||
| 441 | char *rv, *t; | ||
| 442 | |||
| 443 | t = rv = rv_alloc(n); | ||
| 444 | while((*t = *s++) !=0) | ||
| 445 | t++; | ||
| 446 | if (rve) | ||
| 447 | *rve = t; | ||
| 448 | return rv; | ||
| 449 | } | ||
| 450 | |||
| 451 | void | ||
| 452 | __freedtoa(char *s) | ||
| 453 | { | ||
| 454 | Bigint *b = (Bigint *)((int *)s - 1); | ||
| 455 | b->maxwds = 1 << (b->k = *(int*)b); | ||
| 456 | Bfree(b); | ||
| 457 | } | ||
| 458 | |||
| 399 | static Bigint * | 459 | static Bigint * |
| 400 | multadd(Bigint *b, int m, int a) /* multiply by m and add a */ | 460 | multadd(Bigint *b, int m, int a) /* multiply by m and add a */ |
| 401 | { | 461 | { |
| @@ -651,8 +711,10 @@ pow5mult(Bigint *b, int k) | |||
| 651 | return b; | 711 | return b; |
| 652 | if (!(p5 = p5s)) { | 712 | if (!(p5 = p5s)) { |
| 653 | /* first time */ | 713 | /* first time */ |
| 714 | _THREAD_PRIVATE_MUTEX_LOCK(pow5mult); | ||
| 654 | p5 = p5s = i2b(625); | 715 | p5 = p5s = i2b(625); |
| 655 | p5->next = 0; | 716 | p5->next = 0; |
| 717 | _THREAD_PRIVATE_MUTEX_UNLOCK(pow5mult); | ||
| 656 | } | 718 | } |
| 657 | for(;;) { | 719 | for(;;) { |
| 658 | if (k & 1) { | 720 | if (k & 1) { |
| @@ -663,8 +725,12 @@ pow5mult(Bigint *b, int k) | |||
| 663 | if (!(k >>= 1)) | 725 | if (!(k >>= 1)) |
| 664 | break; | 726 | break; |
| 665 | if (!(p51 = p5->next)) { | 727 | if (!(p51 = p5->next)) { |
| 666 | p51 = p5->next = mult(p5,p5); | 728 | _THREAD_PRIVATE_MUTEX_LOCK(pow5mult); |
| 667 | p51->next = 0; | 729 | if (!(p51 = p5->next)) { |
| 730 | p51 = p5->next = mult(p5,p5); | ||
| 731 | p51->next = 0; | ||
| 732 | } | ||
| 733 | _THREAD_PRIVATE_MUTEX_UNLOCK(pow5mult); | ||
| 668 | } | 734 | } |
| 669 | p5 = p51; | 735 | p5 = p51; |
| 670 | } | 736 | } |
| @@ -1848,17 +1914,9 @@ __dtoa(double _d, int mode, int ndigits, int *decpt, int *sign, char **rve) | |||
| 1848 | Bigint *b, *b1, *delta, *mlo, *mhi, *S; | 1914 | Bigint *b, *b1, *delta, *mlo, *mhi, *S; |
| 1849 | double ds; | 1915 | double ds; |
| 1850 | char *s, *s0; | 1916 | char *s, *s0; |
| 1851 | static Bigint *result; | ||
| 1852 | static int result_k; | ||
| 1853 | _double d, d2, eps; | 1917 | _double d, d2, eps; |
| 1854 | 1918 | ||
| 1855 | value(d) = _d; | 1919 | value(d) = _d; |
| 1856 | if (result) { | ||
| 1857 | result->k = result_k; | ||
| 1858 | result->maxwds = 1 << result_k; | ||
| 1859 | Bfree(result); | ||
| 1860 | result = 0; | ||
| 1861 | } | ||
| 1862 | 1920 | ||
| 1863 | if (word0(d) & Sign_bit) { | 1921 | if (word0(d) & Sign_bit) { |
| 1864 | /* set sign for everything, including 0's and NaNs */ | 1922 | /* set sign for everything, including 0's and NaNs */ |
| @@ -1877,18 +1935,11 @@ __dtoa(double _d, int mode, int ndigits, int *decpt, int *sign, char **rve) | |||
| 1877 | { | 1935 | { |
| 1878 | /* Infinity or NaN */ | 1936 | /* Infinity or NaN */ |
| 1879 | *decpt = 9999; | 1937 | *decpt = 9999; |
| 1880 | s = | ||
| 1881 | #ifdef IEEE_Arith | 1938 | #ifdef IEEE_Arith |
| 1882 | !word1(d) && !(word0(d) & 0xfffff) ? ndigits < 8 ? "Inf" : "Infinity" : | 1939 | if (!word1(d) && !(word0(d) & 0xfffff)) |
| 1940 | return nrv_alloc("Infinity", rve, 8); | ||
| 1883 | #endif | 1941 | #endif |
| 1884 | "NaN"; | 1942 | return nrv_alloc("NaN", rve, 3); |
| 1885 | if (rve) | ||
| 1886 | *rve = | ||
| 1887 | #ifdef IEEE_Arith | ||
| 1888 | s[3] ? s + 8 : | ||
| 1889 | #endif | ||
| 1890 | s + 3; | ||
| 1891 | return s; | ||
| 1892 | } | 1943 | } |
| 1893 | #endif | 1944 | #endif |
| 1894 | #ifdef IBM | 1945 | #ifdef IBM |
| @@ -1896,10 +1947,7 @@ __dtoa(double _d, int mode, int ndigits, int *decpt, int *sign, char **rve) | |||
| 1896 | #endif | 1947 | #endif |
| 1897 | if (!value(d)) { | 1948 | if (!value(d)) { |
| 1898 | *decpt = 1; | 1949 | *decpt = 1; |
| 1899 | s = "0"; | 1950 | return nrv_alloc("0", rve, 1); |
| 1900 | if (rve) | ||
| 1901 | *rve = s + 1; | ||
| 1902 | return s; | ||
| 1903 | } | 1951 | } |
| 1904 | 1952 | ||
| 1905 | b = d2b(value(d), &be, &bbits); | 1953 | b = d2b(value(d), &be, &bbits); |
| @@ -2021,11 +2069,7 @@ __dtoa(double _d, int mode, int ndigits, int *decpt, int *sign, char **rve) | |||
| 2021 | if (i <= 0) | 2069 | if (i <= 0) |
| 2022 | i = 1; | 2070 | i = 1; |
| 2023 | } | 2071 | } |
| 2024 | j = sizeof(ULong); | 2072 | s = s0 = rv_alloc(i); |
| 2025 | for(result_k = 0; sizeof(Bigint) - sizeof(ULong) + j <= i; | ||
| 2026 | j <<= 1) result_k++; | ||
| 2027 | result = Balloc(result_k); | ||
| 2028 | s = s0 = (char *)result; | ||
| 2029 | 2073 | ||
| 2030 | if (ilim >= 0 && ilim <= Quick_max && try_quick) { | 2074 | if (ilim >= 0 && ilim <= Quick_max && try_quick) { |
| 2031 | 2075 | ||
