Skip to content
This repository has been archived by the owner on May 13, 2024. It is now read-only.

[no squash] Make equals method symmetric #267

Merged
merged 2 commits into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 10 additions & 30 deletions include/irrMath.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <float.h>
#include <stdlib.h> // for abs() etc.
#include <limits.h> // For INT_MAX / UINT_MAX
#include <type_traits>

namespace irr
{
Expand All @@ -17,9 +18,6 @@ namespace core

//! Rounding error constant often used when comparing f32 values.

const s32 ROUNDING_ERROR_S32 = 0;

const s64 ROUNDING_ERROR_S64 = 0;
const f32 ROUNDING_ERROR_f32 = 0.000001f;
const f64 ROUNDING_ERROR_f64 = 0.00000001;

Expand Down Expand Up @@ -170,30 +168,6 @@ namespace core
return ROUNDING_ERROR_f64;
}

template <>
inline s32 roundingError()
{
return ROUNDING_ERROR_S32;
}

template <>
inline u32 roundingError()
{
return ROUNDING_ERROR_S32;
}

template <>
inline s64 roundingError()
{
return ROUNDING_ERROR_S64;
}

template <>
inline u64 roundingError()
{
return ROUNDING_ERROR_S64;
}

template <class T>
inline T relativeErrorFactor()
{
Expand All @@ -212,14 +186,20 @@ namespace core
return 8;
}

//! returns if a equals b, for types without rounding errors
template <class T, std::enable_if_t<std::is_integral<T>::value, bool> = true>
inline bool equals(const T a, const T b)
{
return a == b;
}

//! returns if a equals b, taking possible rounding errors into account
template <class T>
template <class T, std::enable_if_t<std::is_floating_point<T>::value, bool> = true>
inline bool equals(const T a, const T b, const T tolerance = roundingError<T>())
{
return (a + tolerance >= b) && (a - tolerance <= b);
return abs(a - b) <= tolerance;
sfan5 marked this conversation as resolved.
Show resolved Hide resolved
}


//! returns if a equals b, taking relative error in form of factor
//! this particular function does not involve any division.
template <class T>
Expand Down
34 changes: 17 additions & 17 deletions include/vector2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,47 +75,47 @@ class vector2d
return *(&X+index);
}

//! sort in order X, Y. Equality with rounding tolerance.
//! sort in order X, Y.
bool operator<=(const vector2d<T>&other) const
{
return (X<other.X || core::equals(X, other.X)) ||
(core::equals(X, other.X) && (Y<other.Y || core::equals(Y, other.Y)));
return !(*this > other);
}

//! sort in order X, Y. Equality with rounding tolerance.
//! sort in order X, Y.
bool operator>=(const vector2d<T>&other) const
{
return (X>other.X || core::equals(X, other.X)) ||
(core::equals(X, other.X) && (Y>other.Y || core::equals(Y, other.Y)));
return !(*this < other);
}

//! sort in order X, Y. Difference must be above rounding tolerance.
//! sort in order X, Y.
bool operator<(const vector2d<T>&other) const
{
return (X<other.X && !core::equals(X, other.X)) ||
(core::equals(X, other.X) && Y<other.Y && !core::equals(Y, other.Y));
return X < other.X || (X == other.X && Y < other.Y);
}

//! sort in order X, Y. Difference must be above rounding tolerance.
//! sort in order X, Y.
bool operator>(const vector2d<T>&other) const
{
return (X>other.X && !core::equals(X, other.X)) ||
(core::equals(X, other.X) && Y>other.Y && !core::equals(Y, other.Y));
return X > other.X || (X == other.X && Y > other.Y);
}

bool operator==(const vector2d<T>& other) const { return equals(other); }
bool operator!=(const vector2d<T>& other) const { return !equals(other); }
bool operator==(const vector2d<T>& other) const {
return X == other.X && Y == other.Y;
}

bool operator!=(const vector2d<T>& other) const {
return !(*this == other);
}

// functions

