Blaze  3.6
HybridMatrix.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_DENSE_HYBRIDMATRIX_H_
36 #define _BLAZE_MATH_DENSE_HYBRIDMATRIX_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <algorithm>
44 #include <utility>
45 #include <blaze/math/Aliases.h>
49 #include <blaze/math/Exception.h>
52 #include <blaze/math/Forward.h>
54 #include <blaze/math/shims/Clear.h>
59 #include <blaze/math/SIMD.h>
101 #include <blaze/system/Inline.h>
107 #include <blaze/util/AlignedArray.h>
109 #include <blaze/util/Assert.h>
116 #include <blaze/util/DisableIf.h>
117 #include <blaze/util/EnableIf.h>
119 #include <blaze/util/MaybeUnused.h>
120 #include <blaze/util/Memory.h>
121 #include <blaze/util/StaticAssert.h>
122 #include <blaze/util/Types.h>
128 
129 
130 namespace blaze {
131 
132 //=================================================================================================
133 //
134 // CLASS DEFINITION
135 //
136 //=================================================================================================
137 
138 //*************************************************************************************************
224 template< typename Type // Data type of the matrix
225  , size_t M // Number of rows
226  , size_t N // Number of columns
227  , bool SO = defaultStorageOrder > // Storage order
228 class HybridMatrix
229  : public DenseMatrix< HybridMatrix<Type,M,N,SO>, SO >
230 {
231  private:
232  //**********************************************************************************************
234  static constexpr size_t SIMDSIZE = SIMDTrait<Type>::size;
235 
237  static constexpr size_t NN = ( usePadding ? nextMultiple( N, SIMDSIZE ) : N );
238 
240  static constexpr bool align = ( usePadding || NN % SIMDSIZE == 0UL );
241  //**********************************************************************************************
242 
243  public:
244  //**Type definitions****************************************************************************
247  using ResultType = This;
250  using ElementType = Type;
252  using ReturnType = const Type&;
253  using CompositeType = const This&;
254 
255  using Reference = Type&;
256  using ConstReference = const Type&;
257  using Pointer = Type*;
258  using ConstPointer = const Type*;
259 
262  //**********************************************************************************************
263 
264  //**Rebind struct definition********************************************************************
267  template< typename NewType > // Data type of the other matrix
268  struct Rebind {
270  };
271  //**********************************************************************************************
272 
273  //**Resize struct definition********************************************************************
276  template< size_t NewM // Number of rows of the other matrix
277  , size_t NewN > // Number of columns of the other matrix
278  struct Resize {
280  };
281  //**********************************************************************************************
282 
283  //**Compilation flags***************************************************************************
285 
289  static constexpr bool simdEnabled = IsVectorizable_v<Type>;
290 
292 
295  static constexpr bool smpAssignable = false;
296  //**********************************************************************************************
297 
298  //**Constructors********************************************************************************
301  explicit inline HybridMatrix();
302  explicit inline HybridMatrix( size_t m, size_t n );
303  explicit inline HybridMatrix( size_t m, size_t n, const Type& init );
305 
306  template< typename Other >
307  explicit inline HybridMatrix( size_t m, size_t n, const Other* array );
308 
309  template< typename Other, size_t Rows, size_t Cols >
310  explicit inline HybridMatrix( const Other (&array)[Rows][Cols] );
311 
312  inline HybridMatrix( const HybridMatrix& m );
313  template< typename MT, bool SO2 > inline HybridMatrix( const Matrix<MT,SO2>& m );
315  //**********************************************************************************************
316 
317  //**Destructor**********************************************************************************
320  ~HybridMatrix() = default;
322  //**********************************************************************************************
323 
324  //**Data access functions***********************************************************************
327  inline Reference operator()( size_t i, size_t j ) noexcept;
328  inline ConstReference operator()( size_t i, size_t j ) const noexcept;
329  inline Reference at( size_t i, size_t j );
330  inline ConstReference at( size_t i, size_t j ) const;
331  inline Pointer data () noexcept;
332  inline ConstPointer data () const noexcept;
333  inline Pointer data ( size_t i ) noexcept;
334  inline ConstPointer data ( size_t i ) const noexcept;
335  inline Iterator begin ( size_t i ) noexcept;
336  inline ConstIterator begin ( size_t i ) const noexcept;
337  inline ConstIterator cbegin( size_t i ) const noexcept;
338  inline Iterator end ( size_t i ) noexcept;
339  inline ConstIterator end ( size_t i ) const noexcept;
340  inline ConstIterator cend ( size_t i ) const noexcept;
342  //**********************************************************************************************
343 
344  //**Assignment operators************************************************************************
347  inline HybridMatrix& operator=( const Type& set );
348  inline HybridMatrix& operator=( initializer_list< initializer_list<Type> > list );
349 
350  template< typename Other, size_t Rows, size_t Cols >
351  inline HybridMatrix& operator=( const Other (&array)[Rows][Cols] );
352 
353  inline HybridMatrix& operator= ( const HybridMatrix& rhs );
354  template< typename MT, bool SO2 > inline HybridMatrix& operator= ( const Matrix<MT,SO2>& rhs );
355  template< typename MT, bool SO2 > inline HybridMatrix& operator+=( const Matrix<MT,SO2>& rhs );
356  template< typename MT, bool SO2 > inline HybridMatrix& operator-=( const Matrix<MT,SO2>& rhs );
357  template< typename MT, bool SO2 > inline HybridMatrix& operator%=( const Matrix<MT,SO2>& rhs );
359  //**********************************************************************************************
360 
361  //**Utility functions***************************************************************************
364  inline size_t rows() const noexcept;
365  inline size_t columns() const noexcept;
366  static inline constexpr size_t spacing() noexcept;
367  static inline constexpr size_t capacity() noexcept;
368  inline size_t capacity( size_t i ) const noexcept;
369  inline size_t nonZeros() const;
370  inline size_t nonZeros( size_t i ) const;
371  inline void reset();
372  inline void reset( size_t i );
373  inline void clear();
374  void resize ( size_t m, size_t n, bool preserve=true );
375  inline void extend ( size_t m, size_t n, bool preserve=true );
376  inline void swap( HybridMatrix& m ) noexcept;
378  //**********************************************************************************************
379 
380  //**Numeric functions***************************************************************************
383  inline HybridMatrix& transpose();
384  inline HybridMatrix& ctranspose();
385 
386  template< typename Other > inline HybridMatrix& scale( const Other& scalar );
388  //**********************************************************************************************
389 
390  //**Memory functions****************************************************************************
393  static inline void* operator new ( std::size_t size );
394  static inline void* operator new[]( std::size_t size );
395  static inline void* operator new ( std::size_t size, const std::nothrow_t& );
396  static inline void* operator new[]( std::size_t size, const std::nothrow_t& );
397 
398  static inline void operator delete ( void* ptr );
399  static inline void operator delete[]( void* ptr );
400  static inline void operator delete ( void* ptr, const std::nothrow_t& );
401  static inline void operator delete[]( void* ptr, const std::nothrow_t& );
403  //**********************************************************************************************
404 
405  private:
406  //**********************************************************************************************
408  template< typename MT >
410  static constexpr bool VectorizedAssign_v =
411  ( useOptimizedKernels &&
412  simdEnabled && MT::simdEnabled &&
413  IsSIMDCombinable_v< Type, ElementType_t<MT> > &&
414  IsRowMajorMatrix_v<MT> );
416  //**********************************************************************************************
417 
418  //**********************************************************************************************
420  template< typename MT >
422  static constexpr bool VectorizedAddAssign_v =
423  ( useOptimizedKernels &&
424  simdEnabled && MT::simdEnabled &&
425  IsSIMDCombinable_v< Type, ElementType_t<MT> > &&
426  HasSIMDAdd_v< Type, ElementType_t<MT> > &&
427  IsRowMajorMatrix_v<MT> &&
428  !IsDiagonal_v<MT> );
430  //**********************************************************************************************
431 
432  //**********************************************************************************************
434  template< typename MT >
436  static constexpr bool VectorizedSubAssign_v =
437  ( useOptimizedKernels &&
438  simdEnabled && MT::simdEnabled &&
439  IsSIMDCombinable_v< Type, ElementType_t<MT> > &&
440  HasSIMDSub_v< Type, ElementType_t<MT> > &&
441  IsRowMajorMatrix_v<MT> &&
442  !IsDiagonal_v<MT> );
444  //**********************************************************************************************
445 
446  //**********************************************************************************************
448  template< typename MT >
450  static constexpr bool VectorizedSchurAssign_v =
451  ( useOptimizedKernels &&
452  simdEnabled && MT::simdEnabled &&
453  IsSIMDCombinable_v< Type, ElementType_t<MT> > &&
454  HasSIMDMult_v< Type, ElementType_t<MT> > &&
455  IsRowMajorMatrix_v<MT> );
457  //**********************************************************************************************
458 
459  public:
460  //**Debugging functions*************************************************************************
463  inline bool isIntact() const noexcept;
465  //**********************************************************************************************
466 
467  //**Expression template evaluation functions****************************************************
470  template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
471  template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
472 
473  static inline constexpr bool isAligned() noexcept;
474 
475  BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
476  BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
477  BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
478 
479  BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
480  BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
481  BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
482  BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
483 
484  template< typename MT, bool SO2 >
485  inline auto assign( const DenseMatrix<MT,SO2>& rhs ) -> DisableIf_t< VectorizedAssign_v<MT> >;
486 
487  template< typename MT, bool SO2 >
488  inline auto assign( const DenseMatrix<MT,SO2>& rhs ) -> EnableIf_t< VectorizedAssign_v<MT> >;
489 
490  template< typename MT > inline void assign( const SparseMatrix<MT,SO>& rhs );
491  template< typename MT > inline void assign( const SparseMatrix<MT,!SO>& rhs );
492 
493  template< typename MT, bool SO2 >
494  inline auto addAssign( const DenseMatrix<MT,SO2>& rhs ) -> DisableIf_t< VectorizedAddAssign_v<MT> >;
495 
496  template< typename MT, bool SO2 >
497  inline auto addAssign( const DenseMatrix<MT,SO2>& rhs ) -> EnableIf_t< VectorizedAddAssign_v<MT> >;
498 
499  template< typename MT > inline void addAssign( const SparseMatrix<MT,SO>& rhs );
500  template< typename MT > inline void addAssign( const SparseMatrix<MT,!SO>& rhs );
501 
502  template< typename MT, bool SO2 >
503  inline auto subAssign( const DenseMatrix<MT,SO2>& rhs ) -> DisableIf_t< VectorizedSubAssign_v<MT> >;
504 
505  template< typename MT, bool SO2 >
506  inline auto subAssign( const DenseMatrix<MT,SO2>& rhs ) -> EnableIf_t< VectorizedSubAssign_v<MT> >;
507 
508  template< typename MT > inline void subAssign( const SparseMatrix<MT,SO>& rhs );
509  template< typename MT > inline void subAssign( const SparseMatrix<MT,!SO>& rhs );
510 
511  template< typename MT, bool SO2 >
512  inline auto schurAssign( const DenseMatrix<MT,SO2>& rhs ) -> DisableIf_t< VectorizedSchurAssign_v<MT> >;
513 
514  template< typename MT, bool SO2 >
515  inline auto schurAssign( const DenseMatrix<MT,SO2>& rhs ) -> EnableIf_t< VectorizedSchurAssign_v<MT> >;
516 
517  template< typename MT > inline void schurAssign( const SparseMatrix<MT,SO>& rhs );
518  template< typename MT > inline void schurAssign( const SparseMatrix<MT,!SO>& rhs );
520  //**********************************************************************************************
521 
522  private:
523  //**********************************************************************************************
525  static constexpr size_t Alignment =
526  ( align ? AlignmentOf_v<Type> : std::alignment_of<Type>::value );
527 
530  //**********************************************************************************************
531 
532  //**Member variables****************************************************************************
536 
545  size_t m_;
546  size_t n_;
547 
548  //**********************************************************************************************
549 
550  //**Compile time checks*************************************************************************
556  BLAZE_STATIC_ASSERT( !usePadding || NN % SIMDSIZE == 0UL );
557  BLAZE_STATIC_ASSERT( NN >= N );
559  //**********************************************************************************************
560 };
561 //*************************************************************************************************
562 
563 
564 
565 
566 //=================================================================================================
567 //
568 // CONSTRUCTORS
569 //
570 //=================================================================================================
571 
572 //*************************************************************************************************
577 template< typename Type // Data type of the matrix
578  , size_t M // Number of rows
579  , size_t N // Number of columns
580  , bool SO > // Storage order
581 inline HybridMatrix<Type,M,N,SO>::HybridMatrix()
582  : v_() // The statically allocated matrix elements
583  , m_( 0UL ) // The current number of rows of the matrix
584  , n_( 0UL ) // The current number of columns of the matrix
585 {
586  BLAZE_STATIC_ASSERT( IsVectorizable_v<Type> || NN == N );
587 
588  if( IsNumeric_v<Type> ) {
589  for( size_t i=0UL; i<M*NN; ++i )
590  v_[i] = Type();
591  }
592 
593  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
594 }
595 //*************************************************************************************************
596 
597 
598 //*************************************************************************************************
611 template< typename Type // Data type of the matrix
612  , size_t M // Number of rows
613  , size_t N // Number of columns
614  , bool SO > // Storage order
615 inline HybridMatrix<Type,M,N,SO>::HybridMatrix( size_t m, size_t n )
616  : v_() // The statically allocated matrix elements
617  , m_( m ) // The current number of rows of the matrix
618  , n_( n ) // The current number of columns of the matrix
619 {
620  BLAZE_STATIC_ASSERT( IsVectorizable_v<Type> || NN == N );
621 
622  if( m > M ) {
623  BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of rows for hybrid matrix" );
624  }
625 
626  if( n > N ) {
627  BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of columns for hybrid matrix" );
628  }
629 
630  if( IsNumeric_v<Type> ) {
631  for( size_t i=0UL; i<M*NN; ++i )
632  v_[i] = Type();
633  }
634 
635  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
636 }
637 //*************************************************************************************************
638 
639 
640 //*************************************************************************************************
654 template< typename Type // Data type of the matrix
655  , size_t M // Number of rows
656  , size_t N // Number of columns
657  , bool SO > // Storage order
658 inline HybridMatrix<Type,M,N,SO>::HybridMatrix( size_t m, size_t n, const Type& init )
659  : v_() // The statically allocated matrix elements
660  , m_( m ) // The current number of rows of the matrix
661  , n_( n ) // The current number of columns of the matrix
662 {
663  BLAZE_STATIC_ASSERT( IsVectorizable_v<Type> || NN == N );
664 
665  if( m > M ) {
666  BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of rows for hybrid matrix" );
667  }
668 
669  if( n > N ) {
670  BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of columns for hybrid matrix" );
671  }
672 
673  for( size_t i=0UL; i<m; ++i ) {
674  for( size_t j=0UL; j<n; ++j )
675  v_[i*NN+j] = init;
676 
677  if( IsNumeric_v<Type> ) {
678  for( size_t j=n; j<NN; ++j )
679  v_[i*NN+j] = Type();
680  }
681  }
682 
683  if( IsNumeric_v<Type> ) {
684  for( size_t i=m; i<M; ++i )
685  for( size_t j=0UL; j<NN; ++j )
686  v_[i*NN+j] = Type();
687  }
688 
689  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
690 }
691 //*************************************************************************************************
692 
693 
694 //*************************************************************************************************
718 template< typename Type // Data type of the matrix
719  , size_t M // Number of rows
720  , size_t N // Number of columns
721  , bool SO > // Storage order
723  : v_() // The statically allocated matrix elements
724  , m_( list.size() ) // The current number of rows of the matrix
725  , n_( determineColumns( list ) ) // The current number of columns of the matrix
726 {
727  BLAZE_STATIC_ASSERT( IsVectorizable_v<Type> || NN == N );
728 
729  if( m_ > M ) {
730  BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of rows for hybrid matrix" );
731  }
732 
733  if( n_ > N ) {
734  BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of columns for hybrid matrix" );
735  }
736 
737  size_t i( 0UL );
738 
739  for( const auto& rowList : list ) {
740  std::fill( std::copy( rowList.begin(), rowList.end(), v_+i*NN ), v_+(i+1UL)*NN, Type() );
741  ++i;
742  }
743 
744  if( IsNumeric_v<Type> ) {
745  for( ; i<M; ++i )
746  for( size_t j=0UL; j<NN; ++j )
747  v_[i*NN+j] = Type();
748  }
749 
750  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
751 }
752 //*************************************************************************************************
753 
754 
755 //*************************************************************************************************
782 template< typename Type // Data type of the matrix
783  , size_t M // Number of rows
784  , size_t N // Number of columns
785  , bool SO > // Storage order
786 template< typename Other > // Data type of the initialization array
787 inline HybridMatrix<Type,M,N,SO>::HybridMatrix( size_t m, size_t n, const Other* array )
788  : v_() // The statically allocated matrix elements
789  , m_( m ) // The current number of rows of the matrix
790  , n_( n ) // The current number of columns of the matrix
791 {
792  BLAZE_STATIC_ASSERT( IsVectorizable_v<Type> || NN == N );
793 
794  if( m > M ) {
795  BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of rows for hybrid matrix" );
796  }
797 
798  if( n > N ) {
799  BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of columns for hybrid matrix" );
800  }
801 
802  for( size_t i=0UL; i<m; ++i ) {
803  for( size_t j=0UL; j<n; ++j )
804  v_[i*NN+j] = array[i*n+j];
805 
806  if( IsNumeric_v<Type> ) {
807  for( size_t j=n; j<NN; ++j )
808  v_[i*NN+j] = Type();
809  }
810  }
811 
812  if( IsNumeric_v<Type> ) {
813  for( size_t i=m; i<M; ++i )
814  for( size_t j=0UL; j<NN; ++j )
815  v_[i*NN+j] = Type();
816  }
817 
818  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
819 }
820 //*************************************************************************************************
821 
822 
823 //*************************************************************************************************
844 template< typename Type // Data type of the matrix
845  , size_t M // Number of rows
846  , size_t N // Number of columns
847  , bool SO > // Storage order
848 template< typename Other // Data type of the initialization array
849  , size_t Rows // Number of rows of the initialization array
850  , size_t Cols > // Number of columns of the initialization array
851 inline HybridMatrix<Type,M,N,SO>::HybridMatrix( const Other (&array)[Rows][Cols] )
852  : v_() // The statically allocated matrix elements
853  , m_( Rows ) // The current number of rows of the matrix
854  , n_( Cols ) // The current number of columns of the matrix
855 {
856  BLAZE_STATIC_ASSERT( Rows <= M );
857  BLAZE_STATIC_ASSERT( Cols <= N );
858  BLAZE_STATIC_ASSERT( IsVectorizable_v<Type> || NN == N );
859 
860  for( size_t i=0UL; i<Rows; ++i ) {
861  for( size_t j=0UL; j<Cols; ++j )
862  v_[i*NN+j] = array[i][j];
863 
864  if( IsNumeric_v<Type> ) {
865  for( size_t j=Cols; j<NN; ++j )
866  v_[i*NN+j] = Type();
867  }
868  }
869 
870  if( IsNumeric_v<Type> ) {
871  for( size_t i=Rows; i<M; ++i )
872  for( size_t j=0UL; j<NN; ++j )
873  v_[i*NN+j] = Type();
874  }
875 
876  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
877 }
878 //*************************************************************************************************
879 
880 
881 //*************************************************************************************************
889 template< typename Type // Data type of the matrix
890  , size_t M // Number of rows
891  , size_t N // Number of columns
892  , bool SO > // Storage order
894  : v_() // The statically allocated matrix elements
895  , m_( m.m_ ) // The current number of rows of the matrix
896  , n_( m.n_ ) // The current number of columns of the matrix
897 {
898  BLAZE_STATIC_ASSERT( IsVectorizable_v<Type> || NN == N );
899 
900  for( size_t i=0UL; i<m_; ++i ) {
901  for( size_t j=0UL; j<n_; ++j )
902  v_[i*NN+j] = m.v_[i*NN+j];
903 
904  if( IsNumeric_v<Type> ) {
905  for( size_t j=n_; j<NN; ++j )
906  v_[i*NN+j] = Type();
907  }
908  }
909 
910  if( IsNumeric_v<Type> ) {
911  for( size_t i=m_; i<M; ++i )
912  for( size_t j=0UL; j<NN; ++j )
913  v_[i*NN+j] = Type();
914  }
915 
916  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
917 }
918 //*************************************************************************************************
919 
920 
921 //*************************************************************************************************
927 template< typename Type // Data type of the matrix
928  , size_t M // Number of rows
929  , size_t N // Number of columns
930  , bool SO > // Storage order
931 template< typename MT // Type of the foreign matrix
932  , bool SO2 > // Storage order of the foreign matrix
934  : v_() // The statically allocated matrix elements
935  , m_( (~m).rows() ) // The current number of rows of the matrix
936  , n_( (~m).columns() ) // The current number of columns of the matrix
937 {
938  using blaze::assign;
939 
940  BLAZE_STATIC_ASSERT( IsVectorizable_v<Type> || NN == N );
941 
942  if( (~m).rows() > M || (~m).columns() > N ) {
943  BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of hybrid matrix" );
944  }
945 
946  for( size_t i=0UL; i<m_; ++i ) {
947  for( size_t j=( IsSparseMatrix_v<MT> ? 0UL : n_ );
948  j<( IsNumeric_v<Type> ? NN : n_ );
949  ++j ) {
950  v_[i*NN+j] = Type();
951  }
952  }
953 
954  if( IsNumeric_v<Type> ) {
955  for( size_t i=m_; i<M; ++i )
956  for( size_t j=0UL; j<NN; ++j )
957  v_[i*NN+j] = Type();
958  }
959 
960  assign( *this, ~m );
961 
962  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
963 }
964 //*************************************************************************************************
965 
966 
967 
968 
969 //=================================================================================================
970 //
971 // DATA ACCESS FUNCTIONS
972 //
973 //=================================================================================================
974 
975 //*************************************************************************************************
985 template< typename Type // Data type of the matrix
986  , size_t M // Number of rows
987  , size_t N // Number of columns
988  , bool SO > // Storage order
990  HybridMatrix<Type,M,N,SO>::operator()( size_t i, size_t j ) noexcept
991 {
992  BLAZE_USER_ASSERT( i<M, "Invalid row access index" );
993  BLAZE_USER_ASSERT( j<N, "Invalid column access index" );
994  return v_[i*NN+j];
995 }
996 //*************************************************************************************************
997 
998 
999 //*************************************************************************************************
1009 template< typename Type // Data type of the matrix
1010  , size_t M // Number of rows
1011  , size_t N // Number of columns
1012  , bool SO > // Storage order
1014  HybridMatrix<Type,M,N,SO>::operator()( size_t i, size_t j ) const noexcept
1015 {
1016  BLAZE_USER_ASSERT( i<M, "Invalid row access index" );
1017  BLAZE_USER_ASSERT( j<N, "Invalid column access index" );
1018  return v_[i*NN+j];
1019 }
1020 //*************************************************************************************************
1021 
1022 
1023 //*************************************************************************************************
1034 template< typename Type // Data type of the matrix
1035  , size_t M // Number of rows
1036  , size_t N // Number of columns
1037  , bool SO > // Storage order
1039  HybridMatrix<Type,M,N,SO>::at( size_t i, size_t j )
1040 {
1041  if( i >= m_ ) {
1042  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
1043  }
1044  if( j >= n_ ) {
1045  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
1046  }
1047  return (*this)(i,j);
1048 }
1049 //*************************************************************************************************
1050 
1051 
1052 //*************************************************************************************************
1063 template< typename Type // Data type of the matrix
1064  , size_t M // Number of rows
1065  , size_t N // Number of columns
1066  , bool SO > // Storage order
1068  HybridMatrix<Type,M,N,SO>::at( size_t i, size_t j ) const
1069 {
1070  if( i >= m_ ) {
1071  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
1072  }
1073  if( j >= n_ ) {
1074  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
1075  }
1076  return (*this)(i,j);
1077 }
1078 //*************************************************************************************************
1079 
1080 
1081 //*************************************************************************************************
1093 template< typename Type // Data type of the matrix
1094  , size_t M // Number of rows
1095  , size_t N // Number of columns
1096  , bool SO > // Storage order
1097 inline typename HybridMatrix<Type,M,N,SO>::Pointer
1099 {
1100  return v_;
1101 }
1102 //*************************************************************************************************
1103 
1104 
1105 //*************************************************************************************************
1117 template< typename Type // Data type of the matrix
1118  , size_t M // Number of rows
1119  , size_t N // Number of columns
1120  , bool SO > // Storage order
1123 {
1124  return v_;
1125 }
1126 //*************************************************************************************************
1127 
1128 
1129 //*************************************************************************************************
1137 template< typename Type // Data type of the matrix
1138  , size_t M // Number of rows
1139  , size_t N // Number of columns
1140  , bool SO > // Storage order
1141 inline typename HybridMatrix<Type,M,N,SO>::Pointer
1142  HybridMatrix<Type,M,N,SO>::data( size_t i ) noexcept
1143 {
1144  BLAZE_USER_ASSERT( i < M, "Invalid dense matrix row access index" );
1145  return v_ + i*NN;
1146 }
1147 //*************************************************************************************************
1148 
1149 
1150 //*************************************************************************************************
1158 template< typename Type // Data type of the matrix
1159  , size_t M // Number of rows
1160  , size_t N // Number of columns
1161  , bool SO > // Storage order
1163  HybridMatrix<Type,M,N,SO>::data( size_t i ) const noexcept
1164 {
1165  BLAZE_USER_ASSERT( i < M, "Invalid dense matrix row access index" );
1166  return v_ + i*NN;
1167 }
1168 //*************************************************************************************************
1169 
1170 
1171 //*************************************************************************************************
1182 template< typename Type // Data type of the matrix
1183  , size_t M // Number of rows
1184  , size_t N // Number of columns
1185  , bool SO > // Storage order
1188 {
1189  BLAZE_USER_ASSERT( i < M, "Invalid dense matrix row access index" );
1190  return Iterator( v_ + i*NN );
1191 }
1192 //*************************************************************************************************
1193 
1194 
1195 //*************************************************************************************************
1206 template< typename Type // Data type of the matrix
1207  , size_t M // Number of rows
1208  , size_t N // Number of columns
1209  , bool SO > // Storage order
1211  HybridMatrix<Type,M,N,SO>::begin( size_t i ) const noexcept
1212 {
1213  BLAZE_USER_ASSERT( i < M, "Invalid dense matrix row access index" );
1214  return ConstIterator( v_ + i*NN );
1215 }
1216 //*************************************************************************************************
1217 
1218 
1219 //*************************************************************************************************
1230 template< typename Type // Data type of the matrix
1231  , size_t M // Number of rows
1232  , size_t N // Number of columns
1233  , bool SO > // Storage order
1235  HybridMatrix<Type,M,N,SO>::cbegin( size_t i ) const noexcept
1236 {
1237  BLAZE_USER_ASSERT( i < M, "Invalid dense matrix row access index" );
1238  return ConstIterator( v_ + i*NN );
1239 }
1240 //*************************************************************************************************
1241 
1242 
1243 //*************************************************************************************************
1254 template< typename Type // Data type of the matrix
1255  , size_t M // Number of rows
1256  , size_t N // Number of columns
1257  , bool SO > // Storage order
1259  HybridMatrix<Type,M,N,SO>::end( size_t i ) noexcept
1260 {
1261  BLAZE_USER_ASSERT( i < M, "Invalid dense matrix row access index" );
1262  return Iterator( v_ + i*NN + N );
1263 }
1264 //*************************************************************************************************
1265 
1266 
1267 //*************************************************************************************************
1278 template< typename Type // Data type of the matrix
1279  , size_t M // Number of rows
1280  , size_t N // Number of columns
1281  , bool SO > // Storage order
1283  HybridMatrix<Type,M,N,SO>::end( size_t i ) const noexcept
1284 {
1285  BLAZE_USER_ASSERT( i < M, "Invalid dense matrix row access index" );
1286  return ConstIterator( v_ + i*NN + N );
1287 }
1288 //*************************************************************************************************
1289 
1290 
1291 //*************************************************************************************************
1302 template< typename Type // Data type of the matrix
1303  , size_t M // Number of rows
1304  , size_t N // Number of columns
1305  , bool SO > // Storage order
1307  HybridMatrix<Type,M,N,SO>::cend( size_t i ) const noexcept
1308 {
1309  BLAZE_USER_ASSERT( i < M, "Invalid dense matrix row access index" );
1310  return ConstIterator( v_ + i*NN + N );
1311 }
1312 //*************************************************************************************************
1313 
1314 
1315 
1316 
1317 //=================================================================================================
1318 //
1319 // ASSIGNMENT OPERATORS
1320 //
1321 //=================================================================================================
1322 
1323 //*************************************************************************************************
1329 template< typename Type // Data type of the matrix
1330  , size_t M // Number of rows
1331  , size_t N // Number of columns
1332  , bool SO > // Storage order
1334 {
1335  BLAZE_INTERNAL_ASSERT( m_ <= M, "Invalid number of rows detected" );
1336  BLAZE_INTERNAL_ASSERT( n_ <= N, "Invalid number of columns detected" );
1337 
1338  for( size_t i=0UL; i<m_; ++i )
1339  for( size_t j=0UL; j<n_; ++j )
1340  v_[i*NN+j] = set;
1341 
1342  return *this;
1343 }
1344 //*************************************************************************************************
1345 
1346 
1347 //*************************************************************************************************
1372 template< typename Type // Data type of the matrix
1373  , size_t M // Number of rows
1374  , size_t N // Number of columns
1375  , bool SO > // Storage order
1378 {
1379  const size_t m( list.size() );
1380  const size_t n( determineColumns( list ) );
1381 
1382  if( m > M ) {
1383  BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of rows for hybrid matrix" );
1384  }
1385 
1386  if( n > N ) {
1387  BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of columns for hybrid matrix" );
1388  }
1389 
1390  resize( m, n, false );
1391 
1392  size_t i( 0UL );
1393 
1394  for( const auto& rowList : list ) {
1395  std::fill( std::copy( rowList.begin(), rowList.end(), v_+i*NN ), v_+(i+1UL)*NN, Type() );
1396  ++i;
1397  }
1398 
1399  return *this;
1400 }
1401 //*************************************************************************************************
1402 
1403 
1404 //*************************************************************************************************
1425 template< typename Type // Data type of the matrix
1426  , size_t M // Number of rows
1427  , size_t N // Number of columns
1428  , bool SO > // Storage order
1429 template< typename Other // Data type of the initialization array
1430  , size_t Rows // Number of rows of the initialization array
1431  , size_t Cols > // Number of columns of the initialization array
1432 inline HybridMatrix<Type,M,N,SO>& HybridMatrix<Type,M,N,SO>::operator=( const Other (&array)[Rows][Cols] )
1433 {
1434  BLAZE_STATIC_ASSERT( Rows <= M );
1435  BLAZE_STATIC_ASSERT( Cols <= N );
1436 
1437  resize( Rows, Cols );
1438 
1439  for( size_t i=0UL; i<Rows; ++i )
1440  for( size_t j=0UL; j<Cols; ++j )
1441  v_[i*NN+j] = array[i][j];
1442 
1443  return *this;
1444 }
1445 //*************************************************************************************************
1446 
1447 
1448 //*************************************************************************************************
1456 template< typename Type // Data type of the matrix
1457  , size_t M // Number of rows
1458  , size_t N // Number of columns
1459  , bool SO > // Storage order
1461 {
1462  using blaze::assign;
1463 
1464  BLAZE_INTERNAL_ASSERT( m_ <= M, "Invalid number of rows detected" );
1465  BLAZE_INTERNAL_ASSERT( n_ <= N, "Invalid number of columns detected" );
1466 
1467  resize( rhs.rows(), rhs.columns() );
1468  assign( *this, ~rhs );
1469 
1470  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
1471 
1472  return *this;
1473 }
1474 //*************************************************************************************************
1475 
1476 
1477 //*************************************************************************************************
1488 template< typename Type // Data type of the matrix
1489  , size_t M // Number of rows
1490  , size_t N // Number of columns
1491  , bool SO > // Storage order
1492 template< typename MT // Type of the right-hand side matrix
1493  , bool SO2 > // Storage order of the right-hand side matrix
1495 {
1496  using blaze::assign;
1497 
1498  using TT = decltype( trans( *this ) );
1499  using CT = decltype( ctrans( *this ) );
1500  using IT = decltype( inv( *this ) );
1501 
1502  if( (~rhs).rows() > M || (~rhs).columns() > N ) {
1503  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to hybrid matrix" );
1504  }
1505 
1506  if( IsSame_v<MT,TT> && (~rhs).isAliased( this ) ) {
1507  transpose();
1508  }
1509  else if( IsSame_v<MT,CT> && (~rhs).isAliased( this ) ) {
1510  ctranspose();
1511  }
1512  else if( !IsSame_v<MT,IT> && (~rhs).canAlias( this ) ) {
1513  HybridMatrix tmp( ~rhs );
1514  resize( tmp.rows(), tmp.columns() );
1515  assign( *this, tmp );
1516  }
1517  else {
1518  resize( (~rhs).rows(), (~rhs).columns() );
1519  if( IsSparseMatrix_v<MT> )
1520  reset();
1521  assign( *this, ~rhs );
1522  }
1523 
1524  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
1525 
1526  return *this;
1527 }
1528 //*************************************************************************************************
1529 
1530 
1531 //*************************************************************************************************
1541 template< typename Type // Data type of the matrix
1542  , size_t M // Number of rows
1543  , size_t N // Number of columns
1544  , bool SO > // Storage order
1545 template< typename MT // Type of the right-hand side matrix
1546  , bool SO2 > // Storage order of the right-hand side matrix
1548 {
1549  using blaze::addAssign;
1550 
1551  if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
1552  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1553  }
1554 
1555  if( (~rhs).canAlias( this ) ) {
1556  const ResultType_t<MT> tmp( ~rhs );
1557  addAssign( *this, tmp );
1558  }
1559  else {
1560  addAssign( *this, ~rhs );
1561  }
1562 
1563  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
1564 
1565  return *this;
1566 }
1567 //*************************************************************************************************
1568 
1569 
1570 //*************************************************************************************************
1580 template< typename Type // Data type of the matrix
1581  , size_t M // Number of rows
1582  , size_t N // Number of columns
1583  , bool SO > // Storage order
1584 template< typename MT // Type of the right-hand side matrix
1585  , bool SO2 > // Storage order of the right-hand side matrix
1587 {
1588  using blaze::subAssign;
1589 
1590  if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
1591  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1592  }
1593 
1594  if( (~rhs).canAlias( this ) ) {
1595  const ResultType_t<MT> tmp( ~rhs );
1596  subAssign( *this, tmp );
1597  }
1598  else {
1599  subAssign( *this, ~rhs );
1600  }
1601 
1602  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
1603 
1604  return *this;
1605 }
1606 //*************************************************************************************************
1607 
1608 
1609 //*************************************************************************************************
1619 template< typename Type // Data type of the matrix
1620  , size_t M // Number of rows
1621  , size_t N // Number of columns
1622  , bool SO > // Storage order
1623 template< typename MT // Type of the right-hand side matrix
1624  , bool SO2 > // Storage order of the right-hand side matrix
1626 {
1627  using blaze::schurAssign;
1628 
1629  if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
1630  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1631  }
1632 
1633  if( (~rhs).canAlias( this ) ) {
1634  const ResultType_t<MT> tmp( ~rhs );
1635  schurAssign( *this, tmp );
1636  }
1637  else {
1638  schurAssign( *this, ~rhs );
1639  }
1640 
1641  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
1642 
1643  return *this;
1644 }
1645 //*************************************************************************************************
1646 
1647 
1648 
1649 
1650 //=================================================================================================
1651 //
1652 // UTILITY FUNCTIONS
1653 //
1654 //=================================================================================================
1655 
1656 //*************************************************************************************************
1661 template< typename Type // Data type of the matrix
1662  , size_t M // Number of rows
1663  , size_t N // Number of columns
1664  , bool SO > // Storage order
1665 inline size_t HybridMatrix<Type,M,N,SO>::rows() const noexcept
1666 {
1667  return m_;
1668 }
1669 //*************************************************************************************************
1670 
1671 
1672 //*************************************************************************************************
1677 template< typename Type // Data type of the matrix
1678  , size_t M // Number of rows
1679  , size_t N // Number of columns
1680  , bool SO > // Storage order
1681 inline size_t HybridMatrix<Type,M,N,SO>::columns() const noexcept
1682 {
1683  return n_;
1684 }
1685 //*************************************************************************************************
1686 
1687 
1688 //*************************************************************************************************
1696 template< typename Type // Data type of the matrix
1697  , size_t M // Number of rows
1698  , size_t N // Number of columns
1699  , bool SO > // Storage order
1700 inline constexpr size_t HybridMatrix<Type,M,N,SO>::spacing() noexcept
1701 {
1702  return NN;
1703 }
1704 //*************************************************************************************************
1705 
1706 
1707 //*************************************************************************************************
1712 template< typename Type // Data type of the matrix
1713  , size_t M // Number of rows
1714  , size_t N // Number of columns
1715  , bool SO > // Storage order
1716 inline constexpr size_t HybridMatrix<Type,M,N,SO>::capacity() noexcept
1717 {
1718  return M*NN;
1719 }
1720 //*************************************************************************************************
1721 
1722 
1723 //*************************************************************************************************
1734 template< typename Type // Data type of the matrix
1735  , size_t M // Number of rows
1736  , size_t N // Number of columns
1737  , bool SO > // Storage order
1738 inline size_t HybridMatrix<Type,M,N,SO>::capacity( size_t i ) const noexcept
1739 {
1740  MAYBE_UNUSED( i );
1741 
1742  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
1743 
1744  return NN;
1745 }
1746 //*************************************************************************************************
1747 
1748 
1749 //*************************************************************************************************
1754 template< typename Type // Data type of the matrix
1755  , size_t M // Number of rows
1756  , size_t N // Number of columns
1757  , bool SO > // Storage order
1759 {
1760  size_t nonzeros( 0UL );
1761 
1762  for( size_t i=0UL; i<m_; ++i )
1763  for( size_t j=0UL; j<n_; ++j )
1764  if( !isDefault( v_[i*NN+j] ) )
1765  ++nonzeros;
1766 
1767  return nonzeros;
1768 }
1769 //*************************************************************************************************
1770 
1771 
1772 //*************************************************************************************************
1783 template< typename Type // Data type of the matrix
1784  , size_t M // Number of rows
1785  , size_t N // Number of columns
1786  , bool SO > // Storage order
1787 inline size_t HybridMatrix<Type,M,N,SO>::nonZeros( size_t i ) const
1788 {
1789  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
1790 
1791  const size_t jend( i*NN + n_ );
1792  size_t nonzeros( 0UL );
1793 
1794  for( size_t j=i*NN; j<jend; ++j )
1795  if( !isDefault( v_[j] ) )
1796  ++nonzeros;
1797 
1798  return nonzeros;
1799 }
1800 //*************************************************************************************************
1801 
1802 
1803 //*************************************************************************************************
1808 template< typename Type // Data type of the matrix
1809  , size_t M // Number of rows
1810  , size_t N // Number of columns
1811  , bool SO > // Storage order
1813 {
1814  using blaze::clear;
1815 
1816  for( size_t i=0UL; i<m_; ++i )
1817  for( size_t j=0UL; j<n_; ++j )
1818  clear( v_[i*NN+j] );
1819 }
1820 //*************************************************************************************************
1821 
1822 
1823 //*************************************************************************************************
1834 template< typename Type // Data type of the matrix
1835  , size_t M // Number of rows
1836  , size_t N // Number of columns
1837  , bool SO > // Storage order
1838 inline void HybridMatrix<Type,M,N,SO>::reset( size_t i )
1839 {
1840  using blaze::clear;
1841 
1842  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
1843  for( size_t j=0UL; j<n_; ++j )
1844  clear( v_[i*NN+j] );
1845 }
1846 //*************************************************************************************************
1847 
1848 
1849 //*************************************************************************************************
1856 template< typename Type // Data type of the matrix
1857  , size_t M // Number of rows
1858  , size_t N // Number of columns
1859  , bool SO > // Storage order
1861 {
1862  resize( 0UL, 0UL );
1863 }
1864 //*************************************************************************************************
1865 
1866 
1867 //*************************************************************************************************
1903 template< typename Type // Data type of the matrix
1904  , size_t M // Number of rows
1905  , size_t N // Number of columns
1906  , bool SO > // Storage order
1907 void HybridMatrix<Type,M,N,SO>::resize( size_t m, size_t n, bool preserve )
1908 {
1909  MAYBE_UNUSED( preserve );
1910 
1911  if( m > M ) {
1912  BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of rows for hybrid matrix" );
1913  }
1914 
1915  if( n > N ) {
1916  BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of columns for hybrid matrix" );
1917  }
1918 
1919  if( IsVectorizable_v<Type> && n < n_ ) {
1920  for( size_t i=0UL; i<m; ++i )
1921  for( size_t j=n; j<n_; ++j )
1922  v_[i*NN+j] = Type();
1923  }
1924 
1925  if( IsVectorizable_v<Type> && m < m_ ) {
1926  for( size_t i=m; i<m_; ++i )
1927  for( size_t j=0UL; j<n_; ++j )
1928  v_[i*NN+j] = Type();
1929  }
1930 
1931  m_ = m;
1932  n_ = n;
1933 }
1934 //*************************************************************************************************
1935 
1936 
1937 //*************************************************************************************************
1952 template< typename Type // Data type of the matrix
1953  , size_t M // Number of rows
1954  , size_t N // Number of columns
1955  , bool SO > // Storage order
1956 inline void HybridMatrix<Type,M,N,SO>::extend( size_t m, size_t n, bool preserve )
1957 {
1958  MAYBE_UNUSED( preserve );
1959  resize( m_+m, n_+n );
1960 }
1961 //*************************************************************************************************
1962 
1963 
1964 //*************************************************************************************************
1970 template< typename Type // Data type of the matrix
1971  , size_t M // Number of rows
1972  , size_t N // Number of columns
1973  , bool SO > // Storage order
1975 {
1976  using std::swap;
1977 
1978  const size_t maxrows( max( m_, m.m_ ) );
1979  const size_t maxcols( max( n_, m.n_ ) );
1980 
1981  for( size_t i=0UL; i<maxrows; ++i ) {
1982  for( size_t j=0UL; j<maxcols; ++j ) {
1983  swap( v_[i*NN+j], m(i,j) );
1984  }
1985  }
1986 
1987  swap( m_, m.m_ );
1988  swap( n_, m.n_ );
1989 }
1990 //*************************************************************************************************
1991 
1992 
1993 
1994 
1995 //=================================================================================================
1996 //
1997 // NUMERIC FUNCTIONS
1998 //
1999 //=================================================================================================
2000 
2001 //*************************************************************************************************
2012 template< typename Type // Data type of the matrix
2013  , size_t M // Number of rows
2014  , size_t N // Number of columns
2015  , bool SO > // Storage order
2017 {
2018  using std::swap;
2019 
2020  if( m_ > N || n_ > M ) {
2021  BLAZE_THROW_LOGIC_ERROR( "Impossible transpose operation" );
2022  }
2023 
2024  const size_t maxsize( max( m_, n_ ) );
2025  for( size_t i=1UL; i<maxsize; ++i ) {
2026  for( size_t j=0UL; j<i; ++j ) {
2027  swap( v_[i*NN+j], v_[j*NN+i] );
2028  }
2029  }
2030 
2031  if( IsVectorizable_v<Type> && m_ < n_ ) {
2032  for( size_t i=0UL; i<m_; ++i ) {
2033  for( size_t j=m_; j<n_; ++j ) {
2034  v_[i*NN+j] = Type();
2035  }
2036  }
2037  }
2038 
2039  if( IsVectorizable_v<Type> && m_ > n_ ) {
2040  for( size_t i=n_; i<m_; ++i ) {
2041  for( size_t j=0UL; j<n_; ++j ) {
2042  v_[i*NN+j] = Type();
2043  }
2044  }
2045  }
2046 
2047  swap( m_, n_ );
2048 
2049  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
2050 
2051  return *this;
2052 }
2053 //*************************************************************************************************
2054 
2055 
2056 //*************************************************************************************************
2067 template< typename Type // Data type of the matrix
2068  , size_t M // Number of rows
2069  , size_t N // Number of columns
2070  , bool SO > // Storage order
2072 {
2073  using std::swap;
2074 
2075  if( m_ > N || n_ > M ) {
2076  BLAZE_THROW_LOGIC_ERROR( "Impossible transpose operation" );
2077  }
2078 
2079  const size_t maxsize( max( m_, n_ ) );
2080  for( size_t i=0UL; i<maxsize; ++i ) {
2081  for( size_t j=0UL; j<i; ++j ) {
2082  cswap( v_[i*NN+j], v_[j*NN+i] );
2083  }
2084  conjugate( v_[i*NN+i] );
2085  }
2086 
2087  if( IsVectorizable_v<Type> && m_ < n_ ) {
2088  for( size_t i=0UL; i<m_; ++i ) {
2089  for( size_t j=m_; j<n_; ++j ) {
2090  v_[i*NN+j] = Type();
2091  }
2092  }
2093  }
2094 
2095  if( IsVectorizable_v<Type> && m_ > n_ ) {
2096  for( size_t i=n_; i<m_; ++i ) {
2097  for( size_t j=0UL; j<n_; ++j ) {
2098  v_[i*NN+j] = Type();
2099  }
2100  }
2101  }
2102 
2103  swap( m_, n_ );
2104 
2105  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
2106 
2107  return *this;
2108 }
2109 //*************************************************************************************************
2110 
2111 
2112 //*************************************************************************************************
2129 template< typename Type // Data type of the matrix
2130  , size_t M // Number of rows
2131  , size_t N // Number of columns
2132  , bool SO > // Storage order
2133 template< typename Other > // Data type of the scalar value
2135 {
2136  for( size_t i=0UL; i<m_; ++i )
2137  for( size_t j=0UL; j<n_; ++j )
2138  v_[i*NN+j] *= scalar;
2139 
2140  return *this;
2141 }
2142 //*************************************************************************************************
2143 
2144 
2145 
2146 
2147 //=================================================================================================
2148 //
2149 // MEMORY FUNCTIONS
2150 //
2151 //=================================================================================================
2152 
2153 //*************************************************************************************************
2163 template< typename Type // Data type of the matrix
2164  , size_t M // Number of rows
2165  , size_t N // Number of columns
2166  , bool SO > // Storage order
2167 inline void* HybridMatrix<Type,M,N,SO>::operator new( std::size_t size )
2168 {
2169  MAYBE_UNUSED( size );
2170 
2171  BLAZE_INTERNAL_ASSERT( size == sizeof( HybridMatrix ), "Invalid number of bytes detected" );
2172 
2173  return allocate<HybridMatrix>( 1UL );
2174 }
2175 //*************************************************************************************************
2176 
2177 
2178 //*************************************************************************************************
2188 template< typename Type // Data type of the matrix
2189  , size_t M // Number of rows
2190  , size_t N // Number of columns
2191  , bool SO > // Storage order
2192 inline void* HybridMatrix<Type,M,N,SO>::operator new[]( std::size_t size )
2193 {
2194  BLAZE_INTERNAL_ASSERT( size >= sizeof( HybridMatrix ) , "Invalid number of bytes detected" );
2195  BLAZE_INTERNAL_ASSERT( size % sizeof( HybridMatrix ) == 0UL, "Invalid number of bytes detected" );
2196 
2197  return allocate<HybridMatrix>( size/sizeof(HybridMatrix) );
2198 }
2199 //*************************************************************************************************
2200 
2201 
2202 //*************************************************************************************************
2212 template< typename Type // Data type of the matrix
2213  , size_t M // Number of rows
2214  , size_t N // Number of columns
2215  , bool SO > // Storage order
2216 inline void* HybridMatrix<Type,M,N,SO>::operator new( std::size_t size, const std::nothrow_t& )
2217 {
2218  MAYBE_UNUSED( size );
2219 
2220  BLAZE_INTERNAL_ASSERT( size == sizeof( HybridMatrix ), "Invalid number of bytes detected" );
2221 
2222  return allocate<HybridMatrix>( 1UL );
2223 }
2224 //*************************************************************************************************
2225 
2226 
2227 //*************************************************************************************************
2237 template< typename Type // Data type of the matrix
2238  , size_t M // Number of rows
2239  , size_t N // Number of columns
2240  , bool SO > // Storage order
2241 inline void* HybridMatrix<Type,M,N,SO>::operator new[]( std::size_t size, const std::nothrow_t& )
2242 {
2243  BLAZE_INTERNAL_ASSERT( size >= sizeof( HybridMatrix ) , "Invalid number of bytes detected" );
2244  BLAZE_INTERNAL_ASSERT( size % sizeof( HybridMatrix ) == 0UL, "Invalid number of bytes detected" );
2245 
2246  return allocate<HybridMatrix>( size/sizeof(HybridMatrix) );
2247 }
2248 //*************************************************************************************************
2249 
2250 
2251 //*************************************************************************************************
2257 template< typename Type // Data type of the matrix
2258  , size_t M // Number of rows
2259  , size_t N // Number of columns
2260  , bool SO > // Storage order
2261 inline void HybridMatrix<Type,M,N,SO>::operator delete( void* ptr )
2262 {
2263  deallocate( static_cast<HybridMatrix*>( ptr ) );
2264 }
2265 //*************************************************************************************************
2266 
2267 
2268 //*************************************************************************************************
2274 template< typename Type // Data type of the matrix
2275  , size_t M // Number of rows
2276  , size_t N // Number of columns
2277  , bool SO > // Storage order
2278 inline void HybridMatrix<Type,M,N,SO>::operator delete[]( void* ptr )
2279 {
2280  deallocate( static_cast<HybridMatrix*>( ptr ) );
2281 }
2282 //*************************************************************************************************
2283 
2284 
2285 //*************************************************************************************************
2291 template< typename Type // Data type of the matrix
2292  , size_t M // Number of rows
2293  , size_t N // Number of columns
2294  , bool SO > // Storage order
2295 inline void HybridMatrix<Type,M,N,SO>::operator delete( void* ptr, const std::nothrow_t& )
2296 {
2297  deallocate( static_cast<HybridMatrix*>( ptr ) );
2298 }
2299 //*************************************************************************************************
2300 
2301 
2302 //*************************************************************************************************
2308 template< typename Type // Data type of the matrix
2309  , size_t M // Number of rows
2310  , size_t N // Number of columns
2311  , bool SO > // Storage order
2312 inline void HybridMatrix<Type,M,N,SO>::operator delete[]( void* ptr, const std::nothrow_t& )
2313 {
2314  deallocate( static_cast<HybridMatrix*>( ptr ) );
2315 }
2316 //*************************************************************************************************
2317 
2318 
2319 
2320 
2321 //=================================================================================================
2322 //
2323 // DEBUGGING FUNCTIONS
2324 //
2325 //=================================================================================================
2326 
2327 //*************************************************************************************************
2336 template< typename Type // Data type of the matrix
2337  , size_t M // Number of rows
2338  , size_t N // Number of columns
2339  , bool SO > // Storage order
2340 inline bool HybridMatrix<Type,M,N,SO>::isIntact() const noexcept
2341 {
2342  if( m_ > M || n_ > N )
2343  return false;
2344 
2345  if( IsVectorizable_v<Type> )
2346  {
2347  for( size_t i=0UL; i<m_; ++i ) {
2348  for( size_t j=n_; j<NN; ++j ) {
2349  if( v_[i*NN+j] != Type() )
2350  return false;
2351  }
2352  }
2353 
2354  for( size_t i=m_; i<M; ++i ) {
2355  for( size_t j=0UL; j<NN; ++j ) {
2356  if( v_[i*NN+j] != Type() )
2357  return false;
2358  }
2359  }
2360  }
2361 
2362  return true;
2363 }
2364 //*************************************************************************************************
2365 
2366 
2367 
2368 
2369 //=================================================================================================
2370 //
2371 // EXPRESSION TEMPLATE EVALUATION FUNCTIONS
2372 //
2373 //=================================================================================================
2374 
2375 //*************************************************************************************************
2385 template< typename Type // Data type of the matrix
2386  , size_t M // Number of rows
2387  , size_t N // Number of columns
2388  , bool SO > // Storage order
2389 template< typename Other > // Data type of the foreign expression
2390 inline bool HybridMatrix<Type,M,N,SO>::canAlias( const Other* alias ) const noexcept
2391 {
2392  return static_cast<const void*>( this ) == static_cast<const void*>( alias );
2393 }
2394 //*************************************************************************************************
2395 
2396 
2397 //*************************************************************************************************
2407 template< typename Type // Data type of the matrix
2408  , size_t M // Number of rows
2409  , size_t N // Number of columns
2410  , bool SO > // Storage order
2411 template< typename Other > // Data type of the foreign expression
2412 inline bool HybridMatrix<Type,M,N,SO>::isAliased( const Other* alias ) const noexcept
2413 {
2414  return static_cast<const void*>( this ) == static_cast<const void*>( alias );
2415 }
2416 //*************************************************************************************************
2417 
2418 
2419 //*************************************************************************************************
2428 template< typename Type // Data type of the matrix
2429  , size_t M // Number of rows
2430  , size_t N // Number of columns
2431  , bool SO > // Storage order
2432 inline constexpr bool HybridMatrix<Type,M,N,SO>::isAligned() noexcept
2433 {
2434  return align;
2435 }
2436 //*************************************************************************************************
2437 
2438 
2439 //*************************************************************************************************
2454 template< typename Type // Data type of the matrix
2455  , size_t M // Number of rows
2456  , size_t N // Number of columns
2457  , bool SO > // Storage order
2459  HybridMatrix<Type,M,N,SO>::load( size_t i, size_t j ) const noexcept
2460 {
2461  if( align )
2462  return loada( i, j );
2463  else
2464  return loadu( i, j );
2465 }
2466 //*************************************************************************************************
2467 
2468 
2469 //*************************************************************************************************
2484 template< typename Type // Data type of the matrix
2485  , size_t M // Number of rows
2486  , size_t N // Number of columns
2487  , bool SO > // Storage order
2489  HybridMatrix<Type,M,N,SO>::loada( size_t i, size_t j ) const noexcept
2490 {
2491  using blaze::loada;
2492 
2494 
2495  BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
2496  BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
2497  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= NN, "Invalid column access index" );
2498  BLAZE_INTERNAL_ASSERT( !usePadding || j % SIMDSIZE == 0UL, "Invalid column access index" );
2499  BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[i*NN+j] ), "Invalid alignment detected" );
2500 
2501  return loada( &v_[i*NN+j] );
2502 }
2503 //*************************************************************************************************
2504 
2505 
2506 //*************************************************************************************************
2521 template< typename Type // Data type of the matrix
2522  , size_t M // Number of rows
2523  , size_t N // Number of columns
2524  , bool SO > // Storage order
2526  HybridMatrix<Type,M,N,SO>::loadu( size_t i, size_t j ) const noexcept
2527 {
2528  using blaze::loadu;
2529 
2531 
2532  BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
2533  BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
2534  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= NN, "Invalid column access index" );
2535 
2536  return loadu( &v_[i*NN+j] );
2537 }
2538 //*************************************************************************************************
2539 
2540 
2541 //*************************************************************************************************
2557 template< typename Type // Data type of the matrix
2558  , size_t M // Number of rows
2559  , size_t N // Number of columns
2560  , bool SO > // Storage order
2562  HybridMatrix<Type,M,N,SO>::store( size_t i, size_t j, const SIMDType& value ) noexcept
2563 {
2564  if( align )
2565  storea( i, j, value );
2566  else
2567  storeu( i, j, value );
2568 }
2569 //*************************************************************************************************
2570 
2571 
2572 //*************************************************************************************************
2588 template< typename Type // Data type of the matrix
2589  , size_t M // Number of rows
2590  , size_t N // Number of columns
2591  , bool SO > // Storage order
2593  HybridMatrix<Type,M,N,SO>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
2594 {
2595  using blaze::storea;
2596 
2598 
2599  BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
2600  BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
2601  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= NN, "Invalid column access index" );
2602  BLAZE_INTERNAL_ASSERT( !usePadding || j % SIMDSIZE == 0UL, "Invalid column access index" );
2603  BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[i*NN+j] ), "Invalid alignment detected" );
2604 
2605  storea( &v_[i*NN+j], value );
2606 }
2607 //*************************************************************************************************
2608 
2609 
2610 //*************************************************************************************************
2626 template< typename Type // Data type of the matrix
2627  , size_t M // Number of rows
2628  , size_t N // Number of columns
2629  , bool SO > // Storage order
2631  HybridMatrix<Type,M,N,SO>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
2632 {
2633  using blaze::storeu;
2634 
2636 
2637  BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
2638  BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
2639  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= NN, "Invalid column access index" );
2640 
2641  storeu( &v_[i*NN+j], value );
2642 }
2643 //*************************************************************************************************
2644 
2645 
2646 //*************************************************************************************************
2663 template< typename Type // Data type of the matrix
2664  , size_t M // Number of rows
2665  , size_t N // Number of columns
2666  , bool SO > // Storage order
2668  HybridMatrix<Type,M,N,SO>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
2669 {
2670  using blaze::stream;
2671 
2673 
2674  BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
2675  BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
2676  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= NN, "Invalid column access index" );
2677  BLAZE_INTERNAL_ASSERT( !usePadding || j % SIMDSIZE == 0UL, "Invalid column access index" );
2678  BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[i*NN+j] ), "Invalid alignment detected" );
2679 
2680  stream( &v_[i*NN+j], value );
2681 }
2682 //*************************************************************************************************
2683 
2684 
2685 //*************************************************************************************************
2696 template< typename Type // Data type of the matrix
2697  , size_t M // Number of rows
2698  , size_t N // Number of columns
2699  , bool SO > // Storage order
2700 template< typename MT // Type of the right-hand side dense matrix
2701  , bool SO2 > // Storage order of the right-hand side dense matrix
2704 {
2705  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
2706 
2707  for( size_t i=0UL; i<m_; ++i ) {
2708  for( size_t j=0UL; j<n_; ++j ) {
2709  v_[i*NN+j] = (~rhs)(i,j);
2710  }
2711  }
2712 }
2713 //*************************************************************************************************
2714 
2715 
2716 //*************************************************************************************************
2727 template< typename Type // Data type of the matrix
2728  , size_t M // Number of rows
2729  , size_t N // Number of columns
2730  , bool SO > // Storage order
2731 template< typename MT // Type of the right-hand side dense matrix
2732  , bool SO2 > // Storage order of the right-hand side dense matrix
2735 {
2737 
2738  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
2739 
2740  constexpr bool remainder( !usePadding || !IsPadded_v<MT> );
2741 
2742  const size_t jpos( ( remainder )?( n_ & size_t(-SIMDSIZE) ):( n_ ) );
2743  BLAZE_INTERNAL_ASSERT( !remainder || ( n_ - ( n_ % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
2744 
2745  for( size_t i=0UL; i<m_; ++i )
2746  {
2747  size_t j( 0UL );
2748 
2749  for( ; j<jpos; j+=SIMDSIZE ) {
2750  store( i, j, (~rhs).load(i,j) );
2751  }
2752  for( ; remainder && j<n_; ++j ) {
2753  v_[i*NN+j] = (~rhs)(i,j);
2754  }
2755  }
2756 }
2757 //*************************************************************************************************
2758 
2759 
2760 //*************************************************************************************************
2771 template< typename Type // Data type of the matrix
2772  , size_t M // Number of rows
2773  , size_t N // Number of columns
2774  , bool SO > // Storage order
2775 template< typename MT > // Type of the right-hand side sparse matrix
2777 {
2778  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
2779 
2780  for( size_t i=0UL; i<m_; ++i )
2781  for( auto element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
2782  v_[i*NN+element->index()] = element->value();
2783 }
2784 //*************************************************************************************************
2785 
2786 
2787 //*************************************************************************************************
2798 template< typename Type // Data type of the matrix
2799  , size_t M // Number of rows
2800  , size_t N // Number of columns
2801  , bool SO > // Storage order
2802 template< typename MT > // Type of the right-hand side sparse matrix
2804 {
2806 
2807  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
2808 
2809  for( size_t j=0UL; j<n_; ++j )
2810  for( auto element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
2811  v_[element->index()*NN+j] = element->value();
2812 }
2813 //*************************************************************************************************
2814 
2815 
2816 //*************************************************************************************************
2827 template< typename Type // Data type of the matrix
2828  , size_t M // Number of rows
2829  , size_t N // Number of columns
2830  , bool SO > // Storage order
2831 template< typename MT // Type of the right-hand side dense matrix
2832  , bool SO2 > // Storage order of the right-hand side dense matrix
2835 {
2836  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
2837 
2838  for( size_t i=0UL; i<m_; ++i )
2839  {
2840  if( IsDiagonal_v<MT> )
2841  {
2842  v_[i*NN+i] += (~rhs)(i,i);
2843  }
2844  else
2845  {
2846  const size_t jbegin( ( IsUpper_v<MT> )
2847  ?( IsStrictlyUpper_v<MT> ? i+1UL : i )
2848  :( 0UL ) );
2849  const size_t jend ( ( IsLower_v<MT> )
2850  ?( IsStrictlyLower_v<MT> ? i : i+1UL )
2851  :( n_ ) );
2852  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
2853 
2854  for( size_t j=jbegin; j<jend; ++j ) {
2855  v_[i*NN+j] += (~rhs)(i,j);
2856  }
2857  }
2858  }
2859 }
2860 //*************************************************************************************************
2861 
2862 
2863 //*************************************************************************************************
2874 template< typename Type // Data type of the matrix
2875  , size_t M // Number of rows
2876  , size_t N // Number of columns
2877  , bool SO > // Storage order
2878 template< typename MT // Type of the right-hand side dense matrix
2879  , bool SO2 > // Storage order of the right-hand side dense matrix
2882 {
2885 
2886  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
2887 
2888  constexpr bool remainder( !usePadding || !IsPadded_v<MT> );
2889 
2890  for( size_t i=0UL; i<m_; ++i )
2891  {
2892  const size_t jbegin( ( IsUpper_v<MT> )
2893  ?( ( IsStrictlyUpper_v<MT> ? i+1UL : i ) & size_t(-SIMDSIZE) )
2894  :( 0UL ) );
2895  const size_t jend ( ( IsLower_v<MT> )
2896  ?( IsStrictlyLower_v<MT> ? i : i+1UL )
2897  :( n_ ) );
2898  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
2899 
2900  const size_t jpos( ( remainder )?( jend & size_t(-SIMDSIZE) ):( jend ) );
2901  BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
2902 
2903  size_t j( jbegin );
2904 
2905  for( ; j<jpos; j+=SIMDSIZE ) {
2906  store( i, j, load(i,j) + (~rhs).load(i,j) );
2907  }
2908  for( ; remainder && j<jend; ++j ) {
2909  v_[i*NN+j] += (~rhs)(i,j);
2910  }
2911  }
2912 }
2913 //*************************************************************************************************
2914 
2915 
2916 //*************************************************************************************************
2927 template< typename Type // Data type of the matrix
2928  , size_t M // Number of rows
2929  , size_t N // Number of columns
2930  , bool SO > // Storage order
2931 template< typename MT > // Type of the right-hand side sparse matrix
2933 {
2934  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
2935 
2936  for( size_t i=0UL; i<m_; ++i )
2937  for( auto element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
2938  v_[i*NN+element->index()] += element->value();
2939 }
2940 //*************************************************************************************************
2941 
2942 
2943 //*************************************************************************************************
2954 template< typename Type // Data type of the matrix
2955  , size_t M // Number of rows
2956  , size_t N // Number of columns
2957  , bool SO > // Storage order
2958 template< typename MT > // Type of the right-hand side sparse matrix
2960 {
2962 
2963  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
2964 
2965  for( size_t j=0UL; j<n_; ++j )
2966  for( auto element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
2967  v_[element->index()*NN+j] += element->value();
2968 }
2969 //*************************************************************************************************
2970 
2971 
2972 //*************************************************************************************************
2983 template< typename Type // Data type of the matrix
2984  , size_t M // Number of rows
2985  , size_t N // Number of columns
2986  , bool SO > // Storage order
2987 template< typename MT // Type of the right-hand side dense matrix
2988  , bool SO2 > // Storage order of the right-hand side dense matrix
2991 {
2992  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
2993 
2994  for( size_t i=0UL; i<m_; ++i )
2995  {
2996  if( IsDiagonal_v<MT> )
2997  {
2998  v_[i*NN+i] -= (~rhs)(i,i);
2999  }
3000  else
3001  {
3002  const size_t jbegin( ( IsUpper_v<MT> )
3003  ?( IsStrictlyUpper_v<MT> ? i+1UL : i )
3004  :( 0UL ) );
3005  const size_t jend ( ( IsLower_v<MT> )
3006  ?( IsStrictlyLower_v<MT> ? i : i+1UL )
3007  :( n_ ) );
3008  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
3009 
3010  for( size_t j=jbegin; j<jend; ++j ) {
3011  v_[i*NN+j] -= (~rhs)(i,j);
3012  }
3013  }
3014  }
3015 }
3016 //*************************************************************************************************
3017 
3018 
3019 //*************************************************************************************************
3030 template< typename Type // Data type of the matrix
3031  , size_t M // Number of rows
3032  , size_t N // Number of columns
3033  , bool SO > // Storage order
3034 template< typename MT // Type of the right-hand side dense matrix
3035  , bool SO2 > // Storage order of the right-hand side dense matrix
3038 {
3041 
3042  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
3043 
3044  constexpr bool remainder( !usePadding || !IsPadded_v<MT> );
3045 
3046  for( size_t i=0UL; i<m_; ++i )
3047  {
3048  const size_t jbegin( ( IsUpper_v<MT> )
3049  ?( ( IsStrictlyUpper_v<MT> ? i+1UL : i ) & size_t(-SIMDSIZE) )
3050  :( 0UL ) );
3051  const size_t jend ( ( IsLower_v<MT> )
3052  ?( IsStrictlyLower_v<MT> ? i : i+1UL )
3053  :( n_ ) );
3054  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
3055 
3056  const size_t jpos( ( remainder )?( jend & size_t(-SIMDSIZE) ):( jend ) );
3057  BLAZE_INTERNAL_ASSERT( !remainder || ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
3058 
3059  size_t j( jbegin );
3060 
3061  for( ; j<jpos; j+=SIMDSIZE ) {
3062  store( i, j, load(i,j) - (~rhs).load(i,j) );
3063  }
3064  for( ; remainder && j<jend; ++j ) {
3065  v_[i*NN+j] -= (~rhs)(i,j);
3066  }
3067  }
3068 }
3069 //*************************************************************************************************
3070 
3071 
3072 //*************************************************************************************************
3083 template< typename Type // Data type of the matrix
3084  , size_t M // Number of rows
3085  , size_t N // Number of columns
3086  , bool SO > // Storage order
3087 template< typename MT > // Type of the right-hand side sparse matrix
3089 {
3090  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
3091 
3092  for( size_t i=0UL; i<m_; ++i )
3093  for( auto element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
3094  v_[i*NN+element->index()] -= element->value();
3095 }
3096 //*************************************************************************************************
3097 
3098 
3099 //*************************************************************************************************
3110 template< typename Type // Data type of the matrix
3111  , size_t M // Number of rows
3112  , size_t N // Number of columns
3113  , bool SO > // Storage order
3114 template< typename MT > // Type of the right-hand side sparse matrix
3116 {
3118 
3119  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
3120 
3121  for( size_t j=0UL; j<n_; ++j )
3122  for( auto element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
3123  v_[element->index()*NN+j] -= element->value();
3124 }
3125 //*************************************************************************************************
3126 
3127 
3128 //*************************************************************************************************
3139 template< typename Type // Data type of the matrix
3140  , size_t M // Number of rows
3141  , size_t N // Number of columns
3142  , bool SO > // Storage order
3143 template< typename MT // Type of the right-hand side dense matrix
3144  , bool SO2 > // Storage order of the right-hand side dense matrix
3147 {
3148  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
3149 
3150  for( size_t i=0UL; i<m_; ++i ) {
3151  for( size_t j=0UL; j<n_; ++j ) {
3152  v_[i*NN+j] *= (~rhs)(i,j);
3153  }
3154  }
3155 }
3156 //*************************************************************************************************
3157 
3158 
3159 //*************************************************************************************************
3170 template< typename Type // Data type of the matrix
3171  , size_t M // Number of rows
3172  , size_t N // Number of columns
3173  , bool SO > // Storage order
3174 template< typename MT // Type of the right-hand side dense matrix
3175  , bool SO2 > // Storage order of the right-hand side dense matrix
3178 {
3180 
3181  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
3182 
3183  constexpr bool remainder( !usePadding || !IsPadded_v<MT> );
3184 
3185  for( size_t i=0UL; i<m_; ++i )
3186  {
3187  const size_t jpos( ( remainder )?( n_ & size_t(-SIMDSIZE) ):( n_ ) );
3188  BLAZE_INTERNAL_ASSERT( !remainder || ( n_ - ( n_ % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
3189 
3190  size_t j( 0UL );
3191 
3192  for( ; j<jpos; j+=SIMDSIZE ) {
3193  store( i, j, load(i,j) * (~rhs).load(i,j) );
3194  }
3195  for( ; remainder && j<n_; ++j ) {
3196  v_[i*NN+j] *= (~rhs)(i,j);
3197  }
3198  }
3199 }
3200 //*************************************************************************************************
3201 
3202 
3203 //*************************************************************************************************
3214 template< typename Type // Data type of the matrix
3215  , size_t M // Number of rows
3216  , size_t N // Number of columns
3217  , bool SO > // Storage order
3218 template< typename MT > // Type of the right-hand side sparse matrix
3220 {
3221  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
3222 
3223  const HybridMatrix tmp( serial( *this ) );
3224 
3225  reset();
3226 
3227  for( size_t i=0UL; i<m_; ++i )
3228  for( auto element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
3229  v_[i*NN+element->index()] = tmp.v_[i*NN+element->index()] * element->value();
3230 }
3231 //*************************************************************************************************
3232 
3233 
3234 //*************************************************************************************************
3245 template< typename Type // Data type of the matrix
3246  , size_t M // Number of rows
3247  , size_t N // Number of columns
3248  , bool SO > // Storage order
3249 template< typename MT > // Type of the right-hand side sparse matrix
3251 {
3253 
3254  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
3255 
3256  const HybridMatrix tmp( serial( *this ) );
3257 
3258  reset();
3259 
3260  for( size_t j=0UL; j<n_; ++j )
3261  for( auto element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
3262  v_[element->index()*NN+j] = tmp.v_[element->index()*NN+j] * element->value();
3263 }
3264 //*************************************************************************************************
3265 
3266 
3267 
3268 
3269 
3270 
3271 
3272 
3273 //=================================================================================================
3274 //
3275 // CLASS TEMPLATE SPECIALIZATION FOR COLUMN-MAJOR MATRICES
3276 //
3277 //=================================================================================================
3278 
3279 //*************************************************************************************************
3287 template< typename Type // Data type of the matrix
3288  , size_t M // Number of rows
3289  , size_t N > // Number of columns
3290 class HybridMatrix<Type,M,N,true>
3291  : public DenseMatrix< HybridMatrix<Type,M,N,true>, true >
3292 {
3293  private:
3294  //**********************************************************************************************
3296  static constexpr size_t SIMDSIZE = SIMDTrait<Type>::size;
3297 
3299  static constexpr size_t MM = ( usePadding ? nextMultiple( M, SIMDSIZE ) : M );
3300 
3302  static constexpr bool align = ( usePadding || MM % SIMDSIZE == 0UL );
3303  //**********************************************************************************************
3304 
3305  public:
3306  //**Type definitions****************************************************************************
3309  using ResultType = This;
3312  using ElementType = Type;
3314  using ReturnType = const Type&;
3315  using CompositeType = const This&;
3316 
3317  using Reference = Type&;
3318  using ConstReference = const Type&;
3319  using Pointer = Type*;
3320  using ConstPointer = const Type*;
3321 
3324  //**********************************************************************************************
3325 
3326  //**Rebind struct definition********************************************************************
3329  template< typename NewType > // Data type of the other matrix
3330  struct Rebind {
3332  };
3333  //**********************************************************************************************
3334 
3335  //**Resize struct definition********************************************************************
3338  template< size_t NewM // Number of rows of the other matrix
3339  , size_t NewN > // Number of columns of the other matrix
3340  struct Resize {
3341  using Other = HybridMatrix<Type,NewM,NewN,true>;
3342  };
3343  //**********************************************************************************************
3344 
3345  //**Compilation flags***************************************************************************
3347 
3351  static constexpr bool simdEnabled = IsVectorizable_v<Type>;
3352 
3354 
3357  static constexpr bool smpAssignable = false;
3358  //**********************************************************************************************
3359 
3360  //**Constructors********************************************************************************
3363  explicit inline HybridMatrix();
3364  explicit inline HybridMatrix( size_t m, size_t n );
3365  explicit inline HybridMatrix( size_t m, size_t n, const Type& init );
3366  inline HybridMatrix( initializer_list< initializer_list<Type> > list );
3367 
3368  template< typename Other >
3369  explicit inline HybridMatrix( size_t m, size_t n, const Other* array );
3370 
3371  template< typename Other, size_t Rows, size_t Cols >
3372  explicit inline HybridMatrix( const Other (&array)[Rows][Cols] );
3373 
3374  inline HybridMatrix( const HybridMatrix& m );
3375  template< typename MT, bool SO > inline HybridMatrix( const Matrix<MT,SO>& m );
3377  //**********************************************************************************************
3378 
3379  //**Destructor**********************************************************************************
3382  ~HybridMatrix() = default;
3384  //**********************************************************************************************
3385 
3386  //**Data access functions***********************************************************************
3389  inline Reference operator()( size_t i, size_t j ) noexcept;
3390  inline ConstReference operator()( size_t i, size_t j ) const noexcept;
3391  inline Reference at( size_t i, size_t j );
3392  inline ConstReference at( size_t i, size_t j ) const;
3393  inline Pointer data () noexcept;
3394  inline ConstPointer data () const noexcept;
3395  inline Pointer data ( size_t j ) noexcept;
3396  inline ConstPointer data ( size_t j ) const noexcept;
3397  inline Iterator begin ( size_t j ) noexcept;
3398  inline ConstIterator begin ( size_t j ) const noexcept;
3399  inline ConstIterator cbegin( size_t j ) const noexcept;
3400  inline Iterator end ( size_t j ) noexcept;
3401  inline ConstIterator end ( size_t j ) const noexcept;
3402  inline ConstIterator cend ( size_t j ) const noexcept;
3404  //**********************************************************************************************
3405 
3406  //**Assignment operators************************************************************************
3409  inline HybridMatrix& operator=( const Type& set );
3410  inline HybridMatrix& operator=( initializer_list< initializer_list<Type> > list );
3411 
3412  template< typename Other, size_t Rows, size_t Cols >
3413  inline HybridMatrix& operator=( const Other (&array)[Rows][Cols] );
3414 
3415  inline HybridMatrix& operator= ( const HybridMatrix& rhs );
3416  template< typename MT, bool SO > inline HybridMatrix& operator= ( const Matrix<MT,SO>& rhs );
3417  template< typename MT, bool SO > inline HybridMatrix& operator+=( const Matrix<MT,SO>& rhs );
3418  template< typename MT, bool SO > inline HybridMatrix& operator-=( const Matrix<MT,SO>& rhs );
3419  template< typename MT, bool SO > inline HybridMatrix& operator%=( const Matrix<MT,SO>& rhs );
3421  //**********************************************************************************************
3422 
3423  //**Utility functions***************************************************************************
3426  inline size_t rows() const noexcept;
3427  inline size_t columns() const noexcept;
3428  static inline constexpr size_t spacing() noexcept;
3429  static inline constexpr size_t capacity() noexcept;
3430  inline size_t capacity( size_t j ) const noexcept;
3431  inline size_t nonZeros() const;
3432  inline size_t nonZeros( size_t j ) const;
3433  inline void reset();
3434  inline void reset( size_t i );
3435  inline void clear();
3436  void resize ( size_t m, size_t n, bool preserve=true );
3437  inline void extend ( size_t m, size_t n, bool preserve=true );
3438  inline void swap( HybridMatrix& m ) noexcept;
3440  //**********************************************************************************************
3441 
3442  //**Numeric functions***************************************************************************
3445  inline HybridMatrix& transpose();
3446  inline HybridMatrix& ctranspose();
3447 
3448  template< typename Other > inline HybridMatrix& scale( const Other& scalar );
3450  //**********************************************************************************************
3451 
3452  //**Memory functions****************************************************************************
3455  static inline void* operator new ( std::size_t size );
3456  static inline void* operator new[]( std::size_t size );
3457  static inline void* operator new ( std::size_t size, const std::nothrow_t& );
3458  static inline void* operator new[]( std::size_t size, const std::nothrow_t& );
3459 
3460  static inline void operator delete ( void* ptr );
3461  static inline void operator delete[]( void* ptr );
3462  static inline void operator delete ( void* ptr, const std::nothrow_t& );
3463  static inline void operator delete[]( void* ptr, const std::nothrow_t& );
3465  //**********************************************************************************************
3466 
3467  private:
3468  //**********************************************************************************************
3470  template< typename MT >
3471  static constexpr bool VectorizedAssign_v =
3472  ( useOptimizedKernels &&
3473  simdEnabled && MT::simdEnabled &&
3474  IsSIMDCombinable_v< Type, ElementType_t<MT> > &&
3475  IsColumnMajorMatrix_v<MT> );
3476  //**********************************************************************************************
3477 
3478  //**********************************************************************************************
3480  template< typename MT >
3481  static constexpr bool VectorizedAddAssign_v =
3482  ( useOptimizedKernels &&
3483  simdEnabled && MT::simdEnabled &&
3484  IsSIMDCombinable_v< Type, ElementType_t<MT> > &&
3485  HasSIMDAdd_v< Type, ElementType_t<MT> > &&
3486  IsColumnMajorMatrix_v<MT> &&
3487  !IsDiagonal_v<MT> );
3488  //**********************************************************************************************
3489 
3490  //**********************************************************************************************
3492  template< typename MT >
3493  static constexpr bool VectorizedSubAssign_v =
3494  ( useOptimizedKernels &&
3495  simdEnabled && MT::simdEnabled &&
3496  IsSIMDCombinable_v< Type, ElementType_t<MT> > &&
3497  HasSIMDSub_v< Type, ElementType_t<MT> > &&
3498  IsColumnMajorMatrix_v<MT> &&
3499  !IsDiagonal_v<MT> );
3500  //**********************************************************************************************
3501 
3502  //**********************************************************************************************
3504  template< typename MT >
3505  static constexpr bool VectorizedSchurAssign_v =
3506  ( useOptimizedKernels &&
3507  simdEnabled && MT::simdEnabled &&
3508  IsSIMDCombinable_v< Type, ElementType_t<MT> > &&
3509  HasSIMDMult_v< Type, ElementType_t<MT> > &&
3510  IsColumnMajorMatrix_v<MT> );
3511  //**********************************************************************************************
3512 
3513  public:
3514  //**Debugging functions*************************************************************************
3517  inline bool isIntact() const noexcept;
3519  //**********************************************************************************************
3520 
3521  //**Expression template evaluation functions****************************************************
3524  template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
3525  template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
3526 
3527  static inline constexpr bool isAligned() noexcept;
3528 
3529  BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
3530  BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
3531  BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
3532 
3533  BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
3534  BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
3535  BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
3536  BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
3537 
3538  template< typename MT, bool SO >
3539  inline auto assign( const DenseMatrix<MT,SO>& rhs ) -> DisableIf_t< VectorizedAssign_v<MT> >;
3540 
3541  template< typename MT, bool SO >
3542  inline auto assign( const DenseMatrix<MT,SO>& rhs ) -> EnableIf_t< VectorizedAssign_v<MT> >;
3543 
3544  template< typename MT > inline void assign( const SparseMatrix<MT,true>& rhs );
3545  template< typename MT > inline void assign( const SparseMatrix<MT,false>& rhs );
3546 
3547  template< typename MT, bool SO >
3548  inline auto addAssign( const DenseMatrix<MT,SO>& rhs ) -> DisableIf_t< VectorizedAddAssign_v<MT> >;
3549 
3550  template< typename MT, bool SO >
3551  inline auto addAssign( const DenseMatrix<MT,SO>& rhs ) -> EnableIf_t< VectorizedAddAssign_v<MT> >;
3552 
3553  template< typename MT > inline void addAssign( const SparseMatrix<MT,true>& rhs );
3554  template< typename MT > inline void addAssign( const SparseMatrix<MT,false>& rhs );
3555 
3556  template< typename MT, bool SO >
3557  inline auto subAssign( const DenseMatrix<MT,SO>& rhs ) -> DisableIf_t< VectorizedSubAssign_v<MT> >;
3558 
3559  template< typename MT, bool SO >
3560  inline auto subAssign( const DenseMatrix<MT,SO>& rhs ) -> EnableIf_t< VectorizedSubAssign_v<MT> >;
3561 
3562  template< typename MT > inline void subAssign( const SparseMatrix<MT,true>& rhs );
3563  template< typename MT > inline void subAssign( const SparseMatrix<MT,false>& rhs );
3564 
3565  template< typename MT, bool SO >
3566  inline auto schurAssign( const DenseMatrix<MT,SO>& rhs ) -> DisableIf_t< VectorizedSchurAssign_v<MT> >;
3567 
3568  template< typename MT, bool SO >
3569  inline auto schurAssign( const DenseMatrix<MT,SO>& rhs ) -> EnableIf_t< VectorizedSchurAssign_v<MT> >;
3570 
3571  template< typename MT > inline void schurAssign( const SparseMatrix<MT,true>& rhs );
3572  template< typename MT > inline void schurAssign( const SparseMatrix<MT,false>& rhs );
3574  //**********************************************************************************************
3575 
3576  private:
3577  //**********************************************************************************************
3579  static constexpr size_t Alignment =
3580  ( align ? AlignmentOf_v<Type> : std::alignment_of<Type>::value );
3581 
3583  using AlignedStorage = AlignedArray<Type,MM*N,Alignment>;
3584  //**********************************************************************************************
3585 
3586  //**Member variables****************************************************************************
3589  AlignedStorage v_;
3590 
3591  size_t m_;
3592  size_t n_;
3593 
3594  //**********************************************************************************************
3595 
3596  //**Compile time checks*************************************************************************
3601  BLAZE_STATIC_ASSERT( !usePadding || MM % SIMDSIZE == 0UL );
3602  BLAZE_STATIC_ASSERT( MM >= M );
3603  //**********************************************************************************************
3604 };
3606 //*************************************************************************************************
3607 
3608 
3609 
3610 
3611 //=================================================================================================
3612 //
3613 // CONSTRUCTORS
3614 //
3615 //=================================================================================================
3616 
3617 //*************************************************************************************************
3623 template< typename Type // Data type of the matrix
3624  , size_t M // Number of rows
3625  , size_t N > // Number of columns
3626 inline HybridMatrix<Type,M,N,true>::HybridMatrix()
3627  : v_() // The statically allocated matrix elements
3628  , m_( 0UL ) // The current number of rows of the matrix
3629  , n_( 0UL ) // The current number of columns of the matrix
3630 {
3631  BLAZE_STATIC_ASSERT( IsVectorizable_v<Type> || MM == M );
3632 
3633  if( IsNumeric_v<Type> ) {
3634  for( size_t i=0UL; i<MM*N; ++i )
3635  v_[i] = Type();
3636  }
3637 
3638  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
3639 }
3641 //*************************************************************************************************
3642 
3643 
3644 //*************************************************************************************************
3658 template< typename Type // Data type of the matrix
3659  , size_t M // Number of rows
3660  , size_t N > // Number of columns
3661 inline HybridMatrix<Type,M,N,true>::HybridMatrix( size_t m, size_t n )
3662  : v_() // The statically allocated matrix elements
3663  , m_( m ) // The current number of rows of the matrix
3664  , n_( n ) // The current number of columns of the matrix
3665 {
3666  BLAZE_STATIC_ASSERT( IsVectorizable_v<Type> || MM == M );
3667 
3668  if( m > M ) {
3669  BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of rows for hybrid matrix" );
3670  }
3671 
3672  if( n > N ) {
3673  BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of columns for hybrid matrix" );
3674  }
3675 
3676  if( IsNumeric_v<Type> ) {
3677  for( size_t i=0UL; i<MM*N; ++i )
3678  v_[i] = Type();
3679  }
3680 
3681  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
3682 }
3684 //*************************************************************************************************
3685 
3686 
3687 //*************************************************************************************************
3702 template< typename Type // Data type of the matrix
3703  , size_t M // Number of rows
3704  , size_t N > // Number of columns
3705 inline HybridMatrix<Type,M,N,true>::HybridMatrix( size_t m, size_t n, const Type& init )
3706  : v_() // The statically allocated matrix elements
3707  , m_( m ) // The current number of rows of the matrix
3708  , n_( n ) // The current number of columns of the matrix
3709 {
3710  BLAZE_STATIC_ASSERT( IsVectorizable_v<Type> || MM == M );
3711 
3712  if( m > M ) {
3713  BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of rows for hybrid matrix" );
3714  }
3715 
3716  if( n > N ) {
3717  BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of columns for hybrid matrix" );
3718  }
3719 
3720  for( size_t j=0UL; j<n; ++j ) {
3721  for( size_t i=0UL; i<m; ++i )
3722  v_[i+j*MM] = init;
3723 
3724  if( IsNumeric_v<Type> ) {
3725  for( size_t i=m; i<MM; ++i )
3726  v_[i+j*MM] = Type();
3727  }
3728  }
3729 
3730  if( IsNumeric_v<Type> ) {
3731  for( size_t j=n; j<N; ++j )
3732  for( size_t i=0UL; i<MM; ++i )
3733  v_[i+j*MM] = Type();
3734  }
3735 
3736  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
3737 }
3739 //*************************************************************************************************
3740 
3741 
3742 //*************************************************************************************************
3767 template< typename Type // Data type of the matrix
3768  , size_t M // Number of rows
3769  , size_t N > // Number of columns
3770 inline HybridMatrix<Type,M,N,true>::HybridMatrix( initializer_list< initializer_list<Type> > list )
3771  : v_() // The statically allocated matrix elements
3772  , m_( list.size() ) // The current number of rows of the matrix
3773  , n_( determineColumns( list ) ) // The current number of columns of the matrix
3774 {
3775  BLAZE_STATIC_ASSERT( IsVectorizable_v<Type> || MM == M );
3776 
3777  if( m_ > M ) {
3778  BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of rows for hybrid matrix" );
3779  }
3780 
3781  if( n_ > N ) {
3782  BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of columns for hybrid matrix" );
3783  }
3784 
3785  size_t i( 0UL );
3786 
3787  for( const auto& rowList : list ) {
3788  size_t j( 0UL );
3789  for( const auto& element : rowList ) {
3790  v_[i+j*MM] = element;
3791  ++j;
3792  }
3793  if( IsNumeric_v<Type> ) {
3794  for( ; j<N; ++j ) {
3795  v_[i+j*MM] = Type();
3796  }
3797  }
3798  ++i;
3799  }
3800 
3801  BLAZE_INTERNAL_ASSERT( i == m_, "Invalid number of elements detected" );
3802 
3803  if( IsNumeric_v<Type> ) {
3804  for( ; i<MM; ++i ) {
3805  for( size_t j=0UL; j<N; ++j ) {
3806  v_[i+j*MM] = Type();
3807  }
3808  }
3809  }
3810 
3811  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
3812 }
3814 //*************************************************************************************************
3815 
3816 
3817 //*************************************************************************************************
3845 template< typename Type // Data type of the matrix
3846  , size_t M // Number of rows
3847  , size_t N > // Number of columns
3848 template< typename Other > // Data type of the initialization array
3849 inline HybridMatrix<Type,M,N,true>::HybridMatrix( size_t m, size_t n, const Other* array )
3850  : v_() // The statically allocated matrix elements
3851  , m_( m ) // The current number of rows of the matrix
3852  , n_( n ) // The current number of columns of the matrix
3853 {
3854  BLAZE_STATIC_ASSERT( IsVectorizable_v<Type> || MM == M );
3855 
3856  if( m > M ) {
3857  BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of rows for hybrid matrix" );
3858  }
3859 
3860  if( n > N ) {
3861  BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of columns for hybrid matrix" );
3862  }
3863 
3864  for( size_t j=0UL; j<n; ++j ) {
3865  for( size_t i=0UL; i<m; ++i )
3866  v_[i+j*MM] = array[i+j*m];
3867 
3868  if( IsNumeric_v<Type> ) {
3869  for( size_t i=m; i<MM; ++i )
3870  v_[i+j*MM] = Type();
3871  }
3872  }
3873 
3874  if( IsNumeric_v<Type> ) {
3875  for( size_t j=n; j<N; ++j )
3876  for( size_t i=0UL; i<MM; ++i )
3877  v_[i+j*MM] = Type();
3878  }
3879 
3880  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
3881 }
3883 //*************************************************************************************************
3884 
3885 
3886 //*************************************************************************************************
3908 template< typename Type // Data type of the matrix
3909  , size_t M // Number of rows
3910  , size_t N > // Number of columns
3911 template< typename Other // Data type of the initialization array
3912  , size_t Rows // Number of rows of the initialization array
3913  , size_t Cols > // Number of columns of the initialization array
3914 inline HybridMatrix<Type,M,N,true>::HybridMatrix( const Other (&array)[Rows][Cols] )
3915  : v_() // The statically allocated matrix elements
3916  , m_( Rows ) // The current number of rows of the matrix
3917  , n_( Cols ) // The current number of columns of the matrix
3918 {
3919  BLAZE_STATIC_ASSERT( Rows <= M );
3920  BLAZE_STATIC_ASSERT( Cols <= N );
3921  BLAZE_STATIC_ASSERT( IsVectorizable_v<Type> || MM == M );
3922 
3923  for( size_t j=0UL; j<Cols; ++j ) {
3924  for( size_t i=0UL; i<Rows; ++i )
3925  v_[i+j*MM] = array[i][j];
3926 
3927  if( IsNumeric_v<Type> ) {
3928  for( size_t i=Rows; i<MM; ++i )
3929  v_[i+j*MM] = Type();
3930  }
3931  }
3932 
3933  if( IsNumeric_v<Type> ) {
3934  for( size_t j=Cols; j<N; ++j )
3935  for( size_t i=0UL; i<MM; ++i )
3936  v_[i+j*MM] = Type();
3937  }
3938 
3939  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
3940 }
3942 //*************************************************************************************************
3943 
3944 
3945 //*************************************************************************************************
3954 template< typename Type // Data type of the matrix
3955  , size_t M // Number of rows
3956  , size_t N > // Number of columns
3957 inline HybridMatrix<Type,M,N,true>::HybridMatrix( const HybridMatrix& m )
3958  : v_() // The statically allocated matrix elements
3959  , m_( m.m_ ) // The current number of rows of the matrix
3960  , n_( m.n_ ) // The current number of columns of the matrix
3961 {
3962  BLAZE_STATIC_ASSERT( IsVectorizable_v<Type> || MM == M );
3963 
3964  for( size_t j=0UL; j<n_; ++j ) {
3965  for( size_t i=0UL; i<m_; ++i )
3966  v_[i+j*MM] = m.v_[i+j*MM];
3967 
3968  if( IsNumeric_v<Type> ) {
3969  for( size_t i=m_; i<MM; ++i )
3970  v_[i+j*MM] = Type();
3971  }
3972  }
3973 
3974  if( IsNumeric_v<Type> ) {
3975  for( size_t j=n_; j<N; ++j )
3976  for( size_t i=0UL; i<MM; ++i )
3977  v_[i+j*MM] = Type();
3978  }
3979 
3980  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
3981 }
3983 //*************************************************************************************************
3984 
3985 
3986 //*************************************************************************************************
3993 template< typename Type // Data type of the matrix
3994  , size_t M // Number of rows
3995  , size_t N > // Number of columns
3996 template< typename MT // Type of the foreign matrix
3997  , bool SO2 > // Storage order of the foreign matrix
3998 inline HybridMatrix<Type,M,N,true>::HybridMatrix( const Matrix<MT,SO2>& m )
3999  : v_() // The statically allocated matrix elements
4000  , m_( (~m).rows() ) // The current number of rows of the matrix
4001  , n_( (~m).columns() ) // The current number of columns of the matrix
4002 {
4003  using blaze::assign;
4004 
4005  BLAZE_STATIC_ASSERT( IsVectorizable_v<Type> || MM == M );
4006 
4007  if( (~m).rows() > M || (~m).columns() > N ) {
4008  BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of hybrid matrix" );
4009  }
4010 
4011  for( size_t j=0UL; j<n_; ++j ) {
4012  for( size_t i=( IsSparseMatrix_v<MT> ? 0UL : m_ );
4013  i<( IsNumeric_v<Type> ? MM : m_ );
4014  ++i ) {
4015  v_[i+j*MM] = Type();
4016  }
4017  }
4018 
4019  if( IsNumeric_v<Type> ) {
4020  for( size_t j=n_; j<N; ++j )
4021  for( size_t i=0UL; i<MM; ++i )
4022  v_[i+j*MM] = Type();
4023  }
4024 
4025  assign( *this, ~m );
4026 
4027  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
4028 }
4030 //*************************************************************************************************
4031 
4032 
4033 
4034 
4035 //=================================================================================================
4036 //
4037 // DATA ACCESS FUNCTIONS
4038 //
4039 //=================================================================================================
4040 
4041 //*************************************************************************************************
4052 template< typename Type // Data type of the matrix
4053  , size_t M // Number of rows
4054  , size_t N > // Number of columns
4056  HybridMatrix<Type,M,N,true>::operator()( size_t i, size_t j ) noexcept
4057 {
4058  BLAZE_USER_ASSERT( i<M, "Invalid row access index" );
4059  BLAZE_USER_ASSERT( j<N, "Invalid column access index" );
4060  return v_[i+j*MM];
4061 }
4063 //*************************************************************************************************
4064 
4065 
4066 //*************************************************************************************************
4077 template< typename Type // Data type of the matrix
4078  , size_t M // Number of rows
4079  , size_t N > // Number of columns
4081  HybridMatrix<Type,M,N,true>::operator()( size_t i, size_t j ) const noexcept
4082 {
4083  BLAZE_USER_ASSERT( i<M, "Invalid row access index" );
4084  BLAZE_USER_ASSERT( j<N, "Invalid column access index" );
4085  return v_[i+j*MM];
4086 }
4088 //*************************************************************************************************
4089 
4090 
4091 //*************************************************************************************************
4103 template< typename Type // Data type of the matrix
4104  , size_t M // Number of rows
4105  , size_t N > // Number of columns
4107  HybridMatrix<Type,M,N,true>::at( size_t i, size_t j )
4108 {
4109  if( i >= m_ ) {
4110  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
4111  }
4112  if( j >= n_ ) {
4113  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
4114  }
4115  return (*this)(i,j);
4116 }
4118 //*************************************************************************************************
4119 
4120 
4121 //*************************************************************************************************
4133 template< typename Type // Data type of the matrix
4134  , size_t M // Number of rows
4135  , size_t N > // Number of columns
4137  HybridMatrix<Type,M,N,true>::at( size_t i, size_t j ) const
4138 {
4139  if( i >= m_ ) {
4140  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
4141  }
4142  if( j >= n_ ) {
4143  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
4144  }
4145  return (*this)(i,j);
4146 }
4148 //*************************************************************************************************
4149 
4150 
4151 //*************************************************************************************************
4163 template< typename Type // Data type of the matrix
4164  , size_t M // Number of rows
4165  , size_t N > // Number of columns
4168 {
4169  return v_;
4170 }
4172 //*************************************************************************************************
4173 
4174 
4175 //*************************************************************************************************
4187 template< typename Type // Data type of the matrix
4188  , size_t M // Number of rows
4189  , size_t N > // Number of columns
4191  HybridMatrix<Type,M,N,true>::data() const noexcept
4192 {
4193  return v_;
4194 }
4196 //*************************************************************************************************
4197 
4198 
4199 //*************************************************************************************************
4208 template< typename Type // Data type of the matrix
4209  , size_t M // Number of rows
4210  , size_t N > // Number of columns
4212  HybridMatrix<Type,M,N,true>::data( size_t j ) noexcept
4213 {
4214  BLAZE_USER_ASSERT( j < N, "Invalid dense matrix column access index" );
4215  return v_ + j*MM;
4216 }
4218 //*************************************************************************************************
4219 
4220 
4221 //*************************************************************************************************
4230 template< typename Type // Data type of the matrix
4231  , size_t M // Number of rows
4232  , size_t N > // Number of columns
4234  HybridMatrix<Type,M,N,true>::data( size_t j ) const noexcept
4235 {
4236  BLAZE_USER_ASSERT( j < N, "Invalid dense matrix column access index" );
4237  return v_ + j*MM;
4238 }
4240 //*************************************************************************************************
4241 
4242 
4243 //*************************************************************************************************
4250 template< typename Type // Data type of the matrix
4251  , size_t M // Number of rows
4252  , size_t N > // Number of columns
4254  HybridMatrix<Type,M,N,true>::begin( size_t j ) noexcept
4255 {
4256  BLAZE_USER_ASSERT( j < N, "Invalid dense matrix column access index" );
4257  return Iterator( v_ + j*MM );
4258 }
4260 //*************************************************************************************************
4261 
4262 
4263 //*************************************************************************************************
4270 template< typename Type // Data type of the matrix
4271  , size_t M // Number of rows
4272  , size_t N > // Number of columns
4274  HybridMatrix<Type,M,N,true>::begin( size_t j ) const noexcept
4275 {
4276  BLAZE_USER_ASSERT( j < N, "Invalid dense matrix column access index" );
4277  return ConstIterator( v_ + j*MM );
4278 }
4280 //*************************************************************************************************
4281 
4282 
4283 //*************************************************************************************************
4290 template< typename Type // Data type of the matrix
4291  , size_t M // Number of rows
4292  , size_t N > // Number of columns
4294  HybridMatrix<Type,M,N,true>::cbegin( size_t j ) const noexcept
4295 {
4296  BLAZE_USER_ASSERT( j < N, "Invalid dense matrix column access index" );
4297  return ConstIterator( v_ + j*MM );
4298 }
4300 //*************************************************************************************************
4301 
4302 
4303 //*************************************************************************************************
4310 template< typename Type // Data type of the matrix
4311  , size_t M // Number of rows
4312  , size_t N > // Number of columns
4314  HybridMatrix<Type,M,N,true>::end( size_t j ) noexcept
4315 {
4316  BLAZE_USER_ASSERT( j < N, "Invalid dense matrix column access index" );
4317  return Iterator( v_ + j*MM + M );
4318 }
4320 //*************************************************************************************************
4321 
4322 
4323 //*************************************************************************************************
4330 template< typename Type // Data type of the matrix
4331  , size_t M // Number of rows
4332  , size_t N > // Number of columns
4334  HybridMatrix<Type,M,N,true>::end( size_t j ) const noexcept
4335 {
4336  BLAZE_USER_ASSERT( j < N, "Invalid dense matrix column access index" );
4337  return ConstIterator( v_ + j*MM + M );
4338 }
4340 //*************************************************************************************************
4341 
4342 
4343 //*************************************************************************************************
4350 template< typename Type // Data type of the matrix
4351  , size_t M // Number of rows
4352  , size_t N > // Number of columns
4354  HybridMatrix<Type,M,N,true>::cend( size_t j ) const noexcept
4355 {
4356  BLAZE_USER_ASSERT( j < N, "Invalid dense matrix column access index" );
4357  return ConstIterator( v_ + j*MM + M );
4358 }
4360 //*************************************************************************************************
4361 
4362 
4363 
4364 
4365 //=================================================================================================
4366 //
4367 // ASSIGNMENT OPERATORS
4368 //
4369 //=================================================================================================
4370 
4371 //*************************************************************************************************
4378 template< typename Type // Data type of the matrix
4379  , size_t M // Number of rows
4380  , size_t N > // Number of columns
4381 inline HybridMatrix<Type,M,N,true>&
4383 {
4384  BLAZE_INTERNAL_ASSERT( m_ <= M, "Invalid number of rows detected" );
4385  BLAZE_INTERNAL_ASSERT( n_ <= N, "Invalid number of columns detected" );
4386 
4387  for( size_t j=0UL; j<n_; ++j )
4388  for( size_t i=0UL; i<m_; ++i )
4389  v_[i+j*MM] = set;
4390 
4391  return *this;
4392 }
4394 //*************************************************************************************************
4395 
4396 
4397 //*************************************************************************************************
4423 template< typename Type // Data type of the matrix
4424  , size_t M // Number of rows
4425  , size_t N > // Number of columns
4426 inline HybridMatrix<Type,M,N,true>&
4427  HybridMatrix<Type,M,N,true>::operator=( initializer_list< initializer_list<Type> > list )
4428 {
4429  const size_t m( list.size() );
4430  const size_t n( determineColumns( list ) );
4431 
4432  if( m > M ) {
4433  BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of rows for hybrid matrix" );
4434  }
4435 
4436  if( n > N ) {
4437  BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of columns for hybrid matrix" );
4438  }
4439 
4440  resize( m, n, false );
4441 
4442  size_t i( 0UL );
4443 
4444  for( const auto& rowList : list ) {
4445  size_t j( 0UL );
4446  for( const auto& element : rowList ) {
4447  v_[i+j*MM] = element;
4448  ++j;
4449  }
4450  for( ; j<n_; ++j ) {
4451  v_[i+j*MM] = Type();
4452  }
4453  ++i;
4454  }
4455 
4456  return *this;
4457 }
4459 //*************************************************************************************************
4460 
4461 
4462 //*************************************************************************************************
4484 template< typename Type // Data type of the matrix
4485  , size_t M // Number of rows
4486  , size_t N > // Number of columns
4487 template< typename Other // Data type of the initialization array
4488  , size_t Rows // Number of rows of the initialization array
4489  , size_t Cols > // Number of columns of the initialization array
4490 inline HybridMatrix<Type,M,N,true>&
4491  HybridMatrix<Type,M,N,true>::operator=( const Other (&array)[Rows][Cols] )
4492 {
4493  BLAZE_STATIC_ASSERT( Rows <= M );
4494  BLAZE_STATIC_ASSERT( Cols <= N );
4495 
4496  resize( Rows, Cols );
4497 
4498  for( size_t j=0UL; j<Cols; ++j )
4499  for( size_t i=0UL; i<Rows; ++i )
4500  v_[i+j*MM] = array[i][j];
4501 
4502  return *this;
4503 }
4505 //*************************************************************************************************
4506 
4507 
4508 //*************************************************************************************************
4517 template< typename Type // Data type of the matrix
4518  , size_t M // Number of rows
4519  , size_t N > // Number of columns
4520 inline HybridMatrix<Type,M,N,true>&
4521  HybridMatrix<Type,M,N,true>::operator=( const HybridMatrix& rhs )
4522 {
4523  using blaze::assign;
4524 
4525  BLAZE_INTERNAL_ASSERT( m_ <= M, "Invalid number of rows detected" );
4526  BLAZE_INTERNAL_ASSERT( n_ <= N, "Invalid number of columns detected" );
4527 
4528  resize( rhs.rows(), rhs.columns() );
4529  assign( *this, ~rhs );
4530 
4531  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
4532 
4533  return *this;
4534 }
4536 //*************************************************************************************************
4537 
4538 
4539 //*************************************************************************************************
4551 template< typename Type // Data type of the matrix
4552  , size_t M // Number of rows
4553  , size_t N > // Number of columns
4554 template< typename MT // Type of the right-hand side matrix
4555  , bool SO > // Storage order of the right-hand side matrix
4556 inline HybridMatrix<Type,M,N,true>& HybridMatrix<Type,M,N,true>::operator=( const Matrix<MT,SO>& rhs )
4557 {
4558  using blaze::assign;
4559 
4560  using TT = decltype( trans( *this ) );
4561  using CT = decltype( ctrans( *this ) );
4562  using IT = decltype( inv( *this ) );
4563 
4564  if( (~rhs).rows() > M || (~rhs).columns() > N ) {
4565  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to hybrid matrix" );
4566  }
4567 
4568  if( IsSame_v<MT,TT> && (~rhs).isAliased( this ) ) {
4569  transpose();
4570  }
4571  else if( IsSame_v<MT,CT> && (~rhs).isAliased( this ) ) {
4572  ctranspose();
4573  }
4574  else if( !IsSame_v<MT,IT> && (~rhs).canAlias( this ) ) {
4575  HybridMatrix tmp( ~rhs );
4576  resize( tmp.rows(), tmp.columns() );
4577  assign( *this, tmp );
4578  }
4579  else {
4580  resize( (~rhs).rows(), (~rhs).columns() );
4581  if( IsSparseMatrix_v<MT> )
4582  reset();
4583  assign( *this, ~rhs );
4584  }
4585 
4586  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
4587 
4588  return *this;
4589 }
4591 //*************************************************************************************************
4592 
4593 
4594 //*************************************************************************************************
4605 template< typename Type // Data type of the matrix
4606  , size_t M // Number of rows
4607  , size_t N > // Number of columns
4608 template< typename MT // Type of the right-hand side matrix
4609  , bool SO > // Storage order of the right-hand side matrix
4610 inline HybridMatrix<Type,M,N,true>& HybridMatrix<Type,M,N,true>::operator+=( const Matrix<MT,SO>& rhs )
4611 {
4612  using blaze::addAssign;
4613 
4614  if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
4615  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4616  }
4617 
4618  if( (~rhs).canAlias( this ) ) {
4619  const ResultType_t<MT> tmp( ~rhs );
4620  addAssign( *this, tmp );
4621  }
4622  else {
4623  addAssign( *this, ~rhs );
4624  }
4625 
4626  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
4627 
4628  return *this;
4629 }
4631 //*************************************************************************************************
4632 
4633 
4634 //*************************************************************************************************
4645 template< typename Type // Data type of the matrix
4646  , size_t M // Number of rows
4647  , size_t N > // Number of columns
4648 template< typename MT // Type of the right-hand side matrix
4649  , bool SO > // Storage order of the right-hand side matrix
4650 inline HybridMatrix<Type,M,N,true>& HybridMatrix<Type,M,N,true>::operator-=( const Matrix<MT,SO>& rhs )
4651 {
4652  using blaze::subAssign;
4653 
4654  if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
4655  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4656  }
4657 
4658  if( (~rhs).canAlias( this ) ) {
4659  const ResultType_t<MT> tmp( ~rhs );
4660  subAssign( *this, tmp );
4661  }
4662  else {
4663  subAssign( *this, ~rhs );
4664  }
4665 
4666  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
4667 
4668  return *this;
4669 }
4671 //*************************************************************************************************
4672 
4673 
4674 //*************************************************************************************************
4685 template< typename Type // Data type of the matrix
4686  , size_t M // Number of rows
4687  , size_t N > // Number of columns
4688 template< typename MT // Type of the right-hand side matrix
4689  , bool SO > // Storage order of the right-hand side matrix
4690 inline HybridMatrix<Type,M,N,true>& HybridMatrix<Type,M,N,true>::operator%=( const Matrix<MT,SO>& rhs )
4691 {
4692  using blaze::schurAssign;
4693 
4694  if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) {
4695  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4696  }
4697 
4698  if( (~rhs).canAlias( this ) ) {
4699  const ResultType_t<MT> tmp( ~rhs );
4700  schurAssign( *this, tmp );
4701  }
4702  else {
4703  schurAssign( *this, ~rhs );
4704  }
4705 
4706  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
4707 
4708  return *this;
4709 }
4711 //*************************************************************************************************
4712 
4713 
4714 
4715 
4716 //=================================================================================================
4717 //
4718 // UTILITY FUNCTIONS
4719 //
4720 //=================================================================================================
4721 
4722 //*************************************************************************************************
4728 template< typename Type // Data type of the matrix
4729  , size_t M // Number of rows
4730  , size_t N > // Number of columns
4731 inline size_t HybridMatrix<Type,M,N,true>::rows() const noexcept
4732 {
4733  return m_;
4734 }
4736 //*************************************************************************************************
4737 
4738 
4739 //*************************************************************************************************
4745 template< typename Type // Data type of the matrix
4746  , size_t M // Number of rows
4747  , size_t N > // Number of columns
4748 inline size_t HybridMatrix<Type,M,N,true>::columns() const noexcept
4749 {
4750  return n_;
4751 }
4753 //*************************************************************************************************
4754 
4755 
4756 //*************************************************************************************************
4765 template< typename Type // Data type of the matrix
4766  , size_t M // Number of rows
4767  , size_t N > // Number of columns
4768 inline constexpr size_t HybridMatrix<Type,M,N,true>::spacing() noexcept
4769 {
4770  return MM;
4771 }
4773 //*************************************************************************************************
4774 
4775 
4776 //*************************************************************************************************
4782 template< typename Type // Data type of the matrix
4783  , size_t M // Number of rows
4784  , size_t N > // Number of columns
4785 inline constexpr size_t HybridMatrix<Type,M,N,true>::capacity() noexcept
4786 {
4787  return MM*N;
4788 }
4790 //*************************************************************************************************
4791 
4792 
4793 //*************************************************************************************************
4800 template< typename Type // Data type of the matrix
4801  , size_t M // Number of rows
4802  , size_t N > // Number of columns
4803 inline size_t HybridMatrix<Type,M,N,true>::capacity( size_t j ) const noexcept
4804 {
4805  MAYBE_UNUSED( j );
4806 
4807  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
4808 
4809  return MM;
4810 }
4812 //*************************************************************************************************
4813 
4814 
4815 //*************************************************************************************************
4821 template< typename Type // Data type of the matrix
4822  , size_t M // Number of rows
4823  , size_t N > // Number of columns
4824 inline size_t HybridMatrix<Type,M,N,true>::nonZeros() const
4825 {
4826  size_t nonzeros( 0UL );
4827 
4828  for( size_t j=0UL; j<n_; ++j )
4829  for( size_t i=0UL; i<m_; ++i )
4830  if( !isDefault( v_[i+j*MM] ) )
4831  ++nonzeros;
4832 
4833  return nonzeros;
4834 }
4836 //*************************************************************************************************
4837 
4838 
4839 //*************************************************************************************************
4846 template< typename Type // Data type of the matrix
4847  , size_t M // Number of rows
4848  , size_t N > // Number of columns
4849 inline size_t HybridMatrix<Type,M,N,true>::nonZeros( size_t j ) const
4850 {
4851  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
4852 
4853  const size_t iend( j*MM + m_ );
4854  size_t nonzeros( 0UL );
4855 
4856  for( size_t i=j*MM; i<iend; ++i )
4857  if( !isDefault( v_[i] ) )
4858  ++nonzeros;
4859 
4860  return nonzeros;
4861 }
4863 //*************************************************************************************************
4864 
4865 
4866 //*************************************************************************************************
4872 template< typename Type // Data type of the matrix
4873  , size_t M // Number of rows
4874  , size_t N > // Number of columns
4876 {
4877  using blaze::clear;
4878 
4879  for( size_t j=0UL; j<n_; ++j )
4880  for( size_t i=0UL; i<m_; ++i )
4881  clear( v_[i+j*MM] );
4882 }
4884 //*************************************************************************************************
4885 
4886 
4887 //*************************************************************************************************
4897 template< typename Type // Data type of the matrix
4898  , size_t M // Number of rows
4899  , size_t N > // Number of columns
4900 inline void HybridMatrix<Type,M,N,true>::reset( size_t j )
4901 {
4902  using blaze::clear;
4903 
4904  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
4905  for( size_t i=0UL; i<m_; ++i )
4906  clear( v_[i+j*MM] );
4907 }
4909 //*************************************************************************************************
4910 
4911 
4912 //*************************************************************************************************
4920 template< typename Type // Data type of the matrix
4921  , size_t M // Number of rows
4922  , size_t N > // Number of columns
4924 {
4925  resize( 0UL, 0UL );
4926 }
4928 //*************************************************************************************************
4929 
4930 
4931 //*************************************************************************************************
4968 template< typename Type // Data type of the matrix
4969  , size_t M // Number of rows
4970  , size_t N > // Number of columns
4971 void HybridMatrix<Type,M,N,true>::resize( size_t m, size_t n, bool preserve )
4972 {
4973  MAYBE_UNUSED( preserve );
4974 
4975  if( m > M ) {
4976  BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of rows for hybrid matrix" );
4977  }
4978 
4979  if( n > N ) {
4980  BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of columns for hybrid matrix" );
4981  }
4982 
4983  if( IsVectorizable_v<Type> && m < m_ ) {
4984  for( size_t j=0UL; j<n; ++j )
4985  for( size_t i=m; i<m_; ++i )
4986  v_[i+j*MM] = Type();
4987  }
4988 
4989  if( IsVectorizable_v<Type> && n < n_ ) {
4990  for( size_t j=n; j<n_; ++j )
4991  for( size_t i=0UL; i<m_; ++i )
4992  v_[i+j*MM] = Type();
4993  }
4994 
4995  m_ = m;
4996  n_ = n;
4997 }
4999 //*************************************************************************************************
5000 
5001 
5002 //*************************************************************************************************
5018 template< typename Type // Data type of the matrix
5019  , size_t M // Number of rows
5020  , size_t N > // Number of columns
5021 inline void HybridMatrix<Type,M,N,true>::extend( size_t m, size_t n, bool preserve )
5022 {
5023  MAYBE_UNUSED( preserve );
5024  resize( m_+m, n_+n );
5025 }
5027 //*************************************************************************************************
5028 
5029 
5030 //*************************************************************************************************
5037 template< typename Type // Data type of the matrix
5038  , size_t M // Number of rows
5039  , size_t N > // Number of columns
5040 inline void HybridMatrix<Type,M,N,true>::swap( HybridMatrix& m ) noexcept
5041 {
5042  using std::swap;
5043 
5044  const size_t maxrows( max( m_, m.m_ ) );
5045  const size_t maxcols( max( n_, m.n_ ) );
5046 
5047  for( size_t j=0UL; j<maxcols; ++j ) {
5048  for( size_t i=0UL; i<maxrows; ++i ) {
5049  swap( v_[i+j*MM], m(i,j) );
5050  }
5051  }
5052 
5053  swap( m_, m.m_ );
5054  swap( n_, m.n_ );
5055 }
5057 //*************************************************************************************************
5058 
5059 
5060 
5061 
5062 //=================================================================================================
5063 //
5064 // NUMERIC FUNCTIONS
5065 //
5066 //=================================================================================================
5067 
5068 //*************************************************************************************************
5080 template< typename Type // Data type of the matrix
5081  , size_t M // Number of rows
5082  , size_t N > // Number of columns
5083 inline HybridMatrix<Type,M,N,true>& HybridMatrix<Type,M,N,true>::transpose()
5084 {
5085  using std::swap;
5086 
5087  if( m_ > N || n_ > M ) {
5088  BLAZE_THROW_LOGIC_ERROR( "Impossible transpose operation" );
5089  }
5090 
5091  const size_t maxsize( max( m_, n_ ) );
5092  for( size_t j=1UL; j<maxsize; ++j ) {
5093  for( size_t i=0UL; i<j; ++i ) {
5094  swap( v_[i+j*MM], v_[j+i*MM] );
5095  }
5096  }
5097 
5098  if( IsVectorizable_v<Type> && n_ < m_ ) {
5099  for( size_t j=0UL; j<n_; ++j ) {
5100  for( size_t i=n_; i<m_; ++i ) {
5101  v_[i+j*MM] = Type();
5102  }
5103  }
5104  }
5105 
5106  if( IsVectorizable_v<Type> && n_ > m_ ) {
5107  for( size_t j=m_; j<n_; ++j ) {
5108  for( size_t i=0UL; i<m_; ++i ) {
5109  v_[i+j*MM] = Type();
5110  }
5111  }
5112  }
5113 
5114  swap( m_, n_ );
5115 
5116  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
5117 
5118  return *this;
5119 }
5121 //*************************************************************************************************
5122 
5123 
5124 //*************************************************************************************************
5136 template< typename Type // Data type of the matrix
5137  , size_t M // Number of rows
5138  , size_t N > // Number of columns
5139 inline HybridMatrix<Type,M,N,true>& HybridMatrix<Type,M,N,true>::ctranspose()
5140 {
5141  using std::swap;
5142 
5143  if( m_ > N || n_ > M ) {
5144  BLAZE_THROW_LOGIC_ERROR( "Impossible transpose operation" );
5145  }
5146 
5147  const size_t maxsize( max( m_, n_ ) );
5148  for( size_t j=0UL; j<maxsize; ++j ) {
5149  for( size_t i=0UL; i<j; ++i ) {
5150  cswap( v_[i+j*MM], v_[j+i*MM] );
5151  }
5152  conjugate( v_[j+j*MM] );
5153  }
5154 
5155  if( IsVectorizable_v<Type> && n_ < m_ ) {
5156  for( size_t j=0UL; j<n_; ++j ) {
5157  for( size_t i=n_; i<m_; ++i ) {
5158  v_[i+j*MM] = Type();
5159  }
5160  }
5161  }
5162 
5163  if( IsVectorizable_v<Type> && n_ > m_ ) {
5164  for( size_t j=m_; j<n_; ++j ) {
5165  for( size_t i=0UL; i<m_; ++i ) {
5166  v_[i+j*MM] = Type();
5167  }
5168  }
5169  }
5170 
5171  swap( m_, n_ );
5172 
5173  BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
5174 
5175  return *this;
5176 }
5178 //*************************************************************************************************
5179 
5180 
5181 //*************************************************************************************************
5199 template< typename Type // Data type of the matrix
5200  , size_t M // Number of rows
5201  , size_t N > // Number of columns
5202 template< typename Other > // Data type of the scalar value
5203 inline HybridMatrix<Type,M,N,true>&
5204  HybridMatrix<Type,M,N,true>::scale( const Other& scalar )
5205 {
5206  for( size_t j=0UL; j<n_; ++j )
5207  for( size_t i=0UL; i<m_; ++i )
5208  v_[i+j*MM] *= scalar;
5209 
5210  return *this;
5211 }
5213 //*************************************************************************************************
5214 
5215 
5216 
5217 
5218 //=================================================================================================
5219 //
5220 // MEMORY FUNCTIONS
5221 //
5222 //=================================================================================================
5223 
5224 //*************************************************************************************************
5235 template< typename Type // Data type of the matrix
5236  , size_t M // Number of rows
5237  , size_t N > // Number of columns
5238 inline void* HybridMatrix<Type,M,N,true>::operator new( std::size_t size )
5239 {
5240  MAYBE_UNUSED( size );
5241 
5242  BLAZE_INTERNAL_ASSERT( size == sizeof( HybridMatrix ), "Invalid number of bytes detected" );
5243 
5244  return allocate<HybridMatrix>( 1UL );
5245 }
5247 //*************************************************************************************************
5248 
5249 
5250 //*************************************************************************************************
5261 template< typename Type // Data type of the matrix
5262  , size_t M // Number of rows
5263  , size_t N > // Number of columns
5264 inline void* HybridMatrix<Type,M,N,true>::operator new[]( std::size_t size )
5265 {
5266  BLAZE_INTERNAL_ASSERT( size >= sizeof( HybridMatrix ) , "Invalid number of bytes detected" );
5267  BLAZE_INTERNAL_ASSERT( size % sizeof( HybridMatrix ) == 0UL, "Invalid number of bytes detected" );
5268 
5269  return allocate<HybridMatrix>( size/sizeof(HybridMatrix) );
5270 }
5272 //*************************************************************************************************
5273 
5274 
5275 //*************************************************************************************************
5286 template< typename Type // Data type of the matrix
5287  , size_t M // Number of rows
5288  , size_t N > // Number of columns
5289 inline void* HybridMatrix<Type,M,N,true>::operator new( std::size_t size, const std::nothrow_t& )
5290 {
5291  MAYBE_UNUSED( size );
5292 
5293  BLAZE_INTERNAL_ASSERT( size == sizeof( HybridMatrix ), "Invalid number of bytes detected" );
5294 
5295  return allocate<HybridMatrix>( 1UL );
5296 }
5298 //*************************************************************************************************
5299 
5300 
5301 //*************************************************************************************************
5312 template< typename Type // Data type of the matrix
5313  , size_t M // Number of rows
5314  , size_t N > // Number of columns
5315 inline void* HybridMatrix<Type,M,N,true>::operator new[]( std::size_t size, const std::nothrow_t& )
5316 {
5317  BLAZE_INTERNAL_ASSERT( size >= sizeof( HybridMatrix ) , "Invalid number of bytes detected" );
5318  BLAZE_INTERNAL_ASSERT( size % sizeof( HybridMatrix ) == 0UL, "Invalid number of bytes detected" );
5319 
5320  return allocate<HybridMatrix>( size/sizeof(HybridMatrix) );
5321 }
5323 //*************************************************************************************************
5324 
5325 
5326 //*************************************************************************************************
5333 template< typename Type // Data type of the matrix
5334  , size_t M // Number of rows
5335  , size_t N > // Number of columns
5336 inline void HybridMatrix<Type,M,N,true>::operator delete( void* ptr )
5337 {
5338  deallocate( static_cast<HybridMatrix*>( ptr ) );
5339 }
5341 //*************************************************************************************************
5342 
5343 
5344 //*************************************************************************************************
5351 template< typename Type // Data type of the matrix
5352  , size_t M // Number of rows
5353  , size_t N > // Number of columns
5354 inline void HybridMatrix<Type,M,N,true>::operator delete[]( void* ptr )
5355 {
5356  deallocate( static_cast<HybridMatrix*>( ptr ) );
5357 }
5359 //*************************************************************************************************
5360 
5361 
5362 //*************************************************************************************************
5369 template< typename Type // Data type of the matrix
5370  , size_t M // Number of rows
5371  , size_t N > // Number of columns
5372 inline void HybridMatrix<Type,M,N,true>::operator delete( void* ptr, const std::nothrow_t& )
5373 {
5374  deallocate( static_cast<HybridMatrix*>( ptr ) );
5375 }
5377 //*************************************************************************************************
5378 
5379 
5380 //*************************************************************************************************
5387 template< typename Type // Data type of the matrix
5388  , size_t M // Number of rows
5389  , size_t N > // Number of columns
5390 inline void HybridMatrix<Type,M,N,true>::operator delete[]( void* ptr, const std::nothrow_t& )
5391 {
5392  deallocate( static_cast<HybridMatrix*>( ptr ) );
5393 }
5395 //*************************************************************************************************
5396 
5397 
5398 
5399 
5400 //=================================================================================================
5401 //
5402 // DEBUGGING FUNCTIONS
5403 //
5404 //=================================================================================================
5405 
5406 //*************************************************************************************************
5416 template< typename Type // Data type of the matrix
5417  , size_t M // Number of rows
5418  , size_t N > // Number of columns
5419 inline bool HybridMatrix<Type,M,N,true>::isIntact() const noexcept
5420 {
5421  if( m_ > M || n_ > N )
5422  return false;
5423 
5424  if( IsVectorizable_v<Type> )
5425  {
5426  for( size_t j=0UL; j<n_; ++j ) {
5427  for( size_t i=m_; i<MM; ++i ) {
5428  if( v_[i+j*MM] != Type() )
5429  return false;
5430  }
5431  }
5432 
5433  for( size_t j=n_; j<N; ++j ) {
5434  for( size_t i=0UL; i<MM; ++i ) {
5435  if( v_[i+j*MM] != Type() )
5436  return false;
5437  }
5438  }
5439  }
5440 
5441  return true;
5442 }
5444 //*************************************************************************************************
5445 
5446 
5447 
5448 
5449 //=================================================================================================
5450 //
5451 // EXPRESSION TEMPLATE EVALUATION FUNCTIONS
5452 //
5453 //=================================================================================================
5454 
5455 //*************************************************************************************************
5466 template< typename Type // Data type of the matrix
5467  , size_t M // Number of rows
5468  , size_t N > // Number of columns
5469 template< typename Other > // Data type of the foreign expression
5470 inline bool HybridMatrix<Type,M,N,true>::canAlias( const Other* alias ) const noexcept
5471 {
5472  return static_cast<const void*>( this ) == static_cast<const void*>( alias );
5473 }
5475 //*************************************************************************************************
5476 
5477 
5478 //*************************************************************************************************
5489 template< typename Type // Data type of the matrix
5490  , size_t M // Number of rows
5491  , size_t N > // Number of columns
5492 template< typename Other > // Data type of the foreign expression
5493 inline bool HybridMatrix<Type,M,N,true>::isAliased( const Other* alias ) const noexcept
5494 {
5495  return static_cast<const void*>( this ) == static_cast<const void*>( alias );
5496 }
5498 //*************************************************************************************************
5499 
5500 
5501 //*************************************************************************************************
5511 template< typename Type // Data type of the matrix
5512  , size_t M // Number of rows
5513  , size_t N > // Number of columns
5514 inline constexpr bool HybridMatrix<Type,M,N,true>::isAligned() noexcept
5515 {
5516  return align;
5517 }
5519 //*************************************************************************************************
5520 
5521 
5522 //*************************************************************************************************
5537 template< typename Type // Data type of the matrix
5538  , size_t M // Number of rows
5539  , size_t N > // Number of columns
5541  HybridMatrix<Type,M,N,true>::load( size_t i, size_t j ) const noexcept
5542 {
5543  if( align )
5544  return loada( i, j );
5545  else
5546  return loadu( i, j );
5547 }
5549 //*************************************************************************************************
5550 
5551 
5552 //*************************************************************************************************
5567 template< typename Type // Data type of the matrix
5568  , size_t M // Number of rows
5569  , size_t N > // Number of columns
5571  HybridMatrix<Type,M,N,true>::loada( size_t i, size_t j ) const noexcept
5572 {
5573  using blaze::loada;
5574 
5576 
5577  BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
5578  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= MM, "Invalid row access index" );
5579  BLAZE_INTERNAL_ASSERT( !usePadding || i % SIMDSIZE == 0UL, "Invalid row access index" );
5580  BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
5581  BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[i+j*MM] ), "Invalid alignment detected" );
5582 
5583  return loada( &v_[i+j*MM] );
5584 }
5586 //*************************************************************************************************
5587 
5588 
5589 //*************************************************************************************************
5604 template< typename Type // Data type of the matrix
5605  , size_t M // Number of rows
5606  , size_t N > // Number of columns
5608  HybridMatrix<Type,M,N,true>::loadu( size_t i, size_t j ) const noexcept
5609 {
5610  using blaze::loadu;
5611 
5613 
5614  BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
5615  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= MM, "Invalid row access index" );
5616  BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
5617 
5618  return loadu( &v_[i+j*MM] );
5619 }
5621 //*************************************************************************************************
5622 
5623 
5624 //*************************************************************************************************
5640 template< typename Type // Data type of the matrix
5641  , size_t M // Number of rows
5642  , size_t N > // Number of columns
5644  HybridMatrix<Type,M,N,true>::store( size_t i, size_t j, const SIMDType& value ) noexcept
5645 {
5646  if( align )
5647  storea( i, j, value );
5648  else
5649  storeu( i, j, value );
5650 }
5652 //*************************************************************************************************
5653 
5654 
5655 //*************************************************************************************************
5671 template< typename Type // Data type of the matrix
5672  , size_t M // Number of rows
5673  , size_t N > // Number of columns
5675  HybridMatrix<Type,M,N,true>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
5676 {
5677  using blaze::storea;
5678 
5680 
5681  BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
5682  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= MM, "Invalid row access index" );
5683  BLAZE_INTERNAL_ASSERT( !usePadding || i % SIMDSIZE == 0UL, "Invalid row access index" );
5684  BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
5685  BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[i+j*MM] ), "Invalid alignment detected" );
5686 
5687  storea( &v_[i+j*MM], value );
5688 }
5690 //*************************************************************************************************
5691 
5692 
5693 //*************************************************************************************************
5709 template< typename Type // Data type of the matrix
5710  , size_t M // Number of rows
5711  , size_t N > // Number of columns
5713  HybridMatrix<Type,M,N,true>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
5714 {
5715  using blaze::storeu;
5716 
5718 
5719  BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
5720  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= MM, "Invalid row access index" );
5721  BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
5722 
5723  storeu( &v_[i+j*MM], value );
5724 }
5726 //*************************************************************************************************
5727 
5728 
5729 //*************************************************************************************************
5746 template< typename Type // Data type of the matrix
5747  , size_t M // Number of rows
5748  , size_t N > // Number of columns
5750  HybridMatrix<Type,M,N,true>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
5751 {
5752  using blaze::stream;
5753 
5755 
5756  BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
5757  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= MM, "Invalid row access index" );
5758  BLAZE_INTERNAL_ASSERT( !usePadding || i % SIMDSIZE == 0UL, "Invalid row access index" );
5759  BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
5760  BLAZE_INTERNAL_ASSERT( checkAlignment( &v_[i+j*MM] ), "Invalid alignment detected" );
5761 
5762  stream( &v_[i+j*MM], value );
5763 }
5765 //*************************************************************************************************
5766 
5767 
5768 //*************************************************************************************************
5780 template< typename Type // Data type of the matrix
5781  , size_t M // Number of rows
5782  , size_t N > // Number of columns
5783 template< typename MT // Type of the right-hand side dense matrix
5784  , bool SO > // Storage order of the right-hand side dense matrix
5785 inline auto HybridMatrix<Type,M,N,true>::assign( const DenseMatrix<MT,SO>& rhs )
5786  -> DisableIf_t< VectorizedAssign_v<MT> >
5787 {
5788  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
5789 
5790  for( size_t j=0UL; j<n_; ++j ) {
5791  for( size_t i=0UL; i<m_; ++i ) {
5792  v_[i+j*MM] = (~rhs)(i,j);
5793  }
5794  }
5795 }
5797 //*************************************************************************************************
5798 
5799 
5800 //*************************************************************************************************
5812 template< typename Type // Data type of the matrix
5813  , size_t M // Number of rows
5814  , size_t N > // Number of columns
5815 template< typename MT // Type of the right-hand side dense matrix
5816  , bool SO > // Storage order of the right-hand side dense matrix
5817 inline auto HybridMatrix<Type,M,N,true>::assign( const DenseMatrix<MT,SO>& rhs )
5818  -> EnableIf_t< VectorizedAssign_v<MT> >
5819 {
5821 
5822  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
5823 
5824  constexpr bool remainder( !usePadding || !IsPadded_v<MT> );
5825 
5826  const size_t ipos( ( remainder )?( m_ & size_t(-SIMDSIZE) ):( m_ ) );
5827  BLAZE_INTERNAL_ASSERT( !remainder || ( m_ - ( m_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
5828 
5829  for( size_t j=0UL; j<n_; ++j )
5830  {
5831  size_t i( 0UL );
5832 
5833  for( ; i<ipos; i+=SIMDSIZE ) {
5834  store( i, j, (~rhs).load(i,j) );
5835  }
5836  for( ; remainder && i<m_; ++i ) {
5837  v_[i+j*MM] = (~rhs)(i,j);
5838  }
5839  }
5840 }
5842 //*************************************************************************************************
5843 
5844 
5845 //*************************************************************************************************
5857 template< typename Type // Data type of the matrix
5858  , size_t M // Number of rows
5859  , size_t N > // Number of columns
5860 template< typename MT > // Type of the right-hand side sparse matrix
5861 inline void HybridMatrix<Type,M,N,true>::assign( const SparseMatrix<MT,true>& rhs )
5862 {
5863  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
5864 
5865  for( size_t j=0UL; j<n_; ++j )
5866  for( auto element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
5867  v_[element->index()+j*MM] = element->value();
5868 }
5870 //*************************************************************************************************
5871 
5872 
5873 //*************************************************************************************************
5885 template< typename Type // Data type of the matrix
5886  , size_t M // Number of rows
5887  , size_t N > // Number of columns
5888 template< typename MT > // Type of the right-hand side sparse matrix
5889 inline void HybridMatrix<Type,M,N,true>::assign( const SparseMatrix<MT,false>& rhs )
5890 {
5892 
5893  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
5894 
5895  for( size_t i=0UL; i<m_; ++i )
5896  for( auto element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
5897  v_[i+element->index()*MM] = element->value();
5898 }
5900 //*************************************************************************************************
5901 
5902 
5903 //*************************************************************************************************
5915 template< typename Type // Data type of the matrix
5916  , size_t M // Number of rows
5917  , size_t N > // Number of columns
5918 template< typename MT // Type of the right-hand side dense matrix
5919  , bool SO > // Storage order of the right-hand side dense matrix
5920 inline auto HybridMatrix<Type,M,N,true>::addAssign( const DenseMatrix<MT,SO>& rhs )
5921  -> DisableIf_t< VectorizedAddAssign_v<MT> >
5922 {
5923  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
5924 
5925  for( size_t j=0UL; j<n_; ++j )
5926  {
5927  if( IsDiagonal_v<MT> )
5928  {
5929  v_[j+j*MM] += (~rhs)(j,j);
5930  }
5931  else
5932  {
5933  const size_t ibegin( ( IsLower_v<MT> )
5934  ?( IsStrictlyLower_v<MT> ? j+1UL : j )
5935  :( 0UL ) );
5936  const size_t iend ( ( IsUpper_v<MT> )
5937  ?( IsStrictlyUpper_v<MT> ? j : j+1UL )
5938  :( m_ ) );
5939  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
5940 
5941  for( size_t i=ibegin; i<iend; ++i ) {
5942  v_[i+j*MM] += (~rhs)(i,j);
5943  }
5944  }
5945  }
5946 }
5948 //*************************************************************************************************
5949 
5950 
5951 //*************************************************************************************************
5963 template< typename Type // Data type of the matrix
5964  , size_t M // Number of rows
5965  , size_t N > // Number of columns
5966 template< typename MT // Type of the right-hand side dense matrix
5967  , bool SO > // Storage order of the right-hand side dense matrix
5968 inline auto HybridMatrix<Type,M,N,true>::addAssign( const DenseMatrix<MT,SO>& rhs )
5969  -> EnableIf_t< VectorizedAddAssign_v<MT> >
5970 {
5973 
5974  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
5975 
5976  constexpr bool remainder( !usePadding || !IsPadded_v<MT> );
5977 
5978  for( size_t j=0UL; j<n_; ++j )
5979  {
5980  const size_t ibegin( ( IsLower_v<MT> )
5981  ?( ( IsStrictlyLower_v<MT> ? j+1UL : j ) & size_t(-SIMDSIZE) )
5982  :( 0UL ) );
5983  const size_t iend ( ( IsUpper_v<MT> )
5984  ?( IsStrictlyUpper_v<MT> ? j : j+1UL )
5985  :( m_ ) );
5986  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
5987 
5988  const size_t ipos( ( remainder )?( iend & size_t(-SIMDSIZE) ):( iend ) );
5989  BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
5990 
5991  size_t i( ibegin );
5992 
5993  for( ; i<ipos; i+=SIMDSIZE ) {
5994  store( i, j, load(i,j) + (~rhs).load(i,j) );
5995  }
5996  for( ; remainder && i<iend; ++i ) {
5997  v_[i+j*MM] += (~rhs)(i,j);
5998  }
5999  }
6000 }
6002 //*************************************************************************************************
6003 
6004 
6005 //*************************************************************************************************
6017 template< typename Type // Data type of the matrix
6018  , size_t M // Number of rows
6019  , size_t N > // Number of columns
6020 template< typename MT > // Type of the right-hand side sparse matrix
6021 inline void HybridMatrix<Type,M,N,true>::addAssign( const SparseMatrix<MT,true>& rhs )
6022 {
6023  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
6024 
6025  for( size_t j=0UL; j<n_; ++j )
6026  for( auto element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
6027  v_[element->index()+j*MM] += element->value();
6028 }
6030 //*************************************************************************************************
6031 
6032 
6033 //*************************************************************************************************
6045 template< typename Type // Data type of the matrix
6046  , size_t M // Number of rows
6047  , size_t N > // Number of columns
6048 template< typename MT > // Type of the right-hand side sparse matrix
6049 inline void HybridMatrix<Type,M,N,true>::addAssign( const SparseMatrix<MT,false>& rhs )
6050 {
6052 
6053  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
6054 
6055  for( size_t i=0UL; i<m_; ++i )
6056  for( auto element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
6057  v_[i+element->index()*MM] += element->value();
6058 }
6060 //*************************************************************************************************
6061 
6062 
6063 //*************************************************************************************************
6075 template< typename Type // Data type of the matrix
6076  , size_t M // Number of rows
6077  , size_t N > // Number of columns
6078 template< typename MT // Type of the right-hand side dense matrix
6079  , bool SO > // Storage order of the right-hand side dense matrix
6080 inline auto HybridMatrix<Type,M,N,true>::subAssign( const DenseMatrix<MT,SO>& rhs )
6081  -> DisableIf_t< VectorizedSubAssign_v<MT> >
6082 {
6083  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
6084 
6085  for( size_t j=0UL; j<n_; ++j )
6086  {
6087  if( IsDiagonal_v<MT> )
6088  {
6089  v_[j+j*MM] -= (~rhs)(j,j);
6090  }
6091  else
6092  {
6093  const size_t ibegin( ( IsLower_v<MT> )
6094  ?( IsStrictlyLower_v<MT> ? j+1UL : j )
6095  :( 0UL ) );
6096  const size_t iend ( ( IsUpper_v<MT> )
6097  ?( IsStrictlyUpper_v<MT> ? j : j+1UL )
6098  :( m_ ) );
6099  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
6100 
6101  for( size_t i=ibegin; i<iend; ++i ) {
6102  v_[i+j*MM] -= (~rhs)(i,j);
6103  }
6104  }
6105  }
6106 }
6108 //*************************************************************************************************
6109 
6110 
6111 //*************************************************************************************************
6123 template< typename Type // Data type of the matrix
6124  , size_t M // Number of rows
6125  , size_t N > // Number of columns
6126 template< typename MT // Type of the right-hand side dense matrix
6127  , bool SO > // Storage order of the right-hand side dense matrix
6128 inline auto HybridMatrix<Type,M,N,true>::subAssign( const DenseMatrix<MT,SO>& rhs )
6129  -> EnableIf_t< VectorizedSubAssign_v<MT> >
6130 {
6133 
6134  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
6135 
6136  constexpr bool remainder( !usePadding || !IsPadded_v<MT> );
6137 
6138  for( size_t j=0UL; j<n_; ++j )
6139  {
6140  const size_t ibegin( ( IsLower_v<MT> )
6141  ?( ( IsStrictlyLower_v<MT> ? j+1UL : j ) & size_t(-SIMDSIZE) )
6142  :( 0UL ) );
6143  const size_t iend ( ( IsUpper_v<MT> )
6144  ?( IsStrictlyUpper_v<MT> ? j : j+1UL )
6145  :( m_ ) );
6146  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
6147 
6148  const size_t ipos( ( remainder )?( iend & size_t(-SIMDSIZE) ):( iend ) );
6149  BLAZE_INTERNAL_ASSERT( !remainder || ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
6150 
6151  size_t i( ibegin );
6152 
6153  for( ; i<ipos; i+=SIMDSIZE ) {
6154  store( i, j, load(i,j) - (~rhs).load(i,j) );
6155  }
6156  for( ; remainder && i<iend; ++i ) {
6157  v_[i+j*MM] -= (~rhs)(i,j);
6158  }
6159  }
6160 }
6162 //*************************************************************************************************
6163 
6164 
6165 //*************************************************************************************************
6177 template< typename Type // Data type of the matrix
6178  , size_t M // Number of rows
6179  , size_t N > // Number of columns
6180 template< typename MT > // Type of the right-hand side sparse matrix
6181 inline void HybridMatrix<Type,M,N,true>::subAssign( const SparseMatrix<MT,true>& rhs )
6182 {
6183  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
6184 
6185  for( size_t j=0UL; j<n_; ++j )
6186  for( auto element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
6187  v_[element->index()+j*MM] -= element->value();
6188 }
6190 //*************************************************************************************************
6191 
6192 
6193 //*************************************************************************************************
6205 template< typename Type // Data type of the matrix
6206  , size_t M // Number of rows
6207  , size_t N > // Number of columns
6208 template< typename MT > // Type of the right-hand side sparse matrix
6209 inline void HybridMatrix<Type,M,N,true>::subAssign( const SparseMatrix<MT,false>& rhs )
6210 {
6212 
6213  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
6214 
6215  for( size_t i=0UL; i<m_; ++i )
6216  for( auto element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
6217  v_[i+element->index()*MM] -= element->value();
6218 }
6220 //*************************************************************************************************
6221 
6222 
6223 //*************************************************************************************************
6235 template< typename Type // Data type of the matrix
6236  , size_t M // Number of rows
6237  , size_t N > // Number of columns
6238 template< typename MT // Type of the right-hand side dense matrix
6239  , bool SO > // Storage order of the right-hand side dense matrix
6240 inline auto HybridMatrix<Type,M,N,true>::schurAssign( const DenseMatrix<MT,SO>& rhs )
6241  -> DisableIf_t< VectorizedSchurAssign_v<MT> >
6242 {
6243  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
6244 
6245  for( size_t j=0UL; j<n_; ++j ) {
6246  for( size_t i=0UL; i<m_; ++i ) {
6247  v_[i+j*MM] *= (~rhs)(i,j);
6248  }
6249  }
6250 }
6252 //*************************************************************************************************
6253 
6254 
6255 //*************************************************************************************************
6267 template< typename Type // Data type of the matrix
6268  , size_t M // Number of rows
6269  , size_t N > // Number of columns
6270 template< typename MT // Type of the right-hand side dense matrix
6271  , bool SO > // Storage order of the right-hand side dense matrix
6272 inline auto HybridMatrix<Type,M,N,true>::schurAssign( const DenseMatrix<MT,SO>& rhs )
6273  -> EnableIf_t< VectorizedSchurAssign_v<MT> >
6274 {
6276 
6277  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
6278 
6279  constexpr bool remainder( !usePadding || !IsPadded_v<MT> );
6280 
6281  for( size_t j=0UL; j<n_; ++j )
6282  {
6283  const size_t ipos( ( remainder )?( m_ & size_t(-SIMDSIZE) ):( m_ ) );
6284  BLAZE_INTERNAL_ASSERT( !remainder || ( m_ - ( m_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
6285 
6286  size_t i( 0UL );
6287 
6288  for( ; i<ipos; i+=SIMDSIZE ) {
6289  store( i, j, load(i,j) * (~rhs).load(i,j) );
6290  }
6291  for( ; remainder && i<m_; ++i ) {
6292  v_[i+j*MM] *= (~rhs)(i,j);
6293  }
6294  }
6295 }
6297 //*************************************************************************************************
6298 
6299 
6300 //*************************************************************************************************
6312 template< typename Type // Data type of the matrix
6313  , size_t M // Number of rows
6314  , size_t N > // Number of columns
6315 template< typename MT > // Type of the right-hand side sparse matrix
6316 inline void HybridMatrix<Type,M,N,true>::schurAssign( const SparseMatrix<MT,true>& rhs )
6317 {
6318  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
6319 
6320  const HybridMatrix tmp( serial( *this ) );
6321 
6322  reset();
6323 
6324  for( size_t j=0UL; j<n_; ++j )
6325  for( auto element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
6326  v_[element->index()+j*MM] = tmp.v_[element->index()+j*MM] * element->value();
6327 }
6329 //*************************************************************************************************
6330 
6331 
6332 //*************************************************************************************************
6344 template< typename Type // Data type of the matrix
6345  , size_t M // Number of rows
6346  , size_t N > // Number of columns
6347 template< typename MT > // Type of the right-hand side sparse matrix
6348 inline void HybridMatrix<Type,M,N,true>::schurAssign( const SparseMatrix<MT,false>& rhs )
6349 {
6351 
6352  BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" );
6353 
6354  const HybridMatrix tmp( serial( *this ) );
6355 
6356  reset();
6357 
6358  for( size_t i=0UL; i<m_; ++i )
6359  for( auto element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
6360  v_[i+element->index()*MM] = tmp.v_[i+element->index()*MM] * element->value();
6361 }
6363 //*************************************************************************************************
6364 
6365 
6366 
6367 
6368 
6369 
6370 
6371 
6372 //=================================================================================================
6373 //
6374 // STATICMATRIX OPERATORS
6375 //
6376 //=================================================================================================
6377 
6378 //*************************************************************************************************
6381 template< typename Type, size_t M, size_t N, bool SO >
6382 void reset( HybridMatrix<Type,M,N,SO>& m );
6383 
6384 template< typename Type, size_t M, size_t N, bool SO >
6385 void reset( HybridMatrix<Type,M,N,SO>& m, size_t i );
6386 
6387 template< typename Type, size_t M, size_t N, bool SO >
6388 void clear( HybridMatrix<Type,M,N,SO>& m );
6389 
6390 template< bool RF, typename Type, size_t M, size_t N, bool SO >
6391 bool isDefault( const HybridMatrix<Type,M,N,SO>& m );
6392 
6393 template< typename Type, size_t M, size_t N, bool SO >
6394 bool isIntact( const HybridMatrix<Type,M,N,SO>& m ) noexcept;
6395 
6396 template< typename Type, size_t M, size_t N, bool SO >
6397 void swap( HybridMatrix<Type,M,N,SO>& a, HybridMatrix<Type,M,N,SO>& b ) noexcept;
6399 //*************************************************************************************************
6400 
6401 
6402 //*************************************************************************************************
6409 template< typename Type // Data type of the matrix
6410  , size_t M // Number of rows
6411  , size_t N // Number of columns
6412  , bool SO > // Storage order
6414 {
6415  m.reset();
6416 }
6417 //*************************************************************************************************
6418 
6419 
6420 //*************************************************************************************************
6433 template< typename Type // Data type of the matrix
6434  , size_t M // Number of rows
6435  , size_t N // Number of columns
6436  , bool SO > // Storage order
6437 inline void reset( HybridMatrix<Type,M,N,SO>& m, size_t i )
6438 {
6439  m.reset( i );
6440 }
6441 //*************************************************************************************************
6442 
6443 
6444 //*************************************************************************************************
6451 template< typename Type // Data type of the matrix
6452  , size_t M // Number of rows
6453  , size_t N // Number of columns
6454  , bool SO > // Storage order
6456 {
6457  m.clear();
6458 }
6459 //*************************************************************************************************
6460 
6461 
6462 //*************************************************************************************************
6487 template< bool RF // Relaxation flag
6488  , typename Type // Data type of the matrix
6489  , size_t M // Number of rows
6490  , size_t N // Number of columns
6491  , bool SO > // Storage order
6492 inline bool isDefault( const HybridMatrix<Type,M,N,SO>& m )
6493 {
6494  return ( m.rows() == 0UL && m.columns() == 0UL );
6495 }
6496 //*************************************************************************************************
6497 
6498 
6499 //*************************************************************************************************
6517 template< typename Type // Data type of the matrix
6518  , size_t M // Number of rows
6519  , size_t N // Number of columns
6520  , bool SO > // Storage order
6521 inline bool isIntact( const HybridMatrix<Type,M,N,SO>& m ) noexcept
6522 {
6523  return m.isIntact();
6524 }
6525 //*************************************************************************************************
6526 
6527 
6528 //*************************************************************************************************
6536 template< typename Type // Data type of the matrix
6537  , size_t M // Number of rows
6538  , size_t N // Number of columns
6539  , bool SO > // Storage order
6541 {
6542  a.swap( b );
6543 }
6544 //*************************************************************************************************
6545 
6546 
6547 
6548 
6549 //=================================================================================================
6550 //
6551 // MAXSIZE SPECIALIZATIONS
6552 //
6553 //=================================================================================================
6554 
6555 //*************************************************************************************************
6557 template< typename T, size_t M, size_t N, bool SO >
6558 struct MaxSize< HybridMatrix<T,M,N,SO>, 0UL >
6559  : public Ptrdiff_t<M>
6560 {};
6561 
6562 template< typename T, size_t M, size_t N, bool SO >
6563 struct MaxSize< HybridMatrix<T,M,N,SO>, 1UL >
6564  : public Ptrdiff_t<N>
6565 {};
6567 //*************************************************************************************************
6568 
6569 
6570 
6571 
6572 //=================================================================================================
6573 //
6574 // HASCONSTDATAACCESS SPECIALIZATIONS
6575 //
6576 //=================================================================================================
6577 
6578 //*************************************************************************************************
6580 template< typename T, size_t M, size_t N, bool SO >
6581 struct HasConstDataAccess< HybridMatrix<T,M,N,SO> >
6582  : public TrueType
6583 {};
6585 //*************************************************************************************************
6586 
6587 
6588 
6589 
6590 //=================================================================================================
6591 //
6592 // HASMUTABLEDATAACCESS SPECIALIZATIONS
6593 //
6594 //=================================================================================================
6595 
6596 //*************************************************************************************************
6598 template< typename T, size_t M, size_t N, bool SO >
6599 struct HasMutableDataAccess< HybridMatrix<T,M,N,SO> >
6600  : public TrueType
6601 {};
6603 //*************************************************************************************************
6604 
6605 
6606 
6607 
6608 //=================================================================================================
6609 //
6610 // ISALIGNED SPECIALIZATIONS
6611 //
6612 //=================================================================================================
6613 
6614 //*************************************************************************************************
6616 template< typename T, size_t M, size_t N, bool SO >
6617 struct IsAligned< HybridMatrix<T,M,N,SO> >
6618  : public BoolConstant< HybridMatrix<T,M,N,SO>::isAligned() >
6619 {};
6621 //*************************************************************************************************
6622 
6623 
6624 
6625 
6626 //=================================================================================================
6627 //
6628 // ISCONTIGUOUS SPECIALIZATIONS
6629 //
6630 //=================================================================================================
6631 
6632 //*************************************************************************************************
6634 template< typename T, size_t M, size_t N, bool SO >
6635 struct IsContiguous< HybridMatrix<T,M,N,SO> >
6636  : public TrueType
6637 {};
6639 //*************************************************************************************************
6640 
6641 
6642 
6643 
6644 //=================================================================================================
6645 //
6646 // ISPADDED SPECIALIZATIONS
6647 //
6648 //=================================================================================================
6649 
6650 //*************************************************************************************************
6652 template< typename T, size_t M, size_t N, bool SO >
6653 struct IsPadded< HybridMatrix<T,M,N,SO> >
6654  : public BoolConstant<usePadding>
6655 {};
6657 //*************************************************************************************************
6658 
6659 
6660 
6661 
6662 //=================================================================================================
6663 //
6664 // ISRESIZABLE SPECIALIZATIONS
6665 //
6666 //=================================================================================================
6667 
6668 //*************************************************************************************************
6670 template< typename T, size_t M, size_t N, bool SO >
6671 struct IsResizable< HybridMatrix<T,M,N,SO> >
6672  : public TrueType
6673 {};
6675 //*************************************************************************************************
6676 
6677 
6678 
6679 
6680 //=================================================================================================
6681 //
6682 // ADDTRAIT SPECIALIZATIONS
6683 //
6684 //=================================================================================================
6685 
6686 //*************************************************************************************************
6688 template< typename T1, typename T2 >
6689 struct AddTraitEval2< T1, T2
6690  , EnableIf_t< IsMatrix_v<T1> &&
6691  IsMatrix_v<T2> &&
6692  ( Size_v<T1,0UL> == DefaultSize_v ) &&
6693  ( Size_v<T2,0UL> == DefaultSize_v ) &&
6694  ( Size_v<T1,1UL> == DefaultSize_v ) &&
6695  ( Size_v<T2,1UL> == DefaultSize_v ) &&
6696  ( MaxSize_v<T1,0UL> != DefaultMaxSize_v ||
6697  MaxSize_v<T2,0UL> != DefaultMaxSize_v ) &&
6698  ( MaxSize_v<T1,1UL> != DefaultMaxSize_v ||
6699  MaxSize_v<T2,1UL> != DefaultMaxSize_v ) > >
6700 {
6701  using ET1 = ElementType_t<T1>;
6702  using ET2 = ElementType_t<T2>;
6703 
6704  static constexpr size_t M = min( size_t( MaxSize_v<T1,0UL> ), size_t( MaxSize_v<T2,0UL> ) );
6705  static constexpr size_t N = min( size_t( MaxSize_v<T1,1UL> ), size_t( MaxSize_v<T2,1UL> ) );
6706 
6707  static constexpr bool SO1 = StorageOrder_v<T1>;
6708  static constexpr bool SO2 = StorageOrder_v<T2>;
6709 
6710  static constexpr bool SO = ( IsDenseMatrix_v<T1> && IsDenseMatrix_v<T2>
6711  ? ( IsSymmetric_v<T1> ^ IsSymmetric_v<T2>
6712  ? ( IsSymmetric_v<T1>
6713  ? SO2
6714  : SO1 )
6715  : SO1 && SO2 )
6716  : ( IsDenseMatrix_v<T1>
6717  ? SO1
6718  : SO2 ) );
6719 
6720  using Type = HybridMatrix< AddTrait_t<ET1,ET2>, M, N, SO >;
6721 };
6723 //*************************************************************************************************
6724 
6725 
6726 
6727 
6728 //=================================================================================================
6729 //
6730 // SUBTRAIT SPECIALIZATIONS
6731 //
6732 //=================================================================================================
6733 
6734 //*************************************************************************************************
6736 template< typename T1, typename T2 >
6737 struct SubTraitEval2< T1, T2
6738  , EnableIf_t< IsMatrix_v<T1> &&
6739  IsMatrix_v<T2> &&
6740  ( Size_v<T1,0UL> == DefaultSize_v ) &&
6741  ( Size_v<T2,0UL> == DefaultSize_v ) &&
6742  ( Size_v<T1,1UL> == DefaultSize_v ) &&
6743  ( Size_v<T2,1UL> == DefaultSize_v ) &&
6744  ( MaxSize_v<T1,0UL> != DefaultMaxSize_v ||
6745  MaxSize_v<T2,0UL> != DefaultMaxSize_v ) &&
6746  ( MaxSize_v<T1,1UL> != DefaultMaxSize_v ||
6747  MaxSize_v<T2,1UL> != DefaultMaxSize_v ) > >
6748 {
6749  using ET1 = ElementType_t<T1>;
6750  using ET2 = ElementType_t<T2>;
6751 
6752  static constexpr size_t M = min( size_t( MaxSize_v<T1,0UL> ), size_t( MaxSize_v<T2,0UL> ) );
6753  static constexpr size_t N = min( size_t( MaxSize_v<T1,1UL> ), size_t( MaxSize_v<T2,1UL> ) );
6754 
6755  static constexpr bool SO1 = StorageOrder_v<T1>;
6756  static constexpr bool SO2 = StorageOrder_v<T2>;
6757 
6758  static constexpr bool SO = ( IsDenseMatrix_v<T1> && IsDenseMatrix_v<T2>
6759  ? ( IsSymmetric_v<T1> ^ IsSymmetric_v<T2>
6760  ? ( IsSymmetric_v<T1>
6761  ? SO2
6762  : SO1 )
6763  : SO1 && SO2 )
6764  : ( IsDenseMatrix_v<T1>
6765  ? SO1
6766  : SO2 ) );
6767 
6768  using Type = HybridMatrix< SubTrait_t<ET1,ET2>, M, N, SO >;
6769 };
6771 //*************************************************************************************************
6772 
6773 
6774 
6775 
6776 //=================================================================================================
6777 //
6778 // SCHURTRAIT SPECIALIZATIONS
6779 //
6780 //=================================================================================================
6781 
6782 //*************************************************************************************************
6784 template< typename T1, typename T2 >
6785 struct SchurTraitEval2< T1, T2
6786  , EnableIf_t< IsDenseMatrix_v<T1> &&
6787  IsDenseMatrix_v<T2> &&
6788  ( Size_v<T1,0UL> == DefaultSize_v ) &&
6789  ( Size_v<T2,0UL> == DefaultSize_v ) &&
6790  ( Size_v<T1,1UL> == DefaultSize_v ) &&
6791  ( Size_v<T2,1UL> == DefaultSize_v ) &&
6792  ( MaxSize_v<T1,0UL> != DefaultMaxSize_v ||
6793  MaxSize_v<T2,0UL> != DefaultMaxSize_v ) &&
6794  ( MaxSize_v<T1,1UL> != DefaultMaxSize_v ||
6795  MaxSize_v<T2,1UL> != DefaultMaxSize_v ) > >
6796 {
6797  using ET1 = ElementType_t<T1>;
6798  using ET2 = ElementType_t<T2>;
6799 
6800  static constexpr size_t M = min( size_t( MaxSize_v<T1,0UL> ), size_t( MaxSize_v<T2,0UL> ) );
6801  static constexpr size_t N = min( size_t( MaxSize_v<T1,1UL> ), size_t( MaxSize_v<T2,1UL> ) );
6802 
6803  static constexpr bool SO1 = StorageOrder_v<T1>;
6804  static constexpr bool SO2 = StorageOrder_v<T2>;
6805 
6806  static constexpr bool SO = ( IsSymmetric_v<T1> ^ IsSymmetric_v<T2>
6807  ? ( IsSymmetric_v<T1>
6808  ? SO2
6809  : SO1 )
6810  : SO1 && SO2 );
6811 
6812  using Type = HybridMatrix< MultTrait_t<ET1,ET2>, M, N, SO >;
6813 };
6815 //*************************************************************************************************
6816 
6817 
6818 
6819 
6820 //=================================================================================================
6821 //
6822 // MULTTRAIT SPECIALIZATIONS
6823 //
6824 //=================================================================================================
6825 
6826 //*************************************************************************************************
6828 template< typename T1, typename T2 >
6829 struct MultTraitEval2< T1, T2
6830  , EnableIf_t< IsMatrix_v<T1> &&
6831  IsNumeric_v<T2> &&
6832  ( Size_v<T1,0UL> == DefaultSize_v ) &&
6833  ( Size_v<T1,1UL> == DefaultSize_v ) &&
6834  ( MaxSize_v<T1,0UL> != DefaultMaxSize_v ) &&
6835  ( MaxSize_v<T1,1UL> != DefaultMaxSize_v ) > >
6836 {
6837  using ET1 = ElementType_t<T1>;
6838 
6839  static constexpr size_t M = MaxSize_v<T1,0UL>;
6840  static constexpr size_t N = MaxSize_v<T1,1UL>;
6841 
6842  using Type = HybridMatrix< MultTrait_t<ET1,T2>, M, N, StorageOrder_v<T1> >;
6843 };
6844 
6845 template< typename T1, typename T2 >
6846 struct MultTraitEval2< T1, T2
6847  , EnableIf_t< IsNumeric_v<T1> &&
6848  IsMatrix_v<T2> &&
6849  ( Size_v<T2,0UL> == DefaultSize_v ) &&
6850  ( Size_v<T2,1UL> == DefaultSize_v ) &&
6851  ( MaxSize_v<T2,0UL> != DefaultMaxSize_v ) &&
6852  ( MaxSize_v<T2,1UL> != DefaultMaxSize_v ) > >
6853 {
6854  using ET2 = ElementType_t<T2>;
6855 
6856  static constexpr size_t M = MaxSize_v<T2,0UL>;
6857  static constexpr size_t N = MaxSize_v<T2,1UL>;
6858 
6859  using Type = HybridMatrix< MultTrait_t<T1,ET2>, M, N, StorageOrder_v<T2> >;
6860 };
6861 
6862 template< typename T1, typename T2 >
6863 struct MultTraitEval2< T1, T2
6864  , EnableIf_t< IsColumnVector_v<T1> &&
6865  IsRowVector_v<T2> &&
6866  ( ( Size_v<T1,0UL> == DefaultSize_v ) ||
6867  ( Size_v<T2,0UL> == DefaultSize_v ) ) &&
6868  ( MaxSize_v<T1,0UL> != DefaultMaxSize_v ) &&
6869  ( MaxSize_v<T2,0UL> != DefaultMaxSize_v ) > >
6870 {
6871  using ET1 = ElementType_t<T1>;
6872  using ET2 = ElementType_t<T2>;
6873 
6874  static constexpr size_t M = MaxSize_v<T1,0UL>;
6875  static constexpr size_t N = MaxSize_v<T2,0UL>;
6876 
6877  using Type = HybridMatrix< MultTrait_t<ET1,ET2>, M, N, false >;
6878 };
6879 
6880 template< typename T1, typename T2 >
6881 struct MultTraitEval2< T1, T2
6882  , EnableIf_t< IsMatrix_v<T1> &&
6883  IsMatrix_v<T2> &&
6884  ( ( Size_v<T1,0UL> == DefaultSize_v &&
6885  ( !IsSquare_v<T1> || Size_v<T2,0UL> == DefaultSize_v ) ) ||
6886  ( Size_v<T2,1UL> == DefaultSize_v &&
6887  ( !IsSquare_v<T2> || Size_v<T1,1UL> == DefaultSize_v ) ) ) &&
6888  ( MaxSize_v<T1,0UL> != DefaultMaxSize_v ||
6889  ( IsSquare_v<T1> && MaxSize_v<T2,0UL> != DefaultMaxSize_v ) ) &&
6890  ( MaxSize_v<T2,1UL> != DefaultMaxSize_v ||
6891  ( IsSquare_v<T2> && MaxSize_v<T1,1UL> != DefaultMaxSize_v ) ) > >
6892 {
6893  using ET1 = ElementType_t<T1>;
6894  using ET2 = ElementType_t<T2>;
6895 
6896  static constexpr size_t M = ( MaxSize_v<T1,0UL> != DefaultMaxSize_v ? MaxSize_v<T1,0UL> : MaxSize_v<T2,0UL> );
6897  static constexpr size_t N = ( MaxSize_v<T2,1UL> != DefaultMaxSize_v ? MaxSize_v<T2,1UL> : MaxSize_v<T1,1UL> );
6898 
6899  static constexpr bool SO = ( IsSparseMatrix_v<T1> ? StorageOrder_v<T2> : StorageOrder_v<T1> );
6900 
6901  using Type = HybridMatrix< MultTrait_t<ET1,ET2>, M, N, SO >;
6902 };
6904 //*************************************************************************************************
6905 
6906 
6907 
6908 
6909 //=================================================================================================
6910 //
6911 // KRONTRAIT SPECIALIZATIONS
6912 //
6913 //=================================================================================================
6914 
6915 //*************************************************************************************************
6917 template< typename T1, typename T2 >
6918 struct KronTraitEval2< T1, T2
6919  , EnableIf_t< IsDenseMatrix_v<T1> &&
6920  IsDenseMatrix_v<T2> &&
6921  ( ( Size_v<T1,0UL> == DefaultSize_v ) ||
6922  ( Size_v<T2,0UL> == DefaultSize_v ) ||
6923  ( Size_v<T1,1UL> == DefaultSize_v ) ||
6924  ( Size_v<T2,1UL> == DefaultSize_v ) ) &&
6925  ( MaxSize_v<T1,0UL> != DefaultMaxSize_v ) &&
6926  ( MaxSize_v<T2,0UL> != DefaultMaxSize_v ) &&
6927  ( MaxSize_v<T1,1UL> != DefaultMaxSize_v ) &&
6928  ( MaxSize_v<T2,1UL> != DefaultMaxSize_v ) > >
6929 {
6930  using ET1 = ElementType_t<T1>;
6931  using ET2 = ElementType_t<T2>;
6932 
6933  static constexpr size_t M = MaxSize_v<T1,0UL> * MaxSize_v<T2,0UL>;
6934  static constexpr size_t N = MaxSize_v<T1,1UL> * MaxSize_v<T2,1UL>;
6935 
6936  using Type = HybridMatrix< MultTrait_t<ET1,ET2>, M, N, StorageOrder_v<T2> >;
6937 };
6939 //*************************************************************************************************
6940 
6941 
6942 
6943 
6944 //=================================================================================================
6945 //
6946 // DIVTRAIT SPECIALIZATIONS
6947 //
6948 //=================================================================================================
6949 
6950 //*************************************************************************************************
6952 template< typename T1, typename T2 >
6953 struct DivTraitEval2< T1, T2
6954  , EnableIf_t< IsMatrix_v<T1> &&
6955  IsNumeric_v<T2> &&
6956  ( Size_v<T1,0UL> == DefaultSize_v ) &&
6957  ( Size_v<T1,1UL> == DefaultSize_v ) &&
6958  ( MaxSize_v<T1,0UL> != DefaultMaxSize_v ) &&
6959  ( MaxSize_v<T1,1UL> != DefaultMaxSize_v ) > >
6960 {
6961  using ET1 = ElementType_t<T1>;
6962 
6963  static constexpr size_t M = MaxSize_v<T1,0UL>;
6964  static constexpr size_t N = MaxSize_v<T1,1UL>;
6965 
6966  using Type = HybridMatrix< DivTrait_t<ET1,T2>, M, N, StorageOrder_v<T1> >;
6967 };
6969 //*************************************************************************************************
6970 
6971 
6972 
6973 
6974 //=================================================================================================
6975 //
6976 // MAPTRAIT SPECIALIZATIONS
6977 //
6978 //=================================================================================================
6979 
6980 //*************************************************************************************************
6982 template< typename T, typename OP >
6983 struct UnaryMapTraitEval2< T, OP
6984  , EnableIf_t< IsMatrix_v<T> &&
6985  ( Size_v<T,0UL> == DefaultSize_v ||
6986  Size_v<T,1UL> == DefaultSize_v ) &&
6987  MaxSize_v<T,0UL> != DefaultMaxSize_v &&
6988  MaxSize_v<T,1UL> != DefaultMaxSize_v > >
6989 {
6990  using ET = ElementType_t<T>;
6991 
6992  using Type = HybridMatrix< MapTrait_t<ET,OP>, MaxSize_v<T,0UL>, MaxSize_v<T,1UL>, StorageOrder_v<T> >;
6993 };
6995 //*************************************************************************************************
6996 
6997 
6998 //*************************************************************************************************
7000 template< typename T1, typename T2, typename OP >
7001 struct BinaryMapTraitEval2< T1, T2, OP
7002  , EnableIf_t< IsMatrix_v<T1> &&
7003  IsMatrix_v<T2> &&
7004  ( Size_v<T1,0UL> == DefaultSize_v ) &&
7005  ( Size_v<T2,0UL> == DefaultSize_v ) &&
7006  ( Size_v<T1,1UL> == DefaultSize_v ) &&
7007  ( Size_v<T2,1UL> == DefaultSize_v ) &&
7008  ( MaxSize_v<T1,0UL> != DefaultMaxSize_v ||
7009  MaxSize_v<T2,0UL> != DefaultMaxSize_v ) &&
7010  ( MaxSize_v<T1,1UL> != DefaultMaxSize_v ||
7011  MaxSize_v<T2,1UL> != DefaultMaxSize_v ) > >
7012 {
7013  using ET1 = ElementType_t<T1>;
7014  using ET2 = ElementType_t<T2>;
7015 
7016  static constexpr size_t M = min( size_t( MaxSize_v<T1,0UL> ), size_t( MaxSize_v<T2,0UL> ) );
7017  static constexpr size_t N = min( size_t( MaxSize_v<T1,1UL> ), size_t( MaxSize_v<T2,1UL> ) );
7018 
7019  static constexpr bool SO1 = StorageOrder_v<T1>;
7020  static constexpr bool SO2 = StorageOrder_v<T2>;
7021 
7022  static constexpr bool SO = ( IsDenseMatrix_v<T1> && IsDenseMatrix_v<T2>
7023  ? ( IsSymmetric_v<T1> ^ IsSymmetric_v<T2>
7024  ? ( IsSymmetric_v<T1>
7025  ? SO2
7026  : SO1 )
7027  : SO1 && SO2 )
7028  : ( IsDenseMatrix_v<T1>
7029  ? SO1
7030  : SO2 ) );
7031 
7032  using Type = HybridMatrix< MapTrait_t<ET1,ET2,OP>, M, N, SO >;
7033 };
7035 //*************************************************************************************************
7036 
7037 
7038 
7039 
7040 //=================================================================================================
7041 //
7042 // EXPANDTRAIT SPECIALIZATIONS
7043 //
7044 //=================================================================================================
7045 
7046 //*************************************************************************************************
7048 template< typename T // Type to be expanded
7049  , size_t E > // Compile time expansion
7050 struct ExpandTraitEval2< T, E
7051  , EnableIf_t< IsDenseVector_v<T> &&
7052  ( E != inf ) &&
7053  ( Size_v<T,0UL> == DefaultSize_v ) &&
7054  ( MaxSize_v<T,0UL> != DefaultMaxSize_v ) > >
7055 {
7056  static constexpr size_t M = ( IsColumnVector_v<T> ? MaxSize_v<T,0UL> : E );
7057  static constexpr size_t N = ( IsColumnVector_v<T> ? E : MaxSize_v<T,0UL> );
7058 
7059  static constexpr bool TF = ( IsColumnVector_v<T> ? columnMajor : rowMajor );
7060 
7061  using Type = HybridMatrix< ElementType_t<T>, M, N, TF >;
7062 };
7064 //*************************************************************************************************
7065 
7066 
7067 
7068 
7069 //=================================================================================================
7070 //
7071 // HIGHTYPE SPECIALIZATIONS
7072 //
7073 //=================================================================================================
7074 
7075 //*************************************************************************************************
7077 template< typename T1, size_t M, size_t N, bool SO, typename T2 >
7078 struct HighType< HybridMatrix<T1,M,N,SO>, HybridMatrix<T2,M,N,SO> >
7079 {
7080  using Type = HybridMatrix< typename HighType<T1,T2>::Type, M, N, SO >;
7081 };
7083 //*************************************************************************************************
7084 
7085 
7086 
7087 
7088 //=================================================================================================
7089 //
7090 // LOWTYPE SPECIALIZATIONS
7091 //
7092 //=================================================================================================
7093 
7094 //*************************************************************************************************
7096 template< typename T1, size_t M, size_t N, bool SO, typename T2 >
7097 struct LowType< HybridMatrix<T1,M,N,SO>, HybridMatrix<T2,M,N,SO> >
7098 {
7099  using Type = HybridMatrix< typename LowType<T1,T2>::Type, M, N, SO >;
7100 };
7102 //*************************************************************************************************
7103 
7104 
7105 
7106 
7107 //=================================================================================================
7108 //
7109 // SUBMATRIXTRAIT SPECIALIZATIONS
7110 //
7111 //=================================================================================================
7112 
7113 //*************************************************************************************************
7115 template< typename MT >
7116 struct SubmatrixTraitEval2< MT, inf, inf, inf, inf
7117  , EnableIf_t< IsDenseMatrix_v<MT> &&
7118  ( ( Size_v<MT,0UL> != DefaultSize_v &&
7119  Size_v<MT,1UL> != DefaultSize_v ) ||
7120  ( MaxSize_v<MT,0UL> != DefaultMaxSize_v &&
7121  MaxSize_v<MT,1UL> != DefaultMaxSize_v ) ) > >
7122 {
7123  static constexpr size_t M = max( Size_v<MT,0UL>, MaxSize_v<MT,0UL> );
7124  static constexpr size_t N = max( Size_v<MT,1UL>, MaxSize_v<MT,1UL> );
7125 
7126  using Type = HybridMatrix< RemoveConst_t< ElementType_t<MT> >, M, N, StorageOrder_v<MT> >;
7127 };
7129 //*************************************************************************************************
7130 
7131 
7132 
7133 
7134 //=================================================================================================
7135 //
7136 // ROWSTRAIT SPECIALIZATIONS
7137 //
7138 //=================================================================================================
7139 
7140 //*************************************************************************************************
7142 template< typename MT, size_t M >
7143 struct RowsTraitEval2< MT, M
7144  , EnableIf_t< M != 0UL &&
7145  IsDenseMatrix_v<MT> &&
7146  Size_v<MT,1UL> == DefaultSize_v &&
7147  MaxSize_v<MT,1UL> != DefaultMaxSize_v > >
7148 {
7149  using Type = HybridMatrix< RemoveConst_t< ElementType_t<MT> >, M, MaxSize_v<MT,1UL>, false >;
7150 };
7152 //*************************************************************************************************
7153 
7154 
7155 
7156 
7157 //=================================================================================================
7158 //
7159 // COLUMNSTRAIT SPECIALIZATIONS
7160 //
7161 //=================================================================================================
7162 
7163 //*************************************************************************************************
7165 template< typename MT, size_t N >
7166 struct ColumnsTraitEval2< MT, N
7167  , EnableIf_t< N != 0UL &&
7168  IsDenseMatrix_v<MT> &&
7169  Size_v<MT,0UL> == DefaultSize_v &&
7170  MaxSize_v<MT,0UL> != DefaultMaxSize_v > >
7171 {
7172  using Type = HybridMatrix< RemoveConst_t< ElementType_t<MT> >, MaxSize_v<MT,0UL>, N, true >;
7173 };
7175 //*************************************************************************************************
7176 
7177 } // namespace blaze
7178 
7179 #endif
const This & CompositeType
Data type for composite expression templates.
Definition: HybridMatrix.h:253
Constraint on the data type.
#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
#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
Header file for auxiliary alias declarations.
Headerfile for the generic min algorithm.
Header file for the Schur product trait.
constexpr bool IsMatrix_v
Auxiliary variable template for the IsMatrix type trait.The IsMatrix_v variable template provides a c...
Definition: IsMatrix.h:138
Header file for the nextMultiple shim.
#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
DenseMatrix< This, SO > BaseType
Base type of this HybridMatrix instance.
Definition: HybridMatrix.h:246
Header file for the AlignmentOf type trait.
ConstIterator cend(size_t i) const noexcept
Returns an iterator just past the last element of row/column i.
Definition: HybridMatrix.h:1307
Header file for the subtraction trait.
Header file for basic type definitions.
static constexpr size_t SIMDSIZE
The number of elements packed within a single SIMD element.
Definition: HybridMatrix.h:234
IntegralConstant< ptrdiff_t, N > Ptrdiff_t
Compile time integral constant wrapper for ptrdiff_t.The Ptrdiff_t alias template represents an integ...
Definition: IntegralConstant.h:237
typename T::ResultType ResultType_t
Alias declaration for nested ResultType type definitions.The ResultType_t alias declaration provides ...
Definition: Aliases.h:390
constexpr bool IsSIMDCombinable_v
Auxiliary variable template for the IsSIMDCombinable type trait.The IsSIMDCombinable_v variable templ...
Definition: IsSIMDCombinable.h:137
Header file for the IsSparseMatrix type trait.
Header file for the serial shim.
Header file for the IsDiagonal type trait.
Header file for the IsSame and IsStrictlySame type traits.
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
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
Iterator begin(size_t i) noexcept
Returns an iterator to the first element of row/column i.
Definition: HybridMatrix.h:1187
Header file for the IsColumnMajorMatrix type trait.
Reference at(size_t i, size_t j)
Checked access to the matrix elements.
Definition: HybridMatrix.h:1039
void reset(const DiagonalProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: DiagonalProxy.h:595
HybridMatrix< Type, NewM, NewN, SO > Other
The type of the other HybridMatrix.
Definition: HybridMatrix.h:279
Header file for the IsRowVector type trait.
typename SIMDTrait< T >::Type SIMDTrait_t
Auxiliary alias declaration for the SIMDTrait class template.The SIMDTrait_t alias declaration provid...
Definition: SIMDTrait.h:315
void ctranspose(Matrix< MT, SO > &matrix)
In-place conjugate transpose of the given matrix.
Definition: Matrix.h:851
Header file for the MAYBE_UNUSED function template.
Iterator end(size_t i) noexcept
Returns an iterator just past the last element of row/column i.
Definition: HybridMatrix.h:1259
#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
DenseIterator< Type, align > Iterator
Iterator over non-constant elements.
Definition: HybridMatrix.h:260
BLAZE_ALWAYS_INLINE void cswap(T &a, T &b) noexcept(IsNumeric_v< T >)
Swapping two conjugated values/objects.
Definition: Conjugate.h:195
This ResultType
Result type for expression template evaluations.
Definition: HybridMatrix.h:247
size_t rows() const noexcept
Returns the current number of rows of the matrix.
Definition: HybridMatrix.h:1665
constexpr bool HasSIMDAdd_v
Auxiliary variable template for the HasSIMDAdd type trait.The HasSIMDAdd_v variable template provides...
Definition: HasSIMDAdd.h:187
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 all forward declarations of the math module.
Header file for memory allocation and deallocation functionality.
BLAZE_ALWAYS_INLINE EnableIf_t< IsIntegral_v< T1 > &&HasSize_v< T1, 1UL > > storeu(T1 *address, const SIMDi8< T2 > &value) noexcept
Unaligned store of a vector of 1-byte integral values.
Definition: Storeu.h:75
Header file for the extended initializer_list functionality.
System settings for performance optimizations.
ConstIterator cbegin(size_t i) const noexcept
Returns an iterator to the first element of row/column i.
Definition: HybridMatrix.h:1235
AlignedStorage v_
The statically allocated matrix elements.
Definition: HybridMatrix.h:535
Header file for the MaxSize type trait.
constexpr size_t columns(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of columns of the matrix.
Definition: Matrix.h:514
constexpr bool rowMajor
Storage order flag for row-major matrices.
Definition: StorageOrder.h:71
Type ElementType
Type of the matrix elements.
Definition: HybridMatrix.h:250
Base class for dense matrices.The DenseMatrix class is a base class for all dense matrix classes....
Definition: DenseMatrix.h:81
Base class for sparse matrices.The SparseMatrix class is a base class for all sparse matrix classes....
Definition: Forward.h:145
typename T::ElementType ElementType_t
Alias declaration for nested ElementType type definitions.The ElementType_t alias declaration provide...
Definition: Aliases.h:170
Constraint on the data type.
constexpr bool IsDenseMatrix_v
Auxiliary variable template for the IsDenseMatrix type trait.The IsDenseMatrix_v variable template pr...
Definition: IsDenseMatrix.h:138
HybridMatrix< NewType, M, N, SO > Other
The type of the other HybridMatrix.
Definition: HybridMatrix.h:269
Header file for the IsMatrix type trait.
SIMDTrait_t< ElementType > SIMDType
SIMD type of the matrix elements.
Definition: HybridMatrix.h:251
Header file for the SparseMatrix base class.
Header file for the IsSquare type trait.
void resize(size_t m, size_t n, bool preserve=true)
Changing the size of the matrix.
Definition: HybridMatrix.h:1907
size_t nonZeros() const
Returns the total number of non-zero elements in the matrix.
Definition: HybridMatrix.h:1758
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
constexpr bool columnMajor
Storage order flag for column-major matrices.
Definition: StorageOrder.h:99
Headerfile for the generic max algorithm.
constexpr bool IsRowMajorMatrix_v
Auxiliary variable template for the IsRowMajorMatrix type trait.The IsRowMajorMatrix_v variable templ...
Definition: IsRowMajorMatrix.h:145
Header file for the DisableIf class template.
constexpr bool IsColumnMajorMatrix_v
Auxiliary variable template for the IsColumnMajorMatrix type trait.The IsColumnMajorMatrix_v variable...
Definition: IsColumnMajorMatrix.h:145
Header file for the LowType type trait.
Header file for the multiplication trait.
Header file for the IsStrictlyUpper type trait.
constexpr ptrdiff_t DefaultMaxSize_v
Default size of the MaxSize type trait.
Definition: MaxSize.h:72
Header file for the IsSymmetric type trait.
static constexpr bool align
Compilation switch for the choice of alignment.
Definition: HybridMatrix.h:240
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
decltype(auto) ctrans(const DenseMatrix< MT, SO > &dm)
Returns the conjugate transpose matrix of dm.
Definition: DMatMapExpr.h:1361
HybridMatrix & operator=(const Type &set)
Homogenous assignment to all matrix elements.
Definition: HybridMatrix.h:1333
Compile time assertion.
BLAZE_ALWAYS_INLINE void storeu(size_t i, size_t j, const SIMDType &value) noexcept
Unaligned store of a SIMD element of the matrix.
Definition: HybridMatrix.h:2631
AlignedArray< Type, M *NN, Alignment > AlignedStorage
Type of the aligned storage.
Definition: HybridMatrix.h:529
BLAZE_ALWAYS_INLINE void store(size_t i, size_t j, const SIMDType &value) noexcept
Store of a SIMD element of the matrix.
Definition: HybridMatrix.h:2562
#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
constexpr bool HasSIMDSub_v
Auxiliary variable template for the HasSIMDSub type trait.The HasSIMDSub_v variable template provides...
Definition: HasSIMDSub.h:187
Header file for the expand trait.
decltype(auto) min(const DenseMatrix< MT1, SO1 > &lhs, const DenseMatrix< MT2, SO2 > &rhs)
Computes the componentwise minimum of the dense matrices lhs and rhs.
Definition: DMatDMatMapExpr.h:1162
#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
Type * Pointer
Pointer to a non-constant matrix value.
Definition: HybridMatrix.h:257
Header file for the HasSIMDAdd type trait.
Header file for the DenseMatrix base class.
Header file for the DenseIterator class template.
decltype(auto) inv(const DenseMatrix< MT, SO > &dm)
Calculation of the inverse of the given dense matrix.
Definition: DMatInvExpr.h:423
constexpr bool IsNumeric_v
Auxiliary variable template for the IsNumeric type trait.The IsNumeric_v variable template provides a...
Definition: IsNumeric.h:143
static constexpr size_t capacity() noexcept
Returns the maximum capacity of the matrix.
Definition: HybridMatrix.h:1716
Header file for all SIMD functionality.
HybridMatrix()
The default constructor for HybridMatrix.
Definition: HybridMatrix.h:581
Constraint on the data type.
#define BLAZE_CONSTRAINT_MUST_NOT_BE_DIAGONAL_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is a diagonal matrix type,...
Definition: Diagonal.h:79
Reference operator()(size_t i, size_t j) noexcept
2D-access to the matrix elements.
Definition: HybridMatrix.h:990
auto schurAssign(const DenseMatrix< MT, SO2 > &rhs) -> DisableIf_t< VectorizedSchurAssign_v< MT > >
Default implementation of the Schur product assignment of a dense matrix.
Definition: HybridMatrix.h:3145
Header file for the IsLower type trait.
constexpr void MAYBE_UNUSED(const Args &...)
Suppression of unused parameter warnings.
Definition: MaybeUnused.h:81
size_t m_
The current number of rows of the matrix.
Definition: HybridMatrix.h:545
Header file for the IsAligned type trait.
Type & Reference
Reference to a non-constant matrix value.
Definition: HybridMatrix.h:255
const Type * ConstPointer
Pointer to a constant matrix value.
Definition: HybridMatrix.h:258
auto addAssign(const DenseMatrix< MT, SO2 > &rhs) -> DisableIf_t< VectorizedAddAssign_v< MT > >
Default implementation of the addition assignment of a row-major dense matrix.
Definition: HybridMatrix.h:2833
BLAZE_ALWAYS_INLINE EnableIf_t< IsIntegral_v< T1 > &&HasSize_v< T1, 1UL > > storea(T1 *address, const SIMDi8< T2 > &value) noexcept
Aligned store of a vector of 1-byte integral values.
Definition: Storea.h:78
Header file for the default storage order for all vectors of the Blaze library.
Header file for the Kron product trait.
#define BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE(T)
Constraint on the data type.In case the given data type T is not a vectorizable data type,...
Definition: Vectorizable.h:61
void reset()
Reset to the default initial values.
Definition: HybridMatrix.h:1812
static constexpr size_t NN
Alignment adjustment.
Definition: HybridMatrix.h:237
Header file for the exception macros of the math module.
HybridMatrix & ctranspose()
In-place conjugate transpose of the matrix.
Definition: HybridMatrix.h:2071
decltype(auto) max(const DenseMatrix< MT1, SO1 > &lhs, const DenseMatrix< MT2, SO2 > &rhs)
Computes the componentwise maximum of the dense matrices lhs and rhs.
Definition: DMatDMatMapExpr.h:1198
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
Resize mechanism to obtain a HybridMatrix with different fixed dimensions.
Definition: HybridMatrix.h:278
Header file for the IsDenseMatrix type trait.
Header file for the EnableIf class template.
Header file for the IsStrictlyLower type trait.
void clear(const DiagonalProxy< MT > &proxy)
Clearing the represented element.
Definition: DiagonalProxy.h:615
Header file for the IsPadded type trait.
Header file for the IsVectorizable type trait.
BLAZE_ALWAYS_INLINE void stream(size_t i, size_t j, const SIMDType &value) noexcept
Aligned, non-temporal store of a SIMD element of the matrix.
Definition: HybridMatrix.h:2668
Header file for the conjugate shim.
Header file for the IsNumeric type trait.
Header file for the HasConstDataAccess type trait.
auto assign(const DenseMatrix< MT, SO2 > &rhs) -> DisableIf_t< VectorizedAssign_v< MT > >
Default implementation of the assignment of a dense matrix.
Definition: HybridMatrix.h:2702
void swap(HybridMatrix &m) noexcept
Swapping the contents of two hybrid matrices.
Definition: HybridMatrix.h:1974
static constexpr bool simdEnabled
Compilation flag for SIMD optimization.
Definition: HybridMatrix.h:289
Header file for the RemoveConst type trait.
Header file for the IsSIMDCombinable type trait.
BLAZE_ALWAYS_INLINE void storea(size_t i, size_t j, const SIMDType &value) noexcept
Aligned store of a SIMD element of the matrix.
Definition: HybridMatrix.h:2593
#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 the HasSIMDMult type trait.
BLAZE_ALWAYS_INLINE constexpr auto nextMultiple(T1 value, T2 factor) noexcept
Rounds up an integral value to the next multiple of a given factor.
Definition: NextMultiple.h:68
static constexpr size_t Alignment
Alignment of the data elements.
Definition: HybridMatrix.h:525
Pointer data() noexcept
Low-level data access to the matrix elements.
Definition: HybridMatrix.h:1098
HybridMatrix< Type, N, M,!SO > TransposeType
Transpose type for expression template evaluations.
Definition: HybridMatrix.h:249
BLAZE_ALWAYS_INLINE void conjugate(T &a) noexcept(IsNumeric_v< T >)
In-place conjugation of the given value/object.
Definition: Conjugate.h:120
Header file for run time assertion macros.
HybridMatrix & transpose()
In-place transpose of the matrix.
Definition: HybridMatrix.h:2016
const Type & ConstReference
Reference to a constant matrix value.
Definition: HybridMatrix.h:256
Header file for the addition trait.
BLAZE_ALWAYS_INLINE SIMDType loadu(size_t i, size_t j) const noexcept
Unaligned load of a SIMD element of the matrix.
Definition: HybridMatrix.h:2526
Header file for the division trait.
Header file for the submatrix trait.
Constraint on the data type.
Header file for the IsContiguous type trait.
Header file for the columns trait.
Constraint on the data type.
Header file for the AlignedArray implementation.
SIMD characteristics of data types.The SIMDTrait class template provides the SIMD characteristics of ...
Definition: SIMDTrait.h:295
bool canAlias(const Other *alias) const noexcept
Returns whether the matrix can alias with the given address alias.
Definition: HybridMatrix.h:2390
Efficient implementation of a dynamically sized matrix with static memory.The HybridMatrix class temp...
Definition: Forward.h:58
static constexpr bool isAligned() noexcept
Returns whether the matrix is properly aligned in memory.
Definition: HybridMatrix.h:2432
#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
BLAZE_ALWAYS_INLINE const EnableIf_t< IsIntegral_v< T > &&HasSize_v< T, 1UL >, If_t< IsSigned_v< T >, SIMDint8, SIMDuint8 > > set(T value) noexcept
Sets all values in the vector to the given 1-byte integral value.
Definition: Set.h:75
constexpr size_t size(const Matrix< MT, SO > &matrix) noexcept
Returns the total number of elements of the matrix.
Definition: Matrix.h:530
Constraint on the data type.
void swap(HybridMatrix< Type, M, N, SO > &a, HybridMatrix< Type, M, N, SO > &b) noexcept
Swapping the contents of two hybrid matrices.
Definition: HybridMatrix.h:6540
Base class for matrices.The Matrix class is a base class for all dense and sparse matrix classes with...
Definition: Forward.h:114
HybridMatrix< Type, M, N, SO > This
Type of this HybridMatrix instance.
Definition: HybridMatrix.h:245
Constraint on the data type.
Constraint on the data type.
Header file for the HasSIMDSub type trait.
decltype(auto) serial(const DenseMatrix< MT, SO > &dm)
Forces the serial evaluation of the given dense matrix expression dm.
Definition: DMatSerialExpr.h:808
Header file for the HasMutableDataAccess type trait.
constexpr ptrdiff_t DefaultSize_v
Default size of the Size type trait.
Definition: Size.h:72
IntegralConstant< bool, B > BoolConstant
Generic wrapper for a compile time constant boolean value.The BoolConstant alias template represents ...
Definition: IntegralConstant.h:110
constexpr size_t rows(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of rows of the matrix.
Definition: Matrix.h:498
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
BLAZE_ALWAYS_INLINE SIMDType load(size_t i, size_t j) const noexcept
Load of a SIMD element of the matrix.
Definition: HybridMatrix.h:2459
Header file for the IsDenseVector type trait.
Implementation of a generic iterator for dense vectors and matrices.The DenseIterator represents a ge...
Definition: DenseIterator.h:58
Header file for the rows trait.
BLAZE_ALWAYS_INLINE EnableIf_t< IsIntegral_v< T1 > &&HasSize_v< T1, 1UL > > stream(T1 *address, const SIMDi8< T2 > &value) noexcept
Aligned, non-temporal store of a vector of 1-byte integral values.
Definition: Stream.h:74
BLAZE_ALWAYS_INLINE bool checkAlignment(const T *address)
Checks the alignment of the given address.
Definition: AlignmentCheck.h:68
Rebind mechanism to obtain a HybridMatrix with different data/element type.
Definition: HybridMatrix.h:268
DenseIterator< const Type, align > ConstIterator
Iterator over constant elements.
Definition: HybridMatrix.h:261
decltype(auto) trans(const DenseMatrix< MT, SO > &dm)
Calculation of the transpose of the given dense matrix.
Definition: DMatTransExpr.h:765
constexpr size_t AlignmentOf_v
Auxiliary variable template for the AlignmentOf type trait.The AlignmentOf_v variable template provid...
Definition: AlignmentOf.h:238
HybridMatrix< Type, M, N,!SO > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: HybridMatrix.h:248
Header file for the IsRowMajorMatrix type trait.
EnableIf_t< IsBuiltin_v< T > > deallocate(T *address) noexcept
Deallocation of memory for built-in data types.
Definition: Memory.h:224
Header file for the default transpose flag for all vectors of the Blaze library.
Initializer list type of the Blaze library.
constexpr bool HasSIMDMult_v
Auxiliary variable template for the HasSIMDMult type trait.The HasSIMDMult_v variable template provid...
Definition: HasSIMDMult.h:188
Header file for the alignment check function.
BLAZE_ALWAYS_INLINE SIMDType loada(size_t i, size_t j) const noexcept
Aligned load of a SIMD element of the matrix.
Definition: HybridMatrix.h:2489
constexpr bool IsDenseVector_v
Auxiliary variable template for the IsDenseVector type trait.The IsDenseVector_v variable template pr...
Definition: IsDenseVector.h:138
size_t n_
The current number of columns of the matrix.
Definition: HybridMatrix.h:546
Header file for the StorageOrder type trait.
Header file for the IntegralConstant class template.
const Type & ReturnType
Return type for expression template evaluations.
Definition: HybridMatrix.h:252
constexpr Infinity inf
Global Infinity instance.The blaze::inf instance can be used wherever a built-in data type is expecte...
Definition: Infinity.h:1080
static constexpr size_t spacing() noexcept
Returns the spacing between the beginning of two rows.
Definition: HybridMatrix.h:1700
Header file for the map trait.
bool isIntact(const DiagonalMatrix< MT, SO, DF > &m)
Returns whether the invariants of the given diagonal matrix are intact.
Definition: DiagonalMatrix.h:264
auto subAssign(const DenseMatrix< MT, SO2 > &rhs) -> DisableIf_t< VectorizedSubAssign_v< MT > >
Default implementation of the subtraction assignment of a dense matrix.
Definition: HybridMatrix.h:2989
void clear()
Clearing the hybrid matrix.
Definition: HybridMatrix.h:1860
bool isDefault(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is in default state.
Definition: DiagonalProxy.h:635
constexpr bool IsColumnVector_v
Auxiliary variable template for the IsColumnVector type trait.The IsColumnVector_v variable template ...
Definition: IsColumnVector.h:142
#define BLAZE_THROW_LOGIC_ERROR(MESSAGE)
Macro for the emission of a std::logic_error exception.This macro encapsulates the default way of Bla...
Definition: Exception.h:187
Header file for the IsUpper type trait.
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
constexpr bool IsDiagonal_v
Auxiliary variable template for the IsDiagonal type trait.The IsDiagonal_v variable template provides...
Definition: IsDiagonal.h:148
void extend(size_t m, size_t n, bool preserve=true)
Extending the size of the matrix.
Definition: HybridMatrix.h:1956
Header file for the IsColumnVector type trait.
#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
Header file for the IsResizable type trait.
size_t columns() const noexcept
Returns the current number of columns of the matrix.
Definition: HybridMatrix.h:1681
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
bool isAliased(const Other *alias) const noexcept
Returns whether the matrix is aliased with the given address alias.
Definition: HybridMatrix.h:2412
constexpr size_t determineColumns(initializer_list< initializer_list< Type > > list) noexcept
Determines the maximum number of columns specified by the given initializer list.
Definition: InitializerList.h:108
static constexpr bool smpAssignable
Compilation flag for SMP assignments.
Definition: HybridMatrix.h:295
bool isIntact() const noexcept
Returns whether the invariants of the hybrid matrix are intact.
Definition: HybridMatrix.h:2340
Header file for the HighType type trait.
Header file for the clear shim.
void transpose(Matrix< MT, SO > &matrix)
In-place transpose of the given matrix.
Definition: Matrix.h:825