xref: /inferno-os/libkern/log.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /*
2*37da2899SCharles.Forsyth 	log returns the natural logarithm of its floating
3*37da2899SCharles.Forsyth 	point argument.
4*37da2899SCharles.Forsyth 
5*37da2899SCharles.Forsyth 	The coefficients are #2705 from Hart & Cheney. (19.38D)
6*37da2899SCharles.Forsyth 
7*37da2899SCharles.Forsyth 	It calls frexp.
8*37da2899SCharles.Forsyth */
9*37da2899SCharles.Forsyth 
10*37da2899SCharles.Forsyth #include <lib9.h>
11*37da2899SCharles.Forsyth 
12*37da2899SCharles.Forsyth #define	log2    0.693147180559945309e0
13*37da2899SCharles.Forsyth #define	ln10o1  .4342944819032518276511
14*37da2899SCharles.Forsyth #define	sqrto2  0.707106781186547524e0
15*37da2899SCharles.Forsyth #define	p0      -.240139179559210510e2
16*37da2899SCharles.Forsyth #define	p1      0.309572928215376501e2
17*37da2899SCharles.Forsyth #define	p2      -.963769093377840513e1
18*37da2899SCharles.Forsyth #define	p3      0.421087371217979714e0
19*37da2899SCharles.Forsyth #define	q0      -.120069589779605255e2
20*37da2899SCharles.Forsyth #define	q1      0.194809660700889731e2
21*37da2899SCharles.Forsyth #define	q2      -.891110902798312337e1
22*37da2899SCharles.Forsyth 
23*37da2899SCharles.Forsyth double
log(double arg)24*37da2899SCharles.Forsyth log(double arg)
25*37da2899SCharles.Forsyth {
26*37da2899SCharles.Forsyth 	double x, z, zsq, temp;
27*37da2899SCharles.Forsyth 	int exp;
28*37da2899SCharles.Forsyth 
29*37da2899SCharles.Forsyth 	if(arg <= 0)
30*37da2899SCharles.Forsyth 		return NaN();
31*37da2899SCharles.Forsyth 	x = frexp(arg, &exp);
32*37da2899SCharles.Forsyth 	while(x < 0.5) {
33*37da2899SCharles.Forsyth 		x *= 2;
34*37da2899SCharles.Forsyth 		exp--;
35*37da2899SCharles.Forsyth 	}
36*37da2899SCharles.Forsyth 	if(x < sqrto2) {
37*37da2899SCharles.Forsyth 		x *= 2;
38*37da2899SCharles.Forsyth 		exp--;
39*37da2899SCharles.Forsyth 	}
40*37da2899SCharles.Forsyth 
41*37da2899SCharles.Forsyth 	z = (x-1) / (x+1);
42*37da2899SCharles.Forsyth 	zsq = z*z;
43*37da2899SCharles.Forsyth 
44*37da2899SCharles.Forsyth 	temp = ((p3*zsq + p2)*zsq + p1)*zsq + p0;
45*37da2899SCharles.Forsyth 	temp = temp/(((zsq + q2)*zsq + q1)*zsq + q0);
46*37da2899SCharles.Forsyth 	temp = temp*z + exp*log2;
47*37da2899SCharles.Forsyth 	return temp;
48*37da2899SCharles.Forsyth }
49*37da2899SCharles.Forsyth 
50*37da2899SCharles.Forsyth double
log10(double arg)51*37da2899SCharles.Forsyth log10(double arg)
52*37da2899SCharles.Forsyth {
53*37da2899SCharles.Forsyth 
54*37da2899SCharles.Forsyth 	if(arg <= 0)
55*37da2899SCharles.Forsyth 		return NaN();
56*37da2899SCharles.Forsyth 	return log(arg) * ln10o1;
57*37da2899SCharles.Forsyth }
58