|
@@ -3,54 +3,58 @@
|
|
#include "core/math/Math.hpp"
|
|
#include "core/math/Math.hpp"
|
|
#include "core/utils/New.hpp"
|
|
#include "core/utils/New.hpp"
|
|
|
|
|
|
-static int roundUpDivide(int a, int b) {
|
|
+static u64 roundUpDivide(u64 a, u64 b) {
|
|
if(a % b == 0) {
|
|
if(a % b == 0) {
|
|
return a / b;
|
|
return a / b;
|
|
}
|
|
}
|
|
return a / b + 1;
|
|
return a / b + 1;
|
|
}
|
|
}
|
|
|
|
|
|
-static constexpr int INT_BITS = sizeof(int) * 8;
|
|
+static constexpr u64 U64_BITS = 64;
|
|
-static constexpr int DIVIDE_BITS = Core::Math::roundUpLog2(INT_BITS);
|
|
+static constexpr u64 DIVIDE_BITS = Core::Math::roundUpLog2(U64_BITS);
|
|
|
|
+static constexpr u64 LENGTH_MASK = 0x01FF'FFFF'FFFF'FFFF;
|
|
|
|
+static constexpr u64 LENGTH_BITS = Core::Math::roundUpLog2(LENGTH_MASK);
|
|
|
|
+static_assert(LENGTH_BITS == 57, "wusi");
|
|
|
|
|
|
-static int readBits(const int* data, int index, int bits) {
|
|
+static u64 readBits(const u64* data, u64 index, u64 bits) {
|
|
- int dataIndexA = (index * bits) >> DIVIDE_BITS;
|
|
+ u64 dataIndexA = (index * bits) >> DIVIDE_BITS;
|
|
- int dataIndexB = ((index * bits) + (bits - 1)) >> DIVIDE_BITS;
|
|
+ u64 dataIndexB = ((index * bits) + (bits - 1lu)) >> DIVIDE_BITS;
|
|
- int shifts = (index * bits) & (INT_BITS - 1);
|
|
+ u64 shifts = (index * bits) & (U64_BITS - 1lu);
|
|
if(dataIndexA == dataIndexB) {
|
|
if(dataIndexA == dataIndexB) {
|
|
- return (data[dataIndexA] >> shifts) & ((1 << bits) - 1);
|
|
+ return (data[dataIndexA] >> shifts) & ((1lu << bits) - 1lu);
|
|
}
|
|
}
|
|
- int bitsInA = INT_BITS - shifts;
|
|
+ u64 bitsInA = U64_BITS - shifts;
|
|
- int r = (data[dataIndexA] >> shifts) & ((1 << bitsInA) - 1);
|
|
+ u64 r = (data[dataIndexA] >> shifts) & ((1lu << bitsInA) - 1lu);
|
|
- r |= (data[dataIndexB] & ((1 << (bits - bitsInA)) - 1)) << bitsInA;
|
|
+ r |= (data[dataIndexB] & ((1lu << (bits - bitsInA)) - 1lu)) << bitsInA;
|
|
return r;
|
|
return r;
|
|
}
|
|
}
|
|
|
|
|
|
-static void setBits(int* data, int index, int bits, int value) {
|
|
+static void setBits(u64* data, u64 index, u64 bits, u64 value) {
|
|
- int mask = (1 << bits) - 1;
|
|
+ u64 mask = (1lu << bits) - 1lu;
|
|
value &= mask;
|
|
value &= mask;
|
|
- int dataIndexA = (index * bits) >> DIVIDE_BITS;
|
|
+ u64 dataIndexA = (index * bits) >> DIVIDE_BITS;
|
|
- int dataIndexB = ((index * bits) + (bits - 1)) >> DIVIDE_BITS;
|
|
+ u64 dataIndexB = ((index * bits) + (bits - 1lu)) >> DIVIDE_BITS;
|
|
- int shifts = (index * bits) & (INT_BITS - 1);
|
|
+ u64 shifts = (index * bits) & (U64_BITS - 1lu);
|
|
data[dataIndexA] &= ~(mask << shifts);
|
|
data[dataIndexA] &= ~(mask << shifts);
|
|
data[dataIndexA] |= (value << shifts);
|
|
data[dataIndexA] |= (value << shifts);
|
|
if(dataIndexA != dataIndexB) {
|
|
if(dataIndexA != dataIndexB) {
|
|
- int leftBits = bits - (INT_BITS - shifts);
|
|
+ u64 leftBits = bits - (U64_BITS - shifts);
|
|
- data[dataIndexB] &= ~((1 << leftBits) - 1);
|
|
+ data[dataIndexB] &= ~((1lu << leftBits) - 1lu);
|
|
- data[dataIndexB] |= (value >> (INT_BITS - shifts));
|
|
+ data[dataIndexB] |= (value >> (U64_BITS - shifts));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-static int getArrayLength(int length, int bits) {
|
|
+static u64 getArrayLength(u64 length, u64 bits) {
|
|
- return roundUpDivide(length * bits, INT_BITS);
|
|
+ return roundUpDivide(length * bits, U64_BITS);
|
|
}
|
|
}
|
|
|
|
|
|
-Core::BitArray::BitArray() : length(0), bits(0), data(nullptr) {
|
|
+Core::BitArray::BitArray() : lengthBits(0), data(nullptr) {
|
|
}
|
|
}
|
|
|
|
|
|
check_return Core::Error Core::BitArray::copyFrom(const BitArray& other) {
|
|
check_return Core::Error Core::BitArray::copyFrom(const BitArray& other) {
|
|
- CORE_RETURN_ERROR(resize(other.length, other.bits));
|
|
+ CORE_RETURN_ERROR(resize(other.getLength(), other.getBits()));
|
|
- for(int i = 0; i < length; i++) {
|
|
+ u64 length = getLength();
|
|
|
|
+ for(u64 i = 0; i < length; i++) {
|
|
set(i, other.get(i));
|
|
set(i, other.get(i));
|
|
}
|
|
}
|
|
return Error::NONE;
|
|
return Error::NONE;
|
|
@@ -69,93 +73,92 @@ Core::BitArray& Core::BitArray::operator=(BitArray&& other) {
|
|
return *this;
|
|
return *this;
|
|
}
|
|
}
|
|
|
|
|
|
-Core::BitArray& Core::BitArray::set(int index, int value) {
|
|
+Core::BitArray& Core::BitArray::set(u64 index, u64 value) {
|
|
- if(data == nullptr || index < 0 || index >= length) {
|
|
+ if(data == nullptr || index >= getLength()) {
|
|
return *this;
|
|
return *this;
|
|
}
|
|
}
|
|
- setBits(data, index, bits, value);
|
|
+ setBits(data, index, getBits(), value);
|
|
return *this;
|
|
return *this;
|
|
}
|
|
}
|
|
|
|
|
|
-int Core::BitArray::get(int index) const {
|
|
+u64 Core::BitArray::get(u64 index) const {
|
|
- if(data == nullptr || index < 0 || index >= length) {
|
|
+ if(data == nullptr || index >= getLength()) {
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
- return readBits(data, index, bits);
|
|
+ return readBits(data, index, getBits());
|
|
}
|
|
}
|
|
|
|
|
|
-int Core::BitArray::getLength() const {
|
|
+u64 Core::BitArray::getLength() const {
|
|
- return length;
|
|
+ return lengthBits & LENGTH_MASK;
|
|
}
|
|
}
|
|
|
|
|
|
-int Core::BitArray::getBits() const {
|
|
+u64 Core::BitArray::getBits() const {
|
|
- return bits;
|
|
+ return (lengthBits & ~LENGTH_MASK) >> LENGTH_BITS;
|
|
}
|
|
}
|
|
|
|
|
|
-int Core::BitArray::getInternalByteSize() const {
|
|
+u64 Core::BitArray::getInternalByteSize() const {
|
|
- if(bits <= 0 || length <= 0) {
|
|
+ if(getLength() <= 0 || getBits() <= 0) {
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
- return getArrayLength(length, bits) * CORE_SIZE(int);
|
|
+ return getArrayLength(getLength(), getBits()) * CORE_SIZE(u64);
|
|
}
|
|
}
|
|
|
|
|
|
-int Core::BitArray::select(int index) const {
|
|
+i64 Core::BitArray::select(u64 index) const {
|
|
if(index <= 0) {
|
|
if(index <= 0) {
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
- int found = 0;
|
|
+ u64 found = 0;
|
|
- int end = getArrayLength(length, bits);
|
|
+ u64 end = getArrayLength(getLength(), getBits());
|
|
- for(int i = 0; i < end; i++) {
|
|
+ for(u64 i = 0; i < end; i++) {
|
|
- int ones = Core::popCount(data[i]);
|
|
+ u64 ones = Core::popCount<u64, u64>(data[i]);
|
|
found += ones;
|
|
found += ones;
|
|
if(found >= index) {
|
|
if(found >= index) {
|
|
found -= ones;
|
|
found -= ones;
|
|
- int a = i * 32 - 1;
|
|
+ u64 a = i * U64_BITS - 1;
|
|
- int d = data[i];
|
|
+ u64 d = data[i];
|
|
while(found < index) {
|
|
while(found < index) {
|
|
found += d & 1;
|
|
found += d & 1;
|
|
d >>= 1;
|
|
d >>= 1;
|
|
a++;
|
|
a++;
|
|
}
|
|
}
|
|
- return a;
|
|
+ return static_cast<i64>(a);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
-void Core::BitArray::fill(int value) {
|
|
+void Core::BitArray::fill(u64 value) {
|
|
- for(int i = 0; i < length; i++) {
|
|
+ u64 length = getLength();
|
|
|
|
+ for(u64 i = 0; i < length; i++) {
|
|
set(i, value);
|
|
set(i, value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-check_return Core::Error Core::BitArray::resize(int newLength, int newBits) {
|
|
+check_return Core::Error Core::BitArray::resize(u64 newLength, u64 newBits) {
|
|
- if(newLength <= 0 || newBits <= 0) {
|
|
+ if(newLength == 0 || newBits == 0 || newBits > 64) {
|
|
- return Error::NEGATIVE_ARGUMENT;
|
|
+ return Error::INVALID_ARGUMENT;
|
|
}
|
|
}
|
|
- int arrayLength = getArrayLength(newLength, newBits);
|
|
+ u64 arrayLength = getArrayLength(newLength, newBits);
|
|
- int* newData = new int[arrayLength];
|
|
+ u64* newData = new u64[arrayLength];
|
|
if(newData == nullptr) {
|
|
if(newData == nullptr) {
|
|
return Error::OUT_OF_MEMORY;
|
|
return Error::OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
- Core::memorySet(newData, 0, arrayLength * CORE_SIZE(int));
|
|
+ Core::memorySet(newData, 0, static_cast<i64>(arrayLength) * CORE_SIZE(int));
|
|
|
|
|
|
- int end = Math::min(length, newLength);
|
|
+ u64 end = Math::min(getLength(), newLength);
|
|
- for(int i = 0; i < end; i++) {
|
|
+ for(u64 i = 0; i < end; i++) {
|
|
setBits(newData, i, newBits, get(i));
|
|
setBits(newData, i, newBits, get(i));
|
|
}
|
|
}
|
|
- for(int i = end; i < newLength; i++) {
|
|
+ for(u64 i = end; i < newLength; i++) {
|
|
setBits(newData, i, newBits, 0);
|
|
setBits(newData, i, newBits, 0);
|
|
}
|
|
}
|
|
delete[] data;
|
|
delete[] data;
|
|
data = newData;
|
|
data = newData;
|
|
- bits = newBits;
|
|
+ lengthBits = newLength | (newBits << LENGTH_BITS);
|
|
- length = newLength;
|
|
|
|
return Error::NONE;
|
|
return Error::NONE;
|
|
}
|
|
}
|
|
|
|
|
|
void Core::BitArray::swap(BitArray& other) {
|
|
void Core::BitArray::swap(BitArray& other) {
|
|
- Core::swap(length, other.length);
|
|
+ Core::swap(lengthBits, other.lengthBits);
|
|
- Core::swap(bits, other.bits);
|
|
|
|
Core::swap(data, other.data);
|
|
Core::swap(data, other.data);
|
|
}
|
|
}
|