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;
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>
64 : m_xpr(expr), m_padding_dims(padding_dims), m_padding_value(padding_value) {}
67 const PaddingDimensions&
padding()
const {
return m_padding_dims; }
83 template<
typename PaddingDimensions,
typename ArgType,
typename Device>
104 : m_impl(op.expression(), device), m_padding(op.padding()), m_paddingValue(op.padding_value())
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];
139 m_impl.evalSubExprsIfNeeded(NULL);
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>
183 if (static_cast<int>(Layout) == static_cast<int>(
ColMajor)) {
184 return packetColMajor(index);
186 return packetRowMajor(index);
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; }
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);
218 int dim_index)
const {
219 #if defined(EIGEN_HAS_INDEX_LIST) 220 return internal::index_pair_first_statically_eq<PaddingDimensions>(dim_index, 0);
228 int dim_index)
const {
229 #if defined(EIGEN_HAS_INDEX_LIST) 230 return internal::index_pair_second_statically_eq<PaddingDimensions>(dim_index, 0);
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>()));
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);
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);
376 for (
int i = 0; i < PacketSize; ++i) {
377 values[i] = coeff(index+i);
379 PacketReturnType rslt = internal::pload<PacketReturnType>(values);
397 #endif // EIGEN_CXX11_TENSOR_TENSOR_PADDING_H EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void cleanup()
#define EIGEN_ALWAYS_INLINE
#define EIGEN_STRONG_INLINE
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Dimensions & dimensions() const
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packetRowMajor(Index index) const
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packetColMajor(Index index) const
std::vector< double > values
PacketType< CoeffReturnType, Device >::type PacketReturnType
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool evalSubExprsIfNeeded(Scalar *)
A cost model used to limit the number of threads used for evaluating tensor expression.
#define EIGEN_STATIC_ASSERT(CONDITION, MSG)
Eigen::NumTraits< Scalar >::Real RealScalar
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorOpCost costPerCoeff(bool vectorized) const
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE bool isRightPaddingCompileTimeZero(int dim_index) const
const TensorPaddingOp< PaddingDimensions, XprType > & type
Eigen::internal::traits< TensorPaddingOp >::Scalar Scalar
EIGEN_DEVICE_FUNC Scalar * data() const
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE bool isPaddingAtIndexForDim(Index index, int dim_index) const
XprTraits::StorageKind StorageKind
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorPaddingOp(const XprType &expr, const PaddingDimensions &padding_dims, const Scalar padding_value)
EIGEN_DEFAULT_DENSE_INDEX_TYPE Index
The Index type as used for the API.
array< Index, NumDims > m_inputStrides
TensorEvaluator< ArgType, Device > m_impl
TensorPaddingOp< PaddingDimensions, XprType > type
const Scalar m_padding_value
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorEvaluator(const XprType &op, const Device &device)
EIGEN_DEVICE_FUNC const internal::remove_all< typename XprType::Nested >::type & expression() const
const PaddingDimensions m_padding_dims
PaddingDimensions m_padding
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const
XprType::CoeffReturnType CoeffReturnType
remove_reference< Nested >::type _Nested
Eigen::internal::nested< TensorPaddingOp >::type Nested
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE bool isLeftPaddingCompileTimeZero(int dim_index) const
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packet(Index index) const
EIGEN_DEVICE_FUNC Scalar padding_value() const
TensorPaddingOp< PaddingDimensions, ArgType > XprType
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Dimensions & dimensions() const
Eigen::internal::traits< TensorPaddingOp >::StorageKind StorageKind
void updateCostPerDimension(TensorOpCost &cost, int i, bool first) const
DSizes< Index, NumDims > Dimensions
traits< XprType > XprTraits
array< Index, NumDims+1 > m_outputStrides
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packetWithPossibleZero(Index index) const
XprType::CoeffReturnType CoeffReturnType
Eigen::internal::traits< TensorPaddingOp >::Index Index
#define EIGEN_UNUSED_VARIABLE(var)
internal::packet_traits< Scalar >::type type
EIGEN_DEVICE_FUNC const PaddingDimensions & padding() const