From 49841a7246420decb997f228851b6abfa1c4342c Mon Sep 17 00:00:00 2001 From: jtlap Date: Sun, 20 Aug 2023 22:59:47 +0200 Subject: [PATCH] dist reldist sqr --- include/kyosu/functions.hpp | 2 + include/kyosu/functions/abs.hpp | 44 -------------- include/kyosu/functions/dist.hpp | 79 ++++++++++++++++++++++++ include/kyosu/functions/reldist.hpp | 80 +++++++++++++++++++++++++ include/kyosu/types/impl/arithmetic.hpp | 15 +++++ test/doc/dist.cpp | 38 ++++++++++++ test/test.hpp | 1 + test/unit/function/dist.cpp | 39 ++++++++++++ test/unit/function/sqr.cpp | 9 ++- 9 files changed, 258 insertions(+), 49 deletions(-) create mode 100644 include/kyosu/functions/dist.hpp create mode 100644 include/kyosu/functions/reldist.hpp create mode 100644 test/doc/dist.cpp create mode 100644 test/unit/function/dist.cpp diff --git a/include/kyosu/functions.hpp b/include/kyosu/functions.hpp index 3fae3349..8613eaec 100644 --- a/include/kyosu/functions.hpp +++ b/include/kyosu/functions.hpp @@ -13,11 +13,13 @@ //====================================================================================================================== #include #include +#include #include #include #include #include #include #include +#include #include #include diff --git a/include/kyosu/functions/abs.hpp b/include/kyosu/functions/abs.hpp index f2cf603b..fbbbcc64 100644 --- a/include/kyosu/functions/abs.hpp +++ b/include/kyosu/functions/abs.hpp @@ -1,47 +1,3 @@ -//! -//! **Defined in Header** -//! -//! @code -//! #include -//! @endcode -//! -//! @groupheader{Callable Signatures} -//! -//! @code -//! namespace eve -//! { -//! template< eve::value T > -//! T abs(T x) noexcept; //1 -//! -//! template< eve::floating_value T > -//! T abs(eve::as_complex z) noexcept; //2 -//! -//! } -//! @endcode -//! -//! **Parameters** -//! -//! * `x` : [real argument](@ref eve::value). -//! * `z` : [complex argument ](@ref eve::complex). -//! -//! **Return value** -//! -//! 1. value containing the [elementwise](@ref glossary_elementwise) -//! absolute value of `x` if it is representable in this type. -//! -//! More specifically, for signed integers : the absolute value of eve::valmin -//! is not representable and the result is undefined. -//! -//! -//! 2. -//! -//! @warning -//! abs is also a standard library function name and there possibly -//! exists a C macro version which may be called instead of the EVE version. -//! To avoid confusion, use the eve::abs notation. -//! - - //====================================================================================================================== /* Kyosu - Complex Without Complexes diff --git a/include/kyosu/functions/dist.hpp b/include/kyosu/functions/dist.hpp new file mode 100644 index 00000000..f0ae4f5b --- /dev/null +++ b/include/kyosu/functions/dist.hpp @@ -0,0 +1,79 @@ +//====================================================================================================================== +/* + Kyosu - Complex Without Complexes + Copyright : KYOSU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//====================================================================================================================== +#pragma once + +#include + +namespace kyosu::tags +{ + struct callable_dist : eve::elementwise + { + using callable_tag_type = callable_dist; + + KYOSU_DEFERS_CALLABLE(dist_); + + static KYOSU_FORCEINLINE auto deferred_call(auto + , eve::ordered_value auto const& v0 + , eve::ordered_value auto const& v1) noexcept + { + return eve::dist(v0, v1); + } + + KYOSU_FORCEINLINE auto operator()(auto const& target0, auto const& target1 ) const noexcept + -> decltype(eve::tag_invoke(*this, target0, target1)) + { + return eve::tag_invoke(*this, target0, target1); + } + + template + eve::unsupported_call operator()(T&&... x) const + requires(!requires { eve::tag_invoke(*this, KYOSU_FWD(x)...); }) = delete; + }; +} + +namespace kyosu +{ +//====================================================================================================================== +//! @addtogroup functions +//! @{ +//! @var dist +//! @brief Computes the distance of the two parameters. +//! +//! **Defined in Header** +//! +//! @code +//! #include +//! @endcode +//! +//! @groupheader{Callable Signatures} +//! +//! @code +//! namespace kyosu +//! { +//! template constexpr auto dist(T0 z0, T1, z1) noexcept; +//! template > constexpr auto dist(T0 z0, T1, z1) noexcept; +//! template constexpr auto dist(T0 z0, T1, z1) noexcept; +//! template > constexpr auto dist(T0 z0, T1, z1) noexcept; +///! } +//! @endcode +//! +//! **Parameters** +//! +//! * `z0, z1` : Value to process. +//! +//! **Return value** +//! +//! Returns the absolute value of the arguments difference. +//! +//! @groupheader{Example} +//! +//! @godbolt{doc/dist.cpp} +//! @} +//====================================================================================================================== +inline constexpr tags::callable_dist dist = {}; +} diff --git a/include/kyosu/functions/reldist.hpp b/include/kyosu/functions/reldist.hpp new file mode 100644 index 00000000..3bd02ca0 --- /dev/null +++ b/include/kyosu/functions/reldist.hpp @@ -0,0 +1,80 @@ +//====================================================================================================================== +/* + Kyosu - Complex Without Complexes + Copyright : KYOSU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//====================================================================================================================== +#pragma once + +#include + +namespace kyosu::tags +{ + struct callable_reldist : eve::elementwise + { + using callable_tag_type = callable_reldist; + + KYOSU_DEFERS_CALLABLE(reldist_); + + + static KYOSU_FORCEINLINE auto deferred_call(auto + , eve::ordered_value auto const& v0 + , eve::ordered_value auto const& v1) noexcept + { + return eve::reldist(v0, v1); + } + + KYOSU_FORCEINLINE auto operator()(auto const& target0, auto const& target1 ) const noexcept + -> decltype(eve::tag_invoke(*this, target0, target1)) + { + return eve::tag_invoke(*this, target0, target1); + } + + template + eve::unsupported_call operator()(T&&... x) const + requires(!requires { eve::tag_invoke(*this, KYOSU_FWD(x)...); }) = delete; + }; +} + +namespace kyosu +{ +//====================================================================================================================== +//! @addtogroup functions +//! @{ +//! @var reldist +//! @brief Computes the relative distance of the two parameters. +//! +//! **Defined in Header** +//! +//! @code +//! #include +//! @endcode +//! +//! @groupheader{Callable Signatures} +//! +//! @code +//! namespace kyosu +//! { +//! template constexpr auto reldist(T0 z0, T1, z1) noexcept; +//! template > constexpr auto reldist(T0 z0, T1, z1) noexcept; +//! template constexpr auto reldist(T0 z0, T1, z1) noexcept; +//! template > constexpr auto reldist(T0 z0, T1, z1) noexcept; +///! } +//! @endcode +//! +//! **Parameters** +//! +//! * `z0, z1` : Value to process. +//! +//! **Return value** +//! +//! Returns the absolute value of the arguments difference dived by the maximum of their absolute values and 1. +//! +//! @groupheader{Example} +//! +//! @godbolt{doc/reldist.cpp} +//! @} +//====================================================================================================================== +inline constexpr tags::callable_reldist reldist = {}; +} diff --git a/include/kyosu/types/impl/arithmetic.hpp b/include/kyosu/types/impl/arithmetic.hpp index ae21545b..74d16476 100644 --- a/include/kyosu/types/impl/arithmetic.hpp +++ b/include/kyosu/types/impl/arithmetic.hpp @@ -73,4 +73,19 @@ namespace kyosu::_ real(c) = 0; return r+a*c; } + + template + KYOSU_FORCEINLINE constexpr + auto dispatch(eve::tag_of const&, C0 const & c0, C1 const & c1) noexcept + { + return kyosu::abs(c0-c1); + } + + template + KYOSU_FORCEINLINE constexpr + auto dispatch(eve::tag_of const&, C0 const & c0, C1 const & c1) noexcept + { + return kyosu::dist(c0, c1)/eve::max(kyosu::abs(c0), kyosu::abs(c1), eve::one(eve::as(abs(c0)))); + } + } diff --git a/test/doc/dist.cpp b/test/doc/dist.cpp new file mode 100644 index 00000000..2eaf5f78 --- /dev/null +++ b/test/doc/dist.cpp @@ -0,0 +1,38 @@ +#include +#include +#include + +int main() +{ + using kyosu::dist; + using kyosu::complex; + using kyosu::quaternion; + using e_t = float; + using c_t = complex; + using q_t = quaternion; + + std::cout << "Real: "<< "\n"; + e_t e0(1); + e_t e1(2); + std::cout << e0 << ", " << e1 << " -> " << dist(e0, e1) << "\n"; + + std::cout << "Complex: "<< "\n"; + c_t c0(1, 5); + c_t c1(5, 9); + std::cout << c0 << ", " << c1 << " -> " << dist(c0, c1) << "\n"; + + + + std::cout << "Quaternion: "<< "\n"; + q_t q0(1, 5); + q_t q1(5, 9); + std::cout << q0 << ", " << q1 << " -> " << dist(q0, q1) << "\n"; + + +// std::cout << "SIMD: "; +// using wc_t = eve::wide, eve::fixed<2>>; +// std::cout << wc_t(complex(1.3,-3.7)) << " -> " << dist(wc_t(complex(1.3,-3.7))) << "\n"; +// std::cout << wc_t(complex(1.3,-3.7)) << " -> " << (wc_t(complex(1.3,-3.7)))*(wc_t(complex(1.3,-3.7)))<< "\n"; + + return 0; +} diff --git a/test/test.hpp b/test/test.hpp index 666ebb5c..b1cd4855 100644 --- a/test/test.hpp +++ b/test/test.hpp @@ -86,6 +86,7 @@ int main(int argc, char const **argv) namespace tts { + template auto relative_distance(T const &l, T const &r) { auto [rl,il] = l; diff --git a/test/unit/function/dist.cpp b/test/unit/function/dist.cpp new file mode 100644 index 00000000..20e4a1be --- /dev/null +++ b/test/unit/function/dist.cpp @@ -0,0 +1,39 @@ +#include +#include +#include + +int main() +{ + using kyosu::dist; + using kyosu::complex; + using kyosu::quaternion; + using e_t = float; + using c_t = complex; + using q_t = quaternion; + + std::cout << "Real: "<< "\n"; + e_t e0(1); + e_t e1(2); + std::cout << e0 << ", " << e1 << " -> " << dist(e0, e1) << "\n"; + + std::cout << "Complex: "<< "\n"; + c_t c0(1, 5); + c_t c1(4, 9); + std::cout << c0 << ", " << c1 << " -> " << dist(c0, c1) << "\n"; + + + + std::cout << "Quaternion: "<< "\n"; + q_t q0(1, 5, 2, 3); + q_t q1(5, 9, 6, 7); + std::cout << q0 << ", " << q1 << " -> " << dist(q0, q1) << "\n"; + + + std::cout << "SIMD: "<< "\n"; + using wq_t = eve::wide, eve::fixed<2>>; + wq_t wq0(1, 5, 2, 3); + wq_t wq1(5, 9, 6, 7); + std::cout << wq0 << ", " << wq1 << " -> " << dist(wq0, wq1) << "\n"; + + return 0; +} diff --git a/test/unit/function/sqr.cpp b/test/unit/function/sqr.cpp index f184ee4a..e893b123 100644 --- a/test/unit/function/sqr.cpp +++ b/test/unit/function/sqr.cpp @@ -14,7 +14,7 @@ TTS_CASE_WITH ( "Check kyosu::sqr over real" ) (auto data) { - TTS_EQUAL(kyosu::sqr(data), eve::sqr(data)); + TTS_ULP_EQUAL(kyosu::sqr(data), eve::sqr(data), 0.5); }; TTS_CASE_WITH ( "Check kyosu::sqr over complex" @@ -24,7 +24,7 @@ TTS_CASE_WITH ( "Check kyosu::sqr over complex" (auto r, auto i) { auto c = kyosu::to_complex(r,i); - TTS_EQUAL(kyosu::sqr(c), c*c); + TTS_EXPECT(eve::all(kyosu::reldist(kyosu::sqr(c), c*c) <= 0.0001)); }; TTS_CASE_WITH ( "Check kyosu::sqr over quaternion" @@ -36,7 +36,6 @@ TTS_CASE_WITH ( "Check kyosu::sqr over quaternion" (T r, T i, T j, T k) { using type = kyosu::as_quaternion_t; - auto o = type(r,i,j,k); - - TTS_EQUAL(kyosu::sqr(o), o*o); + auto q = type(r,i,j,k); + TTS_EXPECT(eve::all(kyosu::reldist(kyosu::sqr(q), q*q) <= 0.0001)); };