X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2FMoof%2Fcml%2Fmatrix%2Fmatrix_transpose.h;fp=src%2FMoof%2Fcml%2Fmatrix%2Fmatrix_transpose.h;h=3f54843c32f1206e3b4bc67bd63f327666a2bb3c;hp=0000000000000000000000000000000000000000;hb=c2321281bf12a7efaedde930422c7ddbc92080d4;hpb=87bc17e55b0c1dc73ecc66df856d3f08fd7a7724 diff --git a/src/Moof/cml/matrix/matrix_transpose.h b/src/Moof/cml/matrix/matrix_transpose.h new file mode 100644 index 0000000..3f54843 --- /dev/null +++ b/src/Moof/cml/matrix/matrix_transpose.h @@ -0,0 +1,305 @@ +/* -*- C++ -*- ------------------------------------------------------------ + +Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/ + +The Configurable Math Library (CML) is distributed under the terms of the +Boost Software License, v1.0 (see cml/LICENSE for details). + + *-----------------------------------------------------------------------*/ +/** @file + * @brief + * + * @todo Currently, the transpose() and T() functions copy the transposed + * result into a temporary, and return it to avoid aliasing problems, e.g. + * C = transpose(C). By checking for C on the right-hand side, this can + * be avoided, but experimentation is needed to determine the impact on + * performance. Another option is to use a function to explicitly specify + * when a temporary is needed; e.g. C = transpose(temp(C)). + */ + +#ifndef matrix_transpose_h +#define matrix_transpose_h + +#include + +#define MATRIX_TRANSPOSE_RETURNS_TEMP + +namespace cml { +namespace et { + +/** "Transpose" the given matrix expression. + * + * This does nothing more than change the result type of the expression + * into one with the opposite orientation (i.e. row->col, col->row). + */ +template +class MatrixTransposeOp +{ + public: + + typedef MatrixTransposeOp expr_type; + + /* Record ary-ness of the expression: */ + typedef unary_expression expr_ary; + + /* Copy the expression by value into higher-up expressions: */ + typedef expr_type expr_const_reference; + + typedef typename ExprT::value_type value_type; + typedef matrix_result_tag result_tag; + typedef typename ExprT::size_tag size_tag; + + /* Store the expression traits: */ + typedef ExprTraits expr_traits; + + /* Get the reference type: */ + typedef typename expr_traits::const_reference expr_reference; + + /* Swap the orientation: */ + typedef typename expr_traits::result_type::transposed_type result_type; + + /* Get the temporary type: */ + typedef typename result_type::temporary_type temporary_type; + + /* For matching by assignability: */ + typedef cml::et::not_assignable_tag assignable_tag; + + + public: + + /** Record result size as an enum. */ + enum { + array_rows = result_type::array_rows, + array_cols = result_type::array_cols + }; + + + public: + + /** Return the expression size as a pair. */ + matrix_size size() const { + return matrix_size(this->rows(),this->cols()); + } + + /** Return result rows. + * + * The tranpose has the same number of rows as the original has + * columns. + */ + size_t rows() const { + return expr_traits().cols(m_expr); + } + + /** Return result cols. + * + * The tranpose has the same number of columns as the original has + * rows. + */ + size_t cols() const { + return expr_traits().rows(m_expr); + } + + /** Return reference to contained expression. */ + expr_reference expression() const { return m_expr; } + + /** Compute value at index i of the result matrix. + * + * Element (i,j) of the transpose is element (j,i) of the original + * expression. + */ + value_type operator()(size_t i, size_t j) const { + return expr_traits().get(m_expr,j,i); + } + + + public: + + /** Construct from the subexpression to store. */ + explicit MatrixTransposeOp(const ExprT& expr) : m_expr(expr) {} + + /** Copy constructor. */ + MatrixTransposeOp(const expr_type& e) : m_expr(e.m_expr) {} + + + protected: + + expr_reference m_expr; + + + private: + + /* Cannot be assigned to: */ + expr_type& operator=(const expr_type&); +}; + +/** Expression traits class for VectorTransposeOp<>. */ +template +struct ExprTraits< MatrixTransposeOp > +{ + typedef MatrixTransposeOp expr_type; + typedef typename expr_type::value_type value_type; + typedef typename expr_type::expr_const_reference const_reference; + typedef typename expr_type::result_tag result_tag; + typedef typename expr_type::size_tag size_tag; + typedef typename expr_type::result_type result_type; + typedef typename expr_type::assignable_tag assignable_tag; + typedef expr_node_tag node_tag; + + value_type get(const expr_type& m, size_t i, size_t j) const { + return m(i,j); + } + + matrix_size size(const expr_type& e) const { return e.size(); } + size_t rows(const expr_type& e) const { return e.rows(); } + size_t cols(const expr_type& e) const { return e.cols(); } +}; + +} // namespace et + + +/* Define the transpose operators in the cml namespace: */ +#if defined(MATRIX_TRANSPOSE_RETURNS_TEMP) + +/** Matrix transpose operator taking a matrix operand. */ +template +typename et::MatrixTransposeOp< + matrix +>::temporary_type +transpose(const matrix& expr) +{ + /* Record the matrix type: */ + typedef matrix matrix_type; + + /* Record the type of the transpose op: */ + typedef et::MatrixTransposeOp Op; + + /* Determine the returned matrix type: */ + typedef typename et::MatrixTransposeOp< + matrix_type + >::temporary_type tmp_type; + + /* The expression to use to assign the temporary: */ + typedef et::MatrixXpr ExprT; + + /* Create the temporary and return it: */ + tmp_type tmp; + cml::et::detail::Resize(tmp,expr.rows(),expr.cols()); + tmp = ExprT(Op(expr)); + return tmp; +} + +/** Matrix transpose operator taking an et::MatrixXpr operand. + * + * The parse tree is automatically compressed by hoisting the MatrixXpr's + * subexpression into the subexpression of the MatrixTransposeOp. + */ +template +typename et::MatrixTransposeOp< + XprT +>::temporary_type +transpose(MATXPR_ARG_TYPE expr) +{ + /* Record the type of the transpose op: */ + typedef et::MatrixTransposeOp Op; + + /* Determine the returned matrix type: */ + typedef typename et::MatrixTransposeOp::temporary_type tmp_type; + + /* The expression to use to assign the temporary: */ + typedef et::MatrixXpr ExprT; + + /* Create the temporary and return it: */ + tmp_type tmp; + cml::et::detail::Resize(tmp,expr.rows(),expr.cols()); + tmp = ExprT(Op(expr.expression())); + return tmp; +} + + +/* For notational convenience: */ + +/** Matrix transpose operator taking a matrix operand. */ +template +typename et::MatrixTransposeOp< + matrix +>::temporary_type +T(const matrix& expr) +{ + return transpose(expr); +} + +/** Matrix transpose operator taking an et::MatrixXpr operand. + * + * The parse tree is automatically compressed by hoisting the MatrixXpr's + * subexpression into the subexpression of the MatrixTransposeOp. + */ +template +typename et::MatrixTransposeOp< + XprT +>::temporary_type +T(MATXPR_ARG_TYPE expr) +{ + return transpose(expr); +} + +#else + +/* XXX For this to work correctly, matrix assignment and copy have to be + * changed to either use a temporary all the time, or to create a temporary + * when the same matrix appears on both sides of an assignment, and a + * temporary was not already created on the RHS by the ET code. + */ + +/** Matrix transpose operator taking a matrix operand. */ +template +et::MatrixXpr< et::MatrixTransposeOp< matrix > > +transpose(const matrix& expr) +{ + typedef et::MatrixTransposeOp< matrix > ExprT; + return et::MatrixXpr(ExprT(expr)); +} + +/** Matrix transpose operator taking an et::MatrixXpr operand. + * + * The parse tree is automatically compressed by hoisting the MatrixXpr's + * subexpression into the subexpression of the MatrixTransposeOp. + */ +template +et::MatrixXpr< et::MatrixTransposeOp > +transpose(MATXPR_ARG_TYPE expr) +{ + typedef et::MatrixTransposeOp ExprT; + return et::MatrixXpr(ExprT(expr.expression())); +} + + +/* For notational convenience: */ + +/** Matrix transpose operator taking a matrix operand. */ +template +et::MatrixXpr< et::MatrixTransposeOp< matrix > > +T(const matrix& expr) +{ + return transpose(expr); +} + +/** Matrix transpose operator taking an et::MatrixXpr operand. + * + * The parse tree is automatically compressed by hoisting the MatrixXpr's + * subexpression into the subexpression of the MatrixTransposeOp. + */ +template +et::MatrixXpr< et::MatrixTransposeOp > +T(MATXPR_ARG_TYPE expr) +{ + return transpose(expr); +} + +#endif + +} // namespace cml + +#endif + +// ------------------------------------------------------------------------- +// vim:ft=cpp