1 /* -*- C++ -*- ------------------------------------------------------------
3 Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
5 The Configurable Math Library (CML) is distributed under the terms of the
6 Boost Software License, v1.0 (see cml/LICENSE for details).
8 *-----------------------------------------------------------------------*/
12 * @todo Currently, the transpose() and T() functions copy the transposed
13 * result into a temporary, and return it to avoid aliasing problems, e.g.
14 * C = transpose(C). By checking for C on the right-hand side, this can
15 * be avoided, but experimentation is needed to determine the impact on
16 * performance. Another option is to use a function to explicitly specify
17 * when a temporary is needed; e.g. C = transpose(temp(C)).
20 #ifndef matrix_transpose_h
21 #define matrix_transpose_h
23 #include <cml/matrix/matrix_expr.h>
25 #define MATRIX_TRANSPOSE_RETURNS_TEMP
30 /** "Transpose" the given matrix expression.
32 * This does nothing more than change the result type of the expression
33 * into one with the opposite orientation (i.e. row->col, col->row).
36 class MatrixTransposeOp
40 typedef MatrixTransposeOp
<ExprT
> expr_type
;
42 /* Record ary-ness of the expression: */
43 typedef unary_expression expr_ary
;
45 /* Copy the expression by value into higher-up expressions: */
46 typedef expr_type expr_const_reference
;
48 typedef typename
ExprT::value_type value_type
;
49 typedef matrix_result_tag result_tag
;
50 typedef typename
ExprT::size_tag size_tag
;
52 /* Store the expression traits: */
53 typedef ExprTraits
<ExprT
> expr_traits
;
55 /* Get the reference type: */
56 typedef typename
expr_traits::const_reference expr_reference
;
58 /* Swap the orientation: */
59 typedef typename
expr_traits::result_type::transposed_type result_type
;
61 /* Get the temporary type: */
62 typedef typename
result_type::temporary_type temporary_type
;
64 /* For matching by assignability: */
65 typedef cml::et::not_assignable_tag assignable_tag
;
70 /** Record result size as an enum. */
72 array_rows
= result_type::array_rows
,
73 array_cols
= result_type::array_cols
79 /** Return the expression size as a pair. */
80 matrix_size
size() const {
81 return matrix_size(this->rows(),this->cols());
84 /** Return result rows.
86 * The tranpose has the same number of rows as the original has
90 return expr_traits().cols(m_expr
);
93 /** Return result cols.
95 * The tranpose has the same number of columns as the original has
99 return expr_traits().rows(m_expr
);
102 /** Return reference to contained expression. */
103 expr_reference
expression() const { return m_expr
; }
105 /** Compute value at index i of the result matrix.
107 * Element (i,j) of the transpose is element (j,i) of the original
110 value_type
operator()(size_t i
, size_t j
) const {
111 return expr_traits().get(m_expr
,j
,i
);
117 /** Construct from the subexpression to store. */
118 explicit MatrixTransposeOp(const ExprT
& expr
) : m_expr(expr
) {}
120 /** Copy constructor. */
121 MatrixTransposeOp(const expr_type
& e
) : m_expr(e
.m_expr
) {}
126 expr_reference m_expr
;
131 /* Cannot be assigned to: */
132 expr_type
& operator=(const expr_type
&);
135 /** Expression traits class for VectorTransposeOp<>. */
136 template<class ExprT
>
137 struct ExprTraits
< MatrixTransposeOp
<ExprT
> >
139 typedef MatrixTransposeOp
<ExprT
> expr_type
;
140 typedef typename
expr_type::value_type value_type
;
141 typedef typename
expr_type::expr_const_reference const_reference
;
142 typedef typename
expr_type::result_tag result_tag
;
143 typedef typename
expr_type::size_tag size_tag
;
144 typedef typename
expr_type::result_type result_type
;
145 typedef typename
expr_type::assignable_tag assignable_tag
;
146 typedef expr_node_tag node_tag
;
148 value_type
get(const expr_type
& m
, size_t i
, size_t j
) const {
152 matrix_size
size(const expr_type
& e
) const { return e
.size(); }
153 size_t rows(const expr_type
& e
) const { return e
.rows(); }
154 size_t cols(const expr_type
& e
) const { return e
.cols(); }
160 /* Define the transpose operators in the cml namespace: */
161 #if defined(MATRIX_TRANSPOSE_RETURNS_TEMP)
163 /** Matrix transpose operator taking a matrix operand. */
164 template<typename E
, class AT
, typename BO
, typename L
>
165 typename
et::MatrixTransposeOp
<
168 transpose(const matrix
<E
,AT
,BO
,L
>& expr
)
170 /* Record the matrix type: */
171 typedef matrix
<E
,AT
,BO
,L
> matrix_type
;
173 /* Record the type of the transpose op: */
174 typedef et::MatrixTransposeOp
<matrix_type
> Op
;
176 /* Determine the returned matrix type: */
177 typedef typename
et::MatrixTransposeOp
<
179 >::temporary_type tmp_type
;
181 /* The expression to use to assign the temporary: */
182 typedef et::MatrixXpr
<Op
> ExprT
;
184 /* Create the temporary and return it: */
186 cml::et::detail::Resize(tmp
,expr
.rows(),expr
.cols());
187 tmp
= ExprT(Op(expr
));
191 /** Matrix transpose operator taking an et::MatrixXpr operand.
193 * The parse tree is automatically compressed by hoisting the MatrixXpr's
194 * subexpression into the subexpression of the MatrixTransposeOp.
197 typename
et::MatrixTransposeOp
<
200 transpose(MATXPR_ARG_TYPE expr
)
202 /* Record the type of the transpose op: */
203 typedef et::MatrixTransposeOp
<XprT
> Op
;
205 /* Determine the returned matrix type: */
206 typedef typename
et::MatrixTransposeOp
<XprT
>::temporary_type tmp_type
;
208 /* The expression to use to assign the temporary: */
209 typedef et::MatrixXpr
<Op
> ExprT
;
211 /* Create the temporary and return it: */
213 cml::et::detail::Resize(tmp
,expr
.rows(),expr
.cols());
214 tmp
= ExprT(Op(expr
.expression()));
219 /* For notational convenience: */
221 /** Matrix transpose operator taking a matrix operand. */
222 template<typename E
, class AT
, typename BO
, typename L
>
223 typename
et::MatrixTransposeOp
<
226 T(const matrix
<E
,AT
,BO
,L
>& expr
)
228 return transpose(expr
);
231 /** Matrix transpose operator taking an et::MatrixXpr operand.
233 * The parse tree is automatically compressed by hoisting the MatrixXpr's
234 * subexpression into the subexpression of the MatrixTransposeOp.
237 typename
et::MatrixTransposeOp
<
240 T(MATXPR_ARG_TYPE expr
)
242 return transpose(expr
);
247 /* XXX For this to work correctly, matrix assignment and copy have to be
248 * changed to either use a temporary all the time, or to create a temporary
249 * when the same matrix appears on both sides of an assignment, and a
250 * temporary was not already created on the RHS by the ET code.
253 /** Matrix transpose operator taking a matrix operand. */
254 template<typename E
, class AT
, typename BO
, typename L
>
255 et::MatrixXpr
< et::MatrixTransposeOp
< matrix
<E
,AT
,BO
,L
> > >
256 transpose(const matrix
<E
,AT
,BO
,L
>& expr
)
258 typedef et::MatrixTransposeOp
< matrix
<E
,AT
,BO
,L
> > ExprT
;
259 return et::MatrixXpr
<ExprT
>(ExprT(expr
));
262 /** Matrix transpose operator taking an et::MatrixXpr operand.
264 * The parse tree is automatically compressed by hoisting the MatrixXpr's
265 * subexpression into the subexpression of the MatrixTransposeOp.
268 et::MatrixXpr
< et::MatrixTransposeOp
<XprT
> >
269 transpose(MATXPR_ARG_TYPE expr
)
271 typedef et::MatrixTransposeOp
<XprT
> ExprT
;
272 return et::MatrixXpr
<ExprT
>(ExprT(expr
.expression()));
276 /* For notational convenience: */
278 /** Matrix transpose operator taking a matrix operand. */
279 template<typename E
, class AT
, typename BO
, typename L
>
280 et::MatrixXpr
< et::MatrixTransposeOp
< matrix
<E
,AT
,BO
,L
> > >
281 T(const matrix
<E
,AT
,BO
,L
>& expr
)
283 return transpose(expr
);
286 /** Matrix transpose operator taking an et::MatrixXpr operand.
288 * The parse tree is automatically compressed by hoisting the MatrixXpr's
289 * subexpression into the subexpression of the MatrixTransposeOp.
292 et::MatrixXpr
< et::MatrixTransposeOp
<XprT
> >
293 T(MATXPR_ARG_TYPE expr
)
295 return transpose(expr
);
304 // -------------------------------------------------------------------------