run.h 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  1. /*
  2. * run.h
  3. *
  4. */
  5. #ifndef INCLUDE_CONTAINERS_RUN_H_
  6. #define INCLUDE_CONTAINERS_RUN_H_
  7. #include <roaring/roaring_types.h> // roaring_iterator
  8. // Include other headers after roaring_types.h
  9. #include <assert.h>
  10. #include <stdbool.h>
  11. #include <stdint.h>
  12. #include <string.h>
  13. #include <roaring/array_util.h> // binarySearch()/memequals() for inlining
  14. #include <roaring/containers/container_defs.h> // container_t, perfparameters
  15. #include <roaring/portability.h>
  16. #ifdef __cplusplus
  17. extern "C" {
  18. namespace roaring {
  19. // Note: in pure C++ code, you should avoid putting `using` in header files
  20. using api::roaring_iterator;
  21. using api::roaring_iterator64;
  22. namespace internal {
  23. #endif
  24. /* struct rle16_s - run length pair
  25. *
  26. * @value: start position of the run
  27. * @length: length of the run is `length + 1`
  28. *
  29. * An RLE pair {v, l} would represent the integers between the interval
  30. * [v, v+l+1], e.g. {3, 2} = [3, 4, 5].
  31. */
  32. struct rle16_s {
  33. uint16_t value;
  34. uint16_t length;
  35. };
  36. typedef struct rle16_s rle16_t;
  37. #ifdef __cplusplus
  38. #define CROARING_MAKE_RLE16(val, len) \
  39. { (uint16_t)(val), (uint16_t)(len) } // no tagged structs until c++20
  40. #else
  41. #define CROARING_MAKE_RLE16(val, len) \
  42. (rle16_t) { .value = (uint16_t)(val), .length = (uint16_t)(len) }
  43. #endif
  44. /* struct run_container_s - run container bitmap
  45. *
  46. * @n_runs: number of rle_t pairs in `runs`.
  47. * @capacity: capacity in rle_t pairs `runs` can hold.
  48. * @runs: pairs of rle_t.
  49. */
  50. STRUCT_CONTAINER(run_container_s) {
  51. int32_t n_runs;
  52. int32_t capacity;
  53. rle16_t *runs;
  54. };
  55. typedef struct run_container_s run_container_t;
  56. #define CAST_run(c) CAST(run_container_t *, c) // safer downcast
  57. #define const_CAST_run(c) CAST(const run_container_t *, c)
  58. #define movable_CAST_run(c) movable_CAST(run_container_t **, c)
  59. /* Create a new run container. Return NULL in case of failure. */
  60. run_container_t *run_container_create(void);
  61. /* Create a new run container with given capacity. Return NULL in case of
  62. * failure. */
  63. run_container_t *run_container_create_given_capacity(int32_t size);
  64. /*
  65. * Shrink the capacity to the actual size, return the number of bytes saved.
  66. */
  67. int run_container_shrink_to_fit(run_container_t *src);
  68. /* Free memory owned by `run'. */
  69. void run_container_free(run_container_t *run);
  70. /* Duplicate container */
  71. run_container_t *run_container_clone(const run_container_t *src);
  72. /*
  73. * Effectively deletes the value at index index, repacking data.
  74. */
  75. static inline void recoverRoomAtIndex(run_container_t *run, uint16_t index) {
  76. memmove(run->runs + index, run->runs + (1 + index),
  77. (run->n_runs - index - 1) * sizeof(rle16_t));
  78. run->n_runs--;
  79. }
  80. /**
  81. * Good old binary search through rle data
  82. */
  83. inline int32_t interleavedBinarySearch(const rle16_t *array, int32_t lenarray,
  84. uint16_t ikey) {
  85. int32_t low = 0;
  86. int32_t high = lenarray - 1;
  87. while (low <= high) {
  88. int32_t middleIndex = (low + high) >> 1;
  89. uint16_t middleValue = array[middleIndex].value;
  90. if (middleValue < ikey) {
  91. low = middleIndex + 1;
  92. } else if (middleValue > ikey) {
  93. high = middleIndex - 1;
  94. } else {
  95. return middleIndex;
  96. }
  97. }
  98. return -(low + 1);
  99. }
  100. /*
  101. * Returns index of the run which contains $ikey
  102. */
  103. static inline int32_t rle16_find_run(const rle16_t *array, int32_t lenarray,
  104. uint16_t ikey) {
  105. int32_t low = 0;
  106. int32_t high = lenarray - 1;
  107. while (low <= high) {
  108. int32_t middleIndex = (low + high) >> 1;
  109. uint16_t min = array[middleIndex].value;
  110. uint16_t max = array[middleIndex].value + array[middleIndex].length;
  111. if (ikey > max) {
  112. low = middleIndex + 1;
  113. } else if (ikey < min) {
  114. high = middleIndex - 1;
  115. } else {
  116. return middleIndex;
  117. }
  118. }
  119. return -(low + 1);
  120. }
  121. /**
  122. * Returns number of runs which can'be be merged with the key because they
  123. * are less than the key.
  124. * Note that [5,6,7,8] can be merged with the key 9 and won't be counted.
  125. */
  126. static inline int32_t rle16_count_less(const rle16_t *array, int32_t lenarray,
  127. uint16_t key) {
  128. if (lenarray == 0) return 0;
  129. int32_t low = 0;
  130. int32_t high = lenarray - 1;
  131. while (low <= high) {
  132. int32_t middleIndex = (low + high) >> 1;
  133. uint16_t min_value = array[middleIndex].value;
  134. uint16_t max_value =
  135. array[middleIndex].value + array[middleIndex].length;
  136. if (max_value + UINT32_C(1) < key) { // uint32 arithmetic
  137. low = middleIndex + 1;
  138. } else if (key < min_value) {
  139. high = middleIndex - 1;
  140. } else {
  141. return middleIndex;
  142. }
  143. }
  144. return low;
  145. }
  146. static inline int32_t rle16_count_greater(const rle16_t *array,
  147. int32_t lenarray, uint16_t key) {
  148. if (lenarray == 0) return 0;
  149. int32_t low = 0;
  150. int32_t high = lenarray - 1;
  151. while (low <= high) {
  152. int32_t middleIndex = (low + high) >> 1;
  153. uint16_t min_value = array[middleIndex].value;
  154. uint16_t max_value =
  155. array[middleIndex].value + array[middleIndex].length;
  156. if (max_value < key) {
  157. low = middleIndex + 1;
  158. } else if (key + UINT32_C(1) < min_value) { // uint32 arithmetic
  159. high = middleIndex - 1;
  160. } else {
  161. return lenarray - (middleIndex + 1);
  162. }
  163. }
  164. return lenarray - low;
  165. }
  166. /**
  167. * increase capacity to at least min. Whether the
  168. * existing data needs to be copied over depends on copy. If "copy" is false,
  169. * then the new content will be uninitialized, otherwise a copy is made.
  170. */
  171. void run_container_grow(run_container_t *run, int32_t min, bool copy);
  172. /**
  173. * Moves the data so that we can write data at index
  174. */
  175. static inline void makeRoomAtIndex(run_container_t *run, uint16_t index) {
  176. /* This function calls realloc + memmove sequentially to move by one index.
  177. * Potentially copying twice the array.
  178. */
  179. if (run->n_runs + 1 > run->capacity)
  180. run_container_grow(run, run->n_runs + 1, true);
  181. memmove(run->runs + 1 + index, run->runs + index,
  182. (run->n_runs - index) * sizeof(rle16_t));
  183. run->n_runs++;
  184. }
  185. /* Add `pos' to `run'. Returns true if `pos' was not present. */
  186. bool run_container_add(run_container_t *run, uint16_t pos);
  187. /* Remove `pos' from `run'. Returns true if `pos' was present. */
  188. static inline bool run_container_remove(run_container_t *run, uint16_t pos) {
  189. int32_t index = interleavedBinarySearch(run->runs, run->n_runs, pos);
  190. if (index >= 0) {
  191. int32_t le = run->runs[index].length;
  192. if (le == 0) {
  193. recoverRoomAtIndex(run, (uint16_t)index);
  194. } else {
  195. run->runs[index].value++;
  196. run->runs[index].length--;
  197. }
  198. return true;
  199. }
  200. index = -index - 2; // points to preceding value, possibly -1
  201. if (index >= 0) { // possible match
  202. int32_t offset = pos - run->runs[index].value;
  203. int32_t le = run->runs[index].length;
  204. if (offset < le) {
  205. // need to break in two
  206. run->runs[index].length = (uint16_t)(offset - 1);
  207. // need to insert
  208. uint16_t newvalue = pos + 1;
  209. int32_t newlength = le - offset - 1;
  210. makeRoomAtIndex(run, (uint16_t)(index + 1));
  211. run->runs[index + 1].value = newvalue;
  212. run->runs[index + 1].length = (uint16_t)newlength;
  213. return true;
  214. } else if (offset == le) {
  215. run->runs[index].length--;
  216. return true;
  217. }
  218. }
  219. // no match
  220. return false;
  221. }
  222. /* Check whether `pos' is present in `run'. */
  223. inline bool run_container_contains(const run_container_t *run, uint16_t pos) {
  224. int32_t index = interleavedBinarySearch(run->runs, run->n_runs, pos);
  225. if (index >= 0) return true;
  226. index = -index - 2; // points to preceding value, possibly -1
  227. if (index != -1) { // possible match
  228. int32_t offset = pos - run->runs[index].value;
  229. int32_t le = run->runs[index].length;
  230. if (offset <= le) return true;
  231. }
  232. return false;
  233. }
  234. /*
  235. * Check whether all positions in a range of positions from pos_start (included)
  236. * to pos_end (excluded) is present in `run'.
  237. */
  238. static inline bool run_container_contains_range(const run_container_t *run,
  239. uint32_t pos_start,
  240. uint32_t pos_end) {
  241. uint32_t count = 0;
  242. int32_t index =
  243. interleavedBinarySearch(run->runs, run->n_runs, (uint16_t)pos_start);
  244. if (index < 0) {
  245. index = -index - 2;
  246. if ((index == -1) ||
  247. ((pos_start - run->runs[index].value) > run->runs[index].length)) {
  248. return false;
  249. }
  250. }
  251. for (int32_t i = index; i < run->n_runs; ++i) {
  252. const uint32_t stop = run->runs[i].value + run->runs[i].length;
  253. if (run->runs[i].value >= pos_end) break;
  254. if (stop >= pos_end) {
  255. count += (((pos_end - run->runs[i].value) > 0)
  256. ? (pos_end - run->runs[i].value)
  257. : 0);
  258. break;
  259. }
  260. const uint32_t min = (stop - pos_start) > 0 ? (stop - pos_start) : 0;
  261. count += (min < run->runs[i].length) ? min : run->runs[i].length;
  262. }
  263. return count >= (pos_end - pos_start - 1);
  264. }
  265. /* Get the cardinality of `run'. Requires an actual computation. */
  266. int run_container_cardinality(const run_container_t *run);
  267. /* Card > 0?, see run_container_empty for the reverse */
  268. static inline bool run_container_nonzero_cardinality(
  269. const run_container_t *run) {
  270. return run->n_runs > 0; // runs never empty
  271. }
  272. /* Card == 0?, see run_container_nonzero_cardinality for the reverse */
  273. static inline bool run_container_empty(const run_container_t *run) {
  274. return run->n_runs == 0; // runs never empty
  275. }
  276. /* Copy one container into another. We assume that they are distinct. */
  277. void run_container_copy(const run_container_t *src, run_container_t *dst);
  278. /**
  279. * Append run described by vl to the run container, possibly merging.
  280. * It is assumed that the run would be inserted at the end of the container, no
  281. * check is made.
  282. * It is assumed that the run container has the necessary capacity: caller is
  283. * responsible for checking memory capacity.
  284. *
  285. *
  286. * This is not a safe function, it is meant for performance: use with care.
  287. */
  288. static inline void run_container_append(run_container_t *run, rle16_t vl,
  289. rle16_t *previousrl) {
  290. const uint32_t previousend = previousrl->value + previousrl->length;
  291. if (vl.value > previousend + 1) { // we add a new one
  292. run->runs[run->n_runs] = vl;
  293. run->n_runs++;
  294. *previousrl = vl;
  295. } else {
  296. uint32_t newend = vl.value + vl.length + UINT32_C(1);
  297. if (newend > previousend) { // we merge
  298. previousrl->length = (uint16_t)(newend - 1 - previousrl->value);
  299. run->runs[run->n_runs - 1] = *previousrl;
  300. }
  301. }
  302. }
  303. /**
  304. * Like run_container_append but it is assumed that the content of run is empty.
  305. */
  306. static inline rle16_t run_container_append_first(run_container_t *run,
  307. rle16_t vl) {
  308. run->runs[run->n_runs] = vl;
  309. run->n_runs++;
  310. return vl;
  311. }
  312. /**
  313. * append a single value given by val to the run container, possibly merging.
  314. * It is assumed that the value would be inserted at the end of the container,
  315. * no check is made.
  316. * It is assumed that the run container has the necessary capacity: caller is
  317. * responsible for checking memory capacity.
  318. *
  319. * This is not a safe function, it is meant for performance: use with care.
  320. */
  321. static inline void run_container_append_value(run_container_t *run,
  322. uint16_t val,
  323. rle16_t *previousrl) {
  324. const uint32_t previousend = previousrl->value + previousrl->length;
  325. if (val > previousend + 1) { // we add a new one
  326. *previousrl = CROARING_MAKE_RLE16(val, 0);
  327. run->runs[run->n_runs] = *previousrl;
  328. run->n_runs++;
  329. } else if (val == previousend + 1) { // we merge
  330. previousrl->length++;
  331. run->runs[run->n_runs - 1] = *previousrl;
  332. }
  333. }
  334. /**
  335. * Like run_container_append_value but it is assumed that the content of run is
  336. * empty.
  337. */
  338. static inline rle16_t run_container_append_value_first(run_container_t *run,
  339. uint16_t val) {
  340. rle16_t newrle = CROARING_MAKE_RLE16(val, 0);
  341. run->runs[run->n_runs] = newrle;
  342. run->n_runs++;
  343. return newrle;
  344. }
  345. /* Check whether the container spans the whole chunk (cardinality = 1<<16).
  346. * This check can be done in constant time (inexpensive). */
  347. static inline bool run_container_is_full(const run_container_t *run) {
  348. rle16_t vl = run->runs[0];
  349. return (run->n_runs == 1) && (vl.value == 0) && (vl.length == 0xFFFF);
  350. }
  351. /* Compute the union of `src_1' and `src_2' and write the result to `dst'
  352. * It is assumed that `dst' is distinct from both `src_1' and `src_2'. */
  353. void run_container_union(const run_container_t *src_1,
  354. const run_container_t *src_2, run_container_t *dst);
  355. /* Compute the union of `src_1' and `src_2' and write the result to `src_1' */
  356. void run_container_union_inplace(run_container_t *src_1,
  357. const run_container_t *src_2);
  358. /* Compute the intersection of src_1 and src_2 and write the result to
  359. * dst. It is assumed that dst is distinct from both src_1 and src_2. */
  360. void run_container_intersection(const run_container_t *src_1,
  361. const run_container_t *src_2,
  362. run_container_t *dst);
  363. /* Compute the size of the intersection of src_1 and src_2 . */
  364. int run_container_intersection_cardinality(const run_container_t *src_1,
  365. const run_container_t *src_2);
  366. /* Check whether src_1 and src_2 intersect. */
  367. bool run_container_intersect(const run_container_t *src_1,
  368. const run_container_t *src_2);
  369. /* Compute the symmetric difference of `src_1' and `src_2' and write the result
  370. * to `dst'
  371. * It is assumed that `dst' is distinct from both `src_1' and `src_2'. */
  372. void run_container_xor(const run_container_t *src_1,
  373. const run_container_t *src_2, run_container_t *dst);
  374. /*
  375. * Write out the 16-bit integers contained in this container as a list of 32-bit
  376. * integers using base
  377. * as the starting value (it might be expected that base has zeros in its 16
  378. * least significant bits).
  379. * The function returns the number of values written.
  380. * The caller is responsible for allocating enough memory in out.
  381. */
  382. int run_container_to_uint32_array(void *vout, const run_container_t *cont,
  383. uint32_t base);
  384. /*
  385. * Print this container using printf (useful for debugging).
  386. */
  387. void run_container_printf(const run_container_t *v);
  388. /*
  389. * Print this container using printf as a comma-separated list of 32-bit
  390. * integers starting at base.
  391. */
  392. void run_container_printf_as_uint32_array(const run_container_t *v,
  393. uint32_t base);
  394. bool run_container_validate(const run_container_t *run, const char **reason);
  395. /**
  396. * Return the serialized size in bytes of a container having "num_runs" runs.
  397. */
  398. static inline int32_t run_container_serialized_size_in_bytes(int32_t num_runs) {
  399. return sizeof(uint16_t) +
  400. sizeof(rle16_t) * num_runs; // each run requires 2 2-byte entries.
  401. }
  402. bool run_container_iterate(const run_container_t *cont, uint32_t base,
  403. roaring_iterator iterator, void *ptr);
  404. bool run_container_iterate64(const run_container_t *cont, uint32_t base,
  405. roaring_iterator64 iterator, uint64_t high_bits,
  406. void *ptr);
  407. /**
  408. * Writes the underlying array to buf, outputs how many bytes were written.
  409. * This is meant to be byte-by-byte compatible with the Java and Go versions of
  410. * Roaring.
  411. * The number of bytes written should be run_container_size_in_bytes(container).
  412. */
  413. int32_t run_container_write(const run_container_t *container, char *buf);
  414. /**
  415. * Reads the instance from buf, outputs how many bytes were read.
  416. * This is meant to be byte-by-byte compatible with the Java and Go versions of
  417. * Roaring.
  418. * The number of bytes read should be bitset_container_size_in_bytes(container).
  419. * The cardinality parameter is provided for consistency with other containers,
  420. * but
  421. * it might be effectively ignored..
  422. */
  423. int32_t run_container_read(int32_t cardinality, run_container_t *container,
  424. const char *buf);
  425. /**
  426. * Return the serialized size in bytes of a container (see run_container_write).
  427. * This is meant to be compatible with the Java and Go versions of Roaring.
  428. */
  429. ALLOW_UNALIGNED
  430. static inline int32_t run_container_size_in_bytes(
  431. const run_container_t *container) {
  432. return run_container_serialized_size_in_bytes(container->n_runs);
  433. }
  434. /**
  435. * Return true if the two containers have the same content.
  436. */
  437. ALLOW_UNALIGNED
  438. static inline bool run_container_equals(const run_container_t *container1,
  439. const run_container_t *container2) {
  440. if (container1->n_runs != container2->n_runs) {
  441. return false;
  442. }
  443. return memequals(container1->runs, container2->runs,
  444. container1->n_runs * sizeof(rle16_t));
  445. }
  446. /**
  447. * Return true if container1 is a subset of container2.
  448. */
  449. bool run_container_is_subset(const run_container_t *container1,
  450. const run_container_t *container2);
  451. /**
  452. * Used in a start-finish scan that appends segments, for XOR and NOT
  453. */
  454. void run_container_smart_append_exclusive(run_container_t *src,
  455. const uint16_t start,
  456. const uint16_t length);
  457. /**
  458. * The new container consists of a single run [start,stop).
  459. * It is required that stop>start, the caller is responsability for this check.
  460. * It is required that stop <= (1<<16), the caller is responsability for this
  461. * check. The cardinality of the created container is stop - start. Returns NULL
  462. * on failure
  463. */
  464. static inline run_container_t *run_container_create_range(uint32_t start,
  465. uint32_t stop) {
  466. run_container_t *rc = run_container_create_given_capacity(1);
  467. if (rc) {
  468. rle16_t r;
  469. r.value = (uint16_t)start;
  470. r.length = (uint16_t)(stop - start - 1);
  471. run_container_append_first(rc, r);
  472. }
  473. return rc;
  474. }
  475. /**
  476. * If the element of given rank is in this container, supposing that the first
  477. * element has rank start_rank, then the function returns true and sets element
  478. * accordingly.
  479. * Otherwise, it returns false and update start_rank.
  480. */
  481. bool run_container_select(const run_container_t *container,
  482. uint32_t *start_rank, uint32_t rank,
  483. uint32_t *element);
  484. /* Compute the difference of src_1 and src_2 and write the result to
  485. * dst. It is assumed that dst is distinct from both src_1 and src_2. */
  486. void run_container_andnot(const run_container_t *src_1,
  487. const run_container_t *src_2, run_container_t *dst);
  488. void run_container_offset(const run_container_t *c, container_t **loc,
  489. container_t **hic, uint16_t offset);
  490. /* Returns the smallest value (assumes not empty) */
  491. inline uint16_t run_container_minimum(const run_container_t *run) {
  492. if (run->n_runs == 0) return 0;
  493. return run->runs[0].value;
  494. }
  495. /* Returns the largest value (assumes not empty) */
  496. inline uint16_t run_container_maximum(const run_container_t *run) {
  497. if (run->n_runs == 0) return 0;
  498. return run->runs[run->n_runs - 1].value + run->runs[run->n_runs - 1].length;
  499. }
  500. /* Returns the number of values equal or smaller than x */
  501. int run_container_rank(const run_container_t *arr, uint16_t x);
  502. /* bulk version of run_container_rank(); return number of consumed elements */
  503. uint32_t run_container_rank_many(const run_container_t *arr,
  504. uint64_t start_rank, const uint32_t *begin,
  505. const uint32_t *end, uint64_t *ans);
  506. /* Returns the index of x, if not exsist return -1 */
  507. int run_container_get_index(const run_container_t *arr, uint16_t x);
  508. /* Returns the index of the first run containing a value at least as large as x,
  509. * or -1 */
  510. inline int run_container_index_equalorlarger(const run_container_t *arr,
  511. uint16_t x) {
  512. int32_t index = interleavedBinarySearch(arr->runs, arr->n_runs, x);
  513. if (index >= 0) return index;
  514. index = -index - 2; // points to preceding run, possibly -1
  515. if (index != -1) { // possible match
  516. int32_t offset = x - arr->runs[index].value;
  517. int32_t le = arr->runs[index].length;
  518. if (offset <= le) return index;
  519. }
  520. index += 1;
  521. if (index < arr->n_runs) {
  522. return index;
  523. }
  524. return -1;
  525. }
  526. /*
  527. * Add all values in range [min, max] using hint.
  528. */
  529. static inline void run_container_add_range_nruns(run_container_t *run,
  530. uint32_t min, uint32_t max,
  531. int32_t nruns_less,
  532. int32_t nruns_greater) {
  533. int32_t nruns_common = run->n_runs - nruns_less - nruns_greater;
  534. if (nruns_common == 0) {
  535. makeRoomAtIndex(run, (uint16_t)nruns_less);
  536. run->runs[nruns_less].value = (uint16_t)min;
  537. run->runs[nruns_less].length = (uint16_t)(max - min);
  538. } else {
  539. uint32_t common_min = run->runs[nruns_less].value;
  540. uint32_t common_max = run->runs[nruns_less + nruns_common - 1].value +
  541. run->runs[nruns_less + nruns_common - 1].length;
  542. uint32_t result_min = (common_min < min) ? common_min : min;
  543. uint32_t result_max = (common_max > max) ? common_max : max;
  544. run->runs[nruns_less].value = (uint16_t)result_min;
  545. run->runs[nruns_less].length = (uint16_t)(result_max - result_min);
  546. memmove(&(run->runs[nruns_less + 1]),
  547. &(run->runs[run->n_runs - nruns_greater]),
  548. nruns_greater * sizeof(rle16_t));
  549. run->n_runs = nruns_less + 1 + nruns_greater;
  550. }
  551. }
  552. /**
  553. * Add all values in range [min, max]. This function is currently unused
  554. * and left as documentation.
  555. */
  556. /*static inline void run_container_add_range(run_container_t* run,
  557. uint32_t min, uint32_t max) {
  558. int32_t nruns_greater = rle16_count_greater(run->runs, run->n_runs, max);
  559. int32_t nruns_less = rle16_count_less(run->runs, run->n_runs -
  560. nruns_greater, min); run_container_add_range_nruns(run, min, max, nruns_less,
  561. nruns_greater);
  562. }*/
  563. /**
  564. * Shifts last $count elements either left (distance < 0) or right (distance >
  565. * 0)
  566. */
  567. static inline void run_container_shift_tail(run_container_t *run, int32_t count,
  568. int32_t distance) {
  569. if (distance > 0) {
  570. if (run->capacity < count + distance) {
  571. run_container_grow(run, count + distance, true);
  572. }
  573. }
  574. int32_t srcpos = run->n_runs - count;
  575. int32_t dstpos = srcpos + distance;
  576. memmove(&(run->runs[dstpos]), &(run->runs[srcpos]),
  577. sizeof(rle16_t) * count);
  578. run->n_runs += distance;
  579. }
  580. /**
  581. * Remove all elements in range [min, max]
  582. */
  583. static inline void run_container_remove_range(run_container_t *run,
  584. uint32_t min, uint32_t max) {
  585. int32_t first = rle16_find_run(run->runs, run->n_runs, (uint16_t)min);
  586. int32_t last = rle16_find_run(run->runs, run->n_runs, (uint16_t)max);
  587. if (first >= 0 && min > run->runs[first].value &&
  588. max < ((uint32_t)run->runs[first].value +
  589. (uint32_t)run->runs[first].length)) {
  590. // split this run into two adjacent runs
  591. // right subinterval
  592. makeRoomAtIndex(run, (uint16_t)(first + 1));
  593. run->runs[first + 1].value = (uint16_t)(max + 1);
  594. run->runs[first + 1].length =
  595. (uint16_t)((run->runs[first].value + run->runs[first].length) -
  596. (max + 1));
  597. // left subinterval
  598. run->runs[first].length =
  599. (uint16_t)((min - 1) - run->runs[first].value);
  600. return;
  601. }
  602. // update left-most partial run
  603. if (first >= 0) {
  604. if (min > run->runs[first].value) {
  605. run->runs[first].length =
  606. (uint16_t)((min - 1) - run->runs[first].value);
  607. first++;
  608. }
  609. } else {
  610. first = -first - 1;
  611. }
  612. // update right-most run
  613. if (last >= 0) {
  614. uint16_t run_max = run->runs[last].value + run->runs[last].length;
  615. if (run_max > max) {
  616. run->runs[last].value = (uint16_t)(max + 1);
  617. run->runs[last].length = (uint16_t)(run_max - (max + 1));
  618. last--;
  619. }
  620. } else {
  621. last = (-last - 1) - 1;
  622. }
  623. // remove intermediate runs
  624. if (first <= last) {
  625. run_container_shift_tail(run, run->n_runs - (last + 1),
  626. -(last - first + 1));
  627. }
  628. }
  629. #ifdef __cplusplus
  630. }
  631. }
  632. } // extern "C" { namespace roaring { namespace internal {
  633. #endif
  634. #endif /* INCLUDE_CONTAINERS_RUN_H_ */