![]() |
Eigen-unsupported
3.3.3
|
00001 // This file is part of Eigen, a lightweight C++ template library 00002 // for linear algebra. 00003 // 00004 // Copyright (C) 2014 Navdeep Jaitly <ndjaitly@google.com> 00005 // Benoit Steiner <benoit.steiner.goog@gmail.com> 00006 // 00007 // This Source Code Form is subject to the terms of the Mozilla 00008 // Public License v. 2.0. If a copy of the MPL was not distributed 00009 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 00010 00011 #ifndef EIGEN_CXX11_TENSOR_TENSOR_REVERSE_H 00012 #define EIGEN_CXX11_TENSOR_TENSOR_REVERSE_H 00013 namespace Eigen { 00014 00021 namespace internal { 00022 template<typename ReverseDimensions, typename XprType> 00023 struct traits<TensorReverseOp<ReverseDimensions, 00024 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 ReverseDimensions, typename XprType> 00037 struct eval<TensorReverseOp<ReverseDimensions, XprType>, Eigen::Dense> 00038 { 00039 typedef const TensorReverseOp<ReverseDimensions, XprType>& type; 00040 }; 00041 00042 template<typename ReverseDimensions, typename XprType> 00043 struct nested<TensorReverseOp<ReverseDimensions, XprType>, 1, 00044 typename eval<TensorReverseOp<ReverseDimensions, XprType> >::type> 00045 { 00046 typedef TensorReverseOp<ReverseDimensions, XprType> type; 00047 }; 00048 00049 } // end namespace internal 00050 00051 template<typename ReverseDimensions, typename XprType> 00052 class TensorReverseOp : public TensorBase<TensorReverseOp<ReverseDimensions, 00053 XprType>, WriteAccessors> 00054 { 00055 public: 00056 typedef typename Eigen::internal::traits<TensorReverseOp>::Scalar Scalar; 00057 typedef typename Eigen::NumTraits<Scalar>::Real RealScalar; 00058 typedef typename XprType::CoeffReturnType CoeffReturnType; 00059 typedef typename Eigen::internal::nested<TensorReverseOp>::type Nested; 00060 typedef typename Eigen::internal::traits<TensorReverseOp>::StorageKind 00061 StorageKind; 00062 typedef typename Eigen::internal::traits<TensorReverseOp>::Index Index; 00063 00064 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorReverseOp( 00065 const XprType& expr, const ReverseDimensions& reverse_dims) 00066 : m_xpr(expr), m_reverse_dims(reverse_dims) { } 00067 00068 EIGEN_DEVICE_FUNC 00069 const ReverseDimensions& reverse() const { return m_reverse_dims; } 00070 00071 EIGEN_DEVICE_FUNC 00072 const typename internal::remove_all<typename XprType::Nested>::type& 00073 expression() const { return m_xpr; } 00074 00075 EIGEN_DEVICE_FUNC 00076 EIGEN_STRONG_INLINE TensorReverseOp& operator = (const TensorReverseOp& other) 00077 { 00078 typedef TensorAssignOp<TensorReverseOp, const TensorReverseOp> Assign; 00079 Assign assign(*this, other); 00080 internal::TensorExecutor<const Assign, DefaultDevice>::run(assign, DefaultDevice()); 00081 return *this; 00082 } 00083 00084 template<typename OtherDerived> 00085 EIGEN_DEVICE_FUNC 00086 EIGEN_STRONG_INLINE TensorReverseOp& operator = (const OtherDerived& other) 00087 { 00088 typedef TensorAssignOp<TensorReverseOp, const OtherDerived> Assign; 00089 Assign assign(*this, other); 00090 internal::TensorExecutor<const Assign, DefaultDevice>::run(assign, DefaultDevice()); 00091 return *this; 00092 } 00093 00094 protected: 00095 typename XprType::Nested m_xpr; 00096 const ReverseDimensions m_reverse_dims; 00097 }; 00098 00099 // Eval as rvalue 00100 template<typename ReverseDimensions, typename ArgType, typename Device> 00101 struct TensorEvaluator<const TensorReverseOp<ReverseDimensions, ArgType>, Device> 00102 { 00103 typedef TensorReverseOp<ReverseDimensions, ArgType> XprType; 00104 typedef typename XprType::Index Index; 00105 static const int NumDims = internal::array_size<ReverseDimensions>::value; 00106 typedef DSizes<Index, NumDims> Dimensions; 00107 typedef typename XprType::Scalar Scalar; 00108 typedef typename XprType::CoeffReturnType CoeffReturnType; 00109 typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType; 00110 static const int PacketSize = internal::unpacket_traits<PacketReturnType>::size; 00111 00112 enum { 00113 IsAligned = false, 00114 PacketAccess = TensorEvaluator<ArgType, Device>::PacketAccess, 00115 Layout = TensorEvaluator<ArgType, Device>::Layout, 00116 CoordAccess = false, // to be implemented 00117 RawAccess = false 00118 }; 00119 00120 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorEvaluator(const XprType& op, 00121 const Device& device) 00122 : m_impl(op.expression(), device), m_reverse(op.reverse()) 00123 { 00124 // Reversing a scalar isn't supported yet. It would be a no-op anyway. 00125 EIGEN_STATIC_ASSERT((NumDims > 0), YOU_MADE_A_PROGRAMMING_MISTAKE); 00126 00127 // Compute strides 00128 m_dimensions = m_impl.dimensions(); 00129 if (static_cast<int>(Layout) == static_cast<int>(ColMajor)) { 00130 m_strides[0] = 1; 00131 for (int i = 1; i < NumDims; ++i) { 00132 m_strides[i] = m_strides[i-1] * m_dimensions[i-1]; 00133 } 00134 } else { 00135 m_strides[NumDims-1] = 1; 00136 for (int i = NumDims - 2; i >= 0; --i) { 00137 m_strides[i] = m_strides[i+1] * m_dimensions[i+1]; 00138 } 00139 } 00140 } 00141 00142 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE 00143 const Dimensions& dimensions() const { return m_dimensions; } 00144 00145 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool evalSubExprsIfNeeded(Scalar*) { 00146 m_impl.evalSubExprsIfNeeded(NULL); 00147 return true; 00148 } 00149 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void cleanup() { 00150 m_impl.cleanup(); 00151 } 00152 00153 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index reverseIndex( 00154 Index index) const { 00155 eigen_assert(index < dimensions().TotalSize()); 00156 Index inputIndex = 0; 00157 if (static_cast<int>(Layout) == static_cast<int>(ColMajor)) { 00158 for (int i = NumDims - 1; i > 0; --i) { 00159 Index idx = index / m_strides[i]; 00160 index -= idx * m_strides[i]; 00161 if (m_reverse[i]) { 00162 idx = m_dimensions[i] - idx - 1; 00163 } 00164 inputIndex += idx * m_strides[i] ; 00165 } 00166 if (m_reverse[0]) { 00167 inputIndex += (m_dimensions[0] - index - 1); 00168 } else { 00169 inputIndex += index; 00170 } 00171 } else { 00172 for (int i = 0; i < NumDims - 1; ++i) { 00173 Index idx = index / m_strides[i]; 00174 index -= idx * m_strides[i]; 00175 if (m_reverse[i]) { 00176 idx = m_dimensions[i] - idx - 1; 00177 } 00178 inputIndex += idx * m_strides[i] ; 00179 } 00180 if (m_reverse[NumDims-1]) { 00181 inputIndex += (m_dimensions[NumDims-1] - index - 1); 00182 } else { 00183 inputIndex += index; 00184 } 00185 } 00186 return inputIndex; 00187 } 00188 00189 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE CoeffReturnType coeff( 00190 Index index) const { 00191 return m_impl.coeff(reverseIndex(index)); 00192 } 00193 00194 template<int LoadMode> 00195 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE 00196 PacketReturnType packet(Index index) const 00197 { 00198 EIGEN_STATIC_ASSERT((PacketSize > 1), YOU_MADE_A_PROGRAMMING_MISTAKE) 00199 eigen_assert(index+PacketSize-1 < dimensions().TotalSize()); 00200 00201 // TODO(ndjaitly): write a better packing routine that uses 00202 // local structure. 00203 EIGEN_ALIGN_MAX typename internal::remove_const<CoeffReturnType>::type 00204 values[PacketSize]; 00205 for (int i = 0; i < PacketSize; ++i) { 00206 values[i] = coeff(index+i); 00207 } 00208 PacketReturnType rslt = internal::pload<PacketReturnType>(values); 00209 return rslt; 00210 } 00211 00212 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorOpCost costPerCoeff(bool vectorized) const { 00213 double compute_cost = NumDims * (2 * TensorOpCost::AddCost<Index>() + 00214 2 * TensorOpCost::MulCost<Index>() + 00215 TensorOpCost::DivCost<Index>()); 00216 for (int i = 0; i < NumDims; ++i) { 00217 if (m_reverse[i]) { 00218 compute_cost += 2 * TensorOpCost::AddCost<Index>(); 00219 } 00220 } 00221 return m_impl.costPerCoeff(vectorized) + 00222 TensorOpCost(0, 0, compute_cost, false /* vectorized */, PacketSize); 00223 } 00224 00225 EIGEN_DEVICE_FUNC Scalar* data() const { return NULL; } 00226 00227 protected: 00228 Dimensions m_dimensions; 00229 array<Index, NumDims> m_strides; 00230 TensorEvaluator<ArgType, Device> m_impl; 00231 ReverseDimensions m_reverse; 00232 }; 00233 00234 // Eval as lvalue 00235 00236 template <typename ReverseDimensions, typename ArgType, typename Device> 00237 struct TensorEvaluator<TensorReverseOp<ReverseDimensions, ArgType>, Device> 00238 : public TensorEvaluator<const TensorReverseOp<ReverseDimensions, ArgType>, 00239 Device> { 00240 typedef TensorEvaluator<const TensorReverseOp<ReverseDimensions, ArgType>, 00241 Device> Base; 00242 typedef TensorReverseOp<ReverseDimensions, ArgType> XprType; 00243 typedef typename XprType::Index Index; 00244 static const int NumDims = internal::array_size<ReverseDimensions>::value; 00245 typedef DSizes<Index, NumDims> Dimensions; 00246 00247 enum { 00248 IsAligned = false, 00249 PacketAccess = TensorEvaluator<ArgType, Device>::PacketAccess, 00250 Layout = TensorEvaluator<ArgType, Device>::Layout, 00251 CoordAccess = false, // to be implemented 00252 RawAccess = false 00253 }; 00254 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorEvaluator(const XprType& op, 00255 const Device& device) 00256 : Base(op, device) {} 00257 00258 typedef typename XprType::Scalar Scalar; 00259 typedef typename XprType::CoeffReturnType CoeffReturnType; 00260 typedef typename PacketType<CoeffReturnType, Device>::type PacketReturnType; 00261 static const int PacketSize = internal::unpacket_traits<PacketReturnType>::size; 00262 00263 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE 00264 const Dimensions& dimensions() const { return this->m_dimensions; } 00265 00266 EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Scalar& coeffRef(Index index) { 00267 return this->m_impl.coeffRef(this->reverseIndex(index)); 00268 } 00269 00270 template <int StoreMode> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE 00271 void writePacket(Index index, const PacketReturnType& x) { 00272 EIGEN_STATIC_ASSERT((PacketSize > 1), YOU_MADE_A_PROGRAMMING_MISTAKE) 00273 eigen_assert(index+PacketSize-1 < dimensions().TotalSize()); 00274 00275 // This code is pilfered from TensorMorphing.h 00276 EIGEN_ALIGN_MAX CoeffReturnType values[PacketSize]; 00277 internal::pstore<CoeffReturnType, PacketReturnType>(values, x); 00278 for (int i = 0; i < PacketSize; ++i) { 00279 this->coeffRef(index+i) = values[i]; 00280 } 00281 } 00282 00283 }; 00284 00285 00286 } // end namespace Eigen 00287 00288 #endif // EIGEN_CXX11_TENSOR_TENSOR_REVERSE_H