#pragma once #include "data.hpp" namespace saw { namespace encode { struct NativeRaw { static constexpr string_literal name = "encode::NativeRaw"; }; } template struct raw_native_array_type_helper { using type = data; }; template struct raw_native_array_type_helper> { using Type = typename native_data_type>::type; }; template struct raw_native_array_type_helper> { using Type = typename native_data_type::StorageSchema>::type; }; 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}; } }; template class data>, encode::NativeRaw> { public: using ReferencedSchema = schema::Primitive; using Schema = schema::Ref; using MetaSchema = typename meta_schema::MetaSchema; private: ref::type > value_; public: data(ref::type > value__): value_{value__} {} SAW_DEFAULT_COPY(data); SAW_FORBID_MOVE(data); 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(); } template bool operator<(const data& rhs) const { return get() < rhs.get(); } template bool operator<(const data& rhs) const { return get() < rhs.get(); } }; /** * 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> { 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>& 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>& 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> { 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>& get(){ return std::get(value_); } template const data::type, encode::NativeRaw>& get() const{ return std::get(value_); } constexpr size_t size() const { return sizeof...(T); } }; template class data, encode::NativeRaw> { public: using Schema = schema::Array; using MetaSchema = typename meta_schema::MetaSchema; private: // rawr // data, encode::NativeRaw> dims_; std::array dims_; std::vector::Type> 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; } } /** * Purely internal function for working C interfacing */ typename raw_native_array_type_helper::Type* get_raw_data() { if(value_.size() == 0u){ return nullptr; } return &(value_[0]); } 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, encode::NativeRaw> at(const std::array& ind){ return {value_.at(this->get_flat_index(ind))}; } const data, encode::NativeRaw> at(const std::array& ind) const { return {value_.at(this->get_flat_index(ind))}; } template data, encode::NativeRaw> at(Dims... i){ return {value_.at(this->get_flat_index(std::array{static_cast(i)...}))}; } template const data, encode::NativeRaw> at(Dims... i) const { return {value_.at(this->get_flat_index(std::array{static_cast(i)...}))}; } template data,encode::NativeRaw> at(const data, Encoding>& i){ return {value_.at(this->get_flat_index(i))}; } template const data,encode::NativeRaw> at(const data, Encoding>& 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, encode::NativeRaw> get_dims() const { return {dims_}; } private: template uint64_t get_flat_index(const U& i) const { 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; } }; template class data, encode::NativeRaw> { public: using Schema = schema::FixedArray; using MetaSchema = typename meta_schema::MetaSchema; private: //using inner_type = std::array, multiply_helper::value>; //std::unique_ptr value_; using ArrayT = std::array::Type, ct_multiply::value>; ArrayT value_; public: data() = default; data(data){} data(const std::array, ct_multiply::value>& value__): value_{value__} {} data, encode::NativeRaw> at(const std::array& ind){ return {value_.at(this->get_flat_index(ind))}; } const data, encode::Native> at(const std::array& ind) const { return {value_.at(this->get_flat_index(ind))}; } template data, encode::Native> at(Dims... i) { return {value_.at(this->get_flat_index({i...}))}; } template const data, encode::Native> at(Dims... i) const { return {value_.at(this->get_flat_index({i...}))}; } data, encode::Native> at(const data, encode::NativeRaw>& i){ return {value_.at(this->get_flat_index(i))}; } const data, encode::Native> at(const data, encode::NativeRaw>& i)const{ return {value_.at(this->get_flat_index(i))}; } template uint64_t get_dim_size() const { return parameter_pack_value::value; } data, encode::NativeRaw> get_dims() const { return {std::array{D...}}; } private: uint64_t get_flat_index(const std::array& i) const { uint64_t s = 0; uint64_t stride = 1; constexpr static std::array dims_{D...}; for(uint64_t iter = 0; iter < sizeof...(D); ++iter){ assert(i.at(iter) < dims_.at(iter)); s += i.at(iter) * stride; stride *= dims_.at(iter); } return s; } }; }