11#ifndef EIGEN_TENSOR_TENSOR_STRIDING_H
12#define EIGEN_TENSOR_TENSOR_STRIDING_H
15#include "./InternalHeaderCheck.h"
20template <
typename Str
ides,
typename XprType>
21struct traits<TensorStridingOp<Strides, XprType> > :
public traits<XprType> {
22 typedef typename XprType::Scalar Scalar;
23 typedef traits<XprType> XprTraits;
24 typedef typename XprTraits::StorageKind StorageKind;
25 typedef typename XprTraits::Index Index;
26 static constexpr int NumDimensions = XprTraits::NumDimensions;
27 static constexpr int Layout = XprTraits::Layout;
28 typedef typename XprTraits::PointerType PointerType;
31template <
typename Str
ides,
typename XprType>
32struct eval<TensorStridingOp<Strides, XprType>, Eigen::Dense> {
33 typedef const TensorStridingOp<Strides, XprType> EIGEN_DEVICE_REF type;
43template <
typename Str
ides,
typename XprType>
44class TensorStridingOp :
public TensorBase<TensorStridingOp<Strides, XprType> > {
47 typedef typename Eigen::internal::traits<TensorStridingOp>::Scalar Scalar;
49 typedef typename XprType::CoeffReturnType CoeffReturnType;
50 typedef typename Eigen::internal::ref_selector<TensorStridingOp>::type Nested;
51 typedef typename Eigen::internal::traits<TensorStridingOp>::StorageKind StorageKind;
52 typedef typename Eigen::internal::traits<TensorStridingOp>::Index Index;
54 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorStridingOp(
const XprType& expr,
const Strides& dims)
55 : m_xpr(expr), m_dims(dims) {}
57 EIGEN_DEVICE_FUNC
const Strides& strides()
const {
return m_dims; }
59 EIGEN_DEVICE_FUNC
const internal::remove_all_t<typename XprType::Nested>& expression()
const {
return m_xpr; }
61 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(TensorStridingOp)
64 typename XprType::Nested m_xpr;
69template <
typename Str
ides,
typename ArgType,
typename Device>
72 typedef typename XprType::Index Index;
73 static constexpr int NumDims = internal::array_size<typename TensorEvaluator<ArgType, Device>::Dimensions>::value;
75 typedef typename XprType::Scalar Scalar;
77 typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
78 static constexpr int PacketSize = PacketType<CoeffReturnType, Device>::size;
79 typedef StorageMemory<CoeffReturnType, Device> Storage;
80 typedef typename Storage::Type EvaluatorPointerType;
82 static constexpr int Layout = TensorEvaluator<ArgType, Device>::Layout;
84 static constexpr int kInnerDim = (
static_cast<int>(Layout) ==
static_cast<int>(
ColMajor)) ? 0 : NumDims - 1;
86 typedef std::integral_constant<bool, TensorEvaluator<ArgType, Device>::PacketAccess> ImplHasPacket;
91 PacketAccess = (PacketSize > 1),
99 typedef internal::TensorBlockNotImplemented TensorBlock;
102 EIGEN_STRONG_INLINE TensorEvaluator(
const XprType& op,
const Device& device) : m_impl(op.expression(), device) {
103 m_dimensions = m_impl.dimensions();
104 m_is_identity =
true;
105 for (
int i = 0; i < NumDims; ++i) {
106 m_dimensions[i] = Eigen::numext::ceil(
static_cast<float>(m_dimensions[i]) / op.strides()[i]);
107 if (op.strides()[i] != 1) m_is_identity =
false;
110 const typename TensorEvaluator<ArgType, Device>::Dimensions& input_dims = m_impl.dimensions();
111 EIGEN_IF_CONSTEXPR (
static_cast<int>(Layout) ==
static_cast<int>(
ColMajor)) {
112 m_outputStrides[0] = 1;
113 m_inputStrides[0] = 1;
114 for (
int i = 1; i < NumDims; ++i) {
115 m_outputStrides[i] = m_outputStrides[i - 1] * m_dimensions[i - 1];
116 m_inputStrides[i] = m_inputStrides[i - 1] * input_dims[i - 1];
117 m_inputStrides[i - 1] *= op.strides()[i - 1];
119 m_inputStrides[NumDims - 1] *= op.strides()[NumDims - 1];
121 m_outputStrides[NumDims - 1] = 1;
122 m_inputStrides[NumDims - 1] = 1;
123 for (
int i = NumDims - 2; i >= 0; --i) {
124 m_outputStrides[i] = m_outputStrides[i + 1] * m_dimensions[i + 1];
125 m_inputStrides[i] = m_inputStrides[i + 1] * input_dims[i + 1];
126 m_inputStrides[i + 1] *= op.strides()[i + 1];
128 m_inputStrides[0] *= op.strides()[0];
132 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
const Dimensions& dimensions()
const {
return m_dimensions; }
134 EIGEN_STRONG_INLINE
bool evalSubExprsIfNeeded(EvaluatorPointerType ) {
135 m_impl.evalSubExprsIfNeeded(
nullptr);
138 EIGEN_STRONG_INLINE
void cleanup() { m_impl.cleanup(); }
140 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index)
const {
142 return m_impl.coeff(index);
144 return m_impl.coeff(srcCoeff(index));
154 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType loadInnerRun(Index base, Index inner_stride,
155 std::false_type)
const {
156 EIGEN_ALIGN_TO_BOUNDARY(internal::unpacket_traits<PacketReturnType>::alignment)
157 std::remove_const_t<CoeffReturnType> values[PacketSize];
159 for (
int i = 0; i < PacketSize; ++i) {
160 values[i] = m_impl.coeff(base + i * inner_stride);
162 return internal::pload<PacketReturnType>(values);
165 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType loadInnerRun(Index base, Index inner_stride,
166 std::true_type)
const {
167 if (inner_stride == 1)
return m_impl.template packet<Unaligned>(base);
168 return loadInnerRun(base, inner_stride, std::false_type());
171 template <
int LoadMode>
172 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packet(Index index)
const {
173 eigen_assert(index + PacketSize - 1 < dimensions().TotalSize());
176 if (m_is_identity)
return loadInnerRun(index, 1, ImplHasPacket());
178 if (packetStaysInInnerRun(index, base))
return loadInnerRun(base, m_inputStrides[kInnerDim], ImplHasPacket());
182 EIGEN_ALIGN_TO_BOUNDARY(internal::unpacket_traits<PacketReturnType>::alignment)
183 std::remove_const_t<CoeffReturnType> values[PacketSize];
185 for (
int i = 0; i < PacketSize; ++i) {
186 values[i] = coeff(index + i);
188 return internal::pload<PacketReturnType>(values);
191 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorOpCost costPerCoeff(
bool vectorized)
const {
192 const double compute_cost = m_is_identity
193 ? TensorOpCost::AddCost<Index>()
194 : (NumDims - 1) * (TensorOpCost::AddCost<Index>() + TensorOpCost::MulCost<Index>() +
195 TensorOpCost::DivCost<Index>()) +
196 TensorOpCost::MulCost<Index>();
204 const bool packets_stay_in_inner =
205 m_is_identity || (m_dimensions[kInnerDim] > 0 && m_dimensions[kInnerDim] % PacketSize == 0);
206 const bool packetizes_arg =
207 TensorEvaluator<ArgType, Device>::PacketAccess && packets_stay_in_inner && m_inputStrides[kInnerDim] == 1;
208 return m_impl.costPerCoeff(vectorized && packetizes_arg) +
209 TensorOpCost(0, 0, compute_cost, vectorized && packets_stay_in_inner, PacketSize);
212 EIGEN_DEVICE_FUNC
typename Storage::Type data()
const {
return nullptr; }
219 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index srcCoeffInner(Index index, Index& inner_pos)
const {
220 Index inputIndex = 0;
221 EIGEN_IF_CONSTEXPR (
static_cast<int>(Layout) ==
static_cast<int>(
ColMajor)) {
223 for (
int i = NumDims - 1; i > 0; --i) {
224 const Index idx = index / m_outputStrides[i];
225 inputIndex += idx * m_inputStrides[i];
226 index -= idx * m_outputStrides[i];
229 inputIndex += index * m_inputStrides[0];
232 for (
int i = 0; i < NumDims - 1; ++i) {
233 const Index idx = index / m_outputStrides[i];
234 inputIndex += idx * m_inputStrides[i];
235 index -= idx * m_outputStrides[i];
238 inputIndex += index * m_inputStrides[NumDims - 1];
243 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index srcCoeff(Index index)
const {
245 return srcCoeffInner(index, inner_pos);
250 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
bool packetStaysInInnerRun(Index index, Index& base)
const {
252 base = srcCoeffInner(index, inner_pos);
253 return inner_pos + PacketSize <= m_dimensions[kInnerDim];
256 Dimensions m_dimensions;
258 array<Index, NumDims> m_outputStrides;
259 array<Index, NumDims> m_inputStrides;
260 TensorEvaluator<ArgType, Device> m_impl;
264template <
typename Str
ides,
typename ArgType,
typename Device>
266 :
public TensorEvaluator<const TensorStridingOp<Strides, ArgType>, Device> {
267 typedef TensorStridingOp<Strides, ArgType> XprType;
268 typedef TensorEvaluator<const XprType, Device> Base;
269 static constexpr int NumDims = internal::array_size<typename TensorEvaluator<ArgType, Device>::Dimensions>::value;
271 typedef typename XprType::Index Index;
272 typedef typename XprType::Scalar Scalar;
273 typedef typename XprType::CoeffReturnType CoeffReturnType;
274 typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
275 static constexpr int PacketSize = PacketType<CoeffReturnType, Device>::size;
276 static constexpr int Layout = TensorEvaluator<ArgType, Device>::Layout;
281 PacketAccess = Base::PacketAccess,
282 PreferBlockAccess =
false,
287 EIGEN_STRONG_INLINE TensorEvaluator(
const XprType& op,
const Device& device) : Base(op, device) {}
289 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index index)
const {
290 if (this->m_is_identity)
return this->m_impl.coeffRef(index);
291 return this->m_impl.coeffRef(this->srcCoeff(index));
296 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void storeInnerRun(Index base, Index inner_stride,
const PacketReturnType& x,
297 std::false_type)
const {
298 EIGEN_ALIGN_TO_BOUNDARY(internal::unpacket_traits<PacketReturnType>::alignment) Scalar values[PacketSize];
299 internal::pstore<Scalar, PacketReturnType>(values, x);
301 for (
int i = 0; i < PacketSize; ++i) {
302 this->m_impl.coeffRef(base + i * inner_stride) = values[i];
306 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void storeInnerRun(Index base, Index inner_stride,
const PacketReturnType& x,
307 std::true_type)
const {
308 if (inner_stride == 1) {
309 this->m_impl.template writePacket<Unaligned>(base, x);
312 storeInnerRun(base, inner_stride, x, std::false_type());
315 template <
int StoreMode>
316 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
void writePacket(Index index,
const PacketReturnType& x)
const {
317 eigen_assert(index + PacketSize - 1 < this->dimensions().TotalSize());
318 typedef typename Base::ImplHasPacket ImplHasPacket;
319 if (this->m_is_identity) {
320 storeInnerRun(index, 1, x, ImplHasPacket());
324 if (this->packetStaysInInnerRun(index, base)) {
325 storeInnerRun(base, this->m_inputStrides[Base::kInnerDim], x, ImplHasPacket());
331 EIGEN_ALIGN_TO_BOUNDARY(internal::unpacket_traits<PacketReturnType>::alignment) Scalar values[PacketSize];
332 internal::pstore<Scalar, PacketReturnType>(values, x);
334 for (
int i = 0; i < PacketSize; ++i) {
335 this->coeffRef(index + i) = values[i];
The tensor base class.
Definition TensorForwardDeclarations.h:69
Tensor striding class.
Definition TensorStriding.h:44
Namespace containing all symbols from the Eigen library.
The tensor evaluator class.
Definition TensorEvaluator.h:47