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 // ***********************************************************************
38 // @HEADER
39 
40 #ifndef _TEUCHOS_SERIALDENSEMATRIX_HPP_
41 #define _TEUCHOS_SERIALDENSEMATRIX_HPP_
42 /*! \file Teuchos_SerialDenseMatrix.hpp
43   \brief Templated serial dense matrix class
44 */
45 
46 #include "Teuchos_CompObject.hpp"
47 #include "Teuchos_BLAS.hpp"
48 #include "Teuchos_ScalarTraits.hpp"
49 #include "Teuchos_DataAccess.hpp"
50 #include "Teuchos_ConfigDefs.hpp"
51 #include "Teuchos_Assert.hpp"
52 #include "Teuchos_SerialSymDenseMatrix.hpp"
53 #include <cstddef>
54 #include <utility>
55 
56 /*!     \class Teuchos::SerialDenseMatrix
57         \brief This class creates and provides basic support for dense rectangular matrix of templated type.
58 */
59 /** \example DenseMatrix/cxx_main.cpp
60     This is an example of how to use the Teuchos::SerialDenseMatrix class.
61 */
62 
63 
64 namespace Teuchos {
65 
66 template<typename OrdinalType, typename ScalarType>
67 class SerialDenseMatrix : public CompObject, public BLAS<OrdinalType, ScalarType>
68 {
69 public:
70 
71   //! Typedef for ordinal type
72   typedef OrdinalType ordinalType;
73   //! Typedef for scalar type
74   typedef ScalarType scalarType;
75 
76   //! @name Constructor/Destructor methods.
77   //@{
78 
79   //! Default Constructor
80   /*! Creates a empty matrix of no dimension.  The Shaping methods should be used to size this matrix.
81     Values of this matrix should be set using the [], (), or = operators.
82   */
83   SerialDenseMatrix() = default;
84 
85   //! Shaped Constructor
86   /*!
87     \param numRows - Number of rows in matrix.
88     \param numCols - Number of columns in matrix.
89     \param zeroOut - Initializes values to 0 if true (default)
90 
91     Creates a shaped matrix with \c numRows rows and \c numCols cols.  All values are initialized to 0 when \c zeroOut is true.
92     Values of this matrix should be set using the [] or the () operators.
93   */
94   SerialDenseMatrix(OrdinalType numRows, OrdinalType numCols, bool zeroOut = true);
95 
96   //! Shaped Constructor with Values
97   /*!
98     \param CV - Enumerated type set to Teuchos::Copy or Teuchos::View.
99     \param values - Pointer to an array of ScalarType.  The first column starts at \c values,
100                 the second at \c values+stride, etc.
101     \param stride - The stride between the columns of the matrix in memory.
102     \param numRows - Number of rows in matrix.
103     \param numCols - Number of columns in matrix.
104   */
105   SerialDenseMatrix(DataAccess CV, ScalarType* values, OrdinalType stride, OrdinalType numRows, OrdinalType numCols);
106 
107   //! Copy Constructor
108   /*! \note A deep copy of the \c Source transposed can be obtained if \c trans=Teuchos::TRANS, \c else
109     a non-transposed copy of \c Source is made.  There is no storage of the transpose state of the matrix
110     within the SerialDenseMatrix class, so this information will not propogate to any operation performed
111     on a matrix that has been copy constructed in transpose.
112   */
113   SerialDenseMatrix(const SerialDenseMatrix<OrdinalType, ScalarType> &Source, ETransp trans = Teuchos::NO_TRANS);
114 
115   //! Copy Constructor
116   /*! \note Only a non-transposed deep copy or view of \c Source is made with this copy constructor.
117   */
118   SerialDenseMatrix(DataAccess CV, const SerialDenseMatrix<OrdinalType, ScalarType> &Source);
119 
120   //! Submatrix Copy Constructor
121   /*!
122     \param CV - Enumerated type set to Teuchos::Copy or Teuchos::View.
123     \param Source - Reference to another dense matrix from which values are to be copied.
124     \param numRows - The number of rows in this matrix.
125     \param numCols - The number of columns in this matrix.
126     \param startRow - The row of \c Source from which the submatrix copy should start.
127     \param startCol - The column of \c Source from which the submatrix copy should start.
128 
129     Creates a shaped matrix with \c numRows rows and \c numCols columns, which is a submatrix of \c Source.
130     If \c startRow and \c startCol are not given, then the submatrix is the leading submatrix of \c Source.
131     Otherwise, the (1,1) entry in the copied matrix is the (\c startRow, \c startCol) entry of \c Source.
132   */
133   SerialDenseMatrix(DataAccess CV, const SerialDenseMatrix<OrdinalType, ScalarType> &Source, OrdinalType numRows, OrdinalType numCols, OrdinalType startRow=0, OrdinalType startCol=0);
134 
135   //! Destructor
136   virtual ~SerialDenseMatrix();
137   //@}
138 
139   //! @name Shaping methods.
140   //@{
141   //! Shape method for changing the size of a SerialDenseMatrix, initializing entries to zero.
142   /*!
143     \param numRows - The number of rows in this matrix.
144     \param numCols - The number of columns in this matrix.
145 
146     This method allows the user to define the dimensions of a SerialDenseMatrix at any point.  This method
147     can be called at any point after construction.  Any values previously in this object will be destroyed
148     and the resized matrix starts of with all zero values.
149 
150     \return Integer error code, set to 0 if successful.
151   */
152   int shape(OrdinalType numRows, OrdinalType numCols);
153 
154   //! Same as <tt>shape()</tt> except leaves uninitialized.
155   int shapeUninitialized(OrdinalType numRows, OrdinalType numCols);
156 
157   //! Reshaping method for changing the size of a SerialDenseMatrix, keeping the entries.
158   /*!
159     \param numRows - The number of rows in this matrix.
160     \param numCols - The number of columns in this matrix.
161 
162     This method allows the user to redefine the dimensions of a SerialDenseMatrix at any point.  This method
163     can be called at any point after construction.  Any values previously in this object will be copied into
164     the reshaped matrix.
165 
166     \return Integer error code, set 0 if successful.
167   */
168   int reshape(OrdinalType numRows, OrdinalType numCols);
169 
170 
171   //@}
172 
173   //! @name Set methods.
174   //@{
175 
176   //! Copies values from one matrix to another.
177   /*!
178     The operator= copies the values from one existing SerialDenseMatrix to another.
179     If \c Source is a view (i.e. CV = Teuchos::View), then this method will
180     return a view.  Otherwise, it will return a copy of \c Source.  \e this object
181     will be resized if it is not large enough to copy \c Source into.
182   */
183   SerialDenseMatrix<OrdinalType, ScalarType>& operator= (const SerialDenseMatrix<OrdinalType, ScalarType>& Source);
184 
185   //! Copies values from one matrix to another.
186   /*!
187     Copies the values from one existing SerialDenseMatrix to another
188     if the dimension of both matrices are the same.  If not, \e this matrix
189     will be returned unchanged.
190   */
191   SerialDenseMatrix<OrdinalType, ScalarType>& assign (const SerialDenseMatrix<OrdinalType, ScalarType>& Source);
192 
193   //! Set all values in the matrix to a constant value.
194   /*!
195     \param value - Value to use;
196   */
operator =(const ScalarType value)197   SerialDenseMatrix<OrdinalType, ScalarType>& operator= (const ScalarType value) { putScalar(value); return(*this); }
198 
199   //! Set all values in the matrix to a constant value.
200   /*!
201     \param value - Value to use; zero if none specified.
202     \return Integer error code, set to 0 if successful.
203   */
204   int putScalar( const ScalarType value = Teuchos::ScalarTraits<ScalarType>::zero() );
205 
206   //! Swap values between this matrix and incoming matrix.
207   /*!
208     Swaps pointers and associated state without copying the matrix data.
209   */
210   void swap (SerialDenseMatrix<OrdinalType, ScalarType> &B);
211 
212   //! Set all values in the matrix to be random numbers.
213   int random();
214 
215   //@}
216 
217   //! @name Accessor methods.
218   //@{
219 
220   //! Element access method (non-const).
221   /*! Returns the element in the ith row and jth column if A(i,j) is specified, the
222     expression A[j][i] will return the same element.
223 
224         \return Element from the specified \c rowIndex row and \c colIndex column.
225     \warning The validity of \c rowIndex and \c colIndex will only be checked if Teuchos is
226     configured with --enable-teuchos-abc.
227   */
228   ScalarType& operator () (OrdinalType rowIndex, OrdinalType colIndex);
229 
230   //! Element access method (const).
231   /*! Returns the element in the ith row and jth column if A(i,j) is specified, the expression
232     A[j][i] will return the same element.
233 
234         \return Element from the specified \c rowIndex row and \c colIndex column.
235     \warning The validity of \c rowIndex and \c colIndex will only be checked if Teuchos is
236     configured with --enable-teuchos-abc.
237   */
238   const ScalarType& operator () (OrdinalType rowIndex, OrdinalType colIndex) const;
239 
240   //! Column access method (non-const).
241   /*! Returns the pointer to the ScalarType array at the jth column if A[j] is specified, the expression
242     A[j][i] will return the same element as A(i,j).
243 
244     \return Pointer to the ScalarType array at the \c colIndex column ( \c values_+colIndex*stride_ ).
245   */
246   ScalarType* operator [] (OrdinalType colIndex);
247 
248   //! Column access method (const).
249   /*! Returns the pointer to the ScalarType array at the jth column if A[j] is specified, the expression
250     A[j][i] will return the same element as A(i,j).
251 
252     \return Pointer to the ScalarType array at the \c colIndex column ( \c values_+colIndex*stride_ ).
253   */
254   const ScalarType* operator [] (OrdinalType colIndex) const;
255 
256   //! Data array access method.
257   /*! \return Pointer to the ScalarType data array contained in the object. */
values() const258   ScalarType* values() const { return values_; }
259 
260   //@}
261 
262   //! @name Mathematical methods.
263   //@{
264 
265   //! Add another matrix to \e this matrix.
266   /*! Add \c Source to \e this if the dimension of both matrices are the same.  If not, \e this matrix
267     will be returned unchanged.
268   */
269   SerialDenseMatrix<OrdinalType, ScalarType>& operator+= (const SerialDenseMatrix<OrdinalType, ScalarType>& Source);
270 
271   //! Subtract another matrix from \e this matrix.
272   /*! Subtract \c Source from \e this if the dimension of both matrices are the same.  If not, \e this matrix
273     will be returned unchanged.
274   */
275   SerialDenseMatrix<OrdinalType, ScalarType>& operator-= (const SerialDenseMatrix<OrdinalType, ScalarType>& Source);
276 
277   //! Scale \c this matrix by \c alpha; \c *this = \c alpha*\c *this.
278   /*!
279     \param alpha Scalar to multiply \e this by.
280   */
281   SerialDenseMatrix<OrdinalType, ScalarType>& operator*= (const ScalarType alpha);
282 
283   //! Scale \c this matrix by \c alpha; \c *this = \c alpha*\c *this.
284   /*!
285     \param alpha Scalar to multiply \e this by.
286     \return Integer error code, set to 0 if successful.
287   */
288   int scale ( const ScalarType alpha );
289 
290   //! Point-wise scale \c this matrix by \c A; i.e. *this(i,j) *= A(i,j)
291   /*! The values of \c *this matrix will be point-wise scaled by the values in A.
292     If A and \c this matrix are not the same dimension \c this will be returned unchanged.
293 
294     \param B Teuchos::SerialDenseMatrix used to perform element-wise scaling of \e this.
295     \return Integer error code, set to 0 if successful.
296   */
297   int scale ( const SerialDenseMatrix<OrdinalType, ScalarType>& A );
298 
299   //! Multiply \c A * \c B and add them to \e this; \e this = \c beta * \e this + \c alpha*A*B.
300   /*!
301     \param transa - Use the transpose of \c A if transa = Teuchos::TRANS, else don't use the
302     transpose if transa = Teuchos::NO_TRANS.
303     \param transb - Use the transpose of \c B if transb = Teuchos::TRANS, else don't use the
304     transpose if transb = Teuchos::NO_TRANS.
305     \param alpha - The scaling factor for \c A * \c B.
306     \param A - SerialDenseMatrix
307     \param B - SerialDenseMatrix
308     \param beta - The scaling factor for \e this.
309 
310     If the matrices \c A and \c B are not of the right dimension, consistent with \e this, then \e this
311     matrix will not be altered and -1 will be returned.
312     \return Integer error code, set to 0 if successful.
313   */
314   int multiply (ETransp transa, ETransp transb, ScalarType alpha, const SerialDenseMatrix<OrdinalType, ScalarType> &A, const SerialDenseMatrix<OrdinalType, ScalarType> &B, ScalarType beta);
315 
316   //! Multiply \c A and \c B and add them to \e this; \e this = \c beta * \e this + \c alpha*A*B or \e this = \c beta * \e this + \c alpha*B*A.
317   /*!
318     \param sideA - Which side is A on for the multiplication to B, A*B (Teuchos::LEFT_SIDE) or B*A (Teuchos::RIGHT_SIDE).
319     \param alpha - The scaling factor for \c A * \c B, or \c B * \c A.
320     \param A - SerialSymDenseMatrix (a serial SPD dense matrix)
321     \param B - SerialDenseMatrix (a serial dense matrix)
322     \param beta - The scaling factor for \e this.
323 
324     If the matrices \c A and \c B are not of the right dimension, consistent with \e this, then \e this
325     matrix will not be altered and -1 will be returned.
326     \return Integer error code, set to 0 if successful.
327   */
328   int multiply (ESide sideA, ScalarType alpha, const SerialSymDenseMatrix<OrdinalType, ScalarType> &A, const SerialDenseMatrix<OrdinalType, ScalarType> &B, ScalarType beta);
329 
330   //@}
331 
332   //! @name Comparison methods.
333   //@{
334 
335   //! Equality of two matrices.
336   /*! \return True if \e this matrix and \c Operand are of the same shape (rows and columns) and have
337     the same entries, else False will be returned.
338   */
339   bool operator== (const SerialDenseMatrix<OrdinalType, ScalarType> &Operand) const;
340 
341   //! Inequality of two matrices.
342   /*! \return True if \e this matrix and \c Operand of not of the same shape (rows and columns) or don't
343     have the same entries, else False will be returned.
344   */
345   bool operator!= (const SerialDenseMatrix<OrdinalType, ScalarType> &Operand) const;
346 
347   //@}
348 
349   //! @name Attribute methods.
350   //@{
351 
352   //! Returns the row dimension of this matrix.
numRows() const353   OrdinalType numRows() const { return(numRows_); }
354 
355   //! Returns the column dimension of this matrix.
numCols() const356   OrdinalType numCols() const { return(numCols_); }
357 
358   //! Returns the stride between the columns of this matrix in memory.
stride() const359   OrdinalType stride() const { return(stride_); }
360 
361   //! Returns whether this matrix is empty.
empty() const362   bool empty() const { return(numRows_ == 0 || numCols_ == 0); }
363   //@}
364 
365   //! @name Norm methods.
366   //@{
367 
368   //! Returns the 1-norm of the matrix.
369   typename ScalarTraits<ScalarType>::magnitudeType normOne() const;
370 
371   //! Returns the Infinity-norm of the matrix.
372   typename ScalarTraits<ScalarType>::magnitudeType normInf() const;
373 
374   //! Returns the Frobenius-norm of the matrix.
375   typename ScalarTraits<ScalarType>::magnitudeType normFrobenius() const;
376   //@}
377 
378   //! @name I/O methods.
379   //@{
380   //! Print method.  Defines the behavior of the std::ostream << operator
381   virtual std::ostream& print(std::ostream& os) const;
382 
383   //@}
384 protected:
385   void copyMat(ScalarType* inputMatrix, OrdinalType strideInput,
386     OrdinalType numRows, OrdinalType numCols, ScalarType* outputMatrix,
387     OrdinalType strideOutput, OrdinalType startRow, OrdinalType startCol,
388     ScalarType alpha = ScalarTraits<ScalarType>::zero() );
389   void deleteArrays();
390   void checkIndex( OrdinalType rowIndex, OrdinalType colIndex = 0 ) const;
391 
392   static ScalarType*
allocateValues(const OrdinalType numRows,const OrdinalType numCols)393   allocateValues(const OrdinalType numRows,
394                  const OrdinalType numCols)
395   {
396     const size_t size = size_t(numRows) * size_t(numCols);
397 #pragma GCC diagnostic push
398 #pragma GCC diagnostic ignored "-Wvla"
399     return new ScalarType[size];
400 #pragma GCC diagnostic pop
401   }
402 
403   OrdinalType numRows_ = 0;
404   OrdinalType numCols_ = 0;
405   OrdinalType stride_ = 0;
406   bool valuesCopied_ = false;
407   ScalarType* values_ = nullptr;
408 }; // class Teuchos_SerialDenseMatrix
409 
410 //----------------------------------------------------------------------------------------------------
411 //  Constructors and Destructor
412 //----------------------------------------------------------------------------------------------------
413 
414 template<typename OrdinalType, typename ScalarType>
SerialDenseMatrix(OrdinalType numRows_in,OrdinalType numCols_in,bool zeroOut)415 SerialDenseMatrix<OrdinalType, ScalarType>::SerialDenseMatrix(
416   OrdinalType numRows_in, OrdinalType numCols_in, bool zeroOut
417   )
418   : numRows_(numRows_in),
419     numCols_(numCols_in),
420     stride_(numRows_in),
421     valuesCopied_(true),
422     values_(allocateValues(numRows_in, numCols_in))
423 {
424   if (zeroOut) {
425     putScalar();
426   }
427 }
428 
429 template<typename OrdinalType, typename ScalarType>
SerialDenseMatrix(DataAccess CV,ScalarType * values_in,OrdinalType stride_in,OrdinalType numRows_in,OrdinalType numCols_in)430 SerialDenseMatrix<OrdinalType, ScalarType>::SerialDenseMatrix(
431   DataAccess CV, ScalarType* values_in, OrdinalType stride_in, OrdinalType numRows_in,
432   OrdinalType numCols_in
433   )
434   : numRows_(numRows_in),
435     numCols_(numCols_in),
436     stride_(stride_in),
437     valuesCopied_(false),
438     values_(values_in)
439 {
440   if(CV == Copy)
441   {
442     stride_ = numRows_;
443     values_ = allocateValues(stride_, numCols_);
444     copyMat(values_in, stride_in, numRows_, numCols_, values_, stride_, 0, 0);
445     valuesCopied_ = true;
446   }
447 }
448 
449 template<typename OrdinalType, typename ScalarType>
SerialDenseMatrix(const SerialDenseMatrix<OrdinalType,ScalarType> & Source,ETransp trans)450 SerialDenseMatrix<OrdinalType, ScalarType>::SerialDenseMatrix(const SerialDenseMatrix<OrdinalType, ScalarType> &Source, ETransp trans)
451   : valuesCopied_(true)
452 {
453   if ( trans == Teuchos::NO_TRANS )
454   {
455     numRows_ = Source.numRows_;
456     numCols_ = Source.numCols_;
457 
458     if (!Source.valuesCopied_)
459     {
460       stride_ = Source.stride_;
461       values_ = Source.values_;
462       valuesCopied_ = false;
463     }
464     else
465     {
466       stride_ = numRows_;
467       if(stride_ > 0 && numCols_ > 0) {
468         values_ = allocateValues(stride_, numCols_);
469         copyMat(Source.values_, Source.stride_, numRows_, numCols_, values_, stride_, 0, 0);
470       }
471       else {
472         numRows_ = 0; numCols_ = 0; stride_ = 0;
473         valuesCopied_ = false;
474       }
475     }
476   }
477   else if ( trans == Teuchos::CONJ_TRANS && ScalarTraits<ScalarType>::isComplex )
478   {
479     numRows_ = Source.numCols_;
480     numCols_ = Source.numRows_;
481     stride_ = numRows_;
482     values_ = allocateValues(stride_, numCols_);
483     for (OrdinalType j=0; j<numCols_; j++) {
484       for (OrdinalType i=0; i<numRows_; i++) {
485         values_[j*stride_ + i] = Teuchos::ScalarTraits<ScalarType>::conjugate(Source.values_[i*Source.stride_ + j]);
486       }
487     }
488   }
489   else
490   {
491     numRows_ = Source.numCols_;
492     numCols_ = Source.numRows_;
493     stride_ = numRows_;
494     values_ = allocateValues(stride_, numCols_);
495     for (OrdinalType j=0; j<numCols_; j++) {
496       for (OrdinalType i=0; i<numRows_; i++) {
497         values_[j*stride_ + i] = Source.values_[i*Source.stride_ + j];
498       }
499     }
500   }
501 }
502 
503 
504 template<typename OrdinalType, typename ScalarType>
SerialDenseMatrix(DataAccess CV,const SerialDenseMatrix<OrdinalType,ScalarType> & Source)505 SerialDenseMatrix<OrdinalType, ScalarType>::SerialDenseMatrix(
506   DataAccess CV, const SerialDenseMatrix<OrdinalType, ScalarType> &Source
507   )
508   : numRows_(Source.numRows_), numCols_(Source.numCols_), stride_(Source.stride_),
509     valuesCopied_(false), values_(Source.values_)
510 {
511   if(CV == Copy)
512   {
513     stride_ = numRows_;
514     values_ = allocateValues(stride_, numCols_);
515     copyMat(Source.values_, Source.stride_, numRows_, numCols_, values_, stride_, 0, 0);
516     valuesCopied_ = true;
517   }
518 }
519 
520 
521 template<typename OrdinalType, typename ScalarType>
SerialDenseMatrix(DataAccess CV,const SerialDenseMatrix<OrdinalType,ScalarType> & Source,OrdinalType numRows_in,OrdinalType numCols_in,OrdinalType startRow,OrdinalType startCol)522 SerialDenseMatrix<OrdinalType, ScalarType>::SerialDenseMatrix(
523   DataAccess CV, const SerialDenseMatrix<OrdinalType, ScalarType> &Source,
524   OrdinalType numRows_in, OrdinalType numCols_in, OrdinalType startRow,
525   OrdinalType startCol
526   )
527   : CompObject(), numRows_(numRows_in), numCols_(numCols_in), stride_(Source.stride_),
528     valuesCopied_(false), values_(Source.values_)
529 {
530   if(CV == Copy)
531   {
532     stride_ = numRows_in;
533     values_ = allocateValues(stride_, numCols_in);
534     copyMat(Source.values_, Source.stride_, numRows_in, numCols_in, values_, stride_, startRow, startCol);
535     valuesCopied_ = true;
536   }
537   else // CV == View
538   {
539     values_ = values_ + (stride_ * startCol) + startRow;
540   }
541 }
542 
543 template<typename OrdinalType, typename ScalarType>
~SerialDenseMatrix()544 SerialDenseMatrix<OrdinalType, ScalarType>::~SerialDenseMatrix()
545 {
546   deleteArrays();
547 }
548 
549 //----------------------------------------------------------------------------------------------------
550 //  Shape methods
551 //----------------------------------------------------------------------------------------------------
552 
553 template<typename OrdinalType, typename ScalarType>
shape(OrdinalType numRows_in,OrdinalType numCols_in)554 int SerialDenseMatrix<OrdinalType, ScalarType>::shape(
555   OrdinalType numRows_in, OrdinalType numCols_in
556   )
557 {
558   deleteArrays(); // Get rid of anything that might be already allocated
559   numRows_ = numRows_in;
560   numCols_ = numCols_in;
561   stride_ = numRows_;
562   values_ = allocateValues(stride_, numCols_);
563   putScalar();
564   valuesCopied_ = true;
565   return(0);
566 }
567 
568 template<typename OrdinalType, typename ScalarType>
shapeUninitialized(OrdinalType numRows_in,OrdinalType numCols_in)569 int SerialDenseMatrix<OrdinalType, ScalarType>::shapeUninitialized(
570   OrdinalType numRows_in, OrdinalType numCols_in
571   )
572 {
573   deleteArrays(); // Get rid of anything that might be already allocated
574   numRows_ = numRows_in;
575   numCols_ = numCols_in;
576   stride_ = numRows_;
577   values_ = allocateValues(stride_, numCols_);
578   valuesCopied_ = true;
579   return(0);
580 }
581 
582 template<typename OrdinalType, typename ScalarType>
reshape(OrdinalType numRows_in,OrdinalType numCols_in)583 int SerialDenseMatrix<OrdinalType, ScalarType>::reshape(
584   OrdinalType numRows_in, OrdinalType numCols_in
585   )
586 {
587   // Allocate space for new matrix
588   ScalarType* values_tmp = allocateValues(numRows_in, numCols_in);
589   ScalarType zero = ScalarTraits<ScalarType>::zero();
590   for(OrdinalType k = 0; k < numRows_in * numCols_in; k++)
591   {
592     values_tmp[k] = zero;
593   }
594   OrdinalType numRows_tmp = TEUCHOS_MIN(numRows_, numRows_in);
595   OrdinalType numCols_tmp = TEUCHOS_MIN(numCols_, numCols_in);
596   if(values_ != 0)
597   {
598     copyMat(values_, stride_, numRows_tmp, numCols_tmp, values_tmp,
599       numRows_in, 0, 0); // Copy principal submatrix of A to new A
600   }
601   deleteArrays(); // Get rid of anything that might be already allocated
602   numRows_ = numRows_in;
603   numCols_ = numCols_in;
604   stride_ = numRows_;
605   values_ = values_tmp; // Set pointer to new A
606   valuesCopied_ = true;
607   return(0);
608 }
609 
610 //----------------------------------------------------------------------------------------------------
611 //   Set methods
612 //----------------------------------------------------------------------------------------------------
613 
614 template<typename OrdinalType, typename ScalarType>
putScalar(const ScalarType value_in)615 int SerialDenseMatrix<OrdinalType, ScalarType>::putScalar( const ScalarType value_in )
616 {
617   // Set each value of the dense matrix to "value".
618   for(OrdinalType j = 0; j < numCols_; j++)
619   {
620     for(OrdinalType i = 0; i < numRows_; i++)
621           {
622             values_[i + j*stride_] = value_in;
623           }
624   }
625   return 0;
626 }
627 
628 template<typename OrdinalType, typename ScalarType> void
swap(SerialDenseMatrix<OrdinalType,ScalarType> & B)629 SerialDenseMatrix<OrdinalType, ScalarType>::swap(
630   SerialDenseMatrix<OrdinalType, ScalarType> &B)
631 {
632   // Notes:
633   // > DefaultBLASImpl::SWAP() uses a deep copy. This fn uses a pointer swap.
634   // > this fn covers both Vector and Matrix, such that some care must be
635   //   employed to not swap across types (creating a Vector with non-unitary
636   //   numCols_)
637   // > Inherited data that is not currently swapped (since inactive/deprecated):
638   //   >> Teuchos::CompObject:
639   //        Flops *flopCounter_ [Note: all SerialDenseMatrix ctors initialize a
640   //        NULL flop-counter using CompObject(), such that any flop increments
641   //        that are computed are not accumulated.]
642   //   >> Teuchos::Object: (now removed from inheritance list)
643   //        static int tracebackMode (no swap for statics)
644   //        std::string label_ (has been reported as a cause of memory overhead)
645 
646   std::swap(values_ ,      B.values_);
647   std::swap(numRows_,      B.numRows_);
648   std::swap(numCols_,      B.numCols_);
649   std::swap(stride_,       B.stride_);
650   std::swap(valuesCopied_, B.valuesCopied_);
651 }
652 
653 template<typename OrdinalType, typename ScalarType>
random()654 int SerialDenseMatrix<OrdinalType, ScalarType>::random()
655 {
656   // Set each value of the dense matrix to a random value.
657   for(OrdinalType j = 0; j < numCols_; j++)
658   {
659     for(OrdinalType i = 0; i < numRows_; i++)
660           {
661             values_[i + j*stride_] = ScalarTraits<ScalarType>::random();
662           }
663   }
664   return 0;
665 }
666 
667 template<typename OrdinalType, typename ScalarType>
668 SerialDenseMatrix<OrdinalType,ScalarType>&
operator =(const SerialDenseMatrix<OrdinalType,ScalarType> & Source)669 SerialDenseMatrix<OrdinalType, ScalarType>::operator=(
670   const SerialDenseMatrix<OrdinalType,ScalarType>& Source
671   )
672 {
673   if(this == &Source)
674     return(*this); // Special case of source same as target
675   if((!valuesCopied_) && (!Source.valuesCopied_) && (values_ == Source.values_))
676     return(*this); // Special case of both are views to same data.
677 
678   // If the source is a view then we will return a view, else we will return a copy.
679   if (!Source.valuesCopied_) {
680     if(valuesCopied_)       {
681       // Clean up stored data if this was previously a copy.
682       deleteArrays();
683     }
684     numRows_ = Source.numRows_;
685     numCols_ = Source.numCols_;
686     stride_ = Source.stride_;
687     values_ = Source.values_;
688   }
689   else {
690     // If we were a view, we will now be a copy.
691     if(!valuesCopied_) {
692       numRows_ = Source.numRows_;
693       numCols_ = Source.numCols_;
694       stride_ = Source.numRows_;
695       if(stride_ > 0 && numCols_ > 0) {
696         values_ = allocateValues(stride_, numCols_);
697         valuesCopied_ = true;
698       }
699       else {
700         values_ = 0;
701       }
702     }
703     // If we were a copy, we will stay a copy.
704     else {
705       if((Source.numRows_ <= stride_) && (Source.numCols_ == numCols_)) { // we don't need to reallocate
706         numRows_ = Source.numRows_;
707         numCols_ = Source.numCols_;
708       }
709       else { // we need to allocate more space (or less space)
710         deleteArrays();
711         numRows_ = Source.numRows_;
712         numCols_ = Source.numCols_;
713         stride_ = Source.numRows_;
714         if(stride_ > 0 && numCols_ > 0) {
715           values_ = allocateValues(stride_, numCols_);
716           valuesCopied_ = true;
717         }
718       }
719     }
720     copyMat(Source.values_, Source.stride_, numRows_, numCols_, values_, stride_, 0, 0);
721   }
722   return(*this);
723 }
724 
725 template<typename OrdinalType, typename ScalarType>
operator +=(const SerialDenseMatrix<OrdinalType,ScalarType> & Source)726 SerialDenseMatrix<OrdinalType, ScalarType>& SerialDenseMatrix<OrdinalType, ScalarType>::operator+= (const SerialDenseMatrix<OrdinalType,ScalarType>& Source )
727 {
728   // Check for compatible dimensions
729   if ((numRows_ != Source.numRows_) || (numCols_ != Source.numCols_))
730   {
731     TEUCHOS_CHK_REF(*this); // Return *this without altering it.
732   }
733   copyMat(Source.values_, Source.stride_, numRows_, numCols_, values_, stride_, 0, 0, ScalarTraits<ScalarType>::one());
734   return(*this);
735 }
736 
737 template<typename OrdinalType, typename ScalarType>
operator -=(const SerialDenseMatrix<OrdinalType,ScalarType> & Source)738 SerialDenseMatrix<OrdinalType, ScalarType>& SerialDenseMatrix<OrdinalType, ScalarType>::operator-= (const SerialDenseMatrix<OrdinalType,ScalarType>& Source )
739 {
740   // Check for compatible dimensions
741   if ((numRows_ != Source.numRows_) || (numCols_ != Source.numCols_))
742   {
743     TEUCHOS_CHK_REF(*this); // Return *this without altering it.
744   }
745   copyMat(Source.values_, Source.stride_, numRows_, numCols_, values_, stride_, 0, 0, -ScalarTraits<ScalarType>::one());
746   return(*this);
747 }
748 
749 template<typename OrdinalType, typename ScalarType>
assign(const SerialDenseMatrix<OrdinalType,ScalarType> & Source)750 SerialDenseMatrix<OrdinalType,ScalarType>& SerialDenseMatrix<OrdinalType, ScalarType>::assign (const SerialDenseMatrix<OrdinalType,ScalarType>& Source) {
751   if(this == &Source)
752     return(*this); // Special case of source same as target
753   if((!valuesCopied_) && (!Source.valuesCopied_) && (values_ == Source.values_))
754     return(*this); // Special case of both are views to same data.
755 
756   // Check for compatible dimensions
757   if ((numRows_ != Source.numRows_) || (numCols_ != Source.numCols_))
758   {
759     TEUCHOS_CHK_REF(*this); // Return *this without altering it.
760   }
761   copyMat(Source.values_, Source.stride_, numRows_, numCols_, values_, stride_, 0, 0);
762   return(*this);
763 }
764 
765 //----------------------------------------------------------------------------------------------------
766 //   Accessor methods
767 //----------------------------------------------------------------------------------------------------
768 
769 template<typename OrdinalType, typename ScalarType>
operator ()(OrdinalType rowIndex,OrdinalType colIndex)770 inline ScalarType& SerialDenseMatrix<OrdinalType, ScalarType>::operator () (OrdinalType rowIndex, OrdinalType colIndex)
771 {
772 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
773   checkIndex( rowIndex, colIndex );
774 #endif
775   return(values_[colIndex * stride_ + rowIndex]);
776 }
777 
778 template<typename OrdinalType, typename ScalarType>
operator ()(OrdinalType rowIndex,OrdinalType colIndex) const779 inline const ScalarType& SerialDenseMatrix<OrdinalType, ScalarType>::operator () (OrdinalType rowIndex, OrdinalType colIndex) const
780 {
781 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
782   checkIndex( rowIndex, colIndex );
783 #endif
784   return(values_[colIndex * stride_ + rowIndex]);
785 }
786 
787 template<typename OrdinalType, typename ScalarType>
operator [](OrdinalType colIndex) const788 inline const ScalarType* SerialDenseMatrix<OrdinalType, ScalarType>::operator [] (OrdinalType colIndex) const
789 {
790 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
791   checkIndex( 0, colIndex );
792 #endif
793   return(values_ + colIndex * stride_);
794 }
795 
796 template<typename OrdinalType, typename ScalarType>
operator [](OrdinalType colIndex)797 inline ScalarType* SerialDenseMatrix<OrdinalType, ScalarType>::operator [] (OrdinalType colIndex)
798 {
799 #ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK
800   checkIndex( 0, colIndex );
801 #endif
802   return(values_ + colIndex * stride_);
803 }
804 
805 //----------------------------------------------------------------------------------------------------
806 //   Norm methods
807 //----------------------------------------------------------------------------------------------------
808 
809 template<typename OrdinalType, typename ScalarType>
normOne() const810 typename ScalarTraits<ScalarType>::magnitudeType SerialDenseMatrix<OrdinalType, ScalarType>::normOne() const
811 {
812   OrdinalType i, j;
813   typename ScalarTraits<ScalarType>::magnitudeType anorm = ScalarTraits<ScalarType>::magnitude(ScalarTraits<ScalarType>::zero());
814   typename ScalarTraits<ScalarType>::magnitudeType absSum = ScalarTraits<ScalarType>::magnitude(ScalarTraits<ScalarType>::zero());
815   ScalarType* ptr;
816   for(j = 0; j < numCols_; j++)
817   {
818     ScalarType sum = 0;
819     ptr = values_ + j * stride_;
820     for(i = 0; i < numRows_; i++)
821           {
822             sum += ScalarTraits<ScalarType>::magnitude(*ptr++);
823           }
824     absSum = ScalarTraits<ScalarType>::magnitude(sum);
825     if(absSum > anorm)
826           {
827             anorm = absSum;
828           }
829   }
830   // don't compute flop increment unless there is an accumulator
831   if (flopCounter_!=0) updateFlops(numRows_ * numCols_);
832   return(anorm);
833 }
834 
835 template<typename OrdinalType, typename ScalarType>
normInf() const836 typename ScalarTraits<ScalarType>::magnitudeType SerialDenseMatrix<OrdinalType, ScalarType>::normInf() const
837 {
838   OrdinalType i, j;
839   typename ScalarTraits<ScalarType>::magnitudeType sum, anorm = ScalarTraits<ScalarType>::magnitude(ScalarTraits<ScalarType>::zero());
840 
841   for (i = 0; i < numRows_; i++) {
842     sum = ScalarTraits<ScalarType>::magnitude(ScalarTraits<ScalarType>::zero());
843     for (j=0; j< numCols_; j++) {
844       sum += ScalarTraits<ScalarType>::magnitude(*(values_+i+j*stride_));
845     }
846     anorm = TEUCHOS_MAX( anorm, sum );
847   }
848   // don't compute flop increment unless there is an accumulator
849   if (flopCounter_!=0) updateFlops(numRows_ * numCols_);
850   return(anorm);
851 }
852 
853 template<typename OrdinalType, typename ScalarType>
normFrobenius() const854 typename ScalarTraits<ScalarType>::magnitudeType SerialDenseMatrix<OrdinalType, ScalarType>::normFrobenius() const
855 {
856   OrdinalType i, j;
857   typename ScalarTraits<ScalarType>::magnitudeType anorm = ScalarTraits<ScalarType>::magnitude(ScalarTraits<ScalarType>::zero());
858   for (j = 0; j < numCols_; j++) {
859     for (i = 0; i < numRows_; i++) {
860       anorm += ScalarTraits<ScalarType>::magnitude(values_[i+j*stride_]*values_[i+j*stride_]);
861     }
862   }
863   anorm = ScalarTraits<ScalarType>::magnitude(ScalarTraits<ScalarType>::squareroot(anorm));
864   // don't compute flop increment unless there is an accumulator
865   if (flopCounter_!=0) updateFlops(numRows_ * numCols_);
866   return(anorm);
867 }
868 
869 //----------------------------------------------------------------------------------------------------
870 //   Comparison methods
871 //----------------------------------------------------------------------------------------------------
872 
873 template<typename OrdinalType, typename ScalarType>
operator ==(const SerialDenseMatrix<OrdinalType,ScalarType> & Operand) const874 bool SerialDenseMatrix<OrdinalType, ScalarType>::operator== (const SerialDenseMatrix<OrdinalType, ScalarType> &Operand) const
875 {
876   bool result = 1;
877   if((numRows_ != Operand.numRows_) || (numCols_ != Operand.numCols_))
878   {
879     result = 0;
880   }
881   else
882   {
883     OrdinalType i, j;
884     for(i = 0; i < numRows_; i++)
885           {
886             for(j = 0; j < numCols_; j++)
887       {
888         if((*this)(i, j) != Operand(i, j))
889         {
890           return 0;
891         }
892       }
893           }
894   }
895   return result;
896 }
897 
898 template<typename OrdinalType, typename ScalarType>
operator !=(const SerialDenseMatrix<OrdinalType,ScalarType> & Operand) const899 bool SerialDenseMatrix<OrdinalType, ScalarType>::operator!= (const SerialDenseMatrix<OrdinalType, ScalarType> &Operand) const
900 {
901   return !((*this) == Operand);
902 }
903 
904 //----------------------------------------------------------------------------------------------------
905 //   Multiplication method
906 //----------------------------------------------------------------------------------------------------
907 
908 template<typename OrdinalType, typename ScalarType>
operator *=(const ScalarType alpha)909 SerialDenseMatrix<OrdinalType, ScalarType>& SerialDenseMatrix<OrdinalType, ScalarType>::operator*= (const ScalarType alpha )
910 {
911   this->scale( alpha );
912   return(*this);
913 }
914 
915 template<typename OrdinalType, typename ScalarType>
scale(const ScalarType alpha)916 int SerialDenseMatrix<OrdinalType, ScalarType>::scale( const ScalarType alpha )
917 {
918   OrdinalType i, j;
919   ScalarType* ptr;
920 
921   for (j=0; j<numCols_; j++) {
922     ptr = values_ + j*stride_;
923     for (i=0; i<numRows_; i++) { *ptr = alpha * (*ptr); ptr++; }
924   }
925   // don't compute flop increment unless there is an accumulator
926   if (flopCounter_!=0) updateFlops( numRows_*numCols_ );
927   return(0);
928 }
929 
930 template<typename OrdinalType, typename ScalarType>
scale(const SerialDenseMatrix<OrdinalType,ScalarType> & A)931 int SerialDenseMatrix<OrdinalType, ScalarType>::scale( const SerialDenseMatrix<OrdinalType,ScalarType>& A )
932 {
933   OrdinalType i, j;
934   ScalarType* ptr;
935 
936   // Check for compatible dimensions
937   if ((numRows_ != A.numRows_) || (numCols_ != A.numCols_))
938   {
939     TEUCHOS_CHK_ERR(-1); // Return error
940   }
941   for (j=0; j<numCols_; j++) {
942     ptr = values_ + j*stride_;
943     for (i=0; i<numRows_; i++) { *ptr = A(i,j) * (*ptr); ptr++; }
944   }
945   // don't compute flop increment unless there is an accumulator
946   if (flopCounter_!=0) updateFlops( numRows_*numCols_ );
947   return(0);
948 }
949 
950 template<typename OrdinalType, typename ScalarType>
multiply(ETransp transa,ETransp transb,ScalarType alpha,const SerialDenseMatrix<OrdinalType,ScalarType> & A,const SerialDenseMatrix<OrdinalType,ScalarType> & B,ScalarType beta)951 int  SerialDenseMatrix<OrdinalType, ScalarType>::multiply(ETransp transa, ETransp transb, ScalarType alpha, const SerialDenseMatrix<OrdinalType, ScalarType> &A, const SerialDenseMatrix<OrdinalType, ScalarType> &B, ScalarType beta)
952 {
953   // Check for compatible dimensions
954   OrdinalType A_nrows = (ETranspChar[transa]!='N') ? A.numCols() : A.numRows();
955   OrdinalType A_ncols = (ETranspChar[transa]!='N') ? A.numRows() : A.numCols();
956   OrdinalType B_nrows = (ETranspChar[transb]!='N') ? B.numCols() : B.numRows();
957   OrdinalType B_ncols = (ETranspChar[transb]!='N') ? B.numRows() : B.numCols();
958   if ((numRows_ != A_nrows) || (A_ncols != B_nrows) || (numCols_ != B_ncols))
959   {
960     TEUCHOS_CHK_ERR(-1); // Return error
961   }
962   // Call GEMM function
963   this->GEMM(transa, transb, numRows_, numCols_, A_ncols, alpha, A.values(), A.stride(), B.values(), B.stride(), beta, values_, stride_);
964 
965   // don't compute flop increment unless there is an accumulator
966   if (flopCounter_!=0) {
967     double nflops = 2 * numRows_;
968     nflops *= numCols_;
969     nflops *= A_ncols;
970     updateFlops(nflops);
971   }
972   return(0);
973 }
974 
975 template<typename OrdinalType, typename ScalarType>
multiply(ESide sideA,ScalarType alpha,const SerialSymDenseMatrix<OrdinalType,ScalarType> & A,const SerialDenseMatrix<OrdinalType,ScalarType> & B,ScalarType beta)976 int SerialDenseMatrix<OrdinalType, ScalarType>::multiply (ESide sideA, ScalarType alpha, const SerialSymDenseMatrix<OrdinalType, ScalarType> &A, const SerialDenseMatrix<OrdinalType, ScalarType> &B, ScalarType beta)
977 {
978   // Check for compatible dimensions
979   OrdinalType A_nrows = A.numRows(), A_ncols = A.numCols();
980   OrdinalType B_nrows = B.numRows(), B_ncols = B.numCols();
981 
982   if (ESideChar[sideA]=='L') {
983     if ((numRows_ != A_nrows) || (A_ncols != B_nrows) || (numCols_ != B_ncols)) {
984       TEUCHOS_CHK_ERR(-1); // Return error
985     }
986   } else {
987     if ((numRows_ != B_nrows) || (B_ncols != A_nrows) || (numCols_ != A_ncols)) {
988       TEUCHOS_CHK_ERR(-1); // Return error
989     }
990   }
991 
992   // Call SYMM function
993   EUplo uplo = (A.upper() ? Teuchos::UPPER_TRI : Teuchos::LOWER_TRI);
994   this->SYMM(sideA, uplo, numRows_, numCols_, alpha, A.values(), A.stride(), B.values(), B.stride(), beta, values_, stride_);
995 
996   // don't compute flop increment unless there is an accumulator
997   if (flopCounter_!=0) {
998     double nflops = 2 * numRows_;
999     nflops *= numCols_;
1000     nflops *= A_ncols;
1001     updateFlops(nflops);
1002   }
1003   return(0);
1004 }
1005 
1006 template<typename OrdinalType, typename ScalarType>
print(std::ostream & os) const1007 std::ostream& SerialDenseMatrix<OrdinalType, ScalarType>::print(std::ostream& os) const
1008 {
1009   os << std::endl;
1010   if(valuesCopied_)
1011     os << "Values_copied : yes" << std::endl;
1012   else
1013     os << "Values_copied : no" << std::endl;
1014   os << "Rows : " << numRows_ << std::endl;
1015   os << "Columns : " << numCols_ << std::endl;
1016   os << "LDA : " << stride_ << std::endl;
1017   if(numRows_ == 0 || numCols_ == 0) {
1018     os << "(matrix is empty, no values to display)" << std::endl;
1019   } else {
1020     for(OrdinalType i = 0; i < numRows_; i++) {
1021       for(OrdinalType j = 0; j < numCols_; j++){
1022         os << (*this)(i,j) << " ";
1023       }
1024       os << std::endl;
1025     }
1026   }
1027   return os;
1028 }
1029 
1030 //----------------------------------------------------------------------------------------------------
1031 //   Protected methods
1032 //----------------------------------------------------------------------------------------------------
1033 
1034 template<typename OrdinalType, typename ScalarType>
checkIndex(OrdinalType rowIndex,OrdinalType colIndex) const1035 inline void SerialDenseMatrix<OrdinalType, ScalarType>::checkIndex( OrdinalType rowIndex, OrdinalType colIndex ) const {
1036   TEUCHOS_TEST_FOR_EXCEPTION(rowIndex < 0 || rowIndex >= numRows_, std::out_of_range,
1037     "SerialDenseMatrix<T>::checkIndex: "
1038     "Row index " << rowIndex << " out of range [0, "<< numRows_ << ")");
1039   TEUCHOS_TEST_FOR_EXCEPTION(colIndex < 0 || colIndex >= numCols_, std::out_of_range,
1040     "SerialDenseMatrix<T>::checkIndex: "
1041     "Col index " << colIndex << " out of range [0, "<< numCols_ << ")");
1042 }
1043 
1044 template<typename OrdinalType, typename ScalarType>
deleteArrays(void)1045 void SerialDenseMatrix<OrdinalType, ScalarType>::deleteArrays(void)
1046 {
1047   if (valuesCopied_)
1048   {
1049     delete [] values_;
1050     values_ = 0;
1051     valuesCopied_ = false;
1052   }
1053 }
1054 
1055 template<typename OrdinalType, typename ScalarType>
copyMat(ScalarType * inputMatrix,OrdinalType strideInput,OrdinalType numRows_in,OrdinalType numCols_in,ScalarType * outputMatrix,OrdinalType strideOutput,OrdinalType startRow,OrdinalType startCol,ScalarType alpha)1056 void SerialDenseMatrix<OrdinalType, ScalarType>::copyMat(
1057   ScalarType* inputMatrix, OrdinalType strideInput, OrdinalType numRows_in,
1058   OrdinalType numCols_in, ScalarType* outputMatrix, OrdinalType strideOutput,
1059   OrdinalType startRow, OrdinalType startCol, ScalarType alpha
1060   )
1061 {
1062   OrdinalType i, j;
1063   ScalarType* ptr1 = 0;
1064   ScalarType* ptr2 = 0;
1065   for(j = 0; j < numCols_in; j++) {
1066     ptr1 = outputMatrix + (j * strideOutput);
1067     ptr2 = inputMatrix + (j + startCol) * strideInput + startRow;
1068     if (alpha != Teuchos::ScalarTraits<ScalarType>::zero() ) {
1069       for(i = 0; i < numRows_in; i++)
1070             {
1071               *ptr1++ += alpha*(*ptr2++);
1072             }
1073     } else {
1074       for(i = 0; i < numRows_in; i++)
1075             {
1076               *ptr1++ = *ptr2++;
1077             }
1078     }
1079   }
1080 }
1081 
1082 /// \brief Ostream manipulator for SerialDenseMatrix
1083 template<typename OrdinalType, typename ScalarType>
1084 struct SerialDenseMatrixPrinter {
1085 public:
1086   const SerialDenseMatrix<OrdinalType,ScalarType> &obj;
SerialDenseMatrixPrinterTeuchos::SerialDenseMatrixPrinter1087   SerialDenseMatrixPrinter(
1088         const SerialDenseMatrix<OrdinalType,ScalarType> &obj_in)
1089       : obj(obj_in) {}
1090 };
1091 
1092 /// \brief Output SerialDenseMatrix object through its stream manipulator.
1093 template<typename OrdinalType, typename ScalarType>
1094 std::ostream&
operator <<(std::ostream & out,const SerialDenseMatrixPrinter<OrdinalType,ScalarType> printer)1095 operator<<(std::ostream &out,
1096            const SerialDenseMatrixPrinter<OrdinalType,ScalarType> printer)
1097 {
1098   printer.obj.print(out);
1099   return out;
1100 }
1101 
1102 /// \brief Return SerialDenseMatrix ostream manipulator Use as:
1103 template<typename OrdinalType, typename ScalarType>
1104 SerialDenseMatrixPrinter<OrdinalType,ScalarType>
printMat(const SerialDenseMatrix<OrdinalType,ScalarType> & obj)1105 printMat(const SerialDenseMatrix<OrdinalType,ScalarType> &obj)
1106 {
1107   return SerialDenseMatrixPrinter<OrdinalType,ScalarType>(obj);
1108 }
1109 
1110 
1111 } // namespace Teuchos
1112 
1113 
1114 #endif /* _TEUCHOS_SERIALDENSEMATRIX_HPP_ */
1115