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

<numeric> Optimize gcd to use builtins #665

Merged
merged 6 commits into from
Apr 11, 2020
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
20 changes: 3 additions & 17 deletions stl/inc/bit
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ _STL_DISABLE_CLANG_WARNINGS
#undef new

_STD_BEGIN
enum class endian { little = 0, big = 1, native = little };
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved

#ifdef __cpp_lib_bit_cast // TRANSITION, VSO-1041044
template <class _To, class _From,
enable_if_t<conjunction_v<bool_constant<sizeof(_To) == sizeof(_From)>, is_trivially_copyable<_To>,
Expand All @@ -36,11 +34,6 @@ _NODISCARD constexpr _To bit_cast(const _From& _Val) noexcept {
#endif // TRANSITION, VSO-1041044

#ifdef __cpp_lib_bitops // TRANSITION, VSO-1020212
template <class _Ty>
inline constexpr bool _Is_standard_unsigned_integer =
_Is_any_of_v<remove_cv_t<_Ty>, unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long>;


template <class _Ty, enable_if_t<_Is_standard_unsigned_integer<_Ty>, int> = 0>
_NODISCARD constexpr int countl_zero(_Ty _Val) noexcept;

Expand Down Expand Up @@ -124,20 +117,12 @@ _NODISCARD constexpr int countl_one(const _Ty _Val) noexcept {

template <class _Ty, enable_if_t<_Is_standard_unsigned_integer<_Ty>, int> = 0>
_NODISCARD constexpr int countr_zero(const _Ty _Val) noexcept {
if (_Val == 0) {
return numeric_limits<_Ty>::digits;
}

if constexpr (sizeof(_Ty) <= sizeof(unsigned int)) {
return __builtin_ctz(_Val);
} else {
return __builtin_ctzll(_Val);
}
return _Countr_zero(_Val);
}

template <class _Ty, enable_if_t<_Is_standard_unsigned_integer<_Ty>, int> _Enabled = 0>
_NODISCARD constexpr int countr_one(const _Ty _Val) noexcept {
return _STD countr_zero(static_cast<_Ty>(~_Val));
return _Countr_zero(static_cast<_Ty>(~_Val));
}

template <class _Ty, enable_if_t<_Is_standard_unsigned_integer<_Ty>, int> _Enabled = 0>
Expand All @@ -150,6 +135,7 @@ _NODISCARD constexpr int popcount(const _Ty _Val) noexcept {
}
#endif // __cpp_lib_bitops

enum class endian { little = 0, big = 1, native = little };
_STD_END

#pragma pop_macro("new")
Expand Down
20 changes: 20 additions & 0 deletions stl/inc/limits
Original file line number Diff line number Diff line change
Expand Up @@ -1011,6 +1011,26 @@ public:
static constexpr int min_exponent = LDBL_MIN_EXP;
static constexpr int min_exponent10 = LDBL_MIN_10_EXP;
};

#ifdef __cpp_lib_bitops // TRANSITION, VSO-1020212
template <class _Ty>
inline constexpr bool _Is_standard_unsigned_integer =
_Is_any_of_v<remove_cv_t<_Ty>, unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long>;

template <class _Ty, enable_if_t<_Is_standard_unsigned_integer<_Ty>, int> = 0>
_NODISCARD constexpr int _Countr_zero(const _Ty _Val) noexcept {
if (_Val == 0) {
return numeric_limits<_Ty>::digits;
}

if constexpr (sizeof(_Ty) <= sizeof(unsigned int)) {
return __builtin_ctz(_Val);
} else {
return __builtin_ctzll(_Val);
}
}
#endif // __cpp_lib_bitops

_STD_END
#pragma pop_macro("new")
_STL_RESTORE_CLANG_WARNINGS
Expand Down
6 changes: 5 additions & 1 deletion stl/inc/numeric
Original file line number Diff line number Diff line change
Expand Up @@ -859,7 +859,10 @@ _NODISCARD constexpr auto _Abs_u(const _Arithmetic _Val) noexcept {

// FUNCTION TEMPLATE _Stl_bitscan_forward
template <class _Unsigned>
constexpr unsigned long _Stl_bitscan_forward(_Unsigned _Mask) noexcept {
_NODISCARD constexpr unsigned long _Stl_bitscan_forward(_Unsigned _Mask) noexcept {
#ifdef __cpp_lib_bitops // TRANSITION, VSO-1020212
return static_cast<unsigned long>(_Countr_zero(_Mask));
#else // ^^^ __cpp_lib_bitops / !__cpp_lib_bitops vvv
// find the index of the least significant set bit (_BitScanForward isn't constexpr... yet :))
static_assert(is_unsigned_v<_Unsigned>, "Bitscan only works on bits");
unsigned long _Count = 0;
Expand All @@ -871,6 +874,7 @@ constexpr unsigned long _Stl_bitscan_forward(_Unsigned _Mask) noexcept {
}

return _Count;
#endif // !__cpp_lib_bitops
}

// FUNCTION TEMPLATE gcd
Expand Down