Line data Source code
1 1 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : /// \file
5 : /// Defines metafunctions used to compute the Symmetry<...> for a Tensor
6 :
7 : #pragma once
8 :
9 : #include <type_traits>
10 :
11 : #include "Utilities/Array.hpp"
12 : #include "Utilities/TMPL.hpp"
13 :
14 : namespace detail {
15 : template <size_t Size>
16 : constexpr int find_reduced_index(
17 : const cpp20::array<std::pair<int, int>, Size>& t, const int value) {
18 : for (size_t i = 0; i < Size; ++i) {
19 : if (t[i].first == value) {
20 : return t[i].second;
21 : }
22 : }
23 : return 0;
24 : }
25 :
26 : template <size_t Size>
27 : constexpr cpp20::array<int, Size> symmetry(
28 : const std::array<int, Size>& input_symm) {
29 : cpp20::array<int, Size> output_symm{};
30 : int next_symm_entry = 1;
31 : cpp20::array<std::pair<int, int>, Size> input_to_output_map{};
32 : size_t input_to_output_map_size = 0;
33 : for (size_t i = Size - 1; i < Size; --i) {
34 : // clang-tidy: use gsl::at
35 : int found_symm_entry =
36 : find_reduced_index(input_to_output_map, input_symm[i]); // NOLINT
37 : if (found_symm_entry == 0) {
38 : output_symm[i] = next_symm_entry; // NOLINT
39 : input_to_output_map[input_to_output_map_size].first =
40 : input_symm[i]; // NOLINT
41 : input_to_output_map[input_to_output_map_size].second = output_symm[i];
42 : input_to_output_map_size++;
43 : next_symm_entry++;
44 : } else {
45 : output_symm[i] = found_symm_entry;
46 : }
47 : }
48 : return output_symm;
49 : }
50 :
51 : template <typename IndexSequence, typename SymmetrySequence>
52 : struct SymmetryImpl;
53 :
54 : template <size_t... Is, std::int32_t... Ss>
55 : struct SymmetryImpl<std::index_sequence<Is...>,
56 : tmpl::integral_list<std::int32_t, Ss...>> {
57 : static_assert((... and (Ss > 0)),
58 : "Symmetry values must be positive integers.");
59 : static constexpr cpp20::array<int, sizeof...(Is)> t =
60 : symmetry(std::array<int, sizeof...(Is)>{{Ss...}});
61 : using type = tmpl::integral_list<std::int32_t, t[Is]...>;
62 : };
63 : } // namespace detail
64 :
65 : /// \ingroup TensorGroup
66 : /// \brief Computes the canonical symmetry from the integers `T`
67 : ///
68 : /// \details
69 : /// Compute the canonical symmetry typelist given a set of integers, T. The
70 : /// resulting typelist is in ascending order of the integers, from right to
71 : /// left. For example, the result of `Symmetry<1, 2, 1, 3>` is
72 : /// `integral_list<int32_t, 2, 3, 2, 1>`. Anti-symmetries are not currently
73 : /// supported.
74 : ///
75 : /// \tparam T the integers denoting the symmetry of the Tensor
76 : template <std::int32_t... T>
77 1 : using Symmetry = typename detail::SymmetryImpl<
78 : std::make_index_sequence<sizeof...(T)>,
79 : tmpl::integral_list<std::int32_t, T...>>::type;
|