TensorDimensions.h
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
 All Classes Functions Variables Typedefs Enumerator