POK
/home/jaouen/pok_official/pok/trunk/libpok/libm/e_rem_pio2.c
00001 /*
00002  *                               POK header
00003  * 
00004  * The following file is a part of the POK project. Any modification should
00005  * made according to the POK licence. You CANNOT use this file or a part of
00006  * this file is this part of a file for your own project
00007  *
00008  * For more information on the POK licence, please see our LICENCE FILE
00009  *
00010  * Please follow the coding guidelines described in doc/CODING_GUIDELINES
00011  *
00012  *                                      Copyright (c) 2007-2009 POK team 
00013  *
00014  * Created by julien on Fri Jan 30 14:41:34 2009 
00015  */
00016 
00017 /* @(#)e_rem_pio2.c 5.1 93/09/24 */
00018 /*
00019  * ====================================================
00020  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
00021  *
00022  * Developed at SunPro, a Sun Microsystems, Inc. business.
00023  * Permission to use, copy, modify, and distribute this
00024  * software is freely granted, provided that this notice
00025  * is preserved.
00026  * ====================================================
00027  */
00028 
00029 /* __ieee754_rem_pio2(x,y)
00030  *
00031  * return the remainder of x rem pi/2 in y[0]+y[1]
00032  * use __kernel_rem_pio2()
00033  */
00034 
00035 #ifdef POK_NEEDS_LIBMATH
00036 
00037 #include <libm.h>
00038 #include "math_private.h"
00039 
00040 /*
00041  * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
00042  */
00043 static const int32_t two_over_pi[] = {
00044 0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62,
00045 0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A,
00046 0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129,
00047 0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41,
00048 0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8,
00049 0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF,
00050 0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5,
00051 0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08,
00052 0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3,
00053 0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880,
00054 0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B,
00055 };
00056 
00057 static const int32_t npio2_hw[] = {
00058 0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C,
00059 0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C,
00060 0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A,
00061 0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C, 0x4042106C, 0x4042D97C,
00062 0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB,
00063 0x404858EB, 0x404921FB,
00064 };
00065 
00066 /*
00067  * invpio2:  53 bits of 2/pi
00068  * pio2_1:   first  33 bit of pi/2
00069  * pio2_1t:  pi/2 - pio2_1
00070  * pio2_2:   second 33 bit of pi/2
00071  * pio2_2t:  pi/2 - (pio2_1+pio2_2)
00072  * pio2_3:   third  33 bit of pi/2
00073  * pio2_3t:  pi/2 - (pio2_1+pio2_2+pio2_3)
00074  */
00075 
00076 static const double
00077 zero =  0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
00078 half =  5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
00079 two24 =  1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
00080 invpio2 =  6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
00081 pio2_1  =  1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */
00082 pio2_1t =  6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */
00083 pio2_2  =  6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */
00084 pio2_2t =  2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */
00085 pio2_3  =  2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
00086 pio2_3t =  8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
00087 
00088 int32_t
00089 __ieee754_rem_pio2(double x, double *y)
00090 {
00091         double z,w,t,r,fn;
00092         double tx[3];
00093         int32_t e0,i,j,nx,n,ix,hx;
00094         uint32_t low;
00095 
00096         z = 0;
00097         GET_HIGH_WORD(hx,x);            /* high word of x */
00098         ix = hx&0x7fffffff;
00099         if(ix<=0x3fe921fb)   /* |x| ~<= pi/4 , no need for reduction */
00100             {y[0] = x; y[1] = 0; return 0;}
00101         if(ix<0x4002d97c) {  /* |x| < 3pi/4, special case with n=+-1 */
00102             if(hx>0) {
00103                 z = x - pio2_1;
00104                 if(ix!=0x3ff921fb) {    /* 33+53 bit pi is good enough */
00105                     y[0] = z - pio2_1t;
00106                     y[1] = (z-y[0])-pio2_1t;
00107                 } else {                /* near pi/2, use 33+33+53 bit pi */
00108                     z -= pio2_2;
00109                     y[0] = z - pio2_2t;
00110                     y[1] = (z-y[0])-pio2_2t;
00111                 }
00112                 return 1;
00113             } else {    /* negative x */
00114                 z = x + pio2_1;
00115                 if(ix!=0x3ff921fb) {    /* 33+53 bit pi is good enough */
00116                     y[0] = z + pio2_1t;
00117                     y[1] = (z-y[0])+pio2_1t;
00118                 } else {                /* near pi/2, use 33+33+53 bit pi */
00119                     z += pio2_2;
00120                     y[0] = z + pio2_2t;
00121                     y[1] = (z-y[0])+pio2_2t;
00122                 }
00123                 return -1;
00124             }
00125         }
00126         if(ix<=0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */
00127             t  = fabs(x);
00128             n  = (int32_t) (t*invpio2+half);
00129             fn = (double)n;
00130             r  = t-fn*pio2_1;
00131             w  = fn*pio2_1t;    /* 1st round good to 85 bit */
00132             if(n<32&&ix!=npio2_hw[n-1]) {
00133                 y[0] = r-w;     /* quick check no cancellation */
00134             } else {
00135                 uint32_t high;
00136                 j  = ix>>20;
00137                 y[0] = r-w;
00138                 GET_HIGH_WORD(high,y[0]);
00139                 i = j-((high>>20)&0x7ff);
00140                 if(i>16) {  /* 2nd iteration needed, good to 118 */
00141                     t  = r;
00142                     w  = fn*pio2_2;
00143                     r  = t-w;
00144                     w  = fn*pio2_2t-((t-r)-w);
00145                     y[0] = r-w;
00146                     GET_HIGH_WORD(high,y[0]);
00147                     i = j-((high>>20)&0x7ff);
00148                     if(i>49)  { /* 3rd iteration need, 151 bits acc */
00149                         t  = r; /* will cover all possible cases */
00150                         w  = fn*pio2_3;
00151                         r  = t-w;
00152                         w  = fn*pio2_3t-((t-r)-w);
00153                         y[0] = r-w;
00154                     }
00155                 }
00156             }
00157             y[1] = (r-y[0])-w;
00158             if(hx<0)    {y[0] = -y[0]; y[1] = -y[1]; return -n;}
00159             else         return n;
00160         }
00161     /*
00162      * all other (large) arguments
00163      */
00164         if(ix>=0x7ff00000) {            /* x is inf or NaN */
00165             y[0]=y[1]=x-x; return 0;
00166         }
00167     /* set z = scalbn(|x|,ilogb(x)-23) */
00168         GET_LOW_WORD(low,x);
00169         SET_LOW_WORD(z,low);
00170         e0      = (ix>>20)-1046;        /* e0 = ilogb(z)-23; */
00171         SET_HIGH_WORD(z, ix - ((int32_t)(e0<<20)));
00172         for(i=0;i<2;i++) {
00173                 tx[i] = (double)((int32_t)(z));
00174                 z     = (z-tx[i])*two24;
00175         }
00176         tx[2] = z;
00177         nx = 3;
00178         while(tx[nx-1]==zero) nx--;     /* skip zero term */
00179         n  =  __kernel_rem_pio2(tx,y,e0,nx,2,(int*)two_over_pi);
00180         if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
00181         return n;
00182 }
00183 #endif