From c1cb6cba782c4e2e8dabf7d22f97f2dadf53add6 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Sun, 28 Feb 2021 12:50:05 +0700 Subject: [PATCH 1/4] fix approx with epsilon --- headers/vmath.hpp/vmath_fun.hpp | 20 +++++++------------- untests/vmath_fun_tests.cpp | 9 +++++++++ 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/headers/vmath.hpp/vmath_fun.hpp b/headers/vmath.hpp/vmath_fun.hpp index f155291..88b9b61 100644 --- a/headers/vmath.hpp/vmath_fun.hpp +++ b/headers/vmath.hpp/vmath_fun.hpp @@ -393,6 +393,12 @@ namespace vmath_hpp return !!x; } + template < typename T > + [[nodiscard]] std::enable_if_t, bool> + constexpr approx(T x, T y, T epsilon) noexcept { + return abs(x - y) <= epsilon; + } + template < typename T > [[nodiscard]] std::enable_if_t, bool> constexpr approx(T x, T y) noexcept { @@ -400,24 +406,12 @@ namespace vmath_hpp /// REFERENCE: /// http://www.realtimecollisiondetection.net/pubs/Tolerances const T epsilon = std::numeric_limits::epsilon(); - return abs(x - y) <= epsilon * max(max(T{1}, abs(x)), abs(y)); + return approx(x, y, epsilon * max(T{1}, max(abs(x), abs(y)))); } else { return x == y; } } - template < typename T > - [[nodiscard]] std::enable_if_t, bool> - constexpr approx(T x, T y, T epsilon) noexcept { - if constexpr ( std::is_floating_point_v ) { - /// REFERENCE: - /// http://www.realtimecollisiondetection.net/pubs/Tolerances - return abs(x - y) <= epsilon * max(max(T{1}, abs(x)), abs(y)); - } else { - return abs(x - y) <= epsilon; - } - } - template < typename T > [[nodiscard]] std::enable_if_t, bool> constexpr less(T x, T y) noexcept { diff --git a/untests/vmath_fun_tests.cpp b/untests/vmath_fun_tests.cpp index 4bb37e9..609e966 100644 --- a/untests/vmath_fun_tests.cpp +++ b/untests/vmath_fun_tests.cpp @@ -151,6 +151,15 @@ TEST_CASE("vmath/fun") { STATIC_CHECK_FALSE(approx(0, 1)); STATIC_CHECK_FALSE(approx(0, 1, 0)); STATIC_CHECK(approx(0, 1, 1)); + STATIC_CHECK_FALSE(approx(1, 3, 1)); + STATIC_CHECK(approx(1, 3, 2)); + + STATIC_CHECK(approx(1.f, 1.f)); + STATIC_CHECK_FALSE(approx(0.f, 1.f)); + STATIC_CHECK_FALSE(approx(0.f, 1.f, 0.f)); + STATIC_CHECK(approx(0.f, 1.f, 1.f)); + STATIC_CHECK_FALSE(approx(1.f, 3.f, 1.f)); + STATIC_CHECK(approx(1.f, 3.f, 2.f)); STATIC_CHECK(approx(1.f, 1.f + std::numeric_limits::epsilon() * 0.5f)); STATIC_CHECK_FALSE(approx(1.f, 1.f + std::numeric_limits::epsilon() * 1.5f)); From 29755fe067da4fdf4f3be5d42b4a969579eed375 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Sun, 28 Feb 2021 13:13:50 +0700 Subject: [PATCH 2/4] fix approx with epsilon --- headers/vmath.hpp/vmath_fun.hpp | 6 +++++- untests/vmath_fun_tests.cpp | 7 +++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/headers/vmath.hpp/vmath_fun.hpp b/headers/vmath.hpp/vmath_fun.hpp index 88b9b61..65350fa 100644 --- a/headers/vmath.hpp/vmath_fun.hpp +++ b/headers/vmath.hpp/vmath_fun.hpp @@ -396,7 +396,11 @@ namespace vmath_hpp template < typename T > [[nodiscard]] std::enable_if_t, bool> constexpr approx(T x, T y, T epsilon) noexcept { - return abs(x - y) <= epsilon; + if constexpr ( std::is_unsigned_v ) { + return (x < y ? (y - x) : (x - y)) <= epsilon; + } else { + return abs(x - y) <= epsilon; + } } template < typename T > diff --git a/untests/vmath_fun_tests.cpp b/untests/vmath_fun_tests.cpp index 609e966..d020eb1 100644 --- a/untests/vmath_fun_tests.cpp +++ b/untests/vmath_fun_tests.cpp @@ -154,6 +154,13 @@ TEST_CASE("vmath/fun") { STATIC_CHECK_FALSE(approx(1, 3, 1)); STATIC_CHECK(approx(1, 3, 2)); + STATIC_CHECK(approx(1u, 1u)); + STATIC_CHECK_FALSE(approx(0u, 1u)); + STATIC_CHECK_FALSE(approx(0u, 1u, 0u)); + STATIC_CHECK(approx(0u, 1u, 1u)); + STATIC_CHECK_FALSE(approx(1u, 3u, 1u)); + STATIC_CHECK(approx(1u, 3u, 2u)); + STATIC_CHECK(approx(1.f, 1.f)); STATIC_CHECK_FALSE(approx(0.f, 1.f)); STATIC_CHECK_FALSE(approx(0.f, 1.f, 0.f)); From 9cf33dd16daa63cfcb49e00b1f5c83d2ed30296e Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Sun, 28 Feb 2021 13:40:50 +0700 Subject: [PATCH 3/4] fix distance --- headers/vmath.hpp/vmath_fun.hpp | 19 ++++++++++++------- headers/vmath.hpp/vmath_vec_fun.hpp | 4 ++-- untests/vmath_fun_tests.cpp | 8 ++++++++ 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/headers/vmath.hpp/vmath_fun.hpp b/headers/vmath.hpp/vmath_fun.hpp index 65350fa..c35ff4c 100644 --- a/headers/vmath.hpp/vmath_fun.hpp +++ b/headers/vmath.hpp/vmath_fun.hpp @@ -339,13 +339,22 @@ namespace vmath_hpp template < typename T > [[nodiscard]] std::enable_if_t, T> constexpr distance(T x, T y) noexcept { - return length(y - x); + if constexpr ( std::is_unsigned_v ) { + return x < y ? (y - x) : (x - y); + } else { + return length(x - y); + } } template < typename T > [[nodiscard]] std::enable_if_t, T> constexpr distance2(T x, T y) noexcept { - return length2(y - x); + if constexpr ( std::is_unsigned_v ) { + const T d = x < y ? (y - x) : (x - y); + return d * d; + } else { + return length2(x - y); + } } template < typename T > @@ -396,11 +405,7 @@ namespace vmath_hpp template < typename T > [[nodiscard]] std::enable_if_t, bool> constexpr approx(T x, T y, T epsilon) noexcept { - if constexpr ( std::is_unsigned_v ) { - return (x < y ? (y - x) : (x - y)) <= epsilon; - } else { - return abs(x - y) <= epsilon; - } + return distance(x, y) <= epsilon; } template < typename T > diff --git a/headers/vmath.hpp/vmath_vec_fun.hpp b/headers/vmath.hpp/vmath_vec_fun.hpp index 2667114..02c13de 100644 --- a/headers/vmath.hpp/vmath_vec_fun.hpp +++ b/headers/vmath.hpp/vmath_vec_fun.hpp @@ -954,12 +954,12 @@ namespace vmath_hpp template < typename T, std::size_t Size > [[nodiscard]] constexpr T distance(const vec& xs, const vec& ys) { - return length(ys - xs); + return length(xs - ys); } template < typename T, std::size_t Size > [[nodiscard]] constexpr T distance2(const vec& xs, const vec& ys) { - return length2(ys - xs); + return length2(xs - ys); } template < typename T, typename U diff --git a/untests/vmath_fun_tests.cpp b/untests/vmath_fun_tests.cpp index d020eb1..be59f6c 100644 --- a/untests/vmath_fun_tests.cpp +++ b/untests/vmath_fun_tests.cpp @@ -120,9 +120,17 @@ TEST_CASE("vmath/fun") { STATIC_CHECK(rlength2(10.f) == uapprox(0.01f)); STATIC_CHECK(rlength2(-10.f) == uapprox(0.01f)); + STATIC_CHECK(distance(5, 10) == 5); + STATIC_CHECK(distance(10, 5) == 5); + STATIC_CHECK(distance(5u, 10u) == 5); + STATIC_CHECK(distance(10u, 5u) == 5); STATIC_CHECK(distance(5.f, 10.f) == uapprox(5.f)); STATIC_CHECK(distance(-5.f, -10.f) == uapprox(5.f)); + STATIC_CHECK(distance2(5, 10) == 25); + STATIC_CHECK(distance2(10, 5) == 25); + STATIC_CHECK(distance2(5u, 10u) == 25); + STATIC_CHECK(distance2(10u, 5u) == 25); STATIC_CHECK(distance2(5.f, 10.f) == uapprox(25.f)); STATIC_CHECK(distance2(-5.f, -10.f) == uapprox(25.f)); From e53c394ddb44deb7af637e7380037ff3d9e264c0 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Sun, 28 Feb 2021 13:46:24 +0700 Subject: [PATCH 4/4] update singles --- singles/vmath.hpp/vmath.hpp | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/singles/vmath.hpp/vmath.hpp b/singles/vmath.hpp/vmath.hpp index c68a0eb..093bc48 100644 --- a/singles/vmath.hpp/vmath.hpp +++ b/singles/vmath.hpp/vmath.hpp @@ -446,13 +446,22 @@ namespace vmath_hpp template < typename T > [[nodiscard]] std::enable_if_t, T> constexpr distance(T x, T y) noexcept { - return length(y - x); + if constexpr ( std::is_unsigned_v ) { + return x < y ? (y - x) : (x - y); + } else { + return length(x - y); + } } template < typename T > [[nodiscard]] std::enable_if_t, T> constexpr distance2(T x, T y) noexcept { - return length2(y - x); + if constexpr ( std::is_unsigned_v ) { + const T d = x < y ? (y - x) : (x - y); + return d * d; + } else { + return length2(x - y); + } } template < typename T > @@ -500,6 +509,12 @@ namespace vmath_hpp return !!x; } + template < typename T > + [[nodiscard]] std::enable_if_t, bool> + constexpr approx(T x, T y, T epsilon) noexcept { + return distance(x, y) <= epsilon; + } + template < typename T > [[nodiscard]] std::enable_if_t, bool> constexpr approx(T x, T y) noexcept { @@ -507,24 +522,12 @@ namespace vmath_hpp /// REFERENCE: /// http://www.realtimecollisiondetection.net/pubs/Tolerances const T epsilon = std::numeric_limits::epsilon(); - return abs(x - y) <= epsilon * max(max(T{1}, abs(x)), abs(y)); + return approx(x, y, epsilon * max(T{1}, max(abs(x), abs(y)))); } else { return x == y; } } - template < typename T > - [[nodiscard]] std::enable_if_t, bool> - constexpr approx(T x, T y, T epsilon) noexcept { - if constexpr ( std::is_floating_point_v ) { - /// REFERENCE: - /// http://www.realtimecollisiondetection.net/pubs/Tolerances - return abs(x - y) <= epsilon * max(max(T{1}, abs(x)), abs(y)); - } else { - return abs(x - y) <= epsilon; - } - } - template < typename T > [[nodiscard]] std::enable_if_t, bool> constexpr less(T x, T y) noexcept { @@ -1767,12 +1770,12 @@ namespace vmath_hpp template < typename T, std::size_t Size > [[nodiscard]] constexpr T distance(const vec& xs, const vec& ys) { - return length(ys - xs); + return length(xs - ys); } template < typename T, std::size_t Size > [[nodiscard]] constexpr T distance2(const vec& xs, const vec& ys) { - return length2(ys - xs); + return length2(xs - ys); } template < typename T, typename U