Back to home page

EIC code displayed by LXR

 
 

    


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 // This file is part of Eigen, a lightweight C++ template library
0002 // for linear algebra.
0003 //
0004 // Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com>
0005 //
0006 // This Source Code Form is subject to the terms of the Mozilla
0007 // Public License v. 2.0. If a copy of the MPL was not distributed
0008 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
0009 
0010 #ifndef EIGEN_CXX11_TENSOR_TENSOR_STRIDING_H
0011 #define EIGEN_CXX11_TENSOR_TENSOR_STRIDING_H
0012 
0013 namespace Eigen {
0014 
0015 /** \class TensorStriding
0016   * \ingroup CXX11_Tensor_Module
0017   *
0018   * \brief Tensor striding class.
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 }  // end namespace internal
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 // Eval as rvalue
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 = /*TensorEvaluator<ArgType, Device>::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,  // to be implemented
0105     RawAccess = false
0106   };
0107 
0108   //===- Tensor block evaluation strategy (see TensorBlock.h) -------------===//
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 {  // RowMajor
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/*data*/) {
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 {  // RowMajor
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;  // packet() computes two indices
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         // Computation is not vectorized per se, but it is done once per packet.
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   // binding placeholder accessors to a command group handler for SYCL
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 {  // RowMajor
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 // Eval as lvalue
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   //  typedef typename XprType::Index Index;
0268   static const int NumDims = internal::array_size<typename TensorEvaluator<ArgType, Device>::Dimensions>::value;
0269   //  typedef DSizes<Index, NumDims> Dimensions;
0270 
0271   enum {
0272     IsAligned = /*TensorEvaluator<ArgType, Device>::IsAligned*/false,
0273     PacketAccess = TensorEvaluator<ArgType, Device>::PacketAccess,
0274     PreferBlockAccess = false,
0275     Layout = TensorEvaluator<ArgType, Device>::Layout,
0276     CoordAccess = false,  // to be implemented
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 {  // RowMajor
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 } // end namespace Eigen
0345 
0346 #endif // EIGEN_CXX11_TENSOR_TENSOR_STRIDING_H