/* origin: FreeBSD /usr/src/lib/msun/src/s_log1p.c */
/*
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
* Copyright ( C ) 1993 by Sun Microsystems , Inc . All rights reserved .
*
* Developed at SunPro , a Sun Microsystems , Inc . business .
* Permission to use , copy , modify , and distribute this
* software is freely granted , provided that this notice
* is preserved .
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
/* double log1p(double x)
* Return the natural logarithm of 1 + x .
*
* Method :
* 1 . Argument Reduction : find k and f such that
* 1 + x = 2 ^ k * ( 1 + f ) ,
* where sqrt ( 2 ) / 2 < 1 + f < sqrt ( 2 ) .
*
* Note . If k = 0 , then f = x is exact . However , if k ! = 0 , then f
* may not be representable exactly . In that case , a correction
* term is need . Let u = 1 + x rounded . Let c = ( 1 + x ) - u , then
* log ( 1 + x ) - log ( u ) ~ c / u . Thus , we proceed to compute log ( u ) ,
* and add back the correction term c / u .
* ( Note : when x > 2 * * 53 , one can simply return log ( x ) )
*
* 2 . Approximation of log ( 1 + f ) : See log . c
*
* 3 . Finally , log1p ( x ) = k * ln2 + log ( 1 + f ) + c / u . See log . c
*
* Special cases :
* log1p ( x ) is NaN with signal if x < - 1 ( including - INF ) ;
* log1p ( + INF ) is + INF ; log1p ( - 1 ) is - INF with signal ;
* log1p ( 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 .
*
* Note : Assuming log ( ) return accurate answer , the following
* algorithm can be used to compute log1p ( x ) to within a few ULP :
*
* u = 1 + x ;
* if ( u = = 1 . 0 ) return x ; else
* return log ( u ) * ( x / ( u - 1 . 0 ) ) ;
*
* See HP - 15 C Advanced Functions Handbook , p . 193 .
*/
use core::f64;
const LN2_HI: f64 = 6 .93147180369123816490 e-01 ; /* 3fe62e42 fee00000 */
const LN2_LO: f64 = 1 .90821492927058770002 e-10 ; /* 3dea39ef 35793c76 */
const LG1: f64 = 6 .666666666666735130 e-01 ; /* 3FE55555 55555593 */
const LG2: f64 = 3 .999999999940941908 e-01 ; /* 3FD99999 9997FA04 */
const LG3: f64 = 2 .857142874366239149 e-01 ; /* 3FD24924 94229359 */
const LG4: f64 = 2 .222219843214978396 e-01 ; /* 3FCC71C5 1D8E78AF */
const LG5: f64 = 1 .818357216161805012 e-01 ; /* 3FC74664 96CB03DE */
const LG6: f64 = 1 .531383769920937332 e-01 ; /* 3FC39A09 D078C69F */
const LG7: f64 = 1 .479819860511658591 e-01 ; /* 3FC2F112 DF3E5244 */
#[ cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
pub fn log1p(x: f64) -> f64 {
let mut ui: u64 = x.to_bits();
let hfsq: f64;
let mut f: f64 = 0 .;
let mut c: f64 = 0 .;
let s: f64;
let z: f64;
let r: f64;
let w: f64;
let t1: f64;
let t2: f64;
let dk: f64;
let hx: u32;
let mut hu: u32;
let mut k: i32;
hx = (ui >> 32 ) as u32;
k = 1 ;
if hx < 0 x3fda827a || (hx >> 31 ) > 0 {
/* 1+x < sqrt(2)+ */
if hx >= 0 xbff00000 {
/* x <= -1.0 */
if x == -1 . {
return x / 0 .0 ; /* log1p(-1) = -inf */
}
return (x - x) / 0 .0 ; /* log1p(x<-1) = NaN */
}
if hx << 1 < 0 x3ca00000 << 1 {
/* |x| < 2**-53 */
/* underflow if subnormal */
if (hx & 0 x7ff00000) == 0 {
force_eval!(x as f32);
}
return x;
}
if hx <= 0 xbfd2bec4 {
/* sqrt(2)/2- <= 1+x < sqrt(2)+ */
k = 0 ;
c = 0 .;
f = x;
}
} else if hx >= 0 x7ff00000 {
return x;
}
if k > 0 {
ui = (1 . + x).to_bits();
hu = (ui >> 32 ) as u32;
hu += 0 x3ff00000 - 0 x3fe6a09e;
k = (hu >> 20 ) as i32 - 0 x3ff;
/* correction term ~ log(1+x)-log(u), avoid underflow in c/u */
if k < 54 {
c = if k >= 2 {
1 . - (f64::from_bits(ui) - x)
} else {
x - (f64::from_bits(ui) - 1 .)
};
c /= f64::from_bits(ui);
} else {
c = 0 .;
}
/* reduce u into [sqrt(2)/2, sqrt(2)] */
hu = (hu & 0 x000fffff) + 0 x3fe6a09e;
ui = (hu as u64) << 32 | (ui & 0 xffffffff);
f = f64::from_bits(ui) - 1 .;
}
hfsq = 0 .5 * f * f;
s = f / (2 .0 + f);
z = s * s;
w = z * z;
t1 = w * (LG2 + w * (LG4 + w * LG6));
t2 = z * (LG1 + w * (LG3 + w * (LG5 + w * LG7)));
r = t2 + t1;
dk = k as f64;
s * (hfsq + r) + (dk * LN2_LO + c) - hfsq + f + dk * LN2_HI
}
Messung V0.5 in Prozent C=86 H=100 G=93
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-06-19)
¤
*© Formatika GbR, Deutschland