Boost logo

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