1 |
|
|
/* $OpenBSD: e_log10l.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 |
|
|
/* log10l.c |
20 |
|
|
* |
21 |
|
|
* Common logarithm, long double precision |
22 |
|
|
* |
23 |
|
|
* |
24 |
|
|
* |
25 |
|
|
* SYNOPSIS: |
26 |
|
|
* |
27 |
|
|
* long double x, y, log10l(); |
28 |
|
|
* |
29 |
|
|
* y = log10l( x ); |
30 |
|
|
* |
31 |
|
|
* |
32 |
|
|
* |
33 |
|
|
* DESCRIPTION: |
34 |
|
|
* |
35 |
|
|
* Returns the base 10 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 logarithm |
39 |
|
|
* 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.0e-20 2.6e-20 |
54 |
|
|
* IEEE exp(+-10000) 30000 6.0e-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 MINLOG |
63 |
|
|
* log domain: x < 0; returns MINLOG |
64 |
|
|
*/ |
65 |
|
|
|
66 |
|
|
#include <math.h> |
67 |
|
|
|
68 |
|
|
#include "math_private.h" |
69 |
|
|
|
70 |
|
|
/* Coefficients for log(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 |
|
|
|
100 |
|
|
static long double R[4] = { |
101 |
|
|
1.9757429581415468984296E-3L, |
102 |
|
|
-7.1990767473014147232598E-1L, |
103 |
|
|
1.0777257190312272158094E1L, |
104 |
|
|
-3.5717684488096787370998E1L, |
105 |
|
|
}; |
106 |
|
|
static long double S[4] = { |
107 |
|
|
/* 1.00000000000000000000E0L,*/ |
108 |
|
|
-2.6201045551331104417768E1L, |
109 |
|
|
1.9361891836232102174846E2L, |
110 |
|
|
-4.2861221385716144629696E2L, |
111 |
|
|
}; |
112 |
|
|
/* log10(2) */ |
113 |
|
|
#define L102A 0.3125L |
114 |
|
|
#define L102B -1.1470004336018804786261e-2L |
115 |
|
|
/* log10(e) */ |
116 |
|
|
#define L10EA 0.5L |
117 |
|
|
#define L10EB -6.5705518096748172348871e-2L |
118 |
|
|
|
119 |
|
|
#define SQRTH 0.70710678118654752440L |
120 |
|
|
|
121 |
|
|
long double |
122 |
|
|
log10l(long double x) |
123 |
|
|
{ |
124 |
|
|
long double y; |
125 |
|
|
volatile long double z; |
126 |
|
|
int e; |
127 |
|
|
|
128 |
|
|
if( isnan(x) ) |
129 |
|
|
return(x); |
130 |
|
|
/* Test for domain */ |
131 |
|
|
if( x <= 0.0L ) |
132 |
|
|
{ |
133 |
|
|
if( x == 0.0L ) |
134 |
|
|
return (-1.0L / (x - x)); |
135 |
|
|
else |
136 |
|
|
return (x - x) / (x - x); |
137 |
|
|
} |
138 |
|
|
if( x == INFINITY ) |
139 |
|
|
return(INFINITY); |
140 |
|
|
/* separate mantissa from exponent */ |
141 |
|
|
|
142 |
|
|
/* Note, frexp is used so that denormal numbers |
143 |
|
|
* will be handled properly. |
144 |
|
|
*/ |
145 |
|
|
x = frexpl( x, &e ); |
146 |
|
|
|
147 |
|
|
|
148 |
|
|
/* logarithm using log(x) = z + z**3 P(z)/Q(z), |
149 |
|
|
* where z = 2(x-1)/x+1) |
150 |
|
|
*/ |
151 |
|
|
if( (e > 2) || (e < -2) ) |
152 |
|
|
{ |
153 |
|
|
if( x < SQRTH ) |
154 |
|
|
{ /* 2( 2x-1 )/( 2x+1 ) */ |
155 |
|
|
e -= 1; |
156 |
|
|
z = x - 0.5L; |
157 |
|
|
y = 0.5L * z + 0.5L; |
158 |
|
|
} |
159 |
|
|
else |
160 |
|
|
{ /* 2 (x-1)/(x+1) */ |
161 |
|
|
z = x - 0.5L; |
162 |
|
|
z -= 0.5L; |
163 |
|
|
y = 0.5L * x + 0.5L; |
164 |
|
|
} |
165 |
|
|
x = z / y; |
166 |
|
|
z = x*x; |
167 |
|
|
y = x * ( z * __polevll( z, R, 3 ) / __p1evll( z, S, 3 ) ); |
168 |
|
|
goto done; |
169 |
|
|
} |
170 |
|
|
|
171 |
|
|
|
172 |
|
|
/* logarithm using log(1+x) = x - .5x**2 + x**3 P(x)/Q(x) */ |
173 |
|
|
|
174 |
|
|
if( x < SQRTH ) |
175 |
|
|
{ |
176 |
|
|
e -= 1; |
177 |
|
|
x = ldexpl( x, 1 ) - 1.0L; /* 2x - 1 */ |
178 |
|
|
} |
179 |
|
|
else |
180 |
|
|
{ |
181 |
|
|
x = x - 1.0L; |
182 |
|
|
} |
183 |
|
|
z = x*x; |
184 |
|
|
y = x * ( z * __polevll( x, P, 6 ) / __p1evll( x, Q, 7 ) ); |
185 |
|
|
y = y - ldexpl( z, -1 ); /* -0.5x^2 + ... */ |
186 |
|
|
|
187 |
|
|
done: |
188 |
|
|
|
189 |
|
|
/* Multiply log of fraction by log10(e) |
190 |
|
|
* and base 2 exponent by log10(2). |
191 |
|
|
* |
192 |
|
|
* ***CAUTION*** |
193 |
|
|
* |
194 |
|
|
* This sequence of operations is critical and it may |
195 |
|
|
* be horribly defeated by some compiler optimizers. |
196 |
|
|
*/ |
197 |
|
|
z = y * (L10EB); |
198 |
|
|
z += x * (L10EB); |
199 |
|
|
z += e * (L102B); |
200 |
|
|
z += y * (L10EA); |
201 |
|
|
z += x * (L10EA); |
202 |
|
|
z += e * (L102A); |
203 |
|
|
|
204 |
|
|
return( z ); |
205 |
|
|
} |