diff --git a/test/metabench/CMakeLists.txt b/test/metabench/CMakeLists.txt index c1188dc1..d0c4f10a 100644 --- a/test/metabench/CMakeLists.txt +++ b/test/metabench/CMakeLists.txt @@ -40,5 +40,6 @@ enable_testing() add_custom_target(metabench) -add_subdirectory(ratio) add_subdirectory(list) +add_subdirectory(make_dimension) +add_subdirectory(ratio) diff --git a/test/metabench/make_dimension/CMakeLists.txt b/test/metabench/make_dimension/CMakeLists.txt new file mode 100644 index 00000000..63fdff45 --- /dev/null +++ b/test/metabench/make_dimension/CMakeLists.txt @@ -0,0 +1,36 @@ +# The MIT License (MIT) +# +# Copyright (c) 2018 Mateusz Pusz +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +add_metabench_test(metabench.data.make_dimension.no_concepts "no concepts" no_concepts.cpp.erb "[1, 2, 3, 4, 6, 8, 10]") +add_metabench_test(metabench.data.make_dimension.concepts_iface "concepts iface" concepts_iface.cpp.erb "[1, 2, 3, 4, 6, 8, 10]") +add_metabench_test(metabench.data.make_dimension.concepts_all "concepts all" concepts_all.cpp.erb "[1, 2, 3, 4, 6, 8, 10]") +metabench_add_chart(metabench.chart.make_dimension + TITLE "100 x make_dimension" + SUBTITLE "(lower is better)" + DATASETS + metabench.data.make_dimension.no_concepts + metabench.data.make_dimension.concepts_iface + metabench.data.make_dimension.concepts_all +) + +add_dependencies(metabench metabench.chart.make_dimension) diff --git a/test/metabench/make_dimension/concepts_all.cpp.erb b/test/metabench/make_dimension/concepts_all.cpp.erb new file mode 100644 index 00000000..cc9aa860 --- /dev/null +++ b/test/metabench/make_dimension/concepts_all.cpp.erb @@ -0,0 +1,25 @@ +#include "dimension_concepts_all.h" + +namespace stde = std::experimental; + +<% (1..100).each do |k| %> +struct test<%= k %> { + <% (1..n).each do |i| %> + static constexpr stde::units::base_dimension dim<%= i %>{"dim<%= i %>"}; + <% end %> + +#if defined(METABENCH) + using dim = stde::units::make_dimension_t<<%= + xs = ((1)..(n)).map { |j| "stde::units::exp" } + rng = Random.new(k) + xs.shuffle(random: rng).join(', ') + %>>; +#else + using dim = void; +#endif +}; +<% end %> + +int main() +{ +} diff --git a/test/metabench/make_dimension/concepts_iface.cpp.erb b/test/metabench/make_dimension/concepts_iface.cpp.erb new file mode 100644 index 00000000..b407542a --- /dev/null +++ b/test/metabench/make_dimension/concepts_iface.cpp.erb @@ -0,0 +1,25 @@ +#include "dimension_concepts_iface.h" + +namespace stde = std::experimental; + +<% (1..100).each do |k| %> +struct test<%= k %> { + <% (1..n).each do |i| %> + static constexpr stde::units::base_dimension dim<%= i %>{"dim<%= i %>"}; + <% end %> + +#if defined(METABENCH) + using dim = stde::units::make_dimension_t<<%= + xs = ((1)..(n)).map { |j| "stde::units::exp" } + rng = Random.new(k) + xs.shuffle(random: rng).join(', ') + %>>; +#else + using dim = void; +#endif +}; +<% end %> + +int main() +{ +} diff --git a/test/metabench/make_dimension/dimension_concepts_all.h b/test/metabench/make_dimension/dimension_concepts_all.h new file mode 100644 index 00000000..b44517c2 --- /dev/null +++ b/test/metabench/make_dimension/dimension_concepts_all.h @@ -0,0 +1,216 @@ +// The MIT License (MIT) +// +// Copyright (c) 2018 Mateusz Pusz +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#include "type_list_concepts_all.h" +#include "downcasting_concepts_all.h" +#include "ratio_concepts_all.h" +#include + +namespace std::experimental::units { + + struct base_dimension { + const char* name; + }; + + constexpr bool operator==(const base_dimension& lhs, const base_dimension& rhs) + { + const char* p1 = lhs.name; + const char* p2 = rhs.name; + for(; (*p1 != '\0') && (*p2 != '\0'); ++p1, (void)++p2) { + if(*p1 != *p2) return false; + } + return *p1 == *p2; + } + + constexpr bool operator<(const base_dimension& lhs, const base_dimension& rhs) + { + const char* p1 = lhs.name; + const char* p2 = rhs.name; + for(; (*p1 != '\0') && (*p2 != '\0'); ++p1, (void)++p2) { + if(*p1 < *p2) return true; + if(*p2 < *p1) return false; + } + return (*p1 == '\0') && (*p2 != '\0'); + } + + // base_dimension_less + + template + struct base_dimension_less : std::bool_constant { + }; + + // exp + + template + struct exp { + static constexpr const base_dimension& dimension = BaseDimension; + static constexpr int num = Num; + static constexpr int den = Den; + }; + + // is_exp + namespace detail { + template + inline constexpr bool is_exp = false; + + template + inline constexpr bool is_exp> = true; + } // namespace detail + + template + concept bool Exponent = detail::is_exp; + + // exp_dim_id_less + + template + struct exp_less : base_dimension_less { + }; + + // exp_invert + + template + struct exp_invert; + + template + struct exp_invert> { + using type = exp; + }; + + template + using exp_invert_t = exp_invert::type; + + // dimension + + template + struct dimension : downcast_base> {}; + + // is_dimension + namespace detail { + + template + inline constexpr bool is_dimension = false; + + template + inline constexpr bool is_dimension> = true; + + } // namespace detail + + template + concept bool Dimension = + std::is_empty_v && + detail::is_dimension>; + + + // dim_invert + + template + struct dim_invert; + + template + struct dim_invert> : std::type_identity...>>> {}; + + template + using dim_invert_t = dim_invert::type; + + + // todo: force as the only user interface to create dimensions through modules + // make_dimension + + namespace detail { + + template + struct dim_consolidate; + + template + using dim_consolidate_t = dim_consolidate::type; + + template<> + struct dim_consolidate> { + using type = dimension<>; + }; + + template + struct dim_consolidate> { + using type = dimension; + }; + + template + struct dim_consolidate> { + using rest = dim_consolidate_t>; + using type = conditional>, dimension, type_list_push_front>; + }; + + template + struct dim_consolidate, exp, ERest...>> { + // todo: provide custom implementation for ratio_add + using r1 = std::ratio; + using r2 = std::ratio; + using r = std::ratio_add; + using type = conditional>, + dim_consolidate_t, ERest...>>>; + }; + + } // namespace detail + + template + struct make_dimension { + using type = detail::dim_consolidate_t, exp_less>>; + }; + + template + using make_dimension_t = make_dimension::type; + + template + struct merge_dimension { + using type = detail::dim_consolidate_t>; + }; + + template + using merge_dimension_t = merge_dimension::type; + + // dimension_multiply + + template + struct dimension_multiply; + + template + struct dimension_multiply, dimension> : std::type_identity, dimension>>> {}; + + template + using dimension_multiply_t = dimension_multiply::type; + + // dimension_divide + + template + struct dimension_divide; + + template + struct dimension_divide, dimension> + : dimension_multiply, dimension...>> { + }; + + template + using dimension_divide_t = dimension_divide::type; + +} // namespace std::experimental::units diff --git a/test/metabench/make_dimension/dimension_concepts_iface.h b/test/metabench/make_dimension/dimension_concepts_iface.h new file mode 100644 index 00000000..46b67e87 --- /dev/null +++ b/test/metabench/make_dimension/dimension_concepts_iface.h @@ -0,0 +1,216 @@ +// The MIT License (MIT) +// +// Copyright (c) 2018 Mateusz Pusz +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#include "type_list_concepts_iface.h" +#include "downcasting_concepts_all.h" +#include "ratio_concepts_iface.h" +#include + +namespace std::experimental::units { + + struct base_dimension { + const char* name; + }; + + constexpr bool operator==(const base_dimension& lhs, const base_dimension& rhs) + { + const char* p1 = lhs.name; + const char* p2 = rhs.name; + for(; (*p1 != '\0') && (*p2 != '\0'); ++p1, (void)++p2) { + if(*p1 != *p2) return false; + } + return *p1 == *p2; + } + + constexpr bool operator<(const base_dimension& lhs, const base_dimension& rhs) + { + const char* p1 = lhs.name; + const char* p2 = rhs.name; + for(; (*p1 != '\0') && (*p2 != '\0'); ++p1, (void)++p2) { + if(*p1 < *p2) return true; + if(*p2 < *p1) return false; + } + return (*p1 == '\0') && (*p2 != '\0'); + } + + // base_dimension_less + + template + struct base_dimension_less : std::bool_constant { + }; + + // exp + + template + struct exp { + static constexpr const base_dimension& dimension = BaseDimension; + static constexpr int num = Num; + static constexpr int den = Den; + }; + + // is_exp + namespace detail { + template + inline constexpr bool is_exp = false; + + template + inline constexpr bool is_exp> = true; + } // namespace detail + + template + concept bool Exponent = detail::is_exp; + + // exp_dim_id_less + + template + struct exp_less : base_dimension_less { + }; + + // exp_invert + + template + struct exp_invert; + + template + struct exp_invert> { + using type = exp; + }; + + template + using exp_invert_t = exp_invert::type; + + // dimension + + template + struct dimension : downcast_base> {}; + + // is_dimension + namespace detail { + + template + inline constexpr bool is_dimension = false; + + template + inline constexpr bool is_dimension> = true; + + } // namespace detail + + template + concept bool Dimension = + std::is_empty_v && + detail::is_dimension>; + + + // dim_invert + + template + struct dim_invert; + + template + struct dim_invert> : std::type_identity...>>> {}; + + template + using dim_invert_t = dim_invert::type; + + + // todo: force as the only user interface to create dimensions through modules + // make_dimension + + namespace detail { + + template + struct dim_consolidate; + + template + using dim_consolidate_t = dim_consolidate::type; + + template<> + struct dim_consolidate> { + using type = dimension<>; + }; + + template + struct dim_consolidate> { + using type = dimension; + }; + + template + struct dim_consolidate> { + using rest = dim_consolidate_t>; + using type = conditional>, dimension, type_list_push_front>; + }; + + template + struct dim_consolidate, exp, ERest...>> { + // todo: provide custom implementation for ratio_add + using r1 = std::ratio; + using r2 = std::ratio; + using r = std::ratio_add; + using type = conditional>, + dim_consolidate_t, ERest...>>>; + }; + + } // namespace detail + + template + struct make_dimension { + using type = detail::dim_consolidate_t, exp_less>>; + }; + + template + using make_dimension_t = make_dimension::type; + + template + struct merge_dimension { + using type = detail::dim_consolidate_t>; + }; + + template + using merge_dimension_t = merge_dimension::type; + + // dimension_multiply + + template + struct dimension_multiply; + + template + struct dimension_multiply, dimension> : std::type_identity, dimension>>> {}; + + template + using dimension_multiply_t = dimension_multiply::type; + + // dimension_divide + + template + struct dimension_divide; + + template + struct dimension_divide, dimension> + : dimension_multiply, dimension...>> { + }; + + template + using dimension_divide_t = dimension_divide::type; + +} // namespace std::experimental::units diff --git a/test/metabench/make_dimension/dimension_no_concepts.h b/test/metabench/make_dimension/dimension_no_concepts.h new file mode 100644 index 00000000..869c1aa7 --- /dev/null +++ b/test/metabench/make_dimension/dimension_no_concepts.h @@ -0,0 +1,187 @@ +// The MIT License (MIT) +// +// Copyright (c) 2018 Mateusz Pusz +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#include "type_list_no_concepts.h" +#include "downcasting_no_concepts.h" +#include "ratio_no_concepts.h" +#include + +namespace std::experimental::units { + + struct base_dimension { + const char* name; + }; + + constexpr bool operator==(const base_dimension& lhs, const base_dimension& rhs) + { + const char* p1 = lhs.name; + const char* p2 = rhs.name; + for(; (*p1 != '\0') && (*p2 != '\0'); ++p1, (void)++p2) { + if(*p1 != *p2) return false; + } + return *p1 == *p2; + } + + constexpr bool operator<(const base_dimension& lhs, const base_dimension& rhs) + { + const char* p1 = lhs.name; + const char* p2 = rhs.name; + for(; (*p1 != '\0') && (*p2 != '\0'); ++p1, (void)++p2) { + if(*p1 < *p2) return true; + if(*p2 < *p1) return false; + } + return (*p1 == '\0') && (*p2 != '\0'); + } + + // base_dimension_less + + template + struct base_dimension_less : std::bool_constant { + }; + + // exp + + template + struct exp { + static constexpr const base_dimension& dimension = BaseDimension; + static constexpr int num = Num; + static constexpr int den = Den; + }; + + // exp_dim_id_less + + template + struct exp_less : base_dimension_less { + }; + + // exp_invert + + template + struct exp_invert; + + template + struct exp_invert> { + using type = exp; + }; + + template + using exp_invert_t = exp_invert::type; + + // dimension + + template + struct dimension : downcast_base> {}; + + // dim_invert + + template + struct dim_invert; + + template + struct dim_invert> : std::type_identity...>>> {}; + + template + using dim_invert_t = dim_invert::type; + + + // todo: force as the only user interface to create dimensions through modules + // make_dimension + + namespace detail { + + template + struct dim_consolidate; + + template + using dim_consolidate_t = dim_consolidate::type; + + template<> + struct dim_consolidate> { + using type = dimension<>; + }; + + template + struct dim_consolidate> { + using type = dimension; + }; + + template + struct dim_consolidate> { + using rest = dim_consolidate_t>; + using type = conditional>, dimension, type_list_push_front>; + }; + + template + struct dim_consolidate, exp, ERest...>> { + // todo: provide custom implementation for ratio_add + using r1 = std::ratio; + using r2 = std::ratio; + using r = std::ratio_add; + using type = conditional>, + dim_consolidate_t, ERest...>>>; + }; + + } // namespace detail + + template + struct make_dimension { + using type = detail::dim_consolidate_t, exp_less>>; + }; + + template + using make_dimension_t = make_dimension::type; + + template + struct merge_dimension { + using type = detail::dim_consolidate_t>; + }; + + template + using merge_dimension_t = merge_dimension::type; + + // dimension_multiply + + template + struct dimension_multiply; + + template + struct dimension_multiply, dimension> : std::type_identity, dimension>>> {}; + + template + using dimension_multiply_t = dimension_multiply::type; + + // dimension_divide + + template + struct dimension_divide; + + template + struct dimension_divide, dimension> + : dimension_multiply, dimension...>> { + }; + + template + using dimension_divide_t = dimension_divide::type; + +} // namespace std::experimental::units diff --git a/test/metabench/make_dimension/downcasting_concepts_all.h b/test/metabench/make_dimension/downcasting_concepts_all.h new file mode 100644 index 00000000..f2fde3b6 --- /dev/null +++ b/test/metabench/make_dimension/downcasting_concepts_all.h @@ -0,0 +1,54 @@ +// The MIT License (MIT) +// +// Copyright (c) 2018 Mateusz Pusz +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#include "hacks.h" +#include + +namespace std::experimental::units { + + template + struct downcast_base { + using base_type = BaseType; + }; + + template + concept bool Downcastable = + requires { + typename T::base_type; + } && + std::derived_from>; + + template + using downcast_from = T::base_type; + + template + using downcast_to = std::type_identity; + + template + struct downcasting_traits : downcast_to {}; + + template + using downcasting_traits_t = downcasting_traits::type; + +} // namespace std::experimental::units diff --git a/test/metabench/make_dimension/downcasting_no_concepts.h b/test/metabench/make_dimension/downcasting_no_concepts.h new file mode 100644 index 00000000..17f5b883 --- /dev/null +++ b/test/metabench/make_dimension/downcasting_no_concepts.h @@ -0,0 +1,47 @@ +// The MIT License (MIT) +// +// Copyright (c) 2018 Mateusz Pusz +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#include "hacks.h" +#include + +namespace std::experimental::units { + + template + struct downcast_base { + using base_type = BaseType; + }; + + template + using downcast_from = T::base_type; + + template + using downcast_to = std::type_identity; + + template + struct downcasting_traits : downcast_to {}; + + template + using downcasting_traits_t = downcasting_traits::type; + +} // namespace std::experimental::units diff --git a/test/metabench/make_dimension/hacks.h b/test/metabench/make_dimension/hacks.h new file mode 100644 index 00000000..ac68447a --- /dev/null +++ b/test/metabench/make_dimension/hacks.h @@ -0,0 +1,43 @@ +// The MIT License (MIT) +// +// Copyright (c) 2018 Mateusz Pusz +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#include + +#ifdef NDEBUG +#define Expects(cond) (void)(cond); +#else +#include +#define Expects(cond) assert(cond); +#endif + +namespace std { + + // concepts + using experimental::ranges::same_as; + using experimental::ranges::derived_from; + using experimental::ranges::regular; + using experimental::ranges::totally_ordered; + using experimental::ranges::convertible_to; + +} diff --git a/test/metabench/make_dimension/no_concepts.cpp.erb b/test/metabench/make_dimension/no_concepts.cpp.erb new file mode 100644 index 00000000..422ac4fa --- /dev/null +++ b/test/metabench/make_dimension/no_concepts.cpp.erb @@ -0,0 +1,25 @@ +#include "dimension_no_concepts.h" + +namespace stde = std::experimental; + +<% (1..100).each do |k| %> +struct test<%= k %> { + <% (1..n).each do |i| %> + static constexpr stde::units::base_dimension dim<%= i %>{"dim<%= i %>"}; + <% end %> + +#if defined(METABENCH) + using dim = stde::units::make_dimension_t<<%= + xs = ((1)..(n)).map { |j| "stde::units::exp" } + rng = Random.new(k) + xs.shuffle(random: rng).join(', ') + %>>; +#else + using dim = void; +#endif +}; +<% end %> + +int main() +{ +} diff --git a/test/metabench/make_dimension/ratio_concepts_all.h b/test/metabench/make_dimension/ratio_concepts_all.h new file mode 100644 index 00000000..a77ae4d2 --- /dev/null +++ b/test/metabench/make_dimension/ratio_concepts_all.h @@ -0,0 +1,138 @@ +// The MIT License (MIT) +// +// Copyright (c) 2018 Mateusz Pusz +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#include "hacks.h" +#include +#include +#include + +namespace std::experimental::units { + + namespace detail { + + template + [[nodiscard]] constexpr T abs(T v) noexcept { return v < 0 ? -v : v; } + + } + + template + struct ratio { + static_assert(Den != 0, "zero denominator"); + static_assert(-INTMAX_MAX <= Num, "numerator too negative"); + static_assert(-INTMAX_MAX <= Den, "denominator too negative"); + + static constexpr std::intmax_t num = Num * (Den < 0 ? -1 : 1) / std::gcd(Num, Den); + static constexpr std::intmax_t den = detail::abs(Den) / std::gcd(Num, Den); + + using type = ratio; + }; + + // is_ratio + + namespace detail { + + template + inline constexpr bool is_ratio = false; + + template + inline constexpr bool is_ratio> = true; + + } // namespace detail + + template + concept bool Ratio = detail::is_ratio; + + // ratio_multiply + + namespace detail { + + static constexpr std::intmax_t safe_multiply(std::intmax_t lhs, std::intmax_t rhs) + { + constexpr std::uintmax_t c = std::uintmax_t(1) << (sizeof(std::intmax_t) * 4); + + const std::uintmax_t a0 = detail::abs(lhs) % c; + const std::uintmax_t a1 = detail::abs(lhs) / c; + const std::uintmax_t b0 = detail::abs(rhs) % c; + const std::uintmax_t b1 = detail::abs(rhs) / c; + + Expects(a1 == 0 || b1 == 0); // overflow in multiplication + Expects(a0 * b1 + b0 * a1 < (c >> 1)); // overflow in multiplication + Expects(b0 * a0 <= INTMAX_MAX); // overflow in multiplication + Expects((a0 * b1 + b0 * a1) * c <= INTMAX_MAX - b0 * a0); // overflow in multiplication + + return lhs * rhs; + } + + template + struct ratio_multiply_impl { + private: + static constexpr std::intmax_t gcd1 = std::gcd(R1::num, R2::den); + static constexpr std::intmax_t gcd2 = std::gcd(R2::num, R1::den); + + public: + using type = ratio; + static constexpr std::intmax_t num = type::num; + static constexpr std::intmax_t den = type::den; + }; + + } + + template + using ratio_multiply = detail::ratio_multiply_impl::type; + + // ratio_divide + + namespace detail { + + template + struct ratio_divide_impl { + static_assert(R2::num != 0, "division by 0"); + using type = ratio_multiply>; + static constexpr std::intmax_t num = type::num; + static constexpr std::intmax_t den = type::den; + }; + + } + + template + using ratio_divide = detail::ratio_divide_impl::type; + + // common_ratio + + namespace detail { + + // todo: simplified + template + struct common_ratio_impl { + static constexpr std::intmax_t gcd_num = std::gcd(R1::num, R2::num); + static constexpr std::intmax_t gcd_den = std::gcd(R1::den, R2::den); + using type = ratio; + }; + + } + + template + using common_ratio = detail::common_ratio_impl::type; + +} // namespace std::experimental::units diff --git a/test/metabench/make_dimension/ratio_concepts_iface.h b/test/metabench/make_dimension/ratio_concepts_iface.h new file mode 100644 index 00000000..c18b3e4b --- /dev/null +++ b/test/metabench/make_dimension/ratio_concepts_iface.h @@ -0,0 +1,138 @@ +// The MIT License (MIT) +// +// Copyright (c) 2018 Mateusz Pusz +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#include "hacks.h" +#include +#include +#include + +namespace std::experimental::units { + + namespace detail { + + template + [[nodiscard]] constexpr T abs(T v) noexcept { return v < 0 ? -v : v; } + + } + + template + struct ratio { + static_assert(Den != 0, "zero denominator"); + static_assert(-INTMAX_MAX <= Num, "numerator too negative"); + static_assert(-INTMAX_MAX <= Den, "denominator too negative"); + + static constexpr std::intmax_t num = Num * (Den < 0 ? -1 : 1) / std::gcd(Num, Den); + static constexpr std::intmax_t den = detail::abs(Den) / std::gcd(Num, Den); + + using type = ratio; + }; + + // is_ratio + + namespace detail { + + template + inline constexpr bool is_ratio = false; + + template + inline constexpr bool is_ratio> = true; + + } // namespace detail + + template + concept bool Ratio = detail::is_ratio; + + // ratio_multiply + + namespace detail { + + static constexpr std::intmax_t safe_multiply(std::intmax_t lhs, std::intmax_t rhs) + { + constexpr std::uintmax_t c = std::uintmax_t(1) << (sizeof(std::intmax_t) * 4); + + const std::uintmax_t a0 = detail::abs(lhs) % c; + const std::uintmax_t a1 = detail::abs(lhs) / c; + const std::uintmax_t b0 = detail::abs(rhs) % c; + const std::uintmax_t b1 = detail::abs(rhs) / c; + + Expects(a1 == 0 || b1 == 0); // overflow in multiplication + Expects(a0 * b1 + b0 * a1 < (c >> 1)); // overflow in multiplication + Expects(b0 * a0 <= INTMAX_MAX); // overflow in multiplication + Expects((a0 * b1 + b0 * a1) * c <= INTMAX_MAX - b0 * a0); // overflow in multiplication + + return lhs * rhs; + } + + template + struct ratio_multiply_impl { + private: + static constexpr std::intmax_t gcd1 = std::gcd(R1::num, R2::den); + static constexpr std::intmax_t gcd2 = std::gcd(R2::num, R1::den); + + public: + using type = ratio; + static constexpr std::intmax_t num = type::num; + static constexpr std::intmax_t den = type::den; + }; + + } + + template + using ratio_multiply = detail::ratio_multiply_impl::type; + + // ratio_divide + + namespace detail { + + template + struct ratio_divide_impl { + static_assert(R2::num != 0, "division by 0"); + using type = ratio_multiply>; + static constexpr std::intmax_t num = type::num; + static constexpr std::intmax_t den = type::den; + }; + + } + + template + using ratio_divide = detail::ratio_divide_impl::type; + + // common_ratio + + namespace detail { + + // todo: simplified + template + struct common_ratio_impl { + static constexpr std::intmax_t gcd_num = std::gcd(R1::num, R2::num); + static constexpr std::intmax_t gcd_den = std::gcd(R1::den, R2::den); + using type = ratio; + }; + + } + + template + using common_ratio = detail::common_ratio_impl::type; + +} // namespace std::experimental::units diff --git a/test/metabench/make_dimension/ratio_no_concepts.h b/test/metabench/make_dimension/ratio_no_concepts.h new file mode 100644 index 00000000..0e5ccacd --- /dev/null +++ b/test/metabench/make_dimension/ratio_no_concepts.h @@ -0,0 +1,123 @@ +// The MIT License (MIT) +// +// Copyright (c) 2018 Mateusz Pusz +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#include "hacks.h" +#include +#include +#include + +namespace std::experimental::units { + + namespace detail { + + template + [[nodiscard]] constexpr T abs(T v) noexcept { return v < 0 ? -v : v; } + + } + + template + struct ratio { + static_assert(Den != 0, "zero denominator"); + static_assert(-INTMAX_MAX <= Num, "numerator too negative"); + static_assert(-INTMAX_MAX <= Den, "denominator too negative"); + + static constexpr std::intmax_t num = Num * (Den < 0 ? -1 : 1) / std::gcd(Num, Den); + static constexpr std::intmax_t den = detail::abs(Den) / std::gcd(Num, Den); + + using type = ratio; + }; + + // ratio_multiply + + namespace detail { + + static constexpr std::intmax_t safe_multiply(std::intmax_t lhs, std::intmax_t rhs) + { + constexpr std::uintmax_t c = std::uintmax_t(1) << (sizeof(std::intmax_t) * 4); + + const std::uintmax_t a0 = detail::abs(lhs) % c; + const std::uintmax_t a1 = detail::abs(lhs) / c; + const std::uintmax_t b0 = detail::abs(rhs) % c; + const std::uintmax_t b1 = detail::abs(rhs) / c; + + Expects(a1 == 0 || b1 == 0); // overflow in multiplication + Expects(a0 * b1 + b0 * a1 < (c >> 1)); // overflow in multiplication + Expects(b0 * a0 <= INTMAX_MAX); // overflow in multiplication + Expects((a0 * b1 + b0 * a1) * c <= INTMAX_MAX - b0 * a0); // overflow in multiplication + + return lhs * rhs; + } + + template + struct ratio_multiply_impl { + private: + static constexpr std::intmax_t gcd1 = std::gcd(R1::num, R2::den); + static constexpr std::intmax_t gcd2 = std::gcd(R2::num, R1::den); + + public: + using type = ratio; + static constexpr std::intmax_t num = type::num; + static constexpr std::intmax_t den = type::den; + }; + + } + + template + using ratio_multiply = detail::ratio_multiply_impl::type; + + // ratio_divide + + namespace detail { + + template + struct ratio_divide_impl { + static_assert(R2::num != 0, "division by 0"); + using type = ratio_multiply>; + static constexpr std::intmax_t num = type::num; + static constexpr std::intmax_t den = type::den; + }; + + } + + template + using ratio_divide = detail::ratio_divide_impl::type; + + // common_ratio + + namespace detail { + + // todo: simplified + template + struct common_ratio_impl { + static constexpr std::intmax_t gcd_num = std::gcd(R1::num, R2::num); + static constexpr std::intmax_t gcd_den = std::gcd(R1::den, R2::den); + using type = ratio; + }; + + } + + template + using common_ratio = detail::common_ratio_impl::type; + +} // namespace std::experimental::units diff --git a/test/metabench/make_dimension/type_list_concepts_all.h b/test/metabench/make_dimension/type_list_concepts_all.h new file mode 100644 index 00000000..a67ed8e3 --- /dev/null +++ b/test/metabench/make_dimension/type_list_concepts_all.h @@ -0,0 +1,185 @@ +// The MIT License (MIT) +// +// Copyright (c) 2018 Mateusz Pusz +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#include "type_traits.h" + +namespace std::experimental::units { + + namespace detail { + + template + inline constexpr bool is_type_list = false; + + template typename T, typename... Types> + inline constexpr bool is_type_list> = true; + + } // namespace detail + + template + concept bool TypeList = detail::is_type_list; + + // push_front + + namespace detail { + + template + struct type_list_push_front_impl; + + template typename List, typename... OldTypes, typename... NewTypes> + struct type_list_push_front_impl, NewTypes...> { + using type = List; + }; + + } + + template + using type_list_push_front = detail::type_list_push_front_impl::type; + + // push_back + + namespace detail { + + template + struct type_list_push_back_impl; + + template typename List, typename... OldTypes, typename... NewTypes> + struct type_list_push_back_impl, NewTypes...> { + using type = List; + }; + + } + + template + using type_list_push_back = detail::type_list_push_back_impl::type; + + // split + + namespace detail { + + template typename List, std::size_t Idx, std::size_t N, typename... Types> + struct split_impl; + + template typename List, std::size_t Idx, std::size_t N> + struct split_impl { + using first_list = List<>; + using second_list = List<>; + }; + + template typename List, std::size_t Idx, std::size_t N, typename T, typename... Rest> + struct split_impl : split_impl { + using base = split_impl; + using first_list = conditional::type, + typename base::first_list>; + using second_list = conditional::type>; + }; + + } // namespace detail + + template + struct type_list_split; + + template typename List, std::size_t N, typename... Types> + struct type_list_split, N> { + static_assert(N <= sizeof...(Types), "Invalid index provided"); + using split = detail::split_impl; + using first_list = split::first_list; + using second_list = split::second_list; + }; + + // split_half + + template + struct type_list_split_half; + + template typename List, typename... Types> + struct type_list_split_half> : type_list_split, (sizeof...(Types) + 1) / 2> { + }; + + // merge_sorted + + namespace detail { + + template typename Pred> + struct type_list_merge_sorted_impl; + + template typename List, typename... Lhs, template typename Pred> + struct type_list_merge_sorted_impl, List<>, Pred> { + using type = List; + }; + + template typename List, typename... Rhs, template typename Pred> + struct type_list_merge_sorted_impl, List, Pred> { + using type = List; + }; + + template typename List, typename Lhs1, typename... LhsRest, typename Rhs1, typename... RhsRest, + template typename Pred> + struct type_list_merge_sorted_impl, List, Pred> { + using type = conditional< + Pred::value, + typename type_list_push_front_impl, List, Pred>::type, Lhs1>::type, + typename type_list_push_front_impl, List, Pred>::type, Rhs1>::type>; + }; + + } + + template typename Pred> + using type_list_merge_sorted = detail::type_list_merge_sorted_impl::type; + + + // sort + + namespace detail { + + template typename Pred> + struct type_list_sort_impl; + + template typename List, template typename Pred> + struct type_list_sort_impl, Pred> { + using type = List<>; + }; + + template typename List, typename T, template typename Pred> + struct type_list_sort_impl, Pred> { + using type = List; + }; + + template typename List, typename... Types, template typename Pred> + struct type_list_sort_impl, Pred> { + using types = List; + using split = type_list_split_half>; + using left = type_list_sort_impl::type; + using right = type_list_sort_impl::type; + using type = type_list_merge_sorted_impl::type; + }; + + } + + template typename Pred> + using type_list_sort = detail::type_list_sort_impl::type; + +} // namespace std::experimental::units diff --git a/test/metabench/make_dimension/type_list_concepts_iface.h b/test/metabench/make_dimension/type_list_concepts_iface.h new file mode 100644 index 00000000..5fd73751 --- /dev/null +++ b/test/metabench/make_dimension/type_list_concepts_iface.h @@ -0,0 +1,185 @@ +// The MIT License (MIT) +// +// Copyright (c) 2018 Mateusz Pusz +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#include "type_traits.h" + +namespace std::experimental::units { + + namespace detail { + + template + inline constexpr bool is_type_list = false; + + template typename T, typename... Types> + inline constexpr bool is_type_list> = true; + + } // namespace detail + + template + concept bool TypeList = detail::is_type_list; + + // push_front + + namespace detail { + + template + struct type_list_push_front_impl; + + template typename List, typename... OldTypes, typename... NewTypes> + struct type_list_push_front_impl, NewTypes...> { + using type = List; + }; + + } + + template + using type_list_push_front = detail::type_list_push_front_impl::type; + + // push_back + + namespace detail { + + template + struct type_list_push_back_impl; + + template typename List, typename... OldTypes, typename... NewTypes> + struct type_list_push_back_impl, NewTypes...> { + using type = List; + }; + + } + + template + using type_list_push_back = detail::type_list_push_back_impl::type; + + // split + + namespace detail { + + template typename List, std::size_t Idx, std::size_t N, typename... Types> + struct split_impl; + + template typename List, std::size_t Idx, std::size_t N> + struct split_impl { + using first_list = List<>; + using second_list = List<>; + }; + + template typename List, std::size_t Idx, std::size_t N, typename T, typename... Rest> + struct split_impl : split_impl { + using base = split_impl; + using first_list = conditional::type, + typename base::first_list>; + using second_list = conditional::type>; + }; + + } // namespace detail + + template + struct type_list_split; + + template typename List, std::size_t N, typename... Types> + struct type_list_split, N> { + static_assert(N <= sizeof...(Types), "Invalid index provided"); + using split = detail::split_impl; + using first_list = split::first_list; + using second_list = split::second_list; + }; + + // split_half + + template + struct type_list_split_half; + + template typename List, typename... Types> + struct type_list_split_half> : type_list_split, (sizeof...(Types) + 1) / 2> { + }; + + // merge_sorted + + namespace detail { + + template typename Pred> + struct type_list_merge_sorted_impl; + + template typename List, typename... Lhs, template typename Pred> + struct type_list_merge_sorted_impl, List<>, Pred> { + using type = List; + }; + + template typename List, typename... Rhs, template typename Pred> + struct type_list_merge_sorted_impl, List, Pred> { + using type = List; + }; + + template typename List, typename Lhs1, typename... LhsRest, typename Rhs1, typename... RhsRest, + template typename Pred> + struct type_list_merge_sorted_impl, List, Pred> { + using type = conditional< + Pred::value, + typename type_list_push_front_impl, List, Pred>::type, Lhs1>::type, + typename type_list_push_front_impl, List, Pred>::type, Rhs1>::type>; + }; + + } + + template typename Pred> + using type_list_merge_sorted = detail::type_list_merge_sorted_impl::type; + + + // sort + + namespace detail { + + template typename Pred> + struct type_list_sort_impl; + + template typename List, template typename Pred> + struct type_list_sort_impl, Pred> { + using type = List<>; + }; + + template typename List, typename T, template typename Pred> + struct type_list_sort_impl, Pred> { + using type = List; + }; + + template typename List, typename... Types, template typename Pred> + struct type_list_sort_impl, Pred> { + using types = List; + using split = type_list_split_half>; + using left = type_list_sort_impl::type; + using right = type_list_sort_impl::type; + using type = type_list_merge_sorted_impl::type; + }; + + } + + template typename Pred> + using type_list_sort = detail::type_list_sort_impl::type; + +} // namespace std::experimental::units diff --git a/test/metabench/make_dimension/type_list_no_concepts.h b/test/metabench/make_dimension/type_list_no_concepts.h new file mode 100644 index 00000000..f68f2cee --- /dev/null +++ b/test/metabench/make_dimension/type_list_no_concepts.h @@ -0,0 +1,172 @@ +// The MIT License (MIT) +// +// Copyright (c) 2018 Mateusz Pusz +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#include "type_traits.h" + +namespace std::experimental::units { + + // push_front + + namespace detail { + + template + struct type_list_push_front_impl; + + template typename List, typename... OldTypes, typename... NewTypes> + struct type_list_push_front_impl, NewTypes...> { + using type = List; + }; + + } + + template + using type_list_push_front = detail::type_list_push_front_impl::type; + + // push_back + + namespace detail { + + template + struct type_list_push_back_impl; + + template typename List, typename... OldTypes, typename... NewTypes> + struct type_list_push_back_impl, NewTypes...> { + using type = List; + }; + + } + + template + using type_list_push_back = detail::type_list_push_back_impl::type; + + // split + + namespace detail { + + template typename List, std::size_t Idx, std::size_t N, typename... Types> + struct split_impl; + + template typename List, std::size_t Idx, std::size_t N> + struct split_impl { + using first_list = List<>; + using second_list = List<>; + }; + + template typename List, std::size_t Idx, std::size_t N, typename T, typename... Rest> + struct split_impl : split_impl { + using base = split_impl; + using first_list = conditional::type, + typename base::first_list>; + using second_list = conditional::type>; + }; + + } // namespace detail + + template + struct type_list_split; + + template typename List, std::size_t N, typename... Types> + struct type_list_split, N> { + static_assert(N <= sizeof...(Types), "Invalid index provided"); + using split = detail::split_impl; + using first_list = split::first_list; + using second_list = split::second_list; + }; + + // split_half + + template + struct type_list_split_half; + + template typename List, typename... Types> + struct type_list_split_half> : type_list_split, (sizeof...(Types) + 1) / 2> { + }; + + // merge_sorted + + namespace detail { + + template typename Pred> + struct type_list_merge_sorted_impl; + + template typename List, typename... Lhs, template typename Pred> + struct type_list_merge_sorted_impl, List<>, Pred> { + using type = List; + }; + + template typename List, typename... Rhs, template typename Pred> + struct type_list_merge_sorted_impl, List, Pred> { + using type = List; + }; + + template typename List, typename Lhs1, typename... LhsRest, typename Rhs1, typename... RhsRest, + template typename Pred> + struct type_list_merge_sorted_impl, List, Pred> { + using type = conditional< + Pred::value, + typename type_list_push_front_impl, List, Pred>::type, Lhs1>::type, + typename type_list_push_front_impl, List, Pred>::type, Rhs1>::type>; + }; + + } + + template typename Pred> + using type_list_merge_sorted = detail::type_list_merge_sorted_impl::type; + + + // sort + + namespace detail { + + template typename Pred> + struct type_list_sort_impl; + + template typename List, template typename Pred> + struct type_list_sort_impl, Pred> { + using type = List<>; + }; + + template typename List, typename T, template typename Pred> + struct type_list_sort_impl, Pred> { + using type = List; + }; + + template typename List, typename... Types, template typename Pred> + struct type_list_sort_impl, Pred> { + using types = List; + using split = type_list_split_half>; + using left = type_list_sort_impl::type; + using right = type_list_sort_impl::type; + using type = type_list_merge_sorted_impl::type; + }; + + } + + template typename Pred> + using type_list_sort = detail::type_list_sort_impl::type; + +} // namespace std::experimental::units diff --git a/test/metabench/make_dimension/type_traits.h b/test/metabench/make_dimension/type_traits.h new file mode 100644 index 00000000..a2928c5b --- /dev/null +++ b/test/metabench/make_dimension/type_traits.h @@ -0,0 +1,48 @@ +// The MIT License (MIT) +// +// Copyright (c) 2018 Mateusz Pusz +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#include + +namespace std::experimental::units { + + namespace detail { + + template + struct conditional_impl { + template + using type = F; + }; + + template<> + struct conditional_impl { + template + using type = T; + }; + + } + + template + using conditional = detail::conditional_impl::template type; + +}