Hi John, i think your sign-function (boost/math/special_functions/sign.hpp) is incomplete. Because the resulttype is int, not all cases can be covered correctly (nan, inf, -0). With my implementation this works and it follows the std-conventions (sgn(FP) -> FP, sgn(INT/BOOL) -> double). I also tried to optimize them (branch-free, vectorizable).
sgn(FP) -> FP ±0/±1 sgn(FP nan/inf) -> FP nan/inf sgn(INT) -> double +0/±1 sgn(UINT/BOOL) -> double +0/+1 regards Gero
namespace std { namespace detail { template <typename Type> struct type_floating_point { static_assert(std::is_arithmetic_v<Type>, "invalid type"); using type = std::conditional_t<std::is_floating_point_v<Type>, Type, float64_t>; }; } // detail template <typename Type> using floating_point_t = typename detail::type_floating_point<Type>::type; // is float80_t template <typename Type> struct is_float80 : public bool_constant < #if defined(BOOST_CSTDFLOAT_FLOAT80_NATIVE_TYPE) is_same_v<Type, float80_t> #else false #endif > {}; template <typename Type> inline constexpr bool is_float80_v = is_float80<Type>::value; // arithmetic template <typename Type> concept arithmetic = is_arithmetic_v<Type>; // combined nan/inf template <arithmetic Type> [[nodiscard]] inline constexpr bool isnaninf(const Type a) noexcept { if constexpr (is_floating_point_v<Type>) return bool(int(isnan(a)) | int(isinf(a))); else return false; } template <arithmetic Type> [[nodiscard]] inline constexpr floating_point_t<Type> sgn(const Type a) noexcept { using value_type = floating_point_t<Type>; auto calc = [&]() constexpr noexcept { if constexpr (is_floating_point_v<Type>) { auto get_one_zero = [&]() constexpr noexcept -> value_type { // abs reduces/prevents double conditional jumps return (abs(a) > 0) ? value_type{1} : value_type{0}; }; if constexpr (is_float80_v<Type>) { // optimized for float80_t if supported const bool ni = isnaninf(a); const float80_t oz = get_one_zero(); return copysign(ni ? a : oz, a); } else { // generate better/smaller code in vector/loop-context than isnaninf(a) ? a : copysign(get_one_zero(), a); return !isnaninf(a) ? copysign(get_one_zero(), a) : a; //return isnaninf(a) ? a : copysign(get_one_zero(), a); } } else if constexpr (is_same_v<Type, bool>) { // fukking bool in arithmetic return int(a); } else { if constexpr (is_signed_v<Type>) return int(int(a>0) - int(a<0)); else return int(a>0); } }; return value_type(calc()); } } // std
OpenPGP_signature
Description: OpenPGP digital signature
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org https://lists.boost.org/mailman/listinfo.cgi/boost-users