// Copyright (C) 2012-2015 National ICT Australia (NICTA) // // 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/. // ------------------------------------------------------------------- // // Written by Conrad Sanderson - http://conradsanderson.id.au //! \addtogroup spop_diagmat //! @{ template inline void spop_diagmat::apply(SpMat& out, const SpOp& in) { arma_extra_debug_sigprint(); typedef typename T1::elem_type eT; const SpProxy p(in.m); if(p.is_alias(out) == false) { spop_diagmat::apply_noalias(out, p); } else { SpMat tmp; spop_diagmat::apply_noalias(tmp, p); out.steal_mem(tmp); } } template inline void spop_diagmat::apply_noalias(SpMat& out, const SpProxy& p) { arma_extra_debug_sigprint(); const uword n_rows = p.get_n_rows(); const uword n_cols = p.get_n_cols(); const bool p_is_vec = (n_rows == 1) || (n_cols == 1); if(p_is_vec) // generate a diagonal matrix out of a vector { const uword N = (n_rows == 1) ? n_cols : n_rows; out.zeros(N, N); if(p.get_n_nonzero() == 0) { return; } typename SpProxy::const_iterator_type it = p.begin(); typename SpProxy::const_iterator_type it_end = p.end(); if(n_cols == 1) { while(it != it_end) { const uword row = it.row(); out.at(row,row) = (*it); ++it; } } else if(n_rows == 1) { while(it != it_end) { const uword col = it.col(); out.at(col,col) = (*it); ++it; } } } else // generate a diagonal matrix out of a matrix { out.zeros(n_rows, n_cols); if(p.get_n_nonzero() == 0) { return; } typename SpProxy::const_iterator_type it = p.begin(); typename SpProxy::const_iterator_type it_end = p.end(); while(it != it_end) { const uword row = it.row(); const uword col = it.col(); if(row == col) { out.at(row,row) = (*it); } ++it; } } } template inline void spop_diagmat2::apply(SpMat& out, const SpOp& in) { arma_extra_debug_sigprint(); typedef typename T1::elem_type eT; const uword row_offset = in.aux_uword_a; const uword col_offset = in.aux_uword_b; const unwrap_spmat U(in.m); if(&(U.M) == &out) { SpMat tmp; spop_diagmat2::apply_noalias(tmp, U.M, row_offset, col_offset); out.steal_mem(tmp); } else { spop_diagmat2::apply_noalias(out, U.M, row_offset, col_offset); } } template inline void spop_diagmat2::apply_noalias(SpMat& out, const SpMat& X, const uword row_offset, const uword col_offset) { arma_extra_debug_sigprint(); const uword n_rows = X.n_rows; const uword n_cols = X.n_cols; const uword n_elem = X.n_elem; if(n_elem == 0) { out.reset(); return; } const bool X_is_vec = (n_rows == 1) || (n_cols == 1); if(X_is_vec) // generate a diagonal matrix out of a vector { const uword n_pad = (std::max)(row_offset, col_offset); out.zeros(n_elem + n_pad, n_elem + n_pad); if(X.n_nonzero == 0) { return; } typename SpMat::const_iterator it = X.begin(); typename SpMat::const_iterator it_end = X.end(); if(n_cols == 1) { while(it != it_end) { const uword row = it.row(); out.at(row_offset + row, col_offset + row) = (*it); ++it; } } else if(n_rows == 1) { while(it != it_end) { const uword col = it.col(); out.at(row_offset + col, col_offset + col) = (*it); ++it; } } } else // generate a diagonal matrix out of a matrix { arma_debug_check ( ((row_offset > 0) && (row_offset >= n_rows)) || ((col_offset > 0) && (col_offset >= n_cols)), "diagmat(): requested diagonal out of bounds" ); out.zeros(n_rows, n_cols); if(X.n_nonzero == 0) { return; } // TODO: this is a rudimentary implementation; replace with a faster version using iterators const uword N = (std::min)(n_rows - row_offset, n_cols - col_offset); for(uword i=0; i