|  | // This file is part of Eigen, a lightweight C++ template library | 
|  | // for linear algebra. | 
|  | // | 
|  | // Copyright (C) 2014 Benoit Steiner <benoit.steiner.goog@gmail.com> | 
|  | // | 
|  | // This Source Code Form is subject to the terms of the Mozilla | 
|  | // Public License v. 2.0. If a copy of the MPL was not distributed | 
|  | // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. | 
|  |  | 
|  | #ifndef EIGEN_CXX11_TENSOR_TENSOR_EXPR_H | 
|  | #define EIGEN_CXX11_TENSOR_TENSOR_EXPR_H | 
|  |  | 
|  | namespace Eigen { | 
|  |  | 
|  | /** \class TensorExpr | 
|  | * \ingroup CXX11_Tensor_Module | 
|  | * | 
|  | * \brief Tensor expression classes. | 
|  | * | 
|  | * The TensorCwiseNullaryOp class applies a nullary operators to an expression. | 
|  | * This is typically used to generate constants. | 
|  | * | 
|  | * The TensorCwiseUnaryOp class represents an expression where a unary operator | 
|  | * (e.g. cwiseSqrt) is applied to an expression. | 
|  | * | 
|  | * The TensorCwiseBinaryOp class represents an expression where a binary | 
|  | * operator (e.g. addition) is applied to a lhs and a rhs expression. | 
|  | * | 
|  | */ | 
|  | namespace internal { | 
|  | template<typename NullaryOp, typename XprType> | 
|  | struct traits<TensorCwiseNullaryOp<NullaryOp, XprType> > | 
|  | : traits<XprType> | 
|  | { | 
|  | typedef traits<XprType> XprTraits; | 
|  | typedef typename XprType::Scalar Scalar; | 
|  | typedef typename XprType::Nested XprTypeNested; | 
|  | typedef typename remove_reference<XprTypeNested>::type _XprTypeNested; | 
|  | static const int NumDimensions = XprTraits::NumDimensions; | 
|  | static const int Layout = XprTraits::Layout; | 
|  | typedef typename XprTraits::PointerType PointerType; | 
|  | enum { | 
|  | Flags = 0 | 
|  | }; | 
|  | }; | 
|  |  | 
|  | }  // end namespace internal | 
|  |  | 
|  |  | 
|  |  | 
|  | template<typename NullaryOp, typename XprType> | 
|  | class TensorCwiseNullaryOp : public TensorBase<TensorCwiseNullaryOp<NullaryOp, XprType>, ReadOnlyAccessors> | 
|  | { | 
|  | public: | 
|  | typedef typename Eigen::internal::traits<TensorCwiseNullaryOp>::Scalar Scalar; | 
|  | typedef typename Eigen::NumTraits<Scalar>::Real RealScalar; | 
|  | typedef typename XprType::CoeffReturnType CoeffReturnType; | 
|  | typedef TensorCwiseNullaryOp<NullaryOp, XprType> Nested; | 
|  | typedef typename Eigen::internal::traits<TensorCwiseNullaryOp>::StorageKind StorageKind; | 
|  | typedef typename Eigen::internal::traits<TensorCwiseNullaryOp>::Index Index; | 
|  |  | 
|  | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorCwiseNullaryOp(const XprType& xpr, const NullaryOp& func = NullaryOp()) | 
|  | : m_xpr(xpr), m_functor(func) {} | 
|  |  | 
|  | EIGEN_DEVICE_FUNC | 
|  | const typename internal::remove_all<typename XprType::Nested>::type& | 
|  | nestedExpression() const { return m_xpr; } | 
|  |  | 
|  | EIGEN_DEVICE_FUNC | 
|  | const NullaryOp& functor() const { return m_functor; } | 
|  |  | 
|  | protected: | 
|  | typename XprType::Nested m_xpr; | 
|  | const NullaryOp m_functor; | 
|  | }; | 
|  |  | 
|  |  | 
|  |  | 
|  | namespace internal { | 
|  | template<typename UnaryOp, typename XprType> | 
|  | struct traits<TensorCwiseUnaryOp<UnaryOp, XprType> > | 
|  | : traits<XprType> | 
|  | { | 
|  | // TODO(phli): Add InputScalar, InputPacket.  Check references to | 
|  | // current Scalar/Packet to see if the intent is Input or Output. | 
|  | typedef typename result_of<UnaryOp(typename XprType::Scalar)>::type Scalar; | 
|  | typedef traits<XprType> XprTraits; | 
|  | typedef typename XprType::Nested XprTypeNested; | 
|  | typedef typename remove_reference<XprTypeNested>::type _XprTypeNested; | 
|  | static const int NumDimensions = XprTraits::NumDimensions; | 
|  | static const int Layout = XprTraits::Layout; | 
|  | typedef typename TypeConversion<Scalar, | 
|  | typename XprTraits::PointerType | 
|  | >::type | 
|  | PointerType; | 
|  | }; | 
|  |  | 
|  | template<typename UnaryOp, typename XprType> | 
|  | struct eval<TensorCwiseUnaryOp<UnaryOp, XprType>, Eigen::Dense> | 
|  | { | 
|  | typedef const TensorCwiseUnaryOp<UnaryOp, XprType>& type; | 
|  | }; | 
|  |  | 
|  | template<typename UnaryOp, typename XprType> | 
|  | struct nested<TensorCwiseUnaryOp<UnaryOp, XprType>, 1, typename eval<TensorCwiseUnaryOp<UnaryOp, XprType> >::type> | 
|  | { | 
|  | typedef TensorCwiseUnaryOp<UnaryOp, XprType> type; | 
|  | }; | 
|  |  | 
|  | }  // end namespace internal | 
|  |  | 
|  |  | 
|  |  | 
|  | template<typename UnaryOp, typename XprType> | 
|  | class TensorCwiseUnaryOp : public TensorBase<TensorCwiseUnaryOp<UnaryOp, XprType>, ReadOnlyAccessors> | 
|  | { | 
|  | public: | 
|  | // TODO(phli): Add InputScalar, InputPacket.  Check references to | 
|  | // current Scalar/Packet to see if the intent is Input or Output. | 
|  | typedef typename Eigen::internal::traits<TensorCwiseUnaryOp>::Scalar Scalar; | 
|  | typedef typename Eigen::NumTraits<Scalar>::Real RealScalar; | 
|  | typedef Scalar CoeffReturnType; | 
|  | typedef typename Eigen::internal::nested<TensorCwiseUnaryOp>::type Nested; | 
|  | typedef typename Eigen::internal::traits<TensorCwiseUnaryOp>::StorageKind StorageKind; | 
|  | typedef typename Eigen::internal::traits<TensorCwiseUnaryOp>::Index Index; | 
|  |  | 
|  | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorCwiseUnaryOp(const XprType& xpr, const UnaryOp& func = UnaryOp()) | 
|  | : m_xpr(xpr), m_functor(func) {} | 
|  |  | 
|  | EIGEN_DEVICE_FUNC | 
|  | const UnaryOp& functor() const { return m_functor; } | 
|  |  | 
|  | /** \returns the nested expression */ | 
|  | EIGEN_DEVICE_FUNC | 
|  | const typename internal::remove_all<typename XprType::Nested>::type& | 
|  | nestedExpression() const { return m_xpr; } | 
|  |  | 
|  | protected: | 
|  | typename XprType::Nested m_xpr; | 
|  | const UnaryOp m_functor; | 
|  | }; | 
|  |  | 
|  |  | 
|  | namespace internal { | 
|  | template<typename BinaryOp, typename LhsXprType, typename RhsXprType> | 
|  | struct traits<TensorCwiseBinaryOp<BinaryOp, LhsXprType, RhsXprType> > | 
|  | { | 
|  | // Type promotion to handle the case where the types of the lhs and the rhs | 
|  | // are different. | 
|  | // TODO(phli): Add Lhs/RhsScalar, Lhs/RhsPacket.  Check references to | 
|  | // current Scalar/Packet to see if the intent is Inputs or Output. | 
|  | typedef typename result_of< | 
|  | BinaryOp(typename LhsXprType::Scalar, | 
|  | typename RhsXprType::Scalar)>::type Scalar; | 
|  | typedef traits<LhsXprType> XprTraits; | 
|  | typedef typename promote_storage_type< | 
|  | typename traits<LhsXprType>::StorageKind, | 
|  | typename traits<RhsXprType>::StorageKind>::ret StorageKind; | 
|  | typedef typename promote_index_type< | 
|  | typename traits<LhsXprType>::Index, | 
|  | typename traits<RhsXprType>::Index>::type Index; | 
|  | typedef typename LhsXprType::Nested LhsNested; | 
|  | typedef typename RhsXprType::Nested RhsNested; | 
|  | typedef typename remove_reference<LhsNested>::type _LhsNested; | 
|  | typedef typename remove_reference<RhsNested>::type _RhsNested; | 
|  | static const int NumDimensions = XprTraits::NumDimensions; | 
|  | static const int Layout = XprTraits::Layout; | 
|  | typedef typename TypeConversion<Scalar, | 
|  | typename conditional<Pointer_type_promotion<typename LhsXprType::Scalar, Scalar>::val, | 
|  | typename traits<LhsXprType>::PointerType, | 
|  | typename traits<RhsXprType>::PointerType>::type | 
|  | >::type | 
|  | PointerType; | 
|  | enum { | 
|  | Flags = 0 | 
|  | }; | 
|  | }; | 
|  |  | 
|  | template<typename BinaryOp, typename LhsXprType, typename RhsXprType> | 
|  | struct eval<TensorCwiseBinaryOp<BinaryOp, LhsXprType, RhsXprType>, Eigen::Dense> | 
|  | { | 
|  | typedef const TensorCwiseBinaryOp<BinaryOp, LhsXprType, RhsXprType>& type; | 
|  | }; | 
|  |  | 
|  | template<typename BinaryOp, typename LhsXprType, typename RhsXprType> | 
|  | struct nested<TensorCwiseBinaryOp<BinaryOp, LhsXprType, RhsXprType>, 1, typename eval<TensorCwiseBinaryOp<BinaryOp, LhsXprType, RhsXprType> >::type> | 
|  | { | 
|  | typedef TensorCwiseBinaryOp<BinaryOp, LhsXprType, RhsXprType> type; | 
|  | }; | 
|  |  | 
|  | }  // end namespace internal | 
|  |  | 
|  |  | 
|  |  | 
|  | template<typename BinaryOp, typename LhsXprType, typename RhsXprType> | 
|  | class TensorCwiseBinaryOp : public TensorBase<TensorCwiseBinaryOp<BinaryOp, LhsXprType, RhsXprType>, ReadOnlyAccessors> | 
|  | { | 
|  | public: | 
|  | // TODO(phli): Add Lhs/RhsScalar, Lhs/RhsPacket.  Check references to | 
|  | // current Scalar/Packet to see if the intent is Inputs or Output. | 
|  | typedef typename Eigen::internal::traits<TensorCwiseBinaryOp>::Scalar Scalar; | 
|  | typedef typename Eigen::NumTraits<Scalar>::Real RealScalar; | 
|  | typedef Scalar CoeffReturnType; | 
|  | typedef typename Eigen::internal::nested<TensorCwiseBinaryOp>::type Nested; | 
|  | typedef typename Eigen::internal::traits<TensorCwiseBinaryOp>::StorageKind StorageKind; | 
|  | typedef typename Eigen::internal::traits<TensorCwiseBinaryOp>::Index Index; | 
|  |  | 
|  | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorCwiseBinaryOp(const LhsXprType& lhs, const RhsXprType& rhs, const BinaryOp& func = BinaryOp()) | 
|  | : m_lhs_xpr(lhs), m_rhs_xpr(rhs), m_functor(func) {} | 
|  |  | 
|  | EIGEN_DEVICE_FUNC | 
|  | const BinaryOp& functor() const { return m_functor; } | 
|  |  | 
|  | /** \returns the nested expressions */ | 
|  | EIGEN_DEVICE_FUNC | 
|  | const typename internal::remove_all<typename LhsXprType::Nested>::type& | 
|  | lhsExpression() const { return m_lhs_xpr; } | 
|  |  | 
|  | EIGEN_DEVICE_FUNC | 
|  | const typename internal::remove_all<typename RhsXprType::Nested>::type& | 
|  | rhsExpression() const { return m_rhs_xpr; } | 
|  |  | 
|  | protected: | 
|  | typename LhsXprType::Nested m_lhs_xpr; | 
|  | typename RhsXprType::Nested m_rhs_xpr; | 
|  | const BinaryOp m_functor; | 
|  | }; | 
|  |  | 
|  |  | 
|  | namespace internal { | 
|  | template<typename TernaryOp, typename Arg1XprType, typename Arg2XprType, typename Arg3XprType> | 
|  | struct traits<TensorCwiseTernaryOp<TernaryOp, Arg1XprType, Arg2XprType, Arg3XprType> > | 
|  | { | 
|  | // Type promotion to handle the case where the types of the args are different. | 
|  | typedef typename result_of< | 
|  | TernaryOp(typename Arg1XprType::Scalar, | 
|  | typename Arg2XprType::Scalar, | 
|  | typename Arg3XprType::Scalar)>::type Scalar; | 
|  | typedef traits<Arg1XprType> XprTraits; | 
|  | typedef typename traits<Arg1XprType>::StorageKind StorageKind; | 
|  | typedef typename traits<Arg1XprType>::Index Index; | 
|  | typedef typename Arg1XprType::Nested Arg1Nested; | 
|  | typedef typename Arg2XprType::Nested Arg2Nested; | 
|  | typedef typename Arg3XprType::Nested Arg3Nested; | 
|  | typedef typename remove_reference<Arg1Nested>::type _Arg1Nested; | 
|  | typedef typename remove_reference<Arg2Nested>::type _Arg2Nested; | 
|  | typedef typename remove_reference<Arg3Nested>::type _Arg3Nested; | 
|  | static const int NumDimensions = XprTraits::NumDimensions; | 
|  | static const int Layout = XprTraits::Layout; | 
|  | typedef typename TypeConversion<Scalar, | 
|  | typename conditional<Pointer_type_promotion<typename Arg2XprType::Scalar, Scalar>::val, | 
|  | typename traits<Arg2XprType>::PointerType, | 
|  | typename traits<Arg3XprType>::PointerType>::type | 
|  | >::type | 
|  | PointerType; | 
|  | enum { | 
|  | Flags = 0 | 
|  | }; | 
|  | }; | 
|  |  | 
|  | template<typename TernaryOp, typename Arg1XprType, typename Arg2XprType, typename Arg3XprType> | 
|  | struct eval<TensorCwiseTernaryOp<TernaryOp, Arg1XprType, Arg2XprType, Arg3XprType>, Eigen::Dense> | 
|  | { | 
|  | typedef const TensorCwiseTernaryOp<TernaryOp, Arg1XprType, Arg2XprType, Arg3XprType>& type; | 
|  | }; | 
|  |  | 
|  | template<typename TernaryOp, typename Arg1XprType, typename Arg2XprType, typename Arg3XprType> | 
|  | struct nested<TensorCwiseTernaryOp<TernaryOp, Arg1XprType, Arg2XprType, Arg3XprType>, 1, typename eval<TensorCwiseTernaryOp<TernaryOp, Arg1XprType, Arg2XprType, Arg3XprType> >::type> | 
|  | { | 
|  | typedef TensorCwiseTernaryOp<TernaryOp, Arg1XprType, Arg2XprType, Arg3XprType> type; | 
|  | }; | 
|  |  | 
|  | }  // end namespace internal | 
|  |  | 
|  |  | 
|  |  | 
|  | template<typename TernaryOp, typename Arg1XprType, typename Arg2XprType, typename Arg3XprType> | 
|  | class TensorCwiseTernaryOp : public TensorBase<TensorCwiseTernaryOp<TernaryOp, Arg1XprType, Arg2XprType, Arg3XprType>, ReadOnlyAccessors> | 
|  | { | 
|  | public: | 
|  | typedef typename Eigen::internal::traits<TensorCwiseTernaryOp>::Scalar Scalar; | 
|  | typedef typename Eigen::NumTraits<Scalar>::Real RealScalar; | 
|  | typedef Scalar CoeffReturnType; | 
|  | typedef typename Eigen::internal::nested<TensorCwiseTernaryOp>::type Nested; | 
|  | typedef typename Eigen::internal::traits<TensorCwiseTernaryOp>::StorageKind StorageKind; | 
|  | typedef typename Eigen::internal::traits<TensorCwiseTernaryOp>::Index Index; | 
|  |  | 
|  | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorCwiseTernaryOp(const Arg1XprType& arg1, const Arg2XprType& arg2, const Arg3XprType& arg3, const TernaryOp& func = TernaryOp()) | 
|  | : m_arg1_xpr(arg1), m_arg2_xpr(arg2), m_arg3_xpr(arg3), m_functor(func) {} | 
|  |  | 
|  | EIGEN_DEVICE_FUNC | 
|  | const TernaryOp& functor() const { return m_functor; } | 
|  |  | 
|  | /** \returns the nested expressions */ | 
|  | EIGEN_DEVICE_FUNC | 
|  | const typename internal::remove_all<typename Arg1XprType::Nested>::type& | 
|  | arg1Expression() const { return m_arg1_xpr; } | 
|  |  | 
|  | EIGEN_DEVICE_FUNC | 
|  | const typename internal::remove_all<typename Arg2XprType::Nested>::type& | 
|  | arg2Expression() const { return m_arg2_xpr; } | 
|  |  | 
|  | EIGEN_DEVICE_FUNC | 
|  | const typename internal::remove_all<typename Arg3XprType::Nested>::type& | 
|  | arg3Expression() const { return m_arg3_xpr; } | 
|  |  | 
|  | protected: | 
|  | typename Arg1XprType::Nested m_arg1_xpr; | 
|  | typename Arg2XprType::Nested m_arg2_xpr; | 
|  | typename Arg3XprType::Nested m_arg3_xpr; | 
|  | const TernaryOp m_functor; | 
|  | }; | 
|  |  | 
|  |  | 
|  | namespace internal { | 
|  | template<typename IfXprType, typename ThenXprType, typename ElseXprType> | 
|  | struct traits<TensorSelectOp<IfXprType, ThenXprType, ElseXprType> > | 
|  | : traits<ThenXprType> | 
|  | { | 
|  | typedef typename traits<ThenXprType>::Scalar Scalar; | 
|  | typedef traits<ThenXprType> XprTraits; | 
|  | typedef typename promote_storage_type<typename traits<ThenXprType>::StorageKind, | 
|  | typename traits<ElseXprType>::StorageKind>::ret StorageKind; | 
|  | typedef typename promote_index_type<typename traits<ElseXprType>::Index, | 
|  | typename traits<ThenXprType>::Index>::type Index; | 
|  | typedef typename IfXprType::Nested IfNested; | 
|  | typedef typename ThenXprType::Nested ThenNested; | 
|  | typedef typename ElseXprType::Nested ElseNested; | 
|  | static const int NumDimensions = XprTraits::NumDimensions; | 
|  | static const int Layout = XprTraits::Layout; | 
|  | typedef typename conditional<Pointer_type_promotion<typename ThenXprType::Scalar, Scalar>::val, | 
|  | typename traits<ThenXprType>::PointerType, | 
|  | typename traits<ElseXprType>::PointerType>::type PointerType; | 
|  | }; | 
|  |  | 
|  | template<typename IfXprType, typename ThenXprType, typename ElseXprType> | 
|  | struct eval<TensorSelectOp<IfXprType, ThenXprType, ElseXprType>, Eigen::Dense> | 
|  | { | 
|  | typedef const TensorSelectOp<IfXprType, ThenXprType, ElseXprType>& type; | 
|  | }; | 
|  |  | 
|  | template<typename IfXprType, typename ThenXprType, typename ElseXprType> | 
|  | struct nested<TensorSelectOp<IfXprType, ThenXprType, ElseXprType>, 1, typename eval<TensorSelectOp<IfXprType, ThenXprType, ElseXprType> >::type> | 
|  | { | 
|  | typedef TensorSelectOp<IfXprType, ThenXprType, ElseXprType> type; | 
|  | }; | 
|  |  | 
|  | }  // end namespace internal | 
|  |  | 
|  |  | 
|  | template<typename IfXprType, typename ThenXprType, typename ElseXprType> | 
|  | class TensorSelectOp : public TensorBase<TensorSelectOp<IfXprType, ThenXprType, ElseXprType>, ReadOnlyAccessors> | 
|  | { | 
|  | public: | 
|  | typedef typename Eigen::internal::traits<TensorSelectOp>::Scalar Scalar; | 
|  | typedef typename Eigen::NumTraits<Scalar>::Real RealScalar; | 
|  | typedef typename internal::promote_storage_type<typename ThenXprType::CoeffReturnType, | 
|  | typename ElseXprType::CoeffReturnType>::ret CoeffReturnType; | 
|  | typedef typename Eigen::internal::nested<TensorSelectOp>::type Nested; | 
|  | typedef typename Eigen::internal::traits<TensorSelectOp>::StorageKind StorageKind; | 
|  | typedef typename Eigen::internal::traits<TensorSelectOp>::Index Index; | 
|  |  | 
|  | EIGEN_DEVICE_FUNC | 
|  | TensorSelectOp(const IfXprType& a_condition, | 
|  | const ThenXprType& a_then, | 
|  | const ElseXprType& a_else) | 
|  | : m_condition(a_condition), m_then(a_then), m_else(a_else) | 
|  | { } | 
|  |  | 
|  | EIGEN_DEVICE_FUNC | 
|  | const IfXprType& ifExpression() const { return m_condition; } | 
|  |  | 
|  | EIGEN_DEVICE_FUNC | 
|  | const ThenXprType& thenExpression() const { return m_then; } | 
|  |  | 
|  | EIGEN_DEVICE_FUNC | 
|  | const ElseXprType& elseExpression() const { return m_else; } | 
|  |  | 
|  | protected: | 
|  | typename IfXprType::Nested m_condition; | 
|  | typename ThenXprType::Nested m_then; | 
|  | typename ElseXprType::Nested m_else; | 
|  | }; | 
|  |  | 
|  |  | 
|  | } // end namespace Eigen | 
|  |  | 
|  | #endif // EIGEN_CXX11_TENSOR_TENSOR_EXPR_H |