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