xref: /freebsd/lib/msun/src/e_rem_pio2.c (revision 3a8617a83f16ffc9db4f96e1f0f21af94078e6b1)
13a8617a8SJordan K. Hubbard /* @(#)e_rem_pio2.c 5.1 93/09/24 */
23a8617a8SJordan K. Hubbard /*
33a8617a8SJordan K. Hubbard  * ====================================================
43a8617a8SJordan K. Hubbard  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
53a8617a8SJordan K. Hubbard  *
63a8617a8SJordan K. Hubbard  * Developed at SunPro, a Sun Microsystems, Inc. business.
73a8617a8SJordan K. Hubbard  * Permission to use, copy, modify, and distribute this
83a8617a8SJordan K. Hubbard  * software is freely granted, provided that this notice
93a8617a8SJordan K. Hubbard  * is preserved.
103a8617a8SJordan K. Hubbard  * ====================================================
113a8617a8SJordan K. Hubbard  */
123a8617a8SJordan K. Hubbard 
133a8617a8SJordan K. Hubbard #ifndef lint
143a8617a8SJordan K. Hubbard static char rcsid[] = "$Id: e_rem_pio2.c,v 1.5 1994/08/18 23:05:56 jtc Exp $";
153a8617a8SJordan K. Hubbard #endif
163a8617a8SJordan K. Hubbard 
173a8617a8SJordan K. Hubbard /* __ieee754_rem_pio2(x,y)
183a8617a8SJordan K. Hubbard  *
193a8617a8SJordan K. Hubbard  * return the remainder of x rem pi/2 in y[0]+y[1]
203a8617a8SJordan K. Hubbard  * use __kernel_rem_pio2()
213a8617a8SJordan K. Hubbard  */
223a8617a8SJordan K. Hubbard 
233a8617a8SJordan K. Hubbard #include "math.h"
243a8617a8SJordan K. Hubbard #include "math_private.h"
253a8617a8SJordan K. Hubbard 
263a8617a8SJordan K. Hubbard /*
273a8617a8SJordan K. Hubbard  * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
283a8617a8SJordan K. Hubbard  */
293a8617a8SJordan K. Hubbard #ifdef __STDC__
303a8617a8SJordan K. Hubbard static const int32_t two_over_pi[] = {
313a8617a8SJordan K. Hubbard #else
323a8617a8SJordan K. Hubbard static int32_t two_over_pi[] = {
333a8617a8SJordan K. Hubbard #endif
343a8617a8SJordan K. Hubbard 0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62,
353a8617a8SJordan K. Hubbard 0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A,
363a8617a8SJordan K. Hubbard 0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129,
373a8617a8SJordan K. Hubbard 0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41,
383a8617a8SJordan K. Hubbard 0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8,
393a8617a8SJordan K. Hubbard 0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF,
403a8617a8SJordan K. Hubbard 0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5,
413a8617a8SJordan K. Hubbard 0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08,
423a8617a8SJordan K. Hubbard 0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3,
433a8617a8SJordan K. Hubbard 0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880,
443a8617a8SJordan K. Hubbard 0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B,
453a8617a8SJordan K. Hubbard };
463a8617a8SJordan K. Hubbard 
473a8617a8SJordan K. Hubbard #ifdef __STDC__
483a8617a8SJordan K. Hubbard static const int32_t npio2_hw[] = {
493a8617a8SJordan K. Hubbard #else
503a8617a8SJordan K. Hubbard static int32_t npio2_hw[] = {
513a8617a8SJordan K. Hubbard #endif
523a8617a8SJordan K. Hubbard 0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C,
533a8617a8SJordan K. Hubbard 0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C,
543a8617a8SJordan K. Hubbard 0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A,
553a8617a8SJordan K. Hubbard 0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C, 0x4042106C, 0x4042D97C,
563a8617a8SJordan K. Hubbard 0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB,
573a8617a8SJordan K. Hubbard 0x404858EB, 0x404921FB,
583a8617a8SJordan K. Hubbard };
593a8617a8SJordan K. Hubbard 
603a8617a8SJordan K. Hubbard /*
613a8617a8SJordan K. Hubbard  * invpio2:  53 bits of 2/pi
623a8617a8SJordan K. Hubbard  * pio2_1:   first  33 bit of pi/2
633a8617a8SJordan K. Hubbard  * pio2_1t:  pi/2 - pio2_1
643a8617a8SJordan K. Hubbard  * pio2_2:   second 33 bit of pi/2
653a8617a8SJordan K. Hubbard  * pio2_2t:  pi/2 - (pio2_1+pio2_2)
663a8617a8SJordan K. Hubbard  * pio2_3:   third  33 bit of pi/2
673a8617a8SJordan K. Hubbard  * pio2_3t:  pi/2 - (pio2_1+pio2_2+pio2_3)
683a8617a8SJordan K. Hubbard  */
693a8617a8SJordan K. Hubbard 
703a8617a8SJordan K. Hubbard #ifdef __STDC__
713a8617a8SJordan K. Hubbard static const double
723a8617a8SJordan K. Hubbard #else
733a8617a8SJordan K. Hubbard static double
743a8617a8SJordan K. Hubbard #endif
753a8617a8SJordan K. Hubbard zero =  0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
763a8617a8SJordan K. Hubbard half =  5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
773a8617a8SJordan K. Hubbard two24 =  1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
783a8617a8SJordan K. Hubbard invpio2 =  6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
793a8617a8SJordan K. Hubbard pio2_1  =  1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */
803a8617a8SJordan K. Hubbard pio2_1t =  6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */
813a8617a8SJordan K. Hubbard pio2_2  =  6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */
823a8617a8SJordan K. Hubbard pio2_2t =  2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */
833a8617a8SJordan K. Hubbard pio2_3  =  2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
843a8617a8SJordan K. Hubbard pio2_3t =  8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
853a8617a8SJordan K. Hubbard 
863a8617a8SJordan K. Hubbard #ifdef __STDC__
873a8617a8SJordan K. Hubbard 	int32_t __ieee754_rem_pio2(double x, double *y)
883a8617a8SJordan K. Hubbard #else
893a8617a8SJordan K. Hubbard 	int32_t __ieee754_rem_pio2(x,y)
903a8617a8SJordan K. Hubbard 	double x,y[];
913a8617a8SJordan K. Hubbard #endif
923a8617a8SJordan K. Hubbard {
933a8617a8SJordan K. Hubbard 	double z,w,t,r,fn;
943a8617a8SJordan K. Hubbard 	double tx[3];
953a8617a8SJordan K. Hubbard 	int32_t e0,i,j,nx,n,ix,hx;
963a8617a8SJordan K. Hubbard 	u_int32_t low;
973a8617a8SJordan K. Hubbard 
983a8617a8SJordan K. Hubbard 	GET_HIGH_WORD(hx,x);		/* high word of x */
993a8617a8SJordan K. Hubbard 	ix = hx&0x7fffffff;
1003a8617a8SJordan K. Hubbard 	if(ix<=0x3fe921fb)   /* |x| ~<= pi/4 , no need for reduction */
1013a8617a8SJordan K. Hubbard 	    {y[0] = x; y[1] = 0; return 0;}
1023a8617a8SJordan K. Hubbard 	if(ix<=0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */
1033a8617a8SJordan K. Hubbard 	    t  = fabs(x);
1043a8617a8SJordan K. Hubbard 	    n  = (int32_t) (t*invpio2+half);
1053a8617a8SJordan K. Hubbard 	    fn = (double)n;
1063a8617a8SJordan K. Hubbard 	    r  = t-fn*pio2_1;
1073a8617a8SJordan K. Hubbard 	    w  = fn*pio2_1t;	/* 1st round good to 85 bit */
1083a8617a8SJordan K. Hubbard 	    if(n<32&&ix!=npio2_hw[n-1]) {
1093a8617a8SJordan K. Hubbard 		y[0] = r-w;	/* quick check no cancellation */
1103a8617a8SJordan K. Hubbard 	    } else {
1113a8617a8SJordan K. Hubbard 	        u_int32_t high;
1123a8617a8SJordan K. Hubbard 	        j  = ix>>20;
1133a8617a8SJordan K. Hubbard 	        y[0] = r-w;
1143a8617a8SJordan K. Hubbard 		GET_HIGH_WORD(high,y[0]);
1153a8617a8SJordan K. Hubbard 	        i = j-((high>>20)&0x7ff);
1163a8617a8SJordan K. Hubbard 	        if(i>16) {  /* 2nd iteration needed, good to 118 */
1173a8617a8SJordan K. Hubbard 		    t  = r;
1183a8617a8SJordan K. Hubbard 		    w  = fn*pio2_2;
1193a8617a8SJordan K. Hubbard 		    r  = t-w;
1203a8617a8SJordan K. Hubbard 		    w  = fn*pio2_2t-((t-r)-w);
1213a8617a8SJordan K. Hubbard 		    y[0] = r-w;
1223a8617a8SJordan K. Hubbard 		    GET_HIGH_WORD(high,y[0]);
1233a8617a8SJordan K. Hubbard 		    i = j-((high>>20)&0x7ff);
1243a8617a8SJordan K. Hubbard 		    if(i>49)  {	/* 3rd iteration need, 151 bits acc */
1253a8617a8SJordan K. Hubbard 		    	t  = r;	/* will cover all possible cases */
1263a8617a8SJordan K. Hubbard 		    	w  = fn*pio2_3;
1273a8617a8SJordan K. Hubbard 		    	r  = t-w;
1283a8617a8SJordan K. Hubbard 		    	w  = fn*pio2_3t-((t-r)-w);
1293a8617a8SJordan K. Hubbard 		    	y[0] = r-w;
1303a8617a8SJordan K. Hubbard 		    }
1313a8617a8SJordan K. Hubbard 		}
1323a8617a8SJordan K. Hubbard 	    }
1333a8617a8SJordan K. Hubbard 	    y[1] = (r-y[0])-w;
1343a8617a8SJordan K. Hubbard 	    if(hx<0) 	{y[0] = -y[0]; y[1] = -y[1]; return -n;}
1353a8617a8SJordan K. Hubbard 	    else	 return n;
1363a8617a8SJordan K. Hubbard 	}
1373a8617a8SJordan K. Hubbard     /*
1383a8617a8SJordan K. Hubbard      * all other (large) arguments
1393a8617a8SJordan K. Hubbard      */
1403a8617a8SJordan K. Hubbard 	if(ix>=0x7ff00000) {		/* x is inf or NaN */
1413a8617a8SJordan K. Hubbard 	    y[0]=y[1]=x-x; return 0;
1423a8617a8SJordan K. Hubbard 	}
1433a8617a8SJordan K. Hubbard     /* set z = scalbn(|x|,ilogb(x)-23) */
1443a8617a8SJordan K. Hubbard 	GET_LOW_WORD(low,x);
1453a8617a8SJordan K. Hubbard 	SET_LOW_WORD(z,low);
1463a8617a8SJordan K. Hubbard 	e0 	= (ix>>20)-1046;	/* e0 = ilogb(z)-23; */
1473a8617a8SJordan K. Hubbard 	SET_HIGH_WORD(z, ix - ((int32_t)(e0<<20)));
1483a8617a8SJordan K. Hubbard 	for(i=0;i<2;i++) {
1493a8617a8SJordan K. Hubbard 		tx[i] = (double)((int32_t)(z));
1503a8617a8SJordan K. Hubbard 		z     = (z-tx[i])*two24;
1513a8617a8SJordan K. Hubbard 	}
1523a8617a8SJordan K. Hubbard 	tx[2] = z;
1533a8617a8SJordan K. Hubbard 	nx = 3;
1543a8617a8SJordan K. Hubbard 	while(tx[nx-1]==zero) nx--;	/* skip zero term */
1553a8617a8SJordan K. Hubbard 	n  =  __kernel_rem_pio2(tx,y,e0,nx,2,two_over_pi);
1563a8617a8SJordan K. Hubbard 	if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
1573a8617a8SJordan K. Hubbard 	return n;
1583a8617a8SJordan K. Hubbard }
159