Skip to content
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
24 changes: 22 additions & 2 deletions stl/inc/bit
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,17 @@ _NODISCARD constexpr _Ty rotr(_Ty _Val, int _Rotation) noexcept;
template <class _Ty, enable_if_t<_Is_standard_unsigned_integer<_Ty>, int> = 0>
_NODISCARD constexpr _Ty rotl(const _Ty _Val, const int _Rotation) noexcept {
constexpr auto _Digits = numeric_limits<_Ty>::digits;
const auto _Remainder = _Rotation % _Digits;

if (!_STD is_constant_evaluated()) {
if constexpr (_Digits == 64) {
return _rotl64(_Val, _Rotation);
} else if constexpr (_Digits == 32) {
return _rotl(_Val, _Rotation);
}
// TRANSITION: fallback to non-intrinsic case until <intrin0.h> changes
}

const auto _Remainder = _Rotation % _Digits;
if (_Remainder > 0) {
return static_cast<_Ty>(
static_cast<_Ty>(_Val << _Remainder) | static_cast<_Ty>(_Val >> (_Digits - _Remainder)));
Expand All @@ -106,7 +116,17 @@ _NODISCARD constexpr _Ty rotl(const _Ty _Val, const int _Rotation) noexcept {
template <class _Ty, enable_if_t<_Is_standard_unsigned_integer<_Ty>, int> _Enabled>
Comment thread
AlexGuteniev marked this conversation as resolved.
_NODISCARD constexpr _Ty rotr(const _Ty _Val, const int _Rotation) noexcept {
constexpr auto _Digits = numeric_limits<_Ty>::digits;
const auto _Remainder = _Rotation % _Digits;

if (!_STD is_constant_evaluated()) {
if constexpr (_Digits == 64) {
return _rotr64(_Val, _Rotation);
} else if constexpr (_Digits == 32) {
return _rotr(_Val, _Rotation);
}
// TRANSITION: fallback to non-intrinsic case until <intrin0.h> changes
}

const auto _Remainder = _Rotation % _Digits;
if (_Remainder > 0) {
return static_cast<_Ty>(
static_cast<_Ty>(_Val >> _Remainder) | static_cast<_Ty>(_Val << (_Digits - _Remainder)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,21 @@ template <typename T>
constexpr bool test_rotl() {
constexpr int digits = numeric_limits<T>::digits;
constexpr auto maxval = numeric_limits<T>::max();

constexpr T every_fourth[4] = {
static_cast<T>(0x1111'1111'1111'1111ULL),
static_cast<T>(0x2222'2222'2222'2222ULL),
static_cast<T>(0x4444'4444'4444'4444ULL),
static_cast<T>(0x8888'8888'8888'8888ULL),
};

for (int i = 0; i < digits * 2; ++i) {
assert(rotl(maxval, i) == maxval);
assert(rotl(T{0}, i) == 0);

for (int j = 0; j < 4; ++j) {
assert(rotl(every_fourth[j], i) == every_fourth[(i + j) % 4]);
}
}
return true;
}
Expand All @@ -97,9 +109,21 @@ template <typename T>
constexpr bool test_rotr() {
constexpr int digits = numeric_limits<T>::digits;
constexpr auto maxval = numeric_limits<T>::max();

constexpr T every_fourth[4] = {
static_cast<T>(0x1111'1111'1111'1111ULL),
static_cast<T>(0x2222'2222'2222'2222ULL),
static_cast<T>(0x4444'4444'4444'4444ULL),
static_cast<T>(0x8888'8888'8888'8888ULL),
};

for (int i = 0; i < digits * 2; ++i) {
assert(rotr(maxval, i) == maxval);
assert(rotr(T{0}, i) == 0);

for (int j = 0; j < 4; ++j) {
assert(rotr(every_fourth[(i + j) % 4], i) == every_fourth[j]);
}
}
return true;
}
Expand Down