Example #1
0
static float
sin_pif(float x)
{
	float y,z;
	int n,ix;

	GET_FLOAT_WORD(ix,x);
	ix &= 0x7fffffff;

	if(ix<0x3e800000) return __kernel_sinf(pi*x,zero,0);
	y = -x;		/* x is assume negative */

    /*
     * argument reduction, make sure inexact flag not raised if input
     * is an integer
     */
	z = __floorf(y);
	if(z!=y) {				/* inexact anyway */
	    y  *= (float)0.5;
	    y   = (float)2.0*(y - __floorf(y));	/* y = |x| mod 2.0 */
	    n   = (int) (y*(float)4.0);
	} else {
	    if(ix>=0x4b800000) {
		y = zero; n = 0;                 /* y must be even */
	    } else {
		if(ix<0x4b000000) z = y+two23;	/* exact */
		GET_FLOAT_WORD(n,z);
		n &= 1;
		y  = n;
		n<<= 2;
	    }
	}
	switch (n) {
	    case 0:   y =  __kernel_sinf(pi*y,zero,0); break;
	    case 1:
	    case 2:   y =  __kernel_cosf(pi*((float)0.5-y),zero); break;
	    case 3:
	    case 4:   y =  __kernel_sinf(pi*(one-y),zero,0); break;
	    case 5:
	    case 6:   y = -__kernel_cosf(pi*(y-(float)1.5),zero); break;
	    default:  y =  __kernel_sinf(pi*(y-(float)2.0),zero,0); break;
	    }
	return -y;
}
Example #2
0
int32_t
__fp_kernel_rem_pio2f (float *x, float *y, float e0, int32_t nx)
{
  int32_t jz, jx, jv, jp, jk, carry, n, iq[20], i, j, k, m, q0, ih, exp;
  float z, fw, f[20], fq[20], q[20];

  /* initialize jk */
  jp = jk = 9;

  /* determine jx,jv,q0, note that 3>q0 */
  jx = nx - 1;
  exp = __float_get_exp (e0) - 127;
  jv = (exp - 3) / 8;
  if (jv < 0)
    jv = 0;
  q0 = exp - 8 * (jv + 1);

  /* set up f[0] to f[jx+jk] where f[jx+jk] = two_over_pi[jv+jk] */
  j = jv - jx;
  m = jx + jk;
  for (i = 0; i <= m; i++, j++)
    f[i] = (j < 0) ? zero : two_over_pi[j];

  /* compute q[0],q[1],...q[jk] */
  for (i = 0; i <= jk; i++)
    {
      for (j = 0, fw = 0.0; j <= jx; j++)
	fw += x[j] * f[jx + i - j];
      q[i] = fw;
    }

  jz = jk;
recompute:
  /* distill q[] into iq[] reversingly */
  for (i = 0, j = jz, z = q[jz]; j > 0; i++, j--)
    {
      fw = __truncf (twon8 * z);
      iq[i] = (int32_t) (z - two8 * fw);
      z = q[j - 1] + fw;
    }

  /* compute n */
  z = __scalbnf (z, q0);	/* actual value of z */
  z -= 8.0 * __floorf (z * 0.125);	/* trim off integer >= 8 */
  n = (int32_t) z;
  z -= __truncf (z);
  ih = 0;
  if (q0 > 0)
    {				/* need iq[jz-1] to determine n */
      i = (iq[jz - 1] >> (8 - q0));
      n += i;
      iq[jz - 1] -= i << (8 - q0);
      ih = iq[jz - 1] >> (7 - q0);
    }
Example #3
0
float
LGFUNC (__lgammaf) (float x)
{
	float y = CALL_LGAMMA (float, __ieee754_lgammaf_r, x);
	if(__builtin_expect(!isfinite(y), 0)
	   && isfinite(x) && _LIB_VERSION != _IEEE_)
		return __kernel_standard_f(x, x,
					   __floorf(x)==x&&x<=0.0f
					   ? 115 /* lgamma pole */
					   : 114); /* lgamma overflow */

	return y;
}
Example #4
0
float
__lgammaf_r(float x, int *signgamp)
{
	float y = __ieee754_lgammaf_r(x,signgamp);
	if(__builtin_expect(!__finitef(y), 0)
	   && __finitef(x) && _LIB_VERSION != _IEEE_)
		return __kernel_standard_f(x, x,
					   __floorf(x)==x&&x<=0.0f
					   ? 115 /* lgamma pole */
					   : 114); /* lgamma overflow */

	return y;
}
Example #5
0
int __kernel_rem_pio2f(float *x, float *y, int e0, int nx, int prec, const int32_t *ipio2)
{
	int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih;
	float z,fw,f[20],fq[20],q[20];

    /* initialize jk*/
	jk = init_jk[prec];
	jp = jk;

    /* determine jx,jv,q0, note that 3>q0 */
	jx =  nx-1;
	jv = (e0-3)/8; if(jv<0) jv=0;
	q0 =  e0-8*(jv+1);

    /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
	j = jv-jx; m = jx+jk;
	for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (float) ipio2[j];

    /* compute q[0],q[1],...q[jk] */
	for (i=0;i<=jk;i++) {
	    for(j=0,fw=0.0;j<=jx;j++)
		fw += x[j]*f[jx+i-j];
	    q[i] = fw;
	}

	jz = jk;
recompute:
    /* distill q[] into iq[] reversingly */
	for(i=0,j=jz,z=q[jz];j>0;i++,j--) {
	    fw    =  (float)((int32_t)(twon8* z));
	    iq[i] =  (int32_t)(z-two8*fw);
	    z     =  q[j-1]+fw;
	}

    /* compute n */
	z  = __scalbnf(z,q0);		/* actual value of z */
	z -= (float)8.0*__floorf(z*(float)0.125);	/* trim off integer >= 8 */
	n  = (int32_t) z;
	z -= (float)n;
	ih = 0;
	if(q0>0) {	/* need iq[jz-1] to determine n */
	    i  = (iq[jz-1]>>(8-q0)); n += i;
	    iq[jz-1] -= i<<(8-q0);
	    ih = iq[jz-1]>>(7-q0);
	}
Example #6
0
int32_t
__ieee754_rem_pio2f (float x, float *y)
{
  float ax, z, n, r, w, t, e0;
  float tx[3];
  int32_t i, nx;

  ax = __builtin_fabsf (x);
  if (ax <= pio4)
    {
      y[0] = x;
      y[1] = 0;
      return 0;
    }
  if (ax < pio3_4)
    {
      if (x > 0)
	{
	  z = x - pio2_1;
	  if (!__float_and_test28 (ax, pio2_24b))
	    {
	      y[0] = z - pio2_1t;
	      y[1] = (z - y[0]) - pio2_1t;
	    }
	  else
	    {
	      z -= pio2_2;
	      y[0] = z - pio2_2t;
	      y[1] = (z - y[0]) - pio2_2t;
	    }
	  return 1;
	}
      else
	{
	  z = x + pio2_1;
	  if (!__float_and_test28 (ax, pio2_24b))
	    {
	      y[0] = z + pio2_1t;
	      y[1] = (z - y[0]) + pio2_1t;
	    }
	  else
	    {
	      z += pio2_2;
	      y[0] = z + pio2_2t;
	      y[1] = (z - y[0]) + pio2_2t;
	    }
	  return -1;
	}
    }
  if (ax <= pio2_2e7)
    {
      n = __floorf (ax * invpio2 + half);
      i = (int32_t) n;
      r = ax - n * pio2_1;
      w = n * pio2_1t;		/* 1st round good to 40 bit */
      if (i < 32 && !__float_and_test24 (ax, npio2_hw[i - 1]))
	{
	  y[0] = r - w;
	}
      else
	{
	  float i, j;
	  j = __float_and8 (ax);
	  y[0] = r - w;
	  i = __float_and8 (y[0]);
	  if (j / i > 256.0 || j / i < 3.9062500e-3)
	    {			/* 2nd iterations needed, good to 57 */
	      t = r;
	      w = n * pio2_2;
	      r = t - w;
	      w = n * pio2_2t - ((t - r) - w);
	      y[0] = r - w;
	      i = __float_and8 (y[0]);
	      if (j / i > 33554432 || j / i < 2.9802322e-8)
		{		/* 3rd iteration needed, 74 bits acc */
		  t = r;
		  w = n * pio2_3;
		  r = t - w;
		  w = n * pio2_3t - ((t - r) - w);
		  y[0] = r - w;
		}
	    }
	}
      y[1] = (r - y[0]) - w;
      if (x < 0)
	{
	  y[0] = -y[0];
	  y[1] = -y[1];
	  return -i;
	}
      else
	{
	  return i;
	}
    }

  /* all other (large) arguments */
  if (isnanf (x) || isinff (x))
    {
      y[0] = y[1] = x - x;
      return 0;
    }

  /* set z = scalbn(|x|,ilogb(x)-7) */
  e0 = __float_and8 (ax / 128.0);
  z = ax / e0;

  tx[0] = __floorf (z);
  z = (z - tx[0]) * two8;
  tx[1] = __floorf (z);
  z = (z - tx[1]) * two8;
  tx[2] = __floorf (z);

  nx = 3;
  while (tx[nx - 1] == zero)
    nx--;

  i = __fp_kernel_rem_pio2f (tx, y, e0, nx);
  if (x < 0)
    {
      y[0] = -y[0];
      y[1] = -y[1];
      return -i;
    }
  return i;
}
Example #7
0
float
__lgamma_negf (float x, int *signgamp)
{
  /* Determine the half-integer region X lies in, handle exact
     integers and determine the sign of the result.  */
  int i = __floorf (-2 * x);
  if ((i & 1) == 0 && i == -2 * x)
    return 1.0f / 0.0f;
  float xn = ((i & 1) == 0 ? -i / 2 : (-i - 1) / 2);
  i -= 4;
  *signgamp = ((i & 2) == 0 ? -1 : 1);

  SET_RESTORE_ROUNDF (FE_TONEAREST);

  /* Expand around the zero X0 = X0_HI + X0_LO.  */
  float x0_hi = lgamma_zeros[i][0], x0_lo = lgamma_zeros[i][1];
  float xdiff = x - x0_hi - x0_lo;

  /* For arguments in the range -3 to -2, use polynomial
     approximations to an adjusted version of the gamma function.  */
  if (i < 2)
    {
      int j = __floorf (-8 * x) - 16;
      float xm = (-33 - 2 * j) * 0.0625f;
      float x_adj = x - xm;
      size_t deg = poly_deg[j];
      size_t end = poly_end[j];
      float g = poly_coeff[end];
      for (size_t j = 1; j <= deg; j++)
	g = g * x_adj + poly_coeff[end - j];
      return __log1pf (g * xdiff / (x - xn));
    }

  /* The result we want is log (sinpi (X0) / sinpi (X))
     + log (gamma (1 - X0) / gamma (1 - X)).  */
  float x_idiff = fabsf (xn - x), x0_idiff = fabsf (xn - x0_hi - x0_lo);
  float log_sinpi_ratio;
  if (x0_idiff < x_idiff * 0.5f)
    /* Use log not log1p to avoid inaccuracy from log1p of arguments
       close to -1.  */
    log_sinpi_ratio = __ieee754_logf (lg_sinpi (x0_idiff)
				      / lg_sinpi (x_idiff));
  else
    {
      /* Use log1p not log to avoid inaccuracy from log of arguments
	 close to 1.  X0DIFF2 has positive sign if X0 is further from
	 XN than X is from XN, negative sign otherwise.  */
      float x0diff2 = ((i & 1) == 0 ? xdiff : -xdiff) * 0.5f;
      float sx0d2 = lg_sinpi (x0diff2);
      float cx0d2 = lg_cospi (x0diff2);
      log_sinpi_ratio = __log1pf (2 * sx0d2
				  * (-sx0d2 + cx0d2 * lg_cotpi (x_idiff)));
    }

  float log_gamma_ratio;
  float y0 = math_narrow_eval (1 - x0_hi);
  float y0_eps = -x0_hi + (1 - y0) - x0_lo;
  float y = math_narrow_eval (1 - x);
  float y_eps = -x + (1 - y);
  /* We now wish to compute LOG_GAMMA_RATIO
     = log (gamma (Y0 + Y0_EPS) / gamma (Y + Y_EPS)).  XDIFF
     accurately approximates the difference Y0 + Y0_EPS - Y -
     Y_EPS.  Use Stirling's approximation.  */
  float log_gamma_high
    = (xdiff * __log1pf ((y0 - e_hi - e_lo + y0_eps) / e_hi)
       + (y - 0.5f + y_eps) * __log1pf (xdiff / y));
  /* Compute the sum of (B_2k / 2k(2k-1))(Y0^-(2k-1) - Y^-(2k-1)).  */
  float y0r = 1 / y0, yr = 1 / y;
  float y0r2 = y0r * y0r, yr2 = yr * yr;
  float rdiff = -xdiff / (y * y0);
  float bterm[NCOEFF];
  float dlast = rdiff, elast = rdiff * yr * (yr + y0r);
  bterm[0] = dlast * lgamma_coeff[0];
  for (size_t j = 1; j < NCOEFF; j++)
    {
      float dnext = dlast * y0r2 + elast;
      float enext = elast * yr2;
      bterm[j] = dnext * lgamma_coeff[j];
      dlast = dnext;
      elast = enext;
    }
  float log_gamma_low = 0;
  for (size_t j = 0; j < NCOEFF; j++)
    log_gamma_low += bterm[NCOEFF - 1 - j];
  log_gamma_ratio = log_gamma_high + log_gamma_low;

  return log_sinpi_ratio + log_gamma_ratio;
}