Skip to content

Commit

Permalink
Merge pull request #6 from frederick-vs-ja/overflow-17
Browse files Browse the repository at this point in the history
Backport overflow checking of `lcm`/`gcd` to C++17
  • Loading branch information
AlexGuteniev authored Jul 4, 2024
2 parents 8c95ecd + 260a884 commit 2c5a2c4
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 11 deletions.
11 changes: 3 additions & 8 deletions stl/inc/numeric
Original file line number Diff line number Diff line change
Expand Up @@ -625,10 +625,9 @@ _NODISCARD constexpr common_type_t<_Mt, _Nt> gcd(const _Mt _Mx, const _Nt _Nx) n
using _Common = common_type_t<_Mt, _Nt>;
using _Common_unsigned = make_unsigned_t<_Common>;

#if _HAS_CXX20
if constexpr (is_signed_v<_Common>) {
#ifndef _DEBUG
if (_STD is_constant_evaluated())
if (_STD _Is_constant_evaluated())
#endif // ^^^ !defined(_DEBUG) ^^
{
if (_Mx == _STD _Min_limit<_Common>() || _Nx == _STD _Min_limit<_Common>()) {
Expand All @@ -637,7 +636,6 @@ _NODISCARD constexpr common_type_t<_Mt, _Nt> gcd(const _Mt _Mx, const _Nt _Nx) n
}
}
}
#endif // _HAS_CXX20

return _Select_countr_zero_impl<_Common_unsigned>([=](auto _Countr_zero_impl) {
_Common_unsigned _Mx_magnitude = _Abs_u(_Mx);
Expand Down Expand Up @@ -684,11 +682,10 @@ _NODISCARD constexpr common_type_t<_Mt, _Nt> lcm(const _Mt _Mx, const _Nt _Nx) n
return 0;
}

#if _HAS_CXX20
#ifdef _DEBUG
if constexpr (true)
#else // ^^^ defined(_DEBUG) / !defined(_DEBUG) vvv
if (_STD is_constant_evaluated())
if (_STD _Is_constant_evaluated())
#endif // ^^^ !defined(_DEBUG) ^^^
{
_Common_unsigned _Result = 0;
Expand All @@ -700,9 +697,7 @@ _NODISCARD constexpr common_type_t<_Mt, _Nt> lcm(const _Mt _Mx, const _Nt _Nx) n
}

return static_cast<_Common>(_Result);
} else
#endif // _HAS_CXX20
{
} else {
return static_cast<_Common>((_Mx_magnitude / _STD gcd(_Mx_magnitude, _Nx_magnitude)) * _Nx_magnitude);
}
}
Expand Down
14 changes: 11 additions & 3 deletions stl/inc/xutility
Original file line number Diff line number Diff line change
Expand Up @@ -7374,16 +7374,23 @@ _NODISCARD constexpr bool _Add_overflow(const _Int _Left, const _Int _Right, _In
}
#endif // _HAS_CXX23

#if _HAS_CXX17
#if _HAS_CXX20
template <_Integer_like _Int>
#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv
template <class _Int, enable_if_t<_Is_nonbool_integral<_Int>, int> = 0>
#endif // ^^^ !_HAS_CXX20 ^^^
_NODISCARD constexpr bool _Mul_overflow(const _Int _Left, const _Int _Right, _Int& _Out) {
#if defined(__clang__) && !_HAS_CXX20
return __builtin_mul_overflow(_Left, _Right, &_Out);
#else // ^^^ defined(__clang__) && !_HAS_CXX20 / !defined(__clang__) || _HAS_CXX20 vvv
#ifdef __clang__
if constexpr (integral<_Int>) {
if constexpr (is_integral_v<_Int>) {
return __builtin_mul_overflow(_Left, _Right, &_Out);
} else
#endif // defined(__clang__)
{
if constexpr (!_Signed_integer_like<_Int>) {
if constexpr (static_cast<_Int>(-1) > static_cast<_Int>(0)) {
constexpr auto _UInt_max = _STD _Max_limit<_Int>();
const bool _Overflow = _Left != 0 && _Right > _UInt_max / _Left;
if (!_Overflow) {
Expand Down Expand Up @@ -7422,8 +7429,9 @@ _NODISCARD constexpr bool _Mul_overflow(const _Int _Left, const _Int _Right, _In
// ^^^ Based on llvm::MulOverflow ^^^
}
}
#endif // ^^^ !defined(__clang__) || _HAS_CXX20 ^^^
}
#endif // _HAS_CXX20
#endif // _HAS_CXX17

_STD_END

Expand Down

0 comments on commit 2c5a2c4

Please sign in to comment.