Skip to content

Commit 6cc7107

Browse files
committed
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).
1 parent 6efbbf2 commit 6cc7107

File tree

8 files changed

+155
-4
lines changed

8 files changed

+155
-4
lines changed

src/libcore/core.rc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,11 @@ pub use iter::{CopyableOrderedIter, CopyableNonstrictIter, Times};
104104
pub use iter::{ExtendedMutableIter};
105105

106106
pub use num::{Num, NumCast};
107-
pub use num::{Signed, Unsigned, Integer};
107+
pub use num::{Orderable, Signed, Unsigned, Integer};
108108
pub use num::{Round, Fractional, Real, RealExt};
109109
pub use num::{Bitwise, BitCount, Bounded};
110110
pub use num::{Primitive, Int, Float};
111+
111112
pub use ptr::Ptr;
112113
pub use to_str::ToStr;
113114
pub use clone::Clone;

src/libcore/num/f32.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,20 @@ impl Ord for f32 {
224224
fn gt(&self, other: &f32) -> bool { (*self) > (*other) }
225225
}
226226

227+
impl Orderable for f32 {
228+
#[inline(always)]
229+
fn min(&self, other: &f32) -> f32 { fmin(*self, *other) }
230+
231+
#[inline(always)]
232+
fn max(&self, other: &f32) -> f32 { fmax(*self, *other) }
233+
234+
#[inline(always)]
235+
fn clamp(&self, mn: &f32, mx: &f32) -> f32 {
236+
if *self > *mx { *mx } else
237+
if *self < *mn { *mn } else { *self }
238+
}
239+
}
240+
227241
impl Zero for f32 {
228242
#[inline(always)]
229243
fn zero() -> f32 { 0.0 }
@@ -768,6 +782,17 @@ mod tests {
768782
num::test_num(10f32, 2f32);
769783
}
770784

785+
#[test]
786+
fn test_orderable() {
787+
assert_eq!(1f32.min(&2f32), 1f32);
788+
assert_eq!(2f32.min(&1f32), 1f32);
789+
assert_eq!(1f32.max(&2f32), 2f32);
790+
assert_eq!(2f32.max(&1f32), 2f32);
791+
assert_eq!(1f32.clamp(&2f32, &4f32), 2f32);
792+
assert_eq!(8f32.clamp(&2f32, &4f32), 4f32);
793+
assert_eq!(3f32.clamp(&2f32, &4f32), 3f32);
794+
}
795+
771796
#[test]
772797
fn test_floor() {
773798
assert_fuzzy_eq!(1.0f32.floor(), 1.0f32);

src/libcore/num/f64.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,20 @@ impl Ord for f64 {
245245
fn gt(&self, other: &f64) -> bool { (*self) > (*other) }
246246
}
247247

248+
impl Orderable for f64 {
249+
#[inline(always)]
250+
fn min(&self, other: &f64) -> f64 { fmin(*self, *other) }
251+
252+
#[inline(always)]
253+
fn max(&self, other: &f64) -> f64 { fmax(*self, *other) }
254+
255+
#[inline(always)]
256+
fn clamp(&self, mn: &f64, mx: &f64) -> f64 {
257+
if *self > *mx { *mx } else
258+
if *self < *mn { *mn } else { *self }
259+
}
260+
}
261+
248262
impl Zero for f64 {
249263
#[inline(always)]
250264
fn zero() -> f64 { 0.0 }
@@ -809,6 +823,17 @@ mod tests {
809823
num::test_num(10f64, 2f64);
810824
}
811825

826+
#[test]
827+
fn test_orderable() {
828+
assert_eq!(1f64.min(&2f64), 1f64);
829+
assert_eq!(2f64.min(&1f64), 1f64);
830+
assert_eq!(1f64.max(&2f64), 2f64);
831+
assert_eq!(2f64.max(&1f64), 2f64);
832+
assert_eq!(1f64.clamp(&2f64, &4f64), 2f64);
833+
assert_eq!(8f64.clamp(&2f64, &4f64), 4f64);
834+
assert_eq!(3f64.clamp(&2f64, &4f64), 3f64);
835+
}
836+
812837
#[test]
813838
fn test_floor() {
814839
assert_fuzzy_eq!(1.0f64.floor(), 1.0f64);

src/libcore/num/float.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,24 @@ impl Ord for float {
384384
fn gt(&self, other: &float) -> bool { (*self) > (*other) }
385385
}
386386
387+
impl Orderable for float {
388+
#[inline(always)]
389+
fn min(&self, other: &float) -> float {
390+
fmin(*self as f64, *other as f64) as float
391+
}
392+
393+
#[inline(always)]
394+
fn max(&self, other: &float) -> float {
395+
fmax(*self as f64, *other as f64) as float
396+
}
397+
398+
#[inline(always)]
399+
fn clamp(&self, mn: &float, mx: &float) -> float {
400+
if *self > *mx { *mx } else
401+
if *self < *mn { *mn } else { *self }
402+
}
403+
}
404+
387405
impl Zero for float {
388406
#[inline(always)]
389407
fn zero() -> float { 0.0 }
@@ -738,6 +756,17 @@ mod tests {
738756
num::test_num(10f, 2f);
739757
}
740758
759+
#[test]
760+
fn test_orderable() {
761+
assert_eq!(1f.min(&2f), 1f);
762+
assert_eq!(2f.min(&1f), 1f);
763+
assert_eq!(1f.max(&2f), 2f);
764+
assert_eq!(2f.max(&1f), 2f);
765+
assert_eq!(1f.clamp(&2f, &4f), 2f);
766+
assert_eq!(8f.clamp(&2f, &4f), 4f);
767+
assert_eq!(3f.clamp(&2f, &4f), 3f);
768+
}
769+
741770
#[test]
742771
fn test_floor() {
743772
assert_fuzzy_eq!(1.0f.floor(), 1.0f);

src/libcore/num/int-template.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,24 @@ impl Eq for T {
152152
fn ne(&self, other: &T) -> bool { return (*self) != (*other); }
153153
}
154154
155+
impl Orderable for T {
156+
#[inline(always)]
157+
fn min(&self, other: &T) -> T {
158+
if *self < *other { *self } else { *other }
159+
}
160+
161+
#[inline(always)]
162+
fn max(&self, other: &T) -> T {
163+
if *self > *other { *self } else { *other }
164+
}
165+
166+
#[inline(always)]
167+
fn clamp(&self, mn: &T, mx: &T) -> T {
168+
if *self > *mx { *mx } else
169+
if *self < *mn { *mn } else { *self }
170+
}
171+
}
172+
155173
impl Zero for T {
156174
#[inline(always)]
157175
fn zero() -> T { 0 }
@@ -535,6 +553,17 @@ mod tests {
535553
num::test_num(10 as T, 2 as T);
536554
}
537555
556+
#[test]
557+
fn test_orderable() {
558+
assert_eq!((1 as T).min(&(2 as T)), 1 as T);
559+
assert_eq!((2 as T).min(&(1 as T)), 1 as T);
560+
assert_eq!((1 as T).max(&(2 as T)), 2 as T);
561+
assert_eq!((2 as T).max(&(1 as T)), 2 as T);
562+
assert_eq!((1 as T).clamp(&(2 as T), &(4 as T)), 2 as T);
563+
assert_eq!((8 as T).clamp(&(2 as T), &(4 as T)), 4 as T);
564+
assert_eq!((3 as T).clamp(&(2 as T), &(4 as T)), 3 as T);
565+
}
566+
538567
#[test]
539568
pub fn test_signed() {
540569
assert_eq!((1 as T).abs(), 1 as T);

src/libcore/num/num.rs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ use kinds::Copy;
2424

2525
pub mod strconv;
2626

27+
///
28+
/// The base trait for numeric types
29+
///
2730
pub trait Num: Eq + Zero + One
2831
+ Neg<Self>
2932
+ Add<Self,Self>
@@ -37,6 +40,16 @@ pub trait IntConvertible {
3740
fn from_int(n: int) -> Self;
3841
}
3942

43+
pub trait Orderable: Ord {
44+
// These should be methods on `Ord`, with overridable default implementations. We don't want
45+
// to encumber all implementors of Ord by requiring them to implement these functions, but at
46+
// the same time we want to be able to take advantage of the speed of the specific numeric
47+
// functions (like the `fmin` and `fmax` intrinsics).
48+
fn min(&self, other: &Self) -> Self;
49+
fn max(&self, other: &Self) -> Self;
50+
fn clamp(&self, mn: &Self, mx: &Self) -> Self;
51+
}
52+
4053
pub trait Zero {
4154
fn zero() -> Self; // FIXME (#5527): This should be an associated constant
4255
fn is_zero(&self) -> bool;
@@ -62,7 +75,7 @@ pub fn abs<T:Ord + Zero + Neg<T>>(v: T) -> T {
6275
}
6376

6477
pub trait Integer: Num
65-
+ Ord
78+
+ Orderable
6679
+ Quot<Self,Self>
6780
+ Rem<Self,Self> {
6881
fn div(&self, other: &Self) -> Self;
@@ -86,7 +99,7 @@ pub trait Round {
8699
}
87100

88101
pub trait Fractional: Num
89-
+ Ord
102+
+ Orderable
90103
+ Round
91104
+ Quot<Self,Self> {
92105
fn recip(&self) -> Self;

src/libcore/num/uint-template.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,24 @@ impl Eq for T {
117117
fn ne(&self, other: &T) -> bool { return (*self) != (*other); }
118118
}
119119
120+
impl Orderable for T {
121+
#[inline(always)]
122+
fn min(&self, other: &T) -> T {
123+
if *self < *other { *self } else { *other }
124+
}
125+
126+
#[inline(always)]
127+
fn max(&self, other: &T) -> T {
128+
if *self > *other { *self } else { *other }
129+
}
130+
131+
#[inline(always)]
132+
fn clamp(&self, mn: &T, mx: &T) -> T {
133+
if *self > *mx { *mx } else
134+
if *self < *mn { *mn } else { *self }
135+
}
136+
}
137+
120138
impl Zero for T {
121139
#[inline(always)]
122140
fn zero() -> T { 0 }
@@ -367,6 +385,17 @@ mod tests {
367385
num::test_num(10 as T, 2 as T);
368386
}
369387
388+
#[test]
389+
fn test_orderable() {
390+
assert_eq!((1 as T).min(&(2 as T)), 1 as T);
391+
assert_eq!((2 as T).min(&(1 as T)), 1 as T);
392+
assert_eq!((1 as T).max(&(2 as T)), 2 as T);
393+
assert_eq!((2 as T).max(&(1 as T)), 2 as T);
394+
assert_eq!((1 as T).clamp(&(2 as T), &(4 as T)), 2 as T);
395+
assert_eq!((8 as T).clamp(&(2 as T), &(4 as T)), 4 as T);
396+
assert_eq!((3 as T).clamp(&(2 as T), &(4 as T)), 3 as T);
397+
}
398+
370399
#[test]
371400
fn test_gcd() {
372401
assert_eq!((10 as T).gcd(&2), 2 as T);

src/libcore/prelude.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub use iter::{BaseIter, ReverseIter, MutableIter, ExtendedIter, EqIter};
3838
pub use iter::{CopyableIter, CopyableOrderedIter, CopyableNonstrictIter};
3939
pub use iter::{Times, ExtendedMutableIter};
4040
pub use num::{Num, NumCast};
41-
pub use num::{Signed, Unsigned, Integer};
41+
pub use num::{Orderable, Signed, Unsigned, Integer};
4242
pub use num::{Round, Fractional, Real, RealExt};
4343
pub use num::{Bitwise, BitCount, Bounded};
4444
pub use num::{Primitive, Int, Float};

0 commit comments

Comments
 (0)