Skip to content
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

Fix/operators again #15

Merged
merged 2 commits into from
Aug 29, 2023
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
1 change: 1 addition & 0 deletions include/kyosu/functions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <kyosu/functions/conj.hpp>
#include <kyosu/functions/cosh.hpp>
#include <kyosu/functions/coth.hpp>
#include <kyosu/functions/convert.hpp>
#include <kyosu/functions/dec.hpp>
#include <kyosu/functions/dist.hpp>
#include <kyosu/functions/exp.hpp>
Expand Down
76 changes: 76 additions & 0 deletions include/kyosu/functions/convert.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_convert : eve::elementwise
{
using callable_tag_type = callable_convert;

KYOSU_DEFERS_CALLABLE(convert_);

template<eve::plain_scalar_value T>
static KYOSU_FORCEINLINE auto deferred_call(auto, eve::ordered_value auto const& v, eve::as<T> const& tgt) noexcept
{
return eve::convert(v,tgt);
}

template<typename T>
KYOSU_FORCEINLINE
auto operator()(auto const& v, eve::as<T> const& tgt) const noexcept -> decltype(eve::tag_invoke(*this,v,tgt))
{
return eve::tag_invoke(*this, v, tgt);
}

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

namespace kyosu
{
//======================================================================================================================
//! @addtogroup functions
//! @{
//! @var convert
//! @brief Select a value between two arguments based on a logical mask
//!
//! **Defined in Header**
//!
//! @code
//! #include <kyosu/functions.hpp>
//! @endcode
//!
//! @groupheader{Callable Signatures}
//!
//! @code
//! namespace kyosu
//! {
//! template<eve::value T, eve::value U, eve::value V>
//! constexpr auto convert(T x, U, y, V z ) noexcept;
//! }
//! @endcode
//!
//! **Parameters**
//!
//! * `z` : Value to process.
//!
//! **Return value**
//!
//!
//! @groupheader{Example}
//!
//! @godbolt{doc/convert.cpp}
//! @}
//======================================================================================================================
inline constexpr tags::callable_convert convert = {};
}
12 changes: 11 additions & 1 deletion include/kyosu/types/cayley_dickson.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,16 @@ namespace kyosu
return _::dispatch(fn, m,t,f);
}

template<concepts::cayley_dickson T, eve::value C>
requires( eve::scalar_value<T> )
KYOSU_FORCEINLINE
constexpr auto tag_invoke( eve::tag_of<kyosu::convert> const& f, auto, C const& c, eve::as<T> const& tgt) noexcept
-> decltype(_::dispatch(f, c, tgt))
{
return _::dispatch(f, c, tgt);
}


//==================================================================================================================
// Tag invoke override for parts extraction - Outside so they can see get<I>(c)
//==================================================================================================================
Expand Down Expand Up @@ -204,7 +214,7 @@ struct std::tuple_element<I, kyosu::cayley_dickson<T,N>>
template<typename Wrapper, typename T, unsigned int N>
struct eve::supports_like<Wrapper,kyosu::cayley_dickson<T,N>>
: std::bool_constant< kyosu::concepts::cayley_dickson<Wrapper>
|| std::same_as<T, element_type_t<Wrapper>>
|| std::same_as<T, eve::element_type_t<Wrapper>>
|| plain_scalar_value<Wrapper>
>
{
Expand Down
19 changes: 17 additions & 2 deletions include/kyosu/types/impl/arithmetic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ namespace kyosu::_
{
using r_t = as_cayley_dickson_t<C0,C1,T>;
return r_t{kumi::map([&t](auto const& e, auto const & f) { return eve::lerp(e, f, t); }, c0, c1)};
}
}

