Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Using FastAC by Amir Said -- http://www.cipr.rpi.edu/research/SPIHT/EW_Code/FastAC.zip
- #include "arithmetic_codec.h"
- #include <boost/random/mersenne_twister.hpp>
- #include <boost/random/laplace_distribution.hpp>
- #include <vector>
- std::size_t const N_VAL(1 << 20);
- // ============================================================================
- // Generate some random data with distribution similar to what's in the question
- std::vector<int32_t> gen_data(std::size_t n)
- {
- boost::random::mt19937 rng;
- boost::random::laplace_distribution<> dist(0, 20);
- std::vector<int32_t> data;
- data.reserve(n);
- for (; data.size() < n;) {
- int32_t v = static_cast<int32_t>(std::round(dist(rng)));
- if ((v >= -256) && (v <= 255)) {
- data.push_back(v);
- }
- }
- return data;
- }
- // ============================================================================
- // Ziz-Zag Coding
- //
- // Maps signed integers into unsigned integers
- // 0 => 0, -1 => 1, 1 => 2, -2 => 3, 2 => 4 ...
- uint32_t zigzag_encode(int32_t v)
- {
- return static_cast<uint32_t>((v >> 31) ^ (v << 1));
- }
- std::vector<uint32_t> zigzag_encode(std::vector<int32_t> const& data)
- {
- std::vector<uint32_t> result(data.size());
- std::transform(data.begin(), data.end(), result.begin(),
- [](int32_t v) -> uint32_t { return zigzag_encode(v); });
- return result;
- }
- int32_t zigzag_decode(uint32_t v)
- {
- return (static_cast<int32_t>(v) >> 1) ^ -(static_cast<int32_t>(v)& 1);
- }
- std::vector<int32_t> zigzag_decode(std::vector<uint32_t> const& data)
- {
- std::vector<int32_t> result(data.size());
- std::transform(data.begin(), data.end(), result.begin(),
- [](uint32_t v) -> int32_t { return zigzag_decode(v); });
- return result;
- }
- // ============================================================================
- // Simple approach with 1 adaptive model for 512 symbols
- // Processes zig-zag coded 9-bit values
- template<typename ModelT, typename CodecT = Arithmetic_Codec>
- uint32_t encode(std::vector<uint32_t> const& buffer
- , ModelT& model
- , CodecT& encoder)
- {
- encoder.start_encoder();
- for (uint32_t v : buffer) {
- encoder.encode(v, model);
- }
- return 8 * encoder.stop_encoder();
- }
- template<typename ModelT, typename CodecT = Arithmetic_Codec>
- void decode(std::vector<uint32_t>& buffer
- , ModelT& model
- , CodecT& decoder)
- {
- decoder.start_decoder();
- for (uint32_t i(0); i < buffer.size(); ++i) {
- buffer[i] = decoder.decode(model);
- }
- decoder.stop_decoder();
- }
- void test_simple(std::vector<uint32_t> const& zdata)
- {
- Arithmetic_Codec codec(N_VAL * 2);
- Adaptive_Data_Model adaptive_model(512);
- std::size_t raw_size_bits(N_VAL * 9);
- std::size_t packed_size_bits(encode(zdata, adaptive_model, codec));
- double ratio(double(packed_size_bits) / raw_size_bits * 100);
- std::cout << "Ratio = " << ratio << " %\n";
- std::vector<uint32_t> dzdata(N_VAL);
- adaptive_model.reset();
- decode(dzdata, adaptive_model, codec);
- std::cout << "Match = " << ((zdata == dzdata) ? "true" : "false") << "\n";
- }
- // ============================================================================
- // Split approach with 3 adaptive models (1*2 and 2*256 symbols)
- // Processes zig-zag coded 9-bit values
- //
- // First the MSB is coded using the 2 symbol model_msb
- // If MSB == 0 then LSB is coded using the 256 symbold model_lsb0
- // If MSB == 1 then LSB is coded using the 256 symbold model_lsb1
- template<typename ModelT, typename CodecT = Arithmetic_Codec>
- uint32_t encode(std::vector<uint32_t> const& buffer
- , ModelT& model_msb
- , ModelT& model_lsb0
- , ModelT& model_lsb1
- , CodecT& encoder)
- {
- encoder.start_encoder();
- for (uint32_t v : buffer) {
- uint32_t msb(v >> 8);
- uint32_t lsb(v & 0xFF);
- encoder.encode(msb, model_msb);
- if (msb == 0) {
- encoder.encode(lsb, model_lsb0);
- } else {
- encoder.encode(lsb, model_lsb1);
- }
- }
- return 8 * encoder.stop_encoder();
- }
- template<typename ModelT, typename CodecT = Arithmetic_Codec>
- void decode(std::vector<uint32_t>& buffer
- , ModelT& model_msb
- , ModelT& model_lsb0
- , ModelT& model_lsb1
- , CodecT& decoder)
- {
- decoder.start_decoder();
- for (uint32_t i(0); i < buffer.size(); ++i) {
- uint32_t msb(decoder.decode(model_msb));
- uint32_t lsb;
- if (msb == 0) {
- lsb = decoder.decode(model_lsb0);
- } else {
- lsb = decoder.decode(model_lsb1);
- }
- buffer[i] = (msb << 8) | lsb;
- }
- decoder.stop_decoder();
- }
- void test_split(std::vector<uint32_t> const& zdata)
- {
- Arithmetic_Codec codec(N_VAL * 2);
- Adaptive_Data_Model adaptive_model_msb(2);
- Adaptive_Data_Model adaptive_model_lsb0(256);
- Adaptive_Data_Model adaptive_model_lsb1(256);
- std::size_t raw_size_bits(N_VAL * 9);
- std::size_t packed_size_bits(encode(zdata, adaptive_model_msb
- , adaptive_model_lsb0, adaptive_model_lsb1, codec));
- double ratio(double(packed_size_bits) / raw_size_bits * 100);
- std::cout << "Ratio = " << ratio << " %\n";
- std::vector<uint32_t> dzdata(N_VAL);
- adaptive_model_msb.reset();
- adaptive_model_lsb0.reset();
- adaptive_model_lsb1.reset();
- decode(dzdata, adaptive_model_msb
- , adaptive_model_lsb0, adaptive_model_lsb1, codec);
- std::cout << "Match = " << ((zdata == dzdata) ? "true" : "false") << "\n";
- }
- // ============================================================================
- // PN approach with 3 adaptive models (1*2 and 2*256 symbols)
- // Processes signed 9-bit values
- //
- // First the sign is coded using the 2 symbol model_sign
- // If sign positive then abs value is coded using the 256 symbol model_valuep
- // If sign negative then abs value - 1 is coded using the 256 symbol model_valuen
- template<typename ModelT, typename CodecT = Arithmetic_Codec>
- uint32_t encode(std::vector<int32_t> const& buffer
- , ModelT& model_sign
- , ModelT& model_valuep
- , ModelT& model_valuen
- , CodecT& encoder)
- {
- encoder.start_encoder();
- for (int32_t v : buffer) {
- uint32_t sign, value;
- if (v >= 0) {
- sign = 0;
- value = v;
- } else {
- sign = 1;
- value = std::abs(v) - 1;
- }
- encoder.encode(sign, model_sign);
- if (sign == 0) {
- encoder.encode(value, model_valuep);
- } else {
- encoder.encode(value, model_valuen);
- }
- }
- return 8 * encoder.stop_encoder();
- }
- template<typename ModelT, typename CodecT = Arithmetic_Codec>
- void decode(std::vector<int32_t>& buffer
- , ModelT& model_sign
- , ModelT& model_valuep
- , ModelT& model_valuen
- , CodecT& decoder)
- {
- decoder.start_decoder();
- for (uint32_t i(0); i < buffer.size(); ++i) {
- uint32_t sign(decoder.decode(model_sign));
- int32_t value;
- if (sign == 0) {
- value = decoder.decode(model_valuep);
- buffer[i] = value;
- } else {
- value = decoder.decode(model_valuen);
- buffer[i] = -(value + 1);
- }
- }
- decoder.stop_decoder();
- }
- void test_split_pn(std::vector<int32_t> const& data)
- {
- Arithmetic_Codec codec(N_VAL * 2);
- Adaptive_Data_Model adaptive_model_sign(2);
- Adaptive_Data_Model adaptive_model_valuep(256);
- Adaptive_Data_Model adaptive_model_valuen(256);
- std::size_t raw_size_bits(N_VAL * 9);
- std::size_t packed_size_bits(encode(data, adaptive_model_sign
- , adaptive_model_valuep, adaptive_model_valuen, codec));
- double ratio(double(packed_size_bits) / raw_size_bits * 100);
- std::cout << "Ratio = " << ratio << " %\n";
- std::vector<int32_t> ddata(N_VAL);
- adaptive_model_sign.reset();
- adaptive_model_valuep.reset();
- adaptive_model_valuen.reset();
- decode(ddata, adaptive_model_sign
- , adaptive_model_valuep, adaptive_model_valuen, codec);
- std::cout << "Match = " << ((data == ddata) ? "true" : "false") << "\n";
- }
- // ============================================================================
- int main()
- {
- std::vector<int32_t> data(gen_data(N_VAL));
- std::vector<uint32_t> zdata(zigzag_encode(data));
- test_simple(zdata);
- test_split(zdata);
- test_split_pn(data);
- return 0;
- }
- // ============================================================================
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement