📄 matrix_random_access_iterator.h
字号:
/* * Scythe Statistical Library Copyright (C) 2000-2002 Andrew D. Martin * and Kevin M. Quinn; 2002-present Andrew D. Martin, Kevin M. Quinn, * and Daniel Pemstein. All Rights Reserved. * * This program is free software; you can redistribute it and/or * modify under the terms of the GNU General Public License as * published by Free Software Foundation; either version 2 of the * License, or (at your option) any later version. See the text files * COPYING and LICENSE, distributed with this source code, for further * information. * -------------------------------------------------------------------- * scythestat/matrix_random_access_iterator.h * * Random access iterators for the matrix class. * *//*! \file matrix_random_access_iterator.h * \brief Definitions of STL-compliant random access iterators for * the Matrix class. * * Contains definitions of const_matrix_random_access_iterator, * matrix_random_access_iterator, and related operators. See a * Standard Template Library reference, such as Josuttis (1999), for a * full description of the capabilities of random access iterators. * * These iterators are templated on the type, order and style of the * Matrix they iterate over and their own order, which need not match * the iterated-over matrix. Same-order iteration over concrete * matrices is extremely fast. Cross-grain concrete and/or view * iteration is slower. */#ifndef SCYTHE_MATRIX_RANDOM_ACCESS_ITERATOR_H#define SCYTHE_MATRIX_RANDOM_ACCESS_ITERATOR_H#include <iterator>#ifdef SCYTHE_COMPILE_DIRECT#include "defs.h"#include "error.h"#include "matrix.h"#else#include "scythestat/defs.h"#include "scythestat/error.h"#include "scythestat/matrix.h"#endif/* The const_matrix_iterator and matrix_iterator classes are * essentially identical, except for the return types of the *, ->, * and [] operators. matrix_iterator extends const_matrix_iterator, * overriding most of its members. *//* TODO Current setup uses template argument based branches to * handle views and cross-grained orderings differently than simple * in-order concrete matrices. The work for this gets done at * compile time, but we end with a few unused instance variables in * the concrete case. It might be better to specialize the entire * class, although this will lead to a lot of code duplication. We * should bench the difference down the road and see if it is worth * the maintenance hassle. * * At the moment this is looking like it won't be worth it. * Iterator-based operations on concretes provide comparable * performance to element-access based routines in previous versions * of the library, indicating little performance penalty. */namespace scythe { /* convenience typedefs */ namespace { // local to this file typedef unsigned int uint; } /* forward declaration of the matrix class */ template <typename T_type, matrix_order ORDER, matrix_style STYLE> class Matrix; /*! \brief An STL-compliant const random access iterator for Matrix. * * Provides random access iteration over const Matrix objects. See * Josuttis (1999), or some other STL reference, for a full * description of the random access iterator interface. * * \see Matrix * \see matrix_random_access_iterator * \see const_matrix_forward_iterator * \see matrix_forward_iterator * \see const_matrix_bidirectional_iterator * \see matrix_bidirectional_iterator */ template <typename T_type, matrix_order ORDER, matrix_order M_ORDER, matrix_style M_STYLE> class const_matrix_random_access_iterator : public std::iterator<std::random_access_iterator_tag, T_type> { public: /**** TYPEDEFS ***/ typedef const_matrix_random_access_iterator<T_type, ORDER, M_ORDER, M_STYLE> self; /* These are a little formal, but useful */ typedef typename std::iterator_traits<self>::value_type value_type; typedef typename std::iterator_traits<self>::iterator_category iterator_category; typedef typename std::iterator_traits<self>::difference_type difference_type; typedef typename std::iterator_traits<self>::pointer pointer; typedef typename std::iterator_traits<self>::reference reference; /**** CONSTRUCTORS ****/ /* Default constructor */ const_matrix_random_access_iterator () {} /* Standard constructor */ const_matrix_random_access_iterator ( const Matrix<value_type, M_ORDER, M_STYLE> &M) : start_ (M.getArray()) { SCYTHE_CHECK_30 (start_ == 0, scythe_null_error, "Requesting iterator to NULL matrix"); pos_ = start_; /* The basic story is: when M_STYLE == Concrete and ORDER == * M_ORDER, we only need pos_ and start_ and iteration will be * as fast as possible. All other types of iteration need * more variables to keep track of things and are slower. */ if (M_STYLE != Concrete || M_ORDER != ORDER) { offset_ = 0; if (ORDER == Col) { lead_length_ = M.rows(); lead_inc_ = M.rowstride(); trail_inc_ = M.colstride(); } else { lead_length_ = M.cols(); lead_inc_ = M.colstride(); trail_inc_ = M.rowstride(); } jump_ = trail_inc_ + (1 - lead_length_) * lead_inc_; }#if SCYTHE_DEBUG > 2 size_ = M.size();#endif } /* Copy constructor */ const_matrix_random_access_iterator (const self &mi) : start_ (mi.start_), pos_ (mi.pos_) { if (M_STYLE != Concrete || M_ORDER != ORDER) { offset_ = mi.offset_; lead_length_ = mi.lead_length_; lead_inc_ = mi.lead_inc_; trail_inc_ = mi.trail_inc_; jump_ = mi.jump_; }#if SCYTHE_DEBUG > 2 size_ = mi.size_;#endif } /**** FORWARD ITERATOR FACILITIES ****/ inline self& operator= (const self& mi) { start_ = mi.start_; pos_ = mi.pos_; if (M_STYLE != Concrete || M_ORDER != ORDER) { offset_ = mi.offset_; lead_length_ = mi.lead_length_; lead_inc_ = mi.lead_inc_; trail_inc_ = mi.trail_inc_; jump_ = mi.jump_; }#if SCYTHE_DEBUG > 2 size_ = mi.size_;#endif return *this; } inline const reference operator* () const { SCYTHE_ITER_CHECK_BOUNDS(); return *pos_; } inline const pointer operator-> () const { SCYTHE_ITER_CHECK_BOUNDS(); return pos_; } inline self& operator++ () { if (M_STYLE == Concrete && ORDER == M_ORDER) ++pos_; else if (++offset_ % lead_length_ == 0) pos_ += jump_; else pos_ += lead_inc_; return *this; } inline self operator++ (int) { self tmp = *this; ++(*this); return tmp; } /* == is only defined for iterators of the same template type * that point to the same matrix. Behavior for any other * comparison is undefined. * * Note that we have to be careful about iterator comparisons * when working with views and cross-grain iterators. * Specifically, we always have to rely on the offset value. * Obviously, with <> checks pos_ can jump all over the place in * cross-grain iterators, but also end iterators point to the * value after the last in the matrix. In some cases, the * equation in += and -= will actually put pos_ inside the * matrix (often in an early position) in this case. */ inline bool operator== (const self& x) const { if (M_STYLE == Concrete && ORDER == M_ORDER) { return pos_ == x.pos_; } else { return offset_ == x.offset_; } } /* Again, != is only officially defined for iterators over the * same matrix although the test will be trivially true for * matrices that don't view the same data, by implementation. */ inline bool operator!= (const self &x) const { return !(*this == x); } /**** BIDIRECTIONAL ITERATOR FACILITIES ****/ inline self& operator-- () { if (M_STYLE == Concrete && ORDER == M_ORDER) --pos_; else if (offset_-- % lead_length_ == 0) pos_ -= jump_; else pos_ -= lead_inc_; return *this; } inline self operator-- (int) { self tmp = *this; --(*this); return tmp; } /**** RANDOM ACCESS ITERATOR FACILITIES ****/ inline const reference operator[] (difference_type n) const { if (M_STYLE == Concrete && ORDER == M_ORDER) { SCYTHE_ITER_CHECK_OFFSET_BOUNDS(start_ + n); return *(start_ + n); } else { uint trailing = n / lead_length_; uint leading = n % lead_length_; T_type* place = start_ + leading * lead_inc_ + trailing * trail_inc_; SCYTHE_ITER_CHECK_POINTER_BOUNDS(place); return *place; } } inline self& operator+= (difference_type n) { if (M_STYLE == Concrete && ORDER == M_ORDER) { pos_ += n; } else { offset_ += n; uint trailing = offset_ / lead_length_; uint leading = offset_ % lead_length_; pos_ = start_ + leading * lead_inc_ + trailing * trail_inc_; } return *this; } inline self& operator-= (difference_type n) { if (M_STYLE == Concrete && ORDER == M_ORDER) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -