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

Morton #211

Merged
merged 23 commits into from
Sep 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 36 additions & 5 deletions include/SPECK1D_INT.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,40 @@

#include "SPECK_INT.h"

#include <cstring> // std::memcpy()

namespace sperr {

class Set1D {
// In an effort to reduce the object size of Set1D, I choose to store only the first 7 bytes of
// both the `start` and `length` information of a Set1D. Using another 2 bytes to store the
// `part_level` info, this object fits in 16 bytes nicely.
//
private:
std::array<uint8_t, 16> m_16 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};

public:
uint64_t start = 0;
uint64_t length = 0;
uint16_t part_level = 0;
SetType type = SetType::TypeS; // Only used to indicate garbage status
void set_start(uint64_t val) { std::memcpy(m_16.data(), &val, 7); };
void set_length(uint64_t val) { std::memcpy(m_16.data() + 7, &val, 7); };
void set_level(uint16_t val) { std::memcpy(m_16.data() + 14, &val, 2); };
auto get_start() const -> uint64_t
{
auto val = uint64_t{0};
std::memcpy(&val, m_16.data(), 7);
return val;
}
auto get_length() const -> uint64_t
{
auto val = uint64_t{0};
std::memcpy(&val, m_16.data() + 7, 7);
return val;
}
auto get_level() const -> uint16_t
{
auto val = uint16_t{0};
std::memcpy(&val, m_16.data() + 14, 2);
return val;
}
};

