1ba92b274SDenys Petrov //===- unittests/StaticAnalyzer/RangeSetTest.cpp ----------------------===// 2ba92b274SDenys Petrov // 3ba92b274SDenys Petrov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4ba92b274SDenys Petrov // See https://llvm.org/LICENSE.txt for license information. 5ba92b274SDenys Petrov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6ba92b274SDenys Petrov // 7ba92b274SDenys Petrov //===----------------------------------------------------------------------===// 8ba92b274SDenys Petrov 9ba92b274SDenys Petrov #include "clang/Basic/Builtins.h" 10ba92b274SDenys Petrov #include "clang/Basic/FileManager.h" 11ba92b274SDenys Petrov #include "clang/Basic/SourceManager.h" 12ba92b274SDenys Petrov #include "clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h" 13ba92b274SDenys Petrov #include "clang/Tooling/Tooling.h" 1402b51e53SValeriy Savchenko #include "llvm/ADT/APSInt.h" 1502b51e53SValeriy Savchenko #include "llvm/Support/raw_ostream.h" 16ba92b274SDenys Petrov #include "gtest/gtest.h" 17ba92b274SDenys Petrov 1802b51e53SValeriy Savchenko using namespace clang; 1902b51e53SValeriy Savchenko using namespace ento; 2002b51e53SValeriy Savchenko 21ba92b274SDenys Petrov namespace clang { 22ba92b274SDenys Petrov namespace ento { 2302b51e53SValeriy Savchenko 2402b51e53SValeriy Savchenko template <class RangeOrSet> static std::string toString(const RangeOrSet &Obj) { 2502b51e53SValeriy Savchenko std::string ObjRepresentation; 2602b51e53SValeriy Savchenko llvm::raw_string_ostream SS(ObjRepresentation); 2702b51e53SValeriy Savchenko Obj.dump(SS); 28*918972bdSJOE1994 return ObjRepresentation; 2902b51e53SValeriy Savchenko } 3002b51e53SValeriy Savchenko LLVM_ATTRIBUTE_UNUSED static std::string toString(const llvm::APSInt &Point) { 3161cdaf66SSimon Pilgrim return toString(Point, 10); 3202b51e53SValeriy Savchenko } 3302b51e53SValeriy Savchenko // We need it here for better fail diagnostics from gtest. 3402b51e53SValeriy Savchenko LLVM_ATTRIBUTE_UNUSED static std::ostream &operator<<(std::ostream &OS, 3502b51e53SValeriy Savchenko const RangeSet &Set) { 3602b51e53SValeriy Savchenko return OS << toString(Set); 3702b51e53SValeriy Savchenko } 386a399bf4SDenys Petrov // We need it here for better fail diagnostics from gtest. 396a399bf4SDenys Petrov LLVM_ATTRIBUTE_UNUSED static std::ostream &operator<<(std::ostream &OS, 406a399bf4SDenys Petrov const Range &R) { 416a399bf4SDenys Petrov return OS << toString(R); 426a399bf4SDenys Petrov } 43e37726beSDenys Petrov LLVM_ATTRIBUTE_UNUSED static std::ostream &operator<<(std::ostream &OS, 44e37726beSDenys Petrov APSIntType Ty) { 45e37726beSDenys Petrov return OS << (Ty.isUnsigned() ? "u" : "s") << Ty.getBitWidth(); 46e37726beSDenys Petrov } 4702b51e53SValeriy Savchenko 4802b51e53SValeriy Savchenko } // namespace ento 4902b51e53SValeriy Savchenko } // namespace clang 5002b51e53SValeriy Savchenko 51ba92b274SDenys Petrov namespace { 52ba92b274SDenys Petrov 53e37726beSDenys Petrov template <class T> constexpr bool is_signed_v = std::is_signed<T>::value; 54e37726beSDenys Petrov 556a399bf4SDenys Petrov template <typename T> struct TestValues { 566a399bf4SDenys Petrov static constexpr T MIN = std::numeric_limits<T>::min(); 576a399bf4SDenys Petrov static constexpr T MAX = std::numeric_limits<T>::max(); 586a399bf4SDenys Petrov // MID is a value in the middle of the range 596a399bf4SDenys Petrov // which unary minus does not affect on, 606a399bf4SDenys Petrov // e.g. int8/int32(0), uint8(128), uint32(2147483648). 616a399bf4SDenys Petrov static constexpr T MID = 62e37726beSDenys Petrov is_signed_v<T> ? 0 : ~(static_cast<T>(-1) / static_cast<T>(2)); 636a399bf4SDenys Petrov static constexpr T A = MID - (MAX - MID) / 3 * 2; 646a399bf4SDenys Petrov static constexpr T B = MID - (MAX - MID) / 3; 656a399bf4SDenys Petrov static constexpr T C = -B; 666a399bf4SDenys Petrov static constexpr T D = -A; 676a399bf4SDenys Petrov 686a399bf4SDenys Petrov static_assert(MIN < A && A < B && B < MID && MID < C && C < D && D < MAX, 696a399bf4SDenys Petrov "Values shall be in an ascending order"); 70e37726beSDenys Petrov // Clear bits in low bytes by the given amount. 71e37726beSDenys Petrov template <T Value, size_t Bytes> 72e37726beSDenys Petrov static constexpr T ClearLowBytes = 73e37726beSDenys Petrov static_cast<T>(static_cast<uint64_t>(Value) 74e37726beSDenys Petrov << ((Bytes >= CHAR_BIT) ? 0 : Bytes) * CHAR_BIT); 75e37726beSDenys Petrov 76e37726beSDenys Petrov template <T Value, typename Base> 77e37726beSDenys Petrov static constexpr T TruncZeroOf = ClearLowBytes<Value + 1, sizeof(Base)>; 78e37726beSDenys Petrov 79e37726beSDenys Petrov // Random number with active bits in every byte. 0xAAAA'AAAA 80e37726beSDenys Petrov static constexpr T XAAA = static_cast<T>( 81e37726beSDenys Petrov 0b10101010'10101010'10101010'10101010'10101010'10101010'10101010'10101010); 82e37726beSDenys Petrov template <typename Base> 83e37726beSDenys Petrov static constexpr T XAAATruncZeroOf = TruncZeroOf<XAAA, Base>; // 0xAAAA'AB00 84e37726beSDenys Petrov 85e37726beSDenys Petrov // Random number with active bits in every byte. 0x5555'5555 86e37726beSDenys Petrov static constexpr T X555 = static_cast<T>( 87e37726beSDenys Petrov 0b01010101'01010101'01010101'01010101'01010101'01010101'01010101'01010101); 88e37726beSDenys Petrov template <typename Base> 89e37726beSDenys Petrov static constexpr T X555TruncZeroOf = TruncZeroOf<X555, Base>; // 0x5555'5600 90e37726beSDenys Petrov 910880b9d5SAlexandre Ganea // Silence 'warning C4309: 'initializing': truncation of constant value' 920880b9d5SAlexandre Ganea // in RangeSetCastToPromotionConversionTest. 930880b9d5SAlexandre Ganea #if defined(_MSC_VER) && !defined(__clang__) 940880b9d5SAlexandre Ganea #pragma warning(push) 950880b9d5SAlexandre Ganea #pragma warning(disable : 4309) 960880b9d5SAlexandre Ganea #endif 97e37726beSDenys Petrov // Numbers for ranges with the same bits in the lowest byte. 98e37726beSDenys Petrov // 0xAAAA'AA2A 99e37726beSDenys Petrov static constexpr T FromA = ClearLowBytes<XAAA, sizeof(T) - 1> + 42; 100e37726beSDenys Petrov static constexpr T ToA = FromA + 2; // 0xAAAA'AA2C 101e37726beSDenys Petrov // 0x5555'552A 102e37726beSDenys Petrov static constexpr T FromB = ClearLowBytes<X555, sizeof(T) - 1> + 42; 103e37726beSDenys Petrov static constexpr T ToB = FromB + 2; // 0x5555'552C 1040880b9d5SAlexandre Ganea 1050880b9d5SAlexandre Ganea #if defined(_MSC_VER) && !defined(__clang__) 1060880b9d5SAlexandre Ganea #pragma warning(pop) 1070880b9d5SAlexandre Ganea #endif 1086a399bf4SDenys Petrov }; 1096a399bf4SDenys Petrov 110e37726beSDenys Petrov template <typename T> 111e37726beSDenys Petrov static constexpr APSIntType APSIntTy = 112e37726beSDenys Petrov APSIntType(sizeof(T) * CHAR_BIT, !is_signed_v<T>); 113e37726beSDenys Petrov 11402b51e53SValeriy Savchenko template <typename BaseType> class RangeSetTest : public testing::Test { 11502b51e53SValeriy Savchenko public: 11602b51e53SValeriy Savchenko // Init block 11702b51e53SValeriy Savchenko std::unique_ptr<ASTUnit> AST = tooling::buildASTFromCode("struct foo;"); 11802b51e53SValeriy Savchenko ASTContext &Context = AST->getASTContext(); 11902b51e53SValeriy Savchenko llvm::BumpPtrAllocator Arena; 12002b51e53SValeriy Savchenko BasicValueFactory BVF{Context, Arena}; 12102b51e53SValeriy Savchenko RangeSet::Factory F{BVF}; 12202b51e53SValeriy Savchenko // End init block 123ba92b274SDenys Petrov 12402b51e53SValeriy Savchenko using Self = RangeSetTest<BaseType>; 125e37726beSDenys Petrov template <typename T> using RawRangeT = std::pair<T, T>; 126e37726beSDenys Petrov template <typename T> 127e37726beSDenys Petrov using RawRangeSetT = std::initializer_list<RawRangeT<T>>; 128e37726beSDenys Petrov using RawRange = RawRangeT<BaseType>; 129e37726beSDenys Petrov using RawRangeSet = RawRangeSetT<BaseType>; 130ba92b274SDenys Petrov 131e37726beSDenys Petrov template <typename T> const llvm::APSInt &from(T X) { 132e37726beSDenys Petrov static llvm::APSInt Int = APSIntTy<T>.getZeroValue(); 133e37726beSDenys Petrov Int = X; 134e37726beSDenys Petrov return BVF.getValue(Int); 13502b51e53SValeriy Savchenko } 13602b51e53SValeriy Savchenko 137e37726beSDenys Petrov template <typename T> Range from(const RawRangeT<T> &Init) { 13802b51e53SValeriy Savchenko return Range(from(Init.first), from(Init.second)); 13902b51e53SValeriy Savchenko } 14002b51e53SValeriy Savchenko 141e37726beSDenys Petrov template <typename T> 142e37726beSDenys Petrov RangeSet from(RawRangeSetT<T> Init, APSIntType Ty = APSIntTy<BaseType>) { 14302b51e53SValeriy Savchenko RangeSet RangeSet = F.getEmptySet(); 14402b51e53SValeriy Savchenko for (const auto &Raw : Init) { 14502b51e53SValeriy Savchenko RangeSet = F.add(RangeSet, from(Raw)); 14602b51e53SValeriy Savchenko } 14702b51e53SValeriy Savchenko return RangeSet; 14802b51e53SValeriy Savchenko } 14902b51e53SValeriy Savchenko 15002b51e53SValeriy Savchenko template <class F, class... RawArgTypes> 15102b51e53SValeriy Savchenko void wrap(F ActualFunction, RawArgTypes &&... Args) { 15202b51e53SValeriy Savchenko (this->*ActualFunction)(from(std::forward<RawArgTypes>(Args))...); 15302b51e53SValeriy Savchenko } 15402b51e53SValeriy Savchenko 15502b51e53SValeriy Savchenko void checkNegateImpl(RangeSet Original, RangeSet Expected) { 15602b51e53SValeriy Savchenko RangeSet NegatedFromOriginal = F.negate(Original); 15702b51e53SValeriy Savchenko EXPECT_EQ(NegatedFromOriginal, Expected); 15802b51e53SValeriy Savchenko // Negate negated back and check with original. 15902b51e53SValeriy Savchenko RangeSet NegatedBackward = F.negate(NegatedFromOriginal); 16002b51e53SValeriy Savchenko EXPECT_EQ(NegatedBackward, Original); 16102b51e53SValeriy Savchenko } 16202b51e53SValeriy Savchenko 16302b51e53SValeriy Savchenko void checkNegate(RawRangeSet RawOriginal, RawRangeSet RawExpected) { 16402b51e53SValeriy Savchenko wrap(&Self::checkNegateImpl, RawOriginal, RawExpected); 16502b51e53SValeriy Savchenko } 16602b51e53SValeriy Savchenko 16702b51e53SValeriy Savchenko template <class PointOrSet> 16802b51e53SValeriy Savchenko void checkIntersectImpl(RangeSet LHS, PointOrSet RHS, RangeSet Expected) { 16902b51e53SValeriy Savchenko RangeSet Result = F.intersect(LHS, RHS); 17002b51e53SValeriy Savchenko EXPECT_EQ(Result, Expected) 17102b51e53SValeriy Savchenko << "while intersecting " << toString(LHS) << " and " << toString(RHS); 17202b51e53SValeriy Savchenko } 17302b51e53SValeriy Savchenko 17402b51e53SValeriy Savchenko void checkIntersectRangeImpl(RangeSet LHS, const llvm::APSInt &Lower, 17502b51e53SValeriy Savchenko const llvm::APSInt &Upper, RangeSet Expected) { 17602b51e53SValeriy Savchenko RangeSet Result = F.intersect(LHS, Lower, Upper); 17702b51e53SValeriy Savchenko EXPECT_EQ(Result, Expected) 17802b51e53SValeriy Savchenko << "while intersecting " << toString(LHS) << " and [" << toString(Lower) 17902b51e53SValeriy Savchenko << ", " << toString(Upper) << "]"; 18002b51e53SValeriy Savchenko } 18102b51e53SValeriy Savchenko 18202b51e53SValeriy Savchenko void checkIntersect(RawRangeSet RawLHS, RawRangeSet RawRHS, 18302b51e53SValeriy Savchenko RawRangeSet RawExpected) { 18402b51e53SValeriy Savchenko wrap(&Self::checkIntersectImpl<RangeSet>, RawLHS, RawRHS, RawExpected); 18502b51e53SValeriy Savchenko } 18602b51e53SValeriy Savchenko 18702b51e53SValeriy Savchenko void checkIntersect(RawRangeSet RawLHS, BaseType RawRHS, 18802b51e53SValeriy Savchenko RawRangeSet RawExpected) { 18902b51e53SValeriy Savchenko wrap(&Self::checkIntersectImpl<const llvm::APSInt &>, RawLHS, RawRHS, 19002b51e53SValeriy Savchenko RawExpected); 19102b51e53SValeriy Savchenko } 19202b51e53SValeriy Savchenko 19302b51e53SValeriy Savchenko void checkIntersect(RawRangeSet RawLHS, BaseType RawLower, BaseType RawUpper, 19402b51e53SValeriy Savchenko RawRangeSet RawExpected) { 19502b51e53SValeriy Savchenko wrap(&Self::checkIntersectRangeImpl, RawLHS, RawLower, RawUpper, 19602b51e53SValeriy Savchenko RawExpected); 19702b51e53SValeriy Savchenko } 19802b51e53SValeriy Savchenko 19902b51e53SValeriy Savchenko void checkContainsImpl(RangeSet LHS, const llvm::APSInt &RHS, bool Expected) { 20002b51e53SValeriy Savchenko bool Result = LHS.contains(RHS); 20102b51e53SValeriy Savchenko EXPECT_EQ(Result, Expected) 20202b51e53SValeriy Savchenko << toString(LHS) << (Result ? " contains " : " doesn't contain ") 20302b51e53SValeriy Savchenko << toString(RHS); 20402b51e53SValeriy Savchenko } 20502b51e53SValeriy Savchenko 20602b51e53SValeriy Savchenko void checkContains(RawRangeSet RawLHS, BaseType RawRHS, bool Expected) { 20702b51e53SValeriy Savchenko checkContainsImpl(from(RawLHS), from(RawRHS), Expected); 20802b51e53SValeriy Savchenko } 20902b51e53SValeriy Savchenko 21002b51e53SValeriy Savchenko template <class RHSType> 21102b51e53SValeriy Savchenko void checkAddImpl(RangeSet LHS, RHSType RHS, RangeSet Expected) { 21202b51e53SValeriy Savchenko RangeSet Result = F.add(LHS, RHS); 21302b51e53SValeriy Savchenko EXPECT_EQ(Result, Expected) 21402b51e53SValeriy Savchenko << "while adding " << toString(LHS) << " and " << toString(RHS); 21502b51e53SValeriy Savchenko } 21602b51e53SValeriy Savchenko 21702b51e53SValeriy Savchenko void checkAdd(RawRangeSet RawLHS, RawRange RawRHS, RawRangeSet RawExpected) { 21802b51e53SValeriy Savchenko wrap(&Self::checkAddImpl<Range>, RawLHS, RawRHS, RawExpected); 21902b51e53SValeriy Savchenko } 22002b51e53SValeriy Savchenko 22102b51e53SValeriy Savchenko void checkAdd(RawRangeSet RawLHS, RawRangeSet RawRHS, 22202b51e53SValeriy Savchenko RawRangeSet RawExpected) { 2236a399bf4SDenys Petrov wrap(&Self::checkAddImpl<RangeSet>, RawLHS, RawRHS, RawExpected); 22402b51e53SValeriy Savchenko } 22502b51e53SValeriy Savchenko 22602b51e53SValeriy Savchenko void checkAdd(RawRangeSet RawLHS, BaseType RawRHS, RawRangeSet RawExpected) { 22702b51e53SValeriy Savchenko wrap(&Self::checkAddImpl<const llvm::APSInt &>, RawLHS, RawRHS, 22802b51e53SValeriy Savchenko RawExpected); 22902b51e53SValeriy Savchenko } 23002b51e53SValeriy Savchenko 2316a399bf4SDenys Petrov template <class RHSType> 2326a399bf4SDenys Petrov void checkUniteImpl(RangeSet LHS, RHSType RHS, RangeSet Expected) { 2336a399bf4SDenys Petrov RangeSet Result = F.unite(LHS, RHS); 2346a399bf4SDenys Petrov EXPECT_EQ(Result, Expected) 2356a399bf4SDenys Petrov << "while uniting " << toString(LHS) << " and " << toString(RHS); 2366a399bf4SDenys Petrov } 2376a399bf4SDenys Petrov 2386a399bf4SDenys Petrov void checkUnite(RawRangeSet RawLHS, RawRange RawRHS, 2396a399bf4SDenys Petrov RawRangeSet RawExpected) { 2406a399bf4SDenys Petrov wrap(&Self::checkUniteImpl<Range>, RawLHS, RawRHS, RawExpected); 2416a399bf4SDenys Petrov } 2426a399bf4SDenys Petrov 2436a399bf4SDenys Petrov void checkUnite(RawRangeSet RawLHS, RawRangeSet RawRHS, 2446a399bf4SDenys Petrov RawRangeSet RawExpected) { 2456a399bf4SDenys Petrov wrap(&Self::checkUniteImpl<RangeSet>, RawLHS, RawRHS, RawExpected); 2466a399bf4SDenys Petrov } 2476a399bf4SDenys Petrov 2486a399bf4SDenys Petrov void checkUnite(RawRangeSet RawLHS, BaseType RawRHS, 2496a399bf4SDenys Petrov RawRangeSet RawExpected) { 2506a399bf4SDenys Petrov wrap(&Self::checkUniteImpl<const llvm::APSInt &>, RawLHS, RawRHS, 2516a399bf4SDenys Petrov RawExpected); 2526a399bf4SDenys Petrov } 2536a399bf4SDenys Petrov 25402b51e53SValeriy Savchenko void checkDeleteImpl(const llvm::APSInt &Point, RangeSet From, 25502b51e53SValeriy Savchenko RangeSet Expected) { 25602b51e53SValeriy Savchenko RangeSet Result = F.deletePoint(From, Point); 25702b51e53SValeriy Savchenko EXPECT_EQ(Result, Expected) 25802b51e53SValeriy Savchenko << "while deleting " << toString(Point) << " from " << toString(From); 25902b51e53SValeriy Savchenko } 26002b51e53SValeriy Savchenko 26102b51e53SValeriy Savchenko void checkDelete(BaseType Point, RawRangeSet RawFrom, 26202b51e53SValeriy Savchenko RawRangeSet RawExpected) { 26302b51e53SValeriy Savchenko wrap(&Self::checkDeleteImpl, Point, RawFrom, RawExpected); 264ba92b274SDenys Petrov } 265ba92b274SDenys Petrov 266e37726beSDenys Petrov void checkCastToImpl(RangeSet What, APSIntType Ty, RangeSet Expected) { 267e37726beSDenys Petrov RangeSet Result = F.castTo(What, Ty); 268e37726beSDenys Petrov EXPECT_EQ(Result, Expected) 269e37726beSDenys Petrov << "while casting " << toString(What) << " to " << Ty; 270e37726beSDenys Petrov } 271e37726beSDenys Petrov 272e37726beSDenys Petrov template <typename From, typename To> 273e37726beSDenys Petrov void checkCastTo(RawRangeSetT<From> What, RawRangeSetT<To> Expected) { 274e37726beSDenys Petrov static constexpr APSIntType FromTy = APSIntTy<From>; 275e37726beSDenys Petrov static constexpr APSIntType ToTy = APSIntTy<To>; 276e37726beSDenys Petrov this->checkCastToImpl(from(What, FromTy), ToTy, from(Expected, ToTy)); 277e37726beSDenys Petrov } 278e37726beSDenys Petrov }; 279ba92b274SDenys Petrov 28002b51e53SValeriy Savchenko using IntTypes = ::testing::Types<int8_t, uint8_t, int16_t, uint16_t, int32_t, 28102b51e53SValeriy Savchenko uint32_t, int64_t, uint64_t>; 28205de4b41SBenjamin Kramer TYPED_TEST_SUITE(RangeSetTest, IntTypes, ); 28302b51e53SValeriy Savchenko 28402b51e53SValeriy Savchenko TYPED_TEST(RangeSetTest, RangeSetNegateTest) { 2856a399bf4SDenys Petrov using TV = TestValues<TypeParam>; 2866a399bf4SDenys Petrov constexpr auto MIN = TV::MIN; 2876a399bf4SDenys Petrov constexpr auto MAX = TV::MAX; 2886a399bf4SDenys Petrov constexpr auto MID = TV::MID; 2896a399bf4SDenys Petrov constexpr auto A = TV::A; 2906a399bf4SDenys Petrov constexpr auto B = TV::B; 2916a399bf4SDenys Petrov constexpr auto C = TV::C; 2926a399bf4SDenys Petrov constexpr auto D = TV::D; 293ba92b274SDenys Petrov 29402b51e53SValeriy Savchenko this->checkNegate({{MIN, A}}, {{MIN, MIN}, {D, MAX}}); 29502b51e53SValeriy Savchenko this->checkNegate({{MIN, C}}, {{MIN, MIN}, {B, MAX}}); 29602b51e53SValeriy Savchenko this->checkNegate({{MIN, MID}}, {{MIN, MIN}, {MID, MAX}}); 29702b51e53SValeriy Savchenko this->checkNegate({{MIN, MAX}}, {{MIN, MAX}}); 29802b51e53SValeriy Savchenko this->checkNegate({{A, D}}, {{A, D}}); 29902b51e53SValeriy Savchenko this->checkNegate({{A, B}}, {{C, D}}); 30002b51e53SValeriy Savchenko this->checkNegate({{MIN, A}, {D, MAX}}, {{MIN, A}, {D, MAX}}); 30102b51e53SValeriy Savchenko this->checkNegate({{MIN, B}, {MID, D}}, {{MIN, MIN}, {A, MID}, {C, MAX}}); 30202b51e53SValeriy Savchenko this->checkNegate({{MIN, MID}, {C, D}}, {{MIN, MIN}, {A, B}, {MID, MAX}}); 30302b51e53SValeriy Savchenko this->checkNegate({{MIN, MID}, {C, MAX}}, {{MIN, B}, {MID, MAX}}); 30402b51e53SValeriy Savchenko this->checkNegate({{A, MID}, {D, MAX}}, {{MIN + 1, A}, {MID, D}}); 30502b51e53SValeriy Savchenko this->checkNegate({{A, A}}, {{D, D}}); 30602b51e53SValeriy Savchenko this->checkNegate({{MID, MID}}, {{MID, MID}}); 30702b51e53SValeriy Savchenko this->checkNegate({{MAX, MAX}}, {{MIN + 1, MIN + 1}}); 308ba92b274SDenys Petrov } 309ba92b274SDenys Petrov 31002b51e53SValeriy Savchenko TYPED_TEST(RangeSetTest, RangeSetPointIntersectTest) { 31102b51e53SValeriy Savchenko // Check that we can correctly intersect empty sets. 31202b51e53SValeriy Savchenko this->checkIntersect({}, 42, {}); 31302b51e53SValeriy Savchenko // Check that intersection with itself produces the same set. 31402b51e53SValeriy Savchenko this->checkIntersect({{42, 42}}, 42, {{42, 42}}); 31502b51e53SValeriy Savchenko // Check more general cases. 31602b51e53SValeriy Savchenko this->checkIntersect({{0, 10}, {20, 30}, {30, 40}, {50, 60}}, 42, {}); 31702b51e53SValeriy Savchenko this->checkIntersect({{0, 10}, {20, 30}, {30, 60}}, 42, {{42, 42}}); 31802b51e53SValeriy Savchenko } 31902b51e53SValeriy Savchenko 32002b51e53SValeriy Savchenko TYPED_TEST(RangeSetTest, RangeSetRangeIntersectTest) { 3216a399bf4SDenys Petrov using TV = TestValues<TypeParam>; 3226a399bf4SDenys Petrov constexpr auto MIN = TV::MIN; 3236a399bf4SDenys Petrov constexpr auto MAX = TV::MAX; 32402b51e53SValeriy Savchenko 32502b51e53SValeriy Savchenko // Check that we can correctly intersect empty sets. 32602b51e53SValeriy Savchenko this->checkIntersect({}, 10, 20, {}); 32702b51e53SValeriy Savchenko this->checkIntersect({}, 20, 10, {}); 32802b51e53SValeriy Savchenko // Check that intersection with itself produces the same set. 32902b51e53SValeriy Savchenko this->checkIntersect({{10, 20}}, 10, 20, {{10, 20}}); 33002b51e53SValeriy Savchenko this->checkIntersect({{MIN, 10}, {20, MAX}}, 20, 10, {{MIN, 10}, {20, MAX}}); 33102b51e53SValeriy Savchenko // Check non-overlapping range intersections. 33202b51e53SValeriy Savchenko this->checkIntersect({{10, 20}}, 21, 9, {}); 33302b51e53SValeriy Savchenko this->checkIntersect({{MIN, 9}, {21, MAX}}, 10, 20, {}); 33402b51e53SValeriy Savchenko // Check more general cases. 33502b51e53SValeriy Savchenko this->checkIntersect({{0, 10}, {20, 30}, {30, 40}, {50, 60}}, 10, 35, 33602b51e53SValeriy Savchenko {{10, 10}, {20, 30}, {30, 35}}); 33702b51e53SValeriy Savchenko this->checkIntersect({{0, 10}, {20, 30}, {30, 40}, {50, 60}}, 35, 10, 33802b51e53SValeriy Savchenko {{0, 10}, {35, 40}, {50, 60}}); 33902b51e53SValeriy Savchenko } 34002b51e53SValeriy Savchenko 34102b51e53SValeriy Savchenko TYPED_TEST(RangeSetTest, RangeSetGenericIntersectTest) { 34202b51e53SValeriy Savchenko // Check that we can correctly intersect empty sets. 34302b51e53SValeriy Savchenko this->checkIntersect({}, {}, {}); 34402b51e53SValeriy Savchenko this->checkIntersect({}, {{0, 10}}, {}); 34502b51e53SValeriy Savchenko this->checkIntersect({{0, 10}}, {}, {}); 34602b51e53SValeriy Savchenko 34702b51e53SValeriy Savchenko this->checkIntersect({{0, 10}}, {{4, 6}}, {{4, 6}}); 34802b51e53SValeriy Savchenko this->checkIntersect({{0, 10}}, {{4, 20}}, {{4, 10}}); 34902b51e53SValeriy Savchenko // Check that intersection with points works as expected. 35002b51e53SValeriy Savchenko this->checkIntersect({{0, 10}}, {{4, 4}}, {{4, 4}}); 35102b51e53SValeriy Savchenko // All ranges are closed, check that intersection with edge points works as 35202b51e53SValeriy Savchenko // expected. 35302b51e53SValeriy Savchenko this->checkIntersect({{0, 10}}, {{10, 10}}, {{10, 10}}); 35402b51e53SValeriy Savchenko 35502b51e53SValeriy Savchenko // Let's check that we can skip some intervals and partially intersect 35602b51e53SValeriy Savchenko // other intervals. 35702b51e53SValeriy Savchenko this->checkIntersect({{0, 2}, {4, 5}, {6, 9}, {10, 11}, {12, 12}, {13, 15}}, 35802b51e53SValeriy Savchenko {{8, 14}, {20, 30}}, 35902b51e53SValeriy Savchenko {{8, 9}, {10, 11}, {12, 12}, {13, 14}}); 36002b51e53SValeriy Savchenko // Check more generic case. 36102b51e53SValeriy Savchenko this->checkIntersect( 36202b51e53SValeriy Savchenko {{0, 1}, {2, 3}, {5, 6}, {7, 15}, {25, 30}}, 36302b51e53SValeriy Savchenko {{4, 10}, {11, 11}, {12, 16}, {17, 17}, {19, 20}, {21, 23}, {24, 27}}, 36402b51e53SValeriy Savchenko {{5, 6}, {7, 10}, {11, 11}, {12, 15}, {25, 27}}); 36502b51e53SValeriy Savchenko } 36602b51e53SValeriy Savchenko 36702b51e53SValeriy Savchenko TYPED_TEST(RangeSetTest, RangeSetContainsTest) { 36802b51e53SValeriy Savchenko // Check with an empty set. 36902b51e53SValeriy Savchenko this->checkContains({}, 10, false); 37002b51e53SValeriy Savchenko // Check contains with sets of size one: 37102b51e53SValeriy Savchenko // * when the whole range is less 37202b51e53SValeriy Savchenko this->checkContains({{0, 5}}, 10, false); 37302b51e53SValeriy Savchenko // * when the whole range is greater 37402b51e53SValeriy Savchenko this->checkContains({{20, 25}}, 10, false); 37502b51e53SValeriy Savchenko // * when the range is just the point we are looking for 37602b51e53SValeriy Savchenko this->checkContains({{10, 10}}, 10, true); 37702b51e53SValeriy Savchenko // * when the range starts with the point 37802b51e53SValeriy Savchenko this->checkContains({{10, 15}}, 10, true); 37902b51e53SValeriy Savchenko // * when the range ends with the point 38002b51e53SValeriy Savchenko this->checkContains({{5, 10}}, 10, true); 38102b51e53SValeriy Savchenko // * when the range has the point somewhere in the middle 38202b51e53SValeriy Savchenko this->checkContains({{0, 25}}, 10, true); 38302b51e53SValeriy Savchenko // Check similar cases, but with larger sets. 38402b51e53SValeriy Savchenko this->checkContains({{0, 5}, {10, 10}, {15, 20}}, 10, true); 38502b51e53SValeriy Savchenko this->checkContains({{0, 5}, {10, 12}, {15, 20}}, 10, true); 38602b51e53SValeriy Savchenko this->checkContains({{0, 5}, {5, 7}, {8, 10}, {12, 41}}, 10, true); 38702b51e53SValeriy Savchenko 3886a399bf4SDenys Petrov using TV = TestValues<TypeParam>; 3896a399bf4SDenys Petrov constexpr auto MIN = TV::MIN; 3906a399bf4SDenys Petrov constexpr auto MAX = TV::MAX; 3916a399bf4SDenys Petrov constexpr auto MID = TV::MID; 3926a399bf4SDenys Petrov 39302b51e53SValeriy Savchenko this->checkContains({{MIN, MAX}}, 0, true); 39402b51e53SValeriy Savchenko this->checkContains({{MIN, MAX}}, MID, true); 39502b51e53SValeriy Savchenko this->checkContains({{MIN, MAX}}, -10, true); 39602b51e53SValeriy Savchenko this->checkContains({{MIN, MAX}}, 10, true); 39702b51e53SValeriy Savchenko } 39802b51e53SValeriy Savchenko 39902b51e53SValeriy Savchenko TYPED_TEST(RangeSetTest, RangeSetAddTest) { 40002b51e53SValeriy Savchenko // Check adding single points 40102b51e53SValeriy Savchenko this->checkAdd({}, 10, {{10, 10}}); 40202b51e53SValeriy Savchenko this->checkAdd({{0, 5}}, 10, {{0, 5}, {10, 10}}); 40302b51e53SValeriy Savchenko this->checkAdd({{0, 5}, {30, 40}}, 10, {{0, 5}, {10, 10}, {30, 40}}); 40402b51e53SValeriy Savchenko 40502b51e53SValeriy Savchenko // Check adding single ranges. 40602b51e53SValeriy Savchenko this->checkAdd({}, {10, 20}, {{10, 20}}); 40702b51e53SValeriy Savchenko this->checkAdd({{0, 5}}, {10, 20}, {{0, 5}, {10, 20}}); 40802b51e53SValeriy Savchenko this->checkAdd({{0, 5}, {30, 40}}, {10, 20}, {{0, 5}, {10, 20}, {30, 40}}); 40902b51e53SValeriy Savchenko 41002b51e53SValeriy Savchenko // Check adding whole sets of ranges. 41102b51e53SValeriy Savchenko this->checkAdd({{0, 5}}, {{10, 20}}, {{0, 5}, {10, 20}}); 41202b51e53SValeriy Savchenko // Check that ordering of ranges is as expected. 41302b51e53SValeriy Savchenko this->checkAdd({{0, 5}, {30, 40}}, {{10, 20}}, {{0, 5}, {10, 20}, {30, 40}}); 41402b51e53SValeriy Savchenko this->checkAdd({{0, 5}, {30, 40}}, {{10, 20}, {50, 60}}, 41502b51e53SValeriy Savchenko {{0, 5}, {10, 20}, {30, 40}, {50, 60}}); 41602b51e53SValeriy Savchenko this->checkAdd({{10, 20}, {50, 60}}, {{0, 5}, {30, 40}, {70, 80}}, 41702b51e53SValeriy Savchenko {{0, 5}, {10, 20}, {30, 40}, {50, 60}, {70, 80}}); 41802b51e53SValeriy Savchenko } 41902b51e53SValeriy Savchenko 42002b51e53SValeriy Savchenko TYPED_TEST(RangeSetTest, RangeSetDeletePointTest) { 4216a399bf4SDenys Petrov using TV = TestValues<TypeParam>; 4226a399bf4SDenys Petrov constexpr auto MIN = TV::MIN; 4236a399bf4SDenys Petrov constexpr auto MAX = TV::MAX; 4246a399bf4SDenys Petrov constexpr auto MID = TV::MID; 42502b51e53SValeriy Savchenko 42602b51e53SValeriy Savchenko this->checkDelete(MID, {{MIN, MAX}}, {{MIN, MID - 1}, {MID + 1, MAX}}); 42702b51e53SValeriy Savchenko // Check that delete works with an empty set. 42802b51e53SValeriy Savchenko this->checkDelete(10, {}, {}); 42902b51e53SValeriy Savchenko // Check that delete can remove entire ranges. 43002b51e53SValeriy Savchenko this->checkDelete(10, {{10, 10}}, {}); 43102b51e53SValeriy Savchenko this->checkDelete(10, {{0, 5}, {10, 10}, {20, 30}}, {{0, 5}, {20, 30}}); 43202b51e53SValeriy Savchenko // Check that delete can split existing ranges into two. 43302b51e53SValeriy Savchenko this->checkDelete(10, {{0, 5}, {7, 15}, {20, 30}}, 43402b51e53SValeriy Savchenko {{0, 5}, {7, 9}, {11, 15}, {20, 30}}); 43502b51e53SValeriy Savchenko // Check that delete of the point not from the range set works as expected. 43602b51e53SValeriy Savchenko this->checkDelete(10, {{0, 5}, {20, 30}}, {{0, 5}, {20, 30}}); 43702b51e53SValeriy Savchenko } 4386a399bf4SDenys Petrov 4396a399bf4SDenys Petrov TYPED_TEST(RangeSetTest, RangeSetUniteTest) { 4406a399bf4SDenys Petrov using TV = TestValues<TypeParam>; 4416a399bf4SDenys Petrov constexpr auto MIN = TV::MIN; 4426a399bf4SDenys Petrov constexpr auto MAX = TV::MAX; 4436a399bf4SDenys Petrov constexpr auto MID = TV::MID; 4446a399bf4SDenys Petrov constexpr auto A = TV::A; 4456a399bf4SDenys Petrov constexpr auto B = TV::B; 4466a399bf4SDenys Petrov constexpr auto C = TV::C; 4476a399bf4SDenys Petrov constexpr auto D = TV::D; 4486a399bf4SDenys Petrov 4496a399bf4SDenys Petrov // LHS and RHS is empty. 4506a399bf4SDenys Petrov // RHS => 4516a399bf4SDenys Petrov // LHS => = 4526a399bf4SDenys Petrov // ___________________ ___________________ 4536a399bf4SDenys Petrov this->checkUnite({}, {}, {}); 4546a399bf4SDenys Petrov 4556a399bf4SDenys Petrov // RHS is empty. 4566a399bf4SDenys Petrov // RHS => 4576a399bf4SDenys Petrov // LHS => _____ = _____ 4586a399bf4SDenys Petrov // ______/_____\______ ______/_____\______ 4596a399bf4SDenys Petrov this->checkUnite({{A, B}}, {}, {{A, B}}); 4606a399bf4SDenys Petrov this->checkUnite({{A, B}, {C, D}}, {}, {{A, B}, {C, D}}); 4616a399bf4SDenys Petrov this->checkUnite({{MIN, MIN}}, {}, {{MIN, MIN}}); 4626a399bf4SDenys Petrov this->checkUnite({{MAX, MAX}}, {}, {{MAX, MAX}}); 4636a399bf4SDenys Petrov this->checkUnite({{MIN, MIN}, {MAX, MAX}}, {}, {{MIN, MIN}, {MAX, MAX}}); 4646a399bf4SDenys Petrov 4656a399bf4SDenys Petrov // LHS is empty. 4666a399bf4SDenys Petrov // RHS => ___ 4676a399bf4SDenys Petrov // LHS => / \ = _____ 4686a399bf4SDenys Petrov // ______/_____\______ ______/_____\______ 4696a399bf4SDenys Petrov this->checkUnite({}, B, {{B, B}}); 4706a399bf4SDenys Petrov this->checkUnite({}, {B, C}, {{B, C}}); 4716a399bf4SDenys Petrov this->checkUnite({}, {{MIN, B}, {C, MAX}}, {{MIN, B}, {C, MAX}}); 4726a399bf4SDenys Petrov this->checkUnite({}, {{MIN, MIN}}, {{MIN, MIN}}); 4736a399bf4SDenys Petrov this->checkUnite({}, {{MAX, MAX}}, {{MAX, MAX}}); 4746a399bf4SDenys Petrov this->checkUnite({}, {{MIN, MIN}, {MAX, MAX}}, {{MIN, MIN}, {MAX, MAX}}); 4756a399bf4SDenys Petrov 4766a399bf4SDenys Petrov // RHS is detached from LHS. 4776a399bf4SDenys Petrov // RHS => ___ 4786a399bf4SDenys Petrov // LHS => ___ / \ = ___ _____ 4796a399bf4SDenys Petrov // __/___\___/_____\__ __/___\___/_____\__ 4806a399bf4SDenys Petrov this->checkUnite({{A, C}}, D, {{A, C}, {D, D}}); 4816a399bf4SDenys Petrov this->checkUnite({{MID, C}, {D, MAX}}, A, {{A, A}, {MID, C}, {D, MAX}}); 4826a399bf4SDenys Petrov this->checkUnite({{A, B}}, {MID, D}, {{A, B}, {MID, D}}); 4836a399bf4SDenys Petrov this->checkUnite({{MIN, A}, {D, MAX}}, {B, C}, {{MIN, A}, {B, C}, {D, MAX}}); 4846a399bf4SDenys Petrov this->checkUnite({{B, MID}, {D, MAX}}, {{MIN, A}, {C, C}}, 4856a399bf4SDenys Petrov {{MIN, A}, {B, MID}, {C, C}, {D, MAX}}); 4866a399bf4SDenys Petrov this->checkUnite({{MIN, A}, {C, C}}, {{B, MID}, {D, MAX}}, 4876a399bf4SDenys Petrov {{MIN, A}, {B, MID}, {C, C}, {D, MAX}}); 4886a399bf4SDenys Petrov this->checkUnite({{A, B}}, {{MAX, MAX}}, {{A, B}, {MAX, MAX}}); 4896a399bf4SDenys Petrov this->checkUnite({{MIN, MIN}}, {A, B}, {{MIN, MIN}, {A, B}}); 4906a399bf4SDenys Petrov this->checkUnite({{MIN, MIN}}, {MAX, MAX}, {{MIN, MIN}, {MAX, MAX}}); 4916a399bf4SDenys Petrov 4926a399bf4SDenys Petrov // RHS is inside LHS. 4936a399bf4SDenys Petrov // RHS => ___ 4946a399bf4SDenys Petrov // LHS => ___/___\___ = ___________ 4956a399bf4SDenys Petrov // ___/__/_____\__\___ ___/___________\___ 4966a399bf4SDenys Petrov this->checkUnite({{A, C}}, MID, {{A, C}}); 4976a399bf4SDenys Petrov this->checkUnite({{A, D}}, {B, C}, {{A, D}}); 4986a399bf4SDenys Petrov this->checkUnite({{MIN, MAX}}, {B, C}, {{MIN, MAX}}); 4996a399bf4SDenys Petrov 5006a399bf4SDenys Petrov // RHS wraps LHS. 5016a399bf4SDenys Petrov // RHS => _________ 5026a399bf4SDenys Petrov // LHS => / _____ \ = ___________ 5036a399bf4SDenys Petrov // ___/__/_____\__\___ ___/___________\___ 5046a399bf4SDenys Petrov this->checkUnite({{MID, MID}}, {A, D}, {{A, D}}); 5056a399bf4SDenys Petrov this->checkUnite({{B, C}}, {A, D}, {{A, D}}); 5066a399bf4SDenys Petrov this->checkUnite({{A, B}}, {MIN, MAX}, {{MIN, MAX}}); 5076a399bf4SDenys Petrov 5086a399bf4SDenys Petrov // RHS equals to LHS. 5096a399bf4SDenys Petrov // RHS => _________ 5106a399bf4SDenys Petrov // LHS => /_________\ = ___________ 5116a399bf4SDenys Petrov // ___/___________\___ ___/___________\___ 5126a399bf4SDenys Petrov this->checkUnite({{MIN, MIN}}, MIN, {{MIN, MIN}}); 5136a399bf4SDenys Petrov this->checkUnite({{A, B}}, {A, B}, {{A, B}}); 5146a399bf4SDenys Petrov this->checkUnite({{MAX, MAX}}, {{MAX, MAX}}, {{MAX, MAX}}); 5156a399bf4SDenys Petrov this->checkUnite({{MIN, MIN}}, {{MIN, MIN}}, {{MIN, MIN}}); 5166a399bf4SDenys Petrov this->checkUnite({{MIN, MIN}, {MAX, MAX}}, {{MIN, MIN}, {MAX, MAX}}, 5176a399bf4SDenys Petrov {{MIN, MIN}, {MAX, MAX}}); 5186a399bf4SDenys Petrov 5196a399bf4SDenys Petrov // RHS edge is MIN and attached and inside LHS. 5206a399bf4SDenys Petrov // RHS => _____ 5216a399bf4SDenys Petrov // LHS => /_____\_____ = ___________ 5226a399bf4SDenys Petrov // /_______\____\___ /___________\___ 5236a399bf4SDenys Petrov this->checkUnite({{MIN, A}}, {MIN, B}, {{MIN, B}}); 5246a399bf4SDenys Petrov 5256a399bf4SDenys Petrov // RHS edge is MIN and attached and outsude LHS. 5266a399bf4SDenys Petrov // RHS => __________ 5276a399bf4SDenys Petrov // LHS => /______ \ = ___________ 5286a399bf4SDenys Petrov // /_______\____\___ /___________\___ 5296a399bf4SDenys Petrov this->checkUnite({{MIN, B}}, {MIN, A}, {{MIN, B}}); 5306a399bf4SDenys Petrov 5316a399bf4SDenys Petrov // RHS intersects right of LHS. 5326a399bf4SDenys Petrov // RHS => ______ 5336a399bf4SDenys Petrov // LHS => ___/____ \ = ___________ 5346a399bf4SDenys Petrov // ___/__/_____\__\___ ___/___________\___ 5356a399bf4SDenys Petrov this->checkUnite({{A, C}}, C, {{A, C}}); 5366a399bf4SDenys Petrov this->checkUnite({{A, C}}, {B, D}, {{A, D}}); 5376a399bf4SDenys Petrov 5386a399bf4SDenys Petrov // RHS intersects left of LHS. 5396a399bf4SDenys Petrov // RHS => ______ 5406a399bf4SDenys Petrov // LHS => / ____\___ = ___________ 5416a399bf4SDenys Petrov // ___/__/_____\__\___ ___/___________\___ 5426a399bf4SDenys Petrov this->checkUnite({{B, D}}, B, {{B, D}}); 5436a399bf4SDenys Petrov this->checkUnite({{B, D}}, {A, C}, {{A, D}}); 5446a399bf4SDenys Petrov this->checkUnite({{MID, MAX}}, {MIN, MID}, {{MIN, MAX}}); 5456a399bf4SDenys Petrov 5466a399bf4SDenys Petrov // RHS adjacent to LHS on right. 5476a399bf4SDenys Petrov // RHS => _____ 5486a399bf4SDenys Petrov // LHS => ______ / \ = _______________ 5496a399bf4SDenys Petrov // _/______\/_______\_ _/_______________\_ 5506a399bf4SDenys Petrov this->checkUnite({{A, B - 1}}, B, {{A, B}}); 5516a399bf4SDenys Petrov this->checkUnite({{A, C}}, {C + 1, D}, {{A, D}}); 5526a399bf4SDenys Petrov this->checkUnite({{MIN, MID}}, {MID + 1, MAX}, {{MIN, MAX}}); 5536a399bf4SDenys Petrov 5546a399bf4SDenys Petrov // RHS adjacent to LHS on left. 5556a399bf4SDenys Petrov // RHS => _____ 5566a399bf4SDenys Petrov // LHS => / \ ______ = _______________ 5576a399bf4SDenys Petrov // _/_______\/______\_ _/_______________\_ 5586a399bf4SDenys Petrov this->checkUnite({{B + 1, C}}, B, {{B, C}}); 5596a399bf4SDenys Petrov this->checkUnite({{B, D}}, {A, B - 1}, {{A, D}}); 5606a399bf4SDenys Petrov 5616a399bf4SDenys Petrov // RHS adjacent to LHS in between. 5626a399bf4SDenys Petrov // RHS => ___ 5636a399bf4SDenys Petrov // LHS => ___ / \ ___ = _______________ 5646a399bf4SDenys Petrov // _/___\/_____\/___\_ _/_______________\_ 5656a399bf4SDenys Petrov this->checkUnite({{A, MID - 1}, {MID + 1, D}}, MID, {{A, D}}); 5666a399bf4SDenys Petrov this->checkUnite({{MIN, A}, {D, MAX}}, {A + 1, D - 1}, {{MIN, MAX}}); 5676a399bf4SDenys Petrov 5686a399bf4SDenys Petrov // RHS adjacent to LHS on the outside. 5696a399bf4SDenys Petrov // RHS => __ __ 5706a399bf4SDenys Petrov // LHS => / \ ___ / \ = _______________ 5716a399bf4SDenys Petrov // _/____\/___\/____\_ _/_______________\_ 5726a399bf4SDenys Petrov this->checkUnite({{C, C}}, {{A, C - 1}, {C + 1, D}}, {{A, D}}); 5736a399bf4SDenys Petrov this->checkUnite({{B, MID}}, {{A, B - 1}, {MID + 1, D}}, {{A, D}}); 5746a399bf4SDenys Petrov 5756a399bf4SDenys Petrov // RHS wraps two subranges of LHS. 5766a399bf4SDenys Petrov // RHS => ___________ 5776a399bf4SDenys Petrov // LHS => / ___ ___ \ = _____________ 5786a399bf4SDenys Petrov // __/_/___\_/___\_\__ __/_____________\__ 5796a399bf4SDenys Petrov this->checkUnite({{B, B}, {MID, MID}, {C, C}}, {{A, D}}, {{A, D}}); 5806a399bf4SDenys Petrov this->checkUnite({{A, B}, {MID, C}}, {{MIN, D}}, {{MIN, D}}); 5816a399bf4SDenys Petrov 5826a399bf4SDenys Petrov // RHS intersects two subranges of LHS. 5836a399bf4SDenys Petrov // RHS => _________ 5846a399bf4SDenys Petrov // LHS => __/__ _\__ = _______________ 5856a399bf4SDenys Petrov // _/_/___\____/__\_\_ _/_______________\_ 5866a399bf4SDenys Petrov this->checkUnite({{MIN, B}, {C, MAX}}, {{A, D}}, {{MIN, MAX}}); 5876a399bf4SDenys Petrov this->checkUnite({{A, MID}, {C, MAX}}, {{B, D}}, {{A, MAX}}); 5886a399bf4SDenys Petrov 5896a399bf4SDenys Petrov // Multiple intersections. 5906a399bf4SDenys Petrov 5916a399bf4SDenys Petrov // clang-format off 5926a399bf4SDenys Petrov // RHS => 5936a399bf4SDenys Petrov // LHS => /\ /\ = __ __ 5946a399bf4SDenys Petrov // _/__\_/__\_/\_/\_/\_ _/__\_/__\_/\_/\_/\_ 5956a399bf4SDenys Petrov this->checkUnite({{MID, C}, {C + 2, D - 2}, {D, MAX}}, 5966a399bf4SDenys Petrov {{MIN, A}, {A + 2, B}}, 5976a399bf4SDenys Petrov {{MIN, A}, {A + 2, B}, {MID, C}, {C + 2, D - 2}, {D, MAX}}); 5986a399bf4SDenys Petrov this->checkUnite({{B, B}, {C, C}, {MAX, MAX}}, 5996a399bf4SDenys Petrov {{MIN, MIN}, {A, A}}, 6006a399bf4SDenys Petrov {{MIN, MIN}, {A, A}, {B, B}, {C, C}, {MAX, MAX}}); 6016a399bf4SDenys Petrov 6026a399bf4SDenys Petrov // RHS => 6036a399bf4SDenys Petrov // LHS => /\ /\ = __ __ 6046a399bf4SDenys Petrov // _/\_/\_/\__/__\_/__\_ _/\_/\_/\_/__\_/__\_ 6056a399bf4SDenys Petrov this->checkUnite({{MIN, A}, {A + 2, B}, {MID, C}}, 6066a399bf4SDenys Petrov {{C + 2, D - 2}, {D, MAX}}, 6076a399bf4SDenys Petrov {{MIN, A}, {A + 2, B}, {MID, C}, {C + 2, D - 2}, {D, MAX}}); 6086a399bf4SDenys Petrov this->checkUnite({{MIN, MIN}, {A, A}, {B, B}}, 6096a399bf4SDenys Petrov {{C, C}, {MAX, MAX}}, 6106a399bf4SDenys Petrov {{MIN, MIN}, {A, A}, {B, B}, {C, C}, {MAX, MAX}}); 6116a399bf4SDenys Petrov 6126a399bf4SDenys Petrov // RHS => 6136a399bf4SDenys Petrov // LHS => _ /\ _ /\ _ /\ = 6146a399bf4SDenys Petrov // _/_\_/__\_/_\_/__\_/_\_/__\_ 6156a399bf4SDenys Petrov // 6166a399bf4SDenys Petrov // RSLT => _ __ _ __ _ __ 6176a399bf4SDenys Petrov // _/_\_/__\_/_\_/__\_/_\_/__\_ 6186a399bf4SDenys Petrov this->checkUnite({{MIN, A}, {B + 2, MID}, {C + 2, D}}, 6196a399bf4SDenys Petrov {{A + 2, B}, {MID + 2, C}, {D + 2, MAX}}, 6206a399bf4SDenys Petrov {{MIN, A}, {A + 2, B}, {B + 2, MID}, {MID + 2, C}, {C + 2, D}, {D + 2, MAX}}); 6216a399bf4SDenys Petrov this->checkUnite({{MIN, MIN}, {B, B}, {D, D}}, 6226a399bf4SDenys Petrov {{A, A}, {C, C}, {MAX, MAX}}, 6236a399bf4SDenys Petrov {{MIN, MIN}, {A, A}, {B, B}, {C, C}, {D, D}, {MAX, MAX}}); 6246a399bf4SDenys Petrov 6256a399bf4SDenys Petrov // RHS => 6266a399bf4SDenys Petrov // LHS => /\ _ /\ _ /\ _ = 6276a399bf4SDenys Petrov // _/__\_/_\_/__\_/_\_/__\_/_\_ 6286a399bf4SDenys Petrov // 6296a399bf4SDenys Petrov // RSLT => __ _ __ _ __ _ 6306a399bf4SDenys Petrov // _/__\_/_\_/__\_/_\_/__\_/_\_ 6316a399bf4SDenys Petrov this->checkUnite({{A + 2, B}, {MID + 2, C}, {D + 2, MAX}}, 6326a399bf4SDenys Petrov {{MIN, A}, {B + 2, MID}, {C + 2, D}}, 6336a399bf4SDenys Petrov {{MIN, A}, {A + 2, B}, {B + 2, MID}, {MID + 2, C}, {C + 2, D}, {D + 2, MAX}}); 6346a399bf4SDenys Petrov this->checkUnite({{A, A}, {C, C}, {MAX, MAX}}, 6356a399bf4SDenys Petrov {{MIN, MIN}, {B, B}, {D, D}}, 6366a399bf4SDenys Petrov {{MIN, MIN}, {A, A}, {B, B}, {C, C}, {D, D}, {MAX, MAX}}); 6376a399bf4SDenys Petrov 6386a399bf4SDenys Petrov // RHS => _ __ _ 6396a399bf4SDenys Petrov // LHS => /_\ /_ \ _ / \ = ___ ____________ 6406a399bf4SDenys Petrov // _/___\_/__\_\/_\/___\_ _/___\_/____________\_ 6416a399bf4SDenys Petrov this->checkUnite({{MIN, A}, {B, C}, {D, MAX}}, 6426a399bf4SDenys Petrov {{MIN, A}, {B, C - 2}, {C + 1, D - 1}}, 6436a399bf4SDenys Petrov {{MIN, A}, {B, MAX}}); 6446a399bf4SDenys Petrov this->checkUnite({{A, A}, {B, MID}, {D, D}}, 6456a399bf4SDenys Petrov {{A, A}, {B, B}, {MID + 1, D - 1}}, 6466a399bf4SDenys Petrov {{A, A}, {B, D}}); 6476a399bf4SDenys Petrov 6486a399bf4SDenys Petrov // RHS => ___ ___ 6496a399bf4SDenys Petrov // LHS => /\ _/_ \_ / _ \ /\ = 6506a399bf4SDenys Petrov // _/\_/__\//__\ /\\_/_/_\_\_/__\_ 6516a399bf4SDenys Petrov // 6526a399bf4SDenys Petrov // RSLT => ___________ _____ __ 6536a399bf4SDenys Petrov // _/\_/___________\_/_____\_/__\_ 6546a399bf4SDenys Petrov this->checkUnite({{MIN, MIN}, {B, MID}, {MID + 1, C}, {C + 4, D - 1}}, 6556a399bf4SDenys Petrov {{A, B - 1}, {B + 1, C - 1}, {C + 2, D}, {MAX - 1, MAX}}, 6566a399bf4SDenys Petrov {{MIN, MIN}, {A, C}, {C + 2, D}, {MAX - 1, MAX}}); 6576a399bf4SDenys Petrov // clang-format on 6586a399bf4SDenys Petrov } 659e37726beSDenys Petrov 660e37726beSDenys Petrov template <typename From, typename To> struct CastType { 661e37726beSDenys Petrov using FromType = From; 662e37726beSDenys Petrov using ToType = To; 663e37726beSDenys Petrov }; 664e37726beSDenys Petrov 665e37726beSDenys Petrov template <typename Type> 666e37726beSDenys Petrov class RangeSetCastToNoopTest : public RangeSetTest<typename Type::FromType> {}; 667e37726beSDenys Petrov template <typename Type> 668e37726beSDenys Petrov class RangeSetCastToPromotionTest 669e37726beSDenys Petrov : public RangeSetTest<typename Type::FromType> {}; 670e37726beSDenys Petrov template <typename Type> 671e37726beSDenys Petrov class RangeSetCastToTruncationTest 672e37726beSDenys Petrov : public RangeSetTest<typename Type::FromType> {}; 673e37726beSDenys Petrov template <typename Type> 674e37726beSDenys Petrov class RangeSetCastToConversionTest 675e37726beSDenys Petrov : public RangeSetTest<typename Type::FromType> {}; 676e37726beSDenys Petrov template <typename Type> 677e37726beSDenys Petrov class RangeSetCastToPromotionConversionTest 678e37726beSDenys Petrov : public RangeSetTest<typename Type::FromType> {}; 679e37726beSDenys Petrov template <typename Type> 680e37726beSDenys Petrov class RangeSetCastToTruncationConversionTest 681e37726beSDenys Petrov : public RangeSetTest<typename Type::FromType> {}; 682e37726beSDenys Petrov 683e37726beSDenys Petrov using NoopCastTypes = 684e37726beSDenys Petrov ::testing::Types<CastType<int8_t, int8_t>, CastType<uint8_t, uint8_t>, 685e37726beSDenys Petrov CastType<int16_t, int16_t>, CastType<uint16_t, uint16_t>, 686e37726beSDenys Petrov CastType<int32_t, int32_t>, CastType<uint32_t, uint32_t>, 687e37726beSDenys Petrov CastType<int64_t, int64_t>, CastType<uint64_t, uint64_t>>; 688e37726beSDenys Petrov 689e37726beSDenys Petrov using PromotionCastTypes = 690e37726beSDenys Petrov ::testing::Types<CastType<int8_t, int16_t>, CastType<int8_t, int32_t>, 691e37726beSDenys Petrov CastType<int8_t, int64_t>, CastType<uint8_t, uint16_t>, 692e37726beSDenys Petrov CastType<uint8_t, uint32_t>, CastType<uint8_t, uint64_t>, 693e37726beSDenys Petrov CastType<int16_t, int32_t>, CastType<int16_t, int64_t>, 694e37726beSDenys Petrov CastType<uint16_t, uint32_t>, CastType<uint16_t, uint64_t>, 695e37726beSDenys Petrov CastType<int32_t, int64_t>, CastType<uint32_t, uint64_t>>; 696e37726beSDenys Petrov 697e37726beSDenys Petrov using TruncationCastTypes = 698e37726beSDenys Petrov ::testing::Types<CastType<int16_t, int8_t>, CastType<uint16_t, uint8_t>, 699e37726beSDenys Petrov CastType<int32_t, int16_t>, CastType<int32_t, int8_t>, 700e37726beSDenys Petrov CastType<uint32_t, uint16_t>, CastType<uint32_t, uint8_t>, 701e37726beSDenys Petrov CastType<int64_t, int32_t>, CastType<int64_t, int16_t>, 702e37726beSDenys Petrov CastType<int64_t, int8_t>, CastType<uint64_t, uint32_t>, 703e37726beSDenys Petrov CastType<uint64_t, uint16_t>, CastType<uint64_t, uint8_t>>; 704e37726beSDenys Petrov 705e37726beSDenys Petrov using ConversionCastTypes = 706e37726beSDenys Petrov ::testing::Types<CastType<int8_t, uint8_t>, CastType<uint8_t, int8_t>, 707e37726beSDenys Petrov CastType<int16_t, uint16_t>, CastType<uint16_t, int16_t>, 708e37726beSDenys Petrov CastType<int32_t, uint32_t>, CastType<uint32_t, int32_t>, 709e37726beSDenys Petrov CastType<int64_t, uint64_t>, CastType<uint64_t, int64_t>>; 710e37726beSDenys Petrov 711e37726beSDenys Petrov using PromotionConversionCastTypes = 712e37726beSDenys Petrov ::testing::Types<CastType<int8_t, uint16_t>, CastType<int8_t, uint32_t>, 713e37726beSDenys Petrov CastType<int8_t, uint64_t>, CastType<uint8_t, int16_t>, 714e37726beSDenys Petrov CastType<uint8_t, int32_t>, CastType<uint8_t, int64_t>, 715e37726beSDenys Petrov CastType<int16_t, uint32_t>, CastType<int16_t, uint64_t>, 716e37726beSDenys Petrov CastType<uint16_t, int32_t>, CastType<uint16_t, int64_t>, 717e37726beSDenys Petrov CastType<int32_t, uint64_t>, CastType<uint32_t, int64_t>>; 718e37726beSDenys Petrov 719e37726beSDenys Petrov using TruncationConversionCastTypes = 720e37726beSDenys Petrov ::testing::Types<CastType<int16_t, uint8_t>, CastType<uint16_t, int8_t>, 721e37726beSDenys Petrov CastType<int32_t, uint16_t>, CastType<int32_t, uint8_t>, 722e37726beSDenys Petrov CastType<uint32_t, int16_t>, CastType<uint32_t, int8_t>, 723e37726beSDenys Petrov CastType<int64_t, uint32_t>, CastType<int64_t, uint16_t>, 724e37726beSDenys Petrov CastType<int64_t, uint8_t>, CastType<uint64_t, int32_t>, 725e37726beSDenys Petrov CastType<uint64_t, int16_t>, CastType<uint64_t, int8_t>>; 726e37726beSDenys Petrov 72725b03ae7SPhilipp Tomsich TYPED_TEST_SUITE(RangeSetCastToNoopTest, NoopCastTypes, ); 72825b03ae7SPhilipp Tomsich TYPED_TEST_SUITE(RangeSetCastToPromotionTest, PromotionCastTypes, ); 72925b03ae7SPhilipp Tomsich TYPED_TEST_SUITE(RangeSetCastToTruncationTest, TruncationCastTypes, ); 73025b03ae7SPhilipp Tomsich TYPED_TEST_SUITE(RangeSetCastToConversionTest, ConversionCastTypes, ); 731e37726beSDenys Petrov TYPED_TEST_SUITE(RangeSetCastToPromotionConversionTest, 73225b03ae7SPhilipp Tomsich PromotionConversionCastTypes, ); 733e37726beSDenys Petrov TYPED_TEST_SUITE(RangeSetCastToTruncationConversionTest, 73425b03ae7SPhilipp Tomsich TruncationConversionCastTypes, ); 735e37726beSDenys Petrov 736e37726beSDenys Petrov TYPED_TEST(RangeSetCastToNoopTest, RangeSetCastToNoopTest) { 737e37726beSDenys Petrov // Just to reduce the verbosity. 738e37726beSDenys Petrov using F = typename TypeParam::FromType; // From 739e37726beSDenys Petrov using T = typename TypeParam::ToType; // To 740e37726beSDenys Petrov 741e37726beSDenys Petrov using TV = TestValues<F>; 742e37726beSDenys Petrov constexpr auto MIN = TV::MIN; 743e37726beSDenys Petrov constexpr auto MAX = TV::MAX; 744e37726beSDenys Petrov constexpr auto MID = TV::MID; 745e37726beSDenys Petrov constexpr auto B = TV::B; 746e37726beSDenys Petrov constexpr auto C = TV::C; 747e37726beSDenys Petrov // One point 748e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MIN}}, {{MIN, MIN}}); 749e37726beSDenys Petrov this->template checkCastTo<F, T>({{MAX, MAX}}, {{MAX, MAX}}); 750e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MID}}, {{MID, MID}}); 751e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, B}}, {{B, B}}); 752e37726beSDenys Petrov this->template checkCastTo<F, T>({{C, C}}, {{C, C}}); 753e37726beSDenys Petrov // Two points 754e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MIN}, {MAX, MAX}}, 755e37726beSDenys Petrov {{MIN, MIN}, {MAX, MAX}}); 756e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MIN}, {B, B}}, {{MIN, MIN}, {B, B}}); 757e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MID}, {MAX, MAX}}, 758e37726beSDenys Petrov {{MID, MID}, {MAX, MAX}}); 759e37726beSDenys Petrov this->template checkCastTo<F, T>({{C, C}, {MAX, MAX}}, {{C, C}, {MAX, MAX}}); 760e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MID}, {C, C}}, {{MID, MID}, {C, C}}); 761e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, B}, {MID, MID}}, {{B, B}, {MID, MID}}); 762e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, B}, {C, C}}, {{B, B}, {C, C}}); 763e37726beSDenys Petrov // One range 764e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MAX}}, {{MIN, MAX}}); 765e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MID}}, {{MIN, MID}}); 766e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MAX}}, {{MID, MAX}}); 767e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, MAX}}, {{B, MAX}}); 768e37726beSDenys Petrov this->template checkCastTo<F, T>({{C, MAX}}, {{C, MAX}}); 769e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, C}}, {{MIN, C}}); 770e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, B}}, {{MIN, B}}); 771e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, C}}, {{B, C}}); 772e37726beSDenys Petrov // Two ranges 773e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, B}, {C, MAX}}, {{MIN, B}, {C, MAX}}); 774e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, MID}, {C, MAX}}, {{B, MID}, {C, MAX}}); 775e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, B}, {MID, C}}, {{MIN, B}, {MID, C}}); 776e37726beSDenys Petrov } 777e37726beSDenys Petrov 778e37726beSDenys Petrov TYPED_TEST(RangeSetCastToPromotionTest, Test) { 779e37726beSDenys Petrov // Just to reduce the verbosity. 780e37726beSDenys Petrov using F = typename TypeParam::FromType; // From 781e37726beSDenys Petrov using T = typename TypeParam::ToType; // To 782e37726beSDenys Petrov 783e37726beSDenys Petrov using TV = TestValues<F>; 784e37726beSDenys Petrov constexpr auto MIN = TV::MIN; 785e37726beSDenys Petrov constexpr auto MAX = TV::MAX; 786e37726beSDenys Petrov constexpr auto MID = TV::MID; 787e37726beSDenys Petrov constexpr auto B = TV::B; 788e37726beSDenys Petrov constexpr auto C = TV::C; 789e37726beSDenys Petrov // One point 790e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MIN}}, {{MIN, MIN}}); 791e37726beSDenys Petrov this->template checkCastTo<F, T>({{MAX, MAX}}, {{MAX, MAX}}); 792e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MID}}, {{MID, MID}}); 793e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, B}}, {{B, B}}); 794e37726beSDenys Petrov this->template checkCastTo<F, T>({{C, C}}, {{C, C}}); 795e37726beSDenys Petrov // Two points 796e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MIN}, {MAX, MAX}}, 797e37726beSDenys Petrov {{MIN, MIN}, {MAX, MAX}}); 798e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MIN}, {B, B}}, {{MIN, MIN}, {B, B}}); 799e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MID}, {MAX, MAX}}, 800e37726beSDenys Petrov {{MID, MID}, {MAX, MAX}}); 801e37726beSDenys Petrov this->template checkCastTo<F, T>({{C, C}, {MAX, MAX}}, {{C, C}, {MAX, MAX}}); 802e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MID}, {C, C}}, {{MID, MID}, {C, C}}); 803e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, B}, {MID, MID}}, {{B, B}, {MID, MID}}); 804e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, B}, {C, C}}, {{B, B}, {C, C}}); 805e37726beSDenys Petrov // One range 806e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MAX}}, {{MIN, MAX}}); 807e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MID}}, {{MIN, MID}}); 808e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MAX}}, {{MID, MAX}}); 809e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, MAX}}, {{B, MAX}}); 810e37726beSDenys Petrov this->template checkCastTo<F, T>({{C, MAX}}, {{C, MAX}}); 811e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, C}}, {{MIN, C}}); 812e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, B}}, {{MIN, B}}); 813e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, C}}, {{B, C}}); 814e37726beSDenys Petrov // Two ranges 815e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, B}, {C, MAX}}, {{MIN, B}, {C, MAX}}); 816e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, MID}, {C, MAX}}, {{B, MID}, {C, MAX}}); 817e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, B}, {MID, C}}, {{MIN, B}, {MID, C}}); 818e37726beSDenys Petrov } 819e37726beSDenys Petrov 820e37726beSDenys Petrov TYPED_TEST(RangeSetCastToTruncationTest, Test) { 821e37726beSDenys Petrov // Just to reduce the verbosity. 822e37726beSDenys Petrov using F = typename TypeParam::FromType; // From 823e37726beSDenys Petrov using T = typename TypeParam::ToType; // To 824e37726beSDenys Petrov 825e37726beSDenys Petrov using TV = TestValues<F>; 826e37726beSDenys Petrov constexpr auto MIN = TV::MIN; 827e37726beSDenys Petrov constexpr auto MAX = TV::MAX; 828e37726beSDenys Petrov constexpr auto MID = TV::MID; 829e37726beSDenys Petrov constexpr auto B = TV::B; 830e37726beSDenys Petrov constexpr auto C = TV::C; 831e37726beSDenys Petrov // One point 832e37726beSDenys Petrov // 833e37726beSDenys Petrov // NOTE: We can't use ToMIN, ToMAX, ... everywhere. That would be incorrect: 834e37726beSDenys Petrov // int16(-32768, 32767) -> int8(-128, 127), 835e37726beSDenys Petrov // aka (MIN, MAX) -> (ToMIN, ToMAX) // OK. 836e37726beSDenys Petrov // int16(-32768, -32768) -> int8(-128, -128), 837e37726beSDenys Petrov // aka (MIN, MIN) -> (ToMIN, ToMIN) // NOK. 838e37726beSDenys Petrov // int16(-32768,-32768) -> int8(0, 0), 839e37726beSDenys Petrov // aka (MIN, MIN) -> ((int8)MIN, (int8)MIN) // OK. 840e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MIN}}, {{MIN, MIN}}); 841e37726beSDenys Petrov this->template checkCastTo<F, T>({{MAX, MAX}}, {{MAX, MAX}}); 842e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MID}}, {{MID, MID}}); 843e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, B}}, {{B, B}}); 844e37726beSDenys Petrov this->template checkCastTo<F, T>({{C, C}}, {{C, C}}); 845e37726beSDenys Petrov // Two points 846e37726beSDenys Petrov // Use `if constexpr` here. 847e37726beSDenys Petrov if (is_signed_v<F>) { 848e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MIN}, {MAX, MAX}}, {{MAX, MIN}}); 849e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MID}, {MAX, MAX}}, {{MAX, MID}}); 850e37726beSDenys Petrov } else { 851e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MIN}, {MAX, MAX}}, 852e37726beSDenys Petrov {{MIN, MIN}, {MAX, MAX}}); 853e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MID}, {MAX, MAX}}, 854e37726beSDenys Petrov {{MID, MID}, {MAX, MAX}}); 855e37726beSDenys Petrov } 856e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MIN}, {B, B}}, {{MIN, MIN}, {B, B}}); 857e37726beSDenys Petrov this->template checkCastTo<F, T>({{C, C}, {MAX, MAX}}, {{C, C}, {MAX, MAX}}); 858e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MID}, {C, C}}, {{MID, MID}, {C, C}}); 859e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, B}, {MID, MID}}, {{B, B}, {MID, MID}}); 860e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, B}, {C, C}}, {{B, B}, {C, C}}); 861e37726beSDenys Petrov // One range 862e37726beSDenys Petrov constexpr auto ToMIN = TestValues<T>::MIN; 863e37726beSDenys Petrov constexpr auto ToMAX = TestValues<T>::MAX; 864e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MAX}}, {{ToMIN, ToMAX}}); 865e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MID}}, {{ToMIN, ToMAX}}); 866e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MAX}}, {{ToMIN, ToMAX}}); 867e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, MAX}}, {{ToMIN, ToMAX}}); 868e37726beSDenys Petrov this->template checkCastTo<F, T>({{C, MAX}}, {{ToMIN, ToMAX}}); 869e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, C}}, {{ToMIN, ToMAX}}); 870e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, B}}, {{ToMIN, ToMAX}}); 871e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, C}}, {{ToMIN, ToMAX}}); 872e37726beSDenys Petrov // Two ranges 873e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, B}, {C, MAX}}, {{ToMIN, ToMAX}}); 874e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, MID}, {C, MAX}}, {{ToMIN, ToMAX}}); 875e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, B}, {MID, C}}, {{ToMIN, ToMAX}}); 876e37726beSDenys Petrov constexpr auto XAAA = TV::XAAA; 877e37726beSDenys Petrov constexpr auto X555 = TV::X555; 878e37726beSDenys Petrov constexpr auto ZA = TV::template XAAATruncZeroOf<T>; 879e37726beSDenys Petrov constexpr auto Z5 = TV::template X555TruncZeroOf<T>; 880e37726beSDenys Petrov this->template checkCastTo<F, T>({{XAAA, ZA}, {X555, Z5}}, 881e37726beSDenys Petrov {{ToMIN, 0}, {X555, ToMAX}}); 882e37726beSDenys Petrov // Use `if constexpr` here. 883e37726beSDenys Petrov if (is_signed_v<F>) { 884e37726beSDenys Petrov // One range 885e37726beSDenys Petrov this->template checkCastTo<F, T>({{XAAA, ZA}}, {{XAAA, 0}}); 886e37726beSDenys Petrov // Two ranges 887e37726beSDenys Petrov this->template checkCastTo<F, T>({{XAAA, ZA}, {1, 42}}, {{XAAA, 42}}); 888e37726beSDenys Petrov } else { 889e37726beSDenys Petrov // One range 890e37726beSDenys Petrov this->template checkCastTo<F, T>({{XAAA, ZA}}, {{0, 0}, {XAAA, ToMAX}}); 891e37726beSDenys Petrov // Two ranges 892e37726beSDenys Petrov this->template checkCastTo<F, T>({{1, 42}, {XAAA, ZA}}, 893e37726beSDenys Petrov {{0, 42}, {XAAA, ToMAX}}); 894e37726beSDenys Petrov } 895e37726beSDenys Petrov constexpr auto FromA = TV::FromA; 896e37726beSDenys Petrov constexpr auto ToA = TV::ToA; 897e37726beSDenys Petrov constexpr auto FromB = TV::FromB; 898e37726beSDenys Petrov constexpr auto ToB = TV::ToB; 899e37726beSDenys Petrov // int16 -> int8 900e37726beSDenys Petrov // (0x00'01, 0x00'05)U(0xFF'01, 0xFF'05) casts to 901e37726beSDenys Petrov // (0x01, 0x05)U(0x01, 0x05) unites to 902e37726beSDenys Petrov // (0x01, 0x05) 903e37726beSDenys Petrov this->template checkCastTo<F, T>({{FromA, ToA}, {FromB, ToB}}, 904e37726beSDenys Petrov {{FromA, ToA}}); 905e37726beSDenys Petrov } 906e37726beSDenys Petrov 907e37726beSDenys Petrov TYPED_TEST(RangeSetCastToConversionTest, Test) { 908e37726beSDenys Petrov // Just to reduce the verbosity. 909e37726beSDenys Petrov using F = typename TypeParam::FromType; // From 910e37726beSDenys Petrov using T = typename TypeParam::ToType; // To 911e37726beSDenys Petrov 912e37726beSDenys Petrov using TV = TestValues<F>; 913e37726beSDenys Petrov constexpr auto MIN = TV::MIN; 914e37726beSDenys Petrov constexpr auto MAX = TV::MAX; 915e37726beSDenys Petrov constexpr auto MID = TV::MID; 916e37726beSDenys Petrov constexpr auto B = TV::B; 917e37726beSDenys Petrov constexpr auto C = TV::C; 918e37726beSDenys Petrov // One point 919e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MIN}}, {{MIN, MIN}}); 920e37726beSDenys Petrov this->template checkCastTo<F, T>({{MAX, MAX}}, {{MAX, MAX}}); 921e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MID}}, {{MID, MID}}); 922e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, B}}, {{B, B}}); 923e37726beSDenys Petrov this->template checkCastTo<F, T>({{C, C}}, {{C, C}}); 924e37726beSDenys Petrov // Two points 925e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MIN}, {MAX, MAX}}, {{MAX, MIN}}); 926e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MID}, {MAX, MAX}}, 927e37726beSDenys Petrov {{MID, MID}, {MAX, MAX}}); 928e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MIN}, {B, B}}, {{MIN, MIN}, {B, B}}); 929e37726beSDenys Petrov this->template checkCastTo<F, T>({{C, C}, {MAX, MAX}}, {{C, C}, {MAX, MAX}}); 930e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MID}, {C, C}}, {{MID, MID}, {C, C}}); 931e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, B}, {MID, MID}}, {{B, B}, {MID, MID}}); 932e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, B}, {C, C}}, {{B, B}, {C, C}}); 933e37726beSDenys Petrov // One range 934e37726beSDenys Petrov constexpr auto ToMIN = TestValues<T>::MIN; 935e37726beSDenys Petrov constexpr auto ToMAX = TestValues<T>::MAX; 936e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MAX}}, {{ToMIN, ToMAX}}); 937e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MID}}, 938e37726beSDenys Petrov {{ToMIN, ToMIN}, {MIN, ToMAX}}); 939e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MAX}}, {{MID, MAX}}); 940e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, MAX}}, {{ToMIN, MAX}, {B, ToMAX}}); 941e37726beSDenys Petrov this->template checkCastTo<F, T>({{C, MAX}}, {{C, MAX}}); 942e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, C}}, {{ToMIN, C}, {MIN, ToMAX}}); 943e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, B}}, {{MIN, B}}); 944e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, C}}, {{ToMIN, C}, {B, ToMAX}}); 945e37726beSDenys Petrov // Two ranges 946e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, B}, {C, MAX}}, {{C, B}}); 947e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, MID}, {C, MAX}}, 948e37726beSDenys Petrov {{MID, MID}, {C, MAX}, {B, ToMAX}}); 949e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, B}, {MID, C}}, {{MID, C}, {MIN, B}}); 950e37726beSDenys Petrov } 951e37726beSDenys Petrov 952e37726beSDenys Petrov TYPED_TEST(RangeSetCastToPromotionConversionTest, Test) { 953e37726beSDenys Petrov // Just to reduce the verbosity. 954e37726beSDenys Petrov using F = typename TypeParam::FromType; // From 955e37726beSDenys Petrov using T = typename TypeParam::ToType; // To 956e37726beSDenys Petrov 957e37726beSDenys Petrov using TV = TestValues<F>; 958e37726beSDenys Petrov constexpr auto MIN = TV::MIN; 959e37726beSDenys Petrov constexpr auto MAX = TV::MAX; 960e37726beSDenys Petrov constexpr auto MID = TV::MID; 961e37726beSDenys Petrov constexpr auto B = TV::B; 962e37726beSDenys Petrov constexpr auto C = TV::C; 963e37726beSDenys Petrov // One point 964e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MIN}}, {{MIN, MIN}}); 965e37726beSDenys Petrov this->template checkCastTo<F, T>({{MAX, MAX}}, {{MAX, MAX}}); 966e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MID}}, {{MID, MID}}); 967e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, B}}, {{B, B}}); 968e37726beSDenys Petrov this->template checkCastTo<F, T>({{C, C}}, {{C, C}}); 969e37726beSDenys Petrov // Two points 970e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MIN}, {MAX, MAX}}, 971e37726beSDenys Petrov {{MAX, MAX}, {MIN, MIN}}); 972e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MIN}, {B, B}}, {{MIN, MIN}, {B, B}}); 973e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MID}, {MAX, MAX}}, 974e37726beSDenys Petrov {{MID, MID}, {MAX, MAX}}); 975e37726beSDenys Petrov this->template checkCastTo<F, T>({{C, C}, {MAX, MAX}}, {{C, C}, {MAX, MAX}}); 976e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MID}, {C, C}}, {{MID, MID}, {C, C}}); 977e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, B}, {MID, MID}}, {{B, B}, {MID, MID}}); 978e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, B}, {C, C}}, {{B, B}, {C, C}}); 979e37726beSDenys Petrov 980e37726beSDenys Petrov // Use `if constexpr` here. 981e37726beSDenys Petrov if (is_signed_v<F>) { 982e37726beSDenys Petrov // One range 983e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MAX}}, {{0, MAX}, {MIN, -1}}); 984e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MID}}, {{0, 0}, {MIN, -1}}); 985e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MAX}}, {{0, MAX}}); 986e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, MAX}}, {{0, MAX}, {B, -1}}); 987e37726beSDenys Petrov this->template checkCastTo<F, T>({{C, MAX}}, {{C, MAX}}); 988e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, C}}, {{0, C}, {MIN, -1}}); 989e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, B}}, {{MIN, B}}); 990e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, C}}, {{0, C}, {B, -1}}); 991e37726beSDenys Petrov // Two ranges 992e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, B}, {C, MAX}}, 993e37726beSDenys Petrov {{C, MAX}, {MIN, B}}); 994e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, MID}, {C, MAX}}, 995e37726beSDenys Petrov {{0, 0}, {C, MAX}, {B, -1}}); 996e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, B}, {MID, C}}, {{0, C}, {MIN, B}}); 997e37726beSDenys Petrov } else { 998e37726beSDenys Petrov // One range 999e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MAX}}, {{MIN, MAX}}); 1000e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MID}}, {{MIN, MID}}); 1001e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MAX}}, {{MID, MAX}}); 1002e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, MAX}}, {{B, MAX}}); 1003e37726beSDenys Petrov this->template checkCastTo<F, T>({{C, MAX}}, {{C, MAX}}); 1004e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, C}}, {{MIN, C}}); 1005e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, B}}, {{MIN, B}}); 1006e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, C}}, {{B, C}}); 1007e37726beSDenys Petrov // Two ranges 1008e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, B}, {C, MAX}}, 1009e37726beSDenys Petrov {{MIN, B}, {C, MAX}}); 1010e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, MID}, {C, MAX}}, 1011e37726beSDenys Petrov {{B, MID}, {C, MAX}}); 1012e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, B}, {MID, C}}, 1013e37726beSDenys Petrov {{MIN, B}, {MID, C}}); 1014e37726beSDenys Petrov } 1015e37726beSDenys Petrov } 1016e37726beSDenys Petrov 1017e37726beSDenys Petrov TYPED_TEST(RangeSetCastToTruncationConversionTest, Test) { 1018e37726beSDenys Petrov // Just to reduce the verbosity. 1019e37726beSDenys Petrov using F = typename TypeParam::FromType; // From 1020e37726beSDenys Petrov using T = typename TypeParam::ToType; // To 1021e37726beSDenys Petrov 1022e37726beSDenys Petrov using TV = TestValues<F>; 1023e37726beSDenys Petrov constexpr auto MIN = TV::MIN; 1024e37726beSDenys Petrov constexpr auto MAX = TV::MAX; 1025e37726beSDenys Petrov constexpr auto MID = TV::MID; 1026e37726beSDenys Petrov constexpr auto B = TV::B; 1027e37726beSDenys Petrov constexpr auto C = TV::C; 1028e37726beSDenys Petrov // One point 1029e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MIN}}, {{MIN, MIN}}); 1030e37726beSDenys Petrov this->template checkCastTo<F, T>({{MAX, MAX}}, {{MAX, MAX}}); 1031e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MID}}, {{MID, MID}}); 1032e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, B}}, {{B, B}}); 1033e37726beSDenys Petrov this->template checkCastTo<F, T>({{C, C}}, {{C, C}}); 1034e37726beSDenys Petrov // Two points 1035e37726beSDenys Petrov // Use `if constexpr` here. 1036e37726beSDenys Petrov if (is_signed_v<F>) { 1037e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MIN}, {MAX, MAX}}, 1038e37726beSDenys Petrov {{MIN, MIN}, {MAX, MAX}}); 1039e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MID}, {MAX, MAX}}, 1040e37726beSDenys Petrov {{MID, MID}, {MAX, MAX}}); 1041e37726beSDenys Petrov } else { 1042e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MIN}, {MAX, MAX}}, {{MAX, MIN}}); 1043e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MID}, {MAX, MAX}}, {{MAX, MIN}}); 1044e37726beSDenys Petrov } 1045e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MIN}, {B, B}}, {{MIN, MIN}, {B, B}}); 1046e37726beSDenys Petrov this->template checkCastTo<F, T>({{C, C}, {MAX, MAX}}, {{C, C}, {MAX, MAX}}); 1047e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MID}, {C, C}}, {{MID, MID}, {C, C}}); 1048e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, B}, {MID, MID}}, {{B, B}, {MID, MID}}); 1049e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, B}, {C, C}}, {{B, B}, {C, C}}); 1050e37726beSDenys Petrov // One range 1051e37726beSDenys Petrov constexpr auto ToMIN = TestValues<T>::MIN; 1052e37726beSDenys Petrov constexpr auto ToMAX = TestValues<T>::MAX; 1053e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MAX}}, {{ToMIN, ToMAX}}); 1054e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, MID}}, {{ToMIN, ToMAX}}); 1055e37726beSDenys Petrov this->template checkCastTo<F, T>({{MID, MAX}}, {{ToMIN, ToMAX}}); 1056e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, MAX}}, {{ToMIN, ToMAX}}); 1057e37726beSDenys Petrov this->template checkCastTo<F, T>({{C, MAX}}, {{ToMIN, ToMAX}}); 1058e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, C}}, {{ToMIN, ToMAX}}); 1059e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, B}}, {{ToMIN, ToMAX}}); 1060e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, C}}, {{ToMIN, ToMAX}}); 1061e37726beSDenys Petrov // Two ranges 1062e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, B}, {C, MAX}}, {{ToMIN, ToMAX}}); 1063e37726beSDenys Petrov this->template checkCastTo<F, T>({{B, MID}, {C, MAX}}, {{ToMIN, ToMAX}}); 1064e37726beSDenys Petrov this->template checkCastTo<F, T>({{MIN, B}, {MID, C}}, {{ToMIN, ToMAX}}); 1065e37726beSDenys Petrov constexpr auto XAAA = TV::XAAA; 1066e37726beSDenys Petrov constexpr auto X555 = TV::X555; 1067e37726beSDenys Petrov constexpr auto ZA = TV::template XAAATruncZeroOf<T>; 1068e37726beSDenys Petrov constexpr auto Z5 = TV::template X555TruncZeroOf<T>; 1069e37726beSDenys Petrov this->template checkCastTo<F, T>({{XAAA, ZA}, {X555, Z5}}, 1070e37726beSDenys Petrov {{ToMIN, 0}, {X555, ToMAX}}); 1071e37726beSDenys Petrov // Use `if constexpr` here. 1072e37726beSDenys Petrov if (is_signed_v<F>) { 1073e37726beSDenys Petrov // One range 1074e37726beSDenys Petrov this->template checkCastTo<F, T>({{XAAA, ZA}}, {{0, 0}, {XAAA, ToMAX}}); 1075e37726beSDenys Petrov // Two ranges 1076e37726beSDenys Petrov this->template checkCastTo<F, T>({{XAAA, ZA}, {1, 42}}, 1077e37726beSDenys Petrov {{0, 42}, {XAAA, ToMAX}}); 1078e37726beSDenys Petrov } else { 1079e37726beSDenys Petrov // One range 1080e37726beSDenys Petrov this->template checkCastTo<F, T>({{XAAA, ZA}}, {{XAAA, 0}}); 1081e37726beSDenys Petrov // Two ranges 1082e37726beSDenys Petrov this->template checkCastTo<F, T>({{1, 42}, {XAAA, ZA}}, {{XAAA, 42}}); 1083e37726beSDenys Petrov } 1084e37726beSDenys Petrov constexpr auto FromA = TV::FromA; 1085e37726beSDenys Petrov constexpr auto ToA = TV::ToA; 1086e37726beSDenys Petrov constexpr auto FromB = TV::FromB; 1087e37726beSDenys Petrov constexpr auto ToB = TV::ToB; 1088e37726beSDenys Petrov this->template checkCastTo<F, T>({{FromA, ToA}, {FromB, ToB}}, 1089e37726beSDenys Petrov {{FromA, ToA}}); 1090e37726beSDenys Petrov } 1091e37726beSDenys Petrov 1092e37726beSDenys Petrov } // namespace 1093