bitmap.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /* Licensed under LGPLv2.1+ - see LICENSE file for details */
  2. #include "config.h"
  3. #include <ccan/bitmap/bitmap.h>
  4. #include <assert.h>
  5. #define BIT_ALIGN_DOWN(n) ((n) & ~(BITMAP_WORD_BITS - 1))
  6. #define BIT_ALIGN_UP(n) BIT_ALIGN_DOWN((n) + BITMAP_WORD_BITS - 1)
  7. void bitmap_zero_range(bitmap *bitmap, unsigned long n, unsigned long m)
  8. {
  9. unsigned long an = BIT_ALIGN_UP(n);
  10. unsigned long am = BIT_ALIGN_DOWN(m);
  11. bitmap_word headmask = -1ULL >> (n % BITMAP_WORD_BITS);
  12. bitmap_word tailmask = ~(-1ULL >> (m % BITMAP_WORD_BITS));
  13. assert(m >= n);
  14. if (am < an) {
  15. BITMAP_WORD(bitmap, n) &= ~bitmap_bswap(headmask & tailmask);
  16. return;
  17. }
  18. if (an > n)
  19. BITMAP_WORD(bitmap, n) &= ~bitmap_bswap(headmask);
  20. if (am > an)
  21. memset(&BITMAP_WORD(bitmap, an), 0,
  22. (am - an) / BITMAP_WORD_BITS * sizeof(bitmap_word));
  23. if (m > am)
  24. BITMAP_WORD(bitmap, m) &= ~bitmap_bswap(tailmask);
  25. }
  26. void bitmap_fill_range(bitmap *bitmap, unsigned long n, unsigned long m)
  27. {
  28. unsigned long an = BIT_ALIGN_UP(n);
  29. unsigned long am = BIT_ALIGN_DOWN(m);
  30. bitmap_word headmask = -1ULL >> (n % BITMAP_WORD_BITS);
  31. bitmap_word tailmask = ~(-1ULL >> (m % BITMAP_WORD_BITS));
  32. assert(m >= n);
  33. if (am < an) {
  34. BITMAP_WORD(bitmap, n) |= bitmap_bswap(headmask & tailmask);
  35. return;
  36. }
  37. if (an > n)
  38. BITMAP_WORD(bitmap, n) |= bitmap_bswap(headmask);
  39. if (am > an)
  40. memset(&BITMAP_WORD(bitmap, an), 0xff,
  41. (am - an) / BITMAP_WORD_BITS * sizeof(bitmap_word));
  42. if (m > am)
  43. BITMAP_WORD(bitmap, m) |= bitmap_bswap(tailmask);
  44. }
  45. static int bitmap_clz(bitmap_word w)
  46. {
  47. #if HAVE_BUILTIN_CLZL
  48. return __builtin_clzl(w);
  49. #else
  50. int lz = 0;
  51. bitmap_word mask = 1UL << (BITMAP_WORD_BITS - 1);
  52. while (!(w & mask)) {
  53. lz++;
  54. mask >>= 1;
  55. }
  56. return lz;
  57. #endif
  58. }
  59. unsigned long bitmap_ffs(const bitmap *bitmap,
  60. unsigned long n, unsigned long m)
  61. {
  62. unsigned long an = BIT_ALIGN_UP(n);
  63. unsigned long am = BIT_ALIGN_DOWN(m);
  64. bitmap_word headmask = -1ULL >> (n % BITMAP_WORD_BITS);
  65. bitmap_word tailmask = ~(-1ULL >> (m % BITMAP_WORD_BITS));
  66. assert(m >= n);
  67. if (am < an) {
  68. bitmap_word w = bitmap_bswap(BITMAP_WORD(bitmap, n));
  69. w &= (headmask & tailmask);
  70. return w ? am + bitmap_clz(w) : m;
  71. }
  72. if (an > n) {
  73. bitmap_word w = bitmap_bswap(BITMAP_WORD(bitmap, n));
  74. w &= headmask;
  75. if (w)
  76. return BIT_ALIGN_DOWN(n) + bitmap_clz(w);
  77. }
  78. while (an < am) {
  79. bitmap_word w = bitmap_bswap(BITMAP_WORD(bitmap, an));
  80. if (w)
  81. return an + bitmap_clz(w);
  82. an += BITMAP_WORD_BITS;
  83. }
  84. if (m > am) {
  85. bitmap_word w = bitmap_bswap(BITMAP_WORD(bitmap, m));
  86. w &= tailmask;
  87. if (w)
  88. return am + bitmap_clz(w);
  89. }
  90. return m;
  91. }