Eigen-Contrib  5.0.1
 
Loading...
Searching...
No Matches
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// SPDX-License-Identifier: MPL-2.0
10
11#ifndef EIGEN_TENSORSYMMETRY_SYMMETRY_H
12#define EIGEN_TENSORSYMMETRY_SYMMETRY_H
13
14// IWYU pragma: private
15#include "./InternalHeaderCheck.h"
16
17namespace Eigen {
18
19enum { NegationFlag = 0x01, ConjugationFlag = 0x02 };
20
21enum { GlobalRealFlag = 0x01, GlobalImagFlag = 0x02, GlobalZeroFlag = 0x03 };
22
23namespace internal {
24
25template <std::size_t NumIndices, typename... Sym>
26struct tensor_symmetry_pre_analysis;
27template <std::size_t NumIndices, typename... Sym>
28struct tensor_static_symgroup;
29template <bool instantiate, std::size_t NumIndices, typename... Sym>
30struct tensor_static_symgroup_if;
31template <typename Tensor_>
32struct tensor_symmetry_calculate_flags;
33template <typename Tensor_>
34struct tensor_symmetry_assign_value;
35template <typename... Sym>
36struct tensor_symmetry_num_indices;
37
38} // end namespace internal
39
40template <int One_, int Two_>
41struct Symmetry {
42 static_assert(One_ != Two_, "Symmetries must cover distinct indices.");
43 constexpr static int One = One_;
44 constexpr static int Two = Two_;
45 constexpr static int Flags = 0;
46};
47
48template <int One_, int Two_>
49struct AntiSymmetry {
50 static_assert(One_ != Two_, "Symmetries must cover distinct indices.");
51 constexpr static int One = One_;
52 constexpr static int Two = Two_;
53 constexpr static int Flags = NegationFlag;
54};
55
56template <int One_, int Two_>
57struct Hermiticity {
58 static_assert(One_ != Two_, "Symmetries must cover distinct indices.");
59 constexpr static int One = One_;
60 constexpr static int Two = Two_;
61 constexpr static int Flags = ConjugationFlag;
62};
63
64template <int One_, int Two_>
65struct AntiHermiticity {
66 static_assert(One_ != Two_, "Symmetries must cover distinct indices.");
67 constexpr static int One = One_;
68 constexpr static int Two = Two_;
69 constexpr static int Flags = ConjugationFlag | NegationFlag;
70};
71
85class DynamicSGroup;
86
97template <typename... Gen>
98class DynamicSGroupFromTemplateArgs;
99
119template <typename... Gen>
120class StaticSGroup;
121
134template <typename... Gen>
135class SGroup : public internal::tensor_symmetry_pre_analysis<internal::tensor_symmetry_num_indices<Gen...>::value,
136 Gen...>::root_type {
137 public:
138 constexpr static std::size_t NumIndices = internal::tensor_symmetry_num_indices<Gen...>::value;
139 typedef typename internal::tensor_symmetry_pre_analysis<NumIndices, Gen...>::root_type Base;
140
141 // make standard constructors + assignment operators public
142 inline SGroup() = default;
143 inline SGroup(const SGroup<Gen...>& other) = default;
144 inline SGroup(SGroup<Gen...>&& other) : Base(other) {}
145 inline SGroup<Gen...>& operator=(const SGroup<Gen...>& other) {
146 Base::operator=(other);
147 return *this;
148 }
149 inline SGroup<Gen...>& operator=(SGroup<Gen...>&& other) {
150 Base::operator=(other);
151 return *this;
152 }
153
154 // all else is defined in the base class
155};
156
157namespace internal {
158
159template <typename... Sym>
160struct tensor_symmetry_num_indices {
161 constexpr static std::size_t value = 1;
162};
163
164template <int One_, int Two_, typename... Sym>
165struct tensor_symmetry_num_indices<Symmetry<One_, Two_>, Sym...> {
166 private:
167 constexpr static std::size_t One = static_cast<std::size_t>(One_);
168 constexpr static std::size_t Two = static_cast<std::size_t>(Two_);
169 constexpr static std::size_t Three = tensor_symmetry_num_indices<Sym...>::value;
170
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
177template <int One_, int Two_, typename... Sym>
178struct tensor_symmetry_num_indices<AntiSymmetry<One_, Two_>, Sym...>
179 : public tensor_symmetry_num_indices<Symmetry<One_, Two_>, Sym...> {};
180template <int One_, int Two_, typename... Sym>
181struct tensor_symmetry_num_indices<Hermiticity<One_, Two_>, Sym...>
182 : public tensor_symmetry_num_indices<Symmetry<One_, Two_>, Sym...> {};
183template <int One_, int Two_, typename... Sym>
184struct tensor_symmetry_num_indices<AntiHermiticity<One_, Two_>, Sym...>
185 : public tensor_symmetry_num_indices<Symmetry<One_, Two_>, Sym...> {};
186
234template <std::size_t NumIndices>
235struct tensor_symmetry_pre_analysis<NumIndices> {
236 typedef StaticSGroup<> root_type;
237};
238
239template <std::size_t NumIndices, typename Gen_, typename... Gens_>
240struct 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
251template <bool instantiate, std::size_t NumIndices, typename... Gens>
252struct tensor_static_symgroup_if {
253 constexpr static std::size_t size = 0;
254 typedef void type;
255};
256
257template <std::size_t NumIndices, typename... Gens>
258struct tensor_static_symgroup_if<true, NumIndices, Gens...> : tensor_static_symgroup<NumIndices, Gens...> {};
259
260template <typename Tensor_>
261struct 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
276template <typename Tensor_>
277struct 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
295template <typename Tensor_, typename Symmetry_, int Flags = 0>
296class 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_TENSORSYMMETRY_SYMMETRY_H
332
333/*
334 * kate: space-indent on; indent-width 2; mixedindent off; indent-mode cstyle;
335 */
Dynamic symmetry group.
Definition DynamicSymmetry.h:19
Static symmetry group.
Definition StaticSymmetry.h:167
Namespace containing all symbols from the Eigen library.