DynamicSymmetry.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_DYNAMICSYMMETRY_H
11 #define EIGEN_CXX11_TENSORSYMMETRY_DYNAMICSYMMETRY_H
12 
13 // IWYU pragma: private
14 #include "./InternalHeaderCheck.h"
15 
16 namespace Eigen {
17 
19  public:
20  inline explicit DynamicSGroup() : m_numIndices(1), m_elements(), m_generators(), m_globalFlags(0) {
21  m_elements.push_back(ge(Generator(0, 0, 0)));
22  }
23  inline DynamicSGroup(const DynamicSGroup& o)
30  std::swap(m_elements, o.m_elements);
31  }
37  return *this;
38  }
40  m_numIndices = o.m_numIndices;
41  std::swap(m_elements, o.m_elements);
42  m_generators = o.m_generators;
43  m_globalFlags = o.m_globalFlags;
44  return *this;
45  }
46 
47  void add(int one, int two, int flags = 0);
48 
49  template <typename Gen_>
50  inline void add(Gen_) {
51  add(Gen_::One, Gen_::Two, Gen_::Flags);
52  }
53  inline void addSymmetry(int one, int two) { add(one, two, 0); }
54  inline void addAntiSymmetry(int one, int two) { add(one, two, NegationFlag); }
55  inline void addHermiticity(int one, int two) { add(one, two, ConjugationFlag); }
56  inline void addAntiHermiticity(int one, int two) { add(one, two, NegationFlag | ConjugationFlag); }
57 
58  template <typename Op, typename RV, typename Index, std::size_t N, typename... Args>
59  inline RV apply(const std::array<Index, N>& idx, RV initial, Args&&... args) const {
61  "Can only apply symmetry group to objects that have at least the required amount of indices.");
62  for (std::size_t i = 0; i < size(); i++)
63  initial = Op::run(h_permute(i, idx, typename internal::gen_numeric_list<int, N>::type()), m_elements[i].flags,
64  initial, std::forward<Args>(args)...);
65  return initial;
66  }
67 
68  template <typename Op, typename RV, typename Index, typename... Args>
69  inline RV apply(const std::vector<Index>& idx, RV initial, Args&&... args) const {
70  eigen_assert(idx.size() >= m_numIndices &&
71  "Can only apply symmetry group to objects that have at least the required amount of indices.");
72  for (std::size_t i = 0; i < size(); i++)
73  initial = Op::run(h_permute(i, idx), m_elements[i].flags, initial, std::forward<Args>(args)...);
74  return initial;
75  }
76 
77  inline int globalFlags() const { return m_globalFlags; }
78  inline std::size_t size() const { return m_elements.size(); }
79 
80  template <typename Tensor_, typename... IndexTypes>
82  typename Tensor_::Index firstIndex,
83  IndexTypes... otherIndices) const {
84  static_assert(sizeof...(otherIndices) + 1 == Tensor_::NumIndices,
85  "Number of indices used to access a tensor coefficient must be equal to the rank of the tensor.");
86  return operator()(tensor, std::array<typename Tensor_::Index, Tensor_::NumIndices>{{firstIndex, otherIndices...}});
87  }
88 
89  template <typename Tensor_>
91  Tensor_& tensor, std::array<typename Tensor_::Index, Tensor_::NumIndices> const& indices) const {
93  }
94 
95  private:
96  struct GroupElement {
97  std::vector<int> representation;
98  int flags;
99  bool isId() const {
100  for (std::size_t i = 0; i < representation.size(); i++)
101  if (i != (size_t)representation[i]) return false;
102  return true;
103  }
104  };
105  struct Generator {
106  int one;
107  int two;
108  int flags;
109  constexpr inline Generator(int one_, int two_, int flags_) : one(one_), two(two_), flags(flags_) {}
110  };
111 
112  std::size_t m_numIndices;
113  std::vector<GroupElement> m_elements;
114  std::vector<Generator> m_generators;
116 
117  template <typename Index, std::size_t N, int... n>
118  inline std::array<Index, N> h_permute(std::size_t which, const std::array<Index, N>& idx,
120  return std::array<Index, N>{{idx[n >= m_numIndices ? n : m_elements[which].representation[n]]...}};
121  }
122 
123  template <typename Index>
124  inline std::vector<Index> h_permute(std::size_t which, std::vector<Index> idx) const {
125  std::vector<Index> result;
126  result.reserve(idx.size());
127  for (auto k : m_elements[which].representation) result.push_back(idx[k]);
128  for (std::size_t i = m_numIndices; i < idx.size(); i++) result.push_back(idx[i]);
129  return result;
130  }
131 
132  inline GroupElement ge(Generator const& g) const {
133  GroupElement result;
134  result.representation.reserve(m_numIndices);
135  result.flags = g.flags;
136  for (std::size_t k = 0; k < m_numIndices; k++) {
137  if (k == (std::size_t)g.one)
138  result.representation.push_back(g.two);
139  else if (k == (std::size_t)g.two)
140  result.representation.push_back(g.one);
141  else
142  result.representation.push_back(int(k));
143  }
144  return result;
145  }
146 
147  GroupElement mul(GroupElement, GroupElement) const;
148  inline GroupElement mul(Generator g1, GroupElement g2) const { return mul(ge(g1), g2); }
149 
150  inline GroupElement mul(GroupElement g1, Generator g2) const { return mul(g1, ge(g2)); }
151 
152  inline GroupElement mul(Generator g1, Generator g2) const { return mul(ge(g1), ge(g2)); }
153 
154  inline int findElement(GroupElement e) const {
155  for (auto ee : m_elements) {
156  if (ee.representation == e.representation) return ee.flags ^ e.flags;
157  }
158  return -1;
159  }
160 
161  void updateGlobalFlags(int flagDiffOfSameGenerator);
162 };
163 
164 // dynamic symmetry group that auto-adds the template parameters in the constructor
165 template <typename... Gen>
167  public:
173  return *this;
174  }
177  return *this;
178  }
179 
180  private:
181  template <typename Gen1, typename... GenNext>
183  add(Gen1());
185  }
186 
188 };
189 
193 
194  GroupElement result;
195  result.representation.reserve(m_numIndices);
196  for (std::size_t i = 0; i < m_numIndices; i++) {
197  int v = g2.representation[g1.representation[i]];
198  eigen_assert(v >= 0);
199  result.representation.push_back(v);
200  }
201  result.flags = g1.flags ^ g2.flags;
202  return result;
203 }
204 
205 inline void DynamicSGroup::add(int one, int two, int flags) {
206  eigen_assert(one >= 0);
207  eigen_assert(two >= 0);
208  eigen_assert(one != two);
209 
210  if ((std::size_t)one >= m_numIndices || (std::size_t)two >= m_numIndices) {
211  std::size_t newNumIndices = (one > two) ? one : two + 1;
212  for (auto& gelem : m_elements) {
213  gelem.representation.reserve(newNumIndices);
214  for (std::size_t i = m_numIndices; i < newNumIndices; i++) gelem.representation.push_back(i);
215  }
216  m_numIndices = newNumIndices;
217  }
218 
219  Generator g{one, two, flags};
220  GroupElement e = ge(g);
221 
222  /* special case for first generator */
223  if (m_elements.size() == 1) {
224  while (!e.isId()) {
225  m_elements.push_back(e);
226  e = mul(e, g);
227  }
228 
229  if (e.flags > 0) updateGlobalFlags(e.flags);
230 
231  // only add in case we didn't have identity
232  if (m_elements.size() > 1) m_generators.push_back(g);
233  return;
234  }
235 
236  int p = findElement(e);
237  if (p >= 0) {
239  return;
240  }
241 
242  std::size_t coset_order = m_elements.size();
243  m_elements.push_back(e);
244  for (std::size_t i = 1; i < coset_order; i++) m_elements.push_back(mul(m_elements[i], e));
245  m_generators.push_back(g);
246 
247  std::size_t coset_rep = coset_order;
248  do {
249  for (auto g : m_generators) {
250  e = mul(m_elements[coset_rep], g);
251  p = findElement(e);
252  if (p < 0) {
253  // element not yet in group
254  m_elements.push_back(e);
255  for (std::size_t i = 1; i < coset_order; i++) m_elements.push_back(mul(m_elements[i], e));
256  } else if (p > 0) {
258  }
259  }
260  coset_rep += coset_order;
261  } while (coset_rep < m_elements.size());
262 }
263 
264 inline void DynamicSGroup::updateGlobalFlags(int flagDiffOfSameGenerator) {
265  switch (flagDiffOfSameGenerator) {
266  case 0:
267  default:
268  // nothing happened
269  break;
270  case NegationFlag:
271  // every element is it's own negative => whole tensor is zero
273  break;
274  case ConjugationFlag:
275  // every element is it's own conjugate => whole tensor is real
277  break;
278  case (NegationFlag | ConjugationFlag):
279  // every element is it's own negative conjugate => whole tensor is imaginary
281  break;
282  /* NOTE:
283  * since GlobalZeroFlag == GlobalRealFlag | GlobalImagFlag, if one generator
284  * causes the tensor to be real and the next one to be imaginary, this will
285  * trivially give the correct result
286  */
287  }
288 }
289 
290 } // end namespace Eigen
291 
292 #endif // EIGEN_CXX11_TENSORSYMMETRY_DYNAMICSYMMETRY_H
293 
294 /*
295  * kate: space-indent on; indent-width 2; mixedindent off; indent-mode cstyle;
296  */
Array< int, Dynamic, 1 > v
Definition: Array_initializer_list_vector_cxx11.cpp:1
int i
Definition: BiCGSTAB_step_by_step.cpp:9
const unsigned n
Definition: CG3DPackingUnitTest.cpp:11
Array< double, 1, 3 > e(1./3., 0.5, 2.)
#define eigen_internal_assert(x)
Definition: Macros.h:916
#define eigen_assert(x)
Definition: Macros.h:910
float * p
Definition: Tutorial_Map_using.cpp:9
Dynamic symmetry group, initialized from template arguments.
Definition: DynamicSymmetry.h:166
DynamicSGroupFromTemplateArgs(DynamicSGroupFromTemplateArgs const &other)
Definition: DynamicSymmetry.h:169
void add_all(internal::type_list< Gen1, GenNext... >)
Definition: DynamicSymmetry.h:182
DynamicSGroupFromTemplateArgs< Gen... > & operator=(DynamicSGroupFromTemplateArgs< Gen... > &&o)
Definition: DynamicSymmetry.h:175
DynamicSGroupFromTemplateArgs()
Definition: DynamicSymmetry.h:168
DynamicSGroupFromTemplateArgs< Gen... > & operator=(const DynamicSGroupFromTemplateArgs< Gen... > &o)
Definition: DynamicSymmetry.h:171
void add_all(internal::type_list<>)
Definition: DynamicSymmetry.h:187
DynamicSGroupFromTemplateArgs(DynamicSGroupFromTemplateArgs &&other)
Definition: DynamicSymmetry.h:170
Dynamic symmetry group.
Definition: DynamicSymmetry.h:18
GroupElement mul(GroupElement g1, Generator g2) const
Definition: DynamicSymmetry.h:150
internal::tensor_symmetry_value_setter< Tensor_, DynamicSGroup > operator()(Tensor_ &tensor, typename Tensor_::Index firstIndex, IndexTypes... otherIndices) const
Definition: DynamicSymmetry.h:81
std::vector< Index > h_permute(std::size_t which, std::vector< Index > idx) const
Definition: DynamicSymmetry.h:124
void add(Gen_)
Definition: DynamicSymmetry.h:50
DynamicSGroup & operator=(const DynamicSGroup &o)
Definition: DynamicSymmetry.h:32
std::array< Index, N > h_permute(std::size_t which, const std::array< Index, N > &idx, internal::numeric_list< int, n... >) const
Definition: DynamicSymmetry.h:118
std::size_t m_numIndices
Definition: DynamicSymmetry.h:112
void updateGlobalFlags(int flagDiffOfSameGenerator)
Definition: DynamicSymmetry.h:264
internal::tensor_symmetry_value_setter< Tensor_, DynamicSGroup > operator()(Tensor_ &tensor, std::array< typename Tensor_::Index, Tensor_::NumIndices > const &indices) const
Definition: DynamicSymmetry.h:90
void addSymmetry(int one, int two)
Definition: DynamicSymmetry.h:53
void addHermiticity(int one, int two)
Definition: DynamicSymmetry.h:55
GroupElement mul(Generator g1, Generator g2) const
Definition: DynamicSymmetry.h:152
void addAntiHermiticity(int one, int two)
Definition: DynamicSymmetry.h:56
std::vector< Generator > m_generators
Definition: DynamicSymmetry.h:114
DynamicSGroup()
Definition: DynamicSymmetry.h:20
DynamicSGroup(const DynamicSGroup &o)
Definition: DynamicSymmetry.h:23
int globalFlags() const
Definition: DynamicSymmetry.h:77
DynamicSGroup & operator=(DynamicSGroup &&o)
Definition: DynamicSymmetry.h:39
DynamicSGroup(DynamicSGroup &&o)
Definition: DynamicSymmetry.h:28
void add(int one, int two, int flags=0)
Definition: DynamicSymmetry.h:205
GroupElement mul(GroupElement, GroupElement) const
Definition: DynamicSymmetry.h:190
int m_globalFlags
Definition: DynamicSymmetry.h:115
void addAntiSymmetry(int one, int two)
Definition: DynamicSymmetry.h:54
std::size_t size() const
Definition: DynamicSymmetry.h:78
int findElement(GroupElement e) const
Definition: DynamicSymmetry.h:154
RV apply(const std::array< Index, N > &idx, RV initial, Args &&... args) const
Definition: DynamicSymmetry.h:59
std::vector< GroupElement > m_elements
Definition: DynamicSymmetry.h:113
RV apply(const std::vector< Index > &idx, RV initial, Args &&... args) const
Definition: DynamicSymmetry.h:69
GroupElement ge(Generator const &g) const
Definition: DynamicSymmetry.h:132
GroupElement mul(Generator g1, GroupElement g2) const
Definition: DynamicSymmetry.h:148
@ N
Definition: constructor.cpp:22
EIGEN_BLAS_FUNC() swap(int *n, RealScalar *px, int *incx, RealScalar *py, int *incy)
Definition: level1_impl.h:117
char char char int int * k
Definition: level2_impl.h:374
Namespace containing all symbols from the Eigen library.
Definition: bench_norm.cpp:70
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:83
@ GlobalZeroFlag
Definition: Symmetry.h:20
@ GlobalRealFlag
Definition: Symmetry.h:20
@ GlobalImagFlag
Definition: Symmetry.h:20
@ NegationFlag
Definition: Symmetry.h:18
@ ConjugationFlag
Definition: Symmetry.h:18
args
Definition: compute_granudrum_aor.py:143
Definition: DynamicSymmetry.h:105
constexpr Generator(int one_, int two_, int flags_)
Definition: DynamicSymmetry.h:109
int two
Definition: DynamicSymmetry.h:107
int flags
Definition: DynamicSymmetry.h:108
int one
Definition: DynamicSymmetry.h:106
Definition: DynamicSymmetry.h:96
int flags
Definition: DynamicSymmetry.h:98
bool isId() const
Definition: DynamicSymmetry.h:99
std::vector< int > representation
Definition: DynamicSymmetry.h:97
Definition: MoreMeta.h:55
Definition: MoreMeta.h:33
Definition: MoreMeta.h:22
void run(const string &dir_name, LinearSolver *linear_solver_pt, const unsigned nel_1d, bool mess_up_order)
Definition: two_d_poisson_compare_solvers.cc:317