Warning, file /include/eigen3/unsupported/Eigen/CXX11/src/Tensor/TensorStriding.h was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef EIGEN_CXX11_TENSOR_TENSOR_STRIDING_H
0011 #define EIGEN_CXX11_TENSOR_TENSOR_STRIDING_H
0012
0013 namespace Eigen {
0014
0015
0016
0017
0018
0019
0020
0021
0022 namespace internal {
0023 template<typename Strides, typename XprType>
0024 struct traits<TensorStridingOp<Strides, XprType> > : public traits<XprType>
0025 {
0026 typedef typename XprType::Scalar Scalar;
0027 typedef traits<XprType> XprTraits;
0028 typedef typename XprTraits::StorageKind StorageKind;
0029 typedef typename XprTraits::Index Index;
0030 typedef typename XprType::Nested Nested;
0031 typedef typename remove_reference<Nested>::type _Nested;
0032 static const int NumDimensions = XprTraits::NumDimensions;
0033 static const int Layout = XprTraits::Layout;
0034 typedef typename XprTraits::PointerType PointerType;
0035 };
0036
0037 template<typename Strides, typename XprType>
0038 struct eval<TensorStridingOp<Strides, XprType>, Eigen::Dense>
0039 {
0040 typedef const TensorStridingOp<Strides, XprType>EIGEN_DEVICE_REF type;
0041 };
0042
0043 template<typename Strides, typename XprType>
0044 struct nested<TensorStridingOp<Strides, XprType>, 1, typename eval<TensorStridingOp<Strides, XprType> >::type>
0045 {
0046 typedef TensorStridingOp<Strides, XprType> type;
0047 };
0048
0049 }
0050
0051
0052
0053 template<typename Strides, typename XprType>
0054 class TensorStridingOp : public TensorBase<TensorStridingOp<Strides, XprType> >
0055 {
0056 public:
0057 typedef TensorBase<TensorStridingOp<Strides, XprType> > Base;
0058 typedef typename Eigen::internal::traits<TensorStridingOp>::Scalar Scalar;
0059 typedef typename Eigen::NumTraits<Scalar>::Real RealScalar;
0060 typedef typename XprType::CoeffReturnType CoeffReturnType;
0061 typedef typename Eigen::internal::nested<TensorStridingOp>::type Nested;
0062 typedef typename Eigen::internal::traits<TensorStridingOp>::StorageKind StorageKind;
0063 typedef typename Eigen::internal::traits<TensorStridingOp>::Index Index;
0064
0065 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorStridingOp(const XprType& expr, const Strides& dims)
0066 : m_xpr(expr), m_dims(dims) {}
0067
0068 EIGEN_DEVICE_FUNC
0069 const Strides& strides() const { return m_dims; }
0070
0071 EIGEN_DEVICE_FUNC
0072 const typename internal::remove_all<typename XprType::Nested>::type&
0073 expression() const { return m_xpr; }
0074
0075 EIGEN_TENSOR_INHERIT_ASSIGNMENT_OPERATORS(TensorStridingOp)
0076
0077 protected:
0078 typename XprType::Nested m_xpr;
0079 const Strides m_dims;
0080 };
0081
0082
0083
0084 template<typename Strides, typename ArgType, typename Device>
0085 struct TensorEvaluator<const TensorStridingOp<Strides, ArgType>, Device>
0086 {
0087 typedef TensorStridingOp<Strides, ArgType> XprType;
0088 typedef typename XprType::Index Index;
0089 static const int NumDims = internal::array_size<typename TensorEvaluator<ArgType, Device>::Dimensions>::value;
0090 typedef DSizes<Index, NumDims> Dimensions;
0091 typedef typename XprType::Scalar Scalar;
0092 typedef typename XprType::CoeffReturnType CoeffReturnType;
0093 typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
0094 static const int PacketSize = PacketType<CoeffReturnType, Device>::size;
0095 typedef StorageMemory<CoeffReturnType, Device> Storage;
0096 typedef typename Storage::Type EvaluatorPointerType;
0097
0098 enum {
0099 IsAligned = false,
0100 PacketAccess = TensorEvaluator<ArgType, Device>::PacketAccess,
0101 BlockAccess = false,
0102 PreferBlockAccess = TensorEvaluator<ArgType, Device>::PreferBlockAccess,
0103 Layout = TensorEvaluator<ArgType, Device>::Layout,
0104 CoordAccess = false,
0105 RawAccess = false
0106 };
0107
0108
0109 typedef internal::TensorBlockNotImplemented TensorBlock;
0110
0111
0112 EIGEN_STRONG_INLINE TensorEvaluator(const XprType& op, const Device& device)
0113 : m_impl(op.expression(), device)
0114 {
0115 m_dimensions = m_impl.dimensions();
0116 for (int i = 0; i < NumDims; ++i) {
0117 m_dimensions[i] =Eigen::numext::ceil(static_cast<float>(m_dimensions[i]) / op.strides()[i]);
0118 }
0119
0120 const typename TensorEvaluator<ArgType, Device>::Dimensions& input_dims = m_impl.dimensions();
0121 if (static_cast<int>(Layout) == static_cast<int>(ColMajor)) {
0122 m_outputStrides[0] = 1;
0123 m_inputStrides[0] = 1;
0124 for (int i = 1; i < NumDims; ++i) {
0125 m_outputStrides[i] = m_outputStrides[i-1] * m_dimensions[i-1];
0126 m_inputStrides[i] = m_inputStrides[i-1] * input_dims[i-1];
0127 m_inputStrides[i-1] *= op.strides()[i-1];
0128 }
0129 m_inputStrides[NumDims-1] *= op.strides()[NumDims-1];
0130 } else {
0131 m_outputStrides[NumDims-1] = 1;
0132 m_inputStrides[NumDims-1] = 1;
0133 for (int i = NumDims - 2; i >= 0; --i) {
0134 m_outputStrides[i] = m_outputStrides[i+1] * m_dimensions[i+1];
0135 m_inputStrides[i] = m_inputStrides[i+1] * input_dims[i+1];
0136 m_inputStrides[i+1] *= op.strides()[i+1];
0137 }
0138 m_inputStrides[0] *= op.strides()[0];
0139 }
0140 }
0141
0142
0143 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Dimensions& dimensions() const { return m_dimensions; }
0144
0145 EIGEN_STRONG_INLINE bool evalSubExprsIfNeeded(EvaluatorPointerType) {
0146 m_impl.evalSubExprsIfNeeded(NULL);
0147 return true;
0148 }
0149 EIGEN_STRONG_INLINE void cleanup() {
0150 m_impl.cleanup();
0151 }
0152
0153 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const
0154 {
0155 return m_impl.coeff(srcCoeff(index));
0156 }
0157
0158 template<int LoadMode>
0159 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packet(Index index) const
0160 {
0161 EIGEN_STATIC_ASSERT((PacketSize > 1), YOU_MADE_A_PROGRAMMING_MISTAKE)
0162 eigen_assert(index+PacketSize-1 < dimensions().TotalSize());
0163
0164 Index inputIndices[] = {0, 0};
0165 Index indices[] = {index, index + PacketSize - 1};
0166 if (static_cast<int>(Layout) == static_cast<int>(ColMajor)) {
0167 EIGEN_UNROLL_LOOP
0168 for (int i = NumDims - 1; i > 0; --i) {
0169 const Index idx0 = indices[0] / m_outputStrides[i];
0170 const Index idx1 = indices[1] / m_outputStrides[i];
0171 inputIndices[0] += idx0 * m_inputStrides[i];
0172 inputIndices[1] += idx1 * m_inputStrides[i];
0173 indices[0] -= idx0 * m_outputStrides[i];
0174 indices[1] -= idx1 * m_outputStrides[i];
0175 }
0176 inputIndices[0] += indices[0] * m_inputStrides[0];
0177 inputIndices[1] += indices[1] * m_inputStrides[0];
0178 } else {
0179 EIGEN_UNROLL_LOOP
0180 for (int i = 0; i < NumDims - 1; ++i) {
0181 const Index idx0 = indices[0] / m_outputStrides[i];
0182 const Index idx1 = indices[1] / m_outputStrides[i];
0183 inputIndices[0] += idx0 * m_inputStrides[i];
0184 inputIndices[1] += idx1 * m_inputStrides[i];
0185 indices[0] -= idx0 * m_outputStrides[i];
0186 indices[1] -= idx1 * m_outputStrides[i];
0187 }
0188 inputIndices[0] += indices[0] * m_inputStrides[NumDims-1];
0189 inputIndices[1] += indices[1] * m_inputStrides[NumDims-1];
0190 }
0191 if (inputIndices[1] - inputIndices[0] == PacketSize - 1) {
0192 PacketReturnType rslt = m_impl.template packet<Unaligned>(inputIndices[0]);
0193 return rslt;
0194 }
0195 else {
0196 EIGEN_ALIGN_MAX typename internal::remove_const<CoeffReturnType>::type values[PacketSize];
0197 values[0] = m_impl.coeff(inputIndices[0]);
0198 values[PacketSize-1] = m_impl.coeff(inputIndices[1]);
0199 EIGEN_UNROLL_LOOP
0200 for (int i = 1; i < PacketSize-1; ++i) {
0201 values[i] = coeff(index+i);
0202 }
0203 PacketReturnType rslt = internal::pload<PacketReturnType>(values);
0204 return rslt;
0205 }
0206 }
0207
0208 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorOpCost costPerCoeff(bool vectorized) const {
0209 double compute_cost = (NumDims - 1) * (TensorOpCost::AddCost<Index>() +
0210 TensorOpCost::MulCost<Index>() +
0211 TensorOpCost::DivCost<Index>()) +
0212 TensorOpCost::MulCost<Index>();
0213 if (vectorized) {
0214 compute_cost *= 2;
0215 }
0216 const int innerDim = (static_cast<int>(Layout) == static_cast<int>(ColMajor)) ? 0 : (NumDims - 1);
0217 return m_impl.costPerCoeff(vectorized && m_inputStrides[innerDim] == 1) +
0218
0219 TensorOpCost(0, 0, compute_cost, vectorized, PacketSize);
0220 }
0221
0222 EIGEN_DEVICE_FUNC typename Storage::Type data() const { return NULL; }
0223
0224 #ifdef EIGEN_USE_SYCL
0225
0226 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void bind(cl::sycl::handler &cgh) const {
0227 m_impl.bind(cgh);
0228 }
0229 #endif
0230 protected:
0231 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index srcCoeff(Index index) const
0232 {
0233 Index inputIndex = 0;
0234 if (static_cast<int>(Layout) == static_cast<int>(ColMajor)) {
0235 EIGEN_UNROLL_LOOP
0236 for (int i = NumDims - 1; i > 0; --i) {
0237 const Index idx = index / m_outputStrides[i];
0238 inputIndex += idx * m_inputStrides[i];
0239 index -= idx * m_outputStrides[i];
0240 }
0241 inputIndex += index * m_inputStrides[0];
0242 } else {
0243 EIGEN_UNROLL_LOOP
0244 for (int i = 0; i < NumDims - 1; ++i) {
0245 const Index idx = index / m_outputStrides[i];
0246 inputIndex += idx * m_inputStrides[i];
0247 index -= idx * m_outputStrides[i];
0248 }
0249 inputIndex += index * m_inputStrides[NumDims-1];
0250 }
0251 return inputIndex;
0252 }
0253
0254 Dimensions m_dimensions;
0255 array<Index, NumDims> m_outputStrides;
0256 array<Index, NumDims> m_inputStrides;
0257 TensorEvaluator<ArgType, Device> m_impl;
0258 };
0259
0260
0261 template<typename Strides, typename ArgType, typename Device>
0262 struct TensorEvaluator<TensorStridingOp<Strides, ArgType>, Device>
0263 : public TensorEvaluator<const TensorStridingOp<Strides, ArgType>, Device>
0264 {
0265 typedef TensorStridingOp<Strides, ArgType> XprType;
0266 typedef TensorEvaluator<const XprType, Device> Base;
0267
0268 static const int NumDims = internal::array_size<typename TensorEvaluator<ArgType, Device>::Dimensions>::value;
0269
0270
0271 enum {
0272 IsAligned = false,
0273 PacketAccess = TensorEvaluator<ArgType, Device>::PacketAccess,
0274 PreferBlockAccess = false,
0275 Layout = TensorEvaluator<ArgType, Device>::Layout,
0276 CoordAccess = false,
0277 RawAccess = false
0278 };
0279
0280 EIGEN_STRONG_INLINE TensorEvaluator(const XprType& op, const Device& device)
0281 : Base(op, device) { }
0282
0283 typedef typename XprType::Index Index;
0284 typedef typename XprType::Scalar Scalar;
0285 typedef typename XprType::CoeffReturnType CoeffReturnType;
0286 typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
0287 static const int PacketSize = PacketType<CoeffReturnType, Device>::size;
0288
0289 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index index)
0290 {
0291 return this->m_impl.coeffRef(this->srcCoeff(index));
0292 }
0293
0294 template <int StoreMode> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
0295 void writePacket(Index index, const PacketReturnType& x)
0296 {
0297 EIGEN_STATIC_ASSERT((PacketSize > 1), YOU_MADE_A_PROGRAMMING_MISTAKE)
0298 eigen_assert(index+PacketSize-1 < this->dimensions().TotalSize());
0299
0300 Index inputIndices[] = {0, 0};
0301 Index indices[] = {index, index + PacketSize - 1};
0302 if (static_cast<int>(Layout) == static_cast<int>(ColMajor)) {
0303 EIGEN_UNROLL_LOOP
0304 for (int i = NumDims - 1; i > 0; --i) {
0305 const Index idx0 = indices[0] / this->m_outputStrides[i];
0306 const Index idx1 = indices[1] / this->m_outputStrides[i];
0307 inputIndices[0] += idx0 * this->m_inputStrides[i];
0308 inputIndices[1] += idx1 * this->m_inputStrides[i];
0309 indices[0] -= idx0 * this->m_outputStrides[i];
0310 indices[1] -= idx1 * this->m_outputStrides[i];
0311 }
0312 inputIndices[0] += indices[0] * this->m_inputStrides[0];
0313 inputIndices[1] += indices[1] * this->m_inputStrides[0];
0314 } else {
0315 EIGEN_UNROLL_LOOP
0316 for (int i = 0; i < NumDims - 1; ++i) {
0317 const Index idx0 = indices[0] / this->m_outputStrides[i];
0318 const Index idx1 = indices[1] / this->m_outputStrides[i];
0319 inputIndices[0] += idx0 * this->m_inputStrides[i];
0320 inputIndices[1] += idx1 * this->m_inputStrides[i];
0321 indices[0] -= idx0 * this->m_outputStrides[i];
0322 indices[1] -= idx1 * this->m_outputStrides[i];
0323 }
0324 inputIndices[0] += indices[0] * this->m_inputStrides[NumDims-1];
0325 inputIndices[1] += indices[1] * this->m_inputStrides[NumDims-1];
0326 }
0327 if (inputIndices[1] - inputIndices[0] == PacketSize - 1) {
0328 this->m_impl.template writePacket<Unaligned>(inputIndices[0], x);
0329 }
0330 else {
0331 EIGEN_ALIGN_MAX Scalar values[PacketSize];
0332 internal::pstore<Scalar, PacketReturnType>(values, x);
0333 this->m_impl.coeffRef(inputIndices[0]) = values[0];
0334 this->m_impl.coeffRef(inputIndices[1]) = values[PacketSize-1];
0335 EIGEN_UNROLL_LOOP
0336 for (int i = 1; i < PacketSize-1; ++i) {
0337 this->coeffRef(index+i) = values[i];
0338 }
0339 }
0340 }
0341 };
0342
0343
0344 }
0345
0346 #endif