about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libcore/cmp.rs7
-rw-r--r--src/libcore/num/f32.rs164
-rw-r--r--src/libcore/num/f64.rs165
-rw-r--r--src/libcore/num/float.rs164
-rw-r--r--src/libcore/num/num.rs5
-rw-r--r--src/libcore/prelude.rs2
-rw-r--r--src/libstd/cmp.rs102
-rw-r--r--src/libstd/std.rc1
-rw-r--r--src/libsyntax/ext/expand.rs36
-rw-r--r--src/test/run-fail/assert-approx-eq-eps-macro-fail.rs14
-rw-r--r--src/test/run-fail/assert-approx-eq-macro-fail.rs14
-rw-r--r--src/test/run-pass/assert-approx-eq-macro-success.rs16
-rw-r--r--src/test/run-pass/intrinsics-math.rs56
-rw-r--r--src/test/run-pass/trait-inheritance-num.rs3
-rw-r--r--src/test/run-pass/trait-inheritance-num2.rs3
15 files changed, 389 insertions, 363 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..7c13f136a80 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) }
@@ -810,15 +826,6 @@ mod tests {
     use super::*;
     use prelude::*;
 
-    macro_rules! assert_fuzzy_eq(
-        ($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));
-            }
-        })
-    )
-
     #[test]
     fn test_num() {
         num::test_num(10f32, 2f32);
@@ -848,91 +855,91 @@ mod tests {
 
     #[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);
+        assert_approx_eq!(1.0f32.floor(), 1.0f32);
+        assert_approx_eq!(1.3f32.floor(), 1.0f32);
+        assert_approx_eq!(1.5f32.floor(), 1.0f32);
+        assert_approx_eq!(1.7f32.floor(), 1.0f32);
+        assert_approx_eq!(0.0f32.floor(), 0.0f32);
+        assert_approx_eq!((-0.0f32).floor(), -0.0f32);
+        assert_approx_eq!((-1.0f32).floor(), -1.0f32);
+        assert_approx_eq!((-1.3f32).floor(), -2.0f32);
+        assert_approx_eq!((-1.5f32).floor(), -2.0f32);
+        assert_approx_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);
+        assert_approx_eq!(1.0f32.ceil(), 1.0f32);
+        assert_approx_eq!(1.3f32.ceil(), 2.0f32);
+        assert_approx_eq!(1.5f32.ceil(), 2.0f32);
+        assert_approx_eq!(1.7f32.ceil(), 2.0f32);
+        assert_approx_eq!(0.0f32.ceil(), 0.0f32);
+        assert_approx_eq!((-0.0f32).ceil(), -0.0f32);
+        assert_approx_eq!((-1.0f32).ceil(), -1.0f32);
+        assert_approx_eq!((-1.3f32).ceil(), -1.0f32);
+        assert_approx_eq!((-1.5f32).ceil(), -1.0f32);
+        assert_approx_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);
+        assert_approx_eq!(1.0f32.round(), 1.0f32);
+        assert_approx_eq!(1.3f32.round(), 1.0f32);
+        assert_approx_eq!(1.5f32.round(), 2.0f32);
+        assert_approx_eq!(1.7f32.round(), 2.0f32);
+        assert_approx_eq!(0.0f32.round(), 0.0f32);
+        assert_approx_eq!((-0.0f32).round(), -0.0f32);
+        assert_approx_eq!((-1.0f32).round(), -1.0f32);
+        assert_approx_eq!((-1.3f32).round(), -1.0f32);
+        assert_approx_eq!((-1.5f32).round(), -2.0f32);
+        assert_approx_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);
+        assert_approx_eq!(1.0f32.trunc(), 1.0f32);
+        assert_approx_eq!(1.3f32.trunc(), 1.0f32);
+        assert_approx_eq!(1.5f32.trunc(), 1.0f32);
+        assert_approx_eq!(1.7f32.trunc(), 1.0f32);
+        assert_approx_eq!(0.0f32.trunc(), 0.0f32);
+        assert_approx_eq!((-0.0f32).trunc(), -0.0f32);
+        assert_approx_eq!((-1.0f32).trunc(), -1.0f32);
+        assert_approx_eq!((-1.3f32).trunc(), -1.0f32);
+        assert_approx_eq!((-1.5f32).trunc(), -1.0f32);
+        assert_approx_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);
+        assert_approx_eq!(1.0f32.fract(), 0.0f32);
+        assert_approx_eq!(1.3f32.fract(), 0.3f32);
+        assert_approx_eq!(1.5f32.fract(), 0.5f32);
+        assert_approx_eq!(1.7f32.fract(), 0.7f32);
+        assert_approx_eq!(0.0f32.fract(), 0.0f32);
+        assert_approx_eq!((-0.0f32).fract(), -0.0f32);
+        assert_approx_eq!((-1.0f32).fract(), -0.0f32);
+        assert_approx_eq!((-1.3f32).fract(), -0.3f32);
+        assert_approx_eq!((-1.5f32).fract(), -0.5f32);
+        assert_approx_eq!((-1.7f32).fract(), -0.7f32);
     }
 
     #[test]
     fn test_real_consts() {
-        assert_fuzzy_eq!(Real::two_pi::<f32>(), 2f32 * Real::pi::<f32>());
-        assert_fuzzy_eq!(Real::frac_pi_2::<f32>(), Real::pi::<f32>() / 2f32);
-        assert_fuzzy_eq!(Real::frac_pi_3::<f32>(), Real::pi::<f32>() / 3f32);
-        assert_fuzzy_eq!(Real::frac_pi_4::<f32>(), Real::pi::<f32>() / 4f32);
-        assert_fuzzy_eq!(Real::frac_pi_6::<f32>(), Real::pi::<f32>() / 6f32);
-        assert_fuzzy_eq!(Real::frac_pi_8::<f32>(), Real::pi::<f32>() / 8f32);
-        assert_fuzzy_eq!(Real::frac_1_pi::<f32>(), 1f32 / Real::pi::<f32>());
-        assert_fuzzy_eq!(Real::frac_2_pi::<f32>(), 2f32 / Real::pi::<f32>());
-        assert_fuzzy_eq!(Real::frac_2_sqrtpi::<f32>(), 2f32 / Real::pi::<f32>().sqrt());
-        assert_fuzzy_eq!(Real::sqrt2::<f32>(), 2f32.sqrt());
-        assert_fuzzy_eq!(Real::frac_1_sqrt2::<f32>(), 1f32 / 2f32.sqrt());
-        assert_fuzzy_eq!(Real::log2_e::<f32>(), Real::e::<f32>().log2());
-        assert_fuzzy_eq!(Real::log10_e::<f32>(), Real::e::<f32>().log10());
-        assert_fuzzy_eq!(Real::log_2::<f32>(), 2f32.log());
-        assert_fuzzy_eq!(Real::log_10::<f32>(), 10f32.log());
+        assert_approx_eq!(Real::two_pi::<f32>(), 2f32 * Real::pi::<f32>());
+        assert_approx_eq!(Real::frac_pi_2::<f32>(), Real::pi::<f32>() / 2f32);
+        assert_approx_eq!(Real::frac_pi_3::<f32>(), Real::pi::<f32>() / 3f32);
+        assert_approx_eq!(Real::frac_pi_4::<f32>(), Real::pi::<f32>() / 4f32);
+        assert_approx_eq!(Real::frac_pi_6::<f32>(), Real::pi::<f32>() / 6f32);
+        assert_approx_eq!(Real::frac_pi_8::<f32>(), Real::pi::<f32>() / 8f32);
+        assert_approx_eq!(Real::frac_1_pi::<f32>(), 1f32 / Real::pi::<f32>());
+        assert_approx_eq!(Real::frac_2_pi::<f32>(), 2f32 / Real::pi::<f32>());
+        assert_approx_eq!(Real::frac_2_sqrtpi::<f32>(), 2f32 / Real::pi::<f32>().sqrt());
+        assert_approx_eq!(Real::sqrt2::<f32>(), 2f32.sqrt());
+        assert_approx_eq!(Real::frac_1_sqrt2::<f32>(), 1f32 / 2f32.sqrt());
+        assert_approx_eq!(Real::log2_e::<f32>(), Real::e::<f32>().log2());
+        assert_approx_eq!(Real::log10_e::<f32>(), Real::e::<f32>().log10());
+        assert_approx_eq!(Real::log_2::<f32>(), 2f32.log());
+        assert_approx_eq!(Real::log_10::<f32>(), 10f32.log());
     }
 
     #[test]
