10#ifndef EIGEN_CXX11_TENSOR_TENSOR_PADDING_H
11#define EIGEN_CXX11_TENSOR_TENSOR_PADDING_H
16template<
typename PaddingDimensions,
typename XprType>
17struct traits<TensorPaddingOp<PaddingDimensions, XprType> > :
public traits<XprType>
19 typedef typename XprType::Scalar Scalar;
20 typedef traits<XprType> XprTraits;
21 typedef typename XprTraits::StorageKind StorageKind;
22 typedef typename XprTraits::Index
Index;
23 typedef typename XprType::Nested Nested;
24 typedef typename remove_reference<Nested>::type _Nested;
25 static const int NumDimensions = XprTraits::NumDimensions;
26 static const int Layout = XprTraits::Layout;
29template<
typename PaddingDimensions,
typename XprType>
30struct eval<TensorPaddingOp<PaddingDimensions, XprType>, Eigen::Dense>
32 typedef const TensorPaddingOp<PaddingDimensions, XprType>& type;
35template<
typename PaddingDimensions,
typename XprType>
36struct nested<TensorPaddingOp<PaddingDimensions, XprType>, 1, typename eval<TensorPaddingOp<PaddingDimensions, XprType> >::type>
38 typedef TensorPaddingOp<PaddingDimensions, XprType> type;
50template <
typename PaddingDimensions,
typename XprType>
51class TensorPaddingOp :
public TensorBase<TensorPaddingOp<PaddingDimensions, XprType>, ReadOnlyAccessors> {
53 typedef typename Eigen::internal::traits<TensorPaddingOp>::Scalar Scalar;
55 typedef typename XprType::CoeffReturnType CoeffReturnType;
56 typedef typename Eigen::internal::nested<TensorPaddingOp>::type Nested;
57 typedef typename Eigen::internal::traits<TensorPaddingOp>::StorageKind StorageKind;
58 typedef typename Eigen::internal::traits<TensorPaddingOp>::Index Index;
60 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorPaddingOp(
const XprType& expr,
const PaddingDimensions& padding_dims,
const Scalar padding_value)
61 : m_xpr(expr), m_padding_dims(padding_dims), m_padding_value(padding_value) {}
64 const PaddingDimensions& padding()
const {
return m_padding_dims; }
66 Scalar padding_value()
const {
return m_padding_value; }
69 const typename internal::remove_all<typename XprType::Nested>::type&
70 expression()
const {
return m_xpr; }
73 typename XprType::Nested m_xpr;
74 const PaddingDimensions m_padding_dims;
75 const Scalar m_padding_value;
80template<
typename PaddingDimensions,
typename ArgType,
typename Device>
84 typedef typename XprType::Index
Index;
85 static const int NumDims = internal::array_size<PaddingDimensions>::value;
87 typedef typename XprType::Scalar
Scalar;
88 typedef typename XprType::CoeffReturnType CoeffReturnType;
89 typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
90 static const int PacketSize = internal::unpacket_traits<PacketReturnType>::size;
94 PacketAccess = TensorEvaluator<ArgType, Device>::PacketAccess,
95 Layout = TensorEvaluator<ArgType, Device>::Layout,
100 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorEvaluator(
const XprType& op,
const Device&
device)
101 : m_impl(op.expression(),
device), m_padding(op.padding()), m_paddingValue(op.padding_value())
106 EIGEN_STATIC_ASSERT((NumDims > 0), YOU_MADE_A_PROGRAMMING_MISTAKE);
109 m_dimensions = m_impl.dimensions();
110 for (
int i = 0; i < NumDims; ++i) {
111 m_dimensions[i] += m_padding[i].first + m_padding[i].second;
113 const typename TensorEvaluator<ArgType, Device>::Dimensions& input_dims = m_impl.dimensions();
114 if (
static_cast<int>(Layout) ==
static_cast<int>(
ColMajor)) {
115 m_inputStrides[0] = 1;
116 m_outputStrides[0] = 1;
117 for (
int i = 1; i < NumDims; ++i) {
118 m_inputStrides[i] = m_inputStrides[i-1] * input_dims[i-1];
119 m_outputStrides[i] = m_outputStrides[i-1] * m_dimensions[i-1];
121 m_outputStrides[NumDims] = m_outputStrides[NumDims-1] * m_dimensions[NumDims-1];
123 m_inputStrides[NumDims - 1] = 1;
124 m_outputStrides[NumDims] = 1;
125 for (
int i = NumDims - 2; i >= 0; --i) {
126 m_inputStrides[i] = m_inputStrides[i+1] * input_dims[i+1];
127 m_outputStrides[i+1] = m_outputStrides[i+2] * m_dimensions[i+1];
129 m_outputStrides[0] = m_outputStrides[1] * m_dimensions[0];
133 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const Dimensions& dimensions()
const {
return m_dimensions; }
135 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
bool evalSubExprsIfNeeded(Scalar*) {
136 m_impl.evalSubExprsIfNeeded(NULL);
139 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void cleanup() {
143 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index)
const
145 eigen_assert(index < dimensions().TotalSize());
146 Index inputIndex = 0;
147 if (
static_cast<int>(Layout) ==
static_cast<int>(
ColMajor)) {
148 for (
int i = NumDims - 1; i > 0; --i) {
149 const Index idx = index / m_outputStrides[i];
150 if (isPaddingAtIndexForDim(idx, i)) {
151 return m_paddingValue;
153 inputIndex += (idx - m_padding[i].first) * m_inputStrides[i];
154 index -= idx * m_outputStrides[i];
156 if (isPaddingAtIndexForDim(index, 0)) {
157 return m_paddingValue;
159 inputIndex += (index - m_padding[0].first);
161 for (
int i = 0; i < NumDims - 1; ++i) {
162 const Index idx = index / m_outputStrides[i+1];
163 if (isPaddingAtIndexForDim(idx, i)) {
164 return m_paddingValue;
166 inputIndex += (idx - m_padding[i].first) * m_inputStrides[i];
167 index -= idx * m_outputStrides[i+1];
169 if (isPaddingAtIndexForDim(index, NumDims-1)) {
170 return m_paddingValue;
172 inputIndex += (index - m_padding[NumDims-1].first);
174 return m_impl.coeff(inputIndex);
177 template<
int LoadMode>
178 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packet(Index index)
const
180 if (
static_cast<int>(Layout) ==
static_cast<int>(
ColMajor)) {
181 return packetColMajor(index);
183 return packetRowMajor(index);
186 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorOpCost costPerCoeff(
bool vectorized)
const {
187 TensorOpCost cost = m_impl.costPerCoeff(vectorized);
188 if (
static_cast<int>(Layout) ==
static_cast<int>(
ColMajor)) {
189 for (
int i = 0; i < NumDims; ++i)
190 updateCostPerDimension(cost, i, i == 0);
192 for (
int i = NumDims - 1; i >= 0; --i)
193 updateCostPerDimension(cost, i, i == NumDims - 1);
198 EIGEN_DEVICE_FUNC Scalar* data()
const {
return NULL; }
201 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
bool isPaddingAtIndexForDim(
202 Index index,
int dim_index)
const {
203#if defined(EIGEN_HAS_INDEX_LIST)
204 return (!internal::index_pair_first_statically_eq<PaddingDimensions>(dim_index, 0) &&
205 index < m_padding[dim_index].first) ||
206 (!internal::index_pair_second_statically_eq<PaddingDimensions>(dim_index, 0) &&
207 index >= m_dimensions[dim_index] - m_padding[dim_index].second);
209 return (index < m_padding[dim_index].first) ||
210 (index >= m_dimensions[dim_index] - m_padding[dim_index].second);
214 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
bool isLeftPaddingCompileTimeZero(
215 int dim_index)
const {
216#if defined(EIGEN_HAS_INDEX_LIST)
217 return internal::index_pair_first_statically_eq<PaddingDimensions>(dim_index, 0);
219 EIGEN_UNUSED_VARIABLE(dim_index);
224 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
bool isRightPaddingCompileTimeZero(
225 int dim_index)
const {
226#if defined(EIGEN_HAS_INDEX_LIST)
227 return internal::index_pair_second_statically_eq<PaddingDimensions>(dim_index, 0);
229 EIGEN_UNUSED_VARIABLE(dim_index);
235 void updateCostPerDimension(TensorOpCost& cost,
int i,
bool first)
const {
236 const double in =
static_cast<double>(m_impl.dimensions()[i]);
237 const double out = in + m_padding[i].first + m_padding[i].second;
240 const double reduction = in / out;
243 cost += TensorOpCost(0, 0, 2 * TensorOpCost::AddCost<Index>() +
244 reduction * (1 * TensorOpCost::AddCost<Index>()));
246 cost += TensorOpCost(0, 0, 2 * TensorOpCost::AddCost<Index>() +
247 2 * TensorOpCost::MulCost<Index>() +
248 reduction * (2 * TensorOpCost::MulCost<Index>() +
249 1 * TensorOpCost::DivCost<Index>()));
255 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packetColMajor(Index index)
const
257 EIGEN_STATIC_ASSERT((PacketSize > 1), YOU_MADE_A_PROGRAMMING_MISTAKE)
258 eigen_assert(index+PacketSize-1 < dimensions().TotalSize());
260 const Index initialIndex = index;
261 Index inputIndex = 0;
262 for (
int i = NumDims - 1; i > 0; --i) {
263 const Index first = index;
264 const Index last = index + PacketSize - 1;
265 const Index lastPaddedLeft = m_padding[i].first * m_outputStrides[i];
266 const Index firstPaddedRight = (m_dimensions[i] - m_padding[i].second) * m_outputStrides[i];
267 const Index lastPaddedRight = m_outputStrides[i+1];
269 if (!isLeftPaddingCompileTimeZero(i) && last < lastPaddedLeft) {
271 return internal::pset1<PacketReturnType>(m_paddingValue);
273 else if (!isRightPaddingCompileTimeZero(i) && first >= firstPaddedRight && last < lastPaddedRight) {
275 return internal::pset1<PacketReturnType>(m_paddingValue);
277 else if ((isLeftPaddingCompileTimeZero(i) && isRightPaddingCompileTimeZero(i)) || (first >= lastPaddedLeft && last < firstPaddedRight)) {
279 const Index idx = index / m_outputStrides[i];
280 inputIndex += (idx - m_padding[i].first) * m_inputStrides[i];
281 index -= idx * m_outputStrides[i];
285 return packetWithPossibleZero(initialIndex);
289 const Index last = index + PacketSize - 1;
290 const Index first = index;
291 const Index lastPaddedLeft = m_padding[0].first;
292 const Index firstPaddedRight = (m_dimensions[0] - m_padding[0].second);
293 const Index lastPaddedRight = m_outputStrides[1];
295 if (!isLeftPaddingCompileTimeZero(0) && last < lastPaddedLeft) {
297 return internal::pset1<PacketReturnType>(m_paddingValue);
299 else if (!isRightPaddingCompileTimeZero(0) && first >= firstPaddedRight && last < lastPaddedRight) {
301 return internal::pset1<PacketReturnType>(m_paddingValue);
303 else if ((isLeftPaddingCompileTimeZero(0) && isRightPaddingCompileTimeZero(0)) || (first >= lastPaddedLeft && last < firstPaddedRight)) {
305 inputIndex += (index - m_padding[0].first);
306 return m_impl.template packet<Unaligned>(inputIndex);
309 return packetWithPossibleZero(initialIndex);
312 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packetRowMajor(Index index)
const
314 EIGEN_STATIC_ASSERT((PacketSize > 1), YOU_MADE_A_PROGRAMMING_MISTAKE)
315 eigen_assert(index+PacketSize-1 < dimensions().TotalSize());
317 const Index initialIndex = index;
318 Index inputIndex = 0;
320 for (
int i = 0; i < NumDims - 1; ++i) {
321 const Index first = index;
322 const Index last = index + PacketSize - 1;
323 const Index lastPaddedLeft = m_padding[i].first * m_outputStrides[i+1];
324 const Index firstPaddedRight = (m_dimensions[i] - m_padding[i].second) * m_outputStrides[i+1];
325 const Index lastPaddedRight = m_outputStrides[i];
327 if (!isLeftPaddingCompileTimeZero(i) && last < lastPaddedLeft) {
329 return internal::pset1<PacketReturnType>(m_paddingValue);
331 else if (!isRightPaddingCompileTimeZero(i) && first >= firstPaddedRight && last < lastPaddedRight) {
333 return internal::pset1<PacketReturnType>(m_paddingValue);
335 else if ((isLeftPaddingCompileTimeZero(i) && isRightPaddingCompileTimeZero(i)) || (first >= lastPaddedLeft && last < firstPaddedRight)) {
337 const Index idx = index / m_outputStrides[i+1];
338 inputIndex += (idx - m_padding[i].first) * m_inputStrides[i];
339 index -= idx * m_outputStrides[i+1];
343 return packetWithPossibleZero(initialIndex);
347 const Index last = index + PacketSize - 1;
348 const Index first = index;
349 const Index lastPaddedLeft = m_padding[NumDims-1].first;
350 const Index firstPaddedRight = (m_dimensions[NumDims-1] - m_padding[NumDims-1].second);
351 const Index lastPaddedRight = m_outputStrides[NumDims-1];
353 if (!isLeftPaddingCompileTimeZero(NumDims-1) && last < lastPaddedLeft) {
355 return internal::pset1<PacketReturnType>(m_paddingValue);
357 else if (!isRightPaddingCompileTimeZero(NumDims-1) && first >= firstPaddedRight && last < lastPaddedRight) {
359 return internal::pset1<PacketReturnType>(m_paddingValue);
361 else if ((isLeftPaddingCompileTimeZero(NumDims-1) && isRightPaddingCompileTimeZero(NumDims-1)) || (first >= lastPaddedLeft && last < firstPaddedRight)) {
363 inputIndex += (index - m_padding[NumDims-1].first);
364 return m_impl.template packet<Unaligned>(inputIndex);
367 return packetWithPossibleZero(initialIndex);
370 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packetWithPossibleZero(Index index)
const
372 EIGEN_ALIGN_MAX
typename internal::remove_const<CoeffReturnType>::type values[PacketSize];
373 for (
int i = 0; i < PacketSize; ++i) {
374 values[i] = coeff(index+i);
376 PacketReturnType rslt = internal::pload<PacketReturnType>(values);
380 Dimensions m_dimensions;
381 array<Index, NumDims+1> m_outputStrides;
382 array<Index, NumDims> m_inputStrides;
383 TensorEvaluator<ArgType, Device> m_impl;
384 PaddingDimensions m_padding;
386 Scalar m_paddingValue;
The tensor base class.
Definition TensorForwardDeclarations.h:29
Tensor padding class. At the moment only padding with a constant value is supported.
Definition TensorPadding.h:51
Namespace containing all symbols from the Eigen library.
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The tensor evaluator class.
Definition TensorEvaluator.h:27
const Device & device() const
required by sycl in order to construct sycl buffer from raw pointer
Definition TensorEvaluator.h:112