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

Attachment: OpenPGP_signature
Description: OpenPGP digital signature

_______________________________________________
Boost-users mailing list
Boost-users@lists.boost.org
https://lists.boost.org/mailman/listinfo.cgi/boost-users

Reply via email to