-
Notifications
You must be signed in to change notification settings - Fork 204
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
impl approx::UlpsEqual for geo-types #1312
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,8 +2,6 @@ use crate::{CoordNum, Geometry}; | |
|
||
use alloc::vec; | ||
use alloc::vec::Vec; | ||
#[cfg(any(feature = "approx", test))] | ||
use approx::{AbsDiffEq, RelativeEq}; | ||
use core::iter::FromIterator; | ||
use core::ops::{Index, IndexMut}; | ||
|
||
|
@@ -248,78 +246,101 @@ impl<'a, T: CoordNum> GeometryCollection<T> { | |
} | ||
|
||
#[cfg(any(feature = "approx", test))] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rather than having several conditional cfgs in the file, I consolidated all the |
||
impl<T> RelativeEq for GeometryCollection<T> | ||
where | ||
T: AbsDiffEq<Epsilon = T> + CoordNum + RelativeEq, | ||
{ | ||
#[inline] | ||
fn default_max_relative() -> Self::Epsilon { | ||
T::default_max_relative() | ||
} | ||
|
||
/// Equality assertion within a relative limit. | ||
/// | ||
/// # Examples | ||
/// | ||
/// ``` | ||
/// use geo_types::{GeometryCollection, point}; | ||
/// | ||
/// let a = GeometryCollection::new_from(vec![point![x: 1.0, y: 2.0].into()]); | ||
/// let b = GeometryCollection::new_from(vec![point![x: 1.0, y: 2.01].into()]); | ||
/// | ||
/// approx::assert_relative_eq!(a, b, max_relative=0.1); | ||
/// approx::assert_relative_ne!(a, b, max_relative=0.0001); | ||
/// ``` | ||
#[inline] | ||
fn relative_eq( | ||
&self, | ||
other: &Self, | ||
epsilon: Self::Epsilon, | ||
max_relative: Self::Epsilon, | ||
) -> bool { | ||
if self.0.len() != other.0.len() { | ||
return false; | ||
mod approx_integration { | ||
use super::*; | ||
use approx::{AbsDiffEq, RelativeEq, UlpsEq}; | ||
|
||
impl<T> RelativeEq for GeometryCollection<T> | ||
where | ||
T: CoordNum + RelativeEq<Epsilon = T>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another no-op simplification in the type constraints: We don't need to specify There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice! |
||
{ | ||
#[inline] | ||
fn default_max_relative() -> Self::Epsilon { | ||
T::default_max_relative() | ||
} | ||
|
||
let mut mp_zipper = self.iter().zip(other.iter()); | ||
mp_zipper.all(|(lhs, rhs)| lhs.relative_eq(rhs, epsilon, max_relative)) | ||
/// Equality assertion within a relative limit. | ||
/// | ||
/// # Examples | ||
/// | ||
/// ``` | ||
/// use geo_types::{GeometryCollection, point}; | ||
/// | ||
/// let a = GeometryCollection::new_from(vec![point![x: 1.0, y: 2.0].into()]); | ||
/// let b = GeometryCollection::new_from(vec![point![x: 1.0, y: 2.01].into()]); | ||
/// | ||
/// approx::assert_relative_eq!(a, b, max_relative=0.1); | ||
/// approx::assert_relative_ne!(a, b, max_relative=0.0001); | ||
/// ``` | ||
#[inline] | ||
fn relative_eq( | ||
&self, | ||
other: &Self, | ||
epsilon: Self::Epsilon, | ||
max_relative: Self::Epsilon, | ||
) -> bool { | ||
if self.0.len() != other.0.len() { | ||
return false; | ||
} | ||
|
||
self.iter() | ||
.zip(other.iter()) | ||
.all(|(lhs, rhs)| lhs.relative_eq(rhs, epsilon, max_relative)) | ||
} | ||
} | ||
} | ||
|
||
#[cfg(any(feature = "approx", test))] | ||
impl<T> AbsDiffEq for GeometryCollection<T> | ||
where | ||
T: AbsDiffEq<Epsilon = T> + CoordNum, | ||
T::Epsilon: Copy, | ||
{ | ||
type Epsilon = T; | ||
|
||
#[inline] | ||
fn default_epsilon() -> Self::Epsilon { | ||
T::default_epsilon() | ||
impl<T> AbsDiffEq for GeometryCollection<T> | ||
where | ||
T: CoordNum + AbsDiffEq<Epsilon = T>, | ||
{ | ||
type Epsilon = T; | ||
|
||
#[inline] | ||
fn default_epsilon() -> Self::Epsilon { | ||
T::default_epsilon() | ||
} | ||
|
||
/// Equality assertion with an absolute limit. | ||
/// | ||
/// # Examples | ||
/// | ||
/// ``` | ||
/// use geo_types::{GeometryCollection, point}; | ||
/// | ||
/// let a = GeometryCollection::new_from(vec![point![x: 0.0, y: 0.0].into()]); | ||
/// let b = GeometryCollection::new_from(vec![point![x: 0.0, y: 0.1].into()]); | ||
/// | ||
/// approx::abs_diff_eq!(a, b, epsilon=0.1); | ||
/// approx::abs_diff_ne!(a, b, epsilon=0.001); | ||
/// ``` | ||
#[inline] | ||
fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool { | ||
if self.0.len() != other.0.len() { | ||
return false; | ||
} | ||
|
||
self.into_iter() | ||
.zip(other) | ||
.all(|(lhs, rhs)| lhs.abs_diff_eq(rhs, epsilon)) | ||
} | ||
} | ||
|
||
/// Equality assertion with an absolute limit. | ||
/// | ||
/// # Examples | ||
/// | ||
/// ``` | ||
/// use geo_types::{GeometryCollection, point}; | ||
/// | ||
/// let a = GeometryCollection::new_from(vec![point![x: 0.0, y: 0.0].into()]); | ||
/// let b = GeometryCollection::new_from(vec![point![x: 0.0, y: 0.1].into()]); | ||
/// | ||
/// approx::abs_diff_eq!(a, b, epsilon=0.1); | ||
/// approx::abs_diff_ne!(a, b, epsilon=0.001); | ||
/// ``` | ||
#[inline] | ||
fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool { | ||
if self.0.len() != other.0.len() { | ||
return false; | ||
impl<T> UlpsEq for GeometryCollection<T> | ||
where | ||
T: CoordNum + UlpsEq<Epsilon = T>, | ||
{ | ||
fn default_max_ulps() -> u32 { | ||
T::default_max_ulps() | ||
} | ||
|
||
let mut mp_zipper = self.into_iter().zip(other); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this |
||
mp_zipper.all(|(lhs, rhs)| lhs.abs_diff_eq(rhs, epsilon)) | ||
fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool { | ||
if self.0.len() != other.0.len() { | ||
return false; | ||
} | ||
self.into_iter() | ||
.zip(other) | ||
.all(|(lhs, rhs)| lhs.ulps_eq(rhs, epsilon, max_ulps)) | ||
} | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other than the new UlpsEq impl below, these changes are formatting changes.
Though I also simplified/standardized some of our type constraints.
e.g. here
T::Epsilon: Copy
is replaced byAbsDiffEq<Epsilon=T>
Since
T: CoordNum
, we already know it'sCopy
.In theory, the previous implementation might have allowed something like:
Coord<f32>.abs_diff(Coord<f64>)
But because
pub trait AbsDiffEq<Rhs = Self>
we only ever supported comparing toSelf
anyway (and I think that's just fine).Bottom line, this doesn't change behavior and is more succinct/uniform with the other declarations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW I recommend turning on the option to hide whitespace changes for this diff.