sets.h 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. #ifndef __sti__sets_h__
  2. #define __sti__sets_h__
  3. // Public Domain.
  4. #include <stddef.h> // size_t, ptrdiff_t
  5. #include <stdint.h> // only used for the declarations below, not used in implementation
  6. /*********************************
  7. Pointer Sets
  8. **********************************
  9. Built around sorted vectors
  10. Roughly, tsearch is faster over about 750 inserts.
  11. */
  12. typedef struct PointerSet {
  13. void** set;
  14. size_t length;
  15. size_t alloc;
  16. } PointerSet;
  17. void PointerSet_print(PointerSet* ps);
  18. void PointerSet_insert(PointerSet* ps, void* p);
  19. int PointerSet_remove(PointerSet* ps, void* p);
  20. int PointerSet_exists(PointerSet* ps, void* p);
  21. PointerSet* PointerSet_alloc(void);
  22. void PointerSet_init(PointerSet* ps);
  23. void PointerSet_free(PointerSet* ps);
  24. void PointerSet_destroy(PointerSet* ps);
  25. int PointerSet_equal(PointerSet* a, PointerSet* b);
  26. PointerSet* PointerSet_intersect(PointerSet* a, PointerSet* b);
  27. PointerSet* PointerSet_union(PointerSet* a, PointerSet* b);
  28. PointerSet* PointerSet_difference(PointerSet* a, PointerSet* b);
  29. size_t PointerSet_find_index(PointerSet* ps, void* p);
  30. // adds b into a
  31. void PointerSet_union_inplace(PointerSet* a, PointerSet* b);
  32. /*********************************
  33. Generic Struct Sets
  34. **********************************
  35. */
  36. typedef int (*SetCmpFn)(void*, void*);
  37. typedef struct StructSet {
  38. void* set;
  39. size_t length;
  40. size_t alloc;
  41. size_t elem_size;
  42. SetCmpFn cmp;
  43. } StructSet;
  44. #define StructSet_init(ss, type, comp_fn) \
  45. do { \
  46. (ss)->length = 0; \
  47. (ss)->alloc = 0; \
  48. (ss)->elem_size = sizeof(type); \
  49. (ss)->cmp = (SetCmpFn)(comp_fn); \
  50. } while(0)
  51. int StructSet_insert(StructSet* ss, void* p);
  52. int StructSet_insertGet(StructSet* ss, void* p, void** existing);
  53. int StructSet_remove(StructSet* ss, void* p);
  54. int StructSet_exists(StructSet* ss, void* p);
  55. #define StructSet_alloc(e, c) StructSet_alloc_(sizeof(e), cmp)
  56. StructSet* StructSet_alloc_(size_t elem_size, SetCmpFn cmp);
  57. void StructSet_free(StructSet* ss);
  58. void StructSet_destroy(StructSet* ss);
  59. // must be the exact same set types and compare functions
  60. StructSet* StructSet_intersect(StructSet* a, StructSet* b); \
  61. StructSet* StructSet_union(StructSet* a, StructSet* b); \
  62. StructSet* StructSet_difference(StructSet* a, StructSet* b); \
  63. size_t StructSet_find_index(StructSet* ss, void* p);
  64. /*********************************
  65. Generic Base Typed Sets
  66. **********************************
  67. */
  68. #define DECLARE_SET_FOR_TYPE(type) \
  69. typedef struct type##Set { \
  70. type* set; \
  71. size_t length; \
  72. size_t alloc; \
  73. } type##Set; \
  74. \
  75. void type##Set_print(type##Set* ps); \
  76. void type##Set_insert(type##Set* ps, type p); \
  77. int type##Set_remove(type##Set* ps, type p); \
  78. int type##Set_exists(type##Set* ps, type p); \
  79. type##Set* type##Set_alloc(void); \
  80. void type##Set_init(type##Set* ps); \
  81. void type##Set_free(type##Set* ps); \
  82. void type##Set_destroy(type##Set* ps); \
  83. type##Set* type##Set_intersect(type##Set* a, type##Set* b); \
  84. type##Set* type##Set_union(type##Set* a, type##Set* b); \
  85. void type##Set_union_inplace(type##Set* a, type##Set* b); \
  86. type##Set* type##Set_difference(type##Set* a, type##Set* b); \
  87. size_t type##Set_find_index(type##Set* ps, type p);
  88. #define DEFINE_SET_INSERT(type) \
  89. void type##Set_insert(type##Set* ps, type p) { \
  90. \
  91. if(ps->length == 0) { \
  92. ps->alloc = 8; \
  93. ps->set = calloc(1, ps->alloc * sizeof(*ps->set)); \
  94. \
  95. ps->set[0] = p; \
  96. ps->length++; \
  97. return; \
  98. } \
  99. else if(ps->length + 1 > ps->alloc) { \
  100. ps->alloc *= 2; \
  101. ps->set = realloc(ps->set, ps->alloc * sizeof(*ps->set)); \
  102. } \
  103. \
  104. size_t i = type##Set_find_index(ps, p); \
  105. if(ps->set[i] == p) return; \
  106. \
  107. memmove(ps->set + i + 1, ps->set + i, (ps->length - i) * sizeof(*ps->set)); \
  108. ps->set[i] = p; \
  109. ps->length++; \
  110. }
  111. #define DEFINE_SET_PRINT(type, fmt) \
  112. void type##Set_print(type##Set* ps) { \
  113. printf(#type "Set %p (%ld items)\n", (void*)ps, ps->length); \
  114. for(size_t i = 0; i < ps->length; i++) { \
  115. printf(" %ld: " fmt "\n", i, ps->set[i]); \
  116. } \
  117. }
  118. #define DEFINE_SET_FIND_INDEX(type) \
  119. size_t type##Set_find_index(type##Set* ps, type p) { \
  120. ptrdiff_t R = ps->length - 1; \
  121. ptrdiff_t L = 0; \
  122. ptrdiff_t i; \
  123. \
  124. while(R - L > 0) { \
  125. \
  126. i = L + ((R - L) / 2); \
  127. if(ps->set[i] < p) { \
  128. L = i + 1; \
  129. } \
  130. else if(ps->set[i] > p) { \
  131. R = i - 1; \
  132. } \
  133. else { \
  134. return i; \
  135. } \
  136. } \
  137. \
  138. return (ps->set[L] < p) ? L + 1 : L; \
  139. }
  140. #define DEFINE_SET_REMOVE(type) \
  141. int type##Set_remove(type##Set* ps, type p) { \
  142. if(ps->length == 0) return 0; \
  143. \
  144. size_t i = type##Set_find_index(ps, p); \
  145. if(ps->set[i] != p) return 0; \
  146. \
  147. memmove(ps->set + i, ps->set + i + 1, (ps->length - i - 1) * sizeof(*ps->set)); \
  148. ps->length--; \
  149. return 1; \
  150. }
  151. #define DEFINE_SET_EXISTS(type) \
  152. int type##Set_exists(type##Set* ps, type p) { \
  153. size_t i = type##Set_find_index(ps, p); \
  154. return (ps->set[i] == p); \
  155. }
  156. #define DEFINE_SET_ALLOC(type) \
  157. type##Set* type##Set_alloc(void) { \
  158. type##Set* ps = malloc(sizeof(*ps)); \
  159. type##Set_init(ps); \
  160. return ps; \
  161. }
  162. #define DEFINE_SET_INIT(type) \
  163. void type##Set_init(type##Set* ps) { \
  164. ps->alloc = 0; \
  165. ps->length = 0; \
  166. }
  167. #define DEFINE_SET_FREE(type) \
  168. void type##Set_free(type##Set* ps) { \
  169. free(ps->set); \
  170. free(ps); \
  171. }
  172. #define DEFINE_SET_DESTROY(type) \
  173. void type##Set_destroy(type##Set* ps) { \
  174. free(ps->set); \
  175. }
  176. #define DEFINE_SET_INTERSECT(type) \
  177. type##Set* type##Set_intersect(type##Set* a, type##Set* b) { \
  178. type##Set* c = malloc(sizeof(*c)); \
  179. \
  180. c->alloc = a->length > b->length ? a->length : b->length; \
  181. c->set = malloc(c->alloc * sizeof(*c->set)); \
  182. c->length = 0; \
  183. \
  184. size_t ci = 0; \
  185. size_t bi = 0; \
  186. size_t ai = 0; \
  187. while(ai < a->length && bi < b->length) { \
  188. type ap = a->set[ai]; \
  189. type bp = b->set[bi]; \
  190. if(ap == bp) { \
  191. c->set[ci] = a->set[ai]; \
  192. c->length++; \
  193. ai++; bi++; ci++; \
  194. } \
  195. else if(ap > bp) { \
  196. bi++; \
  197. } \
  198. else { \
  199. ai++; \
  200. } \
  201. } \
  202. \
  203. return c; \
  204. }
  205. #define DEFINE_SET_UNION(type) \
  206. type##Set* type##Set_union(type##Set* a, type##Set* b) { \
  207. type##Set* c = malloc(sizeof(*c)); \
  208. \
  209. c->alloc = a->length + b->length; \
  210. c->set = malloc(c->alloc * sizeof(*c->set)); \
  211. c->length = 0; \
  212. \
  213. size_t ci = 0; \
  214. size_t bi = 0; \
  215. size_t ai = 0; \
  216. while(ai < a->length || bi < b->length) { \
  217. type ap = a->set[ai]; \
  218. type bp = b->set[bi]; \
  219. if(ap == bp) { \
  220. c->set[ci] = a->set[ai]; \
  221. c->length++; \
  222. ai++; bi++; ci++; \
  223. } \
  224. else if(ap > bp) { \
  225. c->set[ci++] = b->set[bi]; \
  226. c->length++; \
  227. bi++; \
  228. } \
  229. else { \
  230. c->set[ci++] = a->set[ai]; \
  231. c->length++; \
  232. ai++; \
  233. } \
  234. } \
  235. \
  236. return c; \
  237. }
  238. #define DEFINE_SET_UNION_INPLACE(type) \
  239. void type##Set_union_inplace(type##Set* a, type##Set* b) { \
  240. type##Set* c = malloc(sizeof(*c)); \
  241. \
  242. a->alloc = a->length + b->length; \
  243. a->set = realloc(a->set, a->alloc * sizeof(*a->set)); \
  244. \
  245. size_t final_length = 0; \
  246. ptrdiff_t bi = b->length - 1; \
  247. ptrdiff_t ai = a->length - 1; \
  248. ptrdiff_t wi = a->alloc - 1; \
  249. while(ai >= 0 && bi >= 0) { \
  250. type ap = a->set[ai]; \
  251. type bp = b->set[bi]; \
  252. if(ap == bp) { \
  253. a->set[wi] = a->set[ai]; \
  254. final_length++; \
  255. ai--; bi--; wi--; \
  256. } \
  257. else if(ap < bp) { \
  258. a->set[wi--] = b->set[bi--]; \
  259. final_length++; \
  260. } \
  261. else { \
  262. a->set[wi--] = a->set[ai--]; \
  263. final_length++; \
  264. } \
  265. }; \
  266. \
  267. while(ai >= 0) { \
  268. a->set[wi--] = a->set[ai--]; \
  269. final_length++; \
  270. } \
  271. while(bi >= 0) { \
  272. a->set[wi--] = b->set[bi--]; \
  273. final_length++; \
  274. } \
  275. \
  276. memmove(a->set, a->set + a->alloc - final_length, final_length * sizeof(*a->set)); \
  277. a->length = final_length; \
  278. }
  279. #define DEFINE_SET_DIFFERENCE(type) \
  280. type##Set* type##Set_difference(type##Set* a, type##Set* b) { \
  281. type##Set* c = malloc(sizeof(*c)); \
  282. \
  283. c->alloc = a->length + b->length; \
  284. c->set = malloc(c->alloc * sizeof(*c->set)); \
  285. c->length = 0; \
  286. \
  287. size_t ci = 0; \
  288. size_t bi = 0; \
  289. size_t ai = 0; \
  290. while(ai < a->length || bi < b->length) { \
  291. type ap = a->set[ai]; \
  292. type bp = b->set[bi]; \
  293. if(ap == bp) { \
  294. ai++; bi++; \
  295. } \
  296. else if(ap > bp) { \
  297. c->set[ci++] = b->set[bi]; \
  298. c->length++; \
  299. bi++; \
  300. } \
  301. else { \
  302. c->set[ci++] = a->set[ai]; \
  303. c->length++; \
  304. ai++; \
  305. } \
  306. } \
  307. \
  308. return c; \
  309. }
  310. #define DEFINE_SET_FOR_TYPE(type, fmt) \
  311. DEFINE_SET_DIFFERENCE(type) \
  312. DEFINE_SET_UNION(type) \
  313. DEFINE_SET_UNION_INPLACE(type) \
  314. DEFINE_SET_INTERSECT(type) \
  315. DEFINE_SET_ALLOC(type) \
  316. DEFINE_SET_INIT(type) \
  317. DEFINE_SET_FREE(type) \
  318. DEFINE_SET_DESTROY(type) \
  319. DEFINE_SET_INSERT(type) \
  320. DEFINE_SET_REMOVE(type) \
  321. DEFINE_SET_EXISTS(type) \
  322. DEFINE_SET_PRINT(type, fmt) \
  323. DEFINE_SET_FIND_INDEX(type)
  324. DECLARE_SET_FOR_TYPE(char)
  325. DECLARE_SET_FOR_TYPE(short)
  326. DECLARE_SET_FOR_TYPE(int)
  327. DECLARE_SET_FOR_TYPE(long)
  328. DECLARE_SET_FOR_TYPE(int8_t)
  329. DECLARE_SET_FOR_TYPE(int16_t)
  330. DECLARE_SET_FOR_TYPE(int32_t)
  331. DECLARE_SET_FOR_TYPE(int64_t)
  332. DECLARE_SET_FOR_TYPE(uint8_t)
  333. DECLARE_SET_FOR_TYPE(uint16_t)
  334. DECLARE_SET_FOR_TYPE(uint32_t)
  335. DECLARE_SET_FOR_TYPE(uint64_t)
  336. DECLARE_SET_FOR_TYPE(double)
  337. DECLARE_SET_FOR_TYPE(float)
  338. #endif // __sti__sets_h__