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