real.c
来自「GCC编译器源代码」· C语言 代码 · 共 2,875 行 · 第 1/5 页
C
2,875 行
++p; /* move the significand */ for (j = 0; j < NE - 1; j++) *q-- = *p++;}/* Clear out exploded e-type number XI. */static void ecleaz (xi) register unsigned EMUSHORT *xi;{ register int i; for (i = 0; i < NI; i++) *xi++ = 0;}/* Clear out exploded e-type XI, but don't touch the sign. */static void ecleazs (xi) register unsigned EMUSHORT *xi;{ register int i; ++xi; for (i = 0; i < NI - 1; i++) *xi++ = 0;}/* Move exploded e-type number from A to B. */static void emovz (a, b) register unsigned EMUSHORT *a, *b;{ register int i; for (i = 0; i < NI - 1; i++) *b++ = *a++; /* clear low guard word */ *b = 0;}/* Generate exploded e-type NaN. The explicit pattern for this is maximum exponent and top two significant bits set. */static voideinan (x) unsigned EMUSHORT x[];{ ecleaz (x); x[E] = 0x7fff; x[M + 1] = 0xc000;}/* Return nonzero if exploded e-type X is a NaN. */static int eiisnan (x) unsigned EMUSHORT x[];{ int i; if ((x[E] & 0x7fff) == 0x7fff) { for (i = M + 1; i < NI; i++) { if (x[i] != 0) return (1); } } return (0);}/* Return nonzero if sign of exploded e-type X is nonzero. */static int eiisneg (x) unsigned EMUSHORT x[];{ return x[0] != 0;}/* Fill exploded e-type X with infinity pattern. This has maximum exponent and significand all zeros. */static voideiinfin (x) unsigned EMUSHORT x[];{ ecleaz (x); x[E] = 0x7fff;}/* Return nonzero if exploded e-type X is infinite. */static int eiisinf (x) unsigned EMUSHORT x[];{#ifdef NANS if (eiisnan (x)) return (0);#endif if ((x[E] & 0x7fff) == 0x7fff) return (1); return (0);}/* Compare significands of numbers in internal exploded e-type format. Guard words are included in the comparison. Returns +1 if a > b 0 if a == b -1 if a < b */static intecmpm (a, b) register unsigned EMUSHORT *a, *b;{ int i; a += M; /* skip up to significand area */ b += M; for (i = M; i < NI; i++) { if (*a++ != *b++) goto difrnt; } return (0); difrnt: if (*(--a) > *(--b)) return (1); else return (-1);}/* Shift significand of exploded e-type X down by 1 bit. */static void eshdn1 (x) register unsigned EMUSHORT *x;{ register unsigned EMUSHORT bits; int i; x += M; /* point to significand area */ bits = 0; for (i = M; i < NI; i++) { if (*x & 1) bits |= 1; *x >>= 1; if (bits & 2) *x |= 0x8000; bits <<= 1; ++x; }}/* Shift significand of exploded e-type X up by 1 bit. */static void eshup1 (x) register unsigned EMUSHORT *x;{ register unsigned EMUSHORT bits; int i; x += NI - 1; bits = 0; for (i = M; i < NI; i++) { if (*x & 0x8000) bits |= 1; *x <<= 1; if (bits & 2) *x |= 1; bits <<= 1; --x; }}/* Shift significand of exploded e-type X down by 8 bits. */static void eshdn8 (x) register unsigned EMUSHORT *x;{ register unsigned EMUSHORT newbyt, oldbyt; int i; x += M; oldbyt = 0; for (i = M; i < NI; i++) { newbyt = *x << 8; *x >>= 8; *x |= oldbyt; oldbyt = newbyt; ++x; }}/* Shift significand of exploded e-type X up by 8 bits. */static void eshup8 (x) register unsigned EMUSHORT *x;{ int i; register unsigned EMUSHORT newbyt, oldbyt; x += NI - 1; oldbyt = 0; for (i = M; i < NI; i++) { newbyt = *x >> 8; *x <<= 8; *x |= oldbyt; oldbyt = newbyt; --x; }}/* Shift significand of exploded e-type X up by 16 bits. */static void eshup6 (x) register unsigned EMUSHORT *x;{ int i; register unsigned EMUSHORT *p; p = x + M; x += M + 1; for (i = M; i < NI - 1; i++) *p++ = *x++; *p = 0;}/* Shift significand of exploded e-type X down by 16 bits. */static void eshdn6 (x) register unsigned EMUSHORT *x;{ int i; register unsigned EMUSHORT *p; x += NI - 1; p = x + 1; for (i = M; i < NI - 1; i++) *(--p) = *(--x); *(--p) = 0;}/* Add significands of exploded e-type X and Y. X + Y replaces Y. */static void eaddm (x, y) unsigned EMUSHORT *x, *y;{ register unsigned EMULONG a; int i; unsigned int carry; x += NI - 1; y += NI - 1; carry = 0; for (i = M; i < NI; i++) { a = (unsigned EMULONG) (*x) + (unsigned EMULONG) (*y) + carry; if (a & 0x10000) carry = 1; else carry = 0; *y = (unsigned EMUSHORT) a; --x; --y; }}/* Subtract significands of exploded e-type X and Y. Y - X replaces Y. */static void esubm (x, y) unsigned EMUSHORT *x, *y;{ unsigned EMULONG a; int i; unsigned int carry; x += NI - 1; y += NI - 1; carry = 0; for (i = M; i < NI; i++) { a = (unsigned EMULONG) (*y) - (unsigned EMULONG) (*x) - carry; if (a & 0x10000) carry = 1; else carry = 0; *y = (unsigned EMUSHORT) a; --x; --y; }}static unsigned EMUSHORT equot[NI];#if 0/* Radix 2 shift-and-add versions of multiply and divide *//* Divide significands */int edivm (den, num) unsigned EMUSHORT den[], num[];{ int i; register unsigned EMUSHORT *p, *q; unsigned EMUSHORT j; p = &equot[0]; *p++ = num[0]; *p++ = num[1]; for (i = M; i < NI; i++) { *p++ = 0; } /* Use faster compare and subtraction if denominator has only 15 bits of significance. */ p = &den[M + 2]; if (*p++ == 0) { for (i = M + 3; i < NI; i++) { if (*p++ != 0) goto fulldiv; } if ((den[M + 1] & 1) != 0) goto fulldiv; eshdn1 (num); eshdn1 (den); p = &den[M + 1]; q = &num[M + 1]; for (i = 0; i < NBITS + 2; i++) { if (*p <= *q) { *q -= *p; j = 1; } else { j = 0; } eshup1 (equot); equot[NI - 2] |= j; eshup1 (num); } goto divdon; } /* The number of quotient bits to calculate is NBITS + 1 scaling guard bit + 1 roundoff bit. */ fulldiv: p = &equot[NI - 2]; for (i = 0; i < NBITS + 2; i++) { if (ecmpm (den, num) <= 0) { esubm (den, num); j = 1; /* quotient bit = 1 */ } else j = 0; eshup1 (equot); *p |= j; eshup1 (num); } divdon: eshdn1 (equot); eshdn1 (equot); /* test for nonzero remainder after roundoff bit */ p = &num[M]; j = 0; for (i = M; i < NI; i++) { j |= *p++; } if (j) j = 1; for (i = 0; i < NI; i++) num[i] = equot[i]; return ((int) j);}/* Multiply significands */int emulm (a, b) unsigned EMUSHORT a[], b[];{ unsigned EMUSHORT *p, *q; int i, j, k; equot[0] = b[0]; equot[1] = b[1]; for (i = M; i < NI; i++) equot[i] = 0; p = &a[NI - 2]; k = NBITS; while (*p == 0) /* significand is not supposed to be zero */ { eshdn6 (a); k -= 16; } if ((*p & 0xff) == 0) { eshdn8 (a); k -= 8; } q = &equot[NI - 1]; j = 0; for (i = 0; i < k; i++) { if (*p & 1) eaddm (b, equot); /* remember if there were any nonzero bits shifted out */ if (*q & 1) j |= 1; eshdn1 (a); eshdn1 (equot); } for (i = 0; i < NI; i++) b[i] = equot[i]; /* return flag for lost nonzero bits */ return (j);}#else/* Radix 65536 versions of multiply and divide. *//* Multiply significand of e-type number B by 16-bit quantity A, return e-type result to C. */static voidm16m (a, b, c) unsigned int a; unsigned EMUSHORT b[], c[];{ register unsigned EMUSHORT *pp; register unsigned EMULONG carry; unsigned EMUSHORT *ps; unsigned EMUSHORT p[NI]; unsigned EMULONG aa, m; int i; aa = a; pp = &p[NI-2]; *pp++ = 0; *pp = 0; ps = &b[NI-1]; for (i=M+1; i<NI; i++) { if (*ps == 0) { --ps; --pp; *(pp-1) = 0; } else { m = (unsigned EMULONG) aa * *ps--; carry = (m & 0xffff) + *pp; *pp-- = (unsigned EMUSHORT)carry; carry = (carry >> 16) + (m >> 16) + *pp; *pp = (unsigned EMUSHORT)carry; *(pp-1) = carry >> 16; } } for (i=M; i<NI; i++) c[i] = p[i];}/* Divide significands of exploded e-types NUM / DEN. Neither the numerator NUM nor the denominator DEN is permitted to have its high guard word nonzero. */static intedivm (den, num) unsigned EMUSHORT den[], num[];{ int i; register unsigned EMUSHORT *p; unsigned EMULONG tnum; unsigned EMUSHORT j, tdenm, tquot; unsigned EMUSHORT tprod[NI+1]; p = &equot[0]; *p++ = num[0]; *p++ = num[1]; for (i=M; i<NI; i++) { *p++ = 0; } eshdn1 (num); tdenm = den[M+1]; for (i=M; i<NI; i++) { /* Find trial quotient digit (the radix is 65536). */ tnum = (((unsigned EMULONG) num[M]) << 16) + num[M+1]; /* Do not execute the divide instruction if it will overflow. */ if ((tdenm * 0xffffL) < tnum) tquot = 0xffff; else tquot = tnum / tdenm; /* Multiply denominator by trial quotient digit. */ m16m ((unsigned int)tquot, den, tprod); /* The quotient digit may have been overestimated. */ if (ecmpm (tprod, num) > 0) { tquot -= 1; esubm (den, tprod); if (ecmpm (tprod, num) > 0) { tquot -= 1; esubm (den, tprod); } } esubm (tprod, num); equot[i] = tquot;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?