real.c
来自「GCC编译器源代码」· C语言 代码 · 共 2,875 行 · 第 1/5 页
C
2,875 行
emul (d2, d1, v); break; case RDIV_EXPR:#ifndef REAL_INFINITY if (ecmp (d2, ezero) == 0) {#ifdef NANS enan (v, eisneg (d1) ^ eisneg (d2)); break;#else abort ();#endif }#endif ediv (d2, d1, v); /* d1/d2 */ break; case MIN_EXPR: /* min (d1,d2) */ if (ecmp (d1, d2) < 0) emov (d1, v); else emov (d2, v); break; case MAX_EXPR: /* max (d1,d2) */ if (ecmp (d1, d2) > 0) emov (d1, v); else emov (d2, v); break; default: emov (ezero, v); break; }PUT_REAL (v, value);}/* Truncate REAL_VALUE_TYPE toward zero to signed HOST_WIDE_INT. implements REAL_VALUE_RNDZINT (x) (etrunci (x)). */REAL_VALUE_TYPE etrunci (x) REAL_VALUE_TYPE x;{ unsigned EMUSHORT f[NE], g[NE]; REAL_VALUE_TYPE r; HOST_WIDE_INT l; GET_REAL (&x, g);#ifdef NANS if (eisnan (g)) return (x);#endif eifrac (g, &l, f); ltoe (&l, g); PUT_REAL (g, &r); return (r);}/* Truncate REAL_VALUE_TYPE toward zero to unsigned HOST_WIDE_INT; implements REAL_VALUE_UNSIGNED_RNDZINT (x) (etruncui (x)). */REAL_VALUE_TYPE etruncui (x) REAL_VALUE_TYPE x;{ unsigned EMUSHORT f[NE], g[NE]; REAL_VALUE_TYPE r; unsigned HOST_WIDE_INT l; GET_REAL (&x, g);#ifdef NANS if (eisnan (g)) return (x);#endif euifrac (g, &l, f); ultoe (&l, g); PUT_REAL (g, &r); return (r);}/* This is the REAL_VALUE_ATOF function. It converts a decimal string to binary, rounding off as indicated by the machine_mode argument. Then it promotes the rounded value to REAL_VALUE_TYPE. */REAL_VALUE_TYPE ereal_atof (s, t) char *s; enum machine_mode t;{ unsigned EMUSHORT tem[NE], e[NE]; REAL_VALUE_TYPE r; switch (t) { case HFmode: case SFmode: asctoe24 (s, tem); e24toe (tem, e); break; case DFmode: asctoe53 (s, tem); e53toe (tem, e); break; case XFmode: asctoe64 (s, tem); e64toe (tem, e); break; case TFmode: asctoe113 (s, tem); e113toe (tem, e); break; default: asctoe (s, e); } PUT_REAL (e, &r); return (r);}/* Expansion of REAL_NEGATE. */REAL_VALUE_TYPE ereal_negate (x) REAL_VALUE_TYPE x;{ unsigned EMUSHORT e[NE]; REAL_VALUE_TYPE r; GET_REAL (&x, e); eneg (e); PUT_REAL (e, &r); return (r);}/* Round real toward zero to HOST_WIDE_INT; implements REAL_VALUE_FIX (x). */HOST_WIDE_INTefixi (x) REAL_VALUE_TYPE x;{ unsigned EMUSHORT f[NE], g[NE]; HOST_WIDE_INT l; GET_REAL (&x, f);#ifdef NANS if (eisnan (f)) { warning ("conversion from NaN to int"); return (-1); }#endif eifrac (f, &l, g); return l;}/* Round real toward zero to unsigned HOST_WIDE_INT implements REAL_VALUE_UNSIGNED_FIX (x). Negative input returns zero. */unsigned HOST_WIDE_INTefixui (x) REAL_VALUE_TYPE x;{ unsigned EMUSHORT f[NE], g[NE]; unsigned HOST_WIDE_INT l; GET_REAL (&x, f);#ifdef NANS if (eisnan (f)) { warning ("conversion from NaN to unsigned int"); return (-1); }#endif euifrac (f, &l, g); return l;}/* REAL_VALUE_FROM_INT macro. */void ereal_from_int (d, i, j, mode) REAL_VALUE_TYPE *d; HOST_WIDE_INT i, j; enum machine_mode mode;{ unsigned EMUSHORT df[NE], dg[NE]; HOST_WIDE_INT low, high; int sign; if (GET_MODE_CLASS (mode) != MODE_FLOAT) abort (); sign = 0; low = i; if ((high = j) < 0) { sign = 1; /* complement and add 1 */ high = ~high; if (low) low = -low; else high += 1; } eldexp (eone, HOST_BITS_PER_WIDE_INT, df); ultoe ((unsigned HOST_WIDE_INT *) &high, dg); emul (dg, df, dg); ultoe ((unsigned HOST_WIDE_INT *) &low, df); eadd (df, dg, dg); if (sign) eneg (dg); /* A REAL_VALUE_TYPE may not be wide enough to hold the two HOST_WIDE_INTS. Avoid double-rounding errors later by rounding off now from the extra-wide internal format to the requested precision. */ switch (GET_MODE_BITSIZE (mode)) { case 32: etoe24 (dg, df); e24toe (df, dg); break; case 64: etoe53 (dg, df); e53toe (df, dg); break; case 96: etoe64 (dg, df); e64toe (df, dg); break; case 128: etoe113 (dg, df); e113toe (df, dg); break; default: abort (); } PUT_REAL (dg, d);}/* REAL_VALUE_FROM_UNSIGNED_INT macro. */void ereal_from_uint (d, i, j, mode) REAL_VALUE_TYPE *d; unsigned HOST_WIDE_INT i, j; enum machine_mode mode;{ unsigned EMUSHORT df[NE], dg[NE]; unsigned HOST_WIDE_INT low, high; if (GET_MODE_CLASS (mode) != MODE_FLOAT) abort (); low = i; high = j; eldexp (eone, HOST_BITS_PER_WIDE_INT, df); ultoe (&high, dg); emul (dg, df, dg); ultoe (&low, df); eadd (df, dg, dg); /* A REAL_VALUE_TYPE may not be wide enough to hold the two HOST_WIDE_INTS. Avoid double-rounding errors later by rounding off now from the extra-wide internal format to the requested precision. */ switch (GET_MODE_BITSIZE (mode)) { case 32: etoe24 (dg, df); e24toe (df, dg); break; case 64: etoe53 (dg, df); e53toe (df, dg); break; case 96: etoe64 (dg, df); e64toe (df, dg); break; case 128: etoe113 (dg, df); e113toe (df, dg); break; default: abort (); } PUT_REAL (dg, d);}/* REAL_VALUE_TO_INT macro. */void ereal_to_int (low, high, rr) HOST_WIDE_INT *low, *high; REAL_VALUE_TYPE rr;{ unsigned EMUSHORT d[NE], df[NE], dg[NE], dh[NE]; int s; GET_REAL (&rr, d);#ifdef NANS if (eisnan (d)) { warning ("conversion from NaN to int"); *low = -1; *high = -1; return; }#endif /* convert positive value */ s = 0; if (eisneg (d)) { eneg (d); s = 1; } eldexp (eone, HOST_BITS_PER_WIDE_INT, df); ediv (df, d, dg); /* dg = d / 2^32 is the high word */ euifrac (dg, (unsigned HOST_WIDE_INT *) high, dh); emul (df, dh, dg); /* fractional part is the low word */ euifrac (dg, (unsigned HOST_WIDE_INT *)low, dh); if (s) { /* complement and add 1 */ *high = ~(*high); if (*low) *low = -(*low); else *high += 1; }}/* REAL_VALUE_LDEXP macro. */REAL_VALUE_TYPEereal_ldexp (x, n) REAL_VALUE_TYPE x; int n;{ unsigned EMUSHORT e[NE], y[NE]; REAL_VALUE_TYPE r; GET_REAL (&x, e);#ifdef NANS if (eisnan (e)) return (x);#endif eldexp (e, n, y); PUT_REAL (y, &r); return (r);}/* These routines are conditionally compiled because functions of the same names may be defined in fold-const.c. */#ifdef REAL_ARITHMETIC/* Check for infinity in a REAL_VALUE_TYPE. */inttarget_isinf (x) REAL_VALUE_TYPE x;{ unsigned EMUSHORT e[NE];#ifdef INFINITY GET_REAL (&x, e); return (eisinf (e));#else return 0;#endif}/* Check whether a REAL_VALUE_TYPE item is a NaN. */inttarget_isnan (x) REAL_VALUE_TYPE x;{ unsigned EMUSHORT e[NE];#ifdef NANS GET_REAL (&x, e); return (eisnan (e));#else return (0);#endif}/* Check for a negative REAL_VALUE_TYPE number. This just checks the sign bit, so that -0 counts as negative. */inttarget_negative (x) REAL_VALUE_TYPE x;{ return ereal_isneg (x);}/* Expansion of REAL_VALUE_TRUNCATE. The result is in floating point, rounded to nearest or even. */REAL_VALUE_TYPEreal_value_truncate (mode, arg) enum machine_mode mode; REAL_VALUE_TYPE arg;{ unsigned EMUSHORT e[NE], t[NE]; REAL_VALUE_TYPE r; GET_REAL (&arg, e);#ifdef NANS if (eisnan (e)) return (arg);#endif eclear (t); switch (mode) { case TFmode: etoe113 (e, t); e113toe (t, t); break; case XFmode: etoe64 (e, t); e64toe (t, t); break; case DFmode: etoe53 (e, t); e53toe (t, t); break; case HFmode: case SFmode: etoe24 (e, t); e24toe (t, t); break; case SImode: r = etrunci (arg); return (r); /* If an unsupported type was requested, presume that the machine files know something useful to do with the unmodified value. */ default: return (arg); } PUT_REAL (t, &r); return (r);}/* Try to change R into its exact multiplicative inverse in machine mode MODE. Return nonzero function value if successful. */intexact_real_inverse (mode, r) enum machine_mode mode; REAL_VALUE_TYPE *r;{ unsigned EMUSHORT e[NE], einv[NE]; REAL_VALUE_TYPE rinv; int i; GET_REAL (r, e); /* Test for input in range. Don't transform IEEE special values. */ if (eisinf (e) || eisnan (e) || (ecmp (e, ezero) == 0)) return 0; /* Test for a power of 2: all significand bits zero except the MSB. We are assuming the target has binary (or hex) arithmetic. */ if (e[NE - 2] != 0x8000) return 0; for (i = 0; i < NE - 2; i++) { if (e[i] != 0) return 0; } /* Compute the inverse and truncate it to the required mode. */ ediv (e, eone, einv); PUT_REAL (einv, &rinv); rinv = real_value_truncate (mode, rinv);#ifdef CHECK_FLOAT_VALUE /* This check is not redundant. It may, for example, flush a supposedly IEEE denormal value to zero. */ i = 0; if (CHECK_FLOAT_VALUE (mode, rinv, i)) return 0;#endif GET_REAL (&rinv, einv); /* Check the bits again, because the truncation might have generated an arbitrary saturation value on overflow. */ if (einv[NE - 2] != 0x8000) return 0; for (i = 0; i < NE - 2; i++) { if (einv[i] != 0) return 0; } /* Fail if the computed inverse is out of range. */ if (eisinf (einv) || eisnan (einv) || (ecmp (einv, ezero) == 0)) return 0; /* Output the reciprocal and return success flag. */ PUT_REAL (einv, r); return 1;}#endif /* REAL_ARITHMETIC defined *//* Used for debugging--print the value of R in human-readable format on stderr. */voiddebug_real (r) REAL_VALUE_TYPE r;{ char dstr[30]; REAL_VALUE_TO_DECIMAL (r, "%.20g", dstr); fprintf (stderr, "%s", dstr);} /* The following routines convert REAL_VALUE_TYPE to the various floating point formats that are meaningful to supported computers. The results are returned in 32-bit pieces, each piece stored in a `long'. This is so they can be printed by statements like fprintf (file, "%lx, %lx", L[0], L[1]); that will work on both narrow- and wide-word host computers. *//* Convert R to a 128-bit long double precision value. The output array L contains four 32-bit pieces of the result, in the order they would appear in memory. */void etartdouble (r, l) REAL_VALUE_TYPE r; long l[];{ unsigned EMUSHORT e[NE]; GET_REAL (&r, e); etoe113 (e, e);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?