// Copyright (C) 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 spdiagview //! @{ template inline spdiagview::~spdiagview() { arma_extra_debug_sigprint(); } template arma_inline spdiagview::spdiagview(const SpMat& in_m, const uword in_row_offset, const uword in_col_offset, const uword in_len) : m(in_m) , row_offset(in_row_offset) , col_offset(in_col_offset) , n_rows(in_len) , n_elem(in_len) { arma_extra_debug_sigprint(); } //! set a diagonal of our matrix using a diagonal from a foreign matrix template inline void spdiagview::operator= (const spdiagview& x) { arma_extra_debug_sigprint(); spdiagview& d = *this; arma_debug_check( (d.n_elem != x.n_elem), "spdiagview: diagonals have incompatible lengths"); SpMat& d_m = const_cast< SpMat& >(d.m); const SpMat& x_m = x.m; if(&d_m != &x_m) { const uword d_n_elem = d.n_elem; const uword d_row_offset = d.row_offset; const uword d_col_offset = d.col_offset; const uword x_row_offset = x.row_offset; const uword x_col_offset = x.col_offset; for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) = x_m.at(i + x_row_offset, i + x_col_offset); } } else { const Mat tmp = x; (*this).operator=(tmp); } } template inline void spdiagview::operator+=(const eT val) { arma_extra_debug_sigprint(); SpMat& t_m = const_cast< SpMat& >(m); const uword t_n_elem = n_elem; const uword t_row_offset = row_offset; const uword t_col_offset = col_offset; for(uword i=0; i < t_n_elem; ++i) { t_m.at(i + t_row_offset, i + t_col_offset) += val; } } template inline void spdiagview::operator-=(const eT val) { arma_extra_debug_sigprint(); SpMat& t_m = const_cast< SpMat& >(m); const uword t_n_elem = n_elem; const uword t_row_offset = row_offset; const uword t_col_offset = col_offset; for(uword i=0; i < t_n_elem; ++i) { t_m.at(i + t_row_offset, i + t_col_offset) -= val; } } template inline void spdiagview::operator*=(const eT val) { arma_extra_debug_sigprint(); SpMat& t_m = const_cast< SpMat& >(m); const uword t_n_elem = n_elem; const uword t_row_offset = row_offset; const uword t_col_offset = col_offset; for(uword i=0; i < t_n_elem; ++i) { t_m.at(i + t_row_offset, i + t_col_offset) *= val; } } template inline void spdiagview::operator/=(const eT val) { arma_extra_debug_sigprint(); SpMat& t_m = const_cast< SpMat& >(m); const uword t_n_elem = n_elem; const uword t_row_offset = row_offset; const uword t_col_offset = col_offset; for(uword i=0; i < t_n_elem; ++i) { t_m.at(i + t_row_offset, i + t_col_offset) /= val; } } //! set a diagonal of our matrix using data from a foreign object template template inline void spdiagview::operator= (const Base& o) { arma_extra_debug_sigprint(); spdiagview& d = *this; SpMat& d_m = const_cast< SpMat& >(d.m); const uword d_n_elem = d.n_elem; const uword d_row_offset = d.row_offset; const uword d_col_offset = d.col_offset; const Proxy P( o.get_ref() ); arma_debug_check ( ( (d_n_elem != P.get_n_elem()) || ((P.get_n_rows() != 1) && (P.get_n_cols() != 1)) ), "spdiagview: given object has incompatible size" ); if( (is_Mat::stored_type>::value) || (Proxy::prefer_at_accessor) ) { const unwrap::stored_type> tmp(P.Q); const Mat& x = tmp.M; const eT* x_mem = x.memptr(); for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) = x_mem[i]; } } else { typename Proxy::ea_type Pea = P.get_ea(); for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) = Pea[i]; } } } template template inline void spdiagview::operator+=(const Base& o) { arma_extra_debug_sigprint(); spdiagview& d = *this; SpMat& d_m = const_cast< SpMat& >(d.m); const uword d_n_elem = d.n_elem; const uword d_row_offset = d.row_offset; const uword d_col_offset = d.col_offset; const Proxy P( o.get_ref() ); arma_debug_check ( ( (d_n_elem != P.get_n_elem()) || ((P.get_n_rows() != 1) && (P.get_n_cols() != 1)) ), "spdiagview: given object has incompatible size" ); if( (is_Mat::stored_type>::value) || (Proxy::prefer_at_accessor) ) { const unwrap::stored_type> tmp(P.Q); const Mat& x = tmp.M; const eT* x_mem = x.memptr(); for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) += x_mem[i]; } } else { typename Proxy::ea_type Pea = P.get_ea(); for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) += Pea[i]; } } } template template inline void spdiagview::operator-=(const Base& o) { arma_extra_debug_sigprint(); spdiagview& d = *this; SpMat& d_m = const_cast< SpMat& >(d.m); const uword d_n_elem = d.n_elem; const uword d_row_offset = d.row_offset; const uword d_col_offset = d.col_offset; const Proxy P( o.get_ref() ); arma_debug_check ( ( (d_n_elem != P.get_n_elem()) || ((P.get_n_rows() != 1) && (P.get_n_cols() != 1)) ), "spdiagview: given object has incompatible size" ); if( (is_Mat::stored_type>::value) || (Proxy::prefer_at_accessor) ) { const unwrap::stored_type> tmp(P.Q); const Mat& x = tmp.M; const eT* x_mem = x.memptr(); for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) -= x_mem[i]; } } else { typename Proxy::ea_type Pea = P.get_ea(); for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) -= Pea[i]; } } } template template inline void spdiagview::operator%=(const Base& o) { arma_extra_debug_sigprint(); spdiagview& d = *this; SpMat& d_m = const_cast< SpMat& >(d.m); const uword d_n_elem = d.n_elem; const uword d_row_offset = d.row_offset; const uword d_col_offset = d.col_offset; const Proxy P( o.get_ref() ); arma_debug_check ( ( (d_n_elem != P.get_n_elem()) || ((P.get_n_rows() != 1) && (P.get_n_cols() != 1)) ), "spdiagview: given object has incompatible size" ); if( (is_Mat::stored_type>::value) || (Proxy::prefer_at_accessor) ) { const unwrap::stored_type> tmp(P.Q); const Mat& x = tmp.M; const eT* x_mem = x.memptr(); for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) *= x_mem[i]; } } else { typename Proxy::ea_type Pea = P.get_ea(); for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) *= Pea[i]; } } } template template inline void spdiagview::operator/=(const Base& o) { arma_extra_debug_sigprint(); spdiagview& d = *this; SpMat& d_m = const_cast< SpMat& >(d.m); const uword d_n_elem = d.n_elem; const uword d_row_offset = d.row_offset; const uword d_col_offset = d.col_offset; const Proxy P( o.get_ref() ); arma_debug_check ( ( (d_n_elem != P.get_n_elem()) || ((P.get_n_rows() != 1) && (P.get_n_cols() != 1)) ), "spdiagview: given object has incompatible size" ); if( (is_Mat::stored_type>::value) || (Proxy::prefer_at_accessor) ) { const unwrap::stored_type> tmp(P.Q); const Mat& x = tmp.M; const eT* x_mem = x.memptr(); for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) /= x_mem[i]; } } else { typename Proxy::ea_type Pea = P.get_ea(); for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) /= Pea[i]; } } } //! set a diagonal of our matrix using data from a foreign object template template inline void spdiagview::operator= (const SpBase& o) { arma_extra_debug_sigprint(); spdiagview& d = *this; SpMat& d_m = const_cast< SpMat& >(d.m); const uword d_n_elem = d.n_elem; const uword d_row_offset = d.row_offset; const uword d_col_offset = d.col_offset; const SpProxy P( o.get_ref() ); arma_debug_check ( ( (d_n_elem != P.get_n_elem()) || ((P.get_n_rows() != 1) && (P.get_n_cols() != 1)) ), "spdiagview: given object has incompatible size" ); if( SpProxy::must_use_iterator || P.is_alias(d_m) ) { const SpMat tmp(P.Q); if(tmp.n_cols == 1) { for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) = tmp.at(i,0); } } else if(tmp.n_rows == 1) { for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) = tmp.at(0,i); } } } else { if(P.get_n_cols() == 1) { for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) = P.at(i,0); } } else if(P.get_n_rows() == 1) { for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) = P.at(0,i); } } } } template template inline void spdiagview::operator+=(const SpBase& o) { arma_extra_debug_sigprint(); spdiagview& d = *this; SpMat& d_m = const_cast< SpMat& >(d.m); const uword d_n_elem = d.n_elem; const uword d_row_offset = d.row_offset; const uword d_col_offset = d.col_offset; const SpProxy P( o.get_ref() ); arma_debug_check ( ( (d_n_elem != P.get_n_elem()) || ((P.get_n_rows() != 1) && (P.get_n_cols() != 1)) ), "spdiagview: given object has incompatible size" ); if( SpProxy::must_use_iterator || P.is_alias(d_m) ) { const SpMat tmp(P.Q); if(tmp.n_cols == 1) { for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) += tmp.at(i,0); } } else if(tmp.n_rows == 1) { for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) += tmp.at(0,i); } } } else { if(P.get_n_cols() == 1) { for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) += P.at(i,0); } } else if(P.get_n_rows() == 1) { for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) += P.at(0,i); } } } } template template inline void spdiagview::operator-=(const SpBase& o) { arma_extra_debug_sigprint(); spdiagview& d = *this; SpMat& d_m = const_cast< SpMat& >(d.m); const uword d_n_elem = d.n_elem; const uword d_row_offset = d.row_offset; const uword d_col_offset = d.col_offset; const SpProxy P( o.get_ref() ); arma_debug_check ( ( (d_n_elem != P.get_n_elem()) || ((P.get_n_rows() != 1) && (P.get_n_cols() != 1)) ), "spdiagview: given object has incompatible size" ); if( SpProxy::must_use_iterator || P.is_alias(d_m) ) { const SpMat tmp(P.Q); if(tmp.n_cols == 1) { for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) -= tmp.at(i,0); } } else if(tmp.n_rows == 1) { for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) -= tmp.at(0,i); } } } else { if(P.get_n_cols() == 1) { for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) -= P.at(i,0); } } else if(P.get_n_rows() == 1) { for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) -= P.at(0,i); } } } } template template inline void spdiagview::operator%=(const SpBase& o) { arma_extra_debug_sigprint(); spdiagview& d = *this; SpMat& d_m = const_cast< SpMat& >(d.m); const uword d_n_elem = d.n_elem; const uword d_row_offset = d.row_offset; const uword d_col_offset = d.col_offset; const SpProxy P( o.get_ref() ); arma_debug_check ( ( (d_n_elem != P.get_n_elem()) || ((P.get_n_rows() != 1) && (P.get_n_cols() != 1)) ), "spdiagview: given object has incompatible size" ); if( SpProxy::must_use_iterator || P.is_alias(d_m) ) { const SpMat tmp(P.Q); if(tmp.n_cols == 1) { for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) *= tmp.at(i,0); } } else if(tmp.n_rows == 1) { for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) *= tmp.at(0,i); } } } else { if(P.get_n_cols() == 1) { for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) *= P.at(i,0); } } else if(P.get_n_rows() == 1) { for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) *= P.at(0,i); } } } } template template inline void spdiagview::operator/=(const SpBase& o) { arma_extra_debug_sigprint(); spdiagview& d = *this; SpMat& d_m = const_cast< SpMat& >(d.m); const uword d_n_elem = d.n_elem; const uword d_row_offset = d.row_offset; const uword d_col_offset = d.col_offset; const SpProxy P( o.get_ref() ); arma_debug_check ( ( (d_n_elem != P.get_n_elem()) || ((P.get_n_rows() != 1) && (P.get_n_cols() != 1)) ), "spdiagview: given object has incompatible size" ); if( SpProxy::must_use_iterator || P.is_alias(d_m) ) { const SpMat tmp(P.Q); if(tmp.n_cols == 1) { for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) /= tmp.at(i,0); } } else if(tmp.n_rows == 1) { for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) /= tmp.at(0,i); } } } else { if(P.get_n_cols() == 1) { for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) /= P.at(i,0); } } else if(P.get_n_rows() == 1) { for(uword i=0; i < d_n_elem; ++i) { d_m.at(i + d_row_offset, i + d_col_offset) /= P.at(0,i); } } } } //! extract a diagonal and store it as a dense column vector template inline void spdiagview::extract(Mat& out, const spdiagview& in) { arma_extra_debug_sigprint(); // NOTE: we're assuming that the 'out' matrix has already been set to the correct size; // size setting is done by either the Mat contructor or Mat::operator=() const SpMat& in_m = in.m; const uword in_n_elem = in.n_elem; const uword in_row_offset = in.row_offset; const uword in_col_offset = in.col_offset; eT* out_mem = out.memptr(); for(uword i=0; i < in_n_elem; ++i) { out_mem[i] = in_m.at(i + in_row_offset, i + in_col_offset ); } } template inline eT spdiagview::at_alt(const uword i) const { return m.at(i+row_offset, i+col_offset); } template inline SpValProxy< SpMat > spdiagview::operator[](const uword i) { return (const_cast< SpMat& >(m)).at(i+row_offset, i+col_offset); } template inline eT spdiagview::operator[](const uword i) const { return m.at(i+row_offset, i+col_offset); } template inline SpValProxy< SpMat > spdiagview::at(const uword i) { return (const_cast< SpMat& >(m)).at(i+row_offset, i+col_offset); } template inline eT spdiagview::at(const uword i) const { return m.at(i+row_offset, i+col_offset); } template inline SpValProxy< SpMat > spdiagview::operator()(const uword i) { arma_debug_check( (i >= n_elem), "spdiagview::operator(): out of bounds" ); return (const_cast< SpMat& >(m)).at(i+row_offset, i+col_offset); } template inline eT spdiagview::operator()(const uword i) const { arma_debug_check( (i >= n_elem), "spdiagview::operator(): out of bounds" ); return m.at(i+row_offset, i+col_offset); } template inline SpValProxy< SpMat > spdiagview::at(const uword row, const uword) { return (const_cast< SpMat& >(m)).at(row+row_offset, row+col_offset); } template inline eT spdiagview::at(const uword row, const uword) const { return m.at(row+row_offset, row+col_offset); } template inline SpValProxy< SpMat > spdiagview::operator()(const uword row, const uword col) { arma_debug_check( ((row >= n_elem) || (col > 0)), "spdiagview::operator(): out of bounds" ); return (const_cast< SpMat& >(m)).at(row+row_offset, row+col_offset); } template inline eT spdiagview::operator()(const uword row, const uword col) const { arma_debug_check( ((row >= n_elem) || (col > 0)), "spdiagview::operator(): out of bounds" ); return m.at(row+row_offset, row+col_offset); } template inline void spdiagview::fill(const eT val) { arma_extra_debug_sigprint(); SpMat& x = const_cast< SpMat& >(m); const uword local_n_elem = n_elem; for(uword i=0; i < local_n_elem; ++i) { x.at(i+row_offset, i+col_offset) = val; } } template inline void spdiagview::zeros() { arma_extra_debug_sigprint(); (*this).fill(eT(0)); } template inline void spdiagview::ones() { arma_extra_debug_sigprint(); (*this).fill(eT(1)); } template inline void spdiagview::randu() { arma_extra_debug_sigprint(); SpMat& x = const_cast< SpMat& >(m); const uword local_n_elem = n_elem; for(uword i=0; i < local_n_elem; ++i) { x.at(i+row_offset, i+col_offset) = eT(arma_rng::randu()); } } template inline void spdiagview::randn() { arma_extra_debug_sigprint(); SpMat& x = const_cast< SpMat& >(m); const uword local_n_elem = n_elem; for(uword i=0; i < local_n_elem; ++i) { x.at(i+row_offset, i+col_offset) = eT(arma_rng::randn()); } } //! @}