/ base / math / e_rem_pio2.c
e_rem_pio2.c
  1  /* @(#)e_rem_pio2.c 5.1 93/09/24 */
  2  /*
  3   * ====================================================
  4   * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  5   *
  6   * Developed at SunPro, a Sun Microsystems, Inc. business.
  7   * Permission to use, copy, modify, and distribute this
  8   * software is freely granted, provided that this notice 
  9   * is preserved.
 10   * ====================================================
 11   */
 12  
 13  #if defined(LIBM_SCCS) && !defined(lint)
 14  static char rcsid[] = "$NetBSD: e_rem_pio2.c,v 1.8 1995/05/10 20:46:02 jtc Exp $";
 15  #endif
 16  
 17  /* __ieee754_rem_pio2(x,y)
 18   * 
 19   * return the remainder of x rem pi/2 in y[0]+y[1] 
 20   * use __kernel_rem_pio2()
 21   */
 22  
 23  #include "math.h"
 24  #include "mathP.h"
 25  
 26  /*
 27   * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi 
 28   */
 29  #ifdef __STDC__
 30  static const int32_t two_over_pi[] = {
 31  #else
 32  static int32_t two_over_pi[] = {
 33  #endif
 34  0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, 
 35  0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, 
 36  0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, 
 37  0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, 
 38  0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8, 
 39  0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF, 
 40  0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, 
 41  0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, 
 42  0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, 
 43  0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, 
 44  0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B, 
 45  };
 46  
 47  #ifdef __STDC__
 48  static const int32_t npio2_hw[] = {
 49  #else
 50  static int32_t npio2_hw[] = {
 51  #endif
 52  0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C,
 53  0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C,
 54  0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A,
 55  0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C, 0x4042106C, 0x4042D97C,
 56  0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB,
 57  0x404858EB, 0x404921FB,
 58  };
 59  
 60  /*
 61   * invpio2:  53 bits of 2/pi
 62   * pio2_1:   first  33 bit of pi/2
 63   * pio2_1t:  pi/2 - pio2_1
 64   * pio2_2:   second 33 bit of pi/2
 65   * pio2_2t:  pi/2 - (pio2_1+pio2_2)
 66   * pio2_3:   third  33 bit of pi/2
 67   * pio2_3t:  pi/2 - (pio2_1+pio2_2+pio2_3)
 68   */
 69  
 70  #ifdef __STDC__
 71  static const double 
 72  #else
 73  static double 
 74  #endif
 75  zero =  0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
 76  half =  5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
 77  two24 =  1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
 78  invpio2 =  6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
 79  pio2_1  =  1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */
 80  pio2_1t =  6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */
 81  pio2_2  =  6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */
 82  pio2_2t =  2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */
 83  pio2_3  =  2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
 84  pio2_3t =  8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
 85  
 86  #ifdef __STDC__
 87  	int32_t __ieee754_rem_pio2(double x, double *y)
 88  #else
 89  	int32_t __ieee754_rem_pio2(x,y)
 90  	double x,y[];
 91  #endif
 92  {
 93  	double z,w,t,r,fn;
 94  	double tx[3];
 95  	int32_t e0,i,j,nx,n,ix,hx;
 96  	u_int32_t low;
 97  
 98  	/* XXX z is not properly initialized without this.  Is this a
 99  	 * bug?  --ds */
100  	z = 0;
101  
102  	GET_HIGH_WORD(hx,x);		/* high word of x */
103  	ix = hx&0x7fffffff;
104  	if(ix<=0x3fe921fb)   /* |x| ~<= pi/4 , no need for reduction */
105  	    {y[0] = x; y[1] = 0; return 0;}
106  	if(ix<0x4002d97c) {  /* |x| < 3pi/4, special case with n=+-1 */
107  	    if(hx>0) { 
108  		z = x - pio2_1;
109  		if(ix!=0x3ff921fb) { 	/* 33+53 bit pi is good enough */
110  		    y[0] = z - pio2_1t;
111  		    y[1] = (z-y[0])-pio2_1t;
112  		} else {		/* near pi/2, use 33+33+53 bit pi */
113  		    z -= pio2_2;
114  		    y[0] = z - pio2_2t;
115  		    y[1] = (z-y[0])-pio2_2t;
116  		}
117  		return 1;
118  	    } else {	/* negative x */
119  		z = x + pio2_1;
120  		if(ix!=0x3ff921fb) { 	/* 33+53 bit pi is good enough */
121  		    y[0] = z + pio2_1t;
122  		    y[1] = (z-y[0])+pio2_1t;
123  		} else {		/* near pi/2, use 33+33+53 bit pi */
124  		    z += pio2_2;
125  		    y[0] = z + pio2_2t;
126  		    y[1] = (z-y[0])+pio2_2t;
127  		}
128  		return -1;
129  	    }
130  	}
131  	if(ix<=0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */
132  	    t  = fabs(x);
133  	    n  = (int32_t) (t*invpio2+half);
134  	    fn = (double)n;
135  	    r  = t-fn*pio2_1;
136  	    w  = fn*pio2_1t;	/* 1st round good to 85 bit */
137  	    if(n<32&&ix!=npio2_hw[n-1]) {	
138  		y[0] = r-w;	/* quick check no cancellation */
139  	    } else {
140  	        u_int32_t high;
141  	        j  = ix>>20;
142  	        y[0] = r-w; 
143  		GET_HIGH_WORD(high,y[0]);
144  	        i = j-((high>>20)&0x7ff);
145  	        if(i>16) {  /* 2nd iteration needed, good to 118 */
146  		    t  = r;
147  		    w  = fn*pio2_2;	
148  		    r  = t-w;
149  		    w  = fn*pio2_2t-((t-r)-w);	
150  		    y[0] = r-w;
151  		    GET_HIGH_WORD(high,y[0]);
152  		    i = j-((high>>20)&0x7ff);
153  		    if(i>49)  {	/* 3rd iteration need, 151 bits acc */
154  		    	t  = r;	/* will cover all possible cases */
155  		    	w  = fn*pio2_3;	
156  		    	r  = t-w;
157  		    	w  = fn*pio2_3t-((t-r)-w);	
158  		    	y[0] = r-w;
159  		    }
160  		}
161  	    }
162  	    y[1] = (r-y[0])-w;
163  	    if(hx<0) 	{y[0] = -y[0]; y[1] = -y[1]; return -n;}
164  	    else	 return n;
165  	}
166      /* 
167       * all other (large) arguments
168       */
169  	if(ix>=0x7ff00000) {		/* x is inf or NaN */
170  	    y[0]=y[1]=x-x; return 0;
171  	}
172      /* set z = scalbn(|x|,ilogb(x)-23) */
173  	GET_LOW_WORD(low,x);
174  	SET_LOW_WORD(z,low);
175  	e0 	= (ix>>20)-1046;	/* e0 = ilogb(z)-23; */
176  	SET_HIGH_WORD(z, ix - ((int32_t)(e0<<20)));
177  	for(i=0;i<2;i++) {
178  		tx[i] = (double)((int32_t)(z));
179  		z     = (z-tx[i])*two24;
180  	}
181  	tx[2] = z;
182  	nx = 3;
183  	while(tx[nx-1]==zero) nx--;	/* skip zero term */
184  	n  =  __kernel_rem_pio2(tx,y,e0,nx,2,two_over_pi);
185  	if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
186  	return n;
187  }