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