| Mat_meat.hpp | | Mat_meat.hpp | |
| | | | |
| skipping to change at line 1833 | | skipping to change at line 1833 | |
| | | | |
| const SpProxy<T1> p(m.get_ref()); | | const SpProxy<T1> p(m.get_ref()); | |
| | | | |
| access::rw(n_rows) = p.get_n_rows(); | | access::rw(n_rows) = p.get_n_rows(); | |
| access::rw(n_cols) = p.get_n_cols(); | | access::rw(n_cols) = p.get_n_cols(); | |
| access::rw(n_elem) = p.get_n_elem(); | | access::rw(n_elem) = p.get_n_elem(); | |
| | | | |
| init_cold(); | | init_cold(); | |
| fill(eT(0)); | | fill(eT(0)); | |
| | | | |
|
| // Iterate over each nonzero element and set it. | | typename SpProxy<T1>::const_iterator_type it = p.begin(); | |
| for(typename SpProxy<T1>::const_iterator_type it = p.begin(); it != p.end | | typename SpProxy<T1>::const_iterator_type it_end = p.end(); | |
| (); ++it) | | | |
| | | while(it != it_end) | |
| { | | { | |
| at(it.row(), it.col()) = (*it); | | at(it.row(), it.col()) = (*it); | |
|
| | | ++it; | |
| } | | } | |
| } | | } | |
| | | | |
| template<typename eT> | | template<typename eT> | |
| template<typename T1> | | template<typename T1> | |
| inline | | inline | |
| const Mat<eT>& | | const Mat<eT>& | |
| Mat<eT>::operator=(const SpBase<eT, T1>& m) | | Mat<eT>::operator=(const SpBase<eT, T1>& m) | |
| { | | { | |
| arma_extra_debug_sigprint(); | | arma_extra_debug_sigprint(); | |
| | | | |
| const SpProxy<T1> p(m.get_ref()); | | const SpProxy<T1> p(m.get_ref()); | |
| | | | |
| init_warm(p.get_n_rows(), p.get_n_cols()); | | init_warm(p.get_n_rows(), p.get_n_cols()); | |
| | | | |
| fill(eT(0)); | | fill(eT(0)); | |
| | | | |
|
| for(typename SpProxy<T1>::const_iterator_type it = p.begin(); it != p.end | | typename SpProxy<T1>::const_iterator_type it = p.begin(); | |
| (); ++it) | | typename SpProxy<T1>::const_iterator_type it_end = p.end(); | |
| | | | |
| | | while(it != it_end) | |
| { | | { | |
| at(it.row(), it.col()) = (*it); | | at(it.row(), it.col()) = (*it); | |
|
| | | ++it; | |
| } | | } | |
| | | | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| template<typename eT> | | template<typename eT> | |
| template<typename T1> | | template<typename T1> | |
| inline | | inline | |
| const Mat<eT>& | | const Mat<eT>& | |
| Mat<eT>::operator+=(const SpBase<eT, T1>& m) | | Mat<eT>::operator+=(const SpBase<eT, T1>& m) | |
| { | | { | |
| arma_extra_debug_sigprint(); | | arma_extra_debug_sigprint(); | |
| | | | |
| const SpProxy<T1> p(m.get_ref()); | | const SpProxy<T1> p(m.get_ref()); | |
| | | | |
| arma_debug_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(
), "addition"); | | arma_debug_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(
), "addition"); | |
| | | | |
|
| for(typename SpProxy<T1>::const_iterator_type it = p.begin(); it != p.end | | typename SpProxy<T1>::const_iterator_type it = p.begin(); | |
| (); ++it) | | typename SpProxy<T1>::const_iterator_type it_end = p.end(); | |
| | | | |
| | | while(it != it_end) | |
| { | | { | |
| at(it.row(), it.col()) += (*it); | | at(it.row(), it.col()) += (*it); | |
|
| | | ++it; | |
| } | | } | |
| | | | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| template<typename eT> | | template<typename eT> | |
| template<typename T1> | | template<typename T1> | |
| inline | | inline | |
| const Mat<eT>& | | const Mat<eT>& | |
| Mat<eT>::operator-=(const SpBase<eT, T1>& m) | | Mat<eT>::operator-=(const SpBase<eT, T1>& m) | |
| { | | { | |
| arma_extra_debug_sigprint(); | | arma_extra_debug_sigprint(); | |
| | | | |
| const SpProxy<T1> p(m.get_ref()); | | const SpProxy<T1> p(m.get_ref()); | |
| | | | |
| arma_debug_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(
), "subtraction"); | | arma_debug_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(
), "subtraction"); | |
| | | | |
|
| for(typename SpProxy<T1>::const_iterator_type it = p.begin(); it != p.end | | typename SpProxy<T1>::const_iterator_type it = p.begin(); | |
| (); ++it) | | typename SpProxy<T1>::const_iterator_type it_end = p.end(); | |
| | | | |
| | | while(it != it_end) | |
| { | | { | |
| at(it.row(), it.col()) -= (*it); | | at(it.row(), it.col()) -= (*it); | |
|
| | | ++it; | |
| } | | } | |
| | | | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| template<typename eT> | | template<typename eT> | |
| template<typename T1> | | template<typename T1> | |
| inline | | inline | |
| const Mat<eT>& | | const Mat<eT>& | |
| Mat<eT>::operator*=(const SpBase<eT, T1>& m) | | Mat<eT>::operator*=(const SpBase<eT, T1>& m) | |
| | | | |
| skipping to change at line 1929 | | skipping to change at line 1944 | |
| inline | | inline | |
| const Mat<eT>& | | const Mat<eT>& | |
| Mat<eT>::operator%=(const SpBase<eT, T1>& m) | | Mat<eT>::operator%=(const SpBase<eT, T1>& m) | |
| { | | { | |
| arma_extra_debug_sigprint(); | | arma_extra_debug_sigprint(); | |
| | | | |
| const SpProxy<T1> p(m.get_ref()); | | const SpProxy<T1> p(m.get_ref()); | |
| | | | |
| arma_debug_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(
), "element-wise multiplication"); | | arma_debug_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(
), "element-wise multiplication"); | |
| | | | |
|
| typename SpProxy<T1>::const_iterator_type it = p.begin(); | | typename SpProxy<T1>::const_iterator_type it = p.begin(); | |
| | | typename SpProxy<T1>::const_iterator_type it_end = p.end(); | |
| | | | |
| // We have to zero everything that isn't being used. | | // We have to zero everything that isn't being used. | |
| arrayops::inplace_set(memptr(), eT(0), (it.col() * n_rows) + it.row()); | | arrayops::inplace_set(memptr(), eT(0), (it.col() * n_rows) + it.row()); | |
| | | | |
|
| while(it != p.end()) | | while(it != it_end) | |
| { | | { | |
| const uword cur_loc = (it.col() * n_rows) + it.row(); | | const uword cur_loc = (it.col() * n_rows) + it.row(); | |
| | | | |
| access::rw(mem[cur_loc]) *= (*it); | | access::rw(mem[cur_loc]) *= (*it); | |
| | | | |
| ++it; | | ++it; | |
| | | | |
|
| const uword next_loc = (it == p.end()) | | const uword next_loc = (it == it_end) | |
| ? (p.get_n_cols() * n_rows) | | ? (p.get_n_cols() * n_rows) | |
| : (it.col() * n_rows) + it.row(); | | : (it.col() * n_rows) + it.row(); | |
| | | | |
| arrayops::inplace_set(memptr() + cur_loc + 1, eT(0), (next_loc - cur_lo
c - 1)); | | arrayops::inplace_set(memptr() + cur_loc + 1, eT(0), (next_loc - cur_lo
c - 1)); | |
| } | | } | |
| | | | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| template<typename eT> | | template<typename eT> | |
| | | | |
| skipping to change at line 1967 | | skipping to change at line 1983 | |
| { | | { | |
| arma_extra_debug_sigprint(); | | arma_extra_debug_sigprint(); | |
| | | | |
| const SpProxy<T1> p(m.get_ref()); | | const SpProxy<T1> p(m.get_ref()); | |
| | | | |
| arma_debug_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(
), "element-wise division"); | | arma_debug_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols(
), "element-wise division"); | |
| | | | |
| // If you use this method, you are probably stupid or misguided, but for
completeness it is implemented. | | // If you use this method, you are probably stupid or misguided, but for
completeness it is implemented. | |
| // Unfortunately the best way to do this is loop over every element. | | // Unfortunately the best way to do this is loop over every element. | |
| for(uword c = 0; c < n_cols; ++c) | | for(uword c = 0; c < n_cols; ++c) | |
|
| | | for(uword r = 0; r < n_rows; ++r) | |
| { | | { | |
|
| for(uword r = 0; r < n_rows; ++r) | | at(r, c) /= p.at(r, c); | |
| { | | | |
| at(r, c) /= p.at(r, c); | | | |
| } | | | |
| } | | } | |
| | | | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| template<typename eT> | | template<typename eT> | |
| inline | | inline | |
| mat_injector< Mat<eT> > | | mat_injector< Mat<eT> > | |
| Mat<eT>::operator<<(const eT val) | | Mat<eT>::operator<<(const eT val) | |
| { | | { | |
| | | | |
End of changes. 13 change blocks. |
| 16 lines changed or deleted | | 26 lines changed or added | |
|
| Op_bones.hpp | | Op_bones.hpp | |
| | | | |
| skipping to change at line 35 | | skipping to change at line 35 | |
| | | | |
| template<typename T1, typename op_type> | | template<typename T1, typename op_type> | |
| class Op : public Base<typename T1::elem_type, Op<T1, op_type> > | | class Op : public Base<typename T1::elem_type, Op<T1, op_type> > | |
| { | | { | |
| public: | | public: | |
| | | | |
| typedef typename T1::elem_type elem_type; | | typedef typename T1::elem_type elem_type; | |
| typedef typename get_pod_type<elem_type>::result pod_type; | | typedef typename get_pod_type<elem_type>::result pod_type; | |
| | | | |
| static const bool is_row = ( T1::is_col && (is_same_type<op_type, op_stra
ns>::value || is_same_type<op_type, op_htrans>::value || is_same_type<op_ty
pe, op_htrans2>::value) ); | | static const bool is_row = ( T1::is_col && (is_same_type<op_type, op_stra
ns>::value || is_same_type<op_type, op_htrans>::value || is_same_type<op_ty
pe, op_htrans2>::value) ); | |
|
| static const bool is_col = ( T1::is_row && (is_same_type<op_type, op_stra
ns>::value || is_same_type<op_type, op_htrans>::value || is_same_type<op_ty
pe, op_htrans2>::value) ); | | static const bool is_col = ( T1::is_row && (is_same_type<op_type, op_stra
ns>::value || is_same_type<op_type, op_htrans>::value || is_same_type<op_ty
pe, op_htrans2>::value) ) || (is_same_type<op_type, op_diagvec>::value); | |
| | | | |
| inline explicit Op(const T1& in_m); | | inline explicit Op(const T1& in_m); | |
| inline Op(const T1& in_m, const elem_type in_aux); | | inline Op(const T1& in_m, const elem_type in_aux); | |
| inline Op(const T1& in_m, const elem_type in_aux, const
uword in_aux_uword_a, const uword in_aux_uword_b); | | inline Op(const T1& in_m, const elem_type in_aux, const
uword in_aux_uword_a, const uword in_aux_uword_b); | |
| inline Op(const T1& in_m, const uword in_aux_uword_a, const
uword in_aux_uword_b); | | inline Op(const T1& in_m, const uword in_aux_uword_a, const
uword in_aux_uword_b); | |
| inline Op(const T1& in_m, const uword in_aux_uword_a, const
uword in_aux_uword_b, const uword in_aux_uword_c, const char junk); | | inline Op(const T1& in_m, const uword in_aux_uword_a, const
uword in_aux_uword_b, const uword in_aux_uword_c, const char junk); | |
| inline ~Op(); | | inline ~Op(); | |
| | | | |
| arma_aligned const T1& m; //!< storage of reference to t
he operand (eg. a matrix) | | arma_aligned const T1& m; //!< storage of reference to t
he operand (eg. a matrix) | |
| arma_aligned elem_type aux; //!< storage of auxiliary data
, user defined format | | arma_aligned elem_type aux; //!< storage of auxiliary data
, user defined format | |
| | | | |
End of changes. 1 change blocks. |
| 1 lines changed or deleted | | 1 lines changed or added | |
|
| Proxy.hpp | | Proxy.hpp | |
| | | | |
| skipping to change at line 280 | | skipping to change at line 280 | |
| arma_inline elem_type operator[] (const uword i) const
{ return Q[i]; } | | arma_inline elem_type operator[] (const uword i) const
{ return Q[i]; } | |
| arma_inline elem_type at (const uword row, const uword col) const
{ return Q.at(row, col); } | | arma_inline elem_type at (const uword row, const uword col) const
{ return Q.at(row, col); } | |
| | | | |
| arma_inline ea_type get_ea() const { return Q.memptr(); } | | arma_inline ea_type get_ea() const { return Q.memptr(); } | |
| | | | |
| template<typename eT2> | | template<typename eT2> | |
| arma_inline bool is_alias(const Mat<eT2>&) const { return false; } | | arma_inline bool is_alias(const Mat<eT2>&) const { return false; } | |
| }; | | }; | |
| | | | |
| template<typename T1> | | template<typename T1> | |
|
| | | class Proxy_diagvec_mat | |
| | | { | |
| | | inline Proxy_diagvec_mat(const T1&) {} | |
| | | }; | |
| | | | |
| | | template<typename T1> | |
| | | class Proxy_diagvec_mat< Op<T1, op_diagvec> > | |
| | | { | |
| | | public: | |
| | | | |
| | | typedef typename T1::elem_type elem_type; | |
| | | typedef typename get_pod_type<elem_type>::result pod_type; | |
| | | typedef diagview<elem_type> stored_type; | |
| | | typedef const diagview<elem_type>& ea_type; | |
| | | | |
| | | static const bool prefer_at_accessor = false; | |
| | | static const bool has_subview = true; | |
| | | static const bool is_fixed = false; | |
| | | static const bool fake_mat = false; | |
| | | | |
| | | static const bool is_row = false; | |
| | | static const bool is_col = true; | |
| | | | |
| | | arma_aligned const Mat<elem_type>& R; | |
| | | arma_aligned const diagview<elem_type> Q; | |
| | | | |
| | | inline explicit Proxy_diagvec_mat(const Op<T1, op_diagvec>& A) | |
| | | : R(A.m), Q( R.diag( (A.aux_uword_b > 0) ? -sword(A.aux_uword_a) : swor | |
| | | d(A.aux_uword_a) ) ) | |
| | | { | |
| | | arma_extra_debug_sigprint(); | |
| | | } | |
| | | | |
| | | arma_inline uword get_n_rows() const { return Q.n_rows; } | |
| | | arma_inline uword get_n_cols() const { return 1; } | |
| | | arma_inline uword get_n_elem() const { return Q.n_elem; } | |
| | | | |
| | | arma_inline elem_type operator[] (const uword i) const { r | |
| | | eturn Q[i]; } | |
| | | arma_inline elem_type at (const uword row, const uword) const { r | |
| | | eturn Q.at(row, 0); } | |
| | | | |
| | | arma_inline ea_type get_ea() const { return Q; } | |
| | | | |
| | | template<typename eT2> | |
| | | arma_inline bool is_alias(const Mat<eT2>& X) const { return (void_ptr(&R) | |
| | | == void_ptr(&X)); } | |
| | | }; | |
| | | | |
| | | template<typename T1> | |
| | | class Proxy_diagvec_expr | |
| | | { | |
| | | inline Proxy_diagvec_expr(const T1&) {} | |
| | | }; | |
| | | | |
| | | template<typename T1> | |
| | | class Proxy_diagvec_expr< Op<T1, op_diagvec> > | |
| | | { | |
| | | public: | |
| | | | |
| | | typedef typename T1::elem_type elem_type; | |
| | | typedef typename get_pod_type<elem_type>::result pod_type; | |
| | | typedef Mat<elem_type> stored_type; | |
| | | typedef const elem_type* ea_type; | |
| | | | |
| | | static const bool prefer_at_accessor = false; | |
| | | static const bool has_subview = false; | |
| | | static const bool is_fixed = false; | |
| | | static const bool fake_mat = false; | |
| | | | |
| | | static const bool is_row = false; | |
| | | static const bool is_col = true; | |
| | | | |
| | | arma_aligned const Mat<elem_type> Q; | |
| | | | |
| | | inline explicit Proxy_diagvec_expr(const Op<T1, op_diagvec>& A) | |
| | | : Q(A) | |
| | | { | |
| | | arma_extra_debug_sigprint(); | |
| | | } | |
| | | | |
| | | arma_inline uword get_n_rows() const { return Q.n_rows; } | |
| | | arma_inline uword get_n_cols() const { return 1; } | |
| | | arma_inline uword get_n_elem() const { return Q.n_elem; } | |
| | | | |
| | | arma_inline elem_type operator[] (const uword i) const { r | |
| | | eturn Q[i]; } | |
| | | arma_inline elem_type at (const uword row, const uword) const { r | |
| | | eturn Q.at(row, 0); } | |
| | | | |
| | | arma_inline ea_type get_ea() const { return Q.memptr(); } | |
| | | | |
| | | template<typename eT2> | |
| | | arma_inline bool is_alias(const Mat<eT2>&) const { return false; } | |
| | | }; | |
| | | | |
| | | template<typename T1, bool condition> | |
| | | struct Proxy_diagvec_redirect {}; | |
| | | | |
| | | template<typename T1> | |
| | | struct Proxy_diagvec_redirect< Op<T1, op_diagvec>, true > { typedef Proxy_d | |
| | | iagvec_mat < Op<T1, op_diagvec> > result; }; | |
| | | | |
| | | template<typename T1> | |
| | | struct Proxy_diagvec_redirect< Op<T1, op_diagvec>, false> { typedef Proxy_d | |
| | | iagvec_expr< Op<T1, op_diagvec> > result; }; | |
| | | | |
| | | template<typename T1> | |
| | | class Proxy< Op<T1, op_diagvec> > | |
| | | : public Proxy_diagvec_redirect< Op<T1, op_diagvec>, is_Mat<T1>::value >: | |
| | | :result | |
| | | { | |
| | | public: | |
| | | | |
| | | typedef typename Proxy_diagvec_redirect< Op<T1, op_diagvec>, is_Mat<T1>:: | |
| | | value >::result Proxy_diagvec; | |
| | | | |
| | | inline explicit Proxy(const Op<T1, op_diagvec>& A) | |
| | | : Proxy_diagvec(A) | |
| | | { | |
| | | arma_extra_debug_sigprint(); | |
| | | } | |
| | | }; | |
| | | | |
| | | template<typename T1> | |
| struct Proxy_xtrans_default | | struct Proxy_xtrans_default | |
| { | | { | |
| typedef typename T1::elem_type eT; | | typedef typename T1::elem_type eT; | |
| | | | |
| static const bool prefer_at_accessor = false; | | static const bool prefer_at_accessor = false; | |
| static const bool has_subview = false; | | static const bool has_subview = false; | |
| static const bool is_fixed = false; | | static const bool is_fixed = false; | |
| static const bool fake_mat = false; | | static const bool fake_mat = false; | |
| | | | |
| arma_aligned const Mat<eT> Q; | | arma_aligned const Mat<eT> Q; | |
| | | | |
End of changes. 1 change blocks. |
| 0 lines changed or deleted | | 125 lines changed or added | |
|
| SpMat_meat.hpp | | SpMat_meat.hpp | |
| | | | |
| skipping to change at line 178 | | skipping to change at line 178 | |
| // Resize to 1x1 then set that to the right value. | | // Resize to 1x1 then set that to the right value. | |
| init(1, 1); // Sets col_ptrs to 0. | | init(1, 1); // Sets col_ptrs to 0. | |
| mem_resize(1); // One element. | | mem_resize(1); // One element. | |
| | | | |
| // Manually set element. | | // Manually set element. | |
| access::rw(values[0]) = val; | | access::rw(values[0]) = val; | |
| access::rw(row_indices[0]) = 0; | | access::rw(row_indices[0]) = 0; | |
| access::rw(col_ptrs[1]) = 1; | | access::rw(col_ptrs[1]) = 1; | |
| | | | |
| return *this; | | return *this; | |
|
| | | | |
| } | | } | |
| | | | |
| template<typename eT> | | template<typename eT> | |
| inline | | inline | |
| const SpMat<eT>& | | const SpMat<eT>& | |
| SpMat<eT>::operator*=(const eT val) | | SpMat<eT>::operator*=(const eT val) | |
| { | | { | |
| arma_extra_debug_sigprint(); | | arma_extra_debug_sigprint(); | |
| | | | |
| if(val == eT(0)) | | if(val == eT(0)) | |
| { | | { | |
| // Everything will be zero. | | // Everything will be zero. | |
| init(n_rows, n_cols); | | init(n_rows, n_cols); | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
|
| // Iterate over nonzero values, which is a lot faster. | | | |
| | | | |
| // for(uword i = 0; i < n_nonzero; ++i) | | | |
| // { | | | |
| // access::rw(values[i]) *= val; | | | |
| // } | | | |
| | | | |
| arrayops::inplace_mul( access::rwp(values), val, n_nonzero ); | | arrayops::inplace_mul( access::rwp(values), val, n_nonzero ); | |
| | | | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| template<typename eT> | | template<typename eT> | |
| inline | | inline | |
| const SpMat<eT>& | | const SpMat<eT>& | |
| SpMat<eT>::operator/=(const eT val) | | SpMat<eT>::operator/=(const eT val) | |
| { | | { | |
| arma_extra_debug_sigprint(); | | arma_extra_debug_sigprint(); | |
| | | | |
| arma_debug_check( (val == eT(0)), "element-wise division: division by zer
o" ); | | arma_debug_check( (val == eT(0)), "element-wise division: division by zer
o" ); | |
| | | | |
|
| // We only have to loop over nonzero values. | | arrayops::inplace_div( access::rwp(values), val, n_nonzero ); | |
| for (uword i = 0; i < n_nonzero; ++i) | | | |
| { | | | |
| access::rw(values[i]) /= val; | | | |
| } | | | |
| | | | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| template<typename eT> | | template<typename eT> | |
| inline | | inline | |
| const SpMat<eT>& | | const SpMat<eT>& | |
| SpMat<eT>::operator=(const SpMat<eT>& x) | | SpMat<eT>::operator=(const SpMat<eT>& x) | |
| { | | { | |
| arma_extra_debug_sigprint(); | | arma_extra_debug_sigprint(); | |
| | | | |
| skipping to change at line 502 | | skipping to change at line 490 | |
| const uword x_n_cols = p.get_n_cols(); | | const uword x_n_cols = p.get_n_cols(); | |
| const uword x_n_elem = p.get_n_elem(); | | const uword x_n_elem = p.get_n_elem(); | |
| | | | |
| init(x_n_rows, x_n_cols); | | init(x_n_rows, x_n_cols); | |
| | | | |
| // Count number of nonzero elements in base object. | | // Count number of nonzero elements in base object. | |
| uword n = 0; | | uword n = 0; | |
| if(Proxy<T1>::prefer_at_accessor == true) | | if(Proxy<T1>::prefer_at_accessor == true) | |
| { | | { | |
| for(uword j = 0; j < x_n_cols; ++j) | | for(uword j = 0; j < x_n_cols; ++j) | |
|
| | | for(uword i = 0; i < x_n_rows; ++i) | |
| { | | { | |
|
| for(uword i = 0; i < x_n_rows; ++i) | | if(p.at(i, j) != eT(0)) { ++n; } | |
| { | | | |
| if(p.at(i, j) != eT(0)) | | | |
| ++n; | | | |
| } | | | |
| } | | } | |
| } | | } | |
| else | | else | |
| { | | { | |
| for(uword i = 0; i < x_n_elem; ++i) | | for(uword i = 0; i < x_n_elem; ++i) | |
| { | | { | |
|
| if(p[i] != eT(0)) | | if(p[i] != eT(0)) { ++n; } | |
| { | | | |
| ++n; | | | |
| } | | | |
| } | | } | |
| } | | } | |
| | | | |
| mem_resize(n); | | mem_resize(n); | |
| | | | |
| // Now the memory is resized correctly; add nonzero elements. | | // Now the memory is resized correctly; add nonzero elements. | |
| n = 0; | | n = 0; | |
| for(uword j = 0; j < x_n_cols; ++j) | | for(uword j = 0; j < x_n_cols; ++j) | |
|
| | | for(uword i = 0; i < x_n_rows; ++i) | |
| { | | { | |
|
| for(uword i = 0; i < x_n_rows; ++i) | | const eT val = p.at(i, j); | |
| | | | |
| | | if(val != eT(0)) | |
| { | | { | |
|
| if(p.at(i, j) != eT(0)) | | access::rw(values[n]) = val; | |
| { | | access::rw(row_indices[n]) = i; | |
| access::rw(values[n]) = p.at(i, j); | | access::rw(col_ptrs[j + 1])++; | |
| access::rw(row_indices[n]) = i; | | ++n; | |
| access::rw(col_ptrs[j + 1])++; | | | |
| ++n; | | | |
| } | | | |
| } | | } | |
| } | | } | |
| | | | |
| // Sum column counts to be column pointers. | | // Sum column counts to be column pointers. | |
| for(uword c = 1; c <= n_cols; ++c) | | for(uword c = 1; c <= n_cols; ++c) | |
| { | | { | |
| access::rw(col_ptrs[c]) += col_ptrs[c - 1]; | | access::rw(col_ptrs[c]) += col_ptrs[c - 1]; | |
| } | | } | |
| | | | |
| return *this; | | return *this; | |
| | | | |
| skipping to change at line 640 | | skipping to change at line 622 | |
| | | | |
| // Resize to final correct size. | | // Resize to final correct size. | |
| z.mem_resize(z.col_ptrs[z.n_cols]); | | z.mem_resize(z.col_ptrs[z.n_cols]); | |
| | | | |
| // Now take the memory of the temporary matrix. | | // Now take the memory of the temporary matrix. | |
| steal_mem(z); | | steal_mem(z); | |
| | | | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
|
| | | /** | |
| | | * Don't use this function. It's not mathematically well-defined and waste | |
| | | s | |
| | | * cycles to trash all your data. This is dumb. | |
| | | */ | |
| template<typename eT> | | template<typename eT> | |
| template<typename T1> | | template<typename T1> | |
| inline | | inline | |
| const SpMat<eT>& | | const SpMat<eT>& | |
| SpMat<eT>::operator/=(const Base<eT, T1>& x) | | SpMat<eT>::operator/=(const Base<eT, T1>& x) | |
| { | | { | |
| arma_extra_debug_sigprint(); | | arma_extra_debug_sigprint(); | |
| | | | |
|
| const Proxy<T1> p(x.get_ref()); | | SpMat<eT> tmp = (*this) / x.get_ref(); | |
| | | | |
| /** | | | |
| * Don't use this function. It's not mathematically well-defined and was | | | |
| tes | | | |
| * cycles to trash all your data. This is dumb. | | | |
| */ | | | |
| arma_debug_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols( | | | |
| ), "element-wise division"); | | | |
| | | | |
|
| for(uword j = 0; j < n_cols; j++) | | steal_mem(tmp); | |
| for(uword i = 0; i < n_rows; i++) | | | |
| { | | | |
| at(i, j) /= p.at(i, j); | | | |
| } | | | |
| | | | |
| return *this; | | return *this; | |
| } | | } | |
| | | | |
| template<typename eT> | | template<typename eT> | |
| template<typename T1> | | template<typename T1> | |
| inline | | inline | |
| const SpMat<eT>& | | const SpMat<eT>& | |
| SpMat<eT>::operator%=(const Base<eT, T1>& x) | | SpMat<eT>::operator%=(const Base<eT, T1>& x) | |
| { | | { | |
| | | | |
End of changes. 12 change blocks. |
| 44 lines changed or deleted | | 19 lines changed or added | |
|
| compiler_setup.hpp | | compiler_setup.hpp | |
| | | | |
| skipping to change at line 22 | | skipping to change at line 22 | |
| | | | |
| #define arma_hot | | #define arma_hot | |
| #define arma_cold | | #define arma_cold | |
| #define arma_pure | | #define arma_pure | |
| #define arma_const | | #define arma_const | |
| #define arma_aligned | | #define arma_aligned | |
| #define arma_warn_unused | | #define arma_warn_unused | |
| #define arma_deprecated | | #define arma_deprecated | |
| #define arma_malloc | | #define arma_malloc | |
| #define arma_inline inline | | #define arma_inline inline | |
|
| | | #define arma_noinline | |
| #define arma_ignore(variable) ((void)(variable)) | | #define arma_ignore(variable) ((void)(variable)) | |
| | | | |
| #if defined(ARMA_BLAS_UNDERSCORE) | | #if defined(ARMA_BLAS_UNDERSCORE) | |
| #define arma_fortran2_noprefix(function) function##_ | | #define arma_fortran2_noprefix(function) function##_ | |
| #define arma_fortran2_prefix(function) wrapper_##function##_ | | #define arma_fortran2_prefix(function) wrapper_##function##_ | |
| #else | | #else | |
|
| #define arma_fortran2_prefix(function) wrapper_##function | | | |
| #define arma_fortran2_noprefix(function) function | | #define arma_fortran2_noprefix(function) function | |
|
| | | #define arma_fortran2_prefix(function) wrapper_##function | |
| #endif | | #endif | |
| | | | |
| #if defined(ARMA_USE_WRAPPER) | | #if defined(ARMA_USE_WRAPPER) | |
| #define arma_fortran(function) arma_fortran2_prefix(function) | | #define arma_fortran(function) arma_fortran2_prefix(function) | |
| #define arma_atlas(function) wrapper_##function | | #define arma_atlas(function) wrapper_##function | |
| #else | | #else | |
| #define arma_fortran(function) arma_fortran2_noprefix(function) | | #define arma_fortran(function) arma_fortran2_noprefix(function) | |
| #define arma_atlas(function) function | | #define arma_atlas(function) function | |
| #endif | | #endif | |
| | | | |
| | | | |
| skipping to change at line 69 | | skipping to change at line 70 | |
| | | | |
| #if (__GNUC__ < 4) | | #if (__GNUC__ < 4) | |
| #error "*** Need a newer compiler ***" | | #error "*** Need a newer compiler ***" | |
| #endif | | #endif | |
| | | | |
| #define ARMA_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNU
C_PATCHLEVEL__) | | #define ARMA_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNU
C_PATCHLEVEL__) | |
| | | | |
| #define ARMA_GOOD_COMPILER | | #define ARMA_GOOD_COMPILER | |
| #undef ARMA_HAVE_STD_TR1 | | #undef ARMA_HAVE_STD_TR1 | |
| | | | |
|
| #undef arma_cold | | | |
| #undef arma_pure | | #undef arma_pure | |
| #undef arma_const | | #undef arma_const | |
| #undef arma_aligned | | #undef arma_aligned | |
| #undef arma_warn_unused | | #undef arma_warn_unused | |
| #undef arma_deprecated | | #undef arma_deprecated | |
| #undef arma_malloc | | #undef arma_malloc | |
| #undef arma_inline | | #undef arma_inline | |
|
| | | #undef arma_noinline | |
| | | | |
|
| #define arma_cold __attribute__((__noinline__)) | | | |
| #define arma_pure __attribute__((__pure__)) | | #define arma_pure __attribute__((__pure__)) | |
| #define arma_const __attribute__((__const__)) | | #define arma_const __attribute__((__const__)) | |
| #define arma_aligned __attribute__((__aligned__)) | | #define arma_aligned __attribute__((__aligned__)) | |
| #define arma_warn_unused __attribute__((__warn_unused_result__)) | | #define arma_warn_unused __attribute__((__warn_unused_result__)) | |
| #define arma_deprecated __attribute__((__deprecated__)) | | #define arma_deprecated __attribute__((__deprecated__)) | |
| #define arma_malloc __attribute__((__malloc__)) | | #define arma_malloc __attribute__((__malloc__)) | |
| #define arma_inline inline __attribute__((__always_inline__)) | | #define arma_inline inline __attribute__((__always_inline__)) | |
|
| | | #define arma_noinline __attribute__((__noinline__)) | |
| | | | |
| #if (ARMA_GCC_VERSION >= 40300) | | #if (ARMA_GCC_VERSION >= 40300) | |
| #undef arma_hot | | #undef arma_hot | |
| #undef arma_cold | | #undef arma_cold | |
| | | | |
| #define arma_hot __attribute__((__hot__)) | | #define arma_hot __attribute__((__hot__)) | |
|
| #define arma_cold __attribute__((__cold__,__noinline__)) | | #define arma_cold __attribute__((__cold__)) | |
| #endif | | #endif | |
| | | | |
| #if (ARMA_GCC_VERSION >= 40200) | | #if (ARMA_GCC_VERSION >= 40200) | |
| #if defined(_GLIBCXX_USE_C99_MATH_TR1) && defined(_GLIBCXX_USE_C99_COMP
LEX_TR1) | | #if defined(_GLIBCXX_USE_C99_MATH_TR1) && defined(_GLIBCXX_USE_C99_COMP
LEX_TR1) | |
| #define ARMA_HAVE_STD_TR1 | | #define ARMA_HAVE_STD_TR1 | |
| #endif | | #endif | |
| #endif | | #endif | |
| | | | |
| #if defined(__GXX_EXPERIMENTAL_CXX0X__) | | #if defined(__GXX_EXPERIMENTAL_CXX0X__) | |
| #undef ARMA_HAVE_STD_TR1 | | #undef ARMA_HAVE_STD_TR1 | |
| | | | |
End of changes. 8 change blocks. |
| 4 lines changed or deleted | | 5 lines changed or added | |
|
| debug.hpp | | debug.hpp | |
| | | | |
| skipping to change at line 81 | | skipping to change at line 81 | |
| { | | { | |
| return arma_stream_err2<char>(NULL); | | return arma_stream_err2<char>(NULL); | |
| } | | } | |
| | | | |
| // | | // | |
| // arma_stop | | // arma_stop | |
| | | | |
| //! print a message to get_stream_err1() and/or throw a logic_error excepti
on | | //! print a message to get_stream_err1() and/or throw a logic_error excepti
on | |
| template<typename T1> | | template<typename T1> | |
| arma_cold | | arma_cold | |
|
| | | arma_noinline | |
| static | | static | |
| void | | void | |
| arma_stop(const T1& x) | | arma_stop(const T1& x) | |
| { | | { | |
| #if defined(ARMA_PRINT_LOGIC_ERRORS) | | #if defined(ARMA_PRINT_LOGIC_ERRORS) | |
| { | | { | |
| std::ostream& out = get_stream_err1(); | | std::ostream& out = get_stream_err1(); | |
| | | | |
| out.flush(); | | out.flush(); | |
| | | | |
| | | | |
| skipping to change at line 107 | | skipping to change at line 108 | |
| { | | { | |
| arma_ignore(x); | | arma_ignore(x); | |
| } | | } | |
| #endif | | #endif | |
| | | | |
| throw std::logic_error(""); | | throw std::logic_error(""); | |
| } | | } | |
| | | | |
| template<typename T1> | | template<typename T1> | |
| arma_cold | | arma_cold | |
|
| | | arma_noinline | |
| static | | static | |
| void | | void | |
| arma_stop_bad_alloc(const T1& x) | | arma_stop_bad_alloc(const T1& x) | |
| { | | { | |
| std::ostream& out = get_stream_err1(); | | std::ostream& out = get_stream_err1(); | |
| | | | |
| out.flush(); | | out.flush(); | |
| | | | |
| out << '\n'; | | out << '\n'; | |
| out << "error: " << x << '\n'; | | out << "error: " << x << '\n'; | |
| | | | |
| skipping to change at line 129 | | skipping to change at line 131 | |
| | | | |
| throw std::bad_alloc(); | | throw std::bad_alloc(); | |
| } | | } | |
| | | | |
| // | | // | |
| // arma_bad | | // arma_bad | |
| | | | |
| //! print a message to get_stream_err2() and/or throw a run-time error exce
ption | | //! print a message to get_stream_err2() and/or throw a run-time error exce
ption | |
| template<typename T1> | | template<typename T1> | |
| arma_cold | | arma_cold | |
|
| | | arma_noinline | |
| static | | static | |
| void | | void | |
| arma_bad(const T1& x, const bool hurl = true) | | arma_bad(const T1& x, const bool hurl = true) | |
| { | | { | |
| #if defined(ARMA_PRINT_RUNTIME_ERRORS) | | #if defined(ARMA_PRINT_RUNTIME_ERRORS) | |
| { | | { | |
| std::ostream& out = get_stream_err2(); | | std::ostream& out = get_stream_err2(); | |
| | | | |
| out.flush(); | | out.flush(); | |
| | | | |
| | | | |
| skipping to change at line 169 | | skipping to change at line 172 | |
| arma_cold | | arma_cold | |
| inline | | inline | |
| void | | void | |
| arma_print() | | arma_print() | |
| { | | { | |
| get_stream_err1() << std::endl; | | get_stream_err1() << std::endl; | |
| } | | } | |
| | | | |
| template<typename T1> | | template<typename T1> | |
| arma_cold | | arma_cold | |
|
| | | arma_noinline | |
| static | | static | |
| void | | void | |
| arma_print(const T1& x) | | arma_print(const T1& x) | |
| { | | { | |
| get_stream_err1() << x << std::endl; | | get_stream_err1() << x << std::endl; | |
| } | | } | |
| | | | |
| template<typename T1, typename T2> | | template<typename T1, typename T2> | |
| arma_cold | | arma_cold | |
|
| | | arma_noinline | |
| static | | static | |
| void | | void | |
| arma_print(const T1& x, const T2& y) | | arma_print(const T1& x, const T2& y) | |
| { | | { | |
| get_stream_err1() << x << y << std::endl; | | get_stream_err1() << x << y << std::endl; | |
| } | | } | |
| | | | |
| template<typename T1, typename T2, typename T3> | | template<typename T1, typename T2, typename T3> | |
| arma_cold | | arma_cold | |
|
| | | arma_noinline | |
| static | | static | |
| void | | void | |
| arma_print(const T1& x, const T2& y, const T3& z) | | arma_print(const T1& x, const T2& y, const T3& z) | |
| { | | { | |
| get_stream_err1() << x << y << z << std::endl; | | get_stream_err1() << x << y << z << std::endl; | |
| } | | } | |
| | | | |
| // | | // | |
| // arma_sigprint | | // arma_sigprint | |
| | | | |
| | | | |
| skipping to change at line 250 | | skipping to change at line 256 | |
| { | | { | |
| get_stream_err1() << " [this = " << this_ptr << ']' << std::endl; | | get_stream_err1() << " [this = " << this_ptr << ']' << std::endl; | |
| } | | } | |
| | | | |
| // | | // | |
| // arma_warn | | // arma_warn | |
| | | | |
| //! print a message to the warn stream | | //! print a message to the warn stream | |
| template<typename T1> | | template<typename T1> | |
| arma_cold | | arma_cold | |
|
| | | arma_noinline | |
| static | | static | |
| void | | void | |
| arma_warn(const bool state, const T1& x) | | arma_warn(const bool state, const T1& x) | |
| { | | { | |
| if(state==true) | | if(state==true) | |
| { | | { | |
| get_stream_err2() << x << std::endl; | | get_stream_err2() << x << std::endl; | |
| } | | } | |
| } | | } | |
| | | | |
| template<typename T1, typename T2> | | template<typename T1, typename T2> | |
| arma_cold | | arma_cold | |
|
| | | arma_noinline | |
| static | | static | |
| void | | void | |
| arma_warn(const bool state, const T1& x, const T2& y) | | arma_warn(const bool state, const T1& x, const T2& y) | |
| { | | { | |
| if(state==true) | | if(state==true) | |
| { | | { | |
| get_stream_err2() << x << y << std::endl; | | get_stream_err2() << x << y << std::endl; | |
| } | | } | |
| } | | } | |
| | | | |
| template<typename T1, typename T2, typename T3> | | template<typename T1, typename T2, typename T3> | |
| arma_cold | | arma_cold | |
|
| | | arma_noinline | |
| static | | static | |
| void | | void | |
| arma_warn(const bool state, const T1& x, const T2& y, const T3& z) | | arma_warn(const bool state, const T1& x, const T2& y, const T3& z) | |
| { | | { | |
| if(state==true) | | if(state==true) | |
| { | | { | |
| get_stream_err2() << x << y << z << std::endl; | | get_stream_err2() << x << y << z << std::endl; | |
| } | | } | |
| } | | } | |
| | | | |
| | | | |
| skipping to change at line 343 | | skipping to change at line 352 | |
| { | | { | |
| err_state = true; | | err_state = true; | |
| err_msg = const_cast<char*>(message); | | err_msg = const_cast<char*>(message); | |
| } | | } | |
| } | | } | |
| | | | |
| // | | // | |
| // functions for generating strings indicating size errors | | // functions for generating strings indicating size errors | |
| | | | |
| arma_cold | | arma_cold | |
|
| | | arma_noinline | |
| static | | static | |
| std::string | | std::string | |
| arma_incompat_size_string(const uword A_n_rows, const uword A_n_cols, const
uword B_n_rows, const uword B_n_cols, const char* x) | | arma_incompat_size_string(const uword A_n_rows, const uword A_n_cols, const
uword B_n_rows, const uword B_n_cols, const char* x) | |
| { | | { | |
| std::stringstream tmp; | | std::stringstream tmp; | |
| | | | |
| tmp << x << ": incompatible matrix dimensions: " << A_n_rows << 'x' << A_
n_cols << " and " << B_n_rows << 'x' << B_n_cols; | | tmp << x << ": incompatible matrix dimensions: " << A_n_rows << 'x' << A_
n_cols << " and " << B_n_rows << 'x' << B_n_cols; | |
| | | | |
| return tmp.str(); | | return tmp.str(); | |
| } | | } | |
| | | | |
| arma_cold | | arma_cold | |
|
| | | arma_noinline | |
| static | | static | |
| std::string | | std::string | |
| arma_incompat_size_string(const uword A_n_rows, const uword A_n_cols, const
uword A_n_slices, const uword B_n_rows, const uword B_n_cols, const uword
B_n_slices, const char* x) | | arma_incompat_size_string(const uword A_n_rows, const uword A_n_cols, const
uword A_n_slices, const uword B_n_rows, const uword B_n_cols, const uword
B_n_slices, const char* x) | |
| { | | { | |
| std::stringstream tmp; | | std::stringstream tmp; | |
| | | | |
| tmp << x << ": incompatible cube dimensions: " << A_n_rows << 'x' << A_n_
cols << 'x' << A_n_slices << " and " << B_n_rows << 'x' << B_n_cols << 'x'
<< B_n_slices; | | tmp << x << ": incompatible cube dimensions: " << A_n_rows << 'x' << A_n_
cols << 'x' << A_n_slices << " and " << B_n_rows << 'x' << B_n_cols << 'x'
<< B_n_slices; | |
| | | | |
| return tmp.str(); | | return tmp.str(); | |
| } | | } | |
| | | | |
| template<typename eT> | | template<typename eT> | |
| arma_cold | | arma_cold | |
|
| | | arma_noinline | |
| static | | static | |
| std::string | | std::string | |
| arma_incompat_size_string(const subview_cube<eT>& Q, const Mat<eT>& A, cons
t char* x) | | arma_incompat_size_string(const subview_cube<eT>& Q, const Mat<eT>& A, cons
t char* x) | |
| { | | { | |
| std::stringstream tmp; | | std::stringstream tmp; | |
| | | | |
| tmp << x | | tmp << x | |
| << ": interpreting matrix as cube with dimenensions: " | | << ": interpreting matrix as cube with dimenensions: " | |
| << A.n_rows << 'x' << A.n_cols << 'x' << 1 | | << A.n_rows << 'x' << A.n_cols << 'x' << 1 | |
| << " or " | | << " or " | |
| | | | |
End of changes. 12 change blocks. |
| 0 lines changed or deleted | | 12 lines changed or added | |
|
| fn_dot.hpp | | fn_dot.hpp | |
| | | | |
| skipping to change at line 122 | | skipping to change at line 122 | |
| ( | | ( | |
| const Op<T1, op_htrans>& A, | | const Op<T1, op_htrans>& A, | |
| const T2& B | | const T2& B | |
| ) | | ) | |
| { | | { | |
| arma_extra_debug_sigprint(); | | arma_extra_debug_sigprint(); | |
| | | | |
| return cdot(A.m, B); | | return cdot(A.m, B); | |
| } | | } | |
| | | | |
|
| //! dot product of two sparse objects | | // | |
| template<typename T1, typename T2> | | // for sparse matrices | |
| inline | | // | |
| arma_warn_unused | | | |
| typename | | | |
| enable_if2 | | | |
| <(is_arma_sparse_type<T1>::value) && (is_arma_sparse_type<T2>::value) && | | | |
| (is_same_type<typename T1::elem_type, typename T2::elem_type>::value), | | | |
| typename T1::elem_type | | | |
| >::result | | | |
| dot | | | |
| ( | | | |
| const SpBase<typename T1::elem_type, T1>& x, | | | |
| const SpBase<typename T2::elem_type, T2>& y | | | |
| ) | | | |
| { | | | |
| arma_extra_debug_sigprint(); | | | |
| | | | |
|
| const SpProxy<T1> pa(x.get_ref()); | | namespace priv | |
| const SpProxy<T2> pb(y.get_ref()); | | { | |
| | | | |
| arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_ro | | | |
| ws(), pb.get_n_cols(), "dot()"); | | | |
| | | | |
| typedef typename T1::elem_type eT; | | | |
| | | | |
|
| if((&(x.get_ref()) == &(y.get_ref())) && (SpProxy<T1>::must_use_iterator | | template<typename T1, typename T2> | |
| == false)) | | arma_hot | |
| { | | inline | |
| // We can do it directly! | | typename T1::elem_type | |
| return op_dot::direct_dot_arma(pa.get_n_nonzero(), pa.get_values(), pa. | | dot_helper(const SpProxy<T1>& pa, const SpProxy<T2>& pb) | |
| get_values()); | | | |
| } | | | |
| else | | | |
| { | | { | |
|
| | | typedef typename T1::elem_type eT; | |
| | | | |
| // Iterate over both objects and see when they are the same | | // Iterate over both objects and see when they are the same | |
| eT result = eT(0); | | eT result = eT(0); | |
| | | | |
|
| typename SpProxy<T1>::const_iterator_type a_it = pa.begin(); | | typename SpProxy<T1>::const_iterator_type a_it = pa.begin(); | |
| typename SpProxy<T2>::const_iterator_type b_it = pb.begin(); | | typename SpProxy<T1>::const_iterator_type a_end = pa.end(); | |
| | | | |
|
| while((a_it != pa.end()) && (b_it != pb.end())) | | typename SpProxy<T2>::const_iterator_type b_it = pb.begin(); | |
| | | typename SpProxy<T2>::const_iterator_type b_end = pb.end(); | |
| | | | |
| | | while((a_it != a_end) && (b_it != b_end)) | |
| { | | { | |
| if(a_it == b_it) | | if(a_it == b_it) | |
| { | | { | |
| result += (*a_it) * (*b_it); | | result += (*a_it) * (*b_it); | |
| | | | |
| ++a_it; | | ++a_it; | |
| ++b_it; | | ++b_it; | |
| } | | } | |
| else if((a_it.col() < b_it.col()) || ((a_it.col() == b_it.col()) && (
a_it.row() < b_it.row()))) | | else if((a_it.col() < b_it.col()) || ((a_it.col() == b_it.col()) && (
a_it.row() < b_it.row()))) | |
| { | | { | |
| | | | |
| skipping to change at line 182 | | skipping to change at line 169 | |
| } | | } | |
| else | | else | |
| { | | { | |
| // b_it is "behind" | | // b_it is "behind" | |
| ++b_it; | | ++b_it; | |
| } | | } | |
| } | | } | |
| | | | |
| return result; | | return result; | |
| } | | } | |
|
| | | | |
| } | | } | |
| | | | |
|
| //! dot product of one sparse and one dense object | | //! dot product of two sparse objects | |
| template<typename T1, typename T2> | | template<typename T1, typename T2> | |
|
| arma_inline | | | |
| arma_warn_unused | | arma_warn_unused | |
|
| | | arma_hot | |
| | | inline | |
| typename | | typename | |
| enable_if2 | | enable_if2 | |
|
| <(is_arma_sparse_type<T1>::value) && (is_arma_type<T2>::value) && (is_sam
e_type<typename T1::elem_type, typename T2::elem_type>::value), | | <(is_arma_sparse_type<T1>::value) && (is_arma_sparse_type<T2>::value) &&
(is_same_type<typename T1::elem_type, typename T2::elem_type>::value), | |
| typename T1::elem_type | | typename T1::elem_type | |
| >::result | | >::result | |
| dot | | dot | |
| ( | | ( | |
|
| const SpBase<typename T1::elem_type, T1>& x, | | const T1& x, | |
| const Base<typename T2::elem_type, T2>& y | | const T2& y | |
| ) | | ) | |
| { | | { | |
|
| // this is commutative | | arma_extra_debug_sigprint(); | |
| return dot(y, x); | | | |
| | | const SpProxy<T1> pa(x); | |
| | | const SpProxy<T2> pb(y); | |
| | | | |
| | | arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_ro | |
| | | ws(), pb.get_n_cols(), "dot()"); | |
| | | | |
| | | typedef typename T1::elem_type eT; | |
| | | | |
| | | typedef typename SpProxy<T1>::stored_type pa_Q_type; | |
| | | typedef typename SpProxy<T2>::stored_type pb_Q_type; | |
| | | | |
| | | if( | |
| | | ( (SpProxy<T1>::must_use_iterator == false) && (SpProxy<T2>::must_ | |
| | | use_iterator == false) ) | |
| | | && ( (is_SpMat<pa_Q_type>::value == true ) && (is_SpMat<pb_Q_type | |
| | | >::value == true ) ) | |
| | | ) | |
| | | { | |
| | | const unwrap_spmat<pa_Q_type> tmp_a(pa.Q); | |
| | | const unwrap_spmat<pb_Q_type> tmp_b(pb.Q); | |
| | | | |
| | | const SpMat<eT>& A = tmp_a.M; | |
| | | const SpMat<eT>& B = tmp_b.M; | |
| | | | |
| | | if( &A == &B ) | |
| | | { | |
| | | // We can do it directly! | |
| | | return op_dot::direct_dot_arma(A.n_nonzero, A.values, A.values); | |
| | | } | |
| | | else | |
| | | { | |
| | | return priv::dot_helper(pa,pb); | |
| | | } | |
| | | } | |
| | | else | |
| | | { | |
| | | return priv::dot_helper(pa,pb); | |
| | | } | |
| } | | } | |
| | | | |
| //! dot product of one dense and one sparse object | | //! dot product of one dense and one sparse object | |
| template<typename T1, typename T2> | | template<typename T1, typename T2> | |
|
| inline | | | |
| arma_warn_unused | | arma_warn_unused | |
|
| | | arma_hot | |
| | | inline | |
| typename | | typename | |
| enable_if2 | | enable_if2 | |
| <(is_arma_type<T1>::value) && (is_arma_sparse_type<T2>::value) && (is_sam
e_type<typename T1::elem_type, typename T2::elem_type>::value), | | <(is_arma_type<T1>::value) && (is_arma_sparse_type<T2>::value) && (is_sam
e_type<typename T1::elem_type, typename T2::elem_type>::value), | |
| typename T1::elem_type | | typename T1::elem_type | |
| >::result | | >::result | |
| dot | | dot | |
| ( | | ( | |
|
| const Base<typename T1::elem_type, T1>& x, | | const T1& x, | |
| const SpBase<typename T2::elem_type, T2>& y | | const T2& y | |
| ) | | ) | |
| { | | { | |
| arma_extra_debug_sigprint(); | | arma_extra_debug_sigprint(); | |
| | | | |
|
| const Proxy<T1> pa(x.get_ref()); | | const Proxy<T1> pa(x); | |
| const SpProxy<T2> pb(y.get_ref()); | | const SpProxy<T2> pb(y); | |
| | | | |
| arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_ro
ws(), pb.get_n_cols(), "dot()"); | | arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_ro
ws(), pb.get_n_cols(), "dot()"); | |
| | | | |
| typedef typename T1::elem_type eT; | | typedef typename T1::elem_type eT; | |
| | | | |
| eT result = eT(0); | | eT result = eT(0); | |
| | | | |
|
| typename SpProxy<T2>::const_iterator_type it = pb.begin(); | | typename SpProxy<T2>::const_iterator_type it = pb.begin(); | |
| | | typename SpProxy<T2>::const_iterator_type it_end = pb.end(); | |
| | | | |
| // prefer_at_accessor won't save us operations | | // prefer_at_accessor won't save us operations | |
|
| while(it != pb.end()) | | while(it != it_end) | |
| { | | { | |
| result += (*it) * pa.at(it.row(), it.col()); | | result += (*it) * pa.at(it.row(), it.col()); | |
| ++it; | | ++it; | |
| } | | } | |
| | | | |
| return result; | | return result; | |
| } | | } | |
| | | | |
|
| | | //! dot product of one sparse and one dense object | |
| | | template<typename T1, typename T2> | |
| | | arma_warn_unused | |
| | | arma_hot | |
| | | inline | |
| | | typename | |
| | | enable_if2 | |
| | | <(is_arma_sparse_type<T1>::value) && (is_arma_type<T2>::value) && (is_sam | |
| | | e_type<typename T1::elem_type, typename T2::elem_type>::value), | |
| | | typename T1::elem_type | |
| | | >::result | |
| | | dot | |
| | | ( | |
| | | const T1& x, | |
| | | const T2& y | |
| | | ) | |
| | | { | |
| | | arma_extra_debug_sigprint(); | |
| | | | |
| | | // this is commutative | |
| | | return dot(y, x); | |
| | | } | |
| | | | |
| //! @} | | //! @} | |
| | | | |
End of changes. 20 change blocks. |
| 49 lines changed or deleted | | 97 lines changed or added | |
|
| fn_trace.hpp | | fn_trace.hpp | |
|
| // Copyright (C) 2008-2010 NICTA (www.nicta.com.au) | | // Copyright (C) 2008-2012 NICTA (www.nicta.com.au) | |
| // Copyright (C) 2008-2010 Conrad Sanderson | | // Copyright (C) 2008-2012 Conrad Sanderson | |
| // Copyright (C) 2012 Ryan Curtin | | // Copyright (C) 2012 Ryan Curtin | |
| // | | // | |
| // This file is part of the Armadillo C++ library. | | // This file is part of the Armadillo C++ library. | |
| // It is provided without any warranty of fitness | | // It is provided without any warranty of fitness | |
| // for any purpose. You can redistribute this file | | // for any purpose. You can redistribute this file | |
| // and/or modify it under the terms of the GNU | | // and/or modify it under the terms of the GNU | |
| // Lesser General Public License (LGPL) as published | | // Lesser General Public License (LGPL) as published | |
| // by the Free Software Foundation, either version 3 | | // by the Free Software Foundation, either version 3 | |
| // of the License or (at your option) any later version. | | // of the License or (at your option) any later version. | |
| // (see http://www.opensource.org/licenses for more info) | | // (see http://www.opensource.org/licenses for more info) | |
| | | | |
| //! \addtogroup fn_trace | | //! \addtogroup fn_trace | |
| //! @{ | | //! @{ | |
| | | | |
| //! Immediate trace (sum of diagonal elements) of a square dense matrix | | //! Immediate trace (sum of diagonal elements) of a square dense matrix | |
| template<typename T1> | | template<typename T1> | |
|
| inline | | arma_hot | |
| arma_warn_unused | | arma_warn_unused | |
|
| typename T1::elem_type | | inline | |
| trace(const Base<typename T1::elem_type,T1>& X) | | typename enable_if2<is_arma_type<T1>::value, typename T1::elem_type>::resul | |
| | | t | |
| | | trace(const T1& X) | |
| { | | { | |
| arma_extra_debug_sigprint(); | | arma_extra_debug_sigprint(); | |
| | | | |
| typedef typename T1::elem_type eT; | | typedef typename T1::elem_type eT; | |
| | | | |
|
| const Proxy<T1> A(X.get_ref()); | | const Proxy<T1> A(X); | |
| | | | |
| arma_debug_check( (A.get_n_rows() != A.get_n_cols()), "trace(): matrix mu
st be square sized" ); | | arma_debug_check( (A.get_n_rows() != A.get_n_cols()), "trace(): matrix mu
st be square sized" ); | |
| | | | |
|
| const uword N = A.get_n_rows(); | | const uword N = A.get_n_rows(); | |
| eT val = eT(0); | | | |
| | | | |
|
| for(uword i=0; i<N; ++i) | | eT val1 = eT(0); | |
| | | eT val2 = eT(0); | |
| | | | |
| | | uword i,j; | |
| | | for(i=0, j=1; j<N; i+=2, j+=2) | |
| { | | { | |
|
| val += A.at(i,i); | | val1 += A.at(i,i); | |
| | | val2 += A.at(j,j); | |
| } | | } | |
| | | | |
|
| return val; | | if(i < N) | |
| | | { | |
| | | val1 += A.at(i,i); | |
| | | } | |
| | | | |
| | | return val1 + val2; | |
| } | | } | |
| | | | |
| template<typename T1> | | template<typename T1> | |
|
| inline | | arma_hot | |
| arma_warn_unused | | arma_warn_unused | |
|
| | | inline | |
| typename T1::elem_type | | typename T1::elem_type | |
| trace(const Op<T1, op_diagmat>& X) | | trace(const Op<T1, op_diagmat>& X) | |
| { | | { | |
| arma_extra_debug_sigprint(); | | arma_extra_debug_sigprint(); | |
| | | | |
| typedef typename T1::elem_type eT; | | typedef typename T1::elem_type eT; | |
| | | | |
| const diagmat_proxy<T1> A(X.m); | | const diagmat_proxy<T1> A(X.m); | |
| | | | |
| const uword N = A.n_elem; | | const uword N = A.n_elem; | |
| | | | |
| skipping to change at line 69 | | skipping to change at line 80 | |
| for(uword i=0; i<N; ++i) | | for(uword i=0; i<N; ++i) | |
| { | | { | |
| val += A[i]; | | val += A[i]; | |
| } | | } | |
| | | | |
| return val; | | return val; | |
| } | | } | |
| | | | |
| //! speedup for trace(A*B), where the result of A*B is a square sized matri
x | | //! speedup for trace(A*B), where the result of A*B is a square sized matri
x | |
| template<typename T1, typename T2> | | template<typename T1, typename T2> | |
|
| | | arma_hot | |
| inline | | inline | |
|
| arma_warn_unused | | | |
| typename T1::elem_type | | typename T1::elem_type | |
|
| trace(const Glue<T1, T2, glue_times>& X) | | trace_mul_unwrap(const T1& XA, const T2& XB) | |
| { | | { | |
| arma_extra_debug_sigprint(); | | arma_extra_debug_sigprint(); | |
| | | | |
| typedef typename T1::elem_type eT; | | typedef typename T1::elem_type eT; | |
| | | | |
|
| const unwrap<T1> tmp1(X.A); | | const Proxy<T1> PA(XA); | |
| const unwrap<T2> tmp2(X.B); | | const unwrap<T2> tmpB(XB); | |
| | | | |
|
| const Mat<eT>& A = tmp1.M; | | const Mat<eT>& B = tmpB.M; | |
| const Mat<eT>& B = tmp2.M; | | | |
| | | | |
|
| arma_debug_assert_mul_size(A, B, "matrix multiply"); | | arma_debug_assert_mul_size(PA.get_n_rows(), PA.get_n_cols(), B.n_rows, B.
n_cols, "matrix multiply"); | |
| | | | |
|
| arma_debug_check( (A.n_rows != B.n_cols), "trace(): matrix must be square
sized" ); | | arma_debug_check( (PA.get_n_rows() != B.n_cols), "trace(): matrix must be
square sized" ); | |
| | | | |
|
| const uword N1 = A.n_rows; | | const uword N1 = PA.get_n_rows(); // equivalent to B.n_cols, due to squ | |
| const uword N2 = A.n_cols; | | are size requirements | |
| eT val = eT(0); | | const uword N2 = PA.get_n_cols(); // equivalent to B.n_rows, due to mat | |
| | | rix multiplication requirements | |
| | | | |
| | | eT val = eT(0); | |
| | | | |
| for(uword i=0; i<N1; ++i) | | for(uword i=0; i<N1; ++i) | |
| { | | { | |
| const eT* B_colmem = B.colptr(i); | | const eT* B_colmem = B.colptr(i); | |
|
| eT acc = eT(0); | | | |
| | | | |
|
| for(uword j=0; j<N2; ++j) | | eT acc1 = eT(0); | |
| | | eT acc2 = eT(0); | |
| | | | |
| | | uword j,k; | |
| | | for(j=0, k=1; k < N2; j+=2, k+=2) | |
| | | { | |
| | | const eT tmp_j = B_colmem[j]; | |
| | | const eT tmp_k = B_colmem[k]; | |
| | | | |
| | | acc1 += PA.at(i,j) * tmp_j; | |
| | | acc2 += PA.at(i,k) * tmp_k; | |
| | | } | |
| | | | |
| | | if(j < N2) | |
| | | { | |
| | | acc1 += PA.at(i,j) * B_colmem[j]; | |
| | | } | |
| | | | |
| | | val += (acc1 + acc2); | |
| | | } | |
| | | | |
| | | return val; | |
| | | } | |
| | | | |
| | | //! speedup for trace(A*B), where the result of A*B is a square sized matri | |
| | | x | |
| | | template<typename T1, typename T2> | |
| | | arma_hot | |
| | | inline | |
| | | typename T1::elem_type | |
| | | trace_mul_proxy(const T1& XA, const T2& XB) | |
| | | { | |
| | | arma_extra_debug_sigprint(); | |
| | | | |
| | | typedef typename T1::elem_type eT; | |
| | | | |
| | | const Proxy<T1> PA(XA); | |
| | | const Proxy<T2> PB(XB); | |
| | | | |
| | | if(is_Mat<typename Proxy<T2>::stored_type>::value == true) | |
| | | { | |
| | | return trace_mul_unwrap(PA.Q, PB.Q); | |
| | | } | |
| | | | |
| | | arma_debug_assert_mul_size(PA.get_n_rows(), PA.get_n_cols(), PB.get_n_row | |
| | | s(), PB.get_n_cols(), "matrix multiply"); | |
| | | | |
| | | arma_debug_check( (PA.get_n_rows() != PB.get_n_cols()), "trace(): matrix | |
| | | must be square sized" ); | |
| | | | |
| | | const uword N1 = PA.get_n_rows(); // equivalent to PB.get_n_cols(), due | |
| | | to square size requirements | |
| | | const uword N2 = PA.get_n_cols(); // equivalent to PB.get_n_rows(), due | |
| | | to matrix multiplication requirements | |
| | | | |
| | | eT val = eT(0); | |
| | | | |
| | | for(uword i=0; i<N1; ++i) | |
| | | { | |
| | | eT acc1 = eT(0); | |
| | | eT acc2 = eT(0); | |
| | | | |
| | | uword j,k; | |
| | | for(j=0, k=1; k < N2; j+=2, k+=2) | |
| { | | { | |
|
| acc += A.at(i,j) * B_colmem[j]; | | const eT tmp_j = PB.at(j,i); | |
| | | const eT tmp_k = PB.at(k,i); | |
| | | | |
| | | acc1 += PA.at(i,j) * tmp_j; | |
| | | acc2 += PA.at(i,k) * tmp_k; | |
| } | | } | |
| | | | |
|
| val += acc; | | if(j < N2) | |
| | | { | |
| | | acc1 += PA.at(i,j) * PB.at(j,i); | |
| | | } | |
| | | | |
| | | val += (acc1 + acc2); | |
| } | | } | |
| | | | |
| return val; | | return val; | |
| } | | } | |
| | | | |
|
| | | //! speedup for trace(A*B), where the result of A*B is a square sized matri | |
| | | x | |
| | | template<typename T1, typename T2> | |
| | | arma_hot | |
| | | arma_warn_unused | |
| | | inline | |
| | | typename T1::elem_type | |
| | | trace(const Glue<T1, T2, glue_times>& X) | |
| | | { | |
| | | arma_extra_debug_sigprint(); | |
| | | | |
| | | return (is_Mat<T2>::value) ? trace_mul_unwrap(X.A, X.B) : trace_mul_proxy | |
| | | (X.A, X.B); | |
| | | } | |
| | | | |
| //! trace of sparse object | | //! trace of sparse object | |
| template<typename T1> | | template<typename T1> | |
|
| inline | | arma_hot | |
| arma_warn_unused | | arma_warn_unused | |
|
| | | inline | |
| typename enable_if2<is_arma_sparse_type<T1>::value, typename T1::elem_type>
::result | | typename enable_if2<is_arma_sparse_type<T1>::value, typename T1::elem_type>
::result | |
|
| trace(const SpBase<typename T1::elem_type, T1>& x) | | trace(const T1& x) | |
| { | | { | |
| arma_extra_debug_sigprint(); | | arma_extra_debug_sigprint(); | |
| | | | |
|
| const SpProxy<T1> p(x.get_ref()); | | const SpProxy<T1> p(x); | |
| | | | |
| arma_debug_check( (p.get_n_rows() != p.get_n_cols()), "trace(): matrix mu
st be square sized" ); | | arma_debug_check( (p.get_n_rows() != p.get_n_cols()), "trace(): matrix mu
st be square sized" ); | |
| | | | |
| typedef typename T1::elem_type eT; | | typedef typename T1::elem_type eT; | |
| | | | |
| eT result = eT(0); | | eT result = eT(0); | |
| | | | |
|
| typename SpProxy<T1>::const_iterator_type it = p.begin(); | | typename SpProxy<T1>::const_iterator_type it = p.begin(); | |
| | | typename SpProxy<T1>::const_iterator_type it_end = p.end(); | |
| | | | |
|
| while(it != p.end()) | | while(it != it_end) | |
| { | | { | |
| if(it.row() == it.col()) | | if(it.row() == it.col()) | |
| { | | { | |
| result += (*it); | | result += (*it); | |
| } | | } | |
| | | | |
| ++it; | | ++it; | |
| } | | } | |
| | | | |
| return result; | | return result; | |
| | | | |
End of changes. 29 change blocks. |
| 32 lines changed or deleted | | 134 lines changed or added | |
|
| op_diagvec_bones.hpp | | op_diagvec_bones.hpp | |
|
| // Copyright (C) 2008-2010 NICTA (www.nicta.com.au) | | // Copyright (C) 2008-2012 NICTA (www.nicta.com.au) | |
| // Copyright (C) 2008-2010 Conrad Sanderson | | // Copyright (C) 2008-2012 Conrad Sanderson | |
| // | | // | |
| // This file is part of the Armadillo C++ library. | | // This file is part of the Armadillo C++ library. | |
| // It is provided without any warranty of fitness | | // It is provided without any warranty of fitness | |
| // for any purpose. You can redistribute this file | | // for any purpose. You can redistribute this file | |
| // and/or modify it under the terms of the GNU | | // and/or modify it under the terms of the GNU | |
| // Lesser General Public License (LGPL) as published | | // Lesser General Public License (LGPL) as published | |
| // by the Free Software Foundation, either version 3 | | // by the Free Software Foundation, either version 3 | |
| // of the License or (at your option) any later version. | | // of the License or (at your option) any later version. | |
| // (see http://www.opensource.org/licenses for more info) | | // (see http://www.opensource.org/licenses for more info) | |
| | | | |
| //! \addtogroup op_diagvec | | //! \addtogroup op_diagvec | |
| //! @{ | | //! @{ | |
| | | | |
| class op_diagvec | | class op_diagvec | |
| { | | { | |
| public: | | public: | |
| | | | |
| template<typename T1> | | template<typename T1> | |
| inline static void apply(Mat<typename T1::elem_type>& out, const Op<T1,op
_diagvec>& X); | | inline static void apply(Mat<typename T1::elem_type>& out, const Op<T1,op
_diagvec>& X); | |
|
| | | | |
| | | template<typename T1> | |
| | | arma_hot inline static void apply_unwrap(Mat<typename T1::elem_type>& out | |
| | | , const T1& X, const uword row_offset, const uword col_offset, const | |
| | | uword len); | |
| | | | |
| | | template<typename T1> | |
| | | arma_hot inline static void apply_proxy(Mat<typename T1::elem_type>& out, | |
| | | const Proxy<T1>& P, const uword row_offset, const uword col_offset, const | |
| | | uword len); | |
| }; | | }; | |
| | | | |
| //! @} | | //! @} | |
| | | | |
End of changes. 2 change blocks. |
| 2 lines changed or deleted | | 12 lines changed or added | |
|
| op_diagvec_meat.hpp | | op_diagvec_meat.hpp | |
|
| // Copyright (C) 2008-2010 NICTA (www.nicta.com.au) | | // Copyright (C) 2008-2012 NICTA (www.nicta.com.au) | |
| // Copyright (C) 2008-2010 Conrad Sanderson | | // Copyright (C) 2008-2012 Conrad Sanderson | |
| // | | // | |
| // This file is part of the Armadillo C++ library. | | // This file is part of the Armadillo C++ library. | |
| // It is provided without any warranty of fitness | | // It is provided without any warranty of fitness | |
| // for any purpose. You can redistribute this file | | // for any purpose. You can redistribute this file | |
| // and/or modify it under the terms of the GNU | | // and/or modify it under the terms of the GNU | |
| // Lesser General Public License (LGPL) as published | | // Lesser General Public License (LGPL) as published | |
| // by the Free Software Foundation, either version 3 | | // by the Free Software Foundation, either version 3 | |
| // of the License or (at your option) any later version. | | // of the License or (at your option) any later version. | |
| // (see http://www.opensource.org/licenses for more info) | | // (see http://www.opensource.org/licenses for more info) | |
| | | | |
| | | | |
| skipping to change at line 25 | | skipping to change at line 25 | |
| | | | |
| template<typename T1> | | template<typename T1> | |
| inline | | inline | |
| void | | void | |
| op_diagvec::apply(Mat<typename T1::elem_type>& out, const Op<T1, op_diagvec
>& X) | | op_diagvec::apply(Mat<typename T1::elem_type>& out, const Op<T1, op_diagvec
>& X) | |
| { | | { | |
| arma_extra_debug_sigprint(); | | arma_extra_debug_sigprint(); | |
| | | | |
| typedef typename T1::elem_type eT; | | typedef typename T1::elem_type eT; | |
| | | | |
|
| const sword id = (X.aux_uword_b > 0) ? -sword(X.aux_uword_a) : sword(X.au | | const uword a = X.aux_uword_a; | |
| x_uword_a); | | const uword b = X.aux_uword_b; | |
| | | | |
|
| const unwrap_check<T1> tmp(X.m, out); | | const uword row_offset = (b > 0) ? a : 0; | |
| const Mat<eT>& A = tmp.M; | | const uword col_offset = (b == 0) ? a : 0; | |
| | | | |
|
| out = A.diag(id); | | const Proxy<T1> P(X.m); | |
| | | | |
| | | const uword n_rows = P.get_n_rows(); | |
| | | const uword n_cols = P.get_n_cols(); | |
| | | | |
| | | arma_debug_check | |
| | | ( | |
| | | ((row_offset > 0) && (row_offset >= n_rows)) || ((col_offset > 0) && (c | |
| | | ol_offset >= n_cols)), | |
| | | "diagvec(): requested diagonal is out of bounds" | |
| | | ); | |
| | | | |
| | | const uword len = (std::min)(n_rows - row_offset, n_cols - col_offset); | |
| | | | |
| | | if(is_Mat<typename Proxy<T1>::stored_type>::value) | |
| | | { | |
| | | op_diagvec::apply_unwrap(out, P.Q, row_offset, col_offset, len); | |
| | | } | |
| | | else | |
| | | { | |
| | | if(P.is_alias(out) == false) | |
| | | { | |
| | | op_diagvec::apply_proxy(out, P, row_offset, col_offset, len); | |
| | | } | |
| | | else | |
| | | { | |
| | | Mat<eT> tmp; | |
| | | | |
| | | op_diagvec::apply_proxy(tmp, P, row_offset, col_offset, len); | |
| | | | |
| | | out.steal_mem(tmp); | |
| | | } | |
| | | } | |
| | | } | |
| | | | |
| | | template<typename T1> | |
| | | arma_hot | |
| | | inline | |
| | | void | |
| | | op_diagvec::apply_unwrap(Mat<typename T1::elem_type>& out, const T1& X, con | |
| | | st uword row_offset, const uword col_offset, const uword len) | |
| | | { | |
| | | arma_extra_debug_sigprint(); | |
| | | | |
| | | typedef typename T1::elem_type eT; | |
| | | | |
| | | const unwrap_check<T1> tmp_A(X, out); | |
| | | const Mat<eT>& A = tmp_A.M; | |
| | | | |
| | | out.set_size(len, 1); | |
| | | | |
| | | eT* out_mem = out.memptr(); | |
| | | | |
| | | uword i,j; | |
| | | for(i=0, j=1; j < len; i+=2, j+=2) | |
| | | { | |
| | | const eT tmp_i = A.at( i + row_offset, i + col_offset ); | |
| | | const eT tmp_j = A.at( j + row_offset, j + col_offset ); | |
| | | | |
| | | out_mem[i] = tmp_i; | |
| | | out_mem[j] = tmp_j; | |
| | | } | |
| | | | |
| | | if(i < len) | |
| | | { | |
| | | out_mem[i] = A.at( i + row_offset, i + col_offset ); | |
| | | } | |
| | | } | |
| | | | |
| | | template<typename T1> | |
| | | arma_hot | |
| | | inline | |
| | | void | |
| | | op_diagvec::apply_proxy(Mat<typename T1::elem_type>& out, const Proxy<T1>& | |
| | | P, const uword row_offset, const uword col_offset, const uword len) | |
| | | { | |
| | | arma_extra_debug_sigprint(); | |
| | | | |
| | | typedef typename T1::elem_type eT; | |
| | | | |
| | | out.set_size(len, 1); | |
| | | | |
| | | eT* out_mem = out.memptr(); | |
| | | | |
| | | uword i,j; | |
| | | for(i=0, j=1; j < len; i+=2, j+=2) | |
| | | { | |
| | | const eT tmp_i = P.at( i + row_offset, i + col_offset ); | |
| | | const eT tmp_j = P.at( j + row_offset, j + col_offset ); | |
| | | | |
| | | out_mem[i] = tmp_i; | |
| | | out_mem[j] = tmp_j; | |
| | | } | |
| | | | |
| | | if(i < len) | |
| | | { | |
| | | out_mem[i] = P.at( i + row_offset, i + col_offset ); | |
| | | } | |
| } | | } | |
| | | | |
| //! @} | | //! @} | |
| | | | |
End of changes. 4 change blocks. |
| 7 lines changed or deleted | | 104 lines changed or added | |
|
| operator_div.hpp | | operator_div.hpp | |
| | | | |
| skipping to change at line 143 | | skipping to change at line 143 | |
| return mtGlue<out_eT, T1, T2, glue_mixed_div>( X, Y ); | | return mtGlue<out_eT, T1, T2, glue_mixed_div>( X, Y ); | |
| } | | } | |
| | | | |
| //! element-wise division of sparse matrix by scalar | | //! element-wise division of sparse matrix by scalar | |
| template<typename T1> | | template<typename T1> | |
| inline | | inline | |
| typename | | typename | |
| enable_if2<is_arma_sparse_type<T1>::value, SpMat<typename T1::elem_type> >:
:result | | enable_if2<is_arma_sparse_type<T1>::value, SpMat<typename T1::elem_type> >:
:result | |
| operator/ | | operator/ | |
| ( | | ( | |
|
| const SpBase<typename T1::elem_type, T1>& X, | | const T1& X, | |
| const typename T1::elem_type y | | const typename T1::elem_type y | |
| ) | | ) | |
| { | | { | |
| arma_extra_debug_sigprint(); | | arma_extra_debug_sigprint(); | |
| | | | |
|
| arma_debug_check(y == typename T1::elem_type(0), "element-wise division:
division by zero"); | | SpMat<typename T1::elem_type> result(X); | |
| | | | |
|
| SpMat<typename T1::elem_type> result(X.get_ref()); | | result /= y; | |
| | | | |
| for(uword i = 0; i < result.n_nonzero; ++i) | | | |
| { | | | |
| access::rw(result.values[i]) /= y; | | | |
| } | | | |
| | | | |
| return result; | | return result; | |
| } | | } | |
| | | | |
|
| // //! element-wise division of two sparse objects. what a bad idea | | | |
| // template<typename T1, typename T2> | | | |
| // inline | | | |
| // typename | | | |
| // enable_if2 | | | |
| // < | | | |
| // (is_arma_sparse_type<T1>::value && is_arma_sparse_type<T2>::value && | | | |
| // is_same_type<typename T1::elem_type, typename T2::elem_type>::value), | | | |
| // SpMat<typename T1::elem_type> | | | |
| // >::result | | | |
| // operator/ | | | |
| // ( | | | |
| // const SpBase<typename T1::elem_type, T1>& x, | | | |
| // const SpBase<typename T2::elem_type, T2>& y | | | |
| // ) | | | |
| // { | | | |
| // arma_extra_debug_sigprint(); | | | |
| // | | | |
| // const SpProxy<T1> pa(x.get_ref()); | | | |
| // const SpProxy<T2> pb(y.get_ref()); | | | |
| // | | | |
| // arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n | | | |
| _rows(), pb.get_n_cols(), "element-wise division"); | | | |
| // | | | |
| // SpMat<typename T1::elem_type> result(pa.get_n_rows(), pa.get_n_cols()) | | | |
| ; | | | |
| // | | | |
| // // terrible | | | |
| // for(uword i = 0; i < result.n_elem; ++i) | | | |
| // { | | | |
| // result[i] = (pa[i] / pb[i]); | | | |
| // } | | | |
| // | | | |
| // return result; | | | |
| // } | | | |
| | | | |
| //! element-wise division of one sparse and one dense object | | //! element-wise division of one sparse and one dense object | |
| template<typename T1, typename T2> | | template<typename T1, typename T2> | |
| inline | | inline | |
| typename | | typename | |
| enable_if2 | | enable_if2 | |
| < | | < | |
| (is_arma_sparse_type<T1>::value && is_arma_type<T2>::value && is_same_typ
e<typename T1::elem_type, typename T2::elem_type>::value), | | (is_arma_sparse_type<T1>::value && is_arma_type<T2>::value && is_same_typ
e<typename T1::elem_type, typename T2::elem_type>::value), | |
| SpMat<typename T1::elem_type> | | SpMat<typename T1::elem_type> | |
| >::result | | >::result | |
| operator/ | | operator/ | |
| ( | | ( | |
|
| const SpBase<typename T1::elem_type, T1>& x, | | const T1& x, | |
| const Base<typename T2::elem_type, T2>& y | | const T2& y | |
| ) | | ) | |
| { | | { | |
| arma_extra_debug_sigprint(); | | arma_extra_debug_sigprint(); | |
| | | | |
|
| const SpProxy<T1> pa(x.get_ref()); | | typedef typename T1::elem_type eT; | |
| const Proxy<T2> pb(y.get_ref()); | | | |
| | | const SpProxy<T1> pa(x); | |
| | | const Proxy<T2> pb(y); | |
| | | | |
| | | const uword n_rows = pa.get_n_rows(); | |
| | | const uword n_cols = pa.get_n_cols(); | |
| | | | |
|
| arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_ro
ws(), pb.get_n_cols(), "element-wise division"); | | arma_debug_assert_same_size(n_rows, n_cols, pb.get_n_rows(), pb.get_n_col
s(), "element-wise division"); | |
| | | | |
|
| SpMat<typename T1::elem_type> result(pa.get_n_rows(), pa.get_n_cols()); | | SpMat<eT> result(n_rows, n_cols); | |
| | | | |
|
| // The compiler should be smart enough to optimize out the inner if/else | | | |
| statement entirely | | | |
| typename SpProxy<T1>::const_iterator_type it = pa.begin(); | | | |
| uword new_n_nonzero = 0; | | uword new_n_nonzero = 0; | |
|
| while(it != pa.end()) | | | |
| | | for(uword col=0; col < n_cols; ++col) | |
| | | for(uword row=0; row < n_rows; ++row) | |
| { | | { | |
|
| if(Proxy<T2>::prefer_at_accessor == false) | | const eT val = pa.at(row,col) / pb.at(row, col); | |
| { | | | |
| const typename T1::elem_type val = (*it) / pb[(it.col() * pb.get_n_ro | | if(val != eT(0)) | |
| ws()) + it.row()]; | | | |
| if(val != 0) | | | |
| { | | | |
| ++new_n_nonzero; | | | |
| } | | | |
| } | | | |
| else | | | |
| { | | { | |
|
| const typename T1::elem_type val = (*it) / pb.at(it.row(), it.col()); | | ++new_n_nonzero; | |
| if(val != 0) | | | |
| { | | | |
| ++new_n_nonzero; | | | |
| } | | | |
| } | | } | |
|
| | | | |
| ++it; | | | |
| } | | } | |
| | | | |
| result.mem_resize(new_n_nonzero); | | result.mem_resize(new_n_nonzero); | |
| | | | |
|
| typename SpProxy<T1>::const_iterator_type it2 = pa.begin(); | | | |
| uword cur_pos = 0; | | uword cur_pos = 0; | |
|
| while(it2 != pa.end()) | | | |
| | | for(uword col=0; col < n_cols; ++col) | |
| | | for(uword row=0; row < n_rows; ++row) | |
| { | | { | |
|
| if(Proxy<T2>::prefer_at_accessor == false) | | const eT val = pa.at(row,col) / pb.at(row, col); | |
| { | | | |
| const typename T1::elem_type val = (*it2) / pb[(it2.col() * pb.get_n_ | | if(val != eT(0)) | |
| rows()) + it2.row()]; | | | |
| if(val != 0) | | | |
| { | | | |
| access::rw(result.values[cur_pos]) = val; | | | |
| access::rw(result.row_indices[cur_pos]) = it2.row(); | | | |
| ++access::rw(result.col_ptrs[it2.col() + 1]); | | | |
| ++cur_pos; | | | |
| } | | | |
| } | | | |
| else | | | |
| { | | { | |
|
| const typename T1::elem_type val = (*it2) / pb.at(it2.row(), it2.col( | | access::rw(result.values[cur_pos]) = val; | |
| )); | | access::rw(result.row_indices[cur_pos]) = row; | |
| if(val != 0) | | ++access::rw(result.col_ptrs[col + 1]); | |
| { | | ++cur_pos; | |
| access::rw(result.values[cur_pos]) = val; | | | |
| access::rw(result.row_indices[cur_pos]) = it2.row(); | | | |
| ++access::rw(result.col_ptrs[it2.col() + 1]); | | | |
| ++cur_pos; | | | |
| } | | | |
| } | | } | |
|
| | | | |
| ++it2; | | | |
| } | | } | |
| | | | |
| // Fix column pointers | | // Fix column pointers | |
| for(uword col = 1; col <= result.n_cols; ++col) | | for(uword col = 1; col <= result.n_cols; ++col) | |
| { | | { | |
| access::rw(result.col_ptrs[col]) += result.col_ptrs[col - 1]; | | access::rw(result.col_ptrs[col]) += result.col_ptrs[col - 1]; | |
| } | | } | |
| | | | |
| return result; | | return result; | |
| } | | } | |
| | | | |
| skipping to change at line 296 | | skipping to change at line 236 | |
| template<typename T1, typename T2> | | template<typename T1, typename T2> | |
| inline | | inline | |
| typename | | typename | |
| enable_if2 | | enable_if2 | |
| < | | < | |
| (is_arma_type<T1>::value && is_arma_sparse_type<T2>::value && is_same_typ
e<typename T1::elem_type, typename T2::elem_type>::value), | | (is_arma_type<T1>::value && is_arma_sparse_type<T2>::value && is_same_typ
e<typename T1::elem_type, typename T2::elem_type>::value), | |
| Mat<typename T1::elem_type> | | Mat<typename T1::elem_type> | |
| >::result | | >::result | |
| operator/ | | operator/ | |
| ( | | ( | |
|
| const Base<typename T1::elem_type, T1>& x, | | const T1& x, | |
| const SpBase<typename T2::elem_type, T2>& y | | const T2& y | |
| ) | | ) | |
| { | | { | |
| arma_extra_debug_sigprint(); | | arma_extra_debug_sigprint(); | |
| | | | |
|
| const Proxy<T1> pa(x.get_ref()); | | typedef typename T1::elem_type eT; | |
| const SpProxy<T2> pb(y.get_ref()); | | | |
| | | | |
|
| arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_ro | | const Proxy<T1> pa(x); | |
| ws(), pb.get_n_cols(), "element-wise division"); | | const SpProxy<T2> pb(y); | |
| | | | |
|
| Mat<typename T1::elem_type> result(pa.get_n_rows(), pa.get_n_cols()); | | const uword n_rows = pa.get_n_rows(); | |
| | | const uword n_cols = pa.get_n_cols(); | |
| | | | |
|
| result.fill(Datum<typename T1::elem_type>::inf); | | arma_debug_assert_same_size(n_rows, n_cols, pb.get_n_rows(), pb.get_n_col
s(), "element-wise division"); | |
| | | | |
|
| // Now divide each element | | Mat<eT> result(n_rows, n_cols); | |
| typename SpProxy<T2>::const_iterator_type it = pb.begin(); | | | |
| | | | |
|
| while(it != pb.end()) | | for(uword col=0; col < n_cols; ++col) | |
| | | for(uword row=0; row < n_rows; ++row) | |
| { | | { | |
|
| if(Proxy<T1>::prefer_at_accessor == false) | | result.at(row, col) = pa.at(row, col) / pb.at(row, col); | |
| { | | | |
| const uword index = (it.col() * result.n_rows) + it.row(); | | | |
| result[index] = pa[index] / (*it); | | | |
| } | | | |
| else | | | |
| { | | | |
| result.at(it.row(), it.col()) = pa.at(it.row(), it.col()) / (*it); | | | |
| } | | | |
| | | | |
| ++it; | | | |
| } | | } | |
| | | | |
| return result; | | return result; | |
| } | | } | |
| | | | |
| //! @} | | //! @} | |
| | | | |
End of changes. 26 change blocks. |
| 119 lines changed or deleted | | 43 lines changed or added | |
|
| operator_minus.hpp | | operator_minus.hpp | |
| | | | |
| skipping to change at line 192 | | skipping to change at line 192 | |
| template<typename T1, typename T2> | | template<typename T1, typename T2> | |
| inline | | inline | |
| typename | | typename | |
| enable_if2 | | enable_if2 | |
| < | | < | |
| (is_arma_sparse_type<T1>::value && is_arma_type<T2>::value && is_same_typ
e<typename T1::elem_type, typename T2::elem_type>::value), | | (is_arma_sparse_type<T1>::value && is_arma_type<T2>::value && is_same_typ
e<typename T1::elem_type, typename T2::elem_type>::value), | |
| Mat<typename T1::elem_type> | | Mat<typename T1::elem_type> | |
| >::result | | >::result | |
| operator- | | operator- | |
| ( | | ( | |
|
| const SpBase<typename T1::elem_type, T1>& x, | | const T1& x, | |
| const Base<typename T2::elem_type, T2>& y | | const T2& y | |
| ) | | ) | |
| { | | { | |
| arma_extra_debug_sigprint(); | | arma_extra_debug_sigprint(); | |
| | | | |
|
| Mat<typename T1::elem_type> result(-y.get_ref()); | | const SpProxy<T1> pa(x); | |
| | | | |
|
| const SpProxy<T1> pa(x.get_ref()); | | Mat<typename T1::elem_type> result(-y); | |
| | | | |
| arma_debug_assert_same_size( pa.get_n_rows(), pa.get_n_cols(), result.n_r
ows, result.n_cols, "subtraction" ); | | arma_debug_assert_same_size( pa.get_n_rows(), pa.get_n_cols(), result.n_r
ows, result.n_cols, "subtraction" ); | |
| | | | |
|
| typename SpProxy<T1>::const_iterator_type it = pa.begin(); | | typename SpProxy<T1>::const_iterator_type it = pa.begin(); | |
| | | typename SpProxy<T1>::const_iterator_type it_end = pa.end(); | |
| | | | |
|
| while(it != pa.end()) | | while(it != it_end) | |
| { | | { | |
|
| const uword pos = it.col() * pa.get_n_cols() + it.row(); | | result.at(it.row(), it.col()) += (*it); | |
| result[pos] += (*it); | | | |
| ++it; | | ++it; | |
| } | | } | |
| | | | |
| return result; | | return result; | |
| } | | } | |
| | | | |
| //! subtraction of one dense and one sparse object | | //! subtraction of one dense and one sparse object | |
| template<typename T1, typename T2> | | template<typename T1, typename T2> | |
| inline | | inline | |
| typename | | typename | |
| enable_if2 | | enable_if2 | |
| < | | < | |
| (is_arma_type<T1>::value && is_arma_sparse_type<T2>::value && is_same_typ
e<typename T1::elem_type, typename T2::elem_type>::value), | | (is_arma_type<T1>::value && is_arma_sparse_type<T2>::value && is_same_typ
e<typename T1::elem_type, typename T2::elem_type>::value), | |
| Mat<typename T1::elem_type> | | Mat<typename T1::elem_type> | |
| >::result | | >::result | |
| operator- | | operator- | |
| ( | | ( | |
|
| const Base<typename T1::elem_type, T1>& x, | | const T1& x, | |
| const SpBase<typename T2::elem_type, T2>& y | | const T2& y | |
| ) | | ) | |
| { | | { | |
| arma_extra_debug_sigprint(); | | arma_extra_debug_sigprint(); | |
| | | | |
|
| Mat<typename T1::elem_type> result(x.get_ref()); | | Mat<typename T1::elem_type> result(x); | |
| | | | |
| const SpProxy<T2> pb(y.get_ref()); | | const SpProxy<T2> pb(y.get_ref()); | |
| | | | |
| arma_debug_assert_same_size( result.n_rows, result.n_cols, pb.get_n_rows(
), pb.get_n_cols(), "subtraction" ); | | arma_debug_assert_same_size( result.n_rows, result.n_cols, pb.get_n_rows(
), pb.get_n_cols(), "subtraction" ); | |
| | | | |
|
| typename SpProxy<T2>::const_iterator_type it = pb.begin(); | | typename SpProxy<T2>::const_iterator_type it = pb.begin(); | |
| | | typename SpProxy<T2>::const_iterator_type it_end = pb.end(); | |
| | | | |
|
| while(it != pb.end()) | | while(it != it_end) | |
| { | | { | |
|
| const uword pos = it.col() * pb.get_n_cols() + it.row(); | | result.at(it.row(), it.col()) -= (*it); | |
| result[pos] -= (*it); | | | |
| ++it; | | ++it; | |
| } | | } | |
| | | | |
| return result; | | return result; | |
| } | | } | |
| | | | |
| //! @} | | //! @} | |
| | | | |
End of changes. 11 change blocks. |
| 15 lines changed or deleted | | 15 lines changed or added | |
|
| operator_plus.hpp | | operator_plus.hpp | |
| | | | |
| skipping to change at line 163 | | skipping to change at line 163 | |
| const T2& y | | const T2& y | |
| ) | | ) | |
| { | | { | |
| arma_extra_debug_sigprint(); | | arma_extra_debug_sigprint(); | |
| | | | |
| return SpGlue<T1,T2,spglue_plus>(x, y); | | return SpGlue<T1,T2,spglue_plus>(x, y); | |
| } | | } | |
| | | | |
| //! addition of sparse and non-sparse object | | //! addition of sparse and non-sparse object | |
| template<typename T1, typename T2> | | template<typename T1, typename T2> | |
|
| arma_inline | | inline | |
| typename | | typename | |
| enable_if2 | | enable_if2 | |
| < | | < | |
|
| (is_arma_sparse_type<T1>::value && is_arma_type<T2>::value && is_same_typ
e<typename T1::elem_type, typename T2::elem_type>::value), | | (is_arma_type<T1>::value && is_arma_sparse_type<T2>::value && is_same_typ
e<typename T1::elem_type, typename T2::elem_type>::value), | |
| Mat<typename T1::elem_type> | | Mat<typename T1::elem_type> | |
| >::result | | >::result | |
| operator+ | | operator+ | |
| ( | | ( | |
|
| const SpBase<typename T1::elem_type, T1>& x, | | const T1& x, | |
| const Base<typename T2::elem_type, T2>& y | | const T2& y | |
| ) | | ) | |
| { | | { | |
|
| // Just call the other order (these operations are commutative) | | arma_extra_debug_sigprint(); | |
| return (y + x); | | | |
| | | Mat<typename T1::elem_type> result(x); | |
| | | | |
| | | const SpProxy<T2> pb(y); | |
| | | | |
| | | arma_debug_assert_same_size( result.n_rows, result.n_cols, pb.get_n_rows( | |
| | | ), pb.get_n_cols(), "addition" ); | |
| | | | |
| | | typename SpProxy<T2>::const_iterator_type it = pb.begin(); | |
| | | typename SpProxy<T2>::const_iterator_type it_end = pb.end(); | |
| | | | |
| | | while(it != it_end) | |
| | | { | |
| | | result.at(it.row(), it.col()) += (*it); | |
| | | ++it; | |
| | | } | |
| | | | |
| | | return result; | |
| } | | } | |
| | | | |
| //! addition of sparse and non-sparse object | | //! addition of sparse and non-sparse object | |
| template<typename T1, typename T2> | | template<typename T1, typename T2> | |
| inline | | inline | |
| typename | | typename | |
| enable_if2 | | enable_if2 | |
| < | | < | |
|
| (is_arma_type<T1>::value && is_arma_sparse_type<T2>::value && is_same_typ
e<typename T1::elem_type, typename T2::elem_type>::value), | | (is_arma_sparse_type<T1>::value && is_arma_type<T2>::value && is_same_typ
e<typename T1::elem_type, typename T2::elem_type>::value), | |
| Mat<typename T1::elem_type> | | Mat<typename T1::elem_type> | |
| >::result | | >::result | |
| operator+ | | operator+ | |
| ( | | ( | |
|
| const Base<typename T1::elem_type, T1>& x, | | const T1& x, | |
| const SpBase<typename T2::elem_type, T2>& y | | const T2& y | |
| ) | | ) | |
| { | | { | |
| arma_extra_debug_sigprint(); | | arma_extra_debug_sigprint(); | |
| | | | |
|
| Mat<typename T1::elem_type> result(x.get_ref()); | | // Just call the other order (these operations are commutative) | |
| | | return (y + x); | |
| const SpProxy<T2> pb(y.get_ref()); | | | |
| | | | |
| arma_debug_assert_same_size( result.n_rows, result.n_cols, pb.get_n_rows( | | | |
| ), pb.get_n_cols(), "addition" ); | | | |
| | | | |
| typename SpProxy<T2>::const_iterator_type it = pb.begin(); | | | |
| | | | |
| while(it != pb.end()) | | | |
| { | | | |
| const uword pos = it.col() * pb.get_n_cols() + it.row(); | | | |
| result[pos] += (*it); | | | |
| ++it; | | | |
| } | | | |
| | | | |
| return result; | | | |
| } | | } | |
| | | | |
| //! @} | | //! @} | |
| | | | |
End of changes. 7 change blocks. |
| 26 lines changed or deleted | | 28 lines changed or added | |
|
| operator_schur.hpp | | operator_schur.hpp | |
| | | | |
| skipping to change at line 151 | | skipping to change at line 151 | |
| // Fix column pointers to be cumulative. | | // Fix column pointers to be cumulative. | |
| for(uword c = 1; c <= result.n_cols; ++c) | | for(uword c = 1; c <= result.n_cols; ++c) | |
| { | | { | |
| access::rw(result.col_ptrs[c]) += result.col_ptrs[c - 1]; | | access::rw(result.col_ptrs[c]) += result.col_ptrs[c - 1]; | |
| } | | } | |
| } | | } | |
| | | | |
| return result; | | return result; | |
| } | | } | |
| | | | |
|
| //! element-wise multiplication of one sparse and one dense object | | | |
| template<typename T1, typename T2> | | | |
| inline | | | |
| typename | | | |
| enable_if2 | | | |
| < | | | |
| (is_arma_sparse_type<T1>::value && is_arma_type<T2>::value && is_same_typ | | | |
| e<typename T1::elem_type, typename T2::elem_type>::value), | | | |
| SpMat<typename T1::elem_type> | | | |
| >::result | | | |
| operator% | | | |
| ( | | | |
| const SpBase<typename T1::elem_type, T1>& x, | | | |
| const Base<typename T2::elem_type, T2>& y | | | |
| ) | | | |
| { | | | |
| // This operation is commutative. | | | |
| return (y % x); | | | |
| } | | | |
| | | | |
| //! element-wise multiplication of one dense and one sparse object | | //! element-wise multiplication of one dense and one sparse object | |
| template<typename T1, typename T2> | | template<typename T1, typename T2> | |
| inline | | inline | |
| typename | | typename | |
| enable_if2 | | enable_if2 | |
| < | | < | |
| (is_arma_type<T1>::value && is_arma_sparse_type<T2>::value && is_same_typ
e<typename T1::elem_type, typename T2::elem_type>::value), | | (is_arma_type<T1>::value && is_arma_sparse_type<T2>::value && is_same_typ
e<typename T1::elem_type, typename T2::elem_type>::value), | |
| SpMat<typename T1::elem_type> | | SpMat<typename T1::elem_type> | |
| >::result | | >::result | |
| operator% | | operator% | |
| ( | | ( | |
|
| const Base<typename T1::elem_type, T1>& x, | | const T1& x, | |
| const SpBase<typename T2::elem_type, T2>& y | | const T2& y | |
| ) | | ) | |
| { | | { | |
| arma_extra_debug_sigprint(); | | arma_extra_debug_sigprint(); | |
| | | | |
|
| const Proxy<T1> pa(x.get_ref()); | | typedef typename T1::elem_type eT; | |
| const SpProxy<T2> pb(y.get_ref()); | | | |
| | | const Proxy<T1> pa(x); | |
| | | const SpProxy<T2> pb(y); | |
| | | | |
| arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_ro
ws(), pb.get_n_cols(), "element-wise multiplication"); | | arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_ro
ws(), pb.get_n_cols(), "element-wise multiplication"); | |
| | | | |
|
| SpMat<typename T1::elem_type> result(pa.get_n_rows(), pa.get_n_cols()); | | SpMat<eT> result(pa.get_n_rows(), pa.get_n_cols()); | |
| | | | |
| | | // count new size | |
| | | uword new_n_nonzero = 0; | |
| | | | |
| | | typename SpProxy<T2>::const_iterator_type it = pb.begin(); | |
| | | typename SpProxy<T2>::const_iterator_type it_end = pb.end(); | |
| | | | |
|
| if(Proxy<T1>::prefer_at_accessor == false) | | while(it != it_end) | |
| { | | { | |
|
| // use direct operator[] access | | if( ((*it) * pa.at(it.row(), it.col())) != eT(0) ) | |
| // count new size | | | |
| uword new_n_nonzero = 0; | | | |
| typename SpProxy<T2>::const_iterator_type it = pb.begin(); | | | |
| while(it != pb.end()) | | | |
| { | | { | |
|
| if(((*it) * pa[(it.col() * pa.get_n_rows()) + it.row()]) != 0) | | ++new_n_nonzero; | |
| { | | | |
| ++new_n_nonzero; | | | |
| } | | | |
| | | | |
| ++it; | | | |
| } | | } | |
| | | | |
|
| // Resize memory accordingly. | | ++it; | |
| result.mem_resize(new_n_nonzero); | | } | |
| | | | |
|
| uword cur_val = 0; | | // Resize memory accordingly. | |
| typename SpProxy<T2>::const_iterator_type it2 = pb.begin(); | | result.mem_resize(new_n_nonzero); | |
| while(it2 != pb.end()) | | | |
| { | | | |
| const typename T1::elem_type val = (*it2) * pa[(it2.col() * pa.get_n_ | | | |
| rows()) + it2.row()]; | | | |
| if(val != 0) | | | |
| { | | | |
| access::rw(result.values[cur_val]) = val; | | | |
| access::rw(result.row_indices[cur_val]) = it2.row(); | | | |
| ++access::rw(result.col_ptrs[it2.col() + 1]); | | | |
| ++cur_val; | | | |
| } | | | |
| | | | |
|
| ++it2; | | uword cur_val = 0; | |
| } | | | |
| } | | | |
| else | | | |
| { | | | |
| // use at() access | | | |
| // count new size | | | |
| uword new_n_nonzero = 0; | | | |
| typename SpProxy<T2>::const_iterator_type it = pb.begin(); | | | |
| while(it != pb.end()) | | | |
| { | | | |
| if(((*it) * pa.at(it.row(), it.col())) != 0) | | | |
| { | | | |
| ++new_n_nonzero; | | | |
| } | | | |
| | | | |
|
| ++it; | | typename SpProxy<T2>::const_iterator_type it2 = pb.begin(); | |
| } | | | |
| | | | |
|
| // Resize memory accordingly. | | while(it2 != it_end) | |
| result.mem_resize(new_n_nonzero); | | { | |
| | | const uword it2_row = it2.row(); | |
| | | const uword it2_col = it2.col(); | |
| | | | |
|
| uword cur_val = 0; | | const eT val = (*it2) * pa.at(it2_row, it2_col); | |
| typename SpProxy<T2>::const_iterator_type it2 = pb.begin(); | | | |
| while(it2 != pb.end()) | | | |
| { | | | |
| const typename T1::elem_type val = (*it2) * pa.at(it2.row(), it2.col( | | | |
| )); | | | |
| if(val != 0) | | | |
| { | | | |
| access::rw(result.values[cur_val]) = val; | | | |
| access::rw(result.row_indices[cur_val]) = it2.row(); | | | |
| ++access::rw(result.col_ptrs[it2.col() + 1]); | | | |
| ++cur_val; | | | |
| } | | | |
| | | | |
|
| ++it2; | | if(val != eT(0)) | |
| | | { | |
| | | access::rw(result.values[cur_val]) = val; | |
| | | access::rw(result.row_indices[cur_val]) = it2_row; | |
| | | ++access::rw(result.col_ptrs[it2_col + 1]); | |
| | | ++cur_val; | |
| } | | } | |
|
| | | | |
| | | ++it2; | |
| } | | } | |
| | | | |
| // Fix column pointers. | | // Fix column pointers. | |
| for(uword c = 1; c <= result.n_cols; ++c) | | for(uword c = 1; c <= result.n_cols; ++c) | |
| { | | { | |
| access::rw(result.col_ptrs[c]) += result.col_ptrs[c - 1]; | | access::rw(result.col_ptrs[c]) += result.col_ptrs[c - 1]; | |
| } | | } | |
| | | | |
| return result; | | return result; | |
| } | | } | |
| | | | |
|
| | | //! element-wise multiplication of one sparse and one dense object | |
| | | template<typename T1, typename T2> | |
| | | inline | |
| | | typename | |
| | | enable_if2 | |
| | | < | |
| | | (is_arma_sparse_type<T1>::value && is_arma_type<T2>::value && is_same_typ | |
| | | e<typename T1::elem_type, typename T2::elem_type>::value), | |
| | | SpMat<typename T1::elem_type> | |
| | | >::result | |
| | | operator% | |
| | | ( | |
| | | const T1& x, | |
| | | const T2& y | |
| | | ) | |
| | | { | |
| | | arma_extra_debug_sigprint(); | |
| | | | |
| | | // This operation is commutative. | |
| | | return (y % x); | |
| | | } | |
| | | | |
| //! @} | | //! @} | |
| | | | |
End of changes. 16 change blocks. |
| 85 lines changed or deleted | | 57 lines changed or added | |
|
| operator_times.hpp | | operator_times.hpp | |
| | | | |
| skipping to change at line 425 | | skipping to change at line 425 | |
| Mat<typename T1::elem_type> | | Mat<typename T1::elem_type> | |
| >::result | | >::result | |
| operator* | | operator* | |
| ( | | ( | |
| const T1& x, | | const T1& x, | |
| const T2& y | | const T2& y | |
| ) | | ) | |
| { | | { | |
| arma_extra_debug_sigprint(); | | arma_extra_debug_sigprint(); | |
| | | | |
|
| const SpProxy<T1> pa(x.get_ref()); | | const SpProxy<T1> pa(x); | |
| const Proxy<T2> pb(y.get_ref()); | | const Proxy<T2> pb(y); | |
| | | | |
| arma_debug_assert_mul_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_row
s(), pb.get_n_cols(), "matrix multiplication"); | | arma_debug_assert_mul_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_row
s(), pb.get_n_cols(), "matrix multiplication"); | |
| | | | |
| Mat<typename T1::elem_type> result(pa.get_n_rows(), pb.get_n_cols()); | | Mat<typename T1::elem_type> result(pa.get_n_rows(), pb.get_n_cols()); | |
| result.zeros(); | | result.zeros(); | |
| | | | |
| if( (pa.get_n_nonzero() > 0) && (pb.get_n_elem() > 0) ) | | if( (pa.get_n_nonzero() > 0) && (pb.get_n_elem() > 0) ) | |
| { | | { | |
|
| if(Proxy<T2>::prefer_at_accessor == false) | | typename SpProxy<T1>::const_iterator_type x_it = pa.begin(); | |
| { | | typename SpProxy<T1>::const_iterator_type x_it_end = pa.end(); | |
| // use direct operator[] access | | | |
| for(typename SpProxy<T1>::const_iterator_type x_it = pa.begin(); x_it | | const uword result_n_cols = result.n_cols; | |
| != pa.end(); x_it++) | | | |
| { | | while(x_it != x_it_end) | |
| // We just want to use values where y.row = x_it.col. | | | |
| for(uword col = 0; col < result.n_cols; col++) | | | |
| { | | | |
| const uword index = x_it.col() + (pb.get_n_rows() * col); | | | |
| result.at(x_it.row(), col) += (*x_it) * pb[index]; | | | |
| } | | | |
| } | | | |
| } | | | |
| else | | | |
| { | | { | |
|
| // use at() access | | for(uword col = 0; col < result_n_cols; ++col) | |
| for(typename SpProxy<T1>::const_iterator_type x_it = pa.begin(); x_it | | | |
| != pa.end(); x_it++) | | | |
| { | | { | |
|
| for(uword col = 0; col < result.n_cols; col++) | | result.at(x_it.row(), col) += (*x_it) * pb.at(x_it.col(), col); | |
| { | | | |
| result.at(x_it.row(), col) += (*x_it) * pb.at(x_it.col(), col); | | | |
| } | | | |
| } | | } | |
|
| | | | |
| | | ++x_it; | |
| } | | } | |
| } | | } | |
| | | | |
| return result; | | return result; | |
| } | | } | |
| | | | |
| //! multiplication of one dense and one sparse object | | //! multiplication of one dense and one sparse object | |
| template<typename T1, typename T2> | | template<typename T1, typename T2> | |
| inline | | inline | |
| typename | | typename | |
| | | | |
| skipping to change at line 481 | | skipping to change at line 471 | |
| Mat<typename T1::elem_type> | | Mat<typename T1::elem_type> | |
| >::result | | >::result | |
| operator* | | operator* | |
| ( | | ( | |
| const T1& x, | | const T1& x, | |
| const T2& y | | const T2& y | |
| ) | | ) | |
| { | | { | |
| arma_extra_debug_sigprint(); | | arma_extra_debug_sigprint(); | |
| | | | |
|
| const Proxy<T1> pa(x.get_ref()); | | const Proxy<T1> pa(x); | |
| const SpProxy<T2> pb(y.get_ref()); | | const SpProxy<T2> pb(y); | |
| | | | |
| arma_debug_assert_mul_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_row
s(), pb.get_n_cols(), "matrix multiplication"); | | arma_debug_assert_mul_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_row
s(), pb.get_n_cols(), "matrix multiplication"); | |
| | | | |
| Mat<typename T1::elem_type> result(pa.get_n_rows(), pb.get_n_cols()); | | Mat<typename T1::elem_type> result(pa.get_n_rows(), pb.get_n_cols()); | |
| result.zeros(); | | result.zeros(); | |
| | | | |
| if( (pa.get_n_elem() > 0) && (pb.get_n_nonzero() > 0) ) | | if( (pa.get_n_elem() > 0) && (pb.get_n_nonzero() > 0) ) | |
| { | | { | |
|
| if(Proxy<T1>::prefer_at_accessor == false) | | typename SpProxy<T2>::const_iterator_type y_col_it = pb.begin(); | |
| { | | typename SpProxy<T2>::const_iterator_type y_col_it_end = pb.end(); | |
| // use direct operator[] access | | | |
| for(typename SpProxy<T2>::const_iterator_type y_col_it = pb.begin(); | | const uword result_n_rows = result.n_rows; | |
| y_col_it != pb.end(); ++y_col_it) | | | |
| { | | while(y_col_it != y_col_it_end) | |
| for(uword row = 0; row < result.n_rows; ++row) | | | |
| { | | | |
| const uword index = row + (y_col_it.row() * result.n_rows); | | | |
| result.at(row, y_col_it.col()) += pa[index] * (*y_col_it); | | | |
| } | | | |
| } | | | |
| } | | | |
| else | | | |
| { | | { | |
|
| // use at() access | | for(uword row = 0; row < result_n_rows; ++row) | |
| for(typename SpProxy<T2>::const_iterator_type y_col_it = pb.begin(); | | | |
| y_col_it != pb.end(); ++y_col_it) | | | |
| { | | { | |
|
| for(uword row = 0; row < result.n_rows; ++row) | | result.at(row, y_col_it.col()) += pa.at(row, y_col_it.row()) * (*y_ | |
| { | | col_it); | |
| result.at(row, y_col_it.col()) += pa.at(row, y_col_it.row()) * (* | | | |
| y_col_it); | | | |
| } | | | |
| } | | } | |
|
| | | | |
| | | ++y_col_it; | |
| } | | } | |
| } | | } | |
| | | | |
| return result; | | return result; | |
| } | | } | |
| | | | |
| //! @} | | //! @} | |
| | | | |
End of changes. 10 change blocks. |
| 48 lines changed or deleted | | 25 lines changed or added | |
|