/* @(#)e_log10.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$");
/*
* Return the base 2 logarithm of x . See e_log . c and k_log . h for most
* comments .
*
* This reduces x to { k , 1 + f } exactly as in e_log . c , then calls the kernel ,
* then does the combining and scaling steps
* log2 ( x ) = ( f - 0 . 5 * f * f + k_log1p ( f ) ) / ln2 + k
* in not - quite - routine extra precision .
*/
#include <float .h>
#include "math_private.h"
#include "k_log.h"
static const double
two54 = 1 .80143985094819840000 e+16 , /* 0x43500000, 0x00000000 */
ivln2hi = 1 .44269504072144627571 e+00 , /* 0x3ff71547, 0x65200000 */
ivln2lo = 1 .67517131648865118353 e-10 ; /* 0x3de705fc, 0x2eefa200 */
static const double zero = 0 .0 ;
static volatile double vzero = 0 .0 ;
double
__ieee754_log2(double x)
{
double f,hfsq,hi,lo,r,val_hi,val_lo,w,y;
int32_t i,k,hx;
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;
if (hx == 0 x3ff00000 && lx == 0 )
return zero; /* log(1) = +0 */
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 );
y = (double )k;
f = x - 1 .0 ;
hfsq = 0 .5 *f*f;
r = k_log1p(f);
/*
* f - hfsq must ( for args near 1 ) be evaluated in extra precision
* to avoid a large cancellation when x is near sqrt ( 2 ) or 1 / sqrt ( 2 ) .
* This is fairly efficient since f - hfsq only depends on f , so can
* be evaluated in parallel with R . Not combining hfsq with R also
* keeps R small ( though not as small as a true ` lo ' term would be ) ,
* so that extra precision is not needed for terms involving R .
*
* Compiler bugs involving extra precision used to break Dekker ' s
* theorem for spitting f - hfsq as hi + lo , unless double_t was used
* or the multi - precision calculations were avoided when double_t
* has extra precision . These problems are now automatically
* avoided as a side effect of the optimization of combining the
* Dekker splitting step with the clear - low - bits step .
*
* y must ( for args near sqrt ( 2 ) and 1 / sqrt ( 2 ) ) be added in extra
* precision to avoid a very large cancellation when x is very near
* these values . Unlike the above cancellations , this problem is
* specific to base 2 . It is strange that adding + - 1 is so much
* harder than adding + - ln2 or + - log10_2 .
*
* This uses Dekker ' s theorem to normalize y + val_hi , so the
* compiler bugs are back in some configurations , sigh . And I
* don ' t want to used double_t to avoid them , since that gives a
* pessimization and the support for avoiding the pessimization
* is not yet available .
*
* The multi - precision calculations for the multiplications are
* routine .
*/
hi = f - hfsq;
SET_LOW_WORD(hi,0 );
lo = (f - hi) - hfsq + r;
val_hi = hi*ivln2hi;
val_lo = (lo+hi)*ivln2lo + lo*ivln2hi;
/* spadd(val_hi, val_lo, y), except for not using double_t: */
w = y + val_hi;
val_lo += (y - w) + val_hi;
val_hi = w;
return val_lo + val_hi;
}
Messung V0.5 in Prozent C=86 H=100 G=93
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-08-26)
¤
*© Formatika GbR, Deutschland