blob: 1f1c91cce78d8afea57d76606efcb6f7a43932a9 [file] [log] [blame]
Christian Heimes284d9272007-12-10 22:28:56 +00001/* 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
33struct 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 */
43struct 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
55typedef UNSIGNED64 Bigit;
56#define BIGSIZE 24
57#define MIN_E -1074
58#define MAX_FIVE 325
59#define B_P1 ((Bigit)1 << 52)
60
61typedef struct {
62 int l;
63 Bigit d[BIGSIZE];
64} Bignum;
65
66static Bignum R, S, MP, MM, five[MAX_FIVE];
67static Bignum S2, S3, S4, S5, S6, S7, S8, S9;
68static int ruf, k, s_n, use_mp, qr_shift, sl, slr;
69
70static void mul10(Bignum *x);
71static void big_short_mul(Bignum *x, Bigit y, Bignum *z);
72/*
73static void print_big(Bignum *x);
74*/
75static int estimate(int n);
76static void one_shift_left(int y, Bignum *z);
77static void short_shift_left(Bigit x, int y, Bignum *z);
78static void big_shift_left(Bignum *x, int y, Bignum *z);
79static int big_comp(Bignum *x, Bignum *y);
80static int sub_big(Bignum *x, Bignum *y, Bignum *z);
81static void add_big(Bignum *x, Bignum *y, Bignum *z);
82static int add_cmp(void);
83static 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
122static void
123mul10(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
135static void
136big_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/*
168static void
169print_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
184static int
185estimate(int n)
186{
187 if (n < 0)
188 return (int)(n*0.3010299956639812);
189 else
190 return 1+(int)(n*0.3010299956639811);
191}
192
193static void
194one_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
207static void
208short_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
229static void
230big_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
254static int
255big_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
276static int
277sub_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
305static void
306add_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
339static int
340add_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
357static int
358qr()
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
406int
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
522again:
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
573void
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}