Skip to content

Commit

Permalink
Implements manhattan, lpnorm and hypot
Browse files Browse the repository at this point in the history
  • Loading branch information
jtlap committed Sep 4, 2023
1 parent cfa3239 commit 0c4112e
Show file tree
Hide file tree
Showing 11 changed files with 534 additions and 1 deletion.
3 changes: 3 additions & 0 deletions include/kyosu/functions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <kyosu/functions/exp_ipi.hpp>
#include <kyosu/functions/floor.hpp>
#include <kyosu/functions/frac.hpp>
#include <kyosu/functions/hypot.hpp>
#include <kyosu/functions/if_else.hpp>
#include <kyosu/functions/inc.hpp>
#include <kyosu/functions/ipart.hpp>
Expand All @@ -59,6 +60,8 @@
#include <kyosu/functions/log1p.hpp>
#include <kyosu/functions/log10.hpp>
#include <kyosu/functions/log2.hpp>
#include <kyosu/functions/lpnorm.hpp>
#include <kyosu/functions/manhattan.hpp>
#include <kyosu/functions/minus.hpp>
#include <kyosu/functions/nearest.hpp>
#include <kyosu/functions/oneminus.hpp>
Expand Down
76 changes: 76 additions & 0 deletions include/kyosu/functions/hypot.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//======================================================================================================================
/*
Kyosu - Complex Without Complexes
Copyright : KYOSU Contributors & Maintainers
SPDX-License-Identifier: BSL-1.0
*/
//======================================================================================================================
#pragma once

#include <kyosu/details/invoke.hpp>

namespace kyosu::tags
{
struct callable_hypot : eve::elementwise
{
using callable_tag_type = callable_hypot;

KYOSU_DEFERS_CALLABLE(hypot_);

static KYOSU_FORCEINLINE auto deferred_call(auto
, eve::ordered_value auto const&... vs) noexcept
{
return eve::hypot(vs...);
}

KYOSU_FORCEINLINE auto operator()(auto const&... targets ) const noexcept
-> decltype(eve::tag_invoke(*this, targets...))
{
return eve::tag_invoke(*this, targets...);
}

// template<typename... T>
// eve::unsupported_call<callable_hypot(T&&...)> operator()(T&&... x) const
// requires(!requires { eve::tag_invoke(*this, KYOSU_FWD(x)...); }) = delete;
};
}

namespace kyosu
{
//======================================================================================================================
//! @addtogroup functions
//! @{
//! @var hypot
//! @brief Callable object computing the hypot operation.
//!
//! **Defined in Header**
//!
//! @code
//! #include <kyosu/functions.hpp>
//! @endcode
//!
//! @groupheader{Callable Signatures}
//!
//! @code
//! namespace kyosu
//! {
//! template< floating_value P, typename ... Ts>
//! auto operator()(Ts ... zi ) const noexcept
///! }
//! @endcode
//!
//! **Parameters**
//!
//! * ` zi...` : Values to process.
//!
//! **Return value**
//!
//! Returns \f$ \sqrt\sum_{i = 0}^n//! |z_i|^2} \f$.
//!
//! @groupheader{Example}
//!
//! @godbolt{doc/hypot.cpp}
//! @}
//======================================================================================================================
inline constexpr tags::callable_hypot hypot = {};
}
78 changes: 78 additions & 0 deletions include/kyosu/functions/lpnorm.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
//======================================================================================================================
/*
Kyosu - Complex Without Complexes
Copyright : KYOSU Contributors & Maintainers
SPDX-License-Identifier: BSL-1.0
*/
//======================================================================================================================
#pragma once

#include <kyosu/details/invoke.hpp>

namespace kyosu::tags
{
struct callable_lpnorm : eve::elementwise
{
using callable_tag_type = callable_lpnorm;

KYOSU_DEFERS_CALLABLE(lpnorm_);

static KYOSU_FORCEINLINE auto deferred_call(auto
, eve::floating_value auto const& p
, eve::floating_ordered_value auto const&... vs) noexcept
{
return eve::lpnorm(p, vs...);
}

KYOSU_FORCEINLINE auto operator()(auto const&... targets ) const noexcept
-> decltype(eve::tag_invoke(*this, targets...))
{
return eve::tag_invoke(*this, targets...);
}

template<typename... T>
eve::unsupported_call<callable_lpnorm(T&&...)> operator()(T&&... x) const
requires(!requires { eve::tag_invoke(*this, KYOSU_FWD(x)...); }) = delete;
};
}

