diff options
-rw-r--r-- | modules/codec-unit/c++/unit.hpp | 12 | ||||
-rw-r--r-- | modules/codec-unit/c++/unit.tmpl.hpp | 32 | ||||
-rw-r--r-- | modules/codec-unit/c++/unit_transform.hpp | 102 | ||||
-rw-r--r-- | modules/codec-unit/tests/codec-unit.cpp | 56 |
4 files changed, 181 insertions, 21 deletions
diff --git a/modules/codec-unit/c++/unit.hpp b/modules/codec-unit/c++/unit.hpp index 986ca8f..0e7bf74 100644 --- a/modules/codec-unit/c++/unit.hpp +++ b/modules/codec-unit/c++/unit.hpp @@ -3,6 +3,8 @@ #include "unit_schema.hpp" #include "unit_transform.hpp" +#include <forstio/codec/data.hpp> + namespace saw { template<typename BaseSchema, typename... Elements> class data<schema::Unit<BaseSchema, Elements...>, encode::Native> { @@ -19,7 +21,15 @@ public: data<Schema, encode::Native> operator+(const data<Schema, encode::Native>& rhs) const; data<Schema, encode::Native> operator-(const data<Schema, encode::Native>& rhs) const; + + bool operator==(const data<Schema, encode::Native>& rhs) const; + + template<typename UnitRhs> + data<typename unit_multiplication<Schema, UnitRhs>::Schema, encode::Native> operator*(const data<UnitRhs, encode::Native>& rhs) const; + + template<typename UnitRhs> + data<typename unit_division<Schema, UnitRhs>::Schema, encode::Native> operator/(const data<UnitRhs, encode::Native>& rhs) const; }; } -#include "unit.tmpl.h" +#include "unit.tmpl.hpp" diff --git a/modules/codec-unit/c++/unit.tmpl.hpp b/modules/codec-unit/c++/unit.tmpl.hpp index 7412199..08edc4f 100644 --- a/modules/codec-unit/c++/unit.tmpl.hpp +++ b/modules/codec-unit/c++/unit.tmpl.hpp @@ -3,17 +3,41 @@ namespace saw { template<typename BaseSchema, typename... Elements> data<schema::Unit<BaseSchema, Elements...>, encode::Native> data<schema::Unit<BaseSchema, Elements...>, encode::Native>::operator+(const -data<schema::Unit<BaseSchema, Elements...>, encode::Native>& rhs){ +data<schema::Unit<BaseSchema, Elements...>, encode::Native>& rhs) const { auto add = dat_ + rhs.dat_; - return {add}; + return add; } template<typename BaseSchema, typename... Elements> data<schema::Unit<BaseSchema, Elements...>, encode::Native> data<schema::Unit<BaseSchema, Elements...>, encode::Native>::operator-(const -data<schema::Unit<BaseSchema, Elements...>, encode::Native>& rhs){ +data<schema::Unit<BaseSchema, Elements...>, encode::Native>& rhs) const { auto sub = dat_ - rhs.dat_; - return {sub}; + return sub; +} + +template<typename BaseSchema, typename... Elements> +bool +data<schema::Unit<BaseSchema, Elements...>, encode::Native>::operator==(const data<Schema, encode::Native>& rhs) const { + return dat_ == rhs.dat_; +} + +template<typename BaseSchema, typename... Elements> +template<typename UnitRhs> +data<typename unit_multiplication<schema::Unit<BaseSchema,Elements...>, UnitRhs>::Schema, encode::Native> +data<schema::Unit<BaseSchema, Elements...>, encode::Native>::operator*(const +data<UnitRhs, encode::Native>& rhs) const { + auto mult = dat_ * rhs.dat_; + return mult; +} + +template<typename BaseSchema, typename... Elements> +template<typename UnitRhs> +data<typename unit_division<schema::Unit<BaseSchema,Elements...>, UnitRhs>::Schema, encode::Native> +data<schema::Unit<BaseSchema, Elements...>, encode::Native>::operator/(const +data<UnitRhs, encode::Native>& rhs) const { + auto div = dat_ / rhs.dat_; + return div; } } diff --git a/modules/codec-unit/c++/unit_transform.hpp b/modules/codec-unit/c++/unit_transform.hpp index 3cae3c5..2e1ace4 100644 --- a/modules/codec-unit/c++/unit_transform.hpp +++ b/modules/codec-unit/c++/unit_transform.hpp @@ -1,5 +1,7 @@ #pragma once +#include <forstio/common.hpp> + #include <type_traits> #include "unit_schema.hpp" @@ -13,40 +15,116 @@ template<typename... T> class unit_redux_list { static_assert(sizeof...(T) == 0u, "Template type not supported"); - using reduced_type = unit_redux_list<>; + using Type = unit_redux_list<>; +}; + +template<typename T0, int64_t E0, typename... TL, int64_t... EL> +struct unit_redux_list<schema::UnitElement<T0,E0>, schema::UnitElement<TL,EL>...> { + using Type = typename unit_matching<unit_redux_list<schema::UnitElement<T0,E0>, schema::UnitElement<TL,EL>...>, unit_redux_list<>>::TypeList; +}; + +template<typename T, typename U, typename V> +class unit_matching_reduce { +public: + static_assert(always_false<T,U,V>, "Template type not supported"); +}; + +/** + * Iterate over the left list to check against the left element. + */ +template<typename T, int64_t E, typename T0, int64_t E0, typename... TL, int64_t... EL, typename... TR, int64_t... ER> +class unit_matching_reduce<schema::UnitElement<T,E>, unit_redux_list<schema::UnitElement<T0,E0>,schema::UnitElement<TL,EL>...>, unit_redux_list<schema::UnitElement<TR,ER>...>> { +public: + static constexpr bool is_same = std::is_same_v<T,T0>; + + // Match T,E against T0,E0 + using ReducedType = typename std::conditional<is_same, schema::UnitElement<T,E+E0>, schema::UnitElement<T,E>>::type; + using ReducedTypeList = typename std::conditional<is_same, unit_redux_list<schema::UnitElement<TR,ER>...>, unit_redux_list<schema::UnitElement<TR,ER>..., schema::UnitElement<T0,E0>>>::type; + + using NextMatcher = unit_matching_reduce<ReducedType, unit_redux_list<schema::UnitElement<TL,EL>...>, ReducedTypeList>; + using Type = typename NextMatcher::Type; + using TypeList = typename NextMatcher::TypeList; + static constexpr int64_t Num = NextMatcher::Num; +}; + +/** + * Final step after going through the list. This contains the final match result. + * On the left is the accumulated type and on the right its's a list of non matching types + */ +template<typename T, int64_t E, typename... TR, int64_t... ER> +class unit_matching_reduce<schema::UnitElement<T,E>, unit_redux_list<>, unit_redux_list<schema::UnitElement<TR,ER>...>> { +public: + using Type = schema::UnitElement<T,E>; + using TypeList = unit_redux_list<schema::UnitElement<TR,ER>...>; + static constexpr int64_t Num = E; }; template<typename LR, typename RR> class unit_matching { - static_assert(is_always_false<LR,RR>, "Template type not supported"); + static_assert(always_false<LR,RR>, "Template type not supported"); }; template<typename... Ele> class unit_matching<unit_redux_list<>, unit_redux_list<Ele...>> { - using Type = unit_redux_list<Ele...>; +public: + using TypeList = unit_redux_list<Ele...>; }; template<typename Ele0, typename... EleL, typename... EleR> -class unit_matching<unit_redux_list<Ele0, ELeL...>, unit_redux_list<EleR...>> { - using Type = +class unit_matching<unit_redux_list<Ele0, EleL...>, unit_redux_list<EleR...>> { +public: + // static constexpr bool is_same = std::is_same_v<T,T0>; + + using MatchReducer = unit_matching_reduce<Ele0, unit_redux_list<EleL...>, unit_redux_list<>>; + + using ReducedType = typename MatchReducer::Type; + using ReducedTypeList = typename MatchReducer::TypeList; + static constexpr int64_t Num = MatchReducer::Num; + + using TypeRightList = typename std::conditional<Num == 0u, unit_redux_list<EleR...>, unit_redux_list<EleR..., ReducedType>>::type; + using TypeList = typename unit_matching<ReducedTypeList, TypeRightList>::TypeList; +}; + +template<typename BaseSchema, typename List> +class unit_add_base { + static_assert(always_false<BaseSchema,List>, "Template type not supported"); +}; + +template<typename BaseSchema, typename... Ele> +class unit_add_base<BaseSchema, unit_redux_list<Ele...>> { +public: + using Schema = schema::Unit<BaseSchema, Ele...>; }; } -template<typename... UE> +template<typename BaseSchema, typename... UE> struct unit_element_reduction { - using Schema = typename impl::unit_matching<impl::unit_redux_list<UE...>, impl::unit_redux_list<>>::Schema; + using TypeList = typename impl::unit_matching<impl::unit_redux_list<UE...>, impl::unit_redux_list<>>::TypeList; + using Schema = typename impl::unit_add_base<BaseSchema, TypeList>::Schema; }; template<typename U0, typename U1> struct unit_multiplication { - static_assert(is_always_false<U0,U1>, "Template type not supported"); + static_assert(always_false<U0,U1>, "Template type not supported"); +}; + +template<typename BaseSchema, typename... UnitT, int64_t... UnitE, typename... UnitRhsT, int64_t... UnitRhsE> +struct unit_multiplication< + schema::Unit<BaseSchema, schema::UnitElement<UnitT,UnitE>...>,schema::Unit<BaseSchema, schema::UnitElement<UnitRhsT,UnitRhsE>...> +> { + using Schema = typename unit_element_reduction<BaseSchema, schema::UnitElement<UnitT,UnitE>..., schema::UnitElement<UnitRhsT, UnitRhsE>...>::Schema; +}; + +template<typename U0, typename U1> +struct unit_division { + static_assert(always_false<U0,U1>, "Template type not supported"); }; -template<typename... UnitT, int64_t... UnitE, typename... UnitRhsT, int64_t... UnitRhsE> -class unit_multiplication< - schema::Unit<schema::UnitElement<UnitT,UnitE>...>,schema::Unit<schema::UnitElement<UnitRhsT,UnitRhsE>...> +template<typename BaseSchema, typename... UnitT, int64_t... UnitE, typename... UnitRhsT, int64_t... UnitRhsE> +struct unit_division< + schema::Unit<BaseSchema, schema::UnitElement<UnitT,UnitE>...>,schema::Unit<BaseSchema, schema::UnitElement<UnitRhsT,UnitRhsE>...> > { - using Schema = typename unit_reduction<schema::UnitElement<UnitT,UnitE>..., schema::UnitElement<UnitRhsT, UnitRhsE>...>::Schema; + using Schema = typename unit_element_reduction<BaseSchema, schema::UnitElement<UnitT,UnitE>..., schema::UnitElement<UnitRhsT, -UnitRhsE>...>::Schema; }; } diff --git a/modules/codec-unit/tests/codec-unit.cpp b/modules/codec-unit/tests/codec-unit.cpp index 0c88e9d..39e590d 100644 --- a/modules/codec-unit/tests/codec-unit.cpp +++ b/modules/codec-unit/tests/codec-unit.cpp @@ -2,15 +2,63 @@ #include <forstio/codec/schema.hpp> +#include "../c++/unit.hpp" + namespace { namespace sch { using namespace saw::schema; + +struct FanMeterEle {}; + +using FanMeter = Unit< + Int64, + UnitElement<FanMeterEle,1> +>; + +using FanSquareMeter = Unit< + Int64, + UnitElement<FanMeterEle,2> +>; +} + + +SAW_TEST("Codec Unit/Addition"){ + using namespace saw; + + data<sch::FanMeter> a{{5}}, b{{4}}; + + auto c = a + b; + + SAW_EXPECT(c == data<sch::FanMeter>{9u}, "Expected result 9"); +} + +SAW_TEST("Codec Unit/Subtraction"){ + using namespace saw; + + data<sch::FanMeter> a{{5}}, b{{4}}; + + auto c = a - b; + + SAW_EXPECT(c == data<sch::FanMeter>{1u}, "Expected result 1"); } -/* -SAW_TEST("Dummy Test"){ +SAW_TEST("Codec Unit/Multiplication"){ using namespace saw; - SAW_EXPECT( false, "Dummy" ); + + data<sch::FanMeter> a{{5}}, b{{4}}; + + auto c = a * b; + + SAW_EXPECT(c == data<sch::FanSquareMeter>{20u}, "Expected result 20"); +} + +SAW_TEST("Codec Unit/Division"){ + using namespace saw; + + data<sch::FanMeter> a{{20}}, b{{4}}; + + auto c = a / b; + + SAW_EXPECT(c == data<sch::Scalar<sch::Int64>>{5u}, "Expected result 5"); } -*/ } |