summaryrefslogtreecommitdiff
path: root/src/jit/bitsetasshortlong.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/jit/bitsetasshortlong.h')
-rw-r--r--src/jit/bitsetasshortlong.h792
1 files changed, 792 insertions, 0 deletions
diff --git a/src/jit/bitsetasshortlong.h b/src/jit/bitsetasshortlong.h
new file mode 100644
index 0000000000..ec437e189c
--- /dev/null
+++ b/src/jit/bitsetasshortlong.h
@@ -0,0 +1,792 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// A set of integers in the range [0..N], for some N defined by the "Env" (via "BitSetTraits").
+//
+// Represented as a pointer-sized item. If N bits can fit in this item, the representation is "direct"; otherwise,
+// the item is a pointer to an array of K size_t's, where K is the number of size_t's necessary to hold N bits.
+
+#ifndef bitSetAsShortLong_DEFINED
+#define bitSetAsShortLong_DEFINED 1
+
+#include "bitset.h"
+#include "compilerbitsettraits.h"
+
+typedef size_t* BitSetShortLongRep;
+
+template <typename Env, typename BitSetTraits>
+class BitSetOps</*BitSetType*/ BitSetShortLongRep,
+ /*Brand*/ BSShortLong,
+ /*Env*/ Env,
+ /*BitSetTraits*/ BitSetTraits>
+{
+public:
+ typedef BitSetShortLongRep Rep;
+
+private:
+ static const unsigned BitsInSizeT = sizeof(size_t) * BitSetSupport::BitsInByte;
+
+ inline static bool IsShort(Env env)
+ {
+ return BitSetTraits::GetArrSize(env, sizeof(size_t)) <= 1;
+ }
+
+ // The operations on the "long" (pointer-to-array-of-size_t) versions of the representation.
+ static void AssignLong(Env env, BitSetShortLongRep& lhs, BitSetShortLongRep rhs);
+ static BitSetShortLongRep MakeSingletonLong(Env env, unsigned bitNum);
+ static BitSetShortLongRep MakeCopyLong(Env env, BitSetShortLongRep bs);
+ static bool IsEmptyLong(Env env, BitSetShortLongRep bs);
+ static unsigned CountLong(Env env, BitSetShortLongRep bs);
+ static void UnionDLong(Env env, BitSetShortLongRep& bs1, BitSetShortLongRep bs2);
+ static void DiffDLong(Env env, BitSetShortLongRep& bs1, BitSetShortLongRep bs2);
+ static void AddElemDLong(Env env, BitSetShortLongRep& bs, unsigned i);
+ static void RemoveElemDLong(Env env, BitSetShortLongRep& bs, unsigned i);
+ static void ClearDLong(Env env, BitSetShortLongRep& bs);
+ static BitSetShortLongRep MakeUninitArrayBits(Env env);
+ static BitSetShortLongRep MakeEmptyArrayBits(Env env);
+ static BitSetShortLongRep MakeFullArrayBits(Env env);
+ static bool IsMemberLong(Env env, BitSetShortLongRep bs, unsigned i);
+ static bool EqualLong(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2);
+ static bool IsSubsetLong(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2);
+ static bool IsEmptyIntersectionLong(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2);
+ static void IntersectionDLong(Env env, BitSetShortLongRep& bs1, BitSetShortLongRep bs2);
+#ifdef DEBUG
+ static const char* ToStringLong(Env env, BitSetShortLongRep bs);
+#endif
+
+public:
+ inline static BitSetShortLongRep UninitVal()
+ {
+ return nullptr;
+ }
+
+ static bool MayBeUninit(BitSetShortLongRep bs)
+ {
+ return bs == UninitVal();
+ }
+
+ static void Assign(Env env, BitSetShortLongRep& lhs, BitSetShortLongRep rhs)
+ {
+ // We can't assert that rhs != UninitVal in the Short case, because in that
+ // case it's a legal value.
+ if (IsShort(env))
+ {
+ // Both are short.
+ lhs = rhs;
+ }
+ else if (lhs == UninitVal())
+ {
+ assert(rhs != UninitVal());
+ lhs = MakeCopy(env, rhs);
+ }
+ else
+ {
+ AssignLong(env, lhs, rhs);
+ }
+ }
+
+ static void AssignAllowUninitRhs(Env env, BitSetShortLongRep& lhs, BitSetShortLongRep rhs)
+ {
+ if (IsShort(env))
+ {
+ // Both are short.
+ lhs = rhs;
+ }
+ else if (rhs == UninitVal())
+ {
+ lhs = rhs;
+ }
+ else if (lhs == UninitVal())
+ {
+ lhs = MakeCopy(env, rhs);
+ }
+ else
+ {
+ AssignLong(env, lhs, rhs);
+ }
+ }
+
+ static void AssignNoCopy(Env env, BitSetShortLongRep& lhs, BitSetShortLongRep rhs)
+ {
+ lhs = rhs;
+ }
+
+ static void ClearD(Env env, BitSetShortLongRep& bs)
+ {
+ if (IsShort(env))
+ {
+ bs = (BitSetShortLongRep) nullptr;
+ }
+ else
+ {
+ assert(bs != UninitVal());
+ ClearDLong(env, bs);
+ }
+ }
+
+ static BitSetShortLongRep MakeSingleton(Env env, unsigned bitNum)
+ {
+ assert(bitNum < BitSetTraits::GetSize(env));
+ if (IsShort(env))
+ {
+ return BitSetShortLongRep(((size_t)1) << bitNum);
+ }
+ else
+ {
+ return MakeSingletonLong(env, bitNum);
+ }
+ }
+
+ static BitSetShortLongRep MakeCopy(Env env, BitSetShortLongRep bs)
+ {
+ if (IsShort(env))
+ {
+ return bs;
+ }
+ else
+ {
+ return MakeCopyLong(env, bs);
+ }
+ }
+
+ static bool IsEmpty(Env env, BitSetShortLongRep bs)
+ {
+ if (IsShort(env))
+ {
+ return bs == nullptr;
+ }
+ else
+ {
+ assert(bs != UninitVal());
+ return IsEmptyLong(env, bs);
+ }
+ }
+
+ static unsigned Count(Env env, BitSetShortLongRep bs)
+ {
+ if (IsShort(env))
+ {
+ return BitSetSupport::CountBitsInIntegral(size_t(bs));
+ }
+ else
+ {
+ assert(bs != UninitVal());
+ return CountLong(env, bs);
+ }
+ }
+
+ static void UnionD(Env env, BitSetShortLongRep& bs1, BitSetShortLongRep bs2)
+ {
+ if (IsShort(env))
+ {
+ bs1 = (BitSetShortLongRep)(((size_t)bs1) | ((size_t)bs2));
+ }
+ else
+ {
+ UnionDLong(env, bs1, bs2);
+ }
+ }
+ static BitSetShortLongRep Union(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2)
+ {
+ BitSetShortLongRep res = MakeCopy(env, bs1);
+ UnionD(env, res, bs2);
+ return res;
+ }
+
+ static void DiffD(Env env, BitSetShortLongRep& bs1, BitSetShortLongRep bs2)
+ {
+ if (IsShort(env))
+ {
+ bs1 = (BitSetShortLongRep)(((size_t)bs1) & (~(size_t)bs2));
+ }
+ else
+ {
+ DiffDLong(env, bs1, bs2);
+ }
+ }
+ static BitSetShortLongRep Diff(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2)
+ {
+ BitSetShortLongRep res = MakeCopy(env, bs1);
+ DiffD(env, res, bs2);
+ return res;
+ }
+
+ static void RemoveElemD(Env env, BitSetShortLongRep& bs, unsigned i)
+ {
+ assert(i < BitSetTraits::GetSize(env));
+ if (IsShort(env))
+ {
+ size_t mask = ((size_t)1) << i;
+ mask = ~mask;
+ bs = (BitSetShortLongRep)(((size_t)bs) & mask);
+ }
+ else
+ {
+ assert(bs != UninitVal());
+ RemoveElemDLong(env, bs, i);
+ }
+ }
+ static BitSetShortLongRep RemoveElem(Env env, BitSetShortLongRep bs, unsigned i)
+ {
+ BitSetShortLongRep res = MakeCopy(env, bs);
+ RemoveElemD(env, res, i);
+ return res;
+ }
+
+ static void AddElemD(Env env, BitSetShortLongRep& bs, unsigned i)
+ {
+ assert(i < BitSetTraits::GetSize(env));
+ if (IsShort(env))
+ {
+ size_t mask = ((size_t)1) << i;
+ bs = (BitSetShortLongRep)(((size_t)bs) | mask);
+ }
+ else
+ {
+ AddElemDLong(env, bs, i);
+ }
+ }
+ static BitSetShortLongRep AddElem(Env env, BitSetShortLongRep bs, unsigned i)
+ {
+ BitSetShortLongRep res = MakeCopy(env, bs);
+ AddElemD(env, res, i);
+ return res;
+ }
+
+ static bool IsMember(Env env, const BitSetShortLongRep bs, unsigned i)
+ {
+ assert(i < BitSetTraits::GetSize(env));
+ if (IsShort(env))
+ {
+ size_t mask = ((size_t)1) << i;
+ return (((size_t)bs) & mask) != 0;
+ }
+ else
+ {
+ assert(bs != UninitVal());
+ return IsMemberLong(env, bs, i);
+ }
+ }
+
+ static void IntersectionD(Env env, BitSetShortLongRep& bs1, BitSetShortLongRep bs2)
+ {
+ if (IsShort(env))
+ {
+ (size_t&)bs1 &= (size_t)bs2;
+ }
+ else
+ {
+ IntersectionDLong(env, bs1, bs2);
+ }
+ }
+
+ static BitSetShortLongRep Intersection(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2)
+ {
+ BitSetShortLongRep res = MakeCopy(env, bs1);
+ IntersectionD(env, res, bs2);
+ return res;
+ }
+ static bool IsEmptyIntersection(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2)
+ {
+ if (IsShort(env))
+ {
+ return (((size_t)bs1) & ((size_t)bs2)) == 0;
+ }
+ else
+ {
+ return IsEmptyIntersectionLong(env, bs1, bs2);
+ }
+ }
+
+ static bool IsSubset(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2)
+ {
+ if (IsShort(env))
+ {
+ size_t u1 = (size_t)bs1;
+ size_t u2 = (size_t)bs2;
+ return (u1 & u2) == u1;
+ }
+ else
+ {
+ return IsSubsetLong(env, bs1, bs2);
+ }
+ }
+
+ static bool Equal(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2)
+ {
+ if (IsShort(env))
+ {
+ return (size_t)bs1 == (size_t)bs2;
+ }
+ else
+ {
+ return EqualLong(env, bs1, bs2);
+ }
+ }
+
+#ifdef DEBUG
+ // Returns a string valid until the allocator releases the memory.
+ static const char* ToString(Env env, BitSetShortLongRep bs)
+ {
+ if (IsShort(env))
+ {
+ assert(sizeof(BitSetShortLongRep) == sizeof(size_t));
+ IAllocator* alloc = BitSetTraits::GetDebugOnlyAllocator(env);
+ const int CharsForSizeT = sizeof(size_t) * 2;
+ char* res = nullptr;
+ const int ShortAllocSize = CharsForSizeT + 4;
+ res = (char*)alloc->Alloc(ShortAllocSize);
+ size_t bits = (size_t)bs;
+ unsigned remaining = ShortAllocSize;
+ char* ptr = res;
+ if (sizeof(size_t) == sizeof(int64_t))
+ {
+ sprintf_s(ptr, remaining, "%016llX", bits);
+ }
+ else
+ {
+ assert(sizeof(size_t) == sizeof(int));
+ sprintf_s(ptr, remaining, "%08X", bits);
+ }
+ return res;
+ }
+ else
+ {
+ return ToStringLong(env, bs);
+ }
+ }
+#endif
+
+ static BitSetShortLongRep MakeEmpty(Env env)
+ {
+ if (IsShort(env))
+ {
+ return nullptr;
+ }
+ else
+ {
+ return MakeEmptyArrayBits(env);
+ }
+ }
+
+ static BitSetShortLongRep MakeFull(Env env)
+ {
+ if (IsShort(env))
+ {
+ // Can't just shift by numBits+1, since that might be 32 (and (1 << 32( == 1, for an unsigned).
+ unsigned numBits = BitSetTraits::GetSize(env);
+ if (numBits == BitsInSizeT)
+ {
+ // Can't use the implementation below to get all 1's...
+ return BitSetShortLongRep(size_t(-1));
+ }
+ else
+ {
+ return BitSetShortLongRep((size_t(1) << numBits) - 1);
+ }
+ }
+ else
+ {
+ return MakeFullArrayBits(env);
+ }
+ }
+
+ class Iter
+ {
+ BitSetShortLongRep m_bs; // The BitSet that we're iterating over.
+ size_t m_bits; // The "current" bits remaining to be iterated over.
+ // In the "short" case, these are all the remaining bits.
+ // In the "long" case, these are remaining bits in element "m_index";
+ // these and the bits in the remaining elements comprise the remaining bits.
+ unsigned m_index; // If "m_bs" uses the long (indirect) representation, the current index in the array.
+ // the index of the element in A(bs) that is currently being iterated.
+ unsigned m_bitNum; // The number of bits that have already been iterated over (set or clear). If you
+ // add this to the bit number of the next bit in "m_bits", you get the proper bit number of that
+ // bit in "m_bs".
+
+ public:
+ Iter(Env env, const BitSetShortLongRep& bs) : m_bs(bs), m_bitNum(0)
+ {
+ if (BitSetOps::IsShort(env))
+ {
+ m_index = 0;
+ m_bits = (size_t)bs;
+ }
+ else
+ {
+ assert(bs != BitSetOps::UninitVal());
+ m_index = 0;
+ m_bits = bs[0];
+ }
+ }
+
+ bool NextElem(Env env, unsigned* pElem)
+ {
+#if BITSET_TRACK_OPCOUNTS
+ BitSetStaticsImpl::RecordOp(BitSetStaticsImpl::BSOP_NextBit);
+#endif
+ for (;;)
+ {
+ DWORD nextBit;
+ BOOL hasBit;
+#ifdef _HOST_64BIT_
+ static_assert_no_msg(sizeof(size_t) == 8);
+ hasBit = BitScanForward64(&nextBit, m_bits);
+#else
+ static_assert_no_msg(sizeof(size_t) == 4);
+ hasBit = BitScanForward(&nextBit, m_bits);
+#endif
+
+ // If there's a bit, doesn't matter if we're short or long.
+ if (hasBit)
+ {
+ *pElem = m_bitNum + nextBit;
+ m_bitNum += nextBit + 1;
+ m_bits >>= nextBit;
+ m_bits >>= 1; // Have to do these separately -- if we have 0x80000000, nextBit == 31, and shifting
+ // by 32 bits does nothing.
+ return true;
+ }
+ else
+ {
+ unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
+ if (len <= 1)
+ {
+ return false;
+ }
+ else
+ {
+ m_index++;
+ if (m_index == len)
+ {
+ return false;
+ }
+ // Otherwise...
+ m_bitNum = m_index * sizeof(size_t) * BitSetSupport::BitsInByte;
+ m_bits = m_bs[m_index];
+ continue;
+ }
+ }
+ }
+ }
+ };
+
+ friend class Iter;
+
+ typedef size_t* ValArgType;
+ typedef size_t* RetValType;
+};
+
+template <typename Env, typename BitSetTraits>
+void BitSetOps</*BitSetType*/ BitSetShortLongRep,
+ /*Brand*/ BSShortLong,
+ /*Env*/ Env,
+ /*BitSetTraits*/ BitSetTraits>::AssignLong(Env env, BitSetShortLongRep& lhs, BitSetShortLongRep rhs)
+{
+ assert(!IsShort(env));
+ unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
+ for (unsigned i = 0; i < len; i++)
+ {
+ lhs[i] = rhs[i];
+ }
+}
+
+template <typename Env, typename BitSetTraits>
+BitSetShortLongRep BitSetOps</*BitSetType*/ BitSetShortLongRep,
+ /*Brand*/ BSShortLong,
+ /*Env*/ Env,
+ /*BitSetTraits*/ BitSetTraits>::MakeSingletonLong(Env env, unsigned bitNum)
+{
+ assert(!IsShort(env));
+ BitSetShortLongRep res = MakeEmptyArrayBits(env);
+ unsigned index = bitNum / BitsInSizeT;
+ res[index] = ((size_t)1) << (bitNum % BitsInSizeT);
+ return res;
+}
+
+template <typename Env, typename BitSetTraits>
+BitSetShortLongRep BitSetOps</*BitSetType*/ BitSetShortLongRep,
+ /*Brand*/ BSShortLong,
+ /*Env*/ Env,
+ /*BitSetTraits*/ BitSetTraits>::MakeCopyLong(Env env, BitSetShortLongRep bs)
+{
+ assert(!IsShort(env));
+ BitSetShortLongRep res = MakeUninitArrayBits(env);
+ unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
+ for (unsigned i = 0; i < len; i++)
+ {
+ res[i] = bs[i];
+ }
+ return res;
+}
+
+template <typename Env, typename BitSetTraits>
+bool BitSetOps</*BitSetType*/ BitSetShortLongRep,
+ /*Brand*/ BSShortLong,
+ /*Env*/ Env,
+ /*BitSetTraits*/ BitSetTraits>::IsEmptyLong(Env env, BitSetShortLongRep bs)
+{
+ assert(!IsShort(env));
+ unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
+ for (unsigned i = 0; i < len; i++)
+ {
+ if (bs[i] != 0)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+template <typename Env, typename BitSetTraits>
+unsigned BitSetOps</*BitSetType*/ BitSetShortLongRep,
+ /*Brand*/ BSShortLong,
+ /*Env*/ Env,
+ /*BitSetTraits*/ BitSetTraits>::CountLong(Env env, BitSetShortLongRep bs)
+{
+ assert(!IsShort(env));
+ unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
+ unsigned res = 0;
+ for (unsigned i = 0; i < len; i++)
+ {
+ res += BitSetSupport::CountBitsInIntegral(bs[i]);
+ }
+ return res;
+}
+
+template <typename Env, typename BitSetTraits>
+void BitSetOps</*BitSetType*/ BitSetShortLongRep,
+ /*Brand*/ BSShortLong,
+ /*Env*/ Env,
+ /*BitSetTraits*/ BitSetTraits>::UnionDLong(Env env, BitSetShortLongRep& bs1, BitSetShortLongRep bs2)
+{
+ assert(!IsShort(env));
+ unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
+ for (unsigned i = 0; i < len; i++)
+ {
+ bs1[i] |= bs2[i];
+ }
+}
+
+template <typename Env, typename BitSetTraits>
+void BitSetOps</*BitSetType*/ BitSetShortLongRep,
+ /*Brand*/ BSShortLong,
+ /*Env*/ Env,
+ /*BitSetTraits*/ BitSetTraits>::DiffDLong(Env env, BitSetShortLongRep& bs1, BitSetShortLongRep bs2)
+{
+ assert(!IsShort(env));
+ unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
+ for (unsigned i = 0; i < len; i++)
+ {
+ bs1[i] &= ~bs2[i];
+ }
+}
+
+template <typename Env, typename BitSetTraits>
+void BitSetOps</*BitSetType*/ BitSetShortLongRep,
+ /*Brand*/ BSShortLong,
+ /*Env*/ Env,
+ /*BitSetTraits*/ BitSetTraits>::AddElemDLong(Env env, BitSetShortLongRep& bs, unsigned i)
+{
+ assert(!IsShort(env));
+ unsigned index = i / BitsInSizeT;
+ size_t mask = ((size_t)1) << (i % BitsInSizeT);
+ bs[index] |= mask;
+}
+
+template <typename Env, typename BitSetTraits>
+void BitSetOps</*BitSetType*/ BitSetShortLongRep,
+ /*Brand*/ BSShortLong,
+ /*Env*/ Env,
+ /*BitSetTraits*/ BitSetTraits>::RemoveElemDLong(Env env, BitSetShortLongRep& bs, unsigned i)
+{
+ assert(!IsShort(env));
+ unsigned index = i / BitsInSizeT;
+ size_t mask = ((size_t)1) << (i % BitsInSizeT);
+ mask = ~mask;
+ bs[index] &= mask;
+}
+
+template <typename Env, typename BitSetTraits>
+void BitSetOps</*BitSetType*/ BitSetShortLongRep,
+ /*Brand*/ BSShortLong,
+ /*Env*/ Env,
+ /*BitSetTraits*/ BitSetTraits>::ClearDLong(Env env, BitSetShortLongRep& bs)
+{
+ assert(!IsShort(env));
+ // Recall that ClearD does *not* require "bs" to be of the current epoch.
+ // Therefore, we must allocate a new representation.
+ bs = MakeEmptyArrayBits(env);
+}
+
+template <typename Env, typename BitSetTraits>
+BitSetShortLongRep BitSetOps</*BitSetType*/ BitSetShortLongRep,
+ /*Brand*/ BSShortLong,
+ /*Env*/ Env,
+ /*BitSetTraits*/ BitSetTraits>::MakeUninitArrayBits(Env env)
+{
+ assert(!IsShort(env));
+ unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
+ assert(len > 1); // Or else would not require an array.
+ return (BitSetShortLongRep)(BitSetTraits::GetAllocator(env)->Alloc(len * sizeof(size_t)));
+}
+
+template <typename Env, typename BitSetTraits>
+BitSetShortLongRep BitSetOps</*BitSetType*/ BitSetShortLongRep,
+ /*Brand*/ BSShortLong,
+ /*Env*/ Env,
+ /*BitSetTraits*/ BitSetTraits>::MakeEmptyArrayBits(Env env)
+{
+ assert(!IsShort(env));
+ unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
+ assert(len > 1); // Or else would not require an array.
+ BitSetShortLongRep res = (BitSetShortLongRep)(BitSetTraits::GetAllocator(env)->Alloc(len * sizeof(size_t)));
+ for (unsigned i = 0; i < len; i++)
+ {
+ res[i] = 0;
+ }
+ return res;
+}
+
+template <typename Env, typename BitSetTraits>
+BitSetShortLongRep BitSetOps</*BitSetType*/ BitSetShortLongRep,
+ /*Brand*/ BSShortLong,
+ /*Env*/ Env,
+ /*BitSetTraits*/ BitSetTraits>::MakeFullArrayBits(Env env)
+{
+ assert(!IsShort(env));
+ unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
+ assert(len > 1); // Or else would not require an array.
+ BitSetShortLongRep res = (BitSetShortLongRep)(BitSetTraits::GetAllocator(env)->Alloc(len * sizeof(size_t)));
+ for (unsigned i = 0; i < len - 1; i++)
+ {
+ res[i] = size_t(-1);
+ }
+ // Start with all ones, shift in zeros in the last elem.
+ unsigned lastElemBits = (BitSetTraits::GetSize(env) - 1) % BitsInSizeT + 1;
+ res[len - 1] = (size_t(-1) >> (BitsInSizeT - lastElemBits));
+ return res;
+}
+
+template <typename Env, typename BitSetTraits>
+bool BitSetOps</*BitSetType*/ BitSetShortLongRep,
+ /*Brand*/ BSShortLong,
+ /*Env*/ Env,
+ /*BitSetTraits*/ BitSetTraits>::IsMemberLong(Env env, BitSetShortLongRep bs, unsigned i)
+{
+ assert(!IsShort(env));
+ unsigned index = i / BitsInSizeT;
+ unsigned bitInElem = (i % BitsInSizeT);
+ size_t mask = ((size_t)1) << bitInElem;
+ return (bs[index] & mask) != 0;
+}
+
+template <typename Env, typename BitSetTraits>
+void BitSetOps</*BitSetType*/ BitSetShortLongRep,
+ /*Brand*/ BSShortLong,
+ /*Env*/ Env,
+ /*BitSetTraits*/ BitSetTraits>::IntersectionDLong(Env env,
+ BitSetShortLongRep& bs1,
+ BitSetShortLongRep bs2)
+{
+ assert(!IsShort(env));
+ unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
+ for (unsigned i = 0; i < len; i++)
+ {
+ bs1[i] &= bs2[i];
+ }
+}
+
+template <typename Env, typename BitSetTraits>
+bool BitSetOps</*BitSetType*/ BitSetShortLongRep,
+ /*Brand*/ BSShortLong,
+ /*Env*/ Env,
+ /*BitSetTraits*/ BitSetTraits>::IsEmptyIntersectionLong(Env env,
+ BitSetShortLongRep bs1,
+ BitSetShortLongRep bs2)
+{
+ assert(!IsShort(env));
+ unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
+ for (unsigned i = 0; i < len; i++)
+ {
+ if ((bs1[i] & bs2[i]) != 0)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+template <typename Env, typename BitSetTraits>
+bool BitSetOps</*BitSetType*/ BitSetShortLongRep,
+ /*Brand*/ BSShortLong,
+ /*Env*/ Env,
+ /*BitSetTraits*/ BitSetTraits>::EqualLong(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2)
+{
+ assert(!IsShort(env));
+ unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
+ for (unsigned i = 0; i < len; i++)
+ {
+ if (bs1[i] != bs2[i])
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+template <typename Env, typename BitSetTraits>
+bool BitSetOps</*BitSetType*/ BitSetShortLongRep,
+ /*Brand*/ BSShortLong,
+ /*Env*/ Env,
+ /*BitSetTraits*/ BitSetTraits>::IsSubsetLong(Env env, BitSetShortLongRep bs1, BitSetShortLongRep bs2)
+{
+ assert(!IsShort(env));
+ unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
+ for (unsigned i = 0; i < len; i++)
+ {
+ if ((bs1[i] & bs2[i]) != bs1[i])
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+#ifdef DEBUG
+template <typename Env, typename BitSetTraits>
+const char* BitSetOps</*BitSetType*/ BitSetShortLongRep,
+ /*Brand*/ BSShortLong,
+ /*Env*/ Env,
+ /*BitSetTraits*/ BitSetTraits>::ToStringLong(Env env, BitSetShortLongRep bs)
+{
+ assert(!IsShort(env));
+ unsigned len = BitSetTraits::GetArrSize(env, sizeof(size_t));
+ const int CharsForSizeT = sizeof(size_t) * 2;
+ unsigned allocSz = len * CharsForSizeT + 4;
+ unsigned remaining = allocSz;
+ IAllocator* alloc = BitSetTraits::GetDebugOnlyAllocator(env);
+ char* res = (char*)alloc->Alloc(allocSz);
+ char* temp = res;
+ for (unsigned i = len; 0 < i; i--)
+ {
+ size_t bits = bs[i - 1];
+ for (unsigned bytesDone = 0; bytesDone < sizeof(size_t); bytesDone += sizeof(unsigned))
+ {
+ unsigned bits0 = (unsigned)bits;
+ sprintf_s(temp, remaining, "%08X", bits0);
+ temp += 8;
+ remaining -= 8;
+ bytesDone += 4;
+ assert(sizeof(unsigned) == 4);
+ // Doing this twice by 16, rather than once by 32, avoids warnings when size_t == unsigned.
+ bits = bits >> 16;
+ bits = bits >> 16;
+ }
+ }
+ return res;
+}
+#endif
+
+#endif // bitSetAsShortLong_DEFINED