Restore Round trait and move appropriate methods out of Real

This commit is contained in:
Brendan Zabarauskas 2013-04-25 11:53:04 +10:00
parent dcd49ccd0b
commit 48c24188f9
6 changed files with 307 additions and 67 deletions

View file

@ -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;

View file

@ -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::<f32>(), 2f32 * Real::pi::<f32>());

View file

@ -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::<f64>(), 2.0 * Real::pi::<f64>());

View file

@ -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::<float>(), 2f * Real::pi::<float>());
@ -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);
}
}
//

View file

@ -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<Self,Self> {
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;

View file

@ -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;