StaticSymmetry.h
Go to the documentation of this file.
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2013 Christian Seiler <christian@iwakd.de>
5 //
6 // This Source Code Form is subject to the terms of the Mozilla
7 // Public License v. 2.0. If a copy of the MPL was not distributed
8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 
10 #ifndef EIGEN_CXX11_TENSORSYMMETRY_STATICSYMMETRY_H
11 #define EIGEN_CXX11_TENSORSYMMETRY_STATICSYMMETRY_H
12 
13 #include "./InternalHeaderCheck.h"
14 
15 namespace Eigen {
16 
17 namespace internal {
18 
19 template<typename list> struct tensor_static_symgroup_permutate;
20 
21 template<int... nn>
22 struct tensor_static_symgroup_permutate<numeric_list<int, nn...>>
23 {
24  constexpr static std::size_t N = sizeof...(nn);
25 
26  template<typename T>
27  constexpr static inline std::array<T, N> run(const std::array<T, N>& indices)
28  {
29  return {{indices[nn]...}};
30  }
31 };
32 
33 template<typename indices_, int flags_>
34 struct tensor_static_symgroup_element
35 {
36  typedef indices_ indices;
37  constexpr static int flags = flags_;
38 };
39 
40 template<typename Gen, int N>
41 struct tensor_static_symgroup_element_ctor
42 {
43  typedef tensor_static_symgroup_element<
44  typename gen_numeric_list_swapped_pair<int, N, Gen::One, Gen::Two>::type,
45  Gen::Flags
46  > type;
47 };
48 
49 template<int N>
50 struct tensor_static_symgroup_identity_ctor
51 {
52  typedef tensor_static_symgroup_element<
53  typename gen_numeric_list<int, N>::type,
54  0
55  > type;
56 };
57 
58 template<typename iib>
59 struct tensor_static_symgroup_multiply_helper
60 {
61  template<int... iia>
62  constexpr static inline numeric_list<int, get<iia, iib>::value...> helper(numeric_list<int, iia...>) {
63  return numeric_list<int, get<iia, iib>::value...>();
64  }
65 };
66 
67 template<typename A, typename B>
68 struct tensor_static_symgroup_multiply
69 {
70  private:
71  typedef typename A::indices iia;
72  typedef typename B::indices iib;
73  constexpr static int ffa = A::flags;
74  constexpr static int ffb = B::flags;
75 
76  public:
77  static_assert(iia::count == iib::count, "Cannot multiply symmetry elements with different number of indices.");
78 
79  typedef tensor_static_symgroup_element<
80  decltype(tensor_static_symgroup_multiply_helper<iib>::helper(iia())),
81  ffa ^ ffb
82  > type;
83 };
84 
85 template<typename A, typename B>
86 struct tensor_static_symgroup_equality
87 {
88  typedef typename A::indices iia;
89  typedef typename B::indices iib;
90  constexpr static int ffa = A::flags;
91  constexpr static int ffb = B::flags;
92  static_assert(iia::count == iib::count, "Cannot compare symmetry elements with different number of indices.");
93 
94  constexpr static bool value = is_same<iia, iib>::value;
95 
96  private:
97  /* this should be zero if they are identical, or else the tensor
98  * will be forced to be pure real, pure imaginary or even pure zero
99  */
100  constexpr static int flags_cmp_ = ffa ^ ffb;
101 
102  /* either they are not equal, then we don't care whether the flags
103  * match, or they are equal, and then we have to check
104  */
105  constexpr static bool is_zero = value && flags_cmp_ == NegationFlag;
106  constexpr static bool is_real = value && flags_cmp_ == ConjugationFlag;
107  constexpr static bool is_imag = value && flags_cmp_ == (NegationFlag | ConjugationFlag);
108 
109  public:
110  constexpr static int global_flags =
111  (is_real ? GlobalRealFlag : 0) |
112  (is_imag ? GlobalImagFlag : 0) |
113  (is_zero ? GlobalZeroFlag : 0);
114 };
115 
116 template<std::size_t NumIndices, typename... Gen>
117 struct tensor_static_symgroup
118 {
119  typedef StaticSGroup<Gen...> type;
120  constexpr static std::size_t size = type::static_size;
121 };
122 
123 template<typename Index, std::size_t N, int... ii, int... jj>
124 constexpr static inline std::array<Index, N> tensor_static_symgroup_index_permute(std::array<Index, N> idx, internal::numeric_list<int, ii...>, internal::numeric_list<int, jj...>)
125 {
126  return {{ idx[ii]..., idx[jj]... }};
127 }
128 
129 template<typename Index, int... ii>
130 static inline std::vector<Index> tensor_static_symgroup_index_permute(std::vector<Index> idx, internal::numeric_list<int, ii...>)
131 {
132  std::vector<Index> result{{ idx[ii]... }};
133  std::size_t target_size = idx.size();
134  for (std::size_t i = result.size(); i < target_size; i++)
135  result.push_back(idx[i]);
136  return result;
137 }
138 
139 template<typename T> struct tensor_static_symgroup_do_apply;
140 
141 template<typename first, typename... next>
142 struct tensor_static_symgroup_do_apply<internal::type_list<first, next...>>
143 {
144  template<typename Op, typename RV, std::size_t SGNumIndices, typename Index, std::size_t NumIndices, typename... Args>
145  static inline RV run(const std::array<Index, NumIndices>& idx, RV initial, Args&&... args)
146  {
147  static_assert(NumIndices >= SGNumIndices, "Can only apply symmetry group to objects that have at least the required amount of indices.");
148  typedef typename internal::gen_numeric_list<int, NumIndices - SGNumIndices, SGNumIndices>::type remaining_indices;
149  initial = Op::run(tensor_static_symgroup_index_permute(idx, typename first::indices(), remaining_indices()), first::flags, initial, std::forward<Args>(args)...);
150  return tensor_static_symgroup_do_apply<internal::type_list<next...>>::template run<Op, RV, SGNumIndices>(idx, initial, args...);
151  }
152 
153  template<typename Op, typename RV, std::size_t SGNumIndices, typename Index, typename... Args>
154  static inline RV run(const std::vector<Index>& idx, RV initial, Args&&... args)
155  {
156  eigen_assert(idx.size() >= SGNumIndices && "Can only apply symmetry group to objects that have at least the required amount of indices.");
157  initial = Op::run(tensor_static_symgroup_index_permute(idx, typename first::indices()), first::flags, initial, std::forward<Args>(args)...);
158  return tensor_static_symgroup_do_apply<internal::type_list<next...>>::template run<Op, RV, SGNumIndices>(idx, initial, args...);
159  }
160 };
161 
162 template<EIGEN_TPL_PP_SPEC_HACK_DEF(typename, empty)>
163 struct tensor_static_symgroup_do_apply<internal::type_list<EIGEN_TPL_PP_SPEC_HACK_USE(empty)>>
164 {
165  template<typename Op, typename RV, std::size_t SGNumIndices, typename Index, std::size_t NumIndices, typename... Args>
166  static inline RV run(const std::array<Index, NumIndices>&, RV initial, Args&&...)
167  {
168  // do nothing
169  return initial;
170  }
171 
172  template<typename Op, typename RV, std::size_t SGNumIndices, typename Index, typename... Args>
173  static inline RV run(const std::vector<Index>&, RV initial, Args&&...)
174  {
175  // do nothing
176  return initial;
177  }
178 };
179 
180 } // end namespace internal
181 
182 template<typename... Gen>
184 {
185  constexpr static std::size_t NumIndices = internal::tensor_symmetry_num_indices<Gen...>::value;
186  typedef internal::group_theory::enumerate_group_elements<
187  internal::tensor_static_symgroup_multiply,
188  internal::tensor_static_symgroup_equality,
189  typename internal::tensor_static_symgroup_identity_ctor<NumIndices>::type,
190  internal::type_list<typename internal::tensor_static_symgroup_element_ctor<Gen, NumIndices>::type...>
192  typedef typename group_elements::type ge;
193  public:
194  constexpr inline StaticSGroup() {}
195  constexpr inline StaticSGroup(const StaticSGroup<Gen...>&) {}
196  constexpr inline StaticSGroup(StaticSGroup<Gen...>&&) {}
197 
198  template<typename Op, typename RV, typename Index, std::size_t N, typename... Args>
199  static inline RV apply(const std::array<Index, N>& idx, RV initial, Args&&... args)
200  {
201  return internal::tensor_static_symgroup_do_apply<ge>::template run<Op, RV, NumIndices>(idx, initial, args...);
202  }
203 
204  template<typename Op, typename RV, typename Index, typename... Args>
205  static inline RV apply(const std::vector<Index>& idx, RV initial, Args&&... args)
206  {
207  eigen_assert(idx.size() == NumIndices);
208  return internal::tensor_static_symgroup_do_apply<ge>::template run<Op, RV, NumIndices>(idx, initial, args...);
209  }
210 
211  constexpr static std::size_t static_size = ge::count;
212 
213  constexpr static inline std::size_t size() {
214  return ge::count;
215  }
216  constexpr static inline int globalFlags() { return group_elements::global_flags; }
217 
218  template<typename Tensor_, typename... IndexTypes>
219  inline internal::tensor_symmetry_value_setter<Tensor_, StaticSGroup<Gen...>> operator()(Tensor_& tensor, typename Tensor_::Index firstIndex, IndexTypes... otherIndices) const
220  {
221  static_assert(sizeof...(otherIndices) + 1 == Tensor_::NumIndices, "Number of indices used to access a tensor coefficient must be equal to the rank of the tensor.");
222  return operator()(tensor, std::array<typename Tensor_::Index, Tensor_::NumIndices>{{firstIndex, otherIndices...}});
223  }
224 
225  template<typename Tensor_>
226  inline internal::tensor_symmetry_value_setter<Tensor_, StaticSGroup<Gen...>> operator()(Tensor_& tensor, std::array<typename Tensor_::Index, Tensor_::NumIndices> const& indices) const
227  {
228  return internal::tensor_symmetry_value_setter<Tensor_, StaticSGroup<Gen...>>(tensor, *this, indices);
229  }
230 };
231 
232 } // end namespace Eigen
233 
234 #endif // EIGEN_CXX11_TENSORSYMMETRY_STATICSYMMETRY_H
235 
236 /*
237  * kate: space-indent on; indent-width 2; mixedindent off; indent-mode cstyle;
238  */
int i
#define eigen_assert(x)
Static symmetry group.
constexpr static std::size_t static_size
static RV apply(const std::array< Index, N > &idx, RV initial, Args &&... args)
internal::tensor_symmetry_value_setter< Tensor_, StaticSGroup< Gen... > > operator()(Tensor_ &tensor, typename Tensor_::Index firstIndex, IndexTypes... otherIndices) const
constexpr static std::size_t size()
constexpr static std::size_t NumIndices
group_elements::type ge
internal::group_theory::enumerate_group_elements< internal::tensor_static_symgroup_multiply, internal::tensor_static_symgroup_equality, typename internal::tensor_static_symgroup_identity_ctor< NumIndices >::type, internal::type_list< typename internal::tensor_static_symgroup_element_ctor< Gen, NumIndices >::type... > > group_elements
constexpr StaticSGroup(const StaticSGroup< Gen... > &)
internal::tensor_symmetry_value_setter< Tensor_, StaticSGroup< Gen... > > operator()(Tensor_ &tensor, std::array< typename Tensor_::Index, Tensor_::NumIndices > const &indices) const
constexpr StaticSGroup()
static RV apply(const std::vector< Index > &idx, RV initial, Args &&... args)
constexpr StaticSGroup(StaticSGroup< Gen... > &&)
constexpr static int globalFlags()
constexpr static std::array< Index, N > tensor_static_symgroup_index_permute(std::array< Index, N > idx, internal::numeric_list< int, ii... >, internal::numeric_list< int, jj... >)
EIGEN_CONSTEXPR Index first(const T &x) EIGEN_NOEXCEPT
: TensorContractionSycl.h, provides various tensor contraction kernel for SYCL backend
@ NegationFlag
Definition: Symmetry.h:18
@ ConjugationFlag
Definition: Symmetry.h:19
@ GlobalZeroFlag
Definition: Symmetry.h:25
@ GlobalRealFlag
Definition: Symmetry.h:23
@ GlobalImagFlag
Definition: Symmetry.h:24
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
SparseMat::Index size