Symmetry.hpp
Go to the documentation of this file.
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 /// \file
5 /// Defines metafunctions used to comute 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 cpp17::array<std::pair<int, int>, Size>& t,
18  const int value) noexcept {
19  for (size_t i = 0; i < Size; ++i) {
20  if (t[i].first == value) {
21  return t[i].second;
22  }
23  }
24  return 0;
25 }
26 
27 template <size_t Size>
28 constexpr cpp17::array<int, Size> symmetry(
29  const std::array<int, Size>& input_symm) noexcept {
30  cpp17::array<int, Size> output_symm{};
31  int next_symm_entry = 1;
32  cpp17::array<std::pair<int, int>, Size> input_to_output_map{};
33  size_t input_to_output_map_size = 0;
34  for (size_t i = Size - 1; i < Size; --i) {
35  // clang-tidy: use gsl::at
36  int found_symm_entry =
37  find_reduced_index(input_to_output_map, input_symm[i]); // NOLINT
38  if (found_symm_entry == 0) {
39  output_symm[i] = next_symm_entry; // NOLINT
40  input_to_output_map[input_to_output_map_size].first =
41  input_symm[i]; // NOLINT
42  input_to_output_map[input_to_output_map_size].second = output_symm[i];
43  input_to_output_map_size++;
44  next_symm_entry++;
45  } else {
46  output_symm[i] = found_symm_entry;
47  }
48  }
49  return output_symm;
50 }
51 
52 template <typename IndexSequence, typename SymmetrySequence>
53 struct SymmetryImpl;
54 
55 template <size_t... Is, std::int32_t... Ss>
56 struct SymmetryImpl<std::index_sequence<Is...>,
57  tmpl::integral_list<std::int32_t, Ss...>> {
58  static constexpr cpp17::array<int, sizeof...(Is)> t =
59  symmetry(std::array<int, sizeof...(Is)>{{Ss...}});
60  using type = tmpl::integral_list<std::int32_t, t[Is]...>;
61 };
62 } // namespace detail
63 
64 /// \ingroup TensorGroup
65 /// \brief Computes the canonical symmetry from the integers `T`
66 ///
67 /// \details
68 /// Compute the canonical symmetry typelist given a set of integers, T. The
69 /// resulting typelist is in descending order of the absolute value of the
70 /// integers. For example, the result of `Symmetry<1, 2, 3>` is
71 /// `integral_list<int32_t, 3, 2, 1>`. Anti-symmetries can be denoted with a
72 /// minus sign on either _or_ both indices. That is, `Symmetry<-1, 2, 1>` is
73 /// anti-symmetric in the first and last index and is the same as `Symmetry<-1,
74 /// 2, -1>`. Note: two minus signs are still anti-symmetric because it
75 /// simplifies the algorithm used to compute the canonical form of the symmetry.
76 ///
77 /// \tparam T the integers denoting the symmetry of the Tensor
78 template <std::int32_t... T>
79 using Symmetry = typename detail::SymmetryImpl<
80  std::make_index_sequence<sizeof...(T)>,
81  tmpl::integral_list<std::int32_t, T...>>::type;
Definition: Determinant.hpp:11
typename detail::SymmetryImpl< std::make_index_sequence< sizeof...(T)>, tmpl::integral_list< std::int32_t, T... > >::type Symmetry
Computes the canonical symmetry from the integers T
Definition: Symmetry.hpp:81
Wraps the template metaprogramming library used (brigand)
Definition: Array.hpp:26