//
Expand All @@ -27,9 +53,14 @@ class SPECK1D_INT : public SPECK_INT<T> {
using SPECK_INT<T>::m_dims;
using SPECK_INT<T>::m_coeff_buf;

// The 1D case is different from 3D and 2D cases in that it implements additional logic that
// infers the significance of subsets by where the significant point is. With this
// consideration, functions such as m_process_S() and m_process_P() have different signatures
// during decoding/encoding, so they're implemented in their respective subclasses.
//
void m_clean_LIS() override;
void m_initialize_lists() override;
auto m_partition_set(const Set1D&) const -> std::array<Set1D, 2>;
auto m_partition_set(Set1D) const -> std::array<Set1D, 2>;

//
// SPECK1D_INT specific data members
Expand Down
4 changes: 2 additions & 2 deletions include/SPECK1D_INT_ENC.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ class SPECK1D_INT_ENC : public SPECK1D_INT<T> {

void m_sorting_pass() override;

void m_process_S(size_t idx1, size_t idx2, SigType, size_t& counter, bool);
void m_process_P(size_t idx, SigType, size_t& counter, bool);
void m_process_S(size_t idx1, size_t idx2, SigType, size_t& counter, bool output);
void m_process_P(size_t idx, SigType, size_t& counter, bool output);
void m_code_S(size_t idx1, size_t idx2, std::array<SigType, 2>);

// Decide if a set is significant or not.
Expand Down
16 changes: 4 additions & 12 deletions include/SPECK2D_INT.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ class Set2D {
uint32_t length_x = 0;
uint32_t length_y = 0;
uint16_t part_level = 0;
SetType type = SetType::TypeS;

public:
auto is_pixel() const -> bool;
auto is_empty() const -> bool;
auto is_pixel() const -> bool { return (size_t{length_x} * length_y == 1); };
auto is_empty() const -> bool { return (size_t{length_x} * length_y == 0); };
void make_empty() { length_x = 0; };
};

//
Expand All @@ -34,14 +34,6 @@ class SPECK2D_INT : public SPECK_INT<T> {
using SPECK_INT<T>::m_coeff_buf;
using SPECK_INT<T>::m_bit_buffer;

// The 2D case is different from 3D and 1D cases in that it doesn't implement the logic that
// infers the significance of subsets by where the significant point is. I.e., the decide
// set significance functions return only true/false, but not the index of the first
// significant point. With this simplification, the m_process_S()/m_process_P()/m_process_I()
// functions have the same signature, so they can be virtual, and m_sorting_pass()/m_code_S/
// m_code_I() are really the same when encoding and decoding, so they can be implemented
// here instead of in SPECK2D_INT_ENC/SPECK2D_INT_DEC.
//
void m_sorting_pass() override;
void m_code_S(size_t idx1, size_t idx2);
void m_code_I();
Expand All @@ -59,7 +51,7 @@ class SPECK2D_INT : public SPECK_INT<T> {
// SPECK2D_INT specific data members
//
std::vector<std::vector<Set2D>> m_LIS;
Set2D m_I = {0, 0, 0, 0, 0, SetType::TypeI};
Set2D m_I;
};

}; // namespace sperr
Expand Down
2 changes: 1 addition & 1 deletion include/SPECK2D_INT_ENC.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class SPECK2D_INT_ENC : public SPECK2D_INT<T> {
void m_process_P(size_t idx, size_t& counter, bool need_decide) override;
void m_process_I(bool need_decide) override;

auto m_decide_S_significance(Set2D) const -> bool;
auto m_decide_S_significance(const Set2D&) const -> bool;
auto m_decide_I_significance() const -> bool;
};

Expand Down
55 changes: 36 additions & 19 deletions include/SPECK3D_INT.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,41 @@

#include "SPECK_INT.h"

#include <cstring> // std::memcpy()
#include <tuple>

namespace sperr {

class Set3D {
private:
// The first 6 bytes of the morton offset in uint64_t. Because each set dimension is
// stored using 16-bit integers, these 48 bits are big enough too!
std::array<uint8_t, 6> m_morton = {0, 0, 0, 0, 0, 0};

public:
//
// Member data
// Publicly accessible public data members.
//
uint32_t start_x = 0;
uint32_t start_y = 0;
uint32_t start_z = 0;
uint32_t length_x = 0;
uint32_t length_y = 0;
uint32_t length_z = 0;
// which partition level is this set at (starting from zero, in all 3 directions).
// This data member is the sum of all 3 partition levels.
uint16_t part_level = 0;
SetType type = SetType::TypeS; // Only used to indicate garbage status
uint16_t start_x = 0;
uint16_t start_y = 0;
uint16_t start_z = 0;
uint16_t length_x = 0;
uint16_t length_y = 0;
uint16_t length_z = 0;

public:
//
// Member functions
// Member functions (intended to be inline)
//
auto is_pixel() const -> bool;
auto is_empty() const -> bool;
auto get_morton() const -> uint64_t
{
auto tmp = uint64_t{0};
std::memcpy(&tmp, m_morton.data(), sizeof(m_morton));
return tmp;
}
void set_morton(uint64_t val) { std::memcpy(m_morton.data(), &val, sizeof(m_morton)); }
void make_empty() { length_x = 0; }
auto num_elem() const -> size_t { return (size_t{length_x} * length_y * length_z); }
};

//
Expand All @@ -44,13 +55,19 @@ class SPECK3D_INT : public SPECK_INT<T> {
using SPECK_INT<T>::m_coeff_buf;
using SPECK_INT<T>::m_bit_buffer;

void m_clean_LIS() override;
void m_initialize_lists() override;
void m_sorting_pass() override;
void m_clean_LIS() override;

virtual void m_process_S(size_t idx1, size_t idx2, size_t& counter, bool) = 0;
virtual void m_process_P(size_t i, size_t m, size_t& c, bool) = 0; // Called by `m_code_S()`.
virtual void m_process_P_lite(size_t idx) = 0; // Called by `m_sorting_pass()` directly.
virtual void m_additional_initialization() = 0;

// Divide a Set3D into 8, 4, or 2 smaller subsets.
auto m_partition_S_XYZ(const Set3D&) const -> std::array<Set3D, 8>;
auto m_partition_S_XY(const Set3D&) const -> std::array<Set3D, 4>;
auto m_partition_S_Z(const Set3D&) const -> std::array<Set3D, 2>;
void m_code_S(size_t idx1, size_t idx2);
auto m_partition_S_XYZ(Set3D, uint16_t) const -> std::tuple<std::array<Set3D, 8>, uint16_t>;
auto m_partition_S_XY(Set3D, uint16_t) const -> std::tuple<std::array<Set3D, 4>, uint16_t>;
auto m_partition_S_Z(Set3D, uint16_t) const -> std::tuple<std::array<Set3D, 2>, uint16_t>;

//
// SPECK3D_INT specific data members
Expand Down
12 changes: 5 additions & 7 deletions include/SPECK3D_INT_DEC.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,16 @@ class SPECK3D_INT_DEC : public SPECK3D_INT<T> {
// Bring members from parent classes to this derived class.
//
using SPECK_INT<T>::m_LIP_mask;
using SPECK_INT<T>::m_dims;
using SPECK_INT<T>::m_LSP_new;
using SPECK_INT<T>::m_bit_buffer;
using SPECK_INT<T>::m_sign_array;
using SPECK3D_INT<T>::m_LIS;
using SPECK3D_INT<T>::m_partition_S_XYZ;
using SPECK3D_INT<T>::m_code_S;

void m_sorting_pass() override;

void m_process_S(size_t idx1, size_t idx2, size_t& counter, bool);
void m_process_P(size_t idx, size_t& counter, bool);
void m_code_S(size_t idx1, size_t idx2);
void m_process_S(size_t idx1, size_t idx2, size_t& counter, bool read) override;
void m_process_P(size_t idx, size_t no_use, size_t& counter, bool read) override;
void m_process_P_lite(size_t idx) override;
void m_additional_initialization() override{}; // empty function
};

}; // namespace sperr
Expand Down
22 changes: 14 additions & 8 deletions include/SPECK3D_INT_ENC.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ namespace sperr {
template <typename T>
class SPECK3D_INT_ENC : public SPECK3D_INT<T> {
private:
//
// Consistant with the base class.
//
using uint_type = T;
using vecui_type = std::vector<uint_type>;

//
// Bring members from parent classes to this derived class.
//
Expand All @@ -25,16 +31,16 @@ class SPECK3D_INT_ENC : public SPECK3D_INT<T> {
using SPECK_INT<T>::m_sign_array;
using SPECK3D_INT<T>::m_LIS;
using SPECK3D_INT<T>::m_partition_S_XYZ;
using SPECK3D_INT<T>::m_code_S;

void m_sorting_pass() override;

void m_process_S(size_t idx1, size_t idx2, SigType, size_t& counter, bool output);
void m_process_P(size_t idx, SigType, size_t& counter, bool output);
void m_code_S(size_t idx1, size_t idx2, std::array<SigType, 8>);
void m_process_S(size_t idx1, size_t idx2, size_t& counter, bool output) override;
void m_process_P(size_t idx, size_t morton, size_t& counter, bool output) override;
void m_process_P_lite(size_t idx) override;
void m_additional_initialization() override;

// Decide if a set is significant or not.
// If it is significant, also identify the point that makes it significant.
auto m_decide_significance(const Set3D&) const -> std::optional<std::array<uint32_t, 3>>;
// Data structures and functions for morton data layout.
vecui_type m_morton_buf;
void m_deposit_set(Set3D);
};

}; // namespace sperr
Expand Down
2 changes: 0 additions & 2 deletions include/sperr_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ using dims_type = std::array<size_t, 3>;
//
enum class SigType : unsigned char { Insig, Sig, NewlySig, Dunno, Garbage };

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

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

enum class CompMode : unsigned char { PSNR, PWE, Rate, Unknown };
Expand Down
Loading