BitArray.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. #include "core/BitArray.h"
  2. #include <assert.h>
  3. #include <inttypes.h>
  4. #include <string.h>
  5. #include "core/ToString.h"
  6. #include "core/Utility.h"
  7. static constexpr size_t U64_BITS = 64;
  8. static constexpr size_t DIVIDE_BITS = 6;
  9. static u64 roundUpDivide(u64 a, u64 b) {
  10. return a / b + ((a % b) != 0);
  11. }
  12. static u64 readBits(const u64* data, size_t index, u64 bits) {
  13. u64 dataIndexA = (index * bits) >> DIVIDE_BITS;
  14. u64 dataIndexB = ((index * bits) + (bits - 1lu)) >> DIVIDE_BITS;
  15. u64 shifts = (index * bits) & (U64_BITS - 1lu);
  16. if(dataIndexA == dataIndexB) {
  17. return (data[dataIndexA] >> shifts) & ((1lu << bits) - 1lu);
  18. }
  19. u64 bitsInA = U64_BITS - shifts;
  20. u64 r = (data[dataIndexA] >> shifts) & ((1lu << bitsInA) - 1lu);
  21. r |= (data[dataIndexB] & ((1lu << (bits - bitsInA)) - 1lu)) << bitsInA;
  22. return r;
  23. }
  24. static void writeBits(u64* data, size_t index, size_t bits, u64 value) {
  25. u64 mask = (1lu << bits) - 1lu;
  26. value &= mask;
  27. u64 dataIndexA = (index * bits) >> DIVIDE_BITS;
  28. u64 dataIndexB = ((index * bits) + (bits - 1lu)) >> DIVIDE_BITS;
  29. u64 shifts = (index * bits) & (U64_BITS - 1lu);
  30. data[dataIndexA] &= ~(mask << shifts);
  31. data[dataIndexA] |= (value << shifts);
  32. if(dataIndexA != dataIndexB) {
  33. u64 leftBits = bits - (U64_BITS - shifts);
  34. data[dataIndexB] &= ~((1lu << leftBits) - 1lu);
  35. data[dataIndexB] |= (value >> (U64_BITS - shifts));
  36. }
  37. }
  38. static size_t getArrayLength(size_t length, size_t bits) {
  39. return roundUpDivide(length * bits, U64_BITS);
  40. }
  41. void initBitArray(BitArray* a, size_t length, size_t bits) {
  42. *a = (BitArray){0};
  43. if(length > 0 && bits > 0) {
  44. setBitLength(a, length, bits);
  45. }
  46. }
  47. void destroyBitArray(BitArray* a) {
  48. coreFree(a->data);
  49. *a = (BitArray){0};
  50. }
  51. void setBits(BitArray* a, size_t index, u64 value) {
  52. assert(a->data != nullptr);
  53. assert(index < a->length);
  54. writeBits(a->data, index, a->bits, value);
  55. }
  56. void setAllBits(BitArray* a, u64 value) {
  57. size_t length = a->length;
  58. for(size_t i = 0; i < length; i++) {
  59. setBits(a, i, value);
  60. }
  61. }
  62. u64 getBits(const BitArray* a, size_t index) {
  63. assert(a->data != nullptr);
  64. assert(index < a->length);
  65. return readBits(a->data, index, a->bits);
  66. }
  67. i64 selectBits(const BitArray* a, size_t index) {
  68. if(index <= 0) {
  69. return -1;
  70. }
  71. u64 found = 0;
  72. size_t end = getArrayLength(a->length, a->bits);
  73. for(size_t i = 0; i < end; i++) {
  74. u64 ones = popCount(a->data[i]);
  75. found += ones;
  76. if(found >= index) {
  77. found -= ones;
  78. u64 c = i * U64_BITS - 1;
  79. u64 d = a->data[i];
  80. while(found < index) {
  81. found += d & 1;
  82. d >>= 1;
  83. c++;
  84. }
  85. return (i64)c;
  86. }
  87. }
  88. return -1;
  89. }
  90. void setBitLength(BitArray* a, size_t newLength, size_t newBits) {
  91. if(newLength == 0 || newBits == 0) {
  92. destroyBitArray(a);
  93. return;
  94. } else if(newBits > 64) {
  95. newBits = 64;
  96. }
  97. size_t arrayLength = getArrayLength(newLength, newBits);
  98. u64* newData = coreAllocate(sizeof(u64) * arrayLength);
  99. memset(newData, 0, arrayLength * sizeof(u64));
  100. size_t end = minSize(a->length, newLength);
  101. for(size_t i = 0; i < end; i++) {
  102. writeBits(newData, i, newBits, getBits(a, i));
  103. }
  104. for(size_t i = end; i < newLength; i++) {
  105. writeBits(newData, i, newBits, 0);
  106. }
  107. coreFree(a->data);
  108. a->data = newData;
  109. a->length = newLength & 0xFF'FFFF'FFFF'FFFF;
  110. a->bits = newBits & 0xFF;
  111. }
  112. size_t toStringBitArray(const BitArray* a, char* buffer, size_t n) {
  113. size_t w = 0;
  114. stringAdd(&w, &buffer, &n, toString(buffer, n, "["));
  115. size_t length = a->length;
  116. if(length > 0) {
  117. length--;
  118. for(size_t i = 0; i < length; i++) {
  119. u64 v = getBits(a, i);
  120. stringAdd(&w, &buffer, &n, toString(buffer, n, "%" PRIu64 ", ", v));
  121. }
  122. u64 v = getBits(a, length);
  123. stringAdd(&w, &buffer, &n, toString(buffer, n, "%" PRIu64, v));
  124. }
  125. stringAdd(&w, &buffer, &n, toString(buffer, n, "]"));
  126. return w;
  127. }