@@ -975,6 +982,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..e5f10c23ecd 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) }
@@ -853,16 +869,6 @@ mod tests {
     use super::*;
     use prelude::*;
 
-    macro_rules! assert_fuzzy_eq(
-        ($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 expected %?", a, b));
-            }
-        })
-    )
-
     #[test]
     fn test_num() {
         num::test_num(10f64, 2f64);
@@ -896,91 +902,91 @@ mod tests {
 
     #[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);
+        assert_approx_eq!(1.0f64.floor(), 1.0f64);
+        assert_approx_eq!(1.3f64.floor(), 1.0f64);
+        assert_approx_eq!(1.5f64.floor(), 1.0f64);
+        assert_approx_eq!(1.7f64.floor(), 1.0f64);
+        assert_approx_eq!(0.0f64.floor(), 0.0f64);
+        assert_approx_eq!((-0.0f64).floor(), -0.0f64);
+        assert_approx_eq!((-1.0f64).floor(), -1.0f64);
+        assert_approx_eq!((-1.3f64).floor(), -2.0f64);
+        assert_approx_eq!((-1.5f64).floor(), -2.0f64);
+        assert_approx_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);
+        assert_approx_eq!(1.0f64.ceil(), 1.0f64);
+        assert_approx_eq!(1.3f64.ceil(), 2.0f64);
+        assert_approx_eq!(1.5f64.ceil(), 2.0f64);
+        assert_approx_eq!(1.7f64.ceil(), 2.0f64);
+        assert_approx_eq!(0.0f64.ceil(), 0.0f64);
+        assert_approx_eq!((-0.0f64).ceil(), -0.0f64);
+        assert_approx_eq!((-1.0f64).ceil(), -1.0f64);
+        assert_approx_eq!((-1.3f64).ceil(), -1.0f64);
+        assert_approx_eq!((-1.5f64).ceil(), -1.0f64);
+        assert_approx_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);
+        assert_approx_eq!(1.0f64.round(), 1.0f64);
+        assert_approx_eq!(1.3f64.round(), 1.0f64);
+        assert_approx_eq!(1.5f64.round(), 2.0f64);
+        assert_approx_eq!(1.7f64.round(), 2.0f64);
+        assert_approx_eq!(0.0f64.round(), 0.0f64);
+        assert_approx_eq!((-0.0f64).round(), -0.0f64);
+        assert_approx_eq!((-1.0f64).round(), -1.0f64);
+        assert_approx_eq!((-1.3f64).round(), -1.0f64);
+        assert_approx_eq!((-1.5f64).round(), -2.0f64);
+        assert_approx_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);
+        assert_approx_eq!(1.0f64.trunc(), 1.0f64);
+        assert_approx_eq!(1.3f64.trunc(), 1.0f64);
+        assert_approx_eq!(1.5f64.trunc(), 1.0f64);
+        assert_approx_eq!(1.7f64.trunc(), 1.0f64);
+        assert_approx_eq!(0.0f64.trunc(), 0.0f64);
+        assert_approx_eq!((-0.0f64).trunc(), -0.0f64);
+        assert_approx_eq!((-1.0f64).trunc(), -1.0f64);
+        assert_approx_eq!((-1.3f64).trunc(), -1.0f64);
+        assert_approx_eq!((-1.5f64).trunc(), -1.0f64);
+        assert_approx_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);
+        assert_approx_eq!(1.0f64.fract(), 0.0f64);
+        assert_approx_eq!(1.3f64.fract(), 0.3f64);
+        assert_approx_eq!(1.5f64.fract(), 0.5f64);
+        assert_approx_eq!(1.7f64.fract(), 0.7f64);
+        assert_approx_eq!(0.0f64.fract(), 0.0f64);
+        assert_approx_eq!((-0.0f64).fract(), -0.0f64);
+        assert_approx_eq!((-1.0f64).fract(), -0.0f64);
+        assert_approx_eq!((-1.3f64).fract(), -0.3f64);
+        assert_approx_eq!((-1.5f64).fract(), -0.5f64);
+        assert_approx_eq!((-1.7f64).fract(), -0.7f64);
     }
 
     #[test]
     fn test_real_consts() {
-        assert_fuzzy_eq!(Real::two_pi::<f64>(), 2.0 * Real::pi::<f64>());
-        assert_fuzzy_eq!(Real::frac_pi_2::<f64>(), Real::pi::<f64>() / 2f64);
-        assert_fuzzy_eq!(Real::frac_pi_3::<f64>(), Real::pi::<f64>() / 3f64);
-        assert_fuzzy_eq!(Real::frac_pi_4::<f64>(), Real::pi::<f64>() / 4f64);
-        assert_fuzzy_eq!(Real::frac_pi_6::<f64>(), Real::pi::<f64>() / 6f64);
-        assert_fuzzy_eq!(Real::frac_pi_8::<f64>(), Real::pi::<f64>() / 8f64);
-        assert_fuzzy_eq!(Real::frac_1_pi::<f64>(), 1f64 / Real::pi::<f64>());
-        assert_fuzzy_eq!(Real::frac_2_pi::<f64>(), 2f64 / Real::pi::<f64>());
-        assert_fuzzy_eq!(Real::frac_2_sqrtpi::<f64>(), 2f64 / Real::pi::<f64>().sqrt());
-        assert_fuzzy_eq!(Real::sqrt2::<f64>(), 2f64.sqrt());
-        assert_fuzzy_eq!(Real::frac_1_sqrt2::<f64>(), 1f64 / 2f64.sqrt());
-        assert_fuzzy_eq!(Real::log2_e::<f64>(), Real::e::<f64>().log2());
-        assert_fuzzy_eq!(Real::log10_e::<f64>(), Real::e::<f64>().log10());
-        assert_fuzzy_eq!(Real::log_2::<f64>(), 2f64.log());
-        assert_fuzzy_eq!(Real::log_10::<f64>(), 10f64.log());
+        assert_approx_eq!(Real::two_pi::<f64>(), 2.0 * Real::pi::<f64>());
+        assert_approx_eq!(Real::frac_pi_2::<f64>(), Real::pi::<f64>() / 2f64);
+        assert_approx_eq!(Real::frac_pi_3::<f64>(), Real::pi::<f64>() / 3f64);
+        assert_approx_eq!(Real::frac_pi_4::<f64>(), Real::pi::<f64>() / 4f64);
+        assert_approx_eq!(Real::frac_pi_6::<f64>(), Real::pi::<f64>() / 6f64);
+        assert_approx_eq!(Real::frac_pi_8::<f64>(), Real::pi::<f64>() / 8f64);
+        assert_approx_eq!(Real::frac_1_pi::<f64>(), 1f64 / Real::pi::<f64>());
+        assert_approx_eq!(Real::frac_2_pi::<f64>(), 2f64 / Real::pi::<f64>());
+        assert_approx_eq!(Real::frac_2_sqrtpi::<f64>(), 2f64 / Real::pi::<f64>().sqrt());
+        assert_approx_eq!(Real::sqrt2::<f64>(), 2f64.sqrt());
+        assert_approx_eq!(Real::frac_1_sqrt2::<f64>(), 1f64 / 2f64.sqrt());
+        assert_approx_eq!(Real::log2_e::<f64>(), Real::e::<f64>().log2());
+        assert_approx_eq!(Real::log10_e::<f64>(), Real::e::<f64>().log10());
+        assert_approx_eq!(Real::log_2::<f64>(), 2f64.log());
+        assert_approx_eq!(Real::log_10::<f64>(), 10f64.log());
     }
 
     #[test]
