Skip to content

Commit

Permalink
Implement complex domain converter
Browse files Browse the repository at this point in the history
Some function on real needs ot be extended ot complex. 
One may want to compute `sqrt(-1)` and get `0+i`.

The `domain::complex` converter handles those situations.
  • Loading branch information
jtlap authored Jan 31, 2023
1 parent 42a7c85 commit d28acc5
Show file tree
Hide file tree
Showing 31 changed files with 397 additions and 5 deletions.
171 changes: 169 additions & 2 deletions include/eve/module/complex/detail/math.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@
namespace eve::detail
{


//==============================================================================================
// sqrt cosh cos acosh asinh atan exp exp_i exp_ipi log rec are here.
// acos asin atanh are in specific files included at the end
//==============================================================================================


//===-------------------------------------------------------------------------------------------
// Unary functions : cbrt
//===-------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -762,10 +762,177 @@ namespace eve::detail
{
return d(lpnorm)(p, abs(z1), abs(z2)...);
}

}

#include <eve/module/complex/detail/math/acos.hpp>
#include <eve/module/complex/detail/math/asin.hpp>
#include <eve/module/complex/detail/math/atanh.hpp>
#include <eve/module/complex/detail/math/pow.hpp>

namespace eve::detail
{

//==============================================================================================
// non-complex => complex kind of functions
//==============================================================================================
//sqrt
template<value T>
EVE_FORCEINLINE constexpr auto
sqrt_(EVE_SUPPORTS(cpu_), eve::domain::complex_converter const&, T const& v) noexcept
{
if constexpr(is_complex_v<T>)
return sqrt(v);
else if(floating_ordered_value<T>)
{
auto s = sqrt(eve::abs(v));
return if_else(is_gez(v), eve::as_complex_t<T>{s,T{0}}, eve::as_complex_t<T>{T{0}, s} );
}
}

//log
template<value T>
EVE_FORCEINLINE constexpr auto
log_(EVE_SUPPORTS(cpu_), eve::domain::complex_converter const&, T const& v) noexcept
{
if constexpr(is_complex_v<T>)
return log(v);
else if(floating_ordered_value<T>)
{
auto s = log_abs(v);
return if_else(is_positive(v), eve::as_complex_t<T>{s,T{0}}, eve::as_complex_t<T>{s, pi(as(v))} );
}
}

//log2
template<value T>
EVE_FORCEINLINE constexpr auto
log2_(EVE_SUPPORTS(cpu_), eve::domain::complex_converter const&, T const& v) noexcept
{
if constexpr(is_complex_v<T>)
return log2(v);
else if(floating_ordered_value<T>)
{
auto s = log2(eve::abs(v));
return if_else(is_positive(v), eve::as_complex_t<T>{s,T{0}}, eve::as_complex_t<T>{s, pi(as(v))*invlog_2(as(v))} );
}
}

//log10
template<value T>
EVE_FORCEINLINE constexpr auto
log10_(EVE_SUPPORTS(cpu_), eve::domain::complex_converter const&, T const& v) noexcept
{
if constexpr(is_complex_v<T>)
return log10(v);
else if(floating_ordered_value<T>)
{
auto s = log10(eve::abs(v));
return if_else(is_positive(v), eve::as_complex_t<T>{s,T{0}}, eve::as_complex_t<T>{s, pi(as(v))*invlog_10(as(v))} );
}
}

//asin
template<value T>
EVE_FORCEINLINE constexpr auto
asin_(EVE_SUPPORTS(cpu_), eve::domain::complex_converter const&, T const& v) noexcept
{
if constexpr(is_complex_v<T>)
return asin(v);
else if(floating_ordered_value<T>)
{
return if_else(abs(v) <= one(as(v)), eve::as_complex_t<T>{asin(v),T{0}}, asin(eve::as_complex_t<T>(v)));
}
}

//acos
template<value T>
EVE_FORCEINLINE constexpr auto
acos_(EVE_SUPPORTS(cpu_), eve::domain::complex_converter const&, T const& v) noexcept
{
if constexpr(is_complex_v<T>)
return acos(v);
else if(floating_ordered_value<T>)
{
return if_else(abs(v) < one(as(v)), eve::as_complex_t<T>{acos(v),T{0}}, acos(eve::as_complex_t<T>(v)));
}
}

//acsc
template<value T>
EVE_FORCEINLINE constexpr auto
acsc_(EVE_SUPPORTS(cpu_), eve::domain::complex_converter const&, T const& v) noexcept
{
if constexpr(is_complex_v<T>)
return acsc(v);
else if(floating_ordered_value<T>)
{
return if_else(abs(v) >= one(as(v)), eve::as_complex_t<T>{acsc(v),T{0}}, acsc(eve::as_complex_t<T>(v)));
}
}

//asec
template<value T>
EVE_FORCEINLINE constexpr auto
asec_(EVE_SUPPORTS(cpu_), eve::domain::complex_converter const&, T const& v) noexcept
{
if constexpr(is_complex_v<T>)
return asec(v);
else if(floating_ordered_value<T>)
{
return if_else(abs(v) >= one(as(v)), eve::as_complex_t<T>{asec(v),T{0}}, asec(eve::as_complex_t<T>(v)));
}
}

//acosh
template<value T>
EVE_FORCEINLINE constexpr auto
acosh_(EVE_SUPPORTS(cpu_), eve::domain::complex_converter const&, T const& v) noexcept
{
if constexpr(is_complex_v<T>)
return acosh(v);
else if(floating_ordered_value<T>)
{
return if_else(v >= one(as(v)), eve::as_complex_t<T>{acosh(v),T{0}}, acosh(eve::as_complex_t<T>(v)));
}
}

//atanh
template<value T>
EVE_FORCEINLINE constexpr auto
atanh_(EVE_SUPPORTS(cpu_), eve::domain::complex_converter const&, T const& v) noexcept
{
if constexpr(is_complex_v<T>)
return atanh(v);
else if(floating_ordered_value<T>)
{
return if_else(eve::abs(v) <= one(as(v)), eve::as_complex_t<T>{atanh(v),T{0}}, atanh(eve::as_complex_t<T>(v)));
}
}

//acoth
template<value T>
EVE_FORCEINLINE constexpr auto
acoth_(EVE_SUPPORTS(cpu_), eve::domain::complex_converter const&, T const& v) noexcept
{
if constexpr(is_complex_v<T>)
return acoth(v);
else if(floating_ordered_value<T>)
{
return if_else(eve::abs(v) >= one(as(v)), eve::as_complex_t<T>{acoth(v),T{0}}, acoth(eve::as_complex_t<T>(v)));
}
}

//pow
template<value T, value U>
EVE_FORCEINLINE constexpr auto
pow_(EVE_SUPPORTS(cpu_), eve::domain::complex_converter const&, T const& t, U const& u) noexcept
{
if constexpr(is_complex_v<T>|| is_complex_v<U>)
return pow(t, u);
else if(floating_ordered_value<T>)
{
return if_else(is_positive(t), eve::as_complex_t<T>{pow_abs(t, u), T{0}}, pow(eve::as_complex_t<T>(t), u));
}
}

}
8 changes: 8 additions & 0 deletions include/eve/module/complex/detail/math/atanh.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ namespace eve
rtype inf = eve::inf(as(a0r));
rtype x = eve::abs(a0r);
rtype y = eve::abs(a0i);
auto special = is_eqz(y) && (x < one(as(a0r)));
auto sr = atanh(a0r);
if (eve::all(special)) {
return Z{sr, zero(as(sr))};
}

rtype r = zero(as(a0r));
rtype i = zero(as(a0r));
auto gtxmax = (x > s_max);
Expand Down Expand Up @@ -162,6 +168,8 @@ namespace eve
i = eve::if_else( ltzia0,-i, i);
r = if_else(realinf, zero(as(a0r)), r);
i = if_else(realinf, -sign(a0r)*pio_2(as(a0r)), i);
r = if_else(special, sr, r);
i = if_else(special, zero, i);
return Z{r, i};
}
}
Expand Down
24 changes: 24 additions & 0 deletions include/eve/module/complex/detail/math/pow.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,29 @@ namespace eve
return pow(inc(z1), z2);
}

//powm1
template<value T, value U>
EVE_FORCEINLINE constexpr auto
powm1_(EVE_SUPPORTS(cpu_), eve::domain::complex_converter const&, T const& t, U const& u) noexcept
{
if constexpr(is_complex_v<T>|| is_complex_v<U>)
return powm1(t, u);
else if(floating_ordered_value<T>)
{
return if_else(is_positive(t), eve::as_complex_t<T>{powm1(t, u), T{0}}, powm1(eve::as_complex_t<T>(t), u));
}
}

template<value T, value U>
EVE_FORCEINLINE constexpr auto
pow1p_(EVE_SUPPORTS(cpu_), eve::domain::complex_converter const&, T const& t, U const& u) noexcept
{
if constexpr(is_complex_v<T>|| is_complex_v<U>)
return pow1p(t, u);
else if(floating_ordered_value<T>)
{
return if_else(is_positive(t), eve::as_complex_t<T>{pow1p(t, u), T{0}}, pow1p(eve::as_complex_t<T>(t), u));
}
}
}
}
7 changes: 7 additions & 0 deletions include/eve/module/complex/regular/traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//==================================================================================================
#pragma once
#include <eve/concept/value.hpp>
#include <eve/module/core/regular/converter.hpp>
#include <eve/traits.hpp>

namespace eve
Expand Down Expand Up @@ -60,4 +61,10 @@ namespace eve
>
{
};

namespace domain
{
using complex_converter = eve::decorated<eve::convert_by_<eve::as_complex, false>()>;
inline constexpr complex_converter const complex = {};
}
}
8 changes: 8 additions & 0 deletions include/eve/module/core/regular/sqrt.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,14 @@ namespace eve
//!
//! @}
//================================================================================================
namespace tag
{
struct sqrt_;
}

template<> struct supports_optimized_conversion<tag::sqrt_> : std::true_type
{};

EVE_MAKE_CALLABLE(sqrt_, sqrt);
}

Expand Down
7 changes: 7 additions & 0 deletions include/eve/module/math/regular/acos.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ namespace eve
//! [floating real values](@ref floating_value) which can be slightly less accurate near 1.
//! @}
//================================================================================================
namespace tag
{
struct acos_;
}

template<> struct supports_optimized_conversion<tag::acos_> : std::true_type
{};

EVE_MAKE_CALLABLE(acos_, acos);
}
Expand Down
8 changes: 8 additions & 0 deletions include/eve/module/math/regular/acosh.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,14 @@ namespace eve
//!
//! @}
//================================================================================================
namespace tag
{
struct acosh_;
}

template<> struct supports_optimized_conversion<tag::acosh_> : std::true_type
{};

EVE_MAKE_CALLABLE(acosh_, acosh);
}

Expand Down
7 changes: 7 additions & 0 deletions include/eve/module/math/regular/acoth.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ namespace eve
//! @godbolt{doc/math/regular/acoth.cpp}
//! @}
//================================================================================================
namespace tag
{
struct acoth_;
}

template<> struct supports_optimized_conversion<tag::acoth_> : std::true_type
{};
EVE_MAKE_CALLABLE(acoth_, acoth);
}

Expand Down
7 changes: 7 additions & 0 deletions include/eve/module/math/regular/acsc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ namespace eve
//! @godbolt{doc/math/regular/acsc.cpp}
//! @}
//================================================================================================
namespace tag
{
struct acsc_;
}

template<> struct supports_optimized_conversion<tag::acsc_> : std::true_type
{};

EVE_MAKE_CALLABLE(acsc_, acsc);
}
Expand Down
7 changes: 7 additions & 0 deletions include/eve/module/math/regular/asec.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ namespace eve
//! @godbolt{doc/math/regular/asec.cpp}
//! @}
//================================================================================================
namespace tag
{
struct asec_;
}

template<> struct supports_optimized_conversion<tag::asec_> : std::true_type
{};

EVE_MAKE_CALLABLE(asec_, asec);
}
Expand Down
7 changes: 7 additions & 0 deletions include/eve/module/math/regular/asin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ namespace eve
//! @godbolt{doc/complex/regular/asin.cpp}
//! @}
//================================================================================================
namespace tag
{
struct asin_;
}

template<> struct supports_optimized_conversion<tag::asin_> : std::true_type
{};

EVE_MAKE_CALLABLE(asin_, asin);
}
Expand Down
10 changes: 9 additions & 1 deletion include/eve/module/math/regular/atanh.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,15 @@ namespace eve
//! @godbolt{doc/complex/regular/atanh.cpp}
//! @}
//================================================================================================
EVE_MAKE_CALLABLE(atanh_, atanh);
namespace tag
{
struct atanh_;
}

template<> struct supports_optimized_conversion<tag::atanh_> : std::true_type
{};

EVE_MAKE_CALLABLE(atanh_, atanh);
}

#include <eve/module/math/regular/impl/atanh.hpp>
10 changes: 9 additions & 1 deletion include/eve/module/math/regular/log.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,15 @@ namespace eve
//! @godbolt{doc/math/masked/log.cpp}
//! @}
//================================================================================================
EVE_MAKE_CALLABLE(log_, log);
namespace tag
{
struct log_;
}

template<> struct supports_optimized_conversion<tag::log_> : std::true_type
{};

EVE_MAKE_CALLABLE(log_, log);
}

#include <eve/module/math/regular/impl/log.hpp>
Expand Down
Loading

0 comments on commit d28acc5

Please sign in to comment.