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