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