| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- /* Licensed under LGPLv2.1+ - see LICENSE file for details */
- #include "config.h"
- #include <ccan/bitmap/bitmap.h>
- #include <assert.h>
- #define BIT_ALIGN_DOWN(n) ((n) & ~(BITMAP_WORD_BITS - 1))
- #define BIT_ALIGN_UP(n) BIT_ALIGN_DOWN((n) + BITMAP_WORD_BITS - 1)
- void bitmap_zero_range(bitmap *bitmap, unsigned long n, unsigned long m)
- {
- unsigned long an = BIT_ALIGN_UP(n);
- unsigned long am = BIT_ALIGN_DOWN(m);
- bitmap_word headmask = -1ULL >> (n % BITMAP_WORD_BITS);
- bitmap_word tailmask = ~(-1ULL >> (m % BITMAP_WORD_BITS));
- assert(m >= n);
- if (am < an) {
- BITMAP_WORD(bitmap, n) &= ~bitmap_bswap(headmask & tailmask);
- return;
- }
- if (an > n)
- BITMAP_WORD(bitmap, n) &= ~bitmap_bswap(headmask);
- if (am > an)
- memset(&BITMAP_WORD(bitmap, an), 0,
- (am - an) / BITMAP_WORD_BITS * sizeof(bitmap_word));
- if (m > am)
- BITMAP_WORD(bitmap, m) &= ~bitmap_bswap(tailmask);
- }
- void bitmap_fill_range(bitmap *bitmap, unsigned long n, unsigned long m)
- {
- unsigned long an = BIT_ALIGN_UP(n);
- unsigned long am = BIT_ALIGN_DOWN(m);
- bitmap_word headmask = -1ULL >> (n % BITMAP_WORD_BITS);
- bitmap_word tailmask = ~(-1ULL >> (m % BITMAP_WORD_BITS));
- assert(m >= n);
- if (am < an) {
- BITMAP_WORD(bitmap, n) |= bitmap_bswap(headmask & tailmask);
- return;
- }
- if (an > n)
- BITMAP_WORD(bitmap, n) |= bitmap_bswap(headmask);
- if (am > an)
- memset(&BITMAP_WORD(bitmap, an), 0xff,
- (am - an) / BITMAP_WORD_BITS * sizeof(bitmap_word));
- if (m > am)
- BITMAP_WORD(bitmap, m) |= bitmap_bswap(tailmask);
- }
- static int bitmap_clz(bitmap_word w)
- {
- #if HAVE_BUILTIN_CLZL
- return __builtin_clzl(w);
- #else
- int lz = 0;
- bitmap_word mask = 1UL << (BITMAP_WORD_BITS - 1);
- while (!(w & mask)) {
- lz++;
- mask >>= 1;
- }
- return lz;
- #endif
- }
- unsigned long bitmap_ffs(const bitmap *bitmap,
- unsigned long n, unsigned long m)
- {
- unsigned long an = BIT_ALIGN_UP(n);
- unsigned long am = BIT_ALIGN_DOWN(m);
- bitmap_word headmask = -1ULL >> (n % BITMAP_WORD_BITS);
- bitmap_word tailmask = ~(-1ULL >> (m % BITMAP_WORD_BITS));
- assert(m >= n);
- if (am < an) {
- bitmap_word w = bitmap_bswap(BITMAP_WORD(bitmap, n));
- w &= (headmask & tailmask);
- return w ? am + bitmap_clz(w) : m;
- }
- if (an > n) {
- bitmap_word w = bitmap_bswap(BITMAP_WORD(bitmap, n));
- w &= headmask;
- if (w)
- return BIT_ALIGN_DOWN(n) + bitmap_clz(w);
- }
- while (an < am) {
- bitmap_word w = bitmap_bswap(BITMAP_WORD(bitmap, an));
- if (w)
- return an + bitmap_clz(w);
- an += BITMAP_WORD_BITS;
- }
- if (m > am) {
- bitmap_word w = bitmap_bswap(BITMAP_WORD(bitmap, m));
- w &= tailmask;
- if (w)
- return am + bitmap_clz(w);
- }
- return m;
- }
|