00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "ruby/ruby.h"
00013 #include "internal.h"
00014
00015 #include <ctype.h>
00016 #include <stdio.h>
00017 #include <errno.h>
00018 #include <math.h>
00019 #include <float.h>
00020
00021 #ifdef _WIN32
00022 #include "missing/file.h"
00023 #endif
00024
00025 #include "ruby/util.h"
00026
00027 unsigned long
00028 ruby_scan_oct(const char *start, size_t len, size_t *retlen)
00029 {
00030 register const char *s = start;
00031 register unsigned long retval = 0;
00032
00033 while (len-- && *s >= '0' && *s <= '7') {
00034 retval <<= 3;
00035 retval |= *s++ - '0';
00036 }
00037 *retlen = (int)(s - start);
00038 return retval;
00039 }
00040
00041 unsigned long
00042 ruby_scan_hex(const char *start, size_t len, size_t *retlen)
00043 {
00044 static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF";
00045 register const char *s = start;
00046 register unsigned long retval = 0;
00047 const char *tmp;
00048
00049 while (len-- && *s && (tmp = strchr(hexdigit, *s))) {
00050 retval <<= 4;
00051 retval |= (tmp - hexdigit) & 15;
00052 s++;
00053 }
00054 *retlen = (int)(s - start);
00055 return retval;
00056 }
00057
00058 static unsigned long
00059 scan_digits(const char *str, int base, size_t *retlen, int *overflow)
00060 {
00061 static signed char table[] = {
00062
00063 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00064 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00065 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00066 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
00067 -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
00068 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1,
00069 -1,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
00070 25,26,27,28,29,30,31,32,33,34,35,-1,-1,-1,-1,-1,
00071 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00072 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00073 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00074 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00075 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00076 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00077 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00078 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
00079 };
00080
00081 const char *start = str;
00082 unsigned long ret = 0, x;
00083 unsigned long mul_overflow = (~(unsigned long)0) / base;
00084 int c;
00085 *overflow = 0;
00086
00087 while ((c = (unsigned char)*str++) != '\0') {
00088 int d = table[c];
00089 if (d == -1 || base <= d) {
00090 *retlen = (str-1) - start;
00091 return ret;
00092 }
00093 if (mul_overflow < ret)
00094 *overflow = 1;
00095 ret *= base;
00096 x = ret;
00097 ret += d;
00098 if (ret < x)
00099 *overflow = 1;
00100 }
00101 *retlen = (str-1) - start;
00102 return ret;
00103 }
00104
00105 unsigned long
00106 ruby_strtoul(const char *str, char **endptr, int base)
00107 {
00108 int c, b, overflow;
00109 int sign = 0;
00110 size_t len;
00111 unsigned long ret;
00112 const char *subject_found = str;
00113
00114 if (base == 1 || 36 < base) {
00115 errno = EINVAL;
00116 return 0;
00117 }
00118
00119 while ((c = *str) && ISSPACE(c))
00120 str++;
00121
00122 if (c == '+') {
00123 sign = 1;
00124 str++;
00125 }
00126 else if (c == '-') {
00127 sign = -1;
00128 str++;
00129 }
00130
00131 if (str[0] == '0') {
00132 subject_found = str+1;
00133 if (base == 0 || base == 16) {
00134 if (str[1] == 'x' || str[1] == 'X') {
00135 b = 16;
00136 str += 2;
00137 }
00138 else {
00139 b = base == 0 ? 8 : 16;
00140 str++;
00141 }
00142 }
00143 else {
00144 b = base;
00145 str++;
00146 }
00147 }
00148 else {
00149 b = base == 0 ? 10 : base;
00150 }
00151
00152 ret = scan_digits(str, b, &len, &overflow);
00153
00154 if (0 < len)
00155 subject_found = str+len;
00156
00157 if (endptr)
00158 *endptr = (char*)subject_found;
00159
00160 if (overflow) {
00161 errno = ERANGE;
00162 return ULONG_MAX;
00163 }
00164
00165 if (sign < 0) {
00166 ret = (unsigned long)(-(long)ret);
00167 return ret;
00168 }
00169 else {
00170 return ret;
00171 }
00172 }
00173
00174 #include <sys/types.h>
00175 #include <sys/stat.h>
00176 #ifdef HAVE_UNISTD_H
00177 #include <unistd.h>
00178 #endif
00179 #if defined(HAVE_FCNTL_H)
00180 #include <fcntl.h>
00181 #endif
00182
00183 #ifndef S_ISDIR
00184 # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
00185 #endif
00186
00187 #if defined(__CYGWIN32__) || defined(_WIN32)
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 static int valid_filename(const char *s);
00259
00260 static const char suffix1[] = ".$$$";
00261 static const char suffix2[] = ".~~~";
00262
00263 #define strEQ(s1,s2) (strcmp((s1),(s2)) == 0)
00264
00265 void
00266 ruby_add_suffix(VALUE str, const char *suffix)
00267 {
00268 long baselen;
00269 long extlen = strlen(suffix);
00270 long slen;
00271 char buf[1024];
00272 const char *name;
00273 const char *ext;
00274 long len;
00275
00276 name = StringValueCStr(str);
00277 slen = strlen(name);
00278 if (slen > (long)(sizeof(buf) - 1))
00279 rb_fatal("Cannot do inplace edit on long filename (%ld characters)",
00280 slen);
00281
00282
00283 rb_str_cat(str, suffix, extlen);
00284 if (valid_filename(RSTRING_PTR(str))) return;
00285
00286
00287 rb_str_resize(str, slen);
00288 name = StringValueCStr(str);
00289 ext = ruby_find_extname(name, &len);
00290
00291 if (*suffix == '.') {
00292 if (ext) {
00293 if (strEQ(ext, suffix)) {
00294 extlen = sizeof(suffix1) - 1;
00295 suffix = strEQ(suffix, suffix1) ? suffix2 : suffix1;
00296 }
00297 slen = ext - name;
00298 }
00299 rb_str_resize(str, slen);
00300 rb_str_cat(str, suffix, extlen);
00301 }
00302 else {
00303 char *p = buf, *q;
00304 strncpy(buf, name, slen);
00305 if (ext)
00306 p += (ext - name);
00307 else
00308 p += slen;
00309 p[len] = '\0';
00310 if (suffix[1] == '\0') {
00311 q = (char *)ruby_find_basename(buf, &baselen, 0);
00312 if (len <= 3) {
00313 if (len == 0 && baselen >= 8 && p + 3 <= buf + sizeof(buf)) p[len++] = '.';
00314 p[len] = *suffix;
00315 p[++len] = '\0';
00316 }
00317 else if (q && baselen < 8) {
00318 q += baselen;
00319 *q++ = *suffix;
00320 if (ext) {
00321 strncpy(q, ext, ext - name);
00322 q[ext - name + 1] = '\0';
00323 }
00324 else
00325 *q = '\0';
00326 }
00327 else if (len == 4 && p[3] != *suffix)
00328 p[3] = *suffix;
00329 else if (baselen == 8 && q[7] != *suffix)
00330 q[7] = *suffix;
00331 else
00332 goto fallback;
00333 }
00334 else {
00335 fallback:
00336 (void)memcpy(p, !ext || strEQ(ext, suffix1) ? suffix2 : suffix1, 5);
00337 }
00338 rb_str_resize(str, strlen(buf));
00339 memcpy(RSTRING_PTR(str), buf, RSTRING_LEN(str));
00340 }
00341 }
00342
00343 static int
00344 valid_filename(const char *s)
00345 {
00346 int fd;
00347
00348
00349
00350
00351
00352 if ((fd = open(s, O_CREAT|O_EXCL, 0666)) >= 0) {
00353 close(fd);
00354 unlink(s);
00355 return 1;
00356 }
00357 else if (errno == EEXIST) {
00358
00359 return 1;
00360 }
00361 return 0;
00362 }
00363 #endif
00364
00365
00366
00367
00368 #define A ((int*)a)
00369 #define B ((int*)b)
00370 #define C ((int*)c)
00371 #define D ((int*)d)
00372
00373 #define mmprepare(base, size) do {\
00374 if (((VALUE)(base) & (0x3)) == 0)\
00375 if ((size) >= 16) mmkind = 1;\
00376 else mmkind = 0;\
00377 else mmkind = -1;\
00378 high = ((size) & (~0xf));\
00379 low = ((size) & 0x0c);\
00380 } while (0)\
00381
00382 #define mmarg mmkind, size, high, low
00383
00384 static void mmswap_(register char *a, register char *b, int mmkind, size_t size, size_t high, size_t low)
00385 {
00386 register int s;
00387 if (a == b) return;
00388 if (mmkind >= 0) {
00389 if (mmkind > 0) {
00390 register char *t = a + high;
00391 do {
00392 s = A[0]; A[0] = B[0]; B[0] = s;
00393 s = A[1]; A[1] = B[1]; B[1] = s;
00394 s = A[2]; A[2] = B[2]; B[2] = s;
00395 s = A[3]; A[3] = B[3]; B[3] = s; a += 16; b += 16;
00396 } while (a < t);
00397 }
00398 if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = s;
00399 if (low >= 8) { s = A[1]; A[1] = B[1]; B[1] = s;
00400 if (low == 12) {s = A[2]; A[2] = B[2]; B[2] = s;}}}
00401 }
00402 else {
00403 register char *t = a + size;
00404 do {s = *a; *a++ = *b; *b++ = s;} while (a < t);
00405 }
00406 }
00407 #define mmswap(a,b) mmswap_((a),(b),mmarg)
00408
00409 static void mmrot3_(register char *a, register char *b, register char *c, int mmkind, size_t size, size_t high, size_t low)
00410 {
00411 register int s;
00412 if (mmkind >= 0) {
00413 if (mmkind > 0) {
00414 register char *t = a + high;
00415 do {
00416 s = A[0]; A[0] = B[0]; B[0] = C[0]; C[0] = s;
00417 s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s;
00418 s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s;
00419 s = A[3]; A[3] = B[3]; B[3] = C[3]; C[3] = s; a += 16; b += 16; c += 16;
00420 } while (a < t);
00421 }
00422 if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = C[0]; C[0] = s;
00423 if (low >= 8) { s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s;
00424 if (low == 12) {s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s;}}}
00425 }
00426 else {
00427 register char *t = a + size;
00428 do {s = *a; *a++ = *b; *b++ = *c; *c++ = s;} while (a < t);
00429 }
00430 }
00431 #define mmrot3(a,b,c) mmrot3_((a),(b),(c),mmarg)
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442 typedef struct { char *LL, *RR; } stack_node;
00443 #define PUSH(ll,rr) do { top->LL = (ll); top->RR = (rr); ++top; } while (0)
00444 #define POP(ll,rr) do { --top; (ll) = top->LL; (rr) = top->RR; } while (0)
00445
00446 #define med3(a,b,c) ((*cmp)((a),(b),d)<0 ? \
00447 ((*cmp)((b),(c),d)<0 ? (b) : ((*cmp)((a),(c),d)<0 ? (c) : (a))) : \
00448 ((*cmp)((b),(c),d)>0 ? (b) : ((*cmp)((a),(c),d)<0 ? (a) : (c))))
00449
00450 void
00451 ruby_qsort(void* base, const size_t nel, const size_t size,
00452 int (*cmp)(const void*, const void*, void*), void *d)
00453 {
00454 register char *l, *r, *m;
00455 register int t, eq_l, eq_r;
00456 char *L = base;
00457 char *R = (char*)base + size*(nel-1);
00458 size_t chklim = 63;
00459 stack_node stack[32], *top = stack;
00460 int mmkind;
00461 size_t high, low, n;
00462
00463 if (nel <= 1) return;
00464 mmprepare(base, size);
00465 goto start;
00466
00467 nxt:
00468 if (stack == top) return;
00469 POP(L,R);
00470
00471 for (;;) {
00472 start:
00473 if (L + size == R) {
00474 if ((*cmp)(L,R,d) > 0) mmswap(L,R); goto nxt;
00475 }
00476
00477 l = L; r = R;
00478 n = (r - l + size) / size;
00479 m = l + size * (n >> 1);
00480
00481 if (n >= 60) {
00482 register char *m1;
00483 register char *m3;
00484 if (n >= 200) {
00485 n = size*(n>>3);
00486 {
00487 register char *p1 = l + n;
00488 register char *p2 = p1 + n;
00489 register char *p3 = p2 + n;
00490 m1 = med3(p1, p2, p3);
00491 p1 = m + n;
00492 p2 = p1 + n;
00493 p3 = p2 + n;
00494 m3 = med3(p1, p2, p3);
00495 }
00496 }
00497 else {
00498 n = size*(n>>2);
00499 m1 = l + n;
00500 m3 = m + n;
00501 }
00502 m = med3(m1, m, m3);
00503 }
00504
00505 if ((t = (*cmp)(l,m,d)) < 0) {
00506 if ((t = (*cmp)(m,r,d)) < 0) {
00507 if (chklim && nel >= chklim) {
00508 char *p;
00509 chklim = 0;
00510 for (p=l; p<r; p+=size) if ((*cmp)(p,p+size,d) > 0) goto fail;
00511 goto nxt;
00512 }
00513 fail: goto loopA;
00514 }
00515 if (t > 0) {
00516 if ((*cmp)(l,r,d) <= 0) {mmswap(m,r); goto loopA;}
00517 mmrot3(r,m,l); goto loopA;
00518 }
00519 goto loopB;
00520 }
00521
00522 if (t > 0) {
00523 if ((t = (*cmp)(m,r,d)) > 0) {
00524 if (chklim && nel >= chklim) {
00525 char *p;
00526 chklim = 0;
00527 for (p=l; p<r; p+=size) if ((*cmp)(p,p+size,d) < 0) goto fail2;
00528 while (l<r) {mmswap(l,r); l+=size; r-=size;}
00529 goto nxt;
00530 }
00531 fail2: mmswap(l,r); goto loopA;
00532 }
00533 if (t < 0) {
00534 if ((*cmp)(l,r,d) <= 0) {mmswap(l,m); goto loopB;}
00535 mmrot3(l,m,r); goto loopA;
00536 }
00537 mmswap(l,r); goto loopA;
00538 }
00539
00540 if ((t = (*cmp)(m,r,d)) < 0) {goto loopA;}
00541 if (t > 0) {mmswap(l,r); goto loopB;}
00542
00543
00544 for (;;) {
00545 if ((l += size) == r) goto nxt;
00546 if (l == m) continue;
00547 if ((t = (*cmp)(l,m,d)) > 0) {mmswap(l,r); l = L; goto loopA;}
00548 if (t < 0) {mmswap(L,l); l = L; goto loopB;}
00549 }
00550
00551 loopA: eq_l = 1; eq_r = 1;
00552 for (;;) {
00553 for (;;) {
00554 if ((l += size) == r)
00555 {l -= size; if (l != m) mmswap(m,l); l -= size; goto fin;}
00556 if (l == m) continue;
00557 if ((t = (*cmp)(l,m,d)) > 0) {eq_r = 0; break;}
00558 if (t < 0) eq_l = 0;
00559 }
00560 for (;;) {
00561 if (l == (r -= size))
00562 {l -= size; if (l != m) mmswap(m,l); l -= size; goto fin;}
00563 if (r == m) {m = l; break;}
00564 if ((t = (*cmp)(r,m,d)) < 0) {eq_l = 0; break;}
00565 if (t == 0) break;
00566 }
00567 mmswap(l,r);
00568 }
00569
00570 loopB: eq_l = 1; eq_r = 1;
00571 for (;;) {
00572 for (;;) {
00573 if (l == (r -= size))
00574 {r += size; if (r != m) mmswap(r,m); r += size; goto fin;}
00575 if (r == m) continue;
00576 if ((t = (*cmp)(r,m,d)) < 0) {eq_l = 0; break;}
00577 if (t > 0) eq_r = 0;
00578 }
00579 for (;;) {
00580 if ((l += size) == r)
00581 {r += size; if (r != m) mmswap(r,m); r += size; goto fin;}
00582 if (l == m) {m = r; break;}
00583 if ((t = (*cmp)(l,m,d)) > 0) {eq_r = 0; break;}
00584 if (t == 0) break;
00585 }
00586 mmswap(l,r);
00587 }
00588
00589 fin:
00590 if (eq_l == 0)
00591 if (eq_r == 0)
00592 if (l-L < R-r) {PUSH(r,R); R = l;}
00593 else {PUSH(L,l); L = r;}
00594 else R = l;
00595 else if (eq_r == 0) L = r;
00596 else goto nxt;
00597 }
00598 }
00599
00600 char *
00601 ruby_strdup(const char *str)
00602 {
00603 char *tmp;
00604 size_t len = strlen(str) + 1;
00605
00606 tmp = xmalloc(len);
00607 memcpy(tmp, str, len);
00608
00609 return tmp;
00610 }
00611
00612 char *
00613 ruby_getcwd(void)
00614 {
00615 #ifdef HAVE_GETCWD
00616 int size = 200;
00617 char *buf = xmalloc(size);
00618
00619 while (!getcwd(buf, size)) {
00620 if (errno != ERANGE) {
00621 xfree(buf);
00622 rb_sys_fail("getcwd");
00623 }
00624 size *= 2;
00625 buf = xrealloc(buf, size);
00626 }
00627 #else
00628 # ifndef PATH_MAX
00629 # define PATH_MAX 8192
00630 # endif
00631 char *buf = xmalloc(PATH_MAX+1);
00632
00633 if (!getwd(buf)) {
00634 xfree(buf);
00635 rb_sys_fail("getwd");
00636 }
00637 #endif
00638 return buf;
00639 }
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806 #ifdef WORDS_BIGENDIAN
00807 #define IEEE_BIG_ENDIAN
00808 #else
00809 #define IEEE_LITTLE_ENDIAN
00810 #endif
00811
00812 #ifdef __vax__
00813 #define VAX
00814 #undef IEEE_BIG_ENDIAN
00815 #undef IEEE_LITTLE_ENDIAN
00816 #endif
00817
00818 #if defined(__arm__) && !defined(__VFP_FP__)
00819 #define IEEE_BIG_ENDIAN
00820 #undef IEEE_LITTLE_ENDIAN
00821 #endif
00822
00823 #undef Long
00824 #undef ULong
00825
00826 #if SIZEOF_INT == 4
00827 #define Long int
00828 #define ULong unsigned int
00829 #elif SIZEOF_LONG == 4
00830 #define Long long int
00831 #define ULong unsigned long int
00832 #endif
00833
00834 #if HAVE_LONG_LONG
00835 #define Llong LONG_LONG
00836 #endif
00837
00838 #ifdef DEBUG
00839 #include "stdio.h"
00840 #define Bug(x) {fprintf(stderr, "%s\n", (x)); exit(EXIT_FAILURE);}
00841 #endif
00842
00843 #include "stdlib.h"
00844 #include "string.h"
00845
00846 #ifdef USE_LOCALE
00847 #include "locale.h"
00848 #endif
00849
00850 #ifdef MALLOC
00851 extern void *MALLOC(size_t);
00852 #else
00853 #define MALLOC malloc
00854 #endif
00855
00856 #ifndef Omit_Private_Memory
00857 #ifndef PRIVATE_MEM
00858 #define PRIVATE_MEM 2304
00859 #endif
00860 #define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double))
00861 static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
00862 #endif
00863
00864 #undef IEEE_Arith
00865 #undef Avoid_Underflow
00866 #ifdef IEEE_BIG_ENDIAN
00867 #define IEEE_Arith
00868 #endif
00869 #ifdef IEEE_LITTLE_ENDIAN
00870 #define IEEE_Arith
00871 #endif
00872
00873 #ifdef Bad_float_h
00874
00875 #ifdef IEEE_Arith
00876 #define DBL_DIG 15
00877 #define DBL_MAX_10_EXP 308
00878 #define DBL_MAX_EXP 1024
00879 #define FLT_RADIX 2
00880 #endif
00881
00882 #ifdef IBM
00883 #define DBL_DIG 16
00884 #define DBL_MAX_10_EXP 75
00885 #define DBL_MAX_EXP 63
00886 #define FLT_RADIX 16
00887 #define DBL_MAX 7.2370055773322621e+75
00888 #endif
00889
00890 #ifdef VAX
00891 #define DBL_DIG 16
00892 #define DBL_MAX_10_EXP 38
00893 #define DBL_MAX_EXP 127
00894 #define FLT_RADIX 2
00895 #define DBL_MAX 1.7014118346046923e+38
00896 #endif
00897
00898 #ifndef LONG_MAX
00899 #define LONG_MAX 2147483647
00900 #endif
00901
00902 #else
00903 #include "float.h"
00904 #endif
00905
00906 #ifndef __MATH_H__
00907 #include "math.h"
00908 #endif
00909
00910 #ifdef __cplusplus
00911 extern "C" {
00912 #if 0
00913 }
00914 #endif
00915 #endif
00916
00917 #if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN) + defined(VAX) + defined(IBM) != 1
00918 Exactly one of IEEE_LITTLE_ENDIAN, IEEE_BIG_ENDIAN, VAX, or IBM should be defined.
00919 #endif
00920
00921 typedef union { double d; ULong L[2]; } U;
00922
00923 #ifdef YES_ALIAS
00924 typedef double double_u;
00925 # define dval(x) (x)
00926 # ifdef IEEE_LITTLE_ENDIAN
00927 # define word0(x) (((ULong *)&(x))[1])
00928 # define word1(x) (((ULong *)&(x))[0])
00929 # else
00930 # define word0(x) (((ULong *)&(x))[0])
00931 # define word1(x) (((ULong *)&(x))[1])
00932 # endif
00933 #else
00934 typedef U double_u;
00935 # ifdef IEEE_LITTLE_ENDIAN
00936 # define word0(x) ((x).L[1])
00937 # define word1(x) ((x).L[0])
00938 # else
00939 # define word0(x) ((x).L[0])
00940 # define word1(x) ((x).L[1])
00941 # endif
00942 # define dval(x) ((x).d)
00943 #endif
00944
00945
00946
00947
00948
00949 #if defined(IEEE_LITTLE_ENDIAN) + defined(VAX) + defined(__arm__)
00950 #define Storeinc(a,b,c) (((unsigned short *)(a))[1] = (unsigned short)(b), \
00951 ((unsigned short *)(a))[0] = (unsigned short)(c), (a)++)
00952 #else
00953 #define Storeinc(a,b,c) (((unsigned short *)(a))[0] = (unsigned short)(b), \
00954 ((unsigned short *)(a))[1] = (unsigned short)(c), (a)++)
00955 #endif
00956
00957
00958
00959
00960
00961
00962
00963 #ifdef IEEE_Arith
00964 #define Exp_shift 20
00965 #define Exp_shift1 20
00966 #define Exp_msk1 0x100000
00967 #define Exp_msk11 0x100000
00968 #define Exp_mask 0x7ff00000
00969 #define P 53
00970 #define Bias 1023
00971 #define Emin (-1022)
00972 #define Exp_1 0x3ff00000
00973 #define Exp_11 0x3ff00000
00974 #define Ebits 11
00975 #define Frac_mask 0xfffff
00976 #define Frac_mask1 0xfffff
00977 #define Ten_pmax 22
00978 #define Bletch 0x10
00979 #define Bndry_mask 0xfffff
00980 #define Bndry_mask1 0xfffff
00981 #define LSB 1
00982 #define Sign_bit 0x80000000
00983 #define Log2P 1
00984 #define Tiny0 0
00985 #define Tiny1 1
00986 #define Quick_max 14
00987 #define Int_max 14
00988 #ifndef NO_IEEE_Scale
00989 #define Avoid_Underflow
00990 #ifdef Flush_Denorm
00991 #undef Sudden_Underflow
00992 #endif
00993 #endif
00994
00995 #ifndef Flt_Rounds
00996 #ifdef FLT_ROUNDS
00997 #define Flt_Rounds FLT_ROUNDS
00998 #else
00999 #define Flt_Rounds 1
01000 #endif
01001 #endif
01002
01003 #ifdef Honor_FLT_ROUNDS
01004 #define Rounding rounding
01005 #undef Check_FLT_ROUNDS
01006 #define Check_FLT_ROUNDS
01007 #else
01008 #define Rounding Flt_Rounds
01009 #endif
01010
01011 #else
01012 #undef Check_FLT_ROUNDS
01013 #undef Honor_FLT_ROUNDS
01014 #undef SET_INEXACT
01015 #undef Sudden_Underflow
01016 #define Sudden_Underflow
01017 #ifdef IBM
01018 #undef Flt_Rounds
01019 #define Flt_Rounds 0
01020 #define Exp_shift 24
01021 #define Exp_shift1 24
01022 #define Exp_msk1 0x1000000
01023 #define Exp_msk11 0x1000000
01024 #define Exp_mask 0x7f000000
01025 #define P 14
01026 #define Bias 65
01027 #define Exp_1 0x41000000
01028 #define Exp_11 0x41000000
01029 #define Ebits 8
01030 #define Frac_mask 0xffffff
01031 #define Frac_mask1 0xffffff
01032 #define Bletch 4
01033 #define Ten_pmax 22
01034 #define Bndry_mask 0xefffff
01035 #define Bndry_mask1 0xffffff
01036 #define LSB 1
01037 #define Sign_bit 0x80000000
01038 #define Log2P 4
01039 #define Tiny0 0x100000
01040 #define Tiny1 0
01041 #define Quick_max 14
01042 #define Int_max 15
01043 #else
01044 #undef Flt_Rounds
01045 #define Flt_Rounds 1
01046 #define Exp_shift 23
01047 #define Exp_shift1 7
01048 #define Exp_msk1 0x80
01049 #define Exp_msk11 0x800000
01050 #define Exp_mask 0x7f80
01051 #define P 56
01052 #define Bias 129
01053 #define Exp_1 0x40800000
01054 #define Exp_11 0x4080
01055 #define Ebits 8
01056 #define Frac_mask 0x7fffff
01057 #define Frac_mask1 0xffff007f
01058 #define Ten_pmax 24
01059 #define Bletch 2
01060 #define Bndry_mask 0xffff007f
01061 #define Bndry_mask1 0xffff007f
01062 #define LSB 0x10000
01063 #define Sign_bit 0x8000
01064 #define Log2P 1
01065 #define Tiny0 0x80
01066 #define Tiny1 0
01067 #define Quick_max 15
01068 #define Int_max 15
01069 #endif
01070 #endif
01071
01072 #ifndef IEEE_Arith
01073 #define ROUND_BIASED
01074 #endif
01075
01076 #ifdef RND_PRODQUOT
01077 #define rounded_product(a,b) ((a) = rnd_prod((a), (b)))
01078 #define rounded_quotient(a,b) ((a) = rnd_quot((a), (b)))
01079 extern double rnd_prod(double, double), rnd_quot(double, double);
01080 #else
01081 #define rounded_product(a,b) ((a) *= (b))
01082 #define rounded_quotient(a,b) ((a) /= (b))
01083 #endif
01084
01085 #define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1))
01086 #define Big1 0xffffffff
01087
01088 #ifndef Pack_32
01089 #define Pack_32
01090 #endif
01091
01092 #define FFFFFFFF 0xffffffffUL
01093
01094 #ifdef NO_LONG_LONG
01095 #undef ULLong
01096 #ifdef Just_16
01097 #undef Pack_32
01098
01099
01100
01101
01102
01103 #endif
01104 #else
01105 #ifndef Llong
01106 #define Llong long long
01107 #endif
01108 #ifndef ULLong
01109 #define ULLong unsigned Llong
01110 #endif
01111 #endif
01112
01113 #define MULTIPLE_THREADS 1
01114
01115 #ifndef MULTIPLE_THREADS
01116 #define ACQUIRE_DTOA_LOCK(n)
01117 #define FREE_DTOA_LOCK(n)
01118 #else
01119 #define ACQUIRE_DTOA_LOCK(n)
01120 #define FREE_DTOA_LOCK(n)
01121 #endif
01122
01123 #define Kmax 15
01124
01125 struct Bigint {
01126 struct Bigint *next;
01127 int k, maxwds, sign, wds;
01128 ULong x[1];
01129 };
01130
01131 typedef struct Bigint Bigint;
01132
01133 static Bigint *freelist[Kmax+1];
01134
01135 static Bigint *
01136 Balloc(int k)
01137 {
01138 int x;
01139 Bigint *rv;
01140 #ifndef Omit_Private_Memory
01141 size_t len;
01142 #endif
01143
01144 ACQUIRE_DTOA_LOCK(0);
01145 if ((rv = freelist[k]) != 0) {
01146 freelist[k] = rv->next;
01147 }
01148 else {
01149 x = 1 << k;
01150 #ifdef Omit_Private_Memory
01151 rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
01152 #else
01153 len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1)
01154 /sizeof(double);
01155 if (pmem_next - private_mem + len <= PRIVATE_mem) {
01156 rv = (Bigint*)pmem_next;
01157 pmem_next += len;
01158 }
01159 else
01160 rv = (Bigint*)MALLOC(len*sizeof(double));
01161 #endif
01162 rv->k = k;
01163 rv->maxwds = x;
01164 }
01165 FREE_DTOA_LOCK(0);
01166 rv->sign = rv->wds = 0;
01167 return rv;
01168 }
01169
01170 static void
01171 Bfree(Bigint *v)
01172 {
01173 if (v) {
01174 ACQUIRE_DTOA_LOCK(0);
01175 v->next = freelist[v->k];
01176 freelist[v->k] = v;
01177 FREE_DTOA_LOCK(0);
01178 }
01179 }
01180
01181 #define Bcopy(x,y) memcpy((char *)&(x)->sign, (char *)&(y)->sign, \
01182 (y)->wds*sizeof(Long) + 2*sizeof(int))
01183
01184 static Bigint *
01185 multadd(Bigint *b, int m, int a)
01186 {
01187 int i, wds;
01188 ULong *x;
01189 #ifdef ULLong
01190 ULLong carry, y;
01191 #else
01192 ULong carry, y;
01193 #ifdef Pack_32
01194 ULong xi, z;
01195 #endif
01196 #endif
01197 Bigint *b1;
01198
01199 wds = b->wds;
01200 x = b->x;
01201 i = 0;
01202 carry = a;
01203 do {
01204 #ifdef ULLong
01205 y = *x * (ULLong)m + carry;
01206 carry = y >> 32;
01207 *x++ = (ULong)(y & FFFFFFFF);
01208 #else
01209 #ifdef Pack_32
01210 xi = *x;
01211 y = (xi & 0xffff) * m + carry;
01212 z = (xi >> 16) * m + (y >> 16);
01213 carry = z >> 16;
01214 *x++ = (z << 16) + (y & 0xffff);
01215 #else
01216 y = *x * m + carry;
01217 carry = y >> 16;
01218 *x++ = y & 0xffff;
01219 #endif
01220 #endif
01221 } while (++i < wds);
01222 if (carry) {
01223 if (wds >= b->maxwds) {
01224 b1 = Balloc(b->k+1);
01225 Bcopy(b1, b);
01226 Bfree(b);
01227 b = b1;
01228 }
01229 b->x[wds++] = (ULong)carry;
01230 b->wds = wds;
01231 }
01232 return b;
01233 }
01234
01235 static Bigint *
01236 s2b(const char *s, int nd0, int nd, ULong y9)
01237 {
01238 Bigint *b;
01239 int i, k;
01240 Long x, y;
01241
01242 x = (nd + 8) / 9;
01243 for (k = 0, y = 1; x > y; y <<= 1, k++) ;
01244 #ifdef Pack_32
01245 b = Balloc(k);
01246 b->x[0] = y9;
01247 b->wds = 1;
01248 #else
01249 b = Balloc(k+1);
01250 b->x[0] = y9 & 0xffff;
01251 b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
01252 #endif
01253
01254 i = 9;
01255 if (9 < nd0) {
01256 s += 9;
01257 do {
01258 b = multadd(b, 10, *s++ - '0');
01259 } while (++i < nd0);
01260 s++;
01261 }
01262 else
01263 s += 10;
01264 for (; i < nd; i++)
01265 b = multadd(b, 10, *s++ - '0');
01266 return b;
01267 }
01268
01269 static int
01270 hi0bits(register ULong x)
01271 {
01272 register int k = 0;
01273
01274 if (!(x & 0xffff0000)) {
01275 k = 16;
01276 x <<= 16;
01277 }
01278 if (!(x & 0xff000000)) {
01279 k += 8;
01280 x <<= 8;
01281 }
01282 if (!(x & 0xf0000000)) {
01283 k += 4;
01284 x <<= 4;
01285 }
01286 if (!(x & 0xc0000000)) {
01287 k += 2;
01288 x <<= 2;
01289 }
01290 if (!(x & 0x80000000)) {
01291 k++;
01292 if (!(x & 0x40000000))
01293 return 32;
01294 }
01295 return k;
01296 }
01297
01298 static int
01299 lo0bits(ULong *y)
01300 {
01301 register int k;
01302 register ULong x = *y;
01303
01304 if (x & 7) {
01305 if (x & 1)
01306 return 0;
01307 if (x & 2) {
01308 *y = x >> 1;
01309 return 1;
01310 }
01311 *y = x >> 2;
01312 return 2;
01313 }
01314 k = 0;
01315 if (!(x & 0xffff)) {
01316 k = 16;
01317 x >>= 16;
01318 }
01319 if (!(x & 0xff)) {
01320 k += 8;
01321 x >>= 8;
01322 }
01323 if (!(x & 0xf)) {
01324 k += 4;
01325 x >>= 4;
01326 }
01327 if (!(x & 0x3)) {
01328 k += 2;
01329 x >>= 2;
01330 }
01331 if (!(x & 1)) {
01332 k++;
01333 x >>= 1;
01334 if (!x)
01335 return 32;
01336 }
01337 *y = x;
01338 return k;
01339 }
01340
01341 static Bigint *
01342 i2b(int i)
01343 {
01344 Bigint *b;
01345
01346 b = Balloc(1);
01347 b->x[0] = i;
01348 b->wds = 1;
01349 return b;
01350 }
01351
01352 static Bigint *
01353 mult(Bigint *a, Bigint *b)
01354 {
01355 Bigint *c;
01356 int k, wa, wb, wc;
01357 ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0;
01358 ULong y;
01359 #ifdef ULLong
01360 ULLong carry, z;
01361 #else
01362 ULong carry, z;
01363 #ifdef Pack_32
01364 ULong z2;
01365 #endif
01366 #endif
01367
01368 if (a->wds < b->wds) {
01369 c = a;
01370 a = b;
01371 b = c;
01372 }
01373 k = a->k;
01374 wa = a->wds;
01375 wb = b->wds;
01376 wc = wa + wb;
01377 if (wc > a->maxwds)
01378 k++;
01379 c = Balloc(k);
01380 for (x = c->x, xa = x + wc; x < xa; x++)
01381 *x = 0;
01382 xa = a->x;
01383 xae = xa + wa;
01384 xb = b->x;
01385 xbe = xb + wb;
01386 xc0 = c->x;
01387 #ifdef ULLong
01388 for (; xb < xbe; xc0++) {
01389 if ((y = *xb++) != 0) {
01390 x = xa;
01391 xc = xc0;
01392 carry = 0;
01393 do {
01394 z = *x++ * (ULLong)y + *xc + carry;
01395 carry = z >> 32;
01396 *xc++ = (ULong)(z & FFFFFFFF);
01397 } while (x < xae);
01398 *xc = (ULong)carry;
01399 }
01400 }
01401 #else
01402 #ifdef Pack_32
01403 for (; xb < xbe; xb++, xc0++) {
01404 if (y = *xb & 0xffff) {
01405 x = xa;
01406 xc = xc0;
01407 carry = 0;
01408 do {
01409 z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
01410 carry = z >> 16;
01411 z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
01412 carry = z2 >> 16;
01413 Storeinc(xc, z2, z);
01414 } while (x < xae);
01415 *xc = (ULong)carry;
01416 }
01417 if (y = *xb >> 16) {
01418 x = xa;
01419 xc = xc0;
01420 carry = 0;
01421 z2 = *xc;
01422 do {
01423 z = (*x & 0xffff) * y + (*xc >> 16) + carry;
01424 carry = z >> 16;
01425 Storeinc(xc, z, z2);
01426 z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
01427 carry = z2 >> 16;
01428 } while (x < xae);
01429 *xc = z2;
01430 }
01431 }
01432 #else
01433 for (; xb < xbe; xc0++) {
01434 if (y = *xb++) {
01435 x = xa;
01436 xc = xc0;
01437 carry = 0;
01438 do {
01439 z = *x++ * y + *xc + carry;
01440 carry = z >> 16;
01441 *xc++ = z & 0xffff;
01442 } while (x < xae);
01443 *xc = (ULong)carry;
01444 }
01445 }
01446 #endif
01447 #endif
01448 for (xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
01449 c->wds = wc;
01450 return c;
01451 }
01452
01453 static Bigint *p5s;
01454
01455 static Bigint *
01456 pow5mult(Bigint *b, int k)
01457 {
01458 Bigint *b1, *p5, *p51;
01459 int i;
01460 static int p05[3] = { 5, 25, 125 };
01461
01462 if ((i = k & 3) != 0)
01463 b = multadd(b, p05[i-1], 0);
01464
01465 if (!(k >>= 2))
01466 return b;
01467 if (!(p5 = p5s)) {
01468
01469 #ifdef MULTIPLE_THREADS
01470 ACQUIRE_DTOA_LOCK(1);
01471 if (!(p5 = p5s)) {
01472 p5 = p5s = i2b(625);
01473 p5->next = 0;
01474 }
01475 FREE_DTOA_LOCK(1);
01476 #else
01477 p5 = p5s = i2b(625);
01478 p5->next = 0;
01479 #endif
01480 }
01481 for (;;) {
01482 if (k & 1) {
01483 b1 = mult(b, p5);
01484 Bfree(b);
01485 b = b1;
01486 }
01487 if (!(k >>= 1))
01488 break;
01489 if (!(p51 = p5->next)) {
01490 #ifdef MULTIPLE_THREADS
01491 ACQUIRE_DTOA_LOCK(1);
01492 if (!(p51 = p5->next)) {
01493 p51 = p5->next = mult(p5,p5);
01494 p51->next = 0;
01495 }
01496 FREE_DTOA_LOCK(1);
01497 #else
01498 p51 = p5->next = mult(p5,p5);
01499 p51->next = 0;
01500 #endif
01501 }
01502 p5 = p51;
01503 }
01504 return b;
01505 }
01506
01507 static Bigint *
01508 lshift(Bigint *b, int k)
01509 {
01510 int i, k1, n, n1;
01511 Bigint *b1;
01512 ULong *x, *x1, *xe, z;
01513
01514 #ifdef Pack_32
01515 n = k >> 5;
01516 #else
01517 n = k >> 4;
01518 #endif
01519 k1 = b->k;
01520 n1 = n + b->wds + 1;
01521 for (i = b->maxwds; n1 > i; i <<= 1)
01522 k1++;
01523 b1 = Balloc(k1);
01524 x1 = b1->x;
01525 for (i = 0; i < n; i++)
01526 *x1++ = 0;
01527 x = b->x;
01528 xe = x + b->wds;
01529 #ifdef Pack_32
01530 if (k &= 0x1f) {
01531 k1 = 32 - k;
01532 z = 0;
01533 do {
01534 *x1++ = *x << k | z;
01535 z = *x++ >> k1;
01536 } while (x < xe);
01537 if ((*x1 = z) != 0)
01538 ++n1;
01539 }
01540 #else
01541 if (k &= 0xf) {
01542 k1 = 16 - k;
01543 z = 0;
01544 do {
01545 *x1++ = *x << k & 0xffff | z;
01546 z = *x++ >> k1;
01547 } while (x < xe);
01548 if (*x1 = z)
01549 ++n1;
01550 }
01551 #endif
01552 else
01553 do {
01554 *x1++ = *x++;
01555 } while (x < xe);
01556 b1->wds = n1 - 1;
01557 Bfree(b);
01558 return b1;
01559 }
01560
01561 static int
01562 cmp(Bigint *a, Bigint *b)
01563 {
01564 ULong *xa, *xa0, *xb, *xb0;
01565 int i, j;
01566
01567 i = a->wds;
01568 j = b->wds;
01569 #ifdef DEBUG
01570 if (i > 1 && !a->x[i-1])
01571 Bug("cmp called with a->x[a->wds-1] == 0");
01572 if (j > 1 && !b->x[j-1])
01573 Bug("cmp called with b->x[b->wds-1] == 0");
01574 #endif
01575 if (i -= j)
01576 return i;
01577 xa0 = a->x;
01578 xa = xa0 + j;
01579 xb0 = b->x;
01580 xb = xb0 + j;
01581 for (;;) {
01582 if (*--xa != *--xb)
01583 return *xa < *xb ? -1 : 1;
01584 if (xa <= xa0)
01585 break;
01586 }
01587 return 0;
01588 }
01589
01590 static Bigint *
01591 diff(Bigint *a, Bigint *b)
01592 {
01593 Bigint *c;
01594 int i, wa, wb;
01595 ULong *xa, *xae, *xb, *xbe, *xc;
01596 #ifdef ULLong
01597 ULLong borrow, y;
01598 #else
01599 ULong borrow, y;
01600 #ifdef Pack_32
01601 ULong z;
01602 #endif
01603 #endif
01604
01605 i = cmp(a,b);
01606 if (!i) {
01607 c = Balloc(0);
01608 c->wds = 1;
01609 c->x[0] = 0;
01610 return c;
01611 }
01612 if (i < 0) {
01613 c = a;
01614 a = b;
01615 b = c;
01616 i = 1;
01617 }
01618 else
01619 i = 0;
01620 c = Balloc(a->k);
01621 c->sign = i;
01622 wa = a->wds;
01623 xa = a->x;
01624 xae = xa + wa;
01625 wb = b->wds;
01626 xb = b->x;
01627 xbe = xb + wb;
01628 xc = c->x;
01629 borrow = 0;
01630 #ifdef ULLong
01631 do {
01632 y = (ULLong)*xa++ - *xb++ - borrow;
01633 borrow = y >> 32 & (ULong)1;
01634 *xc++ = (ULong)(y & FFFFFFFF);
01635 } while (xb < xbe);
01636 while (xa < xae) {
01637 y = *xa++ - borrow;
01638 borrow = y >> 32 & (ULong)1;
01639 *xc++ = (ULong)(y & FFFFFFFF);
01640 }
01641 #else
01642 #ifdef Pack_32
01643 do {
01644 y = (*xa & 0xffff) - (*xb & 0xffff) - borrow;
01645 borrow = (y & 0x10000) >> 16;
01646 z = (*xa++ >> 16) - (*xb++ >> 16) - borrow;
01647 borrow = (z & 0x10000) >> 16;
01648 Storeinc(xc, z, y);
01649 } while (xb < xbe);
01650 while (xa < xae) {
01651 y = (*xa & 0xffff) - borrow;
01652 borrow = (y & 0x10000) >> 16;
01653 z = (*xa++ >> 16) - borrow;
01654 borrow = (z & 0x10000) >> 16;
01655 Storeinc(xc, z, y);
01656 }
01657 #else
01658 do {
01659 y = *xa++ - *xb++ - borrow;
01660 borrow = (y & 0x10000) >> 16;
01661 *xc++ = y & 0xffff;
01662 } while (xb < xbe);
01663 while (xa < xae) {
01664 y = *xa++ - borrow;
01665 borrow = (y & 0x10000) >> 16;
01666 *xc++ = y & 0xffff;
01667 }
01668 #endif
01669 #endif
01670 while (!*--xc)
01671 wa--;
01672 c->wds = wa;
01673 return c;
01674 }
01675
01676 static double
01677 ulp(double x_)
01678 {
01679 register Long L;
01680 double_u x, a;
01681 dval(x) = x_;
01682
01683 L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1;
01684 #ifndef Avoid_Underflow
01685 #ifndef Sudden_Underflow
01686 if (L > 0) {
01687 #endif
01688 #endif
01689 #ifdef IBM
01690 L |= Exp_msk1 >> 4;
01691 #endif
01692 word0(a) = L;
01693 word1(a) = 0;
01694 #ifndef Avoid_Underflow
01695 #ifndef Sudden_Underflow
01696 }
01697 else {
01698 L = -L >> Exp_shift;
01699 if (L < Exp_shift) {
01700 word0(a) = 0x80000 >> L;
01701 word1(a) = 0;
01702 }
01703 else {
01704 word0(a) = 0;
01705 L -= Exp_shift;
01706 word1(a) = L >= 31 ? 1 : 1 << 31 - L;
01707 }
01708 }
01709 #endif
01710 #endif
01711 return dval(a);
01712 }
01713
01714 static double
01715 b2d(Bigint *a, int *e)
01716 {
01717 ULong *xa, *xa0, w, y, z;
01718 int k;
01719 double_u d;
01720 #ifdef VAX
01721 ULong d0, d1;
01722 #else
01723 #define d0 word0(d)
01724 #define d1 word1(d)
01725 #endif
01726
01727 xa0 = a->x;
01728 xa = xa0 + a->wds;
01729 y = *--xa;
01730 #ifdef DEBUG
01731 if (!y) Bug("zero y in b2d");
01732 #endif
01733 k = hi0bits(y);
01734 *e = 32 - k;
01735 #ifdef Pack_32
01736 if (k < Ebits) {
01737 d0 = Exp_1 | y >> (Ebits - k);
01738 w = xa > xa0 ? *--xa : 0;
01739 d1 = y << ((32-Ebits) + k) | w >> (Ebits - k);
01740 goto ret_d;
01741 }
01742 z = xa > xa0 ? *--xa : 0;
01743 if (k -= Ebits) {
01744 d0 = Exp_1 | y << k | z >> (32 - k);
01745 y = xa > xa0 ? *--xa : 0;
01746 d1 = z << k | y >> (32 - k);
01747 }
01748 else {
01749 d0 = Exp_1 | y;
01750 d1 = z;
01751 }
01752 #else
01753 if (k < Ebits + 16) {
01754 z = xa > xa0 ? *--xa : 0;
01755 d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k;
01756 w = xa > xa0 ? *--xa : 0;
01757 y = xa > xa0 ? *--xa : 0;
01758 d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k;
01759 goto ret_d;
01760 }
01761 z = xa > xa0 ? *--xa : 0;
01762 w = xa > xa0 ? *--xa : 0;
01763 k -= Ebits + 16;
01764 d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k;
01765 y = xa > xa0 ? *--xa : 0;
01766 d1 = w << k + 16 | y << k;
01767 #endif
01768 ret_d:
01769 #ifdef VAX
01770 word0(d) = d0 >> 16 | d0 << 16;
01771 word1(d) = d1 >> 16 | d1 << 16;
01772 #else
01773 #undef d0
01774 #undef d1
01775 #endif
01776 return dval(d);
01777 }
01778
01779 static Bigint *
01780 d2b(double d_, int *e, int *bits)
01781 {
01782 double_u d;
01783 Bigint *b;
01784 int de, k;
01785 ULong *x, y, z;
01786 #ifndef Sudden_Underflow
01787 int i;
01788 #endif
01789 #ifdef VAX
01790 ULong d0, d1;
01791 #endif
01792 dval(d) = d_;
01793 #ifdef VAX
01794 d0 = word0(d) >> 16 | word0(d) << 16;
01795 d1 = word1(d) >> 16 | word1(d) << 16;
01796 #else
01797 #define d0 word0(d)
01798 #define d1 word1(d)
01799 #endif
01800
01801 #ifdef Pack_32
01802 b = Balloc(1);
01803 #else
01804 b = Balloc(2);
01805 #endif
01806 x = b->x;
01807
01808 z = d0 & Frac_mask;
01809 d0 &= 0x7fffffff;
01810 #ifdef Sudden_Underflow
01811 de = (int)(d0 >> Exp_shift);
01812 #ifndef IBM
01813 z |= Exp_msk11;
01814 #endif
01815 #else
01816 if ((de = (int)(d0 >> Exp_shift)) != 0)
01817 z |= Exp_msk1;
01818 #endif
01819 #ifdef Pack_32
01820 if ((y = d1) != 0) {
01821 if ((k = lo0bits(&y)) != 0) {
01822 x[0] = y | z << (32 - k);
01823 z >>= k;
01824 }
01825 else
01826 x[0] = y;
01827 #ifndef Sudden_Underflow
01828 i =
01829 #endif
01830 b->wds = (x[1] = z) ? 2 : 1;
01831 }
01832 else {
01833 #ifdef DEBUG
01834 if (!z)
01835 Bug("Zero passed to d2b");
01836 #endif
01837 k = lo0bits(&z);
01838 x[0] = z;
01839 #ifndef Sudden_Underflow
01840 i =
01841 #endif
01842 b->wds = 1;
01843 k += 32;
01844 }
01845 #else
01846 if (y = d1) {
01847 if (k = lo0bits(&y))
01848 if (k >= 16) {
01849 x[0] = y | z << 32 - k & 0xffff;
01850 x[1] = z >> k - 16 & 0xffff;
01851 x[2] = z >> k;
01852 i = 2;
01853 }
01854 else {
01855 x[0] = y & 0xffff;
01856 x[1] = y >> 16 | z << 16 - k & 0xffff;
01857 x[2] = z >> k & 0xffff;
01858 x[3] = z >> k+16;
01859 i = 3;
01860 }
01861 else {
01862 x[0] = y & 0xffff;
01863 x[1] = y >> 16;
01864 x[2] = z & 0xffff;
01865 x[3] = z >> 16;
01866 i = 3;
01867 }
01868 }
01869 else {
01870 #ifdef DEBUG
01871 if (!z)
01872 Bug("Zero passed to d2b");
01873 #endif
01874 k = lo0bits(&z);
01875 if (k >= 16) {
01876 x[0] = z;
01877 i = 0;
01878 }
01879 else {
01880 x[0] = z & 0xffff;
01881 x[1] = z >> 16;
01882 i = 1;
01883 }
01884 k += 32;
01885 }
01886 while (!x[i])
01887 --i;
01888 b->wds = i + 1;
01889 #endif
01890 #ifndef Sudden_Underflow
01891 if (de) {
01892 #endif
01893 #ifdef IBM
01894 *e = (de - Bias - (P-1) << 2) + k;
01895 *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask);
01896 #else
01897 *e = de - Bias - (P-1) + k;
01898 *bits = P - k;
01899 #endif
01900 #ifndef Sudden_Underflow
01901 }
01902 else {
01903 *e = de - Bias - (P-1) + 1 + k;
01904 #ifdef Pack_32
01905 *bits = 32*i - hi0bits(x[i-1]);
01906 #else
01907 *bits = (i+2)*16 - hi0bits(x[i]);
01908 #endif
01909 }
01910 #endif
01911 return b;
01912 }
01913 #undef d0
01914 #undef d1
01915
01916 static double
01917 ratio(Bigint *a, Bigint *b)
01918 {
01919 double_u da, db;
01920 int k, ka, kb;
01921
01922 dval(da) = b2d(a, &ka);
01923 dval(db) = b2d(b, &kb);
01924 #ifdef Pack_32
01925 k = ka - kb + 32*(a->wds - b->wds);
01926 #else
01927 k = ka - kb + 16*(a->wds - b->wds);
01928 #endif
01929 #ifdef IBM
01930 if (k > 0) {
01931 word0(da) += (k >> 2)*Exp_msk1;
01932 if (k &= 3)
01933 dval(da) *= 1 << k;
01934 }
01935 else {
01936 k = -k;
01937 word0(db) += (k >> 2)*Exp_msk1;
01938 if (k &= 3)
01939 dval(db) *= 1 << k;
01940 }
01941 #else
01942 if (k > 0)
01943 word0(da) += k*Exp_msk1;
01944 else {
01945 k = -k;
01946 word0(db) += k*Exp_msk1;
01947 }
01948 #endif
01949 return dval(da) / dval(db);
01950 }
01951
01952 static const double
01953 tens[] = {
01954 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
01955 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
01956 1e20, 1e21, 1e22
01957 #ifdef VAX
01958 , 1e23, 1e24
01959 #endif
01960 };
01961
01962 static const double
01963 #ifdef IEEE_Arith
01964 bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };
01965 static const double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128,
01966 #ifdef Avoid_Underflow
01967 9007199254740992.*9007199254740992.e-256
01968
01969 #else
01970 1e-256
01971 #endif
01972 };
01973
01974
01975 #define Scale_Bit 0x10
01976 #define n_bigtens 5
01977 #else
01978 #ifdef IBM
01979 bigtens[] = { 1e16, 1e32, 1e64 };
01980 static const double tinytens[] = { 1e-16, 1e-32, 1e-64 };
01981 #define n_bigtens 3
01982 #else
01983 bigtens[] = { 1e16, 1e32 };
01984 static const double tinytens[] = { 1e-16, 1e-32 };
01985 #define n_bigtens 2
01986 #endif
01987 #endif
01988
01989 #ifndef IEEE_Arith
01990 #undef INFNAN_CHECK
01991 #endif
01992
01993 #ifdef INFNAN_CHECK
01994
01995 #ifndef NAN_WORD0
01996 #define NAN_WORD0 0x7ff80000
01997 #endif
01998
01999 #ifndef NAN_WORD1
02000 #define NAN_WORD1 0
02001 #endif
02002
02003 static int
02004 match(const char **sp, char *t)
02005 {
02006 int c, d;
02007 const char *s = *sp;
02008
02009 while (d = *t++) {
02010 if ((c = *++s) >= 'A' && c <= 'Z')
02011 c += 'a' - 'A';
02012 if (c != d)
02013 return 0;
02014 }
02015 *sp = s + 1;
02016 return 1;
02017 }
02018
02019 #ifndef No_Hex_NaN
02020 static void
02021 hexnan(double *rvp, const char **sp)
02022 {
02023 ULong c, x[2];
02024 const char *s;
02025 int havedig, udx0, xshift;
02026
02027 x[0] = x[1] = 0;
02028 havedig = xshift = 0;
02029 udx0 = 1;
02030 s = *sp;
02031 while (c = *(const unsigned char*)++s) {
02032 if (c >= '0' && c <= '9')
02033 c -= '0';
02034 else if (c >= 'a' && c <= 'f')
02035 c += 10 - 'a';
02036 else if (c >= 'A' && c <= 'F')
02037 c += 10 - 'A';
02038 else if (c <= ' ') {
02039 if (udx0 && havedig) {
02040 udx0 = 0;
02041 xshift = 1;
02042 }
02043 continue;
02044 }
02045 else if ( c == ')' && havedig) {
02046 *sp = s + 1;
02047 break;
02048 }
02049 else
02050 return;
02051 havedig = 1;
02052 if (xshift) {
02053 xshift = 0;
02054 x[0] = x[1];
02055 x[1] = 0;
02056 }
02057 if (udx0)
02058 x[0] = (x[0] << 4) | (x[1] >> 28);
02059 x[1] = (x[1] << 4) | c;
02060 }
02061 if ((x[0] &= 0xfffff) || x[1]) {
02062 word0(*rvp) = Exp_mask | x[0];
02063 word1(*rvp) = x[1];
02064 }
02065 }
02066 #endif
02067 #endif
02068
02069 double
02070 ruby_strtod(const char *s00, char **se)
02071 {
02072 #ifdef Avoid_Underflow
02073 int scale;
02074 #endif
02075 int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign,
02076 e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign;
02077 const char *s, *s0, *s1;
02078 double aadj, adj;
02079 double_u aadj1, rv, rv0;
02080 Long L;
02081 ULong y, z;
02082 Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
02083 #ifdef SET_INEXACT
02084 int inexact, oldinexact;
02085 #endif
02086 #ifdef Honor_FLT_ROUNDS
02087 int rounding;
02088 #endif
02089 #ifdef USE_LOCALE
02090 const char *s2;
02091 #endif
02092
02093 errno = 0;
02094 sign = nz0 = nz = 0;
02095 dval(rv) = 0.;
02096 for (s = s00;;s++)
02097 switch (*s) {
02098 case '-':
02099 sign = 1;
02100
02101 case '+':
02102 if (*++s)
02103 goto break2;
02104
02105 case 0:
02106 goto ret0;
02107 case '\t':
02108 case '\n':
02109 case '\v':
02110 case '\f':
02111 case '\r':
02112 case ' ':
02113 continue;
02114 default:
02115 goto break2;
02116 }
02117 break2:
02118 if (*s == '0') {
02119 if (s[1] == 'x' || s[1] == 'X') {
02120 static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF";
02121 s0 = ++s;
02122 adj = 0;
02123 aadj = 1.0;
02124 nd0 = -4;
02125
02126 if (!*++s || !(s1 = strchr(hexdigit, *s))) goto ret0;
02127 while (*s == '0') s++;
02128 if ((s1 = strchr(hexdigit, *s)) != NULL) {
02129 do {
02130 adj += aadj * ((s1 - hexdigit) & 15);
02131 nd0 += 4;
02132 aadj /= 16;
02133 } while (*++s && (s1 = strchr(hexdigit, *s)));
02134 }
02135
02136 if (*s == '.') {
02137 dsign = 1;
02138 if (!*++s || !(s1 = strchr(hexdigit, *s))) goto ret0;
02139 if (nd0 < 0) {
02140 while (*s == '0') {
02141 s++;
02142 nd0 -= 4;
02143 }
02144 }
02145 for (; *s && (s1 = strchr(hexdigit, *s)); ++s) {
02146 adj += aadj * ((s1 - hexdigit) & 15);
02147 if ((aadj /= 16) == 0.0) {
02148 while (strchr(hexdigit, *++s));
02149 break;
02150 }
02151 }
02152 }
02153 else {
02154 dsign = 0;
02155 }
02156
02157 if (*s == 'P' || *s == 'p') {
02158 dsign = 0x2C - *++s;
02159 if (abs(dsign) == 1) s++;
02160 else dsign = 1;
02161
02162 nd = 0;
02163 c = *s;
02164 if (c < '0' || '9' < c) goto ret0;
02165 do {
02166 nd *= 10;
02167 nd += c;
02168 nd -= '0';
02169 c = *++s;
02170
02171 if (nd + dsign * nd0 > 2095) {
02172 while ('0' <= c && c <= '9') c = *++s;
02173 break;
02174 }
02175 } while ('0' <= c && c <= '9');
02176 nd0 += nd * dsign;
02177 }
02178 else {
02179 if (dsign) goto ret0;
02180 }
02181 dval(rv) = ldexp(adj, nd0);
02182 goto ret;
02183 }
02184 nz0 = 1;
02185 while (*++s == '0') ;
02186 if (!*s)
02187 goto ret;
02188 }
02189 s0 = s;
02190 y = z = 0;
02191 for (nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
02192 if (nd < 9)
02193 y = 10*y + c - '0';
02194 else if (nd < 16)
02195 z = 10*z + c - '0';
02196 nd0 = nd;
02197 #ifdef USE_LOCALE
02198 s1 = localeconv()->decimal_point;
02199 if (c == *s1) {
02200 c = '.';
02201 if (*++s1) {
02202 s2 = s;
02203 for (;;) {
02204 if (*++s2 != *s1) {
02205 c = 0;
02206 break;
02207 }
02208 if (!*++s1) {
02209 s = s2;
02210 break;
02211 }
02212 }
02213 }
02214 }
02215 #endif
02216 if (c == '.') {
02217 if (!ISDIGIT(s[1]))
02218 goto dig_done;
02219 c = *++s;
02220 if (!nd) {
02221 for (; c == '0'; c = *++s)
02222 nz++;
02223 if (c > '0' && c <= '9') {
02224 s0 = s;
02225 nf += nz;
02226 nz = 0;
02227 goto have_dig;
02228 }
02229 goto dig_done;
02230 }
02231 for (; c >= '0' && c <= '9'; c = *++s) {
02232 have_dig:
02233 nz++;
02234 if (c -= '0') {
02235 nf += nz;
02236 for (i = 1; i < nz; i++)
02237 if (nd++ < 9)
02238 y *= 10;
02239 else if (nd <= DBL_DIG + 1)
02240 z *= 10;
02241 if (nd++ < 9)
02242 y = 10*y + c;
02243 else if (nd <= DBL_DIG + 1)
02244 z = 10*z + c;
02245 nz = 0;
02246 }
02247 }
02248 }
02249 dig_done:
02250 e = 0;
02251 if (c == 'e' || c == 'E') {
02252 if (!nd && !nz && !nz0) {
02253 goto ret0;
02254 }
02255 s00 = s;
02256 esign = 0;
02257 switch (c = *++s) {
02258 case '-':
02259 esign = 1;
02260 case '+':
02261 c = *++s;
02262 }
02263 if (c >= '0' && c <= '9') {
02264 while (c == '0')
02265 c = *++s;
02266 if (c > '0' && c <= '9') {
02267 L = c - '0';
02268 s1 = s;
02269 while ((c = *++s) >= '0' && c <= '9')
02270 L = 10*L + c - '0';
02271 if (s - s1 > 8 || L > 19999)
02272
02273
02274
02275 e = 19999;
02276 else
02277 e = (int)L;
02278 if (esign)
02279 e = -e;
02280 }
02281 else
02282 e = 0;
02283 }
02284 else
02285 s = s00;
02286 }
02287 if (!nd) {
02288 if (!nz && !nz0) {
02289 #ifdef INFNAN_CHECK
02290
02291 switch (c) {
02292 case 'i':
02293 case 'I':
02294 if (match(&s,"nf")) {
02295 --s;
02296 if (!match(&s,"inity"))
02297 ++s;
02298 word0(rv) = 0x7ff00000;
02299 word1(rv) = 0;
02300 goto ret;
02301 }
02302 break;
02303 case 'n':
02304 case 'N':
02305 if (match(&s, "an")) {
02306 word0(rv) = NAN_WORD0;
02307 word1(rv) = NAN_WORD1;
02308 #ifndef No_Hex_NaN
02309 if (*s == '(')
02310 hexnan(&rv, &s);
02311 #endif
02312 goto ret;
02313 }
02314 }
02315 #endif
02316 ret0:
02317 s = s00;
02318 sign = 0;
02319 }
02320 goto ret;
02321 }
02322 e1 = e -= nf;
02323
02324
02325
02326
02327
02328
02329 if (!nd0)
02330 nd0 = nd;
02331 k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
02332 dval(rv) = y;
02333 if (k > 9) {
02334 #ifdef SET_INEXACT
02335 if (k > DBL_DIG)
02336 oldinexact = get_inexact();
02337 #endif
02338 dval(rv) = tens[k - 9] * dval(rv) + z;
02339 }
02340 bd0 = bb = bd = bs = delta = 0;
02341 if (nd <= DBL_DIG
02342 #ifndef RND_PRODQUOT
02343 #ifndef Honor_FLT_ROUNDS
02344 && Flt_Rounds == 1
02345 #endif
02346 #endif
02347 ) {
02348 if (!e)
02349 goto ret;
02350 if (e > 0) {
02351 if (e <= Ten_pmax) {
02352 #ifdef VAX
02353 goto vax_ovfl_check;
02354 #else
02355 #ifdef Honor_FLT_ROUNDS
02356
02357 if (sign) {
02358 dval(rv) = -dval(rv);
02359 sign = 0;
02360 }
02361 #endif
02362 rounded_product(dval(rv), tens[e]);
02363 goto ret;
02364 #endif
02365 }
02366 i = DBL_DIG - nd;
02367 if (e <= Ten_pmax + i) {
02368
02369
02370
02371 #ifdef Honor_FLT_ROUNDS
02372
02373 if (sign) {
02374 dval(rv) = -dval(rv);
02375 sign = 0;
02376 }
02377 #endif
02378 e -= i;
02379 dval(rv) *= tens[i];
02380 #ifdef VAX
02381
02382
02383
02384 vax_ovfl_check:
02385 word0(rv) -= P*Exp_msk1;
02386 rounded_product(dval(rv), tens[e]);
02387 if ((word0(rv) & Exp_mask)
02388 > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
02389 goto ovfl;
02390 word0(rv) += P*Exp_msk1;
02391 #else
02392 rounded_product(dval(rv), tens[e]);
02393 #endif
02394 goto ret;
02395 }
02396 }
02397 #ifndef Inaccurate_Divide
02398 else if (e >= -Ten_pmax) {
02399 #ifdef Honor_FLT_ROUNDS
02400
02401 if (sign) {
02402 dval(rv) = -dval(rv);
02403 sign = 0;
02404 }
02405 #endif
02406 rounded_quotient(dval(rv), tens[-e]);
02407 goto ret;
02408 }
02409 #endif
02410 }
02411 e1 += nd - k;
02412
02413 #ifdef IEEE_Arith
02414 #ifdef SET_INEXACT
02415 inexact = 1;
02416 if (k <= DBL_DIG)
02417 oldinexact = get_inexact();
02418 #endif
02419 #ifdef Avoid_Underflow
02420 scale = 0;
02421 #endif
02422 #ifdef Honor_FLT_ROUNDS
02423 if ((rounding = Flt_Rounds) >= 2) {
02424 if (sign)
02425 rounding = rounding == 2 ? 0 : 2;
02426 else
02427 if (rounding != 2)
02428 rounding = 0;
02429 }
02430 #endif
02431 #endif
02432
02433
02434
02435 if (e1 > 0) {
02436 if ((i = e1 & 15) != 0)
02437 dval(rv) *= tens[i];
02438 if (e1 &= ~15) {
02439 if (e1 > DBL_MAX_10_EXP) {
02440 ovfl:
02441 #ifndef NO_ERRNO
02442 errno = ERANGE;
02443 #endif
02444
02445 #ifdef IEEE_Arith
02446 #ifdef Honor_FLT_ROUNDS
02447 switch (rounding) {
02448 case 0:
02449 case 3:
02450 word0(rv) = Big0;
02451 word1(rv) = Big1;
02452 break;
02453 default:
02454 word0(rv) = Exp_mask;
02455 word1(rv) = 0;
02456 }
02457 #else
02458 word0(rv) = Exp_mask;
02459 word1(rv) = 0;
02460 #endif
02461 #ifdef SET_INEXACT
02462
02463 dval(rv0) = 1e300;
02464 dval(rv0) *= dval(rv0);
02465 #endif
02466 #else
02467 word0(rv) = Big0;
02468 word1(rv) = Big1;
02469 #endif
02470 if (bd0)
02471 goto retfree;
02472 goto ret;
02473 }
02474 e1 >>= 4;
02475 for (j = 0; e1 > 1; j++, e1 >>= 1)
02476 if (e1 & 1)
02477 dval(rv) *= bigtens[j];
02478
02479 word0(rv) -= P*Exp_msk1;
02480 dval(rv) *= bigtens[j];
02481 if ((z = word0(rv) & Exp_mask)
02482 > Exp_msk1*(DBL_MAX_EXP+Bias-P))
02483 goto ovfl;
02484 if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) {
02485
02486
02487 word0(rv) = Big0;
02488 word1(rv) = Big1;
02489 }
02490 else
02491 word0(rv) += P*Exp_msk1;
02492 }
02493 }
02494 else if (e1 < 0) {
02495 e1 = -e1;
02496 if ((i = e1 & 15) != 0)
02497 dval(rv) /= tens[i];
02498 if (e1 >>= 4) {
02499 if (e1 >= 1 << n_bigtens)
02500 goto undfl;
02501 #ifdef Avoid_Underflow
02502 if (e1 & Scale_Bit)
02503 scale = 2*P;
02504 for (j = 0; e1 > 0; j++, e1 >>= 1)
02505 if (e1 & 1)
02506 dval(rv) *= tinytens[j];
02507 if (scale && (j = 2*P + 1 - ((word0(rv) & Exp_mask)
02508 >> Exp_shift)) > 0) {
02509
02510 if (j >= 32) {
02511 word1(rv) = 0;
02512 if (j >= 53)
02513 word0(rv) = (P+2)*Exp_msk1;
02514 else
02515 word0(rv) &= 0xffffffff << (j-32);
02516 }
02517 else
02518 word1(rv) &= 0xffffffff << j;
02519 }
02520 #else
02521 for (j = 0; e1 > 1; j++, e1 >>= 1)
02522 if (e1 & 1)
02523 dval(rv) *= tinytens[j];
02524
02525 dval(rv0) = dval(rv);
02526 dval(rv) *= tinytens[j];
02527 if (!dval(rv)) {
02528 dval(rv) = 2.*dval(rv0);
02529 dval(rv) *= tinytens[j];
02530 #endif
02531 if (!dval(rv)) {
02532 undfl:
02533 dval(rv) = 0.;
02534 #ifndef NO_ERRNO
02535 errno = ERANGE;
02536 #endif
02537 if (bd0)
02538 goto retfree;
02539 goto ret;
02540 }
02541 #ifndef Avoid_Underflow
02542 word0(rv) = Tiny0;
02543 word1(rv) = Tiny1;
02544
02545
02546
02547 }
02548 #endif
02549 }
02550 }
02551
02552
02553
02554
02555
02556 bd0 = s2b(s0, nd0, nd, y);
02557
02558 for (;;) {
02559 bd = Balloc(bd0->k);
02560 Bcopy(bd, bd0);
02561 bb = d2b(dval(rv), &bbe, &bbbits);
02562 bs = i2b(1);
02563
02564 if (e >= 0) {
02565 bb2 = bb5 = 0;
02566 bd2 = bd5 = e;
02567 }
02568 else {
02569 bb2 = bb5 = -e;
02570 bd2 = bd5 = 0;
02571 }
02572 if (bbe >= 0)
02573 bb2 += bbe;
02574 else
02575 bd2 -= bbe;
02576 bs2 = bb2;
02577 #ifdef Honor_FLT_ROUNDS
02578 if (rounding != 1)
02579 bs2++;
02580 #endif
02581 #ifdef Avoid_Underflow
02582 j = bbe - scale;
02583 i = j + bbbits - 1;
02584 if (i < Emin)
02585 j += P - Emin;
02586 else
02587 j = P + 1 - bbbits;
02588 #else
02589 #ifdef Sudden_Underflow
02590 #ifdef IBM
02591 j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3);
02592 #else
02593 j = P + 1 - bbbits;
02594 #endif
02595 #else
02596 j = bbe;
02597 i = j + bbbits - 1;
02598 if (i < Emin)
02599 j += P - Emin;
02600 else
02601 j = P + 1 - bbbits;
02602 #endif
02603 #endif
02604 bb2 += j;
02605 bd2 += j;
02606 #ifdef Avoid_Underflow
02607 bd2 += scale;
02608 #endif
02609 i = bb2 < bd2 ? bb2 : bd2;
02610 if (i > bs2)
02611 i = bs2;
02612 if (i > 0) {
02613 bb2 -= i;
02614 bd2 -= i;
02615 bs2 -= i;
02616 }
02617 if (bb5 > 0) {
02618 bs = pow5mult(bs, bb5);
02619 bb1 = mult(bs, bb);
02620 Bfree(bb);
02621 bb = bb1;
02622 }
02623 if (bb2 > 0)
02624 bb = lshift(bb, bb2);
02625 if (bd5 > 0)
02626 bd = pow5mult(bd, bd5);
02627 if (bd2 > 0)
02628 bd = lshift(bd, bd2);
02629 if (bs2 > 0)
02630 bs = lshift(bs, bs2);
02631 delta = diff(bb, bd);
02632 dsign = delta->sign;
02633 delta->sign = 0;
02634 i = cmp(delta, bs);
02635 #ifdef Honor_FLT_ROUNDS
02636 if (rounding != 1) {
02637 if (i < 0) {
02638
02639 if (!delta->x[0] && delta->wds <= 1) {
02640
02641 #ifdef SET_INEXACT
02642 inexact = 0;
02643 #endif
02644 break;
02645 }
02646 if (rounding) {
02647 if (dsign) {
02648 adj = 1.;
02649 goto apply_adj;
02650 }
02651 }
02652 else if (!dsign) {
02653 adj = -1.;
02654 if (!word1(rv)
02655 && !(word0(rv) & Frac_mask)) {
02656 y = word0(rv) & Exp_mask;
02657 #ifdef Avoid_Underflow
02658 if (!scale || y > 2*P*Exp_msk1)
02659 #else
02660 if (y)
02661 #endif
02662 {
02663 delta = lshift(delta,Log2P);
02664 if (cmp(delta, bs) <= 0)
02665 adj = -0.5;
02666 }
02667 }
02668 apply_adj:
02669 #ifdef Avoid_Underflow
02670 if (scale && (y = word0(rv) & Exp_mask)
02671 <= 2*P*Exp_msk1)
02672 word0(adj) += (2*P+1)*Exp_msk1 - y;
02673 #else
02674 #ifdef Sudden_Underflow
02675 if ((word0(rv) & Exp_mask) <=
02676 P*Exp_msk1) {
02677 word0(rv) += P*Exp_msk1;
02678 dval(rv) += adj*ulp(dval(rv));
02679 word0(rv) -= P*Exp_msk1;
02680 }
02681 else
02682 #endif
02683 #endif
02684 dval(rv) += adj*ulp(dval(rv));
02685 }
02686 break;
02687 }
02688 adj = ratio(delta, bs);
02689 if (adj < 1.)
02690 adj = 1.;
02691 if (adj <= 0x7ffffffe) {
02692
02693 y = adj;
02694 if (y != adj) {
02695 if (!((rounding>>1) ^ dsign))
02696 y++;
02697 adj = y;
02698 }
02699 }
02700 #ifdef Avoid_Underflow
02701 if (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
02702 word0(adj) += (2*P+1)*Exp_msk1 - y;
02703 #else
02704 #ifdef Sudden_Underflow
02705 if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
02706 word0(rv) += P*Exp_msk1;
02707 adj *= ulp(dval(rv));
02708 if (dsign)
02709 dval(rv) += adj;
02710 else
02711 dval(rv) -= adj;
02712 word0(rv) -= P*Exp_msk1;
02713 goto cont;
02714 }
02715 #endif
02716 #endif
02717 adj *= ulp(dval(rv));
02718 if (dsign)
02719 dval(rv) += adj;
02720 else
02721 dval(rv) -= adj;
02722 goto cont;
02723 }
02724 #endif
02725
02726 if (i < 0) {
02727
02728
02729
02730 if (dsign || word1(rv) || word0(rv) & Bndry_mask
02731 #ifdef IEEE_Arith
02732 #ifdef Avoid_Underflow
02733 || (word0(rv) & Exp_mask) <= (2*P+1)*Exp_msk1
02734 #else
02735 || (word0(rv) & Exp_mask) <= Exp_msk1
02736 #endif
02737 #endif
02738 ) {
02739 #ifdef SET_INEXACT
02740 if (!delta->x[0] && delta->wds <= 1)
02741 inexact = 0;
02742 #endif
02743 break;
02744 }
02745 if (!delta->x[0] && delta->wds <= 1) {
02746
02747 #ifdef SET_INEXACT
02748 inexact = 0;
02749 #endif
02750 break;
02751 }
02752 delta = lshift(delta,Log2P);
02753 if (cmp(delta, bs) > 0)
02754 goto drop_down;
02755 break;
02756 }
02757 if (i == 0) {
02758
02759 if (dsign) {
02760 if ((word0(rv) & Bndry_mask1) == Bndry_mask1
02761 && word1(rv) == (
02762 #ifdef Avoid_Underflow
02763 (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1)
02764 ? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) :
02765 #endif
02766 0xffffffff)) {
02767
02768 word0(rv) = (word0(rv) & Exp_mask)
02769 + Exp_msk1
02770 #ifdef IBM
02771 | Exp_msk1 >> 4
02772 #endif
02773 ;
02774 word1(rv) = 0;
02775 #ifdef Avoid_Underflow
02776 dsign = 0;
02777 #endif
02778 break;
02779 }
02780 }
02781 else if (!(word0(rv) & Bndry_mask) && !word1(rv)) {
02782 drop_down:
02783
02784 #ifdef Sudden_Underflow
02785 L = word0(rv) & Exp_mask;
02786 #ifdef IBM
02787 if (L < Exp_msk1)
02788 #else
02789 #ifdef Avoid_Underflow
02790 if (L <= (scale ? (2*P+1)*Exp_msk1 : Exp_msk1))
02791 #else
02792 if (L <= Exp_msk1)
02793 #endif
02794 #endif
02795 goto undfl;
02796 L -= Exp_msk1;
02797 #else
02798 #ifdef Avoid_Underflow
02799 if (scale) {
02800 L = word0(rv) & Exp_mask;
02801 if (L <= (2*P+1)*Exp_msk1) {
02802 if (L > (P+2)*Exp_msk1)
02803
02804
02805 break;
02806
02807 goto undfl;
02808 }
02809 }
02810 #endif
02811 L = (word0(rv) & Exp_mask) - Exp_msk1;
02812 #endif
02813 word0(rv) = L | Bndry_mask1;
02814 word1(rv) = 0xffffffff;
02815 #ifdef IBM
02816 goto cont;
02817 #else
02818 break;
02819 #endif
02820 }
02821 #ifndef ROUND_BIASED
02822 if (!(word1(rv) & LSB))
02823 break;
02824 #endif
02825 if (dsign)
02826 dval(rv) += ulp(dval(rv));
02827 #ifndef ROUND_BIASED
02828 else {
02829 dval(rv) -= ulp(dval(rv));
02830 #ifndef Sudden_Underflow
02831 if (!dval(rv))
02832 goto undfl;
02833 #endif
02834 }
02835 #ifdef Avoid_Underflow
02836 dsign = 1 - dsign;
02837 #endif
02838 #endif
02839 break;
02840 }
02841 if ((aadj = ratio(delta, bs)) <= 2.) {
02842 if (dsign)
02843 aadj = dval(aadj1) = 1.;
02844 else if (word1(rv) || word0(rv) & Bndry_mask) {
02845 #ifndef Sudden_Underflow
02846 if (word1(rv) == Tiny1 && !word0(rv))
02847 goto undfl;
02848 #endif
02849 aadj = 1.;
02850 dval(aadj1) = -1.;
02851 }
02852 else {
02853
02854
02855
02856 if (aadj < 2./FLT_RADIX)
02857 aadj = 1./FLT_RADIX;
02858 else
02859 aadj *= 0.5;
02860 dval(aadj1) = -aadj;
02861 }
02862 }
02863 else {
02864 aadj *= 0.5;
02865 dval(aadj1) = dsign ? aadj : -aadj;
02866 #ifdef Check_FLT_ROUNDS
02867 switch (Rounding) {
02868 case 2:
02869 dval(aadj1) -= 0.5;
02870 break;
02871 case 0:
02872 case 3:
02873 dval(aadj1) += 0.5;
02874 }
02875 #else
02876 if (Flt_Rounds == 0)
02877 dval(aadj1) += 0.5;
02878 #endif
02879 }
02880 y = word0(rv) & Exp_mask;
02881
02882
02883
02884 if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
02885 dval(rv0) = dval(rv);
02886 word0(rv) -= P*Exp_msk1;
02887 adj = dval(aadj1) * ulp(dval(rv));
02888 dval(rv) += adj;
02889 if ((word0(rv) & Exp_mask) >=
02890 Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
02891 if (word0(rv0) == Big0 && word1(rv0) == Big1)
02892 goto ovfl;
02893 word0(rv) = Big0;
02894 word1(rv) = Big1;
02895 goto cont;
02896 }
02897 else
02898 word0(rv) += P*Exp_msk1;
02899 }
02900 else {
02901 #ifdef Avoid_Underflow
02902 if (scale && y <= 2*P*Exp_msk1) {
02903 if (aadj <= 0x7fffffff) {
02904 if ((z = (int)aadj) <= 0)
02905 z = 1;
02906 aadj = z;
02907 dval(aadj1) = dsign ? aadj : -aadj;
02908 }
02909 word0(aadj1) += (2*P+1)*Exp_msk1 - y;
02910 }
02911 adj = dval(aadj1) * ulp(dval(rv));
02912 dval(rv) += adj;
02913 #else
02914 #ifdef Sudden_Underflow
02915 if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
02916 dval(rv0) = dval(rv);
02917 word0(rv) += P*Exp_msk1;
02918 adj = dval(aadj1) * ulp(dval(rv));
02919 dval(rv) += adj;
02920 #ifdef IBM
02921 if ((word0(rv) & Exp_mask) < P*Exp_msk1)
02922 #else
02923 if ((word0(rv) & Exp_mask) <= P*Exp_msk1)
02924 #endif
02925 {
02926 if (word0(rv0) == Tiny0 && word1(rv0) == Tiny1)
02927 goto undfl;
02928 word0(rv) = Tiny0;
02929 word1(rv) = Tiny1;
02930 goto cont;
02931 }
02932 else
02933 word0(rv) -= P*Exp_msk1;
02934 }
02935 else {
02936 adj = dval(aadj1) * ulp(dval(rv));
02937 dval(rv) += adj;
02938 }
02939 #else
02940
02941
02942
02943
02944
02945
02946
02947 if (y <= (P-1)*Exp_msk1 && aadj > 1.) {
02948 dval(aadj1) = (double)(int)(aadj + 0.5);
02949 if (!dsign)
02950 dval(aadj1) = -dval(aadj1);
02951 }
02952 adj = dval(aadj1) * ulp(dval(rv));
02953 dval(rv) += adj;
02954 #endif
02955 #endif
02956 }
02957 z = word0(rv) & Exp_mask;
02958 #ifndef SET_INEXACT
02959 #ifdef Avoid_Underflow
02960 if (!scale)
02961 #endif
02962 if (y == z) {
02963
02964 L = (Long)aadj;
02965 aadj -= L;
02966
02967 if (dsign || word1(rv) || word0(rv) & Bndry_mask) {
02968 if (aadj < .4999999 || aadj > .5000001)
02969 break;
02970 }
02971 else if (aadj < .4999999/FLT_RADIX)
02972 break;
02973 }
02974 #endif
02975 cont:
02976 Bfree(bb);
02977 Bfree(bd);
02978 Bfree(bs);
02979 Bfree(delta);
02980 }
02981 #ifdef SET_INEXACT
02982 if (inexact) {
02983 if (!oldinexact) {
02984 word0(rv0) = Exp_1 + (70 << Exp_shift);
02985 word1(rv0) = 0;
02986 dval(rv0) += 1.;
02987 }
02988 }
02989 else if (!oldinexact)
02990 clear_inexact();
02991 #endif
02992 #ifdef Avoid_Underflow
02993 if (scale) {
02994 word0(rv0) = Exp_1 - 2*P*Exp_msk1;
02995 word1(rv0) = 0;
02996 dval(rv) *= dval(rv0);
02997 #ifndef NO_ERRNO
02998
02999 if (word0(rv) == 0 && word1(rv) == 0)
03000 errno = ERANGE;
03001 #endif
03002 }
03003 #endif
03004 #ifdef SET_INEXACT
03005 if (inexact && !(word0(rv) & Exp_mask)) {
03006
03007 dval(rv0) = 1e-300;
03008 dval(rv0) *= dval(rv0);
03009 }
03010 #endif
03011 retfree:
03012 Bfree(bb);
03013 Bfree(bd);
03014 Bfree(bs);
03015 Bfree(bd0);
03016 Bfree(delta);
03017 ret:
03018 if (se)
03019 *se = (char *)s;
03020 return sign ? -dval(rv) : dval(rv);
03021 }
03022
03023 static int
03024 quorem(Bigint *b, Bigint *S)
03025 {
03026 int n;
03027 ULong *bx, *bxe, q, *sx, *sxe;
03028 #ifdef ULLong
03029 ULLong borrow, carry, y, ys;
03030 #else
03031 ULong borrow, carry, y, ys;
03032 #ifdef Pack_32
03033 ULong si, z, zs;
03034 #endif
03035 #endif
03036
03037 n = S->wds;
03038 #ifdef DEBUG
03039 if (b->wds > n)
03040 Bug("oversize b in quorem");
03041 #endif
03042 if (b->wds < n)
03043 return 0;
03044 sx = S->x;
03045 sxe = sx + --n;
03046 bx = b->x;
03047 bxe = bx + n;
03048 q = *bxe / (*sxe + 1);
03049 #ifdef DEBUG
03050 if (q > 9)
03051 Bug("oversized quotient in quorem");
03052 #endif
03053 if (q) {
03054 borrow = 0;
03055 carry = 0;
03056 do {
03057 #ifdef ULLong
03058 ys = *sx++ * (ULLong)q + carry;
03059 carry = ys >> 32;
03060 y = *bx - (ys & FFFFFFFF) - borrow;
03061 borrow = y >> 32 & (ULong)1;
03062 *bx++ = (ULong)(y & FFFFFFFF);
03063 #else
03064 #ifdef Pack_32
03065 si = *sx++;
03066 ys = (si & 0xffff) * q + carry;
03067 zs = (si >> 16) * q + (ys >> 16);
03068 carry = zs >> 16;
03069 y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
03070 borrow = (y & 0x10000) >> 16;
03071 z = (*bx >> 16) - (zs & 0xffff) - borrow;
03072 borrow = (z & 0x10000) >> 16;
03073 Storeinc(bx, z, y);
03074 #else
03075 ys = *sx++ * q + carry;
03076 carry = ys >> 16;
03077 y = *bx - (ys & 0xffff) - borrow;
03078 borrow = (y & 0x10000) >> 16;
03079 *bx++ = y & 0xffff;
03080 #endif
03081 #endif
03082 } while (sx <= sxe);
03083 if (!*bxe) {
03084 bx = b->x;
03085 while (--bxe > bx && !*bxe)
03086 --n;
03087 b->wds = n;
03088 }
03089 }
03090 if (cmp(b, S) >= 0) {
03091 q++;
03092 borrow = 0;
03093 carry = 0;
03094 bx = b->x;
03095 sx = S->x;
03096 do {
03097 #ifdef ULLong
03098 ys = *sx++ + carry;
03099 carry = ys >> 32;
03100 y = *bx - (ys & FFFFFFFF) - borrow;
03101 borrow = y >> 32 & (ULong)1;
03102 *bx++ = (ULong)(y & FFFFFFFF);
03103 #else
03104 #ifdef Pack_32
03105 si = *sx++;
03106 ys = (si & 0xffff) + carry;
03107 zs = (si >> 16) + (ys >> 16);
03108 carry = zs >> 16;
03109 y = (*bx & 0xffff) - (ys & 0xffff) - borrow;
03110 borrow = (y & 0x10000) >> 16;
03111 z = (*bx >> 16) - (zs & 0xffff) - borrow;
03112 borrow = (z & 0x10000) >> 16;
03113 Storeinc(bx, z, y);
03114 #else
03115 ys = *sx++ + carry;
03116 carry = ys >> 16;
03117 y = *bx - (ys & 0xffff) - borrow;
03118 borrow = (y & 0x10000) >> 16;
03119 *bx++ = y & 0xffff;
03120 #endif
03121 #endif
03122 } while (sx <= sxe);
03123 bx = b->x;
03124 bxe = bx + n;
03125 if (!*bxe) {
03126 while (--bxe > bx && !*bxe)
03127 --n;
03128 b->wds = n;
03129 }
03130 }
03131 return q;
03132 }
03133
03134 #ifndef MULTIPLE_THREADS
03135 static char *dtoa_result;
03136 #endif
03137
03138 #ifndef MULTIPLE_THREADS
03139 static char *
03140 rv_alloc(int i)
03141 {
03142 return dtoa_result = xmalloc(i);
03143 }
03144 #else
03145 #define rv_alloc(i) xmalloc(i)
03146 #endif
03147
03148 static char *
03149 nrv_alloc(const char *s, char **rve, size_t n)
03150 {
03151 char *rv, *t;
03152
03153 t = rv = rv_alloc(n);
03154 while ((*t = *s++) != 0) t++;
03155 if (rve)
03156 *rve = t;
03157 return rv;
03158 }
03159
03160 #define rv_strdup(s, rve) nrv_alloc((s), (rve), strlen(s)+1)
03161
03162 #ifndef MULTIPLE_THREADS
03163
03164
03165
03166
03167
03168
03169 static void
03170 freedtoa(char *s)
03171 {
03172 xfree(s);
03173 }
03174 #endif
03175
03176 static const char INFSTR[] = "Infinity";
03177 static const char NANSTR[] = "NaN";
03178 static const char ZEROSTR[] = "0";
03179
03180
03181
03182
03183
03184
03185
03186
03187
03188
03189
03190
03191
03192
03193
03194
03195
03196
03197
03198
03199
03200
03201
03202
03203
03204
03205
03206
03207
03208
03209
03210
03211
03212
03213
03214 char *
03215 ruby_dtoa(double d_, int mode, int ndigits, int *decpt, int *sign, char **rve)
03216 {
03217
03218
03219
03220
03221
03222
03223
03224
03225
03226
03227
03228
03229
03230
03231
03232
03233
03234
03235
03236
03237
03238
03239
03240
03241
03242
03243
03244
03245
03246
03247
03248
03249
03250
03251 int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1,
03252 j, j1, k, k0, k_check, leftright, m2, m5, s2, s5,
03253 spec_case, try_quick;
03254 Long L;
03255 #ifndef Sudden_Underflow
03256 int denorm;
03257 ULong x;
03258 #endif
03259 Bigint *b, *b1, *delta, *mlo = 0, *mhi = 0, *S;
03260 double ds;
03261 double_u d, d2, eps;
03262 char *s, *s0;
03263 #ifdef Honor_FLT_ROUNDS
03264 int rounding;
03265 #endif
03266 #ifdef SET_INEXACT
03267 int inexact, oldinexact;
03268 #endif
03269
03270 dval(d) = d_;
03271
03272 #ifndef MULTIPLE_THREADS
03273 if (dtoa_result) {
03274 freedtoa(dtoa_result);
03275 dtoa_result = 0;
03276 }
03277 #endif
03278
03279 if (word0(d) & Sign_bit) {
03280
03281 *sign = 1;
03282 word0(d) &= ~Sign_bit;
03283 }
03284 else
03285 *sign = 0;
03286
03287 #if defined(IEEE_Arith) + defined(VAX)
03288 #ifdef IEEE_Arith
03289 if ((word0(d) & Exp_mask) == Exp_mask)
03290 #else
03291 if (word0(d) == 0x8000)
03292 #endif
03293 {
03294
03295 *decpt = 9999;
03296 #ifdef IEEE_Arith
03297 if (!word1(d) && !(word0(d) & 0xfffff))
03298 return rv_strdup(INFSTR, rve);
03299 #endif
03300 return rv_strdup(NANSTR, rve);
03301 }
03302 #endif
03303 #ifdef IBM
03304 dval(d) += 0;
03305 #endif
03306 if (!dval(d)) {
03307 *decpt = 1;
03308 return rv_strdup(ZEROSTR, rve);
03309 }
03310
03311 #ifdef SET_INEXACT
03312 try_quick = oldinexact = get_inexact();
03313 inexact = 1;
03314 #endif
03315 #ifdef Honor_FLT_ROUNDS
03316 if ((rounding = Flt_Rounds) >= 2) {
03317 if (*sign)
03318 rounding = rounding == 2 ? 0 : 2;
03319 else
03320 if (rounding != 2)
03321 rounding = 0;
03322 }
03323 #endif
03324
03325 b = d2b(dval(d), &be, &bbits);
03326 #ifdef Sudden_Underflow
03327 i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
03328 #else
03329 if ((i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) != 0) {
03330 #endif
03331 dval(d2) = dval(d);
03332 word0(d2) &= Frac_mask1;
03333 word0(d2) |= Exp_11;
03334 #ifdef IBM
03335 if (j = 11 - hi0bits(word0(d2) & Frac_mask))
03336 dval(d2) /= 1 << j;
03337 #endif
03338
03339
03340
03341
03342
03343
03344
03345
03346
03347
03348
03349
03350
03351
03352
03353
03354
03355
03356
03357
03358
03359
03360
03361 i -= Bias;
03362 #ifdef IBM
03363 i <<= 2;
03364 i += j;
03365 #endif
03366 #ifndef Sudden_Underflow
03367 denorm = 0;
03368 }
03369 else {
03370
03371
03372 i = bbits + be + (Bias + (P-1) - 1);
03373 x = i > 32 ? word0(d) << (64 - i) | word1(d) >> (i - 32)
03374 : word1(d) << (32 - i);
03375 dval(d2) = x;
03376 word0(d2) -= 31*Exp_msk1;
03377 i -= (Bias + (P-1) - 1) + 1;
03378 denorm = 1;
03379 }
03380 #endif
03381 ds = (dval(d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
03382 k = (int)ds;
03383 if (ds < 0. && ds != k)
03384 k--;
03385 k_check = 1;
03386 if (k >= 0 && k <= Ten_pmax) {
03387 if (dval(d) < tens[k])
03388 k--;
03389 k_check = 0;
03390 }
03391 j = bbits - i - 1;
03392 if (j >= 0) {
03393 b2 = 0;
03394 s2 = j;
03395 }
03396 else {
03397 b2 = -j;
03398 s2 = 0;
03399 }
03400 if (k >= 0) {
03401 b5 = 0;
03402 s5 = k;
03403 s2 += k;
03404 }
03405 else {
03406 b2 -= k;
03407 b5 = -k;
03408 s5 = 0;
03409 }
03410 if (mode < 0 || mode > 9)
03411 mode = 0;
03412
03413 #ifndef SET_INEXACT
03414 #ifdef Check_FLT_ROUNDS
03415 try_quick = Rounding == 1;
03416 #else
03417 try_quick = 1;
03418 #endif
03419 #endif
03420
03421 if (mode > 5) {
03422 mode -= 4;
03423 try_quick = 0;
03424 }
03425 leftright = 1;
03426 ilim = ilim1 = -1;
03427 switch (mode) {
03428 case 0:
03429 case 1:
03430 i = 18;
03431 ndigits = 0;
03432 break;
03433 case 2:
03434 leftright = 0;
03435
03436 case 4:
03437 if (ndigits <= 0)
03438 ndigits = 1;
03439 ilim = ilim1 = i = ndigits;
03440 break;
03441 case 3:
03442 leftright = 0;
03443
03444 case 5:
03445 i = ndigits + k + 1;
03446 ilim = i;
03447 ilim1 = i - 1;
03448 if (i <= 0)
03449 i = 1;
03450 }
03451 s = s0 = rv_alloc(i+1);
03452
03453 #ifdef Honor_FLT_ROUNDS
03454 if (mode > 1 && rounding != 1)
03455 leftright = 0;
03456 #endif
03457
03458 if (ilim >= 0 && ilim <= Quick_max && try_quick) {
03459
03460
03461
03462 i = 0;
03463 dval(d2) = dval(d);
03464 k0 = k;
03465 ilim0 = ilim;
03466 ieps = 2;
03467 if (k > 0) {
03468 ds = tens[k&0xf];
03469 j = k >> 4;
03470 if (j & Bletch) {
03471
03472 j &= Bletch - 1;
03473 dval(d) /= bigtens[n_bigtens-1];
03474 ieps++;
03475 }
03476 for (; j; j >>= 1, i++)
03477 if (j & 1) {
03478 ieps++;
03479 ds *= bigtens[i];
03480 }
03481 dval(d) /= ds;
03482 }
03483 else if ((j1 = -k) != 0) {
03484 dval(d) *= tens[j1 & 0xf];
03485 for (j = j1 >> 4; j; j >>= 1, i++)
03486 if (j & 1) {
03487 ieps++;
03488 dval(d) *= bigtens[i];
03489 }
03490 }
03491 if (k_check && dval(d) < 1. && ilim > 0) {
03492 if (ilim1 <= 0)
03493 goto fast_failed;
03494 ilim = ilim1;
03495 k--;
03496 dval(d) *= 10.;
03497 ieps++;
03498 }
03499 dval(eps) = ieps*dval(d) + 7.;
03500 word0(eps) -= (P-1)*Exp_msk1;
03501 if (ilim == 0) {
03502 S = mhi = 0;
03503 dval(d) -= 5.;
03504 if (dval(d) > dval(eps))
03505 goto one_digit;
03506 if (dval(d) < -dval(eps))
03507 goto no_digits;
03508 goto fast_failed;
03509 }
03510 #ifndef No_leftright
03511 if (leftright) {
03512
03513
03514
03515 dval(eps) = 0.5/tens[ilim-1] - dval(eps);
03516 for (i = 0;;) {
03517 L = (int)dval(d);
03518 dval(d) -= L;
03519 *s++ = '0' + (int)L;
03520 if (dval(d) < dval(eps))
03521 goto ret1;
03522 if (1. - dval(d) < dval(eps))
03523 goto bump_up;
03524 if (++i >= ilim)
03525 break;
03526 dval(eps) *= 10.;
03527 dval(d) *= 10.;
03528 }
03529 }
03530 else {
03531 #endif
03532
03533 dval(eps) *= tens[ilim-1];
03534 for (i = 1;; i++, dval(d) *= 10.) {
03535 L = (Long)(dval(d));
03536 if (!(dval(d) -= L))
03537 ilim = i;
03538 *s++ = '0' + (int)L;
03539 if (i == ilim) {
03540 if (dval(d) > 0.5 + dval(eps))
03541 goto bump_up;
03542 else if (dval(d) < 0.5 - dval(eps)) {
03543 while (*--s == '0') ;
03544 s++;
03545 goto ret1;
03546 }
03547 break;
03548 }
03549 }
03550 #ifndef No_leftright
03551 }
03552 #endif
03553 fast_failed:
03554 s = s0;
03555 dval(d) = dval(d2);
03556 k = k0;
03557 ilim = ilim0;
03558 }
03559
03560
03561
03562 if (be >= 0 && k <= Int_max) {
03563
03564 ds = tens[k];
03565 if (ndigits < 0 && ilim <= 0) {
03566 S = mhi = 0;
03567 if (ilim < 0 || dval(d) <= 5*ds)
03568 goto no_digits;
03569 goto one_digit;
03570 }
03571 for (i = 1;; i++, dval(d) *= 10.) {
03572 L = (Long)(dval(d) / ds);
03573 dval(d) -= L*ds;
03574 #ifdef Check_FLT_ROUNDS
03575
03576 if (dval(d) < 0) {
03577 L--;
03578 dval(d) += ds;
03579 }
03580 #endif
03581 *s++ = '0' + (int)L;
03582 if (!dval(d)) {
03583 #ifdef SET_INEXACT
03584 inexact = 0;
03585 #endif
03586 break;
03587 }
03588 if (i == ilim) {
03589 #ifdef Honor_FLT_ROUNDS
03590 if (mode > 1)
03591 switch (rounding) {
03592 case 0: goto ret1;
03593 case 2: goto bump_up;
03594 }
03595 #endif
03596 dval(d) += dval(d);
03597 if (dval(d) > ds || (dval(d) == ds && (L & 1))) {
03598 bump_up:
03599 while (*--s == '9')
03600 if (s == s0) {
03601 k++;
03602 *s = '0';
03603 break;
03604 }
03605 ++*s++;
03606 }
03607 break;
03608 }
03609 }
03610 goto ret1;
03611 }
03612
03613 m2 = b2;
03614 m5 = b5;
03615 if (leftright) {
03616 i =
03617 #ifndef Sudden_Underflow
03618 denorm ? be + (Bias + (P-1) - 1 + 1) :
03619 #endif
03620 #ifdef IBM
03621 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3);
03622 #else
03623 1 + P - bbits;
03624 #endif
03625 b2 += i;
03626 s2 += i;
03627 mhi = i2b(1);
03628 }
03629 if (m2 > 0 && s2 > 0) {
03630 i = m2 < s2 ? m2 : s2;
03631 b2 -= i;
03632 m2 -= i;
03633 s2 -= i;
03634 }
03635 if (b5 > 0) {
03636 if (leftright) {
03637 if (m5 > 0) {
03638 mhi = pow5mult(mhi, m5);
03639 b1 = mult(mhi, b);
03640 Bfree(b);
03641 b = b1;
03642 }
03643 if ((j = b5 - m5) != 0)
03644 b = pow5mult(b, j);
03645 }
03646 else
03647 b = pow5mult(b, b5);
03648 }
03649 S = i2b(1);
03650 if (s5 > 0)
03651 S = pow5mult(S, s5);
03652
03653
03654
03655 spec_case = 0;
03656 if ((mode < 2 || leftright)
03657 #ifdef Honor_FLT_ROUNDS
03658 && rounding == 1
03659 #endif
03660 ) {
03661 if (!word1(d) && !(word0(d) & Bndry_mask)
03662 #ifndef Sudden_Underflow
03663 && word0(d) & (Exp_mask & ~Exp_msk1)
03664 #endif
03665 ) {
03666
03667 b2 += Log2P;
03668 s2 += Log2P;
03669 spec_case = 1;
03670 }
03671 }
03672
03673
03674
03675
03676
03677
03678
03679
03680 #ifdef Pack_32
03681 if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f) != 0)
03682 i = 32 - i;
03683 #else
03684 if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf) != 0)
03685 i = 16 - i;
03686 #endif
03687 if (i > 4) {
03688 i -= 4;
03689 b2 += i;
03690 m2 += i;
03691 s2 += i;
03692 }
03693 else if (i < 4) {
03694 i += 28;
03695 b2 += i;
03696 m2 += i;
03697 s2 += i;
03698 }
03699 if (b2 > 0)
03700 b = lshift(b, b2);
03701 if (s2 > 0)
03702 S = lshift(S, s2);
03703 if (k_check) {
03704 if (cmp(b,S) < 0) {
03705 k--;
03706 b = multadd(b, 10, 0);
03707 if (leftright)
03708 mhi = multadd(mhi, 10, 0);
03709 ilim = ilim1;
03710 }
03711 }
03712 if (ilim <= 0 && (mode == 3 || mode == 5)) {
03713 if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
03714
03715 no_digits:
03716 k = -1 - ndigits;
03717 goto ret;
03718 }
03719 one_digit:
03720 *s++ = '1';
03721 k++;
03722 goto ret;
03723 }
03724 if (leftright) {
03725 if (m2 > 0)
03726 mhi = lshift(mhi, m2);
03727
03728
03729
03730
03731
03732 mlo = mhi;
03733 if (spec_case) {
03734 mhi = Balloc(mhi->k);
03735 Bcopy(mhi, mlo);
03736 mhi = lshift(mhi, Log2P);
03737 }
03738
03739 for (i = 1;;i++) {
03740 dig = quorem(b,S) + '0';
03741
03742
03743
03744 j = cmp(b, mlo);
03745 delta = diff(S, mhi);
03746 j1 = delta->sign ? 1 : cmp(b, delta);
03747 Bfree(delta);
03748 #ifndef ROUND_BIASED
03749 if (j1 == 0 && mode != 1 && !(word1(d) & 1)
03750 #ifdef Honor_FLT_ROUNDS
03751 && rounding >= 1
03752 #endif
03753 ) {
03754 if (dig == '9')
03755 goto round_9_up;
03756 if (j > 0)
03757 dig++;
03758 #ifdef SET_INEXACT
03759 else if (!b->x[0] && b->wds <= 1)
03760 inexact = 0;
03761 #endif
03762 *s++ = dig;
03763 goto ret;
03764 }
03765 #endif
03766 if (j < 0 || (j == 0 && mode != 1
03767 #ifndef ROUND_BIASED
03768 && !(word1(d) & 1)
03769 #endif
03770 )) {
03771 if (!b->x[0] && b->wds <= 1) {
03772 #ifdef SET_INEXACT
03773 inexact = 0;
03774 #endif
03775 goto accept_dig;
03776 }
03777 #ifdef Honor_FLT_ROUNDS
03778 if (mode > 1)
03779 switch (rounding) {
03780 case 0: goto accept_dig;
03781 case 2: goto keep_dig;
03782 }
03783 #endif
03784 if (j1 > 0) {
03785 b = lshift(b, 1);
03786 j1 = cmp(b, S);
03787 if ((j1 > 0 || (j1 == 0 && (dig & 1))) && dig++ == '9')
03788 goto round_9_up;
03789 }
03790 accept_dig:
03791 *s++ = dig;
03792 goto ret;
03793 }
03794 if (j1 > 0) {
03795 #ifdef Honor_FLT_ROUNDS
03796 if (!rounding)
03797 goto accept_dig;
03798 #endif
03799 if (dig == '9') {
03800 round_9_up:
03801 *s++ = '9';
03802 goto roundoff;
03803 }
03804 *s++ = dig + 1;
03805 goto ret;
03806 }
03807 #ifdef Honor_FLT_ROUNDS
03808 keep_dig:
03809 #endif
03810 *s++ = dig;
03811 if (i == ilim)
03812 break;
03813 b = multadd(b, 10, 0);
03814 if (mlo == mhi)
03815 mlo = mhi = multadd(mhi, 10, 0);
03816 else {
03817 mlo = multadd(mlo, 10, 0);
03818 mhi = multadd(mhi, 10, 0);
03819 }
03820 }
03821 }
03822 else
03823 for (i = 1;; i++) {
03824 *s++ = dig = quorem(b,S) + '0';
03825 if (!b->x[0] && b->wds <= 1) {
03826 #ifdef SET_INEXACT
03827 inexact = 0;
03828 #endif
03829 goto ret;
03830 }
03831 if (i >= ilim)
03832 break;
03833 b = multadd(b, 10, 0);
03834 }
03835
03836
03837
03838 #ifdef Honor_FLT_ROUNDS
03839 switch (rounding) {
03840 case 0: goto trimzeros;
03841 case 2: goto roundoff;
03842 }
03843 #endif
03844 b = lshift(b, 1);
03845 j = cmp(b, S);
03846 if (j > 0 || (j == 0 && (dig & 1))) {
03847 roundoff:
03848 while (*--s == '9')
03849 if (s == s0) {
03850 k++;
03851 *s++ = '1';
03852 goto ret;
03853 }
03854 ++*s++;
03855 }
03856 else {
03857 while (*--s == '0') ;
03858 s++;
03859 }
03860 ret:
03861 Bfree(S);
03862 if (mhi) {
03863 if (mlo && mlo != mhi)
03864 Bfree(mlo);
03865 Bfree(mhi);
03866 }
03867 ret1:
03868 #ifdef SET_INEXACT
03869 if (inexact) {
03870 if (!oldinexact) {
03871 word0(d) = Exp_1 + (70 << Exp_shift);
03872 word1(d) = 0;
03873 dval(d) += 1.;
03874 }
03875 }
03876 else if (!oldinexact)
03877 clear_inexact();
03878 #endif
03879 Bfree(b);
03880 *s = 0;
03881 *decpt = k + 1;
03882 if (rve)
03883 *rve = s;
03884 return s0;
03885 }
03886
03887 void
03888 ruby_each_words(const char *str, void (*func)(const char*, int, void*), void *arg)
03889 {
03890 const char *end;
03891 int len;
03892
03893 if (!str) return;
03894 for (; *str; str = end) {
03895 while (ISSPACE(*str) || *str == ',') str++;
03896 if (!*str) break;
03897 end = str;
03898 while (*end && !ISSPACE(*end) && *end != ',') end++;
03899 len = (int)(end - str);
03900 (*func)(str, len, arg);
03901 }
03902 }
03903
03904
03905
03906
03907
03908
03909
03910
03911
03912
03913
03914
03915
03916
03917
03918
03919
03920
03921
03922
03923
03924
03925
03926
03927
03928
03929
03930 #define DBL_MANH_SIZE 20
03931 #define DBL_MANL_SIZE 32
03932 #define DBL_ADJ (DBL_MAX_EXP - 2)
03933 #define SIGFIGS ((DBL_MANT_DIG + 3) / 4 + 1)
03934 #define dexp_get(u) ((int)(word0(u) >> Exp_shift) & ~Exp_msk1)
03935 #define dexp_set(u,v) (word0(u) = (((int)(word0(u)) & ~Exp_mask) | ((v) << Exp_shift)))
03936 #define dmanh_get(u) ((uint32_t)(word0(u) & Frac_mask))
03937 #define dmanl_get(u) ((uint32_t)word1(u))
03938
03939
03940
03941
03942
03943
03944
03945
03946
03947
03948
03949
03950
03951
03952
03953
03954
03955
03956
03957
03958
03959
03960
03961
03962
03963
03964 char *
03965 ruby_hdtoa(double d, const char *xdigs, int ndigits, int *decpt, int *sign,
03966 char **rve)
03967 {
03968 U u;
03969 char *s, *s0;
03970 int bufsize;
03971 uint32_t manh, manl;
03972
03973 u.d = d;
03974 if (word0(u) & Sign_bit) {
03975
03976 *sign = 1;
03977 word0(u) &= ~Sign_bit;
03978 }
03979 else
03980 *sign = 0;
03981
03982 if (isinf(d)) {
03983 *decpt = INT_MAX;
03984 return rv_strdup(INFSTR, rve);
03985 }
03986 else if (isnan(d)) {
03987 *decpt = INT_MAX;
03988 return rv_strdup(NANSTR, rve);
03989 }
03990 else if (d == 0.0) {
03991 *decpt = 1;
03992 return rv_strdup(ZEROSTR, rve);
03993 }
03994 else if (dexp_get(u)) {
03995 *decpt = dexp_get(u) - DBL_ADJ;
03996 }
03997 else {
03998 u.d *= 5.363123171977039e+154 ;
03999 *decpt = dexp_get(u) - (514 + DBL_ADJ);
04000 }
04001
04002 if (ndigits == 0)
04003 ndigits = 1;
04004
04005
04006
04007
04008
04009 bufsize = (ndigits > 0) ? ndigits : SIGFIGS;
04010 s0 = rv_alloc(bufsize+1);
04011
04012
04013 if (SIGFIGS > ndigits && ndigits > 0) {
04014 float redux = 1.0f;
04015 volatile double d;
04016 int offset = 4 * ndigits + DBL_MAX_EXP - 4 - DBL_MANT_DIG;
04017 dexp_set(u, offset);
04018 d = u.d;
04019 d += redux;
04020 d -= redux;
04021 u.d = d;
04022 *decpt += dexp_get(u) - offset;
04023 }
04024
04025 manh = dmanh_get(u);
04026 manl = dmanl_get(u);
04027 *s0 = '1';
04028 for (s = s0 + 1; s < s0 + bufsize; s++) {
04029 *s = xdigs[(manh >> (DBL_MANH_SIZE - 4)) & 0xf];
04030 manh = (manh << 4) | (manl >> (DBL_MANL_SIZE - 4));
04031 manl <<= 4;
04032 }
04033
04034
04035 if (ndigits < 0) {
04036 for (ndigits = SIGFIGS; s0[ndigits - 1] == '0'; ndigits--)
04037 ;
04038 }
04039
04040 s = s0 + ndigits;
04041 *s = '\0';
04042 if (rve != NULL)
04043 *rve = s;
04044 return (s0);
04045 }
04046
04047 #ifdef __cplusplus
04048 #if 0
04049 {
04050 #endif
04051 }
04052 #endif
04053