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