diff --git a/test/metabench/CMakeLists.txt b/test/metabench/CMakeLists.txt index b8448e3c..8c8d4985 100644 --- a/test/metabench/CMakeLists.txt +++ b/test/metabench/CMakeLists.txt @@ -39,4 +39,7 @@ endif() enable_testing() +add_custom_target(metabench) + add_subdirectory(ratio) +add_subdirectory(list) diff --git a/test/metabench/list/CMakeLists.txt b/test/metabench/list/CMakeLists.txt new file mode 100644 index 00000000..0758fe61 --- /dev/null +++ b/test/metabench/list/CMakeLists.txt @@ -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. + + +add_metabench_test(metabench.data.list.type_list.concepts_all "all concepts" type_list_concepts_all.cpp.erb "[3, 6, 9, 12, 15]") +add_metabench_test(metabench.data.list.type_list.concepts_iface "concepts in interface" type_list_concepts_iface.cpp.erb "[3, 6, 9, 12, 15]") +add_metabench_test(metabench.data.list.type_list.concepts_no "no concepts" type_list_concepts_no.cpp.erb "[3, 6, 9, 12, 15]") +metabench_add_chart(metabench.chart.list.concepts + TITLE "Sorting a list of size N" + SUBTITLE "(smaller is better)" + DATASETS + metabench.data.list.type_list.concepts_all + metabench.data.list.type_list.concepts_iface + metabench.data.list.type_list.concepts_no +) + +add_metabench_test(metabench.data.list.type_list.conditional_std "std::conditional" type_list_conditional_std.cpp.erb "[3, 6, 9, 12, 15]") +add_metabench_test(metabench.data.list.type_list.conditional_alias "alias conditional" type_list_conditional_alias.cpp.erb "[3, 6, 9, 12, 15]") +add_metabench_test(metabench.data.list.type_list.conditional_alias_hard "alias conditional hard" type_list_conditional_alias_hard.cpp.erb "[3, 6, 9, 12, 15]") +metabench_add_chart(metabench.chart.list.conditional + TITLE "Sorting a list of size N" + SUBTITLE "(smaller is better)" + DATASETS + metabench.data.list.type_list.conditional_std + metabench.data.list.type_list.conditional_alias + metabench.data.list.type_list.conditional_alias_hard +) + +add_custom_target(metabench.chart.list + DEPENDS + metabench.chart.list.concepts + metabench.chart.list.conditional +) + +add_dependencies(metabench metabench.chart.list) diff --git a/test/metabench/list/type_list_concepts_all.cpp.erb b/test/metabench/list/type_list_concepts_all.cpp.erb new file mode 100644 index 00000000..8aacaafe --- /dev/null +++ b/test/metabench/list/type_list_concepts_all.cpp.erb @@ -0,0 +1,33 @@ +#include "type_list_concepts_all.h" + +template +using dim_id = std::integral_constant; + +template +using dim_id_less = std::bool_constant; + + +template +struct dimension; + +<% (1..10).each do |k| %> +struct test<%= k %> { + +<% (1..n).each do |i| %> +using <%= "dim#{i}" %> = dimension<<%= + xs = ((1)..(i)).map { |j| "dim_id<#{k*n+i+j}>" } + rng = Random.new(i) + xs.shuffle(random: rng).join(', ') +%>>; +#if defined(METABENCH) +using <%= "result#{i}" %> = units::type_list_sort_t<<%= "dim#{i}" %>, dim_id_less>; +#endif +<% end %> + +}; + +<% end %> + +int main() +{ +} diff --git a/test/metabench/list/type_list_concepts_all.h b/test/metabench/list/type_list_concepts_all.h new file mode 100644 index 00000000..3f0a4746 --- /dev/null +++ b/test/metabench/list/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 + +namespace units { + + namespace detail { + + template + struct conditional { + template + using type = F; + }; + + template<> + struct conditional { + template + using type = T; + }; + + template + using conditional_t = conditional::template type; + + } + + 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 + + template + struct type_list_push_front; + + template typename List, typename... OldTypes, typename... NewTypes> + struct type_list_push_front, NewTypes...> { + using type = List; + }; + + template + using type_list_push_front_t = type_list_push_front::type; + + // push_back + + template + struct type_list_push_back; + + template typename List, typename... OldTypes, typename... NewTypes> + struct type_list_push_back, NewTypes...> { + using type = List; + }; + + template + using type_list_push_back_t = type_list_push_back::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 base_first = base::first_list; + using base_second = base::second_list; + using first_list = detail::conditional_t, base_first>; + using second_list = detail::conditional_t>; + }; + + } // 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 + + template typename Pred> + struct type_list_merge_sorted; + + template typename Pred> + using type_list_merge_sorted_t = type_list_merge_sorted::type; + + template typename List, typename... Lhs, template typename Pred> + struct type_list_merge_sorted, List<>, Pred> { + using type = List; + }; + + template typename List, typename... Rhs, template typename Pred> + struct type_list_merge_sorted, List, Pred> { + using type = List; + }; + + template typename List, typename Lhs1, typename... LhsRest, typename Rhs1, typename... RhsRest, + template typename Pred> + struct type_list_merge_sorted, List, Pred> { + using type = detail::conditional_t< + Pred::value, + type_list_push_front_t, List, Pred>, Lhs1>, + type_list_push_front_t, List, Pred>, Rhs1>>; + }; + + // sort + + template typename Pred> + struct type_list_sort; + + template typename List, template typename Pred> + struct type_list_sort, Pred> { + using type = List<>; + }; + + template typename List, typename T, template typename Pred> + struct type_list_sort, Pred> { + using type = List; + }; + + template typename List, typename... Types, template typename Pred> + struct type_list_sort, Pred> { + using types = List; + using split = type_list_split_half>; + using left = type_list_sort::type; + using right = type_list_sort::type; + using type = type_list_merge_sorted_t; + }; + + template typename Pred> + using type_list_sort_t = type_list_sort::type; + +} // namespace units \ No newline at end of file diff --git a/test/metabench/list/type_list_concepts_iface.cpp.erb b/test/metabench/list/type_list_concepts_iface.cpp.erb new file mode 100644 index 00000000..4b89f825 --- /dev/null +++ b/test/metabench/list/type_list_concepts_iface.cpp.erb @@ -0,0 +1,33 @@ +#include "type_list_concepts_iface.h" + +template +using dim_id = std::integral_constant; + +template +using dim_id_less = std::bool_constant; + + +template +struct dimension; + +<% (1..10).each do |k| %> +struct test<%= k %> { + +<% (1..n).each do |i| %> +using <%= "dim#{i}" %> = dimension<<%= + xs = ((1)..(i)).map { |j| "dim_id<#{k*n+i+j}>" } + rng = Random.new(i) + xs.shuffle(random: rng).join(', ') +%>>; +#if defined(METABENCH) +using <%= "result#{i}" %> = units::type_list_sort<<%= "dim#{i}" %>, dim_id_less>; +#endif +<% end %> + +}; + +<% end %> + +int main() +{ +} diff --git a/test/metabench/list/type_list_concepts_iface.h b/test/metabench/list/type_list_concepts_iface.h new file mode 100644 index 00000000..056ba4f2 --- /dev/null +++ b/test/metabench/list/type_list_concepts_iface.h @@ -0,0 +1,204 @@ +// 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 units { + + namespace detail { + + template + struct conditional { + template + using type = F; + }; + + template<> + struct conditional { + template + using type = T; + }; + + } + + template + using conditional = detail::conditional::template type; + + 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 = units::conditional::type, + typename base::first_list>; + using second_list = units::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 = units::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 units diff --git a/test/metabench/list/type_list_concepts_no.cpp.erb b/test/metabench/list/type_list_concepts_no.cpp.erb new file mode 100644 index 00000000..4adbf45e --- /dev/null +++ b/test/metabench/list/type_list_concepts_no.cpp.erb @@ -0,0 +1,33 @@ +#include "type_list_concepts_no.h" + +template +using dim_id = std::integral_constant; + +template +using dim_id_less = std::bool_constant; + + +template +struct dimension; + +<% (1..10).each do |k| %> +struct test<%= k %> { + +<% (1..n).each do |i| %> +using <%= "dim#{i}" %> = dimension<<%= + xs = ((1)..(i)).map { |j| "dim_id<#{k*n+i+j}>" } + rng = Random.new(i) + xs.shuffle(random: rng).join(', ') +%>>; +#if defined(METABENCH) +using <%= "result#{i}" %> = units::type_list_sort<<%= "dim#{i}" %>, dim_id_less>; +#endif +<% end %> + +}; + +<% end %> + +int main() +{ +} diff --git a/test/metabench/list/type_list_concepts_no.h b/test/metabench/list/type_list_concepts_no.h new file mode 100644 index 00000000..ab74a04e --- /dev/null +++ b/test/metabench/list/type_list_concepts_no.h @@ -0,0 +1,191 @@ +// 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 units { + + namespace detail { + + template + struct conditional { + template + using type = F; + }; + + template<> + struct conditional { + template + using type = T; + }; + + } + + template + using conditional = detail::conditional::template type; + + // 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 = units::conditional::type, + typename base::first_list>; + using second_list = units::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 = units::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 units diff --git a/test/metabench/list/type_list_conditional_alias.cpp.erb b/test/metabench/list/type_list_conditional_alias.cpp.erb new file mode 100644 index 00000000..80bf8526 --- /dev/null +++ b/test/metabench/list/type_list_conditional_alias.cpp.erb @@ -0,0 +1,33 @@ +#include "type_list_conditional_alias.h" + +template +using dim_id = std::integral_constant; + +template +using dim_id_less = std::bool_constant; + + +template +struct dimension; + +<% (1..10).each do |k| %> +struct test<%= k %> { + +<% (1..n).each do |i| %> +using <%= "dim#{i}" %> = dimension<<%= + xs = ((1)..(i)).map { |j| "dim_id<#{k*n+i+j}>" } + rng = Random.new(i) + xs.shuffle(random: rng).join(', ') +%>>; +#if defined(METABENCH) +using <%= "result#{i}" %> = units::type_list_sort<<%= "dim#{i}" %>, dim_id_less>; +#endif +<% end %> + +}; + +<% end %> + +int main() +{ +} diff --git a/test/metabench/list/type_list_conditional_alias.h b/test/metabench/list/type_list_conditional_alias.h new file mode 100644 index 00000000..056ba4f2 --- /dev/null +++ b/test/metabench/list/type_list_conditional_alias.h @@ -0,0 +1,204 @@ +// 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 units { + + namespace detail { + + template + struct conditional { + template + using type = F; + }; + + template<> + struct conditional { + template + using type = T; + }; + + } + + template + using conditional = detail::conditional::template type; + + 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 = units::conditional::type, + typename base::first_list>; + using second_list = units::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 = units::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 units diff --git a/test/metabench/list/type_list_conditional_alias_hard.cpp.erb b/test/metabench/list/type_list_conditional_alias_hard.cpp.erb new file mode 100644 index 00000000..837a0a47 --- /dev/null +++ b/test/metabench/list/type_list_conditional_alias_hard.cpp.erb @@ -0,0 +1,33 @@ +#include "type_list_conditional_alias_hard.h" + +template +using dim_id = std::integral_constant; + +template +using dim_id_less = std::bool_constant; + + +template +struct dimension; + +<% (1..10).each do |k| %> +struct test<%= k %> { + +<% (1..n).each do |i| %> +using <%= "dim#{i}" %> = dimension<<%= + xs = ((1)..(i)).map { |j| "dim_id<#{k*n+i+j}>" } + rng = Random.new(i) + xs.shuffle(random: rng).join(', ') +%>>; +#if defined(METABENCH) +using <%= "result#{i}" %> = units::type_list_sort<<%= "dim#{i}" %>, dim_id_less>; +#endif +<% end %> + +}; + +<% end %> + +int main() +{ +} diff --git a/test/metabench/list/type_list_conditional_alias_hard.h b/test/metabench/list/type_list_conditional_alias_hard.h new file mode 100644 index 00000000..c6b43d43 --- /dev/null +++ b/test/metabench/list/type_list_conditional_alias_hard.h @@ -0,0 +1,197 @@ +// 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 units { + + template + struct conditional { + template + using type = F; + }; + + template<> + struct conditional { + template + using type = T; + }; + + 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::template type< + typename type_list_push_front_impl::type, + typename base::first_list>; + using second_list = conditional::template type< + typename base::second_list, + typename type_list_push_front_impl::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 = units::conditional< + Pred::value>::template type< + 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 units diff --git a/test/metabench/list/type_list_conditional_std.cpp.erb b/test/metabench/list/type_list_conditional_std.cpp.erb new file mode 100644 index 00000000..8c9a1f95 --- /dev/null +++ b/test/metabench/list/type_list_conditional_std.cpp.erb @@ -0,0 +1,33 @@ +#include "type_list_conditional_std.h" + +template +using dim_id = std::integral_constant; + +template +using dim_id_less = std::bool_constant; + + +template +struct dimension; + +<% (1..10).each do |k| %> +struct test<%= k %> { + +<% (1..n).each do |i| %> +using <%= "dim#{i}" %> = dimension<<%= + xs = ((1)..(i)).map { |j| "dim_id<#{k*n+i+j}>" } + rng = Random.new(i) + xs.shuffle(random: rng).join(', ') +%>>; +#if defined(METABENCH) +using <%= "result#{i}" %> = units::type_list_sort<<%= "dim#{i}" %>, dim_id_less>; +#endif +<% end %> + +}; + +<% end %> + +int main() +{ +} diff --git a/test/metabench/list/type_list_conditional_std.h b/test/metabench/list/type_list_conditional_std.h new file mode 100644 index 00000000..54e0a100 --- /dev/null +++ b/test/metabench/list/type_list_conditional_std.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 + +namespace 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 = std::conditional_t::type, + typename base::first_list>; + using second_list = std::conditional_t::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 = std::conditional_t< + 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 units diff --git a/test/metabench/ratio/CMakeLists.txt b/test/metabench/ratio/CMakeLists.txt index dcbe6acc..232eef44 100644 --- a/test/metabench/ratio/CMakeLists.txt +++ b/test/metabench/ratio/CMakeLists.txt @@ -69,4 +69,4 @@ add_custom_target(metabench.chart.ratio metabench.chart.ratio.all ) -add_custom_target(metabench DEPENDS metabench.chart.ratio) +add_dependencies(metabench metabench.chart.ratio)