POK
log1pf.c
1 /*
2  * POK header
3  *
4  * The following file is a part of the POK project. Any modification should
5  * made according to the POK licence. You CANNOT use this file or a part of
6  * this file is this part of a file for your own project
7  *
8  * For more information on the POK licence, please see our LICENCE FILE
9  *
10  * Please follow the coding guidelines described in doc/CODING_GUIDELINES
11  *
12  * Copyright (c) 2007-2009 POK team
13  *
14  * Created by julien on Fri Jan 30 14:41:34 2009
15  */
16 
17 /* s_log1pf.c -- float version of s_log1p.c.
18  * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
19  */
20 
21 /*
22  * ====================================================
23  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
24  *
25  * Developed at SunPro, a Sun Microsystems, Inc. business.
26  * Permission to use, copy, modify, and distribute this
27  * software is freely granted, provided that this notice
28  * is preserved.
29  * ====================================================
30  */
31 
32 #ifdef POK_NEEDS_LIBMATH
33 
34 #include <types.h>
35 #include "math_private.h"
36 
37 static const float
38 ln2_hi = 6.9313812256e-01, /* 0x3f317180 */
39 ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */
40 two25 = 3.355443200e+07, /* 0x4c000000 */
41 Lp1 = 6.6666668653e-01, /* 3F2AAAAB */
42 Lp2 = 4.0000000596e-01, /* 3ECCCCCD */
43 Lp3 = 2.8571429849e-01, /* 3E924925 */
44 Lp4 = 2.2222198546e-01, /* 3E638E29 */
45 Lp5 = 1.8183572590e-01, /* 3E3A3325 */
46 Lp6 = 1.5313838422e-01, /* 3E1CD04F */
47 Lp7 = 1.4798198640e-01; /* 3E178897 */
48 
49 static const float zero = 0.0;
50 
51 float
52 log1pf(float x)
53 {
54  float hfsq,f,c,s,z,R,u;
55  int32_t k,hx,hu,ax;
56 
57  f = c = 0;
58  hu = 0;
59  GET_FLOAT_WORD(hx,x);
60  ax = hx&0x7fffffff;
61 
62  k = 1;
63  if (hx < 0x3ed413d7) { /* x < 0.41422 */
64  if(ax>=0x3f800000) { /* x <= -1.0 */
65  if(x==(float)-1.0) return -two25/zero; /* log1p(-1)=+inf */
66  else return (x-x)/(x-x); /* log1p(x<-1)=NaN */
67  }
68  if(ax<0x31000000) { /* |x| < 2**-29 */
69  if(two25+x>zero /* raise inexact */
70  &&ax<0x24800000) /* |x| < 2**-54 */
71  return x;
72  else
73  return x - x*x*(float)0.5;
74  }
75  if(hx>0||hx<=((int32_t)0xbe95f61f)) {
76  k=0;f=x;hu=1;} /* -0.2929<x<0.41422 */
77  }
78  if (hx >= 0x7f800000) return x+x;
79  if(k!=0) {
80  if(hx<0x5a000000) {
81  u = (float)1.0+x;
82  GET_FLOAT_WORD(hu,u);
83  k = (hu>>23)-127;
84  /* correction term */
85  c = (k>0)? (float)1.0-(u-x):x-(u-(float)1.0);
86  c /= u;
87  } else {
88  u = x;
89  GET_FLOAT_WORD(hu,u);
90  k = (hu>>23)-127;
91  c = 0;
92  }
93  hu &= 0x007fffff;
94  if(hu<0x3504f7) {
95  SET_FLOAT_WORD(u,hu|0x3f800000);/* normalize u */
96  } else {
97  k += 1;
98  SET_FLOAT_WORD(u,hu|0x3f000000); /* normalize u/2 */
99  hu = (0x00800000-hu)>>2;
100  }
101  f = u-(float)1.0;
102  }
103  hfsq=(float)0.5*f*f;
104  if(hu==0) { /* |f| < 2**-20 */
105  if(f==zero) { if(k==0) return zero;
106  else {c += k*ln2_lo; return k*ln2_hi+c;}
107  }
108  R = hfsq*((float)1.0-(float)0.66666666666666666*f);
109  if(k==0) return f-R; else
110  return k*ln2_hi-((R-(k*ln2_lo+c))-f);
111  }
112  s = f/((float)2.0+f);
113  z = s*s;
114  R = z*(Lp1+z*(Lp2+z*(Lp3+z*(Lp4+z*(Lp5+z*(Lp6+z*Lp7))))));
115  if(k==0) return f-(hfsq-s*(hfsq+R)); else
116  return k*ln2_hi-((hfsq-(s*(hfsq+R)+(k*ln2_lo+c)))-f);
117 }
118 
119 #endif
120