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