Skip to content

Commit

Permalink
Implements lerp
Browse files Browse the repository at this point in the history
  • Loading branch information
jfalcou authored Aug 22, 2023
2 parents cc13065 + 8814346 commit f3e75d7
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 12 deletions.
3 changes: 2 additions & 1 deletion include/kyosu/functions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@
#include <kyosu/functions/abs.hpp>
#include <kyosu/functions/ceil.hpp>
#include <kyosu/functions/conj.hpp>
#include <kyosu/functions/dist.hpp>
#include <kyosu/functions/floor.hpp>
#include <kyosu/functions/frac.hpp>
#include <kyosu/functions/dist.hpp>
#include <kyosu/functions/if_else.hpp>
#include <kyosu/functions/ipart.hpp>
#include <kyosu/functions/jpart.hpp>
#include <kyosu/functions/kpart.hpp>
#include <kyosu/functions/lerp.hpp>
#include <kyosu/functions/nearest.hpp>
#include <kyosu/functions/purepart.hpp>
#include <kyosu/functions/real.hpp>
Expand Down
82 changes: 82 additions & 0 deletions include/kyosu/functions/lerp.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//======================================================================================================================
/*
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_lerp : eve::elementwise
{
using callable_tag_type = callable_lerp;

KYOSU_DEFERS_CALLABLE(lerp_);

static KYOSU_FORCEINLINE auto deferred_call(auto
, eve::ordered_value auto const& v0
, eve::ordered_value auto const& v1
, eve::ordered_value auto const& t) noexcept
{
return eve::lerp(v0, v1, t);
}

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

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

namespace kyosu
{
//======================================================================================================================
//! @addtogroup functions
//! @{
//! @var lerp
//! @brief Computes the linear interpolation.
//!
//! **Defined in Header**
//!
//! @code
//! #include <kyosu/functions.hpp>
//! @endcode
//!
//! @groupheader{Callable Signatures}
//!
//! @code
//! namespace kyosu
//! {
//! template<kyosu::concepts::cayley_dickson T0, kyosu::concepts::cayley_dickson T1 > constexpr auto lerp(T0 z0, T1, z1, auto eve::ordered_value t) noexcept;
//! template<eve::ordered_value T0, kyosu::concepts::cayley_dickson T1> > constexpr auto lerp(T0 z0, T1, z1, auto eve::ordered_value t) noexcept;
//! template<kyosu::concepts::cayley_dickson T0, eve::ordered_value T1 > constexpr auto lerp(T0 z0, T1, z1, auto eve::ordered_value t) noexcept;
//! template<eve::ordered_value T0, ordered_value T1> > constexpr auto lerp(T0 z0, T1, z1, auto eve::ordered_value t) noexcept;
///! }
//! @endcode
//!
//! **Parameters**
//!
//! * `z0, z1` : Value to process.
//! * `t` : floating value interpolation coefficient.
//!
//! **Return value**
//!
//! The value of the interpolation (or extrapolation) between `z0` and `z1` is returned.
//! The call is semantically equivalent to `z0+t*(z1-z0)`.
//!
//! @groupheader{Example}
//!
//! @godbolt{doc/lerp.cpp}
//! @}
//======================================================================================================================
inline constexpr tags::callable_lerp lerp = {};
}
1 change: 1 addition & 0 deletions include/kyosu/types/cayley_dickson.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,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>>
|| plain_scalar_value<Wrapper>
>
{
Expand Down
30 changes: 19 additions & 11 deletions include/kyosu/types/impl/arithmetic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,44 +62,44 @@ namespace kyosu::_
}
}

template<concepts::cayley_dickson C>
template<typename C>
KYOSU_FORCEINLINE constexpr
auto dispatch(eve::tag_of<kyosu::ceil> const&, C const& c) noexcept
{
return C{kumi::map([](auto const& e) { return eve::ceil(e); }, c)};
}

template<concepts::cayley_dickson C>
template<typename C>
KYOSU_FORCEINLINE constexpr
auto dispatch(eve::tag_of<kyosu::floor> const&, C const& c) noexcept
{
return C{kumi::map([](auto const& e) { return eve::floor(e); }, c)};
}

template<concepts::cayley_dickson C>
template<typename C>
KYOSU_FORCEINLINE constexpr
auto dispatch(eve::tag_of<kyosu::nearest> const&, C const& c) noexcept
{
return C{kumi::map([](auto const& e) { return eve::nearest(e); }, c)};
}

template<concepts::cayley_dickson C>
template<typename C>
KYOSU_FORCEINLINE constexpr
auto dispatch(eve::tag_of<kyosu::trunc> const&, C const& c) noexcept
{
return C{kumi::map([](auto const& e) { return eve::trunc(e); }, c)};
}

template<concepts::cayley_dickson C>
template<typename C>
KYOSU_FORCEINLINE constexpr
auto dispatch(eve::tag_of<kyosu::frac> const&, C const& c) noexcept
{
return C{kumi::map([](auto const& e) { return eve::frac(e); }, c)};
}

template<concepts::cayley_dickson C>
template<typename C>
KYOSU_FORCEINLINE constexpr
auto dispatch(eve::tag_of<sqr> const&, C c) noexcept
auto dispatch(eve::tag_of<kyosu::sqr> const&, C c) noexcept
{
if constexpr(kyosu::dimension_v<C> <= 2)
{
Expand All @@ -116,18 +116,26 @@ namespace kyosu::_
}
}

template<typename C0, typename C1>
template<concepts::cayley_dickson C0, concepts::cayley_dickson C1>
KYOSU_FORCEINLINE constexpr
auto dispatch(eve::tag_of<dist> const&, C0 const & c0, C1 const & c1) noexcept
auto dispatch(eve::tag_of<kyosu::dist> const&, C0 const & c0, C1 const & c1) noexcept
{
return kyosu::abs(c0-c1);
}

template<typename C0, typename C1>
template<concepts::cayley_dickson C0, concepts::cayley_dickson C1>
KYOSU_FORCEINLINE constexpr
auto dispatch(eve::tag_of<reldist> const&, C0 const & c0, C1 const & c1) noexcept
auto dispatch(eve::tag_of<kyosu::reldist> 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))));
}

template<concepts::cayley_dickson C0, concepts::cayley_dickson C1, eve::ordered_value T>
KYOSU_FORCEINLINE constexpr
auto dispatch(eve::tag_of<kyosu::lerp> const&, C0 const & c0, C1 const & c1, T const & t) noexcept
{
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)};
}

}
52 changes: 52 additions & 0 deletions test/unit/function/lerp.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//======================================================================================================================
/*
Kyosu - Complex Without Complexes
Copyright : KYOSU Contributors & Maintainers
SPDX-License-Identifier: BSL-1.0
*/
//======================================================================================================================
#include <kyosu/kyosu.hpp>
#include <test.hpp>

