10 #ifndef EIGEN_CXX11_TENSOR_TENSOR_PADDING_H 11 #define EIGEN_CXX11_TENSOR_TENSOR_PADDING_H 23 template<
typename PaddingDimensions,
typename XprType>
26 typedef typename XprType::Scalar Scalar;
28 typedef typename XprTraits::StorageKind StorageKind;
29 typedef typename XprTraits::Index
Index;
30 typedef typename XprType::Nested Nested;
32 static const int NumDimensions = XprTraits::NumDimensions;
33 static const int Layout = XprTraits::Layout;
36 template<
typename PaddingDimensions,
typename XprType>
42 template<
typename PaddingDimensions,
typename XprType>
52 template<
typename PaddingDimensions,
typename XprType>
58 typedef typename XprType::CoeffReturnType CoeffReturnType;
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; }
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>
87 typedef typename XprType::Index
Index;
90 typedef typename XprType::Scalar Scalar;
91 typedef typename XprType::CoeffReturnType CoeffReturnType;
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;
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 {
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 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;
387 PaddingDimensions m_padding;
389 Scalar m_paddingValue;
397 #endif // EIGEN_CXX11_TENSOR_TENSOR_PADDING_H Definition: TensorCostModel.h:25
Storage order is column major (see TopicStorageOrders).
Definition: Constants.h:320
Definition: XprHelper.h:158
Definition: TensorForwardDeclarations.h:53
Namespace containing all symbols from the Eigen library.
Definition: bench_norm.cpp:85
A cost model used to limit the number of threads used for evaluating tensor expression.
Definition: TensorEvaluator.h:28
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
Definition: Meta.h:33
The tensor base class.
Definition: TensorBase.h:827
Definition: BandTriangularSolver.h:13
Definition: TensorTraits.h:170
The type used to identify a dense storage.
Definition: Constants.h:491
Generic expression where a coefficient-wise unary operator is applied to an expression.
Definition: CwiseUnaryOp.h:55
Definition: ForwardDeclarations.h:17
Definition: XprHelper.h:312
Definition: EmulateArray.h:203