TensorGenerator.h
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2015 Benoit Steiner <benoit.steiner.goog@gmail.com>
00005 //
00006 // This Source Code Form is subject to the terms of the Mozilla
00007 // Public License v. 2.0. If a copy of the MPL was not distributed
00008 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
00009 
00010 #ifndef EIGEN_CXX11_TENSOR_TENSOR_GENERATOR_H
00011 #define EIGEN_CXX11_TENSOR_TENSOR_GENERATOR_H
00012 
00013 namespace Eigen {
00014 
00022 namespace internal {
00023 template<typename Generator, typename XprType>
00024 struct traits<TensorGeneratorOp<Generator, XprType> > : public traits<XprType>
00025 {
00026   typedef typename XprType::Scalar Scalar;
00027   typedef traits<XprType> XprTraits;
00028   typedef typename XprTraits::StorageKind StorageKind;
00029   typedef typename XprTraits::Index Index;
00030   typedef typename XprType::Nested Nested;
00031   typedef typename remove_reference<Nested>::type _Nested;
00032   static const int NumDimensions = XprTraits::NumDimensions;
00033   static const int Layout = XprTraits::Layout;
00034 };
00035 
00036 template<typename Generator, typename XprType>
00037 struct eval<TensorGeneratorOp<Generator, XprType>, Eigen::Dense>
00038 {
00039   typedef const TensorGeneratorOp<Generator, XprType>& type;
00040 };
00041 
00042 template<typename Generator, typename XprType>
00043 struct nested<TensorGeneratorOp<Generator, XprType>, 1, typename eval<TensorGeneratorOp<Generator, XprType> >::type>
00044 {
00045   typedef TensorGeneratorOp<Generator, XprType> type;
00046 };
00047 
00048 }  // end namespace internal
00049 
00050 
00051 
00052 template<typename Generator, typename XprType>
00053 class TensorGeneratorOp : public TensorBase<TensorGeneratorOp<Generator, XprType>, ReadOnlyAccessors>
00054 {
00055   public:
00056   typedef typename Eigen::internal::traits<TensorGeneratorOp>::Scalar Scalar;
00057   typedef typename Eigen::NumTraits<Scalar>::Real RealScalar;
00058   typedef typename XprType::CoeffReturnType CoeffReturnType;
00059   typedef typename Eigen::internal::nested<TensorGeneratorOp>::type Nested;
00060   typedef typename Eigen::internal::traits<TensorGeneratorOp>::StorageKind StorageKind;
00061   typedef typename Eigen::internal::traits<TensorGeneratorOp>::Index Index;
00062 
00063   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorGeneratorOp(const XprType& expr, const Generator& generator)
00064       : m_xpr(expr), m_generator(generator) {}
00065 
00066     EIGEN_DEVICE_FUNC
00067     const Generator& generator() const { return m_generator; }
00068 
00069     EIGEN_DEVICE_FUNC
00070     const typename internal::remove_all<typename XprType::Nested>::type&
00071     expression() const { return m_xpr; }
00072 
00073   protected:
00074     typename XprType::Nested m_xpr;
00075     const Generator m_generator;
00076 };
00077 
00078 
00079 // Eval as rvalue
00080 template<typename Generator, typename ArgType, typename Device>
00081 struct TensorEvaluator<const TensorGeneratorOp<Generator, ArgType>, Device>
00082 {
00083   typedef TensorGeneratorOp<Generator, ArgType> XprType;
00084   typedef typename XprType::Index Index;
00085   typedef typename TensorEvaluator<ArgType, Device>::Dimensions Dimensions;
00086   static const int NumDims = internal::array_size<Dimensions>::value;
00087   typedef typename XprType::Scalar Scalar;
00088   typedef typename XprType::CoeffReturnType CoeffReturnType;
00089   typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType;
00090   enum {
00091     IsAligned = false,
00092     PacketAccess = (internal::unpacket_traits<PacketReturnType>::size > 1),
00093     BlockAccess = false,
00094     Layout = TensorEvaluator<ArgType, Device>::Layout,
00095     CoordAccess = false,  // to be implemented
00096     RawAccess = false
00097   };
00098 
00099   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorEvaluator(const XprType& op, const Device& device)
00100       : m_generator(op.generator())
00101   {
00102     TensorEvaluator<ArgType, Device> impl(op.expression(), device);
00103     m_dimensions = impl.dimensions();
00104 
00105     if (static_cast<int>(Layout) == static_cast<int>(ColMajor)) {
00106       m_strides[0] = 1;
00107       for (int i = 1; i < NumDims; ++i) {
00108         m_strides[i] = m_strides[i - 1] * m_dimensions[i - 1];
00109       }
00110     } else {
00111       m_strides[NumDims - 1] = 1;
00112       for (int i = NumDims - 2; i >= 0; --i) {
00113         m_strides[i] = m_strides[i + 1] * m_dimensions[i + 1];
00114       }
00115     }
00116   }
00117 
00118   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Dimensions& dimensions() const { return m_dimensions; }
00119 
00120   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool evalSubExprsIfNeeded(Scalar* /*data*/) {
00121     return true;
00122   }
00123   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void cleanup() {
00124   }
00125 
00126   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff(Index index) const
00127   {
00128     array<Index, NumDims> coords;
00129     extract_coordinates(index, coords);
00130     return m_generator(coords);
00131   }
00132 
00133   template<int LoadMode>
00134   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE PacketReturnType packet(Index index) const
00135   {
00136     const int packetSize = internal::unpacket_traits<PacketReturnType>::size;
00137     EIGEN_STATIC_ASSERT((packetSize > 1), YOU_MADE_A_PROGRAMMING_MISTAKE)
00138     eigen_assert(index+packetSize-1 < dimensions().TotalSize());
00139 
00140     EIGEN_ALIGN_MAX typename internal::remove_const<CoeffReturnType>::type values[packetSize];
00141     for (int i = 0; i < packetSize; ++i) {
00142       values[i] = coeff(index+i);
00143     }
00144     PacketReturnType rslt = internal::pload<PacketReturnType>(values);
00145     return rslt;
00146   }
00147 
00148   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorOpCost
00149   costPerCoeff(bool) const {
00150     // TODO(rmlarsen): This is just a placeholder. Define interface to make
00151     // generators return their cost.
00152     return TensorOpCost(0, 0, TensorOpCost::AddCost<Scalar>() +
00153                                   TensorOpCost::MulCost<Scalar>());
00154   }
00155 
00156   EIGEN_DEVICE_FUNC Scalar* data() const { return NULL; }
00157 
00158  protected:
00159   EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
00160   void extract_coordinates(Index index, array<Index, NumDims>& coords) const {
00161     if (static_cast<int>(Layout) == static_cast<int>(ColMajor)) {
00162       for (int i = NumDims - 1; i > 0; --i) {
00163         const Index idx = index / m_strides[i];
00164         index -= idx * m_strides[i];
00165         coords[i] = idx;
00166       }
00167       coords[0] = index;
00168     } else {
00169       for (int i = 0; i < NumDims - 1; ++i) {
00170         const Index idx = index / m_strides[i];
00171         index -= idx * m_strides[i];
00172         coords[i] = idx;
00173       }
00174       coords[NumDims-1] = index;
00175     }
00176   }
00177 
00178   Dimensions m_dimensions;
00179   array<Index, NumDims> m_strides;
00180   Generator m_generator;
00181 };
00182 
00183 } // end namespace Eigen
00184 
00185 #endif // EIGEN_CXX11_TENSOR_TENSOR_GENERATOR_H
 All Classes Functions Variables Typedefs Enumerator