TTS_CASE_WITH ( "Check kyosu::lerp over real"
, kyosu::real_types
, tts::generate(tts::between(-10,10)
,tts::between(-10,10)
,tts::between(0, 1)
)
)
(auto r0, auto r1, auto t)
{
TTS_EQUAL(kyosu::lerp(r0, r1, t), eve::lerp(r0, r1, t));
};

TTS_CASE_WITH ( "Check kyosu::lerp over complex"
, kyosu::real_types
, tts::generate(tts::between(-10,10), tts::between(-10,10)
,tts::between(-10,10), tts::between(-10,10)
,tts::between(0, 1)
)
)
(auto r0, auto i0, auto r1, auto i1, auto t)
{
auto c0 = kyosu::to_complex(r0,i0);
auto c1 = kyosu::to_complex(r1,i1);
TTS_RELATIVE_EQUAL(kyosu::lerp(c0, c1, t), c0+t*(c1-c0), 1e-7);
};

TTS_CASE_WITH ( "Check kyosu::lerp over quaternion"
, kyosu::real_types
, tts::generate ( tts::between(-10,10), tts::between(-10,10)
, tts::between(-10,10), tts::between(-10,10)
, tts::between(-10,10), tts::between(-10,10)
, tts::between(-10,10), tts::between(-10,10)
,tts::between(0, 1)
)
)
<typename T>(T r0, T i0, T j0, T k0, T r1, T i1, T j1, T k1, auto t)
{
using type = kyosu::as_quaternion_t<T>;
auto q0 = type(r0,i0,j0,k0);
auto q1 = type(r1,i1,j1,k1);
TTS_RELATIVE_EQUAL(kyosu::lerp(q0, q1, t), q0+t*(q1-q0) , 1e-7);
};

0 comments on commit f3e75d7

Please sign in to comment.