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;