1 |
|
|
/* $OpenBSD: e_log2l.c,v 1.3 2017/01/21 08:29:13 krw Exp $ */ |
2 |
|
|
|
3 |
|
|
/* |
4 |
|
|
* Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net> |
5 |
|
|
* |
6 |
|
|
* Permission to use, copy, modify, and distribute this software for any |
7 |
|
|
* purpose with or without fee is hereby granted, provided that the above |
8 |
|
|
* copyright notice and this permission notice appear in all copies. |
9 |
|
|
* |
10 |
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
11 |
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
12 |
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
13 |
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
14 |
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
15 |
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
16 |
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
17 |
|
|
*/ |
18 |
|
|
|
19 |
|
|
/* log2l.c |
20 |
|
|
* |
21 |
|
|
* Base 2 logarithm, long double precision |
22 |
|
|
* |
23 |
|
|
* |
24 |
|
|
* |
25 |
|
|
* SYNOPSIS: |
26 |
|
|
* |
27 |
|
|
* long double x, y, log2l(); |
28 |
|
|
* |
29 |
|
|
* y = log2l( x ); |
30 |
|
|
* |
31 |
|
|
* |
32 |
|
|
* |
33 |
|
|
* DESCRIPTION: |
34 |
|
|
* |
35 |
|
|
* Returns the base 2 logarithm of x. |
36 |
|
|
* |
37 |
|
|
* The argument is separated into its exponent and fractional |
38 |
|
|
* parts. If the exponent is between -1 and +1, the (natural) |
39 |
|
|
* logarithm of the fraction is approximated by |
40 |
|
|
* |
41 |
|
|
* log(1+x) = x - 0.5 x**2 + x**3 P(x)/Q(x). |
42 |
|
|
* |
43 |
|
|
* Otherwise, setting z = 2(x-1)/x+1), |
44 |
|
|
* |
45 |
|
|
* log(x) = z + z**3 P(z)/Q(z). |
46 |
|
|
* |
47 |
|
|
* |
48 |
|
|
* |
49 |
|
|
* ACCURACY: |
50 |
|
|
* |
51 |
|
|
* Relative error: |
52 |
|
|
* arithmetic domain # trials peak rms |
53 |
|
|
* IEEE 0.5, 2.0 30000 9.8e-20 2.7e-20 |
54 |
|
|
* IEEE exp(+-10000) 70000 5.4e-20 2.3e-20 |
55 |
|
|
* |
56 |
|
|
* In the tests over the interval exp(+-10000), the logarithms |
57 |
|
|
* of the random arguments were uniformly distributed over |
58 |
|
|
* [-10000, +10000]. |
59 |
|
|
* |
60 |
|
|
* ERROR MESSAGES: |
61 |
|
|
* |
62 |
|
|
* log singularity: x = 0; returns -INFINITY |
63 |
|
|
* log domain: x < 0; returns NAN |
64 |
|
|
*/ |
65 |
|
|
|
66 |
|
|
#include <math.h> |
67 |
|
|
|
68 |
|
|
#include "math_private.h" |
69 |
|
|
|
70 |
|
|
/* Coefficients for ln(1+x) = x - x**2/2 + x**3 P(x)/Q(x) |
71 |
|
|
* 1/sqrt(2) <= x < sqrt(2) |
72 |
|
|
* Theoretical peak relative error = 6.2e-22 |
73 |
|
|
*/ |
74 |
|
|
static long double P[] = { |
75 |
|
|
4.9962495940332550844739E-1L, |
76 |
|
|
1.0767376367209449010438E1L, |
77 |
|
|
7.7671073698359539859595E1L, |
78 |
|
|
2.5620629828144409632571E2L, |
79 |
|
|
4.2401812743503691187826E2L, |
80 |
|
|
3.4258224542413922935104E2L, |
81 |
|
|
1.0747524399916215149070E2L, |
82 |
|
|
}; |
83 |
|
|
static long double Q[] = { |
84 |
|
|
/* 1.0000000000000000000000E0,*/ |
85 |
|
|
2.3479774160285863271658E1L, |
86 |
|
|
1.9444210022760132894510E2L, |
87 |
|
|
7.7952888181207260646090E2L, |
88 |
|
|
1.6911722418503949084863E3L, |
89 |
|
|
2.0307734695595183428202E3L, |
90 |
|
|
1.2695660352705325274404E3L, |
91 |
|
|
3.2242573199748645407652E2L, |
92 |
|
|
}; |
93 |
|
|
|
94 |
|
|
/* Coefficients for log(x) = z + z^3 P(z^2)/Q(z^2), |
95 |
|
|
* where z = 2(x-1)/(x+1) |
96 |
|
|
* 1/sqrt(2) <= x < sqrt(2) |
97 |
|
|
* Theoretical peak relative error = 6.16e-22 |
98 |
|
|
*/ |
99 |
|
|
static long double R[4] = { |
100 |
|
|
1.9757429581415468984296E-3L, |
101 |
|
|
-7.1990767473014147232598E-1L, |
102 |
|
|
1.0777257190312272158094E1L, |
103 |
|
|
-3.5717684488096787370998E1L, |
104 |
|
|
}; |
105 |
|
|
static long double S[4] = { |
106 |
|
|
/* 1.00000000000000000000E0L,*/ |
107 |
|
|
-2.6201045551331104417768E1L, |
108 |
|
|
1.9361891836232102174846E2L, |
109 |
|
|
-4.2861221385716144629696E2L, |
110 |
|
|
}; |
111 |
|
|
/* log2(e) - 1 */ |
112 |
|
|
#define LOG2EA 4.4269504088896340735992e-1L |
113 |
|
|
|
114 |
|
|
#define SQRTH 0.70710678118654752440L |
115 |
|
|
|
116 |
|
|
long double |
117 |
|
|
log2l(long double x) |
118 |
|
|
{ |
119 |
|
|
volatile long double z; |
120 |
|
|
long double y; |
121 |
|
|
int e; |
122 |
|
|
|
123 |
|
|
if( isnan(x) ) |
124 |
|
|
return(x); |
125 |
|
|
if( x == INFINITY ) |
126 |
|
|
return(x); |
127 |
|
|
/* Test for domain */ |
128 |
|
|
if( x <= 0.0L ) |
129 |
|
|
{ |
130 |
|
|
if( x == 0.0L ) |
131 |
|
|
return( -INFINITY ); |
132 |
|
|
else |
133 |
|
|
return( NAN ); |
134 |
|
|
} |
135 |
|
|
|
136 |
|
|
/* separate mantissa from exponent */ |
137 |
|
|
|
138 |
|
|
/* Note, frexp is used so that denormal numbers |
139 |
|
|
* will be handled properly. |
140 |
|
|
*/ |
141 |
|
|
x = frexpl( x, &e ); |
142 |
|
|
|
143 |
|
|
|
144 |
|
|
/* logarithm using log(x) = z + z**3 P(z)/Q(z), |
145 |
|
|
* where z = 2(x-1)/x+1) |
146 |
|
|
*/ |
147 |
|
|
if( (e > 2) || (e < -2) ) |
148 |
|
|
{ |
149 |
|
|
if( x < SQRTH ) |
150 |
|
|
{ /* 2( 2x-1 )/( 2x+1 ) */ |
151 |
|
|
e -= 1; |
152 |
|
|
z = x - 0.5L; |
153 |
|
|
y = 0.5L * z + 0.5L; |
154 |
|
|
} |
155 |
|
|
else |
156 |
|
|
{ /* 2 (x-1)/(x+1) */ |
157 |
|
|
z = x - 0.5L; |
158 |
|
|
z -= 0.5L; |
159 |
|
|
y = 0.5L * x + 0.5L; |
160 |
|
|
} |
161 |
|
|
x = z / y; |
162 |
|
|
z = x*x; |
163 |
|
|
y = x * ( z * __polevll( z, R, 3 ) / __p1evll( z, S, 3 ) ); |
164 |
|
|
goto done; |
165 |
|
|
} |
166 |
|
|
|
167 |
|
|
|
168 |
|
|
/* logarithm using log(1+x) = x - .5x**2 + x**3 P(x)/Q(x) */ |
169 |
|
|
|
170 |
|
|
if( x < SQRTH ) |
171 |
|
|
{ |
172 |
|
|
e -= 1; |
173 |
|
|
x = ldexpl( x, 1 ) - 1.0L; /* 2x - 1 */ |
174 |
|
|
} |
175 |
|
|
else |
176 |
|
|
{ |
177 |
|
|
x = x - 1.0L; |
178 |
|
|
} |
179 |
|
|
z = x*x; |
180 |
|
|
y = x * ( z * __polevll( x, P, 6 ) / __p1evll( x, Q, 7 ) ); |
181 |
|
|
y = y - ldexpl( z, -1 ); /* -0.5x^2 + ... */ |
182 |
|
|
|
183 |
|
|
done: |
184 |
|
|
|
185 |
|
|
/* Multiply log of fraction by log2(e) |
186 |
|
|
* and base 2 exponent by 1 |
187 |
|
|
* |
188 |
|
|
* ***CAUTION*** |
189 |
|
|
* |
190 |
|
|
* This sequence of operations is critical and it may |
191 |
|
|
* be horribly defeated by some compiler optimizers. |
192 |
|
|
*/ |
193 |
|
|
z = y * LOG2EA; |
194 |
|
|
z += x * LOG2EA; |
195 |
|
|
z += y; |
196 |
|
|
z += x; |
197 |
|
|
z += e; |
198 |
|
|
return( z ); |
199 |
|
|
} |