roaring64map.hh 69 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882
  1. /**
  2. * A C++ header for 64-bit Roaring Bitmaps,
  3. * implemented by way of a map of many
  4. * 32-bit Roaring Bitmaps.
  5. *
  6. * Reference (format specification) :
  7. * https://github.com/RoaringBitmap/RoaringFormatSpec#extention-for-64-bit-implementations
  8. */
  9. #ifndef INCLUDE_ROARING_64_MAP_HH_
  10. #define INCLUDE_ROARING_64_MAP_HH_
  11. #include <algorithm>
  12. #include <cinttypes> // PRIu64 macro
  13. #include <cstdarg> // for va_list handling in bitmapOf()
  14. #include <cstdio> // for std::printf() in the printf() method
  15. #include <cstring> // for std::memcpy()
  16. #include <functional>
  17. #include <initializer_list>
  18. #include <limits>
  19. #include <map>
  20. #include <new>
  21. #include <numeric>
  22. #include <queue>
  23. #include <stdexcept>
  24. #include <string>
  25. #include <utility>
  26. #include "roaring.hh"
  27. namespace roaring {
  28. using roaring::Roaring;
  29. class Roaring64MapSetBitBiDirectionalIterator;
  30. // For backwards compatibility; there used to be two kinds of iterators
  31. // (forward and bidirectional) and now there's only one.
  32. typedef Roaring64MapSetBitBiDirectionalIterator
  33. Roaring64MapSetBitForwardIterator;
  34. class Roaring64Map {
  35. typedef api::roaring_bitmap_t roaring_bitmap_t;
  36. public:
  37. /**
  38. * Create an empty bitmap
  39. */
  40. Roaring64Map() = default;
  41. /**
  42. * Construct a bitmap from a list of 32-bit integer values.
  43. */
  44. Roaring64Map(size_t n, const uint32_t *data) { addMany(n, data); }
  45. /**
  46. * Construct a bitmap from a list of 64-bit integer values.
  47. */
  48. Roaring64Map(size_t n, const uint64_t *data) { addMany(n, data); }
  49. /**
  50. * Construct a bitmap from an initializer list.
  51. */
  52. Roaring64Map(std::initializer_list<uint64_t> l) {
  53. addMany(l.size(), l.begin());
  54. }
  55. /**
  56. * Construct a 64-bit map from a 32-bit one
  57. */
  58. explicit Roaring64Map(const Roaring &r) { emplaceOrInsert(0, r); }
  59. /**
  60. * Construct a 64-bit map from a 32-bit rvalue
  61. */
  62. explicit Roaring64Map(Roaring &&r) { emplaceOrInsert(0, std::move(r)); }
  63. /**
  64. * Construct a roaring object from the C struct.
  65. *
  66. * Passing a NULL point is unsafe.
  67. */
  68. explicit Roaring64Map(roaring_bitmap_t *s) {
  69. emplaceOrInsert(0, Roaring(s));
  70. }
  71. Roaring64Map(const Roaring64Map &r) = default;
  72. Roaring64Map(Roaring64Map &&r) noexcept = default;
  73. /**
  74. * Copy assignment operator.
  75. */
  76. Roaring64Map &operator=(const Roaring64Map &r) = default;
  77. /**
  78. * Move assignment operator.
  79. */
  80. Roaring64Map &operator=(Roaring64Map &&r) noexcept = default;
  81. /**
  82. * Assignment from an initializer list.
  83. */
  84. Roaring64Map &operator=(std::initializer_list<uint64_t> l) {
  85. // Delegate to move assignment operator
  86. *this = Roaring64Map(l);
  87. return *this;
  88. }
  89. /**
  90. * Construct a bitmap from a list of uint64_t values.
  91. */
  92. static Roaring64Map bitmapOf(size_t n...) {
  93. Roaring64Map ans;
  94. va_list vl;
  95. va_start(vl, n);
  96. for (size_t i = 0; i < n; i++) {
  97. ans.add(va_arg(vl, uint64_t));
  98. }
  99. va_end(vl);
  100. return ans;
  101. }
  102. /**
  103. * Construct a bitmap from a list of uint64_t values.
  104. * E.g., bitmapOfList({1,2,3}).
  105. */
  106. static Roaring64Map bitmapOfList(std::initializer_list<uint64_t> l) {
  107. Roaring64Map ans;
  108. ans.addMany(l.size(), l.begin());
  109. return ans;
  110. }
  111. /**
  112. * Adds value x.
  113. */
  114. void add(uint32_t x) { lookupOrCreateInner(0).add(x); }
  115. /**
  116. * Adds value x.
  117. */
  118. void add(uint64_t x) { lookupOrCreateInner(highBytes(x)).add(lowBytes(x)); }
  119. /**
  120. * Adds value x.
  121. * Returns true if a new value was added, false if the value was already
  122. * present.
  123. */
  124. bool addChecked(uint32_t x) { return lookupOrCreateInner(0).addChecked(x); }
  125. /**
  126. * Adds value x.
  127. * Returns true if a new value was added, false if the value was already
  128. * present.
  129. */
  130. bool addChecked(uint64_t x) {
  131. return lookupOrCreateInner(highBytes(x)).addChecked(lowBytes(x));
  132. }
  133. /**
  134. * Adds all values in the half-open interval [min, max).
  135. */
  136. void addRange(uint64_t min, uint64_t max) {
  137. if (min >= max) {
  138. return;
  139. }
  140. addRangeClosed(min, max - 1);
  141. }
  142. /**
  143. * Adds all values in the closed interval [min, max].
  144. */
  145. void addRangeClosed(uint32_t min, uint32_t max) {
  146. lookupOrCreateInner(0).addRangeClosed(min, max);
  147. }
  148. /**
  149. * Adds all values in the closed interval [min, max]
  150. */
  151. void addRangeClosed(uint64_t min, uint64_t max) {
  152. if (min > max) {
  153. return;
  154. }
  155. uint32_t start_high = highBytes(min);
  156. uint32_t start_low = lowBytes(min);
  157. uint32_t end_high = highBytes(max);
  158. uint32_t end_low = lowBytes(max);
  159. // We put std::numeric_limits<>::max in parentheses to avoid a
  160. // clash with the Windows.h header under Windows.
  161. const uint32_t uint32_max = (std::numeric_limits<uint32_t>::max)();
  162. // Fill in any nonexistent slots with empty Roarings. This simplifies
  163. // the logic below, allowing it to simply iterate over the map between
  164. // 'start_high' and 'end_high' in a linear fashion.
  165. auto current_iter = ensureRangePopulated(start_high, end_high);
  166. // If start and end land on the same inner bitmap, then we can do the
  167. // whole operation in one call.
  168. if (start_high == end_high) {
  169. auto &bitmap = current_iter->second;
  170. bitmap.addRangeClosed(start_low, end_low);
  171. return;
  172. }
  173. // Because start and end don't land on the same inner bitmap,
  174. // we need to do this in multiple steps:
  175. // 1. Partially fill the first bitmap with values from the closed
  176. // interval [start_low, uint32_max]
  177. // 2. Fill intermediate bitmaps completely: [0, uint32_max]
  178. // 3. Partially fill the last bitmap with values from the closed
  179. // interval [0, end_low]
  180. auto num_intermediate_bitmaps = end_high - start_high - 1;
  181. // Step 1: Partially fill the first bitmap.
  182. {
  183. auto &bitmap = current_iter->second;
  184. bitmap.addRangeClosed(start_low, uint32_max);
  185. ++current_iter;
  186. }
  187. // Step 2. Fill intermediate bitmaps completely.
  188. if (num_intermediate_bitmaps != 0) {
  189. auto &first_intermediate = current_iter->second;
  190. first_intermediate.addRangeClosed(0, uint32_max);
  191. ++current_iter;
  192. // Now make (num_intermediate_bitmaps - 1) copies of this.
  193. for (uint32_t i = 1; i != num_intermediate_bitmaps; ++i) {
  194. auto &next_intermediate = current_iter->second;
  195. next_intermediate = first_intermediate;
  196. ++current_iter;
  197. }
  198. }
  199. // Step 3: Partially fill the last bitmap.
  200. auto &bitmap = current_iter->second;
  201. bitmap.addRangeClosed(0, end_low);
  202. }
  203. /**
  204. * Adds 'n_args' values from the contiguous memory range starting at 'vals'.
  205. */
  206. void addMany(size_t n_args, const uint32_t *vals) {
  207. lookupOrCreateInner(0).addMany(n_args, vals);
  208. }
  209. /**
  210. * Adds 'n_args' values from the contiguous memory range starting at 'vals'.
  211. */
  212. void addMany(size_t n_args, const uint64_t *vals) {
  213. // Potentially reduce outer map lookups by optimistically
  214. // assuming that adjacent values will belong to the same inner bitmap.
  215. Roaring *last_inner_bitmap = nullptr;
  216. uint32_t last_value_high = 0;
  217. BulkContext last_bulk_context;
  218. for (size_t lcv = 0; lcv < n_args; lcv++) {
  219. auto value = vals[lcv];
  220. auto value_high = highBytes(value);
  221. auto value_low = lowBytes(value);
  222. if (last_inner_bitmap == nullptr || value_high != last_value_high) {
  223. last_inner_bitmap = &lookupOrCreateInner(value_high);
  224. last_value_high = value_high;
  225. last_bulk_context = BulkContext{};
  226. }
  227. last_inner_bitmap->addBulk(last_bulk_context, value_low);
  228. }
  229. }
  230. /**
  231. * Removes value x.
  232. */
  233. void remove(uint32_t x) {
  234. auto iter = roarings.begin();
  235. // Since x is a uint32_t, highbytes(x) == 0. The inner bitmap we are
  236. // looking for, if it exists, will be at the first slot of 'roarings'.
  237. if (iter == roarings.end() || iter->first != 0) {
  238. return;
  239. }
  240. auto &bitmap = iter->second;
  241. bitmap.remove(x);
  242. eraseIfEmpty(iter);
  243. }
  244. /**
  245. * Removes value x.
  246. */
  247. void remove(uint64_t x) {
  248. auto iter = roarings.find(highBytes(x));
  249. if (iter == roarings.end()) {
  250. return;
  251. }
  252. auto &bitmap = iter->second;
  253. bitmap.remove(lowBytes(x));
  254. eraseIfEmpty(iter);
  255. }
  256. /**
  257. * Removes value x
  258. * Returns true if a new value was removed, false if the value was not
  259. * present.
  260. */
  261. bool removeChecked(uint32_t x) {
  262. auto iter = roarings.begin();
  263. // Since x is a uint32_t, highbytes(x) == 0. The inner bitmap we are
  264. // looking for, if it exists, will be at the first slot of 'roarings'.
  265. if (iter == roarings.end() || iter->first != 0) {
  266. return false;
  267. }
  268. auto &bitmap = iter->second;
  269. if (!bitmap.removeChecked(x)) {
  270. return false;
  271. }
  272. eraseIfEmpty(iter);
  273. return true;
  274. }
  275. /**
  276. * Remove value x
  277. * Returns true if a new value was removed, false if the value was not
  278. * present.
  279. */
  280. bool removeChecked(uint64_t x) {
  281. auto iter = roarings.find(highBytes(x));
  282. if (iter == roarings.end()) {
  283. return false;
  284. }
  285. auto &bitmap = iter->second;
  286. if (!bitmap.removeChecked(lowBytes(x))) {
  287. return false;
  288. }
  289. eraseIfEmpty(iter);
  290. return true;
  291. }
  292. /**
  293. * Removes all values in the half-open interval [min, max).
  294. */
  295. void removeRange(uint64_t min, uint64_t max) {
  296. if (min >= max) {
  297. return;
  298. }
  299. return removeRangeClosed(min, max - 1);
  300. }
  301. /**
  302. * Removes all values in the closed interval [min, max].
  303. */
  304. void removeRangeClosed(uint32_t min, uint32_t max) {
  305. auto iter = roarings.begin();
  306. // Since min and max are uint32_t, highbytes(min or max) == 0. The inner
  307. // bitmap we are looking for, if it exists, will be at the first slot of
  308. // 'roarings'.
  309. if (iter == roarings.end() || iter->first != 0) {
  310. return;
  311. }
  312. auto &bitmap = iter->second;
  313. bitmap.removeRangeClosed(min, max);
  314. eraseIfEmpty(iter);
  315. }
  316. /**
  317. * Removes all values in the closed interval [min, max].
  318. */
  319. void removeRangeClosed(uint64_t min, uint64_t max) {
  320. if (min > max) {
  321. return;
  322. }
  323. uint32_t start_high = highBytes(min);
  324. uint32_t start_low = lowBytes(min);
  325. uint32_t end_high = highBytes(max);
  326. uint32_t end_low = lowBytes(max);
  327. // We put std::numeric_limits<>::max in parentheses to avoid a
  328. // clash with the Windows.h header under Windows.
  329. const uint32_t uint32_max = (std::numeric_limits<uint32_t>::max)();
  330. // If the outer map is empty, end_high is less than the first key,
  331. // or start_high is greater than the last key, then exit now because
  332. // there is no work to do.
  333. if (roarings.empty() || end_high < roarings.cbegin()->first ||
  334. start_high > (roarings.crbegin())->first) {
  335. return;
  336. }
  337. // If we get here, start_iter points to the first entry in the outer map
  338. // with key >= start_high. Such an entry is known to exist (i.e. the
  339. // iterator will not be equal to end()) because start_high <= the last
  340. // key in the map (thanks to the above if statement).
  341. auto start_iter = roarings.lower_bound(start_high);
  342. // end_iter points to the first entry in the outer map with
  343. // key >= end_high, if such a key exists. Otherwise, it equals end().
  344. auto end_iter = roarings.lower_bound(end_high);
  345. // Note that the 'lower_bound' method will find the start and end slots,
  346. // if they exist; otherwise it will find the next-higher slots.
  347. // In the case where 'start' landed on an existing slot, we need to do a
  348. // partial erase of that slot, and likewise for 'end'. But all the slots
  349. // in between can be fully erased. More precisely:
  350. //
  351. // 1. If the start point falls on an existing entry, there are two
  352. // subcases:
  353. // a. if the end point falls on that same entry, remove the closed
  354. // interval [start_low, end_low] from that entry and we are done.
  355. // b. Otherwise, remove the closed interval [start_low, uint32_max]
  356. // from that entry, advance start_iter, and fall through to
  357. // step 2.
  358. // 2. Completely erase all slots in the half-open interval
  359. // [start_iter, end_iter)
  360. // 3. If the end point falls on an existing entry, remove the closed
  361. // interval [0, end_high] from it.
  362. // Step 1. If the start point falls on an existing entry...
  363. if (start_iter->first == start_high) {
  364. auto &start_inner = start_iter->second;
  365. // 1a. if the end point falls on that same entry...
  366. if (start_iter == end_iter) {
  367. start_inner.removeRangeClosed(start_low, end_low);
  368. eraseIfEmpty(start_iter);
  369. return;
  370. }
  371. // 1b. Otherwise, remove the closed range [start_low, uint32_max]...
  372. start_inner.removeRangeClosed(start_low, uint32_max);
  373. // Advance start_iter, but keep the old value so we can check the
  374. // bitmap we just modified for emptiness and erase if it necessary.
  375. auto temp = start_iter++;
  376. eraseIfEmpty(temp);
  377. }
  378. // 2. Completely erase all slots in the half-open interval...
  379. roarings.erase(start_iter, end_iter);
  380. // 3. If the end point falls on an existing entry...
  381. if (end_iter != roarings.end() && end_iter->first == end_high) {
  382. auto &end_inner = end_iter->second;
  383. end_inner.removeRangeClosed(0, end_low);
  384. eraseIfEmpty(end_iter);
  385. }
  386. }
  387. /**
  388. * Clears the bitmap.
  389. */
  390. void clear() { roarings.clear(); }
  391. /**
  392. * Return the largest value (if not empty)
  393. */
  394. uint64_t maximum() const {
  395. for (auto roaring_iter = roarings.crbegin();
  396. roaring_iter != roarings.crend(); ++roaring_iter) {
  397. if (!roaring_iter->second.isEmpty()) {
  398. return uniteBytes(roaring_iter->first,
  399. roaring_iter->second.maximum());
  400. }
  401. }
  402. // we put std::numeric_limits<>::max/min in parentheses
  403. // to avoid a clash with the Windows.h header under Windows
  404. return (std::numeric_limits<uint64_t>::min)();
  405. }
  406. /**
  407. * Return the smallest value (if not empty)
  408. */
  409. uint64_t minimum() const {
  410. for (auto roaring_iter = roarings.cbegin();
  411. roaring_iter != roarings.cend(); ++roaring_iter) {
  412. if (!roaring_iter->second.isEmpty()) {
  413. return uniteBytes(roaring_iter->first,
  414. roaring_iter->second.minimum());
  415. }
  416. }
  417. // we put std::numeric_limits<>::max/min in parentheses
  418. // to avoid a clash with the Windows.h header under Windows
  419. return (std::numeric_limits<uint64_t>::max)();
  420. }
  421. /**
  422. * Check if value x is present
  423. */
  424. bool contains(uint32_t x) const {
  425. auto iter = roarings.find(0);
  426. if (iter == roarings.end()) {
  427. return false;
  428. }
  429. return iter->second.contains(x);
  430. }
  431. bool contains(uint64_t x) const {
  432. auto iter = roarings.find(highBytes(x));
  433. if (iter == roarings.end()) {
  434. return false;
  435. }
  436. return iter->second.contains(lowBytes(x));
  437. }
  438. // TODO: implement `containsRange`
  439. /**
  440. * Compute the intersection of the current bitmap and the provided bitmap,
  441. * writing the result in the current bitmap. The provided bitmap is not
  442. * modified.
  443. *
  444. * Performance hint: if you are computing the intersection between several
  445. * bitmaps, two-by-two, it is best to start with the smallest bitmap.
  446. */
  447. Roaring64Map &operator&=(const Roaring64Map &other) {
  448. if (this == &other) {
  449. // ANDing *this with itself is a no-op.
  450. return *this;
  451. }
  452. // Logic table summarizing what to do when a given outer key is
  453. // present vs. absent from self and other.
  454. //
  455. // self other (self & other) work to do
  456. // --------------------------------------------
  457. // absent absent empty None
  458. // absent present empty None
  459. // present absent empty Erase self
  460. // present present empty or not Intersect self with other, but
  461. // erase self if result is empty.
  462. //
  463. // Because there is only work to do when a key is present in 'self', the
  464. // main for loop iterates over entries in 'self'.
  465. decltype(roarings.begin()) self_next;
  466. for (auto self_iter = roarings.begin(); self_iter != roarings.end();
  467. self_iter = self_next) {
  468. // Do the 'next' operation now, so we don't have to worry about
  469. // invalidation of self_iter down below with the 'erase' operation.
  470. self_next = std::next(self_iter);
  471. auto self_key = self_iter->first;
  472. auto &self_bitmap = self_iter->second;
  473. auto other_iter = other.roarings.find(self_key);
  474. if (other_iter == other.roarings.end()) {
  475. // 'other' doesn't have self_key. In the logic table above,
  476. // this reflects the case (self.present & other.absent).
  477. // So, erase self.
  478. roarings.erase(self_iter);
  479. continue;
  480. }
  481. // Both sides have self_key. In the logic table above, this reflects
  482. // the case (self.present & other.present). So, intersect self with
  483. // other.
  484. const auto &other_bitmap = other_iter->second;
  485. self_bitmap &= other_bitmap;
  486. if (self_bitmap.isEmpty()) {
  487. // ...but if intersection is empty, remove it altogether.
  488. roarings.erase(self_iter);
  489. }
  490. }
  491. return *this;
  492. }
  493. /**
  494. * Compute the difference between the current bitmap and the provided
  495. * bitmap, writing the result in the current bitmap. The provided bitmap
  496. * is not modified.
  497. */
  498. Roaring64Map &operator-=(const Roaring64Map &other) {
  499. if (this == &other) {
  500. // Subtracting *this from itself results in the empty map.
  501. roarings.clear();
  502. return *this;
  503. }
  504. // Logic table summarizing what to do when a given outer key is
  505. // present vs. absent from self and other.
  506. //
  507. // self other (self - other) work to do
  508. // --------------------------------------------
  509. // absent absent empty None
  510. // absent present empty None
  511. // present absent unchanged None
  512. // present present empty or not Subtract other from self, but
  513. // erase self if result is empty
  514. //
  515. // Because there is only work to do when a key is present in both 'self'
  516. // and 'other', the main while loop ping-pongs back and forth until it
  517. // finds the next key that is the same on both sides.
  518. auto self_iter = roarings.begin();
  519. auto other_iter = other.roarings.cbegin();
  520. while (self_iter != roarings.end() &&
  521. other_iter != other.roarings.cend()) {
  522. auto self_key = self_iter->first;
  523. auto other_key = other_iter->first;
  524. if (self_key < other_key) {
  525. // Because self_key is < other_key, advance self_iter to the
  526. // first point where self_key >= other_key (or end).
  527. self_iter = roarings.lower_bound(other_key);
  528. continue;
  529. }
  530. if (self_key > other_key) {
  531. // Because self_key is > other_key, advance other_iter to the
  532. // first point where other_key >= self_key (or end).
  533. other_iter = other.roarings.lower_bound(self_key);
  534. continue;
  535. }
  536. // Both sides have self_key. In the logic table above, this reflects
  537. // the case (self.present & other.present). So subtract other from
  538. // self.
  539. auto &self_bitmap = self_iter->second;
  540. const auto &other_bitmap = other_iter->second;
  541. self_bitmap -= other_bitmap;
  542. if (self_bitmap.isEmpty()) {
  543. // ...but if subtraction is empty, remove it altogether.
  544. self_iter = roarings.erase(self_iter);
  545. } else {
  546. ++self_iter;
  547. }
  548. ++other_iter;
  549. }
  550. return *this;
  551. }
  552. /**
  553. * Compute the union of the current bitmap and the provided bitmap,
  554. * writing the result in the current bitmap. The provided bitmap is not
  555. * modified.
  556. *
  557. * See also the fastunion function to aggregate many bitmaps more quickly.
  558. */
  559. Roaring64Map &operator|=(const Roaring64Map &other) {
  560. if (this == &other) {
  561. // ORing *this with itself is a no-op.
  562. return *this;
  563. }
  564. // Logic table summarizing what to do when a given outer key is
  565. // present vs. absent from self and other.
  566. //
  567. // self other (self | other) work to do
  568. // --------------------------------------------
  569. // absent absent empty None
  570. // absent present not empty Copy other to self and set flags
  571. // present absent unchanged None
  572. // present present not empty self |= other
  573. //
  574. // Because there is only work to do when a key is present in 'other',
  575. // the main for loop iterates over entries in 'other'.
  576. for (const auto &other_entry : other.roarings) {
  577. const auto &other_bitmap = other_entry.second;
  578. // Try to insert other_bitmap into self at other_key. We take
  579. // advantage of the fact that std::map::insert will not overwrite an
  580. // existing entry.
  581. auto insert_result = roarings.insert(other_entry);
  582. auto self_iter = insert_result.first;
  583. auto insert_happened = insert_result.second;
  584. auto &self_bitmap = self_iter->second;
  585. if (insert_happened) {
  586. // Key was not present in self, so insert was performed above.
  587. // In the logic table above, this reflects the case
  588. // (self.absent | other.present). Because the copy has already
  589. // happened, thanks to the 'insert' operation above, we just
  590. // need to set the copyOnWrite flag.
  591. self_bitmap.setCopyOnWrite(copyOnWrite);
  592. continue;
  593. }
  594. // Both sides have self_key, and the insert was not performed. In
  595. // the logic table above, this reflects the case
  596. // (self.present & other.present). So OR other into self.
  597. self_bitmap |= other_bitmap;
  598. }
  599. return *this;
  600. }
  601. /**
  602. * Compute the XOR of the current bitmap and the provided bitmap, writing
  603. * the result in the current bitmap. The provided bitmap is not modified.
  604. */
  605. Roaring64Map &operator^=(const Roaring64Map &other) {
  606. if (this == &other) {
  607. // XORing *this with itself results in the empty map.
  608. roarings.clear();
  609. return *this;
  610. }
  611. // Logic table summarizing what to do when a given outer key is
  612. // present vs. absent from self and other.
  613. //
  614. // self other (self ^ other) work to do
  615. // --------------------------------------------
  616. // absent absent empty None
  617. // absent present non-empty Copy other to self and set flags
  618. // present absent unchanged None
  619. // present present empty or not XOR other into self, but erase self
  620. // if result is empty.
  621. //
  622. // Because there is only work to do when a key is present in 'other',
  623. // the main for loop iterates over entries in 'other'.
  624. for (const auto &other_entry : other.roarings) {
  625. const auto &other_bitmap = other_entry.second;
  626. // Try to insert other_bitmap into self at other_key. We take
  627. // advantage of the fact that std::map::insert will not overwrite an
  628. // existing entry.
  629. auto insert_result = roarings.insert(other_entry);
  630. auto self_iter = insert_result.first;
  631. auto insert_happened = insert_result.second;
  632. auto &self_bitmap = self_iter->second;
  633. if (insert_happened) {
  634. // Key was not present in self, so insert was performed above.
  635. // In the logic table above, this reflects the case
  636. // (self.absent ^ other.present). Because the copy has already
  637. // happened, thanks to the 'insert' operation above, we just
  638. // need to set the copyOnWrite flag.
  639. self_bitmap.setCopyOnWrite(copyOnWrite);
  640. continue;
  641. }
  642. // Both sides have self_key, and the insert was not performed. In
  643. // the logic table above, this reflects the case
  644. // (self.present ^ other.present). So XOR other into self.
  645. self_bitmap ^= other_bitmap;
  646. if (self_bitmap.isEmpty()) {
  647. // ...but if intersection is empty, remove it altogether.
  648. roarings.erase(self_iter);
  649. }
  650. }
  651. return *this;
  652. }
  653. /**
  654. * Exchange the content of this bitmap with another.
  655. */
  656. void swap(Roaring64Map &r) { roarings.swap(r.roarings); }
  657. /**
  658. * Get the cardinality of the bitmap (number of elements).
  659. * Throws std::length_error in the special case where the bitmap is full
  660. * (cardinality() == 2^64). Check isFull() before calling to avoid
  661. * exception.
  662. */
  663. uint64_t cardinality() const {
  664. if (isFull()) {
  665. #if ROARING_EXCEPTIONS
  666. throw std::length_error(
  667. "bitmap is full, cardinality is 2^64, "
  668. "unable to represent in a 64-bit integer");
  669. #else
  670. ROARING_TERMINATE(
  671. "bitmap is full, cardinality is 2^64, "
  672. "unable to represent in a 64-bit integer");
  673. #endif
  674. }
  675. return std::accumulate(
  676. roarings.cbegin(), roarings.cend(), (uint64_t)0,
  677. [](uint64_t previous,
  678. const std::pair<const uint32_t, Roaring> &map_entry) {
  679. return previous + map_entry.second.cardinality();
  680. });
  681. }
  682. /**
  683. * Returns true if the bitmap is empty (cardinality is zero).
  684. */
  685. bool isEmpty() const {
  686. return std::all_of(
  687. roarings.cbegin(), roarings.cend(),
  688. [](const std::pair<const uint32_t, Roaring> &map_entry) {
  689. return map_entry.second.isEmpty();
  690. });
  691. }
  692. /**
  693. * Returns true if the bitmap is full (cardinality is max uint64_t + 1).
  694. */
  695. bool isFull() const {
  696. // only bother to check if map is fully saturated
  697. //
  698. // we put std::numeric_limits<>::max/min in parentheses
  699. // to avoid a clash with the Windows.h header under Windows
  700. return roarings.size() ==
  701. ((uint64_t)(std::numeric_limits<uint32_t>::max)()) + 1
  702. ? std::all_of(roarings.cbegin(), roarings.cend(),
  703. [](const std::pair<const uint32_t, Roaring>
  704. &roaring_map_entry) {
  705. return roaring_map_entry.second.isFull();
  706. })
  707. : false;
  708. }
  709. /**
  710. * Returns true if the bitmap is subset of the other.
  711. */
  712. bool isSubset(const Roaring64Map &r) const {
  713. for (const auto &map_entry : roarings) {
  714. if (map_entry.second.isEmpty()) {
  715. continue;
  716. }
  717. auto roaring_iter = r.roarings.find(map_entry.first);
  718. if (roaring_iter == r.roarings.cend())
  719. return false;
  720. else if (!map_entry.second.isSubset(roaring_iter->second))
  721. return false;
  722. }
  723. return true;
  724. }
  725. /**
  726. * Returns true if the bitmap is strict subset of the other.
  727. * Throws std::length_error in the special case where the bitmap is full
  728. * (cardinality() == 2^64). Check isFull() before calling to avoid
  729. * exception.
  730. */
  731. bool isStrictSubset(const Roaring64Map &r) const {
  732. return isSubset(r) && cardinality() != r.cardinality();
  733. }
  734. /**
  735. * Convert the bitmap to an array. Write the output to "ans",
  736. * caller is responsible to ensure that there is enough memory
  737. * allocated
  738. * (e.g., ans = new uint32[mybitmap.cardinality()];)
  739. */
  740. void toUint64Array(uint64_t *ans) const {
  741. // Annoyingly, VS 2017 marks std::accumulate() as [[nodiscard]]
  742. (void)std::accumulate(
  743. roarings.cbegin(), roarings.cend(), ans,
  744. [](uint64_t *previous,
  745. const std::pair<const uint32_t, Roaring> &map_entry) {
  746. for (uint32_t low_bits : map_entry.second)
  747. *previous++ = uniteBytes(map_entry.first, low_bits);
  748. return previous;
  749. });
  750. }
  751. /**
  752. * Return true if the two bitmaps contain the same elements.
  753. */
  754. bool operator==(const Roaring64Map &r) const {
  755. // we cannot use operator == on the map because either side may contain
  756. // empty Roaring Bitmaps
  757. auto lhs_iter = roarings.cbegin();
  758. auto lhs_cend = roarings.cend();
  759. auto rhs_iter = r.roarings.cbegin();
  760. auto rhs_cend = r.roarings.cend();
  761. while (lhs_iter != lhs_cend && rhs_iter != rhs_cend) {
  762. auto lhs_key = lhs_iter->first, rhs_key = rhs_iter->first;
  763. const auto &lhs_map = lhs_iter->second, &rhs_map = rhs_iter->second;
  764. if (lhs_map.isEmpty()) {
  765. ++lhs_iter;
  766. continue;
  767. }
  768. if (rhs_map.isEmpty()) {
  769. ++rhs_iter;
  770. continue;
  771. }
  772. if (!(lhs_key == rhs_key)) {
  773. return false;
  774. }
  775. if (!(lhs_map == rhs_map)) {
  776. return false;
  777. }
  778. ++lhs_iter;
  779. ++rhs_iter;
  780. }
  781. while (lhs_iter != lhs_cend) {
  782. if (!lhs_iter->second.isEmpty()) {
  783. return false;
  784. }
  785. ++lhs_iter;
  786. }
  787. while (rhs_iter != rhs_cend) {
  788. if (!rhs_iter->second.isEmpty()) {
  789. return false;
  790. }
  791. ++rhs_iter;
  792. }
  793. return true;
  794. }
  795. /**
  796. * Computes the negation of the roaring bitmap within the half-open interval
  797. * [min, max). Areas outside the interval are unchanged.
  798. */
  799. void flip(uint64_t min, uint64_t max) {
  800. if (min >= max) {
  801. return;
  802. }
  803. flipClosed(min, max - 1);
  804. }
  805. /**
  806. * Computes the negation of the roaring bitmap within the closed interval
  807. * [min, max]. Areas outside the interval are unchanged.
  808. */
  809. void flipClosed(uint32_t min, uint32_t max) {
  810. auto iter = roarings.begin();
  811. // Since min and max are uint32_t, highbytes(min or max) == 0. The inner
  812. // bitmap we are looking for, if it exists, will be at the first slot of
  813. // 'roarings'. If it does not exist, we have to create it.
  814. if (iter == roarings.end() || iter->first != 0) {
  815. iter = roarings.emplace_hint(iter, std::piecewise_construct,
  816. std::forward_as_tuple(0),
  817. std::forward_as_tuple());
  818. auto &bitmap = iter->second;
  819. bitmap.setCopyOnWrite(copyOnWrite);
  820. }
  821. auto &bitmap = iter->second;
  822. bitmap.flipClosed(min, max);
  823. eraseIfEmpty(iter);
  824. }
  825. /**
  826. * Computes the negation of the roaring bitmap within the closed interval
  827. * [min, max]. Areas outside the interval are unchanged.
  828. */
  829. void flipClosed(uint64_t min, uint64_t max) {
  830. if (min > max) {
  831. return;
  832. }
  833. uint32_t start_high = highBytes(min);
  834. uint32_t start_low = lowBytes(min);
  835. uint32_t end_high = highBytes(max);
  836. uint32_t end_low = lowBytes(max);
  837. // We put std::numeric_limits<>::max in parentheses to avoid a
  838. // clash with the Windows.h header under Windows.
  839. const uint32_t uint32_max = (std::numeric_limits<uint32_t>::max)();
  840. // Fill in any nonexistent slots with empty Roarings. This simplifies
  841. // the logic below, allowing it to simply iterate over the map between
  842. // 'start_high' and 'end_high' in a linear fashion.
  843. auto current_iter = ensureRangePopulated(start_high, end_high);
  844. // If start and end land on the same inner bitmap, then we can do the
  845. // whole operation in one call.
  846. if (start_high == end_high) {
  847. auto &bitmap = current_iter->second;
  848. bitmap.flipClosed(start_low, end_low);
  849. eraseIfEmpty(current_iter);
  850. return;
  851. }
  852. // Because start and end don't land on the same inner bitmap,
  853. // we need to do this in multiple steps:
  854. // 1. Partially flip the first bitmap in the closed interval
  855. // [start_low, uint32_max]
  856. // 2. Flip intermediate bitmaps completely: [0, uint32_max]
  857. // 3. Partially flip the last bitmap in the closed interval
  858. // [0, end_low]
  859. auto num_intermediate_bitmaps = end_high - start_high - 1;
  860. // 1. Partially flip the first bitmap.
  861. {
  862. auto &bitmap = current_iter->second;
  863. bitmap.flipClosed(start_low, uint32_max);
  864. auto temp = current_iter++;
  865. eraseIfEmpty(temp);
  866. }
  867. // 2. Flip intermediate bitmaps completely.
  868. for (uint32_t i = 0; i != num_intermediate_bitmaps; ++i) {
  869. auto &bitmap = current_iter->second;
  870. bitmap.flipClosed(0, uint32_max);
  871. auto temp = current_iter++;
  872. eraseIfEmpty(temp);
  873. }
  874. // 3. Partially flip the last bitmap.
  875. auto &bitmap = current_iter->second;
  876. bitmap.flipClosed(0, end_low);
  877. eraseIfEmpty(current_iter);
  878. }
  879. /**
  880. * Remove run-length encoding even when it is more space efficient
  881. * return whether a change was applied
  882. */
  883. bool removeRunCompression() {
  884. return std::accumulate(
  885. roarings.begin(), roarings.end(), true,
  886. [](bool previous, std::pair<const uint32_t, Roaring> &map_entry) {
  887. return map_entry.second.removeRunCompression() && previous;
  888. });
  889. }
  890. /**
  891. * Convert array and bitmap containers to run containers when it is more
  892. * efficient; also convert from run containers when more space efficient.
  893. * Returns true if the result has at least one run container.
  894. * Additional savings might be possible by calling shrinkToFit().
  895. */
  896. bool runOptimize() {
  897. return std::accumulate(
  898. roarings.begin(), roarings.end(), true,
  899. [](bool previous, std::pair<const uint32_t, Roaring> &map_entry) {
  900. return map_entry.second.runOptimize() && previous;
  901. });
  902. }
  903. /**
  904. * If needed, reallocate memory to shrink the memory usage.
  905. * Returns the number of bytes saved.
  906. */
  907. size_t shrinkToFit() {
  908. size_t savedBytes = 0;
  909. auto iter = roarings.begin();
  910. while (iter != roarings.cend()) {
  911. if (iter->second.isEmpty()) {
  912. // empty Roarings are 84 bytes
  913. savedBytes += 88;
  914. roarings.erase(iter++);
  915. } else {
  916. savedBytes += iter->second.shrinkToFit();
  917. iter++;
  918. }
  919. }
  920. return savedBytes;
  921. }
  922. /**
  923. * Iterate over the bitmap elements in order(start from the smallest one)
  924. * and call iterator once for every element until the iterator function
  925. * returns false. To iterate over all values, the iterator function should
  926. * always return true.
  927. *
  928. * The roaring_iterator64 parameter is a pointer to a function that
  929. * returns bool (true means that the iteration should continue while false
  930. * means that it should stop), and takes (uint64_t element, void* ptr) as
  931. * inputs.
  932. */
  933. void iterate(api::roaring_iterator64 iterator, void *ptr) const {
  934. for (const auto &map_entry : roarings) {
  935. bool should_continue =
  936. roaring_iterate64(&map_entry.second.roaring, iterator,
  937. uint64_t(map_entry.first) << 32, ptr);
  938. if (!should_continue) {
  939. break;
  940. }
  941. }
  942. }
  943. /**
  944. * Selects the value at index 'rank' in the bitmap, where the smallest value
  945. * is at index 0. If 'rank' < cardinality(), returns true with *element set
  946. * to the element of the specified rank. Otherwise, returns false and the
  947. * contents of *element are unspecified.
  948. */
  949. bool select(uint64_t rank, uint64_t *element) const {
  950. for (const auto &map_entry : roarings) {
  951. auto key = map_entry.first;
  952. const auto &bitmap = map_entry.second;
  953. uint64_t sub_cardinality = bitmap.cardinality();
  954. if (rank < sub_cardinality) {
  955. uint32_t low_bytes;
  956. // Casting rank to uint32_t is safe because
  957. // rank < sub_cardinality and sub_cardinality <= 2^32.
  958. if (!bitmap.select((uint32_t)rank, &low_bytes)) {
  959. ROARING_TERMINATE(
  960. "Logic error: bitmap.select() "
  961. "returned false despite rank < cardinality()");
  962. }
  963. *element = uniteBytes(key, low_bytes);
  964. return true;
  965. }
  966. rank -= sub_cardinality;
  967. }
  968. return false;
  969. }
  970. /**
  971. * Returns the number of integers that are smaller or equal to x.
  972. */
  973. uint64_t rank(uint64_t x) const {
  974. uint64_t result = 0;
  975. // Find the first bitmap >= x's bucket. If that is the bucket x would be
  976. // in, find it's rank in that bucket. Either way, we're left with a
  977. // range of all buckets strictly smaller than x's bucket, add all their
  978. // cardinalities together.
  979. auto end = roarings.lower_bound(highBytes(x));
  980. if (end != roarings.cend() && end->first == highBytes(x)) {
  981. result += end->second.rank(lowBytes(x));
  982. }
  983. for (auto iter = roarings.cbegin(); iter != end; ++iter) {
  984. result += iter->second.cardinality();
  985. }
  986. return result;
  987. }
  988. /**
  989. * Returns the index of x in the set, index start from 0.
  990. * If the set doesn't contain x , this function will return -1.
  991. * The difference with rank function is that this function will return -1
  992. * when x isn't in the set, but the rank function will return a
  993. * non-negative number.
  994. */
  995. int64_t getIndex(uint64_t x) const {
  996. int64_t index = 0;
  997. auto roaring_destination = roarings.find(highBytes(x));
  998. if (roaring_destination != roarings.cend()) {
  999. for (auto roaring_iter = roarings.cbegin();
  1000. roaring_iter != roaring_destination; ++roaring_iter) {
  1001. index += roaring_iter->second.cardinality();
  1002. }
  1003. auto low_idx = roaring_destination->second.getIndex(lowBytes(x));
  1004. if (low_idx < 0) return -1;
  1005. index += low_idx;
  1006. return index;
  1007. }
  1008. return -1;
  1009. }
  1010. /**
  1011. * Write a bitmap to a char buffer. This is meant to be compatible with
  1012. * the Java and Go versions. Returns how many bytes were written which
  1013. * should be getSizeInBytes().
  1014. *
  1015. * Setting the portable flag to false enables a custom format that
  1016. * can save space compared to the portable format (e.g., for very
  1017. * sparse bitmaps).
  1018. */
  1019. size_t write(char *buf, bool portable = true) const {
  1020. const char *orig = buf;
  1021. // push map size
  1022. uint64_t map_size = roarings.size();
  1023. std::memcpy(buf, &map_size, sizeof(uint64_t));
  1024. buf += sizeof(uint64_t);
  1025. std::for_each(roarings.cbegin(), roarings.cend(),
  1026. [&buf, portable](
  1027. const std::pair<const uint32_t, Roaring> &map_entry) {
  1028. // push map key
  1029. std::memcpy(buf, &map_entry.first, sizeof(uint32_t));
  1030. // ^-- Note: `*((uint32_t*)buf) = map_entry.first;` is
  1031. // undefined
  1032. buf += sizeof(uint32_t);
  1033. // push map value Roaring
  1034. buf += map_entry.second.write(buf, portable);
  1035. });
  1036. return buf - orig;
  1037. }
  1038. /**
  1039. * Read a bitmap from a serialized version. This is meant to be compatible
  1040. * with the Java and Go versions.
  1041. *
  1042. * Setting the portable flag to false enable a custom format that
  1043. * can save space compared to the portable format (e.g., for very
  1044. * sparse bitmaps).
  1045. *
  1046. * This function is unsafe in the sense that if you provide bad data, many
  1047. * bytes could be read, possibly causing a buffer overflow. See also
  1048. * readSafe.
  1049. */
  1050. static Roaring64Map read(const char *buf, bool portable = true) {
  1051. Roaring64Map result;
  1052. // get map size
  1053. uint64_t map_size;
  1054. std::memcpy(&map_size, buf, sizeof(uint64_t));
  1055. buf += sizeof(uint64_t);
  1056. for (uint64_t lcv = 0; lcv < map_size; lcv++) {
  1057. // get map key
  1058. uint32_t key;
  1059. std::memcpy(&key, buf, sizeof(uint32_t));
  1060. // ^-- Note: `uint32_t key = *((uint32_t*)buf);` is undefined
  1061. buf += sizeof(uint32_t);
  1062. // read map value Roaring
  1063. Roaring read_var = Roaring::read(buf, portable);
  1064. // forward buffer past the last Roaring Bitmap
  1065. buf += read_var.getSizeInBytes(portable);
  1066. result.emplaceOrInsert(key, std::move(read_var));
  1067. }
  1068. return result;
  1069. }
  1070. /**
  1071. * Read a bitmap from a serialized version, reading no more than maxbytes
  1072. * bytes. This is meant to be compatible with the Java and Go versions.
  1073. *
  1074. * Setting the portable flag to false enable a custom format that can save
  1075. * space compared to the portable format (e.g., for very sparse bitmaps).
  1076. */
  1077. static Roaring64Map readSafe(const char *buf, size_t maxbytes) {
  1078. if (maxbytes < sizeof(uint64_t)) {
  1079. ROARING_TERMINATE("ran out of bytes");
  1080. }
  1081. Roaring64Map result;
  1082. uint64_t map_size;
  1083. std::memcpy(&map_size, buf, sizeof(uint64_t));
  1084. buf += sizeof(uint64_t);
  1085. maxbytes -= sizeof(uint64_t);
  1086. for (uint64_t lcv = 0; lcv < map_size; lcv++) {
  1087. if (maxbytes < sizeof(uint32_t)) {
  1088. ROARING_TERMINATE("ran out of bytes");
  1089. }
  1090. uint32_t key;
  1091. std::memcpy(&key, buf, sizeof(uint32_t));
  1092. // ^-- Note: `uint32_t key = *((uint32_t*)buf);` is undefined
  1093. buf += sizeof(uint32_t);
  1094. maxbytes -= sizeof(uint32_t);
  1095. // read map value Roaring
  1096. Roaring read_var = Roaring::readSafe(buf, maxbytes);
  1097. // forward buffer past the last Roaring Bitmap
  1098. size_t tz = read_var.getSizeInBytes(true);
  1099. buf += tz;
  1100. maxbytes -= tz;
  1101. result.emplaceOrInsert(key, std::move(read_var));
  1102. }
  1103. return result;
  1104. }
  1105. /**
  1106. * Return the number of bytes required to serialize this bitmap (meant to
  1107. * be compatible with Java and Go versions)
  1108. *
  1109. * Setting the portable flag to false enable a custom format that can save
  1110. * space compared to the portable format (e.g., for very sparse bitmaps).
  1111. */
  1112. size_t getSizeInBytes(bool portable = true) const {
  1113. // start with, respectively, map size and size of keys for each map
  1114. // entry
  1115. return std::accumulate(
  1116. roarings.cbegin(), roarings.cend(),
  1117. sizeof(uint64_t) + roarings.size() * sizeof(uint32_t),
  1118. [=](size_t previous,
  1119. const std::pair<const uint32_t, Roaring> &map_entry) {
  1120. // add in bytes used by each Roaring
  1121. return previous + map_entry.second.getSizeInBytes(portable);
  1122. });
  1123. }
  1124. static const Roaring64Map frozenView(const char *buf) {
  1125. // size of bitmap buffer and key
  1126. const size_t metadata_size = sizeof(size_t) + sizeof(uint32_t);
  1127. Roaring64Map result;
  1128. // get map size
  1129. uint64_t map_size;
  1130. memcpy(&map_size, buf, sizeof(uint64_t));
  1131. buf += sizeof(uint64_t);
  1132. for (uint64_t lcv = 0; lcv < map_size; lcv++) {
  1133. // pad to 32 bytes minus the metadata size
  1134. while (((uintptr_t)buf + metadata_size) % 32 != 0) buf++;
  1135. // get bitmap size
  1136. size_t len;
  1137. memcpy(&len, buf, sizeof(size_t));
  1138. buf += sizeof(size_t);
  1139. // get map key
  1140. uint32_t key;
  1141. memcpy(&key, buf, sizeof(uint32_t));
  1142. buf += sizeof(uint32_t);
  1143. // read map value Roaring
  1144. const Roaring read = Roaring::frozenView(buf, len);
  1145. result.emplaceOrInsert(key, read);
  1146. // forward buffer past the last Roaring Bitmap
  1147. buf += len;
  1148. }
  1149. return result;
  1150. }
  1151. static const Roaring64Map portableDeserializeFrozen(const char *buf) {
  1152. Roaring64Map result;
  1153. // get map size
  1154. uint64_t map_size;
  1155. std::memcpy(&map_size, buf, sizeof(uint64_t));
  1156. buf += sizeof(uint64_t);
  1157. for (uint64_t lcv = 0; lcv < map_size; lcv++) {
  1158. // get map key
  1159. uint32_t key;
  1160. std::memcpy(&key, buf, sizeof(uint32_t));
  1161. buf += sizeof(uint32_t);
  1162. // read map value Roaring
  1163. Roaring read_var = Roaring::portableDeserializeFrozen(buf);
  1164. // forward buffer past the last Roaring bitmap
  1165. buf += read_var.getSizeInBytes(true);
  1166. result.emplaceOrInsert(key, std::move(read_var));
  1167. }
  1168. return result;
  1169. }
  1170. // As with serialized 64-bit bitmaps, 64-bit frozen bitmaps are serialized
  1171. // by concatenating one or more Roaring::write output buffers with the
  1172. // preceeding map key. Unlike standard bitmap serialization, frozen bitmaps
  1173. // must be 32-byte aligned and requires a buffer length to parse. As a
  1174. // result, each concatenated output of Roaring::writeFrozen is preceeded by
  1175. // padding, the buffer size (size_t), and the map key (uint32_t). The
  1176. // padding is used to ensure 32-byte alignment, but since it is followed by
  1177. // the buffer size and map key, it actually pads to `(x - sizeof(size_t) +
  1178. // sizeof(uint32_t)) mod 32` to leave room for the metadata.
  1179. void writeFrozen(char *buf) const {
  1180. // size of bitmap buffer and key
  1181. const size_t metadata_size = sizeof(size_t) + sizeof(uint32_t);
  1182. // push map size
  1183. uint64_t map_size = roarings.size();
  1184. memcpy(buf, &map_size, sizeof(uint64_t));
  1185. buf += sizeof(uint64_t);
  1186. for (auto &map_entry : roarings) {
  1187. size_t frozenSizeInBytes = map_entry.second.getFrozenSizeInBytes();
  1188. // pad to 32 bytes minus the metadata size
  1189. while (((uintptr_t)buf + metadata_size) % 32 != 0) buf++;
  1190. // push bitmap size
  1191. memcpy(buf, &frozenSizeInBytes, sizeof(size_t));
  1192. buf += sizeof(size_t);
  1193. // push map key
  1194. memcpy(buf, &map_entry.first, sizeof(uint32_t));
  1195. buf += sizeof(uint32_t);
  1196. // push map value Roaring
  1197. map_entry.second.writeFrozen(buf);
  1198. buf += map_entry.second.getFrozenSizeInBytes();
  1199. }
  1200. }
  1201. size_t getFrozenSizeInBytes() const {
  1202. // size of bitmap size and map key
  1203. const size_t metadata_size = sizeof(size_t) + sizeof(uint32_t);
  1204. size_t ret = 0;
  1205. // map size
  1206. ret += sizeof(uint64_t);
  1207. for (auto &map_entry : roarings) {
  1208. // pad to 32 bytes minus the metadata size
  1209. while ((ret + metadata_size) % 32 != 0) ret++;
  1210. ret += metadata_size;
  1211. // frozen bitmaps must be 32-byte aligned
  1212. ret += map_entry.second.getFrozenSizeInBytes();
  1213. }
  1214. return ret;
  1215. }
  1216. /**
  1217. * Computes the intersection between two bitmaps and returns new bitmap.
  1218. * The current bitmap and the provided bitmap are unchanged.
  1219. *
  1220. * Performance hint: if you are computing the intersection between several
  1221. * bitmaps, two-by-two, it is best to start with the smallest bitmap.
  1222. * Consider also using the operator &= to avoid needlessly creating
  1223. * many temporary bitmaps.
  1224. */
  1225. Roaring64Map operator&(const Roaring64Map &o) const {
  1226. return Roaring64Map(*this) &= o;
  1227. }
  1228. /**
  1229. * Computes the difference between two bitmaps and returns new bitmap.
  1230. * The current bitmap and the provided bitmap are unchanged.
  1231. */
  1232. Roaring64Map operator-(const Roaring64Map &o) const {
  1233. return Roaring64Map(*this) -= o;
  1234. }
  1235. /**
  1236. * Computes the union between two bitmaps and returns new bitmap.
  1237. * The current bitmap and the provided bitmap are unchanged.
  1238. */
  1239. Roaring64Map operator|(const Roaring64Map &o) const {
  1240. return Roaring64Map(*this) |= o;
  1241. }
  1242. /**
  1243. * Computes the symmetric union between two bitmaps and returns new bitmap.
  1244. * The current bitmap and the provided bitmap are unchanged.
  1245. */
  1246. Roaring64Map operator^(const Roaring64Map &o) const {
  1247. return Roaring64Map(*this) ^= o;
  1248. }
  1249. /**
  1250. * Whether or not we apply copy and write.
  1251. */
  1252. void setCopyOnWrite(bool val) {
  1253. if (copyOnWrite == val) return;
  1254. copyOnWrite = val;
  1255. std::for_each(roarings.begin(), roarings.end(),
  1256. [=](std::pair<const uint32_t, Roaring> &map_entry) {
  1257. map_entry.second.setCopyOnWrite(val);
  1258. });
  1259. }
  1260. /**
  1261. * Print the contents of the bitmap to stdout.
  1262. * Note: this method adds a final newline, but toString() does not.
  1263. */
  1264. void printf() const {
  1265. auto sink = [](const std::string &s) { fputs(s.c_str(), stdout); };
  1266. printToSink(sink);
  1267. sink("\n");
  1268. }
  1269. /**
  1270. * Print the contents of the bitmap into a string.
  1271. */
  1272. std::string toString() const {
  1273. std::string result;
  1274. auto sink = [&result](const std::string &s) { result += s; };
  1275. printToSink(sink);
  1276. return result;
  1277. }
  1278. /**
  1279. * Whether or not copy and write is active.
  1280. */
  1281. bool getCopyOnWrite() const { return copyOnWrite; }
  1282. /**
  1283. * Computes the logical or (union) between "n" bitmaps (referenced by a
  1284. * pointer).
  1285. */
  1286. static Roaring64Map fastunion(size_t n, const Roaring64Map **inputs) {
  1287. // The strategy here is to basically do a "group by" operation.
  1288. // We group the input roarings by key, do a 32-bit
  1289. // roaring_bitmap_or_many on each group, and collect the results.
  1290. // We accomplish the "group by" operation using a priority queue, which
  1291. // tracks the next key for each of our input maps. At each step, our
  1292. // algorithm takes the next subset of maps that share the same next key,
  1293. // runs roaring_bitmap_or_many on those bitmaps, and then advances the
  1294. // current_iter on all the affected entries and then repeats.
  1295. // There is an entry in our priority queue for each of the 'n' inputs.
  1296. // For a given Roaring64Map, we look at its underlying 'roarings'
  1297. // std::map, and take its begin() and end(). This forms our half-open
  1298. // interval [current_iter, end_iter), which we keep in the priority
  1299. // queue as a pq_entry. These entries are updated (removed and then
  1300. // reinserted with the pq_entry.iterator field advanced by one step) as
  1301. // our algorithm progresses. But when a given interval becomes empty
  1302. // (i.e. pq_entry.iterator == pq_entry.end) it is not returned to the
  1303. // priority queue.
  1304. struct pq_entry {
  1305. roarings_t::const_iterator iterator;
  1306. roarings_t::const_iterator end;
  1307. };
  1308. // Custom comparator for the priority queue.
  1309. auto pq_comp = [](const pq_entry &lhs, const pq_entry &rhs) {
  1310. auto left_key = lhs.iterator->first;
  1311. auto right_key = rhs.iterator->first;
  1312. // We compare in the opposite direction than normal because priority
  1313. // queues normally order from largest to smallest, but we want
  1314. // smallest to largest.
  1315. return left_key > right_key;
  1316. };
  1317. // Create and populate the priority queue.
  1318. std::priority_queue<pq_entry, std::vector<pq_entry>, decltype(pq_comp)>
  1319. pq(pq_comp);
  1320. for (size_t i = 0; i < n; ++i) {
  1321. const auto &roarings = inputs[i]->roarings;
  1322. if (roarings.begin() != roarings.end()) {
  1323. pq.push({roarings.begin(), roarings.end()});
  1324. }
  1325. }
  1326. // A reusable vector that holds the pointers to the inner bitmaps that
  1327. // we pass to the underlying 32-bit fastunion operation.
  1328. std::vector<const roaring_bitmap_t *> group_bitmaps;
  1329. // Summary of the algorithm:
  1330. // 1. While the priority queue is not empty:
  1331. // A. Get its lowest key. Call this group_key
  1332. // B. While the lowest entry in the priority queue has a key equal to
  1333. // group_key:
  1334. // 1. Remove this entry (the pair {current_iter, end_iter}) from
  1335. // the priority queue.
  1336. // 2. Add the bitmap pointed to by current_iter to a list of
  1337. // 32-bit bitmaps to process.
  1338. // 3. Advance current_iter. Now it will point to a bitmap entry
  1339. // with some key greater than group_key (or it will point to
  1340. // end()).
  1341. // 4. If current_iter != end_iter, reinsert the pair into the
  1342. // priority queue.
  1343. // C. Invoke the 32-bit roaring_bitmap_or_many() and add to result
  1344. Roaring64Map result;
  1345. while (!pq.empty()) {
  1346. // Find the next key (the lowest key) in the priority queue.
  1347. auto group_key = pq.top().iterator->first;
  1348. // The purpose of the inner loop is to gather all the inner bitmaps
  1349. // that share "group_key" into "group_bitmaps" so that they can be
  1350. // fed to roaring_bitmap_or_many(). While we are doing this, we
  1351. // advance those iterators to their next value and reinsert them
  1352. // into the priority queue (unless they reach their end).
  1353. group_bitmaps.clear();
  1354. while (!pq.empty()) {
  1355. auto candidate_current_iter = pq.top().iterator;
  1356. auto candidate_end_iter = pq.top().end;
  1357. auto candidate_key = candidate_current_iter->first;
  1358. const auto &candidate_bitmap = candidate_current_iter->second;
  1359. // This element will either be in the group (having
  1360. // key == group_key) or it will not be in the group (having
  1361. // key > group_key). (Note it cannot have key < group_key
  1362. // because of the ordered nature of the priority queue itself
  1363. // and the ordered nature of all the underlying roaring maps).
  1364. if (candidate_key != group_key) {
  1365. // This entry, and (thanks to the nature of the priority
  1366. // queue) all other entries as well, are all greater than
  1367. // group_key, so we're done collecting elements for the
  1368. // current group. Because of the way this loop was written,
  1369. // the group will will always contain at least one element.
  1370. break;
  1371. }
  1372. group_bitmaps.push_back(&candidate_bitmap.roaring);
  1373. // Remove this entry from the priority queue. Note this
  1374. // invalidates pq.top() so make sure you don't have any dangling
  1375. // references to it.
  1376. pq.pop();
  1377. // Advance 'candidate_current_iter' and insert a new entry
  1378. // {candidate_current_iter, candidate_end_iter} into the
  1379. // priority queue (unless it has reached its end).
  1380. ++candidate_current_iter;
  1381. if (candidate_current_iter != candidate_end_iter) {
  1382. pq.push({candidate_current_iter, candidate_end_iter});
  1383. }
  1384. }
  1385. // Use the fast inner union to combine these.
  1386. auto *inner_result = roaring_bitmap_or_many(group_bitmaps.size(),
  1387. group_bitmaps.data());
  1388. // Insert the 32-bit result at end of the 'roarings' map of the
  1389. // result we are building.
  1390. result.roarings.insert(
  1391. result.roarings.end(),
  1392. std::make_pair(group_key, Roaring(inner_result)));
  1393. }
  1394. return result;
  1395. }
  1396. friend class Roaring64MapSetBitBiDirectionalIterator;
  1397. typedef Roaring64MapSetBitBiDirectionalIterator const_iterator;
  1398. typedef Roaring64MapSetBitBiDirectionalIterator
  1399. const_bidirectional_iterator;
  1400. /**
  1401. * Returns an iterator that can be used to access the position of the set
  1402. * bits. The running time complexity of a full scan is proportional to the
  1403. * number of set bits: be aware that if you have long strings of 1s, this
  1404. * can be very inefficient.
  1405. *
  1406. * It can be much faster to use the toArray method if you want to
  1407. * retrieve the set bits.
  1408. */
  1409. const_iterator begin() const;
  1410. /**
  1411. * A bogus iterator that can be used together with begin()
  1412. * for constructions such as: for (auto i = b.begin(); * i!=b.end(); ++i) {}
  1413. */
  1414. const_iterator end() const;
  1415. private:
  1416. typedef std::map<uint32_t, Roaring> roarings_t;
  1417. roarings_t roarings{}; // The empty constructor silences warnings from
  1418. // pedantic static analyzers.
  1419. bool copyOnWrite{false};
  1420. static constexpr uint32_t highBytes(const uint64_t in) {
  1421. return uint32_t(in >> 32);
  1422. }
  1423. static constexpr uint32_t lowBytes(const uint64_t in) {
  1424. return uint32_t(in);
  1425. }
  1426. static constexpr uint64_t uniteBytes(const uint32_t highBytes,
  1427. const uint32_t lowBytes) {
  1428. return (uint64_t(highBytes) << 32) | uint64_t(lowBytes);
  1429. }
  1430. // this is needed to tolerate gcc's C++11 libstdc++ lacking emplace
  1431. // prior to version 4.8
  1432. void emplaceOrInsert(const uint32_t key, const Roaring &value) {
  1433. #if defined(__GLIBCXX__) && __GLIBCXX__ < 20130322
  1434. roarings.insert(std::make_pair(key, value));
  1435. #else
  1436. roarings.emplace(std::make_pair(key, value));
  1437. #endif
  1438. }
  1439. void emplaceOrInsert(const uint32_t key, Roaring &&value) {
  1440. #if defined(__GLIBCXX__) && __GLIBCXX__ < 20130322
  1441. roarings.insert(std::make_pair(key, std::move(value)));
  1442. #else
  1443. roarings.emplace(key, std::move(value));
  1444. #endif
  1445. }
  1446. /*
  1447. * Look up 'key' in the 'roarings' map. If it does not exist, create it.
  1448. * Also, set its copyOnWrite flag to 'copyOnWrite'. Then return a reference
  1449. * to the (already existing or newly created) inner bitmap.
  1450. */
  1451. Roaring &lookupOrCreateInner(uint32_t key) {
  1452. auto &bitmap = roarings[key];
  1453. bitmap.setCopyOnWrite(copyOnWrite);
  1454. return bitmap;
  1455. }
  1456. /**
  1457. * Prints the contents of the bitmap to a caller-provided sink function.
  1458. */
  1459. void printToSink(
  1460. const std::function<void(const std::string &)> &sink) const {
  1461. sink("{");
  1462. // Storage for snprintf. Big enough to store the decimal representation
  1463. // of the largest uint64_t value and trailing \0.
  1464. char buffer[32];
  1465. const char *separator = "";
  1466. // Reusable, and therefore avoids many repeated heap allocations.
  1467. std::string callback_string;
  1468. for (const auto &entry : roarings) {
  1469. auto high_bits = entry.first;
  1470. const auto &bitmap = entry.second;
  1471. for (const auto low_bits : bitmap) {
  1472. auto value = uniteBytes(high_bits, low_bits);
  1473. snprintf(buffer, sizeof(buffer), "%" PRIu64, value);
  1474. callback_string = separator;
  1475. callback_string.append(buffer);
  1476. sink(callback_string);
  1477. separator = ",";
  1478. }
  1479. }
  1480. sink("}");
  1481. }
  1482. /**
  1483. * Ensures that every key in the closed interval [start_high, end_high]
  1484. * refers to a Roaring bitmap rather being an empty slot. Inserts empty
  1485. * Roaring bitmaps if necessary. The interval must be valid and non-empty.
  1486. * Returns an iterator to the bitmap at start_high.
  1487. */
  1488. roarings_t::iterator ensureRangePopulated(uint32_t start_high,
  1489. uint32_t end_high) {
  1490. if (start_high > end_high) {
  1491. ROARING_TERMINATE("Logic error: start_high > end_high");
  1492. }
  1493. // next_populated_iter points to the first entry in the outer map with
  1494. // key >= start_high, or end().
  1495. auto next_populated_iter = roarings.lower_bound(start_high);
  1496. // Use uint64_t to avoid an infinite loop when end_high == uint32_max.
  1497. roarings_t::iterator start_iter{}; // Definitely assigned in loop.
  1498. for (uint64_t slot = start_high; slot <= end_high; ++slot) {
  1499. roarings_t::iterator slot_iter;
  1500. if (next_populated_iter != roarings.end() &&
  1501. next_populated_iter->first == slot) {
  1502. // 'slot' index has caught up to next_populated_iter.
  1503. // Note it here and advance next_populated_iter.
  1504. slot_iter = next_populated_iter++;
  1505. } else {
  1506. // 'slot' index has not yet caught up to next_populated_iter.
  1507. // Make a fresh entry {key = 'slot', value = Roaring()}, insert
  1508. // it just prior to next_populated_iter, and set its copy
  1509. // on write flag. We take pains to use emplace_hint and
  1510. // piecewise_construct to minimize effort.
  1511. slot_iter = roarings.emplace_hint(
  1512. next_populated_iter, std::piecewise_construct,
  1513. std::forward_as_tuple(uint32_t(slot)),
  1514. std::forward_as_tuple());
  1515. auto &bitmap = slot_iter->second;
  1516. bitmap.setCopyOnWrite(copyOnWrite);
  1517. }
  1518. // Make a note of the iterator of the starting slot. It will be
  1519. // needed for the return value.
  1520. if (slot == start_high) {
  1521. start_iter = slot_iter;
  1522. }
  1523. }
  1524. return start_iter;
  1525. }
  1526. /**
  1527. * Erases the entry pointed to by 'iter' from the 'roarings' map. Warning:
  1528. * this invalidates 'iter'.
  1529. */
  1530. void eraseIfEmpty(roarings_t::iterator iter) {
  1531. const auto &bitmap = iter->second;
  1532. if (bitmap.isEmpty()) {
  1533. roarings.erase(iter);
  1534. }
  1535. }
  1536. };
  1537. /**
  1538. * Used to go through the set bits. Not optimally fast, but convenient.
  1539. *
  1540. * Recommend to explicitly construct this iterator.
  1541. */
  1542. class Roaring64MapSetBitBiDirectionalIterator {
  1543. public:
  1544. typedef std::bidirectional_iterator_tag iterator_category;
  1545. typedef uint64_t *pointer;
  1546. typedef uint64_t &reference;
  1547. typedef uint64_t value_type;
  1548. typedef int64_t difference_type;
  1549. typedef Roaring64MapSetBitBiDirectionalIterator type_of_iterator;
  1550. Roaring64MapSetBitBiDirectionalIterator(const Roaring64Map &parent,
  1551. bool exhausted = false)
  1552. : p(&parent.roarings) {
  1553. if (exhausted || parent.roarings.empty()) {
  1554. map_iter = p->cend();
  1555. } else {
  1556. map_iter = parent.roarings.cbegin();
  1557. roaring_iterator_init(&map_iter->second.roaring, &i);
  1558. while (!i.has_value) {
  1559. map_iter++;
  1560. if (map_iter == p->cend()) return;
  1561. roaring_iterator_init(&map_iter->second.roaring, &i);
  1562. }
  1563. }
  1564. }
  1565. /**
  1566. * Provides the location of the set bit.
  1567. */
  1568. value_type operator*() const {
  1569. return Roaring64Map::uniteBytes(map_iter->first, i.current_value);
  1570. }
  1571. bool operator<(const type_of_iterator &o) const {
  1572. if (map_iter == p->cend()) return false;
  1573. if (o.map_iter == o.p->cend()) return true;
  1574. return **this < *o;
  1575. }
  1576. bool operator<=(const type_of_iterator &o) const {
  1577. if (o.map_iter == o.p->cend()) return true;
  1578. if (map_iter == p->cend()) return false;
  1579. return **this <= *o;
  1580. }
  1581. bool operator>(const type_of_iterator &o) const {
  1582. if (o.map_iter == o.p->cend()) return false;
  1583. if (map_iter == p->cend()) return true;
  1584. return **this > *o;
  1585. }
  1586. bool operator>=(const type_of_iterator &o) const {
  1587. if (map_iter == p->cend()) return true;
  1588. if (o.map_iter == o.p->cend()) return false;
  1589. return **this >= *o;
  1590. }
  1591. type_of_iterator &operator++() { // ++i, must returned inc. value
  1592. if (i.has_value == true) roaring_uint32_iterator_advance(&i);
  1593. while (!i.has_value) {
  1594. ++map_iter;
  1595. if (map_iter == p->cend()) return *this;
  1596. roaring_iterator_init(&map_iter->second.roaring, &i);
  1597. }
  1598. return *this;
  1599. }
  1600. type_of_iterator operator++(int) { // i++, must return orig. value
  1601. Roaring64MapSetBitBiDirectionalIterator orig(*this);
  1602. roaring_uint32_iterator_advance(&i);
  1603. while (!i.has_value) {
  1604. ++map_iter;
  1605. if (map_iter == p->cend()) return orig;
  1606. roaring_iterator_init(&map_iter->second.roaring, &i);
  1607. }
  1608. return orig;
  1609. }
  1610. /**
  1611. * Move the iterator to the first value >= val.
  1612. * Return true if there is such a value.
  1613. */
  1614. bool move_equalorlarger(const value_type &x) {
  1615. map_iter = p->lower_bound(Roaring64Map::highBytes(x));
  1616. if (map_iter != p->cend()) {
  1617. roaring_iterator_init(&map_iter->second.roaring, &i);
  1618. if (map_iter->first == Roaring64Map::highBytes(x)) {
  1619. if (roaring_uint32_iterator_move_equalorlarger(
  1620. &i, Roaring64Map::lowBytes(x)))
  1621. return true;
  1622. ++map_iter;
  1623. if (map_iter == p->cend()) return false;
  1624. roaring_iterator_init(&map_iter->second.roaring, &i);
  1625. }
  1626. return true;
  1627. }
  1628. return false;
  1629. }
  1630. /** DEPRECATED, use `move_equalorlarger`. */
  1631. CROARING_DEPRECATED bool move(const value_type &x) {
  1632. return move_equalorlarger(x);
  1633. }
  1634. type_of_iterator &operator--() { // --i, must return dec.value
  1635. if (map_iter == p->cend()) {
  1636. --map_iter;
  1637. roaring_iterator_init_last(&map_iter->second.roaring, &i);
  1638. if (i.has_value) return *this;
  1639. }
  1640. roaring_uint32_iterator_previous(&i);
  1641. while (!i.has_value) {
  1642. if (map_iter == p->cbegin()) return *this;
  1643. map_iter--;
  1644. roaring_iterator_init_last(&map_iter->second.roaring, &i);
  1645. }
  1646. return *this;
  1647. }
  1648. type_of_iterator operator--(int) { // i--, must return orig. value
  1649. Roaring64MapSetBitBiDirectionalIterator orig(*this);
  1650. if (map_iter == p->cend()) {
  1651. --map_iter;
  1652. roaring_iterator_init_last(&map_iter->second.roaring, &i);
  1653. return orig;
  1654. }
  1655. roaring_uint32_iterator_previous(&i);
  1656. while (!i.has_value) {
  1657. if (map_iter == p->cbegin()) return orig;
  1658. map_iter--;
  1659. roaring_iterator_init_last(&map_iter->second.roaring, &i);
  1660. }
  1661. return orig;
  1662. }
  1663. bool operator==(const Roaring64MapSetBitBiDirectionalIterator &o) const {
  1664. if (map_iter == p->cend() && o.map_iter == o.p->cend()) return true;
  1665. if (o.map_iter == o.p->cend()) return false;
  1666. return **this == *o;
  1667. }
  1668. bool operator!=(const Roaring64MapSetBitBiDirectionalIterator &o) const {
  1669. if (map_iter == p->cend() && o.map_iter == o.p->cend()) return false;
  1670. if (o.map_iter == o.p->cend()) return true;
  1671. return **this != *o;
  1672. }
  1673. private:
  1674. const std::map<uint32_t, Roaring> *p{nullptr};
  1675. std::map<uint32_t, Roaring>::const_iterator
  1676. map_iter{}; // The empty constructor silences warnings from pedantic
  1677. // static analyzers.
  1678. api::roaring_uint32_iterator_t
  1679. i{}; // The empty constructor silences warnings from pedantic static
  1680. // analyzers.
  1681. };
  1682. inline Roaring64MapSetBitBiDirectionalIterator Roaring64Map::begin() const {
  1683. return Roaring64MapSetBitBiDirectionalIterator(*this);
  1684. }
  1685. inline Roaring64MapSetBitBiDirectionalIterator Roaring64Map::end() const {
  1686. return Roaring64MapSetBitBiDirectionalIterator(*this, true);
  1687. }
  1688. } // namespace roaring
  1689. #endif /* INCLUDE_ROARING_64_MAP_HH_ */