Skip to content

Commit 06c5e7f

Browse files
committed
Implement exp_m1 and ln_1p as methods for Float
Both expm1 and ln1p have been renamed to exp_m1 and ln_1p in order to be consistent with the underscore usage elsewhere. The exp_m1 method is used for increased accuracy when doing floating point calculations, so this has been moved from the more general 'Exponential' trait into 'Float'.
1 parent 9b09dce commit 06c5e7f

File tree

5 files changed

+65
-22
lines changed

5 files changed

+65
-22
lines changed

src/libcore/num/cmath.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ pub mod c_double_utils {
3333
unsafe fn erf(n: c_double) -> c_double;
3434
unsafe fn erfc(n: c_double) -> c_double;
3535
unsafe fn exp(n: c_double) -> c_double;
36-
unsafe fn expm1(n: c_double) -> c_double;
36+
// rename: for consistency with underscore usage elsewhere
37+
#[link_name="expm1"] unsafe fn exp_m1(n: c_double) -> c_double;
3738
unsafe fn exp2(n: c_double) -> c_double;
3839
#[link_name="fabs"] unsafe fn abs(n: c_double) -> c_double;
3940
// rename: for clarity and consistency with add/sub/mul/div
@@ -63,7 +64,7 @@ pub mod c_double_utils {
6364
// renamed: "logb" /often/ is confused for log2 by beginners
6465
#[link_name="logb"] unsafe fn log_radix(n: c_double) -> c_double;
6566
// renamed: to be consitent with log as ln
66-
#[link_name="log1p"] unsafe fn ln1p(n: c_double) -> c_double;
67+
#[link_name="log1p"] unsafe fn ln_1p(n: c_double) -> c_double;
6768
unsafe fn log10(n: c_double) -> c_double;
6869
unsafe fn log2(n: c_double) -> c_double;
6970
#[link_name="ilogb"] unsafe fn ilog_radix(n: c_double) -> c_int;
@@ -117,7 +118,7 @@ pub mod c_float_utils {
117118
#[link_name="erff"] unsafe fn erf(n: c_float) -> c_float;
118119
#[link_name="erfcf"] unsafe fn erfc(n: c_float) -> c_float;
119120
#[link_name="expf"] unsafe fn exp(n: c_float) -> c_float;
120-
#[link_name="expm1f"]unsafe fn expm1(n: c_float) -> c_float;
121+
#[link_name="expm1f"]unsafe fn exp_m1(n: c_float) -> c_float;
121122
#[link_name="exp2f"] unsafe fn exp2(n: c_float) -> c_float;
122123
#[link_name="fabsf"] unsafe fn abs(n: c_float) -> c_float;
123124
#[link_name="fdimf"]
@@ -148,7 +149,7 @@ pub mod c_float_utils {
148149

149150
#[link_name="logf"] unsafe fn ln(n: c_float) -> c_float;
150151
#[link_name="logbf"] unsafe fn log_radix(n: c_float) -> c_float;
151-
#[link_name="log1pf"] unsafe fn ln1p(n: c_float) -> c_float;
152+
#[link_name="log1pf"] unsafe fn ln_1p(n: c_float) -> c_float;
152153
#[link_name="log2f"] unsafe fn log2(n: c_float) -> c_float;
153154
#[link_name="log10f"] unsafe fn log10(n: c_float) -> c_float;
154155
#[link_name="ilogbf"] unsafe fn ilog_radix(n: c_float) -> c_int;

src/libcore/num/f32.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ delegate!(
8282
fn cosh(n: c_float) -> c_float = c_float_utils::cosh,
8383
fn erf(n: c_float) -> c_float = c_float_utils::erf,
8484
fn erfc(n: c_float) -> c_float = c_float_utils::erfc,
85-
fn expm1(n: c_float) -> c_float = c_float_utils::expm1,
85+
fn exp_m1(n: c_float) -> c_float = c_float_utils::exp_m1,
8686
fn abs_sub(a: c_float, b: c_float) -> c_float = c_float_utils::abs_sub,
8787
fn fmax(a: c_float, b: c_float) -> c_float = c_float_utils::fmax,
8888
fn fmin(a: c_float, b: c_float) -> c_float = c_float_utils::fmin,
@@ -92,7 +92,7 @@ delegate!(
9292
fn ldexp(x: c_float, n: c_int) -> c_float = c_float_utils::ldexp,
9393
fn lgamma(n: c_float, sign: &mut c_int) -> c_float = c_float_utils::lgamma,
9494
fn log_radix(n: c_float) -> c_float = c_float_utils::log_radix,
95-
fn ln1p(n: c_float) -> c_float = c_float_utils::ln1p,
95+
fn ln_1p(n: c_float) -> c_float = c_float_utils::ln_1p,
9696
fn ilog_radix(n: c_float) -> c_int = c_float_utils::ilog_radix,
9797
fn modf(n: c_float, iptr: &mut c_float) -> c_float = c_float_utils::modf,
9898
fn round(n: c_float) -> c_float = c_float_utils::round,
@@ -408,15 +408,14 @@ impl Trigonometric for f32 {
408408
}
409409

410410
impl Exponential for f32 {
411+
/// Returns the exponential of the number
411412
#[inline(always)]
412413
fn exp(&self) -> f32 { exp(*self) }
413414

415+
/// Returns 2 raised to the power of the number
414416
#[inline(always)]
415417
fn exp2(&self) -> f32 { exp2(*self) }
416418

417-
#[inline(always)]
418-
fn expm1(&self) -> f32 { expm1(*self) }
419-
420419
/// Returns the natural logarithm of the number
421420
#[inline(always)]
422421
fn ln(&self) -> f32 { ln(*self) }
@@ -588,6 +587,20 @@ impl Float for f32 {
588587
!(self.is_NaN() || self.is_infinite())
589588
}
590589

590+
///
591+
/// Returns the exponential of the number, minus `1`, in a way that is accurate
592+
/// even if the number is close to zero
593+
///
594+
#[inline(always)]
595+
fn exp_m1(&self) -> f32 { exp_m1(*self) }
596+
597+
///
598+
/// Returns the natural logarithm of the number plus `1` (`ln(1+n)`) more accurately
599+
/// than if the operations were performed separately
600+
///
601+
#[inline(always)]
602+
fn ln_1p(&self) -> f32 { ln_1p(*self) }
603+
591604
///
592605
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding error. This
593606
/// produces a more accurate result with better performance than a separate multiplication

src/libcore/num/f64.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ delegate!(
8484
fn cosh(n: c_double) -> c_double = c_double_utils::cosh,
8585
fn erf(n: c_double) -> c_double = c_double_utils::erf,
8686
fn erfc(n: c_double) -> c_double = c_double_utils::erfc,
87-
fn expm1(n: c_double) -> c_double = c_double_utils::expm1,
87+
fn exp_m1(n: c_double) -> c_double = c_double_utils::exp_m1,
8888
fn abs_sub(a: c_double, b: c_double) -> c_double = c_double_utils::abs_sub,
8989
fn fmax(a: c_double, b: c_double) -> c_double = c_double_utils::fmax,
9090
fn fmin(a: c_double, b: c_double) -> c_double = c_double_utils::fmin,
@@ -94,7 +94,7 @@ delegate!(
9494
fn ldexp(x: c_double, n: c_int) -> c_double = c_double_utils::ldexp,
9595
fn lgamma(n: c_double, sign: &mut c_int) -> c_double = c_double_utils::lgamma,
9696
fn log_radix(n: c_double) -> c_double = c_double_utils::log_radix,
97-
fn ln1p(n: c_double) -> c_double = c_double_utils::ln1p,
97+
fn ln_1p(n: c_double) -> c_double = c_double_utils::ln_1p,
9898
fn ilog_radix(n: c_double) -> c_int = c_double_utils::ilog_radix,
9999
fn modf(n: c_double, iptr: &mut c_double) -> c_double = c_double_utils::modf,
100100
fn round(n: c_double) -> c_double = c_double_utils::round,
@@ -421,15 +421,14 @@ impl Trigonometric for f64 {
421421
}
422422

423423
impl Exponential for f64 {
424+
/// Returns the exponential of the number
424425
#[inline(always)]
425426
fn exp(&self) -> f64 { exp(*self) }
426427

428+
/// Returns 2 raised to the power of the number
427429
#[inline(always)]
428430
fn exp2(&self) -> f64 { exp2(*self) }
429431

430-
#[inline(always)]
431-
fn expm1(&self) -> f64 { expm1(*self) }
432-
433432
/// Returns the natural logarithm of the number
434433
#[inline(always)]
435434
fn ln(&self) -> f64 { ln(*self) }
@@ -631,6 +630,20 @@ impl Float for f64 {
631630
#[inline(always)]
632631
fn max_10_exp() -> int { 308 }
633632

633+
///
634+
/// Returns the exponential of the number, minus `1`, in a way that is accurate
635+
/// even if the number is close to zero
636+
///
637+
#[inline(always)]
638+
fn exp_m1(&self) -> f64 { exp_m1(*self) }
639+
640+
///
641+
/// Returns the natural logarithm of the number plus `1` (`ln(1+n)`) more accurately
642+
/// than if the operations were performed separately
643+
///
644+
#[inline(always)]
645+
fn ln_1p(&self) -> f64 { ln_1p(*self) }
646+
634647
///
635648
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding error. This
636649
/// produces a more accurate result with better performance than a separate multiplication

src/libcore/num/float.rs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ use prelude::*;
2626

2727
pub use f64::{add, sub, mul, div, rem, lt, le, eq, ne, ge, gt};
2828
pub use f64::{acos, asin, atan2, cbrt, ceil, copysign, cosh, floor};
29-
pub use f64::{erf, erfc, exp, expm1, exp2, abs_sub};
29+
pub use f64::{erf, erfc, exp, exp_m1, exp2, abs_sub};
3030
pub use f64::{mul_add, fmax, fmin, next_after, frexp, hypot, ldexp};
31-
pub use f64::{lgamma, ln, log_radix, ln1p, log10, log2, ilog_radix};
31+
pub use f64::{lgamma, ln, log_radix, ln_1p, log10, log2, ilog_radix};
3232
pub use f64::{modf, pow, powi, round, sinh, tanh, tgamma, trunc};
3333
pub use f64::{j0, j1, jn, y0, y1, yn};
3434

@@ -532,21 +532,18 @@ impl Trigonometric for float {
532532
}
533533
534534
impl Exponential for float {
535+
/// Returns the exponential of the number
535536
#[inline(always)]
536537
fn exp(&self) -> float {
537538
(*self as f64).exp() as float
538539
}
539540
541+
/// Returns 2 raised to the power of the number
540542
#[inline(always)]
541543
fn exp2(&self) -> float {
542544
(*self as f64).exp2() as float
543545
}
544546
545-
#[inline(always)]
546-
fn expm1(&self) -> float {
547-
(*self as f64).expm1() as float
548-
}
549-
550547
/// Returns the natural logarithm of the number
551548
#[inline(always)]
552549
fn ln(&self) -> float {
@@ -823,6 +820,24 @@ impl Float for float {
823820
!(self.is_NaN() || self.is_infinite())
824821
}
825822
823+
///
824+
/// Returns the exponential of the number, minus `1`, in a way that is accurate
825+
/// even if the number is close to zero
826+
///
827+
#[inline(always)]
828+
fn exp_m1(&self) -> float {
829+
(*self as f64).exp_m1() as float
830+
}
831+
832+
///
833+
/// Returns the natural logarithm of the number plus `1` (`ln(1+n)`) more accurately
834+
/// than if the operations were performed separately
835+
///
836+
#[inline(always)]
837+
fn ln_1p(&self) -> float {
838+
(*self as f64).ln_1p() as float
839+
}
840+
826841
///
827842
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding error. This
828843
/// produces a more accurate result with better performance than a separate multiplication

src/libcore/num/num.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,6 @@ pub trait Trigonometric {
121121
pub trait Exponential {
122122
fn exp(&self) -> Self;
123123
fn exp2(&self) -> Self;
124-
fn expm1(&self) -> Self;
125124
fn ln(&self) -> Self;
126125
fn log(&self, base: Self) -> Self;
127126
fn log2(&self) -> Self;
@@ -261,6 +260,8 @@ pub trait Float: Real
261260
fn min_10_exp() -> int;
262261
fn max_10_exp() -> int;
263262

263+
fn exp_m1(&self) -> Self;
264+
fn ln_1p(&self) -> Self;
264265
fn mul_add(&self, a: Self, b: Self) -> Self;
265266
fn next_after(&self, other: Self) -> Self;
266267
}

0 commit comments

Comments
 (0)