namespace kyosu
{
//======================================================================================================================
//! @addtogroup functions
//! @{
//! @var lpnorm
//! @brief Callable object computing the lpnorm operation \f$ \left(\sum_{i = 0}^n
//! |x_i|^p\right)^{\frac1p} \f$.
//!
//! **Defined in Header**
//!
//! @code
//! #include <kyosu/functions.hpp>
//! @endcode
//!
//! @groupheader{Callable Signatures}
//!
//! @code
//! namespace kyosu
//! {
//! template< floating_value P, typename T, typename ... Ts>
//! auto operator()(P p, T z,Ts ... zs ) const noexcept
///! }
//! @endcode
//!
//! **Parameters**
//!
//! * `z, zs...` : Values to process.
//!
//! **Return value**
//!
//! Returns \f$ \left(\sum_{i = 0}^n//! |x_i|^p\right)^{\frac1p} \f$.
//!
//! @groupheader{Example}
//!
//! @godbolt{doc/lpnorm.cpp}
//! @}
//======================================================================================================================
inline constexpr tags::callable_lpnorm lpnorm = {};
}
76 changes: 76 additions & 0 deletions include/kyosu/functions/manhattan.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//======================================================================================================================
/*
Kyosu - Complex Without Complexes
Copyright : KYOSU Contributors & Maintainers
SPDX-License-Identifier: BSL-1.0
*/
//======================================================================================================================
#pragma once

#include <kyosu/details/invoke.hpp>

namespace kyosu::tags
{
struct callable_manhattan : eve::elementwise
{
using callable_tag_type = callable_manhattan;

KYOSU_DEFERS_CALLABLE(manhattan_);

static KYOSU_FORCEINLINE auto deferred_call(auto
, eve::ordered_value auto const&... vs) noexcept
{
return eve::manhattan(vs...);
}

KYOSU_FORCEINLINE auto operator()(auto const&... targets ) const noexcept
-> decltype(eve::tag_invoke(*this, targets...))
{
return eve::tag_invoke(*this, targets...);
}

// template<typename... T>
// eve::unsupported_call<callable_manhattan(T&&...)> operator()(T&&... x) const
// requires(!requires { eve::tag_invoke(*this, KYOSU_FWD(x)...); }) = delete;
};
}

namespace kyosu
{
//======================================================================================================================
//! @addtogroup functions
//! @{
//! @var manhattan
//! @brief Callable object computing the manhattan operation.
//!
//! **Defined in Header**
//!
//! @code
//! #include <kyosu/functions.hpp>
//! @endcode
//!
//! @groupheader{Callable Signatures}
//!
//! @code
//! namespace kyosu
//! {
//! template< floating_value P, typename ... Ts>
//! auto operator()(Ts ... zi ) const noexcept
///! }
//! @endcode
//!
//! **Parameters**
//!
//! * ` zi...` : Values to process.
//!
//! **Return value**
//!
//! Returns the sum of the absolute values of all elements of all zi.
//!
//! @groupheader{Example}
//!
//! @godbolt{doc/manhattan.cpp}
//! @}
//======================================================================================================================
inline constexpr tags::callable_manhattan manhattan = {};
}
26 changes: 25 additions & 1 deletion include/kyosu/types/impl/math.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,6 @@ namespace kyosu::_
C res;
auto rr1 = eve::if_else(is_real_z, sqrtx, w);
auto ii1 = eve::if_else(is_real_z, eve::zero, iaz*eve::half(eve::as(r))/w);
// auto res = kyosu::to_complex(rr1, ii1);
res = kyosu::if_else(gezrz
, to_complex(rr1, ii1)
, to_complex(ii1, rr1)
Expand Down Expand Up @@ -314,4 +313,29 @@ namespace kyosu::_
}
}

template<eve::floating_value T, typename ...Cs>
KYOSU_FORCEINLINE constexpr
auto dispatch(eve::tag_of<kyosu::lpnorm> const&, T const & p, Cs const &... zs) noexcept
{
if constexpr(sizeof...(zs) == 0) return 0.0f;
if constexpr(sizeof...(zs) == 1) return kyosu::abs(zs...);
else return eve::lpnorm(p, kyosu::abs(zs)...);
}

