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

Move <ranges> and <format> into C++20 #2518

Merged
merged 13 commits into from
Feb 7, 2022
46 changes: 26 additions & 20 deletions stl/inc/__msvc_int128.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ _STD_BEGIN
#define _STL_128_DIV_INTRINSICS 0
#else // ^^^ Clang / other vvv
#define _STL_128_DIV_INTRINSICS 1
#endif
#else // ^^^ X64 / other vvv
#endif // ^^^ detect _udiv128 / _div128 ^^^
#else // ^^^ x64 / other vvv
#define _STL_128_INTRINSICS 0
#define _STL_128_DIV_INTRINSICS 0
#endif // defined(_M_X64) && !defined(_M_ARM64EC)
Expand Down Expand Up @@ -132,8 +132,9 @@ struct
template <size_t __m, size_t __n>
static constexpr void _Knuth_4_3_1_M(
const uint32_t (&__u)[__m], const uint32_t (&__v)[__n], uint32_t (&__w)[__n + __m]) noexcept {
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved
_STL_INTERNAL_STATIC_ASSERT(__m <= size_t{(numeric_limits<int>::max)()});
_STL_INTERNAL_STATIC_ASSERT(__n <= size_t{(numeric_limits<int>::max)()});
constexpr auto _Int_max = size_t{(numeric_limits<int>::max)()};
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
_STL_INTERNAL_STATIC_ASSERT(__m <= _Int_max);
_STL_INTERNAL_STATIC_ASSERT(__n <= _Int_max);

for (auto& _Elem : __w) {
_Elem = 0;
Expand Down Expand Up @@ -179,10 +180,11 @@ struct
static constexpr void _Knuth_4_3_1_D(uint32_t* const __u, const size_t __u_size, const uint32_t* const __v,
const size_t __v_size, uint32_t* const __q) noexcept {
// Pre: __u + [0, __u_size), __v + [0, __v_size), and __q + [0, __u_size - __v_size) are all valid ranges
_STL_INTERNAL_CHECK(__v_size <= uint32_t{(numeric_limits<int>::max)()});
constexpr auto _Int_max = size_t{(numeric_limits<int>::max)()};
_STL_INTERNAL_CHECK(__v_size <= _Int_max);
const auto __n = static_cast<int>(__v_size);
_STL_INTERNAL_CHECK(__u_size > __v_size);
_STL_INTERNAL_CHECK(__u_size <= uint32_t{(numeric_limits<int>::max)()});
_STL_INTERNAL_CHECK(__u_size <= _Int_max);
const auto __m = static_cast<int>(__u_size - __v_size - 1);
_STL_INTERNAL_CHECK(__v[__n - 1] >> 31 != 0); // Arguments are already normalized

Expand Down Expand Up @@ -452,12 +454,14 @@ struct

_NODISCARD_FRIEND constexpr _Uint128 operator/(_Uint128 _Num, _Uint128 _Den) noexcept {
// establish _Den < _Num and _Num._Word[1] > 0
if (_Den._Word[1] > _Num._Word[1]) {
return _Uint128{};
}
if (_Den._Word[1] >= _Num._Word[1]) {
if (_Den._Word[1] > _Num._Word[1]) {
return _Uint128{};
}

if (_Den._Word[1] == _Num._Word[1]) {
return _Uint128{_Num._Word[1] == 0 ? _Num._Word[0] / _Den._Word[0] : _Num._Word[0] >= _Den._Word[0]};
if (_Den._Word[1] == _Num._Word[1]) {
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved
return _Uint128{_Num._Word[1] == 0 ? _Num._Word[0] / _Den._Word[0] : _Num._Word[0] >= _Den._Word[0]};
}
}

// establish _Den has more than 1 non-zero "digit"
Expand Down Expand Up @@ -597,16 +601,18 @@ struct
}
_NODISCARD_FRIEND constexpr _Uint128 operator%(_Uint128 _Num, _Uint128 _Den) noexcept {
// establish _Den < _Num and _Num._Word[1] > 0
if (_Den._Word[1] > _Num._Word[1]) {
return _Num;
}

if (_Den._Word[1] == _Num._Word[1]) {
if (_Den._Word[0] <= _Num._Word[0]) {
return _Uint128{_Num._Word[0] - _Den._Word[0]};
if (_Den._Word[1] >= _Num._Word[1]) {
if (_Den._Word[1] > _Num._Word[1]) {
return _Num;
}

return _Num;
if (_Den._Word[1] == _Num._Word[1]) {
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved
if (_Den._Word[0] <= _Num._Word[0]) {
return _Uint128{_Num._Word[1] == 0 ? _Num._Word[0] % _Den._Word[0] : _Num._Word[0] - _Den._Word[0]};
}

return _Num;
}
}

// establish _Den has more than 1 non-zero "digit"
Expand Down Expand Up @@ -895,7 +901,7 @@ struct _Int128 : _Uint128 {
return _Left;
}

_NODISCARD_FRIEND constexpr _Int128 operator>>(const _Int128& _Left, const _Int128& _Right) noexcept {
_NODISCARD_FRIEND constexpr _Int128 operator>>(const _Int128& _Left, const _Uint128& _Right) noexcept {
auto _Tmp{_Left};
_Tmp._Right_shift(static_cast<unsigned char>(_Right._Word[0]));
return _Tmp;
Expand Down
197 changes: 178 additions & 19 deletions tests/std/tests/P1522R1_difference_type/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,39 @@ constexpr bool test_unsigned() {
assert(tmp == (x ^ y));
}

{
_Uint128 x{};
assert(++x == 1);
assert(--x == 0);
assert(x == std::numeric_limits<_Uint128>::min());
--x;
assert(x._Word[0] == ~0ull);
assert(x._Word[1] == ~0ull);
assert(x == std::numeric_limits<_Uint128>::max());
--x;
assert(x._Word[0] == (~0ull << 1));
assert(x._Word[1] == ~0ull);
x._Word[0] = 0;
x._Word[1] = 1;
--x;
assert(x._Word[0] == ~0ull);
assert(x._Word[1] == 0);
++x;
assert(x._Word[0] == 0);
assert(x._Word[1] == 1);
++x;
assert(x._Word[0] == 1);
assert(x._Word[1] == 1);
x._Word[0] = ~0ull;
x._Word[1] = static_cast<std::uint64_t>(std::numeric_limits<std::int64_t>::max());
++x;
assert(x._Word[0] == 0);
assert(x._Word[1] == static_cast<std::uint64_t>(std::numeric_limits<std::int64_t>::min()));
--x;
assert(x._Word[0] == ~0ull);
assert(x._Word[1] == static_cast<std::uint64_t>(std::numeric_limits<std::int64_t>::max()));
}

return true;
}

Expand Down Expand Up @@ -388,30 +421,60 @@ constexpr bool test_signed() {
assert(static_cast<std::int32_t>(nu) == -42);
assert(static_cast<std::int16_t>(nu) == -42);
assert(static_cast<std::int8_t>(nu) == -42);
}

_Int128 sum = u + nu;
assert(sum._Word[0] == 0);
{
_Int128 u{42};
_Int128 v{13};
_Int128 sum = u + v;
assert(sum._Word[0] == 55);
assert(sum._Word[1] == 0);

--sum;
assert(sum._Word[0] == 0ull - 1);
assert(sum._Word[1] == 0ull - 1);
--sum;
assert(sum._Word[0] == 0ull - 2);
assert(sum._Word[1] == 0ull - 1);
++sum;
assert(sum._Word[0] == 0ull - 1);
assert(sum._Word[1] == 0ull - 1);
++sum;
assert(sum._Word[0] == 0);
sum = v + u;
assert(sum._Word[0] == 55);
assert(sum._Word[1] == 0);

_Int128 product = u * u;
assert(product._Word[0] == 42 * 42);
_Int128 diff = u - v;
assert(diff._Word[0] == 29);
assert(diff._Word[1] == 0);
diff = v - u;
assert(diff._Word[0] == 0ull - 29);
assert(diff._Word[1] == ~0ull);

u = -u;
sum = u + v;
assert(diff._Word[0] == 0ull - 29);
assert(diff._Word[1] == ~0ull);
sum = v + u;
assert(diff._Word[0] == 0ull - 29);
assert(diff._Word[1] == ~0ull);
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved
diff = u - v;
assert(diff._Word[0] == 0ull - 55);
assert(diff._Word[1] == ~0ull);
diff = v - u;
assert(diff._Word[0] == 55);
assert(diff._Word[1] == 0);

u = -u;
_Int128 product = u * v;
assert(product._Word[0] == 42 * 13);
assert(product._Word[1] == 0);
product = v * u;
assert(product._Word[0] == 42 * 13);
assert(product._Word[1] == 0);

product = nu * nu;
assert(product._Word[0] == 42 * 42);
v = -v;
product = u * v;
assert(product._Word[0] == 0ull - (42 * 13));
assert(product._Word[1] == ~0ull);
product = v * u;
assert(product._Word[0] == 0ull - (42 * 13));
assert(product._Word[1] == ~0ull);

u = -u;
product = u * v;
assert(product._Word[0] == 42 * 13);
assert(product._Word[1] == 0);
product = v * u;
assert(product._Word[0] == 42 * 13);
assert(product._Word[1] == 0);

product = _Int128{0x01010101'01010101, 0x01010101'01010101} * 5;
Expand Down Expand Up @@ -457,6 +520,30 @@ constexpr bool test_signed() {
assert(q._Word[0] == 0);
assert(q._Word[1] == 0);

q = _Int128{13} / _Int128{-4};
assert(q._Word[0] == 0ull - 3);
assert(q._Word[1] == ~0ull);

q = _Int128{-4} / _Int128{13};
assert(q._Word[0] == 0);
assert(q._Word[1] == 0);

q = _Int128{-13} / _Int128{4};
assert(q._Word[0] == 0ull - 3);
assert(q._Word[1] == ~0ull);

q = _Int128{4} / _Int128{-13};
assert(q._Word[0] == 0);
assert(q._Word[1] == 0);

q = _Int128{-13} / _Int128{-4};
assert(q._Word[0] == 3);
assert(q._Word[1] == 0);

q = _Int128{-4} / _Int128{-13};
assert(q._Word[0] == 0);
assert(q._Word[1] == 0);

q = _Int128{0x01010101'01010101, 0x01010101'01010101} / _Int128{13};
assert(q._Word[0] == 0xc50013c5'0013c500);
assert(q._Word[1] == 0x0013c500'13c50013);
Expand Down Expand Up @@ -507,6 +594,38 @@ constexpr bool test_signed() {
assert(tmp % tmp == 0);
}
assert(tmp == 0);

_Int128 r = _Int128{13} % _Int128{4};
assert(r._Word[0] == 1);
assert(r._Word[1] == 0);

r = _Int128{4} % _Int128{13};
assert(r._Word[0] == 4);
assert(r._Word[1] == 0);

r = _Int128{13} % _Int128{-4};
assert(r._Word[0] == 1);
assert(r._Word[1] == 0);

r = _Int128{-4} % _Int128{13};
assert(r._Word[0] == 0ull - 4);
assert(r._Word[1] == ~0ull);

r = _Int128{-13} % _Int128{4};
assert(r._Word[0] == 0ull - 1);
assert(r._Word[1] == ~0ull);

r = _Int128{4} % _Int128{-13};
assert(r._Word[0] == 4);
assert(r._Word[1] == 0);

r = _Int128{-13} % _Int128{-4};
assert(r._Word[0] == 0ull - 1);
assert(r._Word[1] == ~0ull);

r = _Int128{-4} % _Int128{-13};
assert(r._Word[0] == 0ull - 4);
assert(r._Word[1] == ~0ull);
}

{
Expand All @@ -528,6 +647,39 @@ constexpr bool test_signed() {
assert(tmp == (x ^ y));
}

{
_Int128 x{};
assert(++x == 1);
assert(--x == 0);
--x;
assert(x._Word[0] == ~0ull);
assert(x._Word[1] == ~0ull);
--x;
assert(x._Word[0] == (~0ull << 1));
assert(x._Word[1] == ~0ull);
x._Word[0] = 0;
x._Word[1] = 1;
--x;
assert(x._Word[0] == ~0ull);
assert(x._Word[1] == 0);
++x;
assert(x._Word[0] == 0);
assert(x._Word[1] == 1);
++x;
assert(x._Word[0] == 1);
assert(x._Word[1] == 1);
x._Word[0] = ~0ull;
x._Word[1] = static_cast<std::uint64_t>(std::numeric_limits<std::int64_t>::max());
++x;
assert(x._Word[0] == 0);
assert(x._Word[1] == static_cast<std::uint64_t>(std::numeric_limits<std::int64_t>::min()));
assert(x == std::numeric_limits<_Int128>::min());
--x;
assert(x._Word[0] == ~0ull);
assert(x._Word[1] == static_cast<std::uint64_t>(std::numeric_limits<std::int64_t>::max()));
assert(x == std::numeric_limits<_Int128>::max());
}

return true;
}

Expand Down Expand Up @@ -559,6 +711,13 @@ constexpr bool test_cross() {

TEST(_Uint128{1} << _Int128{43}, _Uint128{1ull << 43});
TEST(_Int128{1} << _Uint128{43}, _Int128{1ull << 43});
TEST(_Uint128{-1} << _Int128{43}, _Uint128(0ull - (1ull << 43), ~0ull));
TEST(_Int128{-1} << _Uint128{43}, _Int128(0ull - (1ull << 43), ~0ull));

TEST(_Uint128(0, 1) >> _Int128{43}, _Uint128(1ull << 21));
TEST(_Int128(0, 1) >> _Uint128{43}, _Int128(1ull << 21));
TEST(_Uint128(0, ~0ull) >> _Int128{43}, _Uint128(~((1ull << 21) - 1), (1ull << 21) - 1));
TEST(_Int128(0, ~0ull) >> _Uint128{43}, _Int128(~((1ull << 21) - 1), ~0ull));
CaseyCarter marked this conversation as resolved.
Show resolved Hide resolved

TEST(false ? _Uint128{42} : _Int128{-43}, _Uint128{-43});
TEST(true ? _Uint128{42} : _Int128{-43}, _Uint128{42});
Expand Down