BitArray.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #include "core/BitArray.h"
  2. #include <assert.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include "core/Utility.h"
  6. static u64 roundUpDivide(u64 a, u64 b) {
  7. return a / b + ((a % b) != 0);
  8. }
  9. #define U64_BITS 64
  10. #define DIVIDE_BITS 6
  11. static u64 readBits(const u64* data, size_t index, u64 bits) {
  12. u64 dataIndexA = (index * bits) >> DIVIDE_BITS;
  13. u64 dataIndexB = ((index * bits) + (bits - 1lu)) >> DIVIDE_BITS;
  14. u64 shifts = (index * bits) & (U64_BITS - 1lu);
  15. if(dataIndexA == dataIndexB) {
  16. return (data[dataIndexA] >> shifts) & ((1lu << bits) - 1lu);
  17. }
  18. u64 bitsInA = U64_BITS - shifts;
  19. u64 r = (data[dataIndexA] >> shifts) & ((1lu << bitsInA) - 1lu);
  20. r |= (data[dataIndexB] & ((1lu << (bits - bitsInA)) - 1lu)) << bitsInA;
  21. return r;
  22. }
  23. static void setBits(u64* data, size_t index, size_t bits, u64 value) {
  24. u64 mask = (1lu << bits) - 1lu;
  25. value &= mask;
  26. u64 dataIndexA = (index * bits) >> DIVIDE_BITS;
  27. u64 dataIndexB = ((index * bits) + (bits - 1lu)) >> DIVIDE_BITS;
  28. u64 shifts = (index * bits) & (U64_BITS - 1lu);
  29. data[dataIndexA] &= ~(mask << shifts);
  30. data[dataIndexA] |= (value << shifts);
  31. if(dataIndexA != dataIndexB) {
  32. u64 leftBits = bits - (U64_BITS - shifts);
  33. data[dataIndexB] &= ~((1lu << leftBits) - 1lu);
  34. data[dataIndexB] |= (value >> (U64_BITS - shifts));
  35. }
  36. }
  37. static size_t getArrayLength(size_t length, size_t bits) {
  38. return roundUpDivide(length * bits, U64_BITS);
  39. }
  40. void coreCopyBitArray(CoreBitArray* a, const CoreBitArray* other) {
  41. if(a == other) {
  42. return;
  43. }
  44. coreResizeBitArray(a, other->length, other->bits);
  45. size_t length = a->length;
  46. for(size_t i = 0; i < length; i++) {
  47. coreBitArraySet(a, i, coreBitArrayGet(other, i));
  48. }
  49. }
  50. void coreMoveBitArray(CoreBitArray* a, CoreBitArray* other) {
  51. if(a == other) {
  52. return;
  53. }
  54. coreSwapBitArray(a, other);
  55. coreDestroyBitArray(other);
  56. }
  57. void coreDestroyBitArray(CoreBitArray* a) {
  58. coreFree(a->data);
  59. *a = CORE_BIT_ARRAY;
  60. }
  61. CoreBitArray* coreBitArraySet(CoreBitArray* a, size_t index, u64 value) {
  62. assert(a->data != nullptr);
  63. assert(index < a->length);
  64. setBits(a->data, index, a->bits, value);
  65. return a;
  66. }
  67. u64 coreBitArrayGet(const CoreBitArray* a, size_t index) {
  68. assert(a->data != nullptr);
  69. assert(index < a->length);
  70. return readBits(a->data, index, a->bits);
  71. }
  72. size_t coreBitArrayBytes(const CoreBitArray* a) {
  73. if(a->length <= 0 || a->bits <= 0) {
  74. return 0;
  75. }
  76. return getArrayLength(a->length, a->bits) * sizeof(u64);
  77. }
  78. i64 coreBitArraySelect(const CoreBitArray* a, size_t index) {
  79. if(index <= 0) {
  80. return -1;
  81. }
  82. u64 found = 0;
  83. size_t end = getArrayLength(a->length, a->bits);
  84. for(size_t i = 0; i < end; i++) {
  85. u64 ones = corePopCount(a->data[i]);
  86. found += ones;
  87. if(found >= index) {
  88. found -= ones;
  89. u64 c = i * U64_BITS - 1;
  90. u64 d = a->data[i];
  91. while(found < index) {
  92. found += d & 1;
  93. d >>= 1;
  94. c++;
  95. }
  96. return (i64)c;
  97. }
  98. }
  99. return -1;
  100. }
  101. void coreResizeBitArray(CoreBitArray* a, size_t newLength, size_t newBits) {
  102. if(newLength == 0 || newBits == 0) {
  103. coreDestroyBitArray(a);
  104. return;
  105. } else if(newBits > 64) {
  106. newBits = 64;
  107. }
  108. size_t arrayLength = getArrayLength(newLength, newBits);
  109. u64* newData = coreAllocate(sizeof(u64) * arrayLength);
  110. memset(newData, 0, arrayLength * sizeof(u64));
  111. size_t end = coreMinSize(a->length, newLength);
  112. for(size_t i = 0; i < end; i++) {
  113. setBits(newData, i, newBits, coreBitArrayGet(a, i));
  114. }
  115. for(size_t i = end; i < newLength; i++) {
  116. setBits(newData, i, newBits, 0);
  117. }
  118. coreFree(a->data);
  119. a->data = newData;
  120. a->length = newLength & 0xFFFFFFFFFFFFFF;
  121. a->bits = newBits & 0xFF;
  122. }
  123. void coreFillBitArray(CoreBitArray* a, u64 value) {
  124. size_t length = a->length;
  125. for(size_t i = 0; i < length; i++) {
  126. coreBitArraySet(a, i, value);
  127. }
  128. }
  129. size_t coreToStringBitArray(const CoreBitArray* a, char* buffer, size_t n) {
  130. size_t w = 0;
  131. coreStringAddI(&w, &buffer, &n, snprintf(buffer, n, "["));
  132. size_t length = a->length;
  133. if(length > 0) {
  134. length--;
  135. for(size_t i = 0; i < length; i++) {
  136. coreStringAddI(&w, &buffer, &n,
  137. snprintf(buffer, n, "%lu, ", coreBitArrayGet(a, i)));
  138. }
  139. coreStringAddI(&w, &buffer, &n,
  140. snprintf(buffer, n, "%lu", coreBitArrayGet(a, length)));
  141. }
  142. coreStringAddI(&w, &buffer, &n, snprintf(buffer, n, "]"));
  143. return w;
  144. }
  145. void coreSwapBitArray(CoreBitArray* a, CoreBitArray* b) {
  146. CoreBitArray tmp = *a;
  147. *a = *b;
  148. *b = tmp;
  149. }