Symmetry.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_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>
26 template <std::size_t NumIndices, typename... Sym>
28 template <bool instantiate, std::size_t NumIndices, typename... Sym>
30 template <typename Tensor_>
32 template <typename Tensor_>
34 template <typename... Sym>
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_>
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>
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>
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> {
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>
249 };
250 
251 template <bool instantiate, std::size_t NumIndices, typename... Gens>
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_>
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_>
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>
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 
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  */
AnnoyingScalar conj(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:133
AnnoyingScalar imag(const AnnoyingScalar &)
Definition: AnnoyingScalar.h:132
#define eigen_assert(x)
Definition: Macros.h:910
Scalar Scalar int size
Definition: benchVecAdd.cpp:17
SCALAR Scalar
Definition: bench_gemm.cpp:45
Dynamic symmetry group, initialized from template arguments.
Definition: DynamicSymmetry.h:166
Dynamic symmetry group.
Definition: DynamicSymmetry.h:18
Symmetry group, initialized from template arguments.
Definition: Symmetry.h:135
SGroup< Gen... > & operator=(const SGroup< Gen... > &other)
Definition: Symmetry.h:144
SGroup< Gen... > & operator=(SGroup< Gen... > &&other)
Definition: Symmetry.h:148
constexpr static std::size_t NumIndices
Definition: Symmetry.h:137
SGroup()
Definition: Symmetry.h:141
internal::tensor_symmetry_pre_analysis< NumIndices, Gen... >::root_type Base
Definition: Symmetry.h:138
SGroup(SGroup< Gen... > &&other)
Definition: Symmetry.h:143
SGroup(const SGroup< Gen... > &other)
Definition: Symmetry.h:142
Static symmetry group.
Definition: StaticSymmetry.h:172
Tensor_::Index Index
Definition: Symmetry.h:298
tensor_symmetry_value_setter< Tensor_, Symmetry_, Flags > & operator=(Scalar const &value)
Definition: Symmetry.h:306
void doAssign(Scalar const &value)
Definition: Symmetry.h:316
Tensor_ & m_tensor
Definition: Symmetry.h:312
tensor_symmetry_value_setter(Tensor_ &tensor, Symmetry_ const &symmetry, std::array< Index, NumIndices > const &indices)
Definition: Symmetry.h:302
std::array< Index, NumIndices > m_indices
Definition: Symmetry.h:314
Tensor_::Scalar Scalar
Definition: Symmetry.h:299
Symmetry_ m_symmetry
Definition: Symmetry.h:313
constexpr static std::size_t NumIndices
Definition: Symmetry.h:300
float real
Definition: datatypes.h:10
Namespace containing all symbols from the Eigen library.
Definition: bench_norm.cpp:70
squared absolute value
Definition: GlobalFunctions.h:87
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
Extend namespace for flags.
Definition: fsi_chan_precond_driver.cc:56
Definition: Eigen_Colamd.h:49
Definition: Symmetry.h:64
constexpr static int One
Definition: Symmetry.h:66
constexpr static int Two
Definition: Symmetry.h:67
Definition: Symmetry.h:48
constexpr static int Two
Definition: Symmetry.h:51
constexpr static int One
Definition: Symmetry.h:50
Definition: Symmetry.h:56
constexpr static int Two
Definition: Symmetry.h:59
constexpr static int One
Definition: Symmetry.h:58
Definition: Symmetry.h:40
constexpr static int Two
Definition: Symmetry.h:43
constexpr static int One
Definition: Symmetry.h:42
void type
Definition: Symmetry.h:254
constexpr static std::size_t size
Definition: Symmetry.h:253
Definition: StaticSymmetry.h:104
constexpr static std::size_t NumIndices
Definition: Symmetry.h:264
Tensor_::Scalar Scalar
Definition: Symmetry.h:263
static int run(const std::array< Index, NumIndices > &transformed_indices, int transformation_flags, int dummy, Tensor_ &tensor, const Scalar &value_)
Definition: Symmetry.h:266
Tensor_::Index Index
Definition: Symmetry.h:262
Tensor_::Index Index
Definition: Symmetry.h:278
constexpr static std::size_t NumIndices
Definition: Symmetry.h:279
static int run(const std::array< Index, NumIndices > &transformed_indices, int transform_flags, int current_flags, const std::array< Index, NumIndices > &orig_indices)
Definition: Symmetry.h:281
constexpr static std::size_t value
Definition: Symmetry.h:160
tensor_static_symgroup_if<(sizeof...(Gens_)+1<=max_static_generators), NumIndices, Gen_, Gens_... > helper
Definition: Symmetry.h:243
StaticSGroup root_type
Definition: Symmetry.h:236
Pre-select whether to use a static or dynamic symmetry group.
Definition: Symmetry.h:25