Boost logo

Boost :

From: Proton (matt_at_[hidden])
Date: 2022-08-16 02:07:00


> On Aug 15, 2022, at 11:12 AM, Gero Peterhoff via Boost <boost_at_[hidden]> wrote:
>
> 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
>
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
> <OpenPGP_signature.sig>

Gero,

Some of the checks you will find in the ccmath library seem common sense, but it is implemented to match the C++23 proposal (now standard) for constexpr cmath and cstdlib functionality. We used C++17 throughout to provide a clean solution with a reasonable language standard. If you look at the definition of BOOST_MATH_IS_CONSTANT_EVALUATED we are already using compiler intrinsics to allow this to be used without C++20s std::is_constant_evaluated. For non-trivial functionality C++11 would become extremely difficult to implement. C++14 would require code bloat that we can get around with if constexpr. Feel free to open up PRs and I will review your solutions.

Matt


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk