|
Boost : |
From: Gero Peterhoff (g.peterhoff_at_[hidden])
Date: 2022-08-15 18:12:37
Hi John,
Unfortunately, I encountered a very practical problem when implementing the additional math functions: ccmath cannot be compiled with C++11/14 because C++17 features are used. But this could easily be fixed by just using C++11/14 features and/or BOOST-macros. Example isinf:
Original code:
template <typename T>
inline constexpr bool isinf(T x)
{
if(BOOST_MATH_IS_CONSTANT_EVALUATED(x))
{
return x == std::numeric_limits<T>::infinity() || -x == std::numeric_limits<T>::infinity();
}
else
{
using std::isinf;
if constexpr (!std::is_integral_v<T>)
{
return isinf(x);
}
else
{
return isinf(static_cast<double>(x));
}
}
}
"std::is_integral_v<T>" and "if constexpr" doesn't work with C++11/14 - Change 1:
template <typename T>
inline constexpr bool isinf_v1(const T x) noexcept
{
if (BOOST_MATH_IS_CONSTANT_EVALUATED(x))
return (x == std::numeric_limits<T>::infinity()) || (-x == std::numeric_limits<T>::infinity());
else
{
using std::isinf;
BOOST_IF_CONSTEXPR (std::is_integral<T>::value)
return isinf(static_cast<double>(x));
else
return isinf(x);
}
}
But now it is not necessary to check for "std::is_integral<T>", since you can immediately request the Float-type via decltype - change 2:
template <typename T>
inline constexpr bool isinf_v2(const T x) noexcept
{
if (BOOST_MATH_IS_CONSTANT_EVALUATED(x))
return (x == std::numeric_limits<T>::infinity()) || (-x == std::numeric_limits<T>::infinity());
else
{
using type = decltype(std::sin(T{}));
return std::isinf(type(x));
}
}
But isinf only makes sense with float types, so you only have to check in this case - change 3a:
template <typename T>
inline constexpr bool isinf_v3a(const T x) noexcept
{
BOOST_IF_CONSTEXPR (std::is_floating_point<T>::value)
return (x == std::numeric_limits<T>::infinity()) || (-x == std::numeric_limits<T>::infinity());
else
return false;
}
However, you may want to explicitly check integer types only after conversion to float - change 3b:
template <typename T>
inline constexpr bool isinf_v3b(const T x) noexcept
{
BOOST_IF_CONSTEXPR (std::is_floating_point<T>::value)
return (x == std::numeric_limits<T>::infinity()) || (-x == std::numeric_limits<T>::infinity());
else
{
using type = decltype(std::sin(T{}));
return isinf_v3b(type(x));
}
}
Which of these variants makes the most sense and can you adapt the other ccmath functions for them? My favorite is 3a; but it must be compilable with C++11/14.
I could work around the problem, but that's really ugly and buggy.
thx
Gero
PS with a correctly working ccmath::abs you can also save yourself the check x/-x == limits::infinity().
Am 13.08.22 um 13:58 schrieb John Maddock via Boost:
>
>> Yes, that's why I asked which C++ standard can be used. Can I use e.g.
> C++14 unless you can make a really good case why the code needs something else.
>> - concepts
> I'd prefer not to.
>> - lambdas
> Yes absolutely.
>> - constexpr if
>
> In constexpr versions of functions yes - the existing ccmath code requires C++17, so you're on safe ground there. For general runtime special functions I'd prefer it if we can all keep to C++14 for the moment so there's not too much divergence between different functions.
>
> John.
>
>
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk