提交 6cc7107a 编写于 作者: B Brendan Zabarauskas

Add Orderable trait

This is a temporary trait until we have default methods. We don't want to encumber all implementors of Ord by requiring them to implement these functions, but at the same time we want to be able to take advantage of the speed of the specific numeric functions (like the `fmin` and `fmax` intrinsics).
上级 6efbbf2e
......@@ -104,10 +104,11 @@ pub use iter::{CopyableOrderedIter, CopyableNonstrictIter, Times};
pub use iter::{ExtendedMutableIter};
pub use num::{Num, NumCast};
pub use num::{Signed, Unsigned, Integer};
pub use num::{Orderable, Signed, Unsigned, Integer};
pub use num::{Round, Fractional, Real, RealExt};
pub use num::{Bitwise, BitCount, Bounded};
pub use num::{Primitive, Int, Float};
pub use ptr::Ptr;
pub use to_str::ToStr;
pub use clone::Clone;
......
......@@ -224,6 +224,20 @@ fn ge(&self, other: &f32) -> bool { (*self) >= (*other) }
fn gt(&self, other: &f32) -> bool { (*self) > (*other) }
}
impl Orderable for f32 {
#[inline(always)]
fn min(&self, other: &f32) -> f32 { fmin(*self, *other) }
#[inline(always)]
fn max(&self, other: &f32) -> f32 { fmax(*self, *other) }
#[inline(always)]
fn clamp(&self, mn: &f32, mx: &f32) -> f32 {
if *self > *mx { *mx } else
if *self < *mn { *mn } else { *self }
}
}
impl Zero for f32 {
#[inline(always)]
fn zero() -> f32 { 0.0 }
......@@ -768,6 +782,17 @@ fn test_num() {
num::test_num(10f32, 2f32);
}
#[test]
fn test_orderable() {
assert_eq!(1f32.min(&2f32), 1f32);
assert_eq!(2f32.min(&1f32), 1f32);
assert_eq!(1f32.max(&2f32), 2f32);
assert_eq!(2f32.max(&1f32), 2f32);
assert_eq!(1f32.clamp(&2f32, &4f32), 2f32);
assert_eq!(8f32.clamp(&2f32, &4f32), 4f32);
assert_eq!(3f32.clamp(&2f32, &4f32), 3f32);
}
#[test]
fn test_floor() {
assert_fuzzy_eq!(1.0f32.floor(), 1.0f32);
......
......@@ -245,6 +245,20 @@ fn ge(&self, other: &f64) -> bool { (*self) >= (*other) }
fn gt(&self, other: &f64) -> bool { (*self) > (*other) }
}
impl Orderable for f64 {
#[inline(always)]
fn min(&self, other: &f64) -> f64 { fmin(*self, *other) }
#[inline(always)]
fn max(&self, other: &f64) -> f64 { fmax(*self, *other) }
#[inline(always)]
fn clamp(&self, mn: &f64, mx: &f64) -> f64 {
if *self > *mx { *mx } else
if *self < *mn { *mn } else { *self }
}
}
impl Zero for f64 {
#[inline(always)]
fn zero() -> f64 { 0.0 }
......@@ -809,6 +823,17 @@ fn test_num() {
num::test_num(10f64, 2f64);
}
#[test]
fn test_orderable() {
assert_eq!(1f64.min(&2f64), 1f64);
assert_eq!(2f64.min(&1f64), 1f64);
assert_eq!(1f64.max(&2f64), 2f64);
assert_eq!(2f64.max(&1f64), 2f64);
assert_eq!(1f64.clamp(&2f64, &4f64), 2f64);
assert_eq!(8f64.clamp(&2f64, &4f64), 4f64);
assert_eq!(3f64.clamp(&2f64, &4f64), 3f64);
}
#[test]
fn test_floor() {
assert_fuzzy_eq!(1.0f64.floor(), 1.0f64);
......
......@@ -384,6 +384,24 @@ fn ge(&self, other: &float) -> bool { (*self) >= (*other) }
fn gt(&self, other: &float) -> bool { (*self) > (*other) }
}
impl Orderable for float {
#[inline(always)]
fn min(&self, other: &float) -> float {
fmin(*self as f64, *other as f64) as float
}
#[inline(always)]
fn max(&self, other: &float) -> float {
fmax(*self as f64, *other as f64) as float
}
#[inline(always)]
fn clamp(&self, mn: &float, mx: &float) -> float {
if *self > *mx { *mx } else
if *self < *mn { *mn } else { *self }
}
}
impl Zero for float {
#[inline(always)]
fn zero() -> float { 0.0 }
......@@ -738,6 +756,17 @@ fn test_num() {
num::test_num(10f, 2f);
}
#[test]
fn test_orderable() {
assert_eq!(1f.min(&2f), 1f);
assert_eq!(2f.min(&1f), 1f);
assert_eq!(1f.max(&2f), 2f);
assert_eq!(2f.max(&1f), 2f);
assert_eq!(1f.clamp(&2f, &4f), 2f);
assert_eq!(8f.clamp(&2f, &4f), 4f);
assert_eq!(3f.clamp(&2f, &4f), 3f);
}
#[test]
fn test_floor() {
assert_fuzzy_eq!(1.0f.floor(), 1.0f);
......
......@@ -152,6 +152,24 @@ impl Eq for T {
fn ne(&self, other: &T) -> bool { return (*self) != (*other); }
}
impl Orderable for T {
#[inline(always)]
fn min(&self, other: &T) -> T {
if *self < *other { *self } else { *other }
}
#[inline(always)]
fn max(&self, other: &T) -> T {
if *self > *other { *self } else { *other }
}
#[inline(always)]
fn clamp(&self, mn: &T, mx: &T) -> T {
if *self > *mx { *mx } else
if *self < *mn { *mn } else { *self }
}
}
impl Zero for T {
#[inline(always)]
fn zero() -> T { 0 }
......@@ -535,6 +553,17 @@ fn test_num() {
num::test_num(10 as T, 2 as T);
}
#[test]
fn test_orderable() {
assert_eq!((1 as T).min(&(2 as T)), 1 as T);
assert_eq!((2 as T).min(&(1 as T)), 1 as T);
assert_eq!((1 as T).max(&(2 as T)), 2 as T);
assert_eq!((2 as T).max(&(1 as T)), 2 as T);
assert_eq!((1 as T).clamp(&(2 as T), &(4 as T)), 2 as T);
assert_eq!((8 as T).clamp(&(2 as T), &(4 as T)), 4 as T);
assert_eq!((3 as T).clamp(&(2 as T), &(4 as T)), 3 as T);
}
#[test]
pub fn test_signed() {
assert_eq!((1 as T).abs(), 1 as T);
......
......@@ -24,6 +24,9 @@
pub mod strconv;
///
/// The base trait for numeric types
///
pub trait Num: Eq + Zero + One
+ Neg<Self>
+ Add<Self,Self>
......@@ -37,6 +40,16 @@ pub trait IntConvertible {
fn from_int(n: int) -> Self;
}
pub trait Orderable: Ord {
// These should be methods on `Ord`, with overridable default implementations. We don't want
// to encumber all implementors of Ord by requiring them to implement these functions, but at
// the same time we want to be able to take advantage of the speed of the specific numeric
// functions (like the `fmin` and `fmax` intrinsics).
fn min(&self, other: &Self) -> Self;
fn max(&self, other: &Self) -> Self;
fn clamp(&self, mn: &Self, mx: &Self) -> Self;
}
pub trait Zero {
fn zero() -> Self; // FIXME (#5527): This should be an associated constant
fn is_zero(&self) -> bool;
......@@ -62,7 +75,7 @@ pub fn abs<T:Ord + Zero + Neg<T>>(v: T) -> T {
}
pub trait Integer: Num
+ Ord
+ Orderable
+ Quot<Self,Self>
+ Rem<Self,Self> {
fn div(&self, other: &Self) -> Self;
......@@ -86,7 +99,7 @@ pub trait Round {
}
pub trait Fractional: Num
+ Ord
+ Orderable
+ Round
+ Quot<Self,Self> {
fn recip(&self) -> Self;
......
......@@ -117,6 +117,24 @@ impl Eq for T {
fn ne(&self, other: &T) -> bool { return (*self) != (*other); }
}
impl Orderable for T {
#[inline(always)]
fn min(&self, other: &T) -> T {
if *self < *other { *self } else { *other }
}
#[inline(always)]
fn max(&self, other: &T) -> T {
if *self > *other { *self } else { *other }
}
#[inline(always)]
fn clamp(&self, mn: &T, mx: &T) -> T {
if *self > *mx { *mx } else
if *self < *mn { *mn } else { *self }
}
}
impl Zero for T {
#[inline(always)]
fn zero() -> T { 0 }
......@@ -367,6 +385,17 @@ fn test_num() {
num::test_num(10 as T, 2 as T);
}
#[test]
fn test_orderable() {
assert_eq!((1 as T).min(&(2 as T)), 1 as T);
assert_eq!((2 as T).min(&(1 as T)), 1 as T);
assert_eq!((1 as T).max(&(2 as T)), 2 as T);
assert_eq!((2 as T).max(&(1 as T)), 2 as T);
assert_eq!((1 as T).clamp(&(2 as T), &(4 as T)), 2 as T);
assert_eq!((8 as T).clamp(&(2 as T), &(4 as T)), 4 as T);
assert_eq!((3 as T).clamp(&(2 as T), &(4 as T)), 3 as T);
}
#[test]
fn test_gcd() {
assert_eq!((10 as T).gcd(&2), 2 as T);
......
......@@ -38,7 +38,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::{Orderable, Signed, Unsigned, Integer};
pub use num::{Round, Fractional, Real, RealExt};
pub use num::{Bitwise, BitCount, Bounded};
pub use num::{Primitive, Int, Float};
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册