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