@@ -1023,6 +1029,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..a5481653263 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) }
@@ -821,15 +837,6 @@ mod tests {
     use super::*;
     use prelude::*;
 
-    macro_rules! assert_fuzzy_eq(
-        ($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));
-            }
-        })
-    )
-
     #[test]
     fn test_num() {
         num::test_num(10f, 2f);
@@ -859,91 +866,91 @@ mod tests {
 
     #[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);
+        assert_approx_eq!(1.0f.floor(), 1.0f);
+        assert_approx_eq!(1.3f.floor(), 1.0f);
+        assert_approx_eq!(1.5f.floor(), 1.0f);
+        assert_approx_eq!(1.7f.floor(), 1.0f);
+        assert_approx_eq!(0.0f.floor(), 0.0f);
+        assert_approx_eq!((-0.0f).floor(), -0.0f);
+        assert_approx_eq!((-1.0f).floor(), -1.0f);
+        assert_approx_eq!((-1.3f).floor(), -2.0f);
+        assert_approx_eq!((-1.5f).floor(), -2.0f);
+        assert_approx_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);
+        assert_approx_eq!(1.0f.ceil(), 1.0f);
+        assert_approx_eq!(1.3f.ceil(), 2.0f);
+        assert_approx_eq!(1.5f.ceil(), 2.0f);
+        assert_approx_eq!(1.7f.ceil(), 2.0f);
+        assert_approx_eq!(0.0f.ceil(), 0.0f);
+        assert_approx_eq!((-0.0f).ceil(), -0.0f);
+        assert_approx_eq!((-1.0f).ceil(), -1.0f);
+        assert_approx_eq!((-1.3f).ceil(), -1.0f);
+        assert_approx_eq!((-1.5f).ceil(), -1.0f);
+        assert_approx_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);
+        assert_approx_eq!(1.0f.round(), 1.0f);
+        assert_approx_eq!(1.3f.round(), 1.0f);
+        assert_approx_eq!(1.5f.round(), 2.0f);
+        assert_approx_eq!(1.7f.round(), 2.0f);
+        assert_approx_eq!(0.0f.round(), 0.0f);
+        assert_approx_eq!((-0.0f).round(), -0.0f);
+        assert_approx_eq!((-1.0f).round(), -1.0f);
+        assert_approx_eq!((-1.3f).round(), -1.0f);
+        assert_approx_eq!((-1.5f).round(), -2.0f);
+        assert_approx_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);
+        assert_approx_eq!(1.0f.trunc(), 1.0f);
+        assert_approx_eq!(1.3f.trunc(), 1.0f);
+        assert_approx_eq!(1.5f.trunc(), 1.0f);
+        assert_approx_eq!(1.7f.trunc(), 1.0f);
+        assert_approx_eq!(0.0f.trunc(), 0.0f);
+        assert_approx_eq!((-0.0f).trunc(), -0.0f);
+        assert_approx_eq!((-1.0f).trunc(), -1.0f);
+        assert_approx_eq!((-1.3f).trunc(), -1.0f);
+        assert_approx_eq!((-1.5f).trunc(), -1.0f);
+        assert_approx_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);
+        assert_approx_eq!(1.0f.fract(), 0.0f);
+        assert_approx_eq!(1.3f.fract(), 0.3f);
+        assert_approx_eq!(1.5f.fract(), 0.5f);
+        assert_approx_eq!(1.7f.fract(), 0.7f);
+        assert_approx_eq!(0.0f.fract(), 0.0f);
+        assert_approx_eq!((-0.0f).fract(), -0.0f);
+        assert_approx_eq!((-1.0f).fract(), -0.0f);
+        assert_approx_eq!((-1.3f).fract(), -0.3f);
+        assert_approx_eq!((-1.5f).fract(), -0.5f);
+        assert_approx_eq!((-1.7f).fract(), -0.7f);
     }
 
     #[test]
     fn test_real_consts() {
-        assert_fuzzy_eq!(Real::two_pi::<float>(), 2f * Real::pi::<float>());
-        assert_fuzzy_eq!(Real::frac_pi_2::<float>(), Real::pi::<float>() / 2f);
-        assert_fuzzy_eq!(Real::frac_pi_3::<float>(), Real::pi::<float>() / 3f);
-        assert_fuzzy_eq!(Real::frac_pi_4::<float>(), Real::pi::<float>() / 4f);
-        assert_fuzzy_eq!(Real::frac_pi_6::<float>(), Real::pi::<float>() / 6f);
-        assert_fuzzy_eq!(Real::frac_pi_8::<float>(), Real::pi::<float>() / 8f);
-        assert_fuzzy_eq!(Real::frac_1_pi::<float>(), 1f / Real::pi::<float>());
-        assert_fuzzy_eq!(Real::frac_2_pi::<float>(), 2f / Real::pi::<float>());
-        assert_fuzzy_eq!(Real::frac_2_sqrtpi::<float>(), 2f / Real::pi::<float>().sqrt());
-        assert_fuzzy_eq!(Real::sqrt2::<float>(), 2f.sqrt());
-        assert_fuzzy_eq!(Real::frac_1_sqrt2::<float>(), 1f / 2f.sqrt());
-        assert_fuzzy_eq!(Real::log2_e::<float>(), Real::e::<float>().log2());
-        assert_fuzzy_eq!(Real::log10_e::<float>(), Real::e::<float>().log10());
-        assert_fuzzy_eq!(Real::log_2::<float>(), 2f.log());
-        assert_fuzzy_eq!(Real::log_10::<float>(), 10f.log());
+        assert_approx_eq!(Real::two_pi::<float>(), 2f * Real::pi::<float>());
+        assert_approx_eq!(Real::frac_pi_2::<float>(), Real::pi::<float>() / 2f);
+        assert_approx_eq!(Real::frac_pi_3::<float>(), Real::pi::<float>() / 3f);
+        assert_approx_eq!(Real::frac_pi_4::<float>(), Real::pi::<float>() / 4f);
+        assert_approx_eq!(Real::frac_pi_6::<float>(), Real::pi::<float>() / 6f);
+        assert_approx_eq!(Real::frac_pi_8::<float>(), Real::pi::<float>() / 8f);
+        assert_approx_eq!(Real::frac_1_pi::<float>(), 1f / Real::pi::<float>());
+        assert_approx_eq!(Real::frac_2_pi::<float>(), 2f / Real::pi::<float>());
+        assert_approx_eq!(Real::frac_2_sqrtpi::<float>(), 2f / Real::pi::<float>().sqrt());
+        assert_approx_eq!(Real::sqrt2::<float>(), 2f.sqrt());
+        assert_approx_eq!(Real::frac_1_sqrt2::<float>(), 1f / 2f.sqrt());
+        assert_approx_eq!(Real::log2_e::<float>(), Real::e::<float>().log2());
+        assert_approx_eq!(Real::log10_e::<float>(), Real::e::<float>().log10());
+        assert_approx_eq!(Real::log_2::<float>(), 2f.log());
+        assert_approx_eq!(Real::log_10::<float>(), 10f.log());
     }
 
     #[test]
