POK
/home/jaouen/pok_official/pok/trunk/libpok/libm/e_rem_pio2f.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_pio2f.c -- float version of e_rem_pio2.c
00018  * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
00019  */
00020 
00021 /*
00022  * ====================================================
00023  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
00024  *
00025  * Developed at SunPro, a Sun Microsystems, Inc. business.
00026  * Permission to use, copy, modify, and distribute this
00027  * software is freely granted, provided that this notice
00028  * is preserved.
00029  * ====================================================
00030  */
00031 
00032 /* __ieee754_rem_pio2f(x,y)
00033  *
00034  * return the remainder of x rem pi/2 in y[0]+y[1]
00035  * use __kernel_rem_pio2f()
00036  */
00037 
00038 #ifdef POK_NEEDS_LIBMATH
00039 #include <libm.h>
00040 #include "math_private.h"
00041 
00042 /*
00043  * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
00044  */
00045 static const int32_t two_over_pi[] = {
00046 0xA2, 0xF9, 0x83, 0x6E, 0x4E, 0x44, 0x15, 0x29, 0xFC,
00047 0x27, 0x57, 0xD1, 0xF5, 0x34, 0xDD, 0xC0, 0xDB, 0x62,
00048 0x95, 0x99, 0x3C, 0x43, 0x90, 0x41, 0xFE, 0x51, 0x63,
00049 0xAB, 0xDE, 0xBB, 0xC5, 0x61, 0xB7, 0x24, 0x6E, 0x3A,
00050 0x42, 0x4D, 0xD2, 0xE0, 0x06, 0x49, 0x2E, 0xEA, 0x09,
00051 0xD1, 0x92, 0x1C, 0xFE, 0x1D, 0xEB, 0x1C, 0xB1, 0x29,
00052 0xA7, 0x3E, 0xE8, 0x82, 0x35, 0xF5, 0x2E, 0xBB, 0x44,
00053 0x84, 0xE9, 0x9C, 0x70, 0x26, 0xB4, 0x5F, 0x7E, 0x41,
00054 0x39, 0x91, 0xD6, 0x39, 0x83, 0x53, 0x39, 0xF4, 0x9C,
00055 0x84, 0x5F, 0x8B, 0xBD, 0xF9, 0x28, 0x3B, 0x1F, 0xF8,
00056 0x97, 0xFF, 0xDE, 0x05, 0x98, 0x0F, 0xEF, 0x2F, 0x11,
00057 0x8B, 0x5A, 0x0A, 0x6D, 0x1F, 0x6D, 0x36, 0x7E, 0xCF,
00058 0x27, 0xCB, 0x09, 0xB7, 0x4F, 0x46, 0x3F, 0x66, 0x9E,
00059 0x5F, 0xEA, 0x2D, 0x75, 0x27, 0xBA, 0xC7, 0xEB, 0xE5,
00060 0xF1, 0x7B, 0x3D, 0x07, 0x39, 0xF7, 0x8A, 0x52, 0x92,
00061 0xEA, 0x6B, 0xFB, 0x5F, 0xB1, 0x1F, 0x8D, 0x5D, 0x08,
00062 0x56, 0x03, 0x30, 0x46, 0xFC, 0x7B, 0x6B, 0xAB, 0xF0,
00063 0xCF, 0xBC, 0x20, 0x9A, 0xF4, 0x36, 0x1D, 0xA9, 0xE3,
00064 0x91, 0x61, 0x5E, 0xE6, 0x1B, 0x08, 0x65, 0x99, 0x85,
00065 0x5F, 0x14, 0xA0, 0x68, 0x40, 0x8D, 0xFF, 0xD8, 0x80,
00066 0x4D, 0x73, 0x27, 0x31, 0x06, 0x06, 0x15, 0x56, 0xCA,
00067 0x73, 0xA8, 0xC9, 0x60, 0xE2, 0x7B, 0xC0, 0x8C, 0x6B,
00068 };
00069 
00070 /* This array is like the one in e_rem_pio2.c, but the numbers are
00071    single precision and the last 8 bits are forced to 0.  */
00072 static const int32_t npio2_hw[] = {
00073 0x3fc90f00, 0x40490f00, 0x4096cb00, 0x40c90f00, 0x40fb5300, 0x4116cb00,
00074 0x412fed00, 0x41490f00, 0x41623100, 0x417b5300, 0x418a3a00, 0x4196cb00,
00075 0x41a35c00, 0x41afed00, 0x41bc7e00, 0x41c90f00, 0x41d5a000, 0x41e23100,
00076 0x41eec200, 0x41fb5300, 0x4203f200, 0x420a3a00, 0x42108300, 0x4216cb00,
00077 0x421d1400, 0x42235c00, 0x4229a500, 0x422fed00, 0x42363600, 0x423c7e00,
00078 0x4242c700, 0x42490f00
00079 };
00080 
00081 /*
00082  * invpio2:  24 bits of 2/pi
00083  * pio2_1:   first  17 bit of pi/2
00084  * pio2_1t:  pi/2 - pio2_1
00085  * pio2_2:   second 17 bit of pi/2
00086  * pio2_2t:  pi/2 - (pio2_1+pio2_2)
00087  * pio2_3:   third  17 bit of pi/2
00088  * pio2_3t:  pi/2 - (pio2_1+pio2_2+pio2_3)
00089  */
00090 
00091 static const float
00092 zero =  0.0000000000e+00, /* 0x00000000 */
00093 half =  5.0000000000e-01, /* 0x3f000000 */
00094 two8 =  2.5600000000e+02, /* 0x43800000 */
00095 invpio2 =  6.3661980629e-01, /* 0x3f22f984 */
00096 pio2_1  =  1.5707855225e+00, /* 0x3fc90f80 */
00097 pio2_1t =  1.0804334124e-05, /* 0x37354443 */
00098 pio2_2  =  1.0804273188e-05, /* 0x37354400 */
00099 pio2_2t =  6.0770999344e-11, /* 0x2e85a308 */
00100 pio2_3  =  6.0770943833e-11, /* 0x2e85a300 */
00101 pio2_3t =  6.1232342629e-17; /* 0x248d3132 */
00102 
00103 int32_t
00104 __ieee754_rem_pio2f(float x, float *y)
00105 {
00106         float z,w,t,r,fn;
00107         float tx[3];
00108         int32_t e0,i,j,nx,n,ix,hx;
00109 
00110         GET_FLOAT_WORD(hx,x);
00111         ix = hx&0x7fffffff;
00112         if(ix<=0x3f490fd8)   /* |x| ~<= pi/4 , no need for reduction */
00113             {y[0] = x; y[1] = 0; return 0;}
00114         if(ix<0x4016cbe4) {  /* |x| < 3pi/4, special case with n=+-1 */
00115             if(hx>0) {
00116                 z = x - pio2_1;
00117                 if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */
00118                     y[0] = z - pio2_1t;
00119                     y[1] = (z-y[0])-pio2_1t;
00120                 } else {                /* near pi/2, use 24+24+24 bit pi */
00121                     z -= pio2_2;
00122                     y[0] = z - pio2_2t;
00123                     y[1] = (z-y[0])-pio2_2t;
00124                 }
00125                 return 1;
00126             } else {    /* negative x */
00127                 z = x + pio2_1;
00128                 if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */
00129                     y[0] = z + pio2_1t;
00130                     y[1] = (z-y[0])+pio2_1t;
00131                 } else {                /* near pi/2, use 24+24+24 bit pi */
00132                     z += pio2_2;
00133                     y[0] = z + pio2_2t;
00134                     y[1] = (z-y[0])+pio2_2t;
00135                 }
00136                 return -1;
00137             }
00138         }
00139         if(ix<=0x43490f80) { /* |x| ~<= 2^7*(pi/2), medium size */
00140             t  = fabsf(x);
00141             n  = (int32_t) (t*invpio2+half);
00142             fn = (float)n;
00143             r  = t-fn*pio2_1;
00144             w  = fn*pio2_1t;    /* 1st round good to 40 bit */
00145             if(n<32&&(int32_t)(ix&0xffffff00)!=npio2_hw[n-1]) {
00146                 y[0] = r-w;     /* quick check no cancellation */
00147             } else {
00148                 uint32_t high;
00149                 j  = ix>>23;
00150                 y[0] = r-w;
00151                 GET_FLOAT_WORD(high,y[0]);
00152                 i = j-((high>>23)&0xff);
00153                 if(i>8) {  /* 2nd iteration needed, good to 57 */
00154                     t  = r;
00155                     w  = fn*pio2_2;
00156                     r  = t-w;
00157                     w  = fn*pio2_2t-((t-r)-w);
00158                     y[0] = r-w;
00159                     GET_FLOAT_WORD(high,y[0]);
00160                     i = j-((high>>23)&0xff);
00161                     if(i>25)  { /* 3rd iteration need, 74 bits acc */
00162                         t  = r; /* will cover all possible cases */
00163                         w  = fn*pio2_3;
00164                         r  = t-w;
00165                         w  = fn*pio2_3t-((t-r)-w);
00166                         y[0] = r-w;
00167                     }
00168                 }
00169             }
00170             y[1] = (r-y[0])-w;
00171             if(hx<0)    {y[0] = -y[0]; y[1] = -y[1]; return -n;}
00172             else         return n;
00173         }
00174     /*
00175      * all other (large) arguments
00176      */
00177         if(ix>=0x7f800000) {            /* x is inf or NaN */
00178             y[0]=y[1]=x-x; return 0;
00179         }
00180     /* set z = scalbn(|x|,ilogb(x)-7) */
00181         e0      = (ix>>23)-134;         /* e0 = ilogb(z)-7; */
00182         SET_FLOAT_WORD(z, ix - ((int32_t)(e0<<23)));
00183         for(i=0;i<2;i++) {
00184                 tx[i] = (float)((int32_t)(z));
00185                 z     = (z-tx[i])*two8;
00186         }
00187         tx[2] = z;
00188         nx = 3;
00189         while(tx[nx-1]==zero) nx--;     /* skip zero term */
00190         n  =  __kernel_rem_pio2f(tx,y,e0,nx,2,(int*)two_over_pi);
00191         if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
00192         return n;
00193 }
00194 #endif