Chris@49: // Copyright (C) 2008-2012 NICTA (www.nicta.com.au) Chris@49: // Copyright (C) 2008-2012 Conrad Sanderson Chris@49: // Copyright (C) 2012 Ryan Curtin Chris@49: // Chris@49: // This Source Code Form is subject to the terms of the Mozilla Public Chris@49: // License, v. 2.0. If a copy of the MPL was not distributed with this Chris@49: // file, You can obtain one at http://mozilla.org/MPL/2.0/. Chris@49: Chris@49: Chris@49: //! \addtogroup op_htrans Chris@49: //! @{ Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_hot Chris@49: arma_inline Chris@49: void Chris@49: op_htrans::apply_noalias(Mat& out, const Mat& A, const typename arma_not_cx::result* junk) Chris@49: { Chris@49: arma_extra_debug_sigprint(); Chris@49: arma_ignore(junk); Chris@49: Chris@49: op_strans::apply_noalias(out, A); Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: op_htrans::apply_noalias(Mat& out, const Mat& A, const typename arma_cx_only::result* junk) Chris@49: { Chris@49: arma_extra_debug_sigprint(); Chris@49: arma_ignore(junk); Chris@49: Chris@49: const uword A_n_rows = A.n_rows; Chris@49: const uword A_n_cols = A.n_cols; Chris@49: Chris@49: out.set_size(A_n_cols, A_n_rows); Chris@49: Chris@49: if( (A_n_cols == 1) || (A_n_rows == 1) ) Chris@49: { Chris@49: const uword n_elem = A.n_elem; Chris@49: Chris@49: const eT* A_mem = A.memptr(); Chris@49: eT* out_mem = out.memptr(); Chris@49: Chris@49: for(uword i=0; i < n_elem; ++i) Chris@49: { Chris@49: out_mem[i] = std::conj(A_mem[i]); Chris@49: } Chris@49: } Chris@49: else Chris@49: { Chris@49: for(uword in_row = 0; in_row < A_n_rows; ++in_row) Chris@49: { Chris@49: const uword out_col = in_row; Chris@49: Chris@49: for(uword in_col = 0; in_col < A_n_cols; ++in_col) Chris@49: { Chris@49: const uword out_row = in_col; Chris@49: out.at(out_row, out_col) = std::conj( A.at(in_row, in_col) ); Chris@49: } Chris@49: } Chris@49: } Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_hot Chris@49: arma_inline Chris@49: void Chris@49: op_htrans::apply(Mat& out, const Mat& A, const typename arma_not_cx::result* junk) Chris@49: { Chris@49: arma_extra_debug_sigprint(); Chris@49: arma_ignore(junk); Chris@49: Chris@49: op_strans::apply(out, A); Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: op_htrans::apply(Mat& out, const Mat& A, const typename arma_cx_only::result* junk) Chris@49: { Chris@49: arma_extra_debug_sigprint(); Chris@49: arma_ignore(junk); Chris@49: Chris@49: if(&out != &A) Chris@49: { Chris@49: op_htrans::apply_noalias(out, A); Chris@49: } Chris@49: else Chris@49: { Chris@49: const uword n_rows = out.n_rows; Chris@49: const uword n_cols = out.n_cols; Chris@49: Chris@49: if(n_rows == n_cols) Chris@49: { Chris@49: arma_extra_debug_print("doing in-place hermitian transpose of a square matrix"); Chris@49: Chris@49: for(uword col=0; col < n_cols; ++col) Chris@49: { Chris@49: eT* coldata = out.colptr(col); Chris@49: Chris@49: out.at(col,col) = std::conj( out.at(col,col) ); Chris@49: Chris@49: for(uword row=(col+1); row < n_rows; ++row) Chris@49: { Chris@49: const eT val1 = std::conj(coldata[row]); Chris@49: const eT val2 = std::conj(out.at(col,row)); Chris@49: Chris@49: out.at(col,row) = val1; Chris@49: coldata[row] = val2; Chris@49: } Chris@49: } Chris@49: } Chris@49: else Chris@49: { Chris@49: Mat tmp; Chris@49: op_htrans::apply_noalias(tmp, A); Chris@49: Chris@49: out.steal_mem(tmp); Chris@49: } Chris@49: } Chris@49: Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: op_htrans::apply_proxy(Mat& out, const T1& X) Chris@49: { Chris@49: arma_extra_debug_sigprint(); Chris@49: Chris@49: typedef typename T1::elem_type eT; Chris@49: Chris@49: const Proxy P(X); Chris@49: Chris@49: // allow detection of in-place transpose Chris@49: if( (is_Mat::stored_type>::value == true) && (Proxy::fake_mat == false) ) Chris@49: { Chris@49: const unwrap::stored_type> tmp(P.Q); Chris@49: Chris@49: op_htrans::apply(out, tmp.M); Chris@49: } Chris@49: else Chris@49: { Chris@49: const uword n_rows = P.get_n_rows(); Chris@49: const uword n_cols = P.get_n_cols(); Chris@49: Chris@49: const bool is_alias = P.is_alias(out); Chris@49: Chris@49: if( (resolves_to_vector::value == true) && (Proxy::prefer_at_accessor == false) ) Chris@49: { Chris@49: if(is_alias == false) Chris@49: { Chris@49: out.set_size(n_cols, n_rows); Chris@49: Chris@49: eT* out_mem = out.memptr(); Chris@49: Chris@49: const uword n_elem = P.get_n_elem(); Chris@49: Chris@49: typename Proxy::ea_type Pea = P.get_ea(); Chris@49: Chris@49: for(uword i=0; i < n_elem; ++i) Chris@49: { Chris@49: out_mem[i] = std::conj(Pea[i]); Chris@49: } Chris@49: } Chris@49: else // aliasing Chris@49: { Chris@49: Mat out2(n_cols, n_rows); Chris@49: Chris@49: eT* out_mem = out2.memptr(); Chris@49: Chris@49: const uword n_elem = P.get_n_elem(); Chris@49: Chris@49: typename Proxy::ea_type Pea = P.get_ea(); Chris@49: Chris@49: for(uword i=0; i < n_elem; ++i) Chris@49: { Chris@49: out_mem[i] = std::conj(Pea[i]); Chris@49: } Chris@49: Chris@49: out.steal_mem(out2); Chris@49: } Chris@49: } Chris@49: else Chris@49: { Chris@49: if(is_alias == false) Chris@49: { Chris@49: out.set_size(n_cols, n_rows); Chris@49: Chris@49: for(uword k=0; k < n_cols; ++k) Chris@49: for(uword i=0; i < n_rows; ++i) Chris@49: { Chris@49: out.at(k,i) = std::conj(P.at(i,k)); Chris@49: } Chris@49: } Chris@49: else // aliasing Chris@49: { Chris@49: Mat out2(n_cols, n_rows); Chris@49: Chris@49: for(uword k=0; k < n_cols; ++k) Chris@49: for(uword i=0; i < n_rows; ++i) Chris@49: { Chris@49: out2.at(k,i) = std::conj(P.at(i,k)); Chris@49: } Chris@49: Chris@49: out.steal_mem(out2); Chris@49: } Chris@49: } Chris@49: } Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: op_htrans::apply(Mat& out, const Op& in, const typename arma_not_cx::result* junk) Chris@49: { Chris@49: arma_extra_debug_sigprint(); Chris@49: arma_ignore(junk); Chris@49: Chris@49: op_strans::apply_proxy(out, in.m); Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: op_htrans::apply(Mat& out, const Op& in, const typename arma_cx_only::result* junk) Chris@49: { Chris@49: arma_extra_debug_sigprint(); Chris@49: arma_ignore(junk); Chris@49: Chris@49: op_htrans::apply_proxy(out, in.m); Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: op_htrans::apply(Mat& out, const Op< Op, op_htrans>& in) Chris@49: { Chris@49: arma_extra_debug_sigprint(); Chris@49: Chris@49: typedef typename T1::elem_type eT; Chris@49: Chris@49: const unwrap tmp(in.m.m); Chris@49: const Mat& A = tmp.M; Chris@49: Chris@49: const bool upper = in.m.aux_uword_a; Chris@49: Chris@49: op_trimat::apply_htrans(out, A, upper); Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: // Chris@49: // op_htrans2 Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_hot Chris@49: arma_inline Chris@49: void Chris@49: op_htrans2::apply_noalias(Mat& out, const Mat& A, const eT val) Chris@49: { Chris@49: arma_extra_debug_sigprint(); Chris@49: Chris@49: const uword A_n_rows = A.n_rows; Chris@49: const uword A_n_cols = A.n_cols; Chris@49: Chris@49: out.set_size(A_n_cols, A_n_rows); Chris@49: Chris@49: if( (A_n_cols == 1) || (A_n_rows == 1) ) Chris@49: { Chris@49: const uword n_elem = A.n_elem; Chris@49: Chris@49: const eT* A_mem = A.memptr(); Chris@49: eT* out_mem = out.memptr(); Chris@49: Chris@49: for(uword i=0; i < n_elem; ++i) Chris@49: { Chris@49: out_mem[i] = val * std::conj(A_mem[i]); Chris@49: } Chris@49: } Chris@49: else Chris@49: { Chris@49: for(uword in_row = 0; in_row < A_n_rows; ++in_row) Chris@49: { Chris@49: const uword out_col = in_row; Chris@49: Chris@49: for(uword in_col = 0; in_col < A_n_cols; ++in_col) Chris@49: { Chris@49: const uword out_row = in_col; Chris@49: out.at(out_row, out_col) = val * std::conj( A.at(in_row, in_col) ); Chris@49: } Chris@49: } Chris@49: } Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: op_htrans2::apply(Mat& out, const Mat& A, const eT val) Chris@49: { Chris@49: arma_extra_debug_sigprint(); Chris@49: Chris@49: if(&out != &A) Chris@49: { Chris@49: op_htrans2::apply_noalias(out, A, val); Chris@49: } Chris@49: else Chris@49: { Chris@49: const uword n_rows = out.n_rows; Chris@49: const uword n_cols = out.n_cols; Chris@49: Chris@49: if(n_rows == n_cols) Chris@49: { Chris@49: arma_extra_debug_print("doing in-place hermitian transpose of a square matrix"); Chris@49: Chris@49: // TODO: do multiplication while swapping Chris@49: Chris@49: for(uword col=0; col < n_cols; ++col) Chris@49: { Chris@49: eT* coldata = out.colptr(col); Chris@49: Chris@49: out.at(col,col) = std::conj( out.at(col,col) ); Chris@49: Chris@49: for(uword row=(col+1); row < n_rows; ++row) Chris@49: { Chris@49: const eT val1 = std::conj(coldata[row]); Chris@49: const eT val2 = std::conj(out.at(col,row)); Chris@49: Chris@49: out.at(col,row) = val1; Chris@49: coldata[row] = val2; Chris@49: } Chris@49: } Chris@49: Chris@49: arrayops::inplace_mul( out.memptr(), val, out.n_elem ); Chris@49: } Chris@49: else Chris@49: { Chris@49: Mat tmp; Chris@49: op_htrans2::apply_noalias(tmp, A, val); Chris@49: Chris@49: out.steal_mem(tmp); Chris@49: } Chris@49: } Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: op_htrans2::apply_proxy(Mat& out, const T1& X, const typename T1::elem_type val) Chris@49: { Chris@49: arma_extra_debug_sigprint(); Chris@49: Chris@49: typedef typename T1::elem_type eT; Chris@49: Chris@49: const Proxy P(X); Chris@49: Chris@49: // allow detection of in-place transpose Chris@49: if( (is_Mat::stored_type>::value == true) && (Proxy::fake_mat == false) ) Chris@49: { Chris@49: const unwrap::stored_type> tmp(P.Q); Chris@49: Chris@49: op_htrans2::apply(out, tmp.M, val); Chris@49: } Chris@49: else Chris@49: { Chris@49: const uword n_rows = P.get_n_rows(); Chris@49: const uword n_cols = P.get_n_cols(); Chris@49: Chris@49: const bool is_alias = P.is_alias(out); Chris@49: Chris@49: if( (resolves_to_vector::value == true) && (Proxy::prefer_at_accessor == false) ) Chris@49: { Chris@49: if(is_alias == false) Chris@49: { Chris@49: out.set_size(n_cols, n_rows); Chris@49: Chris@49: eT* out_mem = out.memptr(); Chris@49: Chris@49: const uword n_elem = P.get_n_elem(); Chris@49: Chris@49: typename Proxy::ea_type Pea = P.get_ea(); Chris@49: Chris@49: for(uword i=0; i < n_elem; ++i) Chris@49: { Chris@49: out_mem[i] = val * std::conj(Pea[i]); Chris@49: } Chris@49: } Chris@49: else // aliasing Chris@49: { Chris@49: Mat out2(n_cols, n_rows); Chris@49: Chris@49: eT* out_mem = out2.memptr(); Chris@49: Chris@49: const uword n_elem = P.get_n_elem(); Chris@49: Chris@49: typename Proxy::ea_type Pea = P.get_ea(); Chris@49: Chris@49: for(uword i=0; i < n_elem; ++i) Chris@49: { Chris@49: out_mem[i] = val * std::conj(Pea[i]); Chris@49: } Chris@49: Chris@49: out.steal_mem(out2); Chris@49: } Chris@49: } Chris@49: else Chris@49: { Chris@49: if(is_alias == false) Chris@49: { Chris@49: out.set_size(n_cols, n_rows); Chris@49: Chris@49: for(uword k=0; k < n_cols; ++k) Chris@49: for(uword i=0; i < n_rows; ++i) Chris@49: { Chris@49: out.at(k,i) = val * std::conj(P.at(i,k)); Chris@49: } Chris@49: } Chris@49: else // aliasing Chris@49: { Chris@49: Mat out2(n_cols, n_rows); Chris@49: Chris@49: for(uword k=0; k < n_cols; ++k) Chris@49: for(uword i=0; i < n_rows; ++i) Chris@49: { Chris@49: out2.at(k,i) = val * std::conj(P.at(i,k)); Chris@49: } Chris@49: Chris@49: out.steal_mem(out2); Chris@49: } Chris@49: } Chris@49: } Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: op_htrans2::apply(Mat& out, const Op& in, const typename arma_not_cx::result* junk) Chris@49: { Chris@49: arma_extra_debug_sigprint(); Chris@49: arma_ignore(junk); Chris@49: Chris@49: op_strans2::apply_proxy(out, in.m, in.aux); Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: template Chris@49: arma_hot Chris@49: inline Chris@49: void Chris@49: op_htrans2::apply(Mat& out, const Op& in, const typename arma_cx_only::result* junk) Chris@49: { Chris@49: arma_extra_debug_sigprint(); Chris@49: arma_ignore(junk); Chris@49: Chris@49: op_htrans2::apply_proxy(out, in.m, in.aux); Chris@49: } Chris@49: Chris@49: Chris@49: Chris@49: //! @}