7 #ifndef PXR_BASE_TF_COMPRESSED_BITS_H
8 #define PXR_BASE_TF_COMPRESSED_BITS_H
21 #include <type_traits>
65 typedef uint32_t _WordType;
75 static const uint32_t LOCAL_SIZE = 6;
79 _numAllocated(LOCAL_SIZE),
82 _WordArray(
const _WordArray &rhs) :
84 _numAllocated(LOCAL_SIZE),
93 _WordArray&
operator=(
const _WordArray &rhs) {
108 void PushBack(_WordType
value) {
110 if (_num >= _numAllocated) {
125 void PopBackNum(uint32_t popNum) {
131 void MoveInto(_WordArray &rhs) {
132 rhs._numAllocated = _numAllocated;
138 if (_IsStoredLocally()) {
141 for (
size_t i = 0; i < LOCAL_SIZE; ++i) {
142 rhs._data[i] = _data[i];
153 _numAllocated = LOCAL_SIZE;
158 void Swap(_WordArray &rhs) {
159 if (!_IsStoredLocally() && !rhs._IsStoredLocally()) {
161 std::swap(_numAllocated, rhs._numAllocated);
174 const _WordType &
operator[](
size_t index)
const {
179 uint32_t GetNum()
const {
184 uint32_t GetNumAllocated()
const {
185 return _numAllocated;
189 const _WordType *Begin()
const {
194 const _WordType *End()
const {
203 const _WordType &Front()
const {
209 return _data[_num - 1];
212 const _WordType &Back()
const {
213 return _data[_num - 1];
217 bool _IsStoredLocally()
const {
218 return _data == _local;
222 if (!_IsStoredLocally()) {
228 void _Duplicate(
const _WordArray &rhs) {
230 if (_numAllocated < rhs._num) {
232 _data =
new _WordType[rhs._numAllocated];
233 _numAllocated = rhs._numAllocated;
236 if (rhs._IsStoredLocally()) {
239 for (
size_t i = 0; i < LOCAL_SIZE; ++i) {
240 _data[i] = rhs._data[i];
243 memcpy(_data, rhs._data,
sizeof(_WordType) * rhs._num);
252 _WordType *newData =
new _WordType[_numAllocated];
253 memcpy(newData, _data,
sizeof(_WordType) * _num);
262 _WordType _local[LOCAL_SIZE];
265 uint32_t _numAllocated;
305 bits._platforms.GetNum());
308 const uint32_t
n = std::min<uint32_t>(
309 bits._platforms.GetNum(),
311 for (uint32_t i = 0; i <
n; ++i) {
324 _platforms.PushBack(num);
335 _platforms.PushBack(0);
340 if (!TF_VERIFY(first < num && last < num && first <= last)) {
341 _platforms.PushBack(num);
345 size_t trailingZeroes = 0;
346 const size_t range = last - first + 1;
349 _platforms.PushBack(range);
350 trailingZeroes = num -
range;
352 _platforms.PushBack(first);
353 _platforms.PushBack(range);
354 trailingZeroes = num - last - 1;
360 if (trailingZeroes != 0) {
361 _platforms.PushBack(trailingZeroes);
368 _platforms(rhs._platforms),
370 _runningBit(rhs._runningBit) {}
377 _platforms(rhs._platforms),
379 _runningBit(1 - rhs._runningBit) {
394 _runningBit(rhs._runningBit) {
395 rhs._platforms.MoveInto(_platforms);
396 rhs._platforms.Clear();
412 _platforms = rhs._platforms;
414 _runningBit = rhs._runningBit;
427 _runningBit = rhs._runningBit;
428 rhs._platforms.MoveInto(_platforms);
429 rhs._platforms.Clear();
446 _platforms.PushBack(0);
454 if ((UINT32_C(1) - _runningBit) ==
455 (_platforms.GetNum() & UINT32_C(1))) {
456 _platforms.Back() += (num - _num);
458 _platforms.PushBack(num - _num);
463 else if (_num > num) {
464 uint32_t diff = _num - num;
465 while (_platforms.Back() <= diff) {
466 diff -= _platforms.Back();
467 _platforms.PopBack();
469 _platforms.Back() -= diff;
480 _platforms.Swap(rhs._platforms);
486 if (_num <= 0 || (_runningBit == 0 && _platforms.GetNum() == 1)) {
492 _platforms.PushBack(_num);
498 if (_num <= 0 || (_runningBit == 1 && _platforms.GetNum() == 1)) {
504 _platforms.PushBack(_num);
512 if (!TF_VERIFY(index < _num)) {
526 if (!TF_VERIFY(index < _num)) {
559 const bool lastValue = _runningBit == (_platforms.GetNum() & 1);
560 if (value == lastValue) {
561 _platforms.Back() += num;
563 _platforms.PushBack(num);
583 if (_num == 0 || bits == 0) {
588 if (_runningBit == 0) {
589 _platforms.Front() += bits;
597 _platforms.PushBack(0);
598 for (
size_t i = _platforms.GetNum() - 1; i > 0; --i) {
599 _platforms[i] = _platforms[i - 1];
601 _platforms[0] = bits;
605 while (_platforms.Back() <= bits) {
606 bits -= _platforms.Back();
607 _platforms.PopBack();
609 _platforms.Back() -= bits;
616 if (_num == 0 || bits == 0) {
621 size_t trimBits = bits;
622 size_t platformIndex = 0;
623 while (platformIndex < _platforms.GetNum() &&
624 _platforms[platformIndex] <= trimBits) {
625 trimBits -= _platforms[platformIndex];
631 if (platformIndex < _platforms.GetNum()) {
632 _platforms[platformIndex] -= trimBits;
640 if (platformIndex > 0) {
643 const size_t last = _platforms.GetNum() - platformIndex;
644 for (
size_t i = 0; i <
last; ++i) {
645 _platforms[i] = _platforms[i + platformIndex];
647 _platforms.PopBackNum(platformIndex);
650 if (platformIndex & 1) {
651 _runningBit = 1 - _runningBit;
657 if ((UINT32_C(1) - _runningBit) ==
658 (_platforms.GetNum() & UINT32_C(1))) {
659 _platforms.Back() += bits;
665 _platforms.PushBack(std::min<_WordType>(_num, bits));
674 if (!TF_VERIFY(index < _num)) {
678 size_t platformIndex, bitCount;
679 return _LinearSearch(index, &platformIndex, &bitCount) == 1;
694 uint8_t bit = _runningBit;
698 for (
size_t i = 0; i < _platforms.GetNum(); ++i) {
699 const _WordType platform = _platforms[i];
706 if (((count + platform) * bit) > nth) {
707 return index + (nth -
count);
711 count += (platform * bit);
731 size_t platformIndex, bitCount;
732 const uint8_t bit = _LinearSearch(index, &platformIndex, &bitCount);
753 size_t platformIndex, bitCount;
754 const uint8_t bit = _LinearSearch(index, &platformIndex, &bitCount);
760 const size_t first = bitCount - _platforms[platformIndex];
780 size_t platformIndex, bitCount;
781 const uint8_t bit = _LinearSearch(index, &platformIndex, &bitCount);
792 void Count(
size_t *numSet,
size_t *maxGap)
const {
793 const uint32_t lastIndex = _platforms.GetNum() - 1;
796 uint8_t bit = _runningBit;
797 for (
size_t i = 0; i < _platforms.GetNum(); ++i) {
800 num += _platforms[i];
803 else if (i > 0 && i < lastIndex) {
828 if (_num == 0 || _runningBit == 1) {
832 return _platforms.Front();
840 if (_num == 0 || (_runningBit == 0 && _platforms.GetNum() == 1)) {
846 if (_runningBit == (_platforms.GetNum() & 1)) {
850 return _num - 1 - _platforms.Back();
857 for (
size_t i = 1 - _runningBit; i < _platforms.GetNum(); i += 2) {
858 numSet += _platforms[i];
870 return _platforms.GetNum();
880 const uint32_t numP = _platforms.GetNum();
881 return (numP / 2) + (numP & _runningBit);
891 const uint32_t numP = _platforms.GetNum();
892 return (numP / 2) + (numP & (1 - _runningBit));
898 return _num == 0 || (_runningBit == 1 && _platforms.GetNum() == 1);
910 return _num > 0 && (_runningBit == 1 || _platforms.GetNum() > 1);
916 return _num > 0 && (_runningBit == 0 || _platforms.GetNum() > 1);
924 const uint32_t numP = _platforms.GetNum();
926 _num > 0 && numP <= 3 &&
928 (_runningBit == 1 && numP == 1) ||
929 (_runningBit == 0 && numP == 3));
937 if (_platforms.GetNumAllocated() > _WordArray::LOCAL_SIZE) {
938 size +=
sizeof(_WordType) * _platforms.GetNumAllocated();
988 if (
this == &rhs || (_num == 0 && rhs._num == 0)) {
993 if (_num == rhs._num &&
994 _runningBit == rhs._runningBit &&
995 _platforms.GetNum() == rhs._platforms.GetNum()) {
998 for (
size_t i = 0; i < _platforms.GetNum(); ++i) {
1000 if (_platforms[i] != rhs._platforms[i]) {
1016 return !(*
this == rhs);
1024 if (!TF_VERIFY(_num == rhs._num) ||
1025 _num == 0 || rhs._num == 0) {
1029 const uint32_t numA = _platforms.GetNum();
1030 const uint32_t numB = rhs._platforms.GetNum();
1031 const uint8_t bitA = _runningBit;
1032 const uint8_t bitB = rhs._runningBit;
1041 _platforms = rhs._platforms;
1056 if (_AreBoundsDisjoint(rhs)) {
1061 return _Logical<_And>(bitB, rhs._platforms);
1077 if (!TF_VERIFY(_num == rhs._num) ||
1078 _num == 0 || rhs._num == 0) {
1082 const uint32_t numA = _platforms.GetNum();
1083 const uint32_t numB = rhs._platforms.GetNum();
1084 const uint8_t bitA = _runningBit;
1085 const uint8_t bitB = rhs._runningBit;
1094 _platforms = rhs._platforms;
1118 return _Logical<_Or>(bitB, rhs._platforms);
1135 if (!TF_VERIFY(_num == rhs._num) ||
1136 _num == 0 || rhs._num == 0) {
1151 return _Logical<_Xor>(rhs._runningBit, rhs._platforms);
1168 if (!TF_VERIFY(_num == rhs._num) ||
1169 _num == 0 || rhs._num == 0) {
1173 const uint32_t numA = _platforms.GetNum();
1174 const uint32_t numB = rhs._platforms.GetNum();
1175 const uint8_t bitA = _runningBit;
1176 const uint8_t bitB = rhs._runningBit;
1184 _runningBit = 1 - bitB;
1185 _platforms = rhs._platforms;
1208 return _Logical<_And>(1 - bitB, rhs._platforms);
1225 _runningBit = 1 - _runningBit;
1235 return IsSet(index);
1278 if (!TF_VERIFY(_num == rhs._num) ||
1279 _num == 0 || rhs._num == 0) {
1283 uint8_t bitA = _runningBit;
1284 uint8_t bitB = rhs._runningBit;
1289 const uint32_t numA = _platforms.GetNum();
1290 const uint32_t numB = rhs._platforms.GetNum();
1308 if (_AreBoundsDisjoint(rhs)) {
1312 return _HasLogical<_And>(bitB, rhs._platforms);
1321 if (!TF_VERIFY(_num == rhs._num) ||
1322 _num == 0 || rhs._num == 0) {
1326 uint8_t bitA = _runningBit;
1327 uint8_t bitB = rhs._runningBit;
1328 if (bitA && !bitB) {
1332 const uint32_t numA = _platforms.GetNum();
1333 const uint32_t numB = rhs._platforms.GetNum();
1355 if (firstSet < rhsFirstSet) {
1362 if (lastSet > rhsLastSet ||
1363 firstSet > rhsLastSet ||
1364 lastSet < rhsFirstSet) {
1368 return _HasLogical<_And>(1 - bitB, rhs._platforms);
1394 template <Mode mode>
1420 inline uint8_t operator() (uint8_t
a, uint8_t
b) {
1427 inline uint8_t operator() (uint8_t
a, uint8_t
b) {
1434 inline uint8_t operator() (uint8_t
a, uint8_t
b) {
1444 _Logical(uint8_t rhsRunningBit,
const _WordArray &rhsPlatforms) {
1447 const uint32_t numA = _platforms.GetNum();
1448 const uint32_t numB = rhsPlatforms.GetNum();
1449 uint8_t bitA = _runningBit;
1450 uint8_t bitB = rhsRunningBit;
1452 uint8_t
b =
op(bitA, bitB);
1458 _WordType platformA = _platforms[indexA];
1459 _WordType platformB = rhsPlatforms[indexB];
1461 uint32_t newTotal = 0;
1462 _WordType newPlatform = 0;
1465 if (platformA < platformB) {
1466 newTotal += platformA;
1467 newPlatform += platformA;
1471 const uint8_t newBit =
op(bitA, bitB);
1473 result.PushBack(newPlatform);
1480 platformB = platformB - platformA;
1481 if (indexA == numA) {
1482 platformA = _num - newTotal;
1483 }
else if (indexA < numA) {
1484 platformA = _platforms[indexA];
1487 }
else if (platformA > platformB) {
1488 newTotal += platformB;
1489 newPlatform += platformB;
1493 const uint8_t newBit =
op(bitA, bitB);
1495 result.PushBack(newPlatform);
1502 platformA = platformA - platformB;
1503 if (indexB == numB) {
1504 platformB = _num - newTotal;
1505 }
else if(indexB < numB) {
1506 platformB = rhsPlatforms[indexB];
1510 newTotal += platformA;
1511 newPlatform += platformA;
1516 const uint8_t newBit =
op(bitA, bitB);
1517 if (newBit != b || newTotal >= _num) {
1518 result.PushBack(newPlatform);
1523 if (newTotal >= _num)
1528 if (indexA == numA) {
1529 platformA = _num - newTotal;
1530 }
else if (indexA < numA) {
1531 platformA = _platforms[indexA];
1535 if (indexB == numB) {
1536 platformB = _num - newTotal;
1537 }
else if (indexB < numB) {
1538 platformB = rhsPlatforms[indexB];
1543 result.MoveInto(_platforms);
1550 template <
class OP >
bool
1551 _HasLogical(uint8_t rhsRunningBit,
const _WordArray &rhsPlatforms)
const {
1554 uint8_t bitA = _runningBit;
1555 uint8_t bitB = rhsRunningBit;
1556 const uint32_t numA = _platforms.GetNum();
1557 const uint32_t numB = rhsPlatforms.GetNum();
1561 _WordType sumPlatformA = _platforms[indexA];
1562 _WordType sumPlatformB = rhsPlatforms[indexB];
1563 while (indexA < numA && indexB < numB) {
1564 if (
op(bitA, bitB)) {
1568 if (sumPlatformA < sumPlatformB) {
1571 sumPlatformA += _platforms[indexA];
1573 }
else if (sumPlatformA > sumPlatformB) {
1576 sumPlatformB += rhsPlatforms[indexB];
1584 if (indexA >= numA || indexB >= numB) {
1588 sumPlatformA += _platforms[indexA];
1589 sumPlatformB += rhsPlatforms[indexB];
1600 uint8_t _LinearSearch(
1601 size_t index,
size_t *platformIndex,
size_t *bitCount)
const {
1602 uint8_t bit = _runningBit;
1606 for (i = 0; i < _platforms.GetNum(); ++i) {
1607 count += _platforms[i];
1608 if (count > index) {
1634 _WordArray _platforms;
1641 uint8_t _runningBit;
1645 template <TfCompressedBits::Mode mode>
1696 return _bitIndex >= _bits->
GetSize();
1704 uint32_t platformIndex,
1708 _platformIndex(platformIndex),
1709 _bitIndex(bitIndex),
1715 return _bits == rhs._bits && _bitIndex == rhs._bitIndex;
1733 if (_bitCounter >= _bits->_platforms[_platformIndex]) {
1737 const uint32_t numP =
1738 _bits->_platforms.GetNum();
1740 (_platformIndex + 1) < numP) {
1741 _bitIndex += _bits->_platforms[_platformIndex + 1];
1742 _platformIndex += 2;
1749 _value = 1 - _value;
1757 const uint32_t &dereference()
const {
1762 uint32_t _platformIndex;
1764 uint32_t _bitCounter;
1772 const uint8_t bit = _bits->_runningBit;
1813 class const_iterator
1862 const uint32_t *platform,
1864 : _platform(platform)
1870 return _platform == rhs._platform;
1874 _bitIndex += *_platform;
1876 _value = 1 - _value;
1879 const uint32_t &dereference()
const {
1883 const uint32_t *_platform;
1889 return const_iterator(_bits->_platforms.Begin(), _bits->_runningBit);
1893 return const_iterator(_bits->_platforms.End(), 0);
void ShiftLeft(size_t bits)
TfCompressedBits & operator<<=(size_t bits)
void ShiftRight(size_t bits)
size_t GetNumUnsetPlatforms() const
void ResizeKeepContents(size_t num)
size_t GetAllocatedSize() const
TfCompressedBits(size_t num, size_t first, size_t last)
static TF_API TfCompressedBits FromString(const std::string &source)
void swap(UT::ArraySet< Key, MULTI, MAX_LOAD_FACTOR_256, Clearer, Hash, KeyEqual > &a, UT::ArraySet< Key, MULTI, MAX_LOAD_FACTOR_256, Clearer, Hash, KeyEqual > &b)
GLsizei const GLfloat * value
AllSetView GetAllSetView() const
void Swap(TfCompressedBits &rhs)
size_t GetNumPlatforms() const
TF_API size_t GetHash() const
View< Mode::AllSet > AllSetView
GLboolean GLboolean GLboolean GLboolean a
IMATH_HOSTDEVICE constexpr bool equal(T1 a, T2 b, T3 t) IMATH_NOEXCEPT
size_t GetNumSetPlatforms() const
**But if you need a result
bool HasNonEmptyDifference(const TfCompressedBits &rhs) const
reference operator*() const
Fast, compressed bit array which is capable of performing logical operations without first decompress...
TfCompressedBits(TfCompressedBits &&rhs)
bool operator[](size_t index) const
View< Mode::AllUnset > AllUnsetView
bool Contains(const TfCompressedBits &rhs) const
std::forward_iterator_tag iterator_category
size_t FindNextSet(size_t index) const
TF_API std::string GetAsStringLeftToRight() const
TfCompressedBits(const TfCompressedBits &rhs, ComplementTagType)
Fast bit array that keeps track of the number of bits set and can find the next set in a timely manne...
const_iterator end() const
TfCompressedBits & operator^=(const TfCompressedBits &rhs)
TfCompressedBits operator>>(size_t bits) const
size_t FindNextUnset(size_t index) const
const uint32_t & reference
TfCompressedBits operator&(const TfCompressedBits &rhs) const
TF_API std::string GetAsRLEString() const
GLsizei GLsizei GLchar * source
bool IsSet(size_t index) const
bool operator==(const const_iterator &rhs) const
void Count(size_t *numSet, size_t *maxGap) const
TfCompressedBits & operator>>=(size_t bits)
size_t FindNthSet(size_t nth) const
const_iterator & operator++()
TfCompressedBits & operator&=(const TfCompressedBits &rhs)
View< Mode::All > AllView
AllUnsetView GetAllUnsetView() const
GLboolean GLboolean GLboolean b
const uint32_t value_type
const uint32_t difference_type
TF_API std::ostream & operator<<(std::ostream &out, const TfCompressedBits &bits)
TfCompressedBits operator|(const TfCompressedBits &rhs) const
pointer operator->() const
bool HasNonEmptyIntersection(const TfCompressedBits &rhs) const
PlatformsView GetPlatformsView() const
__hostdev__ uint64_t last(uint32_t i) const
AllView GetAllView() const
#define ARCH_CACHE_LINE_SIZE
TF_API std::string GetAsStringRightToLeft() const
size_t operator()(const TfCompressedBits &bits) const
void Append(size_t num, bool value)
const_iterator operator++(int)
static size_t Combine(Args &&...args)
Produce a hash code by combining the hash codes of several objects.
PXR_NAMESPACE_CLOSE_SCOPE PXR_NAMESPACE_OPEN_SCOPE
size_t GetLastSet() const
static const TfCompressedBits & GetEmpty()
TfCompressedBits operator<<(size_t bits) const
void SetRange(size_t first, size_t last)
bool operator==(const TfCompressedBits &rhs) const
ImageBuf OIIO_API max(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
#define PXR_NAMESPACE_CLOSE_SCOPE
TfCompressedBits & Complement()
TfCompressedBits & operator|=(const TfCompressedBits &rhs)
bool operator!=(const TfCompressedBits &rhs) const
TfCompressedBits & operator=(TfCompressedBits &&rhs)
TfCompressedBits(const TfCompressedBits &rhs)
size_t FindPrevSet(size_t index) const
TfCompressedBits operator-(const TfCompressedBits &rhs) const
size_t operator()(const TfCompressedBits &bits) const
const_iterator begin() const
void Assign(size_t index, bool value)
TfCompressedBits & operator-=(const TfCompressedBits &rhs)
size_t GetFirstSet() const
TF_API void Decompress(TfBits *bits) const
bool AreContiguouslySet() const
View< Mode::Platforms > PlatformsView
TfCompressedBits & operator=(const TfCompressedBits &rhs)
bool operator!=(const const_iterator &rhs) const
TfCompressedBits(size_t num=0)
TfCompressedBits operator^(const TfCompressedBits &rhs) const