///////////////////////////////////////////////////////////////////// // = NMatrix // // A linear algebra library for scientific computation in Ruby. // NMatrix is part of SciRuby. // // NMatrix was originally inspired by and derived from NArray, by // Masahiro Tanaka: http://narray.rubyforge.org // // == Copyright Information // // SciRuby is Copyright (c) 2010 - 2013, Ruby Science Foundation // NMatrix is Copyright (c) 2013, Ruby Science Foundation // // Please see LICENSE.txt for additional copyright notices. // // == Contributing // // By contributing source code to SciRuby, you agree to be bound by // our Contributor Agreement: // // * https://github.com/SciRuby/sciruby/wiki/Contributor-Agreement // // == iterator.h // // Iterate over yale as if dense // #ifndef YALE_ITERATORS_ITERATOR_H # define YALE_ITERATORS_ITERATOR_H #include #include namespace nm { namespace yale_storage { /* * Iterator for traversing matrix class as if it were dense (visits each entry in order). */ template ::value, const nm::YaleStorage, nm::YaleStorage >::type> class iterator_T : public basic_iterator_T { using basic_iterator_T::i_; using basic_iterator_T::p_; using basic_iterator_T::y; using basic_iterator_T::offset; using basic_iterator_T::shape; using basic_iterator_T::ija; protected: size_t j_; // These are relative to the slice. public: // Create an iterator. May select the row since this is O(1). iterator_T(YaleRef& obj, size_t ii = 0) : basic_iterator_T(obj, ii, obj.ija(ii + obj.offset(0))), j_(0) { // advance to the beginning of the row if (obj.offset(1) > 0) p_ = y.find_pos_for_insertion(i_,j_); } // Prefix ++ iterator_T& operator++() { size_t prev_j = j_++; if (j_ >= shape(1)) { j_ = 0; ++i_; // Do a binary search to find the beginning of the slice p_ = offset(0) > 0 ? y.find_pos_for_insertion(i_,j_) : ija(i_); } else { // If the last j was actually stored in this row of the matrix, need to advance p. if (!y.real_row_empty(i_ + offset(0)) && ija(p_) <= prev_j + offset(1)) ++p_; // this test is the same as real_ndnz_exists } return *this; } iterator_T operator++(int dummy) const { iterator_T iter(*this); return ++iter; } virtual bool operator!=(const iterator_T& rhs) const { return this->dense_location() != rhs.dense_location(); } virtual bool operator==(const iterator_T& rhs) const { return this->dense_location() == rhs.dense_location(); } bool operator<(const iterator_T& rhs) const { return this->dense_location() < rhs.dense_location(); } bool operator>(const iterator_T& rhs) const { return this->dense_location() > rhs.dense_location(); } virtual bool diag() const { return i_ + offset(0) == j_ + offset(1); } // De-reference RefType& operator*() { if (diag()) return y.a( i_ + offset(0) ); else if (p_ >= ija(i_+offset(0)+1)) return y.const_default_obj(); else if (!y.real_row_empty(i_ + offset(0)) && ija(p_) == j_ + offset(1)) return y.a( p_ ); else return y.const_default_obj(); } RefType& operator*() const { if (diag()) return y.a( i_ + offset(0) ); else if (p_ >= ija(i_+offset(0)+1)) return y.const_default_obj(); else if (!y.real_row_empty(i_ + offset(0)) && ija(p_) == j_ + offset(1)) return y.a( p_ ); else return y.const_default_obj(); } virtual size_t j() const { return j_; } }; } } // end of namespace nm::yale_storage #endif // YALE_ITERATORS_ITERATOR_H