xref: /llvm-project/clang/unittests/StaticAnalyzer/RangeSetTest.cpp (revision 918972bded27de6a2bfacc15b4ad3edebd81f405)
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