From d5bf26c38a28bfe114511375ed125505f8325514 Mon Sep 17 00:00:00 2001 From: Claudius 'keldu' Holeksa Date: Tue, 30 Jul 2024 16:56:29 +0200 Subject: wip for managing the raw data in a native format --- modules/codec/c++/data.hpp | 1 + modules/codec/c++/data_raw.hpp | 478 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 479 insertions(+) create mode 100644 modules/codec/c++/data_raw.hpp (limited to 'modules/codec/c++') diff --git a/modules/codec/c++/data.hpp b/modules/codec/c++/data.hpp index 1cd474c..e955af0 100644 --- a/modules/codec/c++/data.hpp +++ b/modules/codec/c++/data.hpp @@ -25,6 +25,7 @@ struct Native { static constexpr string_literal name = "encode::Native"; }; } + template class codec; /* diff --git a/modules/codec/c++/data_raw.hpp b/modules/codec/c++/data_raw.hpp new file mode 100644 index 0000000..3081423 --- /dev/null +++ b/modules/codec/c++/data_raw.hpp @@ -0,0 +1,478 @@ +#pragma once + +#include "data.hpp" + +namespace saw { +namespace encode { +struct NativeRaw { + static constexpr string_literal name = "encode::NativeRaw"; +}; +} + +template<> +class data { +public: + using Schema = schema::Void; + using MetaSchema = schema::Void; +}; + +template<> +class data { +public: + using Schema = schema::Bool; + using MetaSchema = schema::Void; +private: + bool value_; +public: + data():value_{false}{} + data(data):value_{false}{} + + SAW_DEFAULT_COPY(data); + SAW_DEFAULT_MOVE(data); + + void set(bool val){ + value_ = val; + } + + bool get() const { + return value_; + } +}; + +template +class data, encode::NativeRaw> { +public: + using Schema = schema::Primitive; + using MetaSchema = typename meta_schema::MetaSchema; +private: + typename native_data_type::type value_; +public: + data():value_{}{} + data(data):value_{}{} + + SAW_DEFAULT_COPY(data); + SAW_DEFAULT_MOVE(data); + + data(typename native_data_type::type value__): + value_{std::move(value__)}{} + + void set(typename native_data_type::type val){ + value_ = val; + } + + typename native_data_type::type get() const {return value_;} + + data operator*(const data& rhs)const{ + return {get() * rhs.get()}; + } + + data operator/(const data& rhs)const{ + return {get() / rhs.get()}; + } + + data operator+(const data& rhs)const{ + return {get() + rhs.get()}; + } + + data& operator+=(const data& rhs)const{ + value_ += rhs.get(); + return *this; + } + + data& operator-=(const data& rhs)const{ + value_ -= rhs.get(); + return *this; + } + + data operator-(const data& rhs)const{ + return {get() - rhs.get()}; + } + + template + bool operator==(const data& rhs)const{ + return get() == rhs.get(); + } + + template + bool operator<(const data& rhs) const { + return get() < rhs.get(); + } + + /** + * Casts + */ + template + data cast_to() const { + auto raw_to = static_cast::type>(value_); + return {raw_to}; + } +}; + +/** + * Mixed precision class for native formats + */ +template +class data, schema::Primitive>, encode::NativeRaw>{ +public: + using Schema = schema::MixedPrecision, schema::Primitive>; + using MetaSchema = typename meta_schema::MetaSchema; +private: + data value_; +public: + data():value_{}{} + data(data):value_{}{} + + data(typename saw::native_data_type::type val__):value_{static_cast::type>(val__)}{} + + typename saw::native_data_type::type get() const { + return value_.template cast_to().get(); + } + + data(const saw::data& val){ + value_ = val.template cast_to(); + } + + void set(typename saw::native_data_type::type val){ + value_.set(static_cast(val)); + } + + data operator*(const data& rhs) const { + using CalcType = typename native_data_type::type; + CalcType left = static_cast(value_.get()); + CalcType right = static_cast(rhs.get()); + return {left * right}; + } + + data operator*(const data& rhs) const { + using CalcType = typename native_data_type::type; + CalcType left = static_cast(value_.get()); + CalcType right = rhs.get(); + return {left * right}; + } + + data operator/(const data& rhs)const{ + using CalcType = typename native_data_type::type; + CalcType left = static_cast(value_.get()); + CalcType right = static_cast(rhs.get()); + return {left / right}; + } + + data operator+(const data& rhs)const{ + using CalcType = typename native_data_type::type; + CalcType left = static_cast(value_.get()); + CalcType right = static_cast(rhs.get()); + return {left + right}; + } + + data& operator+=(const data& rhs)const{ + *this = *this + rhs.get(); + return *this; + } + + data operator-(const data& rhs)const{ + using CalcType = typename native_data_type::type; + CalcType left = static_cast(value_.get()); + CalcType right = static_cast(rhs.get()); + return {left - right}; + } + + data& operator-=(const data& rhs) const { + *this = *this - rhs.get(); + return *this; + } + + template + bool operator==(const data& rhs)const{ + return get() == rhs.get(); + } + + template + bool operator<(const data& rhs) const { + return get() < rhs.get(); + } +}; + +/** + * Data class which represents a struct in the native format. + */ +template +class data...>, encode::NativeRaw, storage::Default> { +public: + using Schema = schema::Struct...>; + using MetaSchema = typename meta_schema::MetaSchema; +private: + /** + * Tuple storing the member values. + */ + std::tuple...> value_; + + template + struct init_helper { + static void apply(std::tuple...>& val, data&& init){ + auto& val_i = val.template get(); + auto& init_i = init.template get(); + + val_i = {std::move(init_i)}; + + if constexpr ( (i+1u) < sizeof...(T) ){ + init_helper::apply(val, init); + } + } + }; +public: + /** + * Default constructor. + */ + data() = default; + data(data init){ + if constexpr ( 0u < sizeof...(T) ){ + init_helper<0u>::apply(value_, std::move(init)); + } + } + + SAW_DEFAULT_COPY(data); + SAW_DEFAULT_MOVE(data); + + /** + * Get the member value based on the string_literal. + */ + template + data< + typename parameter_pack_type< + parameter_key_pack_index< + literal, literals... + >::value + , T...>::type + , encode::NativeRaw, storage::Default>& get(){ + return std::get::value>(value_); + } + + /** + * Get the member value based on the string_literal. + */ + template + const data< + typename parameter_pack_type< + parameter_key_pack_index< + literal, literals... + >::value + , T...>::type + , encode::NativeRaw, storage::Default>& get() const { + return std::get::value>(value_); + } + + /** + * Return the amount of members. + */ + constexpr size_t size() const { + return sizeof...(T); + } +}; + +template +class data, encode::NativeRaw, storage::Default> { +public: + using Schema = schema::Tuple; + using MetaSchema = typename meta_schema::MetaSchema; +private: + std::tuple...> value_; + + template + struct init_helper { + static void apply(std::tuple...>& val, data&& init){ + auto& val_i = val.template get(); + auto& init_i = init.template get(); + + val_i = {std::move(init_i)}; + + if constexpr ( (i+1u) < sizeof...(T) ){ + init_helper::apply(val, init); + } + } + }; +public: + data() = default; + data(data init){ + if constexpr ( 0u < sizeof...(T) ){ + init_helper<0u>::apply(value_, std::move(init)); + } + } + + SAW_DEFAULT_COPY(data); + SAW_DEFAULT_MOVE(data); + + template + data::type, encode::NativeRaw, storage::Default>& get(){ + return std::get(value_); + } + + template + const data::type, encode::NativeRaw, storage::Default>& get() const{ + return std::get(value_); + } + + constexpr size_t size() const { + return sizeof...(T); + } +}; + +template +class data, encode::NativeRaw, storage::Default> { + public: + using Schema = schema::Array; + using MetaSchema = typename meta_schema::MetaSchema; + private: + // data> dims_; + std::array dims_; + std::vector< + std::conditional< + is_primitive::value, + typename native_data_type::type, + data + > + > value_; + + uint64_t get_full_size() const { + uint64_t s = 1; + + for(uint64_t iter = 0; iter < Dim; ++iter){ + assert(dims_.at(iter) > 0); + s *= dims_.at(iter); + } + + return s; + } + public: + data(): + value_{} + { + for(auto& iter : dims_){ + iter = 0u; + } + } + + SAW_DEFAULT_COPY(data); + SAW_DEFAULT_MOVE(data); + + data(const std::array& i): + dims_{i}, + value_{} + { + value_.resize(get_full_size()); + } + + data(data init) + { + for(uint64_t i = 0; i < Dim; ++i){ + dims_.at(i) = init.at(i).get(); + } + value_.resize(get_full_size()); + } + + template + error_or add(saw::data data){ + /** @todo + * Generally the last dimension can always accept a element so to say. + * Changing the others would require moving data due to the stride changing. + * Since the last dimension doesn't affect the stride, we don't need reordering there. + * But I want a quick solution for one dimension so here we are. + * + * I can always ignore strides and use a stacked std::vector + * std::vector> and so on. + * But for now I'm keeping the strides. Smaller chunks of memory aren't to bad either + * though. + * I'll probably change it to the smaller chunks + */ + static_assert(Dim == 1, "Currently can't deal with higher dims"); + static_assert(i < Dim, "Can't add to dimension. Index i larger than dimension size"); + + try { + value_.emplace_back(std::move(data)); + }catch(const std::exception& e){ + (void) e; + return make_error(); + } + + ++dims_.at(i); + + return void_t{}; + } + + template + data(Dims... size_): + data{{static_cast(size_)...}} + { + static_assert(sizeof...(Dims)==Dim, "Argument size must be equal to the Dimension"); + } + + data& at(const std::array& ind){ + return value_.at(this->get_flat_index(ind)); + } + + const data& at(const std::array& ind) const { + return value_.at(this->get_flat_index(ind)); + } + + template + data& at(Dims... i){ + return value_.at(this->get_flat_index(std::array{static_cast(i)...})); + } + + template + const data& at(Dims... i) const { + return value_.at(this->get_flat_index(std::array{static_cast(i)...})); + } + + data& at(const data>& i){ + return value_.at(this->get_flat_index(i)); + } + + const data& at(const data>& i)const{ + return value_.at(this->get_flat_index(i)); + } + + std::size_t get_dim_size(uint64_t i) const { + return dims_.at(i); + } + + size_t size() const { return value_.size();} + + data> get_dims() const { + return {dims_}; + } + +private: + template + uint64_t get_flat_index(const U& i) const { + static_assert( + std::is_same_v>> or + std::is_same_v>, + "Unsupported type" + ); + assert(value_.size() == get_full_size()); + uint64_t s = 0; + + uint64_t stride = 1; + + for(uint64_t iter = 0; iter < Dim; ++iter){ + uint64_t ind = [](auto val) -> uint64_t { + using V = std::decay_t; + if constexpr (std::is_same_v>){ + return val.get(); + }else if constexpr (std::is_same_v){ + return val; + }else{ + static_assert(always_false, "Cases exhausted"); + } + }(i.at(iter)); + assert(ind < dims_.at(iter)); + s += ind * stride; + stride *= dims_.at(iter); + } + + return s; + } +}; + + +} -- cgit v1.2.3