Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uint template #202

Merged
merged 16 commits into from
May 24, 2023
21 changes: 18 additions & 3 deletions include/Bitmask.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ namespace sperr {
class Bitmask {
public:
// Constructor
//
Bitmask(size_t nbits = 0); // How many bits does it hold initially?

// Functions for both read and write
//
auto size() const -> size_t;
void resize(size_t nbits); // Resize to hold n bits.
void reset(); // Set the current bitmask to be all 0s.
auto size() const -> size_t; // Num. of useful bits in this mask.
void resize(size_t nbits); // Resize to hold n bits.
void reset(); // Set the current bitmask to be all 0's.
void reset_true(); // Set the current bitmask to be all 1's.

// Functions for read
//
Expand All @@ -43,6 +45,19 @@ class Bitmask {
void write_long(size_t idx, uint64_t value);
void write_bit(size_t idx, bool bit);

// Functions for direct access of the underlying data buffer
// Note: `use_bitstream()` reads the number of values (uint64_t type) that provide
// enough bits for the specified size of this mask.
//
auto view_buffer() const -> const std::vector<uint64_t>&;
void use_bitstream(const void* p);

// Compare if two Bitmasks are identical.
//
#if __cplusplus >= 202002L
auto operator==(const Bitmask& rhs) const -> bool = default;
#endif

private:
std::vector<uint64_t> m_buf;
size_t m_num_bits = 0;
Expand Down
5 changes: 4 additions & 1 deletion include/Bitstream.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@
* 3. Because of 2, true random writes is not possible; it's only possible at the end of
* each word, e.g., positions of 63, 127, 191.
* 4. A function call of flush() will align the writing position to the beginning of the
* next word.
* next word, i.e., the number of truly useful bits is lost!
* One wants to call wtell() to retrieve and keep that info.
* 5. Functions write_bitstream() and parse_bitstream() take in a raw pointer and the
* number of bits to write/read. The memory pointed to by the raw pointer needs to
* be big enough to hold the number of bits specified.
* 6. get_bitstream() and write_bitstream() needs to be supplied a number of bits because
* a Bitstream itself will lose track of how many useful bits are there after flush().
*/

#include <cstddef>
Expand Down
10 changes: 9 additions & 1 deletion include/SPECK1D_INT.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,20 @@ class Set1D {
//
// Main SPECK1D_INT class; intended to be the base class of both encoder and decoder.
//
class SPECK1D_INT : public SPECK_INT {
template <typename T>
class SPECK1D_INT : public SPECK_INT<T> {
public:
// Virtual destructor
virtual ~SPECK1D_INT() = default;

protected:
//
// Bring members from the base class to this derived class.
//
using SPECK_INT<T>::m_LIP;
using SPECK_INT<T>::m_dims;
using SPECK_INT<T>::m_u64_garbage_val;

virtual void m_clean_LIS() override;
virtual void m_initialize_lists() override;
auto m_partition_set(const Set1D&) const -> std::array<Set1D, 2>;
Expand Down
17 changes: 16 additions & 1 deletion include/SPECK1D_INT_DEC.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,23 @@ namespace sperr {
//
// Main SPECK1D_INT_DEC class
//
class SPECK1D_INT_DEC : public SPECK1D_INT {
template <typename T>
class SPECK1D_INT_DEC : public SPECK1D_INT<T> {
private:
//
// Bring members from parent classes to this derived class.
//
using SPECK_INT<T>::m_LIP;
using SPECK_INT<T>::m_LSP_new;
using SPECK_INT<T>::m_bit_idx;
using SPECK_INT<T>::m_threshold;
using SPECK_INT<T>::m_coeff_buf;
using SPECK_INT<T>::m_bit_buffer;
using SPECK_INT<T>::m_sign_array;
using SPECK_INT<T>::m_u64_garbage_val;
using SPECK1D_INT<T>::m_LIS;
using SPECK1D_INT<T>::m_partition_set;

virtual void m_sorting_pass() override;

void m_process_S(size_t idx1, size_t idx2, size_t& counter, bool read);
Expand Down
16 changes: 15 additions & 1 deletion include/SPECK1D_INT_ENC.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,22 @@ namespace sperr {
//
// Main SPECK1D_INT_ENC class
//
class SPECK1D_INT_ENC : public SPECK1D_INT {
template <typename T>
class SPECK1D_INT_ENC : public SPECK1D_INT<T> {
private:
//
// Bring members from parent classes to this derived class.
//
using SPECK_INT<T>::m_LIP;
using SPECK_INT<T>::m_LSP_new;
using SPECK_INT<T>::m_threshold;
using SPECK_INT<T>::m_coeff_buf;
using SPECK_INT<T>::m_bit_buffer;
using SPECK_INT<T>::m_sign_array;
using SPECK_INT<T>::m_u64_garbage_val;
using SPECK1D_INT<T>::m_LIS;
using SPECK1D_INT<T>::m_partition_set;

virtual void m_sorting_pass() override;

void m_process_S(size_t idx1, size_t idx2, SigType, size_t& counter, bool);
Expand Down
13 changes: 12 additions & 1 deletion include/SPECK3D_INT.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,23 @@ class Set3D {
//
// Main SPECK3D_INT class; intended to be the base class of both encoder and decoder.
//
class SPECK3D_INT : public SPECK_INT {
template <typename T>
class SPECK3D_INT : public SPECK_INT<T> {
public:
// Virtual destructor
virtual ~SPECK3D_INT() = default;

protected:
//
// Bring members from the base class to this derived class.
//
using SPECK_INT<T>::m_LIP;
using SPECK_INT<T>::m_dims;
using SPECK_INT<T>::m_LSP_new;
using SPECK_INT<T>::m_coeff_buf;
using SPECK_INT<T>::m_bit_buffer;
using SPECK_INT<T>::m_u64_garbage_val;

virtual void m_clean_LIS() override;
virtual void m_initialize_lists() override;

Expand Down
18 changes: 17 additions & 1 deletion include/SPECK3D_INT_DEC.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,24 @@ namespace sperr {
//
// Main SPECK3D_INT_DEC class
//
class SPECK3D_INT_DEC : public SPECK3D_INT {
template <typename T>
class SPECK3D_INT_DEC : public SPECK3D_INT<T> {
private:
//
// Bring members from parent classes to this derived class.
//
using SPECK_INT<T>::m_LIP;
using SPECK_INT<T>::m_dims;
using SPECK_INT<T>::m_LSP_new;
using SPECK_INT<T>::m_bit_idx;
using SPECK_INT<T>::m_threshold;
using SPECK_INT<T>::m_coeff_buf;
using SPECK_INT<T>::m_bit_buffer;
using SPECK_INT<T>::m_sign_array;
using SPECK_INT<T>::m_u64_garbage_val;
using SPECK3D_INT<T>::m_LIS;
using SPECK3D_INT<T>::m_partition_S_XYZ;

virtual void m_sorting_pass() override;

void m_process_S(size_t idx1, size_t idx2, size_t& counter, bool);
Expand Down
17 changes: 16 additions & 1 deletion include/SPECK3D_INT_ENC.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,23 @@ namespace sperr {
//
// Main SPECK3D_INT_ENC class
//
class SPECK3D_INT_ENC : public SPECK3D_INT {
template <typename T>
class SPECK3D_INT_ENC : public SPECK3D_INT<T> {
private:
//
// Bring members from parent classes to this derived class.
//
using SPECK_INT<T>::m_LIP;
using SPECK_INT<T>::m_dims;
using SPECK_INT<T>::m_LSP_new;
using SPECK_INT<T>::m_threshold;
using SPECK_INT<T>::m_coeff_buf;
using SPECK_INT<T>::m_bit_buffer;
using SPECK_INT<T>::m_sign_array;
using SPECK_INT<T>::m_u64_garbage_val;
using SPECK3D_INT<T>::m_LIS;
using SPECK3D_INT<T>::m_partition_S_XYZ;

virtual void m_sorting_pass() override;

void m_process_S(size_t idx1, size_t idx2, SigType, size_t& counter, bool);
Expand Down
25 changes: 15 additions & 10 deletions include/SPECK_INT.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#ifndef SPECK_INT_H
#define SPECK_INT_H

//
// This is the base class of 1D, 2D, and 3D integer SPECK implementations.
//

#include "sperr_helper.h"

Expand All @@ -12,20 +14,23 @@ namespace sperr {

template <typename T>
class SPECK_INT {

using uint_type = T;
using vecui_type = std::vector<uint_type>;
using uint_type = T;
using vecui_type = std::vector<uint_type>;

public:
// Constructor
// Constructor and destructor
SPECK_INT();
// Virtual destructor
virtual ~SPECK_INT() = default;

// The length (1, 2, 4, 8) of the integer type in use
auto integer_len() const -> size_t;

void set_dims(dims_type);

// Retrieve the full length of a SPECK bitstream from its header
auto get_speck_full_len(const void*) const -> uint64_t;
// Retrieve info of a SPECK bitstream from its header
auto get_num_bitplanes(const void*) const -> uint8_t;
auto get_speck_bits(const void*) const -> uint64_t;
auto get_stream_full_len(const void*) const -> uint64_t;

// Actions
virtual void encode();
Expand All @@ -45,21 +50,21 @@ using vecui_type = std::vector<uint_type>;
protected:
// Core SPECK procedures
virtual void m_clean_LIS() = 0;
virtual void m_initialize_lists() = 0;
virtual void m_sorting_pass() = 0;
virtual void m_initialize_lists() = 0;
virtual void m_refinement_pass_encode();
virtual void m_refinement_pass_decode();

// Data members
dims_type m_dims = {0, 0, 0};
uint_type m_threshold = 0;
Bitmask m_LSP_mask;
vecui_type m_coeff_buf;
vecb_type m_sign_array;
Bitstream m_bit_buffer;
Bitmask m_LSP_mask;
std::vector<uint64_t> m_LIP, m_LSP_new;

const size_t m_u64_garbage_val = std::numeric_limits<size_t>::max();
const uint64_t m_u64_garbage_val = std::numeric_limits<uint64_t>::max();
const size_t m_header_size = 9; // 9 bytes

uint64_t m_bit_idx = 0; // current bit idx when decoding
Expand Down
8 changes: 3 additions & 5 deletions include/SPERR3D.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@
namespace sperr {

class SPERR3D : public SPERR_Driver {
public:
//
// Constructor
//
SPERR3D();

protected:
virtual void m_instantiate_encoder() override;
virtual void m_instantiate_decoder() override;

virtual void m_wavelet_xform() override;
virtual void m_inverse_wavelet_xform() override;

Expand Down
43 changes: 31 additions & 12 deletions include/SPERR_Driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include "Conditioner.h"
#include "SPECK_INT.h"

#include <variant>

namespace sperr {

class SPERR_Driver {
Expand All @@ -21,10 +23,10 @@ class SPERR_Driver {
//
// Input
//
// Accept incoming data: copy from a raw memory block
// Accept incoming data: copy from a raw memory block.
// `len` is the number of values.
template <typename T>
void copy_data(const T* p, // Input: pointer to the memory block
size_t len); // Input: number of values
void copy_data(const T* p, size_t len);

// Accept incoming data: take ownership of a memory block
void take_data(std::vector<double>&&);
Expand Down Expand Up @@ -52,23 +54,39 @@ class SPERR_Driver {
virtual auto decompress() -> RTNType;

protected:
// Default to use 64-bit integers, but can also use smaller sizes.
//
UINTType m_uint_flag = UINTType::UINT64;
std::variant<std::vector<uint64_t>,
std::vector<uint32_t>,
std::vector<uint16_t>,
std::vector<uint8_t>>
m_vals_ui;
std::variant<std::unique_ptr<SPECK_INT<uint64_t>>,
std::unique_ptr<SPECK_INT<uint32_t>>,
std::unique_ptr<SPECK_INT<uint16_t>>,
std::unique_ptr<SPECK_INT<uint8_t>>>
m_encoder, m_decoder;

dims_type m_dims = {0, 0, 0};
double m_q = 1.0; // 1.0 is a better initial value than 0.0
vecd_type m_vals_d;
vecui_t m_vals_ui; // Unsigned integers to be passed to the encoder
vecb_type m_sign_array; // Signs to be passed to the encoder
vecb_type m_sign_array; // Signs to be passed to the encoder
Conditioner::settings_type m_conditioning_settings = {true, false, false, false};

Conditioner::meta_type m_condi_bitstream;
vec8_type m_speck_bitstream;

CDF97 m_cdf;
Conditioner m_conditioner;
std::unique_ptr<SPECK_INT> m_encoder = nullptr;
std::unique_ptr<SPECK_INT> m_decoder = nullptr;

auto m_midtread_f2i() -> RTNType;
void m_midtread_i2f();
// Derived classes instantiate the correct `m_encoder` and `m_decoder` depending on
// 3D/2D/1D classes, and the integer length in use.
virtual void m_instantiate_encoder() = 0;
virtual void m_instantiate_decoder() = 0;

// Instantiate `m_vals_ui` based on the chosen integer length.
virtual void m_instantiate_int_vec();

// Both wavelet transforms operate on `m_vals_d`.
virtual void m_wavelet_xform() = 0;
Expand All @@ -79,9 +97,10 @@ class SPERR_Driver {
virtual auto m_quantize() -> RTNType = 0;
virtual auto m_inverse_quantize() -> RTNType = 0;

// Optional procedures for flexibility
virtual auto m_proc_1() -> RTNType;
virtual auto m_proc_2() -> RTNType;
// This base class provides two midtread quantization implementations, but derived classes
// can have other quantization methods.
auto m_midtread_f2i() -> RTNType;
void m_midtread_i2f();
};

}; // namespace sperr
Expand Down
5 changes: 3 additions & 2 deletions include/sperr_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,16 @@ enum class SigType : unsigned char { Insig, Sig, NewlySig, Dunno, Garbage };

enum class SetType : unsigned char { TypeS, TypeI, Garbage };

enum class UINTType : unsigned char { UINT64, UINT32, UINT16, UINT8 };

// Return Type
enum class RTNType {
Good = 0,
WrongDims,
BitstreamWrongLen,
IOError,
InvalidParam,
QzLevelTooBig, // a very specific type of invalid param
EmptyStream, // a condition but not sure if it's an error
EmptyStream, // a condition but not sure if it's an error
BitBudgetMet,
VersionMismatch,
ZSTDMismatch,
Expand Down
Loading