• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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   typedef typename MakePointer<Scalar>::Type PointerType;
63 };
64 
65 
66 template<typename Scalar_, typename Dimensions, int Options_, typename IndexType_>
67 struct traits<TensorFixedSize<Scalar_, Dimensions, Options_, IndexType_> >
68 {
69   typedef Scalar_ Scalar;
70   typedef Dense StorageKind;
71   typedef IndexType_ Index;
72   static const int NumDimensions = array_size<Dimensions>::value;
73   static const int Layout = Options_ & RowMajor ? RowMajor : ColMajor;
74   enum {
75     Options = Options_,
76     Flags = compute_tensor_flags<Scalar_, Options_>::ret | (is_const<Scalar_>::value ? 0: LvalueBit)
77   };
78   template <typename T> struct MakePointer {
79     typedef T* Type;
80   };
81   typedef typename MakePointer<Scalar>::Type PointerType;
82 };
83 
84 
85 template<typename PlainObjectType, int Options_, template <class> class MakePointer_>
86 struct traits<TensorMap<PlainObjectType, Options_, MakePointer_> >
87   : public traits<PlainObjectType>
88 {
89   typedef traits<PlainObjectType> BaseTraits;
90   typedef typename BaseTraits::Scalar Scalar;
91   typedef typename BaseTraits::StorageKind StorageKind;
92   typedef typename BaseTraits::Index Index;
93   static const int NumDimensions = BaseTraits::NumDimensions;
94   static const int Layout = BaseTraits::Layout;
95   enum {
96     Options = Options_,
97     Flags = BaseTraits::Flags
98   };
99   template <class T> struct MakePointer {
100     // Intermediate typedef to workaround MSVC issue.
101     typedef MakePointer_<T> MakePointerT;
102     typedef typename MakePointerT::Type Type;
103   };
104   typedef typename MakePointer<Scalar>::Type PointerType;
105 };
106 
107 template<typename PlainObjectType>
108 struct traits<TensorRef<PlainObjectType> >
109   : public traits<PlainObjectType>
110 {
111   typedef traits<PlainObjectType> BaseTraits;
112   typedef typename BaseTraits::Scalar Scalar;
113   typedef typename BaseTraits::StorageKind StorageKind;
114   typedef typename BaseTraits::Index Index;
115   static const int NumDimensions = BaseTraits::NumDimensions;
116   static const int Layout = BaseTraits::Layout;
117   enum {
118     Options = BaseTraits::Options,
119     Flags = BaseTraits::Flags
120   };
121   typedef typename BaseTraits::PointerType PointerType;
122 };
123 
124 
125 template<typename _Scalar, int NumIndices_, int Options, typename IndexType_>
126 struct eval<Tensor<_Scalar, NumIndices_, Options, IndexType_>, Eigen::Dense>
127 {
128   typedef const Tensor<_Scalar, NumIndices_, Options, IndexType_>EIGEN_DEVICE_REF type;
129 };
130 
131 template<typename _Scalar, int NumIndices_, int Options, typename IndexType_>
132 struct eval<const Tensor<_Scalar, NumIndices_, Options, IndexType_>, Eigen::Dense>
133 {
134   typedef const Tensor<_Scalar, NumIndices_, Options, IndexType_>EIGEN_DEVICE_REF type;
135 };
136 
137 template<typename Scalar_, typename Dimensions, int Options, typename IndexType_>
138 struct eval<TensorFixedSize<Scalar_, Dimensions, Options, IndexType_>, Eigen::Dense>
139 {
140   typedef const TensorFixedSize<Scalar_, Dimensions, Options, IndexType_>EIGEN_DEVICE_REF type;
141 };
142 
143 template<typename Scalar_, typename Dimensions, int Options, typename IndexType_>
144 struct eval<const TensorFixedSize<Scalar_, Dimensions, Options, IndexType_>, Eigen::Dense>
145 {
146   typedef const TensorFixedSize<Scalar_, Dimensions, Options, IndexType_>EIGEN_DEVICE_REF type;
147 };
148 
149 template<typename PlainObjectType, int Options, template <class> class MakePointer>
150 struct eval<TensorMap<PlainObjectType, Options, MakePointer>, Eigen::Dense>
151 {
152   typedef const TensorMap<PlainObjectType, Options, MakePointer>EIGEN_DEVICE_REF type;
153 };
154 
155 template<typename PlainObjectType, int Options, template <class> class MakePointer>
156 struct eval<const TensorMap<PlainObjectType, Options, MakePointer>, Eigen::Dense>
157 {
158   typedef const TensorMap<PlainObjectType, Options, MakePointer>EIGEN_DEVICE_REF type;
159 };
160 
161 template<typename PlainObjectType>
162 struct eval<TensorRef<PlainObjectType>, Eigen::Dense>
163 {
164   typedef const TensorRef<PlainObjectType>EIGEN_DEVICE_REF type;
165 };
166 
167 template<typename PlainObjectType>
168 struct eval<const TensorRef<PlainObjectType>, Eigen::Dense>
169 {
170   typedef const TensorRef<PlainObjectType>EIGEN_DEVICE_REF type;
171 };
172 
173 // TODO nested<> does not exist anymore in Eigen/Core, and it thus has to be removed in favor of ref_selector.
174 template<typename T, int n=1, typename PlainObject = void> struct nested
175 {
176   typedef typename ref_selector<T>::type type;
177 };
178 
179 template <typename Scalar_, int NumIndices_, int Options_, typename IndexType_>
180 struct nested<Tensor<Scalar_, NumIndices_, Options_, IndexType_> >
181 {
182   typedef const Tensor<Scalar_, NumIndices_, Options_, IndexType_>EIGEN_DEVICE_REF type;
183 };
184 
185 template <typename Scalar_, int NumIndices_, int Options_, typename IndexType_>
186 struct nested<const Tensor<Scalar_, NumIndices_, Options_, IndexType_> >
187 {
188   typedef const Tensor<Scalar_, NumIndices_, Options_, IndexType_>EIGEN_DEVICE_REF type;
189 };
190 
191 template <typename Scalar_, typename Dimensions, int Options, typename IndexType_>
192 struct nested<TensorFixedSize<Scalar_, Dimensions, Options, IndexType_> >
193 {
194   typedef const TensorFixedSize<Scalar_, Dimensions, Options, IndexType_>EIGEN_DEVICE_REF type;
195 };
196 
197 template <typename Scalar_, typename Dimensions, int Options, typename IndexType_>
198 struct nested<const TensorFixedSize<Scalar_, Dimensions, Options, IndexType_> >
199 {
200   typedef const TensorFixedSize<Scalar_, Dimensions, Options, IndexType_>EIGEN_DEVICE_REF type;
201 };
202 
203 
204 template <typename PlainObjectType>
205 struct nested<TensorRef<PlainObjectType> >
206 {
207   typedef const TensorRef<PlainObjectType>EIGEN_DEVICE_REF type;
208 };
209 
210 template <typename PlainObjectType>
211 struct nested<const TensorRef<PlainObjectType> >
212 {
213   typedef const TensorRef<PlainObjectType>EIGEN_DEVICE_REF type;
214 };
215 
216 }  // end namespace internal
217 
218 // Convolutional layers take in an input tensor of shape (D, R, C, B), or (D, C,
219 // R, B), and convolve it with a set of filters, which can also be presented as
220 // a tensor (D, K, K, M), where M is the number of filters, K is the filter
221 // size, and each 3-dimensional tensor of size (D, K, K) is a filter. For
222 // simplicity we assume that we always use square filters (which is usually the
223 // case in images), hence the two Ks in the tensor dimension.  It also takes in
224 // a few additional parameters:
225 // Stride (S): The convolution stride is the offset between locations where we
226 //             apply the filters.  A larger stride means that the output will be
227 //             spatially smaller.
228 // Padding (P): The padding we apply to the input tensor along the R and C
229 //              dimensions.  This is usually used to make sure that the spatial
230 //              dimensions of the output matches our intention.
231 //
232 // Two types of padding are often used:
233 //   SAME: The pad value is computed so that the output will have size
234 //         R/S and C/S.
235 //   VALID: no padding is carried out.
236 // When we do padding, the padded values at the padded locations are usually
237 // zero.
238 //
239 // The output dimensions for convolution, when given all the parameters above,
240 // are as follows:
241 // When Padding = SAME: the output size is (B, R', C', M), where
242 //   R' = ceil(float(R) / float(S))
243 //   C' = ceil(float(C) / float(S))
244 // where ceil is the ceiling function.  The input tensor is padded with 0 as
245 // needed.  The number of padded rows and columns are computed as:
246 //   Pr = ((R' - 1) * S + K - R) / 2
247 //   Pc = ((C' - 1) * S + K - C) / 2
248 // when the stride is 1, we have the simplified case R'=R, C'=C, Pr=Pc=(K-1)/2.
249 // This is where SAME comes from - the output has the same size as the input has.
250 // When Padding = VALID: the output size is computed as
251 //   R' = ceil(float(R - K + 1) / float(S))
252 //   C' = ceil(float(C - K + 1) / float(S))
253 // and the number of padded rows and columns are computed in the same way as in
254 // the SAME case.
255 // When the stride is 1, we have the simplified case R'=R-K+1, C'=C-K+1, Pr=0,
256 // Pc=0.
257 typedef enum {
258   PADDING_VALID = 1,
259   PADDING_SAME = 2
260 } PaddingType;
261 
262 }  // end namespace Eigen
263 
264 #endif // EIGEN_CXX11_TENSOR_TENSOR_TRAITS_H
265