containers.h 98 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486
  1. #ifndef CONTAINERS_CONTAINERS_H
  2. #define CONTAINERS_CONTAINERS_H
  3. #include <assert.h>
  4. #include <stdbool.h>
  5. #include <stdio.h>
  6. #include <roaring/bitset_util.h>
  7. #include <roaring/containers/array.h>
  8. #include <roaring/containers/bitset.h>
  9. #include <roaring/containers/convert.h>
  10. #include <roaring/containers/mixed_andnot.h>
  11. #include <roaring/containers/mixed_equal.h>
  12. #include <roaring/containers/mixed_intersection.h>
  13. #include <roaring/containers/mixed_negation.h>
  14. #include <roaring/containers/mixed_subset.h>
  15. #include <roaring/containers/mixed_union.h>
  16. #include <roaring/containers/mixed_xor.h>
  17. #include <roaring/containers/run.h>
  18. #ifdef __cplusplus
  19. extern "C" {
  20. namespace roaring {
  21. namespace internal {
  22. #endif
  23. // would enum be possible or better?
  24. /**
  25. * The switch case statements follow
  26. * BITSET_CONTAINER_TYPE -- ARRAY_CONTAINER_TYPE -- RUN_CONTAINER_TYPE
  27. * so it makes more sense to number them 1, 2, 3 (in the vague hope that the
  28. * compiler might exploit this ordering).
  29. */
  30. #define BITSET_CONTAINER_TYPE 1
  31. #define ARRAY_CONTAINER_TYPE 2
  32. #define RUN_CONTAINER_TYPE 3
  33. #define SHARED_CONTAINER_TYPE 4
  34. /**
  35. * Macros for pairing container type codes, suitable for switch statements.
  36. * Use PAIR_CONTAINER_TYPES() for the switch, CONTAINER_PAIR() for the cases:
  37. *
  38. * switch (PAIR_CONTAINER_TYPES(type1, type2)) {
  39. * case CONTAINER_PAIR(BITSET,ARRAY):
  40. * ...
  41. * }
  42. */
  43. #define PAIR_CONTAINER_TYPES(type1, type2) (4 * (type1) + (type2))
  44. #define CONTAINER_PAIR(name1, name2) \
  45. (4 * (name1##_CONTAINER_TYPE) + (name2##_CONTAINER_TYPE))
  46. /**
  47. * A shared container is a wrapper around a container
  48. * with reference counting.
  49. */
  50. STRUCT_CONTAINER(shared_container_s) {
  51. container_t *container;
  52. uint8_t typecode;
  53. croaring_refcount_t counter; // to be managed atomically
  54. };
  55. typedef struct shared_container_s shared_container_t;
  56. #define CAST_shared(c) CAST(shared_container_t *, c) // safer downcast
  57. #define const_CAST_shared(c) CAST(const shared_container_t *, c)
  58. #define movable_CAST_shared(c) movable_CAST(shared_container_t **, c)
  59. /*
  60. * With copy_on_write = true
  61. * Create a new shared container if the typecode is not SHARED_CONTAINER_TYPE,
  62. * otherwise, increase the count
  63. * If copy_on_write = false, then clone.
  64. * Return NULL in case of failure.
  65. **/
  66. container_t *get_copy_of_container(container_t *container, uint8_t *typecode,
  67. bool copy_on_write);
  68. /* Frees a shared container (actually decrement its counter and only frees when
  69. * the counter falls to zero). */
  70. void shared_container_free(shared_container_t *container);
  71. /* extract a copy from the shared container, freeing the shared container if
  72. there is just one instance left,
  73. clone instances when the counter is higher than one
  74. */
  75. container_t *shared_container_extract_copy(shared_container_t *container,
  76. uint8_t *typecode);
  77. /* access to container underneath */
  78. static inline const container_t *container_unwrap_shared(
  79. const container_t *candidate_shared_container, uint8_t *type) {
  80. if (*type == SHARED_CONTAINER_TYPE) {
  81. *type = const_CAST_shared(candidate_shared_container)->typecode;
  82. assert(*type != SHARED_CONTAINER_TYPE);
  83. return const_CAST_shared(candidate_shared_container)->container;
  84. } else {
  85. return candidate_shared_container;
  86. }
  87. }
  88. /* access to container underneath */
  89. static inline container_t *container_mutable_unwrap_shared(container_t *c,
  90. uint8_t *type) {
  91. if (*type == SHARED_CONTAINER_TYPE) { // the passed in container is shared
  92. *type = CAST_shared(c)->typecode;
  93. assert(*type != SHARED_CONTAINER_TYPE);
  94. return CAST_shared(c)->container; // return the enclosed container
  95. } else {
  96. return c; // wasn't shared, so return as-is
  97. }
  98. }
  99. /* access to container underneath and queries its type */
  100. static inline uint8_t get_container_type(const container_t *c, uint8_t type) {
  101. if (type == SHARED_CONTAINER_TYPE) {
  102. return const_CAST_shared(c)->typecode;
  103. } else {
  104. return type;
  105. }
  106. }
  107. /**
  108. * Copies a container, requires a typecode. This allocates new memory, caller
  109. * is responsible for deallocation. If the container is not shared, then it is
  110. * physically cloned. Sharable containers are not cloneable.
  111. */
  112. container_t *container_clone(const container_t *container, uint8_t typecode);
  113. /* access to container underneath, cloning it if needed */
  114. static inline container_t *get_writable_copy_if_shared(container_t *c,
  115. uint8_t *type) {
  116. if (*type == SHARED_CONTAINER_TYPE) { // shared, return enclosed container
  117. return shared_container_extract_copy(CAST_shared(c), type);
  118. } else {
  119. return c; // not shared, so return as-is
  120. }
  121. }
  122. /**
  123. * End of shared container code
  124. */
  125. static const char *container_names[] = {"bitset", "array", "run", "shared"};
  126. static const char *shared_container_names[] = {
  127. "bitset (shared)", "array (shared)", "run (shared)"};
  128. // no matter what the initial container was, convert it to a bitset
  129. // if a new container is produced, caller responsible for freeing the previous
  130. // one
  131. // container should not be a shared container
  132. static inline bitset_container_t *container_to_bitset(container_t *c,
  133. uint8_t typecode) {
  134. bitset_container_t *result = NULL;
  135. switch (typecode) {
  136. case BITSET_CONTAINER_TYPE:
  137. return CAST_bitset(c); // nothing to do
  138. case ARRAY_CONTAINER_TYPE:
  139. result = bitset_container_from_array(CAST_array(c));
  140. return result;
  141. case RUN_CONTAINER_TYPE:
  142. result = bitset_container_from_run(CAST_run(c));
  143. return result;
  144. case SHARED_CONTAINER_TYPE:
  145. assert(false);
  146. roaring_unreachable;
  147. }
  148. assert(false);
  149. roaring_unreachable;
  150. return 0; // unreached
  151. }
  152. /**
  153. * Get the container name from the typecode
  154. * (unused at time of writing)
  155. */
  156. /*static inline const char *get_container_name(uint8_t typecode) {
  157. switch (typecode) {
  158. case BITSET_CONTAINER_TYPE:
  159. return container_names[0];
  160. case ARRAY_CONTAINER_TYPE:
  161. return container_names[1];
  162. case RUN_CONTAINER_TYPE:
  163. return container_names[2];
  164. case SHARED_CONTAINER_TYPE:
  165. return container_names[3];
  166. default:
  167. assert(false);
  168. roaring_unreachable;
  169. return "unknown";
  170. }
  171. }*/
  172. static inline const char *get_full_container_name(const container_t *c,
  173. uint8_t typecode) {
  174. switch (typecode) {
  175. case BITSET_CONTAINER_TYPE:
  176. return container_names[0];
  177. case ARRAY_CONTAINER_TYPE:
  178. return container_names[1];
  179. case RUN_CONTAINER_TYPE:
  180. return container_names[2];
  181. case SHARED_CONTAINER_TYPE:
  182. switch (const_CAST_shared(c)->typecode) {
  183. case BITSET_CONTAINER_TYPE:
  184. return shared_container_names[0];
  185. case ARRAY_CONTAINER_TYPE:
  186. return shared_container_names[1];
  187. case RUN_CONTAINER_TYPE:
  188. return shared_container_names[2];
  189. default:
  190. assert(false);
  191. roaring_unreachable;
  192. return "unknown";
  193. }
  194. break;
  195. default:
  196. assert(false);
  197. roaring_unreachable;
  198. return "unknown";
  199. }
  200. roaring_unreachable;
  201. return NULL;
  202. }
  203. /**
  204. * Get the container cardinality (number of elements), requires a typecode
  205. */
  206. static inline int container_get_cardinality(const container_t *c,
  207. uint8_t typecode) {
  208. c = container_unwrap_shared(c, &typecode);
  209. switch (typecode) {
  210. case BITSET_CONTAINER_TYPE:
  211. return bitset_container_cardinality(const_CAST_bitset(c));
  212. case ARRAY_CONTAINER_TYPE:
  213. return array_container_cardinality(const_CAST_array(c));
  214. case RUN_CONTAINER_TYPE:
  215. return run_container_cardinality(const_CAST_run(c));
  216. }
  217. assert(false);
  218. roaring_unreachable;
  219. return 0; // unreached
  220. }
  221. // returns true if a container is known to be full. Note that a lazy bitset
  222. // container
  223. // might be full without us knowing
  224. static inline bool container_is_full(const container_t *c, uint8_t typecode) {
  225. c = container_unwrap_shared(c, &typecode);
  226. switch (typecode) {
  227. case BITSET_CONTAINER_TYPE:
  228. return bitset_container_cardinality(const_CAST_bitset(c)) ==
  229. (1 << 16);
  230. case ARRAY_CONTAINER_TYPE:
  231. return array_container_cardinality(const_CAST_array(c)) ==
  232. (1 << 16);
  233. case RUN_CONTAINER_TYPE:
  234. return run_container_is_full(const_CAST_run(c));
  235. }
  236. assert(false);
  237. roaring_unreachable;
  238. return 0; // unreached
  239. }
  240. static inline int container_shrink_to_fit(container_t *c, uint8_t type) {
  241. c = container_mutable_unwrap_shared(c, &type);
  242. switch (type) {
  243. case BITSET_CONTAINER_TYPE:
  244. return 0; // no shrinking possible
  245. case ARRAY_CONTAINER_TYPE:
  246. return array_container_shrink_to_fit(CAST_array(c));
  247. case RUN_CONTAINER_TYPE:
  248. return run_container_shrink_to_fit(CAST_run(c));
  249. }
  250. assert(false);
  251. roaring_unreachable;
  252. return 0; // unreached
  253. }
  254. /**
  255. * make a container with a run of ones
  256. */
  257. /* initially always use a run container, even if an array might be
  258. * marginally
  259. * smaller */
  260. static inline container_t *container_range_of_ones(uint32_t range_start,
  261. uint32_t range_end,
  262. uint8_t *result_type) {
  263. assert(range_end >= range_start);
  264. uint64_t cardinality = range_end - range_start + 1;
  265. if (cardinality <= 2) {
  266. *result_type = ARRAY_CONTAINER_TYPE;
  267. return array_container_create_range(range_start, range_end);
  268. } else {
  269. *result_type = RUN_CONTAINER_TYPE;
  270. return run_container_create_range(range_start, range_end);
  271. }
  272. }
  273. /* Create a container with all the values between in [min,max) at a
  274. distance k*step from min. */
  275. static inline container_t *container_from_range(uint8_t *type, uint32_t min,
  276. uint32_t max, uint16_t step) {
  277. if (step == 0) return NULL; // being paranoid
  278. if (step == 1) {
  279. return container_range_of_ones(min, max, type);
  280. // Note: the result is not always a run (need to check the cardinality)
  281. //*type = RUN_CONTAINER_TYPE;
  282. // return run_container_create_range(min, max);
  283. }
  284. int size = (max - min + step - 1) / step;
  285. if (size <= DEFAULT_MAX_SIZE) { // array container
  286. *type = ARRAY_CONTAINER_TYPE;
  287. array_container_t *array = array_container_create_given_capacity(size);
  288. array_container_add_from_range(array, min, max, step);
  289. assert(array->cardinality == size);
  290. return array;
  291. } else { // bitset container
  292. *type = BITSET_CONTAINER_TYPE;
  293. bitset_container_t *bitset = bitset_container_create();
  294. bitset_container_add_from_range(bitset, min, max, step);
  295. assert(bitset->cardinality == size);
  296. return bitset;
  297. }
  298. }
  299. /**
  300. * "repair" the container after lazy operations.
  301. */
  302. static inline container_t *container_repair_after_lazy(container_t *c,
  303. uint8_t *type) {
  304. c = get_writable_copy_if_shared(c, type); // !!! unnecessary cloning
  305. container_t *result = NULL;
  306. switch (*type) {
  307. case BITSET_CONTAINER_TYPE: {
  308. bitset_container_t *bc = CAST_bitset(c);
  309. bc->cardinality = bitset_container_compute_cardinality(bc);
  310. if (bc->cardinality <= DEFAULT_MAX_SIZE) {
  311. result = array_container_from_bitset(bc);
  312. bitset_container_free(bc);
  313. *type = ARRAY_CONTAINER_TYPE;
  314. return result;
  315. }
  316. return c;
  317. }
  318. case ARRAY_CONTAINER_TYPE:
  319. return c; // nothing to do
  320. case RUN_CONTAINER_TYPE:
  321. return convert_run_to_efficient_container_and_free(CAST_run(c),
  322. type);
  323. case SHARED_CONTAINER_TYPE:
  324. assert(false);
  325. }
  326. assert(false);
  327. roaring_unreachable;
  328. return 0; // unreached
  329. }
  330. /**
  331. * Writes the underlying array to buf, outputs how many bytes were written.
  332. * This is meant to be byte-by-byte compatible with the Java and Go versions of
  333. * Roaring.
  334. * The number of bytes written should be
  335. * container_write(container, buf).
  336. *
  337. */
  338. static inline int32_t container_write(const container_t *c, uint8_t typecode,
  339. char *buf) {
  340. c = container_unwrap_shared(c, &typecode);
  341. switch (typecode) {
  342. case BITSET_CONTAINER_TYPE:
  343. return bitset_container_write(const_CAST_bitset(c), buf);
  344. case ARRAY_CONTAINER_TYPE:
  345. return array_container_write(const_CAST_array(c), buf);
  346. case RUN_CONTAINER_TYPE:
  347. return run_container_write(const_CAST_run(c), buf);
  348. }
  349. assert(false);
  350. roaring_unreachable;
  351. return 0; // unreached
  352. }
  353. /**
  354. * Get the container size in bytes under portable serialization (see
  355. * container_write), requires a
  356. * typecode
  357. */
  358. static inline int32_t container_size_in_bytes(const container_t *c,
  359. uint8_t typecode) {
  360. c = container_unwrap_shared(c, &typecode);
  361. switch (typecode) {
  362. case BITSET_CONTAINER_TYPE:
  363. return bitset_container_size_in_bytes(const_CAST_bitset(c));
  364. case ARRAY_CONTAINER_TYPE:
  365. return array_container_size_in_bytes(const_CAST_array(c));
  366. case RUN_CONTAINER_TYPE:
  367. return run_container_size_in_bytes(const_CAST_run(c));
  368. }
  369. assert(false);
  370. roaring_unreachable;
  371. return 0; // unreached
  372. }
  373. /**
  374. * print the container (useful for debugging), requires a typecode
  375. */
  376. void container_printf(const container_t *container, uint8_t typecode);
  377. /**
  378. * print the content of the container as a comma-separated list of 32-bit values
  379. * starting at base, requires a typecode
  380. */
  381. void container_printf_as_uint32_array(const container_t *container,
  382. uint8_t typecode, uint32_t base);
  383. bool container_internal_validate(const container_t *container, uint8_t typecode,
  384. const char **reason);
  385. /**
  386. * Checks whether a container is not empty, requires a typecode
  387. */
  388. static inline bool container_nonzero_cardinality(const container_t *c,
  389. uint8_t typecode) {
  390. c = container_unwrap_shared(c, &typecode);
  391. switch (typecode) {
  392. case BITSET_CONTAINER_TYPE:
  393. return bitset_container_const_nonzero_cardinality(
  394. const_CAST_bitset(c));
  395. case ARRAY_CONTAINER_TYPE:
  396. return array_container_nonzero_cardinality(const_CAST_array(c));
  397. case RUN_CONTAINER_TYPE:
  398. return run_container_nonzero_cardinality(const_CAST_run(c));
  399. }
  400. assert(false);
  401. roaring_unreachable;
  402. return 0; // unreached
  403. }
  404. /**
  405. * Recover memory from a container, requires a typecode
  406. */
  407. void container_free(container_t *container, uint8_t typecode);
  408. /**
  409. * Convert a container to an array of values, requires a typecode as well as a
  410. * "base" (most significant values)
  411. * Returns number of ints added.
  412. */
  413. static inline int container_to_uint32_array(uint32_t *output,
  414. const container_t *c,
  415. uint8_t typecode, uint32_t base) {
  416. c = container_unwrap_shared(c, &typecode);
  417. switch (typecode) {
  418. case BITSET_CONTAINER_TYPE:
  419. return bitset_container_to_uint32_array(output,
  420. const_CAST_bitset(c), base);
  421. case ARRAY_CONTAINER_TYPE:
  422. return array_container_to_uint32_array(output, const_CAST_array(c),
  423. base);
  424. case RUN_CONTAINER_TYPE:
  425. return run_container_to_uint32_array(output, const_CAST_run(c),
  426. base);
  427. }
  428. assert(false);
  429. roaring_unreachable;
  430. return 0; // unreached
  431. }
  432. /**
  433. * Add a value to a container, requires a typecode, fills in new_typecode and
  434. * return (possibly different) container.
  435. * This function may allocate a new container, and caller is responsible for
  436. * memory deallocation
  437. */
  438. static inline container_t *container_add(
  439. container_t *c, uint16_t val,
  440. uint8_t typecode, // !!! should be second argument?
  441. uint8_t *new_typecode) {
  442. c = get_writable_copy_if_shared(c, &typecode);
  443. switch (typecode) {
  444. case BITSET_CONTAINER_TYPE:
  445. bitset_container_set(CAST_bitset(c), val);
  446. *new_typecode = BITSET_CONTAINER_TYPE;
  447. return c;
  448. case ARRAY_CONTAINER_TYPE: {
  449. array_container_t *ac = CAST_array(c);
  450. if (array_container_try_add(ac, val, DEFAULT_MAX_SIZE) != -1) {
  451. *new_typecode = ARRAY_CONTAINER_TYPE;
  452. return ac;
  453. } else {
  454. bitset_container_t *bitset = bitset_container_from_array(ac);
  455. bitset_container_add(bitset, val);
  456. *new_typecode = BITSET_CONTAINER_TYPE;
  457. return bitset;
  458. }
  459. } break;
  460. case RUN_CONTAINER_TYPE:
  461. // per Java, no container type adjustments are done (revisit?)
  462. run_container_add(CAST_run(c), val);
  463. *new_typecode = RUN_CONTAINER_TYPE;
  464. return c;
  465. default:
  466. assert(false);
  467. roaring_unreachable;
  468. return NULL;
  469. }
  470. }
  471. /**
  472. * Remove a value from a container, requires a typecode, fills in new_typecode
  473. * and
  474. * return (possibly different) container.
  475. * This function may allocate a new container, and caller is responsible for
  476. * memory deallocation
  477. */
  478. static inline container_t *container_remove(
  479. container_t *c, uint16_t val,
  480. uint8_t typecode, // !!! should be second argument?
  481. uint8_t *new_typecode) {
  482. c = get_writable_copy_if_shared(c, &typecode);
  483. switch (typecode) {
  484. case BITSET_CONTAINER_TYPE:
  485. if (bitset_container_remove(CAST_bitset(c), val)) {
  486. int card = bitset_container_cardinality(CAST_bitset(c));
  487. if (card <= DEFAULT_MAX_SIZE) {
  488. *new_typecode = ARRAY_CONTAINER_TYPE;
  489. return array_container_from_bitset(CAST_bitset(c));
  490. }
  491. }
  492. *new_typecode = typecode;
  493. return c;
  494. case ARRAY_CONTAINER_TYPE:
  495. *new_typecode = typecode;
  496. array_container_remove(CAST_array(c), val);
  497. return c;
  498. case RUN_CONTAINER_TYPE:
  499. // per Java, no container type adjustments are done (revisit?)
  500. run_container_remove(CAST_run(c), val);
  501. *new_typecode = RUN_CONTAINER_TYPE;
  502. return c;
  503. default:
  504. assert(false);
  505. roaring_unreachable;
  506. return NULL;
  507. }
  508. }
  509. /**
  510. * Check whether a value is in a container, requires a typecode
  511. */
  512. static inline bool container_contains(
  513. const container_t *c, uint16_t val,
  514. uint8_t typecode // !!! should be second argument?
  515. ) {
  516. c = container_unwrap_shared(c, &typecode);
  517. switch (typecode) {
  518. case BITSET_CONTAINER_TYPE:
  519. return bitset_container_get(const_CAST_bitset(c), val);
  520. case ARRAY_CONTAINER_TYPE:
  521. return array_container_contains(const_CAST_array(c), val);
  522. case RUN_CONTAINER_TYPE:
  523. return run_container_contains(const_CAST_run(c), val);
  524. default:
  525. assert(false);
  526. roaring_unreachable;
  527. return false;
  528. }
  529. }
  530. /**
  531. * Check whether a range of values from range_start (included) to range_end
  532. * (excluded) is in a container, requires a typecode
  533. */
  534. static inline bool container_contains_range(
  535. const container_t *c, uint32_t range_start, uint32_t range_end,
  536. uint8_t typecode // !!! should be second argument?
  537. ) {
  538. c = container_unwrap_shared(c, &typecode);
  539. switch (typecode) {
  540. case BITSET_CONTAINER_TYPE:
  541. return bitset_container_get_range(const_CAST_bitset(c), range_start,
  542. range_end);
  543. case ARRAY_CONTAINER_TYPE:
  544. return array_container_contains_range(const_CAST_array(c),
  545. range_start, range_end);
  546. case RUN_CONTAINER_TYPE:
  547. return run_container_contains_range(const_CAST_run(c), range_start,
  548. range_end);
  549. default:
  550. assert(false);
  551. roaring_unreachable;
  552. return false;
  553. }
  554. }
  555. /**
  556. * Returns true if the two containers have the same content. Note that
  557. * two containers having different types can be "equal" in this sense.
  558. */
  559. static inline bool container_equals(const container_t *c1, uint8_t type1,
  560. const container_t *c2, uint8_t type2) {
  561. c1 = container_unwrap_shared(c1, &type1);
  562. c2 = container_unwrap_shared(c2, &type2);
  563. switch (PAIR_CONTAINER_TYPES(type1, type2)) {
  564. case CONTAINER_PAIR(BITSET, BITSET):
  565. return bitset_container_equals(const_CAST_bitset(c1),
  566. const_CAST_bitset(c2));
  567. case CONTAINER_PAIR(BITSET, RUN):
  568. return run_container_equals_bitset(const_CAST_run(c2),
  569. const_CAST_bitset(c1));
  570. case CONTAINER_PAIR(RUN, BITSET):
  571. return run_container_equals_bitset(const_CAST_run(c1),
  572. const_CAST_bitset(c2));
  573. case CONTAINER_PAIR(BITSET, ARRAY):
  574. // java would always return false?
  575. return array_container_equal_bitset(const_CAST_array(c2),
  576. const_CAST_bitset(c1));
  577. case CONTAINER_PAIR(ARRAY, BITSET):
  578. // java would always return false?
  579. return array_container_equal_bitset(const_CAST_array(c1),
  580. const_CAST_bitset(c2));
  581. case CONTAINER_PAIR(ARRAY, RUN):
  582. return run_container_equals_array(const_CAST_run(c2),
  583. const_CAST_array(c1));
  584. case CONTAINER_PAIR(RUN, ARRAY):
  585. return run_container_equals_array(const_CAST_run(c1),
  586. const_CAST_array(c2));
  587. case CONTAINER_PAIR(ARRAY, ARRAY):
  588. return array_container_equals(const_CAST_array(c1),
  589. const_CAST_array(c2));
  590. case CONTAINER_PAIR(RUN, RUN):
  591. return run_container_equals(const_CAST_run(c1), const_CAST_run(c2));
  592. default:
  593. assert(false);
  594. roaring_unreachable;
  595. return false;
  596. }
  597. }
  598. /**
  599. * Returns true if the container c1 is a subset of the container c2. Note that
  600. * c1 can be a subset of c2 even if they have a different type.
  601. */
  602. static inline bool container_is_subset(const container_t *c1, uint8_t type1,
  603. const container_t *c2, uint8_t type2) {
  604. c1 = container_unwrap_shared(c1, &type1);
  605. c2 = container_unwrap_shared(c2, &type2);
  606. switch (PAIR_CONTAINER_TYPES(type1, type2)) {
  607. case CONTAINER_PAIR(BITSET, BITSET):
  608. return bitset_container_is_subset(const_CAST_bitset(c1),
  609. const_CAST_bitset(c2));
  610. case CONTAINER_PAIR(BITSET, RUN):
  611. return bitset_container_is_subset_run(const_CAST_bitset(c1),
  612. const_CAST_run(c2));
  613. case CONTAINER_PAIR(RUN, BITSET):
  614. return run_container_is_subset_bitset(const_CAST_run(c1),
  615. const_CAST_bitset(c2));
  616. case CONTAINER_PAIR(BITSET, ARRAY):
  617. return false; // by construction, size(c1) > size(c2)
  618. case CONTAINER_PAIR(ARRAY, BITSET):
  619. return array_container_is_subset_bitset(const_CAST_array(c1),
  620. const_CAST_bitset(c2));
  621. case CONTAINER_PAIR(ARRAY, RUN):
  622. return array_container_is_subset_run(const_CAST_array(c1),
  623. const_CAST_run(c2));
  624. case CONTAINER_PAIR(RUN, ARRAY):
  625. return run_container_is_subset_array(const_CAST_run(c1),
  626. const_CAST_array(c2));
  627. case CONTAINER_PAIR(ARRAY, ARRAY):
  628. return array_container_is_subset(const_CAST_array(c1),
  629. const_CAST_array(c2));
  630. case CONTAINER_PAIR(RUN, RUN):
  631. return run_container_is_subset(const_CAST_run(c1),
  632. const_CAST_run(c2));
  633. default:
  634. assert(false);
  635. roaring_unreachable;
  636. return false;
  637. }
  638. }
  639. // macro-izations possibilities for generic non-inplace binary-op dispatch
  640. /**
  641. * Compute intersection between two containers, generate a new container (having
  642. * type result_type), requires a typecode. This allocates new memory, caller
  643. * is responsible for deallocation.
  644. */
  645. static inline container_t *container_and(const container_t *c1, uint8_t type1,
  646. const container_t *c2, uint8_t type2,
  647. uint8_t *result_type) {
  648. c1 = container_unwrap_shared(c1, &type1);
  649. c2 = container_unwrap_shared(c2, &type2);
  650. container_t *result = NULL;
  651. switch (PAIR_CONTAINER_TYPES(type1, type2)) {
  652. case CONTAINER_PAIR(BITSET, BITSET):
  653. *result_type =
  654. bitset_bitset_container_intersection(
  655. const_CAST_bitset(c1), const_CAST_bitset(c2), &result)
  656. ? BITSET_CONTAINER_TYPE
  657. : ARRAY_CONTAINER_TYPE;
  658. return result;
  659. case CONTAINER_PAIR(ARRAY, ARRAY):
  660. result = array_container_create();
  661. array_container_intersection(
  662. const_CAST_array(c1), const_CAST_array(c2), CAST_array(result));
  663. *result_type = ARRAY_CONTAINER_TYPE; // never bitset
  664. return result;
  665. case CONTAINER_PAIR(RUN, RUN):
  666. result = run_container_create();
  667. run_container_intersection(const_CAST_run(c1), const_CAST_run(c2),
  668. CAST_run(result));
  669. return convert_run_to_efficient_container_and_free(CAST_run(result),
  670. result_type);
  671. case CONTAINER_PAIR(BITSET, ARRAY):
  672. result = array_container_create();
  673. array_bitset_container_intersection(const_CAST_array(c2),
  674. const_CAST_bitset(c1),
  675. CAST_array(result));
  676. *result_type = ARRAY_CONTAINER_TYPE; // never bitset
  677. return result;
  678. case CONTAINER_PAIR(ARRAY, BITSET):
  679. result = array_container_create();
  680. *result_type = ARRAY_CONTAINER_TYPE; // never bitset
  681. array_bitset_container_intersection(const_CAST_array(c1),
  682. const_CAST_bitset(c2),
  683. CAST_array(result));
  684. return result;
  685. case CONTAINER_PAIR(BITSET, RUN):
  686. *result_type =
  687. run_bitset_container_intersection(
  688. const_CAST_run(c2), const_CAST_bitset(c1), &result)
  689. ? BITSET_CONTAINER_TYPE
  690. : ARRAY_CONTAINER_TYPE;
  691. return result;
  692. case CONTAINER_PAIR(RUN, BITSET):
  693. *result_type =
  694. run_bitset_container_intersection(
  695. const_CAST_run(c1), const_CAST_bitset(c2), &result)
  696. ? BITSET_CONTAINER_TYPE
  697. : ARRAY_CONTAINER_TYPE;
  698. return result;
  699. case CONTAINER_PAIR(ARRAY, RUN):
  700. result = array_container_create();
  701. *result_type = ARRAY_CONTAINER_TYPE; // never bitset
  702. array_run_container_intersection(
  703. const_CAST_array(c1), const_CAST_run(c2), CAST_array(result));
  704. return result;
  705. case CONTAINER_PAIR(RUN, ARRAY):
  706. result = array_container_create();
  707. *result_type = ARRAY_CONTAINER_TYPE; // never bitset
  708. array_run_container_intersection(
  709. const_CAST_array(c2), const_CAST_run(c1), CAST_array(result));
  710. return result;
  711. default:
  712. assert(false);
  713. roaring_unreachable;
  714. return NULL;
  715. }
  716. }
  717. /**
  718. * Compute the size of the intersection between two containers.
  719. */
  720. static inline int container_and_cardinality(const container_t *c1,
  721. uint8_t type1,
  722. const container_t *c2,
  723. uint8_t type2) {
  724. c1 = container_unwrap_shared(c1, &type1);
  725. c2 = container_unwrap_shared(c2, &type2);
  726. switch (PAIR_CONTAINER_TYPES(type1, type2)) {
  727. case CONTAINER_PAIR(BITSET, BITSET):
  728. return bitset_container_and_justcard(const_CAST_bitset(c1),
  729. const_CAST_bitset(c2));
  730. case CONTAINER_PAIR(ARRAY, ARRAY):
  731. return array_container_intersection_cardinality(
  732. const_CAST_array(c1), const_CAST_array(c2));
  733. case CONTAINER_PAIR(RUN, RUN):
  734. return run_container_intersection_cardinality(const_CAST_run(c1),
  735. const_CAST_run(c2));
  736. case CONTAINER_PAIR(BITSET, ARRAY):
  737. return array_bitset_container_intersection_cardinality(
  738. const_CAST_array(c2), const_CAST_bitset(c1));
  739. case CONTAINER_PAIR(ARRAY, BITSET):
  740. return array_bitset_container_intersection_cardinality(
  741. const_CAST_array(c1), const_CAST_bitset(c2));
  742. case CONTAINER_PAIR(BITSET, RUN):
  743. return run_bitset_container_intersection_cardinality(
  744. const_CAST_run(c2), const_CAST_bitset(c1));
  745. case CONTAINER_PAIR(RUN, BITSET):
  746. return run_bitset_container_intersection_cardinality(
  747. const_CAST_run(c1), const_CAST_bitset(c2));
  748. case CONTAINER_PAIR(ARRAY, RUN):
  749. return array_run_container_intersection_cardinality(
  750. const_CAST_array(c1), const_CAST_run(c2));
  751. case CONTAINER_PAIR(RUN, ARRAY):
  752. return array_run_container_intersection_cardinality(
  753. const_CAST_array(c2), const_CAST_run(c1));
  754. default:
  755. assert(false);
  756. roaring_unreachable;
  757. return 0;
  758. }
  759. }
  760. /**
  761. * Check whether two containers intersect.
  762. */
  763. static inline bool container_intersect(const container_t *c1, uint8_t type1,
  764. const container_t *c2, uint8_t type2) {
  765. c1 = container_unwrap_shared(c1, &type1);
  766. c2 = container_unwrap_shared(c2, &type2);
  767. switch (PAIR_CONTAINER_TYPES(type1, type2)) {
  768. case CONTAINER_PAIR(BITSET, BITSET):
  769. return bitset_container_intersect(const_CAST_bitset(c1),
  770. const_CAST_bitset(c2));
  771. case CONTAINER_PAIR(ARRAY, ARRAY):
  772. return array_container_intersect(const_CAST_array(c1),
  773. const_CAST_array(c2));
  774. case CONTAINER_PAIR(RUN, RUN):
  775. return run_container_intersect(const_CAST_run(c1),
  776. const_CAST_run(c2));
  777. case CONTAINER_PAIR(BITSET, ARRAY):
  778. return array_bitset_container_intersect(const_CAST_array(c2),
  779. const_CAST_bitset(c1));
  780. case CONTAINER_PAIR(ARRAY, BITSET):
  781. return array_bitset_container_intersect(const_CAST_array(c1),
  782. const_CAST_bitset(c2));
  783. case CONTAINER_PAIR(BITSET, RUN):
  784. return run_bitset_container_intersect(const_CAST_run(c2),
  785. const_CAST_bitset(c1));
  786. case CONTAINER_PAIR(RUN, BITSET):
  787. return run_bitset_container_intersect(const_CAST_run(c1),
  788. const_CAST_bitset(c2));
  789. case CONTAINER_PAIR(ARRAY, RUN):
  790. return array_run_container_intersect(const_CAST_array(c1),
  791. const_CAST_run(c2));
  792. case CONTAINER_PAIR(RUN, ARRAY):
  793. return array_run_container_intersect(const_CAST_array(c2),
  794. const_CAST_run(c1));
  795. default:
  796. assert(false);
  797. roaring_unreachable;
  798. return 0;
  799. }
  800. }
  801. /**
  802. * Compute intersection between two containers, with result in the first
  803. container if possible. If the returned pointer is identical to c1,
  804. then the container has been modified. If the returned pointer is different
  805. from c1, then a new container has been created and the caller is responsible
  806. for freeing it.
  807. The type of the first container may change. Returns the modified
  808. (and possibly new) container.
  809. */
  810. static inline container_t *container_iand(container_t *c1, uint8_t type1,
  811. const container_t *c2, uint8_t type2,
  812. uint8_t *result_type) {
  813. c1 = get_writable_copy_if_shared(c1, &type1);
  814. c2 = container_unwrap_shared(c2, &type2);
  815. container_t *result = NULL;
  816. switch (PAIR_CONTAINER_TYPES(type1, type2)) {
  817. case CONTAINER_PAIR(BITSET, BITSET):
  818. *result_type = bitset_bitset_container_intersection_inplace(
  819. CAST_bitset(c1), const_CAST_bitset(c2), &result)
  820. ? BITSET_CONTAINER_TYPE
  821. : ARRAY_CONTAINER_TYPE;
  822. return result;
  823. case CONTAINER_PAIR(ARRAY, ARRAY):
  824. array_container_intersection_inplace(CAST_array(c1),
  825. const_CAST_array(c2));
  826. *result_type = ARRAY_CONTAINER_TYPE;
  827. return c1;
  828. case CONTAINER_PAIR(RUN, RUN):
  829. result = run_container_create();
  830. run_container_intersection(const_CAST_run(c1), const_CAST_run(c2),
  831. CAST_run(result));
  832. // as of January 2016, Java code used non-in-place intersection for
  833. // two runcontainers
  834. return convert_run_to_efficient_container_and_free(CAST_run(result),
  835. result_type);
  836. case CONTAINER_PAIR(BITSET, ARRAY):
  837. // c1 is a bitmap so no inplace possible
  838. result = array_container_create();
  839. array_bitset_container_intersection(const_CAST_array(c2),
  840. const_CAST_bitset(c1),
  841. CAST_array(result));
  842. *result_type = ARRAY_CONTAINER_TYPE; // never bitset
  843. return result;
  844. case CONTAINER_PAIR(ARRAY, BITSET):
  845. *result_type = ARRAY_CONTAINER_TYPE; // never bitset
  846. array_bitset_container_intersection(
  847. const_CAST_array(c1), const_CAST_bitset(c2),
  848. CAST_array(c1)); // result is allowed to be same as c1
  849. return c1;
  850. case CONTAINER_PAIR(BITSET, RUN):
  851. // will attempt in-place computation
  852. *result_type = run_bitset_container_intersection(
  853. const_CAST_run(c2), const_CAST_bitset(c1), &c1)
  854. ? BITSET_CONTAINER_TYPE
  855. : ARRAY_CONTAINER_TYPE;
  856. return c1;
  857. case CONTAINER_PAIR(RUN, BITSET):
  858. *result_type =
  859. run_bitset_container_intersection(
  860. const_CAST_run(c1), const_CAST_bitset(c2), &result)
  861. ? BITSET_CONTAINER_TYPE
  862. : ARRAY_CONTAINER_TYPE;
  863. return result;
  864. case CONTAINER_PAIR(ARRAY, RUN):
  865. result = array_container_create();
  866. *result_type = ARRAY_CONTAINER_TYPE; // never bitset
  867. array_run_container_intersection(
  868. const_CAST_array(c1), const_CAST_run(c2), CAST_array(result));
  869. return result;
  870. case CONTAINER_PAIR(RUN, ARRAY):
  871. result = array_container_create();
  872. *result_type = ARRAY_CONTAINER_TYPE; // never bitset
  873. array_run_container_intersection(
  874. const_CAST_array(c2), const_CAST_run(c1), CAST_array(result));
  875. return result;
  876. default:
  877. assert(false);
  878. roaring_unreachable;
  879. return NULL;
  880. }
  881. }
  882. /**
  883. * Compute union between two containers, generate a new container (having type
  884. * result_type), requires a typecode. This allocates new memory, caller
  885. * is responsible for deallocation.
  886. */
  887. static inline container_t *container_or(const container_t *c1, uint8_t type1,
  888. const container_t *c2, uint8_t type2,
  889. uint8_t *result_type) {
  890. c1 = container_unwrap_shared(c1, &type1);
  891. c2 = container_unwrap_shared(c2, &type2);
  892. container_t *result = NULL;
  893. switch (PAIR_CONTAINER_TYPES(type1, type2)) {
  894. case CONTAINER_PAIR(BITSET, BITSET):
  895. result = bitset_container_create();
  896. bitset_container_or(const_CAST_bitset(c1), const_CAST_bitset(c2),
  897. CAST_bitset(result));
  898. *result_type = BITSET_CONTAINER_TYPE;
  899. return result;
  900. case CONTAINER_PAIR(ARRAY, ARRAY):
  901. *result_type =
  902. array_array_container_union(const_CAST_array(c1),
  903. const_CAST_array(c2), &result)
  904. ? BITSET_CONTAINER_TYPE
  905. : ARRAY_CONTAINER_TYPE;
  906. return result;
  907. case CONTAINER_PAIR(RUN, RUN):
  908. result = run_container_create();
  909. run_container_union(const_CAST_run(c1), const_CAST_run(c2),
  910. CAST_run(result));
  911. *result_type = RUN_CONTAINER_TYPE;
  912. // todo: could be optimized since will never convert to array
  913. result = convert_run_to_efficient_container_and_free(
  914. CAST_run(result), result_type);
  915. return result;
  916. case CONTAINER_PAIR(BITSET, ARRAY):
  917. result = bitset_container_create();
  918. array_bitset_container_union(const_CAST_array(c2),
  919. const_CAST_bitset(c1),
  920. CAST_bitset(result));
  921. *result_type = BITSET_CONTAINER_TYPE;
  922. return result;
  923. case CONTAINER_PAIR(ARRAY, BITSET):
  924. result = bitset_container_create();
  925. array_bitset_container_union(const_CAST_array(c1),
  926. const_CAST_bitset(c2),
  927. CAST_bitset(result));
  928. *result_type = BITSET_CONTAINER_TYPE;
  929. return result;
  930. case CONTAINER_PAIR(BITSET, RUN):
  931. if (run_container_is_full(const_CAST_run(c2))) {
  932. result = run_container_create();
  933. *result_type = RUN_CONTAINER_TYPE;
  934. run_container_copy(const_CAST_run(c2), CAST_run(result));
  935. return result;
  936. }
  937. result = bitset_container_create();
  938. run_bitset_container_union(
  939. const_CAST_run(c2), const_CAST_bitset(c1), CAST_bitset(result));
  940. *result_type = BITSET_CONTAINER_TYPE;
  941. return result;
  942. case CONTAINER_PAIR(RUN, BITSET):
  943. if (run_container_is_full(const_CAST_run(c1))) {
  944. result = run_container_create();
  945. *result_type = RUN_CONTAINER_TYPE;
  946. run_container_copy(const_CAST_run(c1), CAST_run(result));
  947. return result;
  948. }
  949. result = bitset_container_create();
  950. run_bitset_container_union(
  951. const_CAST_run(c1), const_CAST_bitset(c2), CAST_bitset(result));
  952. *result_type = BITSET_CONTAINER_TYPE;
  953. return result;
  954. case CONTAINER_PAIR(ARRAY, RUN):
  955. result = run_container_create();
  956. array_run_container_union(const_CAST_array(c1), const_CAST_run(c2),
  957. CAST_run(result));
  958. result = convert_run_to_efficient_container_and_free(
  959. CAST_run(result), result_type);
  960. return result;
  961. case CONTAINER_PAIR(RUN, ARRAY):
  962. result = run_container_create();
  963. array_run_container_union(const_CAST_array(c2), const_CAST_run(c1),
  964. CAST_run(result));
  965. result = convert_run_to_efficient_container_and_free(
  966. CAST_run(result), result_type);
  967. return result;
  968. default:
  969. assert(false);
  970. roaring_unreachable;
  971. return NULL; // unreached
  972. }
  973. }
  974. /**
  975. * Compute union between two containers, generate a new container (having type
  976. * result_type), requires a typecode. This allocates new memory, caller
  977. * is responsible for deallocation.
  978. *
  979. * This lazy version delays some operations such as the maintenance of the
  980. * cardinality. It requires repair later on the generated containers.
  981. */
  982. static inline container_t *container_lazy_or(const container_t *c1,
  983. uint8_t type1,
  984. const container_t *c2,
  985. uint8_t type2,
  986. uint8_t *result_type) {
  987. c1 = container_unwrap_shared(c1, &type1);
  988. c2 = container_unwrap_shared(c2, &type2);
  989. container_t *result = NULL;
  990. switch (PAIR_CONTAINER_TYPES(type1, type2)) {
  991. case CONTAINER_PAIR(BITSET, BITSET):
  992. result = bitset_container_create();
  993. bitset_container_or_nocard(const_CAST_bitset(c1),
  994. const_CAST_bitset(c2),
  995. CAST_bitset(result)); // is lazy
  996. *result_type = BITSET_CONTAINER_TYPE;
  997. return result;
  998. case CONTAINER_PAIR(ARRAY, ARRAY):
  999. *result_type =
  1000. array_array_container_lazy_union(const_CAST_array(c1),
  1001. const_CAST_array(c2), &result)
  1002. ? BITSET_CONTAINER_TYPE
  1003. : ARRAY_CONTAINER_TYPE;
  1004. return result;
  1005. case CONTAINER_PAIR(RUN, RUN):
  1006. result = run_container_create();
  1007. run_container_union(const_CAST_run(c1), const_CAST_run(c2),
  1008. CAST_run(result));
  1009. *result_type = RUN_CONTAINER_TYPE;
  1010. // we are being lazy
  1011. result = convert_run_to_efficient_container_and_free(
  1012. CAST_run(result), result_type);
  1013. return result;
  1014. case CONTAINER_PAIR(BITSET, ARRAY):
  1015. result = bitset_container_create();
  1016. array_bitset_container_lazy_union(const_CAST_array(c2),
  1017. const_CAST_bitset(c1),
  1018. CAST_bitset(result)); // is lazy
  1019. *result_type = BITSET_CONTAINER_TYPE;
  1020. return result;
  1021. case CONTAINER_PAIR(ARRAY, BITSET):
  1022. result = bitset_container_create();
  1023. array_bitset_container_lazy_union(const_CAST_array(c1),
  1024. const_CAST_bitset(c2),
  1025. CAST_bitset(result)); // is lazy
  1026. *result_type = BITSET_CONTAINER_TYPE;
  1027. return result;
  1028. case CONTAINER_PAIR(BITSET, RUN):
  1029. if (run_container_is_full(const_CAST_run(c2))) {
  1030. result = run_container_create();
  1031. *result_type = RUN_CONTAINER_TYPE;
  1032. run_container_copy(const_CAST_run(c2), CAST_run(result));
  1033. return result;
  1034. }
  1035. result = bitset_container_create();
  1036. run_bitset_container_lazy_union(const_CAST_run(c2),
  1037. const_CAST_bitset(c1),
  1038. CAST_bitset(result)); // is lazy
  1039. *result_type = BITSET_CONTAINER_TYPE;
  1040. return result;
  1041. case CONTAINER_PAIR(RUN, BITSET):
  1042. if (run_container_is_full(const_CAST_run(c1))) {
  1043. result = run_container_create();
  1044. *result_type = RUN_CONTAINER_TYPE;
  1045. run_container_copy(const_CAST_run(c1), CAST_run(result));
  1046. return result;
  1047. }
  1048. result = bitset_container_create();
  1049. run_bitset_container_lazy_union(const_CAST_run(c1),
  1050. const_CAST_bitset(c2),
  1051. CAST_bitset(result)); // is lazy
  1052. *result_type = BITSET_CONTAINER_TYPE;
  1053. return result;
  1054. case CONTAINER_PAIR(ARRAY, RUN):
  1055. result = run_container_create();
  1056. array_run_container_union(const_CAST_array(c1), const_CAST_run(c2),
  1057. CAST_run(result));
  1058. *result_type = RUN_CONTAINER_TYPE;
  1059. // next line skipped since we are lazy
  1060. // result = convert_run_to_efficient_container(result, result_type);
  1061. return result;
  1062. case CONTAINER_PAIR(RUN, ARRAY):
  1063. result = run_container_create();
  1064. array_run_container_union(const_CAST_array(c2), const_CAST_run(c1),
  1065. CAST_run(result)); // TODO make lazy
  1066. *result_type = RUN_CONTAINER_TYPE;
  1067. // next line skipped since we are lazy
  1068. // result = convert_run_to_efficient_container(result, result_type);
  1069. return result;
  1070. default:
  1071. assert(false);
  1072. roaring_unreachable;
  1073. return NULL; // unreached
  1074. }
  1075. }
  1076. /**
  1077. * Compute the union between two containers, with result in the first container.
  1078. * If the returned pointer is identical to c1, then the container has been
  1079. * modified.
  1080. * If the returned pointer is different from c1, then a new container has been
  1081. * created and the caller is responsible for freeing it.
  1082. * The type of the first container may change. Returns the modified
  1083. * (and possibly new) container
  1084. */
  1085. static inline container_t *container_ior(container_t *c1, uint8_t type1,
  1086. const container_t *c2, uint8_t type2,
  1087. uint8_t *result_type) {
  1088. c1 = get_writable_copy_if_shared(c1, &type1);
  1089. c2 = container_unwrap_shared(c2, &type2);
  1090. container_t *result = NULL;
  1091. switch (PAIR_CONTAINER_TYPES(type1, type2)) {
  1092. case CONTAINER_PAIR(BITSET, BITSET):
  1093. bitset_container_or(const_CAST_bitset(c1), const_CAST_bitset(c2),
  1094. CAST_bitset(c1));
  1095. #ifdef OR_BITSET_CONVERSION_TO_FULL
  1096. if (CAST_bitset(c1)->cardinality == (1 << 16)) { // we convert
  1097. result = run_container_create_range(0, (1 << 16));
  1098. *result_type = RUN_CONTAINER_TYPE;
  1099. return result;
  1100. }
  1101. #endif
  1102. *result_type = BITSET_CONTAINER_TYPE;
  1103. return c1;
  1104. case CONTAINER_PAIR(ARRAY, ARRAY):
  1105. *result_type = array_array_container_inplace_union(
  1106. CAST_array(c1), const_CAST_array(c2), &result)
  1107. ? BITSET_CONTAINER_TYPE
  1108. : ARRAY_CONTAINER_TYPE;
  1109. if ((result == NULL) && (*result_type == ARRAY_CONTAINER_TYPE)) {
  1110. return c1; // the computation was done in-place!
  1111. }
  1112. return result;
  1113. case CONTAINER_PAIR(RUN, RUN):
  1114. run_container_union_inplace(CAST_run(c1), const_CAST_run(c2));
  1115. return convert_run_to_efficient_container(CAST_run(c1),
  1116. result_type);
  1117. case CONTAINER_PAIR(BITSET, ARRAY):
  1118. array_bitset_container_union(
  1119. const_CAST_array(c2), const_CAST_bitset(c1), CAST_bitset(c1));
  1120. *result_type = BITSET_CONTAINER_TYPE; // never array
  1121. return c1;
  1122. case CONTAINER_PAIR(ARRAY, BITSET):
  1123. // c1 is an array, so no in-place possible
  1124. result = bitset_container_create();
  1125. *result_type = BITSET_CONTAINER_TYPE;
  1126. array_bitset_container_union(const_CAST_array(c1),
  1127. const_CAST_bitset(c2),
  1128. CAST_bitset(result));
  1129. return result;
  1130. case CONTAINER_PAIR(BITSET, RUN):
  1131. if (run_container_is_full(const_CAST_run(c2))) {
  1132. result = run_container_create();
  1133. *result_type = RUN_CONTAINER_TYPE;
  1134. run_container_copy(const_CAST_run(c2), CAST_run(result));
  1135. return result;
  1136. }
  1137. run_bitset_container_union(const_CAST_run(c2),
  1138. const_CAST_bitset(c1),
  1139. CAST_bitset(c1)); // allowed
  1140. *result_type = BITSET_CONTAINER_TYPE;
  1141. return c1;
  1142. case CONTAINER_PAIR(RUN, BITSET):
  1143. if (run_container_is_full(const_CAST_run(c1))) {
  1144. *result_type = RUN_CONTAINER_TYPE;
  1145. return c1;
  1146. }
  1147. result = bitset_container_create();
  1148. run_bitset_container_union(
  1149. const_CAST_run(c1), const_CAST_bitset(c2), CAST_bitset(result));
  1150. *result_type = BITSET_CONTAINER_TYPE;
  1151. return result;
  1152. case CONTAINER_PAIR(ARRAY, RUN):
  1153. result = run_container_create();
  1154. array_run_container_union(const_CAST_array(c1), const_CAST_run(c2),
  1155. CAST_run(result));
  1156. result = convert_run_to_efficient_container_and_free(
  1157. CAST_run(result), result_type);
  1158. return result;
  1159. case CONTAINER_PAIR(RUN, ARRAY):
  1160. array_run_container_inplace_union(const_CAST_array(c2),
  1161. CAST_run(c1));
  1162. c1 = convert_run_to_efficient_container(CAST_run(c1), result_type);
  1163. return c1;
  1164. default:
  1165. assert(false);
  1166. roaring_unreachable;
  1167. return NULL;
  1168. }
  1169. }
  1170. /**
  1171. * Compute the union between two containers, with result in the first container.
  1172. * If the returned pointer is identical to c1, then the container has been
  1173. * modified.
  1174. * If the returned pointer is different from c1, then a new container has been
  1175. * created and the caller is responsible for freeing it.
  1176. * The type of the first container may change. Returns the modified
  1177. * (and possibly new) container
  1178. *
  1179. * This lazy version delays some operations such as the maintenance of the
  1180. * cardinality. It requires repair later on the generated containers.
  1181. */
  1182. static inline container_t *container_lazy_ior(container_t *c1, uint8_t type1,
  1183. const container_t *c2,
  1184. uint8_t type2,
  1185. uint8_t *result_type) {
  1186. assert(type1 != SHARED_CONTAINER_TYPE);
  1187. // c1 = get_writable_copy_if_shared(c1,&type1);
  1188. c2 = container_unwrap_shared(c2, &type2);
  1189. container_t *result = NULL;
  1190. switch (PAIR_CONTAINER_TYPES(type1, type2)) {
  1191. case CONTAINER_PAIR(BITSET, BITSET):
  1192. #ifdef LAZY_OR_BITSET_CONVERSION_TO_FULL
  1193. // if we have two bitsets, we might as well compute the cardinality
  1194. bitset_container_or(const_CAST_bitset(c1), const_CAST_bitset(c2),
  1195. CAST_bitset(c1));
  1196. // it is possible that two bitsets can lead to a full container
  1197. if (CAST_bitset(c1)->cardinality == (1 << 16)) { // we convert
  1198. result = run_container_create_range(0, (1 << 16));
  1199. *result_type = RUN_CONTAINER_TYPE;
  1200. return result;
  1201. }
  1202. #else
  1203. bitset_container_or_nocard(const_CAST_bitset(c1),
  1204. const_CAST_bitset(c2), CAST_bitset(c1));
  1205. #endif
  1206. *result_type = BITSET_CONTAINER_TYPE;
  1207. return c1;
  1208. case CONTAINER_PAIR(ARRAY, ARRAY):
  1209. *result_type = array_array_container_lazy_inplace_union(
  1210. CAST_array(c1), const_CAST_array(c2), &result)
  1211. ? BITSET_CONTAINER_TYPE
  1212. : ARRAY_CONTAINER_TYPE;
  1213. if ((result == NULL) && (*result_type == ARRAY_CONTAINER_TYPE)) {
  1214. return c1; // the computation was done in-place!
  1215. }
  1216. return result;
  1217. case CONTAINER_PAIR(RUN, RUN):
  1218. run_container_union_inplace(CAST_run(c1), const_CAST_run(c2));
  1219. *result_type = RUN_CONTAINER_TYPE;
  1220. return convert_run_to_efficient_container(CAST_run(c1),
  1221. result_type);
  1222. case CONTAINER_PAIR(BITSET, ARRAY):
  1223. array_bitset_container_lazy_union(const_CAST_array(c2),
  1224. const_CAST_bitset(c1),
  1225. CAST_bitset(c1)); // is lazy
  1226. *result_type = BITSET_CONTAINER_TYPE; // never array
  1227. return c1;
  1228. case CONTAINER_PAIR(ARRAY, BITSET):
  1229. // c1 is an array, so no in-place possible
  1230. result = bitset_container_create();
  1231. *result_type = BITSET_CONTAINER_TYPE;
  1232. array_bitset_container_lazy_union(const_CAST_array(c1),
  1233. const_CAST_bitset(c2),
  1234. CAST_bitset(result)); // is lazy
  1235. return result;
  1236. case CONTAINER_PAIR(BITSET, RUN):
  1237. if (run_container_is_full(const_CAST_run(c2))) {
  1238. result = run_container_create();
  1239. *result_type = RUN_CONTAINER_TYPE;
  1240. run_container_copy(const_CAST_run(c2), CAST_run(result));
  1241. return result;
  1242. }
  1243. run_bitset_container_lazy_union(
  1244. const_CAST_run(c2), const_CAST_bitset(c1),
  1245. CAST_bitset(c1)); // allowed // lazy
  1246. *result_type = BITSET_CONTAINER_TYPE;
  1247. return c1;
  1248. case CONTAINER_PAIR(RUN, BITSET):
  1249. if (run_container_is_full(const_CAST_run(c1))) {
  1250. *result_type = RUN_CONTAINER_TYPE;
  1251. return c1;
  1252. }
  1253. result = bitset_container_create();
  1254. run_bitset_container_lazy_union(const_CAST_run(c1),
  1255. const_CAST_bitset(c2),
  1256. CAST_bitset(result)); // lazy
  1257. *result_type = BITSET_CONTAINER_TYPE;
  1258. return result;
  1259. case CONTAINER_PAIR(ARRAY, RUN):
  1260. result = run_container_create();
  1261. array_run_container_union(const_CAST_array(c1), const_CAST_run(c2),
  1262. CAST_run(result));
  1263. *result_type = RUN_CONTAINER_TYPE;
  1264. // next line skipped since we are lazy
  1265. // result = convert_run_to_efficient_container_and_free(result,
  1266. // result_type);
  1267. return result;
  1268. case CONTAINER_PAIR(RUN, ARRAY):
  1269. array_run_container_inplace_union(const_CAST_array(c2),
  1270. CAST_run(c1));
  1271. *result_type = RUN_CONTAINER_TYPE;
  1272. // next line skipped since we are lazy
  1273. // result = convert_run_to_efficient_container_and_free(result,
  1274. // result_type);
  1275. return c1;
  1276. default:
  1277. assert(false);
  1278. roaring_unreachable;
  1279. return NULL;
  1280. }
  1281. }
  1282. /**
  1283. * Compute symmetric difference (xor) between two containers, generate a new
  1284. * container (having type result_type), requires a typecode. This allocates new
  1285. * memory, caller is responsible for deallocation.
  1286. */
  1287. static inline container_t *container_xor(const container_t *c1, uint8_t type1,
  1288. const container_t *c2, uint8_t type2,
  1289. uint8_t *result_type) {
  1290. c1 = container_unwrap_shared(c1, &type1);
  1291. c2 = container_unwrap_shared(c2, &type2);
  1292. container_t *result = NULL;
  1293. switch (PAIR_CONTAINER_TYPES(type1, type2)) {
  1294. case CONTAINER_PAIR(BITSET, BITSET):
  1295. *result_type =
  1296. bitset_bitset_container_xor(const_CAST_bitset(c1),
  1297. const_CAST_bitset(c2), &result)
  1298. ? BITSET_CONTAINER_TYPE
  1299. : ARRAY_CONTAINER_TYPE;
  1300. return result;
  1301. case CONTAINER_PAIR(ARRAY, ARRAY):
  1302. *result_type =
  1303. array_array_container_xor(const_CAST_array(c1),
  1304. const_CAST_array(c2), &result)
  1305. ? BITSET_CONTAINER_TYPE
  1306. : ARRAY_CONTAINER_TYPE;
  1307. return result;
  1308. case CONTAINER_PAIR(RUN, RUN):
  1309. *result_type = (uint8_t)run_run_container_xor(
  1310. const_CAST_run(c1), const_CAST_run(c2), &result);
  1311. return result;
  1312. case CONTAINER_PAIR(BITSET, ARRAY):
  1313. *result_type =
  1314. array_bitset_container_xor(const_CAST_array(c2),
  1315. const_CAST_bitset(c1), &result)
  1316. ? BITSET_CONTAINER_TYPE
  1317. : ARRAY_CONTAINER_TYPE;
  1318. return result;
  1319. case CONTAINER_PAIR(ARRAY, BITSET):
  1320. *result_type =
  1321. array_bitset_container_xor(const_CAST_array(c1),
  1322. const_CAST_bitset(c2), &result)
  1323. ? BITSET_CONTAINER_TYPE
  1324. : ARRAY_CONTAINER_TYPE;
  1325. return result;
  1326. case CONTAINER_PAIR(BITSET, RUN):
  1327. *result_type =
  1328. run_bitset_container_xor(const_CAST_run(c2),
  1329. const_CAST_bitset(c1), &result)
  1330. ? BITSET_CONTAINER_TYPE
  1331. : ARRAY_CONTAINER_TYPE;
  1332. return result;
  1333. case CONTAINER_PAIR(RUN, BITSET):
  1334. *result_type =
  1335. run_bitset_container_xor(const_CAST_run(c1),
  1336. const_CAST_bitset(c2), &result)
  1337. ? BITSET_CONTAINER_TYPE
  1338. : ARRAY_CONTAINER_TYPE;
  1339. return result;
  1340. case CONTAINER_PAIR(ARRAY, RUN):
  1341. *result_type = (uint8_t)array_run_container_xor(
  1342. const_CAST_array(c1), const_CAST_run(c2), &result);
  1343. return result;
  1344. case CONTAINER_PAIR(RUN, ARRAY):
  1345. *result_type = (uint8_t)array_run_container_xor(
  1346. const_CAST_array(c2), const_CAST_run(c1), &result);
  1347. return result;
  1348. default:
  1349. assert(false);
  1350. roaring_unreachable;
  1351. return NULL; // unreached
  1352. }
  1353. }
  1354. /* Applies an offset to the non-empty container 'c'.
  1355. * The results are stored in new containers returned via 'lo' and 'hi', for the
  1356. * low and high halves of the result (where the low half matches the original
  1357. * key and the high one corresponds to values for the following key). Either one
  1358. * of 'lo' and 'hi' are allowed to be 'NULL', but not both. Whenever one of them
  1359. * is not 'NULL', it should point to a 'NULL' container. Whenever one of them is
  1360. * 'NULL' the shifted elements for that part will not be computed. If either of
  1361. * the resulting containers turns out to be empty, the pointed container will
  1362. * remain 'NULL'.
  1363. */
  1364. static inline void container_add_offset(const container_t *c, uint8_t type,
  1365. container_t **lo, container_t **hi,
  1366. uint16_t offset) {
  1367. assert(offset != 0);
  1368. assert(container_nonzero_cardinality(c, type));
  1369. assert(lo != NULL || hi != NULL);
  1370. assert(lo == NULL || *lo == NULL);
  1371. assert(hi == NULL || *hi == NULL);
  1372. switch (type) {
  1373. case BITSET_CONTAINER_TYPE:
  1374. bitset_container_offset(const_CAST_bitset(c), lo, hi, offset);
  1375. break;
  1376. case ARRAY_CONTAINER_TYPE:
  1377. array_container_offset(const_CAST_array(c), lo, hi, offset);
  1378. break;
  1379. case RUN_CONTAINER_TYPE:
  1380. run_container_offset(const_CAST_run(c), lo, hi, offset);
  1381. break;
  1382. default:
  1383. assert(false);
  1384. roaring_unreachable;
  1385. break;
  1386. }
  1387. }
  1388. /**
  1389. * Compute xor between two containers, generate a new container (having type
  1390. * result_type), requires a typecode. This allocates new memory, caller
  1391. * is responsible for deallocation.
  1392. *
  1393. * This lazy version delays some operations such as the maintenance of the
  1394. * cardinality. It requires repair later on the generated containers.
  1395. */
  1396. static inline container_t *container_lazy_xor(const container_t *c1,
  1397. uint8_t type1,
  1398. const container_t *c2,
  1399. uint8_t type2,
  1400. uint8_t *result_type) {
  1401. c1 = container_unwrap_shared(c1, &type1);
  1402. c2 = container_unwrap_shared(c2, &type2);
  1403. container_t *result = NULL;
  1404. switch (PAIR_CONTAINER_TYPES(type1, type2)) {
  1405. case CONTAINER_PAIR(BITSET, BITSET):
  1406. result = bitset_container_create();
  1407. bitset_container_xor_nocard(const_CAST_bitset(c1),
  1408. const_CAST_bitset(c2),
  1409. CAST_bitset(result)); // is lazy
  1410. *result_type = BITSET_CONTAINER_TYPE;
  1411. return result;
  1412. case CONTAINER_PAIR(ARRAY, ARRAY):
  1413. *result_type =
  1414. array_array_container_lazy_xor(const_CAST_array(c1),
  1415. const_CAST_array(c2), &result)
  1416. ? BITSET_CONTAINER_TYPE
  1417. : ARRAY_CONTAINER_TYPE;
  1418. return result;
  1419. case CONTAINER_PAIR(RUN, RUN):
  1420. // nothing special done yet.
  1421. *result_type = (uint8_t)run_run_container_xor(
  1422. const_CAST_run(c1), const_CAST_run(c2), &result);
  1423. return result;
  1424. case CONTAINER_PAIR(BITSET, ARRAY):
  1425. result = bitset_container_create();
  1426. *result_type = BITSET_CONTAINER_TYPE;
  1427. array_bitset_container_lazy_xor(const_CAST_array(c2),
  1428. const_CAST_bitset(c1),
  1429. CAST_bitset(result));
  1430. return result;
  1431. case CONTAINER_PAIR(ARRAY, BITSET):
  1432. result = bitset_container_create();
  1433. *result_type = BITSET_CONTAINER_TYPE;
  1434. array_bitset_container_lazy_xor(const_CAST_array(c1),
  1435. const_CAST_bitset(c2),
  1436. CAST_bitset(result));
  1437. return result;
  1438. case CONTAINER_PAIR(BITSET, RUN):
  1439. result = bitset_container_create();
  1440. run_bitset_container_lazy_xor(
  1441. const_CAST_run(c2), const_CAST_bitset(c1), CAST_bitset(result));
  1442. *result_type = BITSET_CONTAINER_TYPE;
  1443. return result;
  1444. case CONTAINER_PAIR(RUN, BITSET):
  1445. result = bitset_container_create();
  1446. run_bitset_container_lazy_xor(
  1447. const_CAST_run(c1), const_CAST_bitset(c2), CAST_bitset(result));
  1448. *result_type = BITSET_CONTAINER_TYPE;
  1449. return result;
  1450. case CONTAINER_PAIR(ARRAY, RUN):
  1451. result = run_container_create();
  1452. array_run_container_lazy_xor(const_CAST_array(c1),
  1453. const_CAST_run(c2), CAST_run(result));
  1454. *result_type = RUN_CONTAINER_TYPE;
  1455. // next line skipped since we are lazy
  1456. // result = convert_run_to_efficient_container(result, result_type);
  1457. return result;
  1458. case CONTAINER_PAIR(RUN, ARRAY):
  1459. result = run_container_create();
  1460. array_run_container_lazy_xor(const_CAST_array(c2),
  1461. const_CAST_run(c1), CAST_run(result));
  1462. *result_type = RUN_CONTAINER_TYPE;
  1463. // next line skipped since we are lazy
  1464. // result = convert_run_to_efficient_container(result, result_type);
  1465. return result;
  1466. default:
  1467. assert(false);
  1468. roaring_unreachable;
  1469. return NULL; // unreached
  1470. }
  1471. }
  1472. /**
  1473. * Compute the xor between two containers, with result in the first container.
  1474. * If the returned pointer is identical to c1, then the container has been
  1475. * modified.
  1476. * If the returned pointer is different from c1, then a new container has been
  1477. * created. The original container is freed by container_ixor.
  1478. * The type of the first container may change. Returns the modified (and
  1479. * possibly new) container.
  1480. */
  1481. static inline container_t *container_ixor(container_t *c1, uint8_t type1,
  1482. const container_t *c2, uint8_t type2,
  1483. uint8_t *result_type) {
  1484. c1 = get_writable_copy_if_shared(c1, &type1);
  1485. c2 = container_unwrap_shared(c2, &type2);
  1486. container_t *result = NULL;
  1487. switch (PAIR_CONTAINER_TYPES(type1, type2)) {
  1488. case CONTAINER_PAIR(BITSET, BITSET):
  1489. *result_type = bitset_bitset_container_ixor(
  1490. CAST_bitset(c1), const_CAST_bitset(c2), &result)
  1491. ? BITSET_CONTAINER_TYPE
  1492. : ARRAY_CONTAINER_TYPE;
  1493. return result;
  1494. case CONTAINER_PAIR(ARRAY, ARRAY):
  1495. *result_type = array_array_container_ixor(
  1496. CAST_array(c1), const_CAST_array(c2), &result)
  1497. ? BITSET_CONTAINER_TYPE
  1498. : ARRAY_CONTAINER_TYPE;
  1499. return result;
  1500. case CONTAINER_PAIR(RUN, RUN):
  1501. *result_type = (uint8_t)run_run_container_ixor(
  1502. CAST_run(c1), const_CAST_run(c2), &result);
  1503. return result;
  1504. case CONTAINER_PAIR(BITSET, ARRAY):
  1505. *result_type = bitset_array_container_ixor(
  1506. CAST_bitset(c1), const_CAST_array(c2), &result)
  1507. ? BITSET_CONTAINER_TYPE
  1508. : ARRAY_CONTAINER_TYPE;
  1509. return result;
  1510. case CONTAINER_PAIR(ARRAY, BITSET):
  1511. *result_type = array_bitset_container_ixor(
  1512. CAST_array(c1), const_CAST_bitset(c2), &result)
  1513. ? BITSET_CONTAINER_TYPE
  1514. : ARRAY_CONTAINER_TYPE;
  1515. return result;
  1516. case CONTAINER_PAIR(BITSET, RUN):
  1517. *result_type = bitset_run_container_ixor(
  1518. CAST_bitset(c1), const_CAST_run(c2), &result)
  1519. ? BITSET_CONTAINER_TYPE
  1520. : ARRAY_CONTAINER_TYPE;
  1521. return result;
  1522. case CONTAINER_PAIR(RUN, BITSET):
  1523. *result_type = run_bitset_container_ixor(
  1524. CAST_run(c1), const_CAST_bitset(c2), &result)
  1525. ? BITSET_CONTAINER_TYPE
  1526. : ARRAY_CONTAINER_TYPE;
  1527. return result;
  1528. case CONTAINER_PAIR(ARRAY, RUN):
  1529. *result_type = (uint8_t)array_run_container_ixor(
  1530. CAST_array(c1), const_CAST_run(c2), &result);
  1531. return result;
  1532. case CONTAINER_PAIR(RUN, ARRAY):
  1533. *result_type = (uint8_t)run_array_container_ixor(
  1534. CAST_run(c1), const_CAST_array(c2), &result);
  1535. return result;
  1536. default:
  1537. assert(false);
  1538. roaring_unreachable;
  1539. return NULL;
  1540. }
  1541. }
  1542. /**
  1543. * Compute the xor between two containers, with result in the first container.
  1544. * If the returned pointer is identical to c1, then the container has been
  1545. * modified.
  1546. * If the returned pointer is different from c1, then a new container has been
  1547. * created and the caller is responsible for freeing it.
  1548. * The type of the first container may change. Returns the modified
  1549. * (and possibly new) container
  1550. *
  1551. * This lazy version delays some operations such as the maintenance of the
  1552. * cardinality. It requires repair later on the generated containers.
  1553. */
  1554. static inline container_t *container_lazy_ixor(container_t *c1, uint8_t type1,
  1555. const container_t *c2,
  1556. uint8_t type2,
  1557. uint8_t *result_type) {
  1558. assert(type1 != SHARED_CONTAINER_TYPE);
  1559. // c1 = get_writable_copy_if_shared(c1,&type1);
  1560. c2 = container_unwrap_shared(c2, &type2);
  1561. switch (PAIR_CONTAINER_TYPES(type1, type2)) {
  1562. case CONTAINER_PAIR(BITSET, BITSET):
  1563. bitset_container_xor_nocard(CAST_bitset(c1), const_CAST_bitset(c2),
  1564. CAST_bitset(c1)); // is lazy
  1565. *result_type = BITSET_CONTAINER_TYPE;
  1566. return c1;
  1567. // TODO: other cases being lazy, esp. when we know inplace not likely
  1568. // could see the corresponding code for union
  1569. default:
  1570. // we may have a dirty bitset (without a precomputed cardinality)
  1571. // and calling container_ixor on it might be unsafe.
  1572. if (type1 == BITSET_CONTAINER_TYPE) {
  1573. bitset_container_t *bc = CAST_bitset(c1);
  1574. if (bc->cardinality == BITSET_UNKNOWN_CARDINALITY) {
  1575. bc->cardinality = bitset_container_compute_cardinality(bc);
  1576. }
  1577. }
  1578. return container_ixor(c1, type1, c2, type2, result_type);
  1579. }
  1580. }
  1581. /**
  1582. * Compute difference (andnot) between two containers, generate a new
  1583. * container (having type result_type), requires a typecode. This allocates new
  1584. * memory, caller is responsible for deallocation.
  1585. */
  1586. static inline container_t *container_andnot(const container_t *c1,
  1587. uint8_t type1,
  1588. const container_t *c2,
  1589. uint8_t type2,
  1590. uint8_t *result_type) {
  1591. c1 = container_unwrap_shared(c1, &type1);
  1592. c2 = container_unwrap_shared(c2, &type2);
  1593. container_t *result = NULL;
  1594. switch (PAIR_CONTAINER_TYPES(type1, type2)) {
  1595. case CONTAINER_PAIR(BITSET, BITSET):
  1596. *result_type =
  1597. bitset_bitset_container_andnot(const_CAST_bitset(c1),
  1598. const_CAST_bitset(c2), &result)
  1599. ? BITSET_CONTAINER_TYPE
  1600. : ARRAY_CONTAINER_TYPE;
  1601. return result;
  1602. case CONTAINER_PAIR(ARRAY, ARRAY):
  1603. result = array_container_create();
  1604. array_array_container_andnot(
  1605. const_CAST_array(c1), const_CAST_array(c2), CAST_array(result));
  1606. *result_type = ARRAY_CONTAINER_TYPE;
  1607. return result;
  1608. case CONTAINER_PAIR(RUN, RUN):
  1609. if (run_container_is_full(const_CAST_run(c2))) {
  1610. result = array_container_create();
  1611. *result_type = ARRAY_CONTAINER_TYPE;
  1612. return result;
  1613. }
  1614. *result_type = (uint8_t)run_run_container_andnot(
  1615. const_CAST_run(c1), const_CAST_run(c2), &result);
  1616. return result;
  1617. case CONTAINER_PAIR(BITSET, ARRAY):
  1618. *result_type =
  1619. bitset_array_container_andnot(const_CAST_bitset(c1),
  1620. const_CAST_array(c2), &result)
  1621. ? BITSET_CONTAINER_TYPE
  1622. : ARRAY_CONTAINER_TYPE;
  1623. return result;
  1624. case CONTAINER_PAIR(ARRAY, BITSET):
  1625. result = array_container_create();
  1626. array_bitset_container_andnot(const_CAST_array(c1),
  1627. const_CAST_bitset(c2),
  1628. CAST_array(result));
  1629. *result_type = ARRAY_CONTAINER_TYPE;
  1630. return result;
  1631. case CONTAINER_PAIR(BITSET, RUN):
  1632. if (run_container_is_full(const_CAST_run(c2))) {
  1633. result = array_container_create();
  1634. *result_type = ARRAY_CONTAINER_TYPE;
  1635. return result;
  1636. }
  1637. *result_type =
  1638. bitset_run_container_andnot(const_CAST_bitset(c1),
  1639. const_CAST_run(c2), &result)
  1640. ? BITSET_CONTAINER_TYPE
  1641. : ARRAY_CONTAINER_TYPE;
  1642. return result;
  1643. case CONTAINER_PAIR(RUN, BITSET):
  1644. *result_type =
  1645. run_bitset_container_andnot(const_CAST_run(c1),
  1646. const_CAST_bitset(c2), &result)
  1647. ? BITSET_CONTAINER_TYPE
  1648. : ARRAY_CONTAINER_TYPE;
  1649. return result;
  1650. case CONTAINER_PAIR(ARRAY, RUN):
  1651. if (run_container_is_full(const_CAST_run(c2))) {
  1652. result = array_container_create();
  1653. *result_type = ARRAY_CONTAINER_TYPE;
  1654. return result;
  1655. }
  1656. result = array_container_create();
  1657. array_run_container_andnot(const_CAST_array(c1), const_CAST_run(c2),
  1658. CAST_array(result));
  1659. *result_type = ARRAY_CONTAINER_TYPE;
  1660. return result;
  1661. case CONTAINER_PAIR(RUN, ARRAY):
  1662. *result_type = (uint8_t)run_array_container_andnot(
  1663. const_CAST_run(c1), const_CAST_array(c2), &result);
  1664. return result;
  1665. default:
  1666. assert(false);
  1667. roaring_unreachable;
  1668. return NULL; // unreached
  1669. }
  1670. }
  1671. /**
  1672. * Compute the andnot between two containers, with result in the first
  1673. * container.
  1674. * If the returned pointer is identical to c1, then the container has been
  1675. * modified.
  1676. * If the returned pointer is different from c1, then a new container has been
  1677. * created. The original container is freed by container_iandnot.
  1678. * The type of the first container may change. Returns the modified (and
  1679. * possibly new) container.
  1680. */
  1681. static inline container_t *container_iandnot(container_t *c1, uint8_t type1,
  1682. const container_t *c2,
  1683. uint8_t type2,
  1684. uint8_t *result_type) {
  1685. c1 = get_writable_copy_if_shared(c1, &type1);
  1686. c2 = container_unwrap_shared(c2, &type2);
  1687. container_t *result = NULL;
  1688. switch (PAIR_CONTAINER_TYPES(type1, type2)) {
  1689. case CONTAINER_PAIR(BITSET, BITSET):
  1690. *result_type = bitset_bitset_container_iandnot(
  1691. CAST_bitset(c1), const_CAST_bitset(c2), &result)
  1692. ? BITSET_CONTAINER_TYPE
  1693. : ARRAY_CONTAINER_TYPE;
  1694. return result;
  1695. case CONTAINER_PAIR(ARRAY, ARRAY):
  1696. array_array_container_iandnot(CAST_array(c1), const_CAST_array(c2));
  1697. *result_type = ARRAY_CONTAINER_TYPE;
  1698. return c1;
  1699. case CONTAINER_PAIR(RUN, RUN):
  1700. *result_type = (uint8_t)run_run_container_iandnot(
  1701. CAST_run(c1), const_CAST_run(c2), &result);
  1702. return result;
  1703. case CONTAINER_PAIR(BITSET, ARRAY):
  1704. *result_type = bitset_array_container_iandnot(
  1705. CAST_bitset(c1), const_CAST_array(c2), &result)
  1706. ? BITSET_CONTAINER_TYPE
  1707. : ARRAY_CONTAINER_TYPE;
  1708. return result;
  1709. case CONTAINER_PAIR(ARRAY, BITSET):
  1710. *result_type = ARRAY_CONTAINER_TYPE;
  1711. array_bitset_container_iandnot(CAST_array(c1),
  1712. const_CAST_bitset(c2));
  1713. return c1;
  1714. case CONTAINER_PAIR(BITSET, RUN):
  1715. *result_type = bitset_run_container_iandnot(
  1716. CAST_bitset(c1), const_CAST_run(c2), &result)
  1717. ? BITSET_CONTAINER_TYPE
  1718. : ARRAY_CONTAINER_TYPE;
  1719. return result;
  1720. case CONTAINER_PAIR(RUN, BITSET):
  1721. *result_type = run_bitset_container_iandnot(
  1722. CAST_run(c1), const_CAST_bitset(c2), &result)
  1723. ? BITSET_CONTAINER_TYPE
  1724. : ARRAY_CONTAINER_TYPE;
  1725. return result;
  1726. case CONTAINER_PAIR(ARRAY, RUN):
  1727. *result_type = ARRAY_CONTAINER_TYPE;
  1728. array_run_container_iandnot(CAST_array(c1), const_CAST_run(c2));
  1729. return c1;
  1730. case CONTAINER_PAIR(RUN, ARRAY):
  1731. *result_type = (uint8_t)run_array_container_iandnot(
  1732. CAST_run(c1), const_CAST_array(c2), &result);
  1733. return result;
  1734. default:
  1735. assert(false);
  1736. roaring_unreachable;
  1737. return NULL;
  1738. }
  1739. }
  1740. /**
  1741. * Visit all values x of the container once, passing (base+x,ptr)
  1742. * to iterator. You need to specify a container and its type.
  1743. * Returns true if the iteration should continue.
  1744. */
  1745. static inline bool container_iterate(const container_t *c, uint8_t type,
  1746. uint32_t base, roaring_iterator iterator,
  1747. void *ptr) {
  1748. c = container_unwrap_shared(c, &type);
  1749. switch (type) {
  1750. case BITSET_CONTAINER_TYPE:
  1751. return bitset_container_iterate(const_CAST_bitset(c), base,
  1752. iterator, ptr);
  1753. case ARRAY_CONTAINER_TYPE:
  1754. return array_container_iterate(const_CAST_array(c), base, iterator,
  1755. ptr);
  1756. case RUN_CONTAINER_TYPE:
  1757. return run_container_iterate(const_CAST_run(c), base, iterator,
  1758. ptr);
  1759. default:
  1760. assert(false);
  1761. roaring_unreachable;
  1762. }
  1763. assert(false);
  1764. roaring_unreachable;
  1765. return false;
  1766. }
  1767. static inline bool container_iterate64(const container_t *c, uint8_t type,
  1768. uint32_t base,
  1769. roaring_iterator64 iterator,
  1770. uint64_t high_bits, void *ptr) {
  1771. c = container_unwrap_shared(c, &type);
  1772. switch (type) {
  1773. case BITSET_CONTAINER_TYPE:
  1774. return bitset_container_iterate64(const_CAST_bitset(c), base,
  1775. iterator, high_bits, ptr);
  1776. case ARRAY_CONTAINER_TYPE:
  1777. return array_container_iterate64(const_CAST_array(c), base,
  1778. iterator, high_bits, ptr);
  1779. case RUN_CONTAINER_TYPE:
  1780. return run_container_iterate64(const_CAST_run(c), base, iterator,
  1781. high_bits, ptr);
  1782. default:
  1783. assert(false);
  1784. roaring_unreachable;
  1785. }
  1786. assert(false);
  1787. roaring_unreachable;
  1788. return false;
  1789. }
  1790. static inline container_t *container_not(const container_t *c, uint8_t type,
  1791. uint8_t *result_type) {
  1792. c = container_unwrap_shared(c, &type);
  1793. container_t *result = NULL;
  1794. switch (type) {
  1795. case BITSET_CONTAINER_TYPE:
  1796. *result_type =
  1797. bitset_container_negation(const_CAST_bitset(c), &result)
  1798. ? BITSET_CONTAINER_TYPE
  1799. : ARRAY_CONTAINER_TYPE;
  1800. return result;
  1801. case ARRAY_CONTAINER_TYPE:
  1802. result = bitset_container_create();
  1803. *result_type = BITSET_CONTAINER_TYPE;
  1804. array_container_negation(const_CAST_array(c), CAST_bitset(result));
  1805. return result;
  1806. case RUN_CONTAINER_TYPE:
  1807. *result_type =
  1808. (uint8_t)run_container_negation(const_CAST_run(c), &result);
  1809. return result;
  1810. default:
  1811. assert(false);
  1812. roaring_unreachable;
  1813. }
  1814. assert(false);
  1815. roaring_unreachable;
  1816. return NULL;
  1817. }
  1818. static inline container_t *container_not_range(const container_t *c,
  1819. uint8_t type,
  1820. uint32_t range_start,
  1821. uint32_t range_end,
  1822. uint8_t *result_type) {
  1823. c = container_unwrap_shared(c, &type);
  1824. container_t *result = NULL;
  1825. switch (type) {
  1826. case BITSET_CONTAINER_TYPE:
  1827. *result_type =
  1828. bitset_container_negation_range(const_CAST_bitset(c),
  1829. range_start, range_end, &result)
  1830. ? BITSET_CONTAINER_TYPE
  1831. : ARRAY_CONTAINER_TYPE;
  1832. return result;
  1833. case ARRAY_CONTAINER_TYPE:
  1834. *result_type =
  1835. array_container_negation_range(const_CAST_array(c), range_start,
  1836. range_end, &result)
  1837. ? BITSET_CONTAINER_TYPE
  1838. : ARRAY_CONTAINER_TYPE;
  1839. return result;
  1840. case RUN_CONTAINER_TYPE:
  1841. *result_type = (uint8_t)run_container_negation_range(
  1842. const_CAST_run(c), range_start, range_end, &result);
  1843. return result;
  1844. default:
  1845. assert(false);
  1846. roaring_unreachable;
  1847. }
  1848. assert(false);
  1849. roaring_unreachable;
  1850. return NULL;
  1851. }
  1852. static inline container_t *container_inot(container_t *c, uint8_t type,
  1853. uint8_t *result_type) {
  1854. c = get_writable_copy_if_shared(c, &type);
  1855. container_t *result = NULL;
  1856. switch (type) {
  1857. case BITSET_CONTAINER_TYPE:
  1858. *result_type =
  1859. bitset_container_negation_inplace(CAST_bitset(c), &result)
  1860. ? BITSET_CONTAINER_TYPE
  1861. : ARRAY_CONTAINER_TYPE;
  1862. return result;
  1863. case ARRAY_CONTAINER_TYPE:
  1864. // will never be inplace
  1865. result = bitset_container_create();
  1866. *result_type = BITSET_CONTAINER_TYPE;
  1867. array_container_negation(CAST_array(c), CAST_bitset(result));
  1868. array_container_free(CAST_array(c));
  1869. return result;
  1870. case RUN_CONTAINER_TYPE:
  1871. *result_type =
  1872. (uint8_t)run_container_negation_inplace(CAST_run(c), &result);
  1873. return result;
  1874. default:
  1875. assert(false);
  1876. roaring_unreachable;
  1877. }
  1878. assert(false);
  1879. roaring_unreachable;
  1880. return NULL;
  1881. }
  1882. static inline container_t *container_inot_range(container_t *c, uint8_t type,
  1883. uint32_t range_start,
  1884. uint32_t range_end,
  1885. uint8_t *result_type) {
  1886. c = get_writable_copy_if_shared(c, &type);
  1887. container_t *result = NULL;
  1888. switch (type) {
  1889. case BITSET_CONTAINER_TYPE:
  1890. *result_type = bitset_container_negation_range_inplace(
  1891. CAST_bitset(c), range_start, range_end, &result)
  1892. ? BITSET_CONTAINER_TYPE
  1893. : ARRAY_CONTAINER_TYPE;
  1894. return result;
  1895. case ARRAY_CONTAINER_TYPE:
  1896. *result_type = array_container_negation_range_inplace(
  1897. CAST_array(c), range_start, range_end, &result)
  1898. ? BITSET_CONTAINER_TYPE
  1899. : ARRAY_CONTAINER_TYPE;
  1900. return result;
  1901. case RUN_CONTAINER_TYPE:
  1902. *result_type = (uint8_t)run_container_negation_range_inplace(
  1903. CAST_run(c), range_start, range_end, &result);
  1904. return result;
  1905. default:
  1906. assert(false);
  1907. roaring_unreachable;
  1908. }
  1909. assert(false);
  1910. roaring_unreachable;
  1911. return NULL;
  1912. }
  1913. /**
  1914. * If the element of given rank is in this container, supposing that
  1915. * the first
  1916. * element has rank start_rank, then the function returns true and
  1917. * sets element
  1918. * accordingly.
  1919. * Otherwise, it returns false and update start_rank.
  1920. */
  1921. static inline bool container_select(const container_t *c, uint8_t type,
  1922. uint32_t *start_rank, uint32_t rank,
  1923. uint32_t *element) {
  1924. c = container_unwrap_shared(c, &type);
  1925. switch (type) {
  1926. case BITSET_CONTAINER_TYPE:
  1927. return bitset_container_select(const_CAST_bitset(c), start_rank,
  1928. rank, element);
  1929. case ARRAY_CONTAINER_TYPE:
  1930. return array_container_select(const_CAST_array(c), start_rank, rank,
  1931. element);
  1932. case RUN_CONTAINER_TYPE:
  1933. return run_container_select(const_CAST_run(c), start_rank, rank,
  1934. element);
  1935. default:
  1936. assert(false);
  1937. roaring_unreachable;
  1938. }
  1939. assert(false);
  1940. roaring_unreachable;
  1941. return false;
  1942. }
  1943. static inline uint16_t container_maximum(const container_t *c, uint8_t type) {
  1944. c = container_unwrap_shared(c, &type);
  1945. switch (type) {
  1946. case BITSET_CONTAINER_TYPE:
  1947. return bitset_container_maximum(const_CAST_bitset(c));
  1948. case ARRAY_CONTAINER_TYPE:
  1949. return array_container_maximum(const_CAST_array(c));
  1950. case RUN_CONTAINER_TYPE:
  1951. return run_container_maximum(const_CAST_run(c));
  1952. default:
  1953. assert(false);
  1954. roaring_unreachable;
  1955. }
  1956. assert(false);
  1957. roaring_unreachable;
  1958. return false;
  1959. }
  1960. static inline uint16_t container_minimum(const container_t *c, uint8_t type) {
  1961. c = container_unwrap_shared(c, &type);
  1962. switch (type) {
  1963. case BITSET_CONTAINER_TYPE:
  1964. return bitset_container_minimum(const_CAST_bitset(c));
  1965. case ARRAY_CONTAINER_TYPE:
  1966. return array_container_minimum(const_CAST_array(c));
  1967. case RUN_CONTAINER_TYPE:
  1968. return run_container_minimum(const_CAST_run(c));
  1969. default:
  1970. assert(false);
  1971. roaring_unreachable;
  1972. }
  1973. assert(false);
  1974. roaring_unreachable;
  1975. return false;
  1976. }
  1977. // number of values smaller or equal to x
  1978. static inline int container_rank(const container_t *c, uint8_t type,
  1979. uint16_t x) {
  1980. c = container_unwrap_shared(c, &type);
  1981. switch (type) {
  1982. case BITSET_CONTAINER_TYPE:
  1983. return bitset_container_rank(const_CAST_bitset(c), x);
  1984. case ARRAY_CONTAINER_TYPE:
  1985. return array_container_rank(const_CAST_array(c), x);
  1986. case RUN_CONTAINER_TYPE:
  1987. return run_container_rank(const_CAST_run(c), x);
  1988. default:
  1989. assert(false);
  1990. roaring_unreachable;
  1991. }
  1992. assert(false);
  1993. roaring_unreachable;
  1994. return false;
  1995. }
  1996. // bulk version of container_rank(); return number of consumed elements
  1997. static inline uint32_t container_rank_many(const container_t *c, uint8_t type,
  1998. uint64_t start_rank,
  1999. const uint32_t *begin,
  2000. const uint32_t *end, uint64_t *ans) {
  2001. c = container_unwrap_shared(c, &type);
  2002. switch (type) {
  2003. case BITSET_CONTAINER_TYPE:
  2004. return bitset_container_rank_many(const_CAST_bitset(c), start_rank,
  2005. begin, end, ans);
  2006. case ARRAY_CONTAINER_TYPE:
  2007. return array_container_rank_many(const_CAST_array(c), start_rank,
  2008. begin, end, ans);
  2009. case RUN_CONTAINER_TYPE:
  2010. return run_container_rank_many(const_CAST_run(c), start_rank, begin,
  2011. end, ans);
  2012. default:
  2013. assert(false);
  2014. roaring_unreachable;
  2015. }
  2016. assert(false);
  2017. roaring_unreachable;
  2018. return 0;
  2019. }
  2020. // return the index of x, if not exsist return -1
  2021. static inline int container_get_index(const container_t *c, uint8_t type,
  2022. uint16_t x) {
  2023. c = container_unwrap_shared(c, &type);
  2024. switch (type) {
  2025. case BITSET_CONTAINER_TYPE:
  2026. return bitset_container_get_index(const_CAST_bitset(c), x);
  2027. case ARRAY_CONTAINER_TYPE:
  2028. return array_container_get_index(const_CAST_array(c), x);
  2029. case RUN_CONTAINER_TYPE:
  2030. return run_container_get_index(const_CAST_run(c), x);
  2031. default:
  2032. assert(false);
  2033. roaring_unreachable;
  2034. }
  2035. assert(false);
  2036. roaring_unreachable;
  2037. return false;
  2038. }
  2039. /**
  2040. * Add all values in range [min, max] to a given container.
  2041. *
  2042. * If the returned pointer is different from $container, then a new container
  2043. * has been created and the caller is responsible for freeing it.
  2044. * The type of the first container may change. Returns the modified
  2045. * (and possibly new) container.
  2046. */
  2047. static inline container_t *container_add_range(container_t *c, uint8_t type,
  2048. uint32_t min, uint32_t max,
  2049. uint8_t *result_type) {
  2050. // NB: when selecting new container type, we perform only inexpensive checks
  2051. switch (type) {
  2052. case BITSET_CONTAINER_TYPE: {
  2053. bitset_container_t *bitset = CAST_bitset(c);
  2054. int32_t union_cardinality = 0;
  2055. union_cardinality += bitset->cardinality;
  2056. union_cardinality += max - min + 1;
  2057. union_cardinality -=
  2058. bitset_lenrange_cardinality(bitset->words, min, max - min);
  2059. if (union_cardinality == INT32_C(0x10000)) {
  2060. *result_type = RUN_CONTAINER_TYPE;
  2061. return run_container_create_range(0, INT32_C(0x10000));
  2062. } else {
  2063. *result_type = BITSET_CONTAINER_TYPE;
  2064. bitset_set_lenrange(bitset->words, min, max - min);
  2065. bitset->cardinality = union_cardinality;
  2066. return bitset;
  2067. }
  2068. }
  2069. case ARRAY_CONTAINER_TYPE: {
  2070. array_container_t *array = CAST_array(c);
  2071. int32_t nvals_greater =
  2072. count_greater(array->array, array->cardinality, (uint16_t)max);
  2073. int32_t nvals_less =
  2074. count_less(array->array, array->cardinality - nvals_greater,
  2075. (uint16_t)min);
  2076. int32_t union_cardinality =
  2077. nvals_less + (max - min + 1) + nvals_greater;
  2078. if (union_cardinality == INT32_C(0x10000)) {
  2079. *result_type = RUN_CONTAINER_TYPE;
  2080. return run_container_create_range(0, INT32_C(0x10000));
  2081. } else if (union_cardinality <= DEFAULT_MAX_SIZE) {
  2082. *result_type = ARRAY_CONTAINER_TYPE;
  2083. array_container_add_range_nvals(array, min, max, nvals_less,
  2084. nvals_greater);
  2085. return array;
  2086. } else {
  2087. *result_type = BITSET_CONTAINER_TYPE;
  2088. bitset_container_t *bitset = bitset_container_from_array(array);
  2089. bitset_set_lenrange(bitset->words, min, max - min);
  2090. bitset->cardinality = union_cardinality;
  2091. return bitset;
  2092. }
  2093. }
  2094. case RUN_CONTAINER_TYPE: {
  2095. run_container_t *run = CAST_run(c);
  2096. int32_t nruns_greater =
  2097. rle16_count_greater(run->runs, run->n_runs, (uint16_t)max);
  2098. int32_t nruns_less = rle16_count_less(
  2099. run->runs, run->n_runs - nruns_greater, (uint16_t)min);
  2100. int32_t run_size_bytes =
  2101. (nruns_less + 1 + nruns_greater) * sizeof(rle16_t);
  2102. int32_t bitset_size_bytes =
  2103. BITSET_CONTAINER_SIZE_IN_WORDS * sizeof(uint64_t);
  2104. if (run_size_bytes <= bitset_size_bytes) {
  2105. run_container_add_range_nruns(run, min, max, nruns_less,
  2106. nruns_greater);
  2107. *result_type = RUN_CONTAINER_TYPE;
  2108. return run;
  2109. } else {
  2110. return container_from_run_range(run, min, max, result_type);
  2111. }
  2112. }
  2113. default:
  2114. roaring_unreachable;
  2115. }
  2116. }
  2117. /*
  2118. * Removes all elements in range [min, max].
  2119. * Returns one of:
  2120. * - NULL if no elements left
  2121. * - pointer to the original container
  2122. * - pointer to a newly-allocated container (if it is more efficient)
  2123. *
  2124. * If the returned pointer is different from $container, then a new container
  2125. * has been created and the caller is responsible for freeing the original
  2126. * container.
  2127. */
  2128. static inline container_t *container_remove_range(container_t *c, uint8_t type,
  2129. uint32_t min, uint32_t max,
  2130. uint8_t *result_type) {
  2131. switch (type) {
  2132. case BITSET_CONTAINER_TYPE: {
  2133. bitset_container_t *bitset = CAST_bitset(c);
  2134. int32_t result_cardinality =
  2135. bitset->cardinality -
  2136. bitset_lenrange_cardinality(bitset->words, min, max - min);
  2137. if (result_cardinality == 0) {
  2138. return NULL;
  2139. } else if (result_cardinality <= DEFAULT_MAX_SIZE) {
  2140. *result_type = ARRAY_CONTAINER_TYPE;
  2141. bitset_reset_range(bitset->words, min, max + 1);
  2142. bitset->cardinality = result_cardinality;
  2143. return array_container_from_bitset(bitset);
  2144. } else {
  2145. *result_type = BITSET_CONTAINER_TYPE;
  2146. bitset_reset_range(bitset->words, min, max + 1);
  2147. bitset->cardinality = result_cardinality;
  2148. return bitset;
  2149. }
  2150. }
  2151. case ARRAY_CONTAINER_TYPE: {
  2152. array_container_t *array = CAST_array(c);
  2153. int32_t nvals_greater =
  2154. count_greater(array->array, array->cardinality, (uint16_t)max);
  2155. int32_t nvals_less =
  2156. count_less(array->array, array->cardinality - nvals_greater,
  2157. (uint16_t)min);
  2158. int32_t result_cardinality = nvals_less + nvals_greater;
  2159. if (result_cardinality == 0) {
  2160. return NULL;
  2161. } else {
  2162. *result_type = ARRAY_CONTAINER_TYPE;
  2163. array_container_remove_range(
  2164. array, nvals_less, array->cardinality - result_cardinality);
  2165. return array;
  2166. }
  2167. }
  2168. case RUN_CONTAINER_TYPE: {
  2169. run_container_t *run = CAST_run(c);
  2170. if (run->n_runs == 0) {
  2171. return NULL;
  2172. }
  2173. if (min <= run_container_minimum(run) &&
  2174. max >= run_container_maximum(run)) {
  2175. return NULL;
  2176. }
  2177. run_container_remove_range(run, min, max);
  2178. return convert_run_to_efficient_container(run, result_type);
  2179. }
  2180. default:
  2181. roaring_unreachable;
  2182. }
  2183. }
  2184. #ifdef __cplusplus
  2185. using api::roaring_container_iterator_t;
  2186. #endif
  2187. /**
  2188. * Initializes the iterator at the first entry in the container.
  2189. */
  2190. roaring_container_iterator_t container_init_iterator(const container_t *c,
  2191. uint8_t typecode,
  2192. uint16_t *value);
  2193. /**
  2194. * Initializes the iterator at the last entry in the container.
  2195. */
  2196. roaring_container_iterator_t container_init_iterator_last(const container_t *c,
  2197. uint8_t typecode,
  2198. uint16_t *value);
  2199. /**
  2200. * Moves the iterator to the next entry. Returns true and sets `value` if a
  2201. * value is present.
  2202. */
  2203. bool container_iterator_next(const container_t *c, uint8_t typecode,
  2204. roaring_container_iterator_t *it, uint16_t *value);
  2205. /**
  2206. * Moves the iterator to the previous entry. Returns true and sets `value` if a
  2207. * value is present.
  2208. */
  2209. bool container_iterator_prev(const container_t *c, uint8_t typecode,
  2210. roaring_container_iterator_t *it, uint16_t *value);
  2211. /**
  2212. * Moves the iterator to the smallest entry that is greater than or equal to
  2213. * `val`. Returns true and sets `value_out` if a value is present. `value_out`
  2214. * should be initialized to a value.
  2215. */
  2216. bool container_iterator_lower_bound(const container_t *c, uint8_t typecode,
  2217. roaring_container_iterator_t *it,
  2218. uint16_t *value_out, uint16_t val);
  2219. /**
  2220. * Reads up to `count` entries from the container, and writes them into `buf`
  2221. * as `high16 | entry`. Returns true and sets `value_out` if a value is present
  2222. * after reading the entries. Sets `consumed` to the number of values read.
  2223. * `count` should be greater than zero.
  2224. */
  2225. bool container_iterator_read_into_uint32(const container_t *c, uint8_t typecode,
  2226. roaring_container_iterator_t *it,
  2227. uint32_t high16, uint32_t *buf,
  2228. uint32_t count, uint32_t *consumed,
  2229. uint16_t *value_out);
  2230. /**
  2231. * Reads up to `count` entries from the container, and writes them into `buf`
  2232. * as `high48 | entry`. Returns true and sets `value_out` if a value is present
  2233. * after reading the entries. Sets `consumed` to the number of values read.
  2234. * `count` should be greater than zero.
  2235. */
  2236. bool container_iterator_read_into_uint64(const container_t *c, uint8_t typecode,
  2237. roaring_container_iterator_t *it,
  2238. uint64_t high48, uint64_t *buf,
  2239. uint32_t count, uint32_t *consumed,
  2240. uint16_t *value_out);
  2241. #ifdef __cplusplus
  2242. }
  2243. }
  2244. } // extern "C" { namespace roaring { namespace internal {
  2245. #endif
  2246. #endif