diff options
Diffstat (limited to 'c++')
-rw-r--r-- | c++/SConscript | 37 | ||||
-rw-r--r-- | c++/distance/meter.h | 20 | ||||
-rw-r--r-- | c++/time/second.h | 15 | ||||
-rw-r--r-- | c++/unit.h | 49 | ||||
-rw-r--r-- | c++/unit.tmpl.h | 53 | ||||
-rw-r--r-- | c++/unit_cast.h | 15 | ||||
-rw-r--r-- | c++/unit_print.h | 55 | ||||
-rw-r--r-- | c++/unit_reduction.h | 133 |
8 files changed, 377 insertions, 0 deletions
diff --git a/c++/SConscript b/c++/SConscript new file mode 100644 index 0000000..1ee0d39 --- /dev/null +++ b/c++/SConscript @@ -0,0 +1,37 @@ +#!/bin/false + +import os +import os.path +import glob + + +Import('env') + +dir_path = Dir('.').abspath + +# Environment for base library +core_env = env.Clone(); + +core_env.sources = sorted(glob.glob(dir_path + "/*.cpp")) +core_env.headers = sorted(glob.glob(dir_path + "/*.h")) +core_env.distance_headers = sorted(glob.glob(dir_path + "/distance/*.h")) +core_env.time_headers = sorted(glob.glob(dir_path + "/time/*.h")) + +env.sources += core_env.sources; +env.headers += core_env.headers; + +## Shared lib +objects_shared = [] +core_env.add_source_files(objects_shared, core_env.sources, shared=True); +core_env.library_shared = core_env.SharedLibrary('#build/kel-unit', [objects_shared]); + +# Set Alias +env.Alias('library_core', [core_env.library_shared]); + +env.targets += ['library_core']; + +# Install +env.Install('$prefix/lib/', [core_env.library_shared]); +env.Install('$prefix/include/kel/unit', [core_env.headers]); +env.Install('$prefix/include/kel/unit/distance', [core_env.distance_headers]); +env.Install('$prefix/include/kel/unit/time', [core_env.time_headers]); diff --git a/c++/distance/meter.h b/c++/distance/meter.h new file mode 100644 index 0000000..0d9fb3b --- /dev/null +++ b/c++/distance/meter.h @@ -0,0 +1,20 @@ +#pragma once + +#include "../unit.h" + +#include <string_view> + +namespace kel { +namespace unit_type { +struct meter{ + static constexpr std::string_view name = "meter"; + static constexpr std::string_view short_name = "m"; +}; +} + +template<typename S> +using meter = unit<S,unit_component<unit_type::meter,1>>; + +template<typename S> +using square_meter = unit<S,unit_component<unit_type::meter,2>>; +} diff --git a/c++/time/second.h b/c++/time/second.h new file mode 100644 index 0000000..6dca456 --- /dev/null +++ b/c++/time/second.h @@ -0,0 +1,15 @@ +#pragma once + +#include "../unit.h" + +namespace kel { +namespace unit_type { +struct second{ + static constexpr std::string_view name = "second"; + static constexpr std::string_view short_name = "s"; +}; +} + +template<typename S> +using second = unit<S,unit_component<unit_type::second,1>>; +} diff --git a/c++/unit.h b/c++/unit.h new file mode 100644 index 0000000..a8e8320 --- /dev/null +++ b/c++/unit.h @@ -0,0 +1,49 @@ +#pragma once + +#include "unit_reduction.h" + +namespace kel { +template<typename UnitType, int64_t Exponent> +struct unit_component {}; + +template<typename StorageT, typename... T> +class unit; + +template<typename StorageT, typename... UnitTypes, int64_t... Exponents> +class unit<StorageT, unit_component<UnitTypes, Exponents>...> { +public: + using value_type = StorageT; + + unit() = default; + + unit(const unit<StorageT,unit_component<UnitTypes, Exponents>...>&) = default; + unit(unit<StorageT,unit_component<UnitTypes,Exponents>...>&&) = default; + + unit<StorageT,unit_component<UnitTypes,Exponents>...>& operator=(const unit<StorageT,unit_component<UnitTypes,Exponents>...>&) = default; + unit<StorageT,unit_component<UnitTypes,Exponents>...>& operator=(unit<StorageT,unit_component<UnitTypes,Exponents>...>&&) = default; + + unit(const value_type&); + unit(value_type&&); + + unit<StorageT,unit_component<UnitTypes,Exponents>...>& operator=(const value_type&); + unit<StorageT,unit_component<UnitTypes,Exponents>...>& operator=(value_type&&); + + unit<StorageT,unit_component<UnitTypes,Exponents>...> operator+(const unit<StorageT,unit_component<UnitTypes,Exponents>...>& rhs); + unit<StorageT,unit_component<UnitTypes,Exponents>...> operator-(const unit<StorageT,unit_component<UnitTypes,Exponents>...>& rhs); + + template<typename... Trhs> + typename unit_multiplication<unit<StorageT,unit_component<UnitTypes,Exponents>...>, unit<StorageT,Trhs...>>::type operator*(const unit<StorageT, Trhs...>& rhs); + + template<typename... Trhs> + typename unit_multiplication<unit<StorageT, unit_component<UnitTypes,Exponents>...>, typename unit_invert<StorageT,Trhs...>::type>::type operator/(const unit<StorageT, Trhs...>& rhs); + + value_type data() const; +private: + value_type value; +}; + +template<typename S> +using scalar = unit<S>; +} + +#include "unit.tmpl.h" diff --git a/c++/unit.tmpl.h b/c++/unit.tmpl.h new file mode 100644 index 0000000..d89e0c1 --- /dev/null +++ b/c++/unit.tmpl.h @@ -0,0 +1,53 @@ +#include <utility> + +namespace kelun { + +template<typename StorageT, typename... UnitTypes, int64_t... Exponents> +unit<StorageT,unit_component<UnitTypes, Exponents>...>::unit(const value_type& value_): + value{value_}{} + +template<typename StorageT, typename... UnitTypes, int64_t... Exponents> +unit<StorageT,unit_component<UnitTypes, Exponents>...>::unit(value_type&& value_):value{std::move(value_)}{} + +template<typename StorageT, typename... UnitTypes, int64_t... Exponents> +unit<StorageT,unit_component<UnitTypes, Exponents>...>& unit<StorageT,unit_component<UnitTypes, Exponents>...>::operator=(const typename unit<StorageT,unit_component<UnitTypes, Exponents>...>::value_type& value_){ + value = value_; + return *this; +} + +template<typename StorageT, typename... UnitTypes, int64_t... Exponents> +unit<StorageT,unit_component<UnitTypes, Exponents>...>& unit<StorageT,unit_component<UnitTypes, Exponents>...>::operator=(typename unit<StorageT,unit_component<UnitTypes, Exponents>...>::value_type&& value_){ + value = std::move(value_); + return *this; +} + +template<typename StorageT, typename... UnitTypes, int64_t... Exponents> +unit<StorageT,unit_component<UnitTypes, Exponents>...> unit<StorageT,unit_component<UnitTypes, Exponents>...>::operator+(const unit<StorageT,unit_component<UnitTypes, Exponents>...>& rhs){ + return value + rhs.value; +} + +template<typename StorageT, typename... UnitTypes, int64_t... Exponents> +unit<StorageT,unit_component<UnitTypes, Exponents>...> unit<StorageT,unit_component<UnitTypes, Exponents>...>::operator-(const unit<StorageT,unit_component<UnitTypes, Exponents>...>& rhs){ + return value - rhs.value; +} + +template<typename StorageT, typename... UnitTypes, int64_t... Exponents> +template<typename... Trhs> +typename unit_multiplication<unit<StorageT,unit_component<UnitTypes,Exponents>...>, unit<StorageT, Trhs...>>::type +unit<StorageT,unit_component<UnitTypes, Exponents>...>::operator*(const unit<StorageT,Trhs...>& rhs){ + return value * rhs.data(); +} + +template<typename StorageT, typename... UnitTypes, int64_t... Exponents> +template<typename... Trhs> +typename unit_multiplication<unit<StorageT,unit_component<UnitTypes,Exponents>...>, typename unit_invert<StorageT,Trhs...>::type>::type +unit<StorageT,unit_component<UnitTypes,Exponents>...>::operator/(const unit<StorageT, Trhs...>& rhs){ + typename unit_invert<StorageT, Trhs...>::type rhs_inverted{static_cast<StorageT>(1)/rhs.data()}; + return value * rhs_inverted.data(); +} + +template<typename StorageT, typename... UnitTypes, int64_t... Exponents> +typename unit<StorageT,unit_component<UnitTypes, Exponents>...>::value_type unit<StorageT,unit_component<UnitTypes, Exponents>...>::data() const { + return value; +} +} diff --git a/c++/unit_cast.h b/c++/unit_cast.h new file mode 100644 index 0000000..8dc2689 --- /dev/null +++ b/c++/unit_cast.h @@ -0,0 +1,15 @@ +#pragma once + +#include <forstio/core/common.h> + +namespace kel { +template<typename S, typename From, typename To> +class unit_convert { + static_assert(always_false<S, From, To>, "Units can't be converted to each other"); +}; + +template<typename Store, typename Same> +class unit_convert<Store, Same, Same> { + static constexpr factor = static_cast<Store>(1); +}; +} diff --git a/c++/unit_print.h b/c++/unit_print.h new file mode 100644 index 0000000..0f3cb72 --- /dev/null +++ b/c++/unit_print.h @@ -0,0 +1,55 @@ +#include "./unit.h" + +#include <iostream> + + +namespace std { +template<typename UnitT, int64_t UnitE> +inline ostream& operator<<(ostream& o, const kelun::unit_base<UnitT,UnitE>& ele){ + o<<UnitT::short_name; + if constexpr ( UnitE != 1 ){ + o<<'^'<<'('<<UnitE<<')'; + } + return o; +} +} + +namespace kelun { +template<typename... T> +struct unit_print_impl { + static_assert(is_always_false<T...>, "Template type not supported"); +}; + +template<typename UnitT, int64_t UnitE, typename... UnitTL, int64_t... UnitEL> +struct unit_print_impl<unit_base<UnitT,UnitE>,unit_base<UnitTL,UnitEL>...> { + static std::ostream& print(std::ostream& o){ + + unit_base<UnitT,UnitE> element; + + std::ostream& o_ret = o << element; + + if constexpr (sizeof...(UnitTL) > 0){ + std::ostream& o_ret_next = o_ret << ' ' << '*' << ' '; + return unit_print_impl<unit_base<UnitTL,UnitEL>...>::print(o_ret_next); + } + + return o_ret<<']'; + } +}; +} + +namespace std { + +template<typename StorageT, typename... T> +inline ostream& operator<<(ostream& o, const kelun::unit<StorageT,T...>& unit); + +template<typename StorageT, typename... UnitT, int64_t... UnitE> +inline ostream& operator<<(ostream& o, const kelun::unit<StorageT,kelun::unit_base<UnitT,UnitE>...>& unit){ + o << unit.data(); + if constexpr (sizeof...(UnitT) > 0) { + auto& o_ret = o << ' '<<'['; + return kelun::unit_print_impl<kelun::unit_base<UnitT,UnitE>...>::print(o_ret); + } + return o; +} +} diff --git a/c++/unit_reduction.h b/c++/unit_reduction.h new file mode 100644 index 0000000..d9060d2 --- /dev/null +++ b/c++/unit_reduction.h @@ -0,0 +1,133 @@ +#pragma once + +#include <cstdint> +#include <type_traits> + +namespace kelun { +template<typename... T> +constexpr bool is_always_false = false; + +template<typename UnitType, int64_t Exponent> +struct unit_component; + +template<typename StorageT, typename... T> +class unit; + +namespace impl { + +template<typename T, typename U> +class unit_matching; + +template<typename... T> +class unit_redux_list { + static_assert(sizeof...(T) == 0, "Template type not supported"); + + using reduced_typed = unit_redux_list<>; +}; + +template<typename T0, int64_t E0, typename... TL, int64_t... EL> +struct unit_redux_list<unit_component<T0,E0>, unit_component<TL,EL>...> { + using reduced_type = typename unit_matching<unit_redux_list<unit_component<T0,E0>, unit_component<TL,EL>...>, unit_redux_list<>>::type; +}; + +template<typename T, typename U, typename V> +class unit_matching_reduce { +public: + static_assert(is_always_false<T, U, V>, "Template type not supported"); +}; + +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<unit_component<T,E>, unit_redux_list<unit_component<T0,E0>,unit_component<TL,EL>...>, unit_redux_list<unit_component<TR,ER>...>> { +public: + static constexpr bool is_same = std::is_same_v<T,T0>; + + using match_reduce_type = typename std::conditional<is_same, unit_component<T,E+E0>, unit_component<T,E>>::type; + using match_reduce_unit_redux_list = typename std::conditional<is_same, unit_redux_list<unit_component<TR,ER>...>, unit_redux_list<unit_component<TR,ER>..., unit_component<T0,E0>>>::type; + + using value_type = typename unit_matching_reduce<match_reduce_type, unit_redux_list<unit_component<TL,EL>...>, match_reduce_unit_redux_list>::value_type; + using unit_redux_list_type = typename unit_matching_reduce<match_reduce_type, unit_redux_list<unit_component<TL,EL>...>, match_reduce_unit_redux_list>::unit_redux_list_type; + + static constexpr int64_t value_num = unit_matching_reduce<match_reduce_type, unit_redux_list<unit_component<TL,EL>...>, match_reduce_unit_redux_list>::value_num; +}; + +template<typename T, int64_t E, typename... TR, int64_t... ER> +class unit_matching_reduce<unit_component<T,E>, unit_redux_list<>, unit_redux_list<unit_component<TR,ER>...>> { +public: + using value_type = unit_component<T,E>; + using unit_redux_list_type = unit_redux_list<unit_component<TR,ER>...>; + + static constexpr int64_t value_num = E; +}; + +template<typename T, typename U> +class unit_matching { + static_assert(is_always_false<T, U>, "Template type not supported"); +}; + +template<typename... T, int64_t... E> +class unit_matching<unit_redux_list<>,unit_redux_list<unit_component<T,E>...>> { +public: + using type = unit_redux_list<unit_component<T,E>...>; + +}; + +template<typename T0, int64_t E0, typename... TL, int64_t... EL, typename... TR, int64_t... ER> +class unit_matching<unit_redux_list<unit_component<T0,E0>,unit_component<TL,EL>...>, unit_redux_list<unit_component<TR,ER>...>> { +public: + using reduced_value_type = typename unit_matching_reduce<unit_component<T0,E0>, unit_redux_list<unit_component<TL,EL>...>, unit_redux_list<>>::value_type; + using reduced_unit_redux_list_type = typename unit_matching_reduce<unit_component<T0,E0>, unit_redux_list<unit_component<TL,EL>...>, unit_redux_list<>>::unit_redux_list_type; + + static constexpr int64_t reduced_value_num = unit_matching_reduce<unit_component<T0,E0>, unit_redux_list<unit_component<TL,EL>...>, unit_redux_list<>>::value_num; + using reduced_result_unit_redux_list = typename std::conditional<reduced_value_num == 0, unit_redux_list<unit_component<TR,ER>...>, unit_redux_list<unit_component<TR,ER>...,reduced_value_type>>::type; + + using type = typename unit_matching<reduced_unit_redux_list_type, reduced_result_unit_redux_list>::type; +}; + +template<typename List, typename StorageT> +class unit_matching_add_storage { +public: + static_assert(is_always_false<List,StorageT>, "Template type not supported"); +}; + +template<typename StorageT, typename... UnitTypes, int64_t... UnitExponents> +class unit_matching_add_storage<unit_redux_list<unit_component<UnitTypes,UnitExponents>...>, StorageT> { +public: + using type = unit<StorageT, unit_component<UnitTypes,UnitExponents>...>; +}; + +} + +template<typename StorageT, typename... T> +class unit_reduction { + static_assert(is_always_false<StorageT,T...>, "Template type not supported"); +}; + +template<typename StorageT, typename... UnitT, int64_t... UnitE> +class unit_reduction<StorageT, unit_component<UnitT, UnitE>...> { +public: + using list_type = typename impl::unit_matching<impl::unit_redux_list<unit_component<UnitT, UnitE>...>, impl::unit_redux_list<>>::type; + using type = typename impl::unit_matching_add_storage<list_type, StorageT>::type; +}; + +template<typename StorageT, typename... T> +class unit_invert { + static_assert(is_always_false<StorageT, T...>, "Template type not supported"); +}; + +template<typename StorageT, typename... UnitT, int64_t... UnitE> +class unit_invert<StorageT, unit_component<UnitT, UnitE>...> { +public: + using type = unit<StorageT, unit_component<UnitT, -UnitE>...>; +}; + +template<typename T, typename U> +class unit_multiplication{ + static_assert(is_always_false<T, U>, "Template type not supported"); +}; + +template<typename StorageT, typename... UnitT, int64_t... UnitE, typename... UnitRhsT, int64_t... UnitRhsE> +class unit_multiplication<unit<StorageT, unit_component<UnitT,UnitE>...>, unit<StorageT, unit_component<UnitRhsT, UnitRhsE>...>> { +public: + using type = typename unit_reduction<StorageT, unit_component<UnitT,UnitE>..., unit_component<UnitRhsT, UnitRhsE>...>::type; +}; +} |