@@ -986,6 +993,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};
diff --git a/src/libstd/cmp.rs b/src/libstd/cmp.rs
deleted file mode 100644
index ea3793c1374..00000000000
--- a/src/libstd/cmp.rs
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2012-2013 The Rust Project Developers. See the
-// COPYRIGHT file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Additional general-purpose comparison functionality.
-
-use core::f32;
-use core::f64;
-use core::float;
-
-pub static FUZZY_EPSILON: float = 1.0e-6;
-
-pub trait FuzzyEq<Eps> {
-    fn fuzzy_eq(&self, other: &Self) -> bool;
-    fn fuzzy_eq_eps(&self, other: &Self, epsilon: &Eps) -> bool;
-}
-
-impl FuzzyEq<float> for float {
-    fn fuzzy_eq(&self, other: &float) -> bool {
-        self.fuzzy_eq_eps(other, &FUZZY_EPSILON)
-    }
-
-    fn fuzzy_eq_eps(&self, other: &float, epsilon: &float) -> bool {
-        float::abs(*self - *other) < *epsilon
-    }
-}
-
-impl FuzzyEq<f32> for f32 {
-    fn fuzzy_eq(&self, other: &f32) -> bool {
-        self.fuzzy_eq_eps(other, &(FUZZY_EPSILON as f32))
-    }
-
-    fn fuzzy_eq_eps(&self, other: &f32, epsilon: &f32) -> bool {
-        f32::abs(*self - *other) < *epsilon
-    }
-}
-
-impl FuzzyEq<f64> for f64 {
-    fn fuzzy_eq(&self, other: &f64) -> bool {
-        self.fuzzy_eq_eps(other, &(FUZZY_EPSILON as f64))
-    }
-
-    fn fuzzy_eq_eps(&self, other: &f64, epsilon: &f64) -> bool {
-        f64::abs(*self - *other) < *epsilon
-    }
-}
-
-#[test]
-fn test_fuzzy_equals() {
-    assert!((&1.0f).fuzzy_eq(&1.0));
-    assert!((&1.0f32).fuzzy_eq(&1.0f32));
-    assert!((&1.0f64).fuzzy_eq(&1.0f64));
-}
-
-#[test]
-fn test_fuzzy_eq_eps() {
-    assert!((&1.2f).fuzzy_eq_eps(&0.9, &0.5));
-    assert!(!(&1.5f).fuzzy_eq_eps(&0.9, &0.5));
-}
-
-#[cfg(test)]
-mod test_complex{
-    use cmp::*;
-
-    struct Complex { r: float, i: float }
-
-    impl FuzzyEq<float> for Complex {
-        fn fuzzy_eq(&self, other: &Complex) -> bool {
-            self.fuzzy_eq_eps(other, &FUZZY_EPSILON)
-        }
-
-        fn fuzzy_eq_eps(&self, other: &Complex,
-                             epsilon: &float) -> bool {
-            self.r.fuzzy_eq_eps(&other.r, epsilon) &&
-            self.i.fuzzy_eq_eps(&other.i, epsilon)
-        }
-    }
-
-    #[test]
-    fn test_fuzzy_equals() {
-        let a = Complex {r: 0.9, i: 0.9};
-        let b = Complex {r: 0.9, i: 0.9};
-
-        assert!((a.fuzzy_eq(&b)));
-    }
-
-    #[test]
-    fn test_fuzzy_eq_eps() {
-        let other = Complex {r: 0.9, i: 0.9};
-
-        assert!((&Complex {r: 0.9, i: 1.2}).fuzzy_eq_eps(&other, &0.5));
-        assert!((&Complex {r: 1.2, i: 0.9}).fuzzy_eq_eps(&other, &0.5));
-        assert!(!(&Complex {r: 0.9, i: 1.5}).fuzzy_eq_eps(&other, &0.5));
-        assert!(!(&Complex {r: 1.5, i: 0.9}).fuzzy_eq_eps(&other, &0.5));
-    }
-}
diff --git a/src/libstd/std.rc b/src/libstd/std.rc
index 4f9de29e726..32c7c82a312 100644
--- a/src/libstd/std.rc
+++ b/src/libstd/std.rc
@@ -86,7 +86,6 @@ pub mod term;
 pub mod time;
 pub mod arena;
 pub mod par;
