/* @(#)e_log.c 1.3 95/01/18 */
/*
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
* Copyright ( C ) 1993 by Sun Microsystems , Inc . All rights reserved .
*
* Developed at SunSoft , a Sun Microsystems , Inc . business .
* Permission to use , copy , modify , and distribute this
* software is freely granted , provided that this notice
* is preserved .
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
//#include <sys/cdefs.h>
//__FBSDID("$FreeBSD$");
/* __ieee754_log(x)
* Return the logrithm of x
*
* Method :
* 1 . Argument Reduction : find k and f such that
* x = 2 ^ k * ( 1 + f ) ,
* where sqrt ( 2 ) / 2 < 1 + f < sqrt ( 2 ) .
*
* 2 . Approximation of log ( 1 + f ) .
* Let s = f / ( 2 + f ) ; based on log ( 1 + f ) = log ( 1 + s ) - log ( 1 - s )
* = 2 s + 2 / 3 s * * 3 + 2 / 5 s * * 5 + . . . . . ,
* = 2 s + s * R
* We use a special Reme algorithm on [ 0 , 0 . 1716 ] to generate
* a polynomial of degree 14 to approximate R The maximum error
* of this polynomial approximation is bounded by 2 * * - 58 . 45 . In
* other words ,
* 2 4 6 8 10 12 14
* R ( z ) ~ Lg1 * s + Lg2 * s + Lg3 * s + Lg4 * s + Lg5 * s + Lg6 * s + Lg7 * s
* ( the values of Lg1 to Lg7 are listed in the program )
* and
* | 2 14 | - 58 . 45
* | Lg1 * s + . . . + Lg7 * s - R ( z ) | < = 2
* | |
* Note that 2 s = f - s * f = f - hfsq + s * hfsq , where hfsq = f * f / 2 .
* In order to guarantee error in log below 1 ulp , we compute log
* by
* log ( 1 + f ) = f - s * ( f - R ) ( if f is not too large )
* log ( 1 + f ) = f - ( hfsq - s * ( hfsq + R ) ) . ( better accuracy )
*
* 3 . Finally , log ( x ) = k * ln2 + log ( 1 + f ) .
* = k * ln2_hi + ( f - ( hfsq - ( s * ( hfsq + R ) + k * ln2_lo ) ) )
* Here ln2 is split into two floating point number :
* ln2_hi + ln2_lo ,
* where n * ln2_hi is always exact for | n | < 2000 .
*
* Special cases :
* log ( x ) is NaN with signal if x < 0 ( including - INF ) ;
* log ( + INF ) is + INF ; log ( 0 ) is - INF with signal ;
* log ( NaN ) is that NaN with no signal .
*
* Accuracy :
* according to an error analysis , the error is always less than
* 1 ulp ( unit in the last place ) .
*
* Constants :
* The hexadecimal values are the intended ones for the following
* constants . The decimal values may be used , provided that the
* compiler will convert from decimal to binary accurately enough
* to produce the hexadecimal values shown .
*/
#include <float .h>
#include "math_private.h"
static const double
ln2_hi = 6 .93147180369123816490 e-01 , /* 3fe62e42 fee00000 */
ln2_lo = 1 .90821492927058770002 e-10 , /* 3dea39ef 35793c76 */
two54 = 1 .80143985094819840000 e+16 , /* 43500000 00000000 */
Lg1 = 6 .666666666666735130 e-01 , /* 3FE55555 55555593 */
Lg2 = 3 .999999999940941908 e-01 , /* 3FD99999 9997FA04 */
Lg3 = 2 .857142874366239149 e-01 , /* 3FD24924 94229359 */
Lg4 = 2 .222219843214978396 e-01 , /* 3FCC71C5 1D8E78AF */
Lg5 = 1 .818357216161805012 e-01 , /* 3FC74664 96CB03DE */
Lg6 = 1 .531383769920937332 e-01 , /* 3FC39A09 D078C69F */
Lg7 = 1 .479819860511658591 e-01 ; /* 3FC2F112 DF3E5244 */
static const double zero = 0 .0 ;
static volatile double vzero = 0 .0 ;
double
__ieee754_log(double x)
{
double hfsq,f,s,z,R,w,t1,t2,dk;
int32_t k,hx,i,j;
u_int32_t lx;
EXTRACT_WORDS(hx,lx,x);
k=0 ;
if (hx < 0 x00100000) { /* x < 2**-1022 */
if (((hx&0 x7fffffff)|lx)==0 )
return -two54/vzero; /* log(+-0)=-inf */
if (hx<0 ) return (x-x)/zero; /* log(-#) = NaN */
k -= 54 ; x *= two54; /* subnormal number, scale up x */
GET_HIGH_WORD(hx,x);
}
if (hx >= 0 x7ff00000) return x+x;
k += (hx>>20 )-1023 ;
hx &= 0 x000fffff;
i = (hx+0 x95f64)&0 x100000;
SET_HIGH_WORD(x,hx|(i^0 x3ff00000)); /* normalize x or x/2 */
k += (i>>20 );
f = x-1 .0 ;
if ((0 x000fffff&(2 +hx))<3 ) { /* -2**-20 <= f < 2**-20 */
if (f==zero) {
if (k==0 ) {
return zero;
} else {
dk=(double )k;
return dk*ln2_hi+dk*ln2_lo;
}
}
R = f*f*(0 .5 -0 .33333333333333333 *f);
if (k==0 ) return f-R; else {dk=(double )k;
return dk*ln2_hi-((R-dk*ln2_lo)-f);}
}
s = f/(2 .0 +f);
dk = (double )k;
z = s*s;
i = hx-0 x6147a;
w = z*z;
j = 0 x6b851-hx;
t1= w*(Lg2+w*(Lg4+w*Lg6));
t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7)));
i |= j;
R = t2+t1;
if (i>0 ) {
hfsq=0 .5 *f*f;
if (k==0 ) return f-(hfsq-s*(hfsq+R)); else
return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f);
} else {
if (k==0 ) return f-s*(f-R); else
return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f);
}
}
Messung V0.5 in Prozent C=86 H=100 G=93
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-08-24)
¤
*© Formatika GbR, Deutschland