• 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 };
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