/*! * Copyright (c) 2014 by Contributors * \file expression.h * \brief definitions of abstract expressions and expressions template * \author Tianqi Chen, Bing Xu */ #ifndef MSHADOW_EXPRESSION_H_ #define MSHADOW_EXPRESSION_H_ #include "./base.h" namespace mshadow { /*! * \brief namespace for abstract expressions and expressions template, * have no dependency on tensor.h, * These data structure takes no charge in computations, * they are only used to define operations and represent expression in a symbolic way */ namespace expr { /*! \brief type of expressions */ namespace type { // type expression type are defined as bitmask // subtype relationshop kRValue < kMapper < kPull < kComplex /*! * \brief this expression directly correspnds to a data class, * can be used to assign data */ const int kRValue = 0; /*! * \brief expression contains element-wise tensor operations, * map a expression to same shape */ const int kMapper = 1; /*! * \brief expression that can be chained with other expressiones * Usually it have function Eval(i,j) defined, which pulls the result (i, j) from input * expression and output the result at certain position. */ const int kChainer = 3; /*! \brief othercase: e.g dot product */ const int kComplex = 7; } // namespace type /*! * \brief expression engine that actually interprets these expressions * this is a function template that needed to be implemented for specific expressions * \tparam Saver the save method * \tparam RValue the type of RValue to be saved * \sa namespace sv */ template struct ExpEngine; /*! \brief defines how expression exp can be evaluated and stored into dst */ // template // inline static void Eval(RValue *dst, const EType &exp); /*! * \brief base class for expression * \tparam SubType inheritated class must put their type into this parameter * \tparam DType the data type of each element in the expression * \tparam exp_type expression type, see namespace type */ template struct Exp { public: /*! \return subtype instance of current class */ inline const SubType& self(void) const { return *static_cast(this); } /*! \return reference of subtype instance of current class */ inline SubType* ptrself(void) { return static_cast(this); } }; /*! * \brief scalar expression * \tparam DType the data type of the scalar */ template struct ScalarExp: public Exp, DType, type::kMapper> { /*! \brief scalar value */ DType scalar_; /*! \brief implicit constructor, MUST NOT BE explicit */ ScalarExp(DType scalar) : scalar_(scalar) {} // NOLINT(*) }; /*! \brief create an scalar expression */ template inline ScalarExp scalar(DType s) { return ScalarExp(s); } /*! * \brief typecast expression, cast the type of elements * \tparam DstDType the target type we want to cast into * \tparam SrcDType the target type we want to cast from * \tparam EType the type of the source expression * \tparam etype the type of expression after cast */ template struct TypecastExp: public Exp, DstDType, etype> { /*! \brief expression to be typecasted */ const EType &exp; /*! \brief constructor */ explicit TypecastExp(const EType &e) : exp(e) {} }; /*! \brief create an scalar expression */ template inline TypecastExp tcast(const Exp &exp) { return TypecastExp(exp.self()); } /*! \brief represent a transpose expression of a container */ template struct TransposeExp: public Exp, DType, type::kChainer> { /*! \brief expression to be transposed */ const EType &exp; /*! \brief constructor */ explicit TransposeExp(const EType &e) : exp(e) {} /*! \brief transpose expression */ inline const EType &T(void) const { return exp; } }; /*! * \brief base class of all rvalues * \tparam Container the actually class of data container, e.g. Tensor1D * \tparam DataType the element data type of each element in the container */ template class RValueExp: public Exp { public: /*! *\brief transpose of a matrix *\return transpose of current expression */ inline const TransposeExp T(void) const { return TransposeExp(this->self()); } /*! \brief operator overload */ inline Container &operator+=(DType s) { ExpEngine::Eval(this->ptrself(), scalar(s)); return *(this->ptrself()); } /*! \brief operator overload */ inline Container &operator-=(DType s) { ExpEngine::Eval(this->ptrself(), scalar(s)); return *(this->ptrself()); } /*! \brief operator overload */ inline Container &operator*=(DType s) { ExpEngine::Eval(this->ptrself(), scalar(s)); return *(this->ptrself()); } /*! \brief operator overload */ inline Container &operator/=(DType s) { ExpEngine::Eval(this->ptrself(), scalar(s)); return *(this->ptrself()); } /*! \brief operator overload */ inline Container &__assign(DType s) { ExpEngine::Eval(this->ptrself(), scalar(s)); return *(this->ptrself()); } /*! \brief we can not define container = container */ template inline Container &__assign(const Exp &exp) { ExpEngine::Eval(this->ptrself(), exp.self()); return *(this->ptrself()); } /*! \brief operator overload, assign */ inline Container &__assign(const Exp &exp); /*! \brief implementation of operator+= */ template inline Container &operator+=(const Exp &exp) { ExpEngine::Eval(this->ptrself(), exp.self()); return *(this->ptrself()); } /*! \brief implementation of operator-= */ template inline Container &operator-=(const Exp &exp) { ExpEngine::Eval(this->ptrself(), exp.self()); return *(this->ptrself()); } /*! \brief implementation of operator*= */ template inline Container &operator*=(const Exp &exp) { ExpEngine::Eval(this->ptrself(), exp.self()); return *(this->ptrself()); } /*! \brief implementation of operator/= */ template inline Container &operator/=(const Exp &exp) { ExpEngine::Eval(this->ptrself(), exp.self()); return *(this->ptrself()); } }; /*! * \brief matrix multiplication expression dot(lhs[.T], rhs[.T]) * \tparam TA type of lhs * \tparam TB type of rhs * \tparam ltrans whether lhs is transposed * \tparam rtrans whether rhs is transposed * \tparam DType the data type of the scalar */ template struct DotExp: public Exp, DType, type::kComplex> { /*! \brief left operand */ const TA &lhs_; /*! \brief right operand */ const TB &rhs_; /*! \brief scale over result */ DType scale_; /*! \brief constructor */ explicit DotExp(const TA &lhs, const TB &rhs, DType scale) : lhs_(lhs), rhs_(rhs), scale_(scale) {} }; // definition of dot expression /*! \brief dot operator def */ template inline DotExp dot(const RValueExp &lhs, const RValueExp &rhs) { return DotExp(lhs.self(), rhs.self(), DType(1.0f)); } /*! \brief dot operator def */ template inline DotExp dot(const TransposeExp &lhs, const RValueExp &rhs) { return DotExp(lhs.exp, rhs.self(), DType(1.0f)); } /*! \brief dot operator def */ template inline DotExp dot(const RValueExp &lhs, const TransposeExp &rhs) { return DotExp(lhs.self(), rhs.exp, DType(1.0f)); } /*! \brief dot operator def */ template inline DotExp dot(const TransposeExp &lhs, const TransposeExp &rhs) { return DotExp(lhs.exp, rhs.exp, DType(1.0f)); } /*! \brief batch_dot operator def */ template inline DotExp batch_dot(const RValueExp &lhs, const RValueExp &rhs) { return DotExp( lhs.self(), rhs.self(), DType(1.0f)); } //--------------- // TernaryMapExp // -------------- /*! * \brief ternary map expression * \tparam OP operator * \tparam TA type of item1 * \tparam TB type of item2 * \tparam etype expression type, sa namespace::type */ template struct TernaryMapExp: public Exp, DType, etype> { /*! \brief first operand */ const TA &item1_; /*! \brief second operand */ const TB &item2_; /*! \brief third operand */ const TC &item3_; /*! \brief constructor */ explicit TernaryMapExp(const TA &item1, const TB &item2, const TC &item3) :item1_(item1), item2_(item2), item3_(item3) {} }; /*! \brief make expression */ template inline TernaryMapExp MakeExp(const Exp &item1, const Exp &item2, const Exp &item3) { return TernaryMapExp(item1.self(), item2.self(), item3.self()); } /*! * \brief short hand for MakeExp, usage F(item1,item2,item3). create a ternary operation expression * \param item1 first operand * \param item2 second operand * \param item3 third operand * \return the result expression * \tparam ternary operator * \tparam TA item1 expression * \tparam ta item1 expression type * \tparam TB item2 expression * \tparam tb item2 expression type * \tparam TC item3 expression * \tparam tc item3 expression type * \sa mshadow::op */ // Ternary template inline TernaryMapExp F(const Exp &item1, const Exp &item2, const Exp &item3) { return MakeExp(item1, item2, item3); } //--------------- // BinaryMapExp // -------------- /*! * \brief binary map expression lhs [op] rhs * \tparam OP operator * \tparam TA type of lhs * \tparam TB type of rhs * \tparam etype expression type, sa namespace::type */ template struct BinaryMapExp: public Exp, DType, etype> { /*! \brief left operand */ const TA &lhs_; /*! \brief right operand */ const TB &rhs_; /*! \brief constructor */ explicit BinaryMapExp(const TA &lhs, const TB &rhs) :lhs_(lhs), rhs_(rhs) {} }; /*! \brief make expression */ template inline BinaryMapExp MakeExp(const Exp &lhs, const Exp &rhs) { return BinaryMapExp(lhs.self(), rhs.self()); } /*! * \brief short hand for MakeExp, usage F(lhs, rhs). create a binary operation expression * \param lhs left operand * \param rhs right operand * \return the result expression * \tparam binary operator * \tparam TA lhs expression * \tparam ta lhs expression type * \tparam TB rhs expression * \tparam tb rhs expression type * \sa mshadow::op */ template inline BinaryMapExp F(const Exp &lhs, const Exp &rhs) { return MakeExp(lhs, rhs); } // operator rules /*! \brief operator overload */ template inline BinaryMapExp operator+(const Exp &lhs, const Exp &rhs) { return MakeExp(lhs, rhs); } /*! \brief operator overload */ template inline BinaryMapExp operator-(const Exp &lhs, const Exp &rhs) { return MakeExp(lhs, rhs); } /*! \brief operator overload */ template inline BinaryMapExp operator*(const Exp &lhs, const Exp &rhs) { return MakeExp(lhs, rhs); } /*! \brief operator overload */ template inline BinaryMapExp operator/(const Exp &lhs, const Exp &rhs) { return MakeExp(lhs, rhs); } //--------------- // UnaryMapExp // -------------- /*! * \brief unary map expression op(src) * \tparam OP operator * \tparam TA type of src * \tparam etype expression type, sa namespace::type */ template struct UnaryMapExp: public Exp, DType, etype> { /*! \brief source expression */ const TA &src_; /*! \brief constructor */ explicit UnaryMapExp(const TA &src) : src_(src) {} }; /*! \brief make expression */ template inline UnaryMapExp MakeExp(const Exp &src) { return UnaryMapExp(src.self()); } /*! * \brief short hand for MakeExp, usage F(src), create a unary operation expression * \param src source expression * \return the result expression * \tparam operator * \tparam TA source expression * \tparam ta source expression type * \sa mshadow::op */ template inline UnaryMapExp F(const Exp &src) { return MakeExp(src); } } // namespace expr } // namespace mshadow #endif // MSHADOW_EXPRESSION_H_