10 #ifndef EIGEN_CXX11_TENSOR_TENSOR_PADDING_H 11 #define EIGEN_CXX11_TENSOR_TENSOR_PADDING_H 23 template<
typename PaddingDimensions,
typename XprType>
24 struct traits<TensorPaddingOp<PaddingDimensions, XprType> > :
public traits<XprType>
26 typedef typename XprType::Scalar Scalar;
27 typedef traits<XprType> XprTraits;
28 typedef typename XprTraits::StorageKind StorageKind;
29 typedef typename XprTraits::Index Index;
30 typedef typename XprType::Nested Nested;
31 typedef typename remove_reference<Nested>::type _Nested;
32 static const int NumDimensions = XprTraits::NumDimensions;
33 static const int Layout = XprTraits::Layout;
36 template<
typename PaddingDimensions,
typename XprType>
37 struct eval<TensorPaddingOp<PaddingDimensions, XprType>,
Eigen::Dense>
39 typedef const TensorPaddingOp<PaddingDimensions, XprType>& type;
42 template<
typename PaddingDimensions,
typename XprType>
43 struct nested<TensorPaddingOp<PaddingDimensions, XprType>, 1, typename eval<TensorPaddingOp<PaddingDimensions, XprType> >::type>
45 typedef TensorPaddingOp<PaddingDimensions, XprType> type;
52 template<
typename PaddingDimensions,
typename XprType>
53 class TensorPaddingOp :
public TensorBase<TensorPaddingOp<PaddingDimensions, XprType>, ReadOnlyAccessors>
56 typedef typename Eigen::internal::traits<TensorPaddingOp>::Scalar Scalar;
57 typedef typename Eigen::NumTraits<Scalar>::Real RealScalar;
58 typedef typename XprType::CoeffReturnType CoeffReturnType;
59 typedef typename Eigen::internal::nested<TensorPaddingOp>::type Nested;
60 typedef typename Eigen::internal::traits<TensorPaddingOp>::StorageKind StorageKind;
61 typedef typename Eigen::internal::traits<TensorPaddingOp>::Index Index;
63 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorPaddingOp(
const XprType& expr,
const PaddingDimensions& padding_dims,
const Scalar padding_value)
64 : m_xpr(expr), m_padding_dims(padding_dims), m_padding_value(padding_value) {}
67 const PaddingDimensions& padding()
const {
return m_padding_dims; }
69 Scalar padding_value()
const {
return m_padding_value; }
72 const typename internal::remove_all<typename XprType::Nested>::type&
73 expression()
const {
return m_xpr; }
76 typename XprType::Nested m_xpr;
77 const PaddingDimensions m_padding_dims;
78 const Scalar m_padding_value;
83 template<
typename PaddingDimensions,
typename ArgType,
typename Device>
84 struct TensorEvaluator<const TensorPaddingOp<PaddingDimensions, ArgType>, Device>
86 typedef TensorPaddingOp<PaddingDimensions, ArgType> XprType;
87 typedef typename XprType::Index Index;
88 static const int NumDims = internal::array_size<PaddingDimensions>::value;
89 typedef DSizes<Index, NumDims> Dimensions;
90 typedef typename XprType::Scalar Scalar;
91 typedef typename XprType::CoeffReturnType CoeffReturnType;
92 typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
93 static const int PacketSize = internal::unpacket_traits<PacketReturnType>::size;
97 PacketAccess = TensorEvaluator<ArgType, Device>::PacketAccess,
98 Layout = TensorEvaluator<ArgType, Device>::Layout,
103 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorEvaluator(
const XprType& op,
const Device& device)
104 : m_impl(op.expression(), device), m_padding(op.padding()), m_paddingValue(op.padding_value())
109 EIGEN_STATIC_ASSERT((NumDims > 0), YOU_MADE_A_PROGRAMMING_MISTAKE);
112 m_dimensions = m_impl.dimensions();
113 for (
int i = 0; i < NumDims; ++i) {
114 m_dimensions[i] += m_padding[i].first + m_padding[i].second;
116 const typename TensorEvaluator<ArgType, Device>::Dimensions& input_dims = m_impl.dimensions();
117 if (static_cast<int>(Layout) == static_cast<int>(ColMajor)) {
118 m_inputStrides[0] = 1;
119 m_outputStrides[0] = 1;
120 for (
int i = 1; i < NumDims; ++i) {
121 m_inputStrides[i] = m_inputStrides[i-1] * input_dims[i-1];
122 m_outputStrides[i] = m_outputStrides[i-1] * m_dimensions[i-1];
124 m_outputStrides[NumDims] = m_outputStrides[NumDims-1] * m_dimensions[NumDims-1];
126 m_inputStrides[NumDims - 1] = 1;
127 m_outputStrides[NumDims] = 1;
128 for (
int i = NumDims - 2; i >= 0; --i) {
129 m_inputStrides[i] = m_inputStrides[i+1] * input_dims[i+1];
130 m_outputStrides[i+1] = m_outputStrides[i+2] * m_dimensions[i+1];
132 m_outputStrides[0] = m_outputStrides[1] * m_dimensions[0];
136 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const Dimensions& dimensions()
const {
return m_dimensions; }
138 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
bool evalSubExprsIfNeeded(Scalar*) {
139 m_impl.evalSubExprsIfNeeded(NULL);
142 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void cleanup() {
146 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index)
const 148 eigen_assert(index < dimensions().TotalSize());
149 Index inputIndex = 0;
150 if (static_cast<int>(Layout) == static_cast<int>(ColMajor)) {
151 for (
int i = NumDims - 1; i > 0; --i) {
152 const Index idx = index / m_outputStrides[i];
153 if (isPaddingAtIndexForDim(idx, i)) {
154 return m_paddingValue;
156 inputIndex += (idx - m_padding[i].first) * m_inputStrides[i];
157 index -= idx * m_outputStrides[i];
159 if (isPaddingAtIndexForDim(index, 0)) {
160 return m_paddingValue;
162 inputIndex += (index - m_padding[0].first);
164 for (
int i = 0; i < NumDims - 1; ++i) {
165 const Index idx = index / m_outputStrides[i+1];
166 if (isPaddingAtIndexForDim(idx, i)) {
167 return m_paddingValue;
169 inputIndex += (idx - m_padding[i].first) * m_inputStrides[i];
170 index -= idx * m_outputStrides[i+1];
172 if (isPaddingAtIndexForDim(index, NumDims-1)) {
173 return m_paddingValue;
175 inputIndex += (index - m_padding[NumDims-1].first);
177 return m_impl.coeff(inputIndex);
180 template<
int LoadMode>
181 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packet(Index index)
const 183 if (static_cast<int>(Layout) == static_cast<int>(ColMajor)) {
184 return packetColMajor(index);
186 return packetRowMajor(index);
189 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorOpCost costPerCoeff(
bool vectorized)
const {
190 TensorOpCost cost = m_impl.costPerCoeff(vectorized);
191 if (static_cast<int>(Layout) == static_cast<int>(ColMajor)) {
192 for (
int i = 0; i < NumDims; ++i)
193 updateCostPerDimension(cost, i, i == 0);
195 for (
int i = NumDims - 1; i >= 0; --i)
196 updateCostPerDimension(cost, i, i == NumDims - 1);
201 EIGEN_DEVICE_FUNC Scalar* data()
const {
return NULL; }
204 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
bool isPaddingAtIndexForDim(
205 Index index,
int dim_index)
const {
206 #if defined(EIGEN_HAS_INDEX_LIST) 207 return (!internal::index_pair_first_statically_eq<PaddingDimensions>(dim_index, 0) &&
208 index < m_padding[dim_index].first) ||
209 (!internal::index_pair_second_statically_eq<PaddingDimensions>(dim_index, 0) &&
210 index >= m_dimensions[dim_index] - m_padding[dim_index].second);
212 return (index < m_padding[dim_index].first) ||
213 (index >= m_dimensions[dim_index] - m_padding[dim_index].second);
217 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
bool isLeftPaddingCompileTimeZero(
218 int dim_index)
const {
219 #if defined(EIGEN_HAS_INDEX_LIST) 220 return internal::index_pair_first_statically_eq<PaddingDimensions>(dim_index, 0);
222 EIGEN_UNUSED_VARIABLE(dim_index);
227 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
bool isRightPaddingCompileTimeZero(
228 int dim_index)
const {
229 #if defined(EIGEN_HAS_INDEX_LIST) 230 return internal::index_pair_second_statically_eq<PaddingDimensions>(dim_index, 0);
232 EIGEN_UNUSED_VARIABLE(dim_index);
238 void updateCostPerDimension(TensorOpCost& cost,
int i,
bool first)
const {
239 const double in =
static_cast<double>(m_impl.dimensions()[i]);
240 const double out = in + m_padding[i].first + m_padding[i].second;
243 const double reduction = in / out;
246 cost += TensorOpCost(0, 0, 2 * TensorOpCost::AddCost<Index>() +
247 reduction * (1 * TensorOpCost::AddCost<Index>()));
249 cost += TensorOpCost(0, 0, 2 * TensorOpCost::AddCost<Index>() +
250 2 * TensorOpCost::MulCost<Index>() +
251 reduction * (2 * TensorOpCost::MulCost<Index>() +
252 1 * TensorOpCost::DivCost<Index>()));
258 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packetColMajor(Index index)
const 260 EIGEN_STATIC_ASSERT((PacketSize > 1), YOU_MADE_A_PROGRAMMING_MISTAKE)
261 eigen_assert(index+PacketSize-1 < dimensions().TotalSize());
263 const Index initialIndex = index;
264 Index inputIndex = 0;
265 for (
int i = NumDims - 1; i > 0; --i) {
266 const Index first = index;
267 const Index last = index + PacketSize - 1;
268 const Index lastPaddedLeft = m_padding[i].first * m_outputStrides[i];
269 const Index firstPaddedRight = (m_dimensions[i] - m_padding[i].second) * m_outputStrides[i];
270 const Index lastPaddedRight = m_outputStrides[i+1];
272 if (!isLeftPaddingCompileTimeZero(i) && last < lastPaddedLeft) {
274 return internal::pset1<PacketReturnType>(m_paddingValue);
276 else if (!isRightPaddingCompileTimeZero(i) && first >= firstPaddedRight && last < lastPaddedRight) {
278 return internal::pset1<PacketReturnType>(m_paddingValue);
280 else if ((isLeftPaddingCompileTimeZero(i) && isRightPaddingCompileTimeZero(i)) || (first >= lastPaddedLeft && last < firstPaddedRight)) {
282 const Index idx = index / m_outputStrides[i];
283 inputIndex += (idx - m_padding[i].first) * m_inputStrides[i];
284 index -= idx * m_outputStrides[i];
288 return packetWithPossibleZero(initialIndex);
292 const Index last = index + PacketSize - 1;
293 const Index first = index;
294 const Index lastPaddedLeft = m_padding[0].first;
295 const Index firstPaddedRight = (m_dimensions[0] - m_padding[0].second);
296 const Index lastPaddedRight = m_outputStrides[1];
298 if (!isLeftPaddingCompileTimeZero(0) && last < lastPaddedLeft) {
300 return internal::pset1<PacketReturnType>(m_paddingValue);
302 else if (!isRightPaddingCompileTimeZero(0) && first >= firstPaddedRight && last < lastPaddedRight) {
304 return internal::pset1<PacketReturnType>(m_paddingValue);
306 else if ((isLeftPaddingCompileTimeZero(0) && isRightPaddingCompileTimeZero(0)) || (first >= lastPaddedLeft && last < firstPaddedRight)) {
308 inputIndex += (index - m_padding[0].first);
309 return m_impl.template packet<Unaligned>(inputIndex);
312 return packetWithPossibleZero(initialIndex);
315 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packetRowMajor(Index index)
const 317 EIGEN_STATIC_ASSERT((PacketSize > 1), YOU_MADE_A_PROGRAMMING_MISTAKE)
318 eigen_assert(index+PacketSize-1 < dimensions().TotalSize());
320 const Index initialIndex = index;
321 Index inputIndex = 0;
323 for (
int i = 0; i < NumDims - 1; ++i) {
324 const Index first = index;
325 const Index last = index + PacketSize - 1;
326 const Index lastPaddedLeft = m_padding[i].first * m_outputStrides[i+1];
327 const Index firstPaddedRight = (m_dimensions[i] - m_padding[i].second) * m_outputStrides[i+1];
328 const Index lastPaddedRight = m_outputStrides[i];
330 if (!isLeftPaddingCompileTimeZero(i) && last < lastPaddedLeft) {
332 return internal::pset1<PacketReturnType>(m_paddingValue);
334 else if (!isRightPaddingCompileTimeZero(i) && first >= firstPaddedRight && last < lastPaddedRight) {
336 return internal::pset1<PacketReturnType>(m_paddingValue);
338 else if ((isLeftPaddingCompileTimeZero(i) && isRightPaddingCompileTimeZero(i)) || (first >= lastPaddedLeft && last < firstPaddedRight)) {
340 const Index idx = index / m_outputStrides[i+1];
341 inputIndex += (idx - m_padding[i].first) * m_inputStrides[i];
342 index -= idx * m_outputStrides[i+1];
346 return packetWithPossibleZero(initialIndex);
350 const Index last = index + PacketSize - 1;
351 const Index first = index;
352 const Index lastPaddedLeft = m_padding[NumDims-1].first;
353 const Index firstPaddedRight = (m_dimensions[NumDims-1] - m_padding[NumDims-1].second);
354 const Index lastPaddedRight = m_outputStrides[NumDims-1];
356 if (!isLeftPaddingCompileTimeZero(NumDims-1) && last < lastPaddedLeft) {
358 return internal::pset1<PacketReturnType>(m_paddingValue);
360 else if (!isRightPaddingCompileTimeZero(NumDims-1) && first >= firstPaddedRight && last < lastPaddedRight) {
362 return internal::pset1<PacketReturnType>(m_paddingValue);
364 else if ((isLeftPaddingCompileTimeZero(NumDims-1) && isRightPaddingCompileTimeZero(NumDims-1)) || (first >= lastPaddedLeft && last < firstPaddedRight)) {
366 inputIndex += (index - m_padding[NumDims-1].first);
367 return m_impl.template packet<Unaligned>(inputIndex);
370 return packetWithPossibleZero(initialIndex);
373 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packetWithPossibleZero(Index index)
const 375 EIGEN_ALIGN_MAX
typename internal::remove_const<CoeffReturnType>::type values[PacketSize];
376 for (
int i = 0; i < PacketSize; ++i) {
377 values[i] = coeff(index+i);
379 PacketReturnType rslt = internal::pload<PacketReturnType>(values);
383 Dimensions m_dimensions;
384 array<Index, NumDims+1> m_outputStrides;
385 array<Index, NumDims> m_inputStrides;
386 TensorEvaluator<ArgType, Device> m_impl;
387 PaddingDimensions m_padding;
389 Scalar m_paddingValue;
397 #endif // EIGEN_CXX11_TENSOR_TENSOR_PADDING_H Namespace containing all symbols from the Eigen library.
Definition: AdolcForward:45