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 + -
显示快捷键?