diff options
author | Yuri Gorshenin <y@maps.me> | 2015-09-02 15:44:15 +0300 |
---|---|---|
committer | Sergey Yershov <yershov@corp.mail.ru> | 2016-03-23 16:02:12 +0300 |
commit | b4bd3a3e802fc25665b7cbcb2a2af2d45b79913c (patch) | |
tree | 97de276e0c92ae9a36984dfcf747a0e36457ca10 /coding/simple_dense_coding.cpp | |
parent | 122fdfda89f513028bf5636b3c6812dbc530aced (diff) |
Review fixes.
Diffstat (limited to 'coding/simple_dense_coding.cpp')
-rw-r--r-- | coding/simple_dense_coding.cpp | 84 |
1 files changed, 43 insertions, 41 deletions
diff --git a/coding/simple_dense_coding.cpp b/coding/simple_dense_coding.cpp index f2e4acfb95..03d88f1b8a 100644 --- a/coding/simple_dense_coding.cpp +++ b/coding/simple_dense_coding.cpp @@ -9,6 +9,8 @@ namespace coding { namespace { +size_t const kAlphabetSize = static_cast<size_t>(numeric_limits<uint8_t>::max()) + 1; + struct Code { Code() : m_code(0), m_length(0) {} @@ -17,42 +19,44 @@ struct Code uint8_t m_length; }; -size_t const kAlphabetSize = static_cast<size_t>(numeric_limits<uint8_t>::max()) + 1; -Code g_codeTable[kAlphabetSize]; -bool g_codeTableInitialized = false; - -// Returns pointer to an initialized code table. If necessary, -// initializes it. In the latter case, code table is filled with -// following code words: 0, 1, 00, 01, 10, 11, 000, 001, ... -Code const * GetCodeTable() +// Initializes code table for simple dense coding with following code +// words: 0, 1, 00, 01, 10, 11, 000, 001, ... +struct CodeTable { - if (g_codeTableInitialized) - return g_codeTable; - - unsigned length = 1; - size_t rank = 0; - while (rank < kAlphabetSize) +public: + CodeTable() { - // Number of codes with the same bit length. - size_t const numCodes = static_cast<size_t>(1) << length; - - size_t base = rank; - while (rank - base < numCodes && rank < kAlphabetSize) + size_t rank = 0; + uint8_t length = 1; + while (rank < kAlphabetSize) { - g_codeTable[rank].m_code = rank - base; - g_codeTable[rank].m_length = length; - ++rank; + // Number of codes with the same bit length. + size_t const numCodes = static_cast<size_t>(1) << length; + + uint8_t code = 0; + for (; code < numCodes && rank + code < kAlphabetSize; ++code) + { + size_t const pos = rank + code; + m_table[pos].m_code = code; + m_table[pos].m_length = length; + } + + rank += code; + length += 1; } + } - ++length; + inline Code const & GetCode(uint8_t rank) const + { + return m_table[rank]; } - g_codeTableInitialized = true; - return g_codeTable; -} +private: + Code m_table[kAlphabetSize]; +}; -// Computes frequences for data symbols. -void GetFrequences(vector<uint8_t> const & data, uint64_t frequency[]) +// Calculates frequences for data symbols. +void CalcFrequences(vector<uint8_t> const & data, uint64_t frequency[]) { memset(frequency, 0, sizeof(*frequency) * kAlphabetSize); for (uint8_t symbol : data) @@ -62,8 +66,11 @@ void GetFrequences(vector<uint8_t> const & data, uint64_t frequency[]) SimpleDenseCoding::SimpleDenseCoding(vector<uint8_t> const & data) { + // This static initialization isn't thread safe prior to C++11. + static CodeTable codeTable; + uint64_t frequency[kAlphabetSize]; // Maps symbols to frequences. - GetFrequences(data, frequency); + CalcFrequences(data, frequency); uint8_t symbols[kAlphabetSize]; // Maps ranks to symbols. uint8_t rank[kAlphabetSize]; // Maps symbols to ranks. @@ -77,27 +84,22 @@ SimpleDenseCoding::SimpleDenseCoding(vector<uint8_t> const & data) for (size_t r = 0; r < kAlphabetSize; ++r) rank[symbols[r]] = r; - Code const * codeTable = GetCodeTable(); - ASSERT(codeTable, ()); - uint64_t bitLength = 0; for (size_t symbol = 0; symbol < kAlphabetSize; ++symbol) - bitLength += static_cast<uint64_t>(frequency[symbol]) * codeTable[rank[symbol]].m_length; + bitLength += frequency[symbol] * codeTable.GetCode(rank[symbol]).m_length; succinct::bit_vector_builder bitsBuilder; bitsBuilder.reserve(bitLength); vector<bool> indexBuilder(bitLength); size_t pos = 0; + for (uint8_t symbol : data) { - for (uint8_t symbol : data) - { - Code const & code = codeTable[rank[symbol]]; - ASSERT_LESS(pos, bitLength, ()); - indexBuilder[pos] = 1; + Code const & code = codeTable.GetCode(rank[symbol]); + ASSERT_LESS(pos, bitLength, ()); + indexBuilder[pos] = 1; - bitsBuilder.append_bits(code.m_code, code.m_length); - pos += code.m_length; - } + bitsBuilder.append_bits(code.m_code, code.m_length); + pos += code.m_length; } ASSERT_EQUAL(pos, bitLength, ()); |