-pub mod cmp;
 pub mod base64;
 pub mod rl;
 pub mod workcache;
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 02721a02fbd..9363807ab9b 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -483,6 +483,42 @@ pub fn core_macros() -> ~str {
         )
     )
 
+    macro_rules! assert_approx_eq (
+        ($given:expr , $expected:expr) => (
+            {
+                use core::cmp::ApproxEq;
+
+                let given_val = $given;
+                let expected_val = $expected;
+                // check both directions of equality....
+                if !(
+                    given_val.approx_eq(&expected_val) &&
+                    expected_val.approx_eq(&given_val)
+                ) {
+                    fail!(\"left: %? does not approximately equal right: %?\",
+                          given_val, expected_val);
+                }
+            }
+        );
+        ($given:expr , $expected:expr , $epsilon:expr) => (
+            {
+                use core::cmp::ApproxEq;
+
+                let given_val = $given;
+                let expected_val = $expected;
+                let epsilon_val = $epsilon;
+                // check both directions of equality....
+                if !(
+                    given_val.approx_eq_eps(&expected_val, &epsilon_val) &&
+                    expected_val.approx_eq_eps(&given_val, &epsilon_val)
+                ) {
+                    fail!(\"left: %? does not approximately equal right: %? with epsilon: %?\",
+                          given_val, expected_val, epsilon_val);
+                }
+            }
+        )
+    )
+
     macro_rules! condition (
 
         { $c:ident: $in:ty -> $out:ty; } => {
diff --git a/src/test/run-fail/assert-approx-eq-eps-macro-fail.rs b/src/test/run-fail/assert-approx-eq-eps-macro-fail.rs
new file mode 100644
index 00000000000..c0c20f7af43
--- /dev/null
+++ b/src/test/run-fail/assert-approx-eq-eps-macro-fail.rs
@@ -0,0 +1,14 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// error-pattern:left: 1.0000001 does not approximately equal right: 1 with epsilon: 0.0000001
+pub fn main() {
+    assert_approx_eq!(1.0000001f, 1.0f, 1.0e-7);
+}
diff --git a/src/test/run-fail/assert-approx-eq-macro-fail.rs b/src/test/run-fail/assert-approx-eq-macro-fail.rs
new file mode 100644
index 00000000000..43de4f92b63
--- /dev/null
+++ b/src/test/run-fail/assert-approx-eq-macro-fail.rs
@@ -0,0 +1,14 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// error-pattern:left: 1.00001 does not approximately equal right: 1
+pub fn main() {
+    assert_approx_eq!(1.00001f, 1.0f);
+}
diff --git a/src/test/run-pass/assert-approx-eq-macro-success.rs b/src/test/run-pass/assert-approx-eq-macro-success.rs
new file mode 100644
index 00000000000..5c7c11ef503
--- /dev/null
+++ b/src/test/run-pass/assert-approx-eq-macro-success.rs
@@ -0,0 +1,16 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub fn main() {
+    assert_approx_eq!(1.0f, 1.0f);
+    assert_approx_eq!(1.0000001f, 1.0f);
+    assert_approx_eq!(1.0000001f, 1.0f, 1.0e-6);
+    assert_approx_eq!(1.000001f, 1.0f, 1.0e-5);
+}
diff --git a/src/test/run-pass/intrinsics-math.rs b/src/test/run-pass/intrinsics-math.rs
index 6f9179bc89d..c73df8209e8 100644
--- a/src/test/run-pass/intrinsics-math.rs
+++ b/src/test/run-pass/intrinsics-math.rs
@@ -10,10 +10,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-extern mod std;
-
-use std::cmp::FuzzyEq;
-
 mod rusti {
     #[abi = "rust-intrinsic"]
     pub extern "rust-intrinsic" {
@@ -54,44 +50,44 @@ pub fn main() {
     unsafe {
         use rusti::*;
 
-        assert!((sqrtf32(64f32).fuzzy_eq(&8f32)));
-        assert!((sqrtf64(64f64).fuzzy_eq(&8f64)));
+        assert!((sqrtf32(64f32).approx_eq(&8f32)));
+        assert!((sqrtf64(64f64).approx_eq(&8f64)));
 
-        assert!((powif32(25f32, -2i32).fuzzy_eq(&0.0016f32)));
-        assert!((powif64(23.2f64, 2i32).fuzzy_eq(&538.24f64)));
+        assert!((powif32(25f32, -2i32).approx_eq(&0.0016f32)));
+        assert!((powif64(23.2f64, 2i32).approx_eq(&538.24f64)));
 
-        assert!((sinf32(0f32).fuzzy_eq(&0f32)));
-        assert!((sinf64(f64::consts::pi / 2f64).fuzzy_eq(&1f64)));
+        assert!((sinf32(0f32).approx_eq(&0f32)));
+        assert!((sinf64(f64::consts::pi / 2f64).approx_eq(&1f64)));
 
-        assert!((cosf32(0f32).fuzzy_eq(&1f32)));
-        assert!((cosf64(f64::consts::pi * 2f64).fuzzy_eq(&1f64)));
+        assert!((cosf32(0f32).approx_eq(&1f32)));
+        assert!((cosf64(f64::consts::pi * 2f64).approx_eq(&1f64)));
 
-        assert!((powf32(25f32, -2f32).fuzzy_eq(&0.0016f32)));
-        assert!((powf64(400f64, 0.5f64).fuzzy_eq(&20f64)));
+        assert!((powf32(25f32, -2f32).approx_eq(&0.0016f32)));
+        assert!((powf64(400f64, 0.5f64).approx_eq(&20f64)));
 
-        assert!((fabsf32(expf32(1f32) - f32::consts::e).fuzzy_eq(&0f32)));
-        assert!((expf64(1f64).fuzzy_eq(&f64::consts::e)));
+        assert!((fabsf32(expf32(1f32) - f32::consts::e).approx_eq(&0f32)));
+        assert!((expf64(1f64).approx_eq(&f64::consts::e)));
 
-        assert!((exp2f32(10f32).fuzzy_eq(&1024f32)));
-        assert!((exp2f64(50f64).fuzzy_eq(&1125899906842624f64)));
+        assert!((exp2f32(10f32).approx_eq(&1024f32)));
+        assert!((exp2f64(50f64).approx_eq(&1125899906842624f64)));
 
-        assert!((fabsf32(logf32(f32::consts::e) - 1f32).fuzzy_eq(&0f32)));
-        assert!((logf64(1f64).fuzzy_eq(&0f64)));
+        assert!((fabsf32(logf32(f32::consts::e) - 1f32).approx_eq(&0f32)));
+        assert!((logf64(1f64).approx_eq(&0f64)));
 
-        assert!((log10f32(10f32).fuzzy_eq(&1f32)));
-        assert!((log10f64(f64::consts::e).fuzzy_eq(&f64::consts::log10_e)));
+        assert!((log10f32(10f32).approx_eq(&1f32)));
+        assert!((log10f64(f64::consts::e).approx_eq(&f64::consts::log10_e)));
 
-        assert!((log2f32(8f32).fuzzy_eq(&3f32)));
-        assert!((log2f64(f64::consts::e).fuzzy_eq(&f64::consts::log2_e)));
+        assert!((log2f32(8f32).approx_eq(&3f32)));
+        assert!((log2f64(f64::consts::e).approx_eq(&f64::consts::log2_e)));
 
-        assert!((fmaf32(1.0f32, 2.0f32, 5.0f32).fuzzy_eq(&7.0f32)));
-        assert!((fmaf64(0.0f64, -2.0f64, f64::consts::e).fuzzy_eq(&f64::consts::e)));
+        assert!((fmaf32(1.0f32, 2.0f32, 5.0f32).approx_eq(&7.0f32)));
+        assert!((fmaf64(0.0f64, -2.0f64, f64::consts::e).approx_eq(&f64::consts::e)));
 
-        assert!((fabsf32(-1.0f32).fuzzy_eq(&1.0f32)));
-        assert!((fabsf64(34.2f64).fuzzy_eq(&34.2f64)));
+        assert!((fabsf32(-1.0f32).approx_eq(&1.0f32)));
+        assert!((fabsf64(34.2f64).approx_eq(&34.2f64)));
 
-        assert!((floorf32(3.8f32).fuzzy_eq(&3.0f32)));
-        assert!((floorf64(-1.1f64).fuzzy_eq(&-2.0f64)));
+        assert!((floorf32(3.8f32).approx_eq(&3.0f32)));
+        assert!((floorf64(-1.1f64).approx_eq(&-2.0f64)));
 
         // Causes linker error
         // undefined reference to llvm.ceil.f32/64
diff --git a/src/test/run-pass/trait-inheritance-num.rs b/src/test/run-pass/trait-inheritance-num.rs
index 0fb2a6b2e72..5179d13813c 100644
--- a/src/test/run-pass/trait-inheritance-num.rs
+++ b/src/test/run-pass/trait-inheritance-num.rs
@@ -14,11 +14,10 @@ extern mod std;
 
 use core::cmp::{Eq, Ord};
 use core::num::NumCast::from;
-use std::cmp::FuzzyEq;
 
 pub trait NumExt: Num + NumCast + Eq + Ord {}
 
-pub trait FloatExt: NumExt + FuzzyEq<Self> {}
+pub trait FloatExt: NumExt + ApproxEq<Self> {}
 
 fn greater_than_one<T:NumExt>(n: &T) -> bool { *n > from(1) }
 fn greater_than_one_float<T:FloatExt>(n: &T) -> bool { *n > from(1) }
diff --git a/src/test/run-pass/trait-inheritance-num2.rs b/src/test/run-pass/trait-inheritance-num2.rs
index b40f647814f..f7edd2855a4 100644
--- a/src/test/run-pass/trait-inheritance-num2.rs
+++ b/src/test/run-pass/trait-inheritance-num2.rs
@@ -16,7 +16,6 @@ extern mod std;
 
 use core::cmp::{Eq, Ord};
 use core::num::NumCast::from;
-use std::cmp::FuzzyEq;
 
 pub trait TypeExt {}
 
@@ -94,7 +93,7 @@ impl IntegerExt for i64 {}
 impl IntegerExt for int {}
 
 
-pub trait FloatExt: NumExt + FuzzyEq<Self> {}
+pub trait FloatExt: NumExt + ApproxEq<Self> {}
 
 impl FloatExt for f32 {}
 impl FloatExt for f64 {}