TensorTraits.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_TRAITS_H
00011 #define EIGEN_CXX11_TENSOR_TENSOR_TRAITS_H
00012 
00013 namespace Eigen {
00014 namespace internal {
00015 
00016 
00017 template<typename Scalar, int Options>
00018 class compute_tensor_flags
00019 {
00020   enum {
00021     is_dynamic_size_storage = 1,
00022 
00023     is_aligned =
00024     (
00025         ((Options&DontAlign)==0) && (
00026 #if EIGEN_MAX_STATIC_ALIGN_BYTES>0
00027             (!is_dynamic_size_storage)
00028 #else
00029             0
00030 #endif
00031             |
00032 #if EIGEN_MAX_ALIGN_BYTES>0
00033             is_dynamic_size_storage
00034 #else
00035             0
00036 #endif
00037       )
00038      ),
00039     packet_access_bit = packet_traits<Scalar>::Vectorizable && is_aligned ? PacketAccessBit : 0
00040   };
00041 
00042   public:
00043     enum { ret = packet_access_bit };
00044 };
00045 
00046 
00047 template<typename Scalar_, int NumIndices_, int Options_, typename IndexType_>
00048 struct traits<Tensor<Scalar_, NumIndices_, Options_, IndexType_> >
00049 {
00050   typedef Scalar_ Scalar;
00051   typedef Dense StorageKind;
00052   typedef IndexType_ Index;
00053   static const int NumDimensions = NumIndices_;
00054   static const int Layout = Options_ & RowMajor ? RowMajor : ColMajor;
00055   enum {
00056     Options = Options_,
00057     Flags = compute_tensor_flags<Scalar_, Options_>::ret | (is_const<Scalar_>::value ? 0 : LvalueBit)
00058   };
00059   template <typename T> struct MakePointer {
00060     typedef T* Type;
00061   };
00062 };
00063 
00064 
00065 template<typename Scalar_, typename Dimensions, int Options_, typename IndexType_>
00066 struct traits<TensorFixedSize<Scalar_, Dimensions, Options_, IndexType_> >
00067 {
00068   typedef Scalar_ Scalar;
00069   typedef Dense StorageKind;
00070   typedef IndexType_ Index;
00071   static const int NumDimensions = array_size<Dimensions>::value;
00072   static const int Layout = Options_ & RowMajor ? RowMajor : ColMajor;
00073   enum {
00074     Options = Options_,
00075     Flags = compute_tensor_flags<Scalar_, Options_>::ret | (is_const<Scalar_>::value ? 0: LvalueBit)
00076   };
00077   template <typename T> struct MakePointer {
00078     typedef T* Type;
00079   };
00080 };
00081 
00082 
00083 template<typename PlainObjectType, int Options_, template <class> class MakePointer_>
00084 struct traits<TensorMap<PlainObjectType, Options_, MakePointer_> >
00085   : public traits<PlainObjectType>
00086 {
00087   typedef traits<PlainObjectType> BaseTraits;
00088   typedef typename BaseTraits::Scalar Scalar;
00089   typedef typename BaseTraits::StorageKind StorageKind;
00090   typedef typename BaseTraits::Index Index;
00091   static const int NumDimensions = BaseTraits::NumDimensions;
00092   static const int Layout = BaseTraits::Layout;
00093   enum {
00094     Options = Options_,
00095     Flags = BaseTraits::Flags
00096   };
00097   template <class T> struct MakePointer {
00098     // Intermediate typedef to workaround MSVC issue.
00099     typedef MakePointer_<T> MakePointerT;
00100     typedef typename MakePointerT::Type Type;
00101   };
00102 };
00103 
00104 template<typename PlainObjectType>
00105 struct traits<TensorRef<PlainObjectType> >
00106   : public traits<PlainObjectType>
00107 {
00108   typedef traits<PlainObjectType> BaseTraits;
00109   typedef typename BaseTraits::Scalar Scalar;
00110   typedef typename BaseTraits::StorageKind StorageKind;
00111   typedef typename BaseTraits::Index Index;
00112   static const int NumDimensions = BaseTraits::NumDimensions;
00113   static const int Layout = BaseTraits::Layout;
00114   enum {
00115     Options = BaseTraits::Options,
00116     Flags = BaseTraits::Flags
00117   };
00118 };
00119 
00120 
00121 template<typename _Scalar, int NumIndices_, int Options, typename IndexType_>
00122 struct eval<Tensor<_Scalar, NumIndices_, Options, IndexType_>, Eigen::Dense>
00123 {
00124   typedef const Tensor<_Scalar, NumIndices_, Options, IndexType_>& type;
00125 };
00126 
00127 template<typename _Scalar, int NumIndices_, int Options, typename IndexType_>
00128 struct eval<const Tensor<_Scalar, NumIndices_, Options, IndexType_>, Eigen::Dense>
00129 {
00130   typedef const Tensor<_Scalar, NumIndices_, Options, IndexType_>& type;
00131 };
00132 
00133 template<typename Scalar_, typename Dimensions, int Options, typename IndexType_>
00134 struct eval<TensorFixedSize<Scalar_, Dimensions, Options, IndexType_>, Eigen::Dense>
00135 {
00136   typedef const TensorFixedSize<Scalar_, Dimensions, Options, IndexType_>& type;
00137 };
00138 
00139 template<typename Scalar_, typename Dimensions, int Options, typename IndexType_>
00140 struct eval<const TensorFixedSize<Scalar_, Dimensions, Options, IndexType_>, Eigen::Dense>
00141 {
00142   typedef const TensorFixedSize<Scalar_, Dimensions, Options, IndexType_>& type;
00143 };
00144 
00145 template<typename PlainObjectType, int Options, template <class> class MakePointer>
00146 struct eval<TensorMap<PlainObjectType, Options, MakePointer>, Eigen::Dense>
00147 {
00148   typedef const TensorMap<PlainObjectType, Options, MakePointer>& type;
00149 };
00150 
00151 template<typename PlainObjectType, int Options, template <class> class MakePointer>
00152 struct eval<const TensorMap<PlainObjectType, Options, MakePointer>, Eigen::Dense>
00153 {
00154   typedef const TensorMap<PlainObjectType, Options, MakePointer>& type;
00155 };
00156 
00157 template<typename PlainObjectType>
00158 struct eval<TensorRef<PlainObjectType>, Eigen::Dense>
00159 {
00160   typedef const TensorRef<PlainObjectType>& type;
00161 };
00162 
00163 template<typename PlainObjectType>
00164 struct eval<const TensorRef<PlainObjectType>, Eigen::Dense>
00165 {
00166   typedef const TensorRef<PlainObjectType>& type;
00167 };
00168 
00169 // TODO nested<> does not exist anymore in Eigen/Core, and it thus has to be removed in favor of ref_selector.
00170 template<typename T, int n=1, typename PlainObject = void> struct nested
00171 {
00172   typedef typename ref_selector<T>::type type;
00173 };
00174 
00175 template <typename Scalar_, int NumIndices_, int Options_, typename IndexType_>
00176 struct nested<Tensor<Scalar_, NumIndices_, Options_, IndexType_> >
00177 {
00178   typedef const Tensor<Scalar_, NumIndices_, Options_, IndexType_>& type;
00179 };
00180 
00181 template <typename Scalar_, int NumIndices_, int Options_, typename IndexType_>
00182 struct nested<const Tensor<Scalar_, NumIndices_, Options_, IndexType_> >
00183 {
00184   typedef const Tensor<Scalar_, NumIndices_, Options_, IndexType_>& type;
00185 };
00186 
00187 template <typename Scalar_, typename Dimensions, int Options, typename IndexType_>
00188 struct nested<TensorFixedSize<Scalar_, Dimensions, Options, IndexType_> >
00189 {
00190   typedef const TensorFixedSize<Scalar_, Dimensions, Options, IndexType_>& type;
00191 };
00192 
00193 template <typename Scalar_, typename Dimensions, int Options, typename IndexType_>
00194 struct nested<const TensorFixedSize<Scalar_, Dimensions, Options, IndexType_> >
00195 {
00196   typedef const TensorFixedSize<Scalar_, Dimensions, Options, IndexType_>& type;
00197 };
00198 
00199 
00200 template <typename PlainObjectType, int Options, template <class> class MakePointer>
00201 struct nested<TensorMap<PlainObjectType, Options, MakePointer> >
00202 {
00203   typedef const TensorMap<PlainObjectType, Options, MakePointer>& type;
00204 };
00205 
00206 template <typename PlainObjectType, int Options, template <class> class MakePointer>
00207 struct nested<const TensorMap<PlainObjectType, Options, MakePointer> >
00208 {
00209   typedef const TensorMap<PlainObjectType, Options, MakePointer>& type;
00210 };
00211 
00212 template <typename PlainObjectType>
00213 struct nested<TensorRef<PlainObjectType> >
00214 {
00215   typedef const TensorRef<PlainObjectType>& type;
00216 };
00217 
00218 template <typename PlainObjectType>
00219 struct nested<const TensorRef<PlainObjectType> >
00220 {
00221   typedef const TensorRef<PlainObjectType>& type;
00222 };
00223 
00224 }  // end namespace internal
00225 
00226 // Convolutional layers take in an input tensor of shape (D, R, C, B), or (D, C,
00227 // R, B), and convolve it with a set of filters, which can also be presented as
00228 // a tensor (D, K, K, M), where M is the number of filters, K is the filter
00229 // size, and each 3-dimensional tensor of size (D, K, K) is a filter. For
00230 // simplicity we assume that we always use square filters (which is usually the
00231 // case in images), hence the two Ks in the tensor dimension.  It also takes in
00232 // a few additional parameters:
00233 // Stride (S): The convolution stride is the offset between locations where we
00234 //             apply the filters.  A larger stride means that the output will be
00235 //             spatially smaller.
00236 // Padding (P): The padding we apply to the input tensor along the R and C
00237 //              dimensions.  This is usually used to make sure that the spatial
00238 //              dimensions of the output matches our intention.
00239 //
00240 // Two types of padding are often used:
00241 //   SAME: The pad value is computed so that the output will have size
00242 //         R/S and C/S.
00243 //   VALID: no padding is carried out.
00244 // When we do padding, the padded values at the padded locations are usually
00245 // zero.
00246 //
00247 // The output dimensions for convolution, when given all the parameters above,
00248 // are as follows:
00249 // When Padding = SAME: the output size is (B, R', C', M), where
00250 //   R' = ceil(float(R) / float(S))
00251 //   C' = ceil(float(C) / float(S))
00252 // where ceil is the ceiling function.  The input tensor is padded with 0 as
00253 // needed.  The number of padded rows and columns are computed as:
00254 //   Pr = ((R' - 1) * S + K - R) / 2
00255 //   Pc = ((C' - 1) * S + K - C) / 2
00256 // when the stride is 1, we have the simplified case R'=R, C'=C, Pr=Pc=(K-1)/2.
00257 // This is where SAME comes from - the output has the same size as the input has.
00258 // When Padding = VALID: the output size is computed as
00259 //   R' = ceil(float(R - K + 1) / float(S))
00260 //   C' = ceil(float(C - K + 1) / float(S))
00261 // and the number of padded rows and columns are computed in the same way as in
00262 // the SAME case.
00263 // When the stride is 1, we have the simplified case R'=R-K+1, C'=C-K+1, Pr=0,
00264 // Pc=0.
00265 typedef enum {
00266   PADDING_VALID = 1,
00267   PADDING_SAME = 2
00268 } PaddingType;
00269 
00270 }  // end namespace Eigen
00271 
00272 #endif // EIGEN_CXX11_TENSOR_TENSOR_TRAITS_H
 All Classes Functions Variables Typedefs Enumerator