Add Fractional, Real and RealExt traits
This commit is contained in:
parent
6fa054df96
commit
dcd49ccd0b
@ -105,6 +105,7 @@ pub use iter::{ExtendedMutableIter};
|
||||
|
||||
pub use num::{Num, NumCast};
|
||||
pub use num::{Signed, Unsigned, Integer};
|
||||
pub use num::{Fractional, Real, RealExt};
|
||||
pub use ptr::Ptr;
|
||||
pub use to_str::ToStr;
|
||||
pub use clone::Clone;
|
||||
|
@ -327,31 +327,176 @@ impl Signed for f32 {
|
||||
fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity }
|
||||
}
|
||||
|
||||
impl num::Round for f32 {
|
||||
impl Fractional for f32 {
|
||||
/// The reciprocal (multiplicative inverse) of the number
|
||||
#[inline(always)]
|
||||
fn round(&self, mode: num::RoundMode) -> f32 {
|
||||
match mode {
|
||||
num::RoundDown => floor(*self),
|
||||
num::RoundUp => ceil(*self),
|
||||
num::RoundToZero if self.is_negative() => ceil(*self),
|
||||
num::RoundToZero => floor(*self),
|
||||
num::RoundFromZero if self.is_negative() => floor(*self),
|
||||
num::RoundFromZero => ceil(*self)
|
||||
}
|
||||
}
|
||||
fn recip(&self) -> f32 { 1.0 / *self }
|
||||
}
|
||||
|
||||
impl Real for f32 {
|
||||
/// Archimedes' constant
|
||||
#[inline(always)]
|
||||
fn pi() -> f32 { 3.14159265358979323846264338327950288 }
|
||||
|
||||
/// 2.0 * pi
|
||||
#[inline(always)]
|
||||
fn two_pi() -> f32 { 6.28318530717958647692528676655900576 }
|
||||
|
||||
/// pi / 2.0
|
||||
#[inline(always)]
|
||||
fn frac_pi_2() -> f32 { 1.57079632679489661923132169163975144 }
|
||||
|
||||
/// pi / 3.0
|
||||
#[inline(always)]
|
||||
fn frac_pi_3() -> f32 { 1.04719755119659774615421446109316763 }
|
||||
|
||||
/// pi / 4.0
|
||||
#[inline(always)]
|
||||
fn frac_pi_4() -> f32 { 0.785398163397448309615660845819875721 }
|
||||
|
||||
/// pi / 6.0
|
||||
#[inline(always)]
|
||||
fn frac_pi_6() -> f32 { 0.52359877559829887307710723054658381 }
|
||||
|
||||
/// pi / 8.0
|
||||
#[inline(always)]
|
||||
fn frac_pi_8() -> f32 { 0.39269908169872415480783042290993786 }
|
||||
|
||||
/// 1 .0/ pi
|
||||
#[inline(always)]
|
||||
fn frac_1_pi() -> f32 { 0.318309886183790671537767526745028724 }
|
||||
|
||||
/// 2.0 / pi
|
||||
#[inline(always)]
|
||||
fn frac_2_pi() -> f32 { 0.636619772367581343075535053490057448 }
|
||||
|
||||
/// 2.0 / sqrt(pi)
|
||||
#[inline(always)]
|
||||
fn frac_2_sqrtpi() -> f32 { 1.12837916709551257389615890312154517 }
|
||||
|
||||
/// sqrt(2.0)
|
||||
#[inline(always)]
|
||||
fn sqrt2() -> f32 { 1.41421356237309504880168872420969808 }
|
||||
|
||||
/// 1.0 / sqrt(2.0)
|
||||
#[inline(always)]
|
||||
fn frac_1_sqrt2() -> f32 { 0.707106781186547524400844362104849039 }
|
||||
|
||||
/// Euler's number
|
||||
#[inline(always)]
|
||||
fn e() -> f32 { 2.71828182845904523536028747135266250 }
|
||||
|
||||
/// log2(e)
|
||||
#[inline(always)]
|
||||
fn log2_e() -> f32 { 1.44269504088896340735992468100189214 }
|
||||
|
||||
/// log10(e)
|
||||
#[inline(always)]
|
||||
fn log10_e() -> f32 { 0.434294481903251827651128918916605082 }
|
||||
|
||||
/// log(2.0)
|
||||
#[inline(always)]
|
||||
fn log_2() -> f32 { 0.693147180559945309417232121458176568 }
|
||||
|
||||
/// log(10.0)
|
||||
#[inline(always)]
|
||||
fn log_10() -> f32 { 2.30258509299404568401799145468436421 }
|
||||
|
||||
#[inline(always)]
|
||||
fn floor(&self) -> f32 { floor(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn ceil(&self) -> f32 { ceil(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn fract(&self) -> f32 {
|
||||
if self.is_negative() {
|
||||
(*self) - ceil(*self)
|
||||
} else {
|
||||
(*self) - floor(*self)
|
||||
}
|
||||
}
|
||||
fn round(&self) -> f32 { round(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn trunc(&self) -> f32 { trunc(*self) }
|
||||
|
||||
/// The fractional part of the number, calculated using: `n - floor(n)`
|
||||
#[inline(always)]
|
||||
fn fract(&self) -> f32 { *self - self.floor() }
|
||||
|
||||
#[inline(always)]
|
||||
fn pow(&self, n: f32) -> f32 { pow(*self, n) }
|
||||
|
||||
#[inline(always)]
|
||||
fn exp(&self) -> f32 { exp(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn exp2(&self) -> f32 { exp2(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn expm1(&self) -> f32 { expm1(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn ldexp(&self, n: int) -> f32 { ldexp(*self, n as c_int) }
|
||||
|
||||
#[inline(always)]
|
||||
fn log(&self) -> f32 { ln(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn log2(&self) -> f32 { log2(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn log10(&self) -> f32 { log10(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn log_radix(&self) -> f32 { log_radix(*self) as f32 }
|
||||
|
||||
#[inline(always)]
|
||||
fn ilog_radix(&self) -> int { ilog_radix(*self) as int }
|
||||
|
||||
#[inline(always)]
|
||||
fn sqrt(&self) -> f32 { sqrt(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn rsqrt(&self) -> f32 { self.sqrt().recip() }
|
||||
|
||||
#[inline(always)]
|
||||
fn cbrt(&self) -> f32 { cbrt(*self) }
|
||||
|
||||
/// Converts to degrees, assuming the number is in radians
|
||||
#[inline(always)]
|
||||
fn to_degrees(&self) -> f32 { *self * (180.0 / Real::pi::<f32>()) }
|
||||
|
||||
/// Converts to radians, assuming the number is in degrees
|
||||
#[inline(always)]
|
||||
fn to_radians(&self) -> f32 { *self * (Real::pi::<f32>() / 180.0) }
|
||||
|
||||
#[inline(always)]
|
||||
fn hypot(&self, other: f32) -> f32 { hypot(*self, other) }
|
||||
|
||||
#[inline(always)]
|
||||
fn sin(&self) -> f32 { sin(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn cos(&self) -> f32 { cos(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn tan(&self) -> f32 { tan(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn asin(&self) -> f32 { asin(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn acos(&self) -> f32 { acos(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn atan(&self) -> f32 { atan(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn atan2(&self, other: f32) -> f32 { atan2(*self, other) }
|
||||
|
||||
#[inline(always)]
|
||||
fn sinh(&self) -> f32 { sinh(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn cosh(&self) -> f32 { cosh(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn tanh(&self) -> f32 { tanh(*self) }
|
||||
}
|
||||
|
||||
/**
|
||||
@ -577,11 +722,39 @@ mod tests {
|
||||
use super::*;
|
||||
use prelude::*;
|
||||
|
||||
macro_rules! assert_fuzzy_eq(
|
||||
($a:expr, $b:expr) => ({
|
||||
let a = $a, b = $b;
|
||||
if !((a - b).abs() < 1.0e-6) {
|
||||
fail!(fmt!("The values were not approximately equal. Found: %? and %?", a, b));
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
#[test]
|
||||
fn test_num() {
|
||||
num::test_num(10f32, 2f32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_real_consts() {
|
||||
assert_fuzzy_eq!(Real::two_pi::<f32>(), 2f32 * Real::pi::<f32>());
|
||||
assert_fuzzy_eq!(Real::frac_pi_2::<f32>(), Real::pi::<f32>() / 2f32);
|
||||
assert_fuzzy_eq!(Real::frac_pi_3::<f32>(), Real::pi::<f32>() / 3f32);
|
||||
assert_fuzzy_eq!(Real::frac_pi_4::<f32>(), Real::pi::<f32>() / 4f32);
|
||||
assert_fuzzy_eq!(Real::frac_pi_6::<f32>(), Real::pi::<f32>() / 6f32);
|
||||
assert_fuzzy_eq!(Real::frac_pi_8::<f32>(), Real::pi::<f32>() / 8f32);
|
||||
assert_fuzzy_eq!(Real::frac_1_pi::<f32>(), 1f32 / Real::pi::<f32>());
|
||||
assert_fuzzy_eq!(Real::frac_2_pi::<f32>(), 2f32 / Real::pi::<f32>());
|
||||
assert_fuzzy_eq!(Real::frac_2_sqrtpi::<f32>(), 2f32 / Real::pi::<f32>().sqrt());
|
||||
assert_fuzzy_eq!(Real::sqrt2::<f32>(), 2f32.sqrt());
|
||||
assert_fuzzy_eq!(Real::frac_1_sqrt2::<f32>(), 1f32 / 2f32.sqrt());
|
||||
assert_fuzzy_eq!(Real::log2_e::<f32>(), Real::e::<f32>().log2());
|
||||
assert_fuzzy_eq!(Real::log10_e::<f32>(), Real::e::<f32>().log10());
|
||||
assert_fuzzy_eq!(Real::log_2::<f32>(), 2f32.log());
|
||||
assert_fuzzy_eq!(Real::log_10::<f32>(), 10f32.log());
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_signed() {
|
||||
assert_eq!(infinity.abs(), infinity);
|
||||
|
@ -337,31 +337,206 @@ impl Signed for f64 {
|
||||
fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity }
|
||||
}
|
||||
|
||||
impl num::Round for f64 {
|
||||
impl Fractional for f64 {
|
||||
/// The reciprocal (multiplicative inverse) of the number
|
||||
#[inline(always)]
|
||||
fn round(&self, mode: num::RoundMode) -> f64 {
|
||||
match mode {
|
||||
num::RoundDown => floor(*self),
|
||||
num::RoundUp => ceil(*self),
|
||||
num::RoundToZero if self.is_negative() => ceil(*self),
|
||||
num::RoundToZero => floor(*self),
|
||||
num::RoundFromZero if self.is_negative() => floor(*self),
|
||||
num::RoundFromZero => ceil(*self)
|
||||
}
|
||||
}
|
||||
fn recip(&self) -> f64 { 1.0 / *self }
|
||||
}
|
||||
|
||||
impl Real for f64 {
|
||||
/// Archimedes' constant
|
||||
#[inline(always)]
|
||||
fn pi() -> f64 { 3.14159265358979323846264338327950288 }
|
||||
|
||||
/// 2.0 * pi
|
||||
#[inline(always)]
|
||||
fn two_pi() -> f64 { 6.28318530717958647692528676655900576 }
|
||||
|
||||
/// pi / 2.0
|
||||
#[inline(always)]
|
||||
fn frac_pi_2() -> f64 { 1.57079632679489661923132169163975144 }
|
||||
|
||||
/// pi / 3.0
|
||||
#[inline(always)]
|
||||
fn frac_pi_3() -> f64 { 1.04719755119659774615421446109316763 }
|
||||
|
||||
/// pi / 4.0
|
||||
#[inline(always)]
|
||||
fn frac_pi_4() -> f64 { 0.785398163397448309615660845819875721 }
|
||||
|
||||
/// pi / 6.0
|
||||
#[inline(always)]
|
||||
fn frac_pi_6() -> f64 { 0.52359877559829887307710723054658381 }
|
||||
|
||||
/// pi / 8.0
|
||||
#[inline(always)]
|
||||
fn frac_pi_8() -> f64 { 0.39269908169872415480783042290993786 }
|
||||
|
||||
/// 1.0 / pi
|
||||
#[inline(always)]
|
||||
fn frac_1_pi() -> f64 { 0.318309886183790671537767526745028724 }
|
||||
|
||||
/// 2.0 / pi
|
||||
#[inline(always)]
|
||||
fn frac_2_pi() -> f64 { 0.636619772367581343075535053490057448 }
|
||||
|
||||
/// 2.0 / sqrt(pi)
|
||||
#[inline(always)]
|
||||
fn frac_2_sqrtpi() -> f64 { 1.12837916709551257389615890312154517 }
|
||||
|
||||
/// sqrt(2.0)
|
||||
#[inline(always)]
|
||||
fn sqrt2() -> f64 { 1.41421356237309504880168872420969808 }
|
||||
|
||||
/// 1.0 / sqrt(2.0)
|
||||
#[inline(always)]
|
||||
fn frac_1_sqrt2() -> f64 { 0.707106781186547524400844362104849039 }
|
||||
|
||||
/// Euler's number
|
||||
#[inline(always)]
|
||||
fn e() -> f64 { 2.71828182845904523536028747135266250 }
|
||||
|
||||
/// log2(e)
|
||||
#[inline(always)]
|
||||
fn log2_e() -> f64 { 1.44269504088896340735992468100189214 }
|
||||
|
||||
/// log10(e)
|
||||
#[inline(always)]
|
||||
fn log10_e() -> f64 { 0.434294481903251827651128918916605082 }
|
||||
|
||||
/// log(2.0)
|
||||
#[inline(always)]
|
||||
fn log_2() -> f64 { 0.693147180559945309417232121458176568 }
|
||||
|
||||
/// log(10.0)
|
||||
#[inline(always)]
|
||||
fn log_10() -> f64 { 2.30258509299404568401799145468436421 }
|
||||
|
||||
#[inline(always)]
|
||||
fn floor(&self) -> f64 { floor(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn ceil(&self) -> f64 { ceil(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn fract(&self) -> f64 {
|
||||
if self.is_negative() {
|
||||
(*self) - ceil(*self)
|
||||
} else {
|
||||
(*self) - floor(*self)
|
||||
}
|
||||
fn round(&self) -> f64 { round(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn trunc(&self) -> f64 { trunc(*self) }
|
||||
|
||||
/// The fractional part of the number, calculated using: `n - floor(n)`
|
||||
#[inline(always)]
|
||||
fn fract(&self) -> f64 { *self - self.floor() }
|
||||
|
||||
#[inline(always)]
|
||||
fn pow(&self, n: f64) -> f64 { pow(*self, n) }
|
||||
|
||||
#[inline(always)]
|
||||
fn exp(&self) -> f64 { exp(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn exp2(&self) -> f64 { exp2(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn expm1(&self) -> f64 { expm1(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn ldexp(&self, n: int) -> f64 { ldexp(*self, n as c_int) }
|
||||
|
||||
#[inline(always)]
|
||||
fn log(&self) -> f64 { ln(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn log2(&self) -> f64 { log2(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn log10(&self) -> f64 { log10(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn log_radix(&self) -> f64 { log_radix(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn ilog_radix(&self) -> int { ilog_radix(*self) as int }
|
||||
|
||||
#[inline(always)]
|
||||
fn sqrt(&self) -> f64 { sqrt(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn rsqrt(&self) -> f64 { self.sqrt().recip() }
|
||||
|
||||
#[inline(always)]
|
||||
fn cbrt(&self) -> f64 { cbrt(*self) }
|
||||
|
||||
/// Converts to degrees, assuming the number is in radians
|
||||
#[inline(always)]
|
||||
fn to_degrees(&self) -> f64 { *self * (180.0 / Real::pi::<f64>()) }
|
||||
|
||||
/// Converts to radians, assuming the number is in degrees
|
||||
#[inline(always)]
|
||||
fn to_radians(&self) -> f64 { *self * (Real::pi::<f64>() / 180.0) }
|
||||
|
||||
#[inline(always)]
|
||||
fn hypot(&self, other: f64) -> f64 { hypot(*self, other) }
|
||||
|
||||
#[inline(always)]
|
||||
fn sin(&self) -> f64 { sin(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn cos(&self) -> f64 { cos(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn tan(&self) -> f64 { tan(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn asin(&self) -> f64 { asin(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn acos(&self) -> f64 { acos(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn atan(&self) -> f64 { atan(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn atan2(&self, other: f64) -> f64 { atan2(*self, other) }
|
||||
|
||||
#[inline(always)]
|
||||
fn sinh(&self) -> f64 { sinh(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn cosh(&self) -> f64 { cosh(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn tanh(&self) -> f64 { tanh(*self) }
|
||||
}
|
||||
|
||||
impl RealExt for f64 {
|
||||
#[inline(always)]
|
||||
fn lgamma(&self) -> (int, f64) {
|
||||
let mut sign = 0;
|
||||
let result = lgamma(*self, &mut sign);
|
||||
(sign as int, result)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn tgamma(&self) -> f64 { tgamma(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn j0(&self) -> f64 { j0(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn j1(&self) -> f64 { j1(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn jn(&self, n: int) -> f64 { jn(n as c_int, *self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn y0(&self) -> f64 { y0(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn y1(&self) -> f64 { y1(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn yn(&self, n: int) -> f64 { yn(n as c_int, *self) }
|
||||
}
|
||||
|
||||
/**
|
||||
@ -587,11 +762,39 @@ mod tests {
|
||||
use super::*;
|
||||
use prelude::*;
|
||||
|
||||
macro_rules! assert_fuzzy_eq(
|
||||
($a:expr, $b:expr) => ({
|
||||
let a = $a, b = $b;
|
||||
if !((a - b).abs() < 1.0e-6) {
|
||||
fail!(fmt!("The values were not approximately equal. Found: %? and %?", a, b));
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
#[test]
|
||||
fn test_num() {
|
||||
num::test_num(10f64, 2f64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_real_consts() {
|
||||
assert_fuzzy_eq!(Real::two_pi::<f64>(), 2.0 * Real::pi::<f64>());
|
||||
assert_fuzzy_eq!(Real::frac_pi_2::<f64>(), Real::pi::<f64>() / 2f64);
|
||||
assert_fuzzy_eq!(Real::frac_pi_3::<f64>(), Real::pi::<f64>() / 3f64);
|
||||
assert_fuzzy_eq!(Real::frac_pi_4::<f64>(), Real::pi::<f64>() / 4f64);
|
||||
assert_fuzzy_eq!(Real::frac_pi_6::<f64>(), Real::pi::<f64>() / 6f64);
|
||||
assert_fuzzy_eq!(Real::frac_pi_8::<f64>(), Real::pi::<f64>() / 8f64);
|
||||
assert_fuzzy_eq!(Real::frac_1_pi::<f64>(), 1f64 / Real::pi::<f64>());
|
||||
assert_fuzzy_eq!(Real::frac_2_pi::<f64>(), 2f64 / Real::pi::<f64>());
|
||||
assert_fuzzy_eq!(Real::frac_2_sqrtpi::<f64>(), 2f64 / Real::pi::<f64>().sqrt());
|
||||
assert_fuzzy_eq!(Real::sqrt2::<f64>(), 2f64.sqrt());
|
||||
assert_fuzzy_eq!(Real::frac_1_sqrt2::<f64>(), 1f64 / 2f64.sqrt());
|
||||
assert_fuzzy_eq!(Real::log2_e::<f64>(), Real::e::<f64>().log2());
|
||||
assert_fuzzy_eq!(Real::log10_e::<f64>(), Real::e::<f64>().log10());
|
||||
assert_fuzzy_eq!(Real::log_2::<f64>(), 2f64.log());
|
||||
assert_fuzzy_eq!(Real::log_10::<f64>(), 10f64.log());
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_signed() {
|
||||
assert_eq!(infinity.abs(), infinity);
|
||||
|
@ -403,37 +403,206 @@ impl num::One for float {
|
||||
fn one() -> float { 1.0 }
|
||||
}
|
||||
|
||||
impl num::Round for float {
|
||||
impl Fractional for float {
|
||||
/// The reciprocal (multiplicative inverse) of the number
|
||||
#[inline(always)]
|
||||
fn round(&self, mode: num::RoundMode) -> float {
|
||||
match mode {
|
||||
num::RoundDown
|
||||
=> f64::floor(*self as f64) as float,
|
||||
num::RoundUp
|
||||
=> f64::ceil(*self as f64) as float,
|
||||
num::RoundToZero if self.is_negative()
|
||||
=> f64::ceil(*self as f64) as float,
|
||||
num::RoundToZero
|
||||
=> f64::floor(*self as f64) as float,
|
||||
num::RoundFromZero if self.is_negative()
|
||||
=> f64::floor(*self as f64) as float,
|
||||
num::RoundFromZero
|
||||
=> f64::ceil(*self as f64) as float
|
||||
}
|
||||
fn recip(&self) -> float { 1.0 / *self }
|
||||
}
|
||||
|
||||
impl Real for float {
|
||||
/// Archimedes' constant
|
||||
#[inline(always)]
|
||||
fn pi() -> float { 3.14159265358979323846264338327950288 }
|
||||
|
||||
/// 2.0 * pi
|
||||
#[inline(always)]
|
||||
fn two_pi() -> float { 6.28318530717958647692528676655900576 }
|
||||
|
||||
/// pi / 2.0
|
||||
#[inline(always)]
|
||||
fn frac_pi_2() -> float { 1.57079632679489661923132169163975144 }
|
||||
|
||||
/// pi / 3.0
|
||||
#[inline(always)]
|
||||
fn frac_pi_3() -> float { 1.04719755119659774615421446109316763 }
|
||||
|
||||
/// pi / 4.0
|
||||
#[inline(always)]
|
||||
fn frac_pi_4() -> float { 0.785398163397448309615660845819875721 }
|
||||
|
||||
/// pi / 6.0
|
||||
#[inline(always)]
|
||||
fn frac_pi_6() -> float { 0.52359877559829887307710723054658381 }
|
||||
|
||||
/// pi / 8.0
|
||||
#[inline(always)]
|
||||
fn frac_pi_8() -> float { 0.39269908169872415480783042290993786 }
|
||||
|
||||
/// 1.0 / pi
|
||||
#[inline(always)]
|
||||
fn frac_1_pi() -> float { 0.318309886183790671537767526745028724 }
|
||||
|
||||
/// 2.0 / pi
|
||||
#[inline(always)]
|
||||
fn frac_2_pi() -> float { 0.636619772367581343075535053490057448 }
|
||||
|
||||
/// 2 .0/ sqrt(pi)
|
||||
#[inline(always)]
|
||||
fn frac_2_sqrtpi() -> float { 1.12837916709551257389615890312154517 }
|
||||
|
||||
/// sqrt(2.0)
|
||||
#[inline(always)]
|
||||
fn sqrt2() -> float { 1.41421356237309504880168872420969808 }
|
||||
|
||||
/// 1.0 / sqrt(2.0)
|
||||
#[inline(always)]
|
||||
fn frac_1_sqrt2() -> float { 0.707106781186547524400844362104849039 }
|
||||
|
||||
/// Euler's number
|
||||
#[inline(always)]
|
||||
fn e() -> float { 2.71828182845904523536028747135266250 }
|
||||
|
||||
/// log2(e)
|
||||
#[inline(always)]
|
||||
fn log2_e() -> float { 1.44269504088896340735992468100189214 }
|
||||
|
||||
/// log10(e)
|
||||
#[inline(always)]
|
||||
fn log10_e() -> float { 0.434294481903251827651128918916605082 }
|
||||
|
||||
/// log(2.0)
|
||||
#[inline(always)]
|
||||
fn log_2() -> float { 0.693147180559945309417232121458176568 }
|
||||
|
||||
/// log(10.0)
|
||||
#[inline(always)]
|
||||
fn log_10() -> float { 2.30258509299404568401799145468436421 }
|
||||
|
||||
#[inline(always)]
|
||||
fn floor(&self) -> float { floor(*self as f64) as float }
|
||||
|
||||
#[inline(always)]
|
||||
fn ceil(&self) -> float { ceil(*self as f64) as float }
|
||||
|
||||
#[inline(always)]
|
||||
fn round(&self) -> float { round(*self as f64) as float }
|
||||
|
||||
#[inline(always)]
|
||||
fn trunc(&self) -> float { trunc(*self as f64) as float }
|
||||
|
||||
/// The fractional part of the number, calculated using: `n - floor(n)`
|
||||
#[inline(always)]
|
||||
fn fract(&self) -> float { *self - self.floor() }
|
||||
|
||||
#[inline(always)]
|
||||
fn pow(&self, n: float) -> float { pow(*self as f64, n as f64) as float }
|
||||
|
||||
#[inline(always)]
|
||||
fn exp(&self) -> float { exp(*self as f64) as float }
|
||||
|
||||
#[inline(always)]
|
||||
fn exp2(&self) -> float { exp2(*self as f64) as float }
|
||||
|
||||
#[inline(always)]
|
||||
fn expm1(&self) -> float { expm1(*self as f64) as float }
|
||||
|
||||
#[inline(always)]
|
||||
fn ldexp(&self, n: int) -> float { ldexp(*self as f64, n as c_int) as float }
|
||||
|
||||
#[inline(always)]
|
||||
fn log(&self) -> float { ln(*self as f64) as float }
|
||||
|
||||
#[inline(always)]
|
||||
fn log2(&self) -> float { log2(*self as f64) as float }
|
||||
|
||||
#[inline(always)]
|
||||
fn log10(&self) -> float { log10(*self as f64) as float }
|
||||
|
||||
#[inline(always)]
|
||||
fn log_radix(&self) -> float { log_radix(*self as f64) as float }
|
||||
|
||||
#[inline(always)]
|
||||
fn ilog_radix(&self) -> int { ilog_radix(*self as f64) as int }
|
||||
|
||||
#[inline(always)]
|
||||
fn sqrt(&self) -> float { sqrt(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn rsqrt(&self) -> float { self.sqrt().recip() }
|
||||
|
||||
#[inline(always)]
|
||||
fn cbrt(&self) -> float { cbrt(*self as f64) as float }
|
||||
|
||||
/// Converts to degrees, assuming the number is in radians
|
||||
#[inline(always)]
|
||||
fn to_degrees(&self) -> float { *self * (180.0 / Real::pi::<float>()) }
|
||||
|
||||
/// Converts to radians, assuming the number is in degrees
|
||||
#[inline(always)]
|
||||
fn to_radians(&self) -> float { *self * (Real::pi::<float>() / 180.0) }
|
||||
|
||||
#[inline(always)]
|
||||
fn hypot(&self, other: float) -> float { hypot(*self as f64, other as f64) as float }
|
||||
|
||||
#[inline(always)]
|
||||
fn sin(&self) -> float { sin(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn cos(&self) -> float { cos(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn tan(&self) -> float { tan(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn asin(&self) -> float { asin(*self as f64) as float }
|
||||
|
||||
#[inline(always)]
|
||||
fn acos(&self) -> float { acos(*self as f64) as float }
|
||||
|
||||
#[inline(always)]
|
||||
fn atan(&self) -> float { atan(*self) }
|
||||
|
||||
#[inline(always)]
|
||||
fn atan2(&self, other: float) -> float { atan2(*self as f64, other as f64) as float }
|
||||
|
||||
#[inline(always)]
|
||||
fn sinh(&self) -> float { sinh(*self as f64) as float }
|
||||
|
||||
#[inline(always)]
|
||||
fn cosh(&self) -> float { cosh(*self as f64) as float }
|
||||
|
||||
#[inline(always)]
|
||||
fn tanh(&self) -> float { tanh(*self as f64) as float }
|
||||
}
|
||||
|
||||
impl RealExt for float {
|
||||
#[inline(always)]
|
||||
fn lgamma(&self) -> (int, float) {
|
||||
let mut sign = 0;
|
||||
let result = lgamma(*self as f64, &mut sign);
|
||||
(sign as int, result as float)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn floor(&self) -> float { f64::floor(*self as f64) as float}
|
||||
fn tgamma(&self) -> float { tgamma(*self as f64) as float }
|
||||
|
||||
#[inline(always)]
|
||||
fn ceil(&self) -> float { f64::ceil(*self as f64) as float}
|
||||
fn j0(&self) -> float { j0(*self as f64) as float }
|
||||
|
||||
#[inline(always)]
|
||||
fn fract(&self) -> float {
|
||||
if self.is_negative() {
|
||||
(*self) - (f64::ceil(*self as f64) as float)
|
||||
} else {
|
||||
(*self) - (f64::floor(*self as f64) as float)
|
||||
}
|
||||
}
|
||||
fn j1(&self) -> float { j1(*self as f64) as float }
|
||||
|
||||
#[inline(always)]
|
||||
fn jn(&self, n: int) -> float { jn(n as c_int, *self as f64) as float }
|
||||
|
||||
#[inline(always)]
|
||||
fn y0(&self) -> float { y0(*self as f64) as float }
|
||||
|
||||
#[inline(always)]
|
||||
fn y1(&self) -> float { y1(*self as f64) as float }
|
||||
|
||||
#[inline(always)]
|
||||
fn yn(&self, n: int) -> float { yn(n as c_int, *self as f64) as float }
|
||||
}
|
||||
|
||||
#[cfg(notest)]
|
||||
@ -511,11 +680,39 @@ mod tests {
|
||||
use super::*;
|
||||
use prelude::*;
|
||||
|
||||
macro_rules! assert_fuzzy_eq(
|
||||
($a:expr, $b:expr) => ({
|
||||
let a = $a, b = $b;
|
||||
if !((a - b).abs() < 1.0e-6) {
|
||||
fail!(fmt!("The values were not approximately equal. Found: %? and %?", a, b));
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
#[test]
|
||||
fn test_num() {
|
||||
num::test_num(10f, 2f);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_real_consts() {
|
||||
assert_fuzzy_eq!(Real::two_pi::<float>(), 2f * Real::pi::<float>());
|
||||
assert_fuzzy_eq!(Real::frac_pi_2::<float>(), Real::pi::<float>() / 2f);
|
||||
assert_fuzzy_eq!(Real::frac_pi_3::<float>(), Real::pi::<float>() / 3f);
|
||||
assert_fuzzy_eq!(Real::frac_pi_4::<float>(), Real::pi::<float>() / 4f);
|
||||
assert_fuzzy_eq!(Real::frac_pi_6::<float>(), Real::pi::<float>() / 6f);
|
||||
assert_fuzzy_eq!(Real::frac_pi_8::<float>(), Real::pi::<float>() / 8f);
|
||||
assert_fuzzy_eq!(Real::frac_1_pi::<float>(), 1f / Real::pi::<float>());
|
||||
assert_fuzzy_eq!(Real::frac_2_pi::<float>(), 2f / Real::pi::<float>());
|
||||
assert_fuzzy_eq!(Real::frac_2_sqrtpi::<float>(), 2f / Real::pi::<float>().sqrt());
|
||||
assert_fuzzy_eq!(Real::sqrt2::<float>(), 2f.sqrt());
|
||||
assert_fuzzy_eq!(Real::frac_1_sqrt2::<float>(), 1f / 2f.sqrt());
|
||||
assert_fuzzy_eq!(Real::log2_e::<float>(), Real::e::<float>().log2());
|
||||
assert_fuzzy_eq!(Real::log10_e::<float>(), Real::e::<float>().log10());
|
||||
assert_fuzzy_eq!(Real::log_2::<float>(), 2f.log());
|
||||
assert_fuzzy_eq!(Real::log_10::<float>(), 10f.log());
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_signed() {
|
||||
assert_eq!(infinity.abs(), infinity);
|
||||
|
@ -77,19 +77,97 @@ pub trait Integer: Num
|
||||
fn is_odd(&self) -> bool;
|
||||
}
|
||||
|
||||
pub trait Round {
|
||||
fn round(&self, mode: RoundMode) -> Self;
|
||||
|
||||
fn floor(&self) -> Self;
|
||||
fn ceil(&self) -> Self;
|
||||
fn fract(&self) -> Self;
|
||||
pub trait Fractional: Num
|
||||
+ Ord
|
||||
+ Quot<Self,Self> {
|
||||
fn recip(&self) -> Self;
|
||||
}
|
||||
|
||||
pub enum RoundMode {
|
||||
RoundDown,
|
||||
RoundUp,
|
||||
RoundToZero,
|
||||
RoundFromZero
|
||||
pub trait Real: Signed
|
||||
+ Fractional {
|
||||
// FIXME (#5527): usages of `int` should be replaced with an associated
|
||||
// integer type once these are implemented
|
||||
|
||||
// Common Constants
|
||||
// FIXME (#5527): These should be associated constants
|
||||
fn pi() -> Self;
|
||||
fn two_pi() -> Self;
|
||||
fn frac_pi_2() -> Self;
|
||||
fn frac_pi_3() -> Self;
|
||||
fn frac_pi_4() -> Self;
|
||||
fn frac_pi_6() -> Self;
|
||||
fn frac_pi_8() -> Self;
|
||||
fn frac_1_pi() -> Self;
|
||||
fn frac_2_pi() -> Self;
|
||||
fn frac_2_sqrtpi() -> Self;
|
||||
fn sqrt2() -> Self;
|
||||
fn frac_1_sqrt2() -> Self;
|
||||
fn e() -> Self;
|
||||
fn log2_e() -> Self;
|
||||
fn log10_e() -> Self;
|
||||
fn log_2() -> Self;
|
||||
fn log_10() -> Self;
|
||||
|
||||
// Rounding operations
|
||||
fn floor(&self) -> Self;
|
||||
fn ceil(&self) -> Self;
|
||||
fn round(&self) -> Self;
|
||||
fn trunc(&self) -> Self;
|
||||
fn fract(&self) -> Self;
|
||||
|
||||
// Exponential functions
|
||||
fn pow(&self, n: Self) -> Self;
|
||||
fn exp(&self) -> Self;
|
||||
fn exp2(&self) -> Self;
|
||||
fn expm1(&self) -> Self;
|
||||
fn ldexp(&self, n: int) -> Self;
|
||||
fn log(&self) -> Self;
|
||||
fn log2(&self) -> Self;
|
||||
fn log10(&self) -> Self;
|
||||
fn log_radix(&self) -> Self;
|
||||
fn ilog_radix(&self) -> int;
|
||||
fn sqrt(&self) -> Self;
|
||||
fn rsqrt(&self) -> Self;
|
||||
fn cbrt(&self) -> Self;
|
||||
|
||||
// Angular conversions
|
||||
fn to_degrees(&self) -> Self;
|
||||
fn to_radians(&self) -> Self;
|
||||
|
||||
// Triganomic functions
|
||||
fn hypot(&self, other: Self) -> Self;
|
||||
fn sin(&self) -> Self;
|
||||
fn cos(&self) -> Self;
|
||||
fn tan(&self) -> Self;
|
||||
|
||||
// Inverse triganomic functions
|
||||
fn asin(&self) -> Self;
|
||||
fn acos(&self) -> Self;
|
||||
fn atan(&self) -> Self;
|
||||
fn atan2(&self, other: Self) -> Self;
|
||||
|
||||
// Hyperbolic triganomic functions
|
||||
fn sinh(&self) -> Self;
|
||||
fn cosh(&self) -> Self;
|
||||
fn tanh(&self) -> Self;
|
||||
}
|
||||
|
||||
/// Methods that are harder to implement and not commonly used.
|
||||
pub trait RealExt: Real {
|
||||
// FIXME (#5527): usages of `int` should be replaced with an associated
|
||||
// integer type once these are implemented
|
||||
|
||||
// Gamma functions
|
||||
fn lgamma(&self) -> (int, Self);
|
||||
fn tgamma(&self) -> Self;
|
||||
|
||||
// Bessel functions
|
||||
fn j0(&self) -> Self;
|
||||
fn j1(&self) -> Self;
|
||||
fn jn(&self, n: int) -> Self;
|
||||
fn y0(&self) -> Self;
|
||||
fn y1(&self) -> Self;
|
||||
fn yn(&self, n: int) -> Self;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -39,6 +39,7 @@ pub use iter::{CopyableIter, CopyableOrderedIter, CopyableNonstrictIter};
|
||||
pub use iter::{Times, ExtendedMutableIter};
|
||||
pub use num::{Num, NumCast};
|
||||
pub use num::{Signed, Unsigned, Integer};
|
||||
pub use num::{Fractional, Real, RealExt};
|
||||
pub use path::GenericPath;
|
||||
pub use path::Path;
|
||||
pub use path::PosixPath;
|
||||
|
Loading…
x
Reference in New Issue
Block a user