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