about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/cmp.rs7
-rw-r--r--src/libcore/num/f32.rs25
-rw-r--r--src/libcore/num/f64.rs25
-rw-r--r--src/libcore/num/float.rs25
-rw-r--r--src/libcore/num/num.rs5
-rw-r--r--src/libcore/prelude.rs2
6 files changed, 86 insertions, 3 deletions
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index b933b60a39f..80f1f05961a 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -66,6 +66,13 @@ totaleq_impl!(uint)
 
 totaleq_impl!(char)
 
+/// Trait for testing approximate equality
+pub trait ApproxEq<Eps> {
+    fn approx_epsilon() -> Eps;
+    fn approx_eq(&self, other: &Self) -> bool;
+    fn approx_eq_eps(&self, other: &Self, approx_epsilon: &Eps) -> bool;
+}
+
 #[deriving(Clone, Eq)]
 pub enum Ordering { Less = -1, Equal = 0, Greater = 1 }
 
diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs
index 416ec2069b5..feeb2c3f836 100644
--- a/src/libcore/num/f32.rs
+++ b/src/libcore/num/f32.rs
@@ -211,6 +211,22 @@ impl Eq for f32 {
 }
 
 #[cfg(notest)]
+impl ApproxEq<f32> for f32 {
+    #[inline(always)]
+    fn approx_epsilon() -> f32 { 1.0e-6 }
+
+    #[inline(always)]
+    fn approx_eq(&self, other: &f32) -> bool {
+        self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<f32, f32>())
+    }
+
+    #[inline(always)]
+    fn approx_eq_eps(&self, other: &f32, approx_epsilon: &f32) -> bool {
+        (*self - *other).abs() < *approx_epsilon
+    }
+}
+
+#[cfg(notest)]
 impl Ord for f32 {
     #[inline(always)]
     fn lt(&self, other: &f32) -> bool { (*self) < (*other) }
@@ -975,6 +991,15 @@ mod tests {
     }
 
     #[test]
+    fn test_approx_eq() {
+        assert!(1.0f32.approx_eq(&1f32));
+        assert!(0.9999999f32.approx_eq(&1f32));
+        assert!(1.000001f32.approx_eq_eps(&1f32, &1.0e-5));
+        assert!(1.0000001f32.approx_eq_eps(&1f32, &1.0e-6));
+        assert!(!1.0000001f32.approx_eq_eps(&1f32, &1.0e-7));
+    }
+
+    #[test]
     fn test_primitive() {
         assert_eq!(Primitive::bits::<f32>(), sys::size_of::<f32>() * 8);
         assert_eq!(Primitive::bytes::<f32>(), sys::size_of::<f32>());
diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs
index 6e09ca61a7d..08f9c341188 100644
--- a/src/libcore/num/f64.rs
+++ b/src/libcore/num/f64.rs
@@ -234,6 +234,22 @@ impl Eq for f64 {
 }
 
 #[cfg(notest)]
+impl ApproxEq<f64> for f64 {
+    #[inline(always)]
+    fn approx_epsilon() -> f64 { 1.0e-6 }
+
+    #[inline(always)]
+    fn approx_eq(&self, other: &f64) -> bool {
+        self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<f64, f64>())
+    }
+
+    #[inline(always)]
+    fn approx_eq_eps(&self, other: &f64, approx_epsilon: &f64) -> bool {
+        (*self - *other).abs() < *approx_epsilon
+    }
+}
+
+#[cfg(notest)]
 impl Ord for f64 {
     #[inline(always)]
     fn lt(&self, other: &f64) -> bool { (*self) < (*other) }
@@ -1023,6 +1039,15 @@ mod tests {
     }
 
     #[test]
+    fn test_approx_eq() {
+        assert!(1.0f64.approx_eq(&1f64));
+        assert!(0.9999999f64.approx_eq(&1f64));
+        assert!(1.000001f64.approx_eq_eps(&1f64, &1.0e-5));
+        assert!(1.0000001f64.approx_eq_eps(&1f64, &1.0e-6));
+        assert!(!1.0000001f64.approx_eq_eps(&1f64, &1.0e-7));
+    }
+
+    #[test]
     fn test_primitive() {
         assert_eq!(Primitive::bits::<f64>(), sys::size_of::<f64>() * 8);
         assert_eq!(Primitive::bytes::<f64>(), sys::size_of::<f64>());
diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs
index da9d03f6a7b..61dd741b671 100644
--- a/src/libcore/num/float.rs
+++ b/src/libcore/num/float.rs
@@ -372,6 +372,22 @@ impl Eq for float {
 }
 
 #[cfg(notest)]
+impl ApproxEq<float> for float {
+    #[inline(always)]
+    fn approx_epsilon() -> float { 1.0e-6 }
+
+    #[inline(always)]
+    fn approx_eq(&self, other: &float) -> bool {
+        self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<float, float>())
+    }
+
+    #[inline(always)]
+    fn approx_eq_eps(&self, other: &float, approx_epsilon: &float) -> bool {
+        (*self - *other).abs() < *approx_epsilon
+    }
+}
+
+#[cfg(notest)]
 impl Ord for float {
     #[inline(always)]
     fn lt(&self, other: &float) -> bool { (*self) < (*other) }
@@ -986,6 +1002,15 @@ mod tests {
     }
 
     #[test]
+    fn test_approx_eq() {
+        assert!(1.0f.approx_eq(&1f));
+        assert!(0.9999999f.approx_eq(&1f));
+        assert!(1.000001f.approx_eq_eps(&1f, &1.0e-5));
+        assert!(1.0000001f.approx_eq_eps(&1f, &1.0e-6));
+        assert!(!1.0000001f.approx_eq_eps(&1f, &1.0e-7));
+    }
+
+    #[test]
     fn test_primitive() {
         assert_eq!(Primitive::bits::<float>(), sys::size_of::<float>() * 8);
         assert_eq!(Primitive::bytes::<float>(), sys::size_of::<float>());
diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs
index 1a59a069df7..caa14ea802f 100644
--- a/src/libcore/num/num.rs
+++ b/src/libcore/num/num.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 //! An interface for numeric types
-use cmp::{Eq, Ord};
+use cmp::{Eq, ApproxEq, Ord};
 use ops::{Add, Sub, Mul, Div, Rem, Neg};
 use ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
 use option::Option;
@@ -240,7 +240,8 @@ pub trait Int: Integer
 ///
 pub trait Float: Real
                + Signed
-               + Primitive {
+               + Primitive
+               + ApproxEq<Self> {
     // FIXME (#5527): These should be associated constants
     fn NaN() -> Self;
     fn infinity() -> Self;
diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs
index 42401ae5a1f..10b36d38d43 100644
--- a/src/libcore/prelude.rs
+++ b/src/libcore/prelude.rs
@@ -28,7 +28,7 @@ pub use io::{print, println};
 /* Reexported types and traits */
 
 pub use clone::Clone;
-pub use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater, Equiv};
+pub use cmp::{Eq, ApproxEq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater, Equiv};
 pub use container::{Container, Mutable, Map, Set};
 pub use hash::Hash;
 pub use old_iter::{BaseIter, ReverseIter, MutableIter, ExtendedIter, EqIter};