Move FuzzyEq trait into core::cmp and rename it to 'ApproxEq'
This commit is contained in:
parent
6e6a4be19d
commit
0211833008
11 changed files with 114 additions and 140 deletions
|
|
@ -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 }
|
||||
|
||||
|
|
|
|||
|
|
@ -210,6 +210,22 @@ impl Eq for f32 {
|
|||
fn ne(&self, other: &f32) -> bool { (*self) != (*other) }
|
||||
}
|
||||
|
||||
#[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)]
|
||||
|
|
@ -974,6 +990,15 @@ mod tests {
|
|||
assert!(!NaN.is_negative());
|
||||
}
|
||||
|
||||
#[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);
|
||||
|
|
|
|||
|
|
@ -233,6 +233,22 @@ impl Eq for f64 {
|
|||
fn ne(&self, other: &f64) -> bool { (*self) != (*other) }
|
||||
}
|
||||
|
||||
#[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)]
|
||||
|
|
@ -1022,6 +1038,15 @@ mod tests {
|
|||
assert!(!NaN.is_negative());
|
||||
}
|
||||
|
||||
#[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);
|
||||
|
|
|
|||
|
|
@ -371,6 +371,22 @@ impl Eq for float {
|
|||
fn ne(&self, other: &float) -> bool { (*self) != (*other) }
|
||||
}
|
||||
|
||||
#[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)]
|
||||
|
|
@ -985,6 +1001,15 @@ mod tests {
|
|||
assert!(!NaN.is_negative());
|
||||
}
|
||||
|
||||
#[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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
|
|
|
|||
|
|
@ -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 {}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue