| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #ifndef moses_PackedArray_h |
| #define moses_PackedArray_h |
|
|
| #include <vector> |
| #include <cmath> |
| #include <cstring> |
| #include <cstdio> |
|
|
| #include "ThrowingFwrite.h" |
|
|
| namespace Moses2 |
| { |
|
|
| 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 |
|
|