template<typename C>
KYOSU_FORCEINLINE constexpr
Expand Down Expand Up @@ -174,5 +174,20 @@ namespace kyosu::_
auto dispatch(eve::tag_of<kyosu::rec> const&, C c) noexcept
{
return conj(c)/sqr_abs(c);
}
}
template<typename C0, concepts::cayley_dickson C1>
requires(dimension_v<C0> <= dimension_v<C1>)
KYOSU_FORCEINLINE constexpr
auto dispatch(eve::tag_of<convert> const&, C0 const & c, eve::as<C1> const & tgt) noexcept
{
using type = eve::as_wide_as_t<C1, C0>;

if constexpr(std::same_as<eve::element_type_t<C0>,C1>) return c;
else if constexpr(dimension_v<C0> == 1ULL) return type{c};
else
{
using u_t = eve::underlying_type_t<C1>;
return kumi::apply([](auto const&... e) { return type{kyosu::convert(e, eve::as<u_t>{})...}; }, c);
}
}
}
20 changes: 13 additions & 7 deletions include/kyosu/types/impl/operators.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,10 @@ namespace kyosu
/// Returns the sum of a Caley-dickson value and a real value in any order
template<eve::value T1, eve::value T2>
requires(concepts::cayley_dickson<T1> || concepts::cayley_dickson<T2>)
as_cayley_dickson_t<T1,T2> operator+(T1 const& a, T2 const& b) noexcept
auto operator+(T1 const& a, T2 const& b) noexcept -> as_cayley_dickson_t<T1,T2>
{
as_cayley_dickson_t<T1,T2> that{a};
using type = as_cayley_dickson_t<T1,T2>;
type that{kyosu::convert(a,eve::as<eve::element_type_t<type>>())};
return that += b;
}

Expand All @@ -53,7 +54,8 @@ namespace kyosu
requires(concepts::cayley_dickson<T1> || concepts::cayley_dickson<T2>)
as_cayley_dickson_t<T1,T2> operator-(T1 const& a, T2 const& b) noexcept
{
as_cayley_dickson_t<T1,T2> that{a};
using type = as_cayley_dickson_t<T1,T2>;
type that{kyosu::convert(a,eve::as<eve::element_type_t<type>>())};
return that -= b;
}

Expand All @@ -62,7 +64,8 @@ namespace kyosu
requires(concepts::cayley_dickson<T1> && concepts::cayley_dickson<T2>)
as_cayley_dickson_t<T1,T2> operator*(T1 const& a, T2 const& b) noexcept
{
as_cayley_dickson_t<T1,T2> that{a};
using type = as_cayley_dickson_t<T1,T2>;
type that{kyosu::convert(a,eve::as<eve::element_type_t<type>>())};
return that *= b;
}

Expand All @@ -73,12 +76,14 @@ namespace kyosu
// This is ok as the non cayley-dickson type is a scalar
if constexpr(concepts::cayley_dickson<T1>)
{
as_cayley_dickson_t<T1,T2> that{a};
using type = as_cayley_dickson_t<T1,T2>;
type that{kyosu::convert(a,eve::as<eve::element_type_t<type>>())};
return that *= b;
}
else
{
as_cayley_dickson_t<T1,T2> that{b};
using type = as_cayley_dickson_t<T1,T2>;
type that{kyosu::convert(b,eve::as<eve::element_type_t<type>>())};
return that *= a;
}
}
Expand All @@ -88,7 +93,8 @@ namespace kyosu
requires(concepts::cayley_dickson<T1> || concepts::cayley_dickson<T2>)
as_cayley_dickson_t<T1,T2> operator/(T1 const& a, T2 const& b) noexcept
{
as_cayley_dickson_t<T1,T2> that{a};
using type = as_cayley_dickson_t<T1,T2>;
type that{kyosu::convert(a,eve::as<eve::element_type_t<type>>())};
return that /= b;
}

Expand Down
7 changes: 1 addition & 6 deletions include/kyosu/types/traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,7 @@ namespace kyosu

template<unsigned int Dim, typename... Ts>
requires( Dim > 1 && !requires(Ts... ts) { eve::add( std::declval<_::sema_t<Ts>>()...); } )
struct as_cayley_dickson_n<Dim, Ts...>
{
static_assert ( requires(Ts... ts) { eve::add( std::declval<_::sema_t<Ts>>()...); }
, "[KYOSU] - STATIC ASSERT: Incompatible types in type resolution"
);
};
struct as_cayley_dickson_n<Dim, Ts...> {};

template<unsigned int Dim, typename T>
requires(Dim > 1)
Expand Down