$darkmode
Eigen-unsupported  5.0.1-dev
Symmetry.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_SYMMETRY_H
11 #define EIGEN_CXX11_TENSORSYMMETRY_SYMMETRY_H
12 
13 // IWYU pragma: private
14 #include "./InternalHeaderCheck.h"
15 
16 namespace Eigen {
17 
18 enum { NegationFlag = 0x01, ConjugationFlag = 0x02 };
19 
20 enum { GlobalRealFlag = 0x01, GlobalImagFlag = 0x02, GlobalZeroFlag = 0x03 };
21 
22 namespace internal {
23 
24 template <std::size_t NumIndices, typename... Sym>
25 struct tensor_symmetry_pre_analysis;
26 template <std::size_t NumIndices, typename... Sym>
27 struct tensor_static_symgroup;
28 template <bool instantiate, std::size_t NumIndices, typename... Sym>
29 struct tensor_static_symgroup_if;
30 template <typename Tensor_>
31 struct tensor_symmetry_calculate_flags;
32 template <typename Tensor_>
33 struct tensor_symmetry_assign_value;
34 template <typename... Sym>
35 struct tensor_symmetry_num_indices;
36 
37 } // end namespace internal
38 
39 template <int One_, int Two_>
40 struct Symmetry {
41  static_assert(One_ != Two_, "Symmetries must cover distinct indices.");
42  constexpr static int One = One_;
43  constexpr static int Two = Two_;
44  constexpr static int Flags = 0;
45 };
46 
47 template <int One_, int Two_>
48 struct AntiSymmetry {
49  static_assert(One_ != Two_, "Symmetries must cover distinct indices.");
50  constexpr static int One = One_;
51  constexpr static int Two = Two_;
52  constexpr static int Flags = NegationFlag;
53 };
54 
55 template <int One_, int Two_>
56 struct Hermiticity {
57  static_assert(One_ != Two_, "Symmetries must cover distinct indices.");
58  constexpr static int One = One_;
59  constexpr static int Two = Two_;
60  constexpr static int Flags = ConjugationFlag;
61 };
62 
63 template <int One_, int Two_>
64 struct AntiHermiticity {
65  static_assert(One_ != Two_, "Symmetries must cover distinct indices.");
66  constexpr static int One = One_;
67  constexpr static int Two = Two_;
68  constexpr static int Flags = ConjugationFlag | NegationFlag;
69 };
70 
84 class DynamicSGroup;
85 
96 template <typename... Gen>
97 class DynamicSGroupFromTemplateArgs;
98 
118 template <typename... Gen>
119 class StaticSGroup;
120 
133 template <typename... Gen>
134 class SGroup : public internal::tensor_symmetry_pre_analysis<internal::tensor_symmetry_num_indices<Gen...>::value,
135  Gen...>::root_type {
136  public:
137  constexpr static std::size_t NumIndices = internal::tensor_symmetry_num_indices<Gen...>::value;
138  typedef typename internal::tensor_symmetry_pre_analysis<NumIndices, Gen...>::root_type Base;
139 
140  // make standard constructors + assignment operators public
141  inline SGroup() : Base() {}
142  inline SGroup(const SGroup<Gen...>& other) : Base(other) {}
143  inline SGroup(SGroup<Gen...>&& other) : Base(other) {}
144  inline SGroup<Gen...>& operator=(const SGroup<Gen...>& other) {
145  Base::operator=(other);
146  return *this;
147  }
148  inline SGroup<Gen...>& operator=(SGroup<Gen...>&& other) {
149  Base::operator=(other);
150  return *this;
151  }
152 
153  // all else is defined in the base class
154 };
155 
156 namespace internal {
157 
158 template <typename... Sym>
159 struct tensor_symmetry_num_indices {
160  constexpr static std::size_t value = 1;
161 };
162 
163 template <int One_, int Two_, typename... Sym>
164 struct tensor_symmetry_num_indices<Symmetry<One_, Two_>, Sym...> {
165  private:
166  constexpr static std::size_t One = static_cast<std::size_t>(One_);
167  constexpr static std::size_t Two = static_cast<std::size_t>(Two_);
168  constexpr static std::size_t Three = tensor_symmetry_num_indices<Sym...>::value;
169 
170  // don't use std::max, since it's not constexpr until C++14...
171  constexpr static std::size_t maxOneTwoPlusOne = ((One > Two) ? One : Two) + 1;
172 
173  public:
174  constexpr static std::size_t value = (maxOneTwoPlusOne > Three) ? maxOneTwoPlusOne : Three;
175 };
176 
177 template <int One_, int Two_, typename... Sym>
178 struct tensor_symmetry_num_indices<AntiSymmetry<One_, Two_>, Sym...>
179  : public tensor_symmetry_num_indices<Symmetry<One_, Two_>, Sym...> {};
180 template <int One_, int Two_, typename... Sym>
181 struct tensor_symmetry_num_indices<Hermiticity<One_, Two_>, Sym...>
182  : public tensor_symmetry_num_indices<Symmetry<One_, Two_>, Sym...> {};
183 template <int One_, int Two_, typename... Sym>
184 struct tensor_symmetry_num_indices<AntiHermiticity<One_, Two_>, Sym...>
185  : public tensor_symmetry_num_indices<Symmetry<One_, Two_>, Sym...> {};
186 
234 template <std::size_t NumIndices>
235 struct tensor_symmetry_pre_analysis<NumIndices> {
236  typedef StaticSGroup<> root_type;
237 };
238 
239 template <std::size_t NumIndices, typename Gen_, typename... Gens_>
240 struct tensor_symmetry_pre_analysis<NumIndices, Gen_, Gens_...> {
241  constexpr static std::size_t max_static_generators = 4;
242  constexpr static std::size_t max_static_elements = 16;
243  typedef tensor_static_symgroup_if<(sizeof...(Gens_) + 1 <= max_static_generators), NumIndices, Gen_, Gens_...> helper;
244  constexpr static std::size_t possible_size = helper::size;
245 
246  typedef std::conditional_t<possible_size == 0 || possible_size >= max_static_elements,
247  DynamicSGroupFromTemplateArgs<Gen_, Gens_...>, typename helper::type>
248  root_type;
249 };
250 
251 template <bool instantiate, std::size_t NumIndices, typename... Gens>
252 struct tensor_static_symgroup_if {
253  constexpr static std::size_t size = 0;
254  typedef void type;
255 };
256 
257 template <std::size_t NumIndices, typename... Gens>
258 struct tensor_static_symgroup_if<true, NumIndices, Gens...> : tensor_static_symgroup<NumIndices, Gens...> {};
259 
260 template <typename Tensor_>
261 struct tensor_symmetry_assign_value {
262  typedef typename Tensor_::Index Index;
263  typedef typename Tensor_::Scalar Scalar;
264  constexpr static std::size_t NumIndices = Tensor_::NumIndices;
265 
266  static inline int run(const std::array<Index, NumIndices>& transformed_indices, int transformation_flags, int dummy,
267  Tensor_& tensor, const Scalar& value_) {
268  Scalar value(value_);
269  if (transformation_flags & ConjugationFlag) value = numext::conj(value);
270  if (transformation_flags & NegationFlag) value = -value;
271  tensor.coeffRef(transformed_indices) = value;
272  return dummy;
273  }
274 };
275 
276 template <typename Tensor_>
277 struct tensor_symmetry_calculate_flags {
278  typedef typename Tensor_::Index Index;
279  constexpr static std::size_t NumIndices = Tensor_::NumIndices;
280 
281  static inline int run(const std::array<Index, NumIndices>& transformed_indices, int transform_flags,
282  int current_flags, const std::array<Index, NumIndices>& orig_indices) {
283  if (transformed_indices == orig_indices) {
284  if (transform_flags & (ConjugationFlag | NegationFlag))
285  return current_flags | GlobalImagFlag; // anti-hermitian diagonal
286  else if (transform_flags & ConjugationFlag)
287  return current_flags | GlobalRealFlag; // hermitian diagonal
288  else if (transform_flags & NegationFlag)
289  return current_flags | GlobalZeroFlag; // anti-symmetric diagonal
290  }
291  return current_flags;
292  }
293 };
294 
295 template <typename Tensor_, typename Symmetry_, int Flags = 0>
296 class tensor_symmetry_value_setter {
297  public:
298  typedef typename Tensor_::Index Index;
299  typedef typename Tensor_::Scalar Scalar;
300  constexpr static std::size_t NumIndices = Tensor_::NumIndices;
301 
302  inline tensor_symmetry_value_setter(Tensor_& tensor, Symmetry_ const& symmetry,
303  std::array<Index, NumIndices> const& indices)
304  : m_tensor(tensor), m_symmetry(symmetry), m_indices(indices) {}
305 
306  inline tensor_symmetry_value_setter<Tensor_, Symmetry_, Flags>& operator=(Scalar const& value) {
307  doAssign(value);
308  return *this;
309  }
310 
311  private:
312  Tensor_& m_tensor;
313  Symmetry_ m_symmetry;
314  std::array<Index, NumIndices> m_indices;
315 
316  inline void doAssign(Scalar const& value) {
317 #ifdef EIGEN_TENSOR_SYMMETRY_CHECK_VALUES
318  int value_flags = m_symmetry.template apply<internal::tensor_symmetry_calculate_flags<Tensor_>, int>(
319  m_indices, m_symmetry.globalFlags(), m_indices);
320  if (value_flags & GlobalRealFlag) eigen_assert(numext::imag(value) == 0);
321  if (value_flags & GlobalImagFlag) eigen_assert(numext::real(value) == 0);
322 #endif
323  m_symmetry.template apply<internal::tensor_symmetry_assign_value<Tensor_>, int>(m_indices, 0, m_tensor, value);
324  }
325 };
326 
327 } // end namespace internal
328 
329 } // end namespace Eigen
330 
331 #endif // EIGEN_CXX11_TENSORSYMMETRY_SYMMETRY_H
332 
333 /*
334  * kate: space-indent on; indent-width 2; mixedindent off; indent-mode cstyle;
335  */
Symmetry group, initialized from template arguments.
Definition: Symmetry.h:134
Namespace containing all symbols from the Eigen library.
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index