#include #include #include "mcc.h" #include "ieeefp.h" typedef struct decpwrtwo DECPWRTWO; /* * A power of two, in decimal. pwrtwo is the power of two represented. * mantissa[] is the decimal digits, with the least significant digit * in [0] and the most in [63]. pwrten is the corresponding power of * ten, where zero corresponds to the decimal point just after * mantissa[63], one to just after mantissa[62], and minus one to * just before manitssa[63]. */ struct decpwrtwo { int pwrtwo; unsigned char mantissa[64]; int pwrten; } ; /* * There are many sets of powers that will work, here. The richer the * set the less arithmetic is needed; the code will _work_ even with * just -1 and 1, though it will be inefficient. */ static const DECPWRTWO powers_two[] = { { -2187, {5,7,3,6,2,1,1,3,8,7,3,1,2,6,2,7,3,2,4,0,0,7,8,4,5,0,3,6,0,2,8,8,6,5,2,3,5,4,1,8,8,1,1,8,1,7,6,1,7,5,6,9,2,0,1,2,8,8,6,1,0,4,4,4}, -659 }, { -729, {4,5,9,5,2,4,4,7,5,1,3,1,2,7,8,4,1,8,9,9,8,9,9,4,7,6,8,2,6,1,9,2,8,5,9,1,9,1,4,8,8,9,5,3,7,1,1,8,1,6,5,3,0,2,4,8,9,8,5,0,1,4,5,3}, -220 }, { -243, {3,8,8,7,1,4,1,1,6,0,1,7,1,0,2,6,4,5,8,9,4,7,2,2,8,5,6,8,2,3,7,8,0,6,0,0,6,4,4,9,9,4,6,1,1,7,3,0,9,6,3,3,3,3,0,8,2,9,4,7,4,7,0,7}, -74 }, { -81, {0,0,0,0,0,0,0,5,2,1,3,5,4,9,3,4,0,5,4,5,5,0,6,0,9,2,8,7,6,2,4,1,8,9,4,3,0,6,4,3,4,0,7,5,3,4,7,3,8,3,1,5,6,7,2,6,0,3,0,9,5,3,1,4}, -25 }, { -27, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,2,1,8,2,8,3,2,9,6,9,5,0,8,5,0,5,4,7}, -9 }, { -9, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,2,1,3,5,9,1}, -3 }, { -3, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,2,1}, -1 }, { -1, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5}, -1 }, { 0, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}, 0 }, { 1, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2}, 0 }, { 3, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8}, 0 }, { 9, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,5}, 2 }, { 27, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,2,7,7,1,2,4,3,1}, 8 }, { 81, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,5,3,2,1,4,9,4,3,8,5,2,9,2,2,9,3,6,1,5,8,7,1,4,2}, 24 }, { 243, {1,6,9,4,8,2,7,9,4,6,6,1,5,9,4,0,0,5,7,1,1,7,8,9,1,6,6,2,1,8,4,3,3,4,9,5,0,0,0,8,3,6,6,6,6,3,6,4,7,0,7,2,2,8,1,5,6,7,7,4,3,1,4,1}, 73 }, { 729, {1,3,9,1,0,4,3,8,6,4,2,5,7,7,5,1,5,8,1,1,9,3,5,3,1,5,3,3,6,8,7,2,6,4,0,2,2,4,8,8,0,1,9,4,9,6,9,4,7,1,2,8,0,7,8,5,9,3,1,0,4,2,8,2}, 219 }, { 2187, {6,7,5,9,3,0,8,4,3,8,3,6,0,3,6,8,1,5,8,9,3,1,8,5,2,9,7,4,2,4,7,4,6,4,5,3,6,8,9,2,1,7,1,0,6,1,7,0,1,8,9,3,7,6,8,1,6,6,6,1,2,5,2,2}, 658 } }; /* * A set where the pwrtwo is powers of two instead of pwoers of three. * Run this through atob | bunzip2. xbtoa Begin 6<\%_0gSqh;d")=ncSpm@G$)Q&3pGLl2V/f"$ZD@,mc7bC7`hJ.\IXdAAlPE0P[539WF:"JX V8sN(/@*6Cs<5K1lUO5Oe$Q;.i)^OSG8Zmlk`qikT2Nlo9te)BcNU8E=.-:OY'P*3j44]V4F=,=*7K[O"dV?aeM op4NColC0U#36-l=o(c0Nb)&?Ie]`#@+Hc0Gt@jLG`>8=f&S8%1HhTmgmQuanPee8*>>)'oK SZ:+6gI&QkR(mTRl>,Mea9JRTdShhLuO9SJ>3-XH&Q:eT(GQqj5 VJ'0p=09RsH"/,%-C#RP/'8[0>F4VC$P[1F(/VH/[m3lp<^S//1RO%,<7N5e8+/]69R`aiff 4JFe=RWj-I[mITYM1*g1GPs/Adp"QZ4ieCnrWj;oMl4cNrAWW,o+SN$]Oi,@,i#_"clos.#R T>#o8lh/\KF._qJ.e)4-l.@lD"rH#MhisO9Zm4UbhD@jLJCB*ld+*4n$-DW#:Yb#1=G^g?%i_.ascT 6\;ck\boaT']DAE_u%Ld xbtoa End N 592 250 E 30 S 123ca R c3074ead */ static const DECPWRTWO two_m3 = { -3, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,2,1}, -1 }; static const DECPWRTWO two_m2 = { -2, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,2}, -1 }; static const DECPWRTWO two_m1 = { -1, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5}, -1 }; static int shift_in(unsigned char *bits, int bytes, unsigned int a, int shf) { int i; for (i=0;i>= 8; } return(a); } /* * Ideally, I would like to round-to-even in exactly-halfway cases. * But doing that demands keeping the entire significand around. * Perhaps someday. */ static void floating_round(unsigned char *mant, int bytes, int rpt, int *exp) { int x; int a; x = bytes - 1 - (rpt >> 3); if (x > 0) bzero(&mant[0],x*sizeof(*mant)); mant[x] &= 0xff << (7 - (rpt & 7)); a = 0x80 >> (rpt & 7); if (mant[x] & a) { while (a && (x < bytes)) { a += mant[x]; mant[x] = a & 0xff; a >>= 8; x ++; } if (a) { if (a != 1) panic(); a = 0x100; for (x=bytes-1;x>=0;x--) { a |= mant[x]; mant[x] = a >> 1; a = (a & 1) << 8; } exp[0] ++; } } } static void shift_mant_right(unsigned char *mant, int nbytes, int bits) { unsigned char *f; unsigned char *t; int b; int n; int i; unsigned int a; t = mant; f = t + (bits >> 3); b = bits & 7; n = nbytes - (bits >> 3) - 1; a = *f++ >> b; for (i=n;i>0;i--) { a |= *f++ << (8-b); *t++ = a & 0xff; a >>= 8; } *t++ = a; for (i=t-mant;i",F)J'u?2" F>"!79,d%1N:>7R1X;7%Vpn;^"&]UXWs6o`fu?BqPu5#+5IR&;dBMeNHBnKKW"]5QCdt1hZt 7l81KAdj?Do-;5bS"!O60]CdU8SenXYH3F3 q&4SL7-JD"%l@:'#c!C+6XH`$#)b3,>&;.2[m3s#aF\D9G.n5((:jYKZ'g+LAfnL2'EfT;h= q[49W%A72Z@V2Uhd0Mp0X*,cU,.S4$Q!rG`2fmk'*G/7Q^V:E,o`rM<2gaOSN=&-cmjh'op_CI2Z>R^p;W;-=h3ua[Lr>p$C;R]_^*J4L=ATE0r[L)B5P(,rH/88.NOtBhkjNY,$Ib.+*!FUd$)3W1TRd3)?_caJfLXd&937Y_Do=WXIrHHlfu1QG n>+%Z"C>:[SLuX)`l,^#d>U46$n."4kcW&A^*M@NU\,s]Q+U*#lq\Xi'ETM.'.7W3,#Bsdj3 EH-57m_6QAB2ZP$*J0\:j:'2MWO:1Xi[oSRhOJ?48GT<,IY.7g12`A'^Vf%Ei`#6*5'93YQZ -VmpbmBPYHY#[OR<^T,1Qc"s'9%)[lJP_boBh8fW!,DE.+D_Q.2BSrK)bn!?8_q0=(s3O!bm =2cAmq#0HZ-$Y(23i','$7>O=:=+QiVS9ZP^D&&-nm#!m'4@*,2VA;[p(1U*?G_GZ*Ta0/]+d`Q>:d>@/-X_LX"Q*rs+.&e,O6mH:cl>SOL'#5d\[OXC[@f4-h7pQPYU3:Ca(-;8mc=X4*Uf@bpBY$F1$BYWm=2 d;!X:q5P'GikacEdZi/!*F]]ohN^f1[3C,ud\K"RR_Z"9R._@5,&uG'/LDW7V9I8drOg3[gt -GgJ9E?t.uelpQK=5]+Z"MNriiN"I#FY#(^/8\n) 2`N@Xn,$k\;T\`U$5.9C/$bI#79h$`>X-UGR&iE8*r%=+%oXa1aBj-aLU/lL>*bHp.NZ\MKp -rnABr\!8hE1nFh2_Cs. xbtoa End N 1167 48f E e1 S 21233 R 3855a023 */ /* * Multiply n1, l1 digits long, by n2, l2 digits long, into p, l1+l2 * digits long. In each case, `digits' are integers in [0..9], and * the [0] digit is the least significant. */ static void decmult(const unsigned char *n1, int l1, const unsigned char *n2, int l2, unsigned char *p) { int lp; int i1; int i2; int ip; unsigned int a; unsigned char v; lp = l1 + l2; bzero(p,lp); for (i2=0;i2>1 corresponds to an exponent of zero, ie, to * a value of 1.mmmm...mmmm. eeee ~0 is used for infinities and NaNs; * eeee 0 is used for zero (mmmm==0) or denormals (mmmm!=0). * * float range: * 1.4013e-45 (min denormal) * 1.17549e-38 (min normal) * 3.40282e+38 (max) * double range: * 4.94066e-324 (min denormal) * 2.22507e-308 (min normal) * 1.79769e+308 (max) * * Constants are always nonnegative. What looks like a negative * constant is actually unary minus applied to a positive constant. * (This has implications for the type when the conceptual constant is * the most negative integer in a two's-complement system.) * * For hex constants, we just take the top bits of the mantissa, round, * and construct the number. We do need to compensate for the * mantissa being in hex but the exponent being a power of 2, not 16. * * For decimal constants, we multiply by suitable powers of two to get * the number into [1,2), maintaining the (decimal) exponent and, * alongside it, a power-of-two exponent. We do this with 64 decimal * digits of mantissa, which gives us, ahem, "substantial" leeway for * roundoff error to accumulate before it gets anywhere near * mattering. Once we have the number in [1,2), we drop the leading 1 * (which corresponds to the hidden bit) and repeatedly multiply by 2 * to extract successive bits, until we have 64 bits. * * Most of this code keeps numbers little-endian; given an array of * digits, the [0] element is the least significant. But the incoming * digit vector is the other way around (digits[0] is the most * significant), because that's the order we get them in from the text * form of the token. * * There is a subtle point: when creating a denormalized number, we * want to round the mantissa - but there is one special case where * doing that ripples all the way up and increments the mantissa to * the point that it's not denormalized any longer. We detect this * case by checking for the high byte of the mantissa being 0x80. If * rounding didn't ripple up, the highbit is still 0 from the shift; * if rounding rippled up but the biased exponent was less than 0, at * least two zero bits were shifted in, so it doesn't ripple that far * up. Either way, if it's not 0x80 the right thing is no action. */ int float_cvt_ieee(TOKEN *t, int base, const unsigned char *digits, int ndigits, int dotloc, int exp, const char **whynot) { unsigned char mant[8]; // 64 bits is always enough for IEEE unsigned char dbufa[128]; unsigned char dbufb[128]; unsigned char *dmant; unsigned char *dmantbuf; unsigned char *dprod; unsigned char *dtmp; #define SWAP() do { dtmp = dprod; dprod = dmantbuf; dmantbuf = dtmp; } while (0) int i; int j; int p2; do <"zero"> { do <"toobig"> { if (ndigits < 1) break <"zero">; if (digits[0] == 0) panic(); switch (base) { default: panic(); break; case 10: // exp is a power of 10 exp += dotloc - 1; // value is now m.mmmmm x 10^exp if (exp < ((t->u.cst.type == CST_FLOAT)?-45:-324)) { // warn about underflowing to zero? break <"zero">; } if (exp > ((t->u.cst.type == CST_FLOAT)?38:307)) break <"toobig">; p2 = 0; dmantbuf = &dbufa[0]; dmant = dmantbuf; dprod = &dbufb[0]; if (ndigits >= 64) { for (i=64-1;i>=0;i--) dmant[64-1-i] = digits[i]; } else { bzero(&dmant[0],64-ndigits); for (i=ndigits-1;i>=0;i--) dmant[64-1-i] = digits[i]; } while (exp) { j = 0; for (i=(sizeof(powers_two)/sizeof(powers_two[0]))-1;i>0;i--) if (abs(exp+powers_two[i].pwrten) < abs(exp+powers_two[j].pwrten)) j = i; decmult(dmant,64,&powers_two[j].mantissa[0],64,dprod); exp += powers_two[j].pwrten; p2 -= powers_two[j].pwrtwo; if (dprod[127]) { dmant = dprod + 64; exp ++; } else { dmant = dprod + 63; } SWAP(); } switch (dmant[63]) { case 8: case 9: decmult(dmant,64,"\5\2\1",3,dprod); j = 3; if (0) { case 7: case 6: case 5: case 4: decmult(dmant,64,"\5\2",2,dprod); j = 2; } if (0) { case 3: case 2: decmult(dmant,64,"\5",1,dprod); j = 1; } break; case 1: bcopy(dmant,dprod,64); j = 0; break; case 0: panic(); break; } dmant = dprod + j; SWAP(); if (dmant[63] != 1) panic(); p2 += j; bzero(&mant[0],8); for (i=64-1;;i--) { if (dmant[63]) mant[i>>3] |= 1U << (i & 7); if (i < 1) break; dmant[63] = 0; decmult(dmant,64,"\2",1,dprod); dmant = dprod; SWAP(); } exp = p2; if (0) { case 16: // exp is a power of 2 exp += dotloc * 4; bzero(&mant[0],8); for (i=0;i<16;i++) { if (shift_in(&mant[0],8,(i 1.mmmm } switch (t->u.cst.type) { default: panic(); break; case CST_FLOAT: floating_round(&mant[0],8,24,&exp); exp += 127; if (exp > 254) break <"toobig">; if (exp < 1) { if (1-exp > 24) { // warn about underflowing to zero? break <"zero">; } shift_mant_right(&mant[0],8,1-exp); floating_round(&mant[0],8,24,&exp); exp = (mant[7] == 0x80) ? 1 : 0; } t->u.cst.val[0] = mant[5]; t->u.cst.val[1] = mant[6]; t->u.cst.val[2] = (mant[7] & 0x7f) | ((exp & 1) << 7); t->u.cst.val[3] = exp >> 1; return(1); break; case CST_DOUBLE: case CST_LDOUBLE: floating_round(&mant[0],8,53,&exp); exp += 1023; if (exp > 2046) break <"toobig">; if (exp < 1) { if (1-exp > 53) { // warn about underflowing to zero? break <"zero">; } shift_mant_right(&mant[0],8,1-exp); floating_round(&mant[0],8,53,&exp); exp = (mant[7] == 0x80) ? 1 : 0; } t->u.cst.val[0] = (mant[1] >> 3) | ((mant[2] & 7) << 5); t->u.cst.val[1] = (mant[2] >> 3) | ((mant[3] & 7) << 5); t->u.cst.val[2] = (mant[3] >> 3) | ((mant[4] & 7) << 5); t->u.cst.val[3] = (mant[4] >> 3) | ((mant[5] & 7) << 5); t->u.cst.val[4] = (mant[5] >> 3) | ((mant[6] & 7) << 5); t->u.cst.val[5] = (mant[6] >> 3) | ((mant[7] & 7) << 5); t->u.cst.val[6] = ((mant[7] >> 3) & 0x0f) | ((exp & 15) << 4); t->u.cst.val[7] = exp >> 4; return(1); break; } break; } } while (0); *whynot = (t->u.cst.type == CST_FLOAT) ? "magnitude too large for float" : "magnitude too large for double"; return(0); } while (0); bzero(&t->u.cst.val[0],sizeof(t->u.cst.val)); return(1); } void float_dump_ieee(FILE *f, CSTTYPE t, const unsigned char *v) { switch (t) { default: panic(); break; case CST_FLOAT: fprintf(f,"FLOAT %02x %02x %02x %02x\n",v[0],v[1],v[2],v[3]); break; case CST_DOUBLE: fprintf(f,"DOUBLE"); if (0) { case CST_LDOUBLE: fprintf(f,"LDOUBLE"); } fprintf(f," %02x %02x %02x %02x %02x %02x %02x %02x\n", v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]); break; } }