Christian Heimes | 284d927 | 2007-12-10 22:28:56 +0000 | [diff] [blame] | 1 | /* Free-format floating point printer |
| 2 | * |
| 3 | * Based on "Floating-Point Printer Sample Code", by Robert G. Burger, |
| 4 | * http://www.cs.indiana.edu/~burger/fp/index.html |
| 5 | */ |
| 6 | |
| 7 | #include "Python.h" |
| 8 | |
| 9 | #if defined(__alpha) || defined(__i386) || defined(_M_IX86) || defined(_M_X64) || defined(_M_IA64) |
| 10 | #define LITTLE_ENDIAN_IEEE_DOUBLE |
| 11 | #elif !(defined(__ppc__) || defined(sparc) || defined(__sgi) || defined(_IBMR2) || defined(hpux)) |
| 12 | #error unknown machine type |
| 13 | #endif |
| 14 | |
| 15 | #if defined(_M_IX86) |
| 16 | #define UNSIGNED64 unsigned __int64 |
| 17 | #elif defined(__alpha) |
| 18 | #define UNSIGNED64 unsigned long |
| 19 | #else |
| 20 | #define UNSIGNED64 unsigned long long |
| 21 | #endif |
| 22 | |
| 23 | #ifndef U32 |
| 24 | #define U32 unsigned int |
| 25 | #endif |
| 26 | |
| 27 | /* exponent stored + 1024, hidden bit to left of decimal point */ |
| 28 | #define bias 1023 |
| 29 | #define bitstoright 52 |
| 30 | #define m1mask 0xf |
| 31 | #define hidden_bit 0x100000 |
| 32 | #ifdef LITTLE_ENDIAN_IEEE_DOUBLE |
| 33 | struct dblflt { |
| 34 | unsigned int m4: 16; |
| 35 | unsigned int m3: 16; |
| 36 | unsigned int m2: 16; |
| 37 | unsigned int m1: 4; |
| 38 | unsigned int e: 11; |
| 39 | unsigned int s: 1; |
| 40 | }; |
| 41 | #else |
| 42 | /* Big Endian IEEE Double Floats */ |
| 43 | struct dblflt { |
| 44 | unsigned int s: 1; |
| 45 | unsigned int e: 11; |
| 46 | unsigned int m1: 4; |
| 47 | unsigned int m2: 16; |
| 48 | unsigned int m3: 16; |
| 49 | unsigned int m4: 16; |
| 50 | }; |
| 51 | #endif |
| 52 | #define float_radix 2.147483648e9 |
| 53 | |
| 54 | |
| 55 | typedef UNSIGNED64 Bigit; |
| 56 | #define BIGSIZE 24 |
| 57 | #define MIN_E -1074 |
| 58 | #define MAX_FIVE 325 |
| 59 | #define B_P1 ((Bigit)1 << 52) |
| 60 | |
| 61 | typedef struct { |
| 62 | int l; |
| 63 | Bigit d[BIGSIZE]; |
| 64 | } Bignum; |
| 65 | |
| 66 | static Bignum R, S, MP, MM, five[MAX_FIVE]; |
| 67 | static Bignum S2, S3, S4, S5, S6, S7, S8, S9; |
| 68 | static int ruf, k, s_n, use_mp, qr_shift, sl, slr; |
| 69 | |
| 70 | static void mul10(Bignum *x); |
| 71 | static void big_short_mul(Bignum *x, Bigit y, Bignum *z); |
| 72 | /* |
| 73 | static void print_big(Bignum *x); |
| 74 | */ |
| 75 | static int estimate(int n); |
| 76 | static void one_shift_left(int y, Bignum *z); |
| 77 | static void short_shift_left(Bigit x, int y, Bignum *z); |
| 78 | static void big_shift_left(Bignum *x, int y, Bignum *z); |
| 79 | static int big_comp(Bignum *x, Bignum *y); |
| 80 | static int sub_big(Bignum *x, Bignum *y, Bignum *z); |
| 81 | static void add_big(Bignum *x, Bignum *y, Bignum *z); |
| 82 | static int add_cmp(void); |
| 83 | static int qr(void); |
| 84 | |
| 85 | /*static int _PyFloat_Digits(char *buf, double v, int *signum);*/ |
| 86 | /*static void _PyFloat_DigitsInit(void);*/ |
| 87 | |
| 88 | #define ADD(x, y, z, k) {\ |
| 89 | Bigit x_add, z_add;\ |
| 90 | x_add = (x);\ |
| 91 | if ((k))\ |
| 92 | z_add = x_add + (y) + 1, (k) = (z_add <= x_add);\ |
| 93 | else\ |
| 94 | z_add = x_add + (y), (k) = (z_add < x_add);\ |
| 95 | (z) = z_add;\ |
| 96 | } |
| 97 | |
| 98 | #define SUB(x, y, z, b) {\ |
| 99 | Bigit x_sub, y_sub;\ |
| 100 | x_sub = (x); y_sub = (y);\ |
| 101 | if ((b))\ |
| 102 | (z) = x_sub - y_sub - 1, b = (y_sub >= x_sub);\ |
| 103 | else\ |
| 104 | (z) = x_sub - y_sub, b = (y_sub > x_sub);\ |
| 105 | } |
| 106 | |
| 107 | #define MUL(x, y, z, k) {\ |
| 108 | Bigit x_mul, low, high;\ |
| 109 | x_mul = (x);\ |
| 110 | low = (x_mul & 0xffffffff) * (y) + (k);\ |
| 111 | high = (x_mul >> 32) * (y) + (low >> 32);\ |
| 112 | (k) = high >> 32;\ |
| 113 | (z) = (low & 0xffffffff) | (high << 32);\ |
| 114 | } |
| 115 | |
| 116 | #define SLL(x, y, z, k) {\ |
| 117 | Bigit x_sll = (x);\ |
| 118 | (z) = (x_sll << (y)) | (k);\ |
| 119 | (k) = x_sll >> (64 - (y));\ |
| 120 | } |
| 121 | |
| 122 | static void |
| 123 | mul10(Bignum *x) |
| 124 | { |
| 125 | int i, l; |
| 126 | Bigit *p, k; |
| 127 | |
| 128 | l = x->l; |
| 129 | for (i = l, p = &x->d[0], k = 0; i >= 0; i--) |
| 130 | MUL(*p, 10, *p++, k); |
| 131 | if (k != 0) |
| 132 | *p = k, x->l = l+1; |
| 133 | } |
| 134 | |
| 135 | static void |
| 136 | big_short_mul(Bignum *x, Bigit y, Bignum *z) |
| 137 | { |
| 138 | int i, xl, zl; |
| 139 | Bigit *xp, *zp, k; |
| 140 | U32 high, low; |
| 141 | |
| 142 | xl = x->l; |
| 143 | xp = &x->d[0]; |
| 144 | zl = xl; |
| 145 | zp = &z->d[0]; |
| 146 | high = y >> 32; |
| 147 | low = y & 0xffffffff; |
| 148 | for (i = xl, k = 0; i >= 0; i--, xp++, zp++) { |
| 149 | Bigit xlow, xhigh, z0, t, c, z1; |
| 150 | xlow = *xp & 0xffffffff; |
| 151 | xhigh = *xp >> 32; |
| 152 | z0 = (xlow * low) + k; /* Cout is (z0 < k) */ |
| 153 | t = xhigh * low; |
| 154 | z1 = (xlow * high) + t; |
| 155 | c = (z1 < t); |
| 156 | t = z0 >> 32; |
| 157 | z1 += t; |
| 158 | c += (z1 < t); |
| 159 | *zp = (z1 << 32) | (z0 & 0xffffffff); |
| 160 | k = (xhigh * high) + (c << 32) + (z1 >> 32) + (z0 < k); |
| 161 | } |
| 162 | if (k != 0) |
| 163 | *zp = k, zl++; |
| 164 | z->l = zl; |
| 165 | } |
| 166 | |
| 167 | /* |
| 168 | static void |
| 169 | print_big(Bignum *x) |
| 170 | { |
| 171 | int i; |
| 172 | Bigit *p; |
| 173 | |
| 174 | printf("#x"); |
| 175 | i = x->l; |
| 176 | p = &x->d[i]; |
| 177 | for (p = &x->d[i]; i >= 0; i--) { |
| 178 | Bigit b = *p--; |
| 179 | printf("%08x%08x", (int)(b >> 32), (int)(b & 0xffffffff)); |
| 180 | } |
| 181 | } |
| 182 | */ |
| 183 | |
| 184 | static int |
| 185 | estimate(int n) |
| 186 | { |
| 187 | if (n < 0) |
| 188 | return (int)(n*0.3010299956639812); |
| 189 | else |
| 190 | return 1+(int)(n*0.3010299956639811); |
| 191 | } |
| 192 | |
| 193 | static void |
| 194 | one_shift_left(int y, Bignum *z) |
| 195 | { |
| 196 | int n, m, i; |
| 197 | Bigit *zp; |
| 198 | |
| 199 | n = y / 64; |
| 200 | m = y % 64; |
| 201 | zp = &z->d[0]; |
| 202 | for (i = n; i > 0; i--) *zp++ = 0; |
| 203 | *zp = (Bigit)1 << m; |
| 204 | z->l = n; |
| 205 | } |
| 206 | |
| 207 | static void |
| 208 | short_shift_left(Bigit x, int y, Bignum *z) |
| 209 | { |
| 210 | int n, m, i, zl; |
| 211 | Bigit *zp; |
| 212 | |
| 213 | n = y / 64; |
| 214 | m = y % 64; |
| 215 | zl = n; |
| 216 | zp = &(z->d[0]); |
| 217 | for (i = n; i > 0; i--) *zp++ = 0; |
| 218 | if (m == 0) |
| 219 | *zp = x; |
| 220 | else { |
| 221 | Bigit high = x >> (64 - m); |
| 222 | *zp = x << m; |
| 223 | if (high != 0) |
| 224 | *++zp = high, zl++; |
| 225 | } |
| 226 | z->l = zl; |
| 227 | } |
| 228 | |
| 229 | static void |
| 230 | big_shift_left(Bignum *x, int y, Bignum *z) |
| 231 | { |
| 232 | int n, m, i, xl, zl; |
| 233 | Bigit *xp, *zp, k; |
| 234 | |
| 235 | n = y / 64; |
| 236 | m = y % 64; |
| 237 | xl = x->l; |
| 238 | xp = &(x->d[0]); |
| 239 | zl = xl + n; |
| 240 | zp = &(z->d[0]); |
| 241 | for (i = n; i > 0; i--) *zp++ = 0; |
| 242 | if (m == 0) |
| 243 | for (i = xl; i >= 0; i--) *zp++ = *xp++; |
| 244 | else { |
| 245 | for (i = xl, k = 0; i >= 0; i--) |
| 246 | SLL(*xp++, m, *zp++, k); |
| 247 | if (k != 0) |
| 248 | *zp = k, zl++; |
| 249 | } |
| 250 | z->l = zl; |
| 251 | } |
| 252 | |
| 253 | |
| 254 | static int |
| 255 | big_comp(Bignum *x, Bignum *y) |
| 256 | { |
| 257 | int i, xl, yl; |
| 258 | Bigit *xp, *yp; |
| 259 | |
| 260 | xl = x->l; |
| 261 | yl = y->l; |
| 262 | if (xl > yl) return 1; |
| 263 | if (xl < yl) return -1; |
| 264 | xp = &x->d[xl]; |
| 265 | yp = &y->d[xl]; |
| 266 | for (i = xl; i >= 0; i--, xp--, yp--) { |
| 267 | Bigit a = *xp; |
| 268 | Bigit b = *yp; |
| 269 | |
| 270 | if (a > b) return 1; |
| 271 | else if (a < b) return -1; |
| 272 | } |
| 273 | return 0; |
| 274 | } |
| 275 | |
| 276 | static int |
| 277 | sub_big(Bignum *x, Bignum *y, Bignum *z) |
| 278 | { |
| 279 | int xl, yl, zl, b, i; |
| 280 | Bigit *xp, *yp, *zp; |
| 281 | |
| 282 | xl = x->l; |
| 283 | yl = y->l; |
| 284 | if (yl > xl) return 1; |
| 285 | xp = &x->d[0]; |
| 286 | yp = &y->d[0]; |
| 287 | zp = &z->d[0]; |
| 288 | |
| 289 | for (i = yl, b = 0; i >= 0; i--) |
| 290 | SUB(*xp++, *yp++, *zp++, b); |
| 291 | for (i = xl-yl; b && i > 0; i--) { |
| 292 | Bigit x_sub; |
| 293 | x_sub = *xp++; |
| 294 | *zp++ = x_sub - 1; |
| 295 | b = (x_sub == 0); |
| 296 | } |
| 297 | for (; i > 0; i--) *zp++ = *xp++; |
| 298 | if (b) return 1; |
| 299 | zl = xl; |
| 300 | while (*--zp == 0) zl--; |
| 301 | z->l = zl; |
| 302 | return 0; |
| 303 | } |
| 304 | |
| 305 | static void |
| 306 | add_big(Bignum *x, Bignum *y, Bignum *z) |
| 307 | { |
| 308 | int xl, yl, k, i; |
| 309 | Bigit *xp, *yp, *zp; |
| 310 | |
| 311 | xl = x->l; |
| 312 | yl = y->l; |
| 313 | if (yl > xl) { |
| 314 | int tl; |
| 315 | Bignum *tn; |
| 316 | tl = xl; xl = yl; yl = tl; |
| 317 | tn = x; x = y; y = tn; |
| 318 | } |
| 319 | |
| 320 | xp = &x->d[0]; |
| 321 | yp = &y->d[0]; |
| 322 | zp = &z->d[0]; |
| 323 | |
| 324 | for (i = yl, k = 0; i >= 0; i--) |
| 325 | ADD(*xp++, *yp++, *zp++, k); |
| 326 | for (i = xl-yl; k && i > 0; i--) { |
| 327 | Bigit z_add; |
| 328 | z_add = *xp++ + 1; |
| 329 | k = (z_add == 0); |
| 330 | *zp++ = z_add; |
| 331 | } |
| 332 | for (; i > 0; i--) *zp++ = *xp++; |
| 333 | if (k) |
| 334 | *zp = 1, z->l = xl+1; |
| 335 | else |
| 336 | z->l = xl; |
| 337 | } |
| 338 | |
| 339 | static int |
| 340 | add_cmp() |
| 341 | { |
| 342 | int rl, ml, sl, suml; |
| 343 | static Bignum sum; |
| 344 | |
| 345 | rl = R.l; |
| 346 | ml = (use_mp ? MP.l : MM.l); |
| 347 | sl = S.l; |
| 348 | |
| 349 | suml = rl >= ml ? rl : ml; |
| 350 | if ((sl > suml+1) || ((sl == suml+1) && (S.d[sl] > 1))) return -1; |
| 351 | if (sl < suml) return 1; |
| 352 | |
| 353 | add_big(&R, (use_mp ? &MP : &MM), &sum); |
| 354 | return big_comp(&sum, &S); |
| 355 | } |
| 356 | |
| 357 | static int |
| 358 | qr() |
| 359 | { |
| 360 | if (big_comp(&R, &S5) < 0) |
| 361 | if (big_comp(&R, &S2) < 0) |
| 362 | if (big_comp(&R, &S) < 0) |
| 363 | return 0; |
| 364 | else { |
| 365 | sub_big(&R, &S, &R); |
| 366 | return 1; |
| 367 | } |
| 368 | else if (big_comp(&R, &S3) < 0) { |
| 369 | sub_big(&R, &S2, &R); |
| 370 | return 2; |
| 371 | } |
| 372 | else if (big_comp(&R, &S4) < 0) { |
| 373 | sub_big(&R, &S3, &R); |
| 374 | return 3; |
| 375 | } |
| 376 | else { |
| 377 | sub_big(&R, &S4, &R); |
| 378 | return 4; |
| 379 | } |
| 380 | else if (big_comp(&R, &S7) < 0) |
| 381 | if (big_comp(&R, &S6) < 0) { |
| 382 | sub_big(&R, &S5, &R); |
| 383 | return 5; |
| 384 | } |
| 385 | else { |
| 386 | sub_big(&R, &S6, &R); |
| 387 | return 6; |
| 388 | } |
| 389 | else if (big_comp(&R, &S9) < 0) |
| 390 | if (big_comp(&R, &S8) < 0) { |
| 391 | sub_big(&R, &S7, &R); |
| 392 | return 7; |
| 393 | } |
| 394 | else { |
| 395 | sub_big(&R, &S8, &R); |
| 396 | return 8; |
| 397 | } |
| 398 | else { |
| 399 | sub_big(&R, &S9, &R); |
| 400 | return 9; |
| 401 | } |
| 402 | } |
| 403 | |
| 404 | #define OUTDIG(d) { *buf++ = (d) + '0'; *buf = 0; return k; } |
| 405 | |
| 406 | int |
| 407 | _PyFloat_Digits(char *buf, double v, int *signum) |
| 408 | { |
| 409 | struct dblflt *x; |
| 410 | int sign, e, f_n, m_n, i, d, tc1, tc2; |
| 411 | Bigit f; |
| 412 | |
| 413 | /* decompose float into sign, mantissa & exponent */ |
| 414 | x = (struct dblflt *)&v; |
| 415 | sign = x->s; |
| 416 | e = x->e; |
| 417 | f = (Bigit)(x->m1 << 16 | x->m2) << 32 | (U32)(x->m3 << 16 | x->m4); |
| 418 | if (e != 0) { |
| 419 | e = e - bias - bitstoright; |
| 420 | f |= (Bigit)hidden_bit << 32; |
| 421 | } |
| 422 | else if (f != 0) |
| 423 | /* denormalized */ |
| 424 | e = 1 - bias - bitstoright; |
| 425 | |
| 426 | *signum = sign; |
| 427 | if (f == 0) { |
| 428 | *buf++ = '0'; |
| 429 | *buf = 0; |
| 430 | return 0; |
| 431 | } |
| 432 | |
| 433 | ruf = !(f & 1); /* ruf = (even? f) */ |
| 434 | |
| 435 | /* Compute the scaling factor estimate, k */ |
| 436 | if (e > MIN_E) |
| 437 | k = estimate(e+52); |
| 438 | else { |
| 439 | int n; |
| 440 | Bigit y; |
| 441 | |
| 442 | for (n = e+52, y = (Bigit)1 << 52; f < y; n--) y >>= 1; |
| 443 | k = estimate(n); |
| 444 | } |
| 445 | |
| 446 | if (e >= 0) |
| 447 | if (f != B_P1) |
| 448 | use_mp = 0, f_n = e+1, s_n = 1, m_n = e; |
| 449 | else |
| 450 | use_mp = 1, f_n = e+2, s_n = 2, m_n = e; |
| 451 | else |
| 452 | if ((e == MIN_E) || (f != B_P1)) |
| 453 | use_mp = 0, f_n = 1, s_n = 1-e, m_n = 0; |
| 454 | else |
| 455 | use_mp = 1, f_n = 2, s_n = 2-e, m_n = 0; |
| 456 | |
| 457 | /* Scale it! */ |
| 458 | if (k == 0) { |
| 459 | short_shift_left(f, f_n, &R); |
| 460 | one_shift_left(s_n, &S); |
| 461 | one_shift_left(m_n, &MM); |
| 462 | if (use_mp) one_shift_left(m_n+1, &MP); |
| 463 | qr_shift = 1; |
| 464 | } |
| 465 | else if (k > 0) { |
| 466 | s_n += k; |
| 467 | if (m_n >= s_n) |
| 468 | f_n -= s_n, m_n -= s_n, s_n = 0; |
| 469 | else |
| 470 | f_n -= m_n, s_n -= m_n, m_n = 0; |
| 471 | short_shift_left(f, f_n, &R); |
| 472 | big_shift_left(&five[k-1], s_n, &S); |
| 473 | one_shift_left(m_n, &MM); |
| 474 | if (use_mp) one_shift_left(m_n+1, &MP); |
| 475 | qr_shift = 0; |
| 476 | } |
| 477 | else { |
| 478 | Bignum *power = &five[-k-1]; |
| 479 | |
| 480 | s_n += k; |
| 481 | big_short_mul(power, f, &S); |
| 482 | big_shift_left(&S, f_n, &R); |
| 483 | one_shift_left(s_n, &S); |
| 484 | big_shift_left(power, m_n, &MM); |
| 485 | if (use_mp) big_shift_left(power, m_n+1, &MP); |
| 486 | qr_shift = 1; |
| 487 | } |
| 488 | |
| 489 | /* fixup */ |
| 490 | if (add_cmp() <= -ruf) { |
| 491 | k--; |
| 492 | mul10(&R); |
| 493 | mul10(&MM); |
| 494 | if (use_mp) mul10(&MP); |
| 495 | } |
| 496 | |
| 497 | /* |
| 498 | printf("\nk = %d\n", k); |
| 499 | printf("R = "); print_big(&R); |
| 500 | printf("\nS = "); print_big(&S); |
| 501 | printf("\nM- = "); print_big(&MM); |
| 502 | if (use_mp) printf("\nM+ = "), print_big(&MP); |
| 503 | putchar('\n'); |
| 504 | fflush(0); |
| 505 | */ |
| 506 | |
| 507 | if (qr_shift) { |
| 508 | sl = s_n / 64; |
| 509 | slr = s_n % 64; |
| 510 | } |
| 511 | else { |
| 512 | big_shift_left(&S, 1, &S2); |
| 513 | add_big(&S2, &S, &S3); |
| 514 | big_shift_left(&S2, 1, &S4); |
| 515 | add_big(&S4, &S, &S5); |
| 516 | add_big(&S4, &S2, &S6); |
| 517 | add_big(&S4, &S3, &S7); |
| 518 | big_shift_left(&S4, 1, &S8); |
| 519 | add_big(&S8, &S, &S9); |
| 520 | } |
| 521 | |
| 522 | again: |
| 523 | if (qr_shift) { /* Take advantage of the fact that S = (ash 1 s_n) */ |
| 524 | if (R.l < sl) |
| 525 | d = 0; |
| 526 | else if (R.l == sl) { |
| 527 | Bigit *p; |
| 528 | |
| 529 | p = &R.d[sl]; |
| 530 | d = *p >> slr; |
| 531 | *p &= ((Bigit)1 << slr) - 1; |
| 532 | for (i = sl; (i > 0) && (*p == 0); i--) p--; |
| 533 | R.l = i; |
| 534 | } |
| 535 | else { |
| 536 | Bigit *p; |
| 537 | |
| 538 | p = &R.d[sl+1]; |
| 539 | d = *p << (64 - slr) | *(p-1) >> slr; |
| 540 | p--; |
| 541 | *p &= ((Bigit)1 << slr) - 1; |
| 542 | for (i = sl; (i > 0) && (*p == 0); i--) p--; |
| 543 | R.l = i; |
| 544 | } |
| 545 | } |
| 546 | else /* We need to do quotient-remainder */ |
| 547 | d = qr(); |
| 548 | |
| 549 | tc1 = big_comp(&R, &MM) < ruf; |
| 550 | tc2 = add_cmp() > -ruf; |
| 551 | if (!tc1) |
| 552 | if (!tc2) { |
| 553 | mul10(&R); |
| 554 | mul10(&MM); |
| 555 | if (use_mp) mul10(&MP); |
| 556 | *buf++ = d + '0'; |
| 557 | goto again; |
| 558 | } |
| 559 | else |
| 560 | OUTDIG(d+1) |
| 561 | else |
| 562 | if (!tc2) |
| 563 | OUTDIG(d) |
| 564 | else { |
| 565 | big_shift_left(&R, 1, &MM); |
| 566 | if (big_comp(&MM, &S) == -1) |
| 567 | OUTDIG(d) |
| 568 | else |
| 569 | OUTDIG(d+1) |
| 570 | } |
| 571 | } |
| 572 | |
| 573 | void |
| 574 | _PyFloat_DigitsInit() |
| 575 | { |
| 576 | int n, i, l; |
| 577 | Bignum *b; |
| 578 | Bigit *xp, *zp, k; |
| 579 | |
| 580 | five[0].l = l = 0; |
| 581 | five[0].d[0] = 5; |
| 582 | for (n = MAX_FIVE-1, b = &five[0]; n > 0; n--) { |
| 583 | xp = &b->d[0]; |
| 584 | b++; |
| 585 | zp = &b->d[0]; |
| 586 | for (i = l, k = 0; i >= 0; i--) |
| 587 | MUL(*xp++, 5, *zp++, k); |
| 588 | if (k != 0) |
| 589 | *zp = k, l++; |
| 590 | b->l = l; |
| 591 | } |
| 592 | |
| 593 | /* |
| 594 | for (n = 1, b = &five[0]; n <= MAX_FIVE; n++) { |
| 595 | big_shift_left(b++, n, &R); |
| 596 | print_big(&R); |
| 597 | putchar('\n'); |
| 598 | } |
| 599 | fflush(0); |
| 600 | */ |
| 601 | } |