![]() |
Eigen-unsupported
3.3.3
|
00001 // This file is part of Eigen, a lightweight C++ template library 00002 // for linear algebra. 00003 // 00004 // Copyright (C) 2013 Christian Seiler <christian@iwakd.de> 00005 // 00006 // This Source Code Form is subject to the terms of the Mozilla 00007 // Public License v. 2.0. If a copy of the MPL was not distributed 00008 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 00009 00010 #ifndef EIGEN_CXX11_TENSORSYMMETRY_SYMMETRY_H 00011 #define EIGEN_CXX11_TENSORSYMMETRY_SYMMETRY_H 00012 00013 namespace Eigen { 00014 00015 enum { 00016 NegationFlag = 0x01, 00017 ConjugationFlag = 0x02 00018 }; 00019 00020 enum { 00021 GlobalRealFlag = 0x01, 00022 GlobalImagFlag = 0x02, 00023 GlobalZeroFlag = 0x03 00024 }; 00025 00026 namespace internal { 00027 00028 template<std::size_t NumIndices, typename... Sym> struct tensor_symmetry_pre_analysis; 00029 template<std::size_t NumIndices, typename... Sym> struct tensor_static_symgroup; 00030 template<bool instantiate, std::size_t NumIndices, typename... Sym> struct tensor_static_symgroup_if; 00031 template<typename Tensor_> struct tensor_symmetry_calculate_flags; 00032 template<typename Tensor_> struct tensor_symmetry_assign_value; 00033 template<typename... Sym> struct tensor_symmetry_num_indices; 00034 00035 } // end namespace internal 00036 00037 template<int One_, int Two_> 00038 struct Symmetry 00039 { 00040 static_assert(One_ != Two_, "Symmetries must cover distinct indices."); 00041 constexpr static int One = One_; 00042 constexpr static int Two = Two_; 00043 constexpr static int Flags = 0; 00044 }; 00045 00046 template<int One_, int Two_> 00047 struct AntiSymmetry 00048 { 00049 static_assert(One_ != Two_, "Symmetries must cover distinct indices."); 00050 constexpr static int One = One_; 00051 constexpr static int Two = Two_; 00052 constexpr static int Flags = NegationFlag; 00053 }; 00054 00055 template<int One_, int Two_> 00056 struct Hermiticity 00057 { 00058 static_assert(One_ != Two_, "Symmetries must cover distinct indices."); 00059 constexpr static int One = One_; 00060 constexpr static int Two = Two_; 00061 constexpr static int Flags = ConjugationFlag; 00062 }; 00063 00064 template<int One_, int Two_> 00065 struct AntiHermiticity 00066 { 00067 static_assert(One_ != Two_, "Symmetries must cover distinct indices."); 00068 constexpr static int One = One_; 00069 constexpr static int Two = Two_; 00070 constexpr static int Flags = ConjugationFlag | NegationFlag; 00071 }; 00072 00086 class DynamicSGroup; 00087 00098 template<typename... Gen> 00099 class DynamicSGroupFromTemplateArgs; 00100 00120 template<typename... Gen> 00121 class StaticSGroup; 00122 00135 template<typename... Gen> 00136 class SGroup : public internal::tensor_symmetry_pre_analysis<internal::tensor_symmetry_num_indices<Gen...>::value, Gen...>::root_type 00137 { 00138 public: 00139 constexpr static std::size_t NumIndices = internal::tensor_symmetry_num_indices<Gen...>::value; 00140 typedef typename internal::tensor_symmetry_pre_analysis<NumIndices, Gen...>::root_type Base; 00141 00142 // make standard constructors + assignment operators public 00143 inline SGroup() : Base() { } 00144 inline SGroup(const SGroup<Gen...>& other) : Base(other) { } 00145 inline SGroup(SGroup<Gen...>&& other) : Base(other) { } 00146 inline SGroup<Gen...>& operator=(const SGroup<Gen...>& other) { Base::operator=(other); return *this; } 00147 inline SGroup<Gen...>& operator=(SGroup<Gen...>&& other) { Base::operator=(other); return *this; } 00148 00149 // all else is defined in the base class 00150 }; 00151 00152 namespace internal { 00153 00154 template<typename... Sym> struct tensor_symmetry_num_indices 00155 { 00156 constexpr static std::size_t value = 1; 00157 }; 00158 00159 template<int One_, int Two_, typename... Sym> struct tensor_symmetry_num_indices<Symmetry<One_, Two_>, Sym...> 00160 { 00161 private: 00162 constexpr static std::size_t One = static_cast<std::size_t>(One_); 00163 constexpr static std::size_t Two = static_cast<std::size_t>(Two_); 00164 constexpr static std::size_t Three = tensor_symmetry_num_indices<Sym...>::value; 00165 00166 // don't use std::max, since it's not constexpr until C++14... 00167 constexpr static std::size_t maxOneTwoPlusOne = ((One > Two) ? One : Two) + 1; 00168 public: 00169 constexpr static std::size_t value = (maxOneTwoPlusOne > Three) ? maxOneTwoPlusOne : Three; 00170 }; 00171 00172 template<int One_, int Two_, typename... Sym> struct tensor_symmetry_num_indices<AntiSymmetry<One_, Two_>, Sym...> 00173 : public tensor_symmetry_num_indices<Symmetry<One_, Two_>, Sym...> {}; 00174 template<int One_, int Two_, typename... Sym> struct tensor_symmetry_num_indices<Hermiticity<One_, Two_>, Sym...> 00175 : public tensor_symmetry_num_indices<Symmetry<One_, Two_>, Sym...> {}; 00176 template<int One_, int Two_, typename... Sym> struct tensor_symmetry_num_indices<AntiHermiticity<One_, Two_>, Sym...> 00177 : public tensor_symmetry_num_indices<Symmetry<One_, Two_>, Sym...> {}; 00178 00226 template<std::size_t NumIndices> 00227 struct tensor_symmetry_pre_analysis<NumIndices> 00228 { 00229 typedef StaticSGroup<> root_type; 00230 }; 00231 00232 template<std::size_t NumIndices, typename Gen_, typename... Gens_> 00233 struct tensor_symmetry_pre_analysis<NumIndices, Gen_, Gens_...> 00234 { 00235 constexpr static std::size_t max_static_generators = 4; 00236 constexpr static std::size_t max_static_elements = 16; 00237 typedef tensor_static_symgroup_if<(sizeof...(Gens_) + 1 <= max_static_generators), NumIndices, Gen_, Gens_...> helper; 00238 constexpr static std::size_t possible_size = helper::size; 00239 00240 typedef typename conditional< 00241 possible_size == 0 || possible_size >= max_static_elements, 00242 DynamicSGroupFromTemplateArgs<Gen_, Gens_...>, 00243 typename helper::type 00244 >::type root_type; 00245 }; 00246 00247 template<bool instantiate, std::size_t NumIndices, typename... Gens> 00248 struct tensor_static_symgroup_if 00249 { 00250 constexpr static std::size_t size = 0; 00251 typedef void type; 00252 }; 00253 00254 template<std::size_t NumIndices, typename... Gens> 00255 struct tensor_static_symgroup_if<true, NumIndices, Gens...> : tensor_static_symgroup<NumIndices, Gens...> {}; 00256 00257 template<typename Tensor_> 00258 struct tensor_symmetry_assign_value 00259 { 00260 typedef typename Tensor_::Index Index; 00261 typedef typename Tensor_::Scalar Scalar; 00262 constexpr static std::size_t NumIndices = Tensor_::NumIndices; 00263 00264 static inline int run(const std::array<Index, NumIndices>& transformed_indices, int transformation_flags, int dummy, Tensor_& tensor, const Scalar& value_) 00265 { 00266 Scalar value(value_); 00267 if (transformation_flags & ConjugationFlag) 00268 value = numext::conj(value); 00269 if (transformation_flags & NegationFlag) 00270 value = -value; 00271 tensor.coeffRef(transformed_indices) = value; 00272 return dummy; 00273 } 00274 }; 00275 00276 template<typename Tensor_> 00277 struct tensor_symmetry_calculate_flags 00278 { 00279 typedef typename Tensor_::Index Index; 00280 constexpr static std::size_t NumIndices = Tensor_::NumIndices; 00281 00282 static inline int run(const std::array<Index, NumIndices>& transformed_indices, int transform_flags, int current_flags, const std::array<Index, NumIndices>& orig_indices) 00283 { 00284 if (transformed_indices == orig_indices) { 00285 if (transform_flags & (ConjugationFlag | NegationFlag)) 00286 return current_flags | GlobalImagFlag; // anti-hermitian diagonal 00287 else if (transform_flags & ConjugationFlag) 00288 return current_flags | GlobalRealFlag; // hermitian diagonal 00289 else if (transform_flags & NegationFlag) 00290 return current_flags | GlobalZeroFlag; // anti-symmetric diagonal 00291 } 00292 return current_flags; 00293 } 00294 }; 00295 00296 template<typename Tensor_, typename Symmetry_, int Flags = 0> 00297 class tensor_symmetry_value_setter 00298 { 00299 public: 00300 typedef typename Tensor_::Index Index; 00301 typedef typename Tensor_::Scalar Scalar; 00302 constexpr static std::size_t NumIndices = Tensor_::NumIndices; 00303 00304 inline tensor_symmetry_value_setter(Tensor_& tensor, Symmetry_ const& symmetry, std::array<Index, NumIndices> const& indices) 00305 : m_tensor(tensor), m_symmetry(symmetry), m_indices(indices) { } 00306 00307 inline tensor_symmetry_value_setter<Tensor_, Symmetry_, Flags>& operator=(Scalar const& value) 00308 { 00309 doAssign(value); 00310 return *this; 00311 } 00312 private: 00313 Tensor_& m_tensor; 00314 Symmetry_ m_symmetry; 00315 std::array<Index, NumIndices> m_indices; 00316 00317 inline void doAssign(Scalar const& value) 00318 { 00319 #ifdef EIGEN_TENSOR_SYMMETRY_CHECK_VALUES 00320 int value_flags = m_symmetry.template apply<internal::tensor_symmetry_calculate_flags<Tensor_>, int>(m_indices, m_symmetry.globalFlags(), m_indices); 00321 if (value_flags & GlobalRealFlag) 00322 eigen_assert(numext::imag(value) == 0); 00323 if (value_flags & GlobalImagFlag) 00324 eigen_assert(numext::real(value) == 0); 00325 #endif 00326 m_symmetry.template apply<internal::tensor_symmetry_assign_value<Tensor_>, int>(m_indices, 0, m_tensor, value); 00327 } 00328 }; 00329 00330 } // end namespace internal 00331 00332 } // end namespace Eigen 00333 00334 #endif // EIGEN_CXX11_TENSORSYMMETRY_SYMMETRY_H 00335 00336 /* 00337 * kate: space-indent on; indent-width 2; mixedindent off; indent-mode cstyle; 00338 */