|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef moses_PackedArray_h |
|
#define moses_PackedArray_h |
|
|
|
#include <vector> |
|
#include <cmath> |
|
#include <cstring> |
|
#include <cstdio> |
|
|
|
#include "ThrowingFwrite.h" |
|
|
|
namespace Moses |
|
{ |
|
|
|
template <typename T = size_t, typename D = unsigned char> |
|
class PackedArray |
|
{ |
|
protected: |
|
static size_t m_dataBits; |
|
|
|
size_t m_size; |
|
size_t m_storageSize; |
|
D* m_storage; |
|
|
|
public: |
|
PackedArray() { |
|
m_size = 0; |
|
m_storageSize = 0; |
|
m_storage = new D[0]; |
|
} |
|
|
|
PackedArray(size_t size, size_t bits) : m_size(size) { |
|
m_storageSize = ceil(float(bits * size) / float(m_dataBits)); |
|
m_storage = new D[m_storageSize]; |
|
} |
|
|
|
PackedArray(const PackedArray<T, D> &c) { |
|
m_size = c.m_size; |
|
|
|
m_storageSize = c.m_storageSize; |
|
m_storage = new D[m_storageSize]; |
|
|
|
std::memcpy(m_storage, c.m_storage, m_storageSize * sizeof(D)); |
|
} |
|
|
|
virtual ~PackedArray() { |
|
delete [] m_storage; |
|
m_size = 0; |
|
m_storageSize = 0; |
|
m_storage = 0; |
|
} |
|
|
|
T Get(size_t i, size_t bits) const { |
|
T out = 0; |
|
|
|
size_t bitstart = (i * bits); |
|
size_t bitpos = bitstart; |
|
|
|
size_t zero = ((1ul << (bits)) - 1); |
|
|
|
while(bitpos - bitstart < bits) { |
|
size_t pos = bitpos / m_dataBits; |
|
size_t off = bitpos % m_dataBits; |
|
|
|
out |= (T(m_storage[pos]) << (bitpos - bitstart)) >> off; |
|
|
|
bitpos += (m_dataBits - off); |
|
} |
|
|
|
out &= zero; |
|
return out; |
|
} |
|
|
|
void Set(size_t i, T v, size_t bits) { |
|
size_t bitstart = (i * bits); |
|
size_t bitpos = bitstart; |
|
|
|
while(bitpos - bitstart < bits) { |
|
size_t pos = bitpos / m_dataBits; |
|
size_t off = bitpos % m_dataBits; |
|
|
|
size_t rest = bits - (bitpos - bitstart); |
|
D zero = ~((1ul << (rest + off)) - 1) | ((1ul << off) - 1); |
|
|
|
m_storage[pos] &= zero; |
|
m_storage[pos] |= v << off; |
|
v = v >> (m_dataBits - off); |
|
bitpos += (m_dataBits - off); |
|
} |
|
} |
|
|
|
virtual D*& GetStorage() { |
|
return m_storage; |
|
} |
|
|
|
virtual size_t GetStorageSize() const { |
|
return m_storageSize; |
|
} |
|
|
|
virtual size_t Size() const { |
|
return m_size; |
|
} |
|
|
|
virtual size_t Load(std::FILE* in) { |
|
size_t a1 = std::ftell(in); |
|
|
|
size_t read = 0; |
|
read += std::fread(&m_size, sizeof(m_size), 1, in); |
|
read += std::fread(&m_storageSize, sizeof(m_storageSize), 1, in); |
|
delete [] m_storage; |
|
m_storage = new D[m_storageSize]; |
|
read += std::fread(m_storage, sizeof(D), m_storageSize, in); |
|
|
|
size_t a2 = std::ftell(in); |
|
return a2 - a1; |
|
} |
|
|
|
virtual size_t Save(std::FILE* out) { |
|
size_t a1 = std::ftell(out); |
|
|
|
ThrowingFwrite(&m_size, sizeof(m_size), 1, out); |
|
ThrowingFwrite(&m_storageSize, sizeof(m_storageSize), 1, out); |
|
ThrowingFwrite(m_storage, sizeof(D), m_storageSize, out); |
|
|
|
size_t a2 = std::ftell(out); |
|
return a2 - a1; |
|
} |
|
|
|
}; |
|
|
|
template <typename T, typename D> |
|
size_t PackedArray<T, D>::m_dataBits = sizeof(D)*8; |
|
|
|
|
|
|
|
template <typename T = size_t, typename D = unsigned char> |
|
class PairedPackedArray : public PackedArray<T,D> |
|
{ |
|
public: |
|
PairedPackedArray() : PackedArray<T,D>() {} |
|
|
|
PairedPackedArray(size_t size, size_t bits1, size_t bits2) |
|
: PackedArray<T, D>(size, bits1 + bits2) { } |
|
|
|
void Set(size_t i, T a, T b, size_t bits1, size_t bits2) { |
|
T c = 0; |
|
c = a | (b << bits1); |
|
PackedArray<T,D>::Set(i, c, bits1 + bits2); |
|
} |
|
|
|
void Set(size_t i, std::pair<T,T> p, size_t bits1, size_t bits2) { |
|
T c = 0; |
|
c = p.second | (p.first << bits1); |
|
PackedArray<T, D>::Set(i, c); |
|
} |
|
|
|
std::pair<T, T> Get(size_t i, size_t bits1, size_t bits2) { |
|
T v = PackedArray<T, D>::Get(i, bits1 + bits2); |
|
T a = v & ((1 << bits1) - 1); |
|
T b = v >> bits1; |
|
return std::pair<T, T>(a, b); |
|
} |
|
}; |
|
|
|
} |
|
|
|
#endif |
|
|