C:/programs/SCPPNT/src/include/region2d.h

Go to the documentation of this file.
00001 /*! \file region2d.h
00002  \brief Two dimensional regions for arrays and matrices (Region2D, const_Region2D, Region2D_iterator).
00003 
00004  Contains definitions of Region2D and const_Region2D classes which allow
00005  working with a rectangular region of a matrix without creating a new
00006  matrix, and the definition of the class Region2D_iterator which defines an
00007  iterator over all elements of a Region2D.
00008 
00009  */
00010 
00011 /*
00012  Simple C++ Numerical Toolkit (SCPPNT)
00013  http://www.smallwaters.com/software/cpp/scppnt.html
00014  This release updates original work contributed by 
00015  Brad Hanson (http://www.b-a-h.com/) in 2001.
00016 
00017  */
00018 
00019 // Modified from region2d.h in:
00020 /*
00021  *
00022  * Template Numerical Toolkit (TNT): Linear Algebra Module
00023  *
00024  * Mathematical and Computational Sciences Division
00025  * National Institute of Technology,
00026  * Gaithersburg, MD USA
00027  *
00028  *
00029  * This software was developed at the National Institute of Standards and
00030  * Technology (NIST) by employees of the Federal Government in the course
00031  * of their official duties. Pursuant to title 17 Section 105 of the
00032  * United States Code, this software is not subject to copyright protection
00033  * and is in the public domain.  The Template Numerical Toolkit (TNT) is
00034  * an experimental system.  NIST assumes no responsibility whatsoever for
00035  * its use by other parties, and makes no guarantees, expressed or implied,
00036  * about its quality, reliability, or any other characteristic.
00037  *
00038  * BETA VERSION INCOMPLETE AND SUBJECT TO CHANGE
00039  * see http://math.nist.gov/tnt for latest updates.
00040  *
00041  */
00042 
00043 #ifndef SCPPNT_REGION2D_H
00044 #define SCPPNT_REGION2D_H
00045 
00046 #ifdef SCPPNT_NO_DIR_PREFIX
00047 #include "scppnt.h"
00048 #include "slice_pointer.h"
00049 #include "scppnt_error.h"
00050 #include "matop.h"
00051 #include "index.h"
00052 #else
00053 #include "scppnt/scppnt.h"
00054 #include "scppnt/slice_pointer.h"
00055 #include "scppnt/scppnt_error.h"
00056 #include "scppnt/matop.h"
00057 #include "scppnt/index.h"
00058 #endif
00059 
00060 #ifndef SCPPNT_NO_IO
00061 #include <iostream>
00062 #endif
00063 
00064 namespace SCPPNT
00065 {
00066 
00067   /*!
00068    \brief Foward iterator over all elements of a matrix region.
00069 
00070    Foward iterator over all elements of a matrix region. Can be used
00071    to define an iterator over all elements of a matrix in either
00072    row-major or column-major order.
00073    For instance, Region2D_iterator<double, Matrix<double>::columns_iterator>
00074    will be an iterator over all elements of a matrix in column-major order
00075    even if the elements of the matrix are stored in row-major order.
00076 
00077    \param T Type of elements iterator points to. This is not the same as
00078    iterator_traits<iterator_traits<IT2D>::value_type>::value_type
00079    if IT2D is a constant iterator (e.g., Matrix<T>::const_rows_iterator).
00080 
00081    \param IT2D A two dimensional iterator (iterator over iterators to row elements or
00082    iterator over iterators to column elements). Possible values of this parameter
00083    are: Matrix<T>::rows_iterator, Matrix<T>::columns_iterator, Matrix<T>::const_rows_iterator,
00084    Matrix<T>::const_columns_iterator. This parameter determines whether the order of
00085    iteration is row-major or column-major.
00086 
00087    The techinique used for logical comparison operators that allow
00088    constant types to be compared with non-constant types is described
00089    in:
00090 
00091    Austern, Matt (2001, January). Defining iterators and const iterators.
00092    C/C++ Users Journal (www.cuj.com), 74-79.
00093 
00094    */
00095   template<class T, class IT2D> class Region2D_iterator
00096   {
00097 public:
00098 
00099     // Types needed for iterator_traits
00100     typedef T value_type; //!< Type of element pointed to
00101     typedef std::forward_iterator_tag iterator_category; //!< Only allows forward iteration
00102     typedef Subscript difference_type; //!< Type for number of elements separating two iterators
00103 
00104     typedef IT2D iterator_2D; //! Iterator over row or column iterators
00105 
00106     // "typename" keyword added on next three lines (ww, 12-2-2007)
00107     typedef typename std::iterator_traits<iterator_2D>::value_type iterator_1D; //! Iterator over row or column elements
00108 
00109     typedef typename std::iterator_traits<iterator_1D>::pointer pointer; //! Pointer to type
00110 
00111     typedef typename std::iterator_traits<iterator_1D>::reference reference; //! Reference to type pointed to
00112 
00113     //! Constructor. Second and third arguments are 1-based indices of initial element iterator points to.
00114     Region2D_iterator(IT2D it, Subscript n2d, Subscript n1d, Subscript initial2 = 1,
00115         Subscript initial1 = 1);
00116 
00117     //! Return reference to current element pointed to
00118     reference operator*() const
00119     {
00120       return *current_;
00121     }
00122 
00123     //! Increment to point to next element and return modified Region2D_iterator (preincrement)
00124     Region2D_iterator& operator++()
00125     {
00126       ++current_;
00127       if (current_ == end_)
00128       {
00129         ++i2D_;
00130         if (i2D_ != end2D_)
00131         {
00132           current_ = *i2D_;
00133           end_ = current_ + n1D_;
00134         }
00135       }
00136       return *this;
00137     }
00138 
00139     //! Increment to point to next element and return Region2D_iterator pointing to original element (postincrement)
00140     Region2D_iterator operator++(int)
00141     {
00142       Region2D_iterator t(*this);
00143       ++current_;
00144       if (current_ == end_)
00145       {
00146         ++i2D_;
00147         if (i2D_ != end2D_)
00148         {
00149           current_ = *i2D_;
00150           end_ = current_ + n1D_;
00151         }
00152       }
00153       return t;
00154     }
00155 
00156 #ifdef SCPPNT_MEMBER_COMPARISONS
00157 
00158     //! Returns true if two Region2D_iterator objects point to the same element
00159     bool operator==(const Region2D_iterator<T, IT2D> &rhs)
00160     {
00161       return current_ == rhs.current_;
00162     }
00163 
00164     //! Returns true if two Region2D_iterator objects point to the different elements
00165     bool operator!=(const Region2D_iterator<T, IT2D> &rhs)
00166     {
00167       return current_ != rhs.current_;
00168     }
00169 
00170 #else
00171 
00172     //! Returns true if two Region2D_iterator objects point to the same element
00173     friend bool operator==(const Region2D_iterator<T, IT2D> &lhs,
00174         const Region2D_iterator<T, IT2D> &rhs)
00175     {
00176       return lhs.current_ == rhs.current_;
00177     }
00178 
00179     //! Returns true if two Region2D_iterator objects point to the different elements
00180     friend bool operator!=(const Region2D_iterator<T, IT2D> &lhs,
00181         const Region2D_iterator<T, IT2D> &rhs)
00182     {
00183       return lhs.current_ != rhs.current_;
00184     }
00185 
00186 #endif
00187 
00188 private:
00189 
00190     //! Iterator over second-order elements (row iterators or column iterators)
00191     iterator_2D i2D_;
00192 
00193     //! Points to current element pointed to by current first-order iterator (element of current row or column)
00194     iterator_1D current_;
00195 
00196     //! Points to one past last element pointed to by current first-order iterator (last element of current row or column)
00197     iterator_1D end_;
00198 
00199     //! Points to one past last element pointed to by second-order iterator (last row or column iterator)
00200     iterator_2D end2D_;
00201 
00202     //! Number of elements pointed to by each first-order iterator (number of rows or columns)
00203     Subscript n1D_;
00204 
00205   };
00206 
00207   /*!
00208    \brief Constructor
00209 
00210    \param it Iterator over row iterators or column iterators.
00211    \param n2d Number of valid elements pointed to by it.
00212    \param n1d Number of valid elements pointed to by each of the iterators it[0], it[1], etc.
00213    \param initial2 Initial element for 2D iterator (one-offset)
00214    \param initial1 Initial element  for each 1D iterator (one-offset)
00215    */
00216   template<class T, class IT2D> Region2D_iterator<T, IT2D>::Region2D_iterator(IT2D it,
00217       Subscript n2d, Subscript n1d, Subscript initial2, Subscript initial1) :
00218     i2D_(it), n1D_(n1d)
00219   {
00220     if (initial2 >= n2d || initial1 >= n1d)
00221       throw BadDimension("SCPPNT::Region2D_iterator::region2D_iterator");
00222     end2D_ = it + n2d;
00223     i2D_ += initial2 - 1;
00224     end_ = *i2D_ + n1D_;
00225     current_ = *i2D_ + initial1 - 1;
00226   }
00227 
00228   /*!
00229    \brief A rectangular subset of a matrix.
00230 
00231    View of a rectangular subset of a matrix. All operations
00232    that can be done with a SCPPNT::Matrix can be done with
00233    a Region2D. Note this is a view of the original matrix
00234    so all operations take place on elements of the original matrix,
00235    not copies.
00236 
00237    \param Array2D Matrix type that forms the basis of the view.
00238    Requires interface consistent with SCPPNT::Matrix.
00239 
00240    */
00241   template<class Array2D> class Region2D
00242   {
00243 public:
00244 
00245     typedef Array2D array_type; //!< Type of matrix underlying region
00246     typedef typename Array2D::size_type size_type; //!< Subscript type
00247     typedef typename Array2D::value_type value_type; //!< Type of elements stored in matrix
00248     typedef typename Array2D::element_type element_type; //!< Type of elements stored in matrix
00249     typedef typename Array2D::pointer pointer; //!< Pointer to type stored in matrix
00250     typedef typename Array2D::reference reference; //!< Reference to type stored in matrix
00251     typedef typename Array2D::const_reference const_reference; //!< Reference to type stored in constant matrix
00252 
00253     /**** Iterators ****/
00254 
00255     //! Iterator over elements of a row
00256     typedef typename Array2D::row_iterator row_iterator;
00257 
00258     //! Iterator over constant elements of a row
00259     typedef typename Array2D::const_row_iterator const_row_iterator;
00260 
00261     //! Iterator over elements of a column
00262     typedef typename Array2D::column_iterator column_iterator;
00263 
00264     //! Iterator over constant elements of a column
00265     typedef typename Array2D::const_column_iterator const_column_iterator;
00266 
00267     /*
00268      rows_iterator - Iterator over row_iterators for rows of matrix.
00269      columns_iterator - Iterator over column_iterators for columns of matrix.
00270      */
00271 #ifdef SCPPNT_BOUNDS_CHECK
00272     typedef slice_pointer_base<row_iterator, row_iterator*, row_iterator&> rows_iterator;
00273     typedef slice_pointer_base<column_iterator, column_iterator*, column_iterator&>
00274         columns_iterator;
00275     typedef
00276     slice_pointer_base<const_row_iterator, const_row_iterator*, const_row_iterator&>
00277         const_rows_iterator;
00278     typedef
00279     slice_pointer_base<const_column_iterator, const_column_iterator*, const_column_iterator&>
00280         const_columns_iterator;
00281 #else
00282     //! Iterator over row iterators (points to row_iterator object for a row)
00283     typedef row_iterator* rows_iterator;
00284 
00285     //! Iterator over row iterators (points to const_row_iterator object for a row)
00286     typedef const_row_iterator* const_rows_iterator;
00287 
00288     //! Iterator over column iterators (points to column_iterator object for a column)
00289     typedef column_iterator* columns_iterator;
00290 
00291     //! Iterator over column iterators (points to const_column_iterator object for a column)
00292     typedef const_column_iterator* const_columns_iterator;
00293 #endif
00294 
00295     //! Iterator over all elements      ("typename" keyword added on next two lines, ww, 12-6-2007)
00296     typedef Region2D_iterator<value_type, typename Region2D<Array2D>::rows_iterator> iterator;
00297     //! Iterator over all constant elements
00298     typedef Region2D_iterator<value_type, typename Region2D<Array2D>::const_rows_iterator>
00299         const_iterator;
00300 
00301     //! Iterator over elements of a matrix diagonal
00302     typedef typename Array2D::diag_iterator diag_iterator;
00303     //! Iterator over constant elements of a matrix diagonal
00304     typedef typename Array2D::const_diag_iterator const_diag_iterator;
00305 
00306     //! Return matrix that is the basis of the view
00307     const array_type & array() const
00308     {
00309       return A_;
00310     }
00311 
00312     //! Return number of rows in matrix
00313     Subscript num_rows() const
00314     {
00315       return dim_[0];
00316     }
00317 
00318     //! Return number of columns in matrix
00319     Subscript num_columns() const
00320     {
00321       return dim_[1];
00322     } //Changed "num_cols" to "num_columns". ww, 12-6-2007
00323 
00324     //! Returns lower bound of subscript
00325     Subscript lbound() const
00326     {
00327       return A_.lbound();
00328     }
00329 
00330     //! Return number of rows if argument is 1, number of columns if argument is 2
00331     Subscript dim(Subscript i) const
00332     {
00333       if (i< 1 || i> 2)throw InvalidArgument("argument must be 1 or 2", "SCPPNT::Region2D::dim");
00334       return (i==1) ? dim_[0] : dim_[1];
00335     }
00336 
00337     //! Return total number of elements in matrix
00338     Subscript size() const
00339     {
00340       return dim_[0]*dim_[1];
00341     }
00342 
00343     /**** constructors ****/
00344 
00345     /*! \brief Constructor from lower and upper limits for rows and columns
00346      
00347      \param A Matrix to use as basis of region.
00348      \param i1 Index in original matrix of first row in region (1-based).
00349      \param i2 Index in original matrix of last row in region (1-based).
00350      \param j1 Index in original matrix of first column in region (1-based).
00351      \param j2 Index in original matrix of last column in region (1-based).
00352      
00353      */
00354     Region2D(Array2D &A, Subscript i1, Subscript i2, Subscript j1, Subscript j2) : A_(A)
00355     {
00356       initialize(i1, i2, j1, j2);
00357     }
00358 
00359     /*! \brief Constructor using row and column index ranges
00360      
00361      \param A Matrix to use as basis of region
00362      \param I Gives first and last rows of original matrix to use in region.
00363      \param J Gives first and last columns of original matrix to use in region.
00364      */
00365     Region2D(Array2D &A, const Index1D &I, const Index1D &J) : A_(A)
00366     {
00367       initialize(I.lbound(), I.ubound(), J.lbound(), J.ubound());
00368     }
00369 
00370     //! Create a region containing entire matrix (convertion of matrix to region)
00371     Region2D(Array2D &A) : A_(A)
00372     {
00373       initialize(1, A.num_rows(), 1, A.num_columns()); // changed num_cols to "num_columns". ww, 12-6-2007
00374     }
00375 
00376     /*! \brief Constructor from region
00377      
00378      \param A Region to use as basis of region.
00379      \param i1 Index in original region of first row in new region (1-based).
00380      \param i2 Index in original region of last row in new region (1-based).
00381      \param j1 Index in original region of first column in new region (1-based).
00382      \param j2 Index in original region of last column in new region (1-based).
00383      */
00384     Region2D(Region2D<Array2D> &A, Subscript i1, Subscript i2, Subscript j1, Subscript j2)
00385     : A_(A.A_)
00386     {
00387       initialize(i1 + A.offset_[0], i2 + A.offset_[0], j1 + A.offset_[1], j2 + A.offset_[1]);
00388     }
00389 
00390     //! Copy constructor
00391     Region2D(const Region2D<Array2D> &A) : A_(A.A_)
00392     {
00393       initialize(1 + A.offset_[0], A.dim_[0] + A.offset_[0],
00394           1 + A.offset_[1], A.dim_[1] + A.offset_[1]);
00395     }
00396 
00397     //! Destructor
00398     ~Region2D()
00399     {
00400       if (row_ != 0) delete [] (row_);
00401       if (column_ != 0) delete [] (column_); // changed "col_" to "columns_", ww, 12-6-2007.
00402       if (const_row_ != 0) delete [] (const_row_);
00403       if (const_column_ != 0) delete [] (const_column_);} // changed "const_col_" to "const_column_". ww, 12-6-2007. 
00404 
00405     /**** Subscripting ****/
00406 
00407     //! Return iterator to elements in row i+1 (0-based subscripting)
00408     row_iterator operator[](Subscript i)
00409     {
00410       return row_[i];
00411     }
00412 
00413     //! Return iterator to constant elements in row i+1 (0-based subscripting)
00414     const_row_iterator operator[](Subscript i) const
00415     {
00416       return row_[i];
00417     }
00418 
00419     //! Return element in row i and column j, where i and j are 1-based indices
00420     reference operator()(Subscript i, Subscript j)
00421     {
00422       return row_[i-1][j-1];
00423     }
00424 
00425     //! Return constant element in row i and column j, where i and j are 1-based indices
00426     const_reference operator()(Subscript i, Subscript j) const
00427     {
00428       return row_[i-1][j-1];
00429     }
00430 
00431     /*! \brief Return new region that is subregion of this region.
00432      
00433      \param i1 Smallest row in current region to be contained in subregion (1-based)
00434      \param i2 Largest row in current region to be contained in subregion (1-based)
00435      \param j1 Smallest column in current region to be contained in subregion (1-based)
00436      \param j2 Largest column in current region to be contained in subregion (1-based)
00437      */
00438     Region2D<Array2D> operator()(Subscript i1, Subscript i2,
00439         Subscript j1, Subscript j2)
00440     {
00441       return Region2D<Array2D>(A_,
00442           i1+offset_[0], offset_[0] + i2,
00443           j1+offset_[1], offset_[1] + j2);
00444     }
00445 
00446     /*! \brief Return new region that is subregion of this region.
00447      
00448      \param I Smallest and largest rows of current retion to be contained in subregion (1-based)
00449      \param J Smallest and largest columns of current retion to be contained in subregion (1-based)
00450      */
00451     Region2D<Array2D> operator()(const Index1D &I,
00452         const Index1D &J)
00453     {
00454       return Region2D<Array2D>(A_, I.lbound()+offset_[0],
00455           offset_[0] + I.ubound(), offset_[1]+J.lbound(),
00456           offset_[1] + J.ubound());
00457     }
00458 
00459     /**** Iterators ****/
00460 
00461     //! Return iterator pointing to row iterator for first row (iterator over row iterators)
00462     rows_iterator begin_rows();
00463 
00464     //! Return iterator pointing to row iterator for first row (constant version)
00465     const_rows_iterator begin_rows() const;
00466 
00467     //! Return iterator pointing to column iterator for first column (iterator over column iterators)
00468     columns_iterator begin_columns();
00469 
00470     //! Return iterator pointing to column iterator for first column (constant version)
00471     const_columns_iterator begin_columns() const;
00472 
00473     //! Return iterator pointing to row iterator for one past last row (iterator over row iterators)
00474     rows_iterator end_rows();
00475 
00476     //! Return iterator pointing to row iterator for one past last row (constant version)
00477     const_rows_iterator end_rows() const;
00478 
00479     //! Return iterator pointing to column iterator for one past last column (iterator over column iterators)
00480     columns_iterator end_columns();
00481 
00482     //! Return iterator pointing to column iterator for one past last column (constant version)
00483     const_columns_iterator end_columns() const;
00484 
00485     // Return row or column iterator to the first or one past the last element in a particular row or column.
00486     // Index is one-offset (first row or column is 1).
00487 
00488     //! Return iterator pointing to first element in row 'index' (1-offset)
00489     row_iterator begin_row(Subscript index)
00490     {
00491       return row_[index-1];
00492     }
00493 
00494     //! Return iterator pointing to first element in row 'index' (1-offset)
00495     const_row_iterator begin_row(Subscript index) const
00496     {
00497       return const_row_[index-1];
00498     }
00499 
00500     //! Return iterator pointing to first element in column 'index' (1-offset)
00501     column_iterator begin_column(Subscript index)
00502     {
00503       return column_[index-1];
00504     }
00505 
00506     //! Return iterator pointing to first element in column 'index' (1-offset)
00507     const_column_iterator begin_column(Subscript index) const
00508     {
00509       return const_column_[index-1];
00510     }
00511 
00512     //! Return iterator pointing to one past last element in row 'index' (1-offset)
00513     row_iterator end_row(Subscript index)
00514     {
00515       return row_[index];
00516     }
00517 
00518     //! Return iterator pointing to one past last element in row 'index' (1-offset)
00519     const_row_iterator end_row(Subscript index) const
00520     {
00521       return const_row_[index];
00522     }
00523 
00524     //! Return iterator pointing to one past last element in column 'index' (1-offset)
00525     column_iterator end_column(Subscript index)
00526     {
00527       return column_[index];
00528     }
00529 
00530     //! Return iterator pointing to one past last element in column 'index' (1-offset)
00531     const_column_iterator end_column(Subscript index) const
00532     {
00533       return const_column_[index];
00534     }
00535 
00536     // Iterators over all elements of matrix.
00537     // Should only be used when the order in which the iteration takes place
00538     // over all elements of the matrix does not matter
00539 
00540     //! Return iterator pointing to first element of matrix
00541     iterator begin()
00542     {
00543       return iterator(begin_rows(), num_rows(), num_columns());
00544     } // Changed "num_cols" to "num_columns". ww, 12-6-2007.
00545 
00546     //! Return iterator pointing to first element of matrix (constant version)
00547     const_iterator begin() const
00548     {
00549       return const_iterator(begin_rows(), num_rows(), num_columns());
00550     } // Changed "num_cols" to "num_columns". ww, 12-6-2007.
00551 
00552     //! Return iterator pointing to one past last element of matrix
00553     iterator end()
00554     {
00555       return iterator(begin_rows(), num_rows(), num_columns(), dim_[0]+1, 1);
00556     } // Changed "num_cols" to "num_columns". ww, 12-6-2007.
00557 
00558     //! Return iterator pointing to one past last element of matrix (constant version)
00559     const_iterator end() const
00560     {
00561       return const_iterator(begin_rows(), num_rows(), num_columns(), dim_[0]+1, 1);
00562     } // Changed "num_cols" to "num_columns". ww, 12-6-2007.
00563 
00564 
00565     // Iterators over diagonals.
00566 
00567     //! Returns iterator pointing to first element of a matrix diagonal
00568     diag_iterator begin_diagonal(Subscript row, Subscript column);
00569     // Changed "col" to "column". ww, 12-6-2207.
00570 
00571     //! Returns iterator pointing to first element of matrix diagonal
00572     const_diag_iterator begin_diagonal(Subscript row, Subscript column) const;
00573     // Changed "col" to "column". ww, 12-6-2207.
00574 
00575     //! Returns iterator pointing to one past the last element of a matrix diagonal
00576     diag_iterator end_diagonal(Subscript row, Subscript column);
00577     // Changed "col" to "column". ww, 12-6-2207.
00578 
00579     //! Returns iterator pointing to one past the last element of matrix diagonal
00580     const_diag_iterator end_diagonal(Subscript row, Subscript column) const;
00581     // Changed "col" to "column". ww, 12-6-2207.
00582 
00583     /**** Assignment operators ****/
00584 
00585     //! Scalar assignment
00586     Region2D<Array2D>& operator=(const value_type& scalar)
00587     {
00588       iterator it = begin();
00589       for (Subscript j = size(); j--; ++it)
00590       *it = scalar;
00591     }
00592 
00593     //! Assignment operator
00594     Region2D<Array2D> & operator=(const Region2D<Array2D> &R);
00595 
00596     /* The following three member templates must be defined within
00597      the class definition for some compilers (such as Visual C++ 6).
00598      The definitions of other members are given outside the class definition */
00599 
00600     //! Add matrix rhs to matrix
00601     template<class MAT>
00602     Region2D<Array2D>& operator+=(const MAT &rhs)
00603     {
00604       matadd(*this, rhs);
00605       return *this;
00606     }
00607 
00608     //! Subtract matrix rhs from matrix
00609     template<class MAT>
00610     Region2D<Array2D>& operator-=(const MAT &rhs)
00611     {
00612       matsub(*this, rhs);
00613       return *this;
00614     }
00615 
00616     //! Matrix multiply of matrix times rhs (rhs must be square)
00617     template<class MAT>
00618     Region2D<Array2D>& operator*=(const MAT &rhs)
00619     {
00620       matmult_assign(*this, rhs);
00621       return *this;
00622     }
00623 
00624     //! Add scalar to all elements of the matrix
00625     Region2D<Array2D>& operator+=(const value_type& value)
00626     { iterator it = begin();
00627       for (Subscript j = size(); j--; ++it)
00628       *it += value;
00629     }
00630 
00631     //! Subtract scalar from all elements of the matrix
00632     Region2D<Array2D>& operator-=(const value_type& value)
00633     {
00634       iterator it = begin();
00635       for (Subscript j = size(); j--; ++it)
00636       *it -= value;
00637     }
00638 
00639     //! Multiply each element of matrix by scalar value
00640     Region2D<Array2D>& operator*=(const value_type& value)
00641     { iterator it = begin(); for (Subscript j = size(); j--; ++it) *it *= value;}
00642 
00643     //! Divide each element of matrix by scalar value
00644     Region2D<Array2D>& operator/=(const value_type& value)
00645     {
00646       iterator it = begin();
00647       for (Subscript j = size(); j--; ++it)
00648       *it /= value;
00649     }
00650 
00651   private:
00652 
00653     //! Initialize data members
00654     void initialize(Subscript rowLow, Subscript rowHi, Subscript colLow, Subscript colHi);
00655 
00656     Array2D& A_; //!< Matrix that is the basis of the view.
00657     Subscript offset_[2]; //!< Zero-based offsets of first row and column from those in original matrix.
00658     Subscript dim_[2]; //!< Number of rows and columns in matrix view.
00659 
00660     row_iterator *row_; //!< points to array of pointers to rows of matrix
00661     const_row_iterator *const_row_;
00662 
00663     // Changed "col" to "column" in next two lines. ww, 12-6-2007
00664     column_iterator *column_; //!< points to array of pointers to columns of matrix
00665     const_column_iterator *const_column_;
00666 
00667     // Changed "col" to "column" in next two lines. ww, 12-6-2007
00668     //! Return the number of elements in the diagonal beginning at (row, column)
00669     Subscript diagonal_size(Subscript row, Subscript column) const;
00670 
00671   };
00672 
00673   /*!
00674    Initialize Region2D object. Allocate memory for row and column iterators.
00675 
00676    \param rowLow Lowest row in original matrix that is in region (1-based)
00677    \param rowHi Highest row in original matrix that is in region (1-based)
00678    \param colLow Lowest column in original matrix that is in region (1-based)
00679    \param colHi Highest column in original matrix that is in region (1-based)
00680    */
00681   template <class Array2D>
00682   void Region2D<Array2D>::initialize(Subscript rowLow, Subscript rowHi,
00683       Subscript colLow, Subscript colHi)
00684   {
00685     Subscript lowerBound = A_.lbound();
00686 
00687     if ( rowHi < rowLow || rowLow < lowerBound || rowHi > A_.num_rows() )
00688     throw RuntimeError("Bad row index range", "SCPPNT::Region2D<Array2D>::initialize()");
00689     if ( colHi < colLow || colLow < lowerBound || colHi > A_.num_columns() )
00690     throw RuntimeError("Bad column index range", "SCPPNT::Region2D<Array2D>::initialize()");
00691 
00692     offset_[0] = rowLow-lowerBound;
00693     offset_[1] = colLow-lowerBound;
00694     dim_[0] = rowHi-rowLow+1;
00695     dim_[1] = colHi-colLow+1;
00696 
00697     /* Allocate space for pointers to rows of matrix. */
00698     row_ = new row_iterator[dim_[0]+1];
00699     const_row_ = new const_row_iterator[dim_[0]+1];
00700 
00701     /* assign pointers to elements of row_ */
00702     Subscript i;
00703     for (i=0; i<dim_[0]; i++)
00704     {
00705       row_[i] = A_.begin_row(i+offset_[0]+1) + offset_[1];
00706 #ifdef SCPPNT_BOUNDS_CHECK
00707       row_[i].set_size(dim_[1]);
00708 #endif
00709       const_row_[i] = row_[i];
00710     }
00711 
00712     /* Assign iterator to point to one past last row iterator */
00713     row_[i] = row_[i-1] + offset_[1];
00714     const_row_[i] = row_[i];
00715 #ifdef SCPPNT_BOUNDS_CHECK
00716     row_[i].set_size(1);
00717 #endif
00718 
00719     /* Allocate space for pointers to columns of matrix. */
00720     column_ = new column_iterator[dim_[1]+1];
00721     const_column_ = new const_column_iterator[dim_[1]+1];
00722 
00723     /* assign pointers to elements of column_ */
00724     for (i=0; i<dim_[1]; ++i)
00725     {
00726       column_[i] = A_.begin_column(i+offset_[1]+1) + offset_[0];
00727 #ifdef SCPPNT_BOUNDS_CHECK
00728       column_[i].set_size(dim_[0]);
00729 #endif
00730       const_column_[i] = column_[i];
00731     }
00732 
00733     /* Assign iterator to point to one past last column iterator */
00734     column_[i] = column_[i-1] + offset_[0];
00735     const_column_[i] = column_[i];
00736 #ifdef SCPPNT_BOUNDS_CHECK
00737     column_[i].set_size(1);
00738 #endif
00739 
00740   }
00741 
00742   //! Return iterator pointing to row iterator for first row (iterator over row iterators)
00743   template <class Array2D>
00744   inline typename Region2D<Array2D>::rows_iterator Region2D<Array2D>::begin_rows()
00745   {
00746 #ifdef SCPPNT_BOUNDS_CHECK
00747     return rows_iterator(row_, 1, dim_[0]);
00748 #else
00749     return row_;
00750 #endif
00751   }
00752 
00753   //! Return iterator pointing to row iterator for first row (constant version)
00754   template <class Array2D>
00755   inline typename Region2D<Array2D>::const_rows_iterator Region2D<Array2D>::begin_rows()
00756   const
00757   {
00758 #ifdef SCPPNT_BOUNDS_CHECK
00759     return const_rows_iterator(const_row_, 1, dim_[0]);
00760 #else
00761     return const_row_;
00762 #endif
00763   }
00764 
00765   //! Return iterator pointing to column iterator for first column (iterator over column iterators)
00766   template <class Array2D>
00767   inline typename Region2D<Array2D>::columns_iterator Region2D<Array2D>::begin_columns()
00768   {
00769 #ifdef SCPPNT_BOUNDS_CHECK
00770     return columns_iterator(column_, 1, dim_[1]);
00771 #else
00772     return column_;
00773 #endif
00774   }
00775 
00776   //! Return iterator pointing to column iterator for first column (constant version)
00777   template <class Array2D>
00778   inline typename Region2D<Array2D>::const_columns_iterator Region2D<Array2D>::begin_columns() const
00779   {
00780 #ifdef SCPPNT_BOUNDS_CHECK
00781     return const_columns_iterator(const_column_, 1, dim_[1]);
00782 #else
00783     return const_column_;
00784 #endif
00785   }
00786 
00787   // Return iterator pointing to row iterator for one past last row (iterator over row iterators)
00788   template <class Array2D>
00789   inline typename Region2D<Array2D>::rows_iterator Region2D<Array2D>::end_rows()
00790   {
00791 #ifdef SCPPNT_BOUNDS_CHECK
00792     return rows_iterator(row_ + dim_[0], 1, 1);
00793 #else
00794     return row_ + dim_[0];
00795 #endif
00796   }
00797 
00798   // Return iterator pointing to row iterator for one past last row (iterator over row iterators)
00799   template <class Array2D>
00800   inline typename Region2D<Array2D>::const_rows_iterator Region2D<Array2D>::end_rows() const
00801   {
00802 #ifdef SCPPNT_BOUNDS_CHECK
00803     return const_rows_iterator(const_row_ + dim_[0], 1, 1);
00804 #else
00805     return (const_rows_iterator) row_ + dim_[0];
00806 #endif
00807   }
00808 
00809   // Return iterator pointing to column iterator for one past last column (iterator over column iterators)
00810   template <class Array2D>
00811   inline typename Region2D<Array2D>::columns_iterator Region2D<Array2D>::end_columns()
00812   {
00813 #ifdef SCPPNT_BOUNDS_CHECK
00814     return columns_iterator(column_ + dim_[1], 1, 1);
00815 #else
00816     return column_ + dim_[1];
00817 #endif
00818   }
00819 
00820   // Return iterator pointing to column iterator for one past last column (iterator over column iterators)
00821   template <class Array2D>
00822   inline typename Region2D<Array2D>::const_columns_iterator Region2D<Array2D>::end_columns() const
00823   {
00824 #ifdef SCPPNT_BOUNDS_CHECK
00825     return const_columns_iterator(const_column_ + dim_[1], 1, 1);
00826 #else
00827     return const_column_ + dim_[1];
00828 #endif
00829   }
00830 
00831   // Returns number of elements in diagonal with first element (row, column)
00832   template <class Array2D>
00833   inline Subscript Region2D<Array2D>::diagonal_size(Subscript row, Subscript column) const
00834   {
00835     Subscript ncolumn = dim_[0] - column + 1;
00836     Subscript nrow = dim_[1] - row + 1;
00837     return (ncolumn > nrow) ? nrow : ncolumn;
00838 
00839   }
00840 
00841   /*!
00842 
00843    Returns iterator pointing to the first element of the matrix diagonal given by
00844    (row, column), (row+1, column+1), (row+2, column+2), ...
00845    For example, if row=1 and column=1 then an iterator pointing to the first element of the
00846    main diagnonal is returned.
00847 
00848    \param row 1-based row number for initial element of diagonal.
00849    \param column 1-based column number for initial element of diagonal.
00850    */
00851 
00852   template <class Array2D>
00853   inline typename Region2D<Array2D>::diag_iterator Region2D<Array2D>::begin_diagonal(Subscript row, Subscript column)
00854   {
00855 
00856     diag_iterator it = A_.begin_diagonal(row + offset_[0], column + offset_[1]);
00857 
00858 #ifdef SCPPNT_BOUNDS_CHECK
00859     it.set_size(diagonal_size(row, column));
00860 #endif
00861 
00862     return it;
00863   }
00864 
00865   /*!
00866 
00867    Returns iterator pointing to the first element of the matrix diagonal given by
00868    (row, column), (row+1, column+1), (row+2, column+2), ...
00869    For example, if row=1 and column=1 then an iterator pointing to the first element of the
00870    main diagnonal is returned.
00871 
00872    \param row 1-based row number for initial element of diagonal.
00873    \param column 1-based column number for initial element of diagonal.
00874    */
00875   template <class Array2D>
00876   inline typename Region2D<Array2D>::const_diag_iterator Region2D<Array2D>::begin_diagonal(Subscript row, Subscript column) const
00877   {
00878     const_diag_iterator it = A_.begin_diagonal(row + offset_[0], column + offset_[1]);
00879 
00880 #ifdef SCPPNT_BOUNDS_CHECK
00881     it.set_size(diagonal_size(row, column));
00882 #endif
00883 
00884     return it;
00885   }
00886 
00887   /*!
00888 
00889    Returns iterator pointing to the one past last element of the matrix diagonal given by
00890    (row, column), (row+1, column+1), (row+2, column+2), ...
00891    For example, for a square matrix with n rows and columns end_diagonal(1, 1)
00892    returns an iterator pointing to the element (row+n, column+n), which is one past
00893    the last element of the main diagonal.
00894 
00895    \param row 1-based row number for initial element of diagonal.
00896    \param column 1-based column number for initial element of diagonal.
00897    */
00898   template <class Array2D>
00899   inline typename Region2D<Array2D>::diag_iterator Region2D<Array2D>::end_diagonal(Subscript row, Subscript column)
00900   {
00901     diag_iterator it = begin_diagonal(row, column);
00902     return it + diagonal_size(row, column);
00903   }
00904 
00905   /*!
00906 
00907    Returns iterator pointing to the one past last element of the matrix diagonal given by
00908    (row, column), (row+1, column+1), (row+2, column+2), ...
00909    For example, for a square matrix with n rows and columns end_diagonal(1, 1)
00910    returns an iterator pointing to the element (row+n, column+n), which is one past
00911    the last element of the main diagonal.
00912 
00913    \param row 1-based row number for initial element of diagonal.
00914    \param column 1-based column number for initial element of diagonal.
00915    */
00916   template <class Array2D>
00917   inline typename Region2D<Array2D>::const_diag_iterator Region2D<Array2D>::end_diagonal(Subscript row, Subscript column) const
00918   {
00919     const_diag_iterator it = begin_diagonal(row, column);
00920     return it + diagonal_size(row, column);
00921   }
00922 
00923   /*!
00924    \brief Assignment operator.
00925 
00926    Assign contents of this region to those of
00927    region R.
00928    */
00929   template <class Array2D>
00930   Region2D<Array2D> & Region2D<Array2D>::operator=(const Region2D<Array2D> &R)
00931   {
00932     Subscript M = num_rows();
00933     Subscript N = num_columns();
00934 
00935     if (M != R.num_rows() || N != R.num_columns())
00936     {
00937       throw BadDimension("Region2D<Array2D>::operator=(const Region2D)");
00938     }
00939 
00940     const_iterator ir = R.begin();
00941     iterator ithis = begin();
00942     for (int i = M*N; i--; ++ir, ++ithis)
00943     {
00944       *ithis = *ir;
00945     }
00946     return *this;
00947   }
00948 
00949 #ifndef SCPPNT_NO_IO
00950   /*!
00951    \brief Write a matrix to an output stream.
00952 
00953    Writes the number of rows and columnumns, followed
00954    by a new line. The following lines contain the
00955    elements in the rows of the matrix.
00956    */
00957   template <class Array2D>
00958   std::ostream& operator<<(std::ostream &s, const Region2D<Array2D> &A)
00959   {
00960     Subscript M=A.num_rows();
00961     Subscript N=A.num_columns();
00962 
00963     Subscript start = A.lbound();
00964     Subscript Mend = M + A.lbound() - 1;
00965     Subscript Nend = N + A.lbound() - 1;
00966 
00967     s << M << "  " << N << std::endl;
00968     for (Subscript i=start; i<=Mend; i++)
00969     {
00970       for (Subscript j=start; j<=Nend; j++)
00971       {
00972         s << A(i,j) << " ";
00973       }
00974       s << std::endl;
00975     }
00976     return s;
00977   }
00978 #endif
00979 
00980   // *******************[ basic matrix operators ]***************************
00981 
00982   //! Add two matrices and return new matrix giving sum
00983   template <class Array2D, class M>
00984   inline M operator+(const Region2D<Array2D> &A,
00985       const M &B)
00986   {
00987     M sum(A.num_rows(), A.num_columns());
00988     matadd(A, B, sum);
00989     return sum;
00990   }
00991 
00992   //! Subtract matrix B from matrix A and return matrix giving difference
00993   template <class Array2D, class M>
00994   inline M operator-(const Region2D<Array2D> &A,
00995       const M &B)
00996   {
00997     M diff(A.num_rows(), A.num_columns());
00998     matsub(A, B, diff);
00999     return diff;
01000   }
01001 
01002   //! Multiplication operator returning a new matrix containing the matrix product A*B
01003   template <class Array2D, class M>
01004   inline M operator*(const Region2D<Array2D> &A,
01005       const M &B)
01006   {
01007     M c(A.num_rows(), B.num_columns());
01008     matmult(c, A, B);
01009     return c;
01010   }
01011 
01012   //! Return a new vector containing the product of the matrix A and the vector x
01013   template <class T, class Array2D>
01014   inline Vector<T> operator*(const Region2D<Array2D> &A, const Vector<T> &x)
01015   {
01016     return matrix_times_vector< Region2D<Array2D>, Vector<T> >(A, x);
01017   }
01018 
01019   /*!
01020    \brief Constant version of Region2D
01021 
01022    View of a rectangular subset of a constant matrix. All operations
01023    that can be done with a SCPPNT::Matrix can be done with
01024    a Region2D. Note this is a view of the original matrix
01025    so all operations take place using elements of the original matrix,
01026    not copies.
01027 
01028    \param Array2D Matrix type that forms the basis of the view.
01029    Requires interface consistent with SCPPNT::Matrix.
01030 
01031    */
01032   template <class Array2D>
01033   class const_Region2D
01034   {
01035   public:
01036 
01037     typedef const Array2D array_type; //!< Type of matrix underlying region
01038     typedef typename Array2D::size_type size_type; //!< Subscript type
01039     typedef typename Array2D::value_type value_type; //!< Type of elements stored in matrix
01040     typedef typename Array2D::element_type element_type; //!< Type of elements stored in matrix
01041     typedef typename Array2D::pointer pointer; //!< Pointer to type stored in matrix
01042     typedef typename Array2D::reference reference; //!< Reference to type stored in matrix
01043     typedef typename Array2D::const_reference const_reference; //!< Reference to type stored in constant matrix
01044 
01045     /**** Iterators ****/
01046 
01047     //! Iterator over constant elements of a row
01048     typedef typename Array2D::const_row_iterator const_row_iterator;
01049     //! Iterator over elements of a column
01050     typedef typename Array2D::const_column_iterator const_column_iterator;
01051 
01052     /*
01053      rows_iterator - Iterator over row_iterators for rows of matrix.
01054      columns_iterator - Iterator over column_iterators for columns of matrix.
01055      */
01056 
01057 #ifdef SCPPNT_BOUNDS_CHECK
01058     typedef slice_pointer_base<const_row_iterator, const_row_iterator*, const_row_iterator&>
01059     const_rows_iterator;
01060     typedef slice_pointer_base<const_column_iterator, const_column_iterator*, const_column_iterator&>
01061     const_columns_iterator;
01062 #else
01063     //! Iterator over row iterators (points to const_row_iterator object for a row)
01064     typedef const_row_iterator* const_rows_iterator;
01065 
01066     //! Iterator over column iterators (points to const_column_iterator object for a column)
01067     typedef const_column_iterator* const_columns_iterator;
01068 #endif
01069 
01070     //! Iterator over all constant elements     ("typename" keyword added. ww, 12-8-2007)
01071     typedef Region2D_iterator<value_type, typename const_Region2D<Array2D>::const_rows_iterator>
01072     const_iterator;
01073 
01074     //! Iterator over constant elements of a matrix diagonal
01075     typedef typename Array2D::const_diag_iterator const_diag_iterator;
01076 
01077     //! Return matrix that is the basis of the view
01078     const array_type & array() const
01079     {
01080       return A_;
01081     }
01082 
01083     //! Return number of rows in matrix
01084     Subscript num_rows() const
01085     {
01086       return dim_[0];
01087     }
01088 
01089     //! Return number of columns in matrix
01090     Subscript num_columns() const
01091     {
01092       return dim_[1];
01093     }
01094 
01095     //! Returns lower bound of subscript
01096     Subscript lbound() const
01097     {
01098       return A_.lbound();
01099     }
01100 
01101     //! Return number of rows if argument is 1, number of columns if argument is 2
01102     Subscript dim(Subscript i) const
01103     {
01104       if (i < 1 || i > 2) throw InvalidArgument("argument must be 1 or 2", "SCPPNT::const_Region2D::dim");
01105       return (i==1) ? dim_[0] : dim_[1];
01106     }
01107 
01108     //! Return total number of elements in matrix
01109     Subscript size() const
01110     {
01111       return dim_[0]*dim_[1];
01112     }
01113 
01114     /**** constructors ****/
01115 
01116     /*! \brief Constructor from lower and upper limits for rows and columns
01117      
01118      \param A Matrix to use as basis of region.
01119      \param i1 Index in original matrix of first row in region (1-based).
01120      \param i2 Index in original matrix of last row in region (1-based).
01121      \param j1 Index in original matrix of first column in region (1-based).
01122      \param j2 Index in original matrix of last column in region (1-based).
01123      
01124      */
01125     const_Region2D(const Array2D &A, Subscript i1, Subscript i2, Subscript j1,
01126         Subscript j2) : A_(A)
01127     {
01128       initialize(i1, i2, j1, j2);
01129     }
01130 
01131     /*! \brief Constructor using row and column index ranges
01132      
01133      \param A Matrix to use as basis of region
01134      \param I Gives first and last rows of original matrix to use in region.
01135      \param J Gives first and last columns of original matrix to use in region.
01136      */
01137     const_Region2D(const Array2D &A, const Index1D &I, const Index1D &J) : A_(A)
01138     {
01139       initialize(I.lbound(), I.ubound(), J.lbound(), J.ubound());
01140     }
01141 
01142     //! Create a region containing entire matrix (convertion of matrix to region)
01143     const_Region2D(const Array2D &A) : A_(A)
01144     {
01145       initialize(1, A.num_rows(), 1, A.num_columns());
01146     }
01147 
01148     /*! \brief Constructor from region
01149      
01150      \param A Region to use as basis of region.
01151      \param i1 Index in original region of first row in new region (1-based).
01152      \param i2 Index in original region of last row in new region (1-based).
01153      \param j1 Index in original region of first column in new region (1-based).
01154      \param j2 Index in original region of last column in new region (1-based).
01155      */
01156     const_Region2D(const const_Region2D<Array2D> &A, Subscript i1, Subscript i2, Subscript j1, Subscript j2)
01157     : A_(A.A_)
01158     {
01159       initialize(i1 + A.offset_[0], i2 + A.offset_[0], j1 + A.offset_[1], j2 + A.offset_[1]);
01160     }
01161 
01162     //! Copy constructor
01163     const_Region2D(const const_Region2D<Array2D> &A) : A_(A.A_)
01164     {
01165       initialize(1 + A.offset_[0], A.dim_[0] + A.offset_[0], 1 + A.offset_[1], A.dim_[1] + A.offset_[1]);
01166     }
01167 
01168     //! Destructor
01169     ~const_Region2D()
01170     {
01171       if (const_row_ != 0) delete [] (const_row_);
01172       if (const_column_ != 0) delete [] (const_column_);
01173     }
01174 
01175     /**** Subscripting ****/
01176 
01177     //! Return iterator to constant elements in row i+1 (0-based subscripting)
01178     const_row_iterator operator[](Subscript i) const
01179     {
01180       return const_row_[i];
01181     }
01182 
01183     //! Return constant element in row i and column j, where i and j are 1-based indices
01184     const_reference operator()(Subscript i, Subscript j) const
01185     {
01186       return const_row_[i-1][j-1];
01187     }
01188 
01189     /*! \brief Return new region that is subregion of this region.
01190      
01191      \param i1 Smallest row in current region to be contained in subregion (1-based)
01192      \param i2 Largest row in current region to be contained in subregion (1-based)
01193      \param j1 Smallest column in current region to be contained in subregion (1-based)
01194      \param j2 Largest column in current region to be contained in subregion (1-based)
01195      */
01196     const_Region2D<Array2D> operator()(Subscript i1, Subscript i2,
01197         Subscript j1, Subscript j2)
01198     {
01199       return const_Region2D<Array2D>(A_,
01200           i1+offset_[0], offset_[0] + i2,
01201           j1+offset_[1], offset_[1] + j2);
01202     }
01203 
01204     /*! \brief Return new region that is subregion of this region.
01205      
01206      \param I Smallest and largest rows of current retion to be contained in subregion (1-based)
01207      \param I Smallest and largest columns of current retion to be contained in subregion (1-based)
01208      */
01209     const_Region2D<Array2D> operator()(const Index1D &I,
01210         const Index1D &J)
01211     {
01212       return const_Region2D<Array2D>(A_, I.lbound()+offset_[0],
01213           offset_[0] + I.ubound(), offset_[1]+J.lbound(),
01214           offset_[1] + J.ubound());
01215     }
01216 
01217     /**** Iterators ****/
01218 
01219     //! Return iterator pointing to row iterator for first row (iterator over row iterators)
01220     const_rows_iterator begin_rows() const;
01221 
01222     //! Return iterator pointing to column iterator for first column (iterator over column iterators)
01223     const_columns_iterator begin_columns() const;
01224 
01225     //! Return iterator pointing to row iterator for one past last row (iterator over row iterators)
01226     const_rows_iterator end_rows() const;
01227 
01228     //! Return iterator pointing to column iterator for one past last column (iterator over column iterators)
01229     const_columns_iterator end_columns() const;
01230 
01231     // Return row or column iterator for particular row or column.
01232     // Index is one-offset (first row or column is 1).
01233     // row(N+1) returns a row_iterator to one past the last row, where there are N rows
01234     // column(M+1) returns a column_iterator to one past the last column, where there are M columns
01235     //
01236 
01237     //! Return iterator pointing to first element in row 'index' (1-offset)
01238     const_row_iterator begin_row(Subscript index) const
01239     {
01240       return const_row_[index-1];
01241     }
01242 
01243     //! Return iterator over constant elements in column 'index' (1-offset)
01244     const_column_iterator begin_column(Subscript index) const
01245     {
01246       return const_column_[index-1];
01247     }
01248 
01249     //! Return iterator pointing to one past last element in row 'index' (1-offset)
01250     const_row_iterator end_row(Subscript index) const
01251     {
01252       return const_row_[index];
01253     }
01254 
01255     //! Return iterator pointing to one past last element in column 'index' (1-offset)
01256     const_column_iterator end_column(Subscript index) const
01257     {
01258       return const_column_[index];
01259     }
01260 
01261     // Iterators over all elements of matrix.
01262     // Should only be used when the order in which the iteration takes place
01263     // over all elements of the matrix does not matter
01264 
01265     //! Return iterator pointing to first element of matrix (constant version)
01266     const_iterator begin() const
01267     {
01268       return const_iterator(begin_rows(), num_rows(), num_columns());
01269     }
01270 
01271     //! Return iterator pointing to one past last element of matrix
01272     const_iterator end() const
01273     {
01274       return const_iterator(begin_rows(), num_rows(), num_columns(), dim_[0]+1, 1);
01275     }
01276 
01277     // Iterators over diagonals.
01278 
01279     //! Returns iterator pointing to first element of matrix diagonal
01280     const_diag_iterator begin_diagonal(Subscript row, Subscript column) const;
01281 
01282     //! Returns iterator pointing to one past the last element of matrix diagonal
01283     const_diag_iterator end_diagonal(Subscript row, Subscript column) const;
01284 
01285   private:
01286 
01287     //! Initialize data members
01288     void initialize(Subscript rowLow, Subscript rowHi, Subscript colLow, Subscript colHi);
01289 
01290     const Array2D& A_; //!< Matrix that is the basis of the view.
01291     Subscript offset_[2]; //!< Zero-based offsets of first row and column from those in original matrix.
01292     Subscript dim_[2]; //!< Number of rows and columns in matrix view.
01293 
01294     const_row_iterator *const_row_; //!< points to array of pointers to rows of matrix
01295 
01296     const_column_iterator *const_column_; //!< points to array of pointers to columns of matrix
01297 
01298     //! Return the number of elements in the diagonal beginning at (row, column)
01299     Subscript diagonal_size(Subscript row, Subscript column) const;
01300   };
01301 
01302   /*!
01303    Initialize const_Region2D object. Allocate memory for row and column iterators.
01304 
01305    \param rowLow Lowest row in original matrix that is in region (1-based)
01306    \param rowHi Highest row in original matrix that is in region (1-based)
01307    \param colLow Lowest column in original matrix that \
01308   s in region (1-based)
01309    \param colHi Highest column in original matrix that is in region (1-based)
01310    */
01311   template <class Array2D>
01312   void const_Region2D<Array2D>::initialize(Subscript rowLow, Subscript rowHi,
01313       Subscript colLow, Subscript colHi)
01314   {
01315     Subscript lowerBound = A_.lbound();
01316 
01317     if ( rowHi < rowLow || rowLow < lowerBound || rowHi > A_.num_rows())
01318     throw RuntimeError("Bad row index range", "SCPPNT::const_Region2D<Array2D>::initialize()");
01319     if ( colHi < colLow || colLow < lowerBound || colHi > A_.num_columns())
01320     throw RuntimeError("Bad column index range", "SCPPNT::const_Region2D<Array2D>::initialize()");
01321 
01322     offset_[0] = rowLow-lowerBound;
01323     offset_[1] = colLow-lowerBound;
01324     dim_[0] = rowHi-rowLow+1;
01325     dim_[1] = colHi-colLow+1;
01326 
01327     /* Allocate space for pointers to rows of matrix. */
01328     const_row_ = new const_row_iterator[dim_[0]+1];
01329 
01330     /* assign pointers to elements of row_ */
01331     Subscript i;
01332     for (i=0; i<dim_[0]; i++)
01333     {
01334       const_row_[i] = A_.row(i+offset_[0]+1) + offset_[1];
01335 #ifdef SCPPNT_BOUNDS_CHECK
01336       const_row_[i].set_size(dim_[1]);
01337 #endif
01338     }
01339 
01340     /* Assign iterator to point to one past last row iterator */
01341     // Note: This code section was in Brad Hanson's last know revision,
01342     //       but it cannot run since neither row_ nor i are defined here.
01343     //       Since const_row_[] is already determined in the code above,
01344     //       the following section is commented out (ww, 12-09-2007)
01345     // row_[i] = row_[i-1] + offset_[1];
01346     // const_row_[i] = row_[i];
01347     // #ifdef SCPPNT_BOUNDS_CHECK
01348     // row_[i].set_size(1);
01349     // #endif
01350 
01351     /* Allocate space for pointers to columns of matrix. */
01352     const_column_ = new const_column_iterator[dim_[1]+1];
01353 
01354     /* assign pointers to elements of column_ */
01355     for (i=0; i<dim_[1]; ++i)
01356     {
01357       const_column_[i] = A_.column(i+offset_[1]+1) + offset_[0];
01358 #ifdef SCPPNT_BOUNDS_CHECK
01359       const_column_[i].set_size(dim_[0]);
01360 #endif
01361     }
01362 
01363     /* Assign iterator to point to one past last column iterator */
01364     // Note: This code section was in Brad Hanson's last known revision,
01365     //       but it cannot run since neither column_ nor i are defined here.
01366     //       Since const_row_[] is already determined in the code above,
01367     //       the following section is commented out (ww, 12-09-2007)
01368     // column_[i] = column_[i-1] + offset_[0];
01369     // const_column_[i] = column_[i];
01370     // #ifdef SCPPNT_BOUNDS_CHECK
01371     // column_[i].set_size(1);
01372     // #endif
01373   }
01374 
01375   //! Return iterator pointing to row iterator for first row (constant version)
01376   template <class Array2D>
01377   inline typename const_Region2D<Array2D>::const_rows_iterator const_Region2D<Array2D>::begin_rows() const
01378   {
01379 #ifdef SCPPNT_BOUNDS_CHECK
01380     return const_rows_iterator(const_row_, 1, dim_[0]);
01381 #else
01382     return const_row_;
01383 #endif
01384   }
01385 
01386   //! Return iterator pointing to column iterator for first column (constant version)
01387   template <class Array2D>
01388   inline typename const_Region2D<Array2D>::const_columns_iterator const_Region2D<Array2D>::begin_columns() const
01389   {
01390 #ifdef SCPPNT_BOUNDS_CHECK
01391     return const_columns_iterator(const_column_, 1, dim_[1]);
01392 #else
01393     return const_column_;
01394 #endif
01395   }
01396 
01397   // Return iterator pointing to row iterator for one past last row (iterator over row iterators)
01398   template <class Array2D>
01399   inline typename const_Region2D<Array2D>::const_rows_iterator const_Region2D<Array2D>::end_rows() const
01400   {
01401 #ifdef SCPPNT_BOUNDS_CHECK
01402     return const_rows_iterator(const_row_ + dim_[0], 1, 1);
01403 #else
01404     return (const_rows_iterator) row_ + dim_[0];
01405 #endif
01406   }
01407 
01408   // Return iterator pointing to column iterator for one past last column (iterator over column iterators)
01409   template <class Array2D>
01410   inline typename const_Region2D<Array2D>::const_columns_iterator const_Region2D<Array2D>::end_columns() const
01411   {
01412 #ifdef SCPPNT_BOUNDS_CHECK
01413     return const_columns_iterator(const_column_ + dim_[1], 1, 1);
01414 #else
01415     return const_column_ + dim_[1];
01416 #endif
01417   }
01418 
01419   // Returns number of elements in diagonal with first element (row, column)
01420   template <class Array2D>
01421   inline Subscript const_Region2D<Array2D>::diagonal_size(Subscript row, Subscript column) const
01422   {
01423     Subscript ncolumn = dim_[0] - column + 1;
01424     Subscript nrow = dim_[1] - row + 1;
01425 
01426     return (ncolumn > nrow) ? nrow : ncolumn;
01427   }
01428 
01429   /*!
01430 
01431    Returns iterator pointing to the first element of the matrix diagonal given by
01432    (row, column), (row+1, column+1), (row+2, column+2), ...
01433    For example, if row=1 and column=1 then an iterator pointing to the first element of the
01434    main diagnonal is returned.
01435 
01436    \param row 1-based row number for initial element of diagonal.
01437    \param column 1-based column number for initial element of diagonal.
01438    */
01439   template <class Array2D>
01440   inline typename const_Region2D<Array2D>::const_diag_iterator
01441   const_Region2D<Array2D>::begin_diagonal(Subscript row, Subscript column) const
01442   {
01443     const_diag_iterator it = A_.begin_diagonal(row + offset_[0], column + offset_[1]);
01444 
01445 #ifdef SCPPNT_BOUNDS_CHECK
01446     it.set_size(diagonal_size(row, column));
01447 #endif
01448 
01449     return it;
01450   }
01451 
01452   /*!
01453 
01454    Returns iterator pointing to the one past last element of the matrix diagonal given by
01455    (row, column), (row+1, column+1), (row+2, column+2), ...
01456    For example, for a square matrix with n rows and columns end_diagonal(1, 1)
01457    returns an iterator pointing to the element (row+n, column+n), which is one past
01458    the last element of the main diagonal.
01459 
01460    \param row 1-based row number for initial element of diagonal.
01461    \param column 1-based column number for initial element of diagonal.
01462    */
01463   template <class Array2D>
01464   inline typename const_Region2D<Array2D>::const_diag_iterator
01465   const_Region2D<Array2D>::end_diagonal(Subscript row, Subscript column) const
01466   {
01467 
01468     const_diag_iterator it = begin_diagonal(row, column);
01469     return it + diagonal_size(row, column);
01470   }
01471 
01472 #ifndef SCPPNT_NO_IO
01473   /*!
01474    \brief Write a matrix to an output stream.
01475 
01476    Writes the number of rows and columns, followed
01477    by a new line. The following lines contain the
01478    elements in the rows of the matrix.
01479    */
01480   template <class Array2D>
01481   std::ostream& operator<<(std::ostream &s, const const_Region2D<Array2D> &A)
01482   {
01483     Subscript M=A.num_rows();
01484     Subscript N=A.num_columns();
01485 
01486     Subscript start = A.lbound();
01487     Subscript Mend = M + A.lbound() - 1;
01488     Subscript Nend = N + A.lbound() - 1;
01489 
01490     s << M << "  " << N << std::endl;
01491     for (Subscript i=start; i<=Mend; i++)
01492     {
01493       for (Subscript j=start; j<=Nend; j++)
01494       {
01495         s << A(i,j) << " ";
01496       }
01497       s << std::endl;
01498     }
01499 
01500     return s;
01501   }
01502 #endif
01503 
01504   // *******************[ basic matrix operators ]***************************
01505 
01506   //! Add two matrices and return new matrix giving sum
01507   template <class Array2D, class M>
01508   inline M operator+(const const_Region2D<Array2D> &A,
01509       const M &B)
01510   {
01511     M sum(A.num_rows(), A.num_columns());
01512     matadd(A, B, sum);
01513     return sum;
01514   }
01515 
01516   //! Subtract matrix B from matrix A and return matrix giving difference
01517   template <class Array2D, class M>
01518   inline M operator-(const const_Region2D<Array2D> &A,
01519       const M &B)
01520   {
01521     M diff(A.num_rows(), A.num_columns());
01522     matsub(A, B, diff);
01523     return diff;
01524   }
01525 
01526   //! Multiplication operator returning a new matrix containing the matrix product A*B
01527   template <class Array2D, class M>
01528   inline M operator*(const const_Region2D<Array2D> &A,
01529       const M &B)
01530   {
01531     M c(A.num_rows(), B.num_columns());
01532     matmult(c, A, B);
01533     return c;
01534   }
01535 
01536   //! Return a new vector containing the product of the matrix A and the vector x
01537   template <class T, class Array2D>
01538   inline Vector<T> operator*(const const_Region2D<Array2D> &A, const Vector<T> &x)
01539   {
01540     return matrix_times_vector< const_Region2D<Array2D>, Vector<T> >(A, x);
01541   }
01542 
01543 } // namespace SCPPNT
01544 
01545 #endif
01546 // SCPPNT_TRANSV_H

Generated on Tue Dec 18 23:34:06 2007 for SCPPNT by  doxygen 1.5.4