sets.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. // Public Domain.
  2. #include <stddef.h> // ptrdiff_t, size_t
  3. #include <stdlib.h> // [c|m|re]alloc, free
  4. #include <string.h> // memcpy
  5. #include <stdio.h> // printf
  6. #include "sets.h"
  7. // Pointer Sets
  8. void PointerSet_print(PointerSet* ps) {
  9. printf("PointerSet %p (%ld items)\n", (void*)ps, ps->length);
  10. for(size_t i = 0; i < ps->length; i++) {
  11. printf(" %ld: %p\n", i, ps->set[i]);
  12. }
  13. }
  14. size_t PointerSet_find_index(PointerSet* ps, void* p) {
  15. ptrdiff_t R = ps->length - 1;
  16. ptrdiff_t L = 0;
  17. ptrdiff_t i;
  18. while(R - L > 0) {
  19. // midpoint
  20. i = L + ((R - L) / 2);
  21. if(ps->set[i] < p) {
  22. L = i + 1;
  23. }
  24. else if(ps->set[i] > p) {
  25. R = i - 1;
  26. }
  27. else {
  28. return i;
  29. }
  30. }
  31. return (ps->set[L] < p) ? L + 1 : L;
  32. }
  33. void PointerSet_insert(PointerSet* ps, void* p) {
  34. if(ps->length == 0) {
  35. ps->alloc = 8;
  36. ps->set = calloc(1, ps->alloc * sizeof(*ps->set));
  37. ps->set[0] = p;
  38. ps->length++;
  39. return;
  40. }
  41. else if(ps->length + 1 > ps->alloc) {
  42. ps->alloc *= 2;
  43. ps->set = realloc(ps->set, ps->alloc * sizeof(*ps->set));
  44. }
  45. // find the slot
  46. size_t i = PointerSet_find_index(ps, p);
  47. if(ps->set[i] == p) return;
  48. memmove(ps->set + i + 1, ps->set + i, (ps->length - i) * sizeof(*ps->set));
  49. ps->set[i] = p;
  50. ps->length++;
  51. }
  52. int PointerSet_remove(PointerSet* ps, void* p) {
  53. if(ps->length == 0) return 0;
  54. size_t i = PointerSet_find_index(ps, p);
  55. if(ps->set[i] != p) return 0;
  56. memmove(ps->set + i, ps->set + i + 1, (ps->length - i - 1) * sizeof(*ps->set));
  57. ps->length--;
  58. return 1;
  59. }
  60. int PointerSet_exists(PointerSet* ps, void* p) {
  61. if(ps->length == 0) return 0;
  62. size_t i = PointerSet_find_index(ps, p);
  63. return (ps->set[i] == p);
  64. }
  65. PointerSet* PointerSet_alloc() {
  66. PointerSet* ps = malloc(sizeof(ps));
  67. ps->alloc = 0;
  68. ps->length = 0;
  69. return ps;
  70. }
  71. void PointerSet_init(PointerSet* ps) {
  72. ps->alloc = 0;
  73. ps->length = 0;
  74. }
  75. void PointerSet_free(PointerSet* ps) {
  76. free(ps->set);
  77. free(ps);
  78. }
  79. void PointerSet_destroy(PointerSet* ps) {
  80. free(ps->set);
  81. ps->alloc = 0;
  82. ps->length = 0;
  83. }
  84. int PointerSet_equal(PointerSet* a, PointerSet* b) {
  85. if(a->length != b->length) return 0;
  86. for(size_t i = 0; i < a->length; i++) {
  87. if(a->set[i] != b->set[i]) return 0;
  88. }
  89. return 1;
  90. }
  91. PointerSet* PointerSet_intersect(PointerSet* a, PointerSet* b) {
  92. PointerSet* c = malloc(sizeof(*c));
  93. c->alloc = a->length > b->length ? a->length : b->length;
  94. c->set = malloc(c->alloc * sizeof(*c->set));
  95. c->length = 0;
  96. size_t ci = 0;
  97. size_t bi = 0;
  98. size_t ai = 0;
  99. while(ai < a->length && bi < b->length) {
  100. void* ap = a->set[ai];
  101. void* bp = b->set[bi];
  102. if(ap == bp) {
  103. c->set[ci] = a->set[ai];
  104. c->length++;
  105. ai++; bi++; ci++;
  106. }
  107. else if(ap > bp) {
  108. bi++;
  109. }
  110. else {
  111. ai++;
  112. }
  113. }
  114. return c;
  115. }
  116. PointerSet* PointerSet_union(PointerSet* a, PointerSet* b) {
  117. PointerSet* c = malloc(sizeof(*c));
  118. c->alloc = a->length + b->length;
  119. c->set = malloc(c->alloc * sizeof(*c->set));
  120. c->length = 0;
  121. size_t ci = 0;
  122. size_t bi = 0;
  123. size_t ai = 0;
  124. while(ai < a->length || bi < b->length) {
  125. void* ap = a->set[ai];
  126. void* bp = b->set[bi];
  127. if(ap == bp) {
  128. c->set[ci] = a->set[ai];
  129. c->length++;
  130. ai++; bi++; ci++;
  131. }
  132. else if(ap > bp) {
  133. c->set[ci++] = b->set[bi];
  134. c->length++;
  135. bi++;
  136. }
  137. else {
  138. c->set[ci++] = a->set[ai];
  139. c->length++;
  140. ai++;
  141. }
  142. }
  143. return c;
  144. }
  145. void PointerSet_union_inplace(PointerSet* a, PointerSet* b) {
  146. a->alloc = a->length + b->length;
  147. a->set = realloc(a->set, a->alloc * sizeof(*a->set));
  148. // work backwards to fill in the data, then do one memmove
  149. size_t final_length = 0;
  150. ptrdiff_t bi = b->length - 1;
  151. ptrdiff_t ai = a->length - 1;
  152. ptrdiff_t wi = a->alloc - 1; // write index
  153. while(ai >= 0 && bi >= 0) {
  154. void* ap = a->set[ai];
  155. void* bp = b->set[bi];
  156. if(ap == bp) {
  157. a->set[wi] = a->set[ai];
  158. final_length++;
  159. ai--; bi--; wi--;
  160. }
  161. else if(ap < bp) {
  162. a->set[wi--] = b->set[bi--];
  163. final_length++;
  164. }
  165. else {
  166. a->set[wi--] = a->set[ai--];
  167. final_length++;
  168. }
  169. };
  170. // finish off any remainder
  171. while(ai >= 0) {
  172. a->set[wi--] = a->set[ai--];
  173. final_length++;
  174. }
  175. while(bi >= 0) {
  176. a->set[wi--] = b->set[bi--];
  177. final_length++;
  178. }
  179. // the unioned data is at the end of the allocation. move it to the front.
  180. memmove(a->set, a->set + a->alloc - final_length, final_length * sizeof(*a->set));
  181. a->length = final_length;
  182. }
  183. PointerSet* PointerSet_difference(PointerSet* a, PointerSet* b) {
  184. PointerSet* c = malloc(sizeof(*c));
  185. c->alloc = a->length + b->length;
  186. c->set = malloc(c->alloc * sizeof(*c->set));
  187. c->length = 0;
  188. size_t ci = 0;
  189. size_t bi = 0;
  190. size_t ai = 0;
  191. while(ai < a->length || bi < b->length) {
  192. void* ap = a->set[ai];
  193. void* bp = b->set[bi];
  194. if(ap == bp) {
  195. ai++; bi++;
  196. }
  197. else if(ap > bp) {
  198. c->set[ci++] = b->set[bi];
  199. c->length++;
  200. bi++;
  201. }
  202. else {
  203. c->set[ci++] = a->set[ai];
  204. c->length++;
  205. ai++;
  206. }
  207. }
  208. return c;
  209. }
  210. // Struct Sets
  211. #define SS_EQ(ss, i, p) \
  212. ss->cmp((char*)ss->set + i * ss->elem_size, p)
  213. #define SS_CMP(a, b, ai, bi) \
  214. a->cmp((char*)a->set + (ai * a->elem_size), (char*)b->set + (bi * b->elem_size))
  215. #define SS_SET(ss, i, p) \
  216. memcpy((char*)ss->set + i * ss->elem_size, p, ss->elem_size)
  217. size_t StructSet_find_index(StructSet* ss, void* p) {
  218. ptrdiff_t R = ss->length - 1;
  219. ptrdiff_t L = 0;
  220. ptrdiff_t i;
  221. while(R - L > 0) {
  222. // midpoint
  223. i = L + ((R - L) / 2);
  224. int n = SS_EQ(ss, i, &p);
  225. if(n < 0) {
  226. L = i + 1;
  227. }
  228. else if(n > 0) {
  229. R = i - 1;
  230. }
  231. else {
  232. return i;
  233. }
  234. }
  235. return (SS_EQ(ss, L, &p) < 0) ? L + 1 : L;
  236. }
  237. int StructSet_insert(StructSet* ss, void* p) {
  238. if(ss->length == 0) {
  239. ss->alloc = 8;
  240. ss->set = calloc(1, ss->alloc * ss->elem_size);
  241. SS_SET(ss, 0, &p);
  242. ss->length++;
  243. return 0;
  244. }
  245. else if(ss->length + 1 > ss->alloc) {
  246. ss->alloc *= 2;
  247. ss->set = realloc(ss->set, ss->alloc * ss->elem_size);
  248. }
  249. // find the slot
  250. size_t i = StructSet_find_index(ss, p);
  251. if(SS_EQ(ss, i, &p) == 0) return 1;
  252. memmove(
  253. (char*)ss->set + (i + 1) * ss->elem_size,
  254. (char*)ss->set + i * ss->elem_size,
  255. (ss->length - i) * ss->elem_size
  256. );
  257. SS_SET(ss, i, &p);
  258. ss->length++;
  259. return 0;
  260. }
  261. int StructSet_insertGet(StructSet* ss, void* p, void** existing) {
  262. if(ss->length == 0) {
  263. ss->alloc = 8;
  264. ss->set = calloc(1, ss->alloc * ss->elem_size);
  265. SS_SET(ss, 0, &p);
  266. ss->length++;
  267. return 0;
  268. }
  269. else if(ss->length + 1 > ss->alloc) {
  270. ss->alloc *= 2;
  271. ss->set = realloc(ss->set, ss->alloc * ss->elem_size);
  272. }
  273. // find the slot
  274. size_t i = StructSet_find_index(ss, p);
  275. if(SS_EQ(ss, i, &p) == 0) {
  276. if(existing) {
  277. memcpy(
  278. existing,
  279. (char*)ss->set + i * ss->elem_size,
  280. (ss->length - i) * ss->elem_size
  281. );
  282. }
  283. return 1;
  284. }
  285. memmove(
  286. (char*)ss->set + (i + 1) * ss->elem_size,
  287. (char*)ss->set + i * ss->elem_size,
  288. (ss->length - i) * ss->elem_size
  289. );
  290. SS_SET(ss, i, &p);
  291. ss->length++;
  292. return 0;
  293. }
  294. int StructSet_remove(StructSet* ss, void* p) {
  295. if(ss->length == 0) return 0;
  296. size_t i = StructSet_find_index(ss, p);
  297. if(SS_EQ(ss, i, &p) != 0) return 0;
  298. memmove(
  299. (char*)ss->set + i * ss->elem_size,
  300. (char*)ss->set + (i + 1) * ss->elem_size,
  301. (ss->length - i - 1) * ss->elem_size
  302. );
  303. ss->length--;
  304. return 1;
  305. }
  306. int StructSet_exists(StructSet* ss, void* p) {
  307. if(ss->length == 0) return 0;
  308. size_t i = StructSet_find_index(ss, p);
  309. return SS_EQ(ss, i, &p) == 0;
  310. }
  311. StructSet* StructSet_alloc_(size_t elem_size, SetCmpFn cmp) {
  312. StructSet* ss = malloc(sizeof(ss));
  313. StructSet_init(ss, elem_size, cmp);
  314. return ss;
  315. }
  316. void StructSet_free(StructSet* ss) {
  317. free(ss->set);
  318. free(ss);
  319. }
  320. void StructSet_destroy(StructSet* ss) {
  321. free(ss->set);
  322. ss->alloc = 0;
  323. }
  324. StructSet* StructSet_intersect(StructSet* a, StructSet* b) {
  325. StructSet* c = malloc(sizeof(*c));
  326. c->elem_size = a->elem_size;
  327. c->alloc = a->length > b->length ? a->length : b->length;
  328. c->set = malloc(c->alloc * c->elem_size);
  329. c->length = 0;
  330. c->elem_size = a->elem_size;
  331. c->cmp = a->cmp;
  332. size_t ci = 0;
  333. size_t bi = 0;
  334. size_t ai = 0;
  335. while(ai < a->length && bi < b->length) {
  336. int n = SS_CMP(a, b, ai, bi);
  337. if(n == 0) {
  338. SS_SET(c, ci, (char*)a->set + ai * a->elem_size);
  339. c->length++;
  340. ai++; bi++; ci++;
  341. }
  342. else if(n > 0) {
  343. bi++;
  344. }
  345. else {
  346. ai++;
  347. }
  348. }
  349. return c;
  350. }
  351. StructSet* StructSet_union(StructSet* a, StructSet* b) {
  352. StructSet* c = malloc(sizeof(*c));
  353. c->elem_size = a->elem_size;
  354. c->alloc = a->length + b->length;
  355. c->set = malloc(c->alloc * c->elem_size);
  356. c->length = 0;
  357. c->elem_size = a->elem_size;
  358. c->cmp = a->cmp;
  359. size_t ci = 0;
  360. size_t bi = 0;
  361. size_t ai = 0;
  362. while(ai < a->length || bi < b->length) {
  363. int n = SS_CMP(a, b, ai, bi);
  364. if(n == 0) {
  365. SS_SET(c, ci, (char*)a->set + ai * a->elem_size);
  366. c->length++;
  367. ai++; bi++; ci++;
  368. }
  369. else if(n > 0) {
  370. SS_SET(c, ci, (char*)b->set + bi * b->elem_size);
  371. c->length++;
  372. bi++;
  373. }
  374. else {
  375. SS_SET(c, ci, (char*)a->set + ai * a->elem_size);
  376. c->length++;
  377. ai++;
  378. }
  379. }
  380. return c;
  381. }
  382. StructSet* StructSet_difference(StructSet* a, StructSet* b) {
  383. StructSet* c = malloc(sizeof(*c));
  384. c->elem_size = a->elem_size;
  385. c->alloc = a->length + b->length;
  386. c->set = malloc(c->alloc * c->elem_size);
  387. c->length = 0;
  388. c->elem_size = a->elem_size;
  389. c->cmp = a->cmp;
  390. size_t ci = 0;
  391. size_t bi = 0;
  392. size_t ai = 0;
  393. while(ai < a->length || bi < b->length) {
  394. int n = SS_CMP(a, b, ai, bi);
  395. if(n == 0) {
  396. ai++; bi++;
  397. }
  398. else if(n > 0) {
  399. SS_SET(c, ci, (char*)b->set + bi * b->elem_size);
  400. c->length++;
  401. bi++;
  402. }
  403. else {
  404. SS_SET(c, ci, (char*)a->set + ai * a->elem_size);
  405. c->length++;
  406. ai++;
  407. }
  408. }
  409. return c;
  410. }
  411. // Sets for base types
  412. DEFINE_SET_FOR_TYPE(char, "%c")
  413. DEFINE_SET_FOR_TYPE(short, "%d")
  414. DEFINE_SET_FOR_TYPE(int, "%d")
  415. DEFINE_SET_FOR_TYPE(long, "%ld")
  416. DEFINE_SET_FOR_TYPE(int8_t, "%d")
  417. DEFINE_SET_FOR_TYPE(int16_t, "%d")
  418. DEFINE_SET_FOR_TYPE(int32_t, "%d")
  419. DEFINE_SET_FOR_TYPE(int64_t, "%ld")
  420. DEFINE_SET_FOR_TYPE(uint8_t, "%d")
  421. DEFINE_SET_FOR_TYPE(uint16_t, "%d")
  422. DEFINE_SET_FOR_TYPE(uint32_t, "%d")
  423. DEFINE_SET_FOR_TYPE(uint64_t, "%ld")
  424. DEFINE_SET_FOR_TYPE(float, "%f")
  425. DEFINE_SET_FOR_TYPE(double, "%f")