![]() |
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) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com> 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_TENSOR_TENSOR_DIMENSIONS_H 00011 #define EIGEN_CXX11_TENSOR_TENSOR_DIMENSIONS_H 00012 00013 00014 namespace Eigen { 00015 00032 // Boilerplate code 00033 namespace internal { 00034 00035 template<std::size_t n, typename Dimension> struct dget { 00036 static const std::size_t value = get<n, Dimension>::value; 00037 }; 00038 00039 00040 template<typename Index, std::size_t NumIndices, std::size_t n, bool RowMajor> 00041 struct fixed_size_tensor_index_linearization_helper 00042 { 00043 template <typename Dimensions> EIGEN_DEVICE_FUNC 00044 static inline Index run(array<Index, NumIndices> const& indices, 00045 const Dimensions& dimensions) 00046 { 00047 return array_get<RowMajor ? n - 1 : (NumIndices - n)>(indices) + 00048 dget<RowMajor ? n - 1 : (NumIndices - n), Dimensions>::value * 00049 fixed_size_tensor_index_linearization_helper<Index, NumIndices, n - 1, RowMajor>::run(indices, dimensions); 00050 } 00051 }; 00052 00053 template<typename Index, std::size_t NumIndices, bool RowMajor> 00054 struct fixed_size_tensor_index_linearization_helper<Index, NumIndices, 0, RowMajor> 00055 { 00056 template <typename Dimensions> EIGEN_DEVICE_FUNC 00057 static inline Index run(array<Index, NumIndices> const&, const Dimensions&) 00058 { 00059 return 0; 00060 } 00061 }; 00062 00063 template<typename Index, std::size_t n> 00064 struct fixed_size_tensor_index_extraction_helper 00065 { 00066 template <typename Dimensions> EIGEN_DEVICE_FUNC 00067 static inline Index run(const Index index, 00068 const Dimensions& dimensions) 00069 { 00070 const Index mult = (index == n-1) ? 1 : 0; 00071 return array_get<n-1>(dimensions) * mult + 00072 fixed_size_tensor_index_extraction_helper<Index, n - 1>::run(index, dimensions); 00073 } 00074 }; 00075 00076 template<typename Index> 00077 struct fixed_size_tensor_index_extraction_helper<Index, 0> 00078 { 00079 template <typename Dimensions> EIGEN_DEVICE_FUNC 00080 static inline Index run(const Index, 00081 const Dimensions&) 00082 { 00083 return 0; 00084 } 00085 }; 00086 00087 } // end namespace internal 00088 00089 00090 // Fixed size 00091 #ifndef EIGEN_EMULATE_CXX11_META_H 00092 template <typename std::ptrdiff_t... Indices> 00093 struct Sizes : internal::numeric_list<std::ptrdiff_t, Indices...> { 00094 typedef internal::numeric_list<std::ptrdiff_t, Indices...> Base; 00095 static const std::ptrdiff_t total_size = internal::arg_prod(Indices...); 00096 00097 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::ptrdiff_t rank() const { 00098 return Base::count; 00099 } 00100 00101 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::ptrdiff_t TotalSize() { 00102 return internal::arg_prod(Indices...); 00103 } 00104 00105 EIGEN_DEVICE_FUNC Sizes() { } 00106 template <typename DenseIndex> 00107 explicit EIGEN_DEVICE_FUNC Sizes(const array<DenseIndex, Base::count>& /*indices*/) { 00108 // todo: add assertion 00109 } 00110 #if EIGEN_HAS_VARIADIC_TEMPLATES 00111 template <typename... DenseIndex> EIGEN_DEVICE_FUNC Sizes(DenseIndex...) { } 00112 explicit EIGEN_DEVICE_FUNC Sizes(std::initializer_list<std::ptrdiff_t> /*l*/) { 00113 // todo: add assertion 00114 } 00115 #endif 00116 00117 template <typename T> Sizes& operator = (const T& /*other*/) { 00118 // add assertion failure if the size of other is different 00119 return *this; 00120 } 00121 00122 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::ptrdiff_t operator[] (const std::size_t index) const { 00123 return internal::fixed_size_tensor_index_extraction_helper<std::ptrdiff_t, Base::count>::run(index, *this); 00124 } 00125 00126 template <typename DenseIndex> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE 00127 size_t IndexOfColMajor(const array<DenseIndex, Base::count>& indices) const { 00128 return internal::fixed_size_tensor_index_linearization_helper<DenseIndex, Base::count, Base::count, false>::run(indices, *static_cast<const Base*>(this)); 00129 } 00130 template <typename DenseIndex> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE 00131 size_t IndexOfRowMajor(const array<DenseIndex, Base::count>& indices) const { 00132 return internal::fixed_size_tensor_index_linearization_helper<DenseIndex, Base::count, Base::count, true>::run(indices, *static_cast<const Base*>(this)); 00133 } 00134 }; 00135 00136 namespace internal { 00137 template <typename std::ptrdiff_t... Indices> 00138 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::ptrdiff_t array_prod(const Sizes<Indices...>&) { 00139 return Sizes<Indices...>::total_size; 00140 } 00141 } 00142 00143 #else 00144 00145 template <std::size_t n> 00146 struct non_zero_size { 00147 typedef internal::type2val<std::size_t, n> type; 00148 }; 00149 template <> 00150 struct non_zero_size<0> { 00151 typedef internal::null_type type; 00152 }; 00153 00154 template <std::size_t V1=0, std::size_t V2=0, std::size_t V3=0, std::size_t V4=0, std::size_t V5=0> struct Sizes { 00155 typedef typename internal::make_type_list<typename non_zero_size<V1>::type, typename non_zero_size<V2>::type, typename non_zero_size<V3>::type, typename non_zero_size<V4>::type, typename non_zero_size<V5>::type >::type Base; 00156 static const size_t count = Base::count; 00157 static const std::size_t total_size = internal::arg_prod<Base>::value; 00158 00159 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE size_t rank() const { 00160 return count; 00161 } 00162 00163 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE size_t TotalSize() { 00164 return internal::arg_prod<Base>::value; 00165 } 00166 00167 Sizes() { } 00168 template <typename DenseIndex> 00169 explicit Sizes(const array<DenseIndex, Base::count>& /*indices*/) { 00170 // todo: add assertion 00171 } 00172 template <typename T> Sizes& operator = (const T& /*other*/) { 00173 // add assertion failure if the size of other is different 00174 return *this; 00175 } 00176 00177 #if EIGEN_HAS_VARIADIC_TEMPLATES 00178 template <typename... DenseIndex> Sizes(DenseIndex... /*indices*/) { } 00179 explicit Sizes(std::initializer_list<std::size_t>) { 00180 // todo: add assertion 00181 } 00182 #else 00183 EIGEN_DEVICE_FUNC explicit Sizes(const DenseIndex) { 00184 } 00185 EIGEN_DEVICE_FUNC Sizes(const DenseIndex, const DenseIndex) { 00186 } 00187 EIGEN_DEVICE_FUNC Sizes(const DenseIndex, const DenseIndex, const DenseIndex) { 00188 } 00189 EIGEN_DEVICE_FUNC Sizes(const DenseIndex, const DenseIndex, const DenseIndex, const DenseIndex) { 00190 } 00191 EIGEN_DEVICE_FUNC Sizes(const DenseIndex, const DenseIndex, const DenseIndex, const DenseIndex, const DenseIndex) { 00192 } 00193 #endif 00194 00195 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DenseIndex operator[] (const int index) const { 00196 switch (index) { 00197 case 0: 00198 return internal::get<0, Base>::value; 00199 case 1: 00200 return internal::get<1, Base>::value; 00201 case 2: 00202 return internal::get<2, Base>::value; 00203 case 3: 00204 return internal::get<3, Base>::value; 00205 case 4: 00206 return internal::get<4, Base>::value; 00207 default: 00208 eigen_assert(false && "index overflow"); 00209 return static_cast<DenseIndex>(-1); 00210 } 00211 } 00212 00213 template <typename DenseIndex> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE 00214 size_t IndexOfColMajor(const array<DenseIndex, Base::count>& indices) const { 00215 return internal::fixed_size_tensor_index_linearization_helper<DenseIndex, Base::count, Base::count, false>::run(indices, *reinterpret_cast<const Base*>(this)); 00216 } 00217 template <typename DenseIndex> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE 00218 size_t IndexOfRowMajor(const array<DenseIndex, Base::count>& indices) const { 00219 return internal::fixed_size_tensor_index_linearization_helper<DenseIndex, Base::count, Base::count, true>::run(indices, *reinterpret_cast<const Base*>(this)); 00220 } 00221 }; 00222 00223 namespace internal { 00224 template <std::size_t V1, std::size_t V2, std::size_t V3, std::size_t V4, std::size_t V5> 00225 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::size_t array_prod(const Sizes<V1, V2, V3, V4, V5>&) { 00226 return Sizes<V1, V2, V3, V4, V5>::total_size; 00227 } 00228 } 00229 00230 #endif 00231 00232 // Boilerplate 00233 namespace internal { 00234 template<typename Index, std::size_t NumIndices, std::size_t n, bool RowMajor> 00235 struct tensor_index_linearization_helper 00236 { 00237 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE 00238 Index run(array<Index, NumIndices> const& indices, array<Index, NumIndices> const& dimensions) 00239 { 00240 return array_get<RowMajor ? n : (NumIndices - n - 1)>(indices) + 00241 array_get<RowMajor ? n : (NumIndices - n - 1)>(dimensions) * 00242 tensor_index_linearization_helper<Index, NumIndices, n - 1, RowMajor>::run(indices, dimensions); 00243 } 00244 }; 00245 00246 template<typename Index, std::size_t NumIndices, bool RowMajor> 00247 struct tensor_index_linearization_helper<Index, NumIndices, 0, RowMajor> 00248 { 00249 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE 00250 Index run(array<Index, NumIndices> const& indices, array<Index, NumIndices> const&) 00251 { 00252 return array_get<RowMajor ? 0 : NumIndices - 1>(indices); 00253 } 00254 }; 00255 } // end namespace internal 00256 00257 00258 00259 // Dynamic size 00260 template <typename DenseIndex, int NumDims> 00261 struct DSizes : array<DenseIndex, NumDims> { 00262 typedef array<DenseIndex, NumDims> Base; 00263 static const int count = NumDims; 00264 00265 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE size_t rank() const { 00266 return NumDims; 00267 } 00268 00269 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DenseIndex TotalSize() const { 00270 return (NumDims == 0) ? 1 : internal::array_prod(*static_cast<const Base*>(this)); 00271 } 00272 00273 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DSizes() { 00274 for (int i = 0 ; i < NumDims; ++i) { 00275 (*this)[i] = 0; 00276 } 00277 } 00278 EIGEN_DEVICE_FUNC explicit DSizes(const array<DenseIndex, NumDims>& a) : Base(a) { } 00279 00280 EIGEN_DEVICE_FUNC explicit DSizes(const DenseIndex i0) { 00281 eigen_assert(NumDims == 1); 00282 (*this)[0] = i0; 00283 } 00284 00285 #if EIGEN_HAS_VARIADIC_TEMPLATES 00286 template<typename... IndexTypes> EIGEN_DEVICE_FUNC 00287 EIGEN_STRONG_INLINE explicit DSizes(DenseIndex firstDimension, DenseIndex secondDimension, IndexTypes... otherDimensions) : Base({{firstDimension, secondDimension, otherDimensions...}}) { 00288 EIGEN_STATIC_ASSERT(sizeof...(otherDimensions) + 2 == NumDims, YOU_MADE_A_PROGRAMMING_MISTAKE) 00289 } 00290 #else 00291 EIGEN_DEVICE_FUNC DSizes(const DenseIndex i0, const DenseIndex i1) { 00292 eigen_assert(NumDims == 2); 00293 (*this)[0] = i0; 00294 (*this)[1] = i1; 00295 } 00296 EIGEN_DEVICE_FUNC DSizes(const DenseIndex i0, const DenseIndex i1, const DenseIndex i2) { 00297 eigen_assert(NumDims == 3); 00298 (*this)[0] = i0; 00299 (*this)[1] = i1; 00300 (*this)[2] = i2; 00301 } 00302 EIGEN_DEVICE_FUNC DSizes(const DenseIndex i0, const DenseIndex i1, const DenseIndex i2, const DenseIndex i3) { 00303 eigen_assert(NumDims == 4); 00304 (*this)[0] = i0; 00305 (*this)[1] = i1; 00306 (*this)[2] = i2; 00307 (*this)[3] = i3; 00308 } 00309 EIGEN_DEVICE_FUNC DSizes(const DenseIndex i0, const DenseIndex i1, const DenseIndex i2, const DenseIndex i3, const DenseIndex i4) { 00310 eigen_assert(NumDims == 5); 00311 (*this)[0] = i0; 00312 (*this)[1] = i1; 00313 (*this)[2] = i2; 00314 (*this)[3] = i3; 00315 (*this)[4] = i4; 00316 } 00317 #endif 00318 00319 EIGEN_DEVICE_FUNC DSizes& operator = (const array<DenseIndex, NumDims>& other) { 00320 *static_cast<Base*>(this) = other; 00321 return *this; 00322 } 00323 00324 // A constexpr would be so much better here 00325 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DenseIndex IndexOfColMajor(const array<DenseIndex, NumDims>& indices) const { 00326 return internal::tensor_index_linearization_helper<DenseIndex, NumDims, NumDims - 1, false>::run(indices, *static_cast<const Base*>(this)); 00327 } 00328 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DenseIndex IndexOfRowMajor(const array<DenseIndex, NumDims>& indices) const { 00329 return internal::tensor_index_linearization_helper<DenseIndex, NumDims, NumDims - 1, true>::run(indices, *static_cast<const Base*>(this)); 00330 } 00331 }; 00332 00333 00334 00335 00336 // Boilerplate 00337 namespace internal { 00338 template<typename Index, std::size_t NumIndices, std::size_t n, bool RowMajor> 00339 struct tensor_vsize_index_linearization_helper 00340 { 00341 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE 00342 Index run(array<Index, NumIndices> const& indices, std::vector<DenseIndex> const& dimensions) 00343 { 00344 return array_get<RowMajor ? n : (NumIndices - n - 1)>(indices) + 00345 array_get<RowMajor ? n : (NumIndices - n - 1)>(dimensions) * 00346 tensor_vsize_index_linearization_helper<Index, NumIndices, n - 1, RowMajor>::run(indices, dimensions); 00347 } 00348 }; 00349 00350 template<typename Index, std::size_t NumIndices, bool RowMajor> 00351 struct tensor_vsize_index_linearization_helper<Index, NumIndices, 0, RowMajor> 00352 { 00353 static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE 00354 Index run(array<Index, NumIndices> const& indices, std::vector<DenseIndex> const&) 00355 { 00356 return array_get<RowMajor ? 0 : NumIndices - 1>(indices); 00357 } 00358 }; 00359 } // end namespace internal 00360 00361 00362 namespace internal { 00363 00364 template <typename DenseIndex, int NumDims> struct array_size<const DSizes<DenseIndex, NumDims> > { 00365 static const size_t value = NumDims; 00366 }; 00367 template <typename DenseIndex, int NumDims> struct array_size<DSizes<DenseIndex, NumDims> > { 00368 static const size_t value = NumDims; 00369 }; 00370 #ifndef EIGEN_EMULATE_CXX11_META_H 00371 template <typename std::ptrdiff_t... Indices> struct array_size<const Sizes<Indices...> > { 00372 static const std::ptrdiff_t value = Sizes<Indices...>::count; 00373 }; 00374 template <typename std::ptrdiff_t... Indices> struct array_size<Sizes<Indices...> > { 00375 static const std::ptrdiff_t value = Sizes<Indices...>::count; 00376 }; 00377 template <std::ptrdiff_t n, typename std::ptrdiff_t... Indices> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::ptrdiff_t array_get(const Sizes<Indices...>&) { 00378 return get<n, internal::numeric_list<std::size_t, Indices...> >::value; 00379 } 00380 template <std::ptrdiff_t n> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::ptrdiff_t array_get(const Sizes<>&) { 00381 eigen_assert(false && "should never be called"); 00382 return -1; 00383 } 00384 #else 00385 template <std::size_t V1, std::size_t V2, std::size_t V3, std::size_t V4, std::size_t V5> struct array_size<const Sizes<V1,V2,V3,V4,V5> > { 00386 static const size_t value = Sizes<V1,V2,V3,V4,V5>::count; 00387 }; 00388 template <std::size_t V1, std::size_t V2, std::size_t V3, std::size_t V4, std::size_t V5> struct array_size<Sizes<V1,V2,V3,V4,V5> > { 00389 static const size_t value = Sizes<V1,V2,V3,V4,V5>::count; 00390 }; 00391 template <std::size_t n, std::size_t V1, std::size_t V2, std::size_t V3, std::size_t V4, std::size_t V5> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::size_t array_get(const Sizes<V1,V2,V3,V4,V5>&) { 00392 return get<n, typename Sizes<V1,V2,V3,V4,V5>::Base>::value; 00393 } 00394 00395 #endif 00396 00397 00398 template <typename Dims1, typename Dims2, size_t n, size_t m> 00399 struct sizes_match_below_dim { 00400 static EIGEN_DEVICE_FUNC inline bool run(Dims1&, Dims2&) { 00401 return false; 00402 } 00403 }; 00404 template <typename Dims1, typename Dims2, size_t n> 00405 struct sizes_match_below_dim<Dims1, Dims2, n, n> { 00406 static EIGEN_DEVICE_FUNC inline bool run(Dims1& dims1, Dims2& dims2) { 00407 return (array_get<n-1>(dims1) == array_get<n-1>(dims2)) & 00408 sizes_match_below_dim<Dims1, Dims2, n-1, n-1>::run(dims1, dims2); 00409 } 00410 }; 00411 template <typename Dims1, typename Dims2> 00412 struct sizes_match_below_dim<Dims1, Dims2, 0, 0> { 00413 static EIGEN_DEVICE_FUNC inline bool run(Dims1&, Dims2&) { 00414 return true; 00415 } 00416 }; 00417 00418 } // end namespace internal 00419 00420 00421 template <typename Dims1, typename Dims2> 00422 EIGEN_DEVICE_FUNC bool dimensions_match(Dims1& dims1, Dims2& dims2) { 00423 return internal::sizes_match_below_dim<Dims1, Dims2, internal::array_size<Dims1>::value, internal::array_size<Dims2>::value>::run(dims1, dims2); 00424 } 00425 00426 } // end namespace Eigen 00427 00428 #endif // EIGEN_CXX11_TENSOR_TENSOR_DIMENSIONS_H