1 // @HEADER
2 // ***********************************************************************
3 //
4 //                    Teuchos: Common Tools Package
5 //                 Copyright (2004) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ***********************************************************************
40 // @HEADER
41 
42 #ifndef _TEUCHOS_SERIALBANDDENSEMATRIX_HPP_
43 #define _TEUCHOS_SERIALBANDDENSEMATRIX_HPP_
44 /*! \file Teuchos_SerialBandDenseMatrix.hpp
45   \brief Templated serial dense matrix class
46 */
47 
48 #include "Teuchos_CompObject.hpp"
49 #include "Teuchos_BLAS.hpp"
50 #include "Teuchos_ScalarTraits.hpp"
51 #include "Teuchos_DataAccess.hpp"
52 #include "Teuchos_ConfigDefs.hpp"
53 #include "Teuchos_RCP.hpp"
54 #include "Teuchos_Assert.hpp"
55 
56 /*! \class Teuchos::SerialBandDenseMatrix
57     \brief This class creates and provides basic support for banded dense matrices of templated type.
58 
59     The Teuchos_SerialBandDenseMatrix class enables the construction and use of banded dense matrices of templated type.
60 
61     The Teuchos::SerialBandDenseMatrix class is intended to provide full-featured support for solving
62     linear and eigen system problems for banded matrices.  It is written on
63     top of BLAS and LAPACK and thus has excellent performance and numerical capabilities.  Using this
64     class, one can either perform simple factorizations and solves or apply all the tricks available in
65     LAPACK to get the best possible solution for very ill-conditioned problems.
66 
67     <b>Teuchos::SerialBandDenseMatrix vs. Teuchos::LAPACK</b>
68 
69     The Teuchos::LAPACK class provides access to most of the same functionality as Teuchos::SerialBandDenseMatrix.
70     The primary difference is that Teuchos::LAPACK is a "thin" layer on top of LAPACK and
71     Teuchos::SerialBandDenseMatrix attempts to provide easy access to the more sophisticated aspects of
72     solving dense linear and eigensystems.
73 <ul>
74 <li> When you should use Teuchos::LAPACK:  If you are simply looking for a convenient wrapper around
75 the Fortran LAPACK routines and you have a well-conditioned problem, you should probably use Teuchos::LAPACK directly.
76 <li> When you should use Teuchos::SerialBandDenseMatrix: If you want to (or potentially want to) solve ill-conditioned
77      problems or want to work with a more object-oriented interface, you should probably use Teuchos::SerialBandDenseMatrix.
78 </ul>
79 
80 <b>Constructing Teuchos::SerialBandDenseMatrix Objects</b>
81 
82 There are three Teuchos::SerialBandDenseMatrix constructors.  The first constructs a zero-sized object
83 which should be made to appropriate length using the Shape() or Reshape() functions and then filled with
84 the [] or () operators. The second is a constructor that accepts user data as a 2D array, the third is a
85 copy constructor. The second constructor has two data access modes (specified by the Teuchos::DataAccess argument):
86 <ol>
87   <li> Copy mode - Allocates memory and makes a copy of the user-provided data. In this case, the
88        user data is not needed after construction.
89   <li> View mode - Creates a "view" of the user data. In this case, the
90        user data is required to remain intact for the life of the object.
91 </ol>
92 
93 \warning View mode is \e extremely dangerous from a data hiding perspective. Therefore, we strongly encourage
94 users to develop code using Copy mode first and only use the View mode in a secondary optimization phase.
95 
96 <b>Format of the matrix A</b>
97 
98 The matrix A is stored as a banded matrix AB according to the LAPACK format. Consider using
99 the non-member conversion routines generalToBanded and bandedToGeneral if the full Teuchos::SerialDenseMatrix is
100 already in storage. However, it is more efficient to simply construct the Teuchos::SerialBandDenseMatrix with the desired
101 parameters and use the provided matrix access operators to assign (legal) entries so that the full
102 rectangular matrix does not need to be stored. A full description of the LAPACK banded format can be found at
103 http://www.netlib.org/lapack/lug/node124.html. Briefly, the banded storage format of AB used internally is as follows:
104 <ul>
105 <li> The dimension of AB is KL+KU+1 by N, where KL and KU are the lower and upper bandwidths, respectively.
106 <li> The entries are stored in a compressed format: AB(KU+i-j,j) = A(i,j) for max(0,j-KU)<=i<=min(M-1,j+KL).
107 </ul>
108 
109 <b>Extracting Data from Teuchos::SerialBandDenseMatrix Objects</b>
110 
111 Once a Teuchos::SerialBandDenseMatrix is constructed, it is possible to view the data via access functions.
112 
113 \warning Use of these access functions cam be \e extremely dangerous from a data hiding perspective.
114 
115 <b>Vector and Utility Functions</b>
116 
117 Once a Teuchos::SerialBandDenseMatrix is constructed, several mathematical functions can be applied to
118 the object.  Specifically:
119 <ul>
120   <li> Multiplication.
121   <li> Norms.
122 </ul>
123 
124 */
125 
126 /** \example DenseMatrix/cxx_main_band.cpp
127     This is an example of how to use the Teuchos::SerialBandDenseMatrix class.
128 */
129 
130 namespace Teuchos {
131 
132 template<typename OrdinalType, typename ScalarType>
133 class SerialBandDenseMatrix : public CompObject, public BLAS<OrdinalType, ScalarType>
134 {
135 public:
136 
137   //! Typedef for ordinal type
138   typedef OrdinalType ordinalType;
139   //! Typedef for scalar type
140   typedef ScalarType scalarType;
141 
142   //! @name Constructor/Destructor methods.
143   //@{
144 
145   //! Default Constructor
146   /*! Creates a empty matrix of no dimension.  The Shaping methods should be used to size this matrix.
147     Values of this matrix should be set using the [], (), or = operators.
148   */
149   SerialBandDenseMatrix();
150 
151   //! Shaped Constructor
152   /*!
153     \param numRows - Number of rows in matrix.
154     \param numCols - Number of columns in matrix.
155     \param kl - Lower bandwidth of matrix.
156     \param ku - Upper bandwidth of matrix.
157     \param zeroOut - Initializes values to 0 if true (default)
158 
159     Creates a shaped matrix with \c numRows rows and \c numCols cols.  All values are initialized to 0 when \c zeroOut is true.
160     Values of this matrix should be set using the [] or the () operators.
161   */
162   SerialBandDenseMatrix(OrdinalType numRows, OrdinalType numCols, OrdinalType kl, OrdinalType ku, bool zeroOut = true);
163 
164   //! Shaped Constructor with Values
165   /*!
166     \param CV - Enumerated type set to Teuchos::Copy or Teuchos::View.
167     \param values - Pointer to an array of ScalarType.  The first column starts at \c values,
168      the second at \c values+stride, etc.
169     \param stride - The stride between the columns of the matrix in memory.
170     \param numRows - Number of rows in matrix.
171     \param numCols - Number of columns in matrix.
172     \param kl - Lower bandwidth of matrix.
173     \param ku - Upper bandwidth of matrix.
174   */
175   SerialBandDenseMatrix(DataAccess CV, ScalarType* values, OrdinalType stride, OrdinalType numRows, OrdinalType numCols, OrdinalType kl, OrdinalType ku);
176 
177   //! Copy Constructor
178   /*! \note A deep copy of the \c Source transposed can be obtained if \c trans=Teuchos::TRANS, \c else
179     a non-transposed copy of \c Source is made.  There is no storage of the transpose state of the matrix
180     within the SerialBandDenseMatrix class, so this information will not propogate to any operation performed
181     on a matrix that has been copy constructed in transpose.
182   */
183   SerialBandDenseMatrix(const SerialBandDenseMatrix<OrdinalType, ScalarType> &Source, ETransp trans = Teuchos::NO_TRANS);
184 
185   //! Submatrix Copy Constructor
186   /*!
187     \param CV - Enumerated type set to Teuchos::Copy or Teuchos::View.
188     \param Source - Reference to another dense matrix from which values are to be copied.
189     \param numRows - The number of rows in this matrix.
190     \param numCols - The number of columns in this matrix.
191     \param kl - Lower bandwidth of matrix.
192     \param ku - Upper bandwidth of matrix.
193     \param startRow - The row of \c Source from which the submatrix copy should start.
194     \param startCol - The column of \c Source from which the submatrix copy should start.
195 
196     Creates a shaped matrix with \c numRows rows and \c numCols columns, which is a submatrix of \c Source.
197     If \c startRow and \c startCol are not given, then the submatrix is the leading submatrix of \c Source.
198     Otherwise, the (1,1) entry in the copied matrix is the (\c startRow, \c startCol) entry of \c Source.
199   */
200   SerialBandDenseMatrix(DataAccess CV, const SerialBandDenseMatrix<OrdinalType, ScalarType> &Source, OrdinalType numRows, OrdinalType numCols, OrdinalType startCol=0);
201 
202   //! Destructor
203   virtual ~SerialBandDenseMatrix();
204   //@}
205 
206   //! @name Shaping methods.
207   //@{
208   //! Shape method for changing the size of a SerialBandDenseMatrix, initializing entries to zero.
209   /*!
210     \param numRows - The number of rows in this matrix.
211     \param numCols - The number of columns in this matrix.
212     \param kl - Lower bandwidth of matrix.
213     \param ku - Upper bandwidth of matrix.
214 
215     This method allows the user to define the dimensions of a SerialBandDenseMatrix at any point.  This method
216     can be called at any point after construction.  Any values previously in this object will be destroyed
217     and the resized matrix starts of with all zero values.
218 
219     \return Integer error code, set to 0 if successful.
220   */
221   int shape(OrdinalType numRows, OrdinalType numCols, OrdinalType kl, OrdinalType ku);
222 
223   //! Same as <tt>shape()</tt> except leaves uninitialized.
224   int shapeUninitialized(OrdinalType numRows, OrdinalType numCols, OrdinalType kl, OrdinalType ku);
225 
226   //! Reshaping method for changing the size of a SerialBandDenseMatrix, keeping the entries.
227   /*!
228     \param numRows - The number of rows in this matrix.
229     \param numCols - The number of columns in this matrix.
230     \param kl - Lower bandwidth of matrix.
231     \param ku - Upper bandwidth of matrix.
232 
233     This method allows the user to redefine the dimensions of a SerialBandDenseMatrix at any point.  This method
234     can be called at any point after construction.  Any values previously in this object will be copied into
235     the reshaped matrix.
236 
237     \return Integer error code, set 0 if successful.
238   */
239   int reshape(OrdinalType numRows, OrdinalType numCols, OrdinalType kl, OrdinalType ku);
240 
241 
242   //@}
243 
244   //! @name Set methods.
245   //@{
246 
247   //! Copies values from one matrix to another.
248   /*!
249     The operator= copies the values from one existing SerialBandDenseMatrix to another.
250     If \c Source is a view (i.e. CV = Teuchos::View), then this method will
251     return a view.  Otherwise, it will return a copy of \c Source.  \e this object
252     will be resized if it is not large enough to copy \c Source into.
253   */
254   SerialBandDenseMatrix<OrdinalType, ScalarType>& operator= (const SerialBandDenseMatrix<OrdinalType, ScalarType>& Source);
255 
256   //! Copies values from one matrix to another.
257   /*!
258     The operator= copies the values from one existing SerialBandDenseMatrix to another
259     if the dimension of both matrices are the same.  If not, \e this matrix
260     will be returned unchanged.
261   */
262   SerialBandDenseMatrix<OrdinalType, ScalarType>& assign (const SerialBandDenseMatrix<OrdinalType, ScalarType>& Source);
263 
264   //! Set all values in the matrix to a constant value.
265   /*!
266     \param value - Value to use;
267   */
operator =(const ScalarType value)268   SerialBandDenseMatrix<OrdinalType, ScalarType>& operator= (const ScalarType value) { putScalar(value); return(*this); }
269 
270   //! Set all values in the matrix to a constant value.
271   /*!
272     \param value - Value to use; zero if none specified.
273     \return Integer error code, set to 0 if successful.
274   */
275   int putScalar( const ScalarType value = Teuchos::ScalarTraits<ScalarType>::zero() );
276 
277   //! Set all values in the matrix to be random numbers.
278   int random();
279 
280   //@}
281 
282   //! @name Accessor methods.
283   //@{
284 
285   //! Element access method (non-const).
286   /*! Returns the element in the ith row and jth column if A(i,j) is specified, the
287     expression A[j][i] will return the same element.
288 
289     \return Element from the specified \c rowIndex row and \c colIndex column.
290     \warning The validity of \c rowIndex and \c colIndex will only be checked if Teuchos is
291     configured with --enable-teuchos-abc.
292   */
293   ScalarType& operator () (OrdinalType rowIndex, OrdinalType colIndex);
294 
295   //! Element access method (const).
296   /*! Returns the element in the ith row and jth column if A(i,j) is specified, the expression
297     A[j][i] will return the same element.
298 
299     \return Element from the specified \c rowIndex row and \c colIndex column.
300     \warning The validity of \c rowIndex and \c colIndex will only be checked if Teuchos is
301     configured with --enable-teuchos-abc.
302   */
303   const ScalarType& operator () (OrdinalType rowIndex, OrdinalType colIndex) const;
304 
305   //! Column access method (non-const).
306   /*! Returns the pointer to the ScalarType array at the jth column if A[j] is specified, the expression
307     A[j][i] will return the same element as A(i,j).
308 
309     \return Pointer to the ScalarType array at the \c colIndex column ( \c values_+colIndex*stride_ ).
310     \warning The validity of \c colIndex will only be checked if Teuchos is     configured with
311     --enable-teuchos-abc.
312   */
313   ScalarType* operator [] (OrdinalType colIndex);
314 
315   //! Column access method (const).
316   /*! Returns the pointer to the ScalarType array at the jth column if A[j] is specified, the expression
317     A[j][i] will return the same element as A(i,j).
318 
319     \return Pointer to the ScalarType array at the \c colIndex column ( \c values_+colIndex*stride_ ).
320     \warning The validity of \c colIndex will only be checked if Teuchos is     configured with
321     --enable-teuchos-abc.
322   */
323   const ScalarType* operator [] (OrdinalType colIndex) const;
324 
325   //! Data array access method.
326   /*! \return Pointer to the ScalarType data array contained in the object. */
values() const327   ScalarType* values() const { return(values_); }
328 
329   //@}
330 
331   //! @name Mathematical methods.
332   //@{
333 
334   //! Add another matrix to \e this matrix.
335   /*! Add \c Source to \e this if the dimension of both matrices are the same.  If not, \e this matrix
336     will be returned unchanged.
337   */
338   SerialBandDenseMatrix<OrdinalType, ScalarType>& operator+= (const SerialBandDenseMatrix<OrdinalType, ScalarType>& Source);
339 
340   //! Subtract another matrix from \e this matrix.
341   /*! Subtract \c Source from \e this if the dimension of both matrices are the same.  If not, \e this matrix
342     will be returned unchanged.
343   */
344   SerialBandDenseMatrix<OrdinalType, ScalarType>& operator-= (const SerialBandDenseMatrix<OrdinalType, ScalarType>& Source);
345 
346   //! Scale \c this matrix by \c alpha; \c *this = \c alpha*\c *this.
347   /*!
348     \param alpha Scalar to multiply \e this by.
349   */
350   SerialBandDenseMatrix<OrdinalType, ScalarType>& operator*= (const ScalarType alpha);
351 
352   //! Scale \c this matrix by \c alpha; \c *this = \c alpha*\c *this.
353   /*!
354     \param alpha Scalar to multiply \e this by.
355     \return Integer error code, set to 0 if successful.
356   */
357   int scale ( const ScalarType alpha );
358 
359   //! Point-wise scale \c this matrix by \c A; i.e. *this(i,j) *= A(i,j)
360   /*! The values of \c *this matrix will be point-wise scaled by the values in A.
361     If A and \c this matrix are not the same dimension \c this will be returned unchanged.
362 
363     \param B Teuchos::SerialBandDenseMatrix used to perform element-wise scaling of \e this.
364     \return Integer error code, set to 0 if successful.
365   */
366   int scale ( const SerialBandDenseMatrix<OrdinalType, ScalarType>& A );
367 
368   //@}
369 
370   //! @name Comparison methods.
371   //@{
372 
373   //! Equality of two matrices.
374   /*! \return True if \e this matrix and \c Operand are of the same shape (rows and columns) and have
375     the same entries, else False will be returned.
376   */
377   bool operator== (const SerialBandDenseMatrix<OrdinalType, ScalarType> &Operand) const;
378 
379   //! Inequality of two matrices.
380   /*! \return True if \e this matrix and \c Operand of not of the same shape (rows and columns) or don't
381     have the same entries, else False will be returned.
382   */
383   bool operator!= (const SerialBandDenseMatrix<OrdinalType, ScalarType> &Operand) const;
384 
385   //@}
386 
387   //! @name Attribute methods.
388   //@{
389 
390   //! Returns the row dimension of this matrix.
numRows() const391   OrdinalType numRows() const { return(numRows_); }
392 
393   //! Returns the column dimension of this matrix.
numCols() const394   OrdinalType numCols() const { return(numCols_); }
395 
396   //! Returns the lower bandwidth of this matrix.
lowerBandwidth() const397   OrdinalType lowerBandwidth() const { return(kl_); }
398 
399   //! Returns the upper bandwidth of this matrix.
upperBandwidth() const400   OrdinalType upperBandwidth() const { return(ku_); }
401 
402   //! Returns the stride between the columns of this matrix in memory.
stride() const403   OrdinalType stride() const { return(stride_); }
404 
405   //! Returns whether this matrix is empty.
empty() const406   bool empty() const { return(numRows_ == 0 || numCols_ == 0); }
407   //@}
408 
409   //! @name Norm methods.
410   //@{
411 
412   //! Returns the 1-norm of the matrix.
413   typename ScalarTraits<ScalarType>::magnitudeType normOne() const;
414 
415   //! Returns the Infinity-norm of the matrix.
416   typename ScalarTraits<ScalarType>::magnitudeType normInf() const;
417 
418   //! Returns the Frobenius-norm of the matrix.
419   typename ScalarTraits<ScalarType>::magnitudeType normFrobenius() const;
420   //@}
421 
422   //! @name I/O methods.
423   //@{
424   //! Print method.  Defines the behavior of the std::ostream << operator
425 
426   virtual std::ostream& print(std::ostream& os) const;
427 
428 
429   //@}
430 protected:
431   void copyMat(ScalarType* inputMatrix, OrdinalType strideInput,
432     OrdinalType numRows, OrdinalType numCols, ScalarType* outputMatrix,
433     OrdinalType strideOutput, OrdinalType startCol, ScalarType alpha = ScalarTraits<ScalarType>::zero() );
434   void deleteArrays();
435   void checkIndex( OrdinalType rowIndex, OrdinalType colIndex = 0 ) const;
436   OrdinalType numRows_;
437   OrdinalType numCols_;
438   OrdinalType stride_;
439   OrdinalType kl_;
440   OrdinalType ku_;
441   bool valuesCopied_;
442   ScalarType* values_;
443 
444 }; // class Teuchos_SerialBandDenseMatrix
445 
446 //----------------------------------------------------------------------------------------------------
447 //  Constructors and Destructor
448 //----------------------------------------------------------------------------------------------------
449 
450 template<typename OrdinalType, typename ScalarType>
SerialBandDenseMatrix()451 SerialBandDenseMatrix<OrdinalType, ScalarType>::SerialBandDenseMatrix ()
452   : CompObject (),
453     BLAS<OrdinalType,ScalarType>(),
454     numRows_ (0),
455     numCols_ (0),
456     stride_ (0),
457     kl_ (0),
458     ku_ (0),
459     valuesCopied_ (false),
460     values_ (0)
461 {}
462 
463 template<typename OrdinalType, typename ScalarType>
464 SerialBandDenseMatrix<OrdinalType, ScalarType>::
SerialBandDenseMatrix(OrdinalType numRows_in,OrdinalType numCols_in,OrdinalType kl_in,OrdinalType ku_in,bool zeroOut)465 SerialBandDenseMatrix (OrdinalType numRows_in,
466                        OrdinalType numCols_in,
467                        OrdinalType kl_in,
468                        OrdinalType ku_in,
469                        bool zeroOut)
470   : CompObject (),
471     BLAS<OrdinalType,ScalarType>(),
472     numRows_ (numRows_in),
473     numCols_ (numCols_in),
474     stride_ (kl_in+ku_in+1),
475     kl_ (kl_in),
476     ku_ (ku_in),
477     valuesCopied_ (true),
478     values_ (NULL) // for safety, in case allocation fails below
479 {
480   values_ = new ScalarType[stride_ * numCols_];
481   if (zeroOut) {
482     putScalar ();
483   }
484 }
485 
486 template<typename OrdinalType, typename ScalarType>
487 SerialBandDenseMatrix<OrdinalType, ScalarType>::
SerialBandDenseMatrix(DataAccess CV,ScalarType * values_in,OrdinalType stride_in,OrdinalType numRows_in,OrdinalType numCols_in,OrdinalType kl_in,OrdinalType ku_in)488 SerialBandDenseMatrix (DataAccess CV,
489                        ScalarType* values_in,
490                        OrdinalType stride_in,
491                        OrdinalType numRows_in,
492                        OrdinalType numCols_in,
493                        OrdinalType kl_in,
494                        OrdinalType ku_in)
495   : CompObject (),
496     BLAS<OrdinalType,ScalarType>(),
497     numRows_ (numRows_in),
498     numCols_ (numCols_in),
499     stride_ (stride_in),
500     kl_ (kl_in),
501     ku_ (ku_in),
502     valuesCopied_ (false),
503     values_ (values_in)
504 {
505   if (CV == Copy) {
506     stride_ = kl_+ku_+1;
507     values_ = new ScalarType[stride_*numCols_];
508     copyMat (values_in, stride_in, numRows_, numCols_, values_, stride_, 0);
509     valuesCopied_ = true;
510   }
511 }
512 
513 template<typename OrdinalType, typename ScalarType>
514 SerialBandDenseMatrix<OrdinalType, ScalarType>::
SerialBandDenseMatrix(const SerialBandDenseMatrix<OrdinalType,ScalarType> & Source,ETransp trans)515 SerialBandDenseMatrix (const SerialBandDenseMatrix<OrdinalType, ScalarType> &Source, ETransp trans)
516   : CompObject (),
517     BLAS<OrdinalType,ScalarType>(),
518     numRows_ (0),
519     numCols_ (0),
520     stride_ (0),
521     kl_ (0),
522     ku_ (0),
523     valuesCopied_ (true),
524     values_ (NULL)
525 {
526   if (trans == NO_TRANS) {
527     numRows_ = Source.numRows_;
528     numCols_ = Source.numCols_;
529     kl_ = Source.kl_;
530     ku_ = Source.ku_;
531     stride_ = kl_+ku_+1;
532     values_ = new ScalarType[stride_*numCols_];
533     copyMat (Source.values_, Source.stride_, numRows_, numCols_,
534              values_, stride_, 0);
535   }
536   else if (trans == CONJ_TRANS && ScalarTraits<ScalarType>::isComplex) {
537     numRows_ = Source.numCols_;
538     numCols_ = Source.numRows_;
539     kl_ = Source.ku_;
540     ku_ = Source.kl_;
541     stride_ = kl_+ku_+1;
542     values_ = new ScalarType[stride_*numCols_];
543     for (OrdinalType j = 0; j < numCols_; ++j) {
544       for (OrdinalType i = TEUCHOS_MAX(0,j-ku_);
545            i <= TEUCHOS_MIN(numRows_-1,j+kl_); ++i) {
546         values_[j*stride_ + (ku_+i-j)] =
547           ScalarTraits<ScalarType>::conjugate (Source.values_[i*Source.stride_ + (Source.ku_+j-i)]);
548       }
549     }
550   }
551   else {
552     numRows_ = Source.numCols_;
553     numCols_ = Source.numRows_;
554     kl_ = Source.ku_;
555     ku_ = Source.kl_;
556     stride_ = kl_+ku_+1;
557     values_ = new ScalarType[stride_*numCols_];
558     for (OrdinalType j=0; j<numCols_; j++) {
559       for (OrdinalType i = TEUCHOS_MAX(0,j-ku_);
560            i <= TEUCHOS_MIN(numRows_-1,j+kl_); ++i) {
561         values_[j*stride_ + (ku_+i-j)] = Source.values_[i*Source.stride_ + (Source.ku_+j-i)];
562       }
563     }
564   }
565 }
566 
567 template<typename OrdinalType, typename ScalarType>
568 SerialBandDenseMatrix<OrdinalType, ScalarType>::
SerialBandDenseMatrix(DataAccess CV,const SerialBandDenseMatrix<OrdinalType,ScalarType> & Source,OrdinalType numRows_in,OrdinalType numCols_in,OrdinalType startCol)569 SerialBandDenseMatrix (DataAccess CV,
570                        const SerialBandDenseMatrix<OrdinalType, ScalarType> &Source,
571                        OrdinalType numRows_in,
572                        OrdinalType numCols_in,
573                        OrdinalType startCol)
574   : CompObject (),
575     BLAS<OrdinalType,ScalarType>(),
576     numRows_ (numRows_in),
577     numCols_ (numCols_in),
578     stride_ (Source.stride_),
579     kl_ (Source.kl_),
580     ku_ (Source.ku_),
581     valuesCopied_ (false),
582     values_ (Source.values_)
583 {
584   if (CV == Copy) {
585     values_ = new ScalarType[stride_ * numCols_in];
586     copyMat (Source.values_, Source.stride_, numRows_in, numCols_in,
587              values_, stride_, startCol);
588     valuesCopied_ = true;
589   } else { // CV = View
590     values_ = values_ + (stride_ * startCol);
591   }
592 }
593 
594 template<typename OrdinalType, typename ScalarType>
~SerialBandDenseMatrix()595 SerialBandDenseMatrix<OrdinalType, ScalarType>::~SerialBandDenseMatrix()
596 {
597   deleteArrays();
598 }
599 
600 //----------------------------------------------------------------------------------------------------
601 //  Shape methods
602 //----------------------------------------------------------------------------------------------------
603 
604 template<typename OrdinalType, typename ScalarType>
shape(OrdinalType numRows_in,OrdinalType numCols_in,OrdinalType kl_in,OrdinalType ku_in)605 int SerialBandDenseMatrix<OrdinalType, ScalarType>::shape(
606   OrdinalType numRows_in, OrdinalType numCols_in, OrdinalType kl_in, OrdinalType ku_in
607   )
608 {
609   deleteArrays(); // Get rid of anything that might be already allocated
610   numRows_ = numRows_in;
611   numCols_ = numCols_in;
612   kl_ = kl_in;
613   ku_ = ku_in;
614   stride_ = kl_+ku_+1;
615   values_ = new ScalarType[stride_*numCols_];
616   putScalar();
617   valuesCopied_ = true;
618 
619   return(0);
620 }
621 
622 template<typename OrdinalType, typename ScalarType>
shapeUninitialized(OrdinalType numRows_in,OrdinalType numCols_in,OrdinalType kl_in,OrdinalType ku_in)623 int SerialBandDenseMatrix<OrdinalType, ScalarType>::shapeUninitialized(
624   OrdinalType numRows_in, OrdinalType numCols_in, OrdinalType kl_in, OrdinalType ku_in
625   )
626 {
627   deleteArrays(); // Get rid of anything that might be already allocated
628   numRows_ = numRows_in;
629   numCols_ = numCols_in;
630   kl_ = kl_in;
631   ku_ = ku_in;
632   stride_ = kl_+ku_+1;
633   values_ = new ScalarType[stride_*numCols_];
634   valuesCopied_ = true;
635 
636   return(0);
637 }
638 
639 template<typename OrdinalType, typename ScalarType>
reshape(OrdinalType numRows_in,OrdinalType numCols_in,OrdinalType kl_in,OrdinalType ku_in)640 int SerialBandDenseMatrix<OrdinalType, ScalarType>::reshape(
641   OrdinalType numRows_in, OrdinalType numCols_in, OrdinalType kl_in, OrdinalType ku_in
642   )
643 {
644 
645   // Allocate space for new matrix
646   ScalarType* values_tmp = new ScalarType[(kl_in+ku_in+1) * numCols_in];
647   ScalarType zero = ScalarTraits<ScalarType>::zero();
648   for(OrdinalType k = 0; k < (kl_in+ku_in+1) * numCols_in; k++) {
649     values_tmp[k] = zero;
650   }
651   OrdinalType numRows_tmp = TEUCHOS_MIN(numRows_, numRows_in);
652   OrdinalType numCols_tmp = TEUCHOS_MIN(numCols_, numCols_in);
653   if(values_ != 0) {
654     copyMat(values_, stride_, numRows_tmp, numCols_tmp, values_tmp,
655             kl_in+ku_in+1, 0); // Copy principal submatrix of A to new A
656   }
657   deleteArrays(); // Get rid of anything that might be already allocated
658   numRows_ = numRows_in;
659   numCols_ = numCols_in;
660   kl_ = kl_in;
661   ku_ = ku_in;
662   stride_ = kl_+ku_+1;
663   values_ = values_tmp; // Set pointer to new A
664   valuesCopied_ = true;
665 
666   return(0);
667 }
668 
669 //----------------------------------------------------------------------------------------------------
670 //   Set methods
671 //----------------------------------------------------------------------------------------------------
672 
673 template<typename OrdinalType, typename ScalarType>
putScalar(const ScalarType value_in)674 int SerialBandDenseMatrix<OrdinalType, ScalarType>::putScalar( const ScalarType value_in )
675 {
676 
677   // Set each value of the dense matrix to "value".
678   for(OrdinalType j = 0; j < numCols_; j++) {
679     for (OrdinalType i=TEUCHOS_MAX(0,j-ku_); i<=TEUCHOS_MIN(numRows_-1,j+kl_); i++) {
680       values_[(ku_+i-j) + j*stride_] = value_in;
681     }
682   }
683 
684   return 0;
685 }
686 
687 template<typename OrdinalType, typename ScalarType>
random()688 int SerialBandDenseMatrix<OrdinalType, ScalarType>::random()
689 {
690 
691   // Set each value of the dense matrix to a random value.
692   for(OrdinalType j = 0; j < numCols_; j++) {
693     for (OrdinalType i=TEUCHOS_MAX(0,j-ku_); i<=TEUCHOS_MIN(numRows_-1,j+kl_); i++) {
694       values_[(ku_+i-j) + j*stride_] = ScalarTraits<ScalarType>::random();
695     }
696   }
697 
698   return 0;
699 }
700 
701 template<typename OrdinalType, typename ScalarType>
702 SerialBandDenseMatrix<OrdinalType,ScalarType>&
operator =(const SerialBandDenseMatrix<OrdinalType,ScalarType> & Source)703 SerialBandDenseMatrix<OrdinalType, ScalarType>::operator=(
704   const SerialBandDenseMatrix<OrdinalType,ScalarType>& Source
705   )
706 {
707 
708   if(this == &Source)
709     return(*this); // Special case of source same as target
710   if((!valuesCopied_) && (!Source.valuesCopied_) && (values_ == Source.values_))
711     return(*this); // Special case of both are views to same data.
712 
713   // If the source is a view then we will return a view, else we will return a copy.
714   if (!Source.valuesCopied_) {
715     if(valuesCopied_) {
716       // Clean up stored data if this was previously a copy.
717       deleteArrays();
718     }
719     numRows_ = Source.numRows_;
720     numCols_ = Source.numCols_;
721     kl_ = Source.kl_;
722     ku_ = Source.ku_;
723     stride_ = Source.stride_;
724     values_ = Source.values_;
725   } else {
726     // If we were a view, we will now be a copy.
727     if(!valuesCopied_) {
728       numRows_ = Source.numRows_;
729       numCols_ = Source.numCols_;
730       kl_ = Source.kl_;
731       ku_ = Source.ku_;
732       stride_ = kl_+ku_+1;
733       const OrdinalType newsize = stride_ * numCols_;
734       if(newsize > 0) {
735         values_ = new ScalarType[newsize];
736         valuesCopied_ = true;
737       } else {
738         values_ = 0;
739       }
740     } else {
741       // If we were a copy, we will stay a copy.
742       if((Source.numRows_ <= stride_) && (Source.numCols_ == numCols_)) { // we don't need to reallocate
743         numRows_ = Source.numRows_;
744         numCols_ = Source.numCols_;
745         kl_ = Source.kl_;
746         ku_ = Source.ku_;
747       } else {
748         // we need to allocate more space (or less space)
749         deleteArrays();
750         numRows_ = Source.numRows_;
751         numCols_ = Source.numCols_;
752         kl_ = Source.kl_;
753         ku_ = Source.ku_;
754         stride_ = kl_+ku_+1;
755         const OrdinalType newsize = stride_ * numCols_;
756         if(newsize > 0) {
757           values_ = new ScalarType[newsize];
758           valuesCopied_ = true;
759         }
760       }
761     }
762     copyMat(Source.values_, Source.stride_, numRows_, numCols_, values_, stride_, 0);
763   }
764   return(*this);
765 
766 }
767 
768 template<typename OrdinalType, typename ScalarType>
operator +=(const SerialBandDenseMatrix<OrdinalType,ScalarType> & Source)769 SerialBandDenseMatrix<OrdinalType, ScalarType>& SerialBandDenseMatrix<OrdinalType, ScalarType>::operator+= (const SerialBandDenseMatrix<OrdinalType,ScalarType>& Source )
770 {
771 
772   // Check for compatible dimensions
773   if ((numRows_ != Source.numRows_) || (numCols_ != Source.numCols_) || (kl_ != Source.kl_) || (ku_ != Source.ku_)) {
774     TEUCHOS_CHK_REF(*this); // Return *this without altering it.
775   }
776   copyMat(Source.values_, Source.stride_, numRows_, numCols_, values_, stride_, 0, ScalarTraits<ScalarType>::one());
777   return(*this);
778 
779 }
780 
781 template<typename OrdinalType, typename ScalarType>
operator -=(const SerialBandDenseMatrix<OrdinalType,ScalarType> & Source)782 SerialBandDenseMatrix<OrdinalType, ScalarType>& SerialBandDenseMatrix<OrdinalType, ScalarType>::operator-= (const SerialBandDenseMatrix<OrdinalType,ScalarType>& Source )
783 {
784 
785   // Check for compatible dimensions
786   if ((numRows_ != Source.numRows_) || (numCols_ != Source.numCols_) || (kl_ != Source.kl_) || (ku_ != Source.ku_)) {
787     TEUCHOS_CHK_REF(*this); // Return *this without altering it.
788   }
789   copyMat(Source.values_, Source.stride_, numRows_, numCols_, values_, stride_, 0, -ScalarTraits<ScalarType>::one());
790   return(*this);
791 
792 }
793 
794 template<typename OrdinalType, typename ScalarType>
assign(const SerialBandDenseMatrix<OrdinalType,ScalarType> & Source)795 SerialBandDenseMatrix<OrdinalType,ScalarType>& SerialBandDenseMatrix<OrdinalType, ScalarType>::assign (const SerialBandDenseMatrix<OrdinalType,ScalarType>& Source) {
796 
797   if(this == &Source)
798     return(*this); // Special case of source same as target
799   if((!valuesCopied_) && (!Source.valuesCopied_) && (values_ == Source.values_))
800     return(*this); // Special case of both are views to same data.
801 
802   // Check for compatible dimensions
803   if ((numRows_ != Source.numRows_) || (numCols_ != Source.numCols_) || (kl_ != Source.kl_) || (ku_ != Source.ku_)) {
804     TEUCHOS_CHK_REF(*this); // Return *this without altering it.
805   }
806   copyMat(Source.values_, Source.stride_, numRows_, numCols_, values_, stride_, 0);
807   return(*this);
808 
809 }
810 
811 //----------------------------------------------------------------------------------------------------
812 //   Accessor methods
813 //----------------------------------------------------------------------------------------------------
814 
815 template<typename OrdinalType, typename ScalarType>
operator ()(OrdinalType rowIndex,OrdinalType colIndex)816 inline ScalarType& SerialBandDenseMatrix<OrdinalType, ScalarType>::operator () (OrdinalType rowIndex, OrdinalType colIndex)
817 {
818 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
819   checkIndex( rowIndex, colIndex );
820 #endif
821   return(values_[colIndex * stride_ + ku_+rowIndex-colIndex]);
822 }
823 
824 template<typename OrdinalType, typename ScalarType>
operator ()(OrdinalType rowIndex,OrdinalType colIndex) const825 inline const ScalarType& SerialBandDenseMatrix<OrdinalType, ScalarType>::operator () (OrdinalType rowIndex, OrdinalType colIndex) const
826 {
827 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
828   checkIndex( rowIndex, colIndex );
829 #endif
830   return(values_[colIndex * stride_ + ku_+rowIndex-colIndex]);
831 }
832 
833 template<typename OrdinalType, typename ScalarType>
operator [](OrdinalType colIndex) const834 inline const ScalarType* SerialBandDenseMatrix<OrdinalType, ScalarType>::operator [] (OrdinalType colIndex) const
835 {
836 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
837   checkIndex( 0, colIndex );
838 #endif
839   return(values_ + colIndex * stride_);
840 }
841 
842 template<typename OrdinalType, typename ScalarType>
operator [](OrdinalType colIndex)843 inline ScalarType* SerialBandDenseMatrix<OrdinalType, ScalarType>::operator [] (OrdinalType colIndex)
844 {
845 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
846   checkIndex( 0, colIndex );
847 #endif
848   return(values_ + colIndex * stride_);
849 }
850 
851 //----------------------------------------------------------------------------------------------------
852 //   Norm methods
853 //----------------------------------------------------------------------------------------------------
854 
855 template<typename OrdinalType, typename ScalarType>
normOne() const856 typename ScalarTraits<ScalarType>::magnitudeType SerialBandDenseMatrix<OrdinalType, ScalarType>::normOne() const
857 {
858   OrdinalType i, j;
859   typename ScalarTraits<ScalarType>::magnitudeType anorm = ScalarTraits<ScalarType>::magnitude(ScalarTraits<ScalarType>::zero());
860   typename ScalarTraits<ScalarType>::magnitudeType absSum = ScalarTraits<ScalarType>::magnitude(ScalarTraits<ScalarType>::zero());
861 
862   ScalarType* ptr;
863   for(j = 0; j < numCols_; j++) {
864     ScalarType sum = 0;
865     ptr = values_ + j * stride_ + TEUCHOS_MAX(0, ku_-j);
866     for (i=TEUCHOS_MAX(0,j-ku_); i<=TEUCHOS_MIN(numRows_-1,j+kl_); i++) {
867       sum += ScalarTraits<ScalarType>::magnitude(*ptr++);
868     }
869     absSum = ScalarTraits<ScalarType>::magnitude(sum);
870     if(absSum > anorm) {
871       anorm = absSum;
872     }
873   }
874   updateFlops((kl_+ku_+1) * numCols_);
875 
876   return(anorm);
877 }
878 
879 template<typename OrdinalType, typename ScalarType>
normInf() const880 typename ScalarTraits<ScalarType>::magnitudeType SerialBandDenseMatrix<OrdinalType, ScalarType>::normInf() const
881 {
882   OrdinalType i, j;
883   typename ScalarTraits<ScalarType>::magnitudeType sum, anorm = ScalarTraits<ScalarType>::magnitude(ScalarTraits<ScalarType>::zero());
884 
885   for (i = 0; i < numRows_; i++) {
886     sum = ScalarTraits<ScalarType>::magnitude(ScalarTraits<ScalarType>::zero());
887     for (j=TEUCHOS_MAX(0,i-kl_); j<=TEUCHOS_MIN(numCols_-1,i+ku_); j++) {
888       sum += ScalarTraits<ScalarType>::magnitude(*(values_+(ku_+i-j)+j*stride_));
889     }
890     anorm = TEUCHOS_MAX( anorm, sum );
891   }
892   updateFlops((kl_+ku_+1) * numCols_);
893 
894   return(anorm);
895 }
896 
897 template<typename OrdinalType, typename ScalarType>
normFrobenius() const898 typename ScalarTraits<ScalarType>::magnitudeType SerialBandDenseMatrix<OrdinalType, ScalarType>::normFrobenius() const
899 {
900   OrdinalType i, j;
901   typename ScalarTraits<ScalarType>::magnitudeType anorm = ScalarTraits<ScalarType>::magnitude(ScalarTraits<ScalarType>::zero());
902 
903   for (j = 0; j < numCols_; j++) {
904     for (i=TEUCHOS_MAX(0,j-ku_); i<=TEUCHOS_MIN(numRows_-1,j+kl_); i++) {
905       anorm += ScalarTraits<ScalarType>::magnitude(values_[(ku_+i-j)+j*stride_]*values_[(ku_+i-j)+j*stride_]);
906     }
907   }
908   anorm = ScalarTraits<ScalarType>::magnitude(ScalarTraits<ScalarType>::squareroot(anorm));
909   updateFlops((kl_+ku_+1) * numCols_);
910 
911   return(anorm);
912 }
913 
914 //----------------------------------------------------------------------------------------------------
915 //   Comparison methods
916 //----------------------------------------------------------------------------------------------------
917 
918 template<typename OrdinalType, typename ScalarType>
operator ==(const SerialBandDenseMatrix<OrdinalType,ScalarType> & Operand) const919 bool SerialBandDenseMatrix<OrdinalType, ScalarType>::operator== (const SerialBandDenseMatrix<OrdinalType, ScalarType> &Operand) const
920 {
921   bool result = 1;
922 
923   if((numRows_ != Operand.numRows_) || (numCols_ != Operand.numCols_) || (kl_ != Operand.kl_) || (ku_ != Operand.ku_)) {
924     result = 0;
925   } else {
926     OrdinalType i, j;
927     for(j = 0; j < numCols_; j++) {
928       for (i=TEUCHOS_MAX(0,j-ku_); i<=TEUCHOS_MIN(numRows_-1,j+kl_); i++) {
929         if((*this)(i, j) != Operand(i, j)) {
930           return 0;
931         }
932       }
933     }
934   }
935 
936   return result;
937 }
938 
939 template<typename OrdinalType, typename ScalarType>
operator !=(const SerialBandDenseMatrix<OrdinalType,ScalarType> & Operand) const940 bool SerialBandDenseMatrix<OrdinalType, ScalarType>::operator!= (const SerialBandDenseMatrix<OrdinalType, ScalarType> &Operand) const
941 {
942   return !((*this) == Operand);
943 }
944 
945 //----------------------------------------------------------------------------------------------------
946 //   Multiplication method
947 //----------------------------------------------------------------------------------------------------
948 
949 template<typename OrdinalType, typename ScalarType>
operator *=(const ScalarType alpha)950 SerialBandDenseMatrix<OrdinalType, ScalarType>& SerialBandDenseMatrix<OrdinalType, ScalarType>::operator*= (const ScalarType alpha )
951 {
952   this->scale( alpha );
953   return(*this);
954 }
955 
956 template<typename OrdinalType, typename ScalarType>
scale(const ScalarType alpha)957 int SerialBandDenseMatrix<OrdinalType, ScalarType>::scale( const ScalarType alpha )
958 {
959 
960   OrdinalType i, j;
961   ScalarType* ptr;
962 
963   for (j=0; j<numCols_; j++) {
964     ptr = values_ + j*stride_ + TEUCHOS_MAX(0, ku_-j);
965     for (i=TEUCHOS_MAX(0,j-ku_); i<=TEUCHOS_MIN(numRows_-1,j+kl_); i++) {
966       *ptr = alpha * (*ptr); ptr++;
967     }
968   }
969   updateFlops( (kl_+ku_+1)*numCols_ );
970 
971   return(0);
972 }
973 
974 template<typename OrdinalType, typename ScalarType>
scale(const SerialBandDenseMatrix<OrdinalType,ScalarType> & A)975 int SerialBandDenseMatrix<OrdinalType, ScalarType>::scale( const SerialBandDenseMatrix<OrdinalType,ScalarType>& A )
976 {
977 
978   OrdinalType i, j;
979   ScalarType* ptr;
980 
981   // Check for compatible dimensions
982   if ((numRows_ != A.numRows_) || (numCols_ != A.numCols_) || (kl_ != A.kl_) || (ku_ != A.ku_)) {
983     TEUCHOS_CHK_ERR(-1); // Return error
984   }
985   for (j=0; j<numCols_; j++) {
986     ptr = values_ + j*stride_ + TEUCHOS_MAX(0, ku_-j);
987     for (i=TEUCHOS_MAX(0,j-ku_); i<=TEUCHOS_MIN(numRows_-1,j+kl_); i++) {
988       *ptr = A(i,j) * (*ptr); ptr++;
989     }
990   }
991   updateFlops( (kl_+ku_+1)*numCols_ );
992 
993   return(0);
994 }
995 
996 template<typename OrdinalType, typename ScalarType>
print(std::ostream & os) const997 std::ostream& SerialBandDenseMatrix<OrdinalType, ScalarType>::print(std::ostream& os) const
998 {
999   os << std::endl;
1000   if(valuesCopied_)
1001     os << "Values_copied : yes" << std::endl;
1002   else
1003     os << "Values_copied : no" << std::endl;
1004   os << "Rows : " << numRows_ << std::endl;
1005   os << "Columns : " << numCols_ << std::endl;
1006   os << "Lower Bandwidth : " << kl_ << std::endl;
1007   os << "Upper Bandwidth : " << ku_ << std::endl;
1008   os << "LDA : " << stride_ << std::endl;
1009   if(numRows_ == 0 || numCols_ == 0) {
1010     os << "(matrix is empty, no values to display)" << std::endl;
1011   } else {
1012 
1013     for(OrdinalType i = 0; i < numRows_; i++) {
1014       for (OrdinalType j=TEUCHOS_MAX(0,i-kl_); j<=TEUCHOS_MIN(numCols_-1,i+ku_); j++) {
1015         os << (*this)(i,j) << " ";
1016       }
1017       os << std::endl;
1018     }
1019   }
1020   return os;
1021 }
1022 
1023 //----------------------------------------------------------------------------------------------------
1024 //   Protected methods
1025 //----------------------------------------------------------------------------------------------------
1026 
1027 template<typename OrdinalType, typename ScalarType>
checkIndex(OrdinalType rowIndex,OrdinalType colIndex) const1028 inline void SerialBandDenseMatrix<OrdinalType, ScalarType>::checkIndex( OrdinalType rowIndex, OrdinalType colIndex ) const {
1029 
1030   TEUCHOS_TEST_FOR_EXCEPTION(rowIndex < 0 || rowIndex >= numRows_ ||
1031                              rowIndex < TEUCHOS_MAX(0,colIndex-ku_) || rowIndex > TEUCHOS_MIN(numRows_-1,colIndex+kl_),
1032                              std::out_of_range,
1033                              "SerialBandDenseMatrix<T>::checkIndex: "
1034                              "Row index " << rowIndex << " out of range [0, "<< numRows_ << ")");
1035   TEUCHOS_TEST_FOR_EXCEPTION(colIndex < 0 || colIndex >= numCols_, std::out_of_range,
1036                              "SerialBandDenseMatrix<T>::checkIndex: "
1037                              "Col index " << colIndex << " out of range [0, "<< numCols_ << ")");
1038 
1039 }
1040 
1041 template<typename OrdinalType, typename ScalarType>
deleteArrays(void)1042 void SerialBandDenseMatrix<OrdinalType, ScalarType>::deleteArrays(void)
1043 {
1044   if (valuesCopied_) {
1045     delete [] values_;
1046     values_ = 0;
1047     valuesCopied_ = false;
1048   }
1049 }
1050 
1051 template<typename OrdinalType, typename ScalarType>
copyMat(ScalarType * inputMatrix,OrdinalType strideInput,OrdinalType numRows_in,OrdinalType numCols_in,ScalarType * outputMatrix,OrdinalType strideOutput,OrdinalType startCol,ScalarType alpha)1052 void SerialBandDenseMatrix<OrdinalType, ScalarType>::copyMat(
1053   ScalarType* inputMatrix, OrdinalType strideInput, OrdinalType numRows_in,
1054   OrdinalType numCols_in, ScalarType* outputMatrix, OrdinalType strideOutput, OrdinalType startCol, ScalarType alpha
1055   )
1056 {
1057   OrdinalType i, j;
1058   ScalarType* ptr1 = 0;
1059   ScalarType* ptr2 = 0;
1060 
1061   for(j = 0; j < numCols_in; j++) {
1062     ptr1 = outputMatrix + (j * strideOutput) + TEUCHOS_MAX(0, ku_-j);
1063     ptr2 = inputMatrix + (j + startCol) * strideInput + TEUCHOS_MAX(0, ku_-j);
1064     if (alpha != Teuchos::ScalarTraits<ScalarType>::zero() ) {
1065       for (i=TEUCHOS_MAX(0,j-ku_); i<=TEUCHOS_MIN(numRows_in-1,j+kl_); i++) {
1066         *ptr1++ += alpha*(*ptr2++);
1067       }
1068     } else {
1069       for (i=TEUCHOS_MAX(0,j-ku_); i<=TEUCHOS_MIN(numRows_in-1,j+kl_); i++) {
1070         *ptr1++ = *ptr2++;
1071       }
1072     }
1073   }
1074 }
1075 
1076 /// \brief Ostream manipulator for SerialBandDenseMatrix
1077 template<typename OrdinalType, typename ScalarType>
1078 struct SerialBandDenseMatrixPrinter {
1079 public:
1080   const SerialBandDenseMatrix<OrdinalType,ScalarType> &obj;
SerialBandDenseMatrixPrinterTeuchos::SerialBandDenseMatrixPrinter1081   SerialBandDenseMatrixPrinter(
1082         const SerialBandDenseMatrix<OrdinalType,ScalarType> &obj_in)
1083       : obj(obj_in) {}
1084 };
1085 
1086 /// \brief Output SerialBandDenseMatrix object through its stream manipulator.
1087 template<typename OrdinalType, typename ScalarType>
1088 std::ostream&
operator <<(std::ostream & out,const SerialBandDenseMatrixPrinter<OrdinalType,ScalarType> printer)1089 operator<<(std::ostream &out,
1090            const SerialBandDenseMatrixPrinter<OrdinalType,ScalarType> printer)
1091 {
1092   printer.obj.print(out);
1093   return out;
1094 }
1095 
1096 /// \brief Return SerialBandDenseMatrix ostream manipulator Use as:
1097 template<typename OrdinalType, typename ScalarType>
1098 SerialBandDenseMatrixPrinter<OrdinalType,ScalarType>
printMat(const SerialBandDenseMatrix<OrdinalType,ScalarType> & obj)1099 printMat(const SerialBandDenseMatrix<OrdinalType,ScalarType> &obj)
1100 {
1101   return SerialBandDenseMatrixPrinter<OrdinalType,ScalarType>(obj);
1102 }
1103 
1104 
1105 } // namespace Teuchos
1106 
1107 
1108 #endif /* _TEUCHOS_SERIALBANDDENSEMATRIX_HPP_ */
1109