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