template<typename ...Cs>
KYOSU_FORCEINLINE constexpr
auto dispatch(eve::tag_of<kyosu::hypot> const&, Cs const &... zs) noexcept
{
if constexpr(sizeof...(zs) == 0) return 0.0f;
if constexpr(sizeof...(zs) == 1) return kyosu::abs(zs...);
else return eve::hypot(kumi::flatten(kumi::cat(zs...)));
}

template<typename ...Cs>
KYOSU_FORCEINLINE constexpr
auto dispatch(eve::tag_of<kyosu::manhattan> const&, Cs const &... zs) noexcept
{
if constexpr(sizeof...(zs) == 0) return 0.0f;
else return eve::manhattan(kumi::flatten(kumi::cat(zs...)));
}
}
42 changes: 42 additions & 0 deletions test/doc/hypot.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include <kyosu/kyosu.hpp>
#include <eve/wide.hpp>
#include <iostream>

int main()
{
using kyosu::hypot;
using kyosu::complex;
using kyosu::quaternion;
using e_t = float;
using c_t = complex<float>;
using q_t = quaternion<float>;
using we_t = eve::wide<float, eve::fixed<2>>;
using wc_t = eve::wide<complex<float>, eve::fixed<2>>;
using wq_t = eve::wide<quaternion<float>, eve::fixed<2>>;

std::cout << "Real: "<< "\n";
e_t e0(1);
e_t e1(2);
std::cout << e0 << ", " << e1 << " -> " << hypot(e0, e1) << "\n";
we_t we0(e0);
we_t we1(e1);
std::cout << we0 << ", " << we1 << " -> " << hypot(we0, we1) << "\n";

std::cout << "Complex: "<< "\n";
c_t c0(5);
c_t c1(5, 9);
std::cout << c0 << ", " << c1 << " -> " << hypot(c0, c1) << "\n";
wc_t wc0(c0);
wc_t wc1(c1);
std::cout << wc0 << ", " << wc1 << " -> " << hypot(wc0, wc1) << "\n";

std::cout << "Quaternion: "<< "\n";
q_t q0(5, 2, 3);
q_t q1(5, 9, 6, 7);
std::cout << q0 << ", " << q1 << " -> " << hypot(q0, q1) << "\n";
wq_t wq0(q0);
wq_t wq1(q1);
std::cout << wq0 << ", " << wq1 << " -> " << hypot(wq0, wq1) << "\n";

return 0;
}
42 changes: 42 additions & 0 deletions test/doc/lpnorm.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include <kyosu/kyosu.hpp>
#include <eve/wide.hpp>
#include <iostream>

int main()
{
using kyosu::lpnorm;
using kyosu::complex;
using kyosu::quaternion;
using e_t = float;
using c_t = complex<float>;
using q_t = quaternion<float>;
using we_t = eve::wide<float, eve::fixed<2>>;
using wc_t = eve::wide<complex<float>, eve::fixed<2>>;
using wq_t = eve::wide<quaternion<float>, eve::fixed<2>>;

std::cout << "Real: "<< "\n";
e_t e0(1);
e_t e1(2);
std::cout << e0 << ", " << e1 << " -> " << lpnorm(e_t(1), e0, e1) << "\n";
we_t we0(e0);
we_t we1(e1);
std::cout << we0 << ", " << we1 << " -> " << lpnorm(e_t(1), we0, we1) << "\n";

std::cout << "Complex: "<< "\n";
c_t c0(e_t(1), 5);
c_t c1(5, 9);
std::cout << c0 << ", " << c1 << " -> " << lpnorm(e_t(1), c0, c1) << "\n";
wc_t wc0(c0);
wc_t wc1(c1);
std::cout << wc0 << ", " << wc1 << " -> " << lpnorm(e_t(1), wc0, wc1) << "\n";

std::cout << "Quaternion: "<< "\n";
q_t q0(e_t(1), 5, 2, 3);
q_t q1(5, 9, 6, 7);
std::cout << q0 << ", " << q1 << " -> " << lpnorm(e_t(1), q0, q1) << "\n";
wq_t wq0(q0);
wq_t wq1(q1);
std::cout << wq0 << ", " << wq1 << " -> " << lpnorm(e_t(1), wq0, wq1) << "\n";

return 0;
}
Loading

0 comments on commit 0c4112e

Please sign in to comment.