Warning, file /include/eigen3/unsupported/Eigen/CXX11/src/TensorSymmetry/Symmetry.h was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef EIGEN_CXX11_TENSORSYMMETRY_SYMMETRY_H
0011 #define EIGEN_CXX11_TENSORSYMMETRY_SYMMETRY_H
0012
0013 namespace Eigen {
0014
0015 enum {
0016 NegationFlag = 0x01,
0017 ConjugationFlag = 0x02
0018 };
0019
0020 enum {
0021 GlobalRealFlag = 0x01,
0022 GlobalImagFlag = 0x02,
0023 GlobalZeroFlag = 0x03
0024 };
0025
0026 namespace internal {
0027
0028 template<std::size_t NumIndices, typename... Sym> struct tensor_symmetry_pre_analysis;
0029 template<std::size_t NumIndices, typename... Sym> struct tensor_static_symgroup;
0030 template<bool instantiate, std::size_t NumIndices, typename... Sym> struct tensor_static_symgroup_if;
0031 template<typename Tensor_> struct tensor_symmetry_calculate_flags;
0032 template<typename Tensor_> struct tensor_symmetry_assign_value;
0033 template<typename... Sym> struct tensor_symmetry_num_indices;
0034
0035 }
0036
0037 template<int One_, int Two_>
0038 struct Symmetry
0039 {
0040 static_assert(One_ != Two_, "Symmetries must cover distinct indices.");
0041 constexpr static int One = One_;
0042 constexpr static int Two = Two_;
0043 constexpr static int Flags = 0;
0044 };
0045
0046 template<int One_, int Two_>
0047 struct AntiSymmetry
0048 {
0049 static_assert(One_ != Two_, "Symmetries must cover distinct indices.");
0050 constexpr static int One = One_;
0051 constexpr static int Two = Two_;
0052 constexpr static int Flags = NegationFlag;
0053 };
0054
0055 template<int One_, int Two_>
0056 struct Hermiticity
0057 {
0058 static_assert(One_ != Two_, "Symmetries must cover distinct indices.");
0059 constexpr static int One = One_;
0060 constexpr static int Two = Two_;
0061 constexpr static int Flags = ConjugationFlag;
0062 };
0063
0064 template<int One_, int Two_>
0065 struct AntiHermiticity
0066 {
0067 static_assert(One_ != Two_, "Symmetries must cover distinct indices.");
0068 constexpr static int One = One_;
0069 constexpr static int Two = Two_;
0070 constexpr static int Flags = ConjugationFlag | NegationFlag;
0071 };
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086 class DynamicSGroup;
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098 template<typename... Gen>
0099 class DynamicSGroupFromTemplateArgs;
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120 template<typename... Gen>
0121 class StaticSGroup;
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135 template<typename... Gen>
0136 class SGroup : public internal::tensor_symmetry_pre_analysis<internal::tensor_symmetry_num_indices<Gen...>::value, Gen...>::root_type
0137 {
0138 public:
0139 constexpr static std::size_t NumIndices = internal::tensor_symmetry_num_indices<Gen...>::value;
0140 typedef typename internal::tensor_symmetry_pre_analysis<NumIndices, Gen...>::root_type Base;
0141
0142
0143 inline SGroup() : Base() { }
0144 inline SGroup(const SGroup<Gen...>& other) : Base(other) { }
0145 inline SGroup(SGroup<Gen...>&& other) : Base(other) { }
0146 inline SGroup<Gen...>& operator=(const SGroup<Gen...>& other) { Base::operator=(other); return *this; }
0147 inline SGroup<Gen...>& operator=(SGroup<Gen...>&& other) { Base::operator=(other); return *this; }
0148
0149
0150 };
0151
0152 namespace internal {
0153
0154 template<typename... Sym> struct tensor_symmetry_num_indices
0155 {
0156 constexpr static std::size_t value = 1;
0157 };
0158
0159 template<int One_, int Two_, typename... Sym> struct tensor_symmetry_num_indices<Symmetry<One_, Two_>, Sym...>
0160 {
0161 private:
0162 constexpr static std::size_t One = static_cast<std::size_t>(One_);
0163 constexpr static std::size_t Two = static_cast<std::size_t>(Two_);
0164 constexpr static std::size_t Three = tensor_symmetry_num_indices<Sym...>::value;
0165
0166
0167 constexpr static std::size_t maxOneTwoPlusOne = ((One > Two) ? One : Two) + 1;
0168 public:
0169 constexpr static std::size_t value = (maxOneTwoPlusOne > Three) ? maxOneTwoPlusOne : Three;
0170 };
0171
0172 template<int One_, int Two_, typename... Sym> struct tensor_symmetry_num_indices<AntiSymmetry<One_, Two_>, Sym...>
0173 : public tensor_symmetry_num_indices<Symmetry<One_, Two_>, Sym...> {};
0174 template<int One_, int Two_, typename... Sym> struct tensor_symmetry_num_indices<Hermiticity<One_, Two_>, Sym...>
0175 : public tensor_symmetry_num_indices<Symmetry<One_, Two_>, Sym...> {};
0176 template<int One_, int Two_, typename... Sym> struct tensor_symmetry_num_indices<AntiHermiticity<One_, Two_>, Sym...>
0177 : public tensor_symmetry_num_indices<Symmetry<One_, Two_>, Sym...> {};
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226 template<std::size_t NumIndices>
0227 struct tensor_symmetry_pre_analysis<NumIndices>
0228 {
0229 typedef StaticSGroup<> root_type;
0230 };
0231
0232 template<std::size_t NumIndices, typename Gen_, typename... Gens_>
0233 struct tensor_symmetry_pre_analysis<NumIndices, Gen_, Gens_...>
0234 {
0235 constexpr static std::size_t max_static_generators = 4;
0236 constexpr static std::size_t max_static_elements = 16;
0237 typedef tensor_static_symgroup_if<(sizeof...(Gens_) + 1 <= max_static_generators), NumIndices, Gen_, Gens_...> helper;
0238 constexpr static std::size_t possible_size = helper::size;
0239
0240 typedef typename conditional<
0241 possible_size == 0 || possible_size >= max_static_elements,
0242 DynamicSGroupFromTemplateArgs<Gen_, Gens_...>,
0243 typename helper::type
0244 >::type root_type;
0245 };
0246
0247 template<bool instantiate, std::size_t NumIndices, typename... Gens>
0248 struct tensor_static_symgroup_if
0249 {
0250 constexpr static std::size_t size = 0;
0251 typedef void type;
0252 };
0253
0254 template<std::size_t NumIndices, typename... Gens>
0255 struct tensor_static_symgroup_if<true, NumIndices, Gens...> : tensor_static_symgroup<NumIndices, Gens...> {};
0256
0257 template<typename Tensor_>
0258 struct tensor_symmetry_assign_value
0259 {
0260 typedef typename Tensor_::Index Index;
0261 typedef typename Tensor_::Scalar Scalar;
0262 constexpr static std::size_t NumIndices = Tensor_::NumIndices;
0263
0264 static inline int run(const std::array<Index, NumIndices>& transformed_indices, int transformation_flags, int dummy, Tensor_& tensor, const Scalar& value_)
0265 {
0266 Scalar value(value_);
0267 if (transformation_flags & ConjugationFlag)
0268 value = numext::conj(value);
0269 if (transformation_flags & NegationFlag)
0270 value = -value;
0271 tensor.coeffRef(transformed_indices) = value;
0272 return dummy;
0273 }
0274 };
0275
0276 template<typename Tensor_>
0277 struct tensor_symmetry_calculate_flags
0278 {
0279 typedef typename Tensor_::Index Index;
0280 constexpr static std::size_t NumIndices = Tensor_::NumIndices;
0281
0282 static inline int run(const std::array<Index, NumIndices>& transformed_indices, int transform_flags, int current_flags, const std::array<Index, NumIndices>& orig_indices)
0283 {
0284 if (transformed_indices == orig_indices) {
0285 if (transform_flags & (ConjugationFlag | NegationFlag))
0286 return current_flags | GlobalImagFlag;
0287 else if (transform_flags & ConjugationFlag)
0288 return current_flags | GlobalRealFlag;
0289 else if (transform_flags & NegationFlag)
0290 return current_flags | GlobalZeroFlag;
0291 }
0292 return current_flags;
0293 }
0294 };
0295
0296 template<typename Tensor_, typename Symmetry_, int Flags = 0>
0297 class tensor_symmetry_value_setter
0298 {
0299 public:
0300 typedef typename Tensor_::Index Index;
0301 typedef typename Tensor_::Scalar Scalar;
0302 constexpr static std::size_t NumIndices = Tensor_::NumIndices;
0303
0304 inline tensor_symmetry_value_setter(Tensor_& tensor, Symmetry_ const& symmetry, std::array<Index, NumIndices> const& indices)
0305 : m_tensor(tensor), m_symmetry(symmetry), m_indices(indices) { }
0306
0307 inline tensor_symmetry_value_setter<Tensor_, Symmetry_, Flags>& operator=(Scalar const& value)
0308 {
0309 doAssign(value);
0310 return *this;
0311 }
0312 private:
0313 Tensor_& m_tensor;
0314 Symmetry_ m_symmetry;
0315 std::array<Index, NumIndices> m_indices;
0316
0317 inline void doAssign(Scalar const& value)
0318 {
0319 #ifdef EIGEN_TENSOR_SYMMETRY_CHECK_VALUES
0320 int value_flags = m_symmetry.template apply<internal::tensor_symmetry_calculate_flags<Tensor_>, int>(m_indices, m_symmetry.globalFlags(), m_indices);
0321 if (value_flags & GlobalRealFlag)
0322 eigen_assert(numext::imag(value) == 0);
0323 if (value_flags & GlobalImagFlag)
0324 eigen_assert(numext::real(value) == 0);
0325 #endif
0326 m_symmetry.template apply<internal::tensor_symmetry_assign_value<Tensor_>, int>(m_indices, 0, m_tensor, value);
0327 }
0328 };
0329
0330 }
0331
0332 }
0333
0334 #endif
0335
0336
0337
0338