//! Checks if this vector equals the other one.
/** Takes floating point rounding errors into account.
\param other Vector to compare with.
\param tolerance Epsilon value for both - comparing X and Y.
\return True if the two vector are (almost) equal, else false. */
bool equals(const vector2d<T>& other, const T tolerance = (T)ROUNDING_ERROR_f32 ) const
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a good default. Fortunately, this parameter is not used.

bool equals(const vector2d<T>& other) const
{
return core::equals(X, other.X, tolerance) && core::equals(Y, other.Y, tolerance);
return core::equals(X, other.X) && core::equals(Y, other.Y);
}

vector2d<T>& set(T nx, T ny) {X=nx; Y=ny; return *this; }
Expand Down
42 changes: 18 additions & 24 deletions include/vector3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,57 +68,51 @@ namespace core
return *(&X+index);
}

//! sort in order X, Y, Z. Equality with rounding tolerance.
//! sort in order X, Y, Z.
bool operator<=(const vector3d<T>&other) const
{
return (X<other.X || core::equals(X, other.X)) ||
(core::equals(X, other.X) && (Y<other.Y || core::equals(Y, other.Y))) ||
(core::equals(X, other.X) && core::equals(Y, other.Y) && (Z<other.Z || core::equals(Z, other.Z)));
return !(*this > other);
}

//! sort in order X, Y, Z. Equality with rounding tolerance.
//! sort in order X, Y, Z.
bool operator>=(const vector3d<T>&other) const
{
return (X>other.X || core::equals(X, other.X)) ||
(core::equals(X, other.X) && (Y>other.Y || core::equals(Y, other.Y))) ||
(core::equals(X, other.X) && core::equals(Y, other.Y) && (Z>other.Z || core::equals(Z, other.Z)));
return !(*this < other);
}

//! sort in order X, Y, Z. Difference must be above rounding tolerance.
//! sort in order X, Y, Z.
bool operator<(const vector3d<T>&other) const
{
return (X<other.X && !core::equals(X, other.X)) ||
(core::equals(X, other.X) && Y<other.Y && !core::equals(Y, other.Y)) ||
(core::equals(X, other.X) && core::equals(Y, other.Y) && Z<other.Z && !core::equals(Z, other.Z));
return X < other.X || (X == other.X && Y < other.Y) ||
(X == other.X && Y == other.Y && Z < other.Z);
}

//! sort in order X, Y, Z. Difference must be above rounding tolerance.
//! sort in order X, Y, Z.
bool operator>(const vector3d<T>&other) const
{
return (X>other.X && !core::equals(X, other.X)) ||
(core::equals(X, other.X) && Y>other.Y && !core::equals(Y, other.Y)) ||
(core::equals(X, other.X) && core::equals(Y, other.Y) && Z>other.Z && !core::equals(Z, other.Z));
return X > other.X || (X == other.X && Y > other.Y) ||
(X == other.X && Y == other.Y && Z > other.Z);
}

//! use weak float compare
bool operator==(const vector3d<T>& other) const
{
return this->equals(other);
return X == other.X && Y == other.Y && Z == other.Z;
}

bool operator!=(const vector3d<T>& other) const
{
return !this->equals(other);
return !(*this == other);
}

// functions

//! returns if this vector equals the other one, taking floating point rounding errors into account
bool equals(const vector3d<T>& other, const T tolerance = (T)ROUNDING_ERROR_f32 ) const
//! Checks if this vector equals the other one.
/** Takes floating point rounding errors into account.
\param other Vector to compare with.
\return True if the two vector are (almost) equal, else false. */
bool equals(const vector3d<T>& other) const
{
return core::equals(X, other.X, tolerance) &&
core::equals(Y, other.Y, tolerance) &&
core::equals(Z, other.Z, tolerance);
return core::equals(X, other.X) && core::equals(Y, other.Y) && core::equals(Z, other.Z);
}

vector3d<T>& set(const T nx, const T ny, const T nz) {X=nx; Y=ny; Z=nz; return *this;}
Expand Down