xref: /openbsd/lib/libm/src/e_rem_pio2f.c (revision 043fbe51)
1df930be7Sderaadt /* e_rem_pio2f.c -- float version of e_rem_pio2.c
2df930be7Sderaadt  * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
3df930be7Sderaadt  */
4df930be7Sderaadt 
5df930be7Sderaadt /*
6df930be7Sderaadt  * ====================================================
7df930be7Sderaadt  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
8df930be7Sderaadt  *
9df930be7Sderaadt  * Developed at SunPro, a Sun Microsystems, Inc. business.
10df930be7Sderaadt  * Permission to use, copy, modify, and distribute this
11df930be7Sderaadt  * software is freely granted, provided that this notice
12df930be7Sderaadt  * is preserved.
13df930be7Sderaadt  * ====================================================
14df930be7Sderaadt  */
15df930be7Sderaadt 
16df930be7Sderaadt /* __ieee754_rem_pio2f(x,y)
17df930be7Sderaadt  *
18df930be7Sderaadt  * return the remainder of x rem pi/2 in y[0]+y[1]
19df930be7Sderaadt  * use __kernel_rem_pio2f()
20df930be7Sderaadt  */
21df930be7Sderaadt 
22df930be7Sderaadt #include "math.h"
23df930be7Sderaadt #include "math_private.h"
24df930be7Sderaadt 
25df930be7Sderaadt /*
26df930be7Sderaadt  * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
27df930be7Sderaadt  */
28df930be7Sderaadt static const int32_t two_over_pi[] = {
29df930be7Sderaadt 0xA2, 0xF9, 0x83, 0x6E, 0x4E, 0x44, 0x15, 0x29, 0xFC,
30df930be7Sderaadt 0x27, 0x57, 0xD1, 0xF5, 0x34, 0xDD, 0xC0, 0xDB, 0x62,
31df930be7Sderaadt 0x95, 0x99, 0x3C, 0x43, 0x90, 0x41, 0xFE, 0x51, 0x63,
32df930be7Sderaadt 0xAB, 0xDE, 0xBB, 0xC5, 0x61, 0xB7, 0x24, 0x6E, 0x3A,
33df930be7Sderaadt 0x42, 0x4D, 0xD2, 0xE0, 0x06, 0x49, 0x2E, 0xEA, 0x09,
34df930be7Sderaadt 0xD1, 0x92, 0x1C, 0xFE, 0x1D, 0xEB, 0x1C, 0xB1, 0x29,
35df930be7Sderaadt 0xA7, 0x3E, 0xE8, 0x82, 0x35, 0xF5, 0x2E, 0xBB, 0x44,
36df930be7Sderaadt 0x84, 0xE9, 0x9C, 0x70, 0x26, 0xB4, 0x5F, 0x7E, 0x41,
37df930be7Sderaadt 0x39, 0x91, 0xD6, 0x39, 0x83, 0x53, 0x39, 0xF4, 0x9C,
38df930be7Sderaadt 0x84, 0x5F, 0x8B, 0xBD, 0xF9, 0x28, 0x3B, 0x1F, 0xF8,
39df930be7Sderaadt 0x97, 0xFF, 0xDE, 0x05, 0x98, 0x0F, 0xEF, 0x2F, 0x11,
40df930be7Sderaadt 0x8B, 0x5A, 0x0A, 0x6D, 0x1F, 0x6D, 0x36, 0x7E, 0xCF,
41df930be7Sderaadt 0x27, 0xCB, 0x09, 0xB7, 0x4F, 0x46, 0x3F, 0x66, 0x9E,
42df930be7Sderaadt 0x5F, 0xEA, 0x2D, 0x75, 0x27, 0xBA, 0xC7, 0xEB, 0xE5,
43df930be7Sderaadt 0xF1, 0x7B, 0x3D, 0x07, 0x39, 0xF7, 0x8A, 0x52, 0x92,
44df930be7Sderaadt 0xEA, 0x6B, 0xFB, 0x5F, 0xB1, 0x1F, 0x8D, 0x5D, 0x08,
45df930be7Sderaadt 0x56, 0x03, 0x30, 0x46, 0xFC, 0x7B, 0x6B, 0xAB, 0xF0,
46df930be7Sderaadt 0xCF, 0xBC, 0x20, 0x9A, 0xF4, 0x36, 0x1D, 0xA9, 0xE3,
47df930be7Sderaadt 0x91, 0x61, 0x5E, 0xE6, 0x1B, 0x08, 0x65, 0x99, 0x85,
48df930be7Sderaadt 0x5F, 0x14, 0xA0, 0x68, 0x40, 0x8D, 0xFF, 0xD8, 0x80,
49df930be7Sderaadt 0x4D, 0x73, 0x27, 0x31, 0x06, 0x06, 0x15, 0x56, 0xCA,
50df930be7Sderaadt 0x73, 0xA8, 0xC9, 0x60, 0xE2, 0x7B, 0xC0, 0x8C, 0x6B,
51df930be7Sderaadt };
52df930be7Sderaadt 
53df930be7Sderaadt /* This array is like the one in e_rem_pio2.c, but the numbers are
54df930be7Sderaadt    single precision and the last 8 bits are forced to 0.  */
55df930be7Sderaadt static const int32_t npio2_hw[] = {
56df930be7Sderaadt 0x3fc90f00, 0x40490f00, 0x4096cb00, 0x40c90f00, 0x40fb5300, 0x4116cb00,
57df930be7Sderaadt 0x412fed00, 0x41490f00, 0x41623100, 0x417b5300, 0x418a3a00, 0x4196cb00,
58df930be7Sderaadt 0x41a35c00, 0x41afed00, 0x41bc7e00, 0x41c90f00, 0x41d5a000, 0x41e23100,
59df930be7Sderaadt 0x41eec200, 0x41fb5300, 0x4203f200, 0x420a3a00, 0x42108300, 0x4216cb00,
60df930be7Sderaadt 0x421d1400, 0x42235c00, 0x4229a500, 0x422fed00, 0x42363600, 0x423c7e00,
61df930be7Sderaadt 0x4242c700, 0x42490f00
62df930be7Sderaadt };
63df930be7Sderaadt 
64df930be7Sderaadt /*
65df930be7Sderaadt  * invpio2:  24 bits of 2/pi
66df930be7Sderaadt  * pio2_1:   first  17 bit of pi/2
67df930be7Sderaadt  * pio2_1t:  pi/2 - pio2_1
68df930be7Sderaadt  * pio2_2:   second 17 bit of pi/2
69df930be7Sderaadt  * pio2_2t:  pi/2 - (pio2_1+pio2_2)
70df930be7Sderaadt  * pio2_3:   third  17 bit of pi/2
71df930be7Sderaadt  * pio2_3t:  pi/2 - (pio2_1+pio2_2+pio2_3)
72df930be7Sderaadt  */
73df930be7Sderaadt 
74df930be7Sderaadt static const float
75df930be7Sderaadt zero =  0.0000000000e+00, /* 0x00000000 */
76df930be7Sderaadt half =  5.0000000000e-01, /* 0x3f000000 */
77df930be7Sderaadt two8 =  2.5600000000e+02, /* 0x43800000 */
78df930be7Sderaadt invpio2 =  6.3661980629e-01, /* 0x3f22f984 */
79df930be7Sderaadt pio2_1  =  1.5707855225e+00, /* 0x3fc90f80 */
80df930be7Sderaadt pio2_1t =  1.0804334124e-05, /* 0x37354443 */
81df930be7Sderaadt pio2_2  =  1.0804273188e-05, /* 0x37354400 */
82df930be7Sderaadt pio2_2t =  6.0770999344e-11, /* 0x2e85a308 */
83df930be7Sderaadt pio2_3  =  6.0770943833e-11, /* 0x2e85a300 */
84df930be7Sderaadt pio2_3t =  6.1232342629e-17; /* 0x248d3132 */
85df930be7Sderaadt 
86*e7beb4a7Smillert int32_t
__ieee754_rem_pio2f(float x,float * y)87*e7beb4a7Smillert __ieee754_rem_pio2f(float x, float *y)
88df930be7Sderaadt {
89df930be7Sderaadt 	float z,w,t,r,fn;
90df930be7Sderaadt 	float tx[3];
91df930be7Sderaadt 	int32_t e0,i,j,nx,n,ix,hx;
92df930be7Sderaadt 
93df930be7Sderaadt 	GET_FLOAT_WORD(hx,x);
94df930be7Sderaadt 	ix = hx&0x7fffffff;
95df930be7Sderaadt 	if(ix<=0x3f490fd8)   /* |x| ~<= pi/4 , no need for reduction */
96df930be7Sderaadt 	    {y[0] = x; y[1] = 0; return 0;}
97df930be7Sderaadt 	if(ix<0x4016cbe4) {  /* |x| < 3pi/4, special case with n=+-1 */
98df930be7Sderaadt 	    if(hx>0) {
99df930be7Sderaadt 		z = x - pio2_1;
100df930be7Sderaadt 		if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */
101df930be7Sderaadt 		    y[0] = z - pio2_1t;
102df930be7Sderaadt 		    y[1] = (z-y[0])-pio2_1t;
103df930be7Sderaadt 		} else {		/* near pi/2, use 24+24+24 bit pi */
104df930be7Sderaadt 		    z -= pio2_2;
105df930be7Sderaadt 		    y[0] = z - pio2_2t;
106df930be7Sderaadt 		    y[1] = (z-y[0])-pio2_2t;
107df930be7Sderaadt 		}
108df930be7Sderaadt 		return 1;
109df930be7Sderaadt 	    } else {	/* negative x */
110df930be7Sderaadt 		z = x + pio2_1;
111df930be7Sderaadt 		if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */
112df930be7Sderaadt 		    y[0] = z + pio2_1t;
113df930be7Sderaadt 		    y[1] = (z-y[0])+pio2_1t;
114df930be7Sderaadt 		} else {		/* near pi/2, use 24+24+24 bit pi */
115df930be7Sderaadt 		    z += pio2_2;
116df930be7Sderaadt 		    y[0] = z + pio2_2t;
117df930be7Sderaadt 		    y[1] = (z-y[0])+pio2_2t;
118df930be7Sderaadt 		}
119df930be7Sderaadt 		return -1;
120df930be7Sderaadt 	    }
121df930be7Sderaadt 	}
122df930be7Sderaadt 	if(ix<=0x43490f80) { /* |x| ~<= 2^7*(pi/2), medium size */
123df930be7Sderaadt 	    t  = fabsf(x);
124df930be7Sderaadt 	    n  = (int32_t) (t*invpio2+half);
125df930be7Sderaadt 	    fn = (float)n;
126df930be7Sderaadt 	    r  = t-fn*pio2_1;
127df930be7Sderaadt 	    w  = fn*pio2_1t;	/* 1st round good to 40 bit */
128df930be7Sderaadt 	    if(n<32&&(ix&0xffffff00)!=npio2_hw[n-1]) {
129df930be7Sderaadt 		y[0] = r-w;	/* quick check no cancellation */
130df930be7Sderaadt 	    } else {
131df930be7Sderaadt 	        u_int32_t high;
132df930be7Sderaadt 	        j  = ix>>23;
133df930be7Sderaadt 	        y[0] = r-w;
134df930be7Sderaadt 		GET_FLOAT_WORD(high,y[0]);
135df930be7Sderaadt 	        i = j-((high>>23)&0xff);
136df930be7Sderaadt 	        if(i>8) {  /* 2nd iteration needed, good to 57 */
137df930be7Sderaadt 		    t  = r;
138df930be7Sderaadt 		    w  = fn*pio2_2;
139df930be7Sderaadt 		    r  = t-w;
140df930be7Sderaadt 		    w  = fn*pio2_2t-((t-r)-w);
141df930be7Sderaadt 		    y[0] = r-w;
142df930be7Sderaadt 		    GET_FLOAT_WORD(high,y[0]);
143df930be7Sderaadt 		    i = j-((high>>23)&0xff);
144df930be7Sderaadt 		    if(i>25)  {	/* 3rd iteration need, 74 bits acc */
145df930be7Sderaadt 		    	t  = r;	/* will cover all possible cases */
146df930be7Sderaadt 		    	w  = fn*pio2_3;
147df930be7Sderaadt 		    	r  = t-w;
148df930be7Sderaadt 		    	w  = fn*pio2_3t-((t-r)-w);
149df930be7Sderaadt 		    	y[0] = r-w;
150df930be7Sderaadt 		    }
151df930be7Sderaadt 		}
152df930be7Sderaadt 	    }
153df930be7Sderaadt 	    y[1] = (r-y[0])-w;
154df930be7Sderaadt 	    if(hx<0) 	{y[0] = -y[0]; y[1] = -y[1]; return -n;}
155df930be7Sderaadt 	    else	 return n;
156df930be7Sderaadt 	}
157df930be7Sderaadt     /*
158df930be7Sderaadt      * all other (large) arguments
159df930be7Sderaadt      */
160df930be7Sderaadt 	if(ix>=0x7f800000) {		/* x is inf or NaN */
161df930be7Sderaadt 	    y[0]=y[1]=x-x; return 0;
162df930be7Sderaadt 	}
163df930be7Sderaadt     /* set z = scalbn(|x|,ilogb(x)-7) */
164df930be7Sderaadt 	e0 	= (ix>>23)-134;		/* e0 = ilogb(z)-7; */
165df930be7Sderaadt 	SET_FLOAT_WORD(z, ix - ((int32_t)(e0<<23)));
166df930be7Sderaadt 	for(i=0;i<2;i++) {
167df930be7Sderaadt 		tx[i] = (float)((int32_t)(z));
168df930be7Sderaadt 		z     = (z-tx[i])*two8;
169df930be7Sderaadt 	}
170df930be7Sderaadt 	tx[2] = z;
171df930be7Sderaadt 	nx = 3;
172df930be7Sderaadt 	while(tx[nx-1]==zero) nx--;	/* skip zero term */
173df930be7Sderaadt 	n  =  __kernel_rem_pio2f(tx,y,e0,nx,2,two_over_pi);
174df930be7Sderaadt 	if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
175df930be7Sderaadt 	return n;
176df930be7Sderaadt }
177