Home | History | Annotate | Download | only in Tensor
      1 // This file is part of Eigen, a lightweight C++ template library
      2 // for linear algebra.
      3 //
      4 // Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog (at) gmail.com>
      5 //
      6 // This Source Code Form is subject to the terms of the Mozilla
      7 // Public License v. 2.0. If a copy of the MPL was not distributed
      8 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
      9 
     10 #ifndef EIGEN_CXX11_TENSOR_TENSOR_TRAITS_H
     11 #define EIGEN_CXX11_TENSOR_TENSOR_TRAITS_H
     12 
     13 namespace Eigen {
     14 namespace internal {
     15 
     16 
     17 template<typename Scalar, int Options>
     18 class compute_tensor_flags
     19 {
     20   enum {
     21     is_dynamic_size_storage = 1,
     22 
     23     is_aligned =
     24     (
     25         ((Options&DontAlign)==0) && (
     26 #if EIGEN_MAX_STATIC_ALIGN_BYTES>0
     27             (!is_dynamic_size_storage)
     28 #else
     29             0
     30 #endif
     31             |
     32 #if EIGEN_MAX_ALIGN_BYTES>0
     33             is_dynamic_size_storage
     34 #else
     35             0
     36 #endif
     37       )
     38      ),
     39     packet_access_bit = packet_traits<Scalar>::Vectorizable && is_aligned ? PacketAccessBit : 0
     40   };
     41 
     42   public:
     43     enum { ret = packet_access_bit };
     44 };
     45 
     46 
     47 template<typename Scalar_, int NumIndices_, int Options_, typename IndexType_>
     48 struct traits<Tensor<Scalar_, NumIndices_, Options_, IndexType_> >
     49 {
     50   typedef Scalar_ Scalar;
     51   typedef Dense StorageKind;
     52   typedef IndexType_ Index;
     53   static const int NumDimensions = NumIndices_;
     54   static const int Layout = Options_ & RowMajor ? RowMajor : ColMajor;
     55   enum {
     56     Options = Options_,
     57     Flags = compute_tensor_flags<Scalar_, Options_>::ret | (is_const<Scalar_>::value ? 0 : LvalueBit)
     58   };
     59   template <typename T> struct MakePointer {
     60     typedef T* Type;
     61   };
     62 };
     63 
     64 
     65 template<typename Scalar_, typename Dimensions, int Options_, typename IndexType_>
     66 struct traits<TensorFixedSize<Scalar_, Dimensions, Options_, IndexType_> >
     67 {
     68   typedef Scalar_ Scalar;
     69   typedef Dense StorageKind;
     70   typedef IndexType_ Index;
     71   static const int NumDimensions = array_size<Dimensions>::value;
     72   static const int Layout = Options_ & RowMajor ? RowMajor : ColMajor;
     73   enum {
     74     Options = Options_,
     75     Flags = compute_tensor_flags<Scalar_, Options_>::ret | (is_const<Scalar_>::value ? 0: LvalueBit)
     76   };
     77   template <typename T> struct MakePointer {
     78     typedef T* Type;
     79   };
     80 };
     81 
     82 
     83 template<typename PlainObjectType, int Options_, template <class> class MakePointer_>
     84 struct traits<TensorMap<PlainObjectType, Options_, MakePointer_> >
     85   : public traits<PlainObjectType>
     86 {
     87   typedef traits<PlainObjectType> BaseTraits;
     88   typedef typename BaseTraits::Scalar Scalar;
     89   typedef typename BaseTraits::StorageKind StorageKind;
     90   typedef typename BaseTraits::Index Index;
     91   static const int NumDimensions = BaseTraits::NumDimensions;
     92   static const int Layout = BaseTraits::Layout;
     93   enum {
     94     Options = Options_,
     95     Flags = BaseTraits::Flags
     96   };
     97   template <class T> struct MakePointer {
     98     // Intermediate typedef to workaround MSVC issue.
     99     typedef MakePointer_<T> MakePointerT;
    100     typedef typename MakePointerT::Type Type;
    101   };
    102 };
    103 
    104 template<typename PlainObjectType>
    105 struct traits<TensorRef<PlainObjectType> >
    106   : public traits<PlainObjectType>
    107 {
    108   typedef traits<PlainObjectType> BaseTraits;
    109   typedef typename BaseTraits::Scalar Scalar;
    110   typedef typename BaseTraits::StorageKind StorageKind;
    111   typedef typename BaseTraits::Index Index;
    112   static const int NumDimensions = BaseTraits::NumDimensions;
    113   static const int Layout = BaseTraits::Layout;
    114   enum {
    115     Options = BaseTraits::Options,
    116     Flags = BaseTraits::Flags
    117   };
    118 };
    119 
    120 
    121 template<typename _Scalar, int NumIndices_, int Options, typename IndexType_>
    122 struct eval<Tensor<_Scalar, NumIndices_, Options, IndexType_>, Eigen::Dense>
    123 {
    124   typedef const Tensor<_Scalar, NumIndices_, Options, IndexType_>& type;
    125 };
    126 
    127 template<typename _Scalar, int NumIndices_, int Options, typename IndexType_>
    128 struct eval<const Tensor<_Scalar, NumIndices_, Options, IndexType_>, Eigen::Dense>
    129 {
    130   typedef const Tensor<_Scalar, NumIndices_, Options, IndexType_>& type;
    131 };
    132 
    133 template<typename Scalar_, typename Dimensions, int Options, typename IndexType_>
    134 struct eval<TensorFixedSize<Scalar_, Dimensions, Options, IndexType_>, Eigen::Dense>
    135 {
    136   typedef const TensorFixedSize<Scalar_, Dimensions, Options, IndexType_>& type;
    137 };
    138 
    139 template<typename Scalar_, typename Dimensions, int Options, typename IndexType_>
    140 struct eval<const TensorFixedSize<Scalar_, Dimensions, Options, IndexType_>, Eigen::Dense>
    141 {
    142   typedef const TensorFixedSize<Scalar_, Dimensions, Options, IndexType_>& type;
    143 };
    144 
    145 template<typename PlainObjectType, int Options, template <class> class MakePointer>
    146 struct eval<TensorMap<PlainObjectType, Options, MakePointer>, Eigen::Dense>
    147 {
    148   typedef const TensorMap<PlainObjectType, Options, MakePointer>& type;
    149 };
    150 
    151 template<typename PlainObjectType, int Options, template <class> class MakePointer>
    152 struct eval<const TensorMap<PlainObjectType, Options, MakePointer>, Eigen::Dense>
    153 {
    154   typedef const TensorMap<PlainObjectType, Options, MakePointer>& type;
    155 };
    156 
    157 template<typename PlainObjectType>
    158 struct eval<TensorRef<PlainObjectType>, Eigen::Dense>
    159 {
    160   typedef const TensorRef<PlainObjectType>& type;
    161 };
    162 
    163 template<typename PlainObjectType>
    164 struct eval<const TensorRef<PlainObjectType>, Eigen::Dense>
    165 {
    166   typedef const TensorRef<PlainObjectType>& type;
    167 };
    168 
    169 // TODO nested<> does not exist anymore in Eigen/Core, and it thus has to be removed in favor of ref_selector.
    170 template<typename T, int n=1, typename PlainObject = void> struct nested
    171 {
    172   typedef typename ref_selector<T>::type type;
    173 };
    174 
    175 template <typename Scalar_, int NumIndices_, int Options_, typename IndexType_>
    176 struct nested<Tensor<Scalar_, NumIndices_, Options_, IndexType_> >
    177 {
    178   typedef const Tensor<Scalar_, NumIndices_, Options_, IndexType_>& type;
    179 };
    180 
    181 template <typename Scalar_, int NumIndices_, int Options_, typename IndexType_>
    182 struct nested<const Tensor<Scalar_, NumIndices_, Options_, IndexType_> >
    183 {
    184   typedef const Tensor<Scalar_, NumIndices_, Options_, IndexType_>& type;
    185 };
    186 
    187 template <typename Scalar_, typename Dimensions, int Options, typename IndexType_>
    188 struct nested<TensorFixedSize<Scalar_, Dimensions, Options, IndexType_> >
    189 {
    190   typedef const TensorFixedSize<Scalar_, Dimensions, Options, IndexType_>& type;
    191 };
    192 
    193 template <typename Scalar_, typename Dimensions, int Options, typename IndexType_>
    194 struct nested<const TensorFixedSize<Scalar_, Dimensions, Options, IndexType_> >
    195 {
    196   typedef const TensorFixedSize<Scalar_, Dimensions, Options, IndexType_>& type;
    197 };
    198 
    199 
    200 template <typename PlainObjectType, int Options, template <class> class MakePointer>
    201 struct nested<TensorMap<PlainObjectType, Options, MakePointer> >
    202 {
    203   typedef const TensorMap<PlainObjectType, Options, MakePointer>& type;
    204 };
    205 
    206 template <typename PlainObjectType, int Options, template <class> class MakePointer>
    207 struct nested<const TensorMap<PlainObjectType, Options, MakePointer> >
    208 {
    209   typedef const TensorMap<PlainObjectType, Options, MakePointer>& type;
    210 };
    211 
    212 template <typename PlainObjectType>
    213 struct nested<TensorRef<PlainObjectType> >
    214 {
    215   typedef const TensorRef<PlainObjectType>& type;
    216 };
    217 
    218 template <typename PlainObjectType>
    219 struct nested<const TensorRef<PlainObjectType> >
    220 {
    221   typedef const TensorRef<PlainObjectType>& type;
    222 };
    223 
    224 }  // end namespace internal
    225 
    226 // Convolutional layers take in an input tensor of shape (D, R, C, B), or (D, C,
    227 // R, B), and convolve it with a set of filters, which can also be presented as
    228 // a tensor (D, K, K, M), where M is the number of filters, K is the filter
    229 // size, and each 3-dimensional tensor of size (D, K, K) is a filter. For
    230 // simplicity we assume that we always use square filters (which is usually the
    231 // case in images), hence the two Ks in the tensor dimension.  It also takes in
    232 // a few additional parameters:
    233 // Stride (S): The convolution stride is the offset between locations where we
    234 //             apply the filters.  A larger stride means that the output will be
    235 //             spatially smaller.
    236 // Padding (P): The padding we apply to the input tensor along the R and C
    237 //              dimensions.  This is usually used to make sure that the spatial
    238 //              dimensions of the output matches our intention.
    239 //
    240 // Two types of padding are often used:
    241 //   SAME: The pad value is computed so that the output will have size
    242 //         R/S and C/S.
    243 //   VALID: no padding is carried out.
    244 // When we do padding, the padded values at the padded locations are usually
    245 // zero.
    246 //
    247 // The output dimensions for convolution, when given all the parameters above,
    248 // are as follows:
    249 // When Padding = SAME: the output size is (B, R', C', M), where
    250 //   R' = ceil(float(R) / float(S))
    251 //   C' = ceil(float(C) / float(S))
    252 // where ceil is the ceiling function.  The input tensor is padded with 0 as
    253 // needed.  The number of padded rows and columns are computed as:
    254 //   Pr = ((R' - 1) * S + K - R) / 2
    255 //   Pc = ((C' - 1) * S + K - C) / 2
    256 // when the stride is 1, we have the simplified case R'=R, C'=C, Pr=Pc=(K-1)/2.
    257 // This is where SAME comes from - the output has the same size as the input has.
    258 // When Padding = VALID: the output size is computed as
    259 //   R' = ceil(float(R - K + 1) / float(S))
    260 //   C' = ceil(float(C - K + 1) / float(S))
    261 // and the number of padded rows and columns are computed in the same way as in
    262 // the SAME case.
    263 // When the stride is 1, we have the simplified case R'=R-K+1, C'=C-K+1, Pr=0,
    264 // Pc=0.
    265 typedef enum {
    266   PADDING_VALID = 1,
    267   PADDING_SAME = 2
    268 } PaddingType;
    269 
    270 }  // end namespace Eigen
    271 
    272 #endif // EIGEN_CXX11_TENSOR_TENSOR_TRAITS_H
    273