10 #ifndef EIGEN_CXX11_TENSORSYMMETRY_SYMMETRY_H 11 #define EIGEN_CXX11_TENSORSYMMETRY_SYMMETRY_H 14 #include "./InternalHeaderCheck.h" 18 enum { NegationFlag = 0x01, ConjugationFlag = 0x02 };
20 enum { GlobalRealFlag = 0x01, GlobalImagFlag = 0x02, GlobalZeroFlag = 0x03 };
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;
39 template <
int One_,
int Two_>
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;
47 template <
int One_,
int Two_>
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;
55 template <
int One_,
int Two_>
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;
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;
96 template <
typename... Gen>
97 class DynamicSGroupFromTemplateArgs;
118 template <
typename... Gen>
133 template <
typename... Gen>
134 class SGroup :
public internal::tensor_symmetry_pre_analysis<internal::tensor_symmetry_num_indices<Gen...>::value,
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;
141 inline SGroup() : Base() {}
145 Base::operator=(other);
149 Base::operator=(other);
158 template <
typename... Sym>
159 struct tensor_symmetry_num_indices {
160 constexpr
static std::size_t value = 1;
163 template <
int One_,
int Two_,
typename... Sym>
164 struct tensor_symmetry_num_indices<Symmetry<One_, Two_>, Sym...> {
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;
171 constexpr
static std::size_t maxOneTwoPlusOne = ((One > Two) ? One : Two) + 1;
174 constexpr
static std::size_t value = (maxOneTwoPlusOne > Three) ? maxOneTwoPlusOne : Three;
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...> {};
234 template <std::
size_t NumIndices>
235 struct tensor_symmetry_pre_analysis<NumIndices> {
236 typedef StaticSGroup<> root_type;
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;
246 typedef std::conditional_t<possible_size == 0 || possible_size >= max_static_elements,
247 DynamicSGroupFromTemplateArgs<Gen_, Gens_...>,
typename helper::type>
251 template <
bool instantiate, std::size_t NumIndices,
typename... Gens>
252 struct tensor_static_symgroup_if {
253 constexpr
static std::size_t size = 0;
257 template <std::size_t NumIndices,
typename... Gens>
258 struct tensor_static_symgroup_if<true, NumIndices, Gens...> : tensor_static_symgroup<NumIndices, Gens...> {};
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;
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;
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;
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;
286 else if (transform_flags & ConjugationFlag)
287 return current_flags | GlobalRealFlag;
288 else if (transform_flags & NegationFlag)
289 return current_flags | GlobalZeroFlag;
291 return current_flags;
295 template <
typename Tensor_,
typename Symmetry_,
int Flags = 0>
296 class tensor_symmetry_value_setter {
298 typedef typename Tensor_::Index
Index;
299 typedef typename Tensor_::Scalar Scalar;
300 constexpr
static std::size_t NumIndices = Tensor_::NumIndices;
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) {}
306 inline tensor_symmetry_value_setter<Tensor_, Symmetry_, Flags>& operator=(Scalar
const& value) {
313 Symmetry_ m_symmetry;
314 std::array<Index, NumIndices> m_indices;
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);
323 m_symmetry.template apply<internal::tensor_symmetry_assign_value<Tensor_>,
int>(m_indices, 0, m_tensor, value);
331 #endif // EIGEN_CXX11_TENSORSYMMETRY_SYMMETRY_H Symmetry group, initialized from template arguments.
Definition: Symmetry.h:134
Namespace containing all symbols from the Eigen library.
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index