![]() |
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_STATICSYMMETRY_H 00011 #define EIGEN_CXX11_TENSORSYMMETRY_STATICSYMMETRY_H 00012 00013 namespace Eigen { 00014 00015 namespace internal { 00016 00017 template<typename list> struct tensor_static_symgroup_permutate; 00018 00019 template<int... nn> 00020 struct tensor_static_symgroup_permutate<numeric_list<int, nn...>> 00021 { 00022 constexpr static std::size_t N = sizeof...(nn); 00023 00024 template<typename T> 00025 constexpr static inline std::array<T, N> run(const std::array<T, N>& indices) 00026 { 00027 return {{indices[nn]...}}; 00028 } 00029 }; 00030 00031 template<typename indices_, int flags_> 00032 struct tensor_static_symgroup_element 00033 { 00034 typedef indices_ indices; 00035 constexpr static int flags = flags_; 00036 }; 00037 00038 template<typename Gen, int N> 00039 struct tensor_static_symgroup_element_ctor 00040 { 00041 typedef tensor_static_symgroup_element< 00042 typename gen_numeric_list_swapped_pair<int, N, Gen::One, Gen::Two>::type, 00043 Gen::Flags 00044 > type; 00045 }; 00046 00047 template<int N> 00048 struct tensor_static_symgroup_identity_ctor 00049 { 00050 typedef tensor_static_symgroup_element< 00051 typename gen_numeric_list<int, N>::type, 00052 0 00053 > type; 00054 }; 00055 00056 template<typename iib> 00057 struct tensor_static_symgroup_multiply_helper 00058 { 00059 template<int... iia> 00060 constexpr static inline numeric_list<int, get<iia, iib>::value...> helper(numeric_list<int, iia...>) { 00061 return numeric_list<int, get<iia, iib>::value...>(); 00062 } 00063 }; 00064 00065 template<typename A, typename B> 00066 struct tensor_static_symgroup_multiply 00067 { 00068 private: 00069 typedef typename A::indices iia; 00070 typedef typename B::indices iib; 00071 constexpr static int ffa = A::flags; 00072 constexpr static int ffb = B::flags; 00073 00074 public: 00075 static_assert(iia::count == iib::count, "Cannot multiply symmetry elements with different number of indices."); 00076 00077 typedef tensor_static_symgroup_element< 00078 decltype(tensor_static_symgroup_multiply_helper<iib>::helper(iia())), 00079 ffa ^ ffb 00080 > type; 00081 }; 00082 00083 template<typename A, typename B> 00084 struct tensor_static_symgroup_equality 00085 { 00086 typedef typename A::indices iia; 00087 typedef typename B::indices iib; 00088 constexpr static int ffa = A::flags; 00089 constexpr static int ffb = B::flags; 00090 static_assert(iia::count == iib::count, "Cannot compare symmetry elements with different number of indices."); 00091 00092 constexpr static bool value = is_same<iia, iib>::value; 00093 00094 private: 00095 /* this should be zero if they are identical, or else the tensor 00096 * will be forced to be pure real, pure imaginary or even pure zero 00097 */ 00098 constexpr static int flags_cmp_ = ffa ^ ffb; 00099 00100 /* either they are not equal, then we don't care whether the flags 00101 * match, or they are equal, and then we have to check 00102 */ 00103 constexpr static bool is_zero = value && flags_cmp_ == NegationFlag; 00104 constexpr static bool is_real = value && flags_cmp_ == ConjugationFlag; 00105 constexpr static bool is_imag = value && flags_cmp_ == (NegationFlag | ConjugationFlag); 00106 00107 public: 00108 constexpr static int global_flags = 00109 (is_real ? GlobalRealFlag : 0) | 00110 (is_imag ? GlobalImagFlag : 0) | 00111 (is_zero ? GlobalZeroFlag : 0); 00112 }; 00113 00114 template<std::size_t NumIndices, typename... Gen> 00115 struct tensor_static_symgroup 00116 { 00117 typedef StaticSGroup<Gen...> type; 00118 constexpr static std::size_t size = type::static_size; 00119 }; 00120 00121 template<typename Index, std::size_t N, int... ii, int... jj> 00122 constexpr static inline std::array<Index, N> tensor_static_symgroup_index_permute(std::array<Index, N> idx, internal::numeric_list<int, ii...>, internal::numeric_list<int, jj...>) 00123 { 00124 return {{ idx[ii]..., idx[jj]... }}; 00125 } 00126 00127 template<typename Index, int... ii> 00128 static inline std::vector<Index> tensor_static_symgroup_index_permute(std::vector<Index> idx, internal::numeric_list<int, ii...>) 00129 { 00130 std::vector<Index> result{{ idx[ii]... }}; 00131 std::size_t target_size = idx.size(); 00132 for (std::size_t i = result.size(); i < target_size; i++) 00133 result.push_back(idx[i]); 00134 return result; 00135 } 00136 00137 template<typename T> struct tensor_static_symgroup_do_apply; 00138 00139 template<typename first, typename... next> 00140 struct tensor_static_symgroup_do_apply<internal::type_list<first, next...>> 00141 { 00142 template<typename Op, typename RV, std::size_t SGNumIndices, typename Index, std::size_t NumIndices, typename... Args> 00143 static inline RV run(const std::array<Index, NumIndices>& idx, RV initial, Args&&... args) 00144 { 00145 static_assert(NumIndices >= SGNumIndices, "Can only apply symmetry group to objects that have at least the required amount of indices."); 00146 typedef typename internal::gen_numeric_list<int, NumIndices - SGNumIndices, SGNumIndices>::type remaining_indices; 00147 initial = Op::run(tensor_static_symgroup_index_permute(idx, typename first::indices(), remaining_indices()), first::flags, initial, std::forward<Args>(args)...); 00148 return tensor_static_symgroup_do_apply<internal::type_list<next...>>::template run<Op, RV, SGNumIndices>(idx, initial, args...); 00149 } 00150 00151 template<typename Op, typename RV, std::size_t SGNumIndices, typename Index, typename... Args> 00152 static inline RV run(const std::vector<Index>& idx, RV initial, Args&&... args) 00153 { 00154 eigen_assert(idx.size() >= SGNumIndices && "Can only apply symmetry group to objects that have at least the required amount of indices."); 00155 initial = Op::run(tensor_static_symgroup_index_permute(idx, typename first::indices()), first::flags, initial, std::forward<Args>(args)...); 00156 return tensor_static_symgroup_do_apply<internal::type_list<next...>>::template run<Op, RV, SGNumIndices>(idx, initial, args...); 00157 } 00158 }; 00159 00160 template<EIGEN_TPL_PP_SPEC_HACK_DEF(typename, empty)> 00161 struct tensor_static_symgroup_do_apply<internal::type_list<EIGEN_TPL_PP_SPEC_HACK_USE(empty)>> 00162 { 00163 template<typename Op, typename RV, std::size_t SGNumIndices, typename Index, std::size_t NumIndices, typename... Args> 00164 static inline RV run(const std::array<Index, NumIndices>&, RV initial, Args&&...) 00165 { 00166 // do nothing 00167 return initial; 00168 } 00169 00170 template<typename Op, typename RV, std::size_t SGNumIndices, typename Index, typename... Args> 00171 static inline RV run(const std::vector<Index>&, RV initial, Args&&...) 00172 { 00173 // do nothing 00174 return initial; 00175 } 00176 }; 00177 00178 } // end namespace internal 00179 00180 template<typename... Gen> 00181 class StaticSGroup 00182 { 00183 constexpr static std::size_t NumIndices = internal::tensor_symmetry_num_indices<Gen...>::value; 00184 typedef internal::group_theory::enumerate_group_elements< 00185 internal::tensor_static_symgroup_multiply, 00186 internal::tensor_static_symgroup_equality, 00187 typename internal::tensor_static_symgroup_identity_ctor<NumIndices>::type, 00188 internal::type_list<typename internal::tensor_static_symgroup_element_ctor<Gen, NumIndices>::type...> 00189 > group_elements; 00190 typedef typename group_elements::type ge; 00191 public: 00192 constexpr inline StaticSGroup() {} 00193 constexpr inline StaticSGroup(const StaticSGroup<Gen...>&) {} 00194 constexpr inline StaticSGroup(StaticSGroup<Gen...>&&) {} 00195 00196 template<typename Op, typename RV, typename Index, std::size_t N, typename... Args> 00197 static inline RV apply(const std::array<Index, N>& idx, RV initial, Args&&... args) 00198 { 00199 return internal::tensor_static_symgroup_do_apply<ge>::template run<Op, RV, NumIndices>(idx, initial, args...); 00200 } 00201 00202 template<typename Op, typename RV, typename Index, typename... Args> 00203 static inline RV apply(const std::vector<Index>& idx, RV initial, Args&&... args) 00204 { 00205 eigen_assert(idx.size() == NumIndices); 00206 return internal::tensor_static_symgroup_do_apply<ge>::template run<Op, RV, NumIndices>(idx, initial, args...); 00207 } 00208 00209 constexpr static std::size_t static_size = ge::count; 00210 00211 constexpr static inline std::size_t size() { 00212 return ge::count; 00213 } 00214 constexpr static inline int globalFlags() { return group_elements::global_flags; } 00215 00216 template<typename Tensor_, typename... IndexTypes> 00217 inline internal::tensor_symmetry_value_setter<Tensor_, StaticSGroup<Gen...>> operator()(Tensor_& tensor, typename Tensor_::Index firstIndex, IndexTypes... otherIndices) const 00218 { 00219 static_assert(sizeof...(otherIndices) + 1 == Tensor_::NumIndices, "Number of indices used to access a tensor coefficient must be equal to the rank of the tensor."); 00220 return operator()(tensor, std::array<typename Tensor_::Index, Tensor_::NumIndices>{{firstIndex, otherIndices...}}); 00221 } 00222 00223 template<typename Tensor_> 00224 inline internal::tensor_symmetry_value_setter<Tensor_, StaticSGroup<Gen...>> operator()(Tensor_& tensor, std::array<typename Tensor_::Index, Tensor_::NumIndices> const& indices) const 00225 { 00226 return internal::tensor_symmetry_value_setter<Tensor_, StaticSGroup<Gen...>>(tensor, *this, indices); 00227 } 00228 }; 00229 00230 } // end namespace Eigen 00231 00232 #endif // EIGEN_CXX11_TENSORSYMMETRY_STATICSYMMETRY_H 00233 00234 /* 00235 * kate: space-indent on; indent-width 2; mixedindent off; indent-mode cstyle; 00236 */