Exemple #1
0
int FN_PROTOTYPE(finitef)(float x)
{


    unsigned int ux;
    GET_BITS_SP32(x, ux);
    return (int)(((ux & ~SIGNBIT_SP32) - PINFBITPATT_SP32) >> 31);

}
Exemple #2
0
float FN_PROTOTYPE(expf)(float x)
{
  static const float
       max_exp_arg =  8.8722839355E+01F, /* 0x42B17218 */
       min_exp_arg = -1.0327893066E+02F, /* 0xC2CE8ED0 */
 thirtytwo_by_log2 =  4.6166240692E+01F, /* 0x4238AA3B */
   log2_by_32_lead =  2.1659851074E-02F, /* 0x3CB17000 */
   log2_by_32_tail =  9.9831822808E-07F; /* 0x3585FDF4 */

  float z1, z2, z;
  int m;
  unsigned int ux, ax;

  /*
    Computation of exp(x).

    We compute the values m, z1, and z2 such that
    exp(x) = 2**m * (z1 + z2),  where
    exp(x) is the natural exponential of x.

    Computations needed in order to obtain m, z1, and z2
    involve three steps.

    First, we reduce the argument x to the form
    x = n * log2/32 + remainder,
    where n has the value of an integer and |remainder| <= log2/64.
    The value of n = x * 32/log2 rounded to the nearest integer and
    the remainder = x - n*log2/32.

    Second, we approximate exp(r1 + r2) - 1 where r1 is the leading
    part of the remainder and r2 is the trailing part of the remainder.

    Third, we reconstruct the exponential of x so that
    exp(x) = 2**m * (z1 + z2).
  */

  GET_BITS_SP32(x, ux);
  ax = ux & (~SIGNBIT_SP32);

  if (ax >= 0x42B17218) /* abs(x) >= 88.7... */
    {
      if(ax >= 0x7f800000)
        {
          /* x is either NaN or infinity */
          if (ux & MANTBITS_SP32)
            /* x is NaN */
            return x + x; /* Raise invalid if it is a signalling NaN */
          else if (ux & SIGNBIT_SP32)
            /* x is negative infinity; return 0.0 with no flags */
            return 0.0;
          else
            /* x is positive infinity */
            return x;
        }
      if (x > max_exp_arg)
        /* Return +infinity with overflow flag */
        return retval_errno_erange_overflow(x);
      else if (x < min_exp_arg)
        /* x is negative. Return +zero with underflow and inexact flags */
        return retval_errno_erange_underflow(x);
    }

  /* Handle small arguments separately */
  if (ax < 0x3c800000)   /* abs(x) < 1/64 */
    {
      if (ax < 0x32800000)   /* abs(x) < 2^(-26) */
        return 1.0F + x; /* Raises inexact if x is non-zero */
      else
        z = (((((((
                   1.0F/5040)*x+
                  1.0F/720)*x+
                 1.0F/120)*x+
                1.0F/24)*x+
               1.0F/6)*x+
              1.0F/2)*x+
             1.0F)*x + 1.0F;
    }
  else
    {
      /* Find m and z such that exp(x) = 2**m * (z1 + z2) */

      splitexpf(x, 1.0F, thirtytwo_by_log2, log2_by_32_lead,
                log2_by_32_tail, &m, &z1, &z2);

      /* Scale (z1 + z2) by 2.0**m */

      if (m >= EMIN_SP32 && m <= EMAX_SP32)
        z = scaleFloat_1((float)(z1+z2),m);
      else
        z = scaleFloat_2((float)(z1+z2),m);
    }
  return z;
}
Exemple #3
0
float FN_PROTOTYPE(exp2f)(float x)
{
  static const float
    max_exp2_arg = 128.0F,  /* 0x43000000 */
    min_exp2_arg = -149.0F, /* 0xc3150000 */
    log2 = 6.931471824645996e-01F, /* 0x3f317218 */
    one_by_32_lead = 0.03125F;

  float y, z1, z2, z;
  int m;
  unsigned int ux, ax;

  /*
    Computation of exp2f(x).

    We compute the values m, z1, and z2 such that
    exp2f(x) = 2**m * (z1 + z2),  where exp2f(x) is 2**x.

    Computations needed in order to obtain m, z1, and z2
    involve three steps.

    First, we reduce the argument x to the form
    x = n/32 + remainder,
    where n has the value of an integer and |remainder| <= 1/64.
    The value of n = x * 32 rounded to the nearest integer and
    the remainder = x - n/32.

    Second, we approximate exp2f(r1 + r2) - 1 where r1 is the leading
    part of the remainder and r2 is the trailing part of the remainder.

    Third, we reconstruct exp2f(x) so that
    exp2f(x) = 2**m * (z1 + z2).
  */

  GET_BITS_SP32(x, ux);
  ax = ux & (~SIGNBIT_SP32);

  if (ax >= 0x43000000) /* abs(x) >= 128.0 */
    {
      if(ax >= 0x7f800000)
        {
          /* x is either NaN or infinity */
          if (ux & MANTBITS_SP32)
            /* x is NaN */
            return x + x; /* Raise invalid if it is a signalling NaN */
          else if (ux & SIGNBIT_SP32)
            /* x is negative infinity; return 0.0 with no flags. */
            return 0.0F;
          else
            /* x is positive infinity */
            return x;
        }
      if (x > max_exp2_arg)
        /* Return +infinity with overflow flag */
        return retval_errno_erange_overflow(x);
      else if (x < min_exp2_arg)
        /* x is negative. Return +zero with underflow and inexact flags */
        return retval_errno_erange_underflow(x);
    }

  /* Handle small arguments separately */
  if (ax < 0x3cb8aa3b)   /* abs(x) < 1/(64*log2) */
    {
      if (ax < 0x32800000)   /* abs(x) < 2^(-26) */
        return 1.0F + x; /* Raises inexact if x is non-zero */
      else
        {
	  y = log2*x;
      z = ((((((((
		    1.0F/40320)*y+
		   1.0F/5040)*y+
		  1.0F/720)*y+
		 1.0F/120)*y+
		1.0F/24)*y+
	       1.0F/6)*y+
	      1.0F/2)*y+
               1.0F)*y + 1.0F;
        }
    }
  else
    {
      /* Find m, z1 and z2 such that exp2f(x) = 2**m * (z1 + z2) */

      splitexpf(x, log2, 32.0F, one_by_32_lead, 0.0F, &m, &z1, &z2);

      /* Scale (z1 + z2) by 2.0**m */

      if (m >= EMIN_SP32 && m <= EMAX_SP32)
        z = scaleFloat_1((float)(z1+z2),m);
      else
        z = scaleFloat_2((float)(z1+z2),m);
    }
  return z;
}
Exemple #4
0
float FN_PROTOTYPE(exp10f)(float x)
{
  static const float
         max_exp10_arg = 3.8531841278E+01F, /* 0x421A209B */
         min_exp10_arg =-4.4853469848E+01F, /* 0xC23369F4 */
                 log10 = 2.3025850929E+00F, /* 0x40135D8E */
 thirtytwo_by_log10of2 = 1.0630169677E+02F, /* 0x42D49A78 */
   log10of2_by_32_lead = 9.4070434570E-03F, /* 0x3C1A2000 */
   log10of2_by_32_tail = 1.4390730030E-07F; /* 0x341A84F0 */

  float y, z1, z2, z;
  int m;
  unsigned int ux, ax;

  /*
    Computation of exp10f (x).

    We compute the values m, z1, and z2 such that
    exp10f(x) = 2**m * (z1 + z2),  where exp10f(x) is 10**x.

    Computations needed in order to obtain m, z1, and z2
    involve three steps.

    First, we reduce the argument x to the form
    x = n * log10of2/32 + remainder,
    where n has the value of an integer and |remainder| <= log10of2/64.
    The value of n = x * 32/log10of2 rounded to the nearest integer and
    the remainder = x - n*log10of2/32.

    Second, we approximate exp10f(r1 + r2) - 1 where r1 is the leading
    part of the remainder and r2 is the trailing part of the remainder.

    Third, we reconstruct exp10f(x) so that
    exp10f(x) = 2**m * (z1 + z2).
  */

  GET_BITS_SP32(x, ux);
  ax = ux & (~SIGNBIT_SP32);

  if (ax >= 0x421A209B) /* abs(x) >= 38.5... */
    {
      if(ax >= 0x7f800000)
        {
          /* x is either NaN or infinity */
          if (ux & MANTBITS_SP32)
            /* x is NaN */
            return x + x; /* Raise invalid if it is a signalling NaN */
          else if (ux & SIGNBIT_SP32)
            /* x is negative infinity; return 0.0 with no flags. */
            return 0.0F;
          else
            /* x is positive infinity */
            return x;
        }
      if (x > max_exp10_arg)
        /* Return +infinity with overflow flag */
        return retval_errno_erange_overflow(x);
      else if (x < min_exp10_arg)
        /* x is negative. Return +zero with underflow and inexact flags */
        return retval_errno_erange_underflow(x);
    }

  /* Handle small arguments separately */
  if (ax < 0x3bde5bd9)   /* abs(x) < 1/(64*log10) */
    {
      if (ax < 0x32800000)   /* abs(x) < 2^(-26) */
        return 1.0F + x; /* Raises inexact if x is non-zero */
      else
        {
        y = log10*x;
      z = ((((((((
		    1.0F/40320)*x+
		   1.0F/5040)*y+
		  1.0F/720)*y+
		 1.0F/120)*y+
		1.0F/24)*y+
	       1.0F/6)*y+
	      1.0F/2)*y+
               1.0F)*y + 1.0F;
        }
    }
  else
    {
      /* Find m, z1 and z2 such that exp10f(x) = 2**m * (z1 + z2) */

      splitexpf(x, log10, thirtytwo_by_log10of2, log10of2_by_32_lead,
                log10of2_by_32_tail, &m, &z1, &z2);

      /* Scale (z1 + z2) by 2.0**m */

      if (m >= EMIN_SP32 && m <= EMAX_SP32)
        z = scaleFloat_1((float)(z1+z2),m);
      else
        z = scaleFloat_2((float)(z1+z2),m);
    }
  return z;
}
Exemple #5
0
float FN_PROTOTYPE(atanhf)(float x)
{

  double dx;
  unsigned int ux, ax;
  double r, t, poly;

  GET_BITS_SP32(x, ux);
  ax = ux & ~SIGNBIT_SP32;

  if ((ux & EXPBITS_SP32) == EXPBITS_SP32)
    {
      /* x is either NaN or infinity */
      if (ux & MANTBITS_SP32)
        {
          /* x is NaN */
#ifdef WINDOWS
          return handle_errorf(_FUNCNAME, ux|0x00400000, _DOMAIN,
                              0, EDOM, x, 0.0F);
#else
          return x + x; /* Raise invalid if it is a signalling NaN */
#endif
        }
      else
        {
          /* x is infinity; return a NaN */
#ifdef WINDOWS
          return handle_errorf(_FUNCNAME, INDEFBITPATT_SP32, _DOMAIN,
                               AMD_F_INVALID, EDOM, x, 0.0F);
#else
          return retval_errno_edom(x,nanf_with_flags(AMD_F_INVALID));
#endif
        }
    }
  else if (ax >= 0x3f800000)
    {
      if (ax > 0x3f800000)
        {
          /* abs(x) > 1.0; return NaN */
#ifdef WINDOWS
          return handle_errorf(_FUNCNAME, INDEFBITPATT_SP32, _DOMAIN,
                               AMD_F_INVALID, EDOM, x, 0.0F);
#else
          return retval_errno_edom(x,nanf_with_flags(AMD_F_INVALID));
#endif
        }
      else if (ux == 0x3f800000)
        {
          /* x = +1.0; return infinity with the same sign as x
             and set the divbyzero status flag */
#ifdef WINDOWS
          return handle_errorf(_FUNCNAME, PINFBITPATT_SP32, _DOMAIN,
                               AMD_F_INVALID, EDOM, x, 0.0F);
#else
          return retval_errno_edom(x,infinityf_with_flags(AMD_F_DIVBYZERO));
#endif
        }
      else
        {
          /* x = -1.0; return infinity with the same sign as x */
#ifdef WINDOWS
          return handle_errorf(_FUNCNAME, NINFBITPATT_SP32, _DOMAIN,
                               AMD_F_INVALID, EDOM, x, 0.0F);
#else
          return retval_errno_edom(x,-infinityf_with_flags(AMD_F_DIVBYZERO));
#endif
        }
    }

  if (ax < 0x39000000)
    {
      if (ax == 0x00000000)
        {
          /* x is +/-zero. Return the same zero. */
          return x;
        }
      else
        {
          /* Arguments smaller than 2^(-13) in magnitude are
             approximated by atanhf(x) = x, raising inexact flag. */
          return valf_with_flags(x, AMD_F_INEXACT);
        }
    }
  else
    {
      dx = x;
      if (ax < 0x3f000000)
        {
          /* Arguments up to 0.5 in magnitude are
             approximated by a [2,2] minimax polynomial */
          t = dx*dx;
          poly =
            (0.39453629046e0 +
           (-0.28120347286e0 +
             0.92834212715e-2 * t) * t) /
            (0.11836088638e1 + 
           (-0.15537744551e1 +
             0.45281890445e0 * t) * t);
          return (float)(dx + dx*t*poly);
        }
      else
        {
          /* abs(x) >= 0.5 */
          /* Note that
               atanhf(x) = 0.5 * ln((1+x)/(1-x))
             (see Abramowitz and Stegun 4.6.22).
             For greater accuracy we use the variant formula
             atanhf(x) = log(1 + 2x/(1-x)) = log1p(2x/(1-x)).
          */
          if (ux & SIGNBIT_SP32)
            {
              /* Argument x is negative */
              r = (-2.0 * dx) / (1.0 + dx);
              r = 0.5 * FN_PROTOTYPE(log1p)(r);
              return (float)-r;
            }
          else
            {
              r = (2.0 * dx) / (1.0 - dx);
              r = 0.5 * FN_PROTOTYPE(log1p)(r);
              return (float)r;
            }
        }
    }
}