diff --git a/src/libcore/core.rc b/src/libcore/core.rc index 0a24fba6663..71bbaf557ce 100644 --- a/src/libcore/core.rc +++ b/src/libcore/core.rc @@ -105,7 +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 num::{Round, Fractional, Real, RealExt}; pub use ptr::Ptr; pub use to_str::ToStr; pub use clone::Clone; diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 57ac6c55176..7d5807ba546 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -327,6 +327,34 @@ impl Signed for f32 { fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity } } +impl Round for f32 { + /// Round half-way cases toward `neg_infinity` + #[inline(always)] + fn floor(&self) -> f32 { floor(*self) } + + /// Round half-way cases toward `infinity` + #[inline(always)] + fn ceil(&self) -> f32 { ceil(*self) } + + /// Round half-way cases away from `0.0` + #[inline(always)] + fn round(&self) -> f32 { round(*self) } + + /// The integer part of the number (rounds towards `0.0`) + #[inline(always)] + fn trunc(&self) -> f32 { trunc(*self) } + + /// + /// The fractional part of the number, satisfying: + /// + /// ~~~ + /// assert!(x == trunc(x) + fract(x)) + /// ~~~ + /// + #[inline(always)] + fn fract(&self) -> f32 { *self - self.trunc() } +} + impl Fractional for f32 { /// The reciprocal (multiplicative inverse) of the number #[inline(always)] @@ -402,22 +430,6 @@ impl Real for f32 { #[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 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) } @@ -736,6 +748,76 @@ mod tests { num::test_num(10f32, 2f32); } + #[test] + fn test_floor() { + assert_fuzzy_eq!(1.0f32.floor(), 1.0f32); + assert_fuzzy_eq!(1.3f32.floor(), 1.0f32); + assert_fuzzy_eq!(1.5f32.floor(), 1.0f32); + assert_fuzzy_eq!(1.7f32.floor(), 1.0f32); + assert_fuzzy_eq!(0.0f32.floor(), 0.0f32); + assert_fuzzy_eq!((-0.0f32).floor(), -0.0f32); + assert_fuzzy_eq!((-1.0f32).floor(), -1.0f32); + assert_fuzzy_eq!((-1.3f32).floor(), -2.0f32); + assert_fuzzy_eq!((-1.5f32).floor(), -2.0f32); + assert_fuzzy_eq!((-1.7f32).floor(), -2.0f32); + } + + #[test] + fn test_ceil() { + assert_fuzzy_eq!(1.0f32.ceil(), 1.0f32); + assert_fuzzy_eq!(1.3f32.ceil(), 2.0f32); + assert_fuzzy_eq!(1.5f32.ceil(), 2.0f32); + assert_fuzzy_eq!(1.7f32.ceil(), 2.0f32); + assert_fuzzy_eq!(0.0f32.ceil(), 0.0f32); + assert_fuzzy_eq!((-0.0f32).ceil(), -0.0f32); + assert_fuzzy_eq!((-1.0f32).ceil(), -1.0f32); + assert_fuzzy_eq!((-1.3f32).ceil(), -1.0f32); + assert_fuzzy_eq!((-1.5f32).ceil(), -1.0f32); + assert_fuzzy_eq!((-1.7f32).ceil(), -1.0f32); + } + + #[test] + fn test_round() { + assert_fuzzy_eq!(1.0f32.round(), 1.0f32); + assert_fuzzy_eq!(1.3f32.round(), 1.0f32); + assert_fuzzy_eq!(1.5f32.round(), 2.0f32); + assert_fuzzy_eq!(1.7f32.round(), 2.0f32); + assert_fuzzy_eq!(0.0f32.round(), 0.0f32); + assert_fuzzy_eq!((-0.0f32).round(), -0.0f32); + assert_fuzzy_eq!((-1.0f32).round(), -1.0f32); + assert_fuzzy_eq!((-1.3f32).round(), -1.0f32); + assert_fuzzy_eq!((-1.5f32).round(), -2.0f32); + assert_fuzzy_eq!((-1.7f32).round(), -2.0f32); + } + + #[test] + fn test_trunc() { + assert_fuzzy_eq!(1.0f32.trunc(), 1.0f32); + assert_fuzzy_eq!(1.3f32.trunc(), 1.0f32); + assert_fuzzy_eq!(1.5f32.trunc(), 1.0f32); + assert_fuzzy_eq!(1.7f32.trunc(), 1.0f32); + assert_fuzzy_eq!(0.0f32.trunc(), 0.0f32); + assert_fuzzy_eq!((-0.0f32).trunc(), -0.0f32); + assert_fuzzy_eq!((-1.0f32).trunc(), -1.0f32); + assert_fuzzy_eq!((-1.3f32).trunc(), -1.0f32); + assert_fuzzy_eq!((-1.5f32).trunc(), -1.0f32); + assert_fuzzy_eq!((-1.7f32).trunc(), -1.0f32); + } + + #[test] + fn test_fract() { + assert_fuzzy_eq!(1.0f32.fract(), 0.0f32); + assert_fuzzy_eq!(1.3f32.fract(), 0.3f32); + assert_fuzzy_eq!(1.5f32.fract(), 0.5f32); + assert_fuzzy_eq!(1.7f32.fract(), 0.7f32); + assert_fuzzy_eq!(0.0f32.fract(), 0.0f32); + assert_fuzzy_eq!((-0.0f32).fract(), -0.0f32); + assert_fuzzy_eq!((-1.0f32).fract(), -0.0f32); + assert_fuzzy_eq!((-1.3f32).fract(), -0.3f32); + assert_fuzzy_eq!((-1.5f32).fract(), -0.5f32); + assert_fuzzy_eq!((-1.7f32).fract(), -0.7f32); + } + #[test] fn test_real_consts() { assert_fuzzy_eq!(Real::two_pi::(), 2f32 * Real::pi::()); diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 53ad78c29f3..3b6198bfc47 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -337,6 +337,34 @@ impl Signed for f64 { fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity } } +impl Round for f64 { + /// Round half-way cases toward `neg_infinity` + #[inline(always)] + fn floor(&self) -> f64 { floor(*self) } + + /// Round half-way cases toward `infinity` + #[inline(always)] + fn ceil(&self) -> f64 { ceil(*self) } + + /// Round half-way cases away from `0.0` + #[inline(always)] + fn round(&self) -> f64 { round(*self) } + + /// The integer part of the number (rounds towards `0.0`) + #[inline(always)] + fn trunc(&self) -> f64 { trunc(*self) } + + /// + /// The fractional part of the number, satisfying: + /// + /// ~~~ + /// assert!(x == trunc(x) + fract(x)) + /// ~~~ + /// + #[inline(always)] + fn fract(&self) -> f64 { *self - self.trunc() } +} + impl Fractional for f64 { /// The reciprocal (multiplicative inverse) of the number #[inline(always)] @@ -412,22 +440,6 @@ impl Real for f64 { #[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 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) } @@ -766,7 +778,8 @@ mod tests { ($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)); + fail!(fmt!("The values were not approximately equal. \ + Found: %? and expected %?", a, b)); } }) ) @@ -776,6 +789,76 @@ mod tests { num::test_num(10f64, 2f64); } + #[test] + fn test_floor() { + assert_fuzzy_eq!(1.0f64.floor(), 1.0f64); + assert_fuzzy_eq!(1.3f64.floor(), 1.0f64); + assert_fuzzy_eq!(1.5f64.floor(), 1.0f64); + assert_fuzzy_eq!(1.7f64.floor(), 1.0f64); + assert_fuzzy_eq!(0.0f64.floor(), 0.0f64); + assert_fuzzy_eq!((-0.0f64).floor(), -0.0f64); + assert_fuzzy_eq!((-1.0f64).floor(), -1.0f64); + assert_fuzzy_eq!((-1.3f64).floor(), -2.0f64); + assert_fuzzy_eq!((-1.5f64).floor(), -2.0f64); + assert_fuzzy_eq!((-1.7f64).floor(), -2.0f64); + } + + #[test] + fn test_ceil() { + assert_fuzzy_eq!(1.0f64.ceil(), 1.0f64); + assert_fuzzy_eq!(1.3f64.ceil(), 2.0f64); + assert_fuzzy_eq!(1.5f64.ceil(), 2.0f64); + assert_fuzzy_eq!(1.7f64.ceil(), 2.0f64); + assert_fuzzy_eq!(0.0f64.ceil(), 0.0f64); + assert_fuzzy_eq!((-0.0f64).ceil(), -0.0f64); + assert_fuzzy_eq!((-1.0f64).ceil(), -1.0f64); + assert_fuzzy_eq!((-1.3f64).ceil(), -1.0f64); + assert_fuzzy_eq!((-1.5f64).ceil(), -1.0f64); + assert_fuzzy_eq!((-1.7f64).ceil(), -1.0f64); + } + + #[test] + fn test_round() { + assert_fuzzy_eq!(1.0f64.round(), 1.0f64); + assert_fuzzy_eq!(1.3f64.round(), 1.0f64); + assert_fuzzy_eq!(1.5f64.round(), 2.0f64); + assert_fuzzy_eq!(1.7f64.round(), 2.0f64); + assert_fuzzy_eq!(0.0f64.round(), 0.0f64); + assert_fuzzy_eq!((-0.0f64).round(), -0.0f64); + assert_fuzzy_eq!((-1.0f64).round(), -1.0f64); + assert_fuzzy_eq!((-1.3f64).round(), -1.0f64); + assert_fuzzy_eq!((-1.5f64).round(), -2.0f64); + assert_fuzzy_eq!((-1.7f64).round(), -2.0f64); + } + + #[test] + fn test_trunc() { + assert_fuzzy_eq!(1.0f64.trunc(), 1.0f64); + assert_fuzzy_eq!(1.3f64.trunc(), 1.0f64); + assert_fuzzy_eq!(1.5f64.trunc(), 1.0f64); + assert_fuzzy_eq!(1.7f64.trunc(), 1.0f64); + assert_fuzzy_eq!(0.0f64.trunc(), 0.0f64); + assert_fuzzy_eq!((-0.0f64).trunc(), -0.0f64); + assert_fuzzy_eq!((-1.0f64).trunc(), -1.0f64); + assert_fuzzy_eq!((-1.3f64).trunc(), -1.0f64); + assert_fuzzy_eq!((-1.5f64).trunc(), -1.0f64); + assert_fuzzy_eq!((-1.7f64).trunc(), -1.0f64); + } + + #[test] + fn test_fract() { + assert_fuzzy_eq!(1.0f64.fract(), 0.0f64); + assert_fuzzy_eq!(1.3f64.fract(), 0.3f64); + assert_fuzzy_eq!(1.5f64.fract(), 0.5f64); + assert_fuzzy_eq!(1.7f64.fract(), 0.7f64); + assert_fuzzy_eq!(0.0f64.fract(), 0.0f64); + assert_fuzzy_eq!((-0.0f64).fract(), -0.0f64); + assert_fuzzy_eq!((-1.0f64).fract(), -0.0f64); + assert_fuzzy_eq!((-1.3f64).fract(), -0.3f64); + assert_fuzzy_eq!((-1.5f64).fract(), -0.5f64); + assert_fuzzy_eq!((-1.7f64).fract(), -0.7f64); + } + #[test] fn test_real_consts() { assert_fuzzy_eq!(Real::two_pi::(), 2.0 * Real::pi::()); diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index ae2d0ce0d71..9c0412b422f 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -403,6 +403,34 @@ impl num::One for float { fn one() -> float { 1.0 } } +impl Round for float { + /// Round half-way cases toward `neg_infinity` + #[inline(always)] + fn floor(&self) -> float { floor(*self as f64) as float } + + /// Round half-way cases toward `infinity` + #[inline(always)] + fn ceil(&self) -> float { ceil(*self as f64) as float } + + /// Round half-way cases away from `0.0` + #[inline(always)] + fn round(&self) -> float { round(*self as f64) as float } + + /// The integer part of the number (rounds towards `0.0`) + #[inline(always)] + fn trunc(&self) -> float { trunc(*self as f64) as float } + + /// + /// The fractional part of the number, satisfying: + /// + /// ~~~ + /// assert!(x == trunc(x) + fract(x)) + /// ~~~ + /// + #[inline(always)] + fn fract(&self) -> float { *self - self.trunc() } +} + impl Fractional for float { /// The reciprocal (multiplicative inverse) of the number #[inline(always)] @@ -478,22 +506,6 @@ impl Real for float { #[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 } @@ -694,6 +706,76 @@ mod tests { num::test_num(10f, 2f); } + #[test] + fn test_floor() { + assert_fuzzy_eq!(1.0f.floor(), 1.0f); + assert_fuzzy_eq!(1.3f.floor(), 1.0f); + assert_fuzzy_eq!(1.5f.floor(), 1.0f); + assert_fuzzy_eq!(1.7f.floor(), 1.0f); + assert_fuzzy_eq!(0.0f.floor(), 0.0f); + assert_fuzzy_eq!((-0.0f).floor(), -0.0f); + assert_fuzzy_eq!((-1.0f).floor(), -1.0f); + assert_fuzzy_eq!((-1.3f).floor(), -2.0f); + assert_fuzzy_eq!((-1.5f).floor(), -2.0f); + assert_fuzzy_eq!((-1.7f).floor(), -2.0f); + } + + #[test] + fn test_ceil() { + assert_fuzzy_eq!(1.0f.ceil(), 1.0f); + assert_fuzzy_eq!(1.3f.ceil(), 2.0f); + assert_fuzzy_eq!(1.5f.ceil(), 2.0f); + assert_fuzzy_eq!(1.7f.ceil(), 2.0f); + assert_fuzzy_eq!(0.0f.ceil(), 0.0f); + assert_fuzzy_eq!((-0.0f).ceil(), -0.0f); + assert_fuzzy_eq!((-1.0f).ceil(), -1.0f); + assert_fuzzy_eq!((-1.3f).ceil(), -1.0f); + assert_fuzzy_eq!((-1.5f).ceil(), -1.0f); + assert_fuzzy_eq!((-1.7f).ceil(), -1.0f); + } + + #[test] + fn test_round() { + assert_fuzzy_eq!(1.0f.round(), 1.0f); + assert_fuzzy_eq!(1.3f.round(), 1.0f); + assert_fuzzy_eq!(1.5f.round(), 2.0f); + assert_fuzzy_eq!(1.7f.round(), 2.0f); + assert_fuzzy_eq!(0.0f.round(), 0.0f); + assert_fuzzy_eq!((-0.0f).round(), -0.0f); + assert_fuzzy_eq!((-1.0f).round(), -1.0f); + assert_fuzzy_eq!((-1.3f).round(), -1.0f); + assert_fuzzy_eq!((-1.5f).round(), -2.0f); + assert_fuzzy_eq!((-1.7f).round(), -2.0f); + } + + #[test] + fn test_trunc() { + assert_fuzzy_eq!(1.0f.trunc(), 1.0f); + assert_fuzzy_eq!(1.3f.trunc(), 1.0f); + assert_fuzzy_eq!(1.5f.trunc(), 1.0f); + assert_fuzzy_eq!(1.7f.trunc(), 1.0f); + assert_fuzzy_eq!(0.0f.trunc(), 0.0f); + assert_fuzzy_eq!((-0.0f).trunc(), -0.0f); + assert_fuzzy_eq!((-1.0f).trunc(), -1.0f); + assert_fuzzy_eq!((-1.3f).trunc(), -1.0f); + assert_fuzzy_eq!((-1.5f).trunc(), -1.0f); + assert_fuzzy_eq!((-1.7f).trunc(), -1.0f); + } + + #[test] + fn test_fract() { + assert_fuzzy_eq!(1.0f.fract(), 0.0f); + assert_fuzzy_eq!(1.3f.fract(), 0.3f); + assert_fuzzy_eq!(1.5f.fract(), 0.5f); + assert_fuzzy_eq!(1.7f.fract(), 0.7f); + assert_fuzzy_eq!(0.0f.fract(), 0.0f); + assert_fuzzy_eq!((-0.0f).fract(), -0.0f); + assert_fuzzy_eq!((-1.0f).fract(), -0.0f); + assert_fuzzy_eq!((-1.3f).fract(), -0.3f); + assert_fuzzy_eq!((-1.5f).fract(), -0.5f); + assert_fuzzy_eq!((-1.7f).fract(), -0.7f); + } + #[test] fn test_real_consts() { assert_fuzzy_eq!(Real::two_pi::(), 2f * Real::pi::()); @@ -893,15 +975,6 @@ mod tests { assert_eq!(to_str_digits(infinity, 10u), ~"inf"); assert_eq!(to_str_digits(-infinity, 10u), ~"-inf"); } - - #[test] - pub fn test_round() { - assert_eq!(round(5.8), 6.0); - assert_eq!(round(5.2), 5.0); - assert_eq!(round(3.0), 3.0); - assert_eq!(round(2.5), 3.0); - assert_eq!(round(-3.5), -4.0); - } } // diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index 733b37e2a4a..e19afdc69c3 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -77,8 +77,17 @@ pub trait Integer: Num fn is_odd(&self) -> bool; } +pub trait Round { + fn floor(&self) -> Self; + fn ceil(&self) -> Self; + fn round(&self) -> Self; + fn trunc(&self) -> Self; + fn fract(&self) -> Self; +} + pub trait Fractional: Num + Ord + + Round + Quot { fn recip(&self) -> Self; } @@ -108,13 +117,6 @@ pub trait Real: Signed 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; diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index c161bd4cf59..553bb826810 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -39,7 +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 num::{Round, Fractional, Real, RealExt}; pub use path::GenericPath; pub use path::Path; pub use path::PosixPath;