1 //=================================================================================================
2 /*!
3 // \file blaze/math/adaptors/symmetricmatrix/DenseNonScalar.h
4 // \brief SymmetricMatrix specialization for dense matrices with non-scalar element type
5 //
6 // Copyright (C) 2012-2020 Klaus Iglberger - All Rights Reserved
7 //
8 // This file is part of the Blaze library. You can redistribute it and/or modify it under
9 // the terms of the New (Revised) BSD License. Redistribution and use in source and binary
10 // forms, with or without modification, are permitted provided that the following conditions
11 // are met:
12 //
13 // 1. Redistributions of source code must retain the above copyright notice, this list of
14 // conditions and the following disclaimer.
15 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
16 // of conditions and the following disclaimer in the documentation and/or other materials
17 // provided with the distribution.
18 // 3. Neither the names of the Blaze development group nor the names of its contributors
19 // may be used to endorse or promote products derived from this software without specific
20 // prior written permission.
21 //
22 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
23 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25 // SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31 // DAMAGE.
32 */
33 //=================================================================================================
34
35 #ifndef _BLAZE_MATH_ADAPTORS_SYMMETRICMATRIX_DENSENONSCALAR_H_
36 #define _BLAZE_MATH_ADAPTORS_SYMMETRICMATRIX_DENSENONSCALAR_H_
37
38
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42
43 #include <iterator>
44 #include <utility>
45 #include <blaze/math/adaptors/symmetricmatrix/BaseTemplate.h>
46 #include <blaze/math/Aliases.h>
47 #include <blaze/math/constraints/Computation.h>
48 #include <blaze/math/constraints/DenseMatrix.h>
49 #include <blaze/math/constraints/Hermitian.h>
50 #include <blaze/math/constraints/Lower.h>
51 #include <blaze/math/constraints/Resizable.h>
52 #include <blaze/math/constraints/Scalar.h>
53 #include <blaze/math/constraints/StorageOrder.h>
54 #include <blaze/math/constraints/Symmetric.h>
55 #include <blaze/math/constraints/Transformation.h>
56 #include <blaze/math/constraints/Upper.h>
57 #include <blaze/math/constraints/View.h>
58 #include <blaze/math/dense/DenseMatrix.h>
59 #include <blaze/math/Exception.h>
60 #include <blaze/math/expressions/DenseMatrix.h>
61 #include <blaze/math/expressions/Forward.h>
62 #include <blaze/math/RelaxationFlag.h>
63 #include <blaze/math/shims/Clear.h>
64 #include <blaze/math/shims/Conjugate.h>
65 #include <blaze/math/shims/IsDefault.h>
66 #include <blaze/math/shims/IsZero.h>
67 #include <blaze/math/typetraits/IsComputation.h>
68 #include <blaze/math/typetraits/IsCustom.h>
69 #include <blaze/math/typetraits/IsScalar.h>
70 #include <blaze/math/typetraits/IsSMPAssignable.h>
71 #include <blaze/math/typetraits/IsSparseMatrix.h>
72 #include <blaze/math/typetraits/IsSquare.h>
73 #include <blaze/math/typetraits/IsSymmetric.h>
74 #include <blaze/math/typetraits/RemoveAdaptor.h>
75 #include <blaze/math/typetraits/Size.h>
76 #include <blaze/math/views/Submatrix.h>
77 #include <blaze/util/Assert.h>
78 #include <blaze/util/constraints/Const.h>
79 #include <blaze/util/constraints/Pointer.h>
80 #include <blaze/util/constraints/Reference.h>
81 #include <blaze/util/constraints/Volatile.h>
82 #include <blaze/util/EnableIf.h>
83 #include <blaze/util/MaybeUnused.h>
84 #include <blaze/util/mpl/If.h>
85 #include <blaze/util/StaticAssert.h>
86 #include <blaze/util/Types.h>
87 #include <blaze/util/typetraits/RemoveReference.h>
88
89
90 namespace blaze {
91
92 //=================================================================================================
93 //
94 // CLASS TEMPLATE SPECIALIZATION FOR DENSE MATRICES WITH NON-SCALAR ELEMENT TYPE
95 //
96 //=================================================================================================
97
98 //*************************************************************************************************
99 /*! \cond BLAZE_INTERNAL */
100 /*!\brief Specialization of SymmetricMatrix for dense matrices with non-scalar element type.
101 // \ingroup symmetric_matrix
102 //
103 // This specialization of SymmetricMatrix adapts the class template to the requirements of dense
104 // matrices with non-scalar data type.
105 */
106 template< typename MT // Type of the adapted dense matrix
107 , bool SO > // Storage order of the adapted dense matrix
108 class SymmetricMatrix<MT,SO,true,false>
109 : public DenseMatrix< SymmetricMatrix<MT,SO,true,false>, SO >
110 {
111 private:
112 //**Type definitions****************************************************************************
113 using OT = OppositeType_t<MT>; //!< Opposite type of the dense matrix.
114 using TT = TransposeType_t<MT>; //!< Transpose type of the dense matrix.
115 using ET = ElementType_t<MT>; //!< Element type of the dense matrix.
116 //**********************************************************************************************
117
118 public:
119 //**Type definitions****************************************************************************
120 using This = SymmetricMatrix<MT,SO,true,false>; //!< Type of this SymmetricMatrix instance.
121 using BaseType = DenseMatrix<This,SO>; //!< Base type of this SymmetricMatrix instance.
122 using ResultType = This; //!< Result type for expression template evaluations.
123 using OppositeType = SymmetricMatrix<OT,!SO,true,false>; //!< Result type with opposite storage order for expression template evaluations.
124 using TransposeType = SymmetricMatrix<TT,!SO,true,false>; //!< Transpose type for expression template evaluations.
125 using ElementType = ET; //!< Type of the matrix elements.
126 using TagType = TagType_t<MT>; //!< Tag type of this SymmetricMatrix instance.
127 using ReturnType = ReturnType_t<MT>; //!< Return type for expression template evaluations.
128 using CompositeType = const This&; //!< Data type for composite expression templates.
129 using Reference = Reference_t<MT>; //!< Reference to a non-constant matrix value.
130 using ConstReference = ConstReference_t<MT>; //!< Reference to a constant matrix value.
131 using Pointer = Pointer_t<MT>; //!< Pointer to a non-constant matrix value.
132 using ConstPointer = ConstPointer_t<MT>; //!< Pointer to a constant matrix value.
133 //**********************************************************************************************
134
135 //**Rebind struct definition********************************************************************
136 /*!\brief Rebind mechanism to obtain a SymmetricMatrix with different data/element type.
137 */
138 template< typename NewType > // Data type of the other matrix
139 struct Rebind {
140 //! The type of the other SymmetricMatrix.
141 using Other = SymmetricMatrix< typename MT::template Rebind<NewType>::Other >;
142 };
143 //**********************************************************************************************
144
145 //**Resize struct definition********************************************************************
146 /*!\brief Resize mechanism to obtain a SymmetricMatrix with different fixed dimensions.
147 */
148 template< size_t NewM // Number of rows of the other matrix
149 , size_t NewN > // Number of columns of the other matrix
150 struct Resize {
151 //! The type of the other SymmetricMatrix.
152 using Other = SymmetricMatrix< typename MT::template Resize<NewM,NewN>::Other >;
153 };
154 //**********************************************************************************************
155
156 //**MatrixIterator class definition*************************************************************
157 /*!\brief Iterator over the elements of the dense symmetric matrix.
158 */
159 template< typename MatrixType > // Type of the adapted dense matrix
160 class MatrixIterator
161 {
162 public:
163 //**Type definitions*************************************************************************
164 //! Return type for the access to the value of a dense matrix element.
165 using Reference = If_t< IsConst_v<MatrixType>
166 , ConstReference_t<MatrixType>
167 , Reference_t<MatrixType> >;
168
169 using IteratorCategory = std::random_access_iterator_tag; //!< The iterator category.
170 using ValueType = RemoveReference_t<Reference>; //!< Type of the underlying elements.
171 using PointerType = ValueType*; //!< Pointer return type.
172 using ReferenceType = Reference; //!< Reference return type.
173 using DifferenceType = ptrdiff_t; //!< Difference between two iterators.
174
175 // STL iterator requirements
176 using iterator_category = IteratorCategory; //!< The iterator category.
177 using value_type = ValueType; //!< Type of the underlying elements.
178 using pointer = PointerType; //!< Pointer return type.
179 using reference = ReferenceType; //!< Reference return type.
180 using difference_type = DifferenceType; //!< Difference between two iterators.
181 //*******************************************************************************************
182
183 //**Constructor******************************************************************************
184 /*!\brief Default constructor of the MatrixIterator class.
185 */
MatrixIterator()186 inline MatrixIterator() noexcept
187 : matrix_( nullptr ) // Reference to the adapted dense matrix
188 , row_ ( 0UL ) // The current row index of the iterator
189 , column_( 0UL ) // The current column index of the iterator
190 {}
191 //*******************************************************************************************
192
193 //**Constructor******************************************************************************
194 /*!\brief Constructor for the MatrixIterator class.
195 //
196 // \param matrix The adapted matrix.
197 // \param row Initial row index of the iterator.
198 // \param column Initial column index of the iterator.
199 */
MatrixIterator(MatrixType & matrix,size_t row,size_t column)200 inline MatrixIterator( MatrixType& matrix, size_t row, size_t column ) noexcept
201 : matrix_( &matrix ) // Reference to the adapted dense matrix
202 , row_ ( row ) // The current row index of the iterator
203 , column_( column ) // The current column index of the iterator
204 {}
205 //*******************************************************************************************
206
207 //**Conversion constructor*******************************************************************
208 /*!\brief Conversion constructor from different MatrixIterator instances.
209 //
210 // \param it The row iterator to be copied.
211 */
212 template< typename MatrixType2 >
MatrixIterator(const MatrixIterator<MatrixType2> & it)213 inline MatrixIterator( const MatrixIterator<MatrixType2>& it ) noexcept
214 : matrix_( it.matrix_ ) // Reference to the adapted dense matrix
215 , row_ ( it.row_ ) // The current row index of the iterator
216 , column_( it.column_ ) // The current column index of the iterator
217 {}
218 //*******************************************************************************************
219
220 //**Addition assignment operator*************************************************************
221 /*!\brief Addition assignment operator.
222 //
223 // \param inc The increment of the iterator.
224 // \return The incremented iterator.
225 */
226 inline MatrixIterator& operator+=( size_t inc ) noexcept {
227 ( SO )?( row_ += inc ):( column_ += inc );
228 return *this;
229 }
230 //*******************************************************************************************
231
232 //**Subtraction assignment operator**********************************************************
233 /*!\brief Subtraction assignment operator.
234 //
235 // \param dec The decrement of the iterator.
236 // \return The decremented iterator.
237 */
238 inline MatrixIterator& operator-=( size_t dec ) noexcept {
239 ( SO )?( row_ -= dec ):( column_ -= dec );
240 return *this;
241 }
242 //*******************************************************************************************
243
244 //**Prefix increment operator****************************************************************
245 /*!\brief Pre-increment operator.
246 //
247 // \return Reference to the incremented iterator.
248 */
249 inline MatrixIterator& operator++() noexcept {
250 ( SO )?( ++row_ ):( ++column_ );
251 return *this;
252 }
253 //*******************************************************************************************
254
255 //**Postfix increment operator***************************************************************
256 /*!\brief Post-increment operator.
257 //
258 // \return The previous position of the iterator.
259 */
260 inline const MatrixIterator operator++( int ) noexcept {
261 const MatrixIterator tmp( *this );
262 ++(*this);
263 return tmp;
264 }
265 //*******************************************************************************************
266
267 //**Prefix decrement operator****************************************************************
268 /*!\brief Pre-decrement operator.
269 //
270 // \return Reference to the decremented iterator.
271 */
272 inline MatrixIterator& operator--() noexcept {
273 ( SO )?( --row_ ):( --column_ );
274 return *this;
275 }
276 //*******************************************************************************************
277
278 //**Postfix decrement operator***************************************************************
279 /*!\brief Post-decrement operator.
280 //
281 // \return The previous position of the iterator.
282 */
283 inline const MatrixIterator operator--( int ) noexcept {
284 const MatrixIterator tmp( *this );
285 --(*this);
286 return tmp;
287 }
288 //*******************************************************************************************
289
290 //**Element access operator******************************************************************
291 /*!\brief Direct access to the element at the current iterator position.
292 //
293 // \return The resulting value.
294 */
295 inline ReferenceType operator*() const {
296 if( ( SO && row_ < column_ ) || ( !SO && row_ > column_ ) )
297 return (*matrix_)(row_,column_);
298 else
299 return (*matrix_)(column_,row_);
300 }
301 //*******************************************************************************************
302
303 //**Element access operator******************************************************************
304 /*!\brief Direct access to the element at the current iterator position.
305 //
306 // \return The resulting value.
307 */
308 inline PointerType operator->() const {
309 if( ( SO && row_ < column_ ) || ( !SO && row_ > column_ ) )
310 return &(*matrix_)(row_,column_);
311 else
312 return &(*matrix_)(column_,row_);
313 }
314 //*******************************************************************************************
315
316 //**Equality operator************************************************************************
317 /*!\brief Equality comparison between two MatrixIterator objects.
318 //
319 // \param rhs The right-hand side iterator.
320 // \return \a true if the iterators refer to the same element, \a false if not.
321 */
322 template< typename MatrixType2 >
323 inline bool operator==( const MatrixIterator<MatrixType2>& rhs ) const noexcept {
324 return ( SO )?( row_ == rhs.row_ ):( column_ == rhs.column_ );
325 }
326 //*******************************************************************************************
327
328 //**Inequality operator**********************************************************************
329 /*!\brief Inequality comparison between two MatrixIterator objects.
330 //
331 // \param rhs The right-hand side iterator.
332 // \return \a true if the iterators don't refer to the same element, \a false if they do.
333 */
334 template< typename MatrixType2 >
335 inline bool operator!=( const MatrixIterator<MatrixType2>& rhs ) const noexcept {
336 return ( SO )?( row_ != rhs.row_ ):( column_ != rhs.column_ );
337 }
338 //*******************************************************************************************
339
340 //**Less-than operator***********************************************************************
341 /*!\brief Less-than comparison between two MatrixIterator objects.
342 //
343 // \param rhs The right-hand side iterator.
344 // \return \a true if the left-hand side iterator is smaller, \a false if not.
345 */
346 template< typename MatrixType2 >
347 inline bool operator<( const MatrixIterator<MatrixType2>& rhs ) const noexcept {
348 return ( SO )?( row_ < rhs.row_ ):( column_ < rhs.column_ );
349 return ( column_ < rhs.column_ );
350 }
351 //*******************************************************************************************
352
353 //**Greater-than operator********************************************************************
354 /*!\brief Greater-than comparison between two MatrixIterator objects.
355 //
356 // \param rhs The right-hand side iterator.
357 // \return \a true if the left-hand side iterator is greater, \a false if not.
358 */
359 template< typename MatrixType2 >
360 inline bool operator>( const MatrixIterator<MatrixType2>& rhs ) const noexcept {
361 return ( SO )?( row_ > rhs.row_ ):( column_ > rhs.column_ );
362 return ( column_ > rhs.column_ );
363 }
364 //*******************************************************************************************
365
366 //**Less-or-equal-than operator**************************************************************
367 /*!\brief Less-than comparison between two MatrixIterator objects.
368 //
369 // \param rhs The right-hand side iterator.
370 // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
371 */
372 template< typename MatrixType2 >
373 inline bool operator<=( const MatrixIterator<MatrixType2>& rhs ) const noexcept {
374 return ( SO )?( row_ <= rhs.row_ ):( column_ <= rhs.column_ );
375 }
376 //*******************************************************************************************
377
378 //**Greater-or-equal-than operator***********************************************************
379 /*!\brief Greater-than comparison between two MatrixIterator objects.
380 //
381 // \param rhs The right-hand side iterator.
382 // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
383 */
384 template< typename MatrixType2 >
385 inline bool operator>=( const MatrixIterator<MatrixType2>& rhs ) const noexcept {
386 return ( SO )?( row_ >= rhs.row_ ):( column_ >= rhs.column_ );
387 }
388 //*******************************************************************************************
389
390 //**Subtraction operator*********************************************************************
391 /*!\brief Calculating the number of elements between two iterators.
392 //
393 // \param rhs The right-hand side iterator.
394 // \return The number of elements between the two iterators.
395 */
396 inline DifferenceType operator-( const MatrixIterator& rhs ) const noexcept {
397 return ( SO )?( row_ - rhs.row_ ):( column_ - rhs.column_ );
398 }
399 //*******************************************************************************************
400
401 //**Addition operator************************************************************************
402 /*!\brief Addition between a MatrixIterator and an integral value.
403 //
404 // \param it The iterator to be incremented.
405 // \param inc The number of elements the iterator is incremented.
406 // \return The incremented iterator.
407 */
408 friend inline const MatrixIterator operator+( const MatrixIterator& it, size_t inc ) noexcept {
409 if( SO )
410 return MatrixIterator( *it.matrix_, it.row_ + inc, it.column_ );
411 else
412 return MatrixIterator( *it.matrix_, it.row_, it.column_ + inc );
413 }
414 //*******************************************************************************************
415
416 //**Addition operator************************************************************************
417 /*!\brief Addition between an integral value and a MatrixIterator.
418 //
419 // \param inc The number of elements the iterator is incremented.
420 // \param it The iterator to be incremented.
421 // \return The incremented iterator.
422 */
423 friend inline const MatrixIterator operator+( size_t inc, const MatrixIterator& it ) noexcept {
424 if( SO )
425 return MatrixIterator( *it.matrix_, it.row_ + inc, it.column_ );
426 else
427 return MatrixIterator( *it.matrix_, it.row_, it.column_ + inc );
428 }
429 //*******************************************************************************************
430
431 //**Subtraction operator*********************************************************************
432 /*!\brief Subtraction between a MatrixIterator and an integral value.
433 //
434 // \param it The iterator to be decremented.
435 // \param dec The number of elements the iterator is decremented.
436 // \return The decremented iterator.
437 */
438 friend inline const MatrixIterator operator-( const MatrixIterator& it, size_t dec ) noexcept {
439 if( SO )
440 return MatrixIterator( *it.matrix_, it.row_ - dec, it.column_ );
441 else
442 return MatrixIterator( *it.matrix_, it.row_, it.column_ - dec );
443 }
444 //*******************************************************************************************
445
446 private:
447 //**Member variables*************************************************************************
448 MatrixType* matrix_; //!< Reference to the adapted dense matrix.
449 size_t row_; //!< The current row index of the iterator.
450 size_t column_; //!< The current column index of the iterator.
451 //*******************************************************************************************
452
453 //**Friend declarations**********************************************************************
454 template< typename MatrixType2 > friend class MatrixIterator;
455 //*******************************************************************************************
456 };
457 //**********************************************************************************************
458
459 //**Type definitions****************************************************************************
460 using Iterator = MatrixIterator<MT>; //!< Iterator over non-constant elements.
461 using ConstIterator = MatrixIterator<const MT>; //!< Iterator over constant elements.
462 //**********************************************************************************************
463
464 //**Compilation flags***************************************************************************
465 //! Compilation switch for the expression template evaluation strategy.
466 static constexpr bool simdEnabled = false;
467
468 //! Compilation switch for the expression template assignment strategy.
469 static constexpr bool smpAssignable = ( MT::smpAssignable && !IsSMPAssignable_v<ET> );
470 //**********************************************************************************************
471
472 //**Constructors********************************************************************************
473 /*!\name Constructors */
474 //@{
475 inline SymmetricMatrix();
476 explicit inline SymmetricMatrix( size_t n );
477
478 inline SymmetricMatrix( ElementType* ptr, size_t n );
479 inline SymmetricMatrix( ElementType* ptr, size_t n, size_t nn );
480
481 inline SymmetricMatrix( const SymmetricMatrix& m );
482 inline SymmetricMatrix( SymmetricMatrix&& m ) noexcept;
483
484 template< typename MT2 > inline SymmetricMatrix( const Matrix<MT2,SO>& m );
485 template< typename MT2 > inline SymmetricMatrix( const Matrix<MT2,!SO>& m );
486 //@}
487 //**********************************************************************************************
488
489 //**Destructor**********************************************************************************
490 /*!\name Destructor */
491 //@{
492 ~SymmetricMatrix() = default;
493 //@}
494 //**********************************************************************************************
495
496 //**Data access functions***********************************************************************
497 /*!\name Data access functions */
498 //@{
499 inline Reference operator()( size_t i, size_t j );
500 inline ConstReference operator()( size_t i, size_t j ) const;
501 inline Reference at( size_t i, size_t j );
502 inline ConstReference at( size_t i, size_t j ) const;
503 inline ConstPointer data () const noexcept;
504 inline ConstPointer data ( size_t i ) const noexcept;
505 inline Iterator begin ( size_t i );
506 inline ConstIterator begin ( size_t i ) const;
507 inline ConstIterator cbegin( size_t i ) const;
508 inline Iterator end ( size_t i );
509 inline ConstIterator end ( size_t i ) const;
510 inline ConstIterator cend ( size_t i ) const;
511 //@}
512 //**********************************************************************************************
513
514 //**Assignment operators************************************************************************
515 /*!\name Assignment operators */
516 //@{
517 inline SymmetricMatrix& operator=( const SymmetricMatrix& rhs );
518 inline SymmetricMatrix& operator=( SymmetricMatrix&& rhs ) noexcept;
519
520 template< typename MT2 >
521 inline auto operator=( const Matrix<MT2,SO>& rhs )
522 -> DisableIf_t< IsComputation_v<MT2>, SymmetricMatrix& >;
523
524 template< typename MT2 >
525 inline auto operator=( const Matrix<MT2,SO>& rhs )
526 -> EnableIf_t< IsComputation_v<MT2>, SymmetricMatrix& >;
527
528 template< typename MT2 >
529 inline auto operator=( const Matrix<MT2,!SO>& rhs ) -> SymmetricMatrix&;
530
531 template< typename MT2 >
532 inline auto operator+=( const Matrix<MT2,SO>& rhs )
533 -> DisableIf_t< IsComputation_v<MT2>, SymmetricMatrix& >;
534
535 template< typename MT2 >
536 inline auto operator+=( const Matrix<MT2,SO>& rhs )
537 -> EnableIf_t< IsComputation_v<MT2>, SymmetricMatrix& >;
538
539 template< typename MT2 >
540 inline auto operator+=( const Matrix<MT2,!SO>& rhs ) -> SymmetricMatrix&;
541
542 template< typename MT2 >
543 inline auto operator-=( const Matrix<MT2,SO>& rhs )
544 -> DisableIf_t< IsComputation_v<MT2>, SymmetricMatrix& >;
545
546 template< typename MT2 >
547 inline auto operator-=( const Matrix<MT2,SO>& rhs )
548 -> EnableIf_t< IsComputation_v<MT2>, SymmetricMatrix& >;
549
550 template< typename MT2 >
551 inline auto operator-=( const Matrix<MT2,!SO>& rhs ) -> SymmetricMatrix&;
552
553 template< typename MT2 >
554 inline auto operator%=( const Matrix<MT2,SO>& rhs )
555 -> DisableIf_t< IsComputation_v<MT2>, SymmetricMatrix& >;
556
557 template< typename MT2 >
558 inline auto operator%=( const Matrix<MT2,SO>& rhs )
559 -> EnableIf_t< IsComputation_v<MT2>, SymmetricMatrix& >;
560
561 template< typename MT2 >
562 inline auto operator%=( const Matrix<MT2,!SO>& rhs ) -> SymmetricMatrix&;
563
564 template< typename ST >
565 inline auto operator*=( ST rhs ) -> EnableIf_t< IsScalar_v<ST>, SymmetricMatrix& >;
566
567 template< typename ST >
568 inline auto operator/=( ST rhs ) -> EnableIf_t< IsScalar_v<ST>, SymmetricMatrix& >;
569 //@}
570 //**********************************************************************************************
571
572 //**Utility functions***************************************************************************
573 /*!\name Utility functions */
574 //@{
575 inline size_t rows() const noexcept;
576 inline size_t columns() const noexcept;
577 inline size_t spacing() const noexcept;
578 inline size_t capacity() const noexcept;
579 inline size_t capacity( size_t i ) const noexcept;
580 inline size_t nonZeros() const;
581 inline size_t nonZeros( size_t i ) const;
582 inline void reset();
583 inline void reset( size_t i );
584 inline void clear();
585 void resize ( size_t n, bool preserve=true );
586 inline void extend ( size_t n, bool preserve=true );
587 inline void reserve( size_t elements );
588 inline void shrinkToFit();
589 inline void swap( SymmetricMatrix& m ) noexcept;
590 //@}
591 //**********************************************************************************************
592
593 //**Numeric functions***************************************************************************
594 /*!\name Numeric functions */
595 //@{
596 inline SymmetricMatrix& transpose();
597 inline SymmetricMatrix& ctranspose();
598
599 template< typename Other > inline SymmetricMatrix& scale( const Other& scalar );
600 //@}
601 //**********************************************************************************************
602
603 //**Debugging functions*************************************************************************
604 /*!\name Utility functions */
605 //@{
606 inline bool isIntact() const noexcept;
607 //@}
608 //**********************************************************************************************
609
610 //**Expression template evaluation functions****************************************************
611 /*!\name Expression template evaluation functions */
612 //@{
613 template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
614 template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
615
616 inline bool isAligned () const noexcept;
617 inline bool canSMPAssign() const noexcept;
618 //@}
619 //**********************************************************************************************
620
621 private:
622 //**Expression template evaluation functions****************************************************
623 /*!\name Expression template evaluation functions */
624 //@{
625 template< typename MT2 > inline void assign ( DenseMatrix <MT2,SO>& rhs );
626 template< typename MT2 > inline void assign ( const DenseMatrix <MT2,SO>& rhs );
627 template< typename MT2 > inline void assign ( const SparseMatrix<MT2,SO>& rhs );
628 template< typename MT2 > inline void addAssign ( const DenseMatrix <MT2,SO>& rhs );
629 template< typename MT2 > inline void addAssign ( const SparseMatrix<MT2,SO>& rhs );
630 template< typename MT2 > inline void subAssign ( const DenseMatrix <MT2,SO>& rhs );
631 template< typename MT2 > inline void subAssign ( const SparseMatrix<MT2,SO>& rhs );
632 template< typename MT2 > inline void schurAssign( const DenseMatrix <MT2,SO>& rhs );
633 template< typename MT2 > inline void schurAssign( const SparseMatrix<MT2,SO>& rhs );
634 //@}
635 //**********************************************************************************************
636
637 //**Member variables****************************************************************************
638 /*!\name Member variables */
639 //@{
640 MT matrix_; //!< The adapted dense matrix.
641 //@}
642 //**********************************************************************************************
643
644 //**Friend declarations*************************************************************************
645 template< RelaxationFlag RF, typename MT2, bool SO2, bool DF2, bool SF2 >
646 friend bool isDefault( const SymmetricMatrix<MT2,SO2,DF2,SF2>& m );
647 //**********************************************************************************************
648
649 //**Compile time checks*************************************************************************
650 BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( MT );
651 BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE ( MT );
652 BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( MT );
653 BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( MT );
654 BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( MT );
655 BLAZE_CONSTRAINT_MUST_NOT_BE_VIEW_TYPE ( MT );
656 BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE ( MT );
657 BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSFORMATION_TYPE ( MT );
658 BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
659 BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE( MT );
660 BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE ( MT );
661 BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE ( MT );
662 BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( OT, !SO );
663 BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER( TT, !SO );
664 BLAZE_CONSTRAINT_MUST_NOT_BE_SCALAR_TYPE ( ElementType );
665 BLAZE_STATIC_ASSERT( ( Size_v<MT,0UL> == Size_v<MT,1UL> ) );
666 //**********************************************************************************************
667 };
668 /*! \endcond */
669 //*************************************************************************************************
670
671
672
673
674 //=================================================================================================
675 //
676 // CONSTRUCTORS
677 //
678 //=================================================================================================
679
680 //*************************************************************************************************
681 /*! \cond BLAZE_INTERNAL */
682 /*!\brief The default constructor for SymmetricMatrix.
683 */
684 template< typename MT // Type of the adapted dense matrix
685 , bool SO > // Storage order of the adapted dense matrix
SymmetricMatrix()686 inline SymmetricMatrix<MT,SO,true,false>::SymmetricMatrix()
687 : matrix_() // The adapted dense matrix
688 {
689 BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
690 }
691 /*! \endcond */
692 //*************************************************************************************************
693
694
695 //*************************************************************************************************
696 /*! \cond BLAZE_INTERNAL */
697 /*!\brief Constructor for a matrix of size \f$ n \times n \f$.
698 //
699 // \param n The number of rows and columns of the matrix.
700 */
701 template< typename MT // Type of the adapted dense matrix
702 , bool SO > // Storage order of the adapted dense matrix
SymmetricMatrix(size_t n)703 inline SymmetricMatrix<MT,SO,true,false>::SymmetricMatrix( size_t n )
704 : matrix_( n, n ) // The adapted dense matrix
705 {
706 BLAZE_CONSTRAINT_MUST_BE_RESIZABLE_TYPE( MT );
707
708 BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
709 }
710 /*! \endcond */
711 //*************************************************************************************************
712
713
714 //*************************************************************************************************
715 /*! \cond BLAZE_INTERNAL */
716 /*!\brief Constructor for a symmetric custom matrix of size \f$ n \times n \f$.
717 //
718 // \param ptr The array of elements to be used by the matrix.
719 // \param n The number of rows and columns of the array of elements.
720 // \exception std::invalid_argument Invalid setup of symmetric custom matrix.
721 //
722 // This constructor creates an unpadded symmetric custom matrix of size \f$ n \times n \f$:
723
724 \code
725 using blaze::SymmetricMatrix;
726 using blaze::CustomMatrix;
727 using blaze::unaligned;
728 using blaze::unpadded;
729
730 using Type = StaticMatrix<int,3UL,3UL>;
731
732 std::vector<Type> memory( 9UL );
733 SymmetricMatrix< CustomMatrix<Type,unaligned,unpadded> > A( memory.data(), 3UL );
734 \endcode
735
736 // The construction fails if ...
737 //
738 // - ... the passed pointer is \c nullptr;
739 // - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
740 // aligned according to the available instruction set (SSE, AVX, ...);
741 // - ... the values in the given array do not represent a symmetric matrix.
742 //
743 // In all failure cases a \a std::invalid_argument exception is thrown.
744 //
745 // \note This constructor is \b NOT available for padded symmetric custom matrices!
746 // \note The matrix does \b NOT take responsibility for the given array of elements!
747 */
748 template< typename MT // Type of the adapted dense matrix
749 , bool SO > // Storage order of the adapted dense matrix
SymmetricMatrix(ElementType * ptr,size_t n)750 inline SymmetricMatrix<MT,SO,true,false>::SymmetricMatrix( ElementType* ptr, size_t n )
751 : matrix_( ptr, n, n ) // The adapted dense matrix
752 {
753 if( !isSymmetric( matrix_ ) ) {
754 BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of symmetric matrix" );
755 }
756
757 BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
758 }
759 /*! \endcond */
760 //*************************************************************************************************
761
762
763 //*************************************************************************************************
764 /*! \cond BLAZE_INTERNAL */
765 /*!\brief Constructor for a symmetric custom matrix of size \f$ n \times n \f$.
766 //
767 // \param ptr The array of elements to be used by the matrix.
768 // \param n The number of rows and columns of the array of elements.
769 // \param nn The total number of elements between two rows/columns.
770 // \exception std::invalid_argument Invalid setup of symmetric custom matrix.
771 //
772 // This constructor creates a symmetric custom matrix of size \f$ n \times n \f$:
773
774 \code
775 using blaze::SymmetricMatrix;
776 using blaze::CustomMatrix;
777 using blaze::unaligned;
778 using blaze::padded;
779
780 using Type = StaticMatrix<int,3UL,3UL>;
781
782 std::vector<Type> memory( 24UL );
783 SymmetricMatrix< CustomMatrix<Type,unaligned,padded> > A( memory.data(), 3UL, 8UL );
784 \endcode
785
786 // The construction fails if ...
787 //
788 // - ... the passed pointer is \c nullptr;
789 // - ... the alignment flag \a AF is set to \a aligned, but the passed pointer is not properly
790 // aligned according to the available instruction set (SSE, AVX, ...);
791 // - ... the specified spacing \a nn is insufficient for the given data type \a Type and the
792 // available instruction set;
793 // - ... the values in the given array do not represent a symmetric matrix.
794 //
795 // In all failure cases a \a std::invalid_argument exception is thrown.
796 //
797 // \note The matrix does \b NOT take responsibility for the given array of elements!
798 */
799 template< typename MT // Type of the adapted dense matrix
800 , bool SO > // Storage order of the adapted dense matrix
SymmetricMatrix(ElementType * ptr,size_t n,size_t nn)801 inline SymmetricMatrix<MT,SO,true,false>::SymmetricMatrix( ElementType* ptr, size_t n, size_t nn )
802 : matrix_( ptr, n, n, nn ) // The adapted dense matrix
803 {
804 if( !isSymmetric( matrix_ ) ) {
805 BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of symmetric matrix" );
806 }
807
808 BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
809 }
810 /*! \endcond */
811 //*************************************************************************************************
812
813
814 //*************************************************************************************************
815 /*! \cond BLAZE_INTERNAL */
816 /*!\brief The copy constructor for SymmetricMatrix.
817 //
818 // \param m The symmetric matrix to be copied.
819 */
820 template< typename MT // Type of the adapted dense matrix
821 , bool SO > // Storage order of the adapted dense matrix
SymmetricMatrix(const SymmetricMatrix & m)822 inline SymmetricMatrix<MT,SO,true,false>::SymmetricMatrix( const SymmetricMatrix& m )
823 : matrix_( m.matrix_ ) // The adapted dense matrix
824 {
825 BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
826 BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
827 }
828 /*! \endcond */
829 //*************************************************************************************************
830
831
832 //*************************************************************************************************
833 /*! \cond BLAZE_INTERNAL */
834 /*!\brief The move constructor for SymmetricMatrix.
835 //
836 // \param m The symmetric matrix to be moved into this instance.
837 */
838 template< typename MT // Type of the adapted dense matrix
839 , bool SO > // Storage order of the adapted dense matrix
SymmetricMatrix(SymmetricMatrix && m)840 inline SymmetricMatrix<MT,SO,true,false>::SymmetricMatrix( SymmetricMatrix&& m ) noexcept
841 : matrix_( std::move( m.matrix_ ) ) // The adapted dense matrix
842 {
843 BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
844 BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
845 }
846 /*! \endcond */
847 //*************************************************************************************************
848
849
850 //*************************************************************************************************
851 /*! \cond BLAZE_INTERNAL */
852 /*!\brief Conversion constructor from different matrices with the same storage order.
853 //
854 // \param m Matrix to be copied.
855 // \exception std::invalid_argument Invalid setup of symmetric matrix.
856 //
857 // This constructor initializes the symmetric matrix as a copy of the given matrix. In case the
858 // given matrix is not a symmetric matrix, a \a std::invalid_argument exception is thrown.
859 */
860 template< typename MT // Type of the adapted dense matrix
861 , bool SO > // Storage order of the adapted dense matrix
862 template< typename MT2 > // Type of the foreign matrix
SymmetricMatrix(const Matrix<MT2,SO> & m)863 inline SymmetricMatrix<MT,SO,true,false>::SymmetricMatrix( const Matrix<MT2,SO>& m )
864 : matrix_() // The adapted dense matrix
865 {
866 using blaze::resize;
867
868 using RT = RemoveAdaptor_t<ResultType_t<MT2> >;
869 using Tmp = If_t< IsComputation_v<MT2>, RT, const MT2& >;
870
871 if( IsSymmetric_v<MT2> ) {
872 resize( matrix_, (*m).rows(), (*m).columns() );
873 assign( *m );
874 }
875 else {
876 Tmp tmp( *m );
877
878 if( !isSymmetric( tmp ) ) {
879 BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of symmetric matrix" );
880 }
881
882 resize( matrix_, tmp.rows(), tmp.rows() );
883 assign( tmp );
884 }
885
886 BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
887 BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
888 }
889 /*! \endcond */
890 //*************************************************************************************************
891
892
893 //*************************************************************************************************
894 /*! \cond BLAZE_INTERNAL */
895 /*!\brief Conversion constructor from different matrices with opposite storage order.
896 //
897 // \param m Matrix to be copied.
898 // \exception std::invalid_argument Invalid setup of symmetric matrix.
899 //
900 // This constructor initializes the symmetric matrix as a copy of the given matrix. In case the
901 // given matrix is not a symmetric matrix, a \a std::invalid_argument exception is thrown.
902 */
903 template< typename MT // Type of the adapted dense matrix
904 , bool SO > // Storage order of the adapted dense matrix
905 template< typename MT2 > // Type of the foreign matrix
SymmetricMatrix(const Matrix<MT2,!SO> & m)906 inline SymmetricMatrix<MT,SO,true,false>::SymmetricMatrix( const Matrix<MT2,!SO>& m )
907 : matrix_() // The adapted dense matrix
908 {
909 using blaze::resize;
910
911 using RT = RemoveAdaptor_t< ResultType_t<MT2> >;
912 using Tmp = If_t< IsComputation_v<MT2>, RT, const MT2& >;
913
914 if( IsSymmetric_v<MT2> ) {
915 resize( matrix_, (*m).rows(), (*m).columns() );
916 assign( trans( *m ) );
917 }
918 else {
919 Tmp tmp( *m );
920
921 if( !isSymmetric( tmp ) ) {
922 BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of symmetric matrix" );
923 }
924
925 resize( matrix_, tmp.rows(), tmp.rows() );
926 assign( trans( tmp ) );
927 }
928
929 BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
930 BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
931 }
932 /*! \endcond */
933 //*************************************************************************************************
934
935
936
937
938 //=================================================================================================
939 //
940 // DATA ACCESS FUNCTIONS
941 //
942 //=================================================================================================
943
944 //*************************************************************************************************
945 /*! \cond BLAZE_INTERNAL */
946 /*!\brief 2D-access to the matrix elements.
947 //
948 // \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
949 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
950 // \return Reference to the accessed value.
951 //
952 // The function call operator provides access to both the elements at position (i,j) and (j,i).
953 // In order to preserve the symmetry of the matrix, any modification to one of the elements will
954 // also be applied to the other element.
955 //
956 // Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
957 // contrast, the at() function is guaranteed to perform a check of the given access indices.
958 */
959 template< typename MT // Type of the adapted dense matrix
960 , bool SO > // Storage order of the adapted dense matrix
961 inline typename SymmetricMatrix<MT,SO,true,false>::Reference
operator()962 SymmetricMatrix<MT,SO,true,false>::operator()( size_t i, size_t j )
963 {
964 BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
965 BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
966
967 if( ( !SO && i > j ) || ( SO && i < j ) )
968 return matrix_(i,j);
969 else
970 return matrix_(j,i);
971 }
972 /*! \endcond */
973 //*************************************************************************************************
974
975
976 //*************************************************************************************************
977 /*! \cond BLAZE_INTERNAL */
978 /*!\brief 2D-access to the matrix elements.
979 //
980 // \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
981 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
982 // \return Reference to the accessed value.
983 //
984 // The function call operator provides access to both the elements at position (i,j) and (j,i).
985 // In order to preserve the symmetry of the matrix, any modification to one of the elements will
986 // also be applied to the other element.
987 //
988 // Note that this function only performs an index check in case BLAZE_USER_ASSERT() is active. In
989 // contrast, the at() function is guaranteed to perform a check of the given access indices.
990 */
991 template< typename MT // Type of the adapted dense matrix
992 , bool SO > // Storage order of the adapted dense matrix
993 inline typename SymmetricMatrix<MT,SO,true,false>::ConstReference
operator()994 SymmetricMatrix<MT,SO,true,false>::operator()( size_t i, size_t j ) const
995 {
996 BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
997 BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
998
999 if( ( !SO && i > j ) || ( SO && i < j ) )
1000 return matrix_(i,j);
1001 else
1002 return matrix_(j,i);
1003 }
1004 /*! \endcond */
1005 //*************************************************************************************************
1006
1007
1008 //*************************************************************************************************
1009 /*! \cond BLAZE_INTERNAL */
1010 /*!\brief Checked access to the matrix elements.
1011 //
1012 // \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
1013 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
1014 // \return Reference to the accessed value.
1015 // \exception std::out_of_range Invalid matrix access index.
1016 //
1017 // The function call operator provides access to both the elements at position (i,j) and (j,i).
1018 // In order to preserve the symmetry of the matrix, any modification to one of the elements will
1019 // also be applied to the other element.
1020 //
1021 // Note that in contrast to the subscript operator this function always performs a check of the
1022 // given access indices.
1023 */
1024 template< typename MT // Type of the adapted dense matrix
1025 , bool SO > // Storage order of the adapted dense matrix
1026 inline typename SymmetricMatrix<MT,SO,true,false>::Reference
at(size_t i,size_t j)1027 SymmetricMatrix<MT,SO,true,false>::at( size_t i, size_t j )
1028 {
1029 if( i >= rows() ) {
1030 BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
1031 }
1032 if( j >= columns() ) {
1033 BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
1034 }
1035 return (*this)(i,j);
1036 }
1037 /*! \endcond */
1038 //*************************************************************************************************
1039
1040
1041 //*************************************************************************************************
1042 /*! \cond BLAZE_INTERNAL */
1043 /*!\brief Checked access to the matrix elements.
1044 //
1045 // \param i Access index for the row. The index has to be in the range \f$[0..N-1]\f$.
1046 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
1047 // \return Reference to the accessed value.
1048 // \exception std::out_of_range Invalid matrix access index.
1049 //
1050 // The function call operator provides access to both the elements at position (i,j) and (j,i).
1051 // In order to preserve the symmetry of the matrix, any modification to one of the elements will
1052 // also be applied to the other element.
1053 //
1054 // Note that in contrast to the subscript operator this function always performs a check of the
1055 // given access indices.
1056 */
1057 template< typename MT // Type of the adapted dense matrix
1058 , bool SO > // Storage order of the adapted dense matrix
1059 inline typename SymmetricMatrix<MT,SO,true,false>::ConstReference
at(size_t i,size_t j)1060 SymmetricMatrix<MT,SO,true,false>::at( size_t i, size_t j ) const
1061 {
1062 if( i >= rows() ) {
1063 BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
1064 }
1065 if( j >= columns() ) {
1066 BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
1067 }
1068 return (*this)(i,j);
1069 }
1070 /*! \endcond */
1071 //*************************************************************************************************
1072
1073
1074 //*************************************************************************************************
1075 /*! \cond BLAZE_INTERNAL */
1076 /*!\brief Low-level data access to the matrix elements.
1077 //
1078 // \return Pointer to the internal element storage.
1079 //
1080 // This function returns a pointer to the internal storage of the symmetric matrix. Note that you
1081 // can NOT assume that all matrix elements lie adjacent to each other! The symmetric matrix may
1082 // use techniques such as padding to improve the alignment of the data. Whereas the number of
1083 // elements within a row/column are given by the \c rows() and \c columns() member functions,
1084 // respectively, the total number of elements including padding is given by the \c spacing()
1085 // member function. Also note that you can NOT assume that the symmetric matrix stores all its
1086 // elements. It may choose to store its elements in a lower or upper triangular matrix fashion.
1087 */
1088 template< typename MT // Type of the adapted dense matrix
1089 , bool SO > // Storage order of the adapted dense matrix
1090 inline typename SymmetricMatrix<MT,SO,true,false>::ConstPointer
data()1091 SymmetricMatrix<MT,SO,true,false>::data() const noexcept
1092 {
1093 return matrix_.data();
1094 }
1095 /*! \endcond */
1096 //*************************************************************************************************
1097
1098
1099 //*************************************************************************************************
1100 /*! \cond BLAZE_INTERNAL */
1101 /*!\brief Low-level data access to the matrix elements of row/column \a i.
1102 //
1103 // \param i The row/column index.
1104 // \return Pointer to the internal element storage.
1105 //
1106 // This function returns a pointer to the internal storage for the elements in row/column \a i.
1107 // Note that you can NOT assume that the symmetric matrix stores all its elements. It may choose
1108 // to store its elements in a lower or upper triangular matrix fashion.
1109 */
1110 template< typename MT // Type of the adapted dense matrix
1111 , bool SO > // Storage order of the adapted dense matrix
1112 inline typename SymmetricMatrix<MT,SO,true,false>::ConstPointer
data(size_t i)1113 SymmetricMatrix<MT,SO,true,false>::data( size_t i ) const noexcept
1114 {
1115 return matrix_.data(i);
1116 }
1117 /*! \endcond */
1118 //*************************************************************************************************
1119
1120
1121 //*************************************************************************************************
1122 /*! \cond BLAZE_INTERNAL */
1123 /*!\brief Returns an iterator to the first element of row/column \a i.
1124 //
1125 // \param i The row/column index.
1126 // \return Iterator to the first element of row/column \a i.
1127 //
1128 // This function returns a row/column iterator to the first element of row/column \a i. In case
1129 // the symmetric matrix adapts a \a rowMajor dense matrix the function returns an iterator to
1130 // the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
1131 // returns an iterator to the first element of column \a i.
1132 */
1133 template< typename MT // Type of the adapted dense matrix
1134 , bool SO > // Storage order of the adapted dense matrix
1135 inline typename SymmetricMatrix<MT,SO,true,false>::Iterator
begin(size_t i)1136 SymmetricMatrix<MT,SO,true,false>::begin( size_t i )
1137 {
1138 if( SO )
1139 return Iterator( matrix_, 0UL, i );
1140 else
1141 return Iterator( matrix_, i, 0UL );
1142 }
1143 /*! \endcond */
1144 //*************************************************************************************************
1145
1146
1147 //*************************************************************************************************
1148 /*! \cond BLAZE_INTERNAL */
1149 /*!\brief Returns an iterator to the first element of row/column \a i.
1150 //
1151 // \param i The row/column index.
1152 // \return Iterator to the first element of row/column \a i.
1153 //
1154 // This function returns a row/column iterator to the first element of row/column \a i. In case
1155 // the symmetric matrix adapts a \a rowMajor dense matrix the function returns an iterator to
1156 // the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
1157 // returns an iterator to the first element of column \a i.
1158 */
1159 template< typename MT // Type of the adapted dense matrix
1160 , bool SO > // Storage order of the adapted dense matrix
1161 inline typename SymmetricMatrix<MT,SO,true,false>::ConstIterator
begin(size_t i)1162 SymmetricMatrix<MT,SO,true,false>::begin( size_t i ) const
1163 {
1164 if( SO )
1165 return ConstIterator( matrix_, 0UL, i );
1166 else
1167 return ConstIterator( matrix_, i, 0UL );
1168 }
1169 /*! \endcond */
1170 //*************************************************************************************************
1171
1172
1173 //*************************************************************************************************
1174 /*! \cond BLAZE_INTERNAL */
1175 /*!\brief Returns an iterator to the first element of row/column \a i.
1176 //
1177 // \param i The row/column index.
1178 // \return Iterator to the first element of row/column \a i.
1179 //
1180 // This function returns a row/column iterator to the first element of row/column \a i. In case
1181 // the symmetric matrix adapts a \a rowMajor dense matrix the function returns an iterator to
1182 // the first element of row \a i, in case it adapts a \a columnMajor dense matrix the function
1183 // returns an iterator to the first element of column \a i.
1184 */
1185 template< typename MT // Type of the adapted dense matrix
1186 , bool SO > // Storage order of the adapted dense matrix
1187 inline typename SymmetricMatrix<MT,SO,true,false>::ConstIterator
cbegin(size_t i)1188 SymmetricMatrix<MT,SO,true,false>::cbegin( size_t i ) const
1189 {
1190 if( SO )
1191 return ConstIterator( matrix_, 0UL, i );
1192 else
1193 return ConstIterator( matrix_, i, 0UL );
1194 }
1195 /*! \endcond */
1196 //*************************************************************************************************
1197
1198
1199 //*************************************************************************************************
1200 /*! \cond BLAZE_INTERNAL */
1201 /*!\brief Returns an iterator just past the last element of row/column \a i.
1202 //
1203 // \param i The row/column index.
1204 // \return Iterator just past the last element of row/column \a i.
1205 //
1206 // This function returns an row/column iterator just past the last element of row/column \a i.
1207 // In case the symmetric matrix adapts a \a rowMajor dense matrix the function returns an iterator
1208 // just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
1209 // function returns an iterator just past the last element of column \a i.
1210 */
1211 template< typename MT // Type of the adapted dense matrix
1212 , bool SO > // Storage order of the adapted dense matrix
1213 inline typename SymmetricMatrix<MT,SO,true,false>::Iterator
end(size_t i)1214 SymmetricMatrix<MT,SO,true,false>::end( size_t i )
1215 {
1216 if( SO )
1217 return Iterator( matrix_, rows(), i );
1218 else
1219 return Iterator( matrix_, i, columns() );
1220 }
1221 /*! \endcond */
1222 //*************************************************************************************************
1223
1224
1225 //*************************************************************************************************
1226 /*! \cond BLAZE_INTERNAL */
1227 /*!\brief Returns an iterator just past the last element of row/column \a i.
1228 //
1229 // \param i The row/column index.
1230 // \return Iterator just past the last element of row/column \a i.
1231 //
1232 // This function returns an row/column iterator just past the last element of row/column \a i.
1233 // In case the symmetric matrix adapts a \a rowMajor dense matrix the function returns an iterator
1234 // just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
1235 // function returns an iterator just past the last element of column \a i.
1236 */
1237 template< typename MT // Type of the adapted dense matrix
1238 , bool SO > // Storage order of the adapted dense matrix
1239 inline typename SymmetricMatrix<MT,SO,true,false>::ConstIterator
end(size_t i)1240 SymmetricMatrix<MT,SO,true,false>::end( size_t i ) const
1241 {
1242 if( SO )
1243 return ConstIterator( matrix_, rows(), i );
1244 else
1245 return ConstIterator( matrix_, i, columns() );
1246 }
1247 /*! \endcond */
1248 //*************************************************************************************************
1249
1250
1251 //*************************************************************************************************
1252 /*! \cond BLAZE_INTERNAL */
1253 /*!\brief Returns an iterator just past the last element of row/column \a i.
1254 //
1255 // \param i The row/column index.
1256 // \return Iterator just past the last element of row/column \a i.
1257 //
1258 // This function returns an row/column iterator just past the last element of row/column \a i.
1259 // In case the symmetric matrix adapts a \a rowMajor dense matrix the function returns an iterator
1260 // just past the last element of row \a i, in case it adapts a \a columnMajor dense matrix the
1261 // function returns an iterator just past the last element of column \a i.
1262 */
1263 template< typename MT // Type of the adapted dense matrix
1264 , bool SO > // Storage order of the adapted dense matrix
1265 inline typename SymmetricMatrix<MT,SO,true,false>::ConstIterator
cend(size_t i)1266 SymmetricMatrix<MT,SO,true,false>::cend( size_t i ) const
1267 {
1268 if( SO )
1269 return ConstIterator( matrix_, rows(), i );
1270 else
1271 return ConstIterator( matrix_, i, columns() );
1272 }
1273 /*! \endcond */
1274 //*************************************************************************************************
1275
1276
1277
1278
1279 //=================================================================================================
1280 //
1281 // ASSIGNMENT OPERATORS
1282 //
1283 //=================================================================================================
1284
1285 //*************************************************************************************************
1286 /*! \cond BLAZE_INTERNAL */
1287 /*!\brief Copy assignment operator for SymmetricMatrix.
1288 //
1289 // \param rhs Matrix to be copied.
1290 // \return Reference to the assigned matrix.
1291 //
1292 // If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
1293 // matrix and initialized as a copy of this matrix.
1294 */
1295 template< typename MT // Type of the adapted dense matrix
1296 , bool SO > // Storage order of the adapted dense matrix
1297 inline SymmetricMatrix<MT,SO,true,false>&
1298 SymmetricMatrix<MT,SO,true,false>::operator=( const SymmetricMatrix& rhs )
1299 {
1300 using blaze::resize;
1301
1302 if( &rhs == this ) return *this;
1303
1304 resize( matrix_, rhs.rows(), rhs.columns() );
1305 assign( rhs );
1306
1307 BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
1308 BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
1309
1310 return *this;
1311 }
1312 /*! \endcond */
1313 //*************************************************************************************************
1314
1315
1316 //*************************************************************************************************
1317 /*! \cond BLAZE_INTERNAL */
1318 /*!\brief Move assignment operator for SymmetricMatrix.
1319 //
1320 // \param rhs The matrix to be moved into this instance.
1321 // \return Reference to the assigned matrix.
1322 */
1323 template< typename MT // Type of the adapted dense matrix
1324 , bool SO > // Storage order of the adapted dense matrix
1325 inline SymmetricMatrix<MT,SO,true,false>&
1326 SymmetricMatrix<MT,SO,true,false>::operator=( SymmetricMatrix&& rhs ) noexcept
1327 {
1328 matrix_ = std::move( rhs.matrix_ );
1329
1330 BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
1331 BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
1332
1333 return *this;
1334 }
1335 /*! \endcond */
1336 //*************************************************************************************************
1337
1338
1339 //*************************************************************************************************
1340 /*! \cond BLAZE_INTERNAL */
1341 /*!\brief Assignment operator for general matrices.
1342 //
1343 // \param rhs The general matrix to be copied.
1344 // \return Reference to the assigned matrix.
1345 // \exception std::invalid_argument Invalid assignment to symmetric matrix.
1346 // \exception std::invalid_argument Matrix sizes do not match.
1347 //
1348 // If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
1349 // matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
1350 // a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
1351 // symmetric matrix. Otherwise, a \a std::invalid_argument exception is thrown.
1352 */
1353 template< typename MT // Type of the adapted dense matrix
1354 , bool SO > // Storage order of the adapted dense matrix
1355 template< typename MT2 > // Type of the right-hand side matrix
1356 inline auto SymmetricMatrix<MT,SO,true,false>::operator=( const Matrix<MT2,SO>& rhs )
1357 -> DisableIf_t< IsComputation_v<MT2>, SymmetricMatrix& >
1358 {
1359 using blaze::resize;
1360
1361 if( !IsSymmetric_v<MT2> && !isSymmetric( *rhs ) ) {
1362 BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
1363 }
1364
1365 if( (*rhs).isAliased( this ) ) {
1366 SymmetricMatrix tmp( *rhs );
1367 swap( tmp );
1368 }
1369 else {
1370 resize( matrix_, (*rhs).rows(), (*rhs).columns() );
1371 if( IsSparseMatrix_v<MT2> )
1372 reset();
1373 assign( *rhs );
1374 }
1375
1376 BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
1377 BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
1378
1379 return *this;
1380 }
1381 /*! \endcond */
1382 //*************************************************************************************************
1383
1384
1385 //*************************************************************************************************
1386 /*! \cond BLAZE_INTERNAL */
1387 /*!\brief Assignment operator for matrix computations.
1388 //
1389 // \param rhs The matrix computation to be copied.
1390 // \return Reference to the assigned matrix.
1391 // \exception std::invalid_argument Invalid assignment to symmetric matrix.
1392 // \exception std::invalid_argument Matrix sizes do not match.
1393 //
1394 // If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
1395 // matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
1396 // a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
1397 // symmetric matrix. Otherwise, a \a std::invalid_argument exception is thrown.
1398 */
1399 template< typename MT // Type of the adapted dense matrix
1400 , bool SO > // Storage order of the adapted dense matrix
1401 template< typename MT2 > // Type of the right-hand side matrix
1402 inline auto SymmetricMatrix<MT,SO,true,false>::operator=( const Matrix<MT2,SO>& rhs )
1403 -> EnableIf_t< IsComputation_v<MT2>, SymmetricMatrix& >
1404 {
1405 using blaze::resize;
1406
1407 using Tmp = If_t< IsSymmetric_v<MT2>, CompositeType_t<MT2>, ResultType_t<MT2> >;
1408
1409 if( !IsSquare_v<MT2> && !isSquare( *rhs ) ) {
1410 BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
1411 }
1412
1413 Tmp tmp( *rhs );
1414
1415 if( !IsSymmetric_v<Tmp> && !isSymmetric( tmp ) ) {
1416 BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
1417 }
1418
1419 BLAZE_INTERNAL_ASSERT( !tmp.canAlias( this ), "Aliasing detected" );
1420
1421 resize( matrix_, tmp.rows(), tmp.columns() );
1422 if( IsSparseMatrix_v<Tmp> )
1423 reset();
1424 assign( tmp );
1425
1426 BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
1427 BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
1428
1429 return *this;
1430 }
1431 /*! \endcond */
1432 //*************************************************************************************************
1433
1434
1435 //*************************************************************************************************
1436 /*! \cond BLAZE_INTERNAL */
1437 /*!\brief Assignment operator for matrices with opposite storage order.
1438 //
1439 // \param rhs The right-hand side matrix to be copied.
1440 // \return Reference to the assigned matrix.
1441 // \exception std::invalid_argument Invalid assignment to symmetric matrix.
1442 // \exception std::invalid_argument Matrix sizes do not match.
1443 //
1444 // If possible and necessary, the matrix is resized according to the given \f$ N \times N \f$
1445 // matrix and initialized as a copy of this matrix. If the matrix cannot be resized accordingly,
1446 // a \a std::invalid_argument exception is thrown. Also note that the given matrix must be a
1447 // symmetric matrix. Otherwise, a \a std::invalid_argument exception is thrown.
1448 */
1449 template< typename MT // Type of the adapted dense matrix
1450 , bool SO > // Storage order of the adapted dense matrix
1451 template< typename MT2 > // Type of the right-hand side matrix
1452 inline auto SymmetricMatrix<MT,SO,true,false>::operator=( const Matrix<MT2,!SO>& rhs )
1453 -> SymmetricMatrix&
1454 {
1455 return this->operator=( trans( *rhs ) );
1456 }
1457 /*! \endcond */
1458 //*************************************************************************************************
1459
1460
1461 //*************************************************************************************************
1462 /*! \cond BLAZE_INTERNAL */
1463 /*!\brief Addition assignment operator for the addition of a general matrix (\f$ A+=B \f$).
1464 //
1465 // \param rhs The right-hand side general matrix to be added.
1466 // \return Reference to the matrix.
1467 // \exception std::invalid_argument Invalid assignment to symmetric matrix.
1468 //
1469 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
1470 // is thrown. Also note that the result of the addition operation must be a symmetric matrix, i.e.
1471 // the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix, a
1472 // \a std::invalid_argument exception is thrown.
1473 */
1474 template< typename MT // Type of the adapted dense matrix
1475 , bool SO > // Storage order of the adapted dense matrix
1476 template< typename MT2 > // Type of the right-hand side matrix
1477 inline auto SymmetricMatrix<MT,SO,true,false>::operator+=( const Matrix<MT2,SO>& rhs )
1478 -> DisableIf_t< IsComputation_v<MT2>, SymmetricMatrix& >
1479 {
1480 if( !IsSymmetric_v<MT2> && !isSymmetric( *rhs ) ) {
1481 BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
1482 }
1483
1484 addAssign( *rhs );
1485
1486 BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
1487 BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
1488
1489 return *this;
1490 }
1491 /*! \endcond */
1492 //*************************************************************************************************
1493
1494
1495 //*************************************************************************************************
1496 /*! \cond BLAZE_INTERNAL */
1497 /*!\brief Addition assignment operator for the addition of a matrix computation (\f$ A+=B \f$).
1498 //
1499 // \param rhs The right-hand side matrix computation to be added.
1500 // \return Reference to the matrix.
1501 // \exception std::invalid_argument Invalid assignment to symmetric matrix.
1502 //
1503 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
1504 // is thrown. Also note that the result of the addition operation must be a symmetric matrix, i.e.
1505 // the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix, a
1506 // \a std::invalid_argument exception is thrown.
1507 */
1508 template< typename MT // Type of the adapted dense matrix
1509 , bool SO > // Storage order of the adapted dense matrix
1510 template< typename MT2 > // Type of the right-hand side matrix
1511 inline auto SymmetricMatrix<MT,SO,true,false>::operator+=( const Matrix<MT2,SO>& rhs )
1512 -> EnableIf_t< IsComputation_v<MT2>, SymmetricMatrix& >
1513 {
1514 using Tmp = If_t< IsSymmetric_v<MT2>, CompositeType_t<MT2>, ResultType_t<MT2> >;
1515
1516 if( !IsSquare_v<MT2> && !isSquare( *rhs ) ) {
1517 BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
1518 }
1519
1520 Tmp tmp( *rhs );
1521
1522 if( !IsSymmetric_v<Tmp> && !isSymmetric( tmp ) ) {
1523 BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
1524 }
1525
1526 BLAZE_INTERNAL_ASSERT( !tmp.canAlias( this ), "Aliasing detected" );
1527
1528 addAssign( tmp );
1529
1530 BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
1531 BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
1532
1533 return *this;
1534 }
1535 /*! \endcond */
1536 //*************************************************************************************************
1537
1538
1539 //*************************************************************************************************
1540 /*! \cond BLAZE_INTERNAL */
1541 /*!\brief Addition assignment operator for the addition of a matrix with opposite storage order
1542 // (\f$ A+=B \f$).
1543 //
1544 // \param rhs The right-hand side matrix to be added.
1545 // \return Reference to the matrix.
1546 // \exception std::invalid_argument Invalid assignment to symmetric matrix.
1547 //
1548 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
1549 // is thrown. Also note that the result of the addition operation must be a symmetric matrix, i.e.
1550 // the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix, a
1551 // \a std::invalid_argument exception is thrown.
1552 */
1553 template< typename MT // Type of the adapted dense matrix
1554 , bool SO > // Storage order of the adapted dense matrix
1555 template< typename MT2 > // Type of the right-hand side matrix
1556 inline auto SymmetricMatrix<MT,SO,true,false>::operator+=( const Matrix<MT2,!SO>& rhs )
1557 -> SymmetricMatrix&
1558 {
1559 return this->operator+=( trans( *rhs ) );
1560 }
1561 /*! \endcond */
1562 //*************************************************************************************************
1563
1564
1565 //*************************************************************************************************
1566 /*! \cond BLAZE_INTERNAL */
1567 /*!\brief Subtraction assignment operator for the subtraction of a general matrix (\f$ A-=B \f$).
1568 //
1569 // \param rhs The right-hand side general matrix to be subtracted.
1570 // \return Reference to the matrix.
1571 // \exception std::invalid_argument Invalid assignment to symmetric matrix.
1572 //
1573 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
1574 // is thrown. Also note that the result of the subtraction operation must be a symmetric matrix,
1575 // i.e. the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix,
1576 // a \a std::invalid_argument exception is thrown.
1577 */
1578 template< typename MT // Type of the adapted dense matrix
1579 , bool SO > // Storage order of the adapted dense matrix
1580 template< typename MT2 > // Type of the right-hand side matrix
1581 inline auto SymmetricMatrix<MT,SO,true,false>::operator-=( const Matrix<MT2,SO>& rhs )
1582 -> DisableIf_t< IsComputation_v<MT2>, SymmetricMatrix& >
1583 {
1584 if( !IsSymmetric_v<MT2> && !isSymmetric( *rhs ) ) {
1585 BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
1586 }
1587
1588 subAssign( *rhs );
1589
1590 BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
1591 BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
1592
1593 return *this;
1594 }
1595 /*! \endcond */
1596 //*************************************************************************************************
1597
1598
1599 //*************************************************************************************************
1600 /*! \cond BLAZE_INTERNAL */
1601 /*!\brief Subtraction assignment operator for the subtraction of a matrix computation (\f$ A-=B \f$).
1602 //
1603 // \param rhs The right-hand side matrix computation to be subtracted.
1604 // \return Reference to the matrix.
1605 // \exception std::invalid_argument Invalid assignment to symmetric matrix.
1606 //
1607 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
1608 // is thrown. Also note that the result of the subtraction operation must be a symmetric matrix,
1609 // i.e. the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix,
1610 // a \a std::invalid_argument exception is thrown.
1611 */
1612 template< typename MT // Type of the adapted dense matrix
1613 , bool SO > // Storage order of the adapted dense matrix
1614 template< typename MT2 > // Type of the right-hand side matrix
1615 inline auto SymmetricMatrix<MT,SO,true,false>::operator-=( const Matrix<MT2,SO>& rhs )
1616 -> EnableIf_t< IsComputation_v<MT2>, SymmetricMatrix& >
1617 {
1618 using Tmp = If_t< IsSymmetric_v<MT2>, CompositeType_t<MT2>, ResultType_t<MT2> >;
1619
1620 if( !IsSquare_v<MT2> && !isSquare( *rhs ) ) {
1621 BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
1622 }
1623
1624 Tmp tmp( *rhs );
1625
1626 if( !IsSymmetric_v<Tmp> && !isSymmetric( tmp ) ) {
1627 BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
1628 }
1629
1630 BLAZE_INTERNAL_ASSERT( !tmp.canAlias( this ), "Aliasing detected" );
1631
1632 subAssign( tmp );
1633
1634 BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
1635 BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
1636
1637 return *this;
1638 }
1639 /*! \endcond */
1640 //*************************************************************************************************
1641
1642
1643 //*************************************************************************************************
1644 /*! \cond BLAZE_INTERNAL */
1645 /*!\brief Subtraction assignment operator for the subtraction of a matrix with opposite storage
1646 // order (\f$ A-=B \f$).
1647 //
1648 // \param rhs The right-hand side matrix to be subtracted.
1649 // \return Reference to the matrix.
1650 // \exception std::invalid_argument Invalid assignment to symmetric matrix.
1651 //
1652 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
1653 // is thrown. Also note that the result of the subtraction operation must be a symmetric matrix,
1654 // i.e. the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix,
1655 // a \a std::invalid_argument exception is thrown.
1656 */
1657 template< typename MT // Type of the adapted dense matrix
1658 , bool SO > // Storage order of the adapted dense matrix
1659 template< typename MT2 > // Type of the right-hand side matrix
1660 inline auto SymmetricMatrix<MT,SO,true,false>::operator-=( const Matrix<MT2,!SO>& rhs )
1661 -> SymmetricMatrix&
1662 {
1663 return this->operator-=( trans( *rhs ) );
1664 }
1665 /*! \endcond */
1666 //*************************************************************************************************
1667
1668
1669 //*************************************************************************************************
1670 /*! \cond BLAZE_INTERNAL */
1671 /*!\brief Schur product assignment operator for the multiplication of a general matrix
1672 // (\f$ A\circ=B \f$).
1673 //
1674 // \param rhs The right-hand side general matrix for the Schur product.
1675 // \return Reference to the matrix.
1676 // \exception std::invalid_argument Invalid assignment to symmetric matrix.
1677 //
1678 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
1679 // is thrown. Also note that the result of the Schur product operation must be a symmetric matrix,
1680 // i.e. the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix,
1681 // a \a std::invalid_argument exception is thrown.
1682 */
1683 template< typename MT // Type of the adapted dense matrix
1684 , bool SO > // Storage order of the adapted dense matrix
1685 template< typename MT2 > // Type of the right-hand side matrix
1686 inline auto SymmetricMatrix<MT,SO,true,false>::operator%=( const Matrix<MT2,SO>& rhs )
1687 -> DisableIf_t< IsComputation_v<MT2>, SymmetricMatrix& >
1688 {
1689 if( !IsSymmetric_v<MT2> && !isSymmetric( *rhs ) ) {
1690 BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
1691 }
1692
1693 schurAssign( *rhs );
1694
1695 BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
1696 BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
1697
1698 return *this;
1699 }
1700 /*! \endcond */
1701 //*************************************************************************************************
1702
1703
1704 //*************************************************************************************************
1705 /*! \cond BLAZE_INTERNAL */
1706 /*!\brief Schur product assignment operator for the multiplication of a matrix computation
1707 // (\f$ A&=B \f$).
1708 //
1709 // \param rhs The right-hand side matrix computation for the Schur product.
1710 // \return Reference to the matrix.
1711 // \exception std::invalid_argument Invalid assignment to symmetric matrix.
1712 //
1713 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
1714 // is thrown. Also note that the result of the Schur product operation must be a symmetric matrix,
1715 // i.e. the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix,
1716 // a \a std::invalid_argument exception is thrown.
1717 */
1718 template< typename MT // Type of the adapted dense matrix
1719 , bool SO > // Storage order of the adapted dense matrix
1720 template< typename MT2 > // Type of the right-hand side matrix
1721 inline auto SymmetricMatrix<MT,SO,true,false>::operator%=( const Matrix<MT2,SO>& rhs )
1722 -> EnableIf_t< IsComputation_v<MT2>, SymmetricMatrix& >
1723 {
1724 using Tmp = If_t< IsSymmetric_v<MT2>, CompositeType_t<MT2>, ResultType_t<MT2> >;
1725
1726 if( !IsSquare_v<MT2> && !isSquare( *rhs ) ) {
1727 BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
1728 }
1729
1730 Tmp tmp( *rhs );
1731
1732 if( !IsSymmetric_v<Tmp> && !isSymmetric( tmp ) ) {
1733 BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" );
1734 }
1735
1736 BLAZE_INTERNAL_ASSERT( !tmp.canAlias( this ), "Aliasing detected" );
1737
1738 schurAssign( tmp );
1739
1740 BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
1741 BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
1742
1743 return *this;
1744 }
1745 /*! \endcond */
1746 //*************************************************************************************************
1747
1748
1749 //*************************************************************************************************
1750 /*! \cond BLAZE_INTERNAL */
1751 /*!\brief Schur product assignment operator for the multiplication of a matrix with opposite
1752 // storage order (\f$ A\circ=B \f$).
1753 //
1754 // \param rhs The right-hand side matrix for the Schur product.
1755 // \return Reference to the matrix.
1756 // \exception std::invalid_argument Invalid assignment to symmetric matrix.
1757 //
1758 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
1759 // is thrown. Also note that the result of the Schur product operation must be a symmetric matrix,
1760 // i.e. the given matrix must be a symmetric matrix. In case the result is not a symmetric matrix,
1761 // a \a std::invalid_argument exception is thrown.
1762 */
1763 template< typename MT // Type of the adapted dense matrix
1764 , bool SO > // Storage order of the adapted dense matrix
1765 template< typename MT2 > // Type of the right-hand side matrix
1766 inline auto SymmetricMatrix<MT,SO,true,false>::operator%=( const Matrix<MT2,!SO>& rhs )
1767 -> SymmetricMatrix&
1768 {
1769 return this->operator%=( trans( *rhs ) );
1770 }
1771 /*! \endcond */
1772 //*************************************************************************************************
1773
1774
1775 //*************************************************************************************************
1776 /*! \cond BLAZE_INTERNAL */
1777 /*!\brief Multiplication assignment operator for the multiplication between a matrix and
1778 // a scalar value (\f$ A*=s \f$).
1779 //
1780 // \param rhs The right-hand side scalar value for the multiplication.
1781 // \return Reference to the matrix.
1782 */
1783 template< typename MT // Type of the adapted dense matrix
1784 , bool SO > // Storage order of the adapted dense matrix
1785 template< typename ST > // Data type of the right-hand side scalar
1786 inline auto SymmetricMatrix<MT,SO,true,false>::operator*=( ST rhs )
1787 -> EnableIf_t< IsScalar_v<ST>, SymmetricMatrix& >
1788 {
1789 if( SO ) {
1790 for( size_t j=0UL; j<columns(); ++j )
1791 for( size_t i=0UL; i<=j; ++i )
1792 matrix_(i,j) *= rhs;
1793 }
1794 else {
1795 for( size_t i=0UL; i<rows(); ++i )
1796 for( size_t j=0UL; j<=i; ++j )
1797 matrix_(i,j) *= rhs;
1798 }
1799
1800 return *this;
1801 }
1802 /*! \endcond */
1803 //*************************************************************************************************
1804
1805
1806 //*************************************************************************************************
1807 /*! \cond BLAZE_INTERNAL */
1808 /*!\brief Division assignment operator for the division of a matrix by a scalar value
1809 // (\f$ A/=s \f$).
1810 //
1811 // \param rhs The right-hand side scalar value for the division.
1812 // \return Reference to the matrix.
1813 */
1814 template< typename MT // Type of the adapted dense matrix
1815 , bool SO > // Storage order of the adapted dense matrix
1816 template< typename ST > // Data type of the right-hand side scalar
1817 inline auto SymmetricMatrix<MT,SO,true,false>::operator/=( ST rhs )
1818 -> EnableIf_t< IsScalar_v<ST>, SymmetricMatrix& >
1819 {
1820 BLAZE_USER_ASSERT( !isZero( rhs ), "Division by zero detected" );
1821
1822 if( SO ) {
1823 for( size_t j=0UL; j<columns(); ++j )
1824 for( size_t i=0UL; i<=j; ++i )
1825 matrix_(i,j) /= rhs;
1826 }
1827 else {
1828 for( size_t i=0UL; i<rows(); ++i )
1829 for( size_t j=0UL; j<=i; ++j )
1830 matrix_(i,j) /= rhs;
1831 }
1832
1833 return *this;
1834 }
1835 /*! \endcond */
1836 //*************************************************************************************************
1837
1838
1839
1840
1841 //=================================================================================================
1842 //
1843 // UTILITY FUNCTIONS
1844 //
1845 //=================================================================================================
1846
1847 //*************************************************************************************************
1848 /*! \cond BLAZE_INTERNAL */
1849 /*!\brief Returns the current number of rows of the matrix.
1850 //
1851 // \return The number of rows of the matrix.
1852 */
1853 template< typename MT // Type of the adapted dense matrix
1854 , bool SO > // Storage order of the adapted dense matrix
rows()1855 inline size_t SymmetricMatrix<MT,SO,true,false>::rows() const noexcept
1856 {
1857 return matrix_.rows();
1858 }
1859 /*! \endcond */
1860 //*************************************************************************************************
1861
1862
1863 //*************************************************************************************************
1864 /*! \cond BLAZE_INTERNAL */
1865 /*!\brief Returns the current number of columns of the matrix.
1866 //
1867 // \return The number of columns of the matrix.
1868 */
1869 template< typename MT // Type of the adapted dense matrix
1870 , bool SO > // Storage order of the adapted dense matrix
columns()1871 inline size_t SymmetricMatrix<MT,SO,true,false>::columns() const noexcept
1872 {
1873 return matrix_.columns();
1874 }
1875 /*! \endcond */
1876 //*************************************************************************************************
1877
1878
1879 //*************************************************************************************************
1880 /*! \cond BLAZE_INTERNAL */
1881 /*!\brief Returns the spacing between the beginning of two rows/columns.
1882 //
1883 // \return The spacing between the beginning of two rows/columns.
1884 //
1885 // This function returns the spacing between the beginning of two rows/columns, i.e.
1886 // the total number of elements of a row/column. In case the symmetric matrix adapts a
1887 // \a rowMajor dense matrix the function returns the spacing between two rows, in case
1888 // it adapts a \a columnMajor dense matrix the function returns the spacing between two
1889 // columns.
1890 */
1891 template< typename MT // Type of the adapted dense matrix
1892 , bool SO > // Storage order of the adapted dense matrix
spacing()1893 inline size_t SymmetricMatrix<MT,SO,true,false>::spacing() const noexcept
1894 {
1895 return matrix_.spacing();
1896 }
1897 /*! \endcond */
1898 //*************************************************************************************************
1899
1900
1901 //*************************************************************************************************
1902 /*! \cond BLAZE_INTERNAL */
1903 /*!\brief Returns the maximum capacity of the matrix.
1904 //
1905 // \return The capacity of the matrix.
1906 */
1907 template< typename MT // Type of the adapted dense matrix
1908 , bool SO > // Storage order of the adapted dense matrix
capacity()1909 inline size_t SymmetricMatrix<MT,SO,true,false>::capacity() const noexcept
1910 {
1911 return matrix_.capacity();
1912 }
1913 /*! \endcond */
1914 //*************************************************************************************************
1915
1916
1917 //*************************************************************************************************
1918 /*! \cond BLAZE_INTERNAL */
1919 /*!\brief Returns the current capacity of the specified row/column.
1920 //
1921 // \param i The index of the row/column.
1922 // \return The current capacity of row/column \a i.
1923 //
1924 // This function returns the current capacity of the specified row/column. In case the symmetric
1925 // matrix adapts a \a rowMajor dense matrix the function returns the capacity of row \a i, in
1926 // case it adapts a \a columnMajor dense matrix the function returns the capacity of column \a i.
1927 */
1928 template< typename MT // Type of the adapted dense matrix
1929 , bool SO > // Storage order of the adapted dense matrix
capacity(size_t i)1930 inline size_t SymmetricMatrix<MT,SO,true,false>::capacity( size_t i ) const noexcept
1931 {
1932 return matrix_.capacity(i);
1933 }
1934 /*! \endcond */
1935 //*************************************************************************************************
1936
1937
1938 //*************************************************************************************************
1939 /*! \cond BLAZE_INTERNAL */
1940 /*!\brief Returns the total number of non-zero elements in the matrix
1941 //
1942 // \return The number of non-zero elements in the symmetric matrix.
1943 */
1944 template< typename MT // Type of the adapted dense matrix
1945 , bool SO > // Storage order of the adapted dense matrix
nonZeros()1946 inline size_t SymmetricMatrix<MT,SO,true,false>::nonZeros() const
1947 {
1948 size_t nonzeros( 0UL );
1949
1950 if( SO )
1951 {
1952 for( size_t j=0UL; j<columns(); ++j ) {
1953 for( size_t i=0UL; i<j; ++i ) {
1954 if( !isDefault( matrix_(i,j) ) )
1955 nonzeros += 2UL;
1956 }
1957 if( !isDefault( matrix_(j,j) ) )
1958 ++nonzeros;
1959 }
1960 }
1961 else
1962 {
1963 for( size_t i=0UL; i<rows(); ++i ) {
1964 for( size_t j=0UL; j<i; ++j ) {
1965 if( !isDefault( matrix_(i,j) ) )
1966 nonzeros += 2UL;
1967 }
1968 if( !isDefault( matrix_(i,i) ) )
1969 ++nonzeros;
1970 }
1971 }
1972
1973 return nonzeros;
1974 }
1975 /*! \endcond */
1976 //*************************************************************************************************
1977
1978
1979 //*************************************************************************************************
1980 /*! \cond BLAZE_INTERNAL */
1981 /*!\brief Returns the number of non-zero elements in the specified row/column.
1982 //
1983 // \param i The index of the row/column.
1984 // \return The number of non-zero elements of row/column \a i.
1985 //
1986 // This function returns the current number of non-zero elements in the specified row/column. In
1987 // case the symmetric matrix adapts a \a rowMajor dense matrix the function returns the number of
1988 // non-zero elements in row \a i, in case it adapts a to \a columnMajor dense matrix the function
1989 // returns the number of non-zero elements in column \a i.
1990 */
1991 template< typename MT // Type of the adapted dense matrix
1992 , bool SO > // Storage order of the adapted dense matrix
nonZeros(size_t i)1993 inline size_t SymmetricMatrix<MT,SO,true,false>::nonZeros( size_t i ) const
1994 {
1995 size_t nonzeros( 0UL );
1996
1997 if( SO )
1998 {
1999 for( size_t j=0UL; j<i; ++j ) {
2000 if( !isDefault( matrix_(j,i) ) )
2001 ++nonzeros;
2002 }
2003 for( size_t j=i; j<rows(); ++j ) {
2004 if( !isDefault( matrix_(i,j) ) )
2005 ++nonzeros;
2006 }
2007 }
2008 else
2009 {
2010 for( size_t j=0UL; j<i; ++j ) {
2011 if( !isDefault( matrix_(i,j) ) )
2012 ++nonzeros;
2013 }
2014 for( size_t j=i; j<rows(); ++j ) {
2015 if( !isDefault( matrix_(j,i) ) )
2016 ++nonzeros;
2017 }
2018 }
2019
2020 return nonzeros;
2021 }
2022 /*! \endcond */
2023 //*************************************************************************************************
2024
2025
2026 //*************************************************************************************************
2027 /*! \cond BLAZE_INTERNAL */
2028 /*!\brief Reset to the default initial values.
2029 //
2030 // \return void
2031 */
2032 template< typename MT // Type of the adapted dense matrix
2033 , bool SO > // Storage order of the adapted dense matrix
reset()2034 inline void SymmetricMatrix<MT,SO,true,false>::reset()
2035 {
2036 using blaze::clear;
2037
2038 if( SO ) {
2039 for( size_t j=0UL; j<columns(); ++j )
2040 for( size_t i=0UL; i<=j; ++i )
2041 clear( matrix_(i,j) );
2042 }
2043 else {
2044 for( size_t i=0UL; i<rows(); ++i )
2045 for( size_t j=0UL; j<=i; ++j )
2046 clear( matrix_(i,j) );
2047 }
2048 }
2049 /*! \endcond */
2050 //*************************************************************************************************
2051
2052
2053 //*************************************************************************************************
2054 /*! \cond BLAZE_INTERNAL */
2055 /*!\brief Reset the specified row \b and column to the default initial values.
2056 //
2057 // \param i The index of the row/column.
2058 // \return void
2059 // \exception std::invalid_argument Invalid row/column access index.
2060 //
2061 // This function resets the values in the specified row \b and column to their default value.
2062 // The following example demonstrates this by means of a \f$ 5 \times 5 \f$ symmetric matrix:
2063
2064 \code
2065 using blaze::DynamicMatrix;
2066 using blaze::StaticVector;
2067 using blaze::SymmetricMatrix;
2068
2069 SymmetricMatrix< DynamicMatrix< StaticVector<int,1UL> > > A;
2070
2071 // Initializing the symmetric matrix A to
2072 //
2073 // ( ( ) ( 2 ) ( 5 ) ( -4 ) ( ) )
2074 // ( ( 2 ) ( 1 ) ( -3 ) ( 7 ) ( ) )
2075 // A = ( ( 5 ) ( -3 ) ( 8 ) ( -1 ) ( -2 ) )
2076 // ( ( -4 ) ( 7 ) ( -1 ) ( ) ( -6 ) )
2077 // ( ( ) ( 0 ) ( -2 ) ( -6 ) ( 1 ) )
2078 // ...
2079
2080 // Resetting the 1st row/column results in the matrix
2081 //
2082 // ( ( ) ( ) ( 5 ) ( -4 ) ( ) )
2083 // ( ( ) ( ) ( ) ( ) ( ) )
2084 // A = ( ( 5 ) ( ) ( 8 ) ( -1 ) ( -2 ) )
2085 // ( ( -4 ) ( ) ( -1 ) ( ) ( -6 ) )
2086 // ( ( ) ( ) ( -2 ) ( -6 ) ( 1 ) )
2087 //
2088 A.reset( 1UL );
2089 \endcode
2090
2091 // Note that the reset() function has no impact on the capacity of the matrix or row/column.
2092 */
2093 template< typename MT // Type of the adapted dense matrix
2094 , bool SO > // Storage order of the adapted dense matrix
reset(size_t i)2095 inline void SymmetricMatrix<MT,SO,true,false>::reset( size_t i )
2096 {
2097 using blaze::clear;
2098
2099 for( auto element=begin(i); element!=end(i); ++element )
2100 clear( *element );
2101 }
2102 /*! \endcond */
2103 //*************************************************************************************************
2104
2105
2106 //*************************************************************************************************
2107 /*! \cond BLAZE_INTERNAL */
2108 /*!\brief Clearing the symmetric matrix.
2109 //
2110 // \return void
2111 //
2112 // This function clears the symmetric matrix and returns it to its default state. The function has
2113 // the same effect as calling clear() on the adapted matrix of type \a MT: In case of a resizable
2114 // matrix (for instance DynamicMatrix or HybridMatrix) the number of rows and columns will be set
2115 // to 0, whereas in case of a fixed-size matrix (for instance StaticMatrix) only the elements will
2116 // be reset to their default state.
2117 */
2118 template< typename MT // Type of the adapted dense matrix
2119 , bool SO > // Storage order of the adapted dense matrix
clear()2120 inline void SymmetricMatrix<MT,SO,true,false>::clear()
2121 {
2122 using blaze::clear;
2123
2124 clear( matrix_ );
2125 }
2126 /*! \endcond */
2127 //*************************************************************************************************
2128
2129
2130 //*************************************************************************************************
2131 /*! \cond BLAZE_INTERNAL */
2132 /*!\brief Changing the size of the symmetric matrix.
2133 //
2134 // \param n The new number of rows and columns of the matrix.
2135 // \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
2136 // \return void
2137 //
2138 // In case the symmetric matrix adapts a resizable matrix, this function resizes the matrix using
2139 // the given size to \f$ n \times n \f$. During this operation, new dynamic memory may be allocated
2140 // in case the capacity of the matrix is too small. Note that this function may invalidate all
2141 // existing views (submatrices, rows, columns, ...) on the matrix if it is used to shrink the
2142 // matrix. Additionally, the resize operation potentially changes all matrix elements. In order
2143 // to preserve the old matrix values, the \a preserve flag can be set to \a true. In case the
2144 // size of the matrix is increased, new elements are default initialized.
2145 */
2146 template< typename MT // Type of the adapted dense matrix
2147 , bool SO > // Storage order of the adapted dense matrix
resize(size_t n,bool preserve)2148 void SymmetricMatrix<MT,SO,true,false>::resize( size_t n, bool preserve )
2149 {
2150 BLAZE_CONSTRAINT_MUST_BE_RESIZABLE_TYPE( MT );
2151
2152 MAYBE_UNUSED( preserve );
2153
2154 BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square symmetric matrix detected" );
2155
2156 const size_t oldsize( matrix_.rows() );
2157
2158 matrix_.resize( n, n, true );
2159
2160 if( n > oldsize ) {
2161 const size_t increment( n - oldsize );
2162 submatrix( matrix_, 0UL, oldsize, oldsize, increment ).reset();
2163 submatrix( matrix_, oldsize, 0UL, increment, n ).reset();
2164 }
2165 }
2166 /*! \endcond */
2167 //*************************************************************************************************
2168
2169
2170 //*************************************************************************************************
2171 /*! \cond BLAZE_INTERNAL */
2172 /*!\brief Extending the size of the matrix.
2173 //
2174 // \param n Number of additional rows and columns.
2175 // \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
2176 // \return void
2177 //
2178 // This function increases the matrix size by \a n rows and \a n columns. During this operation,
2179 // new dynamic memory may be allocated in case the capacity of the matrix is too small. Therefore
2180 // this function potentially changes all matrix elements. In order to preserve the old matrix
2181 // values, the \a preserve flag can be set to \a true. The new elements are default initialized.
2182 */
2183 template< typename MT // Type of the adapted dense matrix
2184 , bool SO > // Storage order of the adapted dense matrix
extend(size_t n,bool preserve)2185 inline void SymmetricMatrix<MT,SO,true,false>::extend( size_t n, bool preserve )
2186 {
2187 BLAZE_CONSTRAINT_MUST_BE_RESIZABLE_TYPE( MT );
2188
2189 MAYBE_UNUSED( preserve );
2190
2191 resize( rows() + n, true );
2192 }
2193 /*! \endcond */
2194 //*************************************************************************************************
2195
2196
2197 //*************************************************************************************************
2198 /*! \cond BLAZE_INTERNAL */
2199 /*!\brief Setting the minimum capacity of the matrix.
2200 //
2201 // \param elements The new minimum capacity of the symmetric matrix.
2202 // \return void
2203 //
2204 // This function increases the capacity of the symmetric matrix to at least \a elements elements.
2205 // The current values of the matrix elements are preserved.
2206 */
2207 template< typename MT // Type of the adapted dense matrix
2208 , bool SO > // Storage order of the adapted dense matrix
reserve(size_t elements)2209 inline void SymmetricMatrix<MT,SO,true,false>::reserve( size_t elements )
2210 {
2211 matrix_.reserve( elements );
2212 }
2213 /*! \endcond */
2214 //*************************************************************************************************
2215
2216
2217 //*************************************************************************************************
2218 /*! \cond BLAZE_INTERNAL */
2219 /*!\brief Requesting the removal of unused capacity.
2220 //
2221 // \return void
2222 //
2223 // This function minimizes the capacity of the matrix by removing unused capacity. Please note
2224 // that in case a reallocation occurs, all iterators (including end() iterators), all pointers
2225 // and references to elements of this matrix are invalidated.
2226 */
2227 template< typename MT // Type of the adapted dense matrix
2228 , bool SO > // Storage order of the adapted dense matrix
shrinkToFit()2229 inline void SymmetricMatrix<MT,SO,true,false>::shrinkToFit()
2230 {
2231 matrix_.shrinkToFit();
2232 }
2233 /*! \endcond */
2234 //*************************************************************************************************
2235
2236
2237 //*************************************************************************************************
2238 /*! \cond BLAZE_INTERNAL */
2239 /*!\brief Swapping the contents of two matrices.
2240 //
2241 // \param m The matrix to be swapped.
2242 // \return void
2243 */
2244 template< typename MT // Type of the adapted dense matrix
2245 , bool SO > // Storage order of the adapted dense matrix
swap(SymmetricMatrix & m)2246 inline void SymmetricMatrix<MT,SO,true,false>::swap( SymmetricMatrix& m ) noexcept
2247 {
2248 using std::swap;
2249
2250 swap( matrix_, m.matrix_ );
2251 }
2252 /*! \endcond */
2253 //*************************************************************************************************
2254
2255
2256
2257
2258 //=================================================================================================
2259 //
2260 // NUMERIC FUNCTIONS
2261 //
2262 //=================================================================================================
2263
2264 //*************************************************************************************************
2265 /*! \cond BLAZE_INTERNAL */
2266 /*!\brief In-place transpose of the symmetric matrix.
2267 //
2268 // \return Reference to the transposed matrix.
2269 */
2270 template< typename MT // Type of the adapted dense matrix
2271 , bool SO > // Storage order of the adapted dense matrix
transpose()2272 inline SymmetricMatrix<MT,SO,true,false>& SymmetricMatrix<MT,SO,true,false>::transpose()
2273 {
2274 return *this;
2275 }
2276 /*! \endcond */
2277 //*************************************************************************************************
2278
2279
2280 //*************************************************************************************************
2281 /*! \cond BLAZE_INTERNAL */
2282 /*!\brief In-place conjugate transpose of the symmetric matrix.
2283 //
2284 // \return Reference to the transposed matrix.
2285 */
2286 template< typename MT // Type of the adapted dense matrix
2287 , bool SO > // Storage order of the adapted dense matrix
ctranspose()2288 inline SymmetricMatrix<MT,SO,true,false>& SymmetricMatrix<MT,SO,true,false>::ctranspose()
2289 {
2290 if( SO ) {
2291 for( size_t j=0UL; j<columns(); ++j )
2292 for( size_t i=0UL; i<=j; ++i )
2293 conjugate( matrix_(i,j) );
2294 }
2295 else {
2296 for( size_t i=0UL; i<rows(); ++i )
2297 for( size_t j=0UL; j<=i; ++j )
2298 conjugate( matrix_(i,j) );
2299 }
2300
2301 return *this;
2302 }
2303 /*! \endcond */
2304 //*************************************************************************************************
2305
2306
2307 //*************************************************************************************************
2308 /*! \cond BLAZE_INTERNAL */
2309 /*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A=B*s \f$).
2310 //
2311 // \param scalar The scalar value for the matrix scaling.
2312 // \return Reference to the matrix.
2313 //
2314 // This function scales the matrix by applying the given scalar value \a scalar to each element
2315 // of the matrix. For built-in and \c complex data types it has the same effect as using the
2316 // multiplication assignment operator:
2317
2318 \code
2319 blaze::SymmetricMatrix< blaze::DynamicMatrix< blaze::StaticVector<int,1UL> > > A;
2320 // ... Resizing and initialization
2321 A *= 4; // Scaling of the matrix
2322 A.scale( 4 ); // Same effect as above
2323 \endcode
2324 */
2325 template< typename MT // Type of the adapted dense matrix
2326 , bool SO > // Storage order of the adapted dense matrix
2327 template< typename Other > // Data type of the scalar value
2328 inline SymmetricMatrix<MT,SO,true,false>&
scale(const Other & scalar)2329 SymmetricMatrix<MT,SO,true,false>::scale( const Other& scalar )
2330 {
2331 if( SO ) {
2332 for( size_t j=0UL; j<columns(); ++j )
2333 for( size_t i=0UL; i<=j; ++i )
2334 matrix_(i,j) *= scalar;
2335 }
2336 else {
2337 for( size_t i=0UL; i<rows(); ++i )
2338 for( size_t j=0UL; j<=i; ++j )
2339 matrix_(i,j) *= scalar;
2340 }
2341
2342 return *this;
2343 }
2344 /*! \endcond */
2345 //*************************************************************************************************
2346
2347
2348
2349
2350 //=================================================================================================
2351 //
2352 // DEBUGGING FUNCTIONS
2353 //
2354 //=================================================================================================
2355
2356 //*************************************************************************************************
2357 /*! \cond BLAZE_INTERNAL */
2358 /*!\brief Returns whether the invariants of the symmetric matrix are intact.
2359 //
2360 // \return \a true in case the symmetric matrix's invariants are intact, \a false otherwise.
2361 //
2362 // This function checks whether the invariants of the symmetric matrix are intact, i.e. if its
2363 // state is valid. In case the invariants are intact, the function returns \a true, else it
2364 // will return \a false.
2365 */
2366 template< typename MT // Type of the adapted dense matrix
2367 , bool SO > // Storage order of the adapted dense matrix
isIntact()2368 inline bool SymmetricMatrix<MT,SO,true,false>::isIntact() const noexcept
2369 {
2370 using blaze::isIntact;
2371
2372 return isIntact( matrix_ ) &&
2373 ( IsCustom_v<MT> || ( SO ? isUpper( matrix_ ) : isLower( matrix_ ) ) );
2374 }
2375 /*! \endcond */
2376 //*************************************************************************************************
2377
2378
2379
2380
2381 //=================================================================================================
2382 //
2383 // EXPRESSION TEMPLATE EVALUATION FUNCTIONS
2384 //
2385 //=================================================================================================
2386
2387 //*************************************************************************************************
2388 /*! \cond BLAZE_INTERNAL */
2389 /*!\brief Returns whether the matrix can alias with the given address \a alias.
2390 //
2391 // \param alias The alias to be checked.
2392 // \return \a true in case the alias corresponds to this matrix, \a false if not.
2393 //
2394 // This function returns whether the given address can alias with the matrix. In contrast
2395 // to the isAliased() function this function is allowed to use compile time expressions
2396 // to optimize the evaluation.
2397 */
2398 template< typename MT // Type of the adapted dense matrix
2399 , bool SO > // Storage order of the adapted dense matrix
2400 template< typename Other > // Data type of the foreign expression
canAlias(const Other * alias)2401 inline bool SymmetricMatrix<MT,SO,true,false>::canAlias( const Other* alias ) const noexcept
2402 {
2403 return matrix_.canAlias( alias );
2404 }
2405 /*! \endcond */
2406 //*************************************************************************************************
2407
2408
2409 //*************************************************************************************************
2410 /*! \cond BLAZE_INTERNAL */
2411 /*!\brief Returns whether the matrix is aliased with the given address \a alias.
2412 //
2413 // \param alias The alias to be checked.
2414 // \return \a true in case the alias corresponds to this matrix, \a false if not.
2415 //
2416 // This function returns whether the given address is aliased with the matrix. In contrast
2417 // to the canAlias() function this function is not allowed to use compile time expressions
2418 // to optimize the evaluation.
2419 */
2420 template< typename MT // Type of the adapted dense matrix
2421 , bool SO > // Storage order of the adapted dense matrix
2422 template< typename Other > // Data type of the foreign expression
isAliased(const Other * alias)2423 inline bool SymmetricMatrix<MT,SO,true,false>::isAliased( const Other* alias ) const noexcept
2424 {
2425 return matrix_.isAliased( alias );
2426 }
2427 /*! \endcond */
2428 //*************************************************************************************************
2429
2430
2431 //*************************************************************************************************
2432 /*! \cond BLAZE_INTERNAL */
2433 /*!\brief Returns whether the matrix is properly aligned in memory.
2434 //
2435 // \return \a true in case the matrix is aligned, \a false if not.
2436 //
2437 // This function returns whether the matrix is guaranteed to be properly aligned in memory, i.e.
2438 // whether the beginning and the end of each row/column of the matrix are guaranteed to conform
2439 // to the alignment restrictions of the element type \a Type.
2440 */
2441 template< typename MT // Type of the adapted dense matrix
2442 , bool SO > // Storage order of the adapted dense matrix
isAligned()2443 inline bool SymmetricMatrix<MT,SO,true,false>::isAligned() const noexcept
2444 {
2445 return matrix_.isAligned();
2446 }
2447 /*! \endcond */
2448 //*************************************************************************************************
2449
2450
2451 //*************************************************************************************************
2452 /*! \cond BLAZE_INTERNAL */
2453 /*!\brief Returns whether the matrix can be used in SMP assignments.
2454 //
2455 // \return \a true in case the matrix can be used in SMP assignments, \a false if not.
2456 //
2457 // This function returns whether the matrix can be used in SMP assignments. In contrast to the
2458 // \a smpAssignable member enumeration, which is based solely on compile time information, this
2459 // function additionally provides runtime information (as for instance the current number of
2460 // rows and/or columns of the matrix).
2461 */
2462 template< typename MT // Type of the adapted dense matrix
2463 , bool SO > // Storage order of the adapted dense matrix
canSMPAssign()2464 inline bool SymmetricMatrix<MT,SO,true,false>::canSMPAssign() const noexcept
2465 {
2466 return matrix_.canSMPAssign();
2467 }
2468 /*! \endcond */
2469 //*************************************************************************************************
2470
2471
2472 //*************************************************************************************************
2473 /*! \cond BLAZE_INTERNAL */
2474 /*!\brief Optimized implementation of the assignment of a temporary dense matrix.
2475 //
2476 // \param rhs The right-hand side dense matrix to be assigned.
2477 // \return void
2478 //
2479 // This function must \b NOT be called explicitly! It is used internally for the performance
2480 // optimized evaluation of expression templates. Calling this function explicitly might result
2481 // in erroneous results and/or in compilation errors. Instead of using this function use the
2482 // assignment operator.
2483 */
2484 template< typename MT // Type of the adapted dense matrix
2485 , bool SO > // Storage order of the adapted dense matrix
2486 template< typename MT2 > // Type of the right-hand side dense matrix
assign(DenseMatrix<MT2,SO> & rhs)2487 inline void SymmetricMatrix<MT,SO,true,false>::assign( DenseMatrix<MT2,SO>& rhs )
2488 {
2489 BLAZE_INTERNAL_ASSERT( rows() == (*rhs).rows() , "Invalid number of rows" );
2490 BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
2491
2492 if( SO ) {
2493 for( size_t j=0UL; j<columns(); ++j )
2494 for( size_t i=0UL; i<=j; ++i )
2495 matrix_(i,j) = std::move( (*rhs)(i,j) );
2496 }
2497 else {
2498 for( size_t i=0UL; i<rows(); ++i )
2499 for( size_t j=0UL; j<=i; ++j )
2500 matrix_(i,j) = std::move( (*rhs)(i,j) );
2501 }
2502 }
2503 /*! \endcond */
2504 //*************************************************************************************************
2505
2506
2507 //*************************************************************************************************
2508 /*! \cond BLAZE_INTERNAL */
2509 /*!\brief Default implementation of the assignment of a dense matrix.
2510 //
2511 // \param rhs The right-hand side dense matrix to be assigned.
2512 // \return void
2513 //
2514 // This function must \b NOT be called explicitly! It is used internally for the performance
2515 // optimized evaluation of expression templates. Calling this function explicitly might result
2516 // in erroneous results and/or in compilation errors. Instead of using this function use the
2517 // assignment operator.
2518 */
2519 template< typename MT // Type of the adapted dense matrix
2520 , bool SO > // Storage order of the adapted dense matrix
2521 template< typename MT2 > // Type of the right-hand side dense matrix
assign(const DenseMatrix<MT2,SO> & rhs)2522 inline void SymmetricMatrix<MT,SO,true,false>::assign( const DenseMatrix<MT2,SO>& rhs )
2523 {
2524 BLAZE_INTERNAL_ASSERT( rows() == (*rhs).rows() , "Invalid number of rows" );
2525 BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
2526
2527 if( SO ) {
2528 for( size_t j=0UL; j<columns(); ++j )
2529 for( size_t i=0UL; i<=j; ++i )
2530 matrix_(i,j) = (*rhs)(i,j);
2531 }
2532 else {
2533 for( size_t i=0UL; i<rows(); ++i )
2534 for( size_t j=0UL; j<=i; ++j )
2535 matrix_(i,j) = (*rhs)(i,j);
2536 }
2537 }
2538 /*! \endcond */
2539 //*************************************************************************************************
2540
2541
2542 //*************************************************************************************************
2543 /*! \cond BLAZE_INTERNAL */
2544 /*!\brief Default implementation of the assignment of a sparse matrix.
2545 //
2546 // \param rhs The right-hand side sparse matrix to be assigned.
2547 // \return void
2548 //
2549 // This function must \b NOT be called explicitly! It is used internally for the performance
2550 // optimized evaluation of expression templates. Calling this function explicitly might result
2551 // in erroneous results and/or in compilation errors. Instead of using this function use the
2552 // assignment operator.
2553 */
2554 template< typename MT // Type of the adapted dense matrix
2555 , bool SO > // Storage order of the adapted dense matrix
2556 template< typename MT2 > // Type of the right-hand side sparse matrix
assign(const SparseMatrix<MT2,SO> & rhs)2557 inline void SymmetricMatrix<MT,SO,true,false>::assign( const SparseMatrix<MT2,SO>& rhs )
2558 {
2559 BLAZE_INTERNAL_ASSERT( rows() == (*rhs).rows() , "Invalid number of rows" );
2560 BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
2561
2562 if( SO ) {
2563 for( size_t j=0UL; j<columns(); ++j ) {
2564 const auto last( (*rhs).upperBound(j,j) );
2565 for( auto element=(*rhs).begin(j); element!=last; ++element )
2566 matrix_(element->index(),j) = element->value();
2567 }
2568 }
2569 else {
2570 for( size_t i=0UL; i<rows(); ++i ) {
2571 const auto last( (*rhs).upperBound(i,i) );
2572 for( auto element=(*rhs).begin(i); element!=last; ++element )
2573 matrix_(i,element->index()) = element->value();
2574 }
2575 }
2576 }
2577 /*! \endcond */
2578 //*************************************************************************************************
2579
2580
2581 //*************************************************************************************************
2582 /*! \cond BLAZE_INTERNAL */
2583 /*!\brief Default implementation of the addition assignment of a dense matrix.
2584 //
2585 // \param rhs The right-hand side dense matrix to be added.
2586 // \return void
2587 //
2588 // This function must \b NOT be called explicitly! It is used internally for the performance
2589 // optimized evaluation of expression templates. Calling this function explicitly might result
2590 // in erroneous results and/or in compilation errors. Instead of using this function use the
2591 // assignment operator.
2592 */
2593 template< typename MT // Type of the adapted dense matrix
2594 , bool SO > // Storage order of the adapted dense matrix
2595 template< typename MT2 > // Type of the right-hand side dense matrix
addAssign(const DenseMatrix<MT2,SO> & rhs)2596 inline void SymmetricMatrix<MT,SO,true,false>::addAssign( const DenseMatrix<MT2,SO>& rhs )
2597 {
2598 BLAZE_INTERNAL_ASSERT( rows() == (*rhs).rows() , "Invalid number of rows" );
2599 BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
2600
2601 if( SO ) {
2602 for( size_t j=0UL; j<columns(); ++j )
2603 for( size_t i=0UL; i<=j; ++i )
2604 matrix_(i,j) += (*rhs)(i,j);
2605 }
2606 else {
2607 for( size_t i=0UL; i<rows(); ++i )
2608 for( size_t j=0UL; j<=i; ++j )
2609 matrix_(i,j) += (*rhs)(i,j);
2610 }
2611 }
2612 /*! \endcond */
2613 //*************************************************************************************************
2614
2615
2616 //*************************************************************************************************
2617 /*! \cond BLAZE_INTERNAL */
2618 /*!\brief Default implementation of the addition assignment of a sparse matrix.
2619 //
2620 // \param rhs The right-hand side sparse matrix to be added.
2621 // \return void
2622 //
2623 // This function must \b NOT be called explicitly! It is used internally for the performance
2624 // optimized evaluation of expression templates. Calling this function explicitly might result
2625 // in erroneous results and/or in compilation errors. Instead of using this function use the
2626 // assignment operator.
2627 */
2628 template< typename MT // Type of the adapted dense matrix
2629 , bool SO > // Storage order of the adapted dense matrix
2630 template< typename MT2 > // Type of the right-hand side sparse matrix
addAssign(const SparseMatrix<MT2,SO> & rhs)2631 inline void SymmetricMatrix<MT,SO,true,false>::addAssign( const SparseMatrix<MT2,SO>& rhs )
2632 {
2633 BLAZE_INTERNAL_ASSERT( rows() == (*rhs).rows() , "Invalid number of rows" );
2634 BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
2635
2636 if( SO ) {
2637 for( size_t j=0UL; j<columns(); ++j ) {
2638 const auto last( (*rhs).upperBound(j,j) );
2639 for( auto element=(*rhs).begin(j); element!=last; ++element )
2640 matrix_(element->index(),j) += element->value();
2641 }
2642 }
2643 else {
2644 for( size_t i=0UL; i<rows(); ++i ) {
2645 const auto last( (*rhs).upperBound(i,i) );
2646 for( auto element=(*rhs).begin(i); element!=last; ++element )
2647 matrix_(i,element->index()) += element->value();
2648 }
2649 }
2650 }
2651 /*! \endcond */
2652 //*************************************************************************************************
2653
2654
2655 //*************************************************************************************************
2656 /*! \cond BLAZE_INTERNAL */
2657 /*!\brief Default implementation of the subtraction assignment of a dense matrix.
2658 //
2659 // \param rhs The right-hand side dense matrix to be subtracted.
2660 // \return void
2661 //
2662 // This function must \b NOT be called explicitly! It is used internally for the performance
2663 // optimized evaluation of expression templates. Calling this function explicitly might result
2664 // in erroneous results and/or in compilation errors. Instead of using this function use the
2665 // assignment operator.
2666 */
2667 template< typename MT // Type of the adapted dense matrix
2668 , bool SO > // Storage order of the adapted dense matrix
2669 template< typename MT2 > // Type of the right-hand side dense matrix
subAssign(const DenseMatrix<MT2,SO> & rhs)2670 inline void SymmetricMatrix<MT,SO,true,false>::subAssign( const DenseMatrix<MT2,SO>& rhs )
2671 {
2672 BLAZE_INTERNAL_ASSERT( rows() == (*rhs).rows() , "Invalid number of rows" );
2673 BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
2674
2675 if( SO ) {
2676 for( size_t j=0UL; j<columns(); ++j )
2677 for( size_t i=0UL; i<=j; ++i )
2678 matrix_(i,j) -= (*rhs)(i,j);
2679 }
2680 else {
2681 for( size_t i=0UL; i<rows(); ++i )
2682 for( size_t j=0UL; j<=i; ++j )
2683 matrix_(i,j) -= (*rhs)(i,j);
2684 }
2685 }
2686 /*! \endcond */
2687 //*************************************************************************************************
2688
2689
2690 //*************************************************************************************************
2691 /*! \cond BLAZE_INTERNAL */
2692 /*!\brief Default implementation of the subtraction assignment of a sparse matrix.
2693 //
2694 // \param rhs The right-hand side sparse matrix to be subtracted.
2695 // \return void
2696 //
2697 // This function must \b NOT be called explicitly! It is used internally for the performance
2698 // optimized evaluation of expression templates. Calling this function explicitly might result
2699 // in erroneous results and/or in compilation errors. Instead of using this function use the
2700 // assignment operator.
2701 */
2702 template< typename MT // Type of the adapted dense matrix
2703 , bool SO > // Storage order of the adapted dense matrix
2704 template< typename MT2 > // Type of the right-hand side sparse matrix
subAssign(const SparseMatrix<MT2,SO> & rhs)2705 inline void SymmetricMatrix<MT,SO,true,false>::subAssign( const SparseMatrix<MT2,SO>& rhs )
2706 {
2707 BLAZE_INTERNAL_ASSERT( rows() == (*rhs).rows() , "Invalid number of rows" );
2708 BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
2709
2710 if( SO ) {
2711 for( size_t j=0UL; j<columns(); ++j ) {
2712 const auto last( (*rhs).upperBound(j,j) );
2713 for( auto element=(*rhs).begin(j); element!=last; ++element )
2714 matrix_(element->index(),j) -= element->value();
2715 }
2716 }
2717 else {
2718 for( size_t i=0UL; i<rows(); ++i ) {
2719 const auto last( (*rhs).upperBound(i,i) );
2720 for( auto element=(*rhs).begin(i); element!=last; ++element )
2721 matrix_(i,element->index()) -= element->value();
2722 }
2723 }
2724 }
2725 /*! \endcond */
2726 //*************************************************************************************************
2727
2728
2729 //*************************************************************************************************
2730 /*! \cond BLAZE_INTERNAL */
2731 /*!\brief Default implementation of the Schur product assignment of a dense matrix.
2732 //
2733 // \param rhs The right-hand side dense matrix for the Schur product.
2734 // \return void
2735 //
2736 // This function must \b NOT be called explicitly! It is used internally for the performance
2737 // optimized evaluation of expression templates. Calling this function explicitly might result
2738 // in erroneous results and/or in compilation errors. Instead of using this function use the
2739 // assignment operator.
2740 */
2741 template< typename MT // Type of the adapted dense matrix
2742 , bool SO > // Storage order of the adapted dense matrix
2743 template< typename MT2 > // Type of the right-hand side dense matrix
schurAssign(const DenseMatrix<MT2,SO> & rhs)2744 inline void SymmetricMatrix<MT,SO,true,false>::schurAssign( const DenseMatrix<MT2,SO>& rhs )
2745 {
2746 BLAZE_INTERNAL_ASSERT( rows() == (*rhs).rows() , "Invalid number of rows" );
2747 BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
2748
2749 if( SO ) {
2750 for( size_t j=0UL; j<columns(); ++j )
2751 for( size_t i=0UL; i<=j; ++i )
2752 matrix_(i,j) *= (*rhs)(i,j);
2753 }
2754 else {
2755 for( size_t i=0UL; i<rows(); ++i )
2756 for( size_t j=0UL; j<=i; ++j )
2757 matrix_(i,j) *= (*rhs)(i,j);
2758 }
2759 }
2760 /*! \endcond */
2761 //*************************************************************************************************
2762
2763
2764 //*************************************************************************************************
2765 /*! \cond BLAZE_INTERNAL */
2766 /*!\brief Default implementation of the Schur product assignment of a sparse matrix.
2767 //
2768 // \param rhs The right-hand side sparse matrix for the Schur product.
2769 // \return void
2770 //
2771 // This function must \b NOT be called explicitly! It is used internally for the performance
2772 // optimized evaluation of expression templates. Calling this function explicitly might result
2773 // in erroneous results and/or in compilation errors. Instead of using this function use the
2774 // assignment operator.
2775 */
2776 template< typename MT // Type of the adapted dense matrix
2777 , bool SO > // Storage order of the adapted dense matrix
2778 template< typename MT2 > // Type of the right-hand side sparse matrix
schurAssign(const SparseMatrix<MT2,SO> & rhs)2779 inline void SymmetricMatrix<MT,SO,true,false>::schurAssign( const SparseMatrix<MT2,SO>& rhs )
2780 {
2781 BLAZE_INTERNAL_ASSERT( rows() == (*rhs).rows() , "Invalid number of rows" );
2782 BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
2783
2784 if( SO ) {
2785 for( size_t j=0UL; j<columns(); ++j )
2786 {
2787 size_t i( 0UL );
2788
2789 const auto last( (*rhs).upperBound(j,j) );
2790 for( auto element=(*rhs).begin(j); element!=last; ++element ) {
2791 for( ; i<element->index(); ++i )
2792 reset( matrix_(i,j) );
2793 matrix_(i,j) *= element->value();
2794 ++i;
2795 }
2796
2797 for( ; i<rows(); ++i ) {
2798 reset( matrix_(i,j) );
2799 }
2800 }
2801 }
2802 else {
2803 for( size_t i=0UL; i<rows(); ++i )
2804 {
2805 size_t j( 0UL );
2806
2807 const auto last( (*rhs).upperBound(i,i) );
2808 for( auto element=(*rhs).begin(i); element!=last; ++element ) {
2809 for( ; j<element->index(); ++j )
2810 reset( matrix_(i,j) );
2811 matrix_(i,j) *= element->value();
2812 ++j;
2813 }
2814
2815 for( ; j<columns(); ++j ) {
2816 reset( matrix_(i,j) );
2817 }
2818 }
2819 }
2820 }
2821 /*! \endcond */
2822 //*************************************************************************************************
2823
2824 } // namespace blaze
2825
2826 #endif
2827