Skip to content

Commit

Permalink
More refurbished math functions
Browse files Browse the repository at this point in the history
  • Loading branch information
jtlap authored Mar 12, 2024
1 parent 954b23c commit edcc32c
Show file tree
Hide file tree
Showing 25 changed files with 552 additions and 532 deletions.
11 changes: 0 additions & 11 deletions include/eve/module/math/pedantic/arg.hpp

This file was deleted.

11 changes: 0 additions & 11 deletions include/eve/module/math/pedantic/exp2.hpp

This file was deleted.

68 changes: 0 additions & 68 deletions include/eve/module/math/pedantic/impl/exp2.hpp

This file was deleted.

3 changes: 0 additions & 3 deletions include/eve/module/math/pedantic/math.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,9 @@
//==================================================================================================
#pragma once

#include <eve/module/math/pedantic/arg.hpp>
#include <eve/module/math/pedantic/atan2.hpp>
#include <eve/module/math/pedantic/atan2d.hpp>
#include <eve/module/math/pedantic/atan2pi.hpp>
#include <eve/module/math/pedantic/exp.hpp>
#include <eve/module/math/pedantic/exp2.hpp>
#include <eve/module/math/pedantic/expm1.hpp>
#include <eve/module/math/pedantic/horner.hpp>
#include <eve/module/math/pedantic/hypot.hpp>
Expand Down
35 changes: 33 additions & 2 deletions include/eve/module/math/regular/arg.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,22 @@
#pragma once

#include <eve/detail/overload.hpp>
#include <eve/module/core.hpp>
#include <eve/module/math/constant/pi.hpp>


namespace eve
{

template<typename Options>
struct arg_t : elementwise_callable<arg_t, Options, pedantic_option>
{
template<eve::value T>
EVE_FORCEINLINE T operator()(T v) const { return EVE_DISPATCH_CALL(v); }

EVE_CALLABLE_OBJECT(arg_t, arg_);
};

//================================================================================================
//! @addtogroup math_trig
//! @{
Expand Down Expand Up @@ -48,7 +61,25 @@ namespace eve
//!
//! @}
//================================================================================================
EVE_MAKE_CALLABLE(arg_, arg);
inline constexpr auto arg = functor<arg_t>;
}

#include <eve/module/math/regular/impl/arg.hpp>

namespace eve::detail
{
template<typename T, callable_options O>
EVE_FORCEINLINE constexpr T
arg_(EVE_REQUIRES(cpu_), O const & o, T a) noexcept
{
if constexpr( has_native_abi_v<T> )
{
auto z = if_else(is_negative(a), pi(eve::as(a)), eve::zero);
if constexpr( platform::supports_nans && O::contains(pedantic2))
return if_else(is_nan(a), eve::allbits, z);
else
return z;
}
else
return apply_over(arg[o], a);
}
}
59 changes: 57 additions & 2 deletions include/eve/module/math/regular/cbrt.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,21 @@
//==================================================================================================
#pragma once

#include <eve/module/core.hpp>
#include <eve/detail/overload.hpp>

namespace eve
{

template<typename Options>
struct cbrt_t : elementwise_callable<cbrt_t, Options>
{
template<eve::floating_ordered_value T>
EVE_FORCEINLINE T operator()(T v) const { return EVE_DISPATCH_CALL(v); }

EVE_CALLABLE_OBJECT(cbrt_t, cbrt_);
};

//================================================================================================
//! @addtogroup math_exp
//! @{
Expand Down Expand Up @@ -58,7 +69,51 @@ namespace eve
//! @godbolt{doc/math/masked/cbrt.cpp}
//! @}
//================================================================================================
EVE_MAKE_CALLABLE(cbrt_, cbrt);
//================================================================================================
inline constexpr auto cbrt = functor<cbrt_t>;
}

#include <eve/module/math/regular/impl/cbrt.hpp>
namespace eve::detail
{
template<eve::floating_ordered_value T, callable_options O>
EVE_FORCEINLINE constexpr auto
cbrt_(EVE_REQUIRES(cpu_), O const & , T x) noexcept
{
if constexpr( has_native_abi_v<T> )
{
using vt_t = element_type_t<T>;
auto test0 = is_eqz(x) || is_not_finite(x);
if constexpr( eve::scalar_value<T> )
if( test0 ) return x;
constexpr vt_t factor[5] = {0.6299605249474365823836,
0.793700525984099737376,
1.0,
1.2599210498948731647672,
1.587401051968199474751};
auto ax = eve::abs(x);
auto test = is_less(eve::abs(x), T(100) * smallestposval(eve::as<T>()));
ax = if_else(test, ldexp(ax, 54), ax);
/* Reduce x. xm now is an range [0.5, 1.0]. */
auto [xm, xe] = raw(ifrexp)(ax);
T u;
if constexpr( std::is_same_v<vt_t, double> )
u = eve::reverse_horner(xm, T(0x1.6b69cba168ff2p-2), T(0x1.8218dde9028b4p+0), T(-0x1.0eb8277cd8d5dp+1)
, T(0x1.39350adad51ecp+1), T(-0x1.d5ae6cfa20f0cp+0)
, T(0x1.91e2a6fe7e984p-1), T(-0x1.29801e893366dp-3));
else if constexpr( std::is_same_v<vt_t, float> )
u = eve::reverse_horner(xm, T(0x1.f87bc4p-2f), T(0x1.6527f4p-1f), T(-0x1.88324ap-3f));
auto t2 = sqr(u) * u;
u *= fma(xm, T(2), t2) / fma(T(2), t2, xm);

if constexpr( eve::scalar_value<T> ) u *= factor[2 + xe % 3];
else u *= gather(&factor[0], 2 + xe - (xe / 3) * 3);
u = minus[is_ltz(x)](u);
if constexpr( eve::scalar_value<T> ) xe = add[test](int(xe) / 3, -18);
else xe = add[test](xe / 3, -18);
auto z = ldexp(u, xe);
if constexpr( eve::scalar_value<T> ) return z;
else return if_else(test0, x, z);
}
else return apply_over(cbrt, x);
}
}
30 changes: 27 additions & 3 deletions include/eve/module/math/regular/deginrad.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,21 @@
//==================================================================================================
#pragma once

#include <eve/module/core.hpp>
#include <eve/detail/overload.hpp>

namespace eve
{

template<typename Options>
struct deginrad_t : elementwise_callable<deginrad_t, Options>
{
template<eve::floating_ordered_value T>
EVE_FORCEINLINE T operator()(T v) const { return EVE_DISPATCH_CALL(v); }

EVE_CALLABLE_OBJECT(deginrad_t, deginrad_);
};

//================================================================================================
//! @addtogroup math_trig
//! @{
Expand Down Expand Up @@ -47,8 +58,21 @@ namespace eve
//! @godbolt{doc/math/regular/deginrad.cpp}
//! @}
//================================================================================================

EVE_MAKE_CALLABLE(deginrad_, deginrad);
inline constexpr auto deginrad = functor<deginrad_t>;
}

#include <eve/module/math/regular/impl/deginrad.hpp>
namespace eve::detail
{
template<floating_ordered_value T, callable_options O>
EVE_FORCEINLINE constexpr T
deginrad_(EVE_REQUIRES(cpu_), O const &, T const& a) noexcept
{
if constexpr( has_native_abi_v<T> )
{
auto ridh = ieee_constant<0x1.1de0000p-6f, 0x1.1df46a0000000p-6>(eve::as<T>{});
auto ridl = ieee_constant<0x1.46a2520p-18f, 0x1.294e9c8ae0ec6p-33>(eve::as<T>{});
return fma(a, ridl, a * ridh);
}
else return apply_over(deginrad, a);
}
}
89 changes: 85 additions & 4 deletions include/eve/module/math/regular/exp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@

namespace eve
{

template<typename Options>
struct exp_t : elementwise_callable<exp_t, Options, pedantic_option>
{
template<eve::value T>
EVE_FORCEINLINE constexpr T operator()(T v) const noexcept
{ return EVE_DISPATCH_CALL(v); }

EVE_CALLABLE_OBJECT(exp_t, exp_);
};

//================================================================================================
//! @addtogroup math_exp
//! @{
Expand All @@ -31,7 +42,7 @@ namespace eve
//! {
//! template< eve::floating_value T >
//! T exp(T x) noexcept;
/// }
//! }
//! @endcode
//!
//! **Parameters**
Expand Down Expand Up @@ -83,7 +94,77 @@ namespace eve
//! @godbolt{doc/math/masked/exp.cpp}
//! @}
//================================================================================================
EVE_MAKE_CALLABLE(exp_, exp);
}
inline constexpr auto exp = functor<exp_t>;

#include <eve/module/math/regular/impl/exp.hpp>
namespace detail
{
template<floating_ordered_value T, callable_options O>
EVE_FORCEINLINE constexpr T
exp_(EVE_REQUIRES(cpu_), O const & o, T x) noexcept
{
auto isnan = is_nan(x);
auto minlogval = []() {
if constexpr(O::contains(pedantic2) && eve::platform::supports_denormals)
return minlogdenormal(eve::as<T>());
else
return minlog(eve::as<T>());
};
if constexpr( scalar_value<T> )
{
if constexpr( has_emulated_abi_v<wide<T>> )
{
return (x <= minlogval()) ? T(0) : (x >= eve::maxlog(as(x))) ? inf(as(x)) : std::exp(x);
}
else
{
wide<T> xx(x);
return exp(xx).get(0);
}
}
else if constexpr( has_native_abi_v<T> )
{
using elt_t = element_type_t<T>;
const T Log_2hi = ieee_constant<0x1.6300000p-1f, 0x1.62e42fee00000p-1>(eve::as<T>{});
const T Log_2lo = ieee_constant<-0x1.bd01060p-13f, 0x1.a39ef35793c76p-33>(eve::as<T>{});
const T Invlog_2 = ieee_constant<0x1.7154760p+0f, 0x1.71547652b82fep+0>(eve::as<T>{});
auto xltminlog = x <= minlogval();
auto xgemaxlog = x >= maxlog(eve::as(x));
if constexpr( scalar_value<T> )
{
if( isnan ) return x;
if( xgemaxlog ) return inf(eve::as(x));
if( xltminlog ) return zero(eve::as(x));
}
auto c = nearest(Invlog_2 * x);
auto k = c;
x = fnma(c, Log_2hi, x); // x-c*L
if constexpr( std::is_same_v<elt_t, float> )
{
x = fnma(c, Log_2lo, x);
auto y = eve::reverse_horner(x, T(0x1.000000p-1f), T(0x1.55534ap-3f), T(0x1.5552aep-5f)
, T(0x1.131b16p-7f), T(0x1.6ef19ep-10f));;
c = inc(fma(y, sqr(x), x));
}
else if constexpr( std::is_same_v<elt_t, double> )
{
auto hi = x;
auto lo = c * Log_2lo;
x = hi - lo;
auto t = sqr(x);
c = fnma(t, eve::reverse_horner(t, T(0x1.555555555553ep-3), T(-0x1.6c16c16bebd93p-9), T(0x1.1566aaf25de2cp-14)
, T(-0x1.bbd41c5d26bf1p-20), T(0x1.6376972bea4d0p-25)), x); // x-h*t
c = oneminus((((lo - (x * c) / (T(2) - c)) - hi)));
}
auto z = ldexp[pedantic](c, k);
if constexpr( simd_value<T> )
{
z = if_else(xltminlog, eve::zero, z);
z = if_else(xgemaxlog, inf(eve::as(x)), z);
z = if_else(isnan, allbits, z);
}
return z;
}
else return apply_over(exp[o], x);
}
}
}
Loading

0 comments on commit edcc32c

Please sign in to comment.