Mat_meat.hpp   Mat_meat.hpp 
skipping to change at line 1835 skipping to change at line 1835
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. // Iterate over each nonzero element and set it.
for(typename SpProxy<T1>::const_iterator_type it = p.begin(); it.pos() < p.get_n_nonzero(); ++it) for(typename SpProxy<T1>::const_iterator_type it = p.begin(); it != p.end (); ++it)
{ {
at(it.row(), it.col()) = (*it); at(it.row(), it.col()) = (*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.pos() < p.get_n_nonzero(); ++it) for(typename SpProxy<T1>::const_iterator_type it = p.begin(); it != p.end (); ++it)
{ {
at(it.row(), it.col()) = (*it); at(it.row(), it.col()) = (*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.pos() < p.get_n_nonzero(); ++it) for(typename SpProxy<T1>::const_iterator_type it = p.begin(); it != p.end (); ++it)
{ {
at(it.row(), it.col()) += (*it); at(it.row(), it.col()) += (*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.pos() < p.get_n_nonzero(); ++it) for(typename SpProxy<T1>::const_iterator_type it = p.begin(); it != p.end (); ++it)
{ {
at(it.row(), it.col()) -= (*it); at(it.row(), it.col()) -= (*it);
} }
return *this; return *this;
} }
template<typename eT> template<typename eT>
template<typename T1> template<typename T1>
inline inline
skipping to change at line 1935 skipping to change at line 1935
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();
// 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.pos() < p.get_n_nonzero()) while(it != p.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.pos() == p.get_n_nonzero()) const uword next_loc = (it == p.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>
 End of changes. 6 change blocks. 
6 lines changed or deleted 6 lines changed or added


 SpMat_bones.hpp   SpMat_bones.hpp 
skipping to change at line 50 skipping to change at line 50
/** /**
* The memory used to store the values of the matrix. * The memory used to store the values of the matrix.
* In accordance with the CSC format, this stores only the actual values. * In accordance with the CSC format, this stores only the actual values.
* The correct locations of the values are assembled from the row indices * The correct locations of the values are assembled from the row indices
* and the column pointers. * and the column pointers.
*/ */
const eT* const values; const eT* const values;
/** /**
* The row indices of each value. row_indices[i] is the row of values[i] . * The row indices of each value. row_indices[i] is the row of values[i] .
* The length of this array is n_nonzero + 1; the final value ensures the
* integrity of iterators.
*/ */
const uword* const row_indices; const uword* const row_indices;
/** /**
* The column pointers. This stores the index of the first item in colum n i. * The column pointers. This stores the index of the first item in colum n i.
* That is, values[col_ptrs[i]] is the first value in column i, and it is in * That is, values[col_ptrs[i]] is the first value in column i, and it is in
* row row_indices[col_ptrs[i]]. * row row_indices[col_ptrs[i]].
*/ */
const uword* const col_ptrs; const uword* const col_ptrs;
skipping to change at line 302 skipping to change at line 304
// Iterator base provides comparison operators but not the actual logic o n how // Iterator base provides comparison operators but not the actual logic o n how
// to iterate. The validity of the position is not checked (that is left up // to iterate. The validity of the position is not checked (that is left up
// to the user). // to the user).
class iterator_base class iterator_base
{ {
public: public:
inline iterator_base(const SpMat& in_M); inline iterator_base(const SpMat& in_M);
inline iterator_base(const SpMat& in_M, const uword col, const uword po s); inline iterator_base(const SpMat& in_M, const uword col, const uword po s);
inline eT operator*() const; inline arma_hot eT operator*() const;
inline bool operator==(const iterator_base& rhs) const; inline arma_hot bool operator==(const iterator_base& rhs) const;
inline bool operator!=(const iterator_base& rhs) const; inline arma_hot bool operator!=(const iterator_base& rhs) const;
inline bool operator==(const typename SpSubview<eT>::iterator_base& rhs inline arma_hot bool operator==(const typename SpSubview<eT>::iterator_
) const; base& rhs) const;
inline bool operator!=(const typename SpSubview<eT>::iterator_base& rhs inline arma_hot bool operator!=(const typename SpSubview<eT>::iterator_
) const; base& rhs) const;
// Don't hold location internally; call "dummy" methods to get that inf ormation. // Don't hold location internally; call "dummy" methods to get that inf ormation.
arma_inline uword row() const { return M.row_indices[internal_pos]; } arma_inline uword row() const { return M.row_indices[internal_pos]; }
arma_inline uword col() const { return internal_col; } arma_inline uword col() const { return internal_col; }
arma_inline uword pos() const { return internal_pos; } arma_inline uword pos() const { return internal_pos; }
arma_aligned const SpMat& M; arma_aligned const SpMat& M;
arma_aligned uword internal_col; arma_aligned uword internal_col;
arma_aligned uword internal_pos; arma_aligned uword internal_pos;
}; };
class const_iterator : public iterator_base class const_iterator : public iterator_base
{ {
public: public:
inline const_iterator(const SpMat& in_M, uword initial_pos = 0); // Ass umes initial_pos is valid. inline const_iterator(const SpMat& in_M, uword initial_pos = 0); // Ass umes initial_pos is valid.
//! Once initialized, will be at the first nonzero value after the give n position (using forward columnwise traversal). //! Once initialized, will be at the first nonzero value after the give n position (using forward columnwise traversal).
inline const_iterator(const SpMat& in_M, uword in_row, uword in_col); inline const_iterator(const SpMat& in_M, uword in_row, uword in_col);
//! If you know the exact position of the iterator. in_row is a dummy
argument.
inline const_iterator(const SpMat& in_M, uword in_row, uword in_col, uw
ord in_pos);
inline const_iterator(const const_iterator& other); inline const_iterator(const const_iterator& other);
inline const_iterator& operator++(); inline arma_hot const_iterator& operator++();
inline void operator++(int); inline arma_hot void operator++(int);
inline const_iterator& operator--(); inline arma_hot const_iterator& operator--();
inline void operator--(int); inline arma_hot void operator--(int);
}; };
/** /**
* So that we can iterate over nonzero values, we need an iterator * So that we can iterate over nonzero values, we need an iterator
* implementation. This can't be as simple as Mat's, which is just a poi nter * implementation. This can't be as simple as Mat's, which is just a poi nter
* to an eT. If a value is set to 0 using this iterator, the iterator is no * to an eT. If a value is set to 0 using this iterator, the iterator is no
* longer valid! * longer valid!
*/ */
class iterator : public const_iterator class iterator : public const_iterator
{ {
public: public:
inline iterator(SpMat& in_M, uword initial_pos = 0) : const_iterator(in _M, initial_pos) { } inline iterator(SpMat& in_M, uword initial_pos = 0) : const_iterator(in _M, initial_pos) { }
inline iterator(SpMat& in_M, uword in_row, uword in_col) : const_iterat or(in_M, in_row, in_col) { } inline iterator(SpMat& in_M, uword in_row, uword in_col) : const_iterat or(in_M, in_row, in_col) { }
inline iterator(SpMat& in_M, uword in_row, uword in_col, uword in_pos) : const_iterator(in_M, in_row, in_col, in_pos) { }
inline iterator(const const_iterator& other) : const_iterator(other) { } inline iterator(const const_iterator& other) : const_iterator(other) { }
inline SpValProxy<SpMat<eT> > operator*(); inline arma_hot SpValProxy<SpMat<eT> > operator*();
// overloads needed for return type correctness // overloads needed for return type correctness
inline iterator& operator++(); inline arma_hot iterator& operator++();
inline void operator++(int); inline arma_hot void operator++(int);
inline iterator& operator--(); inline arma_hot iterator& operator--();
inline void operator--(int); inline arma_hot void operator--(int);
}; };
class const_row_iterator : public iterator_base class const_row_iterator : public iterator_base
{ {
public: public:
inline const_row_iterator(const SpMat& in_M, uword initial_pos = 0); inline const_row_iterator(const SpMat& in_M, uword initial_pos = 0);
//! Once initialized, will be at the first nonzero value after the give n position (using forward row-wise traversal). //! Once initialized, will be at the first nonzero value after the give n position (using forward row-wise traversal).
inline const_row_iterator(const SpMat& in_M, uword in_row, uword in_col ); inline const_row_iterator(const SpMat& in_M, uword in_row, uword in_col );
inline const_row_iterator(const const_row_iterator& other); inline const_row_iterator(const const_row_iterator& other);
inline const_row_iterator& operator++(); inline arma_hot const_row_iterator& operator++();
inline void operator++(int); inline arma_hot void operator++(int);
inline const_row_iterator& operator--(); inline arma_hot const_row_iterator& operator--();
inline void operator--(int); inline arma_hot void operator--(int);
uword internal_row; // Hold row internally because we use internal_pos differently. uword internal_row; // Hold row internally because we use internal_pos differently.
uword actual_pos; // Actual position in matrix. uword actual_pos; // Actual position in matrix.
arma_inline eT operator*() const { return iterator_base::M.values[actua l_pos]; } arma_inline eT operator*() const { return iterator_base::M.values[actua l_pos]; }
arma_inline uword row() const { return internal_row; } arma_inline uword row() const { return internal_row; }
}; };
class row_iterator : public const_row_iterator class row_iterator : public const_row_iterator
{ {
public: public:
inline row_iterator(SpMat& in_M, uword initial_pos = 0) : const_row_ite rator(in_M, initial_pos) { } inline row_iterator(SpMat& in_M, uword initial_pos = 0) : const_row_ite rator(in_M, initial_pos) { }
//! Once initialized, will be at the first nonzero value after the give n position (using forward row-wise traversal). //! Once initialized, will be at the first nonzero value after the give n position (using forward row-wise traversal).
inline row_iterator(SpMat& in_M, uword in_row, uword in_col) : const_ro w_iterator(in_M, in_row, in_col) { } inline row_iterator(SpMat& in_M, uword in_row, uword in_col) : const_ro w_iterator(in_M, in_row, in_col) { }
inline row_iterator(const row_iterator& other) : const_row_iterator(oth er) { } inline row_iterator(const row_iterator& other) : const_row_iterator(oth er) { }
inline SpValProxy<SpMat<eT> > operator*(); inline arma_hot SpValProxy<SpMat<eT> > operator*();
// overloads required for return type correctness // overloads required for return type correctness
inline row_iterator& operator++(); inline arma_hot row_iterator& operator++();
inline void operator++(int); inline arma_hot void operator++(int);
inline row_iterator& operator--(); inline arma_hot row_iterator& operator--();
inline void operator--(int); inline arma_hot void operator--(int);
}; };
inline iterator begin(); inline iterator begin();
inline const_iterator begin() const; inline const_iterator begin() const;
inline iterator end(); inline iterator end();
inline const_iterator end() const; inline const_iterator end() const;
inline iterator begin_col(const uword col_num); inline iterator begin_col(const uword col_num);
inline const_iterator begin_col(const uword col_num) const; inline const_iterator begin_col(const uword col_num) const;
inline iterator end_col(const uword col_num); inline iterator end_col(const uword col_num);
inline const_iterator end_col(const uword col_num) const; inline const_iterator end_col(const uword col_num) const;
inline row_iterator begin_row(const uword row_num = 0); inline row_iterator begin_row(const uword row_num = 0);
inline const_row_iterator begin_row(const uword row_num = 0) const; inline const_row_iterator begin_row(const uword row_num = 0) const;
 End of changes. 17 change blocks. 
27 lines changed or deleted 34 lines changed or added


 SpMat_iterators_meat.hpp   SpMat_iterators_meat.hpp 
skipping to change at line 43 skipping to change at line 43
SpMat<eT>::iterator_base::iterator_base(const SpMat<eT>& in_M, const uword col, const uword pos) SpMat<eT>::iterator_base::iterator_base(const SpMat<eT>& in_M, const uword col, const uword pos)
: M(in_M) : M(in_M)
, internal_col(col) , internal_col(col)
, internal_pos(pos) , internal_pos(pos)
{ {
// Nothing to do. // Nothing to do.
} }
template<typename eT> template<typename eT>
inline inline
arma_hot
eT eT
SpMat<eT>::iterator_base::operator*() const SpMat<eT>::iterator_base::operator*() const
{ {
return M.values[internal_pos]; return M.values[internal_pos];
} }
template<typename eT> template<typename eT>
inline inline
arma_hot
bool bool
SpMat<eT>::iterator_base::operator==(const iterator_base& rhs) const SpMat<eT>::iterator_base::operator==(const iterator_base& rhs) const
{ {
return (rhs.row() == row()) && (rhs.col() == internal_col); return (rhs.row() == row()) && (rhs.col() == internal_col);
} }
template<typename eT> template<typename eT>
inline inline
arma_hot
bool bool
SpMat<eT>::iterator_base::operator!=(const iterator_base& rhs) const SpMat<eT>::iterator_base::operator!=(const iterator_base& rhs) const
{ {
return (rhs.row() != row()) || (rhs.col() != internal_col); return (rhs.row() != row()) || (rhs.col() != internal_col);
} }
template<typename eT> template<typename eT>
inline inline
arma_hot
bool bool
SpMat<eT>::iterator_base::operator==(const typename SpSubview<eT>::iterator _base& rhs) const SpMat<eT>::iterator_base::operator==(const typename SpSubview<eT>::iterator _base& rhs) const
{ {
return (rhs.row() == row()) && (rhs.col() == internal_col); return (rhs.row() == row()) && (rhs.col() == internal_col);
} }
template<typename eT> template<typename eT>
inline inline
arma_hot
bool bool
SpMat<eT>::iterator_base::operator!=(const typename SpSubview<eT>::iterator _base& rhs) const SpMat<eT>::iterator_base::operator!=(const typename SpSubview<eT>::iterator _base& rhs) const
{ {
return (rhs.row() != row()) || (rhs.col() != internal_col); return (rhs.row() != row()) || (rhs.col() != internal_col);
} }
/////////////////////////////////////////////////////////////////////////// //// /////////////////////////////////////////////////////////////////////////// ////
// SpMat::const_iterator implementation // // SpMat::const_iterator implementation //
/////////////////////////////////////////////////////////////////////////// //// /////////////////////////////////////////////////////////////////////////// ////
template<typename eT> template<typename eT>
inline inline
SpMat<eT>::const_iterator::const_iterator(const SpMat<eT>& in_M, uword init ial_pos) SpMat<eT>::const_iterator::const_iterator(const SpMat<eT>& in_M, uword init ial_pos)
: iterator_base(in_M, 0, initial_pos) : iterator_base(in_M, 0, initial_pos)
{ {
// Corner case for empty matrices.
if(in_M.n_nonzero == 0)
{
iterator_base::internal_col = in_M.n_cols;
return;
}
// Determine which column we should be in. // Determine which column we should be in.
while(iterator_base::M.col_ptrs[iterator_base::internal_col + 1] <= itera tor_base::internal_pos) while(iterator_base::M.col_ptrs[iterator_base::internal_col + 1] <= itera tor_base::internal_pos)
{ {
iterator_base::internal_col++; iterator_base::internal_col++;
} }
} }
template<typename eT> template<typename eT>
inline inline
SpMat<eT>::const_iterator::const_iterator(const SpMat<eT>& in_M, uword in_r ow, uword in_col) SpMat<eT>::const_iterator::const_iterator(const SpMat<eT>& in_M, uword in_r ow, uword in_col)
skipping to change at line 120 skipping to change at line 132
// Now we have to get to the right row. // Now we have to get to the right row.
while((iterator_base::M.row_indices[iterator_base::internal_pos] < in_row ) && (iterator_base::internal_col == in_col)) while((iterator_base::M.row_indices[iterator_base::internal_pos] < in_row ) && (iterator_base::internal_col == in_col))
{ {
++(*this); // Increment iterator. ++(*this); // Increment iterator.
} }
} }
template<typename eT> template<typename eT>
inline inline
SpMat<eT>::const_iterator::const_iterator(const SpMat<eT>& in_M, const uwor
d /* in_row */, const uword in_col, const uword in_pos)
: iterator_base(in_M, in_col, in_pos)
{
// Nothing to do.
}
template<typename eT>
inline
SpMat<eT>::const_iterator::const_iterator(const typename SpMat<eT>::const_i terator& other) SpMat<eT>::const_iterator::const_iterator(const typename SpMat<eT>::const_i terator& other)
: iterator_base(other.M, other.internal_col, other.internal_pos) : iterator_base(other.M, other.internal_col, other.internal_pos)
{ {
// Nothing to do. // Nothing to do.
} }
template<typename eT> template<typename eT>
inline inline
arma_hot
typename SpMat<eT>::const_iterator& typename SpMat<eT>::const_iterator&
SpMat<eT>::const_iterator::operator++() SpMat<eT>::const_iterator::operator++()
{ {
++iterator_base::internal_pos; ++iterator_base::internal_pos;
if (iterator_base::internal_pos == iterator_base::M.n_nonzero) if (iterator_base::internal_pos == iterator_base::M.n_nonzero)
{ {
iterator_base::internal_col = iterator_base::M.n_cols; iterator_base::internal_col = iterator_base::M.n_cols;
return *this; return *this;
} }
skipping to change at line 150 skipping to change at line 171
while (iterator_base::M.col_ptrs[iterator_base::internal_col + 1] <= iter ator_base::internal_pos) while (iterator_base::M.col_ptrs[iterator_base::internal_col + 1] <= iter ator_base::internal_pos)
{ {
++iterator_base::internal_col; ++iterator_base::internal_col;
} }
return *this; return *this;
} }
template<typename eT> template<typename eT>
inline inline
arma_hot
void void
SpMat<eT>::const_iterator::operator++(int) SpMat<eT>::const_iterator::operator++(int)
{ {
++(*this); ++(*this);
} }
template<typename eT> template<typename eT>
inline inline
arma_hot
typename SpMat<eT>::const_iterator& typename SpMat<eT>::const_iterator&
SpMat<eT>::const_iterator::operator--() SpMat<eT>::const_iterator::operator--()
{ {
iterator_base::M.print("M"); //iterator_base::M.print("M");
// printf("decrement from %d, %d, %d\n", iterator_base::internal_pos, ite rator_base::internal_col, iterator_base::row()); // printf("decrement from %d, %d, %d\n", iterator_base::internal_pos, ite rator_base::internal_col, iterator_base::row());
--iterator_base::internal_pos; --iterator_base::internal_pos;
// printf("now pos %d\n", iterator_base::internal_pos); // printf("now pos %d\n", iterator_base::internal_pos);
// First, see if we moved back a column. // First, see if we moved back a column.
while (iterator_base::internal_pos < iterator_base::M.col_ptrs[iterator_b ase::internal_col]) while (iterator_base::internal_pos < iterator_base::M.col_ptrs[iterator_b ase::internal_col])
{ {
// printf("colptr %d (col %d)\n", iterator_base::M.col_ptrs[iterator_ba se::internal_col], iterator_base::internal_col); // printf("colptr %d (col %d)\n", iterator_base::M.col_ptrs[iterator_ba se::internal_col], iterator_base::internal_col);
--iterator_base::internal_col; --iterator_base::internal_col;
} }
return *this; return *this;
} }
template<typename eT> template<typename eT>
inline inline
arma_hot
void void
SpMat<eT>::const_iterator::operator--(int) SpMat<eT>::const_iterator::operator--(int)
{ {
--(*this); --(*this);
} }
/////////////////////////////////////////////////////////////////////////// //// /////////////////////////////////////////////////////////////////////////// ////
// SpMat::iterator implementation // // SpMat::iterator implementation //
/////////////////////////////////////////////////////////////////////////// //// /////////////////////////////////////////////////////////////////////////// ////
template<typename eT> template<typename eT>
inline inline
arma_hot
SpValProxy<SpMat<eT> > SpValProxy<SpMat<eT> >
SpMat<eT>::iterator::operator*() SpMat<eT>::iterator::operator*()
{ {
return SpValProxy<SpMat<eT> >( return SpValProxy<SpMat<eT> >(
iterator_base::M.row_indices[iterator_base::internal_pos], iterator_base::M.row_indices[iterator_base::internal_pos],
iterator_base::internal_col, iterator_base::internal_col,
access::rw(iterator_base::M), access::rw(iterator_base::M),
&access::rw(iterator_base::M.values[iterator_base::internal_pos])); &access::rw(iterator_base::M.values[iterator_base::internal_pos]));
} }
template<typename eT> template<typename eT>
inline inline
arma_hot
typename SpMat<eT>::iterator& typename SpMat<eT>::iterator&
SpMat<eT>::iterator::operator++() SpMat<eT>::iterator::operator++()
{ {
const_iterator::operator++(); const_iterator::operator++();
return *this; return *this;
} }
template<typename eT> template<typename eT>
inline inline
arma_hot
void void
SpMat<eT>::iterator::operator++(int) SpMat<eT>::iterator::operator++(int)
{ {
const_iterator::operator++(); const_iterator::operator++();
} }
template<typename eT> template<typename eT>
inline inline
arma_hot
typename SpMat<eT>::iterator& typename SpMat<eT>::iterator&
SpMat<eT>::iterator::operator--() SpMat<eT>::iterator::operator--()
{ {
const_iterator::operator--(); const_iterator::operator--();
return *this; return *this;
} }
template<typename eT> template<typename eT>
inline inline
arma_hot
void void
SpMat<eT>::iterator::operator--(int) SpMat<eT>::iterator::operator--(int)
{ {
const_iterator::operator--(); const_iterator::operator--();
} }
/////////////////////////////////////////////////////////////////////////// //// /////////////////////////////////////////////////////////////////////////// ////
// SpMat::const_row_iterator implementation // // SpMat::const_row_iterator implementation //
/////////////////////////////////////////////////////////////////////////// //// /////////////////////////////////////////////////////////////////////////// ////
/** /**
* Initialize the const_row_iterator. * Initialize the const_row_iterator.
*/ */
template<typename eT> template<typename eT>
inline inline
SpMat<eT>::const_row_iterator::const_row_iterator(const SpMat<eT>& in_M, uw ord initial_pos) SpMat<eT>::const_row_iterator::const_row_iterator(const SpMat<eT>& in_M, uw ord initial_pos)
: iterator_base(in_M, 0, initial_pos) : iterator_base(in_M, 0, initial_pos)
, internal_row(0) , internal_row(0)
, actual_pos(0) , actual_pos(0)
{ {
// Corner case for empty matrix.
if(in_M.n_nonzero == 0)
{
iterator_base::internal_col = in_M.n_cols;
return;
}
// We don't count zeroes in our position count, so we have to find the no nzero // We don't count zeroes in our position count, so we have to find the no nzero
// value corresponding to the given initial position. We assume initial_ pos // value corresponding to the given initial position. We assume initial_ pos
// is valid. // is valid.
// This is irritating because we don't know where the elements are in eac h // This is irritating because we don't know where the elements are in eac h
// row. What we will do is loop across all columns looking for elements in // row. What we will do is loop across all columns looking for elements in
// row 0 (and add to our sum), then in row 1, and so forth, until we get to // row 0 (and add to our sum), then in row 1, and so forth, until we get to
// the desired position. // the desired position.
uword cur_pos = -1; uword cur_pos = -1;
uword cur_row = 0; uword cur_row = 0;
skipping to change at line 343 skipping to change at line 379
, actual_pos(other.actual_pos) , actual_pos(other.actual_pos)
{ {
// Nothing to do. // Nothing to do.
} }
/** /**
* Increment the row_iterator. * Increment the row_iterator.
*/ */
template<typename eT> template<typename eT>
inline inline
arma_hot
typename SpMat<eT>::const_row_iterator& typename SpMat<eT>::const_row_iterator&
SpMat<eT>::const_row_iterator::operator++() SpMat<eT>::const_row_iterator::operator++()
{ {
// We just need to find the next nonzero element. // We just need to find the next nonzero element.
iterator_base::internal_pos++; iterator_base::internal_pos++;
if(iterator_base::internal_pos == iterator_base::M.n_nonzero) if(iterator_base::internal_pos == iterator_base::M.n_nonzero)
{ {
internal_row = iterator_base::M.n_rows; internal_row = iterator_base::M.n_rows;
iterator_base::internal_col = 0; iterator_base::internal_col = 0;
skipping to change at line 392 skipping to change at line 429
} }
} }
} }
} }
/** /**
* Increment the row_iterator (but do not return anything. * Increment the row_iterator (but do not return anything.
*/ */
template<typename eT> template<typename eT>
inline inline
arma_hot
void void
SpMat<eT>::const_row_iterator::operator++(int) SpMat<eT>::const_row_iterator::operator++(int)
{ {
++(*this); ++(*this);
} }
/** /**
* Decrement the row_iterator. * Decrement the row_iterator.
*/ */
template<typename eT> template<typename eT>
inline inline
arma_hot
typename SpMat<eT>::const_row_iterator& typename SpMat<eT>::const_row_iterator&
SpMat<eT>::const_row_iterator::operator--() SpMat<eT>::const_row_iterator::operator--()
{ {
iterator_base::internal_pos--; iterator_base::internal_pos--;
// We have to search backwards. // We have to search backwards.
uword cur_col = iterator_base::internal_col; uword cur_col = iterator_base::internal_col;
uword cur_row = internal_row; uword cur_row = internal_row;
while (true) // This loop is terminated from the inside. while (true) // This loop is terminated from the inside.
skipping to change at line 442 skipping to change at line 481
} }
} }
} }
} }
/** /**
* Decrement the row_iterator. * Decrement the row_iterator.
*/ */
template<typename eT> template<typename eT>
inline inline
arma_hot
void void
SpMat<eT>::const_row_iterator::operator--(int) SpMat<eT>::const_row_iterator::operator--(int)
{ {
--(*this); --(*this);
} }
/////////////////////////////////////////////////////////////////////////// //// /////////////////////////////////////////////////////////////////////////// ////
// SpMat::row_iterator implementation // // SpMat::row_iterator implementation //
/////////////////////////////////////////////////////////////////////////// //// /////////////////////////////////////////////////////////////////////////// ////
template<typename eT> template<typename eT>
inline inline
arma_hot
SpValProxy<SpMat<eT> > SpValProxy<SpMat<eT> >
SpMat<eT>::row_iterator::operator*() SpMat<eT>::row_iterator::operator*()
{ {
return SpValProxy<SpMat<eT> >( return SpValProxy<SpMat<eT> >(
const_row_iterator::internal_row, const_row_iterator::internal_row,
iterator_base::internal_col, iterator_base::internal_col,
access::rw(iterator_base::M), access::rw(iterator_base::M),
&access::rw(iterator_base::M.values[const_row_iterator::actual_pos])); &access::rw(iterator_base::M.values[const_row_iterator::actual_pos]));
} }
template<typename eT> template<typename eT>
inline inline
arma_hot
typename SpMat<eT>::row_iterator& typename SpMat<eT>::row_iterator&
SpMat<eT>::row_iterator::operator++() SpMat<eT>::row_iterator::operator++()
{ {
const_row_iterator::operator++(); const_row_iterator::operator++();
return *this; return *this;
} }
template<typename eT> template<typename eT>
inline inline
arma_hot
void void
SpMat<eT>::row_iterator::operator++(int) SpMat<eT>::row_iterator::operator++(int)
{ {
const_row_iterator::operator++(); const_row_iterator::operator++();
} }
template<typename eT> template<typename eT>
inline inline
arma_hot
typename SpMat<eT>::row_iterator& typename SpMat<eT>::row_iterator&
SpMat<eT>::row_iterator::operator--() SpMat<eT>::row_iterator::operator--()
{ {
const_row_iterator::operator--(); const_row_iterator::operator--();
return *this; return *this;
} }
template<typename eT> template<typename eT>
inline inline
arma_hot
void void
SpMat<eT>::row_iterator::operator--(int) SpMat<eT>::row_iterator::operator--(int)
{ {
const_row_iterator::operator--(); const_row_iterator::operator--();
} }
//! @} //! @}
 End of changes. 27 change blocks. 
1 lines changed or deleted 47 lines changed or added


 SpMat_meat.hpp   SpMat_meat.hpp 
skipping to change at line 28 skipping to change at line 28
* Initialize a sparse matrix with size 0x0 (empty). * Initialize a sparse matrix with size 0x0 (empty).
*/ */
template<typename eT> template<typename eT>
inline inline
SpMat<eT>::SpMat() SpMat<eT>::SpMat()
: n_rows(0) : n_rows(0)
, n_cols(0) , n_cols(0)
, n_elem(0) , n_elem(0)
, n_nonzero(0) , n_nonzero(0)
, vec_state(0) , vec_state(0)
, values(NULL) , values(memory::acquire_chunked<eT>(1))
, row_indices(NULL) , row_indices(memory::acquire_chunked<uword>(1))
, col_ptrs(memory::acquire<uword>(1)) , col_ptrs(memory::acquire<uword>(1))
{ {
arma_extra_debug_sigprint_this(this); arma_extra_debug_sigprint_this(this);
access::rw(values[0]) = 0;
access::rw(row_indices[0]) = 0;
access::rw(col_ptrs[0]) = 0; // No elements. access::rw(col_ptrs[0]) = 0; // No elements.
} }
/** /**
* Clean up the memory of a sparse matrix and destruct it. * Clean up the memory of a sparse matrix and destruct it.
*/ */
template<typename eT> template<typename eT>
inline inline
SpMat<eT>::~SpMat() SpMat<eT>::~SpMat()
{ {
skipping to change at line 243 skipping to change at line 246
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();
arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "addition "); arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "addition ");
// Iterate over nonzero values of other matrix. // Iterate over nonzero values of other matrix.
for (const_iterator it = x.begin(); it.pos() < x.n_nonzero; it++) for (const_iterator it = x.begin(); it != x.end(); it++)
{ {
get_value(it.row(), it.col()) += *it; get_value(it.row(), it.col()) += *it;
} }
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();
arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "subtract ion"); arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "subtract ion");
// Iterate over nonzero values of other matrix. // Iterate over nonzero values of other matrix.
for (const_iterator it = x.begin(); it.pos() < x.n_nonzero; it++) for (const_iterator it = x.begin(); it != x.end(); it++)
{ {
get_value(it.row(), it.col()) -= *it; get_value(it.row(), it.col()) -= *it;
} }
return *this; return *this;
} }
template<typename eT> template<typename eT>
inline inline
const SpMat<eT>& const SpMat<eT>&
skipping to change at line 299 skipping to change at line 302
SpMat<eT>::operator%=(const SpMat<eT>& x) SpMat<eT>::operator%=(const SpMat<eT>& x)
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "element- wise multiplication"); arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "element- wise multiplication");
// We can do this with two iterators rather simply. // We can do this with two iterators rather simply.
iterator it = begin(); iterator it = begin();
const_iterator x_it = x.begin(); const_iterator x_it = x.begin();
while (it.pos() < n_nonzero && x_it.pos() < x.n_nonzero) while (it != end() && x_it != x.end())
{ {
// One of these will be further advanced than the other (or they will b e at the same place). // One of these will be further advanced than the other (or they will b e at the same place).
if ((it.row() == x_it.row()) && (it.col() == x_it.col())) if ((it.row() == x_it.row()) && (it.col() == x_it.col()))
{ {
// There is an element at this place in both matrices. Multiply. // There is an element at this place in both matrices. Multiply.
(*it) *= (*x_it); (*it) *= (*x_it);
// Now move on to the next position. // Now move on to the next position.
it++; it++;
x_it++; x_it++;
skipping to change at line 335 skipping to change at line 338
else /* if our iterator is ahead of the other matrix */ else /* if our iterator is ahead of the other matrix */
{ {
// In this case we don't need to set anything to 0; our element is al ready 0. // In this case we don't need to set anything to 0; our element is al ready 0.
// We can just increment the iterator of the other matrix. // We can just increment the iterator of the other matrix.
x_it++; x_it++;
} }
} }
// If we are not at the end of our matrix, then we must terminate the rem aining elements. // If we are not at the end of our matrix, then we must terminate the rem aining elements.
while (it.pos() < n_nonzero) while (it != end())
{ {
(*it) = 0; (*it) = 0;
// Hack to manually set the position right... // Hack to manually set the position right...
it.internal_pos--; it.internal_pos--;
it++; // ...and then an increment. it++; // ...and then an increment.
} }
return *this; return *this;
} }
skipping to change at line 361 skipping to change at line 364
SpMat<eT>::SpMat SpMat<eT>::SpMat
( (
const SpBase<typename SpMat<eT>::pod_type, T1>& A, const SpBase<typename SpMat<eT>::pod_type, T1>& A,
const SpBase<typename SpMat<eT>::pod_type, T2>& B const SpBase<typename SpMat<eT>::pod_type, T2>& B
) )
: n_rows(0) : n_rows(0)
, n_cols(0) , n_cols(0)
, n_elem(0) , n_elem(0)
, n_nonzero(0) , n_nonzero(0)
, vec_state(0) , vec_state(0)
, values(NULL) , values(NULL) // extra element is set when mem_resize is called
, row_indices(NULL) , row_indices(NULL)
, col_ptrs(NULL) , col_ptrs(NULL)
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
typedef typename T1::elem_type T; typedef typename T1::elem_type T;
// Make sure eT is complex and T is not (compile-time check). // Make sure eT is complex and T is not (compile-time check).
arma_type_check(( is_complex<eT>::value == false )); arma_type_check(( is_complex<eT>::value == false ));
arma_type_check(( is_complex< T>::value == true )); arma_type_check(( is_complex< T>::value == true ));
skipping to change at line 395 skipping to change at line 398
// Set size of matrix correctly. // Set size of matrix correctly.
init(l_n_rows, l_n_cols); init(l_n_rows, l_n_cols);
mem_resize(n_unique(X, Y, op_n_unique_count())); mem_resize(n_unique(X, Y, op_n_unique_count()));
// Now on a second iteration, fill it. // Now on a second iteration, fill it.
typename SpMat<T>::const_iterator x_it = X.begin(); typename SpMat<T>::const_iterator x_it = X.begin();
typename SpMat<T>::const_iterator y_it = Y.begin(); typename SpMat<T>::const_iterator y_it = Y.begin();
uword cur_pos = 0; uword cur_pos = 0;
while ((x_it.pos() < X.n_nonzero) || (y_it.pos() < Y.n_nonzero)) while ((x_it != X.end()) || (y_it != Y.end()))
{ {
if(x_it == y_it) // if we are at the same place if(x_it == y_it) // if we are at the same place
{ {
access::rw(values[cur_pos]) = std::complex<T>((T) *x_it, (T) *y_it); access::rw(values[cur_pos]) = std::complex<T>((T) *x_it, (T) *y_it);
access::rw(row_indices[cur_pos]) = x_it.row(); access::rw(row_indices[cur_pos]) = x_it.row();
++access::rw(col_ptrs[x_it.col() + 1]); ++access::rw(col_ptrs[x_it.col() + 1]);
++x_it; ++x_it;
++y_it; ++y_it;
} }
skipping to change at line 468 skipping to change at line 471
template<typename eT> template<typename eT>
template<typename T1> template<typename T1>
inline inline
SpMat<eT>::SpMat(const Base<eT, T1>& x) SpMat<eT>::SpMat(const Base<eT, T1>& x)
: n_rows(0) : n_rows(0)
, n_cols(0) , n_cols(0)
, n_elem(0) , n_elem(0)
, n_nonzero(0) , n_nonzero(0)
, vec_state(0) , vec_state(0)
, values(NULL) , values(NULL) // extra element is set when mem_resize is called in opera tor=()
, row_indices(NULL) , row_indices(NULL)
, col_ptrs(NULL) , col_ptrs(NULL)
{ {
arma_extra_debug_sigprint_this(this); arma_extra_debug_sigprint_this(this);
(*this).operator=(x); (*this).operator=(x);
} }
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)
{ {
//No easy init function, will have to generate matrix manually.
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
const Proxy<T1> p(x.get_ref()); const Proxy<T1> p(x.get_ref());
const uword x_n_rows = p.get_n_rows(); const uword x_n_rows = p.get_n_rows();
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();
init(x_n_rows, x_n_cols); init(x_n_rows, x_n_cols);
// Count number of nonzero elements in base object.
uword n = 0;
if(Proxy<T1>::prefer_at_accessor == true)
{
for(uword j = 0; j < x_n_cols; ++j)
{
for(uword i = 0; i < x_n_rows; ++i)
{
if(p.at(i, j) != eT(0))
++n;
}
}
}
else
{
for(uword i = 0; i < x_n_elem; ++i)
{
if(p[i] != eT(0))
{
++n;
}
}
}
mem_resize(n);
// Now the memory is resized correctly; add nonzero elements.
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)
{ {
at(i,j) = p.at(i,j); // let SpValProxy handle 0's. for(uword i = 0; i < x_n_rows; ++i)
{
if(p.at(i, j) != eT(0))
{
access::rw(values[n]) = p.at(i, j);
access::rw(row_indices[n]) = i;
access::rw(col_ptrs[j + 1])++;
++n;
}
}
}
// Sum column counts to be column pointers.
for(uword c = 1; c <= n_cols; ++c)
{
access::rw(col_ptrs[c]) += col_ptrs[c - 1];
} }
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>& y) SpMat<eT>::operator*=(const Base<eT, T1>& y)
skipping to change at line 555 skipping to change at line 600
// Now we have to fill all the elements using a modification of the NUMBM M algorithm. // Now we have to fill all the elements using a modification of the NUMBM M algorithm.
uword cur_pos = 0; uword cur_pos = 0;
podarray<eT> partial_sums(n_rows); podarray<eT> partial_sums(n_rows);
partial_sums.zeros(); partial_sums.zeros();
for(uword col = 0; col < n_cols; ++col) for(uword col = 0; col < n_cols; ++col)
{ {
const_iterator it = begin(); const_iterator it = begin();
while(it.pos() < n_nonzero) while(it != end())
{ {
const eT value = (*it); const eT value = (*it);
partial_sums[it.row()] += (value * p.at(it.col(), col)); partial_sums[it.row()] += (value * p.at(it.col(), col));
++it; ++it;
} }
// Now add all partial sums to the matrix. // Now add all partial sums to the matrix.
for(uword i = 0; i < n_rows; ++i) for(uword i = 0; i < n_rows; ++i)
{ {
if(partial_sums[i] != 0) if(partial_sums[i] != eT(0))
{ {
access::rw(z.values[cur_pos]) = partial_sums[i]; access::rw(z.values[cur_pos]) = partial_sums[i];
access::rw(z.row_indices[cur_pos]) = i; access::rw(z.row_indices[cur_pos]) = i;
++access::rw(z.col_ptrs[col + 1]); ++access::rw(z.col_ptrs[col + 1]);
//printf("colptr %d now %d\n", col + 1, z.col_ptrs[col + 1]); //printf("colptr %d now %d\n", col + 1, z.col_ptrs[col + 1]);
++cur_pos; ++cur_pos;
partial_sums[i] = 0; // Would it be faster to do this in batch late r? partial_sums[i] = 0; // Would it be faster to do this in batch late r?
} }
} }
} }
skipping to change at line 636 skipping to change at line 681
const Proxy<T1> p(x.get_ref()); const Proxy<T1> p(x.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");
// Count the number of elements we will need. // Count the number of elements we will need.
SpMat<eT> tmp(n_rows, n_cols); SpMat<eT> tmp(n_rows, n_cols);
const_iterator it = begin(); const_iterator it = begin();
uword new_n_nonzero = 0; uword new_n_nonzero = 0;
while(it.pos() < n_nonzero()) while(it != end())
{ {
// prefer_at_accessor == false can't save us any work here // prefer_at_accessor == false can't save us any work here
if(((*it) * x.at(it.row(), it.col())) != 0) if(((*it) * p.at(it.row(), it.col())) != eT(0))
{ {
++new_n_nonzero; ++new_n_nonzero;
} }
++it; ++it;
} }
// Resize. // Resize.
tmp.mem_resize(new_n_nonzero); tmp.mem_resize(new_n_nonzero);
const_iterator c_it = begin(); const_iterator c_it = begin();
uword cur_pos = 0; uword cur_pos = 0;
while(c_it.pos() < n_nonzero) while(c_it != end())
{ {
// prefer_at_accessor == false can't save us any work here // prefer_at_accessor == false can't save us any work here
const eT val = (*c_it) * x(c_it.row(), c_it.col()); const eT val = (*c_it) * p.at(c_it.row(), c_it.col());
if(val != 0) if(val != eT(0))
{ {
access::rw(tmp.values[cur_pos]) = val; access::rw(tmp.values[cur_pos]) = val;
access::rw(tmp.row_indices[cur_pos]) = c_it.row(); access::rw(tmp.row_indices[cur_pos]) = c_it.row();
++access::rw(tmp.col_ptrs[c_it.col() + 1]); ++access::rw(tmp.col_ptrs[c_it.col() + 1]);
++cur_pos; ++cur_pos;
} }
++c_it; ++c_it;
} }
skipping to change at line 688 skipping to change at line 733
* Functions on subviews. * Functions on subviews.
*/ */
template<typename eT> template<typename eT>
inline inline
SpMat<eT>::SpMat(const SpSubview<eT>& X) SpMat<eT>::SpMat(const SpSubview<eT>& X)
: n_rows(0) : n_rows(0)
, n_cols(0) , n_cols(0)
, n_elem(0) , n_elem(0)
, n_nonzero(0) , n_nonzero(0)
, vec_state(0) , vec_state(0)
, values(NULL) , values(NULL) // extra element added when mem_resize is called
, row_indices(NULL) , row_indices(NULL)
, col_ptrs(NULL) , col_ptrs(NULL)
{ {
arma_extra_debug_sigprint_this(this); arma_extra_debug_sigprint_this(this);
(*this).operator=(X); (*this).operator=(X);
} }
template<typename eT> template<typename eT>
inline inline
skipping to change at line 713 skipping to change at line 758
const uword in_n_cols = X.n_cols; const uword in_n_cols = X.n_cols;
const uword in_n_rows = X.n_rows; const uword in_n_rows = X.n_rows;
const bool alias = (this == &(X.m)); const bool alias = (this == &(X.m));
if(alias == false) if(alias == false)
{ {
init(in_n_rows, in_n_cols); init(in_n_rows, in_n_cols);
const uword x_n_nonzero = X.n_nonzero;
mem_resize(x_n_nonzero);
typename SpSubview<eT>::const_iterator it = X.begin(); typename SpSubview<eT>::const_iterator it = X.begin();
while(it.pos() < X.n_nonzero) while(it != X.end())
{ {
at(it.row(), it.col()) = (*it); access::rw(row_indices[it.pos()]) = it.row();
access::rw(values[it.pos()]) = (*it);
++access::rw(col_ptrs[it.col() + 1]);
++it; ++it;
} }
// Now sum column pointers.
for(uword c = 1; c <= n_cols; ++c)
{
access::rw(col_ptrs[c]) += col_ptrs[c - 1];
}
} }
else else
{ {
// Create it in a temporary. // Create it in a temporary.
SpMat<eT> tmp(X); SpMat<eT> tmp(X);
steal_mem(tmp); steal_mem(tmp);
} }
return *this; return *this;
skipping to change at line 741 skipping to change at line 798
template<typename eT> template<typename eT>
inline inline
const SpMat<eT>& const SpMat<eT>&
SpMat<eT>::operator+=(const SpSubview<eT>& X) SpMat<eT>::operator+=(const SpSubview<eT>& X)
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
arma_debug_assert_same_size(n_rows, n_cols, X.n_rows, X.n_cols, "addition "); arma_debug_assert_same_size(n_rows, n_cols, X.n_rows, X.n_cols, "addition ");
const uword in_n_cols = X.n_cols; typename SpSubview<eT>::const_iterator it = X.begin();
const uword in_n_rows = X.n_rows;
const_iterator it = const_iterator(X.m, X.aux_row1, X.aux_col1);
while(it.col < (X.aux_col1 + in_n_cols)) while(it != X.end())
{ {
// Is it within the proper range? at(it.row(), it.col()) += (*it);
if((it.row >= X.aux_row1) && (it.row < (X.aux_row1 + in_n_rows)))
{
at(it.row - X.aux_row1, it.col - X.aux_col1) += (*it);
}
++it; ++it;
} }
return *this; return *this;
} }
template<typename eT> template<typename eT>
inline inline
const SpMat<eT>& const SpMat<eT>&
SpMat<eT>::operator-=(const SpSubview<eT>& X) SpMat<eT>::operator-=(const SpSubview<eT>& X)
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
arma_debug_assert_same_size(n_rows, n_cols, X.n_rows, X.n_cols, "subtract ion"); arma_debug_assert_same_size(n_rows, n_cols, X.n_rows, X.n_cols, "subtract ion");
const uword in_n_cols = X.n_cols; typename SpSubview<eT>::const_iterator it = X.begin();
const uword in_n_rows = X.n_rows;
const_iterator it = const_iterator(X.m, X.aux_row1, X.aux_col1);
while(it.col < (X.aux_col1 + in_n_cols)) while(it != X.end())
{ {
// Is it within the proper range? at(it.row(), it.col()) -= (*it);
if((it.row >= X.aux_row1) && (it.row < (X.aux_row1 + in_n_rows)))
{
at(it.row - X.aux_row1, it.col - X.aux_col1) -= (*it);
}
++it; ++it;
} }
return *this; return *this;
} }
template<typename eT> template<typename eT>
inline inline
const SpMat<eT>& const SpMat<eT>&
SpMat<eT>::operator*=(const SpSubview<eT>& y) SpMat<eT>::operator*=(const SpSubview<eT>& y)
skipping to change at line 813 skipping to change at line 854
template<typename eT> template<typename eT>
inline inline
const SpMat<eT>& const SpMat<eT>&
SpMat<eT>::operator%=(const SpSubview<eT>& x) SpMat<eT>::operator%=(const SpSubview<eT>& x)
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "element- wise multiplication"); arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "element- wise multiplication");
// We want to iterate over whichever has fewer nonzero points. iterator it = begin();
if (n_nonzero <= x.n_nonzero) typename SpSubview<eT>::const_iterator xit = x.begin();
while((it != end()) || (xit != x.end()))
{ {
// Use our iterator. if((xit.row() == it.row()) && (xit.col() == it.col()))
for (iterator it = begin(); it.pos() < n_nonzero; it++)
{ {
(*it) *= x(it.row(), it.col()); (*it) *= (*xit);
++it;
++xit;
} }
} else
else
{
// Use their iterator. A little more complex...
const_iterator it = const_iterator(x.m, x.aux_row1, x.aux_col1);
while((it.col() < (x.aux_col1 + x.n_cols)))
{ {
if((it.row() >= x.aux_row1) && (it.row() < (x.aux_row1 + x.n_rows))) if((xit.col() > it.col()) || ((xit.col() == it.col()) && (xit.row() > it.row())))
{ {
at(it.row() - x.aux_row1, it.col() - x.aux_col1) *= (*it); // xit is "ahead"
(*it) = eT(0); // erase element; x has a zero here
it.internal_pos--; // update iterator so it still works
++it;
}
else
{
// it is "ahead"
++xit;
} }
++it;
} }
} }
return *this; return *this;
} }
template<typename eT> template<typename eT>
inline inline
const SpMat<eT>& const SpMat<eT>&
SpMat<eT>::operator/=(const SpSubview<eT>& x) SpMat<eT>::operator/=(const SpSubview<eT>& x)
skipping to change at line 869 skipping to change at line 914
* Operators on regular subviews. * Operators on regular subviews.
*/ */
template<typename eT> template<typename eT>
inline inline
SpMat<eT>::SpMat(const subview<eT>& x) SpMat<eT>::SpMat(const subview<eT>& x)
: n_rows(0) : n_rows(0)
, n_cols(0) , n_cols(0)
, n_elem(0) , n_elem(0)
, n_nonzero(0) , n_nonzero(0)
, vec_state(0) , vec_state(0)
, values(NULL) , values(NULL) // extra value set in operator=()
, row_indices(NULL) , row_indices(NULL)
, col_ptrs(NULL) , col_ptrs(NULL)
{ {
arma_extra_debug_sigprint_this(this); arma_extra_debug_sigprint_this(this);
(*this).operator=(x); (*this).operator=(x);
} }
template<typename eT> template<typename eT>
inline inline
const SpMat<eT>& const SpMat<eT>&
SpMat<eT>::operator=(const subview<eT>& x) SpMat<eT>::operator=(const subview<eT>& x)
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
const uword x_n_rows = x.n_rows;
const uword x_n_cols = x.n_cols;
// Set the size correctly. // Set the size correctly.
init(x.n_rows, x.n_cols); init(x_n_rows, x_n_cols);
// Count number of nonzero elements.
uword n = 0;
for(uword c = 0; c < x_n_cols; ++c)
{
for(uword r = 0; r < x_n_rows; ++r)
{
if(x.at(r, c) != eT(0))
{
++n;
}
}
}
// Resize memory appropriately.
mem_resize(n);
for(uword col = 0; col < x.n_cols; col++) n = 0;
for(uword c = 0; c < x_n_cols; ++c)
{ {
for(uword row = 0; row < x.n_rows; row++) for(uword r = 0; r < x_n_rows; ++r)
{ {
// Add any nonzero values. const eT val = x.at(r, c);
at(row, col) = x.at(row, col);
if(val != eT(0))
{
access::rw(values[n]) = val;
access::rw(row_indices[n]) = r;
++access::rw(col_ptrs[c + 1]);
++n;
}
} }
} }
// Fix column counts into column pointers.
for(uword c = 1; c <= n_cols; ++c)
{
access::rw(col_ptrs[c]) += col_ptrs[c - 1];
}
return *this; return *this;
} }
template<typename eT> template<typename eT>
inline inline
const SpMat<eT>& const SpMat<eT>&
SpMat<eT>::operator+=(const subview<eT>& x) SpMat<eT>::operator+=(const subview<eT>& x)
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "addition "); arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "addition ");
// Loop over every element. This could probably be written in a more // Loop over every element. This could probably be written in a more
// efficient way, by calculating the number of nonzero elements the outpu t // efficient way, by calculating the number of nonzero elements the outpu t
// matrix will have, allocating the memory correctly, and then filling th e // matrix will have, allocating the memory correctly, and then filling th e
// matrix correctly. However... for now, this works okay. // matrix correctly. However... for now, this works okay.
for(uword col = 0; col < n_cols; ++col) for(uword col = 0; col < n_cols; ++col)
{ {
for(uword row = 0; row < n_rows; ++row) for(uword row = 0; row < n_rows; ++row)
{ {
at(row, col) += x(row, col); at(row, col) += x.at(row, col);
} }
} }
return *this; return *this;
} }
template<typename eT> template<typename eT>
inline inline
const SpMat<eT>& const SpMat<eT>&
SpMat<eT>::operator-=(const subview<eT>& x) SpMat<eT>::operator-=(const subview<eT>& x)
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "subtract ion"); arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "subtract ion");
// Loop over every element. // Loop over every element.
for(uword col = 0; col < n_cols; ++col) for(uword col = 0; col < n_cols; ++col)
{ {
for(uword row = 0; row < n_rows; ++row) for(uword row = 0; row < n_rows; ++row)
{ {
at(row, col) -= x(row, col); at(row, col) -= x.at(row, col);
} }
} }
return *this; return *this;
} }
template<typename eT> template<typename eT>
inline inline
const SpMat<eT>& const SpMat<eT>&
SpMat<eT>::operator*=(const subview<eT>& y) SpMat<eT>::operator*=(const subview<eT>& y)
skipping to change at line 987 skipping to change at line 1065
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "element- wise multiplication"); arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "element- wise multiplication");
// Loop over every element. // Loop over every element.
for(uword col = 0; col < n_cols; ++col) for(uword col = 0; col < n_cols; ++col)
{ {
for(uword row = 0; row < n_rows; ++row) for(uword row = 0; row < n_rows; ++row)
{ {
at(row, col) *= x(row, col); at(row, col) *= x.at(row, col);
} }
} }
return *this; return *this;
} }
template<typename eT> template<typename eT>
inline inline
const SpMat<eT>& const SpMat<eT>&
SpMat<eT>::operator/=(const subview<eT>& x) SpMat<eT>::operator/=(const subview<eT>& x)
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "element- wise division"); arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "element- wise division");
// Loop over every element. // Loop over every element.
for(uword col = 0; col < n_cols; ++col) for(uword col = 0; col < n_cols; ++col)
{ {
for(uword row = 0; row < n_rows; ++row) for(uword row = 0; row < n_rows; ++row)
{ {
at(row, col) /= x(row, col); at(row, col) /= x.at(row, col);
} }
} }
return *this; return *this;
} }
template<typename eT> template<typename eT>
template<typename T1, typename spop_type> template<typename T1, typename spop_type>
inline inline
SpMat<eT>::SpMat(const SpOp<T1, spop_type>& X) SpMat<eT>::SpMat(const SpOp<T1, spop_type>& X)
: n_rows(0) : n_rows(0)
, n_cols(0) , n_cols(0)
, n_elem(0) , n_elem(0)
, n_nonzero(0) , n_nonzero(0)
, vec_state(0) , vec_state(0)
, values(NULL) , values(NULL) // set in application of sparse operation
, row_indices(NULL) , row_indices(NULL)
, col_ptrs(NULL) , col_ptrs(NULL)
{ {
arma_extra_debug_sigprint_this(this); arma_extra_debug_sigprint_this(this);
arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == fa lse )); arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == fa lse ));
spop_type::apply(*this, X); spop_type::apply(*this, X);
} }
skipping to change at line 1134 skipping to change at line 1212
template<typename eT> template<typename eT>
template<typename T1, typename T2, typename spglue_type> template<typename T1, typename T2, typename spglue_type>
inline inline
SpMat<eT>::SpMat(const SpGlue<T1, T2, spglue_type>& X) SpMat<eT>::SpMat(const SpGlue<T1, T2, spglue_type>& X)
: n_rows(0) : n_rows(0)
, n_cols(0) , n_cols(0)
, n_elem(0) , n_elem(0)
, n_nonzero(0) , n_nonzero(0)
, vec_state(0) , vec_state(0)
, values(NULL) , values(NULL) // extra element set in application of sparse glue
, row_indices(NULL) , row_indices(NULL)
, col_ptrs(NULL) , col_ptrs(NULL)
{ {
arma_extra_debug_sigprint_this(this); arma_extra_debug_sigprint_this(this);
arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == fa lse )); arma_type_check(( is_same_type< eT, typename T1::elem_type >::value == fa lse ));
spglue_type::apply(*this, X); spglue_type::apply(*this, X);
} }
skipping to change at line 1262 skipping to change at line 1340
return SpSubview<eT>(*this, row_num, 0, 1, n_cols); return SpSubview<eT>(*this, row_num, 0, 1, n_cols);
} }
template<typename eT> template<typename eT>
inline inline
SpSubview<eT> SpSubview<eT>
SpMat<eT>::operator()(const uword row_num, const span& col_span) SpMat<eT>::operator()(const uword row_num, const span& col_span)
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
return SpSubview<eT>(*this, row_num, col_span.a, col_span.b - col_span.a const bool col_all = col_span.whole;
+ 1);
const uword local_n_cols = n_cols;
const uword in_col1 = col_all ? 0 : col_span.a;
const uword in_col2 = col_span.b;
const uword submat_n_cols = col_all ? local_n_cols : in_col2 - in_col1 +
1;
arma_debug_check
(
(row_num >= n_rows)
||
( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= local_n_cols))
)
,
"SpMat::operator(): indices out of bounds or incorrectly used"
);
return SpSubview<eT>(*this, row_num, in_col1, 1, submat_n_cols);
} }
template<typename eT> template<typename eT>
inline inline
const SpSubview<eT> const SpSubview<eT>
SpMat<eT>::operator()(const uword row_num, const span& col_span) const SpMat<eT>::operator()(const uword row_num, const span& col_span) const
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
return SpSubview<eT>(*this, row_num, col_span.a, col_span.b - col_span.a const bool col_all = col_span.whole;
+ 1);
const uword local_n_cols = n_cols;
const uword in_col1 = col_all ? 0 : col_span.a;
const uword in_col2 = col_span.b;
const uword submat_n_cols = col_all ? local_n_cols : in_col2 - in_col1 +
1;
arma_debug_check
(
(row_num >= n_rows)
||
( col_all ? false : ((in_col1 > in_col2) || (in_col2 >= local_n_cols))
)
,
"SpMat::operator(): indices out of bounds or incorrectly used"
);
return SpSubview<eT>(*this, row_num, in_col1, 1, submat_n_cols);
} }
template<typename eT> template<typename eT>
arma_inline arma_inline
SpSubview<eT> SpSubview<eT>
SpMat<eT>::col(const uword col_num) SpMat<eT>::col(const uword col_num)
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
return SpSubview<eT>(*this, 0, col_num, n_rows, 1); return SpSubview<eT>(*this, 0, col_num, n_rows, 1);
skipping to change at line 1302 skipping to change at line 1414
return SpSubview<eT>(*this, 0, col_num, n_rows, 1); return SpSubview<eT>(*this, 0, col_num, n_rows, 1);
} }
template<typename eT> template<typename eT>
inline inline
SpSubview<eT> SpSubview<eT>
SpMat<eT>::operator()(const span& row_span, const uword col_num) SpMat<eT>::operator()(const span& row_span, const uword col_num)
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
return SpSubview<eT>(*this, row_span.a, col_num, row_span.b - row_span.a const bool row_all = row_span.whole;
+ 1, 0);
const uword local_n_rows = n_rows;
const uword in_row1 = row_all ? 0 : row_span.a;
const uword in_row2 = row_span.b;
const uword submat_n_rows = row_all ? local_n_rows : in_row2 - in_row1 +
1;
arma_debug_check
(
(col_num >= n_cols)
||
( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= local_n_rows))
)
,
"SpMat::operator(): indices out of bounds or incorrectly used"
);
return SpSubview<eT>(*this, in_row1, col_num, submat_n_rows, 1);
} }
template<typename eT> template<typename eT>
inline inline
const SpSubview<eT> const SpSubview<eT>
SpMat<eT>::operator()(const span& row_span, const uword col_num) const SpMat<eT>::operator()(const span& row_span, const uword col_num) const
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
return SpSubview<eT>(*this, row_span.a, col_num, row_span.b - row_span.a const bool row_all = row_span.whole;
+ 1, 0);
const uword local_n_rows = n_rows;
const uword in_row1 = row_all ? 0 : row_span.a;
const uword in_row2 = row_span.b;
const uword submat_n_rows = row_all ? local_n_rows : in_row2 - in_row1 +
1;
arma_debug_check
(
(col_num >= n_cols)
||
( row_all ? false : ((in_row1 > in_row2) || (in_row2 >= local_n_rows))
)
,
"SpMat::operator(): indices out of bounds or incorrectly used"
);
return SpSubview<eT>(*this, in_row1, col_num, submat_n_rows, 1);
} }
/** /**
* Swap in_row1 with in_row2. * Swap in_row1 with in_row2.
*/ */
template<typename eT> template<typename eT>
inline inline
void void
SpMat<eT>::swap_rows(const uword in_row1, const uword in_row2) SpMat<eT>::swap_rows(const uword in_row1, const uword in_row2)
{ {
skipping to change at line 1608 skipping to change at line 1754
// Copy first set of columns (no manipulation required). // Copy first set of columns (no manipulation required).
if (in_col1 != 0) if (in_col1 != 0)
{ {
arrayops::copy(new_col_ptrs, col_ptrs, in_col1); arrayops::copy(new_col_ptrs, col_ptrs, in_col1);
} }
// Copy second set of columns (manipulation required). // Copy second set of columns (manipulation required).
uword cur_col = in_col1; uword cur_col = in_col1;
for (uword i = in_col2 + 1; i <= n_cols; ++i, ++cur_col) for (uword i = in_col2 + 1; i <= n_cols; ++i, ++cur_col)
{ {
std::cout << "i " << i << " n_cols " << n_cols << std::endl;
new_col_ptrs[cur_col] = col_ptrs[i] - diff; new_col_ptrs[cur_col] = col_ptrs[i] - diff;
} }
memory::release(col_ptrs); memory::release(col_ptrs);
access::rw(col_ptrs) = new_col_ptrs; access::rw(col_ptrs) = new_col_ptrs;
// We update the element and column counts, and we're done. // We update the element and column counts, and we're done.
access::rw(n_cols) = new_n_cols; access::rw(n_cols) = new_n_cols;
access::rw(n_elem) = n_cols * n_rows; access::rw(n_elem) = n_cols * n_rows;
} }
skipping to change at line 2297 skipping to change at line 2442
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
if (dim == 0) if (dim == 0)
{ {
// We have to modify all of the relevant row indices and the relevant c olumn pointers. // We have to modify all of the relevant row indices and the relevant c olumn pointers.
// Iterate over all the points to do this. We won't be deleting any po ints, but we will be modifying // Iterate over all the points to do this. We won't be deleting any po ints, but we will be modifying
// columns and rows. We'll have to store a new set of column vectors. // columns and rows. We'll have to store a new set of column vectors.
uword* new_col_ptrs = memory::acquire<uword>(in_cols + 1); uword* new_col_ptrs = memory::acquire<uword>(in_cols + 1);
uword* new_row_indices = memory::acquire_chunked<uword>(n_nonzero); uword* new_row_indices = memory::acquire_chunked<uword>(n_nonzero + 1);
access::rw(new_row_indices[n_nonzero]) = 0;
arrayops::inplace_set(new_col_ptrs, uword(0), in_cols + 1); arrayops::inplace_set(new_col_ptrs, uword(0), in_cols + 1);
for(const_iterator it = begin(); it.pos() < n_nonzero; it++) for(const_iterator it = begin(); it != end(); it++)
{ {
uword vector_position = (it.col() * n_rows) + it.row(); uword vector_position = (it.col() * n_rows) + it.row();
new_row_indices[it.pos()] = vector_position % in_rows; new_row_indices[it.pos()] = vector_position % in_rows;
++new_col_ptrs[vector_position / in_rows + 1]; ++new_col_ptrs[vector_position / in_rows + 1];
} }
// Now sum the column counts to get the new column pointers. // Now sum the column counts to get the new column pointers.
for(uword i = 1; i <= in_cols; i++) for(uword i = 1; i <= in_cols; i++)
{ {
access::rw(new_col_ptrs[i]) += new_col_ptrs[i - 1]; access::rw(new_col_ptrs[i]) += new_col_ptrs[i - 1];
skipping to change at line 2353 skipping to change at line 2499
const SpMat<eT>& const SpMat<eT>&
SpMat<eT>::zeros() SpMat<eT>::zeros()
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
if (n_nonzero > 0) if (n_nonzero > 0)
{ {
memory::release(values); memory::release(values);
memory::release(row_indices); memory::release(row_indices);
access::rw(values) = NULL; access::rw(values) = memory::acquire_chunked<eT>(1);
access::rw(row_indices) = NULL; access::rw(row_indices) = memory::acquire_chunked<uword>(1);
access::rw(values[0]) = 0;
access::rw(row_indices[0]) = 0;
} }
access::rw(n_nonzero) = 0; access::rw(n_nonzero) = 0;
arrayops::inplace_set(access::rwp(col_ptrs), uword(0), n_cols + 1); arrayops::inplace_set(access::rwp(col_ptrs), uword(0), n_cols + 1);
return *this; return *this;
} }
template<typename eT> template<typename eT>
inline inline
skipping to change at line 2887 skipping to change at line 3036
: false : false
), ),
"SpMat::init(): requested size is too large" "SpMat::init(): requested size is too large"
); );
// Clean out the existing memory. // Clean out the existing memory.
if (values) if (values)
{ {
memory::release(values); memory::release(values);
memory::release(row_indices); memory::release(row_indices);
access::rw(values) = NULL;
access::rw(row_indices) = NULL;
} }
access::rw(values) = memory::acquire_chunked<eT>(1);
access::rw(row_indices) = memory::acquire_chunked<uword>(1);
access::rw(values[0]) = 0;
access::rw(row_indices[0]) = 0;
memory::release(col_ptrs); memory::release(col_ptrs);
// Set the new size accordingly. // Set the new size accordingly.
access::rw(n_rows) = in_rows; access::rw(n_rows) = in_rows;
access::rw(n_cols) = in_cols; access::rw(n_cols) = in_cols;
access::rw(n_elem) = (in_rows * in_cols); access::rw(n_elem) = (in_rows * in_cols);
access::rw(n_nonzero) = 0; access::rw(n_nonzero) = 0;
// Try to allocate the column pointers, filling them with 0. // Try to allocate the column pointers, filling them with 0.
access::rw(col_ptrs) = memory::acquire<uword>(in_cols + 1); access::rw(col_ptrs) = memory::acquire<uword>(in_cols + 1);
skipping to change at line 2988 skipping to change at line 3140
std::string::size_type line_len = line_end - line_start + 1; std::string::size_type line_len = line_end - line_start + 1;
std::stringstream line_stream(text.substr(line_start, line_len)); std::stringstream line_stream(text.substr(line_start, line_len));
uword col = 0; uword col = 0;
eT val; eT val;
while (line_stream >> val) while (line_stream >> val)
{ {
// Only add nonzero elements. // Only add nonzero elements.
if (val != 0) if (val != eT(0))
{ {
get_value(row, col) = val; get_value(row, col) = val;
} }
++col; ++col;
} }
++row; ++row;
line_start = line_end + 1; line_start = line_end + 1;
skipping to change at line 3018 skipping to change at line 3170
void void
SpMat<eT>::init(const SpMat<eT>& x) SpMat<eT>::init(const SpMat<eT>& x)
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
// Ensure we are not initializing to ourselves. // Ensure we are not initializing to ourselves.
if (this != &x) if (this != &x)
{ {
init(x.n_rows, x.n_cols); init(x.n_rows, x.n_cols);
// values and row_indices are null. // values and row_indices may not be null.
access::rw(values) = memory::acquire_chunked<eT> (x.n_nonzero); if (values != NULL)
access::rw(row_indices) = memory::acquire_chunked<uword>(x.n_nonzero); {
memory::release(values);
memory::release(row_indices);
}
access::rw(values) = memory::acquire_chunked<eT> (x.n_nonzero +
1);
access::rw(row_indices) = memory::acquire_chunked<uword>(x.n_nonzero +
1);
// Now copy over the elements. // Now copy over the elements.
arrayops::copy(access::rwp(values), x.values, x.n_nonzero); arrayops::copy(access::rwp(values), x.values, x.n_nonzero + 1
arrayops::copy(access::rwp(row_indices), x.row_indices, x.n_nonzero); );
arrayops::copy(access::rwp(row_indices), x.row_indices, x.n_nonzero + 1
);
arrayops::copy(access::rwp(col_ptrs), x.col_ptrs, x.n_cols + 1); arrayops::copy(access::rwp(col_ptrs), x.col_ptrs, x.n_cols + 1);
access::rw(n_nonzero) = x.n_nonzero; access::rw(n_nonzero) = x.n_nonzero;
} }
} }
template<typename eT> template<typename eT>
inline inline
void void
SpMat<eT>::mem_resize(const uword new_n_nonzero) SpMat<eT>::mem_resize(const uword new_n_nonzero)
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
if(n_nonzero != new_n_nonzero) if(n_nonzero != new_n_nonzero)
{ {
if(new_n_nonzero == 0) if(new_n_nonzero == 0)
{ {
memory::release(values); memory::release(values);
memory::release(row_indices); memory::release(row_indices);
access::rw(values) = NULL; access::rw(values) = memory::acquire_chunked<eT> (1);
access::rw(row_indices) = NULL; access::rw(row_indices) = memory::acquire_chunked<uword>(1);
access::rw(values[0]) = 0;
access::rw(row_indices[0]) = 0;
} }
else else
{ {
// Figure out the actual amount of memory currently allocated // Figure out the actual amount of memory currently allocated
// NOTE: this relies on memory::acquire_chunked() being used for the 'values' and 'row_indices' arrays // NOTE: this relies on memory::acquire_chunked() being used for the 'values' and 'row_indices' arrays
const uword n_alloc = memory::enlarge_to_mult_of_chunksize(n_nonzero) ; const uword n_alloc = memory::enlarge_to_mult_of_chunksize(n_nonzero) ;
if(n_alloc < new_n_nonzero) if(n_alloc < new_n_nonzero)
{ {
eT* new_values = memory::acquire_chunked<eT> (new_n_nonze eT* new_values = memory::acquire_chunked<eT> (new_n_nonze
ro); ro + 1);
uword* new_row_indices = memory::acquire_chunked<uword>(new_n_nonze uword* new_row_indices = memory::acquire_chunked<uword>(new_n_nonze
ro); ro + 1);
access::rw(new_values[new_n_nonzero]) = 0;
access::rw(new_row_indices[new_n_nonzero]) = 0;
if(n_nonzero > 0) if(n_nonzero > 0)
{ {
// Copy old elements. // Copy old elements.
uword copy_size = std::min(n_nonzero, new_n_nonzero); uword copy_size = std::min(n_nonzero, new_n_nonzero);
arrayops::copy(new_values, values, copy_size); arrayops::copy(new_values, values, copy_size);
arrayops::copy(new_row_indices, row_indices, copy_size); arrayops::copy(new_row_indices, row_indices, copy_size);
memory::release(values); memory::release(values);
skipping to change at line 3143 skipping to change at line 3307
SpMat<eT>::begin() const SpMat<eT>::begin() const
{ {
return const_iterator(*this); return const_iterator(*this);
} }
template<typename eT> template<typename eT>
inline inline
typename SpMat<eT>::iterator typename SpMat<eT>::iterator
SpMat<eT>::end() SpMat<eT>::end()
{ {
return iterator(*this, n_nonzero); return iterator(*this, 0, n_cols, n_nonzero);
} }
template<typename eT> template<typename eT>
inline inline
typename SpMat<eT>::const_iterator typename SpMat<eT>::const_iterator
SpMat<eT>::end() const SpMat<eT>::end() const
{ {
return const_iterator(*this, n_nonzero); return const_iterator(*this, 0, n_cols, n_nonzero);
} }
template<typename eT> template<typename eT>
inline inline
typename SpMat<eT>::iterator typename SpMat<eT>::iterator
SpMat<eT>::begin_col(const uword col_num) SpMat<eT>::begin_col(const uword col_num)
{ {
return iterator(*this, 0, col_num); return iterator(*this, 0, col_num);
} }
skipping to change at line 3244 skipping to change at line 3408
template<typename eT> template<typename eT>
inline inline
void void
SpMat<eT>::clear() SpMat<eT>::clear()
{ {
if (values) if (values)
{ {
memory::release(values); memory::release(values);
memory::release(row_indices); memory::release(row_indices);
values = NULL; access::rw(values) = memory::acquire_chunked<eT> (1);
row_indices = NULL; access::rw(row_indices) = memory::acquire_chunked<uword>(1);
access::rw(values[0]) = 0;
access::rw(row_indices[0]) = 0;
} }
memory::release(col_ptrs); memory::release(col_ptrs);
access::rw(col_ptrs) = memory::acquire<uword>(n_cols + 1); access::rw(col_ptrs) = memory::acquire<uword>(n_cols + 1);
arrayops::inplace_set(col_ptrs, eT(0), n_cols + 1); arrayops::inplace_set(col_ptrs, eT(0), n_cols + 1);
access::rw(n_nonzero) = 0; access::rw(n_nonzero) = 0;
} }
skipping to change at line 3462 skipping to change at line 3629
// //
// We have to update the rest of the column pointers. // We have to update the rest of the column pointers.
for (uword i = in_col + 1; i < n_cols + 1; i++) for (uword i = in_col + 1; i < n_cols + 1; i++)
{ {
access::rw(col_ptrs[i])++; // We are only inserting one new element. access::rw(col_ptrs[i])++; // We are only inserting one new element.
} }
// Figure out the actual amount of memory currently allocated // Figure out the actual amount of memory currently allocated
// NOTE: this relies on memory::acquire_chunked() being used for the 'val ues' and 'row_indices' arrays // NOTE: this relies on memory::acquire_chunked() being used for the 'val ues' and 'row_indices' arrays
const uword n_alloc = memory::enlarge_to_mult_of_chunksize(n_nonzero); const uword n_alloc = memory::enlarge_to_mult_of_chunksize(n_nonzero + 1) ;
// If possible, avoid time-consuming memory allocation // If possible, avoid time-consuming memory allocation
if(n_alloc > n_nonzero) if(n_alloc > (n_nonzero + 1))
{ {
if (pos != n_nonzero) arrayops::copy_backwards(access::rwp(values) + pos + 1, values
{ + pos, (n_nonzero - pos) + 1);
arrayops::copy_backwards(access::rwp(values) + pos + 1, values arrayops::copy_backwards(access::rwp(row_indices) + pos + 1, row_indice
+ pos, (n_nonzero - pos)); s + pos, (n_nonzero - pos) + 1);
arrayops::copy_backwards(access::rwp(row_indices) + pos + 1, row_indi
ces + pos, (n_nonzero - pos));
}
// Insert the new element. // Insert the new element.
access::rw(values[pos]) = val; access::rw(values[pos]) = val;
access::rw(row_indices[pos]) = in_row; access::rw(row_indices[pos]) = in_row;
access::rw(n_nonzero)++; access::rw(n_nonzero)++;
} }
else else
{ {
const uword old_n_nonzero = n_nonzero; const uword old_n_nonzero = n_nonzero;
access::rw(n_nonzero)++; // Add to count of nonzero elements. access::rw(n_nonzero)++; // Add to count of nonzero elements.
// Allocate larger memory. // Allocate larger memory.
eT* new_values = memory::acquire_chunked<eT> (n_nonzero); eT* new_values = memory::acquire_chunked<eT> (n_nonzero + 1);
uword* new_row_indices = memory::acquire_chunked<uword>(n_nonzero); uword* new_row_indices = memory::acquire_chunked<uword>(n_nonzero + 1);
// Copy things over, before the new element. // Copy things over, before the new element.
if (pos > 0) if (pos > 0)
{ {
arrayops::copy(new_values, values, pos); arrayops::copy(new_values, values, pos);
arrayops::copy(new_row_indices, row_indices, pos); arrayops::copy(new_row_indices, row_indices, pos);
} }
// Insert the new element. // Insert the new element.
new_values[pos] = val; new_values[pos] = val;
new_row_indices[pos] = in_row; new_row_indices[pos] = in_row;
// Copy the rest of things over. // Copy the rest of things over (including the extra element at the end
if (pos != old_n_nonzero) ).
{ arrayops::copy(new_values + pos + 1, values + pos, (old_n_non
arrayops::copy(new_values + pos + 1, values + pos, (old_n_n zero - pos) + 1);
onzero - pos)); arrayops::copy(new_row_indices + pos + 1, row_indices + pos, (old_n_non
arrayops::copy(new_row_indices + pos + 1, row_indices + pos, (old_n_n zero - pos) + 1);
onzero - pos));
}
// Assign new pointers. // Assign new pointers.
if (old_n_nonzero != 0) memory::release(values);
{ memory::release(row_indices);
memory::release(values);
memory::release(row_indices);
}
access::rw(values) = new_values; access::rw(values) = new_values;
access::rw(row_indices) = new_row_indices; access::rw(row_indices) = new_row_indices;
} }
return access::rw(values[pos]); return access::rw(values[pos]);
} }
/** /**
* Delete an element at the given position. * Delete an element at the given position.
skipping to change at line 3553 skipping to change at line 3711
// Let's see if we are one of them. // Let's see if we are one of them.
for (uword pos = colptr; pos < next_colptr; pos++) for (uword pos = colptr; pos < next_colptr; pos++)
{ {
if (in_row == row_indices[pos]) if (in_row == row_indices[pos])
{ {
const uword old_n_nonzero = n_nonzero; const uword old_n_nonzero = n_nonzero;
--access::rw(n_nonzero); // Remove one from the count of nonzero el ements. --access::rw(n_nonzero); // Remove one from the count of nonzero el ements.
// Found it. Now remove it. // Found it. Now remove it.
if (n_nonzero == 0)
{
memory::release(values);
memory::release(row_indices);
access::rw(values) = NULL; // Figure out the actual amount of memory currently allocated and t
access::rw(row_indices) = NULL; he actual amount that will be required
// NOTE: this relies on memory::acquire_chunked() being used for th
e 'values' and 'row_indices' arrays
const uword n_alloc = memory::enlarge_to_mult_of_chunksize(old_
n_nonzero + 1);
const uword n_alloc_mod = memory::enlarge_to_mult_of_chunksize(n_no
nzero + 1);
// If possible, avoid time-consuming memory allocation
if(n_alloc_mod == n_alloc)
{
if (pos < n_nonzero) // remember, we decremented n_nonzero
{
arrayops::copy_forwards(access::rwp(values) + pos, values
+ pos + 1, (n_nonzero - pos) + 1);
arrayops::copy_forwards(access::rwp(row_indices) + pos, row_ind
ices + pos + 1, (n_nonzero - pos) + 1);
}
} }
else else
{ {
// Figure out the actual amount of memory currently allocated and // Make new arrays.
the actual amount that will be required eT* new_values = memory::acquire_chunked<eT> (n_nonzero
// NOTE: this relies on memory::acquire_chunked() being used for + 1);
the 'values' and 'row_indices' arrays uword* new_row_indices = memory::acquire_chunked<uword>(n_nonzero
+ 1);
const uword n_alloc = memory::enlarge_to_mult_of_chunksize(ol
d_n_nonzero);
const uword n_alloc_mod = memory::enlarge_to_mult_of_chunksize(
n_nonzero);
// If possible, avoid time-consuming memory allocation if (pos > 0)
if(n_alloc_mod == n_alloc)
{ {
if (pos < n_nonzero) // remember, we decremented n_nonzero arrayops::copy(new_values, values, pos);
{ arrayops::copy(new_row_indices, row_indices, pos);
arrayops::copy_forwards(access::rwp(values) + pos, value
s + pos + 1, (n_nonzero - pos));
arrayops::copy_forwards(access::rwp(row_indices) + pos, row_i
ndices + pos + 1, (n_nonzero - pos));
}
} }
else
{
// Make new arrays.
eT* new_values = memory::acquire_chunked<eT> (n_nonze
ro);
uword* new_row_indices = memory::acquire_chunked<uword>(n_nonze
ro);
if (pos > 0)
{
arrayops::copy(new_values, values, pos);
arrayops::copy(new_row_indices, row_indices, pos);
}
if (pos < n_nonzero) // remember, we decremented n_nonzero
{
arrayops::copy(new_values + pos, values + pos + 1,
(n_nonzero - pos));
arrayops::copy(new_row_indices + pos, row_indices + pos + 1,
(n_nonzero - pos));
}
memory::release(values); arrayops::copy(new_values + pos, values + pos + 1, (n_n
memory::release(row_indices); onzero - pos) + 1);
arrayops::copy(new_row_indices + pos, row_indices + pos + 1, (n_n
onzero - pos) + 1);
access::rw(values) = new_values; memory::release(values);
access::rw(row_indices) = new_row_indices; memory::release(row_indices);
}
access::rw(values) = new_values;
access::rw(row_indices) = new_row_indices;
} }
// And lastly, update all the column pointers (decrement by one). // And lastly, update all the column pointers (decrement by one).
for (uword i = in_col + 1; i < n_cols + 1; i++) for (uword i = in_col + 1; i < n_cols + 1; i++)
{ {
--access::rw(col_ptrs[i]); // We only removed one element. --access::rw(col_ptrs[i]); // We only removed one element.
} }
return; // There is nothing left to do. return; // There is nothing left to do.
} }
 End of changes. 83 change blocks. 
177 lines changed or deleted 331 lines changed or added


 SpSubview_bones.hpp   SpSubview_bones.hpp 
skipping to change at line 174 skipping to change at line 174
arma_aligned uword internal_pos; arma_aligned uword internal_pos;
arma_aligned uword skip_pos; // not used in row_iterator or const_row_iterator arma_aligned uword skip_pos; // not used in row_iterator or const_row_iterator
}; };
class const_iterator : public iterator_base class const_iterator : public iterator_base
{ {
public: public:
inline const_iterator(const SpSubview& in_M, uword initial_pos = 0); inline const_iterator(const SpSubview& in_M, uword initial_pos = 0);
inline const_iterator(const SpSubview& in_M, uword in_row, uword in_col ); inline const_iterator(const SpSubview& in_M, uword in_row, uword in_col );
inline const_iterator(const SpSubview& in_M, uword in_row, uword in_col , uword in_pos, uword skip_pos);
inline const_iterator(const const_iterator& other); inline const_iterator(const const_iterator& other);
inline const_iterator& operator++(); inline const_iterator& operator++();
inline void operator++(int); inline void operator++(int);
inline const_iterator& operator--(); inline const_iterator& operator--();
inline void operator--(int); inline void operator--(int);
}; };
class iterator : public const_iterator class iterator : public const_iterator
{ {
public: public:
inline iterator(SpSubview& in_M, const uword initial_pos = 0) : const_i terator(in_M, initial_pos) { } inline iterator(SpSubview& in_M, const uword initial_pos = 0) : const_i terator(in_M, initial_pos) { }
inline iterator(SpSubview& in_M, const uword in_row, const uword in_col ) : const_iterator(in_M, in_row, in_col) { } inline iterator(SpSubview& in_M, const uword in_row, const uword in_col ) : const_iterator(in_M, in_row, in_col) { }
inline iterator(SpSubview& in_M, const uword in_row, const uword in_col , const uword in_pos, const uword skip_pos) : const_iterator(in_M, in_row, in_col, in_pos, skip_pos) { }
inline iterator(const iterator& other) : const_iterator(other) { } inline iterator(const iterator& other) : const_iterator(other) { }
inline SpValProxy<SpSubview<eT> > operator*(); inline SpValProxy<SpSubview<eT> > operator*();
// overloads needed for return type correctness // overloads needed for return type correctness
inline iterator& operator++(); inline iterator& operator++();
inline void operator++(int); inline void operator++(int);
inline iterator& operator--(); inline iterator& operator--();
inline void operator--(int); inline void operator--(int);
 End of changes. 2 change blocks. 
0 lines changed or deleted 2 lines changed or added


 SpSubview_iterators_meat.hpp   SpSubview_iterators_meat.hpp 
skipping to change at line 91 skipping to change at line 91
/////////////////////////////////////////////////////////////////////////// //// /////////////////////////////////////////////////////////////////////////// ////
// SpSubview::const_iterator implementation // // SpSubview::const_iterator implementation //
/////////////////////////////////////////////////////////////////////////// //// /////////////////////////////////////////////////////////////////////////// ////
template<typename eT> template<typename eT>
inline inline
SpSubview<eT>::const_iterator::const_iterator(const SpSubview<eT>& in_M, co nst uword initial_pos) SpSubview<eT>::const_iterator::const_iterator(const SpSubview<eT>& in_M, co nst uword initial_pos)
: iterator_base(in_M, 0, initial_pos, 0) : iterator_base(in_M, 0, initial_pos, 0)
{ {
// Corner case for empty subviews.
if(in_M.n_nonzero == 0)
{
iterator_base::internal_col = in_M.n_cols;
iterator_base::skip_pos = in_M.m.n_nonzero;
return;
}
// Figure out the row and column of the position. // Figure out the row and column of the position.
// skip_pos holds the number of values which aren't part of this subview. // skip_pos holds the number of values which aren't part of this subview.
const uword aux_col = iterator_base::M.aux_col1; const uword aux_col = iterator_base::M.aux_col1;
const uword aux_row = iterator_base::M.aux_row1; const uword aux_row = iterator_base::M.aux_row1;
const uword n_rows = iterator_base::M.n_rows; const uword n_rows = iterator_base::M.n_rows;
uword cur_pos = 0; // off by one because we might be searching for pos 0 uword cur_pos = 0; // off by one because we might be searching for pos 0
uword skip_pos = iterator_base::M.m.col_ptrs[aux_col]; uword skip_pos = iterator_base::M.m.col_ptrs[aux_col];
uword cur_col = 0; uword cur_col = 0;
skipping to change at line 226 skipping to change at line 234
} }
} }
iterator_base::internal_pos = cur_pos; iterator_base::internal_pos = cur_pos;
iterator_base::skip_pos = skip_pos; iterator_base::skip_pos = skip_pos;
iterator_base::internal_col = cur_col; iterator_base::internal_col = cur_col;
} }
template<typename eT> template<typename eT>
inline inline
SpSubview<eT>::const_iterator::const_iterator(const SpSubview<eT>& in_M, uw
ord in_row, uword in_col, uword in_pos, uword skip_pos)
: iterator_base(in_M, in_col, in_pos, skip_pos)
{
// Nothing to do.
}
template<typename eT>
inline
SpSubview<eT>::const_iterator::const_iterator(const const_iterator& other) SpSubview<eT>::const_iterator::const_iterator(const const_iterator& other)
: iterator_base(other.M, other.internal_col, other.internal_pos, other.sk ip_pos) : iterator_base(other.M, other.internal_col, other.internal_pos, other.sk ip_pos)
{ {
// Nothing to do. // Nothing to do.
} }
template<typename eT> template<typename eT>
inline inline
typename SpSubview<eT>::const_iterator& typename SpSubview<eT>::const_iterator&
SpSubview<eT>::const_iterator::operator++() SpSubview<eT>::const_iterator::operator++()
skipping to change at line 262 skipping to change at line 278
// Did we move any columns? // Did we move any columns?
while((cur_col < n_cols) && ((skip_pos + cur_pos) >= iterator_base::M.m .col_ptrs[cur_col + aux_col + 1])) while((cur_col < n_cols) && ((skip_pos + cur_pos) >= iterator_base::M.m .col_ptrs[cur_col + aux_col + 1]))
{ {
++cur_col; ++cur_col;
} }
// Are we at the last position? // Are we at the last position?
if(cur_col >= n_cols) if(cur_col >= n_cols)
{ {
cur_col = n_cols; cur_col = n_cols;
row_index = aux_row; // Make sure we will be pointing at the last element in the parent ma
trix.
skip_pos = iterator_base::M.m.n_nonzero - iterator_base::M.n_nonzero;
break; break;
} }
if(row_index < aux_row) if(row_index < aux_row)
{ {
++skip_pos; ++skip_pos;
} }
else if(row_index < (aux_row + n_rows)) else if(row_index < (aux_row + n_rows))
{ {
break; // found break; // found
} }
else else
{ {
skip_pos += (next_colptr - (cur_pos + skip_pos)); skip_pos += (next_colptr - (cur_pos + skip_pos));
} }
} }
iterator_base::internal_pos = cur_pos; iterator_base::internal_pos = cur_pos;
iterator_base::skip_pos = skip_pos;
iterator_base::internal_col = cur_col; iterator_base::internal_col = cur_col;
iterator_base::skip_pos = skip_pos;
return *this; return *this;
} }
template<typename eT> template<typename eT>
inline inline
void void
SpSubview<eT>::const_iterator::operator++(int) SpSubview<eT>::const_iterator::operator++(int)
{ {
++(*this); ++(*this);
skipping to change at line 307 skipping to change at line 324
typename SpSubview<eT>::const_iterator& typename SpSubview<eT>::const_iterator&
SpSubview<eT>::const_iterator::operator--() SpSubview<eT>::const_iterator::operator--()
{ {
const uword aux_col = iterator_base::M.aux_col1; const uword aux_col = iterator_base::M.aux_col1;
const uword aux_row = iterator_base::M.aux_row1; const uword aux_row = iterator_base::M.aux_row1;
const uword n_rows = iterator_base::M.n_rows; const uword n_rows = iterator_base::M.n_rows;
uword cur_col = iterator_base::internal_col; uword cur_col = iterator_base::internal_col;
uword cur_pos = iterator_base::internal_pos - 1; uword cur_pos = iterator_base::internal_pos - 1;
uword skip_pos = iterator_base::skip_pos; uword skip_pos = iterator_base::skip_pos;
// Special condition for end of iterator.
if((skip_pos + cur_pos + 1) == iterator_base::M.m.n_nonzero)
{
// We are at the last element. So we need to set skip_pos back to what
it
// would be if we didn't manually modify it back in operator++().
skip_pos = iterator_base::M.m.col_ptrs[cur_col + aux_col] - iterator_ba
se::internal_pos;
}
uword row_index; uword row_index;
while(true) while(true)
{ {
const uword colptr = iterator_base::M.m.col_ptrs[cur_col + aux_col]; const uword colptr = iterator_base::M.m.col_ptrs[cur_col + aux_col];
row_index = iterator_base::M.m.row_indices[cur_pos + skip_pos]; row_index = iterator_base::M.m.row_indices[cur_pos + skip_pos];
// Did we move back any columns? // Did we move back any columns?
while((skip_pos + cur_pos) < iterator_base::M.m.col_ptrs[cur_col + aux_ col]) while((skip_pos + cur_pos) < iterator_base::M.m.col_ptrs[cur_col + aux_ col])
{ {
skipping to change at line 410 skipping to change at line 436
// SpSubview<eT>::const_row_iterator implementation // // SpSubview<eT>::const_row_iterator implementation //
/////////////////////////////////////////////////////////////////////////// //// /////////////////////////////////////////////////////////////////////////// ////
template<typename eT> template<typename eT>
inline inline
SpSubview<eT>::const_row_iterator::const_row_iterator(const SpSubview<eT>& in_M, uword initial_pos) SpSubview<eT>::const_row_iterator::const_row_iterator(const SpSubview<eT>& in_M, uword initial_pos)
: iterator_base(in_M, 0, initial_pos, 0) : iterator_base(in_M, 0, initial_pos, 0)
, internal_row(0) , internal_row(0)
, actual_pos(0) , actual_pos(0)
{ {
// Corner case for empty subviews.
if(in_M.n_nonzero == 0)
{
iterator_base::internal_col = in_M.n_cols;
iterator_base::skip_pos = in_M.m.n_nonzero;
return;
}
const uword aux_col = iterator_base::M.aux_col1; const uword aux_col = iterator_base::M.aux_col1;
const uword aux_row = iterator_base::M.aux_row1; const uword aux_row = iterator_base::M.aux_row1;
const uword n_cols = iterator_base::M.n_cols; const uword n_cols = iterator_base::M.n_cols;
// We don't know where the elements are in each row. What we will do is // We don't know where the elements are in each row. What we will do is
// loop across all valid columns looking for elements in row 0 (and add t o // loop across all valid columns looking for elements in row 0 (and add t o
// our sum), then in row 1, and so forth, until we get to the desired // our sum), then in row 1, and so forth, until we get to the desired
// position. // position.
uword cur_pos = -1; uword cur_pos = -1;
uword cur_row = 0; uword cur_row = 0;
 End of changes. 7 change blocks. 
2 lines changed or deleted 40 lines changed or added


 SpSubview_meat.hpp   SpSubview_meat.hpp 
skipping to change at line 89 skipping to change at line 89
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
} }
template<typename eT> template<typename eT>
inline inline
const SpSubview<eT>& const SpSubview<eT>&
SpSubview<eT>::operator+=(const eT val) SpSubview<eT>::operator+=(const eT val)
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
if(val == 0) if(val == eT(0))
{ {
return *this; return *this;
} }
const uword start_row = aux_row1; const uword start_row = aux_row1;
const uword end_row = aux_row1 + n_rows; const uword end_row = aux_row1 + n_rows;
const uword start_col = aux_col1; const uword start_col = aux_col1;
const uword end_col = aux_col1 + n_cols; const uword end_col = aux_col1 + n_cols;
const uword old_n_nonzero = m.n_nonzero; const uword old_n_nonzero = m.n_nonzero;
skipping to change at line 124 skipping to change at line 124
return *this; return *this;
} }
template<typename eT> template<typename eT>
inline inline
const SpSubview<eT>& const SpSubview<eT>&
SpSubview<eT>::operator-=(const eT val) SpSubview<eT>::operator-=(const eT val)
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
if(val == 0) if(val == eT(0))
{ {
return *this; return *this;
} }
const uword start_row = aux_row1; const uword start_row = aux_row1;
const uword end_row = aux_row1 + n_rows; const uword end_row = aux_row1 + n_rows;
const uword start_col = aux_col1; const uword start_col = aux_col1;
const uword end_col = aux_col1 + n_cols; const uword end_col = aux_col1 + n_cols;
const uword old_n_nonzero = m.n_nonzero; const uword old_n_nonzero = m.n_nonzero;
skipping to change at line 161 skipping to change at line 161
template<typename eT> template<typename eT>
inline inline
const SpSubview<eT>& const SpSubview<eT>&
SpSubview<eT>::operator*=(const eT val) SpSubview<eT>::operator*=(const eT val)
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
if(val == eT(0)) if(val == eT(0))
{ {
// Turn it all into zeros. // Turn it all into zeros.
for(iterator it(*this); it.pos() < n_nonzero; ++it) for(iterator it(*this); it != end(); ++it)
{ {
(*it) = eT(0); // zero out the value. (*it) = eT(0); // zero out the value.
it.internal_pos--; it.internal_pos--;
} }
return *this; return *this;
} }
const uword start_row = aux_row1; const uword start_row = aux_row1;
const uword end_row = aux_row1 + n_rows; const uword end_row = aux_row1 + n_rows;
skipping to change at line 201 skipping to change at line 201
const SpSubview<eT>& const SpSubview<eT>&
SpSubview<eT>::operator/=(const eT val) SpSubview<eT>::operator/=(const eT val)
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
const uword start_col = aux_col1; const uword start_col = aux_col1;
const uword end_col = aux_col1 + n_cols; const uword end_col = aux_col1 + n_cols;
const uword start_row = aux_row1; const uword start_row = aux_row1;
const uword end_row = aux_row1 + n_rows; const uword end_row = aux_row1 + n_rows;
const uword old_n_nonzero = m.n_nonzero;
for(uword c = start_col; c < end_col; ++c) for(uword c = start_col; c < end_col; ++c)
{ {
for(uword r = start_row; r < end_row; ++r) for(uword r = start_row; r < end_row; ++r)
{ {
access::rw(m).at(r, c) /= val; access::rw(m).at(r, c) /= val;
} }
} }
const uword new_n_nonzero = m.n_nonzero;
access::rw(n_nonzero) += (new_n_nonzero - old_n_nonzero);
return *this; return *this;
} }
template<typename eT> template<typename eT>
template<typename T1> template<typename T1>
inline inline
const SpSubview<eT>& const SpSubview<eT>&
SpSubview<eT>::operator=(const Base<eT, T1>& x) SpSubview<eT>::operator=(const Base<eT, T1>& x)
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
skipping to change at line 334 skipping to change at line 340
SpSubview<eT>::operator%=(const Base<eT, T1>& x) SpSubview<eT>::operator%=(const Base<eT, T1>& x)
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
const Proxy<T1> P(x.get_ref()); const Proxy<T1> P(x.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");
const uword old_n_nonzero = m.n_nonzero; const uword old_n_nonzero = m.n_nonzero;
for(iterator it(*this); it.pos() < n_nonzero; ++it) for(iterator it(*this); it != end(); ++it)
{ {
(*it) *= P.at(it.row(), it.col()); (*it) *= P.at(it.row(), it.col());
if(P.at(it.row(), it.col()) == 0) if(P.at(it.row(), it.col()) == eT(0))
{ {
it.internal_pos--; it.internal_pos--;
} }
} }
const uword new_n_nonzero = m.n_nonzero; const uword new_n_nonzero = m.n_nonzero;
access::rw(n_nonzero) += (new_n_nonzero - old_n_nonzero); access::rw(n_nonzero) += (new_n_nonzero - old_n_nonzero);
return *this; return *this;
skipping to change at line 395 skipping to change at line 401
arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "insertio n into sparse submatrix"); arma_debug_assert_same_size(n_rows, n_cols, x.n_rows, x.n_cols, "insertio n into sparse submatrix");
const bool alias = ( &m == &(x.m) ); const bool alias = ( &m == &(x.m) );
if(alias == false) if(alias == false)
{ {
const_iterator cit = x.begin(); const_iterator cit = x.begin();
iterator it = begin(); iterator it = begin();
while((cit.pos() < x.n_nonzero) || (it.pos() < n_nonzero)) while((cit != x.end()) || (it != end()))
{ {
if((cit.row() == it.row()) && (cit.col() == it.col())) if((cit.row() == it.row()) && (cit.col() == it.col()))
{ {
(*it) = (*cit); (*it) = (*cit);
++it; ++it;
++cit; ++cit;
} }
else else
{ {
if((cit.col() > it.col()) || ((cit.col() == it.col()) && (cit.row() > it.row()))) if((cit.col() > it.col()) || ((cit.col() == it.col()) && (cit.row() > it.row())))
skipping to change at line 451 skipping to change at line 457
const SpProxy<T1> p(x.get_ref()); const SpProxy<T1> p(x.get_ref());
arma_debug_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols( ), "insertion into sparse submatrix"); arma_debug_assert_same_size(n_rows, n_cols, p.get_n_rows(), p.get_n_cols( ), "insertion into sparse submatrix");
if(p.is_alias(m) == false) if(p.is_alias(m) == false)
{ {
typename SpProxy<T1>::const_iterator_type cit = p.begin(); typename SpProxy<T1>::const_iterator_type cit = p.begin();
iterator it(*this); iterator it(*this);
while((cit.pos() < p.get_n_nonzero()) || (it.pos() < n_nonzero)) while((cit != p.end()) || (it != end()))
{ {
if(cit == it) // at the same location if(cit == it) // at the same location
{ {
(*it) = (*cit); (*it) = (*cit);
++it; ++it;
++cit; ++cit;
} }
else else
{ {
if((cit.col() > it.col()) || ((cit.col() == it.col()) && (cit.row() > it.row()))) if((cit.col() > it.col()) || ((cit.col() == it.col()) && (cit.row() > it.row())))
skipping to change at line 477 skipping to change at line 483
} }
else else
{ {
// it is "ahead" // it is "ahead"
at(cit.row(), cit.col()) = (*cit); at(cit.row(), cit.col()) = (*cit);
it.internal_pos++; // update iterator so it still works it.internal_pos++; // update iterator so it still works
++cit; ++cit;
} }
} }
} }
access::rw(n_nonzero) = p.get_n_nonzero();
} }
else else
{ {
const SpMat<eT> tmp(p.Q); const SpMat<eT> tmp(p.Q);
(*this).operator=(tmp); (*this).operator=(tmp);
} }
return *this; return *this;
} }
skipping to change at line 505 skipping to change at line 509
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
const SpProxy<T1> p(x.get_ref()); const SpProxy<T1> p(x.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");
if(p.is_alias(m) == false) if(p.is_alias(m) == false)
{ {
typename SpProxy<T1>::const_iterator_type cit = p.begin(); typename SpProxy<T1>::const_iterator_type cit = p.begin();
const uword old_n_nonzero = m.n_nonzero;
while(cit.pos() < p.get_n_nonzero()) while(cit != p.end())
{ {
at(cit.row(), cit.col()) += (*cit); at(cit.row(), cit.col()) += (*cit);
++cit; ++cit;
} }
const uword new_n_nonzero = m.n_nonzero;
access::rw(n_nonzero) += (new_n_nonzero - old_n_nonzero);
} }
else else
{ {
const SpMat<eT> tmp(p.Q); const SpMat<eT> tmp(p.Q);
(*this).operator+=(tmp); (*this).operator+=(tmp);
} }
return *this; return *this;
} }
skipping to change at line 544 skipping to change at line 542
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
const SpProxy<T1> p(x.get_ref()); const SpProxy<T1> p(x.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");
if(p.is_alias(m) == false) if(p.is_alias(m) == false)
{ {
typename SpProxy<T1>::const_iterator_type cit = p.begin(); typename SpProxy<T1>::const_iterator_type cit = p.begin();
const uword old_n_nonzero = m.n_nonzero; while(cit != p.end())
while(cit.pos() < p.get_n_nonzero())
{ {
at(cit.row(), cit.col()) -= (*cit); at(cit.row(), cit.col()) -= (*cit);
++cit; ++cit;
} }
const uword new_n_nonzero = m.n_nonzero;
access::rw(n_nonzero) += (new_n_nonzero - old_n_nonzero);
} }
else else
{ {
const SpMat<eT> tmp(p.Q); const SpMat<eT> tmp(p.Q);
(*this).operator-=(tmp); (*this).operator-=(tmp);
} }
return *this; return *this;
} }
skipping to change at line 601 skipping to change at line 592
const SpProxy<T1> p(x.get_ref()); const SpProxy<T1> p(x.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");
if(p.is_alias(m) == false) if(p.is_alias(m) == false)
{ {
typename SpProxy<T1>::const_iterator_type cit = p.begin(); typename SpProxy<T1>::const_iterator_type cit = p.begin();
iterator it(*this); iterator it(*this);
const uword old_n_nonzero = m.n_nonzero; while((it != end()) || (cit != p.end()))
while((it.pos() < n_nonzero) || (cit.pos() < p.get_n_nonzero()))
{ {
if((cit.row() == it.row()) && (cit.col() == it.col())) if((cit.row() == it.row()) && (cit.col() == it.col()))
{ {
(*it) *= (*cit); (*it) *= (*cit);
++it; ++it;
++cit; ++cit;
} }
else else
{ {
if((cit.col() > it.col()) || ((cit.col() == it.col()) && (cit.row() > it.row()))) if((cit.col() > it.col()) || ((cit.col() == it.col()) && (cit.row() > it.row())))
skipping to change at line 627 skipping to change at line 616
it.internal_pos--; // update iterator so it still works it.internal_pos--; // update iterator so it still works
++it; ++it;
} }
else else
{ {
// it is "ahead" // it is "ahead"
++cit; ++cit;
} }
} }
} }
const uword new_n_nonzero = m.n_nonzero;
access::rw(n_nonzero) += (new_n_nonzero - old_n_nonzero);
} }
else else
{ {
const SpMat<eT> tmp(p.Q); const SpMat<eT> tmp(p.Q);
(*this).operator%=(tmp); (*this).operator%=(tmp);
} }
return *this; return *this;
} }
skipping to change at line 657 skipping to change at line 642
SpSubview<eT>::operator/=(const SpBase<eT, T1>& x) SpSubview<eT>::operator/=(const SpBase<eT, T1>& x)
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
SpProxy<T1> p(x.get_ref()); SpProxy<T1> p(x.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(p.is_alias(m) == false) if(p.is_alias(m) == false)
{ {
const uword old_n_nonzero = p.get_n_nonzero();
for(uword col = 0; col < n_cols; ++col) for(uword col = 0; col < n_cols; ++col)
for(uword row = 0; row < n_rows; ++row) for(uword row = 0; row < n_rows; ++row)
{ {
at(row,col) /= p.at(row,col); at(row,col) /= p.at(row,col);
} }
const uword new_n_nonzero = p.get_n_nonzero();
access::rw(n_nonzero) += (new_n_nonzero - old_n_nonzero);
} }
else else
{ {
const SpMat<eT> tmp(p.Q); const SpMat<eT> tmp(p.Q);
(*this).operator/=(tmp); (*this).operator/=(tmp);
} }
return *this; return *this;
} }
skipping to change at line 701 skipping to change at line 680
const uword end_row = aux_row1 + n_rows; const uword end_row = aux_row1 + n_rows;
const uword start_col = aux_col1; const uword start_col = aux_col1;
const uword end_col = aux_col1 + n_cols; const uword end_col = aux_col1 + n_cols;
// iterate over our part of the sparse matrix // iterate over our part of the sparse matrix
for(uword col = start_col; col < end_col; ++col) for(uword col = start_col; col < end_col; ++col)
for(uword row = start_row; row < end_row; ++row) for(uword row = start_row; row < end_row; ++row)
{ {
access::rw(m).at(row, col) = val; access::rw(m).at(row, col) = val;
} }
access::rw(n_nonzero) = n_elem;
} }
else else
{ {
(*this).zeros(); (*this).zeros();
} }
} }
template<typename eT> template<typename eT>
inline inline
void void
SpSubview<eT>::zeros() SpSubview<eT>::zeros()
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
// we can be a little smarter here // we can be a little smarter here
iterator it(*this); iterator it(*this);
while(it.pos() < n_nonzero) while(it != end())
{ {
(*it) = 0; (*it) = eT(0);
it.internal_pos--; // hack to update iterator without requiring a new o ne it.internal_pos--; // hack to update iterator without requiring a new o ne
++it; ++it;
} }
access::rw(n_nonzero) = 0;
} }
template<typename eT> template<typename eT>
inline inline
void void
SpSubview<eT>::ones() SpSubview<eT>::ones()
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
(*this).fill(eT(1)); (*this).fill(eT(1));
skipping to change at line 757 skipping to change at line 732
// clear other things // clear other things
(*this).zeros(); (*this).zeros();
// now the diagonal ones // now the diagonal ones
const uword end_index = std::min(n_rows, n_cols); const uword end_index = std::min(n_rows, n_cols);
for(uword ind = 0; ind < end_index; ++ind) for(uword ind = 0; ind < end_index; ++ind)
{ {
m.at(ind + aux_row1, ind + aux_col1) = eT(1); m.at(ind + aux_row1, ind + aux_col1) = eT(1);
} }
access::rw(n_nonzero) = end_index;
} }
template<typename eT> template<typename eT>
arma_hot arma_hot
inline inline
SpValProxy<SpSubview<eT> > SpValProxy<SpSubview<eT> >
SpSubview<eT>::operator[](const uword i) SpSubview<eT>::operator[](const uword i)
{ {
const uword row = i % n_rows; const uword row = i % n_rows;
const uword col = i / n_rows; const uword col = i / n_rows;
skipping to change at line 1037 skipping to change at line 1010
SpSubview<eT>::begin_row() const SpSubview<eT>::begin_row() const
{ {
return const_row_iterator(*this); return const_row_iterator(*this);
} }
template<typename eT> template<typename eT>
inline inline
typename SpSubview<eT>::iterator typename SpSubview<eT>::iterator
SpSubview<eT>::end() SpSubview<eT>::end()
{ {
return iterator(*this, n_nonzero); return iterator(*this, 0, n_cols, n_nonzero, m.n_nonzero - n_nonzero);
} }
template<typename eT> template<typename eT>
inline inline
typename SpSubview<eT>::const_iterator typename SpSubview<eT>::const_iterator
SpSubview<eT>::end() const SpSubview<eT>::end() const
{ {
return const_iterator(*this, n_nonzero); return const_iterator(*this, 0, n_cols, n_nonzero, m.n_nonzero - n_nonzer o);
} }
template<typename eT> template<typename eT>
inline inline
typename SpSubview<eT>::row_iterator typename SpSubview<eT>::row_iterator
SpSubview<eT>::end_row() SpSubview<eT>::end_row()
{ {
return row_iterator(*this, n_nonzero); return row_iterator(*this, n_nonzero);
} }
 End of changes. 28 change blocks. 
47 lines changed or deleted 20 lines changed or added


 arma_ostream_meat.hpp   arma_ostream_meat.hpp 
skipping to change at line 491 skipping to change at line 491
if(cell_width > 0) if(cell_width > 0)
{ {
// An efficient row_iterator would make this simpler and faster // An efficient row_iterator would make this simpler and faster
for(uword row=0; row < m_n_rows; ++row) for(uword row=0; row < m_n_rows; ++row)
{ {
for(uword col=0; col < m_n_cols; ++col) for(uword col=0; col < m_n_cols; ++col)
{ {
// the cell width appears to be reset after each element is pri nted, // the cell width appears to be reset after each element is pri nted,
// hence we need to restore it // hence we need to restore it
o.width(cell_width); o.width(cell_width);
eT val = 0; eT val = eT(0);
for(typename SpMat<eT>::const_iterator it = begin; it.pos() < m .n_nonzero; ++it) for(typename SpMat<eT>::const_iterator it = begin; it.pos() < m .n_nonzero; ++it)
{ {
if(it.row() == row && it.col() == col) if(it.row() == row && it.col() == col)
{ {
val = *it; val = *it;
break; break;
} }
} }
arma_ostream::print_elem(o,eT(val)); arma_ostream::print_elem(o,eT(val));
} }
skipping to change at line 513 skipping to change at line 513
o << '\n'; o << '\n';
} }
} }
else else
{ {
// An efficient row_iterator would make this simpler and faster // An efficient row_iterator would make this simpler and faster
for(uword row=0; row < m_n_rows; ++row) for(uword row=0; row < m_n_rows; ++row)
{ {
for(uword col=0; col < m_n_cols; ++col) for(uword col=0; col < m_n_cols; ++col)
{ {
eT val = 0; eT val = eT(0);
for(typename SpMat<eT>::const_iterator it = begin; it.pos() < m .n_nonzero; ++it) for(typename SpMat<eT>::const_iterator it = begin; it.pos() < m .n_nonzero; ++it)
{ {
if(it.row() == row && it.col() == col) if(it.row() == row && it.col() == col)
{ {
val = *it; val = *it;
break; break;
} }
} }
arma_ostream::print_elem(o,eT(val)); arma_ostream::print_elem(o,eT(val));
o << ' '; o << ' ';
} }
o << '\n'; o << '\n';
} }
} }
} }
} }
else else
{ {
o << "[matrix size: " << m_n_rows << 'x' << m_n_cols << "]\n"; if(m.n_elem == 0)
{
o << "[matrix size: " << m_n_rows << 'x' << m_n_cols << "]\n";
}
else
{
eT tmp[1];
tmp[0] = eT(0);
const std::streamsize cell_width = modify ? arma_ostream::modify_stre
am(o, &tmp[0], 1) : o.width();
const uword m_n_rows = m.n_rows;
const uword m_n_cols = m.n_cols;
for(uword row=0; row < m_n_rows; ++row)
{
for(uword col=0; col < m_n_cols; ++col)
{
o.width(cell_width);
arma_ostream::print_elem_zero<eT>(o);
o << ' ';
}
o << '\n';
}
}
} }
o.flush(); o.flush();
stream_state.restore(o); stream_state.restore(o);
} }
template<typename eT> template<typename eT>
inline inline
void void
arma_ostream::print(std::ostream& o, const SpMat<eT>& m, const bool modify) arma_ostream::print(std::ostream& o, const SpMat<eT>& m, const bool modify)
skipping to change at line 571 skipping to change at line 596
<< "%]\n\n"; << "%]\n\n";
if(modify == false) { stream_state.restore(o); } if(modify == false) { stream_state.restore(o); }
if(m_n_nonzero > 0) if(m_n_nonzero > 0)
{ {
const std::streamsize cell_width = modify ? modify_stream<eT>(o, m.begi n(), m_n_nonzero) : o.width(); const std::streamsize cell_width = modify ? modify_stream<eT>(o, m.begi n(), m_n_nonzero) : o.width();
typename SpMat<eT>::const_iterator begin = m.begin(); typename SpMat<eT>::const_iterator begin = m.begin();
while(begin.pos() < m_n_nonzero) while(begin != m.end())
{ {
const uword row = begin.row(); const uword row = begin.row();
// TODO: change the maximum number of spaces before and after each lo cation to be dependent on n_rows and n_cols // TODO: change the maximum number of spaces before and after each lo cation to be dependent on n_rows and n_cols
if(row < 10) { o << " "; } if(row < 10) { o << " "; }
else if(row < 100) { o << " "; } else if(row < 100) { o << " "; }
else if(row < 1000) { o << " "; } else if(row < 1000) { o << " "; }
else if(row < 10000) { o << " "; } else if(row < 10000) { o << " "; }
else if(row < 100000) { o << ' '; } else if(row < 100000) { o << ' '; }
 End of changes. 6 change blocks. 
7 lines changed or deleted 33 lines changed or added


 arma_version.hpp   arma_version.hpp 
skipping to change at line 18 skipping to change at line 18
// 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 arma_version //! \addtogroup arma_version
//! @{ //! @{
#define ARMA_VERSION_MAJOR 3 #define ARMA_VERSION_MAJOR 3
#define ARMA_VERSION_MINOR 4 #define ARMA_VERSION_MINOR 4
#define ARMA_VERSION_PATCH 1 #define ARMA_VERSION_PATCH 2
#define ARMA_VERSION_NAME "Ku De Ta" #define ARMA_VERSION_NAME "Ku De Ta"
struct arma_version struct arma_version
{ {
static const unsigned int major = ARMA_VERSION_MAJOR; static const unsigned int major = ARMA_VERSION_MAJOR;
static const unsigned int minor = ARMA_VERSION_MINOR; static const unsigned int minor = ARMA_VERSION_MINOR;
static const unsigned int patch = ARMA_VERSION_PATCH; static const unsigned int patch = ARMA_VERSION_PATCH;
static static
inline inline
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 diskio_meat.hpp   diskio_meat.hpp 
skipping to change at line 2476 skipping to change at line 2476
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
uword x_n_rows = x.n_rows; uword x_n_rows = x.n_rows;
uword x_n_cols = x.n_cols; uword x_n_cols = x.n_cols;
uword x_n_nonzero = x.n_nonzero; uword x_n_nonzero = x.n_nonzero;
//Put down the header //Put down the header
f << x_n_rows << " " << x_n_cols << " " << x_n_nonzero << endl; f << x_n_rows << " " << x_n_cols << " " << x_n_nonzero << endl;
typename SpMat<eT>::const_iterator iter = x.begin(); typename SpMat<eT>::const_iterator iter = x.begin();
for(; iter.pos() < x.n_nonzero; iter++) for(; iter != x.end(); iter++)
f << iter.row() << " " << iter.col() << " " << *iter << endl; f << iter.row() << " " << iter.col() << " " << *iter << endl;
const bool save_okay = f.good(); const bool save_okay = f.good();
return save_okay; return save_okay;
} }
//! Load a matrix as raw text (no header, human readable). //! Load a matrix as raw text (no header, human readable).
//! Can read matrices saved as text in Matlab and Octave. //! Can read matrices saved as text in Matlab and Octave.
//! NOTE: this is much slower than reading a file with a header. //! NOTE: this is much slower than reading a file with a header.
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 fn_accu.hpp   fn_accu.hpp 
skipping to change at line 300 skipping to change at line 300
const SpProxy<T1> p(x); const SpProxy<T1> p(x);
if(SpProxy<T1>::must_use_iterator == false) if(SpProxy<T1>::must_use_iterator == false)
{ {
// direct counting // direct counting
return arrayops::accumulate(p.get_values(), p.get_n_nonzero()); return arrayops::accumulate(p.get_values(), p.get_n_nonzero());
} }
else else
{ {
typename SpProxy<T1>::const_iterator_type it = p.begin(); typename SpProxy<T1>::const_iterator_type it = p.begin();
eT result = eT(0); eT result = eT(0);
while(it.pos() < p.get_n_nonzero()) while(it != p.end())
{ {
result += (*it); result += (*it);
++it; ++it;
} }
return result; return result;
} }
} }
//! @} //! @}
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 fn_dot.hpp   fn_dot.hpp 
skipping to change at line 159 skipping to change at line 159
return op_dot::direct_dot_arma(pa.get_n_nonzero(), pa.get_values(), pa. get_values()); return op_dot::direct_dot_arma(pa.get_n_nonzero(), pa.get_values(), pa. get_values());
} }
else else
{ {
// 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<T2>::const_iterator_type b_it = pb.begin();
while((a_it.pos() < pa.get_n_nonzero()) && (b_it.pos() < pb.get_n_nonze ro())) while((a_it != pa.end()) && (b_it != pb.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 232 skipping to change at line 232
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();
// prefer_at_accessor won't save us operations // prefer_at_accessor won't save us operations
while(it.pos() < pb.get_n_nonzero()) while(it != pb.end())
{ {
result += (*it) * pa.at(it.row(), it.col()); result += (*it) * pa.at(it.row(), it.col());
++it; ++it;
} }
return result; return result;
} }
//! @} //! @}
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 fn_n_unique.hpp   fn_n_unique.hpp 
skipping to change at line 59 skipping to change at line 59
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
arma_ignore(junk); arma_ignore(junk);
// Use iterators. // Use iterators.
typename SpProxy<T1>::const_iterator_type x_it = pa.begin(); typename SpProxy<T1>::const_iterator_type x_it = pa.begin();
typename SpProxy<T2>::const_iterator_type y_it = pb.begin(); typename SpProxy<T2>::const_iterator_type y_it = pb.begin();
uword total_n_nonzero = 0; uword total_n_nonzero = 0;
while((x_it.pos() < pa.get_n_nonzero()) || (y_it.pos() < pb.get_n_nonzero ())) while((x_it != pa.end()) || (y_it != pb.end()))
{ {
if(x_it == y_it) if(x_it == y_it)
{ {
if(op_n_unique_type::eval((*x_it), (*y_it)) != 0) if(op_n_unique_type::eval((*x_it), (*y_it)) != 0)
{ {
++total_n_nonzero; ++total_n_nonzero;
} }
++x_it; ++x_it;
++y_it; ++y_it;
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 fn_trace.hpp   fn_trace.hpp 
skipping to change at line 127 skipping to change at line 127
const SpProxy<T1> p(x.get_ref()); const SpProxy<T1> p(x.get_ref());
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();
while(it.pos() < p.get_n_nonzero()) while(it != p.end())
{ {
if(it.row() == it.col()) if(it.row() == it.col())
{ {
result += (*it); result += (*it);
} }
++it; ++it;
} }
return result; return result;
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 operator_div.hpp   operator_div.hpp 
skipping to change at line 222 skipping to change at line 222
const SpProxy<T1> pa(x.get_ref()); const SpProxy<T1> pa(x.get_ref());
const Proxy<T2> pb(y.get_ref()); const Proxy<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(), "element-wise division"); 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");
SpMat<typename T1::elem_type> result(pa.get_n_rows(), pa.get_n_cols()); SpMat<typename T1::elem_type> result(pa.get_n_rows(), pa.get_n_cols());
// The compiler should be smart enough to optimize out the inner if/else statement entirely // The compiler should be smart enough to optimize out the inner if/else statement entirely
typename SpProxy<T1>::const_iterator_type it = pa.begin(); typename SpProxy<T1>::const_iterator_type it = pa.begin();
uword new_n_nonzero; uword new_n_nonzero;
while(it.pos() < pa.get_n_nonzero()) while(it != pa.end())
{ {
if(Proxy<T2>::prefer_at_accessor == false) if(Proxy<T2>::prefer_at_accessor == false)
{ {
const typename T1::elem_type val = (*it) / pb[(it.col() * pb.get_n_ro ws()) + it.row()]; const typename T1::elem_type val = (*it) / pb[(it.col() * pb.get_n_ro ws()) + it.row()];
if(val != 0) if(val != 0)
{ {
++new_n_nonzero; ++new_n_nonzero;
} }
} }
else else
skipping to change at line 248 skipping to change at line 248
} }
} }
++it; ++it;
} }
result.mem_resize(new_n_nonzero); result.mem_resize(new_n_nonzero);
typename SpProxy<T1>::const_iterator_type it2 = pa.begin(); typename SpProxy<T1>::const_iterator_type it2 = pa.begin();
uword cur_pos = 0; uword cur_pos = 0;
while(it2.pos() < pa.get_n_nonzero()) while(it2 != pa.end())
{ {
if(Proxy<T2>::prefer_at_accessor == false) if(Proxy<T2>::prefer_at_accessor == false)
{ {
const typename T1::elem_type val = (*it2) / pb[(it2.col() * pb.get_n_ rows()) + it2.row()]; const typename T1::elem_type val = (*it2) / pb[(it2.col() * pb.get_n_ rows()) + it2.row()];
if(val != 0) if(val != 0)
{ {
access::rw(result.values[cur_pos]) = val; access::rw(result.values[cur_pos]) = val;
access::rw(result.row_indices[cur_pos]) = it2.row(); access::rw(result.row_indices[cur_pos]) = it2.row();
++access::rw(result.col_ptrs[it2.col() + 1]); ++access::rw(result.col_ptrs[it2.col() + 1]);
++cur_pos; ++cur_pos;
skipping to change at line 314 skipping to change at line 314
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(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_ro ws(), pb.get_n_cols(), "element-wise division");
Mat<typename T1::elem_type> result(pa.get_n_rows(), pa.get_n_cols()); Mat<typename T1::elem_type> result(pa.get_n_rows(), pa.get_n_cols());
result.fill(Datum<typename T1::elem_type>::inf); result.fill(Datum<typename T1::elem_type>::inf);
// Now divide each element // Now divide each element
typename SpProxy<T2>::const_iterator_type it = pb.begin(); typename SpProxy<T2>::const_iterator_type it = pb.begin();
while(it.pos() < pb.get_n_nonzero()) while(it != pb.end())
{ {
if(Proxy<T1>::prefer_at_accessor == false) if(Proxy<T1>::prefer_at_accessor == false)
{ {
const uword index = (it.col() * result.n_rows) + it.row(); const uword index = (it.col() * result.n_rows) + it.row();
result[index] = pa[index] / (*it); result[index] = pa[index] / (*it);
} }
else else
{ {
result.at(it.row(), it.col()) = pa.at(it.row(), it.col()) / (*it); result.at(it.row(), it.col()) = pa.at(it.row(), it.col()) / (*it);
} }
 End of changes. 3 change blocks. 
3 lines changed or deleted 3 lines changed or added


 operator_minus.hpp   operator_minus.hpp 
skipping to change at line 206 skipping to change at line 206
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
Mat<typename T1::elem_type> result(-y.get_ref()); Mat<typename T1::elem_type> result(-y.get_ref());
const SpProxy<T1> pa(x.get_ref()); const SpProxy<T1> pa(x.get_ref());
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();
while(it.pos() != pa.get_n_nonzero()) while(it != pa.end())
{ {
const uword pos = it.col() * pa.get_n_cols() + it.row(); const uword pos = it.col() * pa.get_n_cols() + it.row();
result[pos] += (*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
skipping to change at line 241 skipping to change at line 241
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
Mat<typename T1::elem_type> result(x.get_ref()); Mat<typename T1::elem_type> result(x.get_ref());
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();
while(it.pos() < pb.get_n_nonzero()) while(it != pb.end())
{ {
const uword pos = it.col() * pb.get_n_cols() + it.row(); const uword pos = it.col() * pb.get_n_cols() + it.row();
result[pos] -= (*it); result[pos] -= (*it);
++it; ++it;
} }
return result; return result;
} }
//! @} //! @}
 End of changes. 2 change blocks. 
2 lines changed or deleted 2 lines changed or added


 operator_plus.hpp   operator_plus.hpp 
skipping to change at line 205 skipping to change at line 205
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
Mat<typename T1::elem_type> result(x.get_ref()); Mat<typename T1::elem_type> result(x.get_ref());
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(), "addition" ); 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 = pb.begin();
while(it.pos() < pb.get_n_nonzero()) while(it != pb.end())
{ {
const uword pos = it.col() * pb.get_n_cols() + it.row(); const uword pos = it.col() * pb.get_n_cols() + it.row();
result[pos] += (*it); result[pos] += (*it);
++it; ++it;
} }
return result; return result;
} }
//! @} //! @}
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 operator_schur.hpp   operator_schur.hpp 
skipping to change at line 83 skipping to change at line 83
SpMat<typename T1::elem_type> SpMat<typename T1::elem_type>
>::result >::result
operator% operator%
( (
const SpBase<typename T1::elem_type, T1>& x, const SpBase<typename T1::elem_type, T1>& x,
const SpBase<typename T2::elem_type, T2>& y const SpBase<typename T2::elem_type, T2>& y
) )
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
typedef typename T1::elem_type eT;
const SpProxy<T1> pa(x.get_ref()); const SpProxy<T1> pa(x.get_ref());
const SpProxy<T2> pb(y.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_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<typename T1::elem_type> result(pa.get_n_rows(), pa.get_n_cols());
if( (pa.get_n_nonzero() != 0) && (pb.get_n_nonzero() != 0) ) if( (pa.get_n_nonzero() != 0) && (pb.get_n_nonzero() != 0) )
{ {
// Resize memory to correct size. // Resize memory to correct size.
result.mem_resize(n_unique(x, y, op_n_unique_mul())); result.mem_resize(n_unique(x, y, op_n_unique_mul()));
// Now iterate across both matrices. // Now iterate across both matrices.
typename SpProxy<T1>::const_iterator_type x_it = pa.begin(); typename SpProxy<T1>::const_iterator_type x_it = pa.begin();
typename SpProxy<T2>::const_iterator_type y_it = pb.begin(); typename SpProxy<T2>::const_iterator_type y_it = pb.begin();
typename SpProxy<T1>::const_iterator_type x_end = pa.end();
typename SpProxy<T2>::const_iterator_type y_end = pb.end();
uword cur_val = 0; uword cur_val = 0;
while((x_it.pos() < pa.get_n_nonzero()) || (y_it.pos() < pb.get_n_nonze ro())) while((x_it != x_end) || (y_it != y_end))
{ {
if(x_it == y_it) if(x_it == y_it)
{ {
const typename T1::elem_type val = (*x_it) * (*y_it); const eT val = (*x_it) * (*y_it);
if (val != 0)
if (val != eT(0))
{ {
access::rw(result.values[cur_val]) = val; access::rw(result.values[cur_val]) = val;
access::rw(result.row_indices[cur_val]) = x_it.row(); access::rw(result.row_indices[cur_val]) = x_it.row();
++access::rw(result.col_ptrs[x_it.col() + 1]); ++access::rw(result.col_ptrs[x_it.col() + 1]);
++cur_val; ++cur_val;
} }
++x_it; ++x_it;
++y_it; ++y_it;
} }
else else
{ {
if((x_it.col() < y_it.col()) || ((x_it.col() == y_it.col()) && (x_i const uword x_it_row = x_it.row();
t.row() < y_it.row()))) // if y is closer to the end const uword x_it_col = x_it.col();
const uword y_it_row = y_it.row();
const uword y_it_col = y_it.col();
if((x_it_col < y_it_col) || ((x_it_col == y_it_col) && (x_it_row <
y_it_row))) // if y is closer to the end
{ {
++x_it; ++x_it;
} }
else else
{ {
++y_it; ++y_it;
} }
} }
} }
skipping to change at line 188 skipping to change at line 200
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<typename T1::elem_type> result(pa.get_n_rows(), pa.get_n_cols());
if(Proxy<T1>::prefer_at_accessor == false) if(Proxy<T1>::prefer_at_accessor == false)
{ {
// use direct operator[] access // use direct operator[] access
// count new size // count new size
uword new_n_nonzero = 0; uword new_n_nonzero = 0;
typename SpProxy<T2>::const_iterator_type it = pb.begin(); typename SpProxy<T2>::const_iterator_type it = pb.begin();
while(it.pos() < pb.get_n_nonzero()) while(it != pb.end())
{ {
if(((*it) * pa[(it.col() * pa.get_n_rows()) + it.row()]) != 0) if(((*it) * pa[(it.col() * pa.get_n_rows()) + it.row()]) != 0)
{ {
++new_n_nonzero; ++new_n_nonzero;
} }
++it; ++it;
} }
// Resize memory accordingly. // Resize memory accordingly.
result.mem_resize(new_n_nonzero); result.mem_resize(new_n_nonzero);
uword cur_val = 0; uword cur_val = 0;
typename SpProxy<T2>::const_iterator_type it2 = pb.begin(); typename SpProxy<T2>::const_iterator_type it2 = pb.begin();
while(it2.pos() < pb.get_n_nonzero()) while(it2 != pb.end())
{ {
const typename T1::elem_type val = (*it2) * pa[(it2.col() * pa.get_n_ rows()) + it2.row()]; const typename T1::elem_type val = (*it2) * pa[(it2.col() * pa.get_n_ rows()) + it2.row()];
if(val != 0) if(val != 0)
{ {
access::rw(result.values[cur_val]) = val; access::rw(result.values[cur_val]) = val;
access::rw(result.row_indices[cur_val]) = it2.row(); access::rw(result.row_indices[cur_val]) = it2.row();
++access::rw(result.col_ptrs[it2.col() + 1]); ++access::rw(result.col_ptrs[it2.col() + 1]);
++cur_val; ++cur_val;
} }
++it2; ++it2;
} }
} }
else else
{ {
// use at() access // use at() access
// count new size // count new size
uword new_n_nonzero = 0; uword new_n_nonzero = 0;
typename SpProxy<T2>::const_iterator_type it = pb.begin(); typename SpProxy<T2>::const_iterator_type it = pb.begin();
while(it.pos() < pb.get_n_nonzero()) while(it != pb.end())
{ {
if(((*it) * pa.at(it.row(), it.col())) != 0) if(((*it) * pa.at(it.row(), it.col())) != 0)
{ {
++new_n_nonzero; ++new_n_nonzero;
} }
++it; ++it;
} }
// Resize memory accordingly. // Resize memory accordingly.
result.mem_resize(new_n_nonzero); result.mem_resize(new_n_nonzero);
uword cur_val = 0; uword cur_val = 0;
typename SpProxy<T2>::const_iterator_type it2 = pb.begin(); typename SpProxy<T2>::const_iterator_type it2 = pb.begin();
while(it2.pos() < pb.get_n_nonzero()) while(it2 != pb.end())
{ {
const typename T1::elem_type val = (*it2) * pa.at(it2.row(), it2.col( )); const typename T1::elem_type val = (*it2) * pa.at(it2.row(), it2.col( ));
if(val != 0) if(val != 0)
{ {
access::rw(result.values[cur_val]) = val; access::rw(result.values[cur_val]) = val;
access::rw(result.row_indices[cur_val]) = it2.row(); access::rw(result.row_indices[cur_val]) = it2.row();
++access::rw(result.col_ptrs[it2.col() + 1]); ++access::rw(result.col_ptrs[it2.col() + 1]);
++cur_val; ++cur_val;
} }
 End of changes. 9 change blocks. 
9 lines changed or deleted 21 lines changed or added


 operator_times.hpp   operator_times.hpp 
skipping to change at line 438 skipping to change at line 438
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) if(Proxy<T2>::prefer_at_accessor == false)
{ {
// use direct operator[] access // use direct operator[] access
for(typename SpProxy<T1>::const_iterator_type x_it = pa.begin(); x_it .pos() < pa.get_n_nonzero(); x_it++) for(typename SpProxy<T1>::const_iterator_type x_it = pa.begin(); x_it != pa.end(); x_it++)
{ {
// We just want to use values where y.row = x_it.col. // We just want to use values where y.row = x_it.col.
for(uword col = 0; col < result.n_cols; col++) for(uword col = 0; col < result.n_cols; col++)
{ {
const uword index = x_it.col() + (pb.get_n_rows() * col); const uword index = x_it.col() + (pb.get_n_rows() * col);
result.at(x_it.row(), col) += (*x_it) * pb[index]; result.at(x_it.row(), col) += (*x_it) * pb[index];
} }
} }
} }
else else
{ {
// use at() access // use at() access
for(typename SpProxy<T1>::const_iterator_type x_it = pa.begin(); x_it .pos() < pa.get_n_nonzero(); x_it++) 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++) 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);
} }
} }
} }
} }
return result; return result;
skipping to change at line 494 skipping to change at line 494
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) if(Proxy<T1>::prefer_at_accessor == false)
{ {
// use direct operator[] access // use direct operator[] access
for(typename SpProxy<T2>::const_iterator_type y_col_it = pb.begin(); y_col_it.pos() < pb.get_n_nonzero(); ++y_col_it) 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) for(uword row = 0; row < result.n_rows; ++row)
{ {
const uword index = row + (y_col_it.row() * result.n_rows); const uword index = row + (y_col_it.row() * result.n_rows);
result.at(row, y_col_it.col()) += pa[index] * (*y_col_it); result.at(row, y_col_it.col()) += pa[index] * (*y_col_it);
} }
} }
} }
else else
{ {
// use at() access // use at() access
for(typename SpProxy<T2>::const_iterator_type y_col_it = pb.begin(); y_col_it.pos() < pb.get_n_nonzero(); ++y_col_it) 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) 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);
} }
} }
} }
} }
return result; return result;
 End of changes. 4 change blocks. 
4 lines changed or deleted 4 lines changed or added


 span.hpp   span.hpp 
// Copyright (C) 2010-2011 NICTA (www.nicta.com.au) // Copyright (C) 2010-2012 NICTA (www.nicta.com.au)
// Copyright (C) 2010-2011 Conrad Sanderson // Copyright (C) 2010-2012 Conrad Sanderson
// Copyright (C) 2011 Stanislav Funiak // Copyright (C) 2011 Stanislav Funiak
// //
// 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 64 skipping to change at line 64
// as such, removal of "explicit" needs thorough testing. // as such, removal of "explicit" needs thorough testing.
inline inline
explicit explicit
span(const uword in_a) span(const uword in_a)
: a(in_a) : a(in_a)
, b(in_a) , b(in_a)
, whole(false) , whole(false)
{ {
} }
#if defined(ARMA_USE_CXX11)
span(const double in_a) = delete;
#endif
inline inline
span(const uword in_a, const uword in_b) span(const uword in_a, const uword in_b)
: a(in_a) : a(in_a)
, b(in_b) , b(in_b)
, whole(false) , whole(false)
{ {
} }
}; };
 End of changes. 2 change blocks. 
2 lines changed or deleted 6 lines changed or added


 spglue_minus_meat.hpp   spglue_minus_meat.hpp 
skipping to change at line 53 skipping to change at line 53
template<typename eT, typename T1, typename T2> template<typename eT, typename T1, typename T2>
arma_hot arma_hot
inline inline
void void
spglue_minus::apply_noalias(SpMat<eT>& result, const SpProxy<T1>& pa, const SpProxy<T2>& pb) spglue_minus::apply_noalias(SpMat<eT>& result, const SpProxy<T1>& pa, const SpProxy<T2>& pb)
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_ro ws(), pb.get_n_cols(), "subtraction"); arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_ro ws(), pb.get_n_cols(), "subtraction");
if(pa.get_n_nonzero() == 0) if( (pa.get_n_nonzero() != 0) && (pb.get_n_nonzero() != 0) )
{ {
result = pb.Q; result.set_size(pa.get_n_rows(), pa.get_n_cols());
result *= eT(-1);
return; // Resize memory to correct size.
} result.mem_resize(n_unique(pa, pb, op_n_unique_sub()));
if(pb.get_n_nonzero() == 0)
{
result = pa.Q;
return;
}
result.set_size(pa.get_n_rows(), pa.get_n_cols()); // Now iterate across both matrices.
typename SpProxy<T1>::const_iterator_type x_it = pa.begin();
typename SpProxy<T2>::const_iterator_type y_it = pb.begin();
// Resize memory to correct size. typename SpProxy<T1>::const_iterator_type x_end = pa.end();
result.mem_resize(n_unique(pa, pb, op_n_unique_sub())); typename SpProxy<T2>::const_iterator_type y_end = pb.end();
// Now iterate across both matrices. uword cur_val = 0;
typename SpProxy<T1>::const_iterator_type x_it = pa.begin(); while((x_it != x_end) || (y_it != y_end))
typename SpProxy<T2>::const_iterator_type y_it = pb.begin();
uword cur_val = 0;
while((x_it.pos() < pa.get_n_nonzero()) || (y_it.pos() < pb.get_n_nonzero
()))
{
if(x_it == y_it)
{ {
const typename T1::elem_type val = (*x_it) - (*y_it); if(x_it == y_it)
if (val != 0)
{ {
access::rw(result.values[cur_val]) = val; const eT val = (*x_it) - (*y_it);
access::rw(result.row_indices[cur_val]) = x_it.row();
++access::rw(result.col_ptrs[x_it.col() + 1]); if (val != eT(0))
++cur_val; {
} access::rw(result.values[cur_val]) = val;
access::rw(result.row_indices[cur_val]) = x_it.row();
++access::rw(result.col_ptrs[x_it.col() + 1]);
++cur_val;
}
++x_it;
++y_it;
}
else
{
if((x_it.col() < y_it.col()) || ((x_it.col() == y_it.col()) && (x_it.
row() < y_it.row()))) // if y is closer to the end
{
access::rw(result.values[cur_val]) = (*x_it);
access::rw(result.row_indices[cur_val]) = x_it.row();
++access::rw(result.col_ptrs[x_it.col() + 1]);
++cur_val;
++x_it; ++x_it;
++y_it;
} }
else else
{ {
access::rw(result.values[cur_val]) = -(*y_it); const uword x_it_row = x_it.row();
access::rw(result.row_indices[cur_val]) = y_it.row(); const uword x_it_col = x_it.col();
++access::rw(result.col_ptrs[y_it.col() + 1]);
++cur_val; const uword y_it_row = y_it.row();
++y_it; const uword y_it_col = y_it.col();
if((x_it_col < y_it_col) || ((x_it_col == y_it_col) && (x_it_row <
y_it_row))) // if y is closer to the end
{
access::rw(result.values[cur_val]) = (*x_it);
access::rw(result.row_indices[cur_val]) = x_it_row;
++access::rw(result.col_ptrs[x_it_col + 1]);
++cur_val;
++x_it;
}
else
{
access::rw(result.values[cur_val]) = -(*y_it);
access::rw(result.row_indices[cur_val]) = y_it_row;
++access::rw(result.col_ptrs[y_it_col + 1]);
++cur_val;
++y_it;
}
} }
} }
}
// 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];
}
}
else
{ {
access::rw(result.col_ptrs[c]) += result.col_ptrs[c - 1]; if(pa.get_n_nonzero() == 0)
{
result = pb.Q;
result *= eT(-1);
return;
}
if(pb.get_n_nonzero() == 0)
{
result = pa.Q;
return;
}
} }
} }
// //
// //
// spglue_minus2: scalar*(A - B) // spglue_minus2: scalar*(A - B)
template<typename T1, typename T2> template<typename T1, typename T2>
inline inline
void void
 End of changes. 14 change blocks. 
51 lines changed or deleted 65 lines changed or added


 spglue_plus_meat.hpp   spglue_plus_meat.hpp 
skipping to change at line 54 skipping to change at line 54
template<typename eT, typename T1, typename T2> template<typename eT, typename T1, typename T2>
arma_hot arma_hot
inline inline
void void
spglue_plus::apply_noalias(SpMat<eT>& out, const SpProxy<T1>& pa, const SpP roxy<T2>& pb) spglue_plus::apply_noalias(SpMat<eT>& out, const SpProxy<T1>& pa, const SpP roxy<T2>& pb)
{ {
arma_extra_debug_sigprint(); arma_extra_debug_sigprint();
arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_ro ws(), pb.get_n_cols(), "addition"); arma_debug_assert_same_size(pa.get_n_rows(), pa.get_n_cols(), pb.get_n_ro ws(), pb.get_n_cols(), "addition");
if(pa.get_n_nonzero() == 0) if( (pa.get_n_nonzero() != 0) && (pb.get_n_nonzero() != 0) )
{ {
out = pb.Q; out.set_size(pa.get_n_rows(), pa.get_n_cols());
return;
}
if(pb.get_n_nonzero() == 0)
{
out = pa.Q;
return;
}
out.set_size(pa.get_n_rows(), pa.get_n_cols()); // Resize memory to correct size.
out.mem_resize(n_unique(pa, pb, op_n_unique_add()));
// Resize memory to correct size. // Now iterate across both matrices.
out.mem_resize(n_unique(pa, pb, op_n_unique_add())); typename SpProxy<T1>::const_iterator_type x_it = pa.begin();
typename SpProxy<T2>::const_iterator_type y_it = pb.begin();
// Now iterate across both matrices. typename SpProxy<T1>::const_iterator_type x_end = pa.end();
typename SpProxy<T1>::const_iterator_type x_it = pa.begin(); typename SpProxy<T2>::const_iterator_type y_end = pb.end();
typename SpProxy<T2>::const_iterator_type y_it = pb.begin();
uword cur_val = 0; uword cur_val = 0;
while( (x_it.pos() < pa.get_n_nonzero()) || (y_it.pos() < pb.get_n_nonzer while( (x_it != x_end) || (y_it != y_end) )
o()) )
{
if(x_it == y_it)
{ {
const typename T1::elem_type val = (*x_it) + (*y_it); if(x_it == y_it)
if (val != 0)
{ {
access::rw(out.values[cur_val]) = val; const eT val = (*x_it) + (*y_it);
access::rw(out.row_indices[cur_val]) = x_it.row();
++access::rw(out.col_ptrs[x_it.col() + 1]); if (val != eT(0))
++cur_val; {
} access::rw(out.values[cur_val]) = val;
access::rw(out.row_indices[cur_val]) = x_it.row();
++access::rw(out.col_ptrs[x_it.col() + 1]);
++cur_val;
}
++x_it;
++y_it;
}
else
{
if((x_it.col() < y_it.col()) || ((x_it.col() == y_it.col()) && (x_it.
row() < y_it.row()))) // if y is closer to the end
{
access::rw(out.values[cur_val]) = (*x_it);
access::rw(out.row_indices[cur_val]) = x_it.row();
++access::rw(out.col_ptrs[x_it.col() + 1]);
++cur_val;
++x_it; ++x_it;
++y_it;
} }
else else
{ {
access::rw(out.values[cur_val]) = (*y_it); const uword x_it_row = x_it.row();
access::rw(out.row_indices[cur_val]) = y_it.row(); const uword x_it_col = x_it.col();
++access::rw(out.col_ptrs[y_it.col() + 1]);
++cur_val; const uword y_it_row = y_it.row();
++y_it; const uword y_it_col = y_it.col();
if((x_it_col < y_it_col) || ((x_it_col == y_it_col) && (x_it_row <
y_it_row))) // if y is closer to the end
{
access::rw(out.values[cur_val]) = (*x_it);
access::rw(out.row_indices[cur_val]) = x_it_row;
++access::rw(out.col_ptrs[x_it_col + 1]);
++cur_val;
++x_it;
}
else
{
access::rw(out.values[cur_val]) = (*y_it);
access::rw(out.row_indices[cur_val]) = y_it_row;
++access::rw(out.col_ptrs[y_it_col + 1]);
++cur_val;
++y_it;
}
} }
} }
}
const uword out_n_cols = out.n_cols; const uword out_n_cols = out.n_cols;
uword* col_ptrs = access::rwp(out.col_ptrs); uword* col_ptrs = access::rwp(out.col_ptrs);
// Fix column pointers to be cumulative. // Fix column pointers to be cumulative.
for(uword c = 1; c <= out_n_cols; ++c) for(uword c = 1; c <= out_n_cols; ++c)
{
col_ptrs[c] += col_ptrs[c - 1];
}
}
else
{ {
col_ptrs[c] += col_ptrs[c - 1]; if(pa.get_n_nonzero() == 0)
{
out = pb.Q;
return;
}
if(pb.get_n_nonzero() == 0)
{
out = pa.Q;
return;
}
} }
} }
// //
// //
// spglue_plus2: scalar*(A + B) // spglue_plus2: scalar*(A + B)
template<typename T1, typename T2> template<typename T1, typename T2>
arma_hot arma_hot
inline inline
 End of changes. 16 change blocks. 
51 lines changed or deleted 65 lines changed or added


 spglue_times_meat.hpp   spglue_times_meat.hpp 
skipping to change at line 80 skipping to change at line 80
//if( (pa.get_n_elem() == 0) || (pb.get_n_elem() == 0) ) //if( (pa.get_n_elem() == 0) || (pb.get_n_elem() == 0) )
if( (pa.get_n_nonzero() == 0) || (pb.get_n_nonzero() == 0) ) if( (pa.get_n_nonzero() == 0) || (pb.get_n_nonzero() == 0) )
{ {
return; return;
} }
// Auxiliary storage which denotes when items have been found. // Auxiliary storage which denotes when items have been found.
podarray<uword> index(x_n_rows); podarray<uword> index(x_n_rows);
index.fill(x_n_rows); // Fill with invalid links. index.fill(x_n_rows); // Fill with invalid links.
typename SpProxy<T2>::const_iterator_type y_it = pb.begin(); typename SpProxy<T2>::const_iterator_type y_it = pb.begin();
typename SpProxy<T2>::const_iterator_type y_end = pb.end();
// SYMBMM: calculate column pointers for resultant matrix to obtain a goo d // SYMBMM: calculate column pointers for resultant matrix to obtain a goo d
// upper bound on the number of nonzero elements. // upper bound on the number of nonzero elements.
uword cur_col_length = 0; uword cur_col_length = 0;
uword last_ind = x_n_rows + 1; uword last_ind = x_n_rows + 1;
do do
{ {
const uword y_it_row = y_it.row();
// Look through the column that this point (*y_it) could affect. // Look through the column that this point (*y_it) could affect.
typename SpProxy<T1>::const_iterator_type x_it = pa.begin_col(y_it.row( )); typename SpProxy<T1>::const_iterator_type x_it = pa.begin_col(y_it_row) ;
while(x_it.col() == y_it.row()) while(x_it.col() == y_it_row)
{ {
// A point at x(i, j) and y(j, k) implies a point at c(i, k). // A point at x(i, j) and y(j, k) implies a point at c(i, k).
if(index[x_it.row()] == x_n_rows) if(index[x_it.row()] == x_n_rows)
{ {
index[x_it.row()] = last_ind; index[x_it.row()] = last_ind;
last_ind = x_it.row(); last_ind = x_it.row();
++cur_col_length; ++cur_col_length;
} }
++x_it; ++x_it;
skipping to change at line 123 skipping to change at line 126
// Return index markers to zero. Use last_ind for traversal. // Return index markers to zero. Use last_ind for traversal.
while(last_ind != x_n_rows + 1) while(last_ind != x_n_rows + 1)
{ {
const uword tmp = index[last_ind]; const uword tmp = index[last_ind];
index[last_ind] = x_n_rows; index[last_ind] = x_n_rows;
last_ind = tmp; last_ind = tmp;
} }
} }
} }
while(y_it.pos() < pb.get_n_nonzero()); while(y_it != y_end);
// Accumulate column pointers. // Accumulate column pointers.
for(uword i = 0; i < c.n_cols; ++i) for(uword i = 0; i < c.n_cols; ++i)
{ {
access::rw(c.col_ptrs[i + 1]) += c.col_ptrs[i]; access::rw(c.col_ptrs[i + 1]) += c.col_ptrs[i];
} }
// Now that we know a decent bound on the number of nonzero elements, all ocate // Now that we know a decent bound on the number of nonzero elements, all ocate
// the memory and fill it. // the memory and fill it.
c.mem_resize(c.col_ptrs[c.n_cols]); c.mem_resize(c.col_ptrs[c.n_cols]);
 End of changes. 5 change blocks. 
4 lines changed or deleted 7 lines changed or added


 spop_max_meat.hpp   spop_max_meat.hpp 
skipping to change at line 74 skipping to change at line 74
// maximum in each column // maximum in each column
result.set_size(1, p.get_n_cols()); result.set_size(1, p.get_n_cols());
typename SpProxy<T1>::const_iterator_type it = p.begin(); typename SpProxy<T1>::const_iterator_type it = p.begin();
uword cur_col = it.col(); uword cur_col = it.col();
uword elem_in_col = 1; uword elem_in_col = 1;
eT cur_max = (*it); eT cur_max = (*it);
++it; ++it;
while(it.pos() < p.get_n_nonzero()) while(it != p.end())
{ {
if(it.col() != cur_col) if(it.col() != cur_col)
{ {
// was the column full? // was the column full?
if(elem_in_col == p.get_n_rows()) if(elem_in_col == p.get_n_rows())
{ {
result.at(0, cur_col) = cur_max; result.at(0, cur_col) = cur_max;
} }
else else
{ {
skipping to change at line 197 skipping to change at line 197
typename SpProxy<T1>::const_iterator_type it = p.begin(); typename SpProxy<T1>::const_iterator_type it = p.begin();
uword cur_col = it.col(); uword cur_col = it.col();
uword elem_in_col = 1; uword elem_in_col = 1;
eT cur_max_orig = *it; eT cur_max_orig = *it;
T cur_max_abs = std::abs(cur_max_orig); T cur_max_abs = std::abs(cur_max_orig);
++it; ++it;
while(it.pos() < p.get_n_nonzero()) while(it != p.end())
{ {
if(it.col() != cur_col) if(it.col() != cur_col)
{ {
// was the column full? // was the column full?
if(elem_in_col == p.get_n_rows()) if(elem_in_col == p.get_n_rows())
{ {
result.at(0, cur_col) = cur_max_orig; result.at(0, cur_col) = cur_max_orig;
} }
else else
{ {
skipping to change at line 353 skipping to change at line 353
} }
} }
else else
{ {
// use iterator // use iterator
typename SpProxy<T1>::const_iterator_type it = p.begin(); typename SpProxy<T1>::const_iterator_type it = p.begin();
eT result = (*it); eT result = (*it);
++it; ++it;
while(it.pos() < p.get_n_nonzero()) while(it != p.end())
{ {
if((*it) > result) if((*it) > result)
{ {
result = (*it); result = (*it);
} }
++it; ++it;
} }
if(p.get_n_nonzero() == p.get_n_elem()) if(p.get_n_nonzero() == p.get_n_elem())
skipping to change at line 421 skipping to change at line 421
else else
{ {
// use iterator // use iterator
typename SpProxy<T1>::const_iterator_type it = p.begin(); typename SpProxy<T1>::const_iterator_type it = p.begin();
eT best_val_orig = *it; eT best_val_orig = *it;
T best_val_abs = std::abs(best_val_orig); T best_val_abs = std::abs(best_val_orig);
++it; ++it;
while(it.pos() < p.get_n_nonzero()) while(it != p.end())
{ {
eT val_orig = *it; eT val_orig = *it;
T val_abs = std::abs(val_orig); T val_abs = std::abs(val_orig);
if(val_abs > best_val_abs) if(val_abs > best_val_abs)
{ {
best_val_abs = val_abs; best_val_abs = val_abs;
best_val_orig = val_orig; best_val_orig = val_orig;
} }
 End of changes. 4 change blocks. 
4 lines changed or deleted 4 lines changed or added


 spop_min_meat.hpp   spop_min_meat.hpp 
skipping to change at line 74 skipping to change at line 74
// minimum in each column // minimum in each column
result.set_size(1, p.get_n_cols()); result.set_size(1, p.get_n_cols());
typename SpProxy<T1>::const_iterator_type it = p.begin(); typename SpProxy<T1>::const_iterator_type it = p.begin();
uword cur_col = it.col(); uword cur_col = it.col();
uword elem_in_col = 1; uword elem_in_col = 1;
eT cur_min = (*it); eT cur_min = (*it);
++it; ++it;
while(it.pos() < p.get_n_nonzero()) while(it != p.end())
{ {
if(it.col() != cur_col) if(it.col() != cur_col)
{ {
// was the column full? // was the column full?
if(elem_in_col == p.get_n_rows()) if(elem_in_col == p.get_n_rows())
{ {
result.at(0, cur_col) = cur_min; result.at(0, cur_col) = cur_min;
} }
else else
{ {
skipping to change at line 197 skipping to change at line 197
typename SpProxy<T1>::const_iterator_type it = p.begin(); typename SpProxy<T1>::const_iterator_type it = p.begin();
uword cur_col = it.col(); uword cur_col = it.col();
uword elem_in_col = 1; uword elem_in_col = 1;
eT cur_min_orig = *it; eT cur_min_orig = *it;
T cur_min_abs = std::abs(cur_min_orig); T cur_min_abs = std::abs(cur_min_orig);
++it; ++it;
while(it.pos() < p.get_n_nonzero()) while(it != p.end())
{ {
if(it.col() != cur_col) if(it.col() != cur_col)
{ {
// was the column full? // was the column full?
if(elem_in_col == p.get_n_rows()) if(elem_in_col == p.get_n_rows())
{ {
result.at(0, cur_col) = cur_min_orig; result.at(0, cur_col) = cur_min_orig;
} }
else else
{ {
skipping to change at line 353 skipping to change at line 353
} }
} }
else else
{ {
// use iterator // use iterator
typename SpProxy<T1>::const_iterator_type it = p.begin(); typename SpProxy<T1>::const_iterator_type it = p.begin();
eT result = (*it); eT result = (*it);
++it; ++it;
while(it.pos() < p.get_n_nonzero()) while(it != p.end())
{ {
if((*it) < result) if((*it) < result)
{ {
result = (*it); result = (*it);
} }
++it; ++it;
} }
if(p.get_n_nonzero() == p.get_n_elem()) if(p.get_n_nonzero() == p.get_n_elem())
skipping to change at line 421 skipping to change at line 421
else else
{ {
// use iterator // use iterator
typename SpProxy<T1>::const_iterator_type it = p.begin(); typename SpProxy<T1>::const_iterator_type it = p.begin();
eT best_val_orig = *it; eT best_val_orig = *it;
T best_val_abs = std::abs(best_val_orig); T best_val_abs = std::abs(best_val_orig);
++it; ++it;
while(it.pos() < p.get_n_nonzero()) while(it != p.end())
{ {
eT val_orig = *it; eT val_orig = *it;
T val_abs = std::abs(val_orig); T val_abs = std::abs(val_orig);
if(val_abs < best_val_abs) if(val_abs < best_val_abs)
{ {
best_val_abs = val_abs; best_val_abs = val_abs;
best_val_orig = val_orig; best_val_orig = val_orig;
} }
 End of changes. 4 change blocks. 
4 lines changed or deleted 4 lines changed or added


 spop_sum_meat.hpp   spop_sum_meat.hpp 
skipping to change at line 38 skipping to change at line 38
const SpProxy<T1> p(in.m); const SpProxy<T1> p(in.m);
if(p.is_alias(out) == false) if(p.is_alias(out) == false)
{ {
if(dim == 0) // find the sum in each column if(dim == 0) // find the sum in each column
{ {
out.zeros(1, p.get_n_cols()); out.zeros(1, p.get_n_cols());
typename SpProxy<T1>::const_iterator_type it = p.begin(); typename SpProxy<T1>::const_iterator_type it = p.begin();
while(it.pos() < p.get_n_nonzero()) while(it != p.end())
{ {
out.at(0, it.col()) += (*it); out.at(0, it.col()) += (*it);
++it; ++it;
} }
} }
else // find the sum in each row else // find the sum in each row
{ {
out.zeros(p.get_n_rows(), 1); out.zeros(p.get_n_rows(), 1);
typename SpProxy<T1>::const_iterator_type it = p.begin(); typename SpProxy<T1>::const_iterator_type it = p.begin();
while(it.pos() < p.get_n_nonzero()) while(it != p.end())
{ {
out.at(it.row(), 0) += (*it); out.at(it.row(), 0) += (*it);
++it; ++it;
} }
} }
} }
else else
{ {
if(dim == 0) // find the sum in each column if(dim == 0) // find the sum in each column
{ {
SpMat<eT> result(1, p.get_n_cols()); SpMat<eT> result(1, p.get_n_cols());
typename SpProxy<T1>::const_iterator_type it = p.begin(); typename SpProxy<T1>::const_iterator_type it = p.begin();
while(it.pos() < p.get_n_nonzero()) while(it != p.end())
{ {
result.at(0, it.col()) += (*it); result.at(0, it.col()) += (*it);
++it; ++it;
} }
out.steal_mem(result); out.steal_mem(result);
} }
else // find the sum in each row else // find the sum in each row
{ {
SpMat<eT> result(p.get_n_rows(), 1); SpMat<eT> result(p.get_n_rows(), 1);
typename SpProxy<T1>::const_iterator_type it = p.begin(); typename SpProxy<T1>::const_iterator_type it = p.begin();
while(it.pos() < p.get_n_nonzero()) while(it != p.end())
{ {
result.at(it.row(), 0) += (*it); result.at(it.row(), 0) += (*it);
++it; ++it;
} }
out.steal_mem(result); out.steal_mem(result);
} }
} }
} }
 End of changes. 4 change blocks. 
4 lines changed or deleted 4 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/