bitmap.h 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144
  1. #pragma once
  2. #include "fwd.h"
  3. #include "ptr.h"
  4. #include "bitops.h"
  5. #include "typetraits.h"
  6. #include "algorithm.h"
  7. #include "utility.h"
  8. #include <util/system/yassert.h>
  9. #include <util/system/defaults.h>
  10. #include <util/str_stl.h>
  11. #include <util/ysaveload.h>
  12. namespace NBitMapPrivate {
  13. // Returns number of bits set; result is in most significatnt byte
  14. inline ui64 ByteSums(ui64 x) {
  15. ui64 byteSums = x - ((x & 0xAAAAAAAAAAAAAAAAULL) >> 1);
  16. byteSums = (byteSums & 0x3333333333333333ULL) + ((byteSums >> 2) & 0x3333333333333333ULL);
  17. byteSums = (byteSums + (byteSums >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
  18. return byteSums * 0x0101010101010101ULL;
  19. }
  20. // better than intrinsics without -mpopcnt
  21. template <typename T>
  22. static unsigned CountBitsPrivate(T v) noexcept {
  23. return static_cast<unsigned>(ByteSums(v) >> 56);
  24. }
  25. template <typename TChunkType, size_t ExtraBits>
  26. struct TSanitizeMask {
  27. static constexpr TChunkType Value = ~((~TChunkType(0)) << ExtraBits);
  28. };
  29. template <typename TChunkType>
  30. struct TSanitizeMask<TChunkType, 0> {
  31. static constexpr TChunkType Value = (TChunkType)~TChunkType(0u);
  32. };
  33. template <typename TTargetChunk, typename TSourceChunk>
  34. struct TBigToSmallDataCopier {
  35. static_assert(sizeof(TTargetChunk) < sizeof(TSourceChunk), "expect sizeof(TTargetChunk) < sizeof(TSourceChunk)");
  36. static_assert(0 == sizeof(TSourceChunk) % sizeof(TTargetChunk), "expect 0 == sizeof(TSourceChunk) % sizeof(TTargetChunk)");
  37. static constexpr size_t BLOCK_SIZE = sizeof(TSourceChunk) / sizeof(TTargetChunk);
  38. union TCnv {
  39. TSourceChunk BigData;
  40. TTargetChunk SmallData[BLOCK_SIZE];
  41. };
  42. static inline void CopyChunk(TTargetChunk* target, TSourceChunk source) {
  43. TCnv c;
  44. c.BigData = source;
  45. #if defined(_big_endian_)
  46. ::ReverseCopy(c.SmallData, c.SmallData + Y_ARRAY_SIZE(c.SmallData), target);
  47. #else
  48. ::Copy(c.SmallData, c.SmallData + Y_ARRAY_SIZE(c.SmallData), target);
  49. #endif
  50. }
  51. static inline void Copy(TTargetChunk* target, size_t targetSize, const TSourceChunk* source, size_t sourceSize) {
  52. Y_ASSERT(targetSize >= sourceSize * BLOCK_SIZE);
  53. if (targetSize > sourceSize * BLOCK_SIZE) {
  54. ::Fill(target + sourceSize * BLOCK_SIZE, target + targetSize, 0);
  55. }
  56. for (size_t i = 0; i < sourceSize; ++i) {
  57. CopyChunk(target + i * BLOCK_SIZE, source[i]);
  58. }
  59. }
  60. };
  61. template <typename TTargetChunk, typename TSourceChunk>
  62. struct TSmallToBigDataCopier {
  63. static_assert(sizeof(TTargetChunk) > sizeof(TSourceChunk), "expect sizeof(TTargetChunk) > sizeof(TSourceChunk)");
  64. static_assert(0 == sizeof(TTargetChunk) % sizeof(TSourceChunk), "expect 0 == sizeof(TTargetChunk) % sizeof(TSourceChunk)");
  65. static constexpr size_t BLOCK_SIZE = sizeof(TTargetChunk) / sizeof(TSourceChunk);
  66. union TCnv {
  67. TSourceChunk SmallData[BLOCK_SIZE];
  68. TTargetChunk BigData;
  69. };
  70. static inline TTargetChunk CopyFullChunk(const TSourceChunk* source) {
  71. TCnv c;
  72. #if defined(_big_endian_)
  73. ::ReverseCopy(source, source + BLOCK_SIZE, c.SmallData);
  74. #else
  75. ::Copy(source, source + BLOCK_SIZE, c.SmallData);
  76. #endif
  77. return c.BigData;
  78. }
  79. static inline TTargetChunk CopyPartChunk(const TSourceChunk* source, size_t count) {
  80. Y_ASSERT(count <= BLOCK_SIZE);
  81. TCnv c;
  82. c.BigData = 0;
  83. #if defined(_big_endian_)
  84. ::ReverseCopy(source, source + count, c.SmallData);
  85. #else
  86. ::Copy(source, source + count, c.SmallData);
  87. #endif
  88. return c.BigData;
  89. }
  90. static inline void Copy(TTargetChunk* target, size_t targetSize, const TSourceChunk* source, size_t sourceSize) {
  91. Y_ASSERT(targetSize * BLOCK_SIZE >= sourceSize);
  92. if (targetSize * BLOCK_SIZE > sourceSize) {
  93. ::Fill(target + sourceSize / BLOCK_SIZE, target + targetSize, 0);
  94. }
  95. size_t i = 0;
  96. for (; i < sourceSize / BLOCK_SIZE; ++i) {
  97. target[i] = CopyFullChunk(source + i * BLOCK_SIZE);
  98. }
  99. if (0 != sourceSize % BLOCK_SIZE) {
  100. target[i] = CopyPartChunk(source + i * BLOCK_SIZE, sourceSize % BLOCK_SIZE);
  101. }
  102. }
  103. };
  104. template <typename TChunk>
  105. struct TUniformDataCopier {
  106. static inline void Copy(TChunk* target, size_t targetSize, const TChunk* source, size_t sourceSize) {
  107. Y_ASSERT(targetSize >= sourceSize);
  108. for (size_t i = 0; i < sourceSize; ++i) {
  109. target[i] = source[i];
  110. }
  111. for (size_t i = sourceSize; i < targetSize; ++i) {
  112. target[i] = 0;
  113. }
  114. }
  115. };
  116. template <typename TFirst, typename TSecond>
  117. struct TIsSmaller {
  118. enum {
  119. Result = sizeof(TFirst) < sizeof(TSecond)
  120. };
  121. };
  122. template <typename TTargetChunk, typename TSourceChunk>
  123. struct TDataCopier: public std::conditional_t<std::is_same<TTargetChunk, TSourceChunk>::value, TUniformDataCopier<TTargetChunk>, std::conditional_t<TIsSmaller<TTargetChunk, TSourceChunk>::Result, TBigToSmallDataCopier<TTargetChunk, TSourceChunk>, TSmallToBigDataCopier<TTargetChunk, TSourceChunk>>> {
  124. };
  125. template <typename TTargetChunk, typename TSourceChunk>
  126. inline void CopyData(TTargetChunk* target, size_t targetSize, const TSourceChunk* source, size_t sourceSize) {
  127. TDataCopier<TTargetChunk, TSourceChunk>::Copy(target, targetSize, source, sourceSize);
  128. }
  129. template <size_t BitCount, typename TChunkType>
  130. struct TFixedStorage {
  131. using TChunk = TChunkType;
  132. static constexpr size_t Size = (BitCount + 8 * sizeof(TChunk) - 1) / (8 * sizeof(TChunk));
  133. TChunk Data[Size];
  134. TFixedStorage() {
  135. Zero(Data);
  136. }
  137. TFixedStorage(const TFixedStorage<BitCount, TChunkType>& st) {
  138. for (size_t i = 0; i < Size; ++i) {
  139. Data[i] = st.Data[i];
  140. }
  141. }
  142. template <typename TOtherChunk>
  143. TFixedStorage(const TOtherChunk* data, size_t size) {
  144. Y_ABORT_UNLESS(Size * sizeof(TChunk) >= size * sizeof(TOtherChunk), "Exceeding bitmap storage capacity");
  145. CopyData(Data, Size, data, size);
  146. }
  147. Y_FORCE_INLINE void Swap(TFixedStorage<BitCount, TChunkType>& st) {
  148. for (size_t i = 0; i < Size; ++i) {
  149. DoSwap(Data[i], st.Data[i]);
  150. }
  151. }
  152. Y_FORCE_INLINE static constexpr size_t GetBitCapacity() noexcept {
  153. return BitCount;
  154. }
  155. Y_FORCE_INLINE static constexpr size_t GetChunkCapacity() noexcept {
  156. return Size;
  157. }
  158. // Returns true if the resulting storage capacity is enough to fit the requested size
  159. Y_FORCE_INLINE static constexpr bool ExpandBitSize(const size_t bitSize) noexcept {
  160. return bitSize <= BitCount;
  161. }
  162. Y_FORCE_INLINE void Sanitize() {
  163. Data[Size - 1] &= TSanitizeMask<TChunk, BitCount % (8 * sizeof(TChunk))>::Value;
  164. }
  165. };
  166. // Dynamically expanded storage.
  167. // It uses "on stack" realization with no allocation for one chunk spaces
  168. template <typename TChunkType>
  169. struct TDynamicStorage {
  170. using TChunk = TChunkType;
  171. size_t Size;
  172. TChunk StackData;
  173. TArrayHolder<TChunk> ArrayData;
  174. TChunk* Data;
  175. TDynamicStorage()
  176. : Size(1)
  177. , StackData(0)
  178. , Data(&StackData)
  179. {
  180. }
  181. TDynamicStorage(const TDynamicStorage<TChunk>& st)
  182. : Size(1)
  183. , StackData(0)
  184. , Data(&StackData)
  185. {
  186. ExpandSize(st.Size, false);
  187. for (size_t i = 0; i < st.Size; ++i) {
  188. Data[i] = st.Data[i];
  189. }
  190. for (size_t i = st.Size; i < Size; ++i) {
  191. Data[i] = 0;
  192. }
  193. }
  194. template <typename TOtherChunk>
  195. TDynamicStorage(const TOtherChunk* data, size_t size)
  196. : Size(1)
  197. , StackData(0)
  198. , Data(&StackData)
  199. {
  200. ExpandBitSize(size * sizeof(TOtherChunk) * 8, false);
  201. CopyData(Data, Size, data, size);
  202. }
  203. Y_FORCE_INLINE void Swap(TDynamicStorage<TChunkType>& st) {
  204. DoSwap(Size, st.Size);
  205. DoSwap(StackData, st.StackData);
  206. DoSwap(ArrayData, st.ArrayData);
  207. Data = 1 == Size ? &StackData : ArrayData.Get();
  208. st.Data = 1 == st.Size ? &st.StackData : st.ArrayData.Get();
  209. }
  210. Y_FORCE_INLINE size_t GetBitCapacity() const {
  211. return Size * 8 * sizeof(TChunk);
  212. }
  213. Y_FORCE_INLINE size_t GetChunkCapacity() const {
  214. return Size;
  215. }
  216. // Returns true if the resulting storage capacity is enough to fit the requested size
  217. Y_FORCE_INLINE bool ExpandSize(size_t size, bool keepData = true) {
  218. if (size > Size) {
  219. size = Max(size, Size * 2);
  220. TArrayHolder<TChunk> newData(new TChunk[size]);
  221. if (keepData) {
  222. for (size_t i = 0; i < Size; ++i) {
  223. newData[i] = Data[i];
  224. }
  225. for (size_t i = Size; i < size; ++i) {
  226. newData[i] = 0;
  227. }
  228. }
  229. DoSwap(ArrayData, newData);
  230. Data = ArrayData.Get();
  231. Size = size;
  232. }
  233. return true;
  234. }
  235. Y_FORCE_INLINE bool ExpandBitSize(size_t bitSize, bool keepData = true) {
  236. return ExpandSize((bitSize + 8 * sizeof(TChunk) - 1) / (8 * sizeof(TChunk)), keepData);
  237. }
  238. Y_FORCE_INLINE void Sanitize() {
  239. }
  240. };
  241. template <size_t num>
  242. struct TDivCount {
  243. static constexpr size_t Value = 1 + TDivCount<(num >> 1)>::Value;
  244. };
  245. template <>
  246. struct TDivCount<0> {
  247. static constexpr size_t Value = 0;
  248. };
  249. } // namespace NBitMapPrivate
  250. template <size_t BitCount, typename TChunkType>
  251. struct TFixedBitMapTraits {
  252. using TChunk = TChunkType;
  253. using TStorage = NBitMapPrivate::TFixedStorage<BitCount, TChunkType>;
  254. };
  255. template <typename TChunkType>
  256. struct TDynamicBitMapTraits {
  257. using TChunk = TChunkType;
  258. using TStorage = NBitMapPrivate::TDynamicStorage<TChunkType>;
  259. };
  260. template <class TTraits>
  261. class TBitMapOps {
  262. public:
  263. using TChunk = typename TTraits::TChunk;
  264. using TThis = TBitMapOps<TTraits>;
  265. private:
  266. static_assert(std::is_unsigned<TChunk>::value, "expect std::is_unsigned<TChunk>::value");
  267. static constexpr size_t BitsPerChunk = 8 * sizeof(TChunk);
  268. static constexpr TChunk ModMask = static_cast<TChunk>(BitsPerChunk - 1);
  269. static constexpr size_t DivCount = NBitMapPrivate::TDivCount<BitsPerChunk>::Value - 1;
  270. static constexpr TChunk FullChunk = (TChunk)~TChunk(0);
  271. template <class>
  272. friend class TBitMapOps;
  273. using TStorage = typename TTraits::TStorage;
  274. // The smallest unsigned type, which can be used in bit ops
  275. using TIntType = std::conditional_t<sizeof(TChunk) < sizeof(unsigned int), unsigned int, TChunk>;
  276. TStorage Mask;
  277. public:
  278. class TReference {
  279. private:
  280. friend class TBitMapOps<TTraits>;
  281. TChunk* Chunk;
  282. size_t Offset;
  283. TReference(TChunk* c, size_t offset)
  284. : Chunk(c)
  285. , Offset(offset)
  286. {
  287. }
  288. public:
  289. ~TReference() = default;
  290. Y_FORCE_INLINE TReference& operator=(bool val) {
  291. if (val) {
  292. *Chunk |= static_cast<TChunk>(1) << Offset;
  293. } else {
  294. *Chunk &= ~(static_cast<TChunk>(1) << Offset);
  295. }
  296. return *this;
  297. }
  298. Y_FORCE_INLINE TReference& operator=(const TReference& ref) {
  299. if (ref) {
  300. *Chunk |= static_cast<TChunk>(1) << Offset;
  301. } else {
  302. *Chunk &= ~(static_cast<TChunk>(1) << Offset);
  303. }
  304. return *this;
  305. }
  306. Y_FORCE_INLINE bool operator~() const {
  307. return 0 == (*Chunk & (static_cast<TChunk>(1) << Offset));
  308. }
  309. Y_FORCE_INLINE operator bool() const {
  310. return 0 != (*Chunk & (static_cast<TChunk>(1) << Offset));
  311. }
  312. Y_FORCE_INLINE TReference& Flip() {
  313. *Chunk ^= static_cast<TChunk>(1) << Offset;
  314. return *this;
  315. }
  316. };
  317. private:
  318. struct TSetOp {
  319. static constexpr TChunk Op(const TChunk src, const TChunk mask) noexcept {
  320. return src | mask;
  321. }
  322. };
  323. struct TResetOp {
  324. static constexpr TChunk Op(const TChunk src, const TChunk mask) noexcept {
  325. return src & ~mask;
  326. }
  327. };
  328. template <class TUpdateOp>
  329. void UpdateRange(size_t start, size_t end) {
  330. const size_t startChunk = start >> DivCount;
  331. const size_t startBitOffset = start & ModMask;
  332. const size_t endChunk = end >> DivCount;
  333. const size_t endBitOffset = end & ModMask;
  334. size_t bitOffset = startBitOffset;
  335. for (size_t chunk = startChunk; chunk <= endChunk; ++chunk) {
  336. TChunk updateMask = FullChunk << bitOffset;
  337. if (chunk == endChunk) {
  338. updateMask ^= FullChunk << endBitOffset;
  339. if (!updateMask) {
  340. break;
  341. }
  342. }
  343. Mask.Data[chunk] = TUpdateOp::Op(Mask.Data[chunk], updateMask);
  344. bitOffset = 0;
  345. }
  346. }
  347. public:
  348. TBitMapOps() = default;
  349. TBitMapOps(TChunk val) {
  350. Mask.Data[0] = val;
  351. Mask.Sanitize();
  352. }
  353. TBitMapOps(const TThis&) = default;
  354. template <class T>
  355. TBitMapOps(const TBitMapOps<T>& bitmap)
  356. : Mask(bitmap.Mask.Data, bitmap.Mask.GetChunkCapacity())
  357. {
  358. Mask.Sanitize();
  359. }
  360. template <class T>
  361. Y_FORCE_INLINE bool operator==(const TBitMapOps<T>& bitmap) const {
  362. return Equal(bitmap);
  363. }
  364. Y_FORCE_INLINE TThis& operator=(const TThis& bitmap) {
  365. if (this != &bitmap) {
  366. TThis bm(bitmap);
  367. Swap(bm);
  368. }
  369. return *this;
  370. }
  371. template <class T>
  372. Y_FORCE_INLINE TThis& operator=(const TBitMapOps<T>& bitmap) {
  373. TThis bm(bitmap);
  374. Swap(bm);
  375. return *this;
  376. }
  377. template <class T>
  378. Y_FORCE_INLINE TThis& operator&=(const TBitMapOps<T>& bitmap) {
  379. return And(bitmap);
  380. }
  381. Y_FORCE_INLINE TThis& operator&=(const TChunk& val) {
  382. return And(val);
  383. }
  384. template <class T>
  385. Y_FORCE_INLINE TThis& operator|=(const TBitMapOps<T>& bitmap) {
  386. return Or(bitmap);
  387. }
  388. Y_FORCE_INLINE TThis& operator|=(const TChunk& val) {
  389. return Or(val);
  390. }
  391. template <class T>
  392. Y_FORCE_INLINE TThis& operator^=(const TBitMapOps<T>& bitmap) {
  393. return Xor(bitmap);
  394. }
  395. Y_FORCE_INLINE TThis& operator^=(const TChunk& val) {
  396. return Xor(val);
  397. }
  398. template <class T>
  399. Y_FORCE_INLINE TThis& operator-=(const TBitMapOps<T>& bitmap) {
  400. return SetDifference(bitmap);
  401. }
  402. Y_FORCE_INLINE TThis& operator-=(const TChunk& val) {
  403. return SetDifference(val);
  404. }
  405. Y_FORCE_INLINE TThis& operator<<=(size_t pos) {
  406. return LShift(pos);
  407. }
  408. Y_FORCE_INLINE TThis& operator>>=(size_t pos) {
  409. return RShift(pos);
  410. }
  411. Y_FORCE_INLINE TThis operator<<(size_t pos) const {
  412. return TThis(*this).LShift(pos);
  413. }
  414. Y_FORCE_INLINE TThis operator>>(size_t pos) const {
  415. return TThis(*this).RShift(pos);
  416. }
  417. Y_FORCE_INLINE bool operator[](size_t pos) const {
  418. return Get(pos);
  419. }
  420. Y_FORCE_INLINE TReference operator[](size_t pos) {
  421. const bool fitStorage = Mask.ExpandBitSize(pos + 1);
  422. Y_ASSERT(fitStorage);
  423. return TReference(&Mask.Data[pos >> DivCount], ModMask & pos);
  424. }
  425. Y_FORCE_INLINE void Swap(TThis& bitmap) {
  426. DoSwap(Mask, bitmap.Mask);
  427. }
  428. Y_FORCE_INLINE TThis& Set(size_t pos) {
  429. const bool fitStorage = Mask.ExpandBitSize(pos + 1);
  430. Y_ASSERT(fitStorage);
  431. Mask.Data[pos >> DivCount] |= static_cast<TChunk>(1) << (pos & ModMask);
  432. return *this;
  433. }
  434. // Fills the specified [start, end) bit range by the 1. Other bits are kept unchanged
  435. TThis& Set(size_t start, size_t end) {
  436. Y_ASSERT(start <= end);
  437. if (start < end) {
  438. Reserve(end);
  439. UpdateRange<TSetOp>(start, end);
  440. }
  441. return *this;
  442. }
  443. Y_FORCE_INLINE TThis& Reset(size_t pos) {
  444. if ((pos >> DivCount) < Mask.GetChunkCapacity()) {
  445. Mask.Data[pos >> DivCount] &= ~(static_cast<TChunk>(1) << (pos & ModMask));
  446. }
  447. return *this;
  448. }
  449. // Clears the specified [start, end) bit range. Other bits are kept unchanged
  450. TThis& Reset(size_t start, size_t end) {
  451. Y_ASSERT(start <= end);
  452. if (start < end && (start >> DivCount) < Mask.GetChunkCapacity()) {
  453. UpdateRange<TResetOp>(start, Min(end, Mask.GetBitCapacity()));
  454. }
  455. return *this;
  456. }
  457. Y_FORCE_INLINE TThis& Flip(size_t pos) {
  458. const bool fitStorage = Mask.ExpandBitSize(pos + 1);
  459. Y_ASSERT(fitStorage);
  460. Mask.Data[pos >> DivCount] ^= static_cast<TChunk>(1) << (pos & ModMask);
  461. return *this;
  462. }
  463. Y_FORCE_INLINE bool Get(size_t pos) const {
  464. if ((pos >> DivCount) < Mask.GetChunkCapacity()) {
  465. return Mask.Data[pos >> DivCount] & (static_cast<TChunk>(1) << (pos & ModMask));
  466. }
  467. return false;
  468. }
  469. template <class TTo>
  470. void Export(size_t pos, TTo& to) const {
  471. static_assert(std::is_unsigned<TTo>::value, "expect std::is_unsigned<TTo>::value");
  472. to = 0;
  473. size_t chunkpos = pos >> DivCount;
  474. if (chunkpos >= Mask.GetChunkCapacity()) {
  475. return;
  476. }
  477. if ((pos & ModMask) == 0) {
  478. if (sizeof(TChunk) >= sizeof(TTo)) {
  479. to = (TTo)Mask.Data[chunkpos];
  480. } else { // if (sizeof(TChunk) < sizeof(TTo))
  481. NBitMapPrivate::CopyData(&to, 1, Mask.Data + chunkpos, Min(((sizeof(TTo) * 8) >> DivCount), Mask.GetChunkCapacity() - chunkpos));
  482. }
  483. } else if ((pos & (sizeof(TTo) * 8 - 1)) == 0 && sizeof(TChunk) >= 2 * sizeof(TTo)) {
  484. to = (TTo)(Mask.Data[chunkpos] >> (pos & ModMask));
  485. } else {
  486. static constexpr size_t copyToSize = (sizeof(TChunk) >= sizeof(TTo)) ? (sizeof(TChunk) / sizeof(TTo)) + 2 : 3;
  487. TTo temp[copyToSize] = {0, 0};
  488. // or use non defined by now TBitmap<copyToSize, TTo>::CopyData,RShift(pos & ModMask),Export(0,to)
  489. NBitMapPrivate::CopyData(temp, copyToSize, Mask.Data + chunkpos, Min((sizeof(TTo) / sizeof(TChunk)) + 1, Mask.GetChunkCapacity() - chunkpos));
  490. to = (temp[0] >> (pos & ModMask)) | (temp[1] << (8 * sizeof(TTo) - (pos & ModMask)));
  491. }
  492. }
  493. Y_FORCE_INLINE bool Test(size_t n) const {
  494. return Get(n);
  495. }
  496. Y_FORCE_INLINE TThis& Push(bool val) {
  497. LShift(1);
  498. return val ? Set(0) : *this;
  499. }
  500. Y_FORCE_INLINE bool Pop() {
  501. bool val = Get(0);
  502. return RShift(1), val;
  503. }
  504. // Clear entire bitmap. Current capacity is kept unchanged
  505. Y_FORCE_INLINE TThis& Clear() {
  506. for (size_t i = 0; i < Mask.GetChunkCapacity(); ++i) {
  507. Mask.Data[i] = 0;
  508. }
  509. return *this;
  510. }
  511. // Returns bits capacity
  512. Y_FORCE_INLINE constexpr size_t Size() const noexcept {
  513. return Mask.GetBitCapacity();
  514. }
  515. Y_FORCE_INLINE void Reserve(size_t bitCount) {
  516. Y_ABORT_UNLESS(Mask.ExpandBitSize(bitCount), "Exceeding bitmap storage capacity");
  517. }
  518. Y_FORCE_INLINE size_t ValueBitCount() const {
  519. size_t nonZeroChunk = Mask.GetChunkCapacity() - 1;
  520. while (nonZeroChunk != 0 && !Mask.Data[nonZeroChunk]) {
  521. --nonZeroChunk;
  522. }
  523. return nonZeroChunk || Mask.Data[nonZeroChunk]
  524. ? nonZeroChunk * BitsPerChunk + GetValueBitCount(TIntType(Mask.Data[nonZeroChunk]))
  525. : 0;
  526. }
  527. Y_PURE_FUNCTION Y_FORCE_INLINE bool Empty() const {
  528. for (size_t i = 0; i < Mask.GetChunkCapacity(); ++i) {
  529. if (Mask.Data[i]) {
  530. return false;
  531. }
  532. }
  533. return true;
  534. }
  535. bool HasAny(const TThis& bitmap) const {
  536. for (size_t i = 0; i < Min(Mask.GetChunkCapacity(), bitmap.Mask.GetChunkCapacity()); ++i) {
  537. if (0 != (Mask.Data[i] & bitmap.Mask.Data[i])) {
  538. return true;
  539. }
  540. }
  541. return false;
  542. }
  543. template <class T>
  544. Y_FORCE_INLINE bool HasAny(const TBitMapOps<T>& bitmap) const {
  545. return HasAny(TThis(bitmap));
  546. }
  547. Y_FORCE_INLINE bool HasAny(const TChunk& val) const {
  548. return 0 != (Mask.Data[0] & val);
  549. }
  550. bool HasAll(const TThis& bitmap) const {
  551. for (size_t i = 0; i < Min(Mask.GetChunkCapacity(), bitmap.Mask.GetChunkCapacity()); ++i) {
  552. if (bitmap.Mask.Data[i] != (Mask.Data[i] & bitmap.Mask.Data[i])) {
  553. return false;
  554. }
  555. }
  556. for (size_t i = Mask.GetChunkCapacity(); i < bitmap.Mask.GetChunkCapacity(); ++i) {
  557. if (bitmap.Mask.Data[i] != 0) {
  558. return false;
  559. }
  560. }
  561. return true;
  562. }
  563. template <class T>
  564. Y_FORCE_INLINE bool HasAll(const TBitMapOps<T>& bitmap) const {
  565. return HasAll(TThis(bitmap));
  566. }
  567. Y_FORCE_INLINE bool HasAll(const TChunk& val) const {
  568. return (Mask.Data[0] & val) == val;
  569. }
  570. TThis& And(const TThis& bitmap) {
  571. // Don't expand capacity here, because resulting bits in positions,
  572. // which are greater then size of one of these bitmaps, will be zero
  573. for (size_t i = 0; i < Min(bitmap.Mask.GetChunkCapacity(), Mask.GetChunkCapacity()); ++i) {
  574. Mask.Data[i] &= bitmap.Mask.Data[i];
  575. }
  576. // Clear bits if current bitmap size is greater than AND-ed one
  577. for (size_t i = bitmap.Mask.GetChunkCapacity(); i < Mask.GetChunkCapacity(); ++i) {
  578. Mask.Data[i] = 0;
  579. }
  580. return *this;
  581. }
  582. template <class T>
  583. Y_FORCE_INLINE TThis& And(const TBitMapOps<T>& bitmap) {
  584. return And(TThis(bitmap));
  585. }
  586. Y_FORCE_INLINE TThis& And(const TChunk& val) {
  587. Mask.Data[0] &= val;
  588. for (size_t i = 1; i < Mask.GetChunkCapacity(); ++i) {
  589. Mask.Data[i] = 0;
  590. }
  591. return *this;
  592. }
  593. TThis& Or(const TThis& bitmap) {
  594. const size_t valueBitCount = bitmap.ValueBitCount();
  595. if (valueBitCount) {
  596. // Memory optimization: expand size only for non-zero bits
  597. Reserve(valueBitCount);
  598. for (size_t i = 0; i < Min(bitmap.Mask.GetChunkCapacity(), Mask.GetChunkCapacity()); ++i) {
  599. Mask.Data[i] |= bitmap.Mask.Data[i];
  600. }
  601. }
  602. return *this;
  603. }
  604. template <class T>
  605. Y_FORCE_INLINE TThis& Or(const TBitMapOps<T>& bitmap) {
  606. return Or(TThis(bitmap));
  607. }
  608. Y_FORCE_INLINE TThis& Or(const TChunk& val) {
  609. Mask.Data[0] |= val;
  610. Mask.Sanitize();
  611. return *this;
  612. }
  613. TThis& Xor(const TThis& bitmap) {
  614. Reserve(bitmap.Size());
  615. for (size_t i = 0; i < bitmap.Mask.GetChunkCapacity(); ++i) {
  616. Mask.Data[i] ^= bitmap.Mask.Data[i];
  617. }
  618. return *this;
  619. }
  620. template <class T>
  621. Y_FORCE_INLINE TThis& Xor(const TBitMapOps<T>& bitmap) {
  622. return Xor(TThis(bitmap));
  623. }
  624. Y_FORCE_INLINE TThis& Xor(const TChunk& val) {
  625. Mask.Data[0] ^= val;
  626. Mask.Sanitize();
  627. return *this;
  628. }
  629. TThis& SetDifference(const TThis& bitmap) {
  630. for (size_t i = 0; i < Min(bitmap.Mask.GetChunkCapacity(), Mask.GetChunkCapacity()); ++i) {
  631. Mask.Data[i] &= ~bitmap.Mask.Data[i];
  632. }
  633. return *this;
  634. }
  635. template <class T>
  636. Y_FORCE_INLINE TThis& SetDifference(const TBitMapOps<T>& bitmap) {
  637. return SetDifference(TThis(bitmap));
  638. }
  639. Y_FORCE_INLINE TThis& SetDifference(const TChunk& val) {
  640. Mask.Data[0] &= ~val;
  641. return *this;
  642. }
  643. Y_FORCE_INLINE TThis& Flip() {
  644. for (size_t i = 0; i < Mask.GetChunkCapacity(); ++i) {
  645. Mask.Data[i] = ~Mask.Data[i];
  646. }
  647. Mask.Sanitize();
  648. return *this;
  649. }
  650. TThis& LShift(size_t shift) {
  651. if (shift != 0) {
  652. const size_t valueBitCount = ValueBitCount();
  653. // Do nothing for empty bitmap
  654. if (valueBitCount != 0) {
  655. const size_t eshift = shift / BitsPerChunk;
  656. const size_t offset = shift % BitsPerChunk;
  657. const size_t subOffset = BitsPerChunk - offset;
  658. // Don't verify expand result, so l-shift of fixed bitmap will work in the same way as for unsigned integer.
  659. Mask.ExpandBitSize(valueBitCount + shift);
  660. if (offset == 0) {
  661. for (size_t i = Mask.GetChunkCapacity() - 1; i >= eshift; --i) {
  662. Mask.Data[i] = Mask.Data[i - eshift];
  663. }
  664. } else {
  665. for (size_t i = Mask.GetChunkCapacity() - 1; i > eshift; --i) {
  666. Mask.Data[i] = (Mask.Data[i - eshift] << offset) | (Mask.Data[i - eshift - 1] >> subOffset);
  667. }
  668. if (eshift < Mask.GetChunkCapacity()) {
  669. Mask.Data[eshift] = Mask.Data[0] << offset;
  670. }
  671. }
  672. for (size_t i = 0; i < Min(eshift, Mask.GetChunkCapacity()); ++i) {
  673. Mask.Data[i] = 0;
  674. }
  675. // Cleanup extra high bits in the storage
  676. Mask.Sanitize();
  677. }
  678. }
  679. return *this;
  680. }
  681. TThis& RShift(size_t shift) {
  682. if (shift != 0) {
  683. const size_t eshift = shift / BitsPerChunk;
  684. const size_t offset = shift % BitsPerChunk;
  685. if (eshift >= Mask.GetChunkCapacity()) {
  686. Clear();
  687. } else {
  688. const size_t limit = Mask.GetChunkCapacity() - eshift - 1;
  689. if (offset == 0) {
  690. for (size_t i = 0; i <= limit; ++i) {
  691. Mask.Data[i] = Mask.Data[i + eshift];
  692. }
  693. } else {
  694. const size_t subOffset = BitsPerChunk - offset;
  695. for (size_t i = 0; i < limit; ++i) {
  696. Mask.Data[i] = (Mask.Data[i + eshift] >> offset) | (Mask.Data[i + eshift + 1] << subOffset);
  697. }
  698. Mask.Data[limit] = Mask.Data[Mask.GetChunkCapacity() - 1] >> offset;
  699. }
  700. for (size_t i = limit + 1; i < Mask.GetChunkCapacity(); ++i) {
  701. Mask.Data[i] = 0;
  702. }
  703. }
  704. }
  705. return *this;
  706. }
  707. // Applies bitmap at the specified offset using OR operator.
  708. // This method is optimized combination of Or() and LShift(), which allows reducing memory allocation
  709. // when combining long dynamic bitmaps.
  710. TThis& Or(const TThis& bitmap, size_t offset) {
  711. if (0 == offset) {
  712. return Or(bitmap);
  713. }
  714. const size_t otherValueBitCount = bitmap.ValueBitCount();
  715. // Continue only if OR-ed bitmap have non-zero bits
  716. if (otherValueBitCount) {
  717. const size_t chunkShift = offset / BitsPerChunk;
  718. const size_t subShift = offset % BitsPerChunk;
  719. const size_t subOffset = BitsPerChunk - subShift;
  720. Reserve(otherValueBitCount + offset);
  721. if (subShift == 0) {
  722. for (size_t i = chunkShift; i < Min(bitmap.Mask.GetChunkCapacity() + chunkShift, Mask.GetChunkCapacity()); ++i) {
  723. Mask.Data[i] |= bitmap.Mask.Data[i - chunkShift];
  724. }
  725. } else {
  726. Mask.Data[chunkShift] |= bitmap.Mask.Data[0] << subShift;
  727. size_t i = chunkShift + 1;
  728. for (; i < Min(bitmap.Mask.GetChunkCapacity() + chunkShift, Mask.GetChunkCapacity()); ++i) {
  729. Mask.Data[i] |= (bitmap.Mask.Data[i - chunkShift] << subShift) | (bitmap.Mask.Data[i - chunkShift - 1] >> subOffset);
  730. }
  731. if (i < Mask.GetChunkCapacity()) {
  732. Mask.Data[i] |= bitmap.Mask.Data[i - chunkShift - 1] >> subOffset;
  733. }
  734. }
  735. }
  736. return *this;
  737. }
  738. bool Equal(const TThis& bitmap) const {
  739. if (Mask.GetChunkCapacity() > bitmap.Mask.GetChunkCapacity()) {
  740. for (size_t i = bitmap.Mask.GetChunkCapacity(); i < Mask.GetChunkCapacity(); ++i) {
  741. if (0 != Mask.Data[i]) {
  742. return false;
  743. }
  744. }
  745. } else if (Mask.GetChunkCapacity() < bitmap.Mask.GetChunkCapacity()) {
  746. for (size_t i = Mask.GetChunkCapacity(); i < bitmap.Mask.GetChunkCapacity(); ++i) {
  747. if (0 != bitmap.Mask.Data[i]) {
  748. return false;
  749. }
  750. }
  751. }
  752. size_t size = Min(Mask.GetChunkCapacity(), bitmap.Mask.GetChunkCapacity());
  753. for (size_t i = 0; i < size; ++i) {
  754. if (Mask.Data[i] != bitmap.Mask.Data[i]) {
  755. return false;
  756. }
  757. }
  758. return true;
  759. }
  760. template <class T>
  761. Y_FORCE_INLINE bool Equal(const TBitMapOps<T>& bitmap) const {
  762. return Equal(TThis(bitmap));
  763. }
  764. int Compare(const TThis& bitmap) const {
  765. size_t size = Min(Mask.GetChunkCapacity(), bitmap.Mask.GetChunkCapacity());
  766. int res = ::memcmp(Mask.Data, bitmap.Mask.Data, size * sizeof(TChunk));
  767. if (0 != res || Mask.GetChunkCapacity() == bitmap.Mask.GetChunkCapacity()) {
  768. return res;
  769. }
  770. if (Mask.GetChunkCapacity() > bitmap.Mask.GetChunkCapacity()) {
  771. for (size_t i = bitmap.Mask.GetChunkCapacity(); i < Mask.GetChunkCapacity(); ++i) {
  772. if (0 != Mask.Data[i]) {
  773. return 1;
  774. }
  775. }
  776. } else {
  777. for (size_t i = Mask.GetChunkCapacity(); i < bitmap.Mask.GetChunkCapacity(); ++i) {
  778. if (0 != bitmap.Mask.Data[i]) {
  779. return -1;
  780. }
  781. }
  782. }
  783. return 0;
  784. }
  785. template <class T>
  786. Y_FORCE_INLINE int Compare(const TBitMapOps<T>& bitmap) const {
  787. return Compare(TThis(bitmap));
  788. }
  789. // For backward compatibility
  790. Y_FORCE_INLINE static int Compare(const TThis& l, const TThis& r) {
  791. return l.Compare(r);
  792. }
  793. size_t FirstNonZeroBit() const {
  794. for (size_t i = 0; i < Mask.GetChunkCapacity(); ++i) {
  795. if (Mask.Data[i]) {
  796. // CountTrailingZeroBits() expects unsigned types not smaller than unsigned int. So, convert before calling
  797. return BitsPerChunk * i + CountTrailingZeroBits(TIntType(Mask.Data[i]));
  798. }
  799. }
  800. return Size();
  801. }
  802. // Returns position of the next non-zero bit, which offset is greater than specified pos
  803. // Typical loop for iterating bits:
  804. // for (size_t pos = bits.FirstNonZeroBit(); pos != bits.Size(); pos = bits.NextNonZeroBit(pos)) {
  805. // ...
  806. // }
  807. // See Y_FOR_EACH_BIT macro definition at the bottom
  808. size_t NextNonZeroBit(size_t pos) const {
  809. size_t i = (pos + 1) >> DivCount;
  810. if (i < Mask.GetChunkCapacity()) {
  811. const size_t offset = (pos + 1) & ModMask;
  812. // Process the current chunk
  813. if (offset) {
  814. // Zero already iterated trailing bits using mask
  815. const TChunk val = Mask.Data[i] & ((~TChunk(0)) << offset);
  816. if (val) {
  817. return BitsPerChunk * i + CountTrailingZeroBits(TIntType(val));
  818. }
  819. // Continue with other chunks
  820. ++i;
  821. }
  822. for (; i < Mask.GetChunkCapacity(); ++i) {
  823. if (Mask.Data[i]) {
  824. return BitsPerChunk * i + CountTrailingZeroBits(TIntType(Mask.Data[i]));
  825. }
  826. }
  827. }
  828. return Size();
  829. }
  830. Y_FORCE_INLINE size_t Count() const {
  831. size_t count = 0;
  832. for (size_t i = 0; i < Mask.GetChunkCapacity(); ++i) {
  833. count += ::NBitMapPrivate::CountBitsPrivate(Mask.Data[i]);
  834. }
  835. return count;
  836. }
  837. void Save(IOutputStream* out) const {
  838. ::Save(out, ui8(sizeof(TChunk)));
  839. ::Save(out, ui64(Size()));
  840. ::SavePodArray(out, Mask.Data, Mask.GetChunkCapacity());
  841. }
  842. void Load(IInputStream* inp) {
  843. ui8 chunkSize = 0;
  844. ::Load(inp, chunkSize);
  845. Y_ABORT_UNLESS(size_t(chunkSize) == sizeof(TChunk), "Chunk size is not the same");
  846. ui64 bitCount64 = 0;
  847. ::Load(inp, bitCount64);
  848. size_t bitCount = size_t(bitCount64);
  849. Reserve(bitCount);
  850. size_t chunkCount = 0;
  851. if (bitCount > 0) {
  852. chunkCount = ((bitCount - 1) >> DivCount) + 1;
  853. ::LoadPodArray(inp, Mask.Data, chunkCount);
  854. }
  855. if (chunkCount < Mask.GetChunkCapacity()) {
  856. ::memset(Mask.Data + chunkCount, 0, (Mask.GetChunkCapacity() - chunkCount) * sizeof(TChunk));
  857. }
  858. Mask.Sanitize();
  859. }
  860. inline size_t Hash() const {
  861. THash<TChunk> chunkHasher;
  862. size_t hash = chunkHasher(0);
  863. bool tailSkipped = false;
  864. for (size_t i = Mask.GetChunkCapacity(); i > 0; --i) {
  865. if (tailSkipped || Mask.Data[i - 1]) {
  866. hash = ::CombineHashes(hash, chunkHasher(Mask.Data[i - 1]));
  867. tailSkipped = true;
  868. }
  869. }
  870. return hash;
  871. }
  872. inline const TChunk* GetChunks() const {
  873. return Mask.Data;
  874. }
  875. constexpr size_t GetChunkCount() const noexcept {
  876. return Mask.GetChunkCapacity();
  877. }
  878. };
  879. template <class X, class Y>
  880. inline TBitMapOps<X> operator&(const TBitMapOps<X>& x, const TBitMapOps<Y>& y) {
  881. return TBitMapOps<X>(x).And(y);
  882. }
  883. template <class X>
  884. inline TBitMapOps<X> operator&(const TBitMapOps<X>& x, const typename TBitMapOps<X>::TChunk& y) {
  885. return TBitMapOps<X>(x).And(y);
  886. }
  887. template <class X>
  888. inline TBitMapOps<X> operator&(const typename TBitMapOps<X>::TChunk& x, const TBitMapOps<X>& y) {
  889. return TBitMapOps<X>(x).And(y);
  890. }
  891. template <class X, class Y>
  892. inline TBitMapOps<X> operator|(const TBitMapOps<X>& x, const TBitMapOps<Y>& y) {
  893. return TBitMapOps<X>(x).Or(y);
  894. }
  895. template <class X>
  896. inline TBitMapOps<X> operator|(const TBitMapOps<X>& x, const typename TBitMapOps<X>::TChunk& y) {
  897. return TBitMapOps<X>(x).Or(y);
  898. }
  899. template <class X>
  900. inline TBitMapOps<X> operator|(const typename TBitMapOps<X>::TChunk& x, const TBitMapOps<X>& y) {
  901. return TBitMapOps<X>(x).Or(y);
  902. }
  903. template <class X, class Y>
  904. inline TBitMapOps<X> operator^(const TBitMapOps<X>& x, const TBitMapOps<Y>& y) {
  905. return TBitMapOps<X>(x).Xor(y);
  906. }
  907. template <class X>
  908. inline TBitMapOps<X> operator^(const TBitMapOps<X>& x, const typename TBitMapOps<X>::TChunk& y) {
  909. return TBitMapOps<X>(x).Xor(y);
  910. }
  911. template <class X>
  912. inline TBitMapOps<X> operator^(const typename TBitMapOps<X>::TChunk& x, const TBitMapOps<X>& y) {
  913. return TBitMapOps<X>(x).Xor(y);
  914. }
  915. template <class X, class Y>
  916. inline TBitMapOps<X> operator-(const TBitMapOps<X>& x, const TBitMapOps<Y>& y) {
  917. return TBitMapOps<X>(x).SetDifference(y);
  918. }
  919. template <class X>
  920. inline TBitMapOps<X> operator-(const TBitMapOps<X>& x, const typename TBitMapOps<X>::TChunk& y) {
  921. return TBitMapOps<X>(x).SetDifference(y);
  922. }
  923. template <class X>
  924. inline TBitMapOps<X> operator-(const typename TBitMapOps<X>::TChunk& x, const TBitMapOps<X>& y) {
  925. return TBitMapOps<X>(x).SetDifference(y);
  926. }
  927. template <class X>
  928. inline TBitMapOps<X> operator~(const TBitMapOps<X>& x) {
  929. return TBitMapOps<X>(x).Flip();
  930. }
  931. /////////////////// Specialization ///////////////////////////
  932. template <size_t BitCount, typename TChunkType /*= ui64*/>
  933. class TBitMap: public TBitMapOps<TFixedBitMapTraits<BitCount, TChunkType>> {
  934. private:
  935. using TBase = TBitMapOps<TFixedBitMapTraits<BitCount, TChunkType>>;
  936. public:
  937. TBitMap()
  938. : TBase()
  939. {
  940. }
  941. TBitMap(typename TBase::TChunk val)
  942. : TBase(val)
  943. {
  944. }
  945. TBitMap(const TBitMap&) = default;
  946. TBitMap& operator=(const TBitMap&) = default;
  947. template <class T>
  948. TBitMap(const TBitMapOps<T>& bitmap)
  949. : TBase(bitmap)
  950. {
  951. }
  952. };
  953. using TDynBitMap = TBitMapOps<TDynamicBitMapTraits<ui64>>;
  954. #define Y_FOR_EACH_BIT(var, bitmap) for (size_t var = (bitmap).FirstNonZeroBit(); var != (bitmap).Size(); var = (bitmap).NextNonZeroBit(var))
  955. template <typename TTraits>
  956. struct THash<TBitMapOps<TTraits>> {
  957. size_t operator()(const TBitMapOps<TTraits>& elem) const {
  958. return elem.Hash();
  959. }
  960. };