From 488653602d0636a1fa5ef6e64cabb9b903dce42a Mon Sep 17 00:00:00 2001 From: "Claudius \"keldu\" Holeksa" Date: Fri, 25 Aug 2023 10:10:51 +0200 Subject: Renamed src folder to c++ --- c++/SConscript | 37 ++++++++++++++ c++/distance/meter.h | 20 ++++++++ c++/time/second.h | 15 ++++++ c++/unit.h | 49 +++++++++++++++++++ c++/unit.tmpl.h | 53 ++++++++++++++++++++ c++/unit_cast.h | 15 ++++++ c++/unit_print.h | 55 +++++++++++++++++++++ c++/unit_reduction.h | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 377 insertions(+) create mode 100644 c++/SConscript create mode 100644 c++/distance/meter.h create mode 100644 c++/time/second.h create mode 100644 c++/unit.h create mode 100644 c++/unit.tmpl.h create mode 100644 c++/unit_cast.h create mode 100644 c++/unit_print.h create mode 100644 c++/unit_reduction.h (limited to 'c++') 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 + +namespace kel { +namespace unit_type { +struct meter{ + static constexpr std::string_view name = "meter"; + static constexpr std::string_view short_name = "m"; +}; +} + +template +using meter = unit>; + +template +using square_meter = unit>; +} 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 +using second = unit>; +} 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 +struct unit_component {}; + +template +class unit; + +template +class unit...> { +public: + using value_type = StorageT; + + unit() = default; + + unit(const unit...>&) = default; + unit(unit...>&&) = default; + + unit...>& operator=(const unit...>&) = default; + unit...>& operator=(unit...>&&) = default; + + unit(const value_type&); + unit(value_type&&); + + unit...>& operator=(const value_type&); + unit...>& operator=(value_type&&); + + unit...> operator+(const unit...>& rhs); + unit...> operator-(const unit...>& rhs); + + template + typename unit_multiplication...>, unit>::type operator*(const unit& rhs); + + template + typename unit_multiplication...>, typename unit_invert::type>::type operator/(const unit& rhs); + + value_type data() const; +private: + value_type value; +}; + +template +using scalar = unit; +} + +#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 + +namespace kelun { + +template +unit...>::unit(const value_type& value_): + value{value_}{} + +template +unit...>::unit(value_type&& value_):value{std::move(value_)}{} + +template +unit...>& unit...>::operator=(const typename unit...>::value_type& value_){ + value = value_; + return *this; +} + +template +unit...>& unit...>::operator=(typename unit...>::value_type&& value_){ + value = std::move(value_); + return *this; +} + +template +unit...> unit...>::operator+(const unit...>& rhs){ + return value + rhs.value; +} + +template +unit...> unit...>::operator-(const unit...>& rhs){ + return value - rhs.value; +} + +template +template +typename unit_multiplication...>, unit>::type +unit...>::operator*(const unit& rhs){ + return value * rhs.data(); +} + +template +template +typename unit_multiplication...>, typename unit_invert::type>::type +unit...>::operator/(const unit& rhs){ + typename unit_invert::type rhs_inverted{static_cast(1)/rhs.data()}; + return value * rhs_inverted.data(); +} + +template +typename unit...>::value_type unit...>::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 + +namespace kel { +template +class unit_convert { + static_assert(always_false, "Units can't be converted to each other"); +}; + +template +class unit_convert { + static constexpr factor = static_cast(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 + + +namespace std { +template +inline ostream& operator<<(ostream& o, const kelun::unit_base& ele){ + o< +struct unit_print_impl { + static_assert(is_always_false, "Template type not supported"); +}; + +template +struct unit_print_impl,unit_base...> { + static std::ostream& print(std::ostream& o){ + + unit_base element; + + std::ostream& o_ret = o << element; + + if constexpr (sizeof...(UnitTL) > 0){ + std::ostream& o_ret_next = o_ret << ' ' << '*' << ' '; + return unit_print_impl...>::print(o_ret_next); + } + + return o_ret<<']'; + } +}; +} + +namespace std { + +template +inline ostream& operator<<(ostream& o, const kelun::unit& unit); + +template +inline ostream& operator<<(ostream& o, const kelun::unit...>& unit){ + o << unit.data(); + if constexpr (sizeof...(UnitT) > 0) { + auto& o_ret = o << ' '<<'['; + return kelun::unit_print_impl...>::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 +#include + +namespace kelun { +template +constexpr bool is_always_false = false; + +template +struct unit_component; + +template +class unit; + +namespace impl { + +template +class unit_matching; + +template +class unit_redux_list { + static_assert(sizeof...(T) == 0, "Template type not supported"); + + using reduced_typed = unit_redux_list<>; +}; + +template +struct unit_redux_list, unit_component...> { + using reduced_type = typename unit_matching, unit_component...>, unit_redux_list<>>::type; +}; + +template +class unit_matching_reduce { +public: + static_assert(is_always_false, "Template type not supported"); +}; + +template +class unit_matching_reduce, unit_redux_list,unit_component...>, unit_redux_list...>> { +public: + static constexpr bool is_same = std::is_same_v; + + using match_reduce_type = typename std::conditional, unit_component>::type; + using match_reduce_unit_redux_list = typename std::conditional...>, unit_redux_list..., unit_component>>::type; + + using value_type = typename unit_matching_reduce...>, match_reduce_unit_redux_list>::value_type; + using unit_redux_list_type = typename unit_matching_reduce...>, match_reduce_unit_redux_list>::unit_redux_list_type; + + static constexpr int64_t value_num = unit_matching_reduce...>, match_reduce_unit_redux_list>::value_num; +}; + +template +class unit_matching_reduce, unit_redux_list<>, unit_redux_list...>> { +public: + using value_type = unit_component; + using unit_redux_list_type = unit_redux_list...>; + + static constexpr int64_t value_num = E; +}; + +template +class unit_matching { + static_assert(is_always_false, "Template type not supported"); +}; + +template +class unit_matching,unit_redux_list...>> { +public: + using type = unit_redux_list...>; + +}; + +template +class unit_matching,unit_component...>, unit_redux_list...>> { +public: + using reduced_value_type = typename unit_matching_reduce, unit_redux_list...>, unit_redux_list<>>::value_type; + using reduced_unit_redux_list_type = typename unit_matching_reduce, unit_redux_list...>, unit_redux_list<>>::unit_redux_list_type; + + static constexpr int64_t reduced_value_num = unit_matching_reduce, unit_redux_list...>, unit_redux_list<>>::value_num; + using reduced_result_unit_redux_list = typename std::conditional...>, unit_redux_list...,reduced_value_type>>::type; + + using type = typename unit_matching::type; +}; + +template +class unit_matching_add_storage { +public: + static_assert(is_always_false, "Template type not supported"); +}; + +template +class unit_matching_add_storage...>, StorageT> { +public: + using type = unit...>; +}; + +} + +template +class unit_reduction { + static_assert(is_always_false, "Template type not supported"); +}; + +template +class unit_reduction...> { +public: + using list_type = typename impl::unit_matching...>, impl::unit_redux_list<>>::type; + using type = typename impl::unit_matching_add_storage::type; +}; + +template +class unit_invert { + static_assert(is_always_false, "Template type not supported"); +}; + +template +class unit_invert...> { +public: + using type = unit...>; +}; + +template +class unit_multiplication{ + static_assert(is_always_false, "Template type not supported"); +}; + +template +class unit_multiplication...>, unit...>> { +public: + using type = typename unit_reduction..., unit_component...>::type; +}; +} -- cgit v1.2.3