Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix unsafe bool usage #794

Merged
merged 2 commits into from
Jul 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 39 additions & 36 deletions include/boost/math/ccmath/fmod.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// (C) Copyright Matt Borland 2021.
// (C) Copyright Matt Borland 2021 - 2022.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Expand All @@ -10,6 +10,7 @@
#include <cstdint>
#include <limits>
#include <type_traits>
#include <boost/math/tools/promotion.hpp>
#include <boost/math/tools/is_constant_evaluated.hpp>
#include <boost/math/ccmath/abs.hpp>
#include <boost/math/ccmath/isinf.hpp>
Expand All @@ -20,38 +21,57 @@ namespace boost::math::ccmath {

namespace detail {

template <typename ReturnType, typename T1, typename T2>
inline constexpr ReturnType fmod_impl(T1 x, T2 y) noexcept
template <typename T>
constexpr T fmod_impl(T x, T y)
{
if(x == y)
if (x == y)
{
return ReturnType(0);
return static_cast<T>(0);
}
else
{
while(x >= y)
while (x >= y)
{
x -= y;
}

return static_cast<ReturnType>(x);
return static_cast<T>(x);
}
}

} // Namespace detail

template <typename Real, std::enable_if_t<!std::is_integral_v<Real>, bool> = true>
inline constexpr Real fmod(Real x, Real y) noexcept
constexpr Real fmod(Real x, Real y)
{
if(BOOST_MATH_IS_CONSTANT_EVALUATED(x))
{
return boost::math::ccmath::abs(x) == Real(0) && y != Real(0) ? x :
boost::math::ccmath::isinf(x) && !boost::math::ccmath::isnan(y) ? std::numeric_limits<Real>::quiet_NaN() :
boost::math::ccmath::abs(y) == Real(0) && !boost::math::ccmath::isnan(x) ? std::numeric_limits<Real>::quiet_NaN() :
boost::math::ccmath::isinf(y) && boost::math::ccmath::isfinite(x) ? x :
boost::math::ccmath::isnan(x) ? std::numeric_limits<Real>::quiet_NaN() :
boost::math::ccmath::isnan(y) ? std::numeric_limits<Real>::quiet_NaN() :
boost::math::ccmath::detail::fmod_impl<Real>(x, y);
if (boost::math::ccmath::abs(x) == static_cast<Real>(0) && y != static_cast<Real>(0))
{
return x;
}
else if (boost::math::ccmath::isinf(x) && !boost::math::ccmath::isnan(y))
{
return std::numeric_limits<Real>::quiet_NaN();
}
else if (boost::math::ccmath::abs(y) == static_cast<Real>(0) && !boost::math::ccmath::isnan(x))
{
return std::numeric_limits<Real>::quiet_NaN();
}
else if (boost::math::ccmath::isinf(y) && boost::math::ccmath::isfinite(x))
{
return x;
}
else if (boost::math::ccmath::isnan(x))
{
return x;
}
else if (boost::math::ccmath::isnan(y))
{
return y;
}

return boost::math::ccmath::detail::fmod_impl<Real>(x, y);
}
else
{
Expand All @@ -61,28 +81,11 @@ inline constexpr Real fmod(Real x, Real y) noexcept
}

template <typename T1, typename T2>
inline constexpr auto fmod(T1 x, T2 y) noexcept
constexpr auto fmod(T1 x, T2 y)
{
if(BOOST_MATH_IS_CONSTANT_EVALUATED(x))
{
// If the type is an integer (e.g. epsilon == 0) then set the epsilon value to 1 so that type is at a minimum
// cast to double
constexpr auto T1p = std::numeric_limits<T1>::epsilon() > 0 ? std::numeric_limits<T1>::epsilon() : 1;
constexpr auto T2p = std::numeric_limits<T2>::epsilon() > 0 ? std::numeric_limits<T2>::epsilon() : 1;

using promoted_type =
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
std::conditional_t<T1p <= LDBL_EPSILON && T1p <= T2p, T1,
std::conditional_t<T2p <= LDBL_EPSILON && T2p <= T1p, T2,
#endif
std::conditional_t<T1p <= DBL_EPSILON && T1p <= T2p, T1,
std::conditional_t<T2p <= DBL_EPSILON && T2p <= T1p, T2, double
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
>>>>;
#else
>>;
#endif

using promoted_type = boost::math::tools::promote_args_t<T1, T2>;
return boost::math::ccmath::fmod(promoted_type(x), promoted_type(y));
}
else
Expand All @@ -92,13 +95,13 @@ inline constexpr auto fmod(T1 x, T2 y) noexcept
}
}

inline constexpr float fmodf(float x, float y) noexcept
constexpr float fmodf(float x, float y)
{
return boost::math::ccmath::fmod(x, y);
}

#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
inline constexpr long double fmodl(long double x, long double y) noexcept
constexpr long double fmodl(long double x, long double y)
{
return boost::math::ccmath::fmod(x, y);
}
Expand Down
63 changes: 30 additions & 33 deletions include/boost/math/ccmath/remainder.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// (C) Copyright Matt Borland 2021.
// (C) Copyright Matt Borland 2021 - 2022.
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Expand All @@ -10,6 +10,7 @@
#include <cstdint>
#include <limits>
#include <type_traits>
#include <boost/math/tools/promotion.hpp>
#include <boost/math/tools/is_constant_evaluated.hpp>
#include <boost/math/ccmath/abs.hpp>
#include <boost/math/ccmath/isinf.hpp>
Expand All @@ -22,16 +23,15 @@ namespace boost::math::ccmath {
namespace detail {

template <typename T>
inline constexpr T remainder_impl(const T x, const T y) noexcept
constexpr T remainder_impl(const T x, const T y)
{
T n = 0;
const T fractional_part = boost::math::ccmath::modf((x / y), &n);

if(fractional_part > T(1.0/2))
if (T fractional_part = boost::math::ccmath::modf((x / y), &n); fractional_part > static_cast<T>(1.0/2))
{
++n;
}
else if(fractional_part < T(-1.0/2))
else if (fractional_part < static_cast<T>(-1.0/2))
{
--n;
}
Expand All @@ -42,14 +42,28 @@ inline constexpr T remainder_impl(const T x, const T y) noexcept
} // Namespace detail

template <typename Real, std::enable_if_t<!std::is_integral_v<Real>, bool> = true>
inline constexpr Real remainder(Real x, Real y) noexcept
constexpr Real remainder(Real x, Real y)
{
if(BOOST_MATH_IS_CONSTANT_EVALUATED(x))
if (BOOST_MATH_IS_CONSTANT_EVALUATED(x))
{
return boost::math::ccmath::isinf(x) && !boost::math::ccmath::isnan(y) ? std::numeric_limits<Real>::quiet_NaN() :
boost::math::ccmath::abs(y) == Real(0) && !boost::math::ccmath::isnan(x) ? std::numeric_limits<Real>::quiet_NaN() :
boost::math::ccmath::isnan(x) || boost::math::ccmath::isnan(y) ? std::numeric_limits<Real>::quiet_NaN() :
boost::math::ccmath::detail::remainder_impl<Real>(x, y);
if (boost::math::ccmath::isinf(x) && !boost::math::ccmath::isnan(y))
{
return std::numeric_limits<Real>::quiet_NaN();
}
else if (boost::math::ccmath::abs(y) == static_cast<Real>(0) && !boost::math::ccmath::isnan(x))
{
return std::numeric_limits<Real>::quiet_NaN();
}
else if (boost::math::ccmath::isnan(x))
{
return x;
}
else if (boost::math::ccmath::isnan(y))
{
return y;
}

return boost::math::ccmath::detail::remainder_impl(x, y);
}
else
{
Expand All @@ -59,28 +73,11 @@ inline constexpr Real remainder(Real x, Real y) noexcept
}

template <typename T1, typename T2>
inline constexpr auto remainder(T1 x, T2 y) noexcept
constexpr auto remainder(T1 x, T2 y)
{
if(BOOST_MATH_IS_CONSTANT_EVALUATED(x))
if (BOOST_MATH_IS_CONSTANT_EVALUATED(x))
{
// If the type is an integer (e.g. epsilon == 0) then set the epsilon value to 1 so that type is at a minimum
// cast to double
constexpr auto T1p = std::numeric_limits<T1>::epsilon() > 0 ? std::numeric_limits<T1>::epsilon() : 1;
constexpr auto T2p = std::numeric_limits<T2>::epsilon() > 0 ? std::numeric_limits<T2>::epsilon() : 1;

using promoted_type =
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
std::conditional_t<T1p <= LDBL_EPSILON && T1p <= T2p, T1,
std::conditional_t<T2p <= LDBL_EPSILON && T2p <= T1p, T2,
#endif
std::conditional_t<T1p <= DBL_EPSILON && T1p <= T2p, T1,
std::conditional_t<T2p <= DBL_EPSILON && T2p <= T1p, T2, double
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
>>>>;
#else
>>;
#endif

using promoted_type = boost::math::tools::promote_args_t<T1, T2>;
return boost::math::ccmath::remainder(promoted_type(x), promoted_type(y));
}
else
Expand All @@ -90,13 +87,13 @@ inline constexpr auto remainder(T1 x, T2 y) noexcept
}
}

inline constexpr float remainderf(float x, float y) noexcept
constexpr float remainderf(float x, float y)
{
return boost::math::ccmath::remainder(x, y);
}

#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
inline constexpr long double remainderl(long double x, long double y) noexcept
constexpr long double remainderl(long double x, long double y)
{
return boost::math::ccmath::remainder(x, y);
}
Expand Down