Skip to content

Commit

Permalink
Implements to_quaternion
Browse files Browse the repository at this point in the history
  • Loading branch information
jtlap authored Aug 25, 2023
1 parent cbb86f3 commit 80c7368
Show file tree
Hide file tree
Showing 3 changed files with 203 additions and 0 deletions.
110 changes: 110 additions & 0 deletions include/kyosu/functions/to_quaternion.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
//======================================================================================================================
/*
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_to_quaternion
{
using callable_tag_type = callable_to_quaternion;

KYOSU_DEFERS_CALLABLE(to_quaternion_);

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

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

namespace kyosu
{
//======================================================================================================================
//! @addtogroup functions
//! @{
//! @var to_quaternion
//! @brief Constructs a kyosu::quaternion
//!
//! **Defined in Header**
//!
//! @code
//! #include <kyosu/functions.hpp>
//! @endcode
//!
//! @groupheader{Callable Signatures}
//!
//! @code
//! namespace kyosu
//! {
//! template<eve::ordered_value T> constexpr auto to_quaternion(T r) noexcept;
//! template<eve::ordered_value T> constexpr auto to_quaternion(T r, T i) noexcept;

//! template<kyosu::concepts::cayley_dickson T> constexpr T to_quaternion(T z) noexcept;
//! }
//! @endcode
//!
//! **Parameters**
//!
//! * `z` : Quaternion value.
//! * `r`, `i` : Real and imaginary part sued to construct a @ref kyosu::quaternion..
//!
//! **Return value**
//!
//! Returns a @ref kyosu::quaternion constructed from its arguments.
//!
//! @groupheader{Example}
//!
//! @godbolt{doc/to_quaternion.cpp}
//! @}
//======================================================================================================================
inline constexpr tags::callable_to_quaternion to_quaternion = {};
}

namespace kyosu::_
{
template<eve::floating_value T>
constexpr auto to_quaternion_(EVE_EXPECTS(eve::cpu_), T r) noexcept { return as_quaternion_t<T>(r, 0, 0, 0); }

template<eve::floating_value T0, eve::floating_value T1>
constexpr auto to_quaternion_(EVE_EXPECTS(eve::cpu_), T0 r, T1 i) noexcept -> as_quaternion_t<decltype(eve::add(r, i))>
{
return as_quaternion_t<decltype(eve::add(r, i))>{r, i, 0, 0};
}

template<eve::floating_value T0, eve::floating_value T1, eve::floating_value T2, eve::floating_value T3>
constexpr auto to_quaternion_(EVE_EXPECTS(eve::cpu_), T0 r, T1 i, T2 j, T3 k) noexcept -> as_quaternion_t<decltype(eve::add(r, i, j, k))>
{
return as_quaternion_t<decltype(eve::add(r, i, j, k))>{r, i, j, k};
}

template<concepts::complex T0>
constexpr auto to_quaternion_(EVE_EXPECTS(eve::cpu_), T0 const & c0) noexcept
{
return to_quaternion(get<0>(c0), get<1>(c0));
}

template<concepts::complex T0,concepts::complex T1>
constexpr auto to_quaternion_(EVE_EXPECTS(eve::cpu_), T0 const & c0, T1 const & c1) noexcept
{
return to_quaternion(get<0>(c0), get<1>(c0),get<0>(c1), get<1>(c1));
}

template<concepts::quaternion T>
constexpr auto to_quaternion_(EVE_EXPECTS(eve::cpu_), T const& v) noexcept
{
return v;
}

}
12 changes: 12 additions & 0 deletions include/kyosu/types/quaternion.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,21 @@

namespace kyosu
{
//====================================================================================================================
//! @addtogroup types
//! @{
//! @typedef quaternion
//! @brief Type alias for quaternion numbers
//!
//! Quaternion numbers are implemented as Caley-dickson numbers of dimension 4.
//!
//! @}
//====================================================================================================================
template<typename T>
using quaternion = cayley_dickson<T,4>;

template<typename T>
using as_quaternion_t = as_cayley_dickson_n_t<4,T>;
}

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

TTS_CASE_TPL( "Check to_quaternion converter from constants", kyosu::scalar_real_types)
<typename T>(tts::type<T>)
{
using e_t = T;
using w_t = eve::wide<e_t>;
using q_t = kyosu::quaternion<e_t>;
using wq_t = eve::wide<kyosu::quaternion<e_t>>;
auto zer (e_t(0));
auto wzer(w_t(0));
auto o(e_t(1));
auto z(e_t(0));
auto wo(w_t(1));
auto wz(w_t(0));

q_t z_0 = kyosu::to_quaternion(zer);
TTS_EQUAL( get<0>(z_0), T{0});
TTS_EQUAL( get<1>(z_0), T{0});
TTS_EQUAL( get<2>(z_0), T{0});
TTS_EQUAL( get<3>(z_0), T{0});

wq_t wz_0 = kyosu::to_quaternion(wzer);
TTS_EQUAL( get<0>(wz_0), w_t{0});
TTS_EQUAL( get<1>(wz_0), w_t{0});
TTS_EQUAL( get<2>(wz_0), w_t{0});
TTS_EQUAL( get<3>(wz_0), w_t{0});

{
auto z_1 = kyosu::to_quaternion(o, o);

TTS_EQUAL( get<0>(z_1), T(1));
TTS_EQUAL( get<1>(z_1), T(1));
TTS_EQUAL( get<2>(z_1), T(0));
TTS_EQUAL( get<3>(z_1), T(0));


wq_t wz_1 = kyosu::to_quaternion(wo, wo);
TTS_EQUAL( get<0>(wz_1), wo);
TTS_EQUAL( get<1>(wz_1), wo);
TTS_EQUAL( get<2>(wz_1), wz);
TTS_EQUAL( get<3>(wz_1), wz);

wq_t wz_2 = kyosu::to_quaternion(wo, o, wo, o);
TTS_EQUAL( get<0>(wz_2), wo);
TTS_EQUAL( get<1>(wz_2), wo);
TTS_EQUAL( get<2>(wz_2), wo);
TTS_EQUAL( get<3>(wz_2), wo);

wq_t wz_3 = kyosu::to_quaternion(o, wo, z, o);
TTS_EQUAL( get<0>(wz_3), wo);
TTS_EQUAL( get<1>(wz_3), wo);
TTS_EQUAL( get<2>(wz_3), wz);
TTS_EQUAL( get<3>(wz_3), wo);
}

using c_t = kyosu::complex<e_t>;
auto zcc = kyosu::to_quaternion(c_t(1, 1), c_t(0, 1));

TTS_EQUAL( get<0>(zcc), T(1));
TTS_EQUAL( get<1>(zcc), T(1));
TTS_EQUAL( get<2>(zcc), T(0));
TTS_EQUAL( get<3>(zcc), T(1));

auto zc = kyosu::to_quaternion(c_t(1, 1));

TTS_EQUAL( get<0>(zc), T(1));
TTS_EQUAL( get<1>(zc), T(1));
TTS_EQUAL( get<2>(zc), T(0));
TTS_EQUAL( get<3>(zc), T(0));


};

0 comments on commit 80c7368

Please sign in to comment.