#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: constexpr data():value_{}{} constexpr data(data):value_{}{} SAW_DEFAULT_COPY(data); SAW_DEFAULT_MOVE(data); constexpr data(typename native_data_type::type value__): value_{std::move(value__)}{} constexpr void set(typename native_data_type::type val){ value_ = val; } constexpr typename native_data_type::type get() const {return value_;} constexpr data operator*(const data& rhs)const{ return {get() * rhs.get()}; } constexpr data operator/(const data& rhs)const{ return {get() / rhs.get()}; } constexpr data operator+(const data& rhs)const{ return {get() + rhs.get()}; } constexpr data& operator+=(const data& rhs)const{ value_ += rhs.get(); return *this; } constexpr data& operator-=(const data& rhs)const{ value_ -= rhs.get(); return *this; } constexpr data operator-(const data& rhs)const{ return {get() - rhs.get()}; } template constexpr bool operator==(const data& rhs)const{ return get() == rhs.get(); } template constexpr bool operator<(const data& rhs) const { return get() < rhs.get(); } /** * Casts */ template constexpr 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: constexpr data(ref::type > value__): value_{value__} {} SAW_DEFAULT_COPY(data); SAW_FORBID_MOVE(data); constexpr void set(typename native_data_type::type val){ value_() = val; } constexpr typename native_data_type::type get() const { return value_(); } constexpr data operator*(const data& rhs)const{ return {get() * rhs.get()}; } constexpr data operator/(const data& rhs)const{ return {get() / rhs.get()}; } constexpr data operator+(const data& rhs)const{ return {get() + rhs.get()}; } constexpr data& operator+=(const data& rhs)const{ value_ += rhs.get(); return *this; } constexpr data& operator-=(const data& rhs)const{ value_ -= rhs.get(); return *this; } constexpr data operator-(const data& rhs)const{ return {get() - rhs.get()}; } template constexpr bool operator==(const data& rhs)const{ return get() == rhs.get(); } template constexpr bool operator==(const data& rhs)const{ return get() == rhs.get(); } template constexpr bool operator<(const data& rhs) const { return get() < rhs.get(); } template constexpr 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__)}{} constexpr typename saw::native_data_type::type get() const { return value_.template cast_to().get(); } constexpr data(const saw::data& val){ value_ = val.template cast_to(); } constexpr void set(typename saw::native_data_type::type val){ value_.set(static_cast(val)); } constexpr 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}; } constexpr 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}; } constexpr 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}; } constexpr 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}; } constexpr data& operator+=(const data& rhs)const{ *this = *this + rhs.get(); return *this; } constexpr 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}; } constexpr data& operator-=(const data& rhs) const { *this = *this - rhs.get(); return *this; } template constexpr bool operator==(const data& rhs)const{ return get() == rhs.get(); } template constexpr 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_; typename raw_native_array_type_helper::Type* value_; uint64_t value_size_; constexpr uint64_t get_full_size() const { uint64_t s = 1; for(uint64_t iter = 0; iter < Dim; ++iter){ s *= dims_[iter]; } return s; } public: data(): value_{nullptr}, value_size_{0u} { for(auto& iter : dims_){ iter = 0u; } } /** * Purely internal function for working C interfacing */ constexpr typename raw_native_array_type_helper::Type* get_raw_data() { if(value_size_ == 0u){ return nullptr; } return &(value_[0]); } SAW_FORBID_COPY(data); SAW_FORBID_MOVE(data); data(const std::array& i): dims_{i}, value_{nullptr}, value_size_{0u} { // auto old_value = value_; // auto old_value_size = value_size_; value_size_ = get_full_size(); value_ = new typename raw_native_array_type_helper::Type (value_size_); } data(data init) { for(uint64_t i = 0; i < Dim; ++i){ dims_.at(i) = init.at(i).get(); } value_size_ = get_full_size(); value_ = new typename raw_native_array_type_helper::Type (value_size_); } ~data(){ if(value_){ delete value_; value_ = nullptr; value_size_ = 0u; } } template constexpr data(Dims... size_): data{{static_cast(size_)...}} { static_assert(sizeof...(Dims)==Dim, "Argument size must be equal to the Dimension"); } template constexpr error_or adopt(typename raw_native_array_type_helper::Type* adoptee, Dims... adoptee_size){ if(value_ != nullptr){ return make_error("Can't adopt into existing state"); } dims_ = {adoptee_size...}; value_size_ = get_full_size(); value_ = adoptee; return make_void(); } constexpr error_or::Type*> extract(){ auto old_val = value_; value_ = nullptr; value_size_ = 0u; return old_val; } constexpr data, encode::NativeRaw> at(const std::array& ind){ return {value_[this->get_flat_index(ind)]}; } constexpr const data, encode::NativeRaw> at(const std::array& ind) const { return {value_[this->get_flat_index(ind)]}; } template constexpr data, encode::NativeRaw> at(Dims... i){ return {value_[this->get_flat_index(std::array{static_cast(i)...})]}; } template constexpr const data, encode::NativeRaw> at(Dims... i) const { return {value_[this->get_flat_index(std::array{static_cast(i)...})]}; } template constexpr data,encode::NativeRaw> at(const data, Encoding>& i){ return {value_[this->get_flat_index(i)]}; } template constexpr const data,encode::NativeRaw> at(const data, Encoding>& i)const{ return {value_[this->get_flat_index(i)]}; } constexpr std::size_t get_dim_size(uint64_t i) const { return dims_.at(i); } constexpr uint64_t size() const { return value_size_;} constexpr data, encode::NativeRaw> get_dims() const { return {dims_}; } private: template constexpr uint64_t get_flat_index(const U& i) const { 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[iter]); s += ind * stride; stride *= dims_[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; } }; }