Skip to content

Commit

Permalink
More core cleanup & update to new callable style
Browse files Browse the repository at this point in the history
  • Loading branch information
jtlap authored Apr 20, 2024
1 parent faf9d43 commit 3f95018
Show file tree
Hide file tree
Showing 186 changed files with 3,416 additions and 3,446 deletions.
5 changes: 3 additions & 2 deletions include/eve/arch/cpu/wide.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,7 @@ namespace eve
//! @brief Perform the addition between all lanes of its parameters
//! See also: eve::add
friend EVE_FORCEINLINE auto operator+(wide const& v, wide const& w) noexcept
requires(!kumi::product_type<Type>)
{
auto that = v;
return that += w;
Expand All @@ -561,15 +562,15 @@ namespace eve
//! @brief Perform the addition between a scalar and all lanes of a eve::wide
//! See also: eve::add
friend EVE_FORCEINLINE auto operator+(plain_scalar_value auto s, wide const& v) noexcept
requires(!kumi::product_type<Type>)
requires(!kumi::product_type<Type>)
{
return v + wide(s);
}

//! @brief Perform the addition between all lanes of a eve::wide and a scalar
//! See also: eve::add
friend EVE_FORCEINLINE auto operator+(wide const& v, plain_scalar_value auto s) noexcept
requires(!kumi::product_type<Type>)
requires(!kumi::product_type<Type>)
{
return v + wide(s);
}
Expand Down
39 changes: 32 additions & 7 deletions include/eve/module/core/decorator/core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include <eve/module/core/decorator/sph.hpp>
#include <eve/module/core/decorator/spherical.hpp>
#include <eve/module/core/decorator/successor.hpp>
#include <eve/as_element.hpp>
#include <eve/as.hpp>

//======================================================================================================================
// New option style - TODO rename later without the '2'
Expand Down Expand Up @@ -57,11 +59,9 @@ namespace eve
struct toward_zero_mode {};
struct upward_mode {};

[[maybe_unused]] inline constexpr auto almost2 = ::rbr::flag( almost_mode{} );
[[maybe_unused]] inline constexpr auto associated2 = ::rbr::flag( associated_mode{} );
[[maybe_unused]] inline constexpr auto compensated2 = ::rbr::flag( compensated_mode{} );
[[maybe_unused]] inline constexpr auto condon_shortley2 = ::rbr::flag( condon_shortley_mode{} );
[[maybe_unused]] inline constexpr auto definitely2 = ::rbr::flag( definitely_mode{} );
[[maybe_unused]] inline constexpr auto downward2 = ::rbr::flag( downward_mode{} );
[[maybe_unused]] inline constexpr auto kind_12 = ::rbr::flag( kind_1_mode{} );
[[maybe_unused]] inline constexpr auto kind_22 = ::rbr::flag( kind_2_mode{} );
Expand All @@ -81,11 +81,9 @@ namespace eve
[[maybe_unused]] inline constexpr auto toward_zero2 = ::rbr::flag( toward_zero_mode{} );
[[maybe_unused]] inline constexpr auto upward2 = ::rbr::flag( upward_mode{} );

struct almost_option : detail::exact_option<almost2> {};
struct associated_option : detail::exact_option<associated2> {};
struct compensated_option : detail::exact_option<compensated2> {};
struct condon_shortley_option : detail::exact_option<condon_shortley2> {};
struct definitely_option : detail::exact_option<definitely2> {};
struct downward_option : detail::exact_option<downward2> {};
struct kind_1_option : detail::exact_option<kind_12> {};
struct kind_2_option : detail::exact_option<kind_22> {};
Expand All @@ -108,11 +106,9 @@ namespace eve
// ----------------------------------------------------------------------------------
// [TEMPORARY] Will be removed when all decorator have been converted
// ----------------------------------------------------------------------------------
inline constexpr auto as_option(almost_type const&) { return almost2; }
inline constexpr auto as_option(associated_type const&) { return associated2; }
inline constexpr auto as_option(compensated_type const&) { return compensated2; }
inline constexpr auto as_option(condon_shortley_type const&) { return condon_shortley2; }
inline constexpr auto as_option(definitely_type const&) { return definitely2; }
inline constexpr auto as_option(downward_type const&) { return downward2; }
inline constexpr auto as_option(kind_1_type const&) { return kind_12; }
inline constexpr auto as_option(kind_2_type const&) { return kind_22; }
Expand All @@ -133,6 +129,36 @@ namespace eve
inline constexpr auto as_option(upward_type const&) { return upward2; }

// New tolerance option that carry a value
template<typename Value>
struct almost_t;

struct almost_option
{
template<typename Value>
EVE_FORCEINLINE constexpr auto process(auto const& base, almost_t<Value> const& opts) const
{
auto news = rbr::merge(options{opts}, base);
return options<decltype(news)>{news};
}

EVE_FORCEINLINE constexpr auto default_to(auto const& base) const { return base; }
};

template<typename Value>
struct definitely_t;

struct definitely_option
{
template<typename Value>
EVE_FORCEINLINE constexpr auto process(auto const& base, definitely_t<Value> const& opts) const
{
auto news = rbr::merge(options{opts}, base);
return options<decltype(news)>{news};
}

EVE_FORCEINLINE constexpr auto default_to(auto const& base) const { return base; }
};

struct tolerant_mode {};
struct default_tolerance
{
Expand All @@ -144,5 +170,4 @@ namespace eve

struct tolerant_option : detail::exact_option<tolerance> {};
inline constexpr auto as_option(tolerant_type const&) { return tolerant2; }

}
116 changes: 116 additions & 0 deletions include/eve/module/core/detail/tolerance.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
//==================================================================================================
/*
EVE - Expressive Vector Engine
Copyright : EVE Project Contributors
SPDX-License-Identifier: BSL-1.0
*/
//==================================================================================================
#pragma once

#include <eve/module/core/constant/eps.hpp>
#include <eve/module/core/decorator/core.hpp>
#include <eve/module/core/regular/convert.hpp>

namespace eve
{
// ===============================================================================================
//almost

template<typename Value>
struct almost_t
{
constexpr almost_t() {}
constexpr explicit almost_t(Value v) : value_(v) {}
constexpr almost_t(almost_t const& v) : value_(v.value_) {}

/// ID type associated to the keyword
using id_type = almost_mode;

template<typename T> static constexpr bool accept() { return true; }

std::ostream& show(std::ostream& os, auto const& v) const
{
return os << "almost by " << v.value_;
}

using tag_type = almost_t<default_tolerance>;
using keyword_type = almost_t<default_tolerance>;
using stored_value_type = almost_t<Value>;

template<eve::scalar_value Type>
constexpr auto operator=(Type v) const noexcept { return almost_t<Type>{v}; }

template<typename T>
constexpr auto operator=(almost_t<T> const& v) const noexcept
{
return v;
}

constexpr auto operator()(keyword_type const&) const noexcept { return *this; }

template<typename T> constexpr auto value(T const&) const
{
using type = element_type_t<T>;
if constexpr(std::same_as<Value,default_tolerance>) return 3 * eps(as<type>{});
else if constexpr(integral_value<Value>) return value_;
else return type{value_};
}

Value value_;
};

inline constexpr almost_t<default_tolerance> almost2 = {};

inline constexpr auto as_option(almost_type const&) { return almost2; }

// ============================================================================================
// definitely

template<typename Value>
struct definitely_t
{
constexpr definitely_t() {}
constexpr explicit definitely_t(Value v) : value_(v) {}
constexpr definitely_t(definitely_t const& v) : value_(v.value_) {}

/// ID type associated to the keyword
using id_type = definitely_mode;

template<typename T> static constexpr bool accept() { return true; }

std::ostream& show(std::ostream& os, auto const& v) const
{
return os << "definitely by " << v.value_;
}

using tag_type = definitely_t<default_tolerance>;
using keyword_type = definitely_t<default_tolerance>;
using stored_value_type = definitely_t<Value>;

template<eve::scalar_value Type>
constexpr auto operator=(Type v) const noexcept { return definitely_t<Type>{v}; }

template<typename T>
constexpr auto operator=(definitely_t<T> const& v) const noexcept
{
return v;
}

constexpr auto operator()(keyword_type const&) const noexcept { return *this; }

template<typename T> constexpr auto value(T const&) const
{
using type = element_type_t<T>;
if constexpr(std::same_as<Value,default_tolerance>) return 3 * eps(as<type>{});
else if constexpr(integral_value<Value>) return value_;
else return type{value_};
}

Value value_;
};

inline constexpr definitely_t<default_tolerance> definitely2 = {};

inline constexpr auto as_option(definitely_type const&) { return definitely2; }

}
2 changes: 0 additions & 2 deletions include/eve/module/core/fuzzy/core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,10 @@
//==================================================================================================
#pragma once

#include <eve/module/core/fuzzy/is_equal.hpp>
#include <eve/module/core/fuzzy/is_greater.hpp>
#include <eve/module/core/fuzzy/is_greater_equal.hpp>
#include <eve/module/core/fuzzy/is_less.hpp>
#include <eve/module/core/fuzzy/is_less_equal.hpp>
#include <eve/module/core/fuzzy/is_not_equal.hpp>
#include <eve/module/core/fuzzy/is_not_greater.hpp>
#include <eve/module/core/fuzzy/is_not_greater_equal.hpp>
#include <eve/module/core/fuzzy/is_not_less.hpp>
Expand Down
11 changes: 0 additions & 11 deletions include/eve/module/core/numeric/core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,3 @@
*/
//==================================================================================================
#pragma once

#include <eve/module/core/numeric/fam.hpp>
#include <eve/module/core/numeric/fanm.hpp>
#include <eve/module/core/numeric/fms.hpp>
#include <eve/module/core/numeric/fnma.hpp>
#include <eve/module/core/numeric/fnms.hpp>
#include <eve/module/core/numeric/fsm.hpp>
#include <eve/module/core/numeric/fsnm.hpp>
#include <eve/module/core/numeric/is_equal.hpp>
#include <eve/module/core/numeric/is_not_equal.hpp>
#include <eve/module/core/numeric/lerp.hpp>
95 changes: 78 additions & 17 deletions include/eve/module/core/numeric/impl/fsm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,91 @@
#pragma once

#include <eve/traits/common_value.hpp>
#include <eve/concept/properly_convertible.hpp>
#include <eve/concept/value.hpp>
#include <eve/detail/apply_over.hpp>
#include <eve/detail/implementation.hpp>
#include <eve/detail/skeleton_calls.hpp>
#include <eve/module/core/decorator/numeric.hpp>
#include <eve/module/core/numeric/fms.hpp>
#include <eve/module/core/regular/all.hpp>

#include <type_traits>
#include <eve/module/core/regular/fma.hpp>

namespace eve::detail
{
template<ordered_value T, ordered_value U, ordered_value V>
EVE_FORCEINLINE auto
fsm_(EVE_SUPPORTS(cpu_), numeric_type const&, T const& a, U const& b, V const& c) noexcept
-> common_value_t<T, U, V>
{
return arithmetic_call(numeric(fsm), a, b, c);
}
template<typename T, typename U, typename V, callable_options O>
EVE_FORCEINLINE constexpr auto fsm_(EVE_REQUIRES(cpu_), O const& o, T const& a, U const& b, V const& c)
{
// PROMOTE ---------------------
if constexpr(O::contains(promote2))
{
using er_t = common_type_t<element_type_t<T>, element_type_t<U>, element_type_t<V>>;
constexpr auto tgt = as(eve::as<er_t>());
return fsm[o.drop(promote2)](convert(a, tgt), convert(b, tgt), convert(c,tgt));
}
// OTHERS ---------------------
else
{
using r_t = common_value_t<T, U, V>;
return fsm[o](r_t(a), r_t(b), r_t(c));
}
}

template<ordered_value T>
EVE_FORCEINLINE T
fsm_(EVE_SUPPORTS(cpu_), numeric_type const&, T const& a, T const& b, T const& c) noexcept
{
return numeric(fms)(b, c, a);
}
// PROMOTE may mix values of different types, making automatic masking from the default behaviors unwieldy
// We catch the mask + PROMOTE case and handle it properly
// No special provision is made for PEDANTIC as it is handled in the second pass without issues.
template<typename T, typename U, typename V, conditional_expr C, callable_options O>
EVE_FORCEINLINE constexpr auto
fsm_(EVE_REQUIRES(cpu_), C const& mask, O const& o, T const& a, U const& b, V const& c)
{
// PROMOTE ---------------------
if constexpr(O::contains(promote2))
{
using er_t = common_type_t<element_type_t<T>, element_type_t<U>, element_type_t<V>>;
constexpr auto tgt = as(eve::as<er_t>());

return fsm[o.drop(promote2)](convert(a, tgt), convert(b, tgt), convert(c,tgt));
}
// OTHERS ---------------------
else
{
using r_t = common_value_t<T, U, V>;
// Drop the mask key to prevent circular calls
auto opt = o.drop(condition_key);
return detail::mask_op(mask, detail::return_2nd, r_t(a), fsm[opt](r_t(a), r_t(b), r_t(c)));
}
}

template<typename T, callable_options O>
EVE_FORCEINLINE constexpr auto fsm_(EVE_REQUIRES(cpu_), O const& o, T const& a, T const& b, T const& c)
{
// PROMOTE ---------------------
// We promote before going pedantic in case it changes the behavior
if constexpr(O::contains(promote2)) return fsm[o.drop(promote2)](a,b,c);
// PEDANTIC ---------------------
else if constexpr(O::contains(pedantic2))
{
if constexpr( std::same_as<element_type_t<T>, float> )
{
constexpr auto tgt = as<double>{};
return convert( convert(b,tgt) * convert(c,tgt) - convert(a,tgt), as_element(a));
}
else if constexpr( std::same_as<element_type_t<T>, double> )
{
[[maybe_unused]] auto stdfsm = [](auto sa, auto sb, auto sc){return std::fma(sb, sa, sc); };
if constexpr(scalar_value<T>) return std::fma(b, c, -a);
else return map(stdfsm, a, b, c);
}
else if constexpr( std::is_integral_v<element_type_t<T>> )
{
// Pedantic fsm has to ensure "no intermediate overflow".
// This is done in the case of signed integers by trans-typing to unsigned type
// to perform the computations in a guarantee 2-complement environment
// since signed integer overflows in C++ produce "undefined results"
constexpr auto tgt = as<as_integer_t<T, unsigned>>{};
return bit_cast(fsm(bit_cast(a,tgt), bit_cast(b,tgt), bit_cast(c,tgt)), as<T>());
}
else return fsm(a, b, c);
}
// REGULAR ---------------------
else return b * c - a;
}
}
2 changes: 1 addition & 1 deletion include/eve/module/core/pedantic/impl/diff_of_prod.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ namespace eve::detail
{
T mcd = c * d;
T err = fma[pedantic](-c, d, mcd);
T dop = pedantic(fms)(a, b, mcd);
T dop = fms[pedantic](a, b, mcd);
return if_else(is_finite(err), dop + err, dop);
}
}
Expand Down
2 changes: 1 addition & 1 deletion include/eve/module/core/pedantic/impl/fanm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@ fanm_(EVE_SUPPORTS(cpu_),
T const& b,
T const& c) noexcept requires has_native_abi_v<T>
{
return pedantic(fnma)(b, c, a);
return fnma[pedantic2](b, c, a);
}
}
2 changes: 1 addition & 1 deletion include/eve/module/core/pedantic/impl/rem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ rem_(EVE_SUPPORTS(cpu_), pedantic_type const&, T const& a, T const& b) noexcept
allbits,
if_else(is_eqz(a) || is_infinite(b),
a,
pedantic(fnma)(b, trunc(div(a, b)), a) // rem(a, b)
fnma[pedantic2](b, trunc(div(a, b)), a) // rem(a, b)
)); // as remainder
}
else return if_else(is_nez(b), rem(a, bb), a);
Expand Down
Loading

0 comments on commit 3f95018

Please sign in to comment.