bm.h83 lines · 2.2 KB · raw
1#pragma once
2#include <assert.h>
3
4#include <stddef.h>
5#include <stdbool.h>
6
7// Bitmask operations
8// Uses uint64_t arrays as underlying store
9
10#define BM_SET(BS, I) bm_set((BS), sizeof(BS)/sizeof(uint64_t), (I))
11static inline void
12bm_set(uint64_t *bs, size_t n, size_t i) {
13    assert(i < (n * 64));
14    bs[i / 64] |= 1ul << (i % 64);
15}
16
17/*
18#define BM_CLEAR(BS, I) bm_clear((BS), sizeof(BS)/sizeof(uint64_t), (I))
19static inline void
20bm_clear(uint64_t *bs, size_t n, size_t i) {
21    assert(i < (n * 64));
22    bs[i / 64] &= ~(1ul << (i % 64));
23}
24*/
25
26#define BM_ISSET(BS, I) bm_isset((BS), sizeof(BS)/sizeof(uint64_t), (I))
27static inline bool
28bm_isset(const uint64_t *bs, size_t n, size_t i) {
29    assert(i < (n * 64));
30    return !!(bs[i / 64] & (1ul << (i % 64)));
31}
32
33#define BM_ISEMPTY(BS) bm_isempty((BS), sizeof(BS)/sizeof(uint64_t))
34static inline bool
35bm_isempty(const uint64_t *bs, size_t n) {
36    for(; n; n--) {
37        if (*bs++) return false;
38    }
39    return true;
40}
41
42#define BM_ISMATCH(BS, INVS) bm_ismatch((BS), (INVS), sizeof(BS)/sizeof(uint64_t))
43static inline bool
44bm_ismatch(const uint64_t *bs, const uint64_t *invs, size_t n) {
45    // This is an operation needed by ap_req.c,
46    // if `invs` satisfies the requirements in `bs`
47    for(; n; n--) {
48        if (*bs++ & ~*invs++) return false;
49    }
50    return true;
51}
52
53#define BM_ANDEQ(BS, XS) bm_andeq((BS), (XS), sizeof(BS)/sizeof(uint64_t))
54static inline void
55bm_andeq(uint64_t *bs, const uint64_t *xs, size_t n) {
56    for(; n; n--) {
57        *bs++ &= *xs++;
58    }
59}
60
61#define BM_POPCOUNT(BS) bm_popcount((BS), sizeof(BS)/sizeof(uint64_t))
62static inline size_t
63bm_popcount(const uint64_t *bs, size_t n) {
64    size_t c = 0;
65    static_assert(sizeof(unsigned long) == sizeof(uint64_t), "Update __builtin_popcountl to match uint64_t");
66    for(; n; n--) {
67        c += __builtin_popcountl(*bs++);
68    }
69    return c;
70}
71
72#define BM_FFZ(BS) bm_ffz((BS), sizeof(BS)/sizeof(uint64_t))
73static inline size_t 
74bm_ffz(const uint64_t *bs, size_t n) {
75    static_assert(sizeof(unsigned long) == sizeof(uint64_t), "Update __builtin_ffsl to match uint64_t");
76    for (size_t i = 0; i < n; i++) {
77        size_t z = __builtin_ffsl(~bs[i]);
78        if (z != 0) {
79            return (z - 1) + (i * 64);
80        }
81    }
82    return n * 64;
83}