BitArray.h 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. #ifndef BITARRAY_H
  2. #define BITARRAY_H
  3. #include <iostream>
  4. template<int N, int BITS>
  5. class BitArray final {
  6. static constexpr int INT_BITS = sizeof (int) * 8;
  7. static_assert(BITS >= 1, "each bit array element must have at least one bit");
  8. static_assert(BITS <= INT_BITS, "each bit array element can have at most as much bits as an int");
  9. static constexpr int MASK = (1 << BITS) - 1;
  10. static constexpr int LENGTH = (N * BITS) / INT_BITS + (((N * BITS) % INT_BITS) > 0);
  11. static constexpr bool ALIGNED = (INT_BITS % BITS) == 0;
  12. constexpr static int getDivideBits() {
  13. int c = 0;
  14. int i = INT_BITS - 1;
  15. while(i > 0) {
  16. i >>= 1;
  17. c++;
  18. }
  19. return c;
  20. }
  21. static constexpr int DIVIDE_BITS = getDivideBits();
  22. int data[LENGTH];
  23. static int readBits(const int* data, int index) {
  24. int dataIndexA = (index * BITS) >> DIVIDE_BITS;
  25. int dataIndexB = ((index + 1) * BITS) >> DIVIDE_BITS;
  26. int shifts = (index * BITS) & (INT_BITS - 1);
  27. if(dataIndexA == dataIndexB || ALIGNED) {
  28. return (data[dataIndexA] >> shifts) & MASK;
  29. }
  30. int bitsInA = INT_BITS - shifts;
  31. int r = (data[dataIndexA] >> shifts) & ((1 << bitsInA) - 1);
  32. r |= (data[dataIndexB] & ((1 << (BITS - bitsInA)) - 1)) << bitsInA;
  33. return r;
  34. }
  35. public:
  36. class BitInt {
  37. friend BitArray;
  38. int* data;
  39. int index;
  40. BitInt(int* data, int index) : data(data), index(index) {
  41. }
  42. BitInt(const BitInt& other) = default;
  43. BitInt(BitInt&& other) = default;
  44. public:
  45. BitInt& operator=(const BitInt& other) {
  46. return (*this) = static_cast<int> (other);
  47. }
  48. BitInt& operator=(BitInt&& other) {
  49. return (*this) = static_cast<int> (other);
  50. }
  51. BitInt& operator=(int i) {
  52. i &= MASK;
  53. int dataIndexA = (index * BITS) >> DIVIDE_BITS;
  54. int dataIndexB = ((index + 1) * BITS) >> DIVIDE_BITS;
  55. int shifts = (index * BITS) & (INT_BITS - 1);
  56. data[dataIndexA] &= ~(MASK << shifts);
  57. data[dataIndexA] |= (i << shifts);
  58. if(dataIndexA != dataIndexB && !ALIGNED) {
  59. int leftBits = BITS - (INT_BITS - shifts);
  60. int mask = (1 << leftBits) - 1;
  61. data[dataIndexB] &= ~mask;
  62. data[dataIndexB] |= (i >> (INT_BITS - shifts));
  63. }
  64. return *this;
  65. }
  66. operator int() const {
  67. return readBits(data, index);
  68. }
  69. };
  70. BitArray(int bits = 0) {
  71. fill(bits);
  72. }
  73. void fill(int bits) {
  74. for(int i = 0; i < N; i++) {
  75. (*this)[i] = bits;
  76. }
  77. }
  78. BitInt operator[](int index) {
  79. return BitInt(data, index);
  80. }
  81. int operator[](int index) const {
  82. return readBits(data, index);
  83. }
  84. constexpr int getLength() const {
  85. return N;
  86. }
  87. };
  88. #endif