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