Blaze  3.6
Dense.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_ADAPTORS_DIAGONALMATRIX_DENSE_H_
36 #define _BLAZE_MATH_ADAPTORS_DIAGONALMATRIX_DENSE_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <iterator>
44 #include <utility>
47 #include <blaze/math/Aliases.h>
61 #include <blaze/math/Exception.h>
64 #include <blaze/math/shims/Clear.h>
75 #include <blaze/math/views/Band.h>
77 #include <blaze/system/Inline.h>
78 #include <blaze/util/Assert.h>
84 #include <blaze/util/DisableIf.h>
85 #include <blaze/util/EnableIf.h>
87 #include <blaze/util/MaybeUnused.h>
88 #include <blaze/util/mpl/If.h>
90 #include <blaze/util/Types.h>
95 
96 
97 namespace blaze {
98 
99 //=================================================================================================
100 //
101 // CLASS TEMPLATE SPECIALIZATION FOR DENSE MATRICES
102 //
103 //=================================================================================================
104 
105 //*************************************************************************************************
113 template< typename MT // Type of the adapted dense matrix
114  , bool SO > // Storage order of the adapted dense matrix
115 class DiagonalMatrix<MT,SO,true>
116  : public DenseMatrix< DiagonalMatrix<MT,SO,true>, SO >
117 {
118  private:
119  //**Type definitions****************************************************************************
120  using OT = OppositeType_t<MT>;
121  using TT = TransposeType_t<MT>;
122  using ET = ElementType_t<MT>;
123  //**********************************************************************************************
124 
125  public:
126  //**Type definitions****************************************************************************
127  using This = DiagonalMatrix<MT,SO,true>;
128  using BaseType = DenseMatrix<This,SO>;
129  using ResultType = This;
130  using OppositeType = DiagonalMatrix<OT,!SO,true>;
131  using TransposeType = DiagonalMatrix<TT,!SO,true>;
132  using ElementType = ET;
133  using SIMDType = SIMDType_t<MT>;
134  using ReturnType = ReturnType_t<MT>;
135  using CompositeType = const This&;
136  using Reference = DiagonalProxy<MT>;
137  using ConstReference = ConstReference_t<MT>;
138  using Pointer = Pointer_t<MT>;
139  using ConstPointer = ConstPointer_t<MT>;
140  using ConstIterator = ConstIterator_t<MT>;
141  //**********************************************************************************************
142 
143  //**Rebind struct definition********************************************************************
146  template< typename NewType > // Data type of the other matrix
147  struct Rebind {
149  using Other = DiagonalMatrix< typename MT::template Rebind<NewType>::Other >;
150  };
151  //**********************************************************************************************
152 
153  //**Resize struct definition********************************************************************
156  template< size_t NewM // Number of rows of the other matrix
157  , size_t NewN > // Number of columns of the other matrix
158  struct Resize {
160  using Other = DiagonalMatrix< typename MT::template Resize<NewM,NewN>::Other >;
161  };
162  //**********************************************************************************************
163 
164  //**Iterator class definition*******************************************************************
167  class Iterator
168  {
169  public:
170  //**Type definitions*************************************************************************
171  using IteratorCategory = std::random_access_iterator_tag;
172  using ValueType = ElementType_t<MT>;
173  using PointerType = DiagonalProxy<MT>;
174  using ReferenceType = DiagonalProxy<MT>;
175  using DifferenceType = ptrdiff_t;
176 
177  // STL iterator requirements
178  using iterator_category = IteratorCategory;
179  using value_type = ValueType;
180  using pointer = PointerType;
181  using reference = ReferenceType;
182  using difference_type = DifferenceType;
183  //*******************************************************************************************
184 
185  //**Constructor******************************************************************************
188  inline Iterator() noexcept
189  : matrix_( nullptr ) // Reference to the adapted dense matrix
190  , row_ ( 0UL ) // The current row index of the iterator
191  , column_( 0UL ) // The current column index of the iterator
192  {}
193  //*******************************************************************************************
194 
195  //**Constructor******************************************************************************
202  inline Iterator( MT& matrix, size_t row, size_t column ) noexcept
203  : matrix_( &matrix ) // Reference to the adapted dense matrix
204  , row_ ( row ) // The current row-index of the iterator
205  , column_( column ) // The current column-index of the iterator
206  {}
207  //*******************************************************************************************
208 
209  //**Addition assignment operator*************************************************************
215  inline Iterator& operator+=( size_t inc ) noexcept {
216  ( SO )?( row_ += inc ):( column_ += inc );
217  return *this;
218  }
219  //*******************************************************************************************
220 
221  //**Subtraction assignment operator**********************************************************
227  inline Iterator& operator-=( size_t dec ) noexcept {
228  ( SO )?( row_ -= dec ):( column_ -= dec );
229  return *this;
230  }
231  //*******************************************************************************************
232 
233  //**Prefix increment operator****************************************************************
238  inline Iterator& operator++() noexcept {
239  ( SO )?( ++row_ ):( ++column_ );
240  return *this;
241  }
242  //*******************************************************************************************
243 
244  //**Postfix increment operator***************************************************************
249  inline const Iterator operator++( int ) noexcept {
250  const Iterator tmp( *this );
251  ++(*this);
252  return tmp;
253  }
254  //*******************************************************************************************
255 
256  //**Prefix decrement operator****************************************************************
261  inline Iterator& operator--() noexcept {
262  ( SO )?( --row_ ):( --column_ );
263  return *this;
264  }
265  //*******************************************************************************************
266 
267  //**Postfix decrement operator***************************************************************
272  inline const Iterator operator--( int ) noexcept {
273  const Iterator tmp( *this );
274  --(*this);
275  return tmp;
276  }
277  //*******************************************************************************************
278 
279  //**Element access operator******************************************************************
284  inline ReferenceType operator*() const {
285  return ReferenceType( *matrix_, row_, column_ );
286  }
287  //*******************************************************************************************
288 
289  //**Element access operator******************************************************************
294  inline PointerType operator->() const {
295  return PointerType( *matrix_, row_, column_ );
296  }
297  //*******************************************************************************************
298 
299  //**Load function****************************************************************************
309  inline SIMDType load() const {
310  return (*matrix_).load(row_,column_);
311  }
312  //*******************************************************************************************
313 
314  //**Loada function***************************************************************************
324  inline SIMDType loada() const {
325  return (*matrix_).loada(row_,column_);
326  }
327  //*******************************************************************************************
328 
329  //**Loadu function***************************************************************************
339  inline SIMDType loadu() const {
340  return (*matrix_).loadu(row_,column_);
341  }
342  //*******************************************************************************************
343 
344  //**Conversion operator**********************************************************************
349  inline operator ConstIterator() const {
350  if( SO )
351  return matrix_->begin( column_ ) + row_;
352  else
353  return matrix_->begin( row_ ) + column_;
354  }
355  //*******************************************************************************************
356 
357  //**Equality operator************************************************************************
364  friend inline bool operator==( const Iterator& lhs, const Iterator& rhs ) noexcept {
365  return ( SO )?( lhs.row_ == rhs.row_ ):( lhs.column_ == rhs.column_ );
366  }
367  //*******************************************************************************************
368 
369  //**Equality operator************************************************************************
376  friend inline bool operator==( const Iterator& lhs, const ConstIterator& rhs ) {
377  return ( ConstIterator( lhs ) == rhs );
378  }
379  //*******************************************************************************************
380 
381  //**Equality operator************************************************************************
388  friend inline bool operator==( const ConstIterator& lhs, const Iterator& rhs ) {
389  return ( lhs == ConstIterator( rhs ) );
390  }
391  //*******************************************************************************************
392 
393  //**Inequality operator**********************************************************************
400  friend inline bool operator!=( const Iterator& lhs, const Iterator& rhs ) noexcept {
401  return ( SO )?( lhs.row_ != rhs.row_ ):( lhs.column_ != rhs.column_ );
402  }
403  //*******************************************************************************************
404 
405  //**Inequality operator**********************************************************************
412  friend inline bool operator!=( const Iterator& lhs, const ConstIterator& rhs ) {
413  return ( ConstIterator( lhs ) != rhs );
414  }
415  //*******************************************************************************************
416 
417  //**Inequality operator**********************************************************************
424  friend inline bool operator!=( const ConstIterator& lhs, const Iterator& rhs ) {
425  return ( lhs != ConstIterator( rhs ) );
426  }
427  //*******************************************************************************************
428 
429  //**Less-than operator***********************************************************************
436  friend inline bool operator<( const Iterator& lhs, const Iterator& rhs ) noexcept {
437  return ( SO )?( lhs.row_ < rhs.row_ ):( lhs.column_ < rhs.column_ );
438  }
439  //*******************************************************************************************
440 
441  //**Less-than operator***********************************************************************
448  friend inline bool operator<( const Iterator& lhs, const ConstIterator& rhs ) {
449  return ( ConstIterator( lhs ) < rhs );
450  }
451  //*******************************************************************************************
452 
453  //**Less-than operator***********************************************************************
460  friend inline bool operator<( const ConstIterator& lhs, const Iterator& rhs ) {
461  return ( lhs < ConstIterator( rhs ) );
462  }
463  //*******************************************************************************************
464 
465  //**Greater-than operator********************************************************************
472  friend inline bool operator>( const Iterator& lhs, const Iterator& rhs ) noexcept {
473  return ( SO )?( lhs.row_ > rhs.row_ ):( lhs.column_ > rhs.column_ );
474  }
475  //*******************************************************************************************
476 
477  //**Greater-than operator********************************************************************
484  friend inline bool operator>( const Iterator& lhs, const ConstIterator& rhs ) {
485  return ( ConstIterator( lhs ) > rhs );
486  }
487  //*******************************************************************************************
488 
489  //**Greater-than operator********************************************************************
496  friend inline bool operator>( const ConstIterator& lhs, const Iterator& rhs ) {
497  return ( lhs > ConstIterator( rhs ) );
498  }
499  //*******************************************************************************************
500 
501  //**Less-or-equal-than operator**************************************************************
508  friend inline bool operator<=( const Iterator& lhs, const Iterator& rhs ) noexcept {
509  return ( SO )?( lhs.row_ <= rhs.row_ ):( lhs.column_ <= rhs.column_ );
510  }
511  //*******************************************************************************************
512 
513  //**Less-or-equal-than operator**************************************************************
520  friend inline bool operator<=( const Iterator& lhs, const ConstIterator& rhs ) {
521  return ( ConstIterator( lhs ) <= rhs );
522  }
523  //*******************************************************************************************
524 
525  //**Less-or-equal-than operator**************************************************************
532  friend inline bool operator<=( const ConstIterator& lhs, const Iterator& rhs ) {
533  return ( lhs <= ConstIterator( rhs ) );
534  }
535  //*******************************************************************************************
536 
537  //**Greater-or-equal-than operator***********************************************************
544  friend inline bool operator>=( const Iterator& lhs, const Iterator& rhs ) noexcept {
545  return ( SO )?( lhs.row_ >= rhs.row_ ):( lhs.column_ >= rhs.column_ );
546  }
547  //*******************************************************************************************
548 
549  //**Greater-or-equal-than operator***********************************************************
556  friend inline bool operator>=( const Iterator& lhs, const ConstIterator& rhs ) {
557  return ( ConstIterator( lhs ) >= rhs );
558  }
559  //*******************************************************************************************
560 
561  //**Greater-or-equal-than operator***********************************************************
568  friend inline bool operator>=( const ConstIterator& lhs, const Iterator& rhs ) {
569  return ( lhs >= ConstIterator( rhs ) );
570  }
571  //*******************************************************************************************
572 
573  //**Subtraction operator*********************************************************************
579  inline DifferenceType operator-( const Iterator& rhs ) const noexcept {
580  return ( SO )?( row_ - rhs.row_ ):( column_ - rhs.column_ );
581  }
582  //*******************************************************************************************
583 
584  //**Addition operator************************************************************************
591  friend inline const Iterator operator+( const Iterator& it, size_t inc ) noexcept {
592  if( SO )
593  return Iterator( *it.matrix_, it.row_ + inc, it.column_ );
594  else
595  return Iterator( *it.matrix_, it.row_, it.column_ + inc );
596  }
597  //*******************************************************************************************
598 
599  //**Addition operator************************************************************************
606  friend inline const Iterator operator+( size_t inc, const Iterator& it ) noexcept {
607  if( SO )
608  return Iterator( *it.matrix_, it.row_ + inc, it.column_ );
609  else
610  return Iterator( *it.matrix_, it.row_, it.column_ + inc );
611  }
612  //*******************************************************************************************
613 
614  //**Subtraction operator*********************************************************************
621  friend inline const Iterator operator-( const Iterator& it, size_t dec ) noexcept {
622  if( SO )
623  return Iterator( *it.matrix_, it.row_ - dec, it.column_ );
624  else
625  return Iterator( *it.matrix_, it.row_, it.column_ - dec );
626  }
627  //*******************************************************************************************
628 
629  private:
630  //**Member variables*************************************************************************
631  MT* matrix_;
632  size_t row_;
633  size_t column_;
634  //*******************************************************************************************
635  };
636  //**********************************************************************************************
637 
638  //**Compilation flags***************************************************************************
640  static constexpr bool simdEnabled = MT::simdEnabled;
641 
643  static constexpr bool smpAssignable = MT::smpAssignable;
644  //**********************************************************************************************
645 
646  //**Constructors********************************************************************************
649  explicit inline DiagonalMatrix();
650  template< typename A1 > explicit inline DiagonalMatrix( const A1& a1 );
651  explicit inline DiagonalMatrix( size_t n, const ElementType& init );
652 
653  inline DiagonalMatrix( initializer_list< initializer_list<ElementType> > list );
654 
655  template< typename Other >
656  explicit inline DiagonalMatrix( size_t n, const Other* array );
657 
658  template< typename Other, size_t N >
659  explicit inline DiagonalMatrix( const Other (&array)[N][N] );
660 
661  explicit inline DiagonalMatrix( ElementType* ptr, size_t n );
662  explicit inline DiagonalMatrix( ElementType* ptr, size_t n, size_t nn );
663 
664  inline DiagonalMatrix( const DiagonalMatrix& m );
665  inline DiagonalMatrix( DiagonalMatrix&& m ) noexcept;
667  //**********************************************************************************************
668 
669  //**Destructor**********************************************************************************
672  ~DiagonalMatrix() = default;
674  //**********************************************************************************************
675 
676  //**Data access functions***********************************************************************
679  inline Reference operator()( size_t i, size_t j );
680  inline ConstReference operator()( size_t i, size_t j ) const;
681  inline Reference at( size_t i, size_t j );
682  inline ConstReference at( size_t i, size_t j ) const;
683  inline ConstPointer data () const noexcept;
684  inline ConstPointer data ( size_t i ) const noexcept;
685  inline Iterator begin ( size_t i );
686  inline ConstIterator begin ( size_t i ) const;
687  inline ConstIterator cbegin( size_t i ) const;
688  inline Iterator end ( size_t i );
689  inline ConstIterator end ( size_t i ) const;
690  inline ConstIterator cend ( size_t i ) const;
692  //**********************************************************************************************
693 
694  //**Assignment operators************************************************************************
697  inline DiagonalMatrix& operator=( const ElementType& rhs );
698  inline DiagonalMatrix& operator=( initializer_list< initializer_list<ElementType> > list );
699 
700  template< typename Other, size_t N >
701  inline DiagonalMatrix& operator=( const Other (&array)[N][N] );
702 
703  inline DiagonalMatrix& operator=( const DiagonalMatrix& rhs );
704  inline DiagonalMatrix& operator=( DiagonalMatrix&& rhs ) noexcept;
705 
706  template< typename MT2, bool SO2 >
707  inline auto operator=( const Matrix<MT2,SO2>& rhs )
708  -> DisableIf_t< IsComputation_v<MT2>, DiagonalMatrix& >;
709 
710  template< typename MT2, bool SO2 >
711  inline auto operator=( const Matrix<MT2,SO2>& rhs )
712  -> EnableIf_t< IsComputation_v<MT2>, DiagonalMatrix& >;
713 
714  template< typename MT2, bool SO2 >
715  inline auto operator+=( const Matrix<MT2,SO2>& rhs )
716  -> DisableIf_t< IsComputation_v<MT2>, DiagonalMatrix& >;
717 
718  template< typename MT2, bool SO2 >
719  inline auto operator+=( const Matrix<MT2,SO2>& rhs )
720  -> EnableIf_t< IsComputation_v<MT2>, DiagonalMatrix& >;
721 
722  template< typename MT2, bool SO2 >
723  inline auto operator-=( const Matrix<MT2,SO2>& rhs )
724  -> DisableIf_t< IsComputation_v<MT2>, DiagonalMatrix& >;
725 
726  template< typename MT2, bool SO2 >
727  inline auto operator-=( const Matrix<MT2,SO2>& rhs )
728  -> EnableIf_t< IsComputation_v<MT2>, DiagonalMatrix& >;
729 
730  template< typename MT2, bool SO2 >
731  inline auto operator%=( const Matrix<MT2,SO2>& rhs ) -> DiagonalMatrix&;
732 
733  template< typename ST >
734  inline auto operator*=( ST rhs ) -> EnableIf_t< IsNumeric_v<ST>, DiagonalMatrix& >;
735 
736  template< typename ST >
737  inline auto operator/=( ST rhs ) -> EnableIf_t< IsNumeric_v<ST>, DiagonalMatrix& >;
739  //**********************************************************************************************
740 
741  //**Utility functions***************************************************************************
744  inline size_t rows() const noexcept;
745  inline size_t columns() const noexcept;
746  inline size_t spacing() const noexcept;
747  inline size_t capacity() const noexcept;
748  inline size_t capacity( size_t i ) const noexcept;
749  inline size_t nonZeros() const;
750  inline size_t nonZeros( size_t i ) const;
751  inline void reset();
752  inline void reset( size_t i );
753  inline void clear();
754  void resize ( size_t n, bool preserve=true );
755  inline void extend ( size_t n, bool preserve=true );
756  inline void reserve( size_t elements );
757  inline void shrinkToFit();
758  inline void swap( DiagonalMatrix& m ) noexcept;
760  //**********************************************************************************************
761 
762  //**Numeric functions***************************************************************************
765  template< typename Other > inline DiagonalMatrix& scale( const Other& scalar );
767  //**********************************************************************************************
768 
769  //**Debugging functions*************************************************************************
772  inline bool isIntact() const noexcept;
774  //**********************************************************************************************
775 
776  //**Expression template evaluation functions****************************************************
779  template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
780  template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
781 
782  inline bool isAligned () const noexcept;
783  inline bool canSMPAssign() const noexcept;
784 
785  BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
786  BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
787  BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
789  //**********************************************************************************************
790 
791  private:
792  //**Construction functions**********************************************************************
795  inline const MT construct( size_t n , TrueType );
796  inline const MT construct( const ElementType& value, FalseType );
797 
798  template< typename MT2, bool SO2, typename T >
799  inline const MT construct( const Matrix<MT2,SO2>& m, T );
801  //**********************************************************************************************
802 
803  //**Member variables****************************************************************************
806  MT matrix_;
807 
808  //**********************************************************************************************
809 
810  //**Friend declarations*************************************************************************
811  template< bool RF, typename MT2, bool SO2, bool DF2 >
812  friend bool isDefault( const DiagonalMatrix<MT2,SO2,DF2>& m );
813 
814  template< typename MT2, bool SO2, bool DF2 >
815  friend MT2& derestrict( DiagonalMatrix<MT2,SO2,DF2>& m );
816  //**********************************************************************************************
817 
818  //**Compile time checks*************************************************************************
833  BLAZE_STATIC_ASSERT( ( Size_v<MT,0UL> == Size_v<MT,1UL> ) );
834  //**********************************************************************************************
835 };
837 //*************************************************************************************************
838 
839 
840 
841 
842 //=================================================================================================
843 //
844 // CONSTRUCTORS
845 //
846 //=================================================================================================
847 
848 //*************************************************************************************************
852 template< typename MT // Type of the adapted dense matrix
853  , bool SO > // Storage order of the adapted dense matrix
854 inline DiagonalMatrix<MT,SO,true>::DiagonalMatrix()
855  : matrix_() // The adapted dense matrix
856 {
857  BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
858  BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
859 }
861 //*************************************************************************************************
862 
863 
864 //*************************************************************************************************
882 template< typename MT // Type of the adapted dense matrix
883  , bool SO > // Storage order of the adapted dense matrix
884 template< typename A1 > // Type of the constructor argument
885 inline DiagonalMatrix<MT,SO,true>::DiagonalMatrix( const A1& a1 )
886  : matrix_( construct( a1, typename IsResizable<MT>::Type() ) ) // The adapted dense matrix
887 {
888  BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
889  BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
890 }
892 //*************************************************************************************************
893 
894 
895 //*************************************************************************************************
902 template< typename MT // Type of the adapted dense matrix
903  , bool SO > // Storage order of the adapted dense matrix
904 inline DiagonalMatrix<MT,SO,true>::DiagonalMatrix( size_t n, const ElementType& init )
905  : matrix_( n, n, ElementType() ) // The adapted dense matrix
906 {
908 
909  for( size_t i=0UL; i<n; ++i )
910  matrix_(i,i) = init;
911 
912  BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
913  BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
914 }
916 //*************************************************************************************************
917 
918 
919 //*************************************************************************************************
943 template< typename MT // Type of the adapted dense matrix
944  , bool SO > // Storage order of the adapted dense matrix
945 inline DiagonalMatrix<MT,SO,true>::DiagonalMatrix( initializer_list< initializer_list<ElementType> > list )
946  : matrix_( list ) // The adapted dense matrix
947 {
948  if( !isDiagonal( matrix_ ) ) {
949  BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of diagonal matrix" );
950  }
951 
952  BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
953 }
955 //*************************************************************************************************
956 
957 
958 //*************************************************************************************************
984 template< typename MT // Type of the adapted dense matrix
985  , bool SO > // Storage order of the adapted dense matrix
986 template< typename Other > // Data type of the initialization array
987 inline DiagonalMatrix<MT,SO,true>::DiagonalMatrix( size_t n, const Other* array )
988  : matrix_( n, n, array ) // The adapted dense matrix
989 {
990  if( !isDiagonal( matrix_ ) ) {
991  BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of diagonal matrix" );
992  }
993 
994  BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
995 }
997 //*************************************************************************************************
998 
999 
1000 //*************************************************************************************************
1023 template< typename MT // Type of the adapted dense matrix
1024  , bool SO > // Storage order of the adapted dense matrix
1025 template< typename Other // Data type of the initialization array
1026  , size_t N > // Number of rows and columns of the initialization array
1027 inline DiagonalMatrix<MT,SO,true>::DiagonalMatrix( const Other (&array)[N][N] )
1028  : matrix_( array ) // The adapted dense matrix
1029 {
1030  if( !isDiagonal( matrix_ ) ) {
1031  BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of diagonal matrix" );
1032  }
1033 
1034  BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
1035 }
1037 //*************************************************************************************************
1038 
1039 
1040 //*************************************************************************************************
1072 template< typename MT // Type of the adapted dense matrix
1073  , bool SO > // Storage order of the adapted dense matrix
1074 inline DiagonalMatrix<MT,SO,true>::DiagonalMatrix( ElementType* ptr, size_t n )
1075  : matrix_( ptr, n, n ) // The adapted dense matrix
1076 {
1077  if( !isDiagonal( matrix_ ) ) {
1078  BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of diagonal matrix" );
1079  }
1080 
1081  BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
1082 }
1084 //*************************************************************************************************
1085 
1086 
1087 //*************************************************************************************************
1121 template< typename MT // Type of the adapted dense matrix
1122  , bool SO > // Storage order of the adapted dense matrix
1123 inline DiagonalMatrix<MT,SO,true>::DiagonalMatrix( ElementType* ptr, size_t n, size_t nn )
1124  : matrix_( ptr, n, n, nn ) // The adapted dense matrix
1125 {
1126  if( !isDiagonal( matrix_ ) ) {
1127  BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of diagonal matrix" );
1128  }
1129 
1130  BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
1131 }
1133 //*************************************************************************************************
1134 
1135 
1136 //*************************************************************************************************
1142 template< typename MT // Type of the adapted dense matrix
1143  , bool SO > // Storage order of the adapted dense matrix
1144 inline DiagonalMatrix<MT,SO,true>::DiagonalMatrix( const DiagonalMatrix& m )
1145  : matrix_( m.matrix_ ) // The adapted dense matrix
1146 {
1147  BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
1148  BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
1149 }
1151 //*************************************************************************************************
1152 
1153 
1154 //*************************************************************************************************
1160 template< typename MT // Type of the adapted dense matrix
1161  , bool SO > // Storage order of the adapted dense matrix
1162 inline DiagonalMatrix<MT,SO,true>::DiagonalMatrix( DiagonalMatrix&& m ) noexcept
1163  : matrix_( std::move( m.matrix_ ) ) // The adapted dense matrix
1164 {
1165  BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
1166  BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
1167 }
1169 //*************************************************************************************************
1170 
1171 
1172 
1173 
1174 //=================================================================================================
1175 //
1176 // DATA ACCESS FUNCTIONS
1177 //
1178 //=================================================================================================
1179 
1180 //*************************************************************************************************
1196 template< typename MT // Type of the adapted dense matrix
1197  , bool SO > // Storage order of the adapted dense matrix
1198 inline typename DiagonalMatrix<MT,SO,true>::Reference
1199  DiagonalMatrix<MT,SO,true>::operator()( size_t i, size_t j )
1200 {
1201  BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
1202  BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
1203 
1204  return Reference( matrix_, i, j );
1205 }
1207 //*************************************************************************************************
1208 
1209 
1210 //*************************************************************************************************
1226 template< typename MT // Type of the adapted dense matrix
1227  , bool SO > // Storage order of the adapted dense matrix
1228 inline typename DiagonalMatrix<MT,SO,true>::ConstReference
1229  DiagonalMatrix<MT,SO,true>::operator()( size_t i, size_t j ) const
1230 {
1231  BLAZE_USER_ASSERT( i<rows() , "Invalid row access index" );
1232  BLAZE_USER_ASSERT( j<columns(), "Invalid column access index" );
1233 
1234  return matrix_(i,j);
1235 }
1237 //*************************************************************************************************
1238 
1239 
1240 //*************************************************************************************************
1257 template< typename MT // Type of the adapted dense matrix
1258  , bool SO > // Storage order of the adapted dense matrix
1259 inline typename DiagonalMatrix<MT,SO,true>::Reference
1260  DiagonalMatrix<MT,SO,true>::at( size_t i, size_t j )
1261 {
1262  if( i >= rows() ) {
1263  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
1264  }
1265  if( j >= columns() ) {
1266  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
1267  }
1268  return (*this)(i,j);
1269 }
1271 //*************************************************************************************************
1272 
1273 
1274 //*************************************************************************************************
1291 template< typename MT // Type of the adapted dense matrix
1292  , bool SO > // Storage order of the adapted dense matrix
1293 inline typename DiagonalMatrix<MT,SO,true>::ConstReference
1294  DiagonalMatrix<MT,SO,true>::at( size_t i, size_t j ) const
1295 {
1296  if( i >= rows() ) {
1297  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
1298  }
1299  if( j >= columns() ) {
1300  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
1301  }
1302  return (*this)(i,j);
1303 }
1305 //*************************************************************************************************
1306 
1307 
1308 //*************************************************************************************************
1321 template< typename MT // Type of the adapted dense matrix
1322  , bool SO > // Storage order of the adapted dense matrix
1323 inline typename DiagonalMatrix<MT,SO,true>::ConstPointer
1324  DiagonalMatrix<MT,SO,true>::data() const noexcept
1325 {
1326  return matrix_.data();
1327 }
1329 //*************************************************************************************************
1330 
1331 
1332 //*************************************************************************************************
1341 template< typename MT // Type of the adapted dense matrix
1342  , bool SO > // Storage order of the adapted dense matrix
1343 inline typename DiagonalMatrix<MT,SO,true>::ConstPointer
1344  DiagonalMatrix<MT,SO,true>::data( size_t i ) const noexcept
1345 {
1346  return matrix_.data(i);
1347 }
1349 //*************************************************************************************************
1350 
1351 
1352 //*************************************************************************************************
1364 template< typename MT // Type of the adapted dense matrix
1365  , bool SO > // Storage order of the adapted dense matrix
1366 inline typename DiagonalMatrix<MT,SO,true>::Iterator
1368 {
1369  if( SO )
1370  return Iterator( matrix_, 0UL, i );
1371  else
1372  return Iterator( matrix_, i, 0UL );
1373 }
1375 //*************************************************************************************************
1376 
1377 
1378 //*************************************************************************************************
1390 template< typename MT // Type of the adapted dense matrix
1391  , bool SO > // Storage order of the adapted dense matrix
1392 inline typename DiagonalMatrix<MT,SO,true>::ConstIterator
1393  DiagonalMatrix<MT,SO,true>::begin( size_t i ) const
1394 {
1395  return matrix_.begin(i);
1396 }
1398 //*************************************************************************************************
1399 
1400 
1401 //*************************************************************************************************
1413 template< typename MT // Type of the adapted dense matrix
1414  , bool SO > // Storage order of the adapted dense matrix
1415 inline typename DiagonalMatrix<MT,SO,true>::ConstIterator
1416  DiagonalMatrix<MT,SO,true>::cbegin( size_t i ) const
1417 {
1418  return matrix_.cbegin(i);
1419 }
1421 //*************************************************************************************************
1422 
1423 
1424 //*************************************************************************************************
1436 template< typename MT // Type of the adapted dense matrix
1437  , bool SO > // Storage order of the adapted dense matrix
1438 inline typename DiagonalMatrix<MT,SO,true>::Iterator
1440 {
1441  if( SO )
1442  return Iterator( matrix_, rows(), i );
1443  else
1444  return Iterator( matrix_, i, columns() );
1445 }
1447 //*************************************************************************************************
1448 
1449 
1450 //*************************************************************************************************
1462 template< typename MT // Type of the adapted dense matrix
1463  , bool SO > // Storage order of the adapted dense matrix
1464 inline typename DiagonalMatrix<MT,SO,true>::ConstIterator
1465  DiagonalMatrix<MT,SO,true>::end( size_t i ) const
1466 {
1467  return matrix_.end(i);
1468 }
1470 //*************************************************************************************************
1471 
1472 
1473 //*************************************************************************************************
1485 template< typename MT // Type of the adapted dense matrix
1486  , bool SO > // Storage order of the adapted dense matrix
1487 inline typename DiagonalMatrix<MT,SO,true>::ConstIterator
1488  DiagonalMatrix<MT,SO,true>::cend( size_t i ) const
1489 {
1490  return matrix_.cend(i);
1491 }
1493 //*************************************************************************************************
1494 
1495 
1496 
1497 
1498 //=================================================================================================
1499 //
1500 // ASSIGNMENT OPERATORS
1501 //
1502 //=================================================================================================
1503 
1504 //*************************************************************************************************
1511 template< typename MT // Type of the adapted dense matrix
1512  , bool SO > // Storage order of the adapted dense matrix
1513 inline DiagonalMatrix<MT,SO,true>&
1514  DiagonalMatrix<MT,SO,true>::operator=( const ElementType& rhs )
1515 {
1516  for( size_t i=0UL; i<rows(); ++i )
1517  matrix_(i,i) = rhs;
1518 
1519  return *this;
1520 }
1522 //*************************************************************************************************
1523 
1524 
1525 //*************************************************************************************************
1550 template< typename MT // Type of the adapted dense matrix
1551  , bool SO > // Storage order of the adapted dense matrix
1552 inline DiagonalMatrix<MT,SO,true>&
1553  DiagonalMatrix<MT,SO,true>::operator=( initializer_list< initializer_list<ElementType> > list )
1554 {
1555  const InitializerMatrix<ElementType> tmp( list, list.size() );
1556 
1557  if( !isDiagonal( tmp ) ) {
1558  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
1559  }
1560 
1561  matrix_ = list;
1562 
1563  BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
1564  BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
1565 
1566  return *this;
1567 }
1569 //*************************************************************************************************
1570 
1571 
1572 //*************************************************************************************************
1596 template< typename MT // Type of the adapted dense matrix
1597  , bool SO > // Storage order of the adapted dense matrix
1598 template< typename Other // Data type of the initialization array
1599  , size_t N > // Number of rows and columns of the initialization array
1600 inline DiagonalMatrix<MT,SO,true>&
1601  DiagonalMatrix<MT,SO,true>::operator=( const Other (&array)[N][N] )
1602 {
1603  MT tmp( array );
1604 
1605  if( !isDiagonal( tmp ) ) {
1606  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
1607  }
1608 
1609  matrix_ = std::move( tmp );
1610 
1611  BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
1612  BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
1613 
1614  return *this;
1615 }
1617 //*************************************************************************************************
1618 
1619 
1620 //*************************************************************************************************
1630 template< typename MT // Type of the adapted dense matrix
1631  , bool SO > // Storage order of the adapted dense matrix
1632 inline DiagonalMatrix<MT,SO,true>&
1633  DiagonalMatrix<MT,SO,true>::operator=( const DiagonalMatrix& rhs )
1634 {
1635  matrix_ = rhs.matrix_;
1636 
1637  BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
1638  BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
1639 
1640  return *this;
1641 }
1643 //*************************************************************************************************
1644 
1645 
1646 //*************************************************************************************************
1653 template< typename MT // Type of the adapted dense matrix
1654  , bool SO > // Storage order of the adapted dense matrix
1655 inline DiagonalMatrix<MT,SO,true>&
1656  DiagonalMatrix<MT,SO,true>::operator=( DiagonalMatrix&& rhs ) noexcept
1657 {
1658  matrix_ = std::move( rhs.matrix_ );
1659 
1660  BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
1661  BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
1662 
1663  return *this;
1664 }
1666 //*************************************************************************************************
1667 
1668 
1669 //*************************************************************************************************
1682 template< typename MT // Type of the adapted dense matrix
1683  , bool SO > // Storage order of the adapted dense matrix
1684 template< typename MT2 // Type of the right-hand side matrix
1685  , bool SO2 > // Storage order of the right-hand side matrix
1686 inline auto DiagonalMatrix<MT,SO,true>::operator=( const Matrix<MT2,SO2>& rhs )
1687  -> DisableIf_t< IsComputation_v<MT2>, DiagonalMatrix& >
1688 {
1689  if( !IsDiagonal_v<MT2> && !isDiagonal( ~rhs ) ) {
1690  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
1691  }
1692 
1693  matrix_ = decldiag( ~rhs );
1694 
1695  BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
1696  BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
1697 
1698  return *this;
1699 }
1701 //*************************************************************************************************
1702 
1703 
1704 //*************************************************************************************************
1717 template< typename MT // Type of the adapted dense matrix
1718  , bool SO > // Storage order of the adapted dense matrix
1719 template< typename MT2 // Type of the right-hand side matrix
1720  , bool SO2 > // Storage order of the right-hand side matrix
1721 inline auto DiagonalMatrix<MT,SO,true>::operator=( const Matrix<MT2,SO2>& rhs )
1722  -> EnableIf_t< IsComputation_v<MT2>, DiagonalMatrix& >
1723 {
1724  if( !IsSquare_v<MT2> && !isSquare( ~rhs ) ) {
1725  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
1726  }
1727 
1728  if( IsDiagonal_v<MT2> ) {
1729  matrix_ = ~rhs;
1730  }
1731  else {
1732  MT tmp( ~rhs );
1733 
1734  if( !isDiagonal( tmp ) ) {
1735  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
1736  }
1737 
1738  matrix_ = std::move( tmp );
1739  }
1740 
1741  BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
1742  BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
1743 
1744  return *this;
1745 }
1747 //*************************************************************************************************
1748 
1749 
1750 //*************************************************************************************************
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  , bool SO2 > // Storage order of the right-hand side matrix
1767 inline auto DiagonalMatrix<MT,SO,true>::operator+=( const Matrix<MT2,SO2>& rhs )
1768  -> DisableIf_t< IsComputation_v<MT2>, DiagonalMatrix& >
1769 {
1770  if( !IsDiagonal_v<MT2> && !isDiagonal( ~rhs ) ) {
1771  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
1772  }
1773 
1774  matrix_ += decldiag( ~rhs );
1775 
1776  BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
1777  BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
1778 
1779  return *this;
1780 }
1782 //*************************************************************************************************
1783 
1784 
1785 //*************************************************************************************************
1798 template< typename MT // Type of the adapted dense matrix
1799  , bool SO > // Storage order of the adapted dense matrix
1800 template< typename MT2 // Type of the right-hand side matrix
1801  , bool SO2 > // Storage order of the right-hand side matrix
1802 inline auto DiagonalMatrix<MT,SO,true>::operator+=( const Matrix<MT2,SO2>& rhs )
1803  -> EnableIf_t< IsComputation_v<MT2>, DiagonalMatrix& >
1804 {
1805  if( !IsSquare_v<MT2> && !isSquare( ~rhs ) ) {
1806  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
1807  }
1808 
1809  if( IsDiagonal_v<MT2> ) {
1810  matrix_ += ~rhs;
1811  }
1812  else {
1813  const ResultType_t<MT2> tmp( ~rhs );
1814 
1815  if( !isDiagonal( tmp ) ) {
1816  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
1817  }
1818 
1819  matrix_ += decldiag( tmp );
1820  }
1821 
1822  BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
1823  BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
1824 
1825  return *this;
1826 }
1828 //*************************************************************************************************
1829 
1830 
1831 //*************************************************************************************************
1844 template< typename MT // Type of the adapted dense matrix
1845  , bool SO > // Storage order of the adapted dense matrix
1846 template< typename MT2 // Type of the right-hand side matrix
1847  , bool SO2 > // Storage order of the right-hand side matrix
1848 inline auto DiagonalMatrix<MT,SO,true>::operator-=( const Matrix<MT2,SO2>& rhs )
1849  -> DisableIf_t< IsComputation_v<MT2>, DiagonalMatrix& >
1850 {
1851  if( !IsDiagonal_v<MT2> && !isDiagonal( ~rhs ) ) {
1852  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
1853  }
1854 
1855  matrix_ -= decldiag( ~rhs );
1856 
1857  BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
1858  BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
1859 
1860  return *this;
1861 }
1863 //*************************************************************************************************
1864 
1865 
1866 //*************************************************************************************************
1879 template< typename MT // Type of the adapted dense matrix
1880  , bool SO > // Storage order of the adapted dense matrix
1881 template< typename MT2 // Type of the right-hand side matrix
1882  , bool SO2 > // Storage order of the right-hand side matrix
1883 inline auto DiagonalMatrix<MT,SO,true>::operator-=( const Matrix<MT2,SO2>& rhs )
1884  -> EnableIf_t< IsComputation_v<MT2>, DiagonalMatrix& >
1885 {
1886  if( !IsSquare_v<MT2> && !isSquare( ~rhs ) ) {
1887  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
1888  }
1889 
1890  if( IsDiagonal_v<MT2> ) {
1891  matrix_ -= ~rhs;
1892  }
1893  else {
1894  const ResultType_t<MT2> tmp( ~rhs );
1895 
1896  if( !isDiagonal( tmp ) ) {
1897  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
1898  }
1899 
1900  matrix_ -= decldiag( tmp );
1901  }
1902 
1903  BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
1904  BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
1905 
1906  return *this;
1907 }
1909 //*************************************************************************************************
1910 
1911 
1912 //*************************************************************************************************
1923 template< typename MT // Type of the adapted dense matrix
1924  , bool SO > // Storage order of the adapted dense matrix
1925 template< typename MT2 // Type of the right-hand side matrix
1926  , bool SO2 > // Storage order of the right-hand side matrix
1927 inline auto DiagonalMatrix<MT,SO,true>::operator%=( const Matrix<MT2,SO2>& rhs )
1928  -> DiagonalMatrix&
1929 {
1930  if( !IsSquare_v<MT2> && !isSquare( ~rhs ) ) {
1931  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" );
1932  }
1933 
1934  matrix_ %= ~rhs;
1935 
1936  BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
1937  BLAZE_INTERNAL_ASSERT( isIntact(), "Broken invariant detected" );
1938 
1939  return *this;
1940 }
1942 //*************************************************************************************************
1943 
1944 
1945 //*************************************************************************************************
1953 template< typename MT // Type of the adapted dense matrix
1954  , bool SO > // Storage order of the adapted dense matrix
1955 template< typename ST > // Data type of the right-hand side scalar
1956 inline auto DiagonalMatrix<MT,SO,true>::operator*=( ST scalar )
1957  -> EnableIf_t< IsNumeric_v<ST>, DiagonalMatrix& >
1958 {
1959  diagonal( matrix_ ) *= scalar;
1960 
1961  return *this;
1962 }
1964 //*************************************************************************************************
1965 
1966 
1967 //*************************************************************************************************
1975 template< typename MT // Type of the adapted dense matrix
1976  , bool SO > // Storage order of the adapted dense matrix
1977 template< typename ST > // Data type of the right-hand side scalar
1978 inline auto DiagonalMatrix<MT,SO,true>::operator/=( ST scalar )
1979  -> EnableIf_t< IsNumeric_v<ST>, DiagonalMatrix& >
1980 {
1981  diagonal( matrix_ ) /= scalar;
1982 
1983  return *this;
1984 }
1986 //*************************************************************************************************
1987 
1988 
1989 
1990 
1991 //=================================================================================================
1992 //
1993 // UTILITY FUNCTIONS
1994 //
1995 //=================================================================================================
1996 
1997 //*************************************************************************************************
2003 template< typename MT // Type of the adapted dense matrix
2004  , bool SO > // Storage order of the adapted dense matrix
2005 inline size_t DiagonalMatrix<MT,SO,true>::rows() const noexcept
2006 {
2007  return matrix_.rows();
2008 }
2010 //*************************************************************************************************
2011 
2012 
2013 //*************************************************************************************************
2019 template< typename MT // Type of the adapted dense matrix
2020  , bool SO > // Storage order of the adapted dense matrix
2021 inline size_t DiagonalMatrix<MT,SO,true>::columns() const noexcept
2022 {
2023  return matrix_.columns();
2024 }
2026 //*************************************************************************************************
2027 
2028 
2029 //*************************************************************************************************
2040 template< typename MT // Type of the adapted dense matrix
2041  , bool SO > // Storage order of the adapted dense matrix
2042 inline size_t DiagonalMatrix<MT,SO,true>::spacing() const noexcept
2043 {
2044  return matrix_.spacing();
2045 }
2047 //*************************************************************************************************
2048 
2049 
2050 //*************************************************************************************************
2056 template< typename MT // Type of the adapted dense matrix
2057  , bool SO > // Storage order of the adapted dense matrix
2058 inline size_t DiagonalMatrix<MT,SO,true>::capacity() const noexcept
2059 {
2060  return matrix_.capacity();
2061 }
2063 //*************************************************************************************************
2064 
2065 
2066 //*************************************************************************************************
2078 template< typename MT // Type of the adapted dense matrix
2079  , bool SO > // Storage order of the adapted dense matrix
2080 inline size_t DiagonalMatrix<MT,SO,true>::capacity( size_t i ) const noexcept
2081 {
2082  return matrix_.capacity(i);
2083 }
2085 //*************************************************************************************************
2086 
2087 
2088 //*************************************************************************************************
2094 template< typename MT // Type of the adapted dense matrix
2095  , bool SO > // Storage order of the adapted dense matrix
2096 inline size_t DiagonalMatrix<MT,SO,true>::nonZeros() const
2097 {
2098  return matrix_.nonZeros();
2099 }
2101 //*************************************************************************************************
2102 
2103 
2104 //*************************************************************************************************
2116 template< typename MT // Type of the adapted dense matrix
2117  , bool SO > // Storage order of the adapted dense matrix
2118 inline size_t DiagonalMatrix<MT,SO,true>::nonZeros( size_t i ) const
2119 {
2120  return matrix_.nonZeros(i);
2121 }
2123 //*************************************************************************************************
2124 
2125 
2126 //*************************************************************************************************
2132 template< typename MT // Type of the adapted dense matrix
2133  , bool SO > // Storage order of the adapted dense matrix
2135 {
2136  matrix_.reset();
2137 }
2139 //*************************************************************************************************
2140 
2141 
2142 //*************************************************************************************************
2155 template< typename MT // Type of the adapted dense matrix
2156  , bool SO > // Storage order of the adapted dense matrix
2157 inline void DiagonalMatrix<MT,SO,true>::reset( size_t i )
2158 {
2159  matrix_.reset( i );
2160 }
2162 //*************************************************************************************************
2163 
2164 
2165 //*************************************************************************************************
2177 template< typename MT // Type of the adapted dense matrix
2178  , bool SO > // Storage order of the adapted dense matrix
2180 {
2181  using blaze::clear;
2182 
2183  clear( matrix_ );
2184 }
2186 //*************************************************************************************************
2187 
2188 
2189 //*************************************************************************************************
2225 template< typename MT // Type of the adapted dense matrix
2226  , bool SO > // Storage order of the adapted dense matrix
2227 void DiagonalMatrix<MT,SO,true>::resize( size_t n, bool preserve )
2228 {
2230 
2231  MAYBE_UNUSED( preserve );
2232 
2233  BLAZE_INTERNAL_ASSERT( isSquare( matrix_ ), "Non-square diagonal matrix detected" );
2234 
2235  const size_t oldsize( matrix_.rows() );
2236 
2237  matrix_.resize( n, n, true );
2238 
2239  if( n > oldsize ) {
2240  const size_t increment( n - oldsize );
2241  submatrix( matrix_, 0UL, oldsize, n, increment ).reset();
2242  submatrix( matrix_, oldsize, 0UL, increment, increment ).reset();
2243  }
2244 }
2246 //*************************************************************************************************
2247 
2248 
2249 //*************************************************************************************************
2262 template< typename MT // Type of the adapted dense matrix
2263  , bool SO > // Storage order of the adapted dense matrix
2264 inline void DiagonalMatrix<MT,SO,true>::extend( size_t n, bool preserve )
2265 {
2267 
2268  MAYBE_UNUSED( preserve );
2269 
2270  resize( rows() + n, true );
2271 }
2273 //*************************************************************************************************
2274 
2275 
2276 //*************************************************************************************************
2286 template< typename MT // Type of the adapted dense matrix
2287  , bool SO > // Storage order of the adapted dense matrix
2288 inline void DiagonalMatrix<MT,SO,true>::reserve( size_t elements )
2289 {
2290  matrix_.reserve( elements );
2291 }
2293 //*************************************************************************************************
2294 
2295 
2296 //*************************************************************************************************
2306 template< typename MT // Type of the adapted dense matrix
2307  , bool SO > // Storage order of the adapted dense matrix
2309 {
2310  matrix_.shrinkToFit();
2311 }
2313 //*************************************************************************************************
2314 
2315 
2316 //*************************************************************************************************
2323 template< typename MT // Type of the adapted dense matrix
2324  , bool SO > // Storage order of the adapted dense matrix
2325 inline void DiagonalMatrix<MT,SO,true>::swap( DiagonalMatrix& m ) noexcept
2326 {
2327  using std::swap;
2328 
2329  swap( matrix_, m.matrix_ );
2330 }
2332 //*************************************************************************************************
2333 
2334 
2335 
2336 
2337 //=================================================================================================
2338 //
2339 // NUMERIC FUNCTIONS
2340 //
2341 //=================================================================================================
2342 
2343 //*************************************************************************************************
2361 template< typename MT // Type of the adapted dense matrix
2362  , bool SO > // Storage order of the adapted dense matrix
2363 template< typename Other > // Data type of the scalar value
2364 inline DiagonalMatrix<MT,SO,true>& DiagonalMatrix<MT,SO,true>::scale( const Other& scalar )
2365 {
2366  matrix_.scale( scalar );
2367  return *this;
2368 }
2370 //*************************************************************************************************
2371 
2372 
2373 
2374 
2375 //=================================================================================================
2376 //
2377 // DEBUGGING FUNCTIONS
2378 //
2379 //=================================================================================================
2380 
2381 //*************************************************************************************************
2391 template< typename MT // Type of the adapted dense matrix
2392  , bool SO > // Storage order of the adapted dense matrix
2393 inline bool DiagonalMatrix<MT,SO,true>::isIntact() const noexcept
2394 {
2395  using blaze::isIntact;
2396 
2397  return ( isIntact( matrix_ ) && isDiagonal( matrix_ ) );
2398 }
2400 //*************************************************************************************************
2401 
2402 
2403 
2404 
2405 //=================================================================================================
2406 //
2407 // EXPRESSION TEMPLATE EVALUATION FUNCTIONS
2408 //
2409 //=================================================================================================
2410 
2411 //*************************************************************************************************
2422 template< typename MT // Type of the adapted dense matrix
2423  , bool SO > // Storage order of the adapted dense matrix
2424 template< typename Other > // Data type of the foreign expression
2425 inline bool DiagonalMatrix<MT,SO,true>::canAlias( const Other* alias ) const noexcept
2426 {
2427  return matrix_.canAlias( alias );
2428 }
2430 //*************************************************************************************************
2431 
2432 
2433 //*************************************************************************************************
2444 template< typename MT // Type of the adapted dense matrix
2445  , bool SO > // Storage order of the adapted dense matrix
2446 template< typename Other > // Data type of the foreign expression
2447 inline bool DiagonalMatrix<MT,SO,true>::isAliased( const Other* alias ) const noexcept
2448 {
2449  return matrix_.isAliased( alias );
2450 }
2452 //*************************************************************************************************
2453 
2454 
2455 //*************************************************************************************************
2465 template< typename MT // Type of the adapted dense matrix
2466  , bool SO > // Storage order of the adapted dense matrix
2467 inline bool DiagonalMatrix<MT,SO,true>::isAligned() const noexcept
2468 {
2469  return matrix_.isAligned();
2470 }
2472 //*************************************************************************************************
2473 
2474 
2475 //*************************************************************************************************
2486 template< typename MT // Type of the adapted dense matrix
2487  , bool SO > // Storage order of the adapted dense matrix
2488 inline bool DiagonalMatrix<MT,SO,true>::canSMPAssign() const noexcept
2489 {
2490  return matrix_.canSMPAssign();
2491 }
2493 //*************************************************************************************************
2494 
2495 
2496 //*************************************************************************************************
2512 template< typename MT // Type of the adapted dense matrix
2513  , bool SO > // Storage order of the adapted dense matrix
2514 BLAZE_ALWAYS_INLINE typename DiagonalMatrix<MT,SO,true>::SIMDType
2515  DiagonalMatrix<MT,SO,true>::load( size_t i, size_t j ) const noexcept
2516 {
2517  return matrix_.load( i, j );
2518 }
2520 //*************************************************************************************************
2521 
2522 
2523 //*************************************************************************************************
2539 template< typename MT // Type of the adapted dense matrix
2540  , bool SO > // Storage order of the adapted dense matrix
2541 BLAZE_ALWAYS_INLINE typename DiagonalMatrix<MT,SO,true>::SIMDType
2542  DiagonalMatrix<MT,SO,true>::loada( size_t i, size_t j ) const noexcept
2543 {
2544  return matrix_.loada( i, j );
2545 }
2547 //*************************************************************************************************
2548 
2549 
2550 //*************************************************************************************************
2566 template< typename MT // Type of the adapted dense matrix
2567  , bool SO > // Storage order of the adapted dense matrix
2568 BLAZE_ALWAYS_INLINE typename DiagonalMatrix<MT,SO,true>::SIMDType
2569  DiagonalMatrix<MT,SO,true>::loadu( size_t i, size_t j ) const noexcept
2570 {
2571  return matrix_.loadu( i, j );
2572 }
2574 //*************************************************************************************************
2575 
2576 
2577 
2578 
2579 //=================================================================================================
2580 //
2581 // CONSTRUCTION FUNCTIONS
2582 //
2583 //=================================================================================================
2584 
2585 //*************************************************************************************************
2592 template< typename MT // Type of the adapted dense matrix
2593  , bool SO > // Storage order of the adapted dense matrix
2594 inline const MT DiagonalMatrix<MT,SO,true>::construct( size_t n, TrueType )
2595 {
2597 
2598  return MT( n, n, ElementType() );
2599 }
2601 //*************************************************************************************************
2602 
2603 
2604 //*************************************************************************************************
2611 template< typename MT // Type of the adapted dense matrix
2612  , bool SO > // Storage order of the adapted dense matrix
2613 inline const MT DiagonalMatrix<MT,SO,true>::construct( const ElementType& init, FalseType )
2614 {
2617 
2618  MT tmp;
2619 
2620  for( size_t i=0UL; i<tmp.rows(); ++i )
2621  tmp(i,i) = init;
2622 
2623  return tmp;
2624 }
2626 //*************************************************************************************************
2627 
2628 
2629 //*************************************************************************************************
2640 template< typename MT // Type of the adapted dense matrix
2641  , bool SO > // Storage order of the adapted dense matrix
2642 template< typename MT2 // Type of the foreign matrix
2643  , bool SO2 // Storage order of the foreign matrix
2644  , typename T > // Type of the third argument
2645 inline const MT DiagonalMatrix<MT,SO,true>::construct( const Matrix<MT2,SO2>& m, T )
2646 {
2647  const MT tmp( ~m );
2648 
2649  if( !IsDiagonal_v<MT2> && !isDiagonal( tmp ) ) {
2650  BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of diagonal matrix" );
2651  }
2652 
2653  return tmp;
2654 }
2656 //*************************************************************************************************
2657 
2658 } // namespace blaze
2659 
2660 #endif
#define BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSFORMATION_TYPE(T)
Constraint on the data type.In case the given data type T is a transformation expression (i....
Definition: Transformation.h:81
Constraint on the data type.
Header file for the implementation of the Submatrix view.
#define BLAZE_CONSTRAINT_MUST_NOT_BE_CONST(T)
Constraint on the data type.In case the given data type is a const-qualified type,...
Definition: Const.h:79
Header file for the UnderlyingNumeric type trait.
BoolConstant< false > FalseType
Type/value traits base class.The FalseType class is used as base class for type traits and value trai...
Definition: IntegralConstant.h:121
#define BLAZE_THROW_INVALID_ARGUMENT(MESSAGE)
Macro for the emission of a std::invalid_argument exception.This macro encapsulates the default way o...
Definition: Exception.h:235
Constraint on the data type.
Header file for auxiliary alias declarations.
decltype(auto) column(Matrix< MT, SO > &matrix, RCAs... args)
Creating a view on a specific column of the given matrix.
Definition: Column.h:133
auto operator-=(DenseMatrix< MT, SO > &mat, ST scalar) -> EnableIf_t< IsNumeric_v< ST >, MT & >
Subtraction assignment operator for the subtraction of a dense matrix and a scalar value ( ).
Definition: DenseMatrix.h:432
constexpr ptrdiff_t Size_v
Auxiliary variable template for the Size type trait.The Size_v variable template provides a convenien...
Definition: Size.h:176
decltype(auto) decldiag(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as diagonal.
Definition: DMatDeclDiagExpr.h:975
Constraint on the data type.
#define BLAZE_USER_ASSERT(expr, msg)
Run time assertion macro for user checks.In case of an invalid run time expression,...
Definition: Assert.h:117
size_t capacity(const Matrix< MT, SO > &matrix) noexcept
Returns the maximum capacity of the matrix.
Definition: Matrix.h:546
Header file for basic type definitions.
constexpr const DenseIterator< Type, AF > operator-(const DenseIterator< Type, AF > &it, ptrdiff_t inc) noexcept
Subtraction between a DenseIterator and an integral value.
Definition: DenseIterator.h:750
MT::ElementType * data(DenseMatrix< MT, SO > &dm) noexcept
Low-level data access to the dense matrix elements.
Definition: DenseMatrix.h:170
decltype(auto) submatrix(Matrix< MT, SO > &, RSAs...)
Creating a view on a specific submatrix of the given matrix.
Definition: Submatrix.h:178
#define BLAZE_CONSTRAINT_MUST_BE_MATRIX_WITH_STORAGE_ORDER(T, SO)
Constraint on the data type.In case the given data type T is not a dense or sparse matrix type and in...
Definition: StorageOrder.h:63
Header file for the isZero shim.
Header file for the IsDiagonal type trait.
#define BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE(T)
Constraint on the data type.In case the given data type T is a computational expression (i....
Definition: Computation.h:81
Header file for the implementation of the Band view.
#define BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a dense, N-dimensional matrix type,...
Definition: DenseMatrix.h:61
constexpr bool operator<(const NegativeAccuracy< A > &lhs, const T &rhs)
Less-than comparison between a NegativeAccuracy object and a floating point value.
Definition: Accuracy.h:332
BLAZE_ALWAYS_INLINE const EnableIf_t< IsIntegral_v< T > &&HasSize_v< T, 1UL >, If_t< IsSigned_v< T >, SIMDint8, SIMDuint8 > > loadu(const T *address) noexcept
Loads a vector of 1-byte integral values.
Definition: Loadu.h:76
Constraint on the data type.
MT::Iterator begin(Matrix< MT, SO > &matrix, size_t i)
Returns an iterator to the first element of row/column i.
Definition: Matrix.h:372
void reset(const DiagonalProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: DiagonalProxy.h:595
void shrinkToFit(Matrix< MT, SO > &matrix)
Requesting the removal of unused capacity.
Definition: Matrix.h:799
Header file for the MAYBE_UNUSED function template.
#define BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE(T)
Constraint on the data type.In case the given data type is a volatile-qualified type,...
Definition: Volatile.h:79
bool isDiagonal(const DenseMatrix< MT, SO > &dm)
Checks if the give dense matrix is diagonal.
Definition: DenseMatrix.h:2328
size_t nonZeros(const Matrix< MT, SO > &matrix)
Returns the total number of non-zero elements in the matrix.
Definition: Matrix.h:584
BoolConstant< true > TrueType
Type traits base class.The TrueType class is used as base class for type traits and value traits that...
Definition: IntegralConstant.h:132
Header file for the extended initializer_list functionality.
Constraint on the data type.
constexpr size_t columns(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of columns of the matrix.
Definition: Matrix.h:514
MT::ConstIterator cend(const Matrix< MT, SO > &matrix, size_t i)
Returns an iterator just past the last element of row/column i.
Definition: Matrix.h:482
MT::ConstIterator cbegin(const Matrix< MT, SO > &matrix, size_t i)
Returns an iterator to the first element of row/column i.
Definition: Matrix.h:416
Constraint on the data type.
Constraint on the data type.
size_t spacing(const DenseMatrix< MT, SO > &dm) noexcept
Returns the spacing between the beginning of two rows/columns.
Definition: DenseMatrix.h:253
#define BLAZE_CONSTRAINT_MUST_BE_SQUARE_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a square matrix type,...
Definition: Square.h:60
Header file for the IsSquare type trait.
Constraint on the data type.
Header file for the implementation of a matrix representation of an initializer list.
typename EnableIf< Condition, T >::Type EnableIf_t
Auxiliary type for the EnableIf class template.The EnableIf_t alias declaration provides a convenient...
Definition: EnableIf.h:138
Header file for the DisableIf class template.
Header file for the DiagonalProxy class.
Namespace of the Blaze C++ math library.
Definition: Blaze.h:58
#define BLAZE_ALWAYS_INLINE
Platform dependent setup of an enforced inline keyword.
Definition: Inline.h:85
Header file for the If class template.
Compile time assertion.
Header file for the IsFloatingPoint type trait.
decltype(auto) operator *(const DenseMatrix< MT1, false > &lhs, const DenseMatrix< MT2, false > &rhs)
Multiplication operator for the multiplication of two row-major dense matrices ( ).
Definition: DMatDMatMultExpr.h:9091
Header file for the UnderlyingBuiltin type trait.
#define BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE(T)
Constraint on the data type.In case the given data type T is not a pointer type, a compilation error ...
Definition: Pointer.h:79
#define BLAZE_THROW_OUT_OF_RANGE(MESSAGE)
Macro for the emission of a std::out_of_range exception.This macro encapsulates the default way of Bl...
Definition: Exception.h:331
Header file for the DenseMatrix base class.
constexpr bool operator>(const NegativeAccuracy< A > &lhs, const T &rhs)
Greater-than comparison between a NegativeAccuracy object and a floating point value.
Definition: Accuracy.h:370
constexpr bool operator>=(const NegativeAccuracy< A > &, const T &rhs)
Greater-or-equal-than comparison between a NegativeAccuracy object and a floating point value.
Definition: Accuracy.h:446
auto operator+=(DenseMatrix< MT, SO > &mat, ST scalar) -> EnableIf_t< IsNumeric_v< ST >, MT & >
Addition assignment operator for the addition of a dense matrix and a scalar value ( ).
Definition: DenseMatrix.h:370
constexpr bool operator==(const NegativeAccuracy< A > &lhs, const T &rhs)
Equality comparison between a NegativeAccuracy object and a floating point value.
Definition: Accuracy.h:253
constexpr bool IsNumeric_v
Auxiliary variable template for the IsNumeric type trait.The IsNumeric_v variable template provides a...
Definition: IsNumeric.h:143
Constraint on the data type.
constexpr void MAYBE_UNUSED(const Args &...)
Suppression of unused parameter warnings.
Definition: MaybeUnused.h:81
Constraints on the storage order of matrix types.
decltype(auto) elements(Vector< VT, TF > &vector, REAs... args)
Creating a view on a selection of elements of the given vector.
Definition: Elements.h:139
Header file for the exception macros of the math module.
#define BLAZE_CONSTRAINT_MUST_NOT_BE_UPPER_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is a upper triangular matrix type,...
Definition: Upper.h:81
void resize(Matrix< MT, SO > &matrix, size_t rows, size_t columns, bool preserve=true)
Changing the size of the matrix.
Definition: Matrix.h:738
MT::Iterator end(Matrix< MT, SO > &matrix, size_t i)
Returns an iterator just past the last element of row/column i.
Definition: Matrix.h:438
decltype(auto) diagonal(Matrix< MT, SO > &matrix, RDAs... args)
Creating a view on the diagonal of the given matrix.
Definition: Band.h:377
constexpr bool operator!=(const NegativeAccuracy< A > &lhs, const T &rhs)
Inequality comparison between a NegativeAccuracy object and a floating point value.
Definition: Accuracy.h:293
Header file for the EnableIf class template.
Header file for utility functions for dense matrices.
void clear(const DiagonalProxy< MT > &proxy)
Clearing the represented element.
Definition: DiagonalProxy.h:615
constexpr bool IsComputation_v
Auxiliary variable template for the IsComputation type trait.The IsComputation_v variable template pr...
Definition: IsComputation.h:90
Header file for the IsNumeric type trait.
auto operator/=(DenseMatrix< MT, SO > &mat, ST scalar) -> EnableIf_t< IsNumeric_v< ST >, MT & >
Division assignment operator for the division of a dense matrix by a scalar value ( ).
Definition: DenseMatrix.h:558
#define BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is a symmetric matrix type,...
Definition: Symmetric.h:79
Header file for run time assertion macros.
Constraint on the data type.
Constraint on the data type.
Constraint on the data type.
decltype(auto) row(Matrix< MT, SO > &, RRAs...)
Creating a view on a specific row of the given matrix.
Definition: Row.h:133
#define BLAZE_CONSTRAINT_MUST_NOT_BE_LOWER_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is a lower triangular matrix type,...
Definition: Lower.h:81
#define BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE_TYPE(T)
Constraint on the data type.In case the given data type T is resizable, i.e. has a 'resize' member fu...
Definition: Resizable.h:81
#define BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE(T)
Constraint on the data type.In case the given data type T is not a reference type,...
Definition: Reference.h:79
Header file for the isDefault shim.
void swap(DiagonalMatrix< MT, SO, DF > &a, DiagonalMatrix< MT, SO, DF > &b) noexcept
Swapping the contents of two matrices.
Definition: DiagonalMatrix.h:282
Constraint on the data type.
Constraint on the data type.
constexpr bool operator<=(const NegativeAccuracy< A > &, const T &rhs)
Less-or-equal-than comparison between a NegativeAccuracy object and a floating point value.
Definition: Accuracy.h:408
#define BLAZE_CONSTRAINT_MUST_NOT_BE_VIEW_TYPE(T)
Constraint on the data type.In case the given data type T is a view type (i.e. a subvector,...
Definition: View.h:81
constexpr size_t rows(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of rows of the matrix.
Definition: Matrix.h:498
constexpr const DenseIterator< Type, AF > operator+(const DenseIterator< Type, AF > &it, ptrdiff_t inc) noexcept
Addition between a DenseIterator and an integral value.
Definition: DenseIterator.h:718
Header file for the IsInvertible type trait.
BLAZE_ALWAYS_INLINE const EnableIf_t< IsIntegral_v< T > &&HasSize_v< T, 1UL >, If_t< IsSigned_v< T >, SIMDint8, SIMDuint8 > > loada(const T *address) noexcept
Loads a vector of 1-byte integral values.
Definition: Loada.h:79
Header file for the implementation of the base template of the DiagonalMatrix.
#define BLAZE_CONSTRAINT_MUST_BE_RESIZABLE_TYPE(T)
Constraint on the data type.In case the given data type T is not resizable, i.e. does not have a 'res...
Definition: Resizable.h:61
Header file for the IsComputation type trait class.
Header file for the IsBuiltin type trait.
Header file for the IntegralConstant class template.
bool isIntact(const DiagonalMatrix< MT, SO, DF > &m)
Returns whether the invariants of the given diagonal matrix are intact.
Definition: DiagonalMatrix.h:264
Header file for the IsComplex type trait.
auto operator *=(DenseMatrix< MT, SO > &mat, ST scalar) -> EnableIf_t< IsNumeric_v< ST >, MT & >
Multiplication assignment operator for the multiplication of a dense matrix and a scalar value ( ).
Definition: DenseMatrix.h:494
bool isDefault(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is in default state.
Definition: DiagonalProxy.h:635
#define BLAZE_CONSTRAINT_MUST_NOT_BE_HERMITIAN_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is an Hermitian matrix type,...
Definition: Hermitian.h:79
typename DisableIf< Condition, T >::Type DisableIf_t
Auxiliary type for the DisableIf class template.The DisableIf_t alias declaration provides a convenie...
Definition: DisableIf.h:138
#define BLAZE_STATIC_ASSERT(expr)
Compile time assertion macro.In case of an invalid compile time expression, a compilation error is cr...
Definition: StaticAssert.h:112
bool isSquare(const Matrix< MT, SO > &matrix) noexcept
Checks if the given matrix is a square matrix.
Definition: Matrix.h:951
Header file for the IsResizable type trait.
Constraint on the data type.
System settings for the inline keywords.
Header file for the Size type trait.
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression,...
Definition: Assert.h:101
Header file for the clear shim.