diff options
author | Devtools Arcadia <arcadia-devtools@yandex-team.ru> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/int128/ut | |
download | ydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/int128/ut')
-rw-r--r-- | library/cpp/int128/ut/.gitignore | 2 | ||||
-rw-r--r-- | library/cpp/int128/ut/i128_and_intrinsic_identity_ut.cpp | 598 | ||||
-rw-r--r-- | library/cpp/int128/ut/i128_comparison_ut.cpp | 145 | ||||
-rw-r--r-- | library/cpp/int128/ut/i128_division_ut.cpp | 413 | ||||
-rw-r--r-- | library/cpp/int128/ut/i128_type_traits_ut.cpp | 68 | ||||
-rw-r--r-- | library/cpp/int128/ut/i128_ut.cpp | 12 | ||||
-rw-r--r-- | library/cpp/int128/ut/int128_old_ut.cpp | 179 | ||||
-rw-r--r-- | library/cpp/int128/ut/int128_typetraits_ut.cpp | 306 | ||||
-rw-r--r-- | library/cpp/int128/ut/int128_ut.cpp | 83 | ||||
-rw-r--r-- | library/cpp/int128/ut/int128_ut_helpers.cpp | 56 | ||||
-rw-r--r-- | library/cpp/int128/ut/int128_ut_helpers.h | 15 | ||||
-rw-r--r-- | library/cpp/int128/ut/int128_via_intrinsic_ut.cpp | 34 | ||||
-rw-r--r-- | library/cpp/int128/ut/ui128_division_ut.cpp | 262 | ||||
-rw-r--r-- | library/cpp/int128/ut/ya.make | 20 |
14 files changed, 2193 insertions, 0 deletions
diff --git a/library/cpp/int128/ut/.gitignore b/library/cpp/int128/ut/.gitignore new file mode 100644 index 0000000000..36abcb2a2c --- /dev/null +++ b/library/cpp/int128/ut/.gitignore @@ -0,0 +1,2 @@ +library-int128-ut + diff --git a/library/cpp/int128/ut/i128_and_intrinsic_identity_ut.cpp b/library/cpp/int128/ut/i128_and_intrinsic_identity_ut.cpp new file mode 100644 index 0000000000..dbb7507a73 --- /dev/null +++ b/library/cpp/int128/ut/i128_and_intrinsic_identity_ut.cpp @@ -0,0 +1,598 @@ +#include "int128_ut_helpers.h" + +#include <library/cpp/testing/unittest/registar.h> + +#include <library/cpp/int128/int128.h> + +#include <util/generic/cast.h> + +#include <array> +#include <type_traits> + +#if defined(Y_HAVE_INT128) +bool IsIdentical(const i128 a, const signed __int128 b) { + const std::array<ui8, 16> arrayA = NInt128Private::GetAsArray(a); + const std::array<ui8, 16> arrayB = NInt128Private::GetAsArray(b); + return arrayA == arrayB; +} + +Y_UNIT_TEST_SUITE(i128_And_i8_BitwiseIdentity) { + Y_UNIT_TEST(i128_from_i8_Zero) { + i8 n = 0; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i8_Minus1) { + i8 n = -1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i8_Plus1) { + i8 n = 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i8_Minus42) { + i8 n = -42; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i8_Plus42) { + i8 n = 42; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i8_Min) { + i8 n = std::numeric_limits<i8>::min(); + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i8_Max) { + i8 n = std::numeric_limits<i8>::max(); + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i8_MinPlus1) { + i8 n = std::numeric_limits<i8>::min() + 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i8_MaxMinus1) { + i8 n = std::numeric_limits<i8>::max() - 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } +} + +Y_UNIT_TEST_SUITE(i128_And_i16_BitwiseIdentity) { + Y_UNIT_TEST(i128_from_i16_Zero) { + i16 n = 0; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i16_Minus1) { + i16 n = -1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i16_Plus1) { + i16 n = 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i16_Minus42) { + i16 n = -42; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i16_Plus42) { + i16 n = 42; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i16_Min) { + i16 n = std::numeric_limits<i16>::min(); + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i16_Max) { + i16 n = std::numeric_limits<i16>::max(); + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i16_MinPlus1) { + i16 n = std::numeric_limits<i16>::min() + 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i16_MaxMinus1) { + i16 n = std::numeric_limits<i16>::max() - 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } +} + +Y_UNIT_TEST_SUITE(i128_And_i32_BitwiseIdentity) { + Y_UNIT_TEST(i128_from_i32_Zero) { + i32 n = 0; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i32_Minus1) { + i32 n = -1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i32_Plus1) { + i32 n = 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i32_Minus42) { + i32 n = -42; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i32_Plus42) { + i32 n = 42; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i32_Min) { + i32 n = std::numeric_limits<i32>::min(); + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i32_Max) { + i32 n = std::numeric_limits<i32>::max(); + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i32_MinPlus1) { + i32 n = std::numeric_limits<i32>::min() + 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i32_MaxMinus1) { + i32 n = std::numeric_limits<i32>::max() - 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } +} + +Y_UNIT_TEST_SUITE(i128_And_i64_BitwiseIdentity) { + Y_UNIT_TEST(i128_from_i64_Zero) { + i64 n = 0; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i64_Minus1) { + i64 n = -1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i64_Plus1) { + i64 n = 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i64_Minus42) { + i64 n = -42; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i64_Plus42) { + i64 n = 42; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i64_Min) { + i64 n = std::numeric_limits<i64>::min(); + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i64_Max) { + i64 n = std::numeric_limits<i64>::max(); + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i64_MinPlus1) { + i64 n = std::numeric_limits<i64>::min() + 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_i64_MaxMinus1) { + i64 n = std::numeric_limits<i64>::max() - 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } +} + +Y_UNIT_TEST_SUITE(i128_And_signed_int128_BitwiseIdentity) { + Y_UNIT_TEST(i128_from_signed_int128_Zero) { + signed __int128 n = 0; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_signed_int128_Minus1) { + signed __int128 n = -1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_signed_int128_Plus1) { + signed __int128 n = 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_signed_int128_Minus42) { + signed __int128 n = -42; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_signed_int128_Plus42) { + signed __int128 n = 42; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_signed_int128_Min) { + signed __int128 n = std::numeric_limits<signed __int128>::min(); + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_signed_int128_Max) { + signed __int128 n = std::numeric_limits<signed __int128>::max(); + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_signed_int128_MinPlus1) { + signed __int128 n = std::numeric_limits<signed __int128>::min() + 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_signed_int128_MaxMinus1) { + signed __int128 n = std::numeric_limits<signed __int128>::max() - 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } +} + +Y_UNIT_TEST_SUITE(i128_And_ui8_BitwiseIdentity) { + Y_UNIT_TEST(i128_from_ui8_Zero) { + ui8 n = 0; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_ui8_Plus1) { + ui8 n = 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_ui8_Plus42) { + ui8 n = 42; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_ui8_Min) { + ui8 n = std::numeric_limits<i8>::min(); + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_ui8_Max) { + ui8 n = std::numeric_limits<i8>::max(); + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_ui8_MinPlus1) { + ui8 n = std::numeric_limits<i8>::min() + 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_ui8_MaxMinus1) { + ui8 n = std::numeric_limits<i8>::max() - 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } +} + +Y_UNIT_TEST_SUITE(i128_And_ui16_BitwiseIdentity) { + Y_UNIT_TEST(i128_from_ui16_Zero) { + ui16 n = 0; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_ui16_Plus1) { + ui16 n = 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_ui16_Plus42) { + ui16 n = 42; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_ui16_Min) { + ui16 n = std::numeric_limits<i8>::min(); + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_ui16_Max) { + ui16 n = std::numeric_limits<i8>::max(); + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_ui16_MinPlus1) { + ui16 n = std::numeric_limits<i8>::min() + 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_ui16_MaxMinus1) { + ui16 n = std::numeric_limits<i8>::max() - 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } +} + +Y_UNIT_TEST_SUITE(i128_And_ui32_BitwiseIdentity) { + Y_UNIT_TEST(i128_from_ui32_Zero) { + ui32 n = 0; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_ui32_Plus1) { + ui32 n = 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_ui32_Plus42) { + ui32 n = 42; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_ui32_Min) { + ui32 n = std::numeric_limits<i8>::min(); + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_ui32_Max) { + ui32 n = std::numeric_limits<i8>::max(); + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_ui32_MinPlus1) { + ui32 n = std::numeric_limits<i8>::min() + 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_ui32_MaxMinus1) { + ui32 n = std::numeric_limits<i8>::max() - 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } +} + +Y_UNIT_TEST_SUITE(i128_And_ui64_BitwiseIdentity) { + Y_UNIT_TEST(i128_from_ui64_Zero) { + ui64 n = 0; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_ui64_Plus1) { + ui64 n = 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_ui64_Plus42) { + ui64 n = 42; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_ui64_Min) { + ui64 n = std::numeric_limits<i8>::min(); + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_ui64_Max) { + ui64 n = std::numeric_limits<i8>::max(); + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_ui64_MinPlus1) { + ui64 n = std::numeric_limits<i8>::min() + 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_ui64_MaxMinus1) { + ui64 n = std::numeric_limits<i8>::max() - 1; + i128 t1{n}; + signed __int128 t2{n}; + UNIT_ASSERT(IsIdentical(t1, t2)); + } +} + +Y_UNIT_TEST_SUITE(i128_And_unsigned_int128_BitwiseIdentity) { + Y_UNIT_TEST(i128_from_unsigned_int128_Zero) { + unsigned __int128 n = 0; + i128 t1{n}; + signed __int128 t2 = static_cast<signed __int128>(n); + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_unsigned_int128_Plus1) { + unsigned __int128 n = 1; + i128 t1{n}; + signed __int128 t2 = static_cast<signed __int128>(n); + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_unsigned_int128_Plus42) { + unsigned __int128 n = 42; + i128 t1{n}; + signed __int128 t2 = static_cast<signed __int128>(n); + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_unsigned_int128_Min) { + unsigned __int128 n = std::numeric_limits<i8>::min(); + i128 t1{n}; + signed __int128 t2 = static_cast<signed __int128>(n); + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_unsigned_int128_Max) { + unsigned __int128 n = std::numeric_limits<i8>::max(); + i128 t1{n}; + signed __int128 t2 = static_cast<signed __int128>(n); + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_unsigned_int128_MinPlus1) { + unsigned __int128 n = std::numeric_limits<i8>::min() + 1; + i128 t1{n}; + signed __int128 t2 = static_cast<signed __int128>(n); + UNIT_ASSERT(IsIdentical(t1, t2)); + } + + Y_UNIT_TEST(i128_from_unsigned_int128_MaxMinus1) { + unsigned __int128 n = std::numeric_limits<i8>::max() - 1; + i128 t1{n}; + signed __int128 t2 = static_cast<signed __int128>(n); + UNIT_ASSERT(IsIdentical(t1, t2)); + } +} +#endif diff --git a/library/cpp/int128/ut/i128_comparison_ut.cpp b/library/cpp/int128/ut/i128_comparison_ut.cpp new file mode 100644 index 0000000000..7b8d508815 --- /dev/null +++ b/library/cpp/int128/ut/i128_comparison_ut.cpp @@ -0,0 +1,145 @@ +#include <library/cpp/testing/unittest/registar.h> + +#include <library/cpp/int128/int128.h> + +#include <util/generic/cast.h> + +Y_UNIT_TEST_SUITE(I128ComparisonPositiveWithPositiveSuite) { + Y_UNIT_TEST(PositivePositiveGreater) { + UNIT_ASSERT(i128{1} > i128{0}); + UNIT_ASSERT(i128{2} > i128{1}); + UNIT_ASSERT(i128{42} > i128{0}); + UNIT_ASSERT(i128{42} > i128{1}); + i128 big = i128{1, 0}; + UNIT_ASSERT(big > i128{1}); + UNIT_ASSERT(std::numeric_limits<i128>::max() > i128{0}); + } + + Y_UNIT_TEST(PositivePositiveGreaterOrEqual) { + UNIT_ASSERT(i128{1} >= i128{0}); + UNIT_ASSERT(i128{2} >= i128{1}); + UNIT_ASSERT(i128{42} >= i128{0}); + UNIT_ASSERT(i128{42} >= i128{1}); + i128 big = i128{1, 0}; + UNIT_ASSERT(big >= i128{1}); + UNIT_ASSERT(std::numeric_limits<i128>::max() >= i128{0}); + + UNIT_ASSERT(i128{0} >= i128{0}); + UNIT_ASSERT(i128{1} >= i128{1}); + UNIT_ASSERT(i128{2} >= i128{2}); + UNIT_ASSERT(i128{42} >= i128{42}); + UNIT_ASSERT(big >= big); + UNIT_ASSERT(std::numeric_limits<i128>::max() >= std::numeric_limits<i128>::max()); + } + + Y_UNIT_TEST(PositivePositiveLess) { + UNIT_ASSERT(i128{0} < i128{1}); + UNIT_ASSERT(i128{1} < i128{2}); + UNIT_ASSERT(i128{0} < i128{42}); + UNIT_ASSERT(i128{1} < i128{42}); + i128 big = i128{1, 0}; + UNIT_ASSERT(i128{1} < big); + UNIT_ASSERT(i128{0} < std::numeric_limits<i128>::max()); + } + + Y_UNIT_TEST(PositivePositiveLessOrEqual) { + UNIT_ASSERT(i128{0} <= i128{1}); + UNIT_ASSERT(i128{1} <= i128{2}); + UNIT_ASSERT(i128{0} <= i128{42}); + UNIT_ASSERT(i128{1} <= i128{42}); + i128 big = i128{1, 0}; + UNIT_ASSERT(i128{1} <= big); + UNIT_ASSERT(i128{0} <= std::numeric_limits<i128>::max()); + + UNIT_ASSERT(i128{0} <= i128{0}); + UNIT_ASSERT(i128{1} <= i128{1}); + UNIT_ASSERT(i128{2} <= i128{2}); + UNIT_ASSERT(i128{42} <= i128{42}); + UNIT_ASSERT(big <= big); + UNIT_ASSERT(std::numeric_limits<i128>::max() <= std::numeric_limits<i128>::max()); + } +} + +Y_UNIT_TEST_SUITE(I128ComparisonPositiveWithNegativeSuite) { + Y_UNIT_TEST(PositiveNegativeGreater) { + UNIT_ASSERT(i128{0} > i128{-1}); + UNIT_ASSERT(i128{2} > i128{-1}); + UNIT_ASSERT(i128{0} > i128{-42}); + UNIT_ASSERT(i128{42} > i128{-1}); + i128 big = i128{1, 0}; + UNIT_ASSERT(big > i128{-1}); + UNIT_ASSERT(std::numeric_limits<i128>::max() > i128{-1}); + } + + Y_UNIT_TEST(PositiveNegativeGreaterOrEqual) { + UNIT_ASSERT(i128{0} >= i128{-1}); + UNIT_ASSERT(i128{2} >= i128{-1}); + UNIT_ASSERT(i128{0} >= i128{-42}); + UNIT_ASSERT(i128{42} >= i128{-1}); + i128 big = i128{1, 0}; + UNIT_ASSERT(big >= i128{-1}); + UNIT_ASSERT(std::numeric_limits<i128>::max() >= i128{-1}); + } + + Y_UNIT_TEST(NegativePositiveLess) { + UNIT_ASSERT(i128{-1} < i128{0}); + UNIT_ASSERT(i128{-1} < i128{2}); + UNIT_ASSERT(i128{-42} < i128{0}); + UNIT_ASSERT(i128{-1} < i128{42}); + i128 big = i128{1, 0}; + UNIT_ASSERT(i128{-1} < big); + UNIT_ASSERT(i128{-1} < std::numeric_limits<i128>::max()); + } + + Y_UNIT_TEST(NegativePositiveLessOrEqual) { + UNIT_ASSERT(i128{-1} <= i128{0}); + UNIT_ASSERT(i128{-1} <= i128{2}); + UNIT_ASSERT(i128{-42} <= i128{0}); + UNIT_ASSERT(i128{-1} <= i128{42}); + i128 big = i128{1, 0}; + UNIT_ASSERT(i128{-1} <= big); + UNIT_ASSERT(i128{-1} <= std::numeric_limits<i128>::max()); + } +} + +Y_UNIT_TEST_SUITE(I128ComparisonNegativeWithNegativeSuite) { + Y_UNIT_TEST(NegativeNegativeGreater) { + UNIT_ASSERT(i128{-1} > i128{-2}); + UNIT_ASSERT(i128{-2} > i128{-3}); + UNIT_ASSERT(i128{-1} > i128{-42}); + UNIT_ASSERT(i128{-42} > i128{-142}); + i128 big = -i128{1, 0}; + UNIT_ASSERT(i128{-1} > big); + UNIT_ASSERT(i128{-1} > std::numeric_limits<i128>::min()); + } + + Y_UNIT_TEST(NegativeNegativeGreaterOrEqual) { + UNIT_ASSERT(i128{-1} >= i128{-2}); + UNIT_ASSERT(i128{-2} >= i128{-3}); + UNIT_ASSERT(i128{-1} >= i128{-42}); + UNIT_ASSERT(i128{-42} >= i128{-142}); + i128 big = -i128{1, 0}; + UNIT_ASSERT(i128{-1} >= big); + UNIT_ASSERT(i128{-1} >= std::numeric_limits<i128>::min()); + } + + Y_UNIT_TEST(NegativeNegativeLess) { + UNIT_ASSERT(i128{-2} < i128{-1}); + UNIT_ASSERT(i128{-3} < i128{-2}); + UNIT_ASSERT(i128{-42} < i128{-1}); + UNIT_ASSERT(i128{-142} < i128{42}); + i128 big = -i128{1, 0}; + UNIT_ASSERT(big < i128{-1}); + UNIT_ASSERT(std::numeric_limits<i128>::min() < i128{-1}); + } + + Y_UNIT_TEST(NegativeNegativeLessOrEqual) { + UNIT_ASSERT(i128{-2} <= i128{-1}); + UNIT_ASSERT(i128{-3} <= i128{-2}); + UNIT_ASSERT(i128{-42} <= i128{-1}); + UNIT_ASSERT(i128{-142} <= i128{42}); + i128 big = -i128{1, 0}; + UNIT_ASSERT(big <= i128{-1}); + UNIT_ASSERT(std::numeric_limits<i128>::min() <= i128{-1}); + } +} diff --git a/library/cpp/int128/ut/i128_division_ut.cpp b/library/cpp/int128/ut/i128_division_ut.cpp new file mode 100644 index 0000000000..46b0ca27f5 --- /dev/null +++ b/library/cpp/int128/ut/i128_division_ut.cpp @@ -0,0 +1,413 @@ +#include <library/cpp/testing/unittest/registar.h> + +#include <library/cpp/int128/int128.h> + +#include <util/generic/cast.h> + +Y_UNIT_TEST_SUITE(I128DivisionBy1Suite) { + Y_UNIT_TEST(I128Divide0By1) { + i128 dividend = 0; + i128 divider = 1; + i128 expectedQuotient = 0; + i128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(I128Divide1By1) { + i128 dividend = 1; + i128 divider = 1; + i128 expectedQuotient = 1; + i128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(I128Divide2By1) { + i128 dividend = 2; + i128 divider = 1; + i128 expectedQuotient = 2; + i128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(I128Divide42By1) { + i128 dividend = 42; + i128 divider = 1; + i128 expectedQuotient = 42; + i128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(I128DivideMaxUi64By1) { + i128 dividend = std::numeric_limits<ui64>::max(); + i128 divider = 1; + i128 expectedQuotient = std::numeric_limits<ui64>::max(); + i128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(I128DivideMaxUi64Plus1By1) { + i128 dividend = i128{std::numeric_limits<ui64>::max()} + i128{1}; + i128 divider = 1; + i128 expectedQuotient = i128{std::numeric_limits<ui64>::max()} + i128{1}; + i128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(I128DivideMaxUi64Plus42By1) { + i128 dividend = i128{std::numeric_limits<ui64>::max()} + i128{42}; + i128 divider = 1; + i128 expectedQuotient = i128{std::numeric_limits<ui64>::max()} + i128{42}; + i128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(I128DivideMaxI128By1) { + i128 dividend = std::numeric_limits<i128>::max(); + i128 divider = 1; + i128 expectedQuotient = std::numeric_limits<i128>::max(); + i128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(I128DivideMaxI128Minus1By1) { + i128 dividend = std::numeric_limits<i128>::max() - 1; + i128 divider = 1; + i128 expectedQuotient = std::numeric_limits<i128>::max() - 1; + i128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } +} + +Y_UNIT_TEST_SUITE(I128DivisionByEqualSuite) { + Y_UNIT_TEST(I128Divide1ByEqual) { + i128 dividend = 1; + i128 divider = dividend; + i128 expectedQuotient = 1; + i128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(I128Divide2ByEqual) { + i128 dividend = 2; + i128 divider = dividend; + i128 expectedQuotient = 1; + i128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(I128Divide42ByEqual) { + i128 dividend = 42; + i128 divider = dividend; + i128 expectedQuotient = 1; + i128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(I128DivideMaxUi64ByEqual) { + i128 dividend = std::numeric_limits<ui64>::max(); + i128 divider = dividend; + i128 expectedQuotient = 1; + i128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(I128DivideMaxUi64Plus1ByEqual) { + i128 dividend = i128{std::numeric_limits<ui64>::max()} + i128{1}; + i128 divider = dividend; + i128 expectedQuotient = 1; + i128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(I128DivideMaxUi64Plus42ByEqual) { + i128 dividend = i128{std::numeric_limits<ui64>::max()} + i128{42}; + i128 divider = dividend; + i128 expectedQuotient = 1; + i128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(I128DivideMaxI128ByEqual) { + i128 dividend = std::numeric_limits<i128>::max(); + i128 divider = dividend; + i128 expectedQuotient = 1; + i128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(I128DivideMaxI128Minus1ByEqual) { + i128 dividend = std::numeric_limits<i128>::max() - 1; + i128 divider = dividend; + i128 expectedQuotient = 1; + i128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } +} + +Y_UNIT_TEST_SUITE(I128DivisionLessByHigherSuite) { + Y_UNIT_TEST(I128Divide42By84) { + i128 dividend = 42; + i128 divider = 84; + i128 expectedQuotient = 0; + i128 expectedRemainder = 42; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(I128Divide42ByMaxUi64) { + i128 dividend = 42; + i128 divider = std::numeric_limits<ui64>::max(); + i128 expectedQuotient = 0; + i128 expectedRemainder = 42; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(I128Divide42ByMaxUi64Plus1) { + i128 dividend = 42; + i128 divider = i128{std::numeric_limits<ui64>::max()} + i128{1}; + i128 expectedQuotient = 0; + i128 expectedRemainder = 42; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(I128DivideMaxUi64ByMaxUi64Plus1) { + i128 dividend = i128{std::numeric_limits<ui64>::max()}; + i128 divider = i128{std::numeric_limits<ui64>::max()} + i128{1}; + i128 expectedQuotient = 0; + i128 expectedRemainder = i128{std::numeric_limits<ui64>::max()}; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } +} + +Y_UNIT_TEST_SUITE(I128DivisionWithDifferentSigns) { + Y_UNIT_TEST(DivisionPositiveByNegative) { + i128 dividend = i128{100}; + i128 divider = i128{-33}; + i128 expectedQuotient = -3; + i128 expectedRemainder = 1; + i128 quotient = dividend / divider; + i128 remainder = dividend % divider; + + UNIT_ASSERT_EQUAL(quotient, expectedQuotient); + UNIT_ASSERT_EQUAL(remainder, expectedRemainder); + } + + Y_UNIT_TEST(DivisionNegativeByPositive) { + i128 dividend = i128{-100}; + i128 divider = i128{33}; + i128 expectedQuotient = -3; + i128 expectedRemainder = -1; + i128 quotient = dividend / divider; + i128 remainder = dividend % divider; + + UNIT_ASSERT_EQUAL(quotient, expectedQuotient); + UNIT_ASSERT_EQUAL(remainder, expectedRemainder); + } + + Y_UNIT_TEST(DivisionNegativeByNegative) { + i128 dividend = i128{-100}; + i128 divider = i128{-33}; + i128 expectedQuotient = 3; + i128 expectedRemainder = -1; + i128 quotient = dividend / divider; + i128 remainder = dividend % divider; + + UNIT_ASSERT_EQUAL(quotient, expectedQuotient); + UNIT_ASSERT_EQUAL(remainder, expectedRemainder); + } +} + +Y_UNIT_TEST_SUITE(i128DivisionBigByBigSuite) { + Y_UNIT_TEST(i128DivideBigByBig1) { + i128 dividend = {64, 0}; + i128 divider = {1, 0}; + i128 expectedQuotient = 64; + i128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(i128DivideBigByBig1_PosByNeg) { + i128 dividend = i128{64, 0}; + i128 divider = -i128{1, 0}; + i128 expectedQuotient = -i128{64}; + i128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(i128DivideBigByBig1_NegByPos) { + i128 dividend = -i128{64, 0}; + i128 divider = i128{1, 0}; + i128 expectedQuotient = -i128{64}; + i128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(i128DivideBigByBig1_NegByNeg) { + i128 dividend = -i128{64, 0}; + i128 divider = -i128{1, 0}; + i128 expectedQuotient = i128{64}; + i128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(i128DivideBigByBig2) { + i128 dividend = {64, 0}; + i128 divider = {12, 5}; + i128 expectedQuotient = 5; + i128 expectedRemainder = i128{3, 18446744073709551591ull}; // plz don't ask + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(i128DivideBigByBig2_PosByNeg) { + i128 dividend = i128{64, 0}; + i128 divider = -i128{12, 5}; + i128 expectedQuotient = -5; + i128 expectedRemainder = i128{3, 18446744073709551591ull}; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(i128DivideBigByBig2_NegByPos) { + i128 dividend = -i128{64, 0}; + i128 divider = i128{12, 5}; + i128 expectedQuotient = -5; + i128 expectedRemainder = -i128{3, 18446744073709551591ull}; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(i128DivideBigByBig2_NegByNeg) { + i128 dividend = -i128{64, 0}; + i128 divider = -i128{12, 5}; + i128 expectedQuotient = 5; + i128 expectedRemainder = -i128{3, 18446744073709551591ull}; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + +} + +Y_UNIT_TEST_SUITE(i128DivisionAlgo) { + Y_UNIT_TEST(ii128DivideAlgoCheck_PosByPos) { + /* + 49672666804009505000000 / 10000000 == 4967266680400950 + 49672666804009505000000 % 10000000 == 5000000 + */ + i128 dividend = {2692ull, 14031757583392049728ull}; + i64 divider = 10000000; + i128 expectedQuotient = {0, 4967266680400950ull}; + i128 expectedRemainder = {0, 5000000ull}; + + i128 quotient = dividend / divider; + i128 reminder = dividend % divider; + + UNIT_ASSERT_EQUAL(quotient, expectedQuotient); + UNIT_ASSERT_EQUAL(reminder, expectedRemainder); + } + + Y_UNIT_TEST(ii128DivideAlgoCheck_PosByNeg) { + /* + 49672666804009505000000 / -10000000 == -4967266680400950 + 49672666804009505000000 % -10000000 == 5000000 + */ + i128 dividend = {2692ull, 14031757583392049728ull}; + i64 divider = -10000000; + i128 expectedQuotient = -i128{0, 4967266680400950ull}; + i128 expectedRemainder = {0, 5000000ull}; + + i128 quotient = dividend / divider; + i128 reminder = dividend % divider; + + UNIT_ASSERT_EQUAL(quotient, expectedQuotient); + UNIT_ASSERT_EQUAL(reminder, expectedRemainder); + } + + Y_UNIT_TEST(ii128DivideAlgoCheck_NegByPos) { + /* + -49672666804009505000000 / 10000000 == -4967266680400950 + -49672666804009505000000 % 10000000 == -5000000 + */ + i128 dividend = -i128{2692ull, 14031757583392049728ull}; + i64 divider = 10000000; + i128 expectedQuotient = -i128{0, 4967266680400950ull}; + i128 expectedRemainder = -i128{0, 5000000ull}; + + i128 quotient = dividend / divider; + i128 reminder = dividend % divider; + + UNIT_ASSERT_EQUAL(quotient, expectedQuotient); + UNIT_ASSERT_EQUAL(reminder, expectedRemainder); + } + + Y_UNIT_TEST(ii128DivideAlgoCheck_NegByNeg) { + /* + -49672666804009505000000 / -10000000 == 4967266680400950 + -49672666804009505000000 % -10000000 == -5000000 + */ + i128 dividend = -i128{2692ull, 14031757583392049728ull}; + i64 divider = -10000000; + i128 expectedQuotient = {0, 4967266680400950ull}; + i128 expectedRemainder = -i128{0, 5000000ull}; + + i128 quotient = dividend / divider; + i128 reminder = dividend % divider; + + UNIT_ASSERT_EQUAL(quotient, expectedQuotient); + UNIT_ASSERT_EQUAL(reminder, expectedRemainder); + } + +} diff --git a/library/cpp/int128/ut/i128_type_traits_ut.cpp b/library/cpp/int128/ut/i128_type_traits_ut.cpp new file mode 100644 index 0000000000..4ed87bf229 --- /dev/null +++ b/library/cpp/int128/ut/i128_type_traits_ut.cpp @@ -0,0 +1,68 @@ +#include <library/cpp/testing/unittest/registar.h> + +#include <library/cpp/int128/int128.h> + +#include <util/generic/cast.h> + +Y_UNIT_TEST_SUITE(I128TypeTraitsSuite) { + Y_UNIT_TEST(OperatorNegate0) { + const i128 n = 0; + const i128 m = -n; + UNIT_ASSERT(n == m); + } + + Y_UNIT_TEST(OperatorNegate1) { + const i128 n = 1; + const i128 m = -n; + const i128 expected = -1; + UNIT_ASSERT(m == expected); + } + + Y_UNIT_TEST(OperatorNegate2Pow64) { + const i128 n = i128{1, 0}; + const i128 m = -n; + const i128 expected = {static_cast<ui64>(-1), 0}; + UNIT_ASSERT(m == expected); + } + + Y_UNIT_TEST(OperatorNegateNegate) { + const i128 x = 1; + const i128 y = -x; + const i128 z = -y; + UNIT_ASSERT(z == x); + } + + Y_UNIT_TEST(AbsFromPositive) { + const i128 n = 1; + const i128 m = std::abs(n); + UNIT_ASSERT(m == n); + } + + Y_UNIT_TEST(AbsFromNegative) { + const i128 n = -1; + const i128 m = std::abs(n); + const i128 expected = 1; + UNIT_ASSERT(m == expected); + } + + Y_UNIT_TEST(AbsFromZero) { + const i128 n = 0; + const i128 m = std::abs(n); + UNIT_ASSERT(m == n); + } + + Y_UNIT_TEST(SignbitOfPositive) { + const i128 n = 1; + UNIT_ASSERT(!std::signbit(n)); + } + + Y_UNIT_TEST(SignbitOfNegative) { + const i128 n = -1; + UNIT_ASSERT(std::signbit(n)); + } + + Y_UNIT_TEST(SignbitOfZero) { + const i128 n = 0; + UNIT_ASSERT(!std::signbit(n)); + } +} diff --git a/library/cpp/int128/ut/i128_ut.cpp b/library/cpp/int128/ut/i128_ut.cpp new file mode 100644 index 0000000000..c196d132a2 --- /dev/null +++ b/library/cpp/int128/ut/i128_ut.cpp @@ -0,0 +1,12 @@ +#include <library/cpp/testing/unittest/registar.h> + +#include <library/cpp/int128/int128.h> + +#include <util/generic/cast.h> + +Y_UNIT_TEST_SUITE(I128Suite) { + Y_UNIT_TEST(CreateI128FromUnsigned) { + i128 v{ui64(1)}; + Y_UNUSED(v); + } +} diff --git a/library/cpp/int128/ut/int128_old_ut.cpp b/library/cpp/int128/ut/int128_old_ut.cpp new file mode 100644 index 0000000000..2c5b9e9610 --- /dev/null +++ b/library/cpp/int128/ut/int128_old_ut.cpp @@ -0,0 +1,179 @@ +#include <library/cpp/testing/unittest/registar.h> +#include <library/cpp/int128/int128.h> + +#include "int128_ut_helpers.h" + +class TUInt128Test: public TTestBase { + UNIT_TEST_SUITE(TUInt128Test); + UNIT_TEST(Create); + UNIT_TEST(Minus); + UNIT_TEST(Plus); + UNIT_TEST(Shift) + UNIT_TEST(Overflow); + UNIT_TEST(Underflow); + UNIT_TEST(ToStringTest); + UNIT_TEST(FromStringTest); +#if defined(Y_HAVE_INT128) + UNIT_TEST(FromSystemUint128); +#endif + UNIT_TEST_SUITE_END(); + +private: + void Create(); + void Minus(); + void Plus(); + void Shift(); + void Overflow(); + void Underflow(); + void ToStringTest(); + void FromStringTest(); +#if defined(Y_HAVE_INT128) + void FromSystemUint128(); +#endif +}; + +UNIT_TEST_SUITE_REGISTRATION(TUInt128Test); + +void TUInt128Test::Create() { + const ui128 n1 = 10; + UNIT_ASSERT_EQUAL(n1, 10); + + const ui128 n2 = n1; + UNIT_ASSERT_EQUAL(n2, 10); + + const ui128 n3(10); + UNIT_ASSERT_EQUAL(n3, 10); +} +void TUInt128Test::Minus() { + const ui128 n2 = 20; + const ui128 n3 = 30; + + ui128 n4 = n3 - n2; + UNIT_ASSERT_EQUAL(n4, 10); + + n4 = n4 - 2; + UNIT_ASSERT_EQUAL(n4, 8); + + n4 -= 2; + UNIT_ASSERT_EQUAL(n4, 6); + + n4 = 10 - n4; + UNIT_ASSERT_EQUAL(n4, 4); +} +void TUInt128Test::Plus() { + const ui128 n2 = 20; + const ui128 n3 = 30; + + ui128 n4 = n3 + n2; + UNIT_ASSERT_EQUAL(n4, 50); + + n4 = n4 + 2; + UNIT_ASSERT_EQUAL(n4, 52); + + n4 += 2; + UNIT_ASSERT_EQUAL(n4, 54); + + n4 = 10 + n4; + UNIT_ASSERT_EQUAL(n4, 64); +} +void TUInt128Test::Shift() { + ui128 n = 1; + + const ui128 n4 = n << 4; + UNIT_ASSERT_EQUAL(n4, ui128(0x0, 0x0000000000000010)); + UNIT_ASSERT_EQUAL(n4 >> 4, 1); + + const ui128 n8 = n << 8; + UNIT_ASSERT_EQUAL(n8, ui128(0x0, 0x0000000000000100)); + UNIT_ASSERT_EQUAL(n8 >> 8, 1); + + const ui128 n60 = n << 60; + UNIT_ASSERT_EQUAL(n60, ui128(0x0, 0x1000000000000000)); + UNIT_ASSERT_EQUAL(n60 >> 60, 1); + + const ui128 n64 = n << 64; + UNIT_ASSERT_EQUAL(n64, ui128(0x1, 0x0000000000000000)); + UNIT_ASSERT_EQUAL(n64 >> 64, 1); + + const ui128 n124 = n << 124; + UNIT_ASSERT_EQUAL(n124, ui128(0x1000000000000000, 0x0000000000000000)); + UNIT_ASSERT_EQUAL(n124 >> 124, 1); +} + +void TUInt128Test::Overflow() { + ui128 n = ui128(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF); + const ui128 n2 = n + 2; + UNIT_ASSERT_EQUAL(n2, 1); +} +void TUInt128Test::Underflow() { + ui128 n = 1; + const ui128 n128 = n - 2; + UNIT_ASSERT_EQUAL(n128, ui128(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF)); +} + +void TUInt128Test::ToStringTest() { + ui128 n(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF); + TString correct = "340282366920938463463374607431768211455"; + UNIT_ASSERT_EQUAL(correct, ::ToString(n)); +} + +void TUInt128Test::FromStringTest() { + { + const TString originalString = "37778931862957161709568"; + const ui128 number = FromString<ui128>(originalString); + UNIT_ASSERT_EQUAL(ToString(number), originalString); + } + + { + const TString originalString = "1024"; + const ui128 number = FromString<ui128>(originalString); + UNIT_ASSERT_EQUAL(ToString(number), originalString); + UNIT_ASSERT_EQUAL(GetHigh(number), 0); + UNIT_ASSERT_EQUAL(GetLow(number), 1024); + } + + { + const TString originalString = "18446744073709551616"; // 2^64, i.e. UINT64_MAX + 1 + const ui128 number = FromString<ui128>(originalString); + UNIT_ASSERT_EQUAL(ToString(number), originalString); + UNIT_ASSERT_EQUAL(GetHigh(number), 1); + UNIT_ASSERT_EQUAL(GetLow(number), 0); + } + + { + const TString originalString = "340282366920938463463374607431768211455"; // 2^128-1, i.e. UINT128_MAX + const ui128 number = FromString<ui128>(originalString); + UNIT_ASSERT_EQUAL(ToString(number), originalString); + UNIT_ASSERT_EQUAL(GetHigh(number), 0xFFFFFFFFFFFFFFFF); + UNIT_ASSERT_EQUAL(GetLow(number), 0xFFFFFFFFFFFFFFFF); + } +} + +#if defined(Y_HAVE_INT128) +void TUInt128Test::FromSystemUint128() { + unsigned __int128 n = 1; + ui128 number{n}; + + UNIT_ASSERT_EQUAL(GetLow(number), 1); + UNIT_ASSERT_EQUAL(GetHigh(number), 0); + + auto byteArray = NInt128Private::GetAsArray(number); +#ifdef _little_endian_ + UNIT_ASSERT_EQUAL(byteArray[0], 1); + for (size_t i = 1; i < 16; i++) { + UNIT_ASSERT_EQUAL(byteArray[i], 0); + } +#elif defined(_big_endian_) + UNIT_ASSERT_EQUAL(byteArray[15], 1); + for (size_t i = 0; i < 15; i++) { + UNIT_ASSERT_EQUAL(byteArray[i], 0); + } +#endif + + UNIT_ASSERT_EQUAL(std::memcmp((void*)&n, (void*)&number, 16), 0); + + UNIT_ASSERT_EQUAL(ToString(n), "1"); + + UNIT_ASSERT_EQUAL(FromString<unsigned __int128>(ToString(n)), n); +} +#endif diff --git a/library/cpp/int128/ut/int128_typetraits_ut.cpp b/library/cpp/int128/ut/int128_typetraits_ut.cpp new file mode 100644 index 0000000000..fd5f19d7b8 --- /dev/null +++ b/library/cpp/int128/ut/int128_typetraits_ut.cpp @@ -0,0 +1,306 @@ +#include <library/cpp/testing/unittest/registar.h> + +#include <library/cpp/int128/int128.h> + +#include <type_traits> + +Y_UNIT_TEST_SUITE(TypeTraitsSuite) { + Y_UNIT_TEST(Uint128TypeTraits) { + // checks that all type traits of ui128 are the same as of ui64 + // https://en.cppreference.com/w/cpp/header/type_traits + UNIT_ASSERT_EQUAL( + std::is_void<ui128>::value, + std::is_void<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_null_pointer<ui128>::value, + std::is_null_pointer<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_integral<ui128>::value, + std::is_integral<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_floating_point<ui128>::value, + std::is_floating_point<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_array<ui128>::value, + std::is_array<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_enum<ui128>::value, + std::is_enum<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_union<ui128>::value, + std::is_union<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_class<ui128>::value, + std::is_class<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_function<ui128>::value, + std::is_function<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_pointer<ui128>::value, + std::is_pointer<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_lvalue_reference<ui128>::value, + std::is_lvalue_reference<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_rvalue_reference<ui128>::value, + std::is_rvalue_reference<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_member_object_pointer<ui128>::value, + std::is_member_object_pointer<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_member_function_pointer<ui128>::value, + std::is_member_function_pointer<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_fundamental<ui128>::value, + std::is_fundamental<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_arithmetic<ui128>::value, + std::is_arithmetic<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_scalar<ui128>::value, + std::is_scalar<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_object<ui128>::value, + std::is_object<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_compound<ui128>::value, + std::is_compound<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_reference<ui128>::value, + std::is_reference<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_member_pointer<ui128>::value, + std::is_member_pointer<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_const<ui128>::value, + std::is_const<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_volatile<ui128>::value, + std::is_volatile<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_trivial<ui128>::value, + std::is_trivial<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_standard_layout<ui128>::value, + std::is_standard_layout<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_pod<ui128>::value, + std::is_pod<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_literal_type<ui128>::value, + std::is_literal_type<ui64>::value + ); +#ifndef _MSC_VER + UNIT_ASSERT_EQUAL( + std::has_unique_object_representations<ui128>::value, + std::has_unique_object_representations<ui64>::value + ); +#endif + UNIT_ASSERT_EQUAL( + std::is_empty<ui128>::value, + std::is_empty<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_polymorphic<ui128>::value, + std::is_polymorphic<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_abstract<ui128>::value, + std::is_abstract<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_final<ui128>::value, + std::is_final<ui64>::value + ); +#ifndef _MSC_VER + UNIT_ASSERT_EQUAL( + std::is_aggregate<ui128>::value, + std::is_aggregate<ui64>::value + ); +#endif + UNIT_ASSERT_EQUAL( + std::is_signed<ui128>::value, + std::is_signed<ui64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_unsigned<ui128>::value, + std::is_unsigned<ui64>::value + ); + } + + Y_UNIT_TEST(Int128TypeTraits) { + // checks that all type traits of i128 are the same as of i64 + // https://en.cppreference.com/w/cpp/header/type_traits + UNIT_ASSERT_EQUAL( + std::is_void<i128>::value, + std::is_void<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_null_pointer<i128>::value, + std::is_null_pointer<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_integral<i128>::value, + std::is_integral<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_floating_point<i128>::value, + std::is_floating_point<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_array<i128>::value, + std::is_array<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_enum<i128>::value, + std::is_enum<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_union<i128>::value, + std::is_union<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_class<i128>::value, + std::is_class<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_function<i128>::value, + std::is_function<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_pointer<i128>::value, + std::is_pointer<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_lvalue_reference<i128>::value, + std::is_lvalue_reference<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_rvalue_reference<i128>::value, + std::is_rvalue_reference<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_member_object_pointer<i128>::value, + std::is_member_object_pointer<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_member_function_pointer<i128>::value, + std::is_member_function_pointer<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_fundamental<i128>::value, + std::is_fundamental<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_arithmetic<i128>::value, + std::is_arithmetic<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_scalar<i128>::value, + std::is_scalar<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_object<i128>::value, + std::is_object<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_compound<i128>::value, + std::is_compound<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_reference<i128>::value, + std::is_reference<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_member_pointer<i128>::value, + std::is_member_pointer<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_const<i128>::value, + std::is_const<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_volatile<i128>::value, + std::is_volatile<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_trivial<i128>::value, + std::is_trivial<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_standard_layout<i128>::value, + std::is_standard_layout<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_pod<i128>::value, + std::is_pod<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_literal_type<i128>::value, + std::is_literal_type<i64>::value + ); +#ifndef _MSC_VER + UNIT_ASSERT_EQUAL( + std::has_unique_object_representations<i128>::value, + std::has_unique_object_representations<i64>::value + ); +#endif + UNIT_ASSERT_EQUAL( + std::is_empty<i128>::value, + std::is_empty<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_polymorphic<i128>::value, + std::is_polymorphic<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_abstract<i128>::value, + std::is_abstract<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_final<i128>::value, + std::is_final<i64>::value + ); +#ifndef _MSC_VER + UNIT_ASSERT_EQUAL( + std::is_aggregate<i128>::value, + std::is_aggregate<i64>::value + ); +#endif + UNIT_ASSERT_EQUAL( + std::is_signed<i128>::value, + std::is_signed<i64>::value + ); + UNIT_ASSERT_EQUAL( + std::is_unsigned<i128>::value, + std::is_unsigned<i64>::value + ); + } +} + diff --git a/library/cpp/int128/ut/int128_ut.cpp b/library/cpp/int128/ut/int128_ut.cpp new file mode 100644 index 0000000000..7339264017 --- /dev/null +++ b/library/cpp/int128/ut/int128_ut.cpp @@ -0,0 +1,83 @@ +#include <library/cpp/testing/unittest/registar.h> + +#include <library/cpp/int128/int128.h> + +#include <util/generic/cast.h> + +#include <type_traits> + +Y_UNIT_TEST_SUITE(Uint128Suite) { + Y_UNIT_TEST(Uint128DefaultCtor) { + const ui128 value{}; + UNIT_ASSERT_EQUAL(GetLow(value), 0); + UNIT_ASSERT_EQUAL(GetHigh(value), 0); + } + + Y_UNIT_TEST(Uint128NumericLimits) { + UNIT_ASSERT_EQUAL(std::numeric_limits<ui128>::digits, 128); + UNIT_ASSERT_EQUAL(std::numeric_limits<ui128>::max() + 1, ui128{0}); + } + + Y_UNIT_TEST(Uint128Sizeof) { + UNIT_ASSERT_EQUAL(sizeof(ui128), sizeof(ui64) * 2); + } + + Y_UNIT_TEST(Uint128Cast) { + // see util/generic/cast.h + const auto underlyingTypeIsSelf = std::is_same<::NPrivate::TUnderlyingTypeOrSelf<ui128>, ui128>::value; + UNIT_ASSERT_EQUAL(underlyingTypeIsSelf, true); + + const auto convertibleUi128Ui128 = ::NPrivate::TSafelyConvertible<ui128, ui128>::Result; + const auto convertibleUi64Ui128 = ::NPrivate::TSafelyConvertible<ui64, ui128>::Result; + const auto convertibleUi128Ui64 = ::NPrivate::TSafelyConvertible<ui128, ui64>::Result; + UNIT_ASSERT_EQUAL(convertibleUi128Ui128, true); // from ui128 to ui128 => safe + UNIT_ASSERT_EQUAL(convertibleUi64Ui128, false); // from ui128 to ui64 => not safe + UNIT_ASSERT_EQUAL(convertibleUi128Ui64, true); // from ui64 to ui128 => safe + } + + Y_UNIT_TEST(SafeIntegerCastTest) { + ui128 narrowNumber = 1; + + UNIT_ASSERT_NO_EXCEPTION(SafeIntegerCast<ui64>(narrowNumber)); + + ui128 wideNumber{0}; + wideNumber -= 1; + UNIT_ASSERT_EXCEPTION(SafeIntegerCast<ui64>(wideNumber), yexception); + } + + Y_UNIT_TEST(SignbitTest) { + UNIT_ASSERT(!std::signbit(ui128{0})); + UNIT_ASSERT(!std::signbit(ui128{-1})); + UNIT_ASSERT(!std::signbit(i128{0})); + UNIT_ASSERT(std::signbit(i128{-1})); + } + + Y_UNIT_TEST(ToStringTest) { + // int128 + UNIT_ASSERT_VALUES_EQUAL(ToString(i128(0)), "0"); + UNIT_ASSERT_VALUES_EQUAL(ToString(i128(42)), "42"); + UNIT_ASSERT_VALUES_EQUAL(ToString(i128(-142)), "-142"); + UNIT_ASSERT_VALUES_EQUAL(ToString(std::numeric_limits<i128>::min()), "-170141183460469231731687303715884105728"); + UNIT_ASSERT_VALUES_EQUAL(ToString(std::numeric_limits<i128>::max()), "170141183460469231731687303715884105727"); + + // Just random number + UNIT_ASSERT_VALUES_EQUAL( + ToString( + - ((i128(8741349088318632894ul) << 64) | i128(1258331728153556511ul)) + ), + "-161249429491168133245752281683002013215"); + + // uint128 + UNIT_ASSERT_VALUES_EQUAL(ToString(ui128(0)), "0"); + UNIT_ASSERT_VALUES_EQUAL(ToString(ui128(42)), "42"); + UNIT_ASSERT_VALUES_EQUAL(ToString(std::numeric_limits<ui128>::min()), "0"); + UNIT_ASSERT_VALUES_EQUAL(ToString(std::numeric_limits<ui128>::max()), "340282366920938463463374607431768211455"); + + // Just random number + UNIT_ASSERT_VALUES_EQUAL( + ToString( + ((ui128(12745260439834612983ul) << 64) | ui128(10970669179777569799ul)) + ), + "235108557486403940296800289353599800327"); + } +} diff --git a/library/cpp/int128/ut/int128_ut_helpers.cpp b/library/cpp/int128/ut/int128_ut_helpers.cpp new file mode 100644 index 0000000000..e6c3e24d10 --- /dev/null +++ b/library/cpp/int128/ut/int128_ut_helpers.cpp @@ -0,0 +1,56 @@ +#include "int128_ut_helpers.h" + +namespace NInt128Private { +#if defined(_little_endian_) + std::array<ui8, 16> GetAsArray(const ui128 value) { + std::array<ui8, 16> result; + const ui64 low = GetLow(value); + const ui64 high = GetHigh(value); + MemCopy(result.data(), reinterpret_cast<const ui8*>(&low), sizeof(low)); + MemCopy(result.data() + sizeof(low), reinterpret_cast<const ui8*>(&high), sizeof(high)); + return result; + } + + std::array<ui8, 16> GetAsArray(const i128 value) { + std::array<ui8, 16> result; + const ui64 low = GetLow(value); + const ui64 high = GetHigh(value); + MemCopy(result.data(), reinterpret_cast<const ui8*>(&low), sizeof(low)); + MemCopy(result.data() + sizeof(low), reinterpret_cast<const ui8*>(&high), sizeof(high)); + return result; + } +#elif defined(_big_endian_) + std::array<ui8, 16> GetAsArray(const i128 value) { + std::array<ui8, 16> result; + const ui64 low = GetLow(value); + const ui64 high = GetHigh(value); + MemCopy(result.data(), reinterpret_cast<const ui8*>(&high), sizeof(high)); + MemCopy(result.data() + sizeof(high), reinterpret_cast<const ui8*>(&low), sizeof(low)); + return result; + } + + std::array<ui8, 16> GetAsArray(const ui128 value) { + std::array<ui8, 16> result; + const ui64 low = GetLow(value); + const ui64 high = GetHigh(value); + MemCopy(result.data(), reinterpret_cast<const ui8*>(&high), sizeof(high)); + MemCopy(result.data() + sizeof(high), reinterpret_cast<const ui8*>(&low), sizeof(low)); + return result; + } +#endif + +#if defined(Y_HAVE_INT128) + std::array<ui8, 16> GetAsArray(const unsigned __int128 value) { + std::array<ui8, 16> result; + MemCopy(result.data(), reinterpret_cast<const ui8*>(&value), sizeof(value)); + return result; + } + + std::array<ui8, 16> GetAsArray(const signed __int128 value) { + std::array<ui8, 16> result; + MemCopy(result.data(), reinterpret_cast<const ui8*>(&value), sizeof(value)); + return result; + } +#endif + +} diff --git a/library/cpp/int128/ut/int128_ut_helpers.h b/library/cpp/int128/ut/int128_ut_helpers.h new file mode 100644 index 0000000000..b7778c3f32 --- /dev/null +++ b/library/cpp/int128/ut/int128_ut_helpers.h @@ -0,0 +1,15 @@ +#pragma once + +#include <library/cpp/int128/int128.h> + +#include <array> + +namespace NInt128Private { + std::array<ui8, 16> GetAsArray(const ui128 value); + std::array<ui8, 16> GetAsArray(const i128 value); + +#if defined(Y_HAVE_INT128) + std::array<ui8, 16> GetAsArray(const unsigned __int128 value); + std::array<ui8, 16> GetAsArray(const signed __int128 value); +#endif +} diff --git a/library/cpp/int128/ut/int128_via_intrinsic_ut.cpp b/library/cpp/int128/ut/int128_via_intrinsic_ut.cpp new file mode 100644 index 0000000000..9decc2fd48 --- /dev/null +++ b/library/cpp/int128/ut/int128_via_intrinsic_ut.cpp @@ -0,0 +1,34 @@ +#include <library/cpp/int128/int128.h> + +#include <library/cpp/testing/unittest/registar.h> + +// from https://a.yandex-team.ru/arc/trunk/arcadia/library/ticket_parser/c/src/ut/utils_ut.cpp?rev=4221861 + +#if defined(Y_HAVE_INT128) +Y_UNIT_TEST_SUITE(Int128ViaIntrinsicSuite) { + using guint128_t = unsigned __int128; + guint128_t toGcc(ui128 num) { + guint128_t res = 0; + res |= GetLow(num); + res |= guint128_t(GetHigh(num)) << 64; + return res; + } + + Y_UNIT_TEST(bigintTest) { + UNIT_ASSERT(guint128_t(127) == toGcc(ui128(127))); + UNIT_ASSERT(guint128_t(127) * guint128_t(127) == toGcc(ui128(127) * ui128(127))); + UNIT_ASSERT(guint128_t(127) + guint128_t(127) == toGcc(ui128(127) + ui128(127))); + UNIT_ASSERT(guint128_t(127) << 3 == toGcc(ui128(127) << 3)); + UNIT_ASSERT(guint128_t(127) >> 1 == toGcc(ui128(127) >> 1)); + + UNIT_ASSERT(guint128_t(1000000000027UL) * guint128_t(1000000000027UL) == toGcc(ui128(1000000000027UL) * ui128(1000000000027UL))); + UNIT_ASSERT(guint128_t(1000000000027UL) + guint128_t(1000000000027UL) == toGcc(ui128(1000000000027UL) + ui128(1000000000027UL))); + UNIT_ASSERT(guint128_t(1000000000027UL) << 3 == toGcc(ui128(1000000000027UL) << 3)); + UNIT_ASSERT(guint128_t(1000000000027UL) >> 1 == toGcc(ui128(1000000000027UL) >> 1)); + UNIT_ASSERT((guint128_t(1000000000027UL) * guint128_t(1000000000027UL)) << 3 == toGcc((ui128(1000000000027UL) * ui128(1000000000027UL)) << 3)); + UNIT_ASSERT((guint128_t(1000000000027UL) + guint128_t(1000000000027UL)) >> 1 == toGcc((ui128(1000000000027UL) + ui128(1000000000027UL)) >> 1)); + + UNIT_ASSERT((ui64)(guint128_t(1000000000027UL) * guint128_t(1000000000027UL)) == GetLow(ui128(1000000000027UL) * ui128(1000000000027UL))); + } +} +#endif diff --git a/library/cpp/int128/ut/ui128_division_ut.cpp b/library/cpp/int128/ut/ui128_division_ut.cpp new file mode 100644 index 0000000000..4826a531e0 --- /dev/null +++ b/library/cpp/int128/ut/ui128_division_ut.cpp @@ -0,0 +1,262 @@ +#include <library/cpp/testing/unittest/registar.h> + +#include <library/cpp/int128/int128.h> + +#include <util/generic/cast.h> + +Y_UNIT_TEST_SUITE(Ui128DivisionBy1Suite) { + Y_UNIT_TEST(Ui128Divide0By1) { + ui128 dividend = 0; + ui128 divider = 1; + ui128 expectedQuotient = 0; + ui128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(Ui128Divide1By1) { + ui128 dividend = 1; + ui128 divider = 1; + ui128 expectedQuotient = 1; + ui128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(Ui128Divide2By1) { + ui128 dividend = 2; + ui128 divider = 1; + ui128 expectedQuotient = 2; + ui128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(Ui128Divide42By1) { + ui128 dividend = 42; + ui128 divider = 1; + ui128 expectedQuotient = 42; + ui128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(Ui128DivideMaxUi64By1) { + ui128 dividend = std::numeric_limits<ui64>::max(); + ui128 divider = 1; + ui128 expectedQuotient = std::numeric_limits<ui64>::max(); + ui128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(Ui128DivideMaxUi64Plus1By1) { + ui128 dividend = ui128{std::numeric_limits<ui64>::max()} + ui128{1}; + ui128 divider = 1; + ui128 expectedQuotient = ui128{std::numeric_limits<ui64>::max()} + ui128{1}; + ui128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(Ui128DivideMaxUi64Plus42By1) { + ui128 dividend = ui128{std::numeric_limits<ui64>::max()} + ui128{42}; + ui128 divider = 1; + ui128 expectedQuotient = ui128{std::numeric_limits<ui64>::max()} + ui128{42}; + ui128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(Ui128DivideMaxUi128By1) { + ui128 dividend = std::numeric_limits<ui128>::max(); + ui128 divider = 1; + ui128 expectedQuotient = std::numeric_limits<ui128>::max(); + ui128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(Ui128DivideMaxUi128Minus1By1) { + ui128 dividend = std::numeric_limits<ui128>::max() - 1; + ui128 divider = 1; + ui128 expectedQuotient = std::numeric_limits<ui128>::max() - 1; + ui128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } +} + +Y_UNIT_TEST_SUITE(Ui128DivisionByEqualSuite) { + Y_UNIT_TEST(Ui128Divide1ByEqual) { + ui128 dividend = 1; + ui128 divider = dividend; + ui128 expectedQuotient = 1; + ui128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(Ui128Divide2ByEqual) { + ui128 dividend = 2; + ui128 divider = dividend; + ui128 expectedQuotient = 1; + ui128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(Ui128Divide42ByEqual) { + ui128 dividend = 42; + ui128 divider = dividend; + ui128 expectedQuotient = 1; + ui128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(Ui128DivideMaxUi64ByEqual) { + ui128 dividend = std::numeric_limits<ui64>::max(); + ui128 divider = dividend; + ui128 expectedQuotient = 1; + ui128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(Ui128DivideMaxUi64Plus1ByEqual) { + ui128 dividend = ui128{std::numeric_limits<ui64>::max()} + ui128{1}; + ui128 divider = dividend; + ui128 expectedQuotient = 1; + ui128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(Ui128DivideMaxUi64Plus42ByEqual) { + ui128 dividend = ui128{std::numeric_limits<ui64>::max()} + ui128{42}; + ui128 divider = dividend; + ui128 expectedQuotient = 1; + ui128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(Ui128DivideMaxUi128ByEqual) { + ui128 dividend = std::numeric_limits<ui128>::max(); + ui128 divider = dividend; + ui128 expectedQuotient = 1; + ui128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(Ui128DivideMaxUi128Minus1ByEqual) { + ui128 dividend = std::numeric_limits<ui128>::max() - 1; + ui128 divider = dividend; + ui128 expectedQuotient = 1; + ui128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } +} + +Y_UNIT_TEST_SUITE(Ui128DivisionLessByHigherSuite) { + Y_UNIT_TEST(Ui128Divide42By84) { + ui128 dividend = 42; + ui128 divider = 84; + ui128 expectedQuotient = 0; + ui128 expectedRemainder = 42; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(Ui128Divide42ByMaxUi64) { + ui128 dividend = 42; + ui128 divider = std::numeric_limits<ui64>::max(); + ui128 expectedQuotient = 0; + ui128 expectedRemainder = 42; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(Ui128Divide42ByMaxUi64Plus1) { + ui128 dividend = 42; + ui128 divider = ui128{std::numeric_limits<ui64>::max()} + ui128{1}; + ui128 expectedQuotient = 0; + ui128 expectedRemainder = 42; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(Ui128DivideMaxUi64ByMaxUi64Plus1) { + ui128 dividend = ui128{std::numeric_limits<ui64>::max()}; + ui128 divider = ui128{std::numeric_limits<ui64>::max()} + ui128{1}; + ui128 expectedQuotient = 0; + ui128 expectedRemainder = ui128{std::numeric_limits<ui64>::max()}; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } +} + +Y_UNIT_TEST_SUITE(Ui128DivisionBigByBigSuite) { + Y_UNIT_TEST(Ui128DivideBigByBig1) { + ui128 dividend = {64, 0}; + ui128 divider = {1, 0}; + ui128 expectedQuotient = 64; + ui128 expectedRemainder = 0; + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } + + Y_UNIT_TEST(Ui128DivideBigByBig2) { + ui128 dividend = {64, 0}; + ui128 divider = {12, 5}; + ui128 expectedQuotient = 5; + ui128 expectedRemainder = ui128{3, 18446744073709551591ull}; // plz don't ask + + UNIT_ASSERT_EQUAL(dividend / divider, expectedQuotient); + UNIT_ASSERT_EQUAL(dividend % divider, expectedRemainder); + } +} + +Y_UNIT_TEST_SUITE(Ui128DivisionAlgo) { + Y_UNIT_TEST(Ui128DivideAlgoCheck) { + /* + 49672666804009505000000 / 10000000 == 4967266680400950 + 49672666804009505000000 % 10000000 == 5000000 + */ + ui128 dividend = {2692ull, 14031757583392049728ull}; + ui64 divider = 10000000; + ui128 expectedQuotient = {0, 4967266680400950ull}; + ui128 expectedRemainder = {0, 5000000ull}; + + ui128 quotient = dividend / divider; + ui128 reminder = dividend % divider; + + UNIT_ASSERT_EQUAL(quotient, expectedQuotient); + UNIT_ASSERT_EQUAL(reminder, expectedRemainder); + } +} diff --git a/library/cpp/int128/ut/ya.make b/library/cpp/int128/ut/ya.make new file mode 100644 index 0000000000..fd43531c5f --- /dev/null +++ b/library/cpp/int128/ut/ya.make @@ -0,0 +1,20 @@ +UNITTEST_FOR(library/cpp/int128) + +OWNER(vladon) + +SRCS( + int128_ut_helpers.cpp + int128_ut_helpers.h + int128_ut.cpp + int128_typetraits_ut.cpp + int128_old_ut.cpp + int128_via_intrinsic_ut.cpp + i128_ut.cpp + i128_and_intrinsic_identity_ut.cpp + i128_comparison_ut.cpp + i128_division_ut.cpp + i128_type_traits_ut.cpp + ui128_division_ut.cpp +) + +END() |