POK
/home/jaouen/pok_official/pok/trunk/libpok/libm/log1pf.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 /* s_log1pf.c -- float version of s_log1p.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 #ifdef POK_NEEDS_LIBMATH
00033 
00034 #include <types.h>
00035 #include "math_private.h"
00036 
00037 static const float
00038 ln2_hi =   6.9313812256e-01,    /* 0x3f317180 */
00039 ln2_lo =   9.0580006145e-06,    /* 0x3717f7d1 */
00040 two25 =    3.355443200e+07,     /* 0x4c000000 */
00041 Lp1 = 6.6666668653e-01, /* 3F2AAAAB */
00042 Lp2 = 4.0000000596e-01, /* 3ECCCCCD */
00043 Lp3 = 2.8571429849e-01, /* 3E924925 */
00044 Lp4 = 2.2222198546e-01, /* 3E638E29 */
00045 Lp5 = 1.8183572590e-01, /* 3E3A3325 */
00046 Lp6 = 1.5313838422e-01, /* 3E1CD04F */
00047 Lp7 = 1.4798198640e-01; /* 3E178897 */
00048 
00049 static const float zero = 0.0;
00050 
00051 float
00052 log1pf(float x)
00053 {
00054         float hfsq,f,c,s,z,R,u;
00055         int32_t k,hx,hu,ax;
00056 
00057         f = c = 0;
00058         hu = 0;
00059         GET_FLOAT_WORD(hx,x);
00060         ax = hx&0x7fffffff;
00061 
00062         k = 1;
00063         if (hx < 0x3ed413d7) {                  /* x < 0.41422  */
00064             if(ax>=0x3f800000) {                /* x <= -1.0 */
00065                 if(x==(float)-1.0) return -two25/zero; /* log1p(-1)=+inf */
00066                 else return (x-x)/(x-x);        /* log1p(x<-1)=NaN */
00067             }
00068             if(ax<0x31000000) {                 /* |x| < 2**-29 */
00069                 if(two25+x>zero                 /* raise inexact */
00070                     &&ax<0x24800000)            /* |x| < 2**-54 */
00071                     return x;
00072                 else
00073                     return x - x*x*(float)0.5;
00074             }
00075             if(hx>0||hx<=((int32_t)0xbe95f61f)) {
00076                 k=0;f=x;hu=1;}  /* -0.2929<x<0.41422 */
00077         }
00078         if (hx >= 0x7f800000) return x+x;
00079         if(k!=0) {
00080             if(hx<0x5a000000) {
00081                 u  = (float)1.0+x;
00082                 GET_FLOAT_WORD(hu,u);
00083                 k  = (hu>>23)-127;
00084                 /* correction term */
00085                 c  = (k>0)? (float)1.0-(u-x):x-(u-(float)1.0);
00086                 c /= u;
00087             } else {
00088                 u  = x;
00089                 GET_FLOAT_WORD(hu,u);
00090                 k  = (hu>>23)-127;
00091                 c  = 0;
00092             }
00093             hu &= 0x007fffff;
00094             if(hu<0x3504f7) {
00095                 SET_FLOAT_WORD(u,hu|0x3f800000);/* normalize u */
00096             } else {
00097                 k += 1;
00098                 SET_FLOAT_WORD(u,hu|0x3f000000);        /* normalize u/2 */
00099                 hu = (0x00800000-hu)>>2;
00100             }
00101             f = u-(float)1.0;
00102         }
00103         hfsq=(float)0.5*f*f;
00104         if(hu==0) {     /* |f| < 2**-20 */
00105             if(f==zero) { if(k==0) return zero;
00106                           else {c += k*ln2_lo; return k*ln2_hi+c;}
00107             }
00108             R = hfsq*((float)1.0-(float)0.66666666666666666*f);
00109             if(k==0) return f-R; else
00110                      return k*ln2_hi-((R-(k*ln2_lo+c))-f);
00111         }
00112         s = f/((float)2.0+f);
00113         z = s*s;
00114         R = z*(Lp1+z*(Lp2+z*(Lp3+z*(Lp4+z*(Lp5+z*(Lp6+z*Lp7))))));
00115         if(k==0) return f-(hfsq-s*(hfsq+R)); else
00116                  return k*ln2_hi-((hfsq-(s*(hfsq+R)+(k*ln2_lo+c)))-f);
00117 }
00118 
00119 #endif
00120