Blame sysdeps/ieee754/flt-32/e_rem_pio2f.c

Packit 6c4009
/* e_rem_pio2f.c -- float version of e_rem_pio2.c
Packit 6c4009
 * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * ====================================================
Packit 6c4009
 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
Packit 6c4009
 *
Packit 6c4009
 * Developed at SunPro, a Sun Microsystems, Inc. business.
Packit 6c4009
 * Permission to use, copy, modify, and distribute this
Packit 6c4009
 * software is freely granted, provided that this notice
Packit 6c4009
 * is preserved.
Packit 6c4009
 * ====================================================
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
#if defined(LIBM_SCCS) && !defined(lint)
Packit 6c4009
static char rcsid[] = "$NetBSD: e_rem_pio2f.c,v 1.5 1995/05/10 20:46:03 jtc Exp $";
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* __ieee754_rem_pio2f(x,y)
Packit 6c4009
 *
Packit 6c4009
 * return the remainder of x rem pi/2 in y[0]+y[1]
Packit 6c4009
 * use __kernel_rem_pio2f()
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
#include <math.h>
Packit 6c4009
#include <math_private.h>
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
Packit 6c4009
 */
Packit 6c4009
static const int32_t two_over_pi[] = {
Packit 6c4009
0xA2, 0xF9, 0x83, 0x6E, 0x4E, 0x44, 0x15, 0x29, 0xFC,
Packit 6c4009
0x27, 0x57, 0xD1, 0xF5, 0x34, 0xDD, 0xC0, 0xDB, 0x62,
Packit 6c4009
0x95, 0x99, 0x3C, 0x43, 0x90, 0x41, 0xFE, 0x51, 0x63,
Packit 6c4009
0xAB, 0xDE, 0xBB, 0xC5, 0x61, 0xB7, 0x24, 0x6E, 0x3A,
Packit 6c4009
0x42, 0x4D, 0xD2, 0xE0, 0x06, 0x49, 0x2E, 0xEA, 0x09,
Packit 6c4009
0xD1, 0x92, 0x1C, 0xFE, 0x1D, 0xEB, 0x1C, 0xB1, 0x29,
Packit 6c4009
0xA7, 0x3E, 0xE8, 0x82, 0x35, 0xF5, 0x2E, 0xBB, 0x44,
Packit 6c4009
0x84, 0xE9, 0x9C, 0x70, 0x26, 0xB4, 0x5F, 0x7E, 0x41,
Packit 6c4009
0x39, 0x91, 0xD6, 0x39, 0x83, 0x53, 0x39, 0xF4, 0x9C,
Packit 6c4009
0x84, 0x5F, 0x8B, 0xBD, 0xF9, 0x28, 0x3B, 0x1F, 0xF8,
Packit 6c4009
0x97, 0xFF, 0xDE, 0x05, 0x98, 0x0F, 0xEF, 0x2F, 0x11,
Packit 6c4009
0x8B, 0x5A, 0x0A, 0x6D, 0x1F, 0x6D, 0x36, 0x7E, 0xCF,
Packit 6c4009
0x27, 0xCB, 0x09, 0xB7, 0x4F, 0x46, 0x3F, 0x66, 0x9E,
Packit 6c4009
0x5F, 0xEA, 0x2D, 0x75, 0x27, 0xBA, 0xC7, 0xEB, 0xE5,
Packit 6c4009
0xF1, 0x7B, 0x3D, 0x07, 0x39, 0xF7, 0x8A, 0x52, 0x92,
Packit 6c4009
0xEA, 0x6B, 0xFB, 0x5F, 0xB1, 0x1F, 0x8D, 0x5D, 0x08,
Packit 6c4009
0x56, 0x03, 0x30, 0x46, 0xFC, 0x7B, 0x6B, 0xAB, 0xF0,
Packit 6c4009
0xCF, 0xBC, 0x20, 0x9A, 0xF4, 0x36, 0x1D, 0xA9, 0xE3,
Packit 6c4009
0x91, 0x61, 0x5E, 0xE6, 0x1B, 0x08, 0x65, 0x99, 0x85,
Packit 6c4009
0x5F, 0x14, 0xA0, 0x68, 0x40, 0x8D, 0xFF, 0xD8, 0x80,
Packit 6c4009
0x4D, 0x73, 0x27, 0x31, 0x06, 0x06, 0x15, 0x56, 0xCA,
Packit 6c4009
0x73, 0xA8, 0xC9, 0x60, 0xE2, 0x7B, 0xC0, 0x8C, 0x6B,
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
/* This array is like the one in e_rem_pio2.c, but the numbers are
Packit 6c4009
   single precision and the last 8 bits are forced to 0.  */
Packit 6c4009
static const int32_t npio2_hw[] = {
Packit 6c4009
0x3fc90f00, 0x40490f00, 0x4096cb00, 0x40c90f00, 0x40fb5300, 0x4116cb00,
Packit 6c4009
0x412fed00, 0x41490f00, 0x41623100, 0x417b5300, 0x418a3a00, 0x4196cb00,
Packit 6c4009
0x41a35c00, 0x41afed00, 0x41bc7e00, 0x41c90f00, 0x41d5a000, 0x41e23100,
Packit 6c4009
0x41eec200, 0x41fb5300, 0x4203f200, 0x420a3a00, 0x42108300, 0x4216cb00,
Packit 6c4009
0x421d1400, 0x42235c00, 0x4229a500, 0x422fed00, 0x42363600, 0x423c7e00,
Packit 6c4009
0x4242c700, 0x42490f00
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * invpio2:  24 bits of 2/pi
Packit 6c4009
 * pio2_1:   first  17 bit of pi/2
Packit 6c4009
 * pio2_1t:  pi/2 - pio2_1
Packit 6c4009
 * pio2_2:   second 17 bit of pi/2
Packit 6c4009
 * pio2_2t:  pi/2 - (pio2_1+pio2_2)
Packit 6c4009
 * pio2_3:   third  17 bit of pi/2
Packit 6c4009
 * pio2_3t:  pi/2 - (pio2_1+pio2_2+pio2_3)
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
static const float
Packit 6c4009
zero =  0.0000000000e+00, /* 0x00000000 */
Packit 6c4009
half =  5.0000000000e-01, /* 0x3f000000 */
Packit 6c4009
two8 =  2.5600000000e+02, /* 0x43800000 */
Packit 6c4009
invpio2 =  6.3661980629e-01, /* 0x3f22f984 */
Packit 6c4009
pio2_1  =  1.5707855225e+00, /* 0x3fc90f80 */
Packit 6c4009
pio2_1t =  1.0804334124e-05, /* 0x37354443 */
Packit 6c4009
pio2_2  =  1.0804273188e-05, /* 0x37354400 */
Packit 6c4009
pio2_2t =  6.0770999344e-11, /* 0x2e85a308 */
Packit 6c4009
pio2_3  =  6.0770943833e-11, /* 0x2e85a300 */
Packit 6c4009
pio2_3t =  6.1232342629e-17; /* 0x248d3132 */
Packit 6c4009
Packit 6c4009
int32_t __ieee754_rem_pio2f(float x, float *y)
Packit 6c4009
{
Packit 6c4009
	float z,w,t,r,fn;
Packit 6c4009
	float tx[3];
Packit 6c4009
	int32_t e0,i,j,nx,n,ix,hx;
Packit 6c4009
Packit 6c4009
	GET_FLOAT_WORD(hx,x);
Packit 6c4009
	ix = hx&0x7fffffff;
Packit 6c4009
	if(ix<=0x3f490fd8)   /* |x| ~<= pi/4 , no need for reduction */
Packit 6c4009
	    {y[0] = x; y[1] = 0; return 0;}
Packit 6c4009
	if(ix<0x4016cbe4) {  /* |x| < 3pi/4, special case with n=+-1 */
Packit 6c4009
	    if(hx>0) {
Packit 6c4009
		z = x - pio2_1;
Packit 6c4009
		if((ix&0xffffffc0)!=0x3fc90fc0) { /* 24+24 bit pi OK */
Packit 6c4009
		    y[0] = z - pio2_1t;
Packit 6c4009
		    y[1] = (z-y[0])-pio2_1t;
Packit 6c4009
		} else {		/* near pi/2, use 24+24+24 bit pi */
Packit 6c4009
		    z -= pio2_2;
Packit 6c4009
		    y[0] = z - pio2_2t;
Packit 6c4009
		    y[1] = (z-y[0])-pio2_2t;
Packit 6c4009
		}
Packit 6c4009
		return 1;
Packit 6c4009
	    } else {	/* negative x */
Packit 6c4009
		z = x + pio2_1;
Packit 6c4009
		if((ix&0xffffffc0)!=0x3fc90fc0) { /* 24+24 bit pi OK */
Packit 6c4009
		    y[0] = z + pio2_1t;
Packit 6c4009
		    y[1] = (z-y[0])+pio2_1t;
Packit 6c4009
		} else {		/* near pi/2, use 24+24+24 bit pi */
Packit 6c4009
		    z += pio2_2;
Packit 6c4009
		    y[0] = z + pio2_2t;
Packit 6c4009
		    y[1] = (z-y[0])+pio2_2t;
Packit 6c4009
		}
Packit 6c4009
		return -1;
Packit 6c4009
	    }
Packit 6c4009
	}
Packit 6c4009
	if(ix<=0x43490f80) { /* |x| ~<= 2^7*(pi/2), medium size */
Packit 6c4009
	    t  = fabsf(x);
Packit 6c4009
	    n  = (int32_t) (t*invpio2+half);
Packit 6c4009
	    fn = (float)n;
Packit 6c4009
	    r  = t-fn*pio2_1;
Packit 6c4009
	    w  = fn*pio2_1t;	/* 1st round good to 40 bit */
Packit 6c4009
	    if(n<32&&(int32_t)(ix&0xffffff00)!=npio2_hw[n-1]) {
Packit 6c4009
		y[0] = r-w;	/* quick check no cancellation */
Packit 6c4009
	    } else {
Packit 6c4009
	        uint32_t high;
Packit 6c4009
	        j  = ix>>23;
Packit 6c4009
	        y[0] = r-w;
Packit 6c4009
		GET_FLOAT_WORD(high,y[0]);
Packit 6c4009
	        i = j-((high>>23)&0xff);
Packit 6c4009
	        if(i>8) {  /* 2nd iteration needed, good to 57 */
Packit 6c4009
		    t  = r;
Packit 6c4009
		    w  = fn*pio2_2;
Packit 6c4009
		    r  = t-w;
Packit 6c4009
		    w  = fn*pio2_2t-((t-r)-w);
Packit 6c4009
		    y[0] = r-w;
Packit 6c4009
		    GET_FLOAT_WORD(high,y[0]);
Packit 6c4009
		    i = j-((high>>23)&0xff);
Packit 6c4009
		    if(i>25)  {	/* 3rd iteration need, 74 bits acc */
Packit 6c4009
			t  = r;	/* will cover all possible cases */
Packit 6c4009
			w  = fn*pio2_3;
Packit 6c4009
			r  = t-w;
Packit 6c4009
			w  = fn*pio2_3t-((t-r)-w);
Packit 6c4009
			y[0] = r-w;
Packit 6c4009
		    }
Packit 6c4009
		}
Packit 6c4009
	    }
Packit 6c4009
	    y[1] = (r-y[0])-w;
Packit 6c4009
	    if(hx<0) 	{y[0] = -y[0]; y[1] = -y[1]; return -n;}
Packit 6c4009
	    else	 return n;
Packit 6c4009
	}
Packit 6c4009
    /*
Packit 6c4009
     * all other (large) arguments
Packit 6c4009
     */
Packit 6c4009
	if(ix>=0x7f800000) {		/* x is inf or NaN */
Packit 6c4009
	    y[0]=y[1]=x-x; return 0;
Packit 6c4009
	}
Packit 6c4009
    /* set z = scalbn(|x|,ilogb(x)-7) */
Packit 6c4009
	e0 	= (ix>>23)-134;		/* e0 = ilogb(z)-7; */
Packit 6c4009
	SET_FLOAT_WORD(z, ix - ((int32_t)(e0<<23)));
Packit 6c4009
	for(i=0;i<2;i++) {
Packit 6c4009
		tx[i] = (float)((int32_t)(z));
Packit 6c4009
		z     = (z-tx[i])*two8;
Packit 6c4009
	}
Packit 6c4009
	tx[2] = z;
Packit 6c4009
	nx = 3;
Packit 6c4009
	while(tx[nx-1]==zero) nx--;	/* skip zero term */
Packit 6c4009
	n  =  __kernel_rem_pio2f(tx,y,e0,nx,2,two_over_pi);
Packit 6c4009
	if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
Packit 6c4009
	return n;
Packit 6c4009
}