Dense.h
Go to the documentation of this file.
1 //=================================================================================================
33 //=================================================================================================
34 
35 #ifndef _BLAZE_MATH_VIEWS_SUBMATRIX_DENSE_H_
36 #define _BLAZE_MATH_VIEWS_SUBMATRIX_DENSE_H_
37 
38 
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42 
43 #include <algorithm>
44 #include <iterator>
45 #include <blaze/math/Aliases.h>
56 #include <blaze/math/Exception.h>
59 #include <blaze/math/Functions.h>
61 #include <blaze/math/shims/Clear.h>
63 #include <blaze/math/SIMD.h>
87 #include <blaze/system/Blocking.h>
88 #include <blaze/system/CacheSize.h>
89 #include <blaze/system/Inline.h>
93 #include <blaze/util/Assert.h>
97 #include <blaze/util/DisableIf.h>
98 #include <blaze/util/EnableIf.h>
99 #include <blaze/util/mpl/And.h>
100 #include <blaze/util/mpl/If.h>
101 #include <blaze/util/mpl/Not.h>
102 #include <blaze/util/mpl/Or.h>
103 #include <blaze/util/Template.h>
104 #include <blaze/util/Types.h>
108 #include <blaze/util/Unused.h>
109 
110 
111 namespace blaze {
112 
113 //=================================================================================================
114 //
115 // CLASS TEMPLATE SPECIALIZATION FOR UNALIGNED ROW-MAJOR DENSE SUBMATRICES
116 //
117 //=================================================================================================
118 
119 //*************************************************************************************************
127 template< typename MT > // Type of the dense matrix
128 class Submatrix<MT,unaligned,false,true>
129  : public DenseMatrix< Submatrix<MT,unaligned,false,true>, false >
130  , private View
131 {
132  private:
133  //**Type definitions****************************************************************************
135  typedef If_< IsExpression<MT>, MT, MT& > Operand;
136  //**********************************************************************************************
137 
138  public:
139  //**Type definitions****************************************************************************
140  typedef Submatrix<MT,unaligned,false,true> This;
141  typedef DenseMatrix<This,false> BaseType;
142  typedef SubmatrixTrait_<MT> ResultType;
143  typedef OppositeType_<ResultType> OppositeType;
144  typedef TransposeType_<ResultType> TransposeType;
145  typedef ElementType_<MT> ElementType;
146  typedef SIMDTrait_<ElementType> SIMDType;
147  typedef ReturnType_<MT> ReturnType;
148  typedef const Submatrix& CompositeType;
149 
151  typedef ConstReference_<MT> ConstReference;
152 
154  typedef If_< IsConst<MT>, ConstReference, Reference_<MT> > Reference;
155 
157  typedef const ElementType* ConstPointer;
158 
160  typedef If_< Or< IsConst<MT>, Not< HasMutableDataAccess<MT> > >, ConstPointer, ElementType* > Pointer;
161  //**********************************************************************************************
162 
163  //**SubmatrixIterator class definition**********************************************************
166  template< typename IteratorType > // Type of the dense matrix iterator
167  class SubmatrixIterator
168  {
169  public:
170  //**Type definitions*************************************************************************
172  typedef typename std::iterator_traits<IteratorType>::iterator_category IteratorCategory;
173 
175  typedef typename std::iterator_traits<IteratorType>::value_type ValueType;
176 
178  typedef typename std::iterator_traits<IteratorType>::pointer PointerType;
179 
181  typedef typename std::iterator_traits<IteratorType>::reference ReferenceType;
182 
184  typedef typename std::iterator_traits<IteratorType>::difference_type DifferenceType;
185 
186  // STL iterator requirements
187  typedef IteratorCategory iterator_category;
188  typedef ValueType value_type;
189  typedef PointerType pointer;
190  typedef ReferenceType reference;
191  typedef DifferenceType difference_type;
192  //*******************************************************************************************
193 
194  //**Constructor******************************************************************************
197  inline SubmatrixIterator()
198  : iterator_ ( ) // Iterator to the current submatrix element
199  , isAligned_( false ) // Memory alignment flag
200  {}
201  //*******************************************************************************************
202 
203  //**Constructor******************************************************************************
209  inline SubmatrixIterator( IteratorType iterator, bool isMemoryAligned )
210  : iterator_ ( iterator ) // Iterator to the current submatrix element
211  , isAligned_( isMemoryAligned ) // Memory alignment flag
212  {}
213  //*******************************************************************************************
214 
215  //**Constructor******************************************************************************
220  template< typename IteratorType2 >
221  inline SubmatrixIterator( const SubmatrixIterator<IteratorType2>& it )
222  : iterator_ ( it.base() ) // Iterator to the current submatrix element
223  , isAligned_( it.isAligned() ) // Memory alignment flag
224  {}
225  //*******************************************************************************************
226 
227  //**Addition assignment operator*************************************************************
233  inline SubmatrixIterator& operator+=( size_t inc ) {
234  iterator_ += inc;
235  return *this;
236  }
237  //*******************************************************************************************
238 
239  //**Subtraction assignment operator**********************************************************
245  inline SubmatrixIterator& operator-=( size_t dec ) {
246  iterator_ -= dec;
247  return *this;
248  }
249  //*******************************************************************************************
250 
251  //**Prefix increment operator****************************************************************
256  inline SubmatrixIterator& operator++() {
257  ++iterator_;
258  return *this;
259  }
260  //*******************************************************************************************
261 
262  //**Postfix increment operator***************************************************************
267  inline const SubmatrixIterator operator++( int ) {
268  return SubmatrixIterator( iterator_++, isAligned_ );
269  }
270  //*******************************************************************************************
271 
272  //**Prefix decrement operator****************************************************************
277  inline SubmatrixIterator& operator--() {
278  --iterator_;
279  return *this;
280  }
281  //*******************************************************************************************
282 
283  //**Postfix decrement operator***************************************************************
288  inline const SubmatrixIterator operator--( int ) {
289  return SubmatrixIterator( iterator_--, isAligned_ );
290  }
291  //*******************************************************************************************
292 
293  //**Element access operator******************************************************************
298  inline ReferenceType operator*() const {
299  return *iterator_;
300  }
301  //*******************************************************************************************
302 
303  //**Load function****************************************************************************
313  inline SIMDType load() const noexcept {
314  if( isAligned_ )
315  return loada();
316  else
317  return loadu();
318  }
319  //*******************************************************************************************
320 
321  //**Loada function***************************************************************************
331  inline SIMDType loada() const noexcept {
332  return iterator_.loada();
333  }
334  //*******************************************************************************************
335 
336  //**Loadu function***************************************************************************
346  inline SIMDType loadu() const noexcept {
347  return iterator_.loadu();
348  }
349  //*******************************************************************************************
350 
351  //**Store function***************************************************************************
362  inline void store( const SIMDType& value ) const {
363  storeu( value );
364  }
365  //*******************************************************************************************
366 
367  //**Storea function**************************************************************************
378  inline void storea( const SIMDType& value ) const {
379  iterator_.storea( value );
380  }
381  //*******************************************************************************************
382 
383  //**Storeu function**************************************************************************
394  inline void storeu( const SIMDType& value ) const {
395  if( isAligned_ ) {
396  iterator_.storea( value );
397  }
398  else {
399  iterator_.storeu( value );
400  }
401  }
402  //*******************************************************************************************
403 
404  //**Stream function**************************************************************************
415  inline void stream( const SIMDType& value ) const {
416  iterator_.stream( value );
417  }
418  //*******************************************************************************************
419 
420  //**Equality operator************************************************************************
426  inline bool operator==( const SubmatrixIterator& rhs ) const {
427  return iterator_ == rhs.iterator_;
428  }
429  //*******************************************************************************************
430 
431  //**Inequality operator**********************************************************************
437  inline bool operator!=( const SubmatrixIterator& rhs ) const {
438  return iterator_ != rhs.iterator_;
439  }
440  //*******************************************************************************************
441 
442  //**Less-than operator***********************************************************************
448  inline bool operator<( const SubmatrixIterator& rhs ) const {
449  return iterator_ < rhs.iterator_;
450  }
451  //*******************************************************************************************
452 
453  //**Greater-than operator********************************************************************
459  inline bool operator>( const SubmatrixIterator& rhs ) const {
460  return iterator_ > rhs.iterator_;
461  }
462  //*******************************************************************************************
463 
464  //**Less-or-equal-than operator**************************************************************
470  inline bool operator<=( const SubmatrixIterator& rhs ) const {
471  return iterator_ <= rhs.iterator_;
472  }
473  //*******************************************************************************************
474 
475  //**Greater-or-equal-than operator***********************************************************
481  inline bool operator>=( const SubmatrixIterator& rhs ) const {
482  return iterator_ >= rhs.iterator_;
483  }
484  //*******************************************************************************************
485 
486  //**Subtraction operator*********************************************************************
492  inline DifferenceType operator-( const SubmatrixIterator& rhs ) const {
493  return iterator_ - rhs.iterator_;
494  }
495  //*******************************************************************************************
496 
497  //**Addition operator************************************************************************
504  friend inline const SubmatrixIterator operator+( const SubmatrixIterator& it, size_t inc ) {
505  return SubmatrixIterator( it.iterator_ + inc, it.isAligned_ );
506  }
507  //*******************************************************************************************
508 
509  //**Addition operator************************************************************************
516  friend inline const SubmatrixIterator operator+( size_t inc, const SubmatrixIterator& it ) {
517  return SubmatrixIterator( it.iterator_ + inc, it.isAligned_ );
518  }
519  //*******************************************************************************************
520 
521  //**Subtraction operator*********************************************************************
528  friend inline const SubmatrixIterator operator-( const SubmatrixIterator& it, size_t dec ) {
529  return SubmatrixIterator( it.iterator_ - dec, it.isAligned_ );
530  }
531  //*******************************************************************************************
532 
533  //**Base function****************************************************************************
538  inline IteratorType base() const {
539  return iterator_;
540  }
541  //*******************************************************************************************
542 
543  //**IsAligned function***********************************************************************
548  inline bool isAligned() const noexcept {
549  return isAligned_;
550  }
551  //*******************************************************************************************
552 
553  private:
554  //**Member variables*************************************************************************
555  IteratorType iterator_;
556  bool isAligned_;
557  //*******************************************************************************************
558  };
559  //**********************************************************************************************
560 
561  //**Type definitions****************************************************************************
563  typedef SubmatrixIterator< ConstIterator_<MT> > ConstIterator;
564 
566  typedef If_< IsConst<MT>, ConstIterator, SubmatrixIterator< Iterator_<MT> > > Iterator;
567  //**********************************************************************************************
568 
569  //**Compilation flags***************************************************************************
571  enum : bool { simdEnabled = MT::simdEnabled };
572 
574  enum : bool { smpAssignable = MT::smpAssignable };
575  //**********************************************************************************************
576 
577  //**Constructors********************************************************************************
580  explicit inline Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n );
581  // No explicitly declared copy constructor.
583  //**********************************************************************************************
584 
585  //**Destructor**********************************************************************************
586  // No explicitly declared destructor.
587  //**********************************************************************************************
588 
589  //**Data access functions***********************************************************************
592  inline Reference operator()( size_t i, size_t j );
593  inline ConstReference operator()( size_t i, size_t j ) const;
594  inline Reference at( size_t i, size_t j );
595  inline ConstReference at( size_t i, size_t j ) const;
596  inline Pointer data () noexcept;
597  inline ConstPointer data () const noexcept;
598  inline Pointer data ( size_t i ) noexcept;
599  inline ConstPointer data ( size_t i ) const noexcept;
600  inline Iterator begin ( size_t i );
601  inline ConstIterator begin ( size_t i ) const;
602  inline ConstIterator cbegin( size_t i ) const;
603  inline Iterator end ( size_t i );
604  inline ConstIterator end ( size_t i ) const;
605  inline ConstIterator cend ( size_t i ) const;
607  //**********************************************************************************************
608 
609  //**Assignment operators************************************************************************
612  inline Submatrix& operator=( const ElementType& rhs );
613  inline Submatrix& operator=( initializer_list< initializer_list<ElementType> > list );
614  inline Submatrix& operator=( const Submatrix& rhs );
615 
616  template< typename MT2, bool SO2 >
617  inline Submatrix& operator=( const Matrix<MT2,SO2>& rhs );
618 
619  template< typename MT2, bool SO2 >
620  inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
621  operator+=( const Matrix<MT2,SO2>& rhs );
622 
623  template< typename MT2, bool SO2 >
624  inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
625  operator+=( const Matrix<MT2,SO2>& rhs );
626 
627  template< typename MT2, bool SO2 >
628  inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
629  operator-=( const Matrix<MT2,SO2>& rhs );
630 
631  template< typename MT2, bool SO2 >
632  inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
633  operator-=( const Matrix<MT2,SO2>& rhs );
634 
635  template< typename MT2, bool SO2 >
636  inline Submatrix& operator*=( const Matrix<MT2,SO2>& rhs );
637 
638  template< typename Other >
639  inline EnableIf_< IsNumeric<Other>, Submatrix >& operator*=( Other rhs );
640 
641  template< typename Other >
642  inline EnableIf_< IsNumeric<Other>, Submatrix >& operator/=( Other rhs );
644  //**********************************************************************************************
645 
646  //**Utility functions***************************************************************************
649  inline size_t row() const noexcept;
650  inline size_t rows() const noexcept;
651  inline size_t column() const noexcept;
652  inline size_t columns() const noexcept;
653  inline size_t spacing() const noexcept;
654  inline size_t capacity() const noexcept;
655  inline size_t capacity( size_t i ) const noexcept;
656  inline size_t nonZeros() const;
657  inline size_t nonZeros( size_t i ) const;
658  inline void reset();
659  inline void reset( size_t i );
661  //**********************************************************************************************
662 
663  //**Numeric functions***************************************************************************
666  inline Submatrix& transpose();
667  inline Submatrix& ctranspose();
668 
669  template< typename Other > inline Submatrix& scale( const Other& scalar );
671  //**********************************************************************************************
672 
673  private:
674  //**********************************************************************************************
676  template< typename MT2 >
677  struct VectorizedAssign {
678  enum : bool { value = useOptimizedKernels &&
679  simdEnabled && MT2::simdEnabled &&
680  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value };
681  };
682  //**********************************************************************************************
683 
684  //**********************************************************************************************
686  template< typename MT2 >
687  struct VectorizedAddAssign {
688  enum : bool { value = useOptimizedKernels &&
689  simdEnabled && MT2::simdEnabled &&
690  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
691  HasSIMDAdd< ElementType, ElementType_<MT2> >::value &&
692  !IsDiagonal<MT2>::value };
693  };
694  //**********************************************************************************************
695 
696  //**********************************************************************************************
698  template< typename MT2 >
699  struct VectorizedSubAssign {
700  enum : bool { value = useOptimizedKernels &&
701  simdEnabled && MT2::simdEnabled &&
702  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
703  HasSIMDSub< ElementType, ElementType_<MT2> >::value &&
704  !IsDiagonal<MT2>::value };
705  };
706  //**********************************************************************************************
707 
708  //**SIMD properties*****************************************************************************
710  enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
711  //**********************************************************************************************
712 
713  public:
714  //**Expression template evaluation functions****************************************************
717  template< typename Other >
718  inline bool canAlias( const Other* alias ) const noexcept;
719 
720  template< typename MT2, bool AF2, bool SO2 >
721  inline bool canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
722 
723  template< typename Other >
724  inline bool isAliased( const Other* alias ) const noexcept;
725 
726  template< typename MT2, bool AF2, bool SO2 >
727  inline bool isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
728 
729  inline bool isAligned () const noexcept;
730  inline bool canSMPAssign() const noexcept;
731 
732  BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
733  BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
734  BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
735 
736  BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
737  BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
738  BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
739  BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
740 
741  template< typename MT2 >
742  inline DisableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,false>& rhs );
743 
744  template< typename MT2 >
745  inline EnableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,false>& rhs );
746 
747  template< typename MT2 > inline void assign( const DenseMatrix<MT2,true>& rhs );
748  template< typename MT2 > inline void assign( const SparseMatrix<MT2,false>& rhs );
749  template< typename MT2 > inline void assign( const SparseMatrix<MT2,true>& rhs );
750 
751  template< typename MT2 >
752  inline DisableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,false>& rhs );
753 
754  template< typename MT2 >
755  inline EnableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,false>& rhs );
756 
757  template< typename MT2 > inline void addAssign( const DenseMatrix<MT2,true>& rhs );
758  template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,false>& rhs );
759  template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,true>& rhs );
760 
761  template< typename MT2 >
762  inline DisableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,false>& rhs );
763 
764  template< typename MT2 >
765  inline EnableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,false>& rhs );
766 
767  template< typename MT2 > inline void subAssign( const DenseMatrix<MT2,true>& rhs );
768  template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,false>& rhs );
769  template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,true>& rhs );
771  //**********************************************************************************************
772 
773  private:
774  //**Utility functions***************************************************************************
777  inline bool hasOverlap() const noexcept;
779  //**********************************************************************************************
780 
781  //**Member variables****************************************************************************
784  Operand matrix_;
785  const size_t row_;
786  const size_t column_;
787  const size_t m_;
788  const size_t n_;
789  const bool isAligned_;
790 
797  //**********************************************************************************************
798 
799  //**Friend declarations*************************************************************************
800  template< typename MT2, bool AF2, bool SO2, bool DF2 > friend class Submatrix;
801 
802  template< bool AF1, typename MT2, bool AF2, bool SO2, bool DF2 >
803  friend const Submatrix<MT2,AF1,SO2,DF2>
804  submatrix( const Submatrix<MT2,AF2,SO2,DF2>& sm, size_t row, size_t column, size_t m, size_t n );
805 
806  template< typename MT2, bool AF2, bool SO2, bool DF2 >
807  friend bool isIntact( const Submatrix<MT2,AF2,SO2,DF2>& sm ) noexcept;
808 
809  template< typename MT2, bool AF2, bool SO2, bool DF2 >
810  friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Matrix<MT2,SO2>& b ) noexcept;
811 
812  template< typename MT2, bool AF2, bool SO2, bool DF2 >
813  friend bool isSame( const Matrix<MT2,SO2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
814 
815  template< typename MT2, bool AF2, bool SO2, bool DF2 >
816  friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
817 
818  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
819  friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
820  size_t row, size_t column );
821 
822  template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
823  friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
824  size_t row, size_t column );
825 
826  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
827  friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
828  size_t row, size_t column );
829 
830  template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
831  friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
832  size_t row, size_t column );
833 
834  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
835  friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
836  size_t row, size_t column );
837 
838  template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
839  friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
840  size_t row, size_t column );
841 
842  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
843  friend bool tryMultAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
844  size_t row, size_t column );
845 
846  template< typename MT2, bool AF2, bool SO2, bool DF2 >
847  friend DerestrictTrait_< Submatrix<MT2,AF2,SO2,DF2> > derestrict( Submatrix<MT2,AF2,SO2,DF2>& sm );
848  //**********************************************************************************************
849 
850  //**Compile time checks*************************************************************************
858  //**********************************************************************************************
859 };
861 //*************************************************************************************************
862 
863 
864 
865 
866 //=================================================================================================
867 //
868 // CONSTRUCTOR
869 //
870 //=================================================================================================
871 
872 //*************************************************************************************************
886 template< typename MT > // Type of the dense matrix
887 inline Submatrix<MT,unaligned,false,true>::Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n )
888  : matrix_ ( matrix ) // The dense matrix containing the submatrix
889  , row_ ( rindex ) // The first row of the submatrix
890  , column_ ( cindex ) // The first column of the submatrix
891  , m_ ( m ) // The number of rows of the submatrix
892  , n_ ( n ) // The number of columns of the submatrix
893  , isAligned_( simdEnabled && matrix.data() != nullptr && checkAlignment( data() ) &&
894  ( m < 2UL || ( matrix.spacing() & size_t(-SIMDSIZE) ) == 0UL ) )
895 {
896  if( ( row_ + m_ > matrix_.rows() ) || ( column_ + n_ > matrix_.columns() ) ) {
897  BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix specification" );
898  }
899 }
901 //*************************************************************************************************
902 
903 
904 
905 
906 //=================================================================================================
907 //
908 // DATA ACCESS FUNCTIONS
909 //
910 //=================================================================================================
911 
912 //*************************************************************************************************
923 template< typename MT > // Type of the dense matrix
925  Submatrix<MT,unaligned,false,true>::operator()( size_t i, size_t j )
926 {
927  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
928  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
929 
930  return matrix_(row_+i,column_+j);
931 }
933 //*************************************************************************************************
934 
935 
936 //*************************************************************************************************
947 template< typename MT > // Type of the dense matrix
949  Submatrix<MT,unaligned,false,true>::operator()( size_t i, size_t j ) const
950 {
951  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
952  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
953 
954  return const_cast<const MT&>( matrix_ )(row_+i,column_+j);
955 }
957 //*************************************************************************************************
958 
959 
960 //*************************************************************************************************
972 template< typename MT > // Type of the dense matrix
974  Submatrix<MT,unaligned,false,true>::at( size_t i, size_t j )
975 {
976  if( i >= rows() ) {
977  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
978  }
979  if( j >= columns() ) {
980  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
981  }
982  return (*this)(i,j);
983 }
985 //*************************************************************************************************
986 
987 
988 //*************************************************************************************************
1000 template< typename MT > // Type of the dense matrix
1002  Submatrix<MT,unaligned,false,true>::at( size_t i, size_t j ) const
1003 {
1004  if( i >= rows() ) {
1005  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
1006  }
1007  if( j >= columns() ) {
1008  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
1009  }
1010  return (*this)(i,j);
1011 }
1013 //*************************************************************************************************
1014 
1015 
1016 //*************************************************************************************************
1026 template< typename MT > // Type of the dense matrix
1027 inline typename Submatrix<MT,unaligned,false,true>::Pointer
1028  Submatrix<MT,unaligned,false,true>::data() noexcept
1029 {
1030  return matrix_.data() + row_*spacing() + column_;
1031 }
1033 //*************************************************************************************************
1034 
1035 
1036 //*************************************************************************************************
1046 template< typename MT > // Type of the dense matrix
1047 inline typename Submatrix<MT,unaligned,false,true>::ConstPointer
1048  Submatrix<MT,unaligned,false,true>::data() const noexcept
1049 {
1050  return matrix_.data() + row_*spacing() + column_;
1051 }
1053 //*************************************************************************************************
1054 
1055 
1056 //*************************************************************************************************
1065 template< typename MT > // Type of the dense matrix
1066 inline typename Submatrix<MT,unaligned,false,true>::Pointer
1067  Submatrix<MT,unaligned,false,true>::data( size_t i ) noexcept
1068 {
1069  return matrix_.data() + (row_+i)*spacing() + column_;
1070 }
1072 //*************************************************************************************************
1073 
1074 
1075 //*************************************************************************************************
1084 template< typename MT > // Type of the dense matrix
1085 inline typename Submatrix<MT,unaligned,false,true>::ConstPointer
1086  Submatrix<MT,unaligned,false,true>::data( size_t i ) const noexcept
1087 {
1088  return matrix_.data() + (row_+i)*spacing() + column_;
1089 }
1091 //*************************************************************************************************
1092 
1093 
1094 //*************************************************************************************************
1106 template< typename MT > // Type of the dense matrix
1109 {
1110  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
1111  return Iterator( matrix_.begin( row_ + i ) + column_, isAligned_ );
1112 }
1114 //*************************************************************************************************
1115 
1116 
1117 //*************************************************************************************************
1129 template< typename MT > // Type of the dense matrix
1132 {
1133  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
1134  return ConstIterator( matrix_.cbegin( row_ + i ) + column_, isAligned_ );
1135 }
1137 //*************************************************************************************************
1138 
1139 
1140 //*************************************************************************************************
1152 template< typename MT > // Type of the dense matrix
1155 {
1156  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
1157  return ConstIterator( matrix_.cbegin( row_ + i ) + column_, isAligned_ );
1158 }
1160 //*************************************************************************************************
1161 
1162 
1163 //*************************************************************************************************
1175 template< typename MT > // Type of the dense matrix
1178 {
1179  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
1180  return Iterator( matrix_.begin( row_ + i ) + column_ + n_, isAligned_ );
1181 }
1183 //*************************************************************************************************
1184 
1185 
1186 //*************************************************************************************************
1198 template< typename MT > // Type of the dense matrix
1200  Submatrix<MT,unaligned,false,true>::end( size_t i ) const
1201 {
1202  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
1203  return ConstIterator( matrix_.cbegin( row_ + i ) + column_ + n_, isAligned_ );
1204 }
1206 //*************************************************************************************************
1207 
1208 
1209 //*************************************************************************************************
1221 template< typename MT > // Type of the dense matrix
1224 {
1225  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
1226  return ConstIterator( matrix_.cbegin( row_ + i ) + column_ + n_, isAligned_ );
1227 }
1229 //*************************************************************************************************
1230 
1231 
1232 
1233 
1234 //=================================================================================================
1235 //
1236 // ASSIGNMENT OPERATORS
1237 //
1238 //=================================================================================================
1239 
1240 //*************************************************************************************************
1251 template< typename MT > // Type of the dense matrix
1252 inline Submatrix<MT,unaligned,false,true>&
1253  Submatrix<MT,unaligned,false,true>::operator=( const ElementType& rhs )
1254 {
1255  const size_t iend( row_ + m_ );
1256 
1257  for( size_t i=row_; i<iend; ++i )
1258  {
1259  const size_t jbegin( ( IsUpper<MT>::value )
1260  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
1261  ?( max( i+1UL, column_ ) )
1262  :( max( i, column_ ) ) )
1263  :( column_ ) );
1264  const size_t jend ( ( IsLower<MT>::value )
1265  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
1266  ?( min( i, column_+n_ ) )
1267  :( min( i+1UL, column_+n_ ) ) )
1268  :( column_+n_ ) );
1269 
1270  for( size_t j=jbegin; j<jend; ++j )
1271  matrix_(i,j) = rhs;
1272  }
1273 
1274  return *this;
1275 }
1277 //*************************************************************************************************
1278 
1279 
1280 //*************************************************************************************************
1293 template< typename MT > // Type of the dense matrix
1294 inline Submatrix<MT,unaligned,false,true>&
1295  Submatrix<MT,unaligned,false,true>::operator=( initializer_list< initializer_list<ElementType> > list )
1296 {
1297  if( list.size() != rows() || determineColumns( list ) > columns() ) {
1298  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to submatrix" );
1299  }
1300 
1301  size_t i( 0UL );
1302 
1303  for( const auto& rowList : list ) {
1304  std::fill( std::copy( rowList.begin(), rowList.end(), begin(i) ), end(i), ElementType() );
1305  ++i;
1306  }
1307 
1308  return *this;
1309 }
1311 //*************************************************************************************************
1312 
1313 
1314 //*************************************************************************************************
1329 template< typename MT > // Type of the dense matrix
1330 inline Submatrix<MT,unaligned,false,true>&
1331  Submatrix<MT,unaligned,false,true>::operator=( const Submatrix& rhs )
1332 {
1335 
1336  if( this == &rhs || ( &matrix_ == &rhs.matrix_ && row_ == rhs.row_ && column_ == rhs.column_ ) )
1337  return *this;
1338 
1339  if( rows() != rhs.rows() || columns() != rhs.columns() ) {
1340  BLAZE_THROW_INVALID_ARGUMENT( "Submatrix sizes do not match" );
1341  }
1342 
1343  if( !tryAssign( matrix_, rhs, row_, column_ ) ) {
1344  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1345  }
1346 
1347  DerestrictTrait_<This> left( derestrict( *this ) );
1348 
1349  if( rhs.canAlias( &matrix_ ) ) {
1350  const ResultType tmp( rhs );
1351  smpAssign( left, tmp );
1352  }
1353  else {
1354  smpAssign( left, rhs );
1355  }
1356 
1357  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1358 
1359  return *this;
1360 }
1362 //*************************************************************************************************
1363 
1364 
1365 //*************************************************************************************************
1380 template< typename MT > // Type of the dense matrix
1381 template< typename MT2 // Type of the right-hand side matrix
1382  , bool SO2 > // Storage order of the right-hand side matrix
1383 inline Submatrix<MT,unaligned,false,true>&
1384  Submatrix<MT,unaligned,false,true>::operator=( const Matrix<MT2,SO2>& rhs )
1385 {
1387 
1388  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
1389  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1390  }
1391 
1392  typedef If_< IsRestricted<MT>, CompositeType_<MT2>, const MT2& > Right;
1393  Right right( ~rhs );
1394 
1395  if( !tryAssign( matrix_, right, row_, column_ ) ) {
1396  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1397  }
1398 
1399  if( IsSparseMatrix<MT2>::value )
1400  reset();
1401 
1402  DerestrictTrait_<This> left( derestrict( *this ) );
1403 
1404  if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
1405  const ResultType_<MT2> tmp( right );
1406  smpAssign( left, tmp );
1407  }
1408  else {
1409  smpAssign( left, right );
1410  }
1411 
1412  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1413 
1414  return *this;
1415 }
1417 //*************************************************************************************************
1418 
1419 
1420 //*************************************************************************************************
1434 template< typename MT > // Type of the dense matrix
1435 template< typename MT2 // Type of the right-hand side matrix
1436  , bool SO2 > // Storage order of the right-hand side matrix
1437 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,false,true>& >
1438  Submatrix<MT,unaligned,false,true>::operator+=( const Matrix<MT2,SO2>& rhs )
1439 {
1443 
1444  typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
1445 
1448 
1449  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
1450  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1451  }
1452 
1453  if( !tryAddAssign( matrix_, ~rhs, row_, column_ ) ) {
1454  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1455  }
1456 
1457  DerestrictTrait_<This> left( derestrict( *this ) );
1458 
1459  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
1460  (~rhs).canAlias( &matrix_ ) ) {
1461  const AddType tmp( *this + (~rhs) );
1462  smpAssign( left, tmp );
1463  }
1464  else {
1465  smpAddAssign( left, ~rhs );
1466  }
1467 
1468  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1469 
1470  return *this;
1471 }
1473 //*************************************************************************************************
1474 
1475 
1476 //*************************************************************************************************
1490 template< typename MT > // Type of the dense matrix
1491 template< typename MT2 // Type of the right-hand side matrix
1492  , bool SO2 > // Storage order of the right-hand side matrix
1493 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,false,true>& >
1494  Submatrix<MT,unaligned,false,true>::operator+=( const Matrix<MT2,SO2>& rhs )
1495 {
1499 
1500  typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
1501 
1504 
1505  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
1506  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1507  }
1508 
1509  const AddType tmp( *this + (~rhs) );
1510 
1511  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
1512  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1513  }
1514 
1515  DerestrictTrait_<This> left( derestrict( *this ) );
1516 
1517  smpAssign( left, tmp );
1518 
1519  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1520 
1521  return *this;
1522 }
1524 //*************************************************************************************************
1525 
1526 
1527 //*************************************************************************************************
1541 template< typename MT > // Type of the dense matrix
1542 template< typename MT2 // Type of the right-hand side matrix
1543  , bool SO2 > // Storage order of the right-hand side matrix
1544 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,false,true>& >
1545  Submatrix<MT,unaligned,false,true>::operator-=( const Matrix<MT2,SO2>& rhs )
1546 {
1550 
1551  typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
1552 
1555 
1556  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
1557  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1558  }
1559 
1560  if( !trySubAssign( matrix_, ~rhs, row_, column_ ) ) {
1561  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1562  }
1563 
1564  DerestrictTrait_<This> left( derestrict( *this ) );
1565 
1566  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
1567  (~rhs).canAlias( &matrix_ ) ) {
1568  const SubType tmp( *this - (~rhs ) );
1569  smpAssign( left, tmp );
1570  }
1571  else {
1572  smpSubAssign( left, ~rhs );
1573  }
1574 
1575  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1576 
1577  return *this;
1578 }
1580 //*************************************************************************************************
1581 
1582 
1583 //*************************************************************************************************
1597 template< typename MT > // Type of the dense matrix
1598 template< typename MT2 // Type of the right-hand side matrix
1599  , bool SO2 > // Storage order of the right-hand side matrix
1600 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,false,true>& >
1601  Submatrix<MT,unaligned,false,true>::operator-=( const Matrix<MT2,SO2>& rhs )
1602 {
1606 
1607  typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
1608 
1611 
1612  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
1613  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1614  }
1615 
1616  const SubType tmp( *this - (~rhs) );
1617 
1618  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
1619  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1620  }
1621 
1622  DerestrictTrait_<This> left( derestrict( *this ) );
1623 
1624  smpAssign( left, tmp );
1625 
1626  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1627 
1628  return *this;
1629 }
1631 //*************************************************************************************************
1632 
1633 
1634 //*************************************************************************************************
1648 template< typename MT > // Type of the dense matrix
1649 template< typename MT2 // Type of the right-hand side matrix
1650  , bool SO2 > // Storage order of the right-hand side matrix
1651 inline Submatrix<MT,unaligned,false,true>&
1652  Submatrix<MT,unaligned,false,true>::operator*=( const Matrix<MT2,SO2>& rhs )
1653 {
1657 
1658  typedef MultTrait_< ResultType, ResultType_<MT2> > MultType;
1659 
1662 
1663  if( columns() != (~rhs).rows() ) {
1664  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1665  }
1666 
1667  const MultType tmp( *this * (~rhs) );
1668 
1669  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
1670  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1671  }
1672 
1673  DerestrictTrait_<This> left( derestrict( *this ) );
1674 
1675  smpAssign( left, tmp );
1676 
1677  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1678 
1679  return *this;
1680 }
1682 //*************************************************************************************************
1683 
1684 
1685 //*************************************************************************************************
1696 template< typename MT > // Type of the dense matrix
1697 template< typename Other > // Data type of the right-hand side scalar
1698 inline EnableIf_< IsNumeric<Other>, Submatrix<MT,unaligned,false,true> >&
1700 {
1702 
1703  DerestrictTrait_<This> left( derestrict( *this ) );
1704  smpAssign( left, (*this) * rhs );
1705 
1706  return *this;
1707 }
1709 //*************************************************************************************************
1710 
1711 
1712 //*************************************************************************************************
1725 template< typename MT > // Type of the dense matrix
1726 template< typename Other > // Data type of the right-hand side scalar
1727 inline EnableIf_< IsNumeric<Other>, Submatrix<MT,unaligned,false,true> >&
1729 {
1731 
1732  BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
1733 
1734  DerestrictTrait_<This> left( derestrict( *this ) );
1735  smpAssign( left, (*this) / rhs );
1736 
1737  return *this;
1738 }
1740 //*************************************************************************************************
1741 
1742 
1743 
1744 
1745 //=================================================================================================
1746 //
1747 // UTILITY FUNCTIONS
1748 //
1749 //=================================================================================================
1750 
1751 //*************************************************************************************************
1757 template< typename MT > // Type of the dense matrix
1758 inline size_t Submatrix<MT,unaligned,false,true>::row() const noexcept
1759 {
1760  return row_;
1761 }
1763 //*************************************************************************************************
1764 
1765 
1766 //*************************************************************************************************
1772 template< typename MT > // Type of the dense matrix
1773 inline size_t Submatrix<MT,unaligned,false,true>::rows() const noexcept
1774 {
1775  return m_;
1776 }
1778 //*************************************************************************************************
1779 
1780 
1781 //*************************************************************************************************
1787 template< typename MT > // Type of the dense matrix
1788 inline size_t Submatrix<MT,unaligned,false,true>::column() const noexcept
1789 {
1790  return column_;
1791 }
1792 //*************************************************************************************************
1793 
1794 
1795 //*************************************************************************************************
1801 template< typename MT > // Type of the dense matrix
1802 inline size_t Submatrix<MT,unaligned,false,true>::columns() const noexcept
1803 {
1804  return n_;
1805 }
1807 //*************************************************************************************************
1808 
1809 
1810 //*************************************************************************************************
1821 template< typename MT > // Type of the dense matrix
1822 inline size_t Submatrix<MT,unaligned,false,true>::spacing() const noexcept
1823 {
1824  return matrix_.spacing();
1825 }
1826 //*************************************************************************************************
1827 
1828 
1829 //*************************************************************************************************
1835 template< typename MT > // Type of the dense matrix
1836 inline size_t Submatrix<MT,unaligned,false,true>::capacity() const noexcept
1837 {
1838  return rows() * columns();
1839 }
1841 //*************************************************************************************************
1842 
1843 
1844 //*************************************************************************************************
1856 template< typename MT > // Type of the dense matrix
1857 inline size_t Submatrix<MT,unaligned,false,true>::capacity( size_t i ) const noexcept
1858 {
1859  UNUSED_PARAMETER( i );
1860 
1861  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
1862 
1863  return columns();
1864 }
1866 //*************************************************************************************************
1867 
1868 
1869 //*************************************************************************************************
1875 template< typename MT > // Type of the dense matrix
1877 {
1878  const size_t iend( row_ + m_ );
1879  const size_t jend( column_ + n_ );
1880  size_t nonzeros( 0UL );
1881 
1882  for( size_t i=row_; i<iend; ++i )
1883  for( size_t j=column_; j<jend; ++j )
1884  if( !isDefault( matrix_(i,j) ) )
1885  ++nonzeros;
1886 
1887  return nonzeros;
1888 }
1890 //*************************************************************************************************
1891 
1892 
1893 //*************************************************************************************************
1905 template< typename MT > // Type of the dense matrix
1906 inline size_t Submatrix<MT,unaligned,false,true>::nonZeros( size_t i ) const
1907 {
1908  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
1909 
1910  const size_t jend( column_ + n_ );
1911  size_t nonzeros( 0UL );
1912 
1913  for( size_t j=column_; j<jend; ++j )
1914  if( !isDefault( matrix_(row_+i,j) ) )
1915  ++nonzeros;
1916 
1917  return nonzeros;
1918 }
1920 //*************************************************************************************************
1921 
1922 
1923 //*************************************************************************************************
1929 template< typename MT > // Type of the dense matrix
1931 {
1932  using blaze::clear;
1933 
1934  for( size_t i=row_; i<row_+m_; ++i )
1935  {
1936  const size_t jbegin( ( IsUpper<MT>::value )
1937  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
1938  ?( max( i+1UL, column_ ) )
1939  :( max( i, column_ ) ) )
1940  :( column_ ) );
1941  const size_t jend ( ( IsLower<MT>::value )
1942  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
1943  ?( min( i, column_+n_ ) )
1944  :( min( i+1UL, column_+n_ ) ) )
1945  :( column_+n_ ) );
1946 
1947  for( size_t j=jbegin; j<jend; ++j )
1948  clear( matrix_(i,j) );
1949  }
1950 }
1952 //*************************************************************************************************
1953 
1954 
1955 //*************************************************************************************************
1967 template< typename MT > // Type of the dense matrix
1968 inline void Submatrix<MT,unaligned,false,true>::reset( size_t i )
1969 {
1970  using blaze::clear;
1971 
1972  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
1973 
1974  const size_t jbegin( ( IsUpper<MT>::value )
1975  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
1976  ?( max( i+1UL, column_ ) )
1977  :( max( i, column_ ) ) )
1978  :( column_ ) );
1979  const size_t jend ( ( IsLower<MT>::value )
1980  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
1981  ?( min( i, column_+n_ ) )
1982  :( min( i+1UL, column_+n_ ) ) )
1983  :( column_+n_ ) );
1984 
1985  for( size_t j=jbegin; j<jend; ++j )
1986  clear( matrix_(row_+i,j) );
1987 }
1989 //*************************************************************************************************
1990 
1991 
1992 //*************************************************************************************************
2002 template< typename MT > // Type of the dense matrix
2003 inline bool Submatrix<MT,unaligned,false,true>::hasOverlap() const noexcept
2004 {
2005  BLAZE_INTERNAL_ASSERT( IsSymmetric<MT>::value || IsHermitian<MT>::value, "Invalid matrix detected" );
2006 
2007  if( ( row_ + m_ <= column_ ) || ( column_ + n_ <= row_ ) )
2008  return false;
2009  else return true;
2010 }
2012 //*************************************************************************************************
2013 
2014 
2015 
2016 
2017 //=================================================================================================
2018 //
2019 // NUMERIC FUNCTIONS
2020 //
2021 //=================================================================================================
2022 
2023 //*************************************************************************************************
2041 template< typename MT > // Type of the dense matrix
2042 inline Submatrix<MT,unaligned,false,true>& Submatrix<MT,unaligned,false,true>::transpose()
2043 {
2044  if( m_ != n_ ) {
2045  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
2046  }
2047 
2048  if( !tryAssign( matrix_, trans( *this ), row_, column_ ) ) {
2049  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
2050  }
2051 
2052  DerestrictTrait_<This> left( derestrict( *this ) );
2053  const ResultType tmp( trans( *this ) );
2054  smpAssign( left, tmp );
2055 
2056  return *this;
2057 }
2059 //*************************************************************************************************
2060 
2061 
2062 //*************************************************************************************************
2080 template< typename MT > // Type of the dense matrix
2081 inline Submatrix<MT,unaligned,false,true>& Submatrix<MT,unaligned,false,true>::ctranspose()
2082 {
2083  if( m_ != n_ ) {
2084  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
2085  }
2086 
2087  if( !tryAssign( matrix_, ctrans( *this ), row_, column_ ) ) {
2088  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
2089  }
2090 
2091  DerestrictTrait_<This> left( derestrict( *this ) );
2092  const ResultType tmp( ctrans( *this ) );
2093  smpAssign( left, tmp );
2094 
2095  return *this;
2096 }
2098 //*************************************************************************************************
2099 
2100 
2101 //*************************************************************************************************
2112 template< typename MT > // Type of the dense matrix
2113 template< typename Other > // Data type of the scalar value
2114 inline Submatrix<MT,unaligned,false,true>&
2115  Submatrix<MT,unaligned,false,true>::scale( const Other& scalar )
2116 {
2118 
2119  const size_t iend( row_ + m_ );
2120 
2121  for( size_t i=row_; i<iend; ++i )
2122  {
2123  const size_t jbegin( ( IsUpper<MT>::value )
2124  ?( ( IsStrictlyUpper<MT>::value )
2125  ?( max( i+1UL, column_ ) )
2126  :( max( i, column_ ) ) )
2127  :( column_ ) );
2128  const size_t jend ( ( IsLower<MT>::value )
2129  ?( ( IsStrictlyLower<MT>::value )
2130  ?( min( i, column_+n_ ) )
2131  :( min( i+1UL, column_+n_ ) ) )
2132  :( column_+n_ ) );
2133 
2134  for( size_t j=jbegin; j<jend; ++j )
2135  matrix_(i,j) *= scalar;
2136  }
2137 
2138  return *this;
2139 }
2141 //*************************************************************************************************
2142 
2143 
2144 
2145 
2146 //=================================================================================================
2147 //
2148 // EXPRESSION TEMPLATE EVALUATION FUNCTIONS
2149 //
2150 //=================================================================================================
2151 
2152 //*************************************************************************************************
2163 template< typename MT > // Type of the dense matrix
2164 template< typename Other > // Data type of the foreign expression
2165 inline bool Submatrix<MT,unaligned,false,true>::canAlias( const Other* alias ) const noexcept
2166 {
2167  return matrix_.isAliased( alias );
2168 }
2170 //*************************************************************************************************
2171 
2172 
2173 //*************************************************************************************************
2184 template< typename MT > // Type of the dense matrix
2185 template< typename MT2 // Data type of the foreign dense submatrix
2186  , bool AF2 // Alignment flag of the foreign dense submatrix
2187  , bool SO2 > // Storage order of the foreign dense submatrix
2188 inline bool Submatrix<MT,unaligned,false,true>::canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
2189 {
2190  return ( matrix_.isAliased( &alias->matrix_ ) &&
2191  ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
2192  ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
2193 }
2195 //*************************************************************************************************
2196 
2197 
2198 //*************************************************************************************************
2209 template< typename MT > // Type of the dense matrix
2210 template< typename Other > // Data type of the foreign expression
2211 inline bool Submatrix<MT,unaligned,false,true>::isAliased( const Other* alias ) const noexcept
2212 {
2213  return matrix_.isAliased( alias );
2214 }
2216 //*************************************************************************************************
2217 
2218 
2219 //*************************************************************************************************
2230 template< typename MT > // Type of the dense matrix
2231 template< typename MT2 // Data type of the foreign dense submatrix
2232  , bool AF2 // Alignment flag of the foreign dense submatrix
2233  , bool SO2 > // Storage order of the foreign dense submatrix
2234 inline bool Submatrix<MT,unaligned,false,true>::isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
2235 {
2236  return ( matrix_.isAliased( &alias->matrix_ ) &&
2237  ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
2238  ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
2239 }
2241 //*************************************************************************************************
2242 
2243 
2244 //*************************************************************************************************
2254 template< typename MT > // Type of the dense matrix
2255 inline bool Submatrix<MT,unaligned,false,true>::isAligned() const noexcept
2256 {
2257  return isAligned_;
2258 }
2260 //*************************************************************************************************
2261 
2262 
2263 //*************************************************************************************************
2274 template< typename MT > // Type of the dense matrix
2275 inline bool Submatrix<MT,unaligned,false,true>::canSMPAssign() const noexcept
2276 {
2277  return ( rows() * columns() >= SMP_DMATASSIGN_THRESHOLD );
2278 }
2280 //*************************************************************************************************
2281 
2282 
2283 //*************************************************************************************************
2299 template< typename MT > // Type of the dense matrix
2300 BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,false,true>::SIMDType
2301  Submatrix<MT,unaligned,false,true>::load( size_t i, size_t j ) const noexcept
2302 {
2303  if( isAligned_ )
2304  return loada( i, j );
2305  else
2306  return loadu( i, j );
2307 }
2309 //*************************************************************************************************
2310 
2311 
2312 //*************************************************************************************************
2328 template< typename MT > // Type of the dense matrix
2329 BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,false,true>::SIMDType
2330  Submatrix<MT,unaligned,false,true>::loada( size_t i, size_t j ) const noexcept
2331 {
2333 
2334  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
2335  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
2336  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
2337  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
2338 
2339  return matrix_.loada( row_+i, column_+j );
2340 }
2342 //*************************************************************************************************
2343 
2344 
2345 //*************************************************************************************************
2361 template< typename MT > // Type of the dense matrix
2362 BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,false,true>::SIMDType
2363  Submatrix<MT,unaligned,false,true>::loadu( size_t i, size_t j ) const noexcept
2364 {
2366 
2367  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
2368  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
2369  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
2370  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
2371 
2372  return matrix_.loadu( row_+i, column_+j );
2373 }
2375 //*************************************************************************************************
2376 
2377 
2378 //*************************************************************************************************
2395 template< typename MT > // Type of the dense matrix
2397  Submatrix<MT,unaligned,false,true>::store( size_t i, size_t j, const SIMDType& value ) noexcept
2398 {
2399  if( isAligned_ )
2400  storea( i, j, value );
2401  else
2402  storeu( i, j, value );
2403 }
2405 //*************************************************************************************************
2406 
2407 
2408 //*************************************************************************************************
2425 template< typename MT > // Type of the dense matrix
2427  Submatrix<MT,unaligned,false,true>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
2428 {
2430 
2431  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
2432  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
2433  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
2434  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
2435 
2436  matrix_.storea( row_+i, column_+j, value );
2437 }
2439 //*************************************************************************************************
2440 
2441 
2442 //*************************************************************************************************
2459 template< typename MT > // Type of the dense matrix
2461  Submatrix<MT,unaligned,false,true>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
2462 {
2464 
2465  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
2466  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
2467  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
2468  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
2469 
2470  matrix_.storeu( row_+i, column_+j, value );
2471 }
2473 //*************************************************************************************************
2474 
2475 
2476 //*************************************************************************************************
2493 template< typename MT > // Type of the dense matrix
2495  Submatrix<MT,unaligned,false,true>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
2496 {
2498 
2499  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
2500  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
2501  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
2502  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
2503 
2504  if( isAligned_ )
2505  matrix_.stream( row_+i, column_+j, value );
2506  else
2507  matrix_.storeu( row_+i, column_+j, value );
2508 }
2510 //*************************************************************************************************
2511 
2512 
2513 //*************************************************************************************************
2525 template< typename MT > // Type of the dense matrix
2526 template< typename MT2 > // Type of the right-hand side dense matrix
2527 inline DisableIf_< typename Submatrix<MT,unaligned,false,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
2528  Submatrix<MT,unaligned,false,true>::assign( const DenseMatrix<MT2,false>& rhs )
2529 {
2530  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2531  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2532 
2533  const size_t jpos( n_ & size_t(-2) );
2534  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
2535 
2536  for( size_t i=0UL; i<m_; ++i ) {
2537  for( size_t j=0UL; j<jpos; j+=2UL ) {
2538  matrix_(row_+i,column_+j ) = (~rhs)(i,j );
2539  matrix_(row_+i,column_+j+1UL) = (~rhs)(i,j+1UL);
2540  }
2541  if( jpos < n_ ) {
2542  matrix_(row_+i,column_+jpos) = (~rhs)(i,jpos);
2543  }
2544  }
2545 }
2547 //*************************************************************************************************
2548 
2549 
2550 //*************************************************************************************************
2562 template< typename MT > // Type of the dense matrix
2563 template< typename MT2 > // Type of the right-hand side dense matrix
2564 inline EnableIf_< typename Submatrix<MT,unaligned,false,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
2565  Submatrix<MT,unaligned,false,true>::assign( const DenseMatrix<MT2,false>& rhs )
2566 {
2568 
2569  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2570  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2571 
2572  const size_t jpos( n_ & size_t(-SIMDSIZE) );
2573  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
2574 
2575  if( useStreaming && isAligned_ &&
2576  m_*n_ > ( cacheSize / ( sizeof(ElementType) * 3UL ) ) &&
2577  !(~rhs).isAliased( &matrix_ ) )
2578  {
2579  for( size_t i=0UL; i<m_; ++i )
2580  {
2581  size_t j( 0UL );
2582  Iterator left( begin(i) );
2583  ConstIterator_<MT2> right( (~rhs).begin(i) );
2584 
2585  for( ; j<jpos; j+=SIMDSIZE ) {
2586  left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2587  }
2588  for( ; j<n_; ++j ) {
2589  *left = *right;
2590  }
2591  }
2592  }
2593  else
2594  {
2595  for( size_t i=0UL; i<m_; ++i )
2596  {
2597  size_t j( 0UL );
2598  Iterator left( begin(i) );
2599  ConstIterator_<MT2> right( (~rhs).begin(i) );
2600 
2601  for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
2602  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2603  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2604  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2605  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2606  }
2607  for( ; j<jpos; j+=SIMDSIZE ) {
2608  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2609  }
2610  for( ; j<n_; ++j ) {
2611  *left = *right; ++left; ++right;
2612  }
2613  }
2614  }
2615 }
2617 //*************************************************************************************************
2618 
2619 
2620 //*************************************************************************************************
2632 template< typename MT > // Type of the dense matrix
2633 template< typename MT2 > // Type of the right-hand side dense matrix
2634 inline void Submatrix<MT,unaligned,false,true>::assign( const DenseMatrix<MT2,true>& rhs )
2635 {
2637 
2638  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2639  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2640 
2641  constexpr size_t block( BLOCK_SIZE );
2642 
2643  for( size_t ii=0UL; ii<m_; ii+=block ) {
2644  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
2645  for( size_t jj=0UL; jj<n_; jj+=block ) {
2646  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
2647  for( size_t i=ii; i<iend; ++i ) {
2648  for( size_t j=jj; j<jend; ++j ) {
2649  matrix_(row_+i,column_+j) = (~rhs)(i,j);
2650  }
2651  }
2652  }
2653  }
2654 }
2656 //*************************************************************************************************
2657 
2658 
2659 //*************************************************************************************************
2671 template< typename MT > // Type of the dense matrix
2672 template< typename MT2 > // Type of the right-hand side sparse matrix
2673 inline void Submatrix<MT,unaligned,false,true>::assign( const SparseMatrix<MT2,false>& rhs )
2674 {
2675  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2676  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2677 
2678  for( size_t i=0UL; i<m_; ++i )
2679  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
2680  matrix_(row_+i,column_+element->index()) = element->value();
2681 }
2683 //*************************************************************************************************
2684 
2685 
2686 //*************************************************************************************************
2698 template< typename MT > // Type of the dense matrix
2699 template< typename MT2 > // Type of the right-hand side sparse matrix
2700 inline void Submatrix<MT,unaligned,false,true>::assign( const SparseMatrix<MT2,true>& rhs )
2701 {
2703 
2704  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2705  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2706 
2707  for( size_t j=0UL; j<n_; ++j )
2708  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
2709  matrix_(row_+element->index(),column_+j) = element->value();
2710 }
2712 //*************************************************************************************************
2713 
2714 
2715 //*************************************************************************************************
2727 template< typename MT > // Type of the dense matrix
2728 template< typename MT2 > // Type of the right-hand side dense matrix
2729 inline DisableIf_< typename Submatrix<MT,unaligned,false,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
2730  Submatrix<MT,unaligned,false,true>::addAssign( const DenseMatrix<MT2,false>& rhs )
2731 {
2732  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2733  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2734 
2735  const size_t jpos( n_ & size_t(-2) );
2736  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
2737 
2738  for( size_t i=0UL; i<m_; ++i )
2739  {
2740  if( IsDiagonal<MT2>::value ) {
2741  matrix_(row_+i,column_+i) += (~rhs)(i,i);
2742  }
2743  else {
2744  for( size_t j=0UL; j<jpos; j+=2UL ) {
2745  matrix_(row_+i,column_+j ) += (~rhs)(i,j );
2746  matrix_(row_+i,column_+j+1UL) += (~rhs)(i,j+1UL);
2747  }
2748  if( jpos < n_ ) {
2749  matrix_(row_+i,column_+jpos) += (~rhs)(i,jpos);
2750  }
2751  }
2752  }
2753 }
2755 //*************************************************************************************************
2756 
2757 
2758 //*************************************************************************************************
2770 template< typename MT > // Type of the dense matrix
2771 template< typename MT2 > // Type of the right-hand side dense matrix
2772 inline EnableIf_< typename Submatrix<MT,unaligned,false,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
2773  Submatrix<MT,unaligned,false,true>::addAssign( const DenseMatrix<MT2,false>& rhs )
2774 {
2776 
2777  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2778  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2779 
2780  for( size_t i=0UL; i<m_; ++i )
2781  {
2782  const size_t jbegin( ( IsUpper<MT2>::value )
2783  ?( ( IsStrictlyUpper<MT2>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
2784  :( 0UL ) );
2785  const size_t jend ( ( IsLower<MT2>::value )
2786  ?( IsStrictlyLower<MT2>::value ? i : i+1UL )
2787  :( n_ ) );
2788  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
2789 
2790  const size_t jpos( jend & size_t(-SIMDSIZE) );
2791  BLAZE_INTERNAL_ASSERT( ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
2792 
2793  size_t j( jbegin );
2794  Iterator left( begin(i) + jbegin );
2795  ConstIterator_<MT2> right( (~rhs).begin(i) + jbegin );
2796 
2797  for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
2798  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2799  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2800  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2801  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2802  }
2803  for( ; j<jpos; j+=SIMDSIZE ) {
2804  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2805  }
2806  for( ; j<jend; ++j ) {
2807  *left += *right; ++left; ++right;
2808  }
2809  }
2810 }
2812 //*************************************************************************************************
2813 
2814 
2815 //*************************************************************************************************
2827 template< typename MT > // Type of the dense matrix
2828 template< typename MT2 > // Type of the right-hand side dense matrix
2829 inline void Submatrix<MT,unaligned,false,true>::addAssign( const DenseMatrix<MT2,true>& rhs )
2830 {
2832 
2833  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2834  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2835 
2836  constexpr size_t block( BLOCK_SIZE );
2837 
2838  for( size_t ii=0UL; ii<m_; ii+=block ) {
2839  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
2840  for( size_t jj=0UL; jj<n_; jj+=block ) {
2841  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
2842  for( size_t i=ii; i<iend; ++i ) {
2843  for( size_t j=jj; j<jend; ++j ) {
2844  matrix_(row_+i,column_+j) += (~rhs)(i,j);
2845  }
2846  }
2847  }
2848  }
2849 }
2851 //*************************************************************************************************
2852 
2853 
2854 //*************************************************************************************************
2866 template< typename MT > // Type of the dense matrix
2867 template< typename MT2 > // Type of the right-hand side sparse matrix
2868 inline void Submatrix<MT,unaligned,false,true>::addAssign( const SparseMatrix<MT2,false>& rhs )
2869 {
2870  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2871  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2872 
2873  for( size_t i=0UL; i<m_; ++i )
2874  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
2875  matrix_(row_+i,column_+element->index()) += element->value();
2876 }
2878 //*************************************************************************************************
2879 
2880 
2881 //*************************************************************************************************
2893 template< typename MT > // Type of the dense matrix
2894 template< typename MT2 > // Type of the right-hand side sparse matrix
2895 inline void Submatrix<MT,unaligned,false,true>::addAssign( const SparseMatrix<MT2,true>& rhs )
2896 {
2898 
2899  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2900  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2901 
2902  for( size_t j=0UL; j<n_; ++j )
2903  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
2904  matrix_(row_+element->index(),column_+j) += element->value();
2905 }
2907 //*************************************************************************************************
2908 
2909 
2910 //*************************************************************************************************
2922 template< typename MT > // Type of the dense matrix
2923 template< typename MT2 > // Type of the right-hand side dense matrix
2924 inline DisableIf_< typename Submatrix<MT,unaligned,false,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
2925  Submatrix<MT,unaligned,false,true>::subAssign( const DenseMatrix<MT2,false>& rhs )
2926 {
2927  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2928  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2929 
2930  const size_t jpos( n_ & size_t(-2) );
2931  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
2932 
2933  for( size_t i=0UL; i<m_; ++i )
2934  {
2935  if( IsDiagonal<MT2>::value ) {
2936  matrix_(row_+i,column_+i) -= (~rhs)(i,i);
2937  }
2938  else {
2939  for( size_t j=0UL; j<jpos; j+=2UL ) {
2940  matrix_(row_+i,column_+j ) -= (~rhs)(i,j );
2941  matrix_(row_+i,column_+j+1UL) -= (~rhs)(i,j+1UL);
2942  }
2943  if( jpos < n_ ) {
2944  matrix_(row_+i,column_+jpos) -= (~rhs)(i,jpos);
2945  }
2946  }
2947  }
2948 }
2950 //*************************************************************************************************
2951 
2952 
2953 //*************************************************************************************************
2965 template< typename MT > // Type of the dense matrix
2966 template< typename MT2 > // Type of the right-hand side dense matrix
2967 inline EnableIf_< typename Submatrix<MT,unaligned,false,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
2968  Submatrix<MT,unaligned,false,true>::subAssign( const DenseMatrix<MT2,false>& rhs )
2969 {
2971 
2972  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2973  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2974 
2975  for( size_t i=0UL; i<m_; ++i )
2976  {
2977  const size_t jbegin( ( IsUpper<MT2>::value )
2978  ?( ( IsStrictlyUpper<MT2>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
2979  :( 0UL ) );
2980  const size_t jend ( ( IsLower<MT2>::value )
2981  ?( IsStrictlyLower<MT2>::value ? i : i+1UL )
2982  :( n_ ) );
2983  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
2984 
2985  const size_t jpos( jend & size_t(-SIMDSIZE) );
2986  BLAZE_INTERNAL_ASSERT( ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
2987 
2988  size_t j( jbegin );
2989  Iterator left( begin(i) + jbegin );
2990  ConstIterator_<MT2> right( (~rhs).begin(i) + jbegin );
2991 
2992  for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
2993  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2994  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2995  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2996  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2997  }
2998  for( ; j<jpos; j+=SIMDSIZE ) {
2999  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3000  }
3001  for( ; j<jend; ++j ) {
3002  *left -= *right; ++left; ++right;
3003  }
3004  }
3005 }
3007 //*************************************************************************************************
3008 
3009 
3010 //*************************************************************************************************
3022 template< typename MT > // Type of the dense matrix
3023 template< typename MT2 > // Type of the right-hand side dense matrix
3024 inline void Submatrix<MT,unaligned,false,true>::subAssign( const DenseMatrix<MT2,true>& rhs )
3025 {
3027 
3028  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
3029  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
3030 
3031  constexpr size_t block( BLOCK_SIZE );
3032 
3033  for( size_t ii=0UL; ii<m_; ii+=block ) {
3034  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
3035  for( size_t jj=0UL; jj<n_; jj+=block ) {
3036  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
3037  for( size_t i=ii; i<iend; ++i ) {
3038  for( size_t j=jj; j<jend; ++j ) {
3039  matrix_(row_+i,column_+j) -= (~rhs)(i,j);
3040  }
3041  }
3042  }
3043  }
3044 }
3046 //*************************************************************************************************
3047 
3048 
3049 //*************************************************************************************************
3061 template< typename MT > // Type of the dense matrix
3062 template< typename MT2 > // Type of the right-hand side sparse matrix
3063 inline void Submatrix<MT,unaligned,false,true>::subAssign( const SparseMatrix<MT2,false>& rhs )
3064 {
3065  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
3066  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
3067 
3068  for( size_t i=0UL; i<m_; ++i )
3069  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
3070  matrix_(row_+i,column_+element->index()) -= element->value();
3071 }
3073 //*************************************************************************************************
3074 
3075 
3076 //*************************************************************************************************
3088 template< typename MT > // Type of the dense matrix
3089 template< typename MT2 > // Type of the right-hand side sparse matrix
3090 inline void Submatrix<MT,unaligned,false,true>::subAssign( const SparseMatrix<MT2,true>& rhs )
3091 {
3093 
3094  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
3095  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
3096 
3097  for( size_t j=0UL; j<n_; ++j )
3098  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
3099  matrix_(row_+element->index(),column_+j) -= element->value();
3100 }
3102 //*************************************************************************************************
3103 
3104 
3105 
3106 
3107 
3108 
3109 
3110 
3111 //=================================================================================================
3112 //
3113 // CLASS TEMPLATE SPECIALIZATION FOR UNALIGNED COLUMN-MAJOR DENSE SUBMATRICES
3114 //
3115 //=================================================================================================
3116 
3117 //*************************************************************************************************
3125 template< typename MT > // Type of the dense matrix
3126 class Submatrix<MT,unaligned,true,true>
3127  : public DenseMatrix< Submatrix<MT,unaligned,true,true>, true >
3128  , private View
3129 {
3130  private:
3131  //**Type definitions****************************************************************************
3133  typedef If_< IsExpression<MT>, MT, MT& > Operand;
3134  //**********************************************************************************************
3135 
3136  public:
3137  //**Type definitions****************************************************************************
3138  typedef Submatrix<MT,unaligned,true,true> This;
3139  typedef DenseMatrix<This,true> BaseType;
3140  typedef SubmatrixTrait_<MT> ResultType;
3141  typedef OppositeType_<ResultType> OppositeType;
3142  typedef TransposeType_<ResultType> TransposeType;
3143  typedef ElementType_<MT> ElementType;
3144  typedef SIMDTrait_<ElementType> SIMDType;
3145  typedef ReturnType_<MT> ReturnType;
3146  typedef const Submatrix& CompositeType;
3147 
3149  typedef ConstReference_<MT> ConstReference;
3150 
3152  typedef If_< IsConst<MT>, ConstReference, Reference_<MT> > Reference;
3153 
3155  typedef const ElementType* ConstPointer;
3156 
3158  typedef If_< Or< IsConst<MT>, Not< HasMutableDataAccess<MT> > >, ConstPointer, ElementType* > Pointer;
3159  //**********************************************************************************************
3160 
3161  //**SubmatrixIterator class definition**********************************************************
3164  template< typename IteratorType > // Type of the dense matrix iterator
3165  class SubmatrixIterator
3166  {
3167  public:
3168  //**Type definitions*************************************************************************
3170  typedef typename std::iterator_traits<IteratorType>::iterator_category IteratorCategory;
3171 
3173  typedef typename std::iterator_traits<IteratorType>::value_type ValueType;
3174 
3176  typedef typename std::iterator_traits<IteratorType>::pointer PointerType;
3177 
3179  typedef typename std::iterator_traits<IteratorType>::reference ReferenceType;
3180 
3182  typedef typename std::iterator_traits<IteratorType>::difference_type DifferenceType;
3183 
3184  // STL iterator requirements
3185  typedef IteratorCategory iterator_category;
3186  typedef ValueType value_type;
3187  typedef PointerType pointer;
3188  typedef ReferenceType reference;
3189  typedef DifferenceType difference_type;
3190  //*******************************************************************************************
3191 
3192  //**Constructor******************************************************************************
3195  inline SubmatrixIterator()
3196  : iterator_ ( ) // Iterator to the current submatrix element
3197  , isAligned_( false ) // Memory alignment flag
3198  {}
3199  //*******************************************************************************************
3200 
3201  //**Constructor******************************************************************************
3209  inline SubmatrixIterator( IteratorType iterator, bool isMemoryAligned )
3210  : iterator_ ( iterator ) // Iterator to the current submatrix element
3211  , isAligned_( isMemoryAligned ) // Memory alignment flag
3212  {}
3213  //*******************************************************************************************
3214 
3215  //**Constructor******************************************************************************
3220  template< typename IteratorType2 >
3221  inline SubmatrixIterator( const SubmatrixIterator<IteratorType2>& it )
3222  : iterator_ ( it.base() ) // Iterator to the current submatrix element
3223  , isAligned_( it.isAligned() ) // Memory alignment flag
3224  {}
3225  //*******************************************************************************************
3226 
3227  //**Addition assignment operator*************************************************************
3233  inline SubmatrixIterator& operator+=( size_t inc ) {
3234  iterator_ += inc;
3235  return *this;
3236  }
3237  //*******************************************************************************************
3238 
3239  //**Subtraction assignment operator**********************************************************
3245  inline SubmatrixIterator& operator-=( size_t dec ) {
3246  iterator_ -= dec;
3247  return *this;
3248  }
3249  //*******************************************************************************************
3250 
3251  //**Prefix increment operator****************************************************************
3256  inline SubmatrixIterator& operator++() {
3257  ++iterator_;
3258  return *this;
3259  }
3260  //*******************************************************************************************
3261 
3262  //**Postfix increment operator***************************************************************
3267  inline const SubmatrixIterator operator++( int ) {
3268  return SubmatrixIterator( iterator_++, isAligned_ );
3269  }
3270  //*******************************************************************************************
3271 
3272  //**Prefix decrement operator****************************************************************
3277  inline SubmatrixIterator& operator--() {
3278  --iterator_;
3279  return *this;
3280  }
3281  //*******************************************************************************************
3282 
3283  //**Postfix decrement operator***************************************************************
3288  inline const SubmatrixIterator operator--( int ) {
3289  return SubmatrixIterator( iterator_--, isAligned_ );
3290  }
3291  //*******************************************************************************************
3292 
3293  //**Element access operator******************************************************************
3298  inline ReferenceType operator*() const {
3299  return *iterator_;
3300  }
3301  //*******************************************************************************************
3302 
3303  //**Load function****************************************************************************
3313  inline SIMDType load() const noexcept {
3314  if( isAligned_ )
3315  return loada();
3316  else
3317  return loadu();
3318  }
3319  //*******************************************************************************************
3320 
3321  //**Loada function***************************************************************************
3331  inline SIMDType loada() const noexcept {
3332  return iterator_.loada();
3333  }
3334  //*******************************************************************************************
3335 
3336  //**Loadu function***************************************************************************
3346  inline SIMDType loadu() const noexcept {
3347  return iterator_.loadu();
3348  }
3349  //*******************************************************************************************
3350 
3351  //**Store function***************************************************************************
3362  inline void store( const SIMDType& value ) const {
3363  storeu( value );
3364  }
3365  //*******************************************************************************************
3366 
3367  //**Storea function**************************************************************************
3378  inline void storea( const SIMDType& value ) const {
3379  iterator_.storea( value );
3380  }
3381  //*******************************************************************************************
3382 
3383  //**Storeu function**************************************************************************
3394  inline void storeu( const SIMDType& value ) const {
3395  if( isAligned_ ) {
3396  iterator_.storea( value );
3397  }
3398  else {
3399  iterator_.storeu( value );
3400  }
3401  }
3402  //*******************************************************************************************
3403 
3404  //**Stream function**************************************************************************
3415  inline void stream( const SIMDType& value ) const {
3416  iterator_.stream( value );
3417  }
3418  //*******************************************************************************************
3419 
3420  //**Equality operator************************************************************************
3426  inline bool operator==( const SubmatrixIterator& rhs ) const {
3427  return iterator_ == rhs.iterator_;
3428  }
3429  //*******************************************************************************************
3430 
3431  //**Inequality operator**********************************************************************
3437  inline bool operator!=( const SubmatrixIterator& rhs ) const {
3438  return iterator_ != rhs.iterator_;
3439  }
3440  //*******************************************************************************************
3441 
3442  //**Less-than operator***********************************************************************
3448  inline bool operator<( const SubmatrixIterator& rhs ) const {
3449  return iterator_ < rhs.iterator_;
3450  }
3451  //*******************************************************************************************
3452 
3453  //**Greater-than operator********************************************************************
3459  inline bool operator>( const SubmatrixIterator& rhs ) const {
3460  return iterator_ > rhs.iterator_;
3461  }
3462  //*******************************************************************************************
3463 
3464  //**Less-or-equal-than operator**************************************************************
3470  inline bool operator<=( const SubmatrixIterator& rhs ) const {
3471  return iterator_ <= rhs.iterator_;
3472  }
3473  //*******************************************************************************************
3474 
3475  //**Greater-or-equal-than operator***********************************************************
3481  inline bool operator>=( const SubmatrixIterator& rhs ) const {
3482  return iterator_ >= rhs.iterator_;
3483  }
3484  //*******************************************************************************************
3485 
3486  //**Subtraction operator*********************************************************************
3492  inline DifferenceType operator-( const SubmatrixIterator& rhs ) const {
3493  return iterator_ - rhs.iterator_;
3494  }
3495  //*******************************************************************************************
3496 
3497  //**Addition operator************************************************************************
3504  friend inline const SubmatrixIterator operator+( const SubmatrixIterator& it, size_t inc ) {
3505  return SubmatrixIterator( it.iterator_ + inc, it.isAligned_ );
3506  }
3507  //*******************************************************************************************
3508 
3509  //**Addition operator************************************************************************
3516  friend inline const SubmatrixIterator operator+( size_t inc, const SubmatrixIterator& it ) {
3517  return SubmatrixIterator( it.iterator_ + inc, it.isAligned_ );
3518  }
3519  //*******************************************************************************************
3520 
3521  //**Subtraction operator*********************************************************************
3528  friend inline const SubmatrixIterator operator-( const SubmatrixIterator& it, size_t dec ) {
3529  return SubmatrixIterator( it.iterator_ - dec, it.isAligned_ );
3530  }
3531  //*******************************************************************************************
3532 
3533  //**Base function****************************************************************************
3538  inline IteratorType base() const {
3539  return iterator_;
3540  }
3541  //*******************************************************************************************
3542 
3543  //**IsAligned function***********************************************************************
3548  inline bool isAligned() const noexcept {
3549  return isAligned_;
3550  }
3551  //*******************************************************************************************
3552 
3553  private:
3554  //**Member variables*************************************************************************
3555  IteratorType iterator_;
3556  bool isAligned_;
3557  //*******************************************************************************************
3558  };
3559  //**********************************************************************************************
3560 
3561  //**Type definitions****************************************************************************
3563  typedef SubmatrixIterator< ConstIterator_<MT> > ConstIterator;
3564 
3566  typedef If_< IsConst<MT>, ConstIterator, SubmatrixIterator< Iterator_<MT> > > Iterator;
3567  //**********************************************************************************************
3568 
3569  //**Compilation flags***************************************************************************
3571  enum : bool { simdEnabled = MT::simdEnabled };
3572 
3574  enum : bool { smpAssignable = MT::smpAssignable };
3575  //**********************************************************************************************
3576 
3577  //**Constructors********************************************************************************
3580  explicit inline Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n );
3581  // No explicitly declared copy constructor.
3583  //**********************************************************************************************
3584 
3585  //**Destructor**********************************************************************************
3586  // No explicitly declared destructor.
3587  //**********************************************************************************************
3588 
3589  //**Data access functions***********************************************************************
3592  inline Reference operator()( size_t i, size_t j );
3593  inline ConstReference operator()( size_t i, size_t j ) const;
3594  inline Reference at( size_t i, size_t j );
3595  inline ConstReference at( size_t i, size_t j ) const;
3596  inline Pointer data () noexcept;
3597  inline ConstPointer data () const noexcept;
3598  inline Pointer data ( size_t j ) noexcept;
3599  inline ConstPointer data ( size_t j ) const noexcept;
3600  inline Iterator begin ( size_t j );
3601  inline ConstIterator begin ( size_t j ) const;
3602  inline ConstIterator cbegin( size_t j ) const;
3603  inline Iterator end ( size_t j );
3604  inline ConstIterator end ( size_t j ) const;
3605  inline ConstIterator cend ( size_t j ) const;
3607  //**********************************************************************************************
3608 
3609  //**Assignment operators************************************************************************
3612  inline Submatrix& operator=( const ElementType& rhs );
3613  inline Submatrix& operator=( initializer_list< initializer_list<ElementType> > list );
3614  inline Submatrix& operator=( const Submatrix& rhs );
3615 
3616  template< typename MT2, bool SO >
3617  inline Submatrix& operator=( const Matrix<MT2,SO>& rhs );
3618 
3619  template< typename MT2, bool SO >
3620  inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
3621  operator+=( const Matrix<MT2,SO>& rhs );
3622 
3623  template< typename MT2, bool SO >
3624  inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
3625  operator+=( const Matrix<MT2,SO>& rhs );
3626 
3627  template< typename MT2, bool SO >
3628  inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
3629  operator-=( const Matrix<MT2,SO>& rhs );
3630 
3631  template< typename MT2, bool SO >
3632  inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
3633  operator-=( const Matrix<MT2,SO>& rhs );
3634 
3635  template< typename MT2, bool SO >
3636  inline Submatrix& operator*=( const Matrix<MT2,SO>& rhs );
3637 
3638  template< typename Other >
3639  inline EnableIf_< IsNumeric<Other>, Submatrix >& operator*=( Other rhs );
3640 
3641  template< typename Other >
3642  inline EnableIf_< IsNumeric<Other>, Submatrix >& operator/=( Other rhs );
3644  //**********************************************************************************************
3645 
3646  //**Utility functions***************************************************************************
3649  inline size_t row() const noexcept;
3650  inline size_t rows() const noexcept;
3651  inline size_t column() const noexcept;
3652  inline size_t columns() const noexcept;
3653  inline size_t spacing() const noexcept;
3654  inline size_t capacity() const noexcept;
3655  inline size_t capacity( size_t i ) const noexcept;
3656  inline size_t nonZeros() const;
3657  inline size_t nonZeros( size_t i ) const;
3658  inline void reset();
3659  inline void reset( size_t i );
3661  //**********************************************************************************************
3662 
3663  //**Numeric functions***************************************************************************
3666  inline Submatrix& transpose();
3667  inline Submatrix& ctranspose();
3668 
3669  template< typename Other > inline Submatrix& scale( const Other& scalar );
3671  //**********************************************************************************************
3672 
3673  private:
3674  //**********************************************************************************************
3676  template< typename MT2 >
3677  struct VectorizedAssign {
3678  enum : bool { value = useOptimizedKernels &&
3679  simdEnabled && MT2::simdEnabled &&
3680  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value };
3681  };
3682  //**********************************************************************************************
3683 
3684  //**********************************************************************************************
3686  template< typename MT2 >
3687  struct VectorizedAddAssign {
3688  enum : bool { value = useOptimizedKernels &&
3689  simdEnabled && MT2::simdEnabled &&
3690  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
3691  HasSIMDAdd< ElementType, ElementType_<MT2> >::value &&
3692  !IsDiagonal<MT2>::value };
3693  };
3694  //**********************************************************************************************
3695 
3696  //**********************************************************************************************
3698  template< typename MT2 >
3699  struct VectorizedSubAssign {
3700  enum : bool { value = useOptimizedKernels &&
3701  simdEnabled && MT2::simdEnabled &&
3702  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
3703  HasSIMDSub< ElementType, ElementType_<MT2> >::value &&
3704  !IsDiagonal<MT2>::value };
3705  };
3706  //**********************************************************************************************
3707 
3708  //**SIMD properties*****************************************************************************
3710  enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
3711  //**********************************************************************************************
3712 
3713  public:
3714  //**Expression template evaluation functions****************************************************
3717  template< typename Other >
3718  inline bool canAlias( const Other* alias ) const noexcept;
3719 
3720  template< typename MT2, bool AF2, bool SO2 >
3721  inline bool canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
3722 
3723  template< typename Other >
3724  inline bool isAliased( const Other* alias ) const noexcept;
3725 
3726  template< typename MT2, bool AF2, bool SO2 >
3727  inline bool isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
3728 
3729  inline bool isAligned () const noexcept;
3730  inline bool canSMPAssign() const noexcept;
3731 
3732  BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
3733  BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
3734  BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
3735 
3736  BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
3737  BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
3738  BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
3739  BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
3740 
3741  template< typename MT2 >
3742  inline DisableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,true>& rhs );
3743 
3744  template< typename MT2 >
3745  inline EnableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,true>& rhs );
3746 
3747  template< typename MT2 > inline void assign( const DenseMatrix<MT2,false>& rhs );
3748  template< typename MT2 > inline void assign( const SparseMatrix<MT2,true>& rhs );
3749  template< typename MT2 > inline void assign( const SparseMatrix<MT2,false>& rhs );
3750 
3751  template< typename MT2 >
3752  inline DisableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,true>& rhs );
3753 
3754  template< typename MT2 >
3755  inline EnableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,true>& rhs );
3756 
3757  template< typename MT2 > inline void addAssign( const DenseMatrix<MT2,false>& rhs );
3758  template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,true>& rhs );
3759  template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,false>& rhs );
3760 
3761  template< typename MT2 >
3762  inline DisableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,true>& rhs );
3763 
3764  template< typename MT2 >
3765  inline EnableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,true>& rhs );
3766 
3767  template< typename MT2 > inline void subAssign( const DenseMatrix<MT2,false>& rhs );
3768  template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,true>& rhs );
3769  template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,false>& rhs );
3771  //**********************************************************************************************
3772 
3773  private:
3774  //**Utility functions***************************************************************************
3777  inline bool hasOverlap() const noexcept;
3779  //**********************************************************************************************
3780 
3781  //**Member variables****************************************************************************
3784  Operand matrix_;
3785  const size_t row_;
3786  const size_t column_;
3787  const size_t m_;
3788  const size_t n_;
3789  const bool isAligned_;
3790 
3797  //**********************************************************************************************
3798 
3799  //**Friend declarations*************************************************************************
3800  template< typename MT2, bool AF2, bool SO2, bool DF2 > friend class Submatrix;
3801 
3802  template< bool AF1, typename MT2, bool AF2, bool SO2, bool DF2 >
3803  friend const Submatrix<MT2,AF1,SO2,DF2>
3804  submatrix( const Submatrix<MT2,AF2,SO2,DF2>& sm, size_t row, size_t column, size_t m, size_t n );
3805 
3806  template< typename MT2, bool AF2, bool SO2, bool DF2 >
3807  friend bool isIntact( const Submatrix<MT2,AF2,SO2,DF2>& sm ) noexcept;
3808 
3809  template< typename MT2, bool AF2, bool SO2, bool DF2 >
3810  friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Matrix<MT2,SO2>& b ) noexcept;
3811 
3812  template< typename MT2, bool AF2, bool SO2, bool DF2 >
3813  friend bool isSame( const Matrix<MT2,SO2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
3814 
3815  template< typename MT2, bool AF2, bool SO2, bool DF2 >
3816  friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
3817 
3818  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
3819  friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
3820  size_t row, size_t column );
3821 
3822  template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
3823  friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
3824  size_t row, size_t column );
3825 
3826  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
3827  friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
3828  size_t row, size_t column );
3829 
3830  template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
3831  friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
3832  size_t row, size_t column );
3833 
3834  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
3835  friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
3836  size_t row, size_t column );
3837 
3838  template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
3839  friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
3840  size_t row, size_t column );
3841 
3842  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
3843  friend bool tryMultAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
3844  size_t row, size_t column );
3845 
3846  template< typename MT2, bool AF2, bool SO2, bool DF2 >
3847  friend DerestrictTrait_< Submatrix<MT2,AF2,SO2,DF2> > derestrict( Submatrix<MT2,AF2,SO2,DF2>& sm );
3848  //**********************************************************************************************
3849 
3850  //**Compile time checks*************************************************************************
3858  //**********************************************************************************************
3859 };
3861 //*************************************************************************************************
3862 
3863 
3864 
3865 
3866 //=================================================================================================
3867 //
3868 // CONSTRUCTOR
3869 //
3870 //=================================================================================================
3871 
3872 //*************************************************************************************************
3886 template< typename MT > // Type of the dense matrix
3887 inline Submatrix<MT,unaligned,true,true>::Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n )
3888  : matrix_ ( matrix ) // The dense matrix containing the submatrix
3889  , row_ ( rindex ) // The first row of the submatrix
3890  , column_ ( cindex ) // The first column of the submatrix
3891  , m_ ( m ) // The number of rows of the submatrix
3892  , n_ ( n ) // The number of columns of the submatrix
3893  , isAligned_( simdEnabled && matrix.data() != nullptr && checkAlignment( data() ) &&
3894  ( n < 2UL || ( matrix.spacing() & size_t(-SIMDSIZE) ) == 0UL ) )
3895 {
3896  if( ( row_ + m_ > matrix_.rows() ) || ( column_ + n_ > matrix_.columns() ) ) {
3897  BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix specification" );
3898  }
3899 }
3901 //*************************************************************************************************
3902 
3903 
3904 
3905 
3906 //=================================================================================================
3907 //
3908 // DATA ACCESS FUNCTIONS
3909 //
3910 //=================================================================================================
3911 
3912 //*************************************************************************************************
3923 template< typename MT > // Type of the dense matrix
3925  Submatrix<MT,unaligned,true,true>::operator()( size_t i, size_t j )
3926 {
3927  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
3928  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
3929 
3930  return matrix_(row_+i,column_+j);
3931 }
3933 //*************************************************************************************************
3934 
3935 
3936 //*************************************************************************************************
3947 template< typename MT > // Type of the dense matrix
3949  Submatrix<MT,unaligned,true,true>::operator()( size_t i, size_t j ) const
3950 {
3951  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
3952  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
3953 
3954  return const_cast<const MT&>( matrix_ )(row_+i,column_+j);
3955 }
3957 //*************************************************************************************************
3958 
3959 
3960 //*************************************************************************************************
3972 template< typename MT > // Type of the dense matrix
3974  Submatrix<MT,unaligned,true,true>::at( size_t i, size_t j )
3975 {
3976  if( i >= rows() ) {
3977  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
3978  }
3979  if( j >= columns() ) {
3980  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
3981  }
3982  return (*this)(i,j);
3983 }
3985 //*************************************************************************************************
3986 
3987 
3988 //*************************************************************************************************
4000 template< typename MT > // Type of the dense matrix
4002  Submatrix<MT,unaligned,true,true>::at( size_t i, size_t j ) const
4003 {
4004  if( i >= rows() ) {
4005  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
4006  }
4007  if( j >= columns() ) {
4008  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
4009  }
4010  return (*this)(i,j);
4011 }
4013 //*************************************************************************************************
4014 
4015 
4016 //*************************************************************************************************
4026 template< typename MT > // Type of the dense matrix
4027 inline typename Submatrix<MT,unaligned,true,true>::Pointer
4028  Submatrix<MT,unaligned,true,true>::data() noexcept
4029 {
4030  return matrix_.data() + row_ + column_*spacing();
4031 }
4033 //*************************************************************************************************
4034 
4035 
4036 //*************************************************************************************************
4046 template< typename MT > // Type of the dense matrix
4047 inline typename Submatrix<MT,unaligned,true,true>::ConstPointer
4048  Submatrix<MT,unaligned,true,true>::data() const noexcept
4049 {
4050  return matrix_.data() + row_ + column_*spacing();
4051 }
4053 //*************************************************************************************************
4054 
4055 
4056 //*************************************************************************************************
4065 template< typename MT > // Type of the dense matrix
4066 inline typename Submatrix<MT,unaligned,true,true>::Pointer
4067  Submatrix<MT,unaligned,true,true>::data( size_t j ) noexcept
4068 {
4069  return matrix_.data() + row_ + (column_+j)*spacing();
4070 }
4072 //*************************************************************************************************
4073 
4074 
4075 //*************************************************************************************************
4084 template< typename MT > // Type of the dense matrix
4085 inline typename Submatrix<MT,unaligned,true,true>::ConstPointer
4086  Submatrix<MT,unaligned,true,true>::data( size_t j ) const noexcept
4087 {
4088  return matrix_.data() + row_ + (column_+j)*spacing();
4089 }
4091 //*************************************************************************************************
4092 
4093 
4094 //*************************************************************************************************
4101 template< typename MT > // Type of the dense matrix
4104 {
4105  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
4106  return Iterator( matrix_.begin( column_ + j ) + row_, isAligned_ );
4107 }
4109 //*************************************************************************************************
4110 
4111 
4112 //*************************************************************************************************
4119 template< typename MT > // Type of the dense matrix
4122 {
4123  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
4124  return ConstIterator( matrix_.cbegin( column_ + j ) + row_, isAligned_ );
4125 }
4127 //*************************************************************************************************
4128 
4129 
4130 //*************************************************************************************************
4137 template< typename MT > // Type of the dense matrix
4140 {
4141  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
4142  return ConstIterator( matrix_.cbegin( column_ + j ) + row_, isAligned_ );
4143 }
4145 //*************************************************************************************************
4146 
4147 
4148 //*************************************************************************************************
4155 template< typename MT > // Type of the dense matrix
4158 {
4159  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
4160  return Iterator( matrix_.begin( column_ + j ) + row_ + m_, isAligned_ );
4161 }
4163 //*************************************************************************************************
4164 
4165 
4166 //*************************************************************************************************
4173 template< typename MT > // Type of the dense matrix
4175  Submatrix<MT,unaligned,true,true>::end( size_t j ) const
4176 {
4177  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
4178  return ConstIterator( matrix_.cbegin( column_ + j ) + row_ + m_, isAligned_ );
4179 }
4181 //*************************************************************************************************
4182 
4183 
4184 //*************************************************************************************************
4191 template< typename MT > // Type of the dense matrix
4193  Submatrix<MT,unaligned,true,true>::cend( size_t j ) const
4194 {
4195  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
4196  return ConstIterator( matrix_.cbegin( column_ + j ) + row_ + m_, isAligned_ );
4197 }
4199 //*************************************************************************************************
4200 
4201 
4202 
4203 
4204 //=================================================================================================
4205 //
4206 // ASSIGNMENT OPERATORS
4207 //
4208 //=================================================================================================
4209 
4210 //*************************************************************************************************
4221 template< typename MT > // Type of the dense matrix
4222 inline Submatrix<MT,unaligned,true,true>&
4223  Submatrix<MT,unaligned,true,true>::operator=( const ElementType& rhs )
4224 {
4225  const size_t jend( column_ + n_ );
4226 
4227  for( size_t j=column_; j<jend; ++j )
4228  {
4229  const size_t ibegin( ( IsLower<MT>::value )
4230  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
4231  ?( max( j+1UL, row_ ) )
4232  :( max( j, row_ ) ) )
4233  :( row_ ) );
4234  const size_t iend ( ( IsUpper<MT>::value )
4235  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
4236  ?( min( j, row_+m_ ) )
4237  :( min( j+1UL, row_+m_ ) ) )
4238  :( row_+m_ ) );
4239 
4240  for( size_t i=ibegin; i<iend; ++i )
4241  matrix_(i,j) = rhs;
4242  }
4243 
4244  return *this;
4245 }
4247 //*************************************************************************************************
4248 
4249 
4250 //*************************************************************************************************
4263 template< typename MT > // Type of the dense matrix
4264 inline Submatrix<MT,unaligned,true,true>&
4265  Submatrix<MT,unaligned,true,true>::operator=( initializer_list< initializer_list<ElementType> > list )
4266 {
4267  if( list.size() != rows() || determineColumns( list ) > columns() ) {
4268  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to submatrix" );
4269  }
4270 
4271  size_t i( 0UL );
4272 
4273  for( const auto& rowList : list ) {
4274  size_t j( 0UL );
4275  for( const auto& element : rowList ) {
4276  matrix_(row_+i,column_+j) = element;
4277  ++j;
4278  }
4279  for( ; j<n_; ++j ) {
4280  matrix_(row_+i,column_+j) = ElementType();
4281  }
4282  ++i;
4283  }
4284 
4285  return *this;
4286 }
4288 //*************************************************************************************************
4289 
4290 
4291 //*************************************************************************************************
4306 template< typename MT > // Type of the dense matrix
4307 inline Submatrix<MT,unaligned,true,true>&
4308  Submatrix<MT,unaligned,true,true>::operator=( const Submatrix& rhs )
4309 {
4312 
4313  if( this == &rhs || ( &matrix_ == &rhs.matrix_ && row_ == rhs.row_ && column_ == rhs.column_ ) )
4314  return *this;
4315 
4316  if( rows() != rhs.rows() || columns() != rhs.columns() ) {
4317  BLAZE_THROW_INVALID_ARGUMENT( "Submatrix sizes do not match" );
4318  }
4319 
4320  if( !tryAssign( matrix_, rhs, row_, column_ ) ) {
4321  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4322  }
4323 
4324  DerestrictTrait_<This> left( derestrict( *this ) );
4325 
4326  if( rhs.canAlias( &matrix_ ) ) {
4327  const ResultType tmp( rhs );
4328  smpAssign( left, tmp );
4329  }
4330  else {
4331  smpAssign( left, rhs );
4332  }
4333 
4334  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4335 
4336  return *this;
4337 }
4339 //*************************************************************************************************
4340 
4341 
4342 //*************************************************************************************************
4357 template< typename MT > // Type of the dense matrix
4358 template< typename MT2 // Type of the right-hand side matrix
4359  , bool SO > // Storage order of the right-hand side matrix
4360 inline Submatrix<MT,unaligned,true,true>&
4361  Submatrix<MT,unaligned,true,true>::operator=( const Matrix<MT2,SO>& rhs )
4362 {
4364 
4365  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
4366  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4367  }
4368 
4369  typedef If_< IsRestricted<MT>, CompositeType_<MT2>, const MT2& > Right;
4370  Right right( ~rhs );
4371 
4372  if( !tryAssign( matrix_, right, row_, column_ ) ) {
4373  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4374  }
4375 
4376  if( IsSparseMatrix<MT2>::value )
4377  reset();
4378 
4379  DerestrictTrait_<This> left( derestrict( *this ) );
4380 
4381  if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
4382  const ResultType_<MT2> tmp( right );
4383  smpAssign( left, tmp );
4384  }
4385  else {
4386  smpAssign( left, right );
4387  }
4388 
4389  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4390 
4391  return *this;
4392 }
4394 //*************************************************************************************************
4395 
4396 
4397 //*************************************************************************************************
4411 template< typename MT > // Type of the dense matrix
4412 template< typename MT2 // Type of the right-hand side matrix
4413  , bool SO > // Storage order of the right-hand side matrix
4414 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,true,true>& >
4415  Submatrix<MT,unaligned,true,true>::operator+=( const Matrix<MT2,SO>& rhs )
4416 {
4420 
4421  typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
4422 
4425 
4426  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
4427  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4428  }
4429 
4430  if( !tryAddAssign( matrix_, ~rhs, row_, column_ ) ) {
4431  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4432  }
4433 
4434  DerestrictTrait_<This> left( derestrict( *this ) );
4435 
4436  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
4437  (~rhs).canAlias( &matrix_ ) ) {
4438  const AddType tmp( *this + (~rhs) );
4439  smpAssign( left, tmp );
4440  }
4441  else {
4442  smpAddAssign( left, ~rhs );
4443  }
4444 
4445  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4446 
4447  return *this;
4448 }
4450 //*************************************************************************************************
4451 
4452 
4453 //*************************************************************************************************
4467 template< typename MT > // Type of the dense matrix
4468 template< typename MT2 // Type of the right-hand side matrix
4469  , bool SO > // Storage order of the right-hand side matrix
4470 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,true,true>& >
4471  Submatrix<MT,unaligned,true,true>::operator+=( const Matrix<MT2,SO>& rhs )
4472 {
4476 
4477  typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
4478 
4481 
4482  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
4483  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4484  }
4485 
4486  const AddType tmp( *this + (~rhs) );
4487 
4488  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
4489  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4490  }
4491 
4492  DerestrictTrait_<This> left( derestrict( *this ) );
4493 
4494  smpAssign( left, tmp );
4495 
4496  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4497 
4498  return *this;
4499 }
4501 //*************************************************************************************************
4502 
4503 
4504 //*************************************************************************************************
4518 template< typename MT > // Type of the dense matrix
4519 template< typename MT2 // Type of the right-hand side matrix
4520  , bool SO > // Storage order of the right-hand side matrix
4521 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,true,true>& >
4522  Submatrix<MT,unaligned,true,true>::operator-=( const Matrix<MT2,SO>& rhs )
4523 {
4527 
4528  typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
4529 
4532 
4533  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
4534  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4535  }
4536 
4537  if( !trySubAssign( matrix_, ~rhs, row_, column_ ) ) {
4538  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4539  }
4540 
4541  DerestrictTrait_<This> left( derestrict( *this ) );
4542 
4543  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
4544  (~rhs).canAlias( &matrix_ ) ) {
4545  const SubType tmp( *this - (~rhs ) );
4546  smpAssign( left, tmp );
4547  }
4548  else {
4549  smpSubAssign( left, ~rhs );
4550  }
4551 
4552  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4553 
4554  return *this;
4555 }
4557 //*************************************************************************************************
4558 
4559 
4560 //*************************************************************************************************
4574 template< typename MT > // Type of the dense matrix
4575 template< typename MT2 // Type of the right-hand side matrix
4576  , bool SO > // Storage order of the right-hand side matrix
4577 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,true,true>& >
4578  Submatrix<MT,unaligned,true,true>::operator-=( const Matrix<MT2,SO>& rhs )
4579 {
4583 
4584  typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
4585 
4588 
4589  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
4590  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4591  }
4592 
4593  const SubType tmp( *this - (~rhs) );
4594 
4595  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
4596  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4597  }
4598 
4599  DerestrictTrait_<This> left( derestrict( *this ) );
4600 
4601  smpAssign( left, tmp );
4602 
4603  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4604 
4605  return *this;
4606 }
4608 //*************************************************************************************************
4609 
4610 
4611 //*************************************************************************************************
4625 template< typename MT > // Type of the dense matrix
4626 template< typename MT2 // Type of the right-hand side matrix
4627  , bool SO > // Storage order of the right-hand side matrix
4628 inline Submatrix<MT,unaligned,true,true>&
4629  Submatrix<MT,unaligned,true,true>::operator*=( const Matrix<MT2,SO>& rhs )
4630 {
4634 
4635  typedef MultTrait_< ResultType, ResultType_<MT2> > MultType;
4636 
4639 
4640  if( columns() != (~rhs).rows() ) {
4641  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4642  }
4643 
4644  const MultType tmp( *this * (~rhs) );
4645 
4646  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
4647  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4648  }
4649 
4650  DerestrictTrait_<This> left( derestrict( *this ) );
4651 
4652  smpAssign( left, tmp );
4653 
4654  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4655 
4656  return *this;
4657 }
4659 //*************************************************************************************************
4660 
4661 
4662 //*************************************************************************************************
4673 template< typename MT > // Type of the dense matrix
4674 template< typename Other > // Data type of the right-hand side scalar
4675 inline EnableIf_< IsNumeric<Other>, Submatrix<MT,unaligned,true,true> >&
4677 {
4679 
4680  DerestrictTrait_<This> left( derestrict( *this ) );
4681  smpAssign( left, (*this) * rhs );
4682 
4683  return *this;
4684 }
4686 //*************************************************************************************************
4687 
4688 
4689 //*************************************************************************************************
4702 template< typename MT > // Type of the dense matrix
4703 template< typename Other > // Data type of the right-hand side scalar
4704 inline EnableIf_< IsNumeric<Other>, Submatrix<MT,unaligned,true,true> >&
4706 {
4708 
4709  BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
4710 
4711  DerestrictTrait_<This> left( derestrict( *this ) );
4712  smpAssign( left, (*this) / rhs );
4713 
4714  return *this;
4715 }
4717 //*************************************************************************************************
4718 
4719 
4720 
4721 
4722 //=================================================================================================
4723 //
4724 // UTILITY FUNCTIONS
4725 //
4726 //=================================================================================================
4727 
4728 //*************************************************************************************************
4734 template< typename MT > // Type of the dense matrix
4735 inline size_t Submatrix<MT,unaligned,true,true>::row() const noexcept
4736 {
4737  return row_;
4738 }
4740 //*************************************************************************************************
4741 
4742 
4743 //*************************************************************************************************
4749 template< typename MT > // Type of the dense matrix
4750 inline size_t Submatrix<MT,unaligned,true,true>::rows() const noexcept
4751 {
4752  return m_;
4753 }
4755 //*************************************************************************************************
4756 
4757 
4758 //*************************************************************************************************
4764 template< typename MT > // Type of the dense matrix
4765 inline size_t Submatrix<MT,unaligned,true,true>::column() const noexcept
4766 {
4767  return column_;
4768 }
4770 //*************************************************************************************************
4771 
4772 
4773 //*************************************************************************************************
4779 template< typename MT > // Type of the dense matrix
4780 inline size_t Submatrix<MT,unaligned,true,true>::columns() const noexcept
4781 {
4782  return n_;
4783 }
4785 //*************************************************************************************************
4786 
4787 
4788 //*************************************************************************************************
4797 template< typename MT > // Type of the dense matrix
4798 inline size_t Submatrix<MT,unaligned,true,true>::spacing() const noexcept
4799 {
4800  return matrix_.spacing();
4801 }
4803 //*************************************************************************************************
4804 
4805 
4806 //*************************************************************************************************
4812 template< typename MT > // Type of the dense matrix
4813 inline size_t Submatrix<MT,unaligned,true,true>::capacity() const noexcept
4814 {
4815  return rows() * columns();
4816 }
4818 //*************************************************************************************************
4819 
4820 
4821 //*************************************************************************************************
4828 template< typename MT > // Type of the dense matrix
4829 inline size_t Submatrix<MT,unaligned,true,true>::capacity( size_t j ) const noexcept
4830 {
4831  UNUSED_PARAMETER( j );
4832 
4833  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
4834 
4835  return rows();
4836 }
4838 //*************************************************************************************************
4839 
4840 
4841 //*************************************************************************************************
4847 template< typename MT > // Type of the dense matrix
4848 inline size_t Submatrix<MT,unaligned,true,true>::nonZeros() const
4849 {
4850  const size_t iend( row_ + m_ );
4851  const size_t jend( column_ + n_ );
4852  size_t nonzeros( 0UL );
4853 
4854  for( size_t j=column_; j<jend; ++j )
4855  for( size_t i=row_; i<iend; ++i )
4856  if( !isDefault( matrix_(i,j) ) )
4857  ++nonzeros;
4858 
4859  return nonzeros;
4860 }
4862 //*************************************************************************************************
4863 
4864 
4865 //*************************************************************************************************
4872 template< typename MT > // Type of the dense matrix
4873 inline size_t Submatrix<MT,unaligned,true,true>::nonZeros( size_t j ) const
4874 {
4875  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
4876 
4877  const size_t iend( row_ + m_ );
4878  size_t nonzeros( 0UL );
4879 
4880  for( size_t i=row_; i<iend; ++i )
4881  if( !isDefault( matrix_(i,column_+j) ) )
4882  ++nonzeros;
4883 
4884  return nonzeros;
4885 }
4887 //*************************************************************************************************
4888 
4889 
4890 //*************************************************************************************************
4896 template< typename MT > // Type of the dense matrix
4898 {
4899  using blaze::clear;
4900 
4901  for( size_t j=column_; j<column_+n_; ++j )
4902  {
4903  const size_t ibegin( ( IsLower<MT>::value )
4904  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
4905  ?( max( j+1UL, row_ ) )
4906  :( max( j, row_ ) ) )
4907  :( row_ ) );
4908  const size_t iend ( ( IsUpper<MT>::value )
4909  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
4910  ?( min( j, row_+m_ ) )
4911  :( min( j+1UL, row_+m_ ) ) )
4912  :( row_+m_ ) );
4913 
4914  for( size_t i=ibegin; i<iend; ++i )
4915  clear( matrix_(i,j) );
4916  }
4917 }
4919 //*************************************************************************************************
4920 
4921 
4922 //*************************************************************************************************
4929 template< typename MT > // Type of the dense matrix
4930 inline void Submatrix<MT,unaligned,true,true>::reset( size_t j )
4931 {
4932  using blaze::clear;
4933 
4934  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
4935 
4936  const size_t ibegin( ( IsLower<MT>::value )
4937  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
4938  ?( max( j+1UL, row_ ) )
4939  :( max( j, row_ ) ) )
4940  :( row_ ) );
4941  const size_t iend ( ( IsUpper<MT>::value )
4942  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
4943  ?( min( j, row_+m_ ) )
4944  :( min( j+1UL, row_+m_ ) ) )
4945  :( row_+m_ ) );
4946 
4947  for( size_t i=ibegin; i<iend; ++i )
4948  clear( matrix_(i,column_+j) );
4949 }
4951 //*************************************************************************************************
4952 
4953 
4954 //*************************************************************************************************
4964 template< typename MT > // Type of the dense matrix
4965 inline bool Submatrix<MT,unaligned,true,true>::hasOverlap() const noexcept
4966 {
4967  BLAZE_INTERNAL_ASSERT( IsSymmetric<MT>::value || IsHermitian<MT>::value, "Invalid matrix detected" );
4968 
4969  if( ( row_ + m_ <= column_ ) || ( column_ + n_ <= row_ ) )
4970  return false;
4971  else return true;
4972 }
4974 //*************************************************************************************************
4975 
4976 
4977 
4978 
4979 //=================================================================================================
4980 //
4981 // NUMERIC FUNCTIONS
4982 //
4983 //=================================================================================================
4984 
4985 //*************************************************************************************************
5003 template< typename MT > // Type of the dense matrix
5004 inline Submatrix<MT,unaligned,true,true>& Submatrix<MT,unaligned,true,true>::transpose()
5005 {
5006  if( m_ != n_ ) {
5007  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
5008  }
5009 
5010  if( !tryAssign( matrix_, trans( *this ), row_, column_ ) ) {
5011  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
5012  }
5013 
5014  DerestrictTrait_<This> left( derestrict( *this ) );
5015  const ResultType tmp( trans( *this ) );
5016  smpAssign( left, tmp );
5017 
5018  return *this;
5019 }
5021 //*************************************************************************************************
5022 
5023 
5024 //*************************************************************************************************
5042 template< typename MT > // Type of the dense matrix
5043 inline Submatrix<MT,unaligned,true,true>& Submatrix<MT,unaligned,true,true>::ctranspose()
5044 {
5045  if( m_ != n_ ) {
5046  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
5047  }
5048 
5049  if( !tryAssign( matrix_, ctrans( *this ), row_, column_ ) ) {
5050  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
5051  }
5052 
5053  DerestrictTrait_<This> left( derestrict( *this ) );
5054  const ResultType tmp( ctrans( *this ) );
5055  smpAssign( left, tmp );
5056 
5057  return *this;
5058 }
5060 //*************************************************************************************************
5061 
5062 
5063 //*************************************************************************************************
5074 template< typename MT > // Type of the dense matrix
5075 template< typename Other > // Data type of the scalar value
5076 inline Submatrix<MT,unaligned,true,true>& Submatrix<MT,unaligned,true,true>::scale( const Other& scalar )
5077 {
5079 
5080  const size_t jend( column_ + n_ );
5081 
5082  for( size_t j=column_; j<jend; ++j )
5083  {
5084  const size_t ibegin( ( IsLower<MT>::value )
5085  ?( ( IsStrictlyLower<MT>::value )
5086  ?( max( j+1UL, row_ ) )
5087  :( max( j, row_ ) ) )
5088  :( row_ ) );
5089  const size_t iend ( ( IsUpper<MT>::value )
5090  ?( ( IsStrictlyUpper<MT>::value )
5091  ?( min( j, row_+m_ ) )
5092  :( min( j+1UL, row_+m_ ) ) )
5093  :( row_+m_ ) );
5094 
5095  for( size_t i=ibegin; i<iend; ++i )
5096  matrix_(i,j) *= scalar;
5097  }
5098 
5099  return *this;
5100 }
5102 //*************************************************************************************************
5103 
5104 
5105 
5106 
5107 //=================================================================================================
5108 //
5109 // EXPRESSION TEMPLATE EVALUATION FUNCTIONS
5110 //
5111 //=================================================================================================
5112 
5113 //*************************************************************************************************
5124 template< typename MT > // Type of the dense matrix
5125 template< typename Other > // Data type of the foreign expression
5126 inline bool Submatrix<MT,unaligned,true,true>::canAlias( const Other* alias ) const noexcept
5127 {
5128  return matrix_.isAliased( alias );
5129 }
5131 //*************************************************************************************************
5132 
5133 
5134 //*************************************************************************************************
5145 template< typename MT > // Type of the dense matrix
5146 template< typename MT2 // Data type of the foreign dense submatrix
5147  , bool AF2 // Alignment flag of the foreign dense submatrix
5148  , bool SO2 > // Storage order of the foreign dense submatrix
5149 inline bool Submatrix<MT,unaligned,true,true>::canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
5150 {
5151  return ( matrix_.isAliased( &alias->matrix_ ) &&
5152  ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
5153  ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
5154 }
5156 //*************************************************************************************************
5157 
5158 
5159 //*************************************************************************************************
5170 template< typename MT > // Type of the dense matrix
5171 template< typename Other > // Data type of the foreign expression
5172 inline bool Submatrix<MT,unaligned,true,true>::isAliased( const Other* alias ) const noexcept
5173 {
5174  return matrix_.isAliased( alias );
5175 }
5177 //*************************************************************************************************
5178 
5179 
5180 //*************************************************************************************************
5191 template< typename MT > // Type of the dense matrix
5192 template< typename MT2 // Data type of the foreign dense submatrix
5193  , bool AF2 // Alignment flag of the foreign dense submatrix
5194  , bool SO2 > // Storage order of the foreign dense submatrix
5195 inline bool Submatrix<MT,unaligned,true,true>::isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
5196 {
5197  return ( matrix_.isAliased( &alias->matrix_ ) &&
5198  ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
5199  ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
5200 }
5202 //*************************************************************************************************
5203 
5204 
5205 //*************************************************************************************************
5215 template< typename MT > // Type of the dense matrix
5216 inline bool Submatrix<MT,unaligned,true,true>::isAligned() const noexcept
5217 {
5218  return isAligned_;
5219 }
5221 //*************************************************************************************************
5222 
5223 
5224 //*************************************************************************************************
5235 template< typename MT > // Type of the dense matrix
5236 inline bool Submatrix<MT,unaligned,true,true>::canSMPAssign() const noexcept
5237 {
5238  return ( rows() * columns() >= SMP_DMATASSIGN_THRESHOLD );
5239 }
5241 //*************************************************************************************************
5242 
5243 
5244 //*************************************************************************************************
5259 template< typename MT > // Type of the dense matrix
5260 BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,true,true>::SIMDType
5261  Submatrix<MT,unaligned,true,true>::load( size_t i, size_t j ) const noexcept
5262 {
5263  if( isAligned_ )
5264  return loada( i, j );
5265  else
5266  return loadu( i, j );
5267 }
5269 //*************************************************************************************************
5270 
5271 
5272 //*************************************************************************************************
5287 template< typename MT > // Type of the dense matrix
5288 BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,true,true>::SIMDType
5289  Submatrix<MT,unaligned,true,true>::loada( size_t i, size_t j ) const noexcept
5290 {
5292 
5293  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
5294  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
5295  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
5296  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
5297 
5298  return matrix_.loada( row_+i, column_+j );
5299 }
5301 //*************************************************************************************************
5302 
5303 
5304 //*************************************************************************************************
5319 template< typename MT > // Type of the dense matrix
5320 BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,true,true>::SIMDType
5321  Submatrix<MT,unaligned,true,true>::loadu( size_t i, size_t j ) const noexcept
5322 {
5324 
5325  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
5326  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
5327  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
5328  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
5329 
5330  return matrix_.loadu( row_+i, column_+j );
5331 }
5333 //*************************************************************************************************
5334 
5335 
5336 //*************************************************************************************************
5352 template< typename MT > // Type of the dense matrix
5354  Submatrix<MT,unaligned,true,true>::store( size_t i, size_t j, const SIMDType& value ) noexcept
5355 {
5356  if( isAligned_ )
5357  storea( i, j, value );
5358  else
5359  storeu( i, j, value );
5360 }
5362 //*************************************************************************************************
5363 
5364 
5365 //*************************************************************************************************
5381 template< typename MT > // Type of the dense matrix
5383  Submatrix<MT,unaligned,true,true>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
5384 {
5386 
5387  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
5388  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
5389  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
5390  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
5391 
5392  matrix_.storea( row_+i, column_+j, value );
5393 }
5395 //*************************************************************************************************
5396 
5397 
5398 //*************************************************************************************************
5414 template< typename MT > // Type of the dense matrix
5416  Submatrix<MT,unaligned,true,true>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
5417 {
5419 
5420  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
5421  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
5422  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
5423  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
5424 
5425  matrix_.storeu( row_+i, column_+j, value );
5426 }
5428 //*************************************************************************************************
5429 
5430 
5431 //*************************************************************************************************
5448 template< typename MT > // Type of the dense matrix
5450  Submatrix<MT,unaligned,true,true>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
5451 {
5453 
5454  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
5455  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
5456  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
5457  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
5458 
5459  if( isAligned_ )
5460  matrix_.stream( row_+i, column_+j, value );
5461  else
5462  matrix_.storeu( row_+i, column_+j, value );
5463 }
5465 //*************************************************************************************************
5466 
5467 
5468 //*************************************************************************************************
5480 template< typename MT > // Type of the dense matrix
5481 template< typename MT2 > // Type of the right-hand side dense matrix
5482 inline DisableIf_< typename Submatrix<MT,unaligned,true,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
5483  Submatrix<MT,unaligned,true,true>::assign( const DenseMatrix<MT2,true>& rhs )
5484 {
5485  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5486  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5487 
5488  const size_t ipos( m_ & size_t(-2) );
5489  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
5490 
5491  for( size_t j=0UL; j<n_; ++j ) {
5492  for( size_t i=0UL; i<ipos; i+=2UL ) {
5493  matrix_(row_+i ,column_+j) = (~rhs)(i ,j);
5494  matrix_(row_+i+1UL,column_+j) = (~rhs)(i+1UL,j);
5495  }
5496  if( ipos < m_ ) {
5497  matrix_(row_+ipos,column_+j) = (~rhs)(ipos,j);
5498  }
5499  }
5500 }
5502 //*************************************************************************************************
5503 
5504 
5505 //*************************************************************************************************
5517 template< typename MT > // Type of the dense matrix
5518 template< typename MT2 > // Type of the right-hand side dense matrix
5519 inline EnableIf_< typename Submatrix<MT,unaligned,true,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
5520  Submatrix<MT,unaligned,true,true>::assign( const DenseMatrix<MT2,true>& rhs )
5521 {
5523 
5524  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5525  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5526 
5527  const size_t ipos( m_ & size_t(-SIMDSIZE) );
5528  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
5529 
5530  if( useStreaming && isAligned_ &&
5531  m_*n_ > ( cacheSize / ( sizeof(ElementType) * 3UL ) ) &&
5532  !(~rhs).isAliased( &matrix_ ) )
5533  {
5534  for( size_t j=0UL; j<n_; ++j )
5535  {
5536  size_t i( 0UL );
5537  Iterator left( begin(j) );
5538  ConstIterator_<MT2> right( (~rhs).begin(j) );
5539 
5540  for( ; i<ipos; i+=SIMDSIZE ) {
5541  left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5542  }
5543  for( ; i<m_; ++i ) {
5544  *left = *right; ++left; ++right;
5545  }
5546  }
5547  }
5548  else
5549  {
5550  for( size_t j=0UL; j<n_; ++j )
5551  {
5552  size_t i( 0UL );
5553  Iterator left( begin(j) );
5554  ConstIterator_<MT2> right( (~rhs).begin(j) );
5555 
5556  for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
5557  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5558  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5559  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5560  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5561  }
5562  for( ; i<ipos; i+=SIMDSIZE ) {
5563  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5564  }
5565  for( ; i<m_; ++i ) {
5566  *left = *right; ++left; ++right;
5567  }
5568  }
5569  }
5570 }
5572 //*************************************************************************************************
5573 
5574 
5575 //*************************************************************************************************
5587 template< typename MT > // Type of the dense matrix
5588 template< typename MT2 > // Type of the right-hand side dense matrix
5589 inline void Submatrix<MT,unaligned,true,true>::assign( const DenseMatrix<MT2,false>& rhs )
5590 {
5592 
5593  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5594  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5595 
5596  constexpr size_t block( BLOCK_SIZE );
5597 
5598  for( size_t jj=0UL; jj<n_; jj+=block ) {
5599  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
5600  for( size_t ii=0UL; ii<m_; ii+=block ) {
5601  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
5602  for( size_t j=jj; j<jend; ++j ) {
5603  for( size_t i=ii; i<iend; ++i ) {
5604  matrix_(row_+i,column_+j) = (~rhs)(i,j);
5605  }
5606  }
5607  }
5608  }
5609 }
5611 //*************************************************************************************************
5612 
5613 
5614 //*************************************************************************************************
5626 template< typename MT > // Type of the dense matrix
5627 template< typename MT2 > // Type of the right-hand side sparse matrix
5628 inline void Submatrix<MT,unaligned,true,true>::assign( const SparseMatrix<MT2,true>& rhs )
5629 {
5630  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5631  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5632 
5633  for( size_t j=0UL; j<n_; ++j )
5634  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
5635  matrix_(row_+element->index(),column_+j) = element->value();
5636 }
5638 //*************************************************************************************************
5639 
5640 
5641 //*************************************************************************************************
5653 template< typename MT > // Type of the dense matrix
5654 template< typename MT2 > // Type of the right-hand side sparse matrix
5655 inline void Submatrix<MT,unaligned,true,true>::assign( const SparseMatrix<MT2,false>& rhs )
5656 {
5658 
5659  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5660  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5661 
5662  for( size_t i=0UL; i<m_; ++i )
5663  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
5664  matrix_(row_+i,column_+element->index()) = element->value();
5665 }
5667 //*************************************************************************************************
5668 
5669 
5670 //*************************************************************************************************
5682 template< typename MT > // Type of the dense matrix
5683 template< typename MT2 > // Type of the right-hand side dense matrix
5684 inline DisableIf_< typename Submatrix<MT,unaligned,true,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
5685  Submatrix<MT,unaligned,true,true>::addAssign( const DenseMatrix<MT2,true>& rhs )
5686 {
5687  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5688  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5689 
5690  const size_t ipos( m_ & size_t(-2) );
5691  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
5692 
5693  for( size_t j=0UL; j<n_; ++j )
5694  {
5695  if( IsDiagonal<MT2>::value ) {
5696  matrix_(row_+j,column_+j) += (~rhs)(j,j);
5697  }
5698  else {
5699  for( size_t i=0UL; i<ipos; i+=2UL ) {
5700  matrix_(row_+i ,column_+j) += (~rhs)(i ,j);
5701  matrix_(row_+i+1UL,column_+j) += (~rhs)(i+1UL,j);
5702  }
5703  if( ipos < m_ ) {
5704  matrix_(row_+ipos,column_+j) += (~rhs)(ipos,j);
5705  }
5706  }
5707  }
5708 }
5710 //*************************************************************************************************
5711 
5712 
5713 //*************************************************************************************************
5725 template< typename MT > // Type of the dense matrix
5726 template< typename MT2 > // Type of the right-hand side dense matrix
5727 inline EnableIf_< typename Submatrix<MT,unaligned,true,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
5728  Submatrix<MT,unaligned,true,true>::addAssign( const DenseMatrix<MT2,true>& rhs )
5729 {
5731 
5732  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5733  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5734 
5735  for( size_t j=0UL; j<n_; ++j )
5736  {
5737  const size_t ibegin( ( IsLower<MT>::value )
5738  ?( ( IsStrictlyLower<MT>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
5739  :( 0UL ) );
5740  const size_t iend ( ( IsUpper<MT>::value )
5741  ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
5742  :( m_ ) );
5743  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
5744 
5745  const size_t ipos( iend & size_t(-SIMDSIZE) );
5746  BLAZE_INTERNAL_ASSERT( ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
5747 
5748  size_t i( ibegin );
5749  Iterator left( begin(j) + ibegin );
5750  ConstIterator_<MT2> right( (~rhs).begin(j) + ibegin );
5751 
5752  for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
5753  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5754  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5755  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5756  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5757  }
5758  for( ; i<ipos; i+=SIMDSIZE ) {
5759  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5760  }
5761  for( ; i<iend; ++i ) {
5762  *left += *right; ++left; ++right;
5763  }
5764  }
5765 }
5767 //*************************************************************************************************
5768 
5769 
5770 //*************************************************************************************************
5782 template< typename MT > // Type of the dense matrix
5783 template< typename MT2 > // Type of the right-hand side dense matrix
5784 inline void Submatrix<MT,unaligned,true,true>::addAssign( const DenseMatrix<MT2,false>& rhs )
5785 {
5787 
5788  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5789  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5790 
5791  constexpr size_t block( BLOCK_SIZE );
5792 
5793  for( size_t jj=0UL; jj<n_; jj+=block ) {
5794  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
5795  for( size_t ii=0UL; ii<m_; ii+=block ) {
5796  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
5797  for( size_t j=jj; j<jend; ++j ) {
5798  for( size_t i=ii; i<iend; ++i ) {
5799  matrix_(row_+i,column_+j) += (~rhs)(i,j);
5800  }
5801  }
5802  }
5803  }
5804 }
5806 //*************************************************************************************************
5807 
5808 
5809 //*************************************************************************************************
5821 template< typename MT > // Type of the dense matrix
5822 template< typename MT2 > // Type of the right-hand side sparse matrix
5823 inline void Submatrix<MT,unaligned,true,true>::addAssign( const SparseMatrix<MT2,true>& rhs )
5824 {
5825  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5826  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5827 
5828  for( size_t j=0UL; j<n_; ++j )
5829  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
5830  matrix_(row_+element->index(),column_+j) += element->value();
5831 }
5833 //*************************************************************************************************
5834 
5835 
5836 //*************************************************************************************************
5848 template< typename MT > // Type of the dense matrix
5849 template< typename MT2 > // Type of the right-hand side sparse matrix
5850 inline void Submatrix<MT,unaligned,true,true>::addAssign( const SparseMatrix<MT2,false>& rhs )
5851 {
5853 
5854  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5855  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5856 
5857  for( size_t i=0UL; i<m_; ++i )
5858  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
5859  matrix_(row_+i,column_+element->index()) += element->value();
5860 }
5862 //*************************************************************************************************
5863 
5864 
5865 //*************************************************************************************************
5877 template< typename MT > // Type of the dense matrix
5878 template< typename MT2 > // Type of the right-hand side dense matrix
5879 inline DisableIf_< typename Submatrix<MT,unaligned,true,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
5880  Submatrix<MT,unaligned,true,true>::subAssign( const DenseMatrix<MT2,true>& rhs )
5881 {
5882  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5883  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5884 
5885  const size_t ipos( m_ & size_t(-2) );
5886  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
5887 
5888  for( size_t j=0UL; j<n_; ++j )
5889  {
5890  if( IsDiagonal<MT2>::value ) {
5891  matrix_(row_+j,column_+j) -= (~rhs)(j,j);
5892  }
5893  else {
5894  for( size_t i=0UL; i<ipos; i+=2UL ) {
5895  matrix_(row_+i ,column_+j) -= (~rhs)(i ,j);
5896  matrix_(row_+i+1UL,column_+j) -= (~rhs)(i+1UL,j);
5897  }
5898  if( ipos < m_ ) {
5899  matrix_(row_+ipos,column_+j) -= (~rhs)(ipos,j);
5900  }
5901  }
5902  }
5903 }
5905 //*************************************************************************************************
5906 
5907 
5908 //*************************************************************************************************
5920 template< typename MT > // Type of the dense matrix
5921 template< typename MT2 > // Type of the right-hand side dense matrix
5922 inline EnableIf_< typename Submatrix<MT,unaligned,true,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
5923  Submatrix<MT,unaligned,true,true>::subAssign( const DenseMatrix<MT2,true>& rhs )
5924 {
5926 
5927  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5928  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5929 
5930  for( size_t j=0UL; j<n_; ++j )
5931  {
5932  const size_t ibegin( ( IsLower<MT>::value )
5933  ?( ( IsStrictlyLower<MT>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
5934  :( 0UL ) );
5935  const size_t iend ( ( IsUpper<MT>::value )
5936  ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
5937  :( m_ ) );
5938  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
5939 
5940  const size_t ipos( iend & size_t(-SIMDSIZE) );
5941  BLAZE_INTERNAL_ASSERT( ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
5942 
5943  size_t i( ibegin );
5944  Iterator left( begin(j) + ibegin );
5945  ConstIterator_<MT2> right( (~rhs).begin(j) + ibegin );
5946 
5947  for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
5948  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5949  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5950  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5951  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5952  }
5953  for( ; i<ipos; i+=SIMDSIZE ) {
5954  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5955  }
5956  for( ; i<iend; ++i ) {
5957  *left -= *right; ++left; ++right;
5958  }
5959  }
5960 }
5962 //*************************************************************************************************
5963 
5964 
5965 //*************************************************************************************************
5977 template< typename MT > // Type of the dense matrix
5978 template< typename MT2 > // Type of the right-hand side dense matrix
5979 inline void Submatrix<MT,unaligned,true,true>::subAssign( const DenseMatrix<MT2,false>& rhs )
5980 {
5982 
5983  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5984  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5985 
5986  constexpr size_t block( BLOCK_SIZE );
5987 
5988  for( size_t jj=0UL; jj<n_; jj+=block ) {
5989  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
5990  for( size_t ii=0UL; ii<m_; ii+=block ) {
5991  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
5992  for( size_t j=jj; j<jend; ++j ) {
5993  for( size_t i=ii; i<iend; ++i ) {
5994  matrix_(row_+i,column_+j) -= (~rhs)(i,j);
5995  }
5996  }
5997  }
5998  }
5999 }
6001 //*************************************************************************************************
6002 
6003 
6004 //*************************************************************************************************
6016 template< typename MT > // Type of the dense matrix
6017 template< typename MT2 > // Type of the right-hand side sparse matrix
6018 inline void Submatrix<MT,unaligned,true,true>::subAssign( const SparseMatrix<MT2,true>& rhs )
6019 {
6020  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
6021  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
6022 
6023  for( size_t j=0UL; j<n_; ++j )
6024  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
6025  matrix_(row_+element->index(),column_+j) -= element->value();
6026 }
6028 //*************************************************************************************************
6029 
6030 
6031 //*************************************************************************************************
6043 template< typename MT > // Type of the dense matrix
6044 template< typename MT2 > // Type of the right-hand side sparse matrix
6045 inline void Submatrix<MT,unaligned,true,true>::subAssign( const SparseMatrix<MT2,false>& rhs )
6046 {
6048 
6049  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
6050  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
6051 
6052  for( size_t i=0UL; i<m_; ++i )
6053  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
6054  matrix_(row_+i,column_+element->index()) -= element->value();
6055 }
6057 //*************************************************************************************************
6058 
6059 
6060 
6061 
6062 
6063 
6064 
6065 
6066 //=================================================================================================
6067 //
6068 // CLASS TEMPLATE SPECIALIZATION FOR ALIGNED ROW-MAJOR DENSE SUBMATRICES
6069 //
6070 //=================================================================================================
6071 
6072 //*************************************************************************************************
6080 template< typename MT > // Type of the dense matrix
6081 class Submatrix<MT,aligned,false,true>
6082  : public DenseMatrix< Submatrix<MT,aligned,false,true>, false >
6083  , private View
6084 {
6085  private:
6086  //**Type definitions****************************************************************************
6088  typedef If_< IsExpression<MT>, MT, MT& > Operand;
6089  //**********************************************************************************************
6090 
6091  public:
6092  //**Type definitions****************************************************************************
6093  typedef Submatrix<MT,aligned,false,true> This;
6094  typedef DenseMatrix<This,false> BaseType;
6095  typedef SubmatrixTrait_<MT> ResultType;
6096  typedef OppositeType_<ResultType> OppositeType;
6097  typedef TransposeType_<ResultType> TransposeType;
6098  typedef ElementType_<MT> ElementType;
6099  typedef SIMDTrait_<ElementType> SIMDType;
6100  typedef ReturnType_<MT> ReturnType;
6101  typedef const Submatrix& CompositeType;
6102 
6104  typedef ConstReference_<MT> ConstReference;
6105 
6107  typedef If_< IsConst<MT>, ConstReference, Reference_<MT> > Reference;
6108 
6110  typedef const ElementType* ConstPointer;
6111 
6113  typedef If_< Or< IsConst<MT>, Not< HasMutableDataAccess<MT> > >, ConstPointer, ElementType* > Pointer;
6114 
6116  typedef ConstIterator_<MT> ConstIterator;
6117 
6119  typedef If_< IsConst<MT>, ConstIterator, Iterator_<MT> > Iterator;
6120  //**********************************************************************************************
6121 
6122  //**Compilation flags***************************************************************************
6124  enum : bool { simdEnabled = MT::simdEnabled };
6125 
6127  enum : bool { smpAssignable = MT::smpAssignable };
6128  //**********************************************************************************************
6129 
6130  //**Constructors********************************************************************************
6133  explicit inline Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n );
6134  // No explicitly declared copy constructor.
6136  //**********************************************************************************************
6137 
6138  //**Destructor**********************************************************************************
6139  // No explicitly declared destructor.
6140  //**********************************************************************************************
6141 
6142  //**Data access functions***********************************************************************
6145  inline Reference operator()( size_t i, size_t j );
6146  inline ConstReference operator()( size_t i, size_t j ) const;
6147  inline Reference at( size_t i, size_t j );
6148  inline ConstReference at( size_t i, size_t j ) const;
6149  inline Pointer data () noexcept;
6150  inline ConstPointer data () const noexcept;
6151  inline Pointer data ( size_t i ) noexcept;
6152  inline ConstPointer data ( size_t i ) const noexcept;
6153  inline Iterator begin ( size_t i );
6154  inline ConstIterator begin ( size_t i ) const;
6155  inline ConstIterator cbegin( size_t i ) const;
6156  inline Iterator end ( size_t i );
6157  inline ConstIterator end ( size_t i ) const;
6158  inline ConstIterator cend ( size_t i ) const;
6160  //**********************************************************************************************
6161 
6162  //**Assignment operators************************************************************************
6165  inline Submatrix& operator=( const ElementType& rhs );
6166  inline Submatrix& operator=( initializer_list< initializer_list<ElementType> > list );
6167  inline Submatrix& operator=( const Submatrix& rhs );
6168 
6169  template< typename MT2, bool SO >
6170  inline Submatrix& operator=( const Matrix<MT2,SO>& rhs );
6171 
6172  template< typename MT2, bool SO >
6173  inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
6174  operator+=( const Matrix<MT2,SO>& rhs );
6175 
6176  template< typename MT2, bool SO >
6177  inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
6178  operator+=( const Matrix<MT2,SO>& rhs );
6179 
6180  template< typename MT2, bool SO >
6181  inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
6182  operator-=( const Matrix<MT2,SO>& rhs );
6183 
6184  template< typename MT2, bool SO >
6185  inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
6186  operator-=( const Matrix<MT2,SO>& rhs );
6187 
6188  template< typename MT2, bool SO >
6189  inline Submatrix& operator*=( const Matrix<MT2,SO>& rhs );
6190 
6191  template< typename Other >
6192  inline EnableIf_< IsNumeric<Other>, Submatrix >& operator*=( Other rhs );
6193 
6194  template< typename Other >
6195  inline EnableIf_< IsNumeric<Other>, Submatrix >& operator/=( Other rhs );
6197  //**********************************************************************************************
6198 
6199  //**Utility functions***************************************************************************
6202  inline size_t row() const noexcept;
6203  inline size_t rows() const noexcept;
6204  inline size_t column() const noexcept;
6205  inline size_t columns() const noexcept;
6206  inline size_t spacing() const noexcept;
6207  inline size_t capacity() const noexcept;
6208  inline size_t capacity( size_t i ) const noexcept;
6209  inline size_t nonZeros() const;
6210  inline size_t nonZeros( size_t i ) const;
6211  inline void reset();
6212  inline void reset( size_t i );
6214  //**********************************************************************************************
6215 
6216  //**Numeric functions***************************************************************************
6219  inline Submatrix& transpose();
6220  inline Submatrix& ctranspose();
6221 
6222  template< typename Other > inline Submatrix& scale( const Other& scalar );
6224  //**********************************************************************************************
6225 
6226  private:
6227  //**********************************************************************************************
6229  template< typename MT2 >
6230  struct VectorizedAssign {
6231  enum : bool { value = useOptimizedKernels &&
6232  simdEnabled && MT2::simdEnabled &&
6233  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value };
6234  };
6235  //**********************************************************************************************
6236 
6237  //**********************************************************************************************
6239  template< typename MT2 >
6240  struct VectorizedAddAssign {
6241  enum : bool { value = useOptimizedKernels &&
6242  simdEnabled && MT2::simdEnabled &&
6243  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
6244  HasSIMDAdd< ElementType, ElementType_<MT2> >::value &&
6245  !IsDiagonal<MT2>::value };
6246  };
6247  //**********************************************************************************************
6248 
6249  //**********************************************************************************************
6251  template< typename MT2 >
6252  struct VectorizedSubAssign {
6253  enum : bool { value = useOptimizedKernels &&
6254  simdEnabled && MT2::simdEnabled &&
6255  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
6256  HasSIMDSub< ElementType, ElementType_<MT2> >::value &&
6257  !IsDiagonal<MT2>::value };
6258  };
6259  //**********************************************************************************************
6260 
6261  //**SIMD properties*****************************************************************************
6263  enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
6264  //**********************************************************************************************
6265 
6266  public:
6267  //**Expression template evaluation functions****************************************************
6270  template< typename Other >
6271  inline bool canAlias( const Other* alias ) const noexcept;
6272 
6273  template< typename MT2, bool AF2, bool SO2 >
6274  inline bool canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
6275 
6276  template< typename Other >
6277  inline bool isAliased( const Other* alias ) const noexcept;
6278 
6279  template< typename MT2, bool AF2, bool SO2 >
6280  inline bool isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
6281 
6282  inline bool isAligned () const noexcept;
6283  inline bool canSMPAssign() const noexcept;
6284 
6285  BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
6286  BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
6287  BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
6288 
6289  BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
6290  BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
6291  BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
6292  BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
6293 
6294  template< typename MT2 >
6295  inline DisableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,false>& rhs );
6296 
6297  template< typename MT2 >
6298  inline EnableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,false>& rhs );
6299 
6300  template< typename MT2 > inline void assign( const DenseMatrix<MT2,true>& rhs );
6301  template< typename MT2 > inline void assign( const SparseMatrix<MT2,false>& rhs );
6302  template< typename MT2 > inline void assign( const SparseMatrix<MT2,true>& rhs );
6303 
6304  template< typename MT2 >
6305  inline DisableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,false>& rhs );
6306 
6307  template< typename MT2 >
6308  inline EnableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,false>& rhs );
6309 
6310  template< typename MT2 > inline void addAssign( const DenseMatrix<MT2,true>& rhs );
6311  template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,false>& rhs );
6312  template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,true>& rhs );
6313 
6314  template< typename MT2 >
6315  inline DisableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,false>& rhs );
6316 
6317  template< typename MT2 >
6318  inline EnableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,false>& rhs );
6319 
6320  template< typename MT2 > inline void subAssign( const DenseMatrix<MT2,true>& rhs );
6321  template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,false>& rhs );
6322  template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,true>& rhs );
6324  //**********************************************************************************************
6325 
6326  private:
6327  //**Utility functions***************************************************************************
6330  inline bool hasOverlap() const noexcept;
6332  //**********************************************************************************************
6333 
6334  //**Member variables****************************************************************************
6337  Operand matrix_;
6338  const size_t row_;
6339  const size_t column_;
6340  const size_t m_;
6341  const size_t n_;
6342 
6343  //**********************************************************************************************
6344 
6345  //**Friend declarations*************************************************************************
6346  template< typename MT2, bool AF2, bool SO2, bool DF2 > friend class Submatrix;
6347 
6348  template< bool AF1, typename MT2, bool AF2, bool SO2, bool DF2 >
6349  friend const Submatrix<MT2,AF1,SO2,DF2>
6350  submatrix( const Submatrix<MT2,AF2,SO2,DF2>& sm, size_t row, size_t column, size_t m, size_t n );
6351 
6352  template< typename MT2, bool AF2, bool SO2, bool DF2 >
6353  friend bool isIntact( const Submatrix<MT2,AF2,SO2,DF2>& sm ) noexcept;
6354 
6355  template< typename MT2, bool AF2, bool SO2, bool DF2 >
6356  friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Matrix<MT2,SO2>& b ) noexcept;
6357 
6358  template< typename MT2, bool AF2, bool SO2, bool DF2 >
6359  friend bool isSame( const Matrix<MT2,SO2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
6360 
6361  template< typename MT2, bool AF2, bool SO2, bool DF2 >
6362  friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
6363 
6364  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
6365  friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
6366  size_t row, size_t column );
6367 
6368  template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
6369  friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
6370  size_t row, size_t column );
6371 
6372  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
6373  friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
6374  size_t row, size_t column );
6375 
6376  template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
6377  friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
6378  size_t row, size_t column );
6379 
6380  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
6381  friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
6382  size_t row, size_t column );
6383 
6384  template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
6385  friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
6386  size_t row, size_t column );
6387 
6388  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
6389  friend bool tryMultAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
6390  size_t row, size_t column );
6391 
6392  template< typename MT2, bool AF2, bool SO2, bool DF2 >
6393  friend DerestrictTrait_< Submatrix<MT2,AF2,SO2,DF2> > derestrict( Submatrix<MT2,AF2,SO2,DF2>& sm );
6394  //**********************************************************************************************
6395 
6396  //**Compile time checks*************************************************************************
6404  //**********************************************************************************************
6405 };
6407 //*************************************************************************************************
6408 
6409 
6410 
6411 
6412 //=================================================================================================
6413 //
6414 // CONSTRUCTOR
6415 //
6416 //=================================================================================================
6417 
6418 //*************************************************************************************************
6432 template< typename MT > // Type of the dense matrix
6433 inline Submatrix<MT,aligned,false,true>::Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n )
6434  : matrix_( matrix ) // The dense matrix containing the submatrix
6435  , row_ ( rindex ) // The first row of the submatrix
6436  , column_( cindex ) // The first column of the submatrix
6437  , m_ ( m ) // The number of rows of the submatrix
6438  , n_ ( n ) // The number of columns of the submatrix
6439 {
6440  if( ( row_ + m_ > matrix_.rows() ) || ( column_ + n_ > matrix_.columns() ) ) {
6441  BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix specification" );
6442  }
6443 
6444  if( ( simdEnabled && matrix_.data() != nullptr && !checkAlignment( data() ) ) ||
6445  ( m_ > 1UL && matrix_.spacing() % SIMDSIZE != 0UL ) ) {
6446  BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix alignment" );
6447  }
6448 }
6450 //*************************************************************************************************
6451 
6452 
6453 
6454 
6455 //=================================================================================================
6456 //
6457 // DATA ACCESS FUNCTIONS
6458 //
6459 //=================================================================================================
6460 
6461 //*************************************************************************************************
6472 template< typename MT > // Type of the dense matrix
6474  Submatrix<MT,aligned,false,true>::operator()( size_t i, size_t j )
6475 {
6476  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
6477  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
6478 
6479  return matrix_(row_+i,column_+j);
6480 }
6482 //*************************************************************************************************
6483 
6484 
6485 //*************************************************************************************************
6496 template< typename MT > // Type of the dense matrix
6498  Submatrix<MT,aligned,false,true>::operator()( size_t i, size_t j ) const
6499 {
6500  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
6501  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
6502 
6503  return const_cast<const MT&>( matrix_ )(row_+i,column_+j);
6504 }
6506 //*************************************************************************************************
6507 
6508 
6509 //*************************************************************************************************
6521 template< typename MT > // Type of the dense matrix
6523  Submatrix<MT,aligned,false,true>::at( size_t i, size_t j )
6524 {
6525  if( i >= rows() ) {
6526  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
6527  }
6528  if( j >= columns() ) {
6529  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
6530  }
6531  return (*this)(i,j);
6532 }
6534 //*************************************************************************************************
6535 
6536 
6537 //*************************************************************************************************
6549 template< typename MT > // Type of the dense matrix
6551  Submatrix<MT,aligned,false,true>::at( size_t i, size_t j ) const
6552 {
6553  if( i >= rows() ) {
6554  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
6555  }
6556  if( j >= columns() ) {
6557  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
6558  }
6559  return (*this)(i,j);
6560 }
6562 //*************************************************************************************************
6563 
6564 
6565 //*************************************************************************************************
6575 template< typename MT > // Type of the dense matrix
6576 inline typename Submatrix<MT,aligned,false,true>::Pointer
6577  Submatrix<MT,aligned,false,true>::data() noexcept
6578 {
6579  return matrix_.data() + row_*spacing() + column_;
6580 }
6582 //*************************************************************************************************
6583 
6584 
6585 //*************************************************************************************************
6595 template< typename MT > // Type of the dense matrix
6596 inline typename Submatrix<MT,aligned,false,true>::ConstPointer
6597  Submatrix<MT,aligned,false,true>::data() const noexcept
6598 {
6599  return matrix_.data() + row_*spacing() + column_;
6600 }
6602 //*************************************************************************************************
6603 
6604 
6605 //*************************************************************************************************
6614 template< typename MT > // Type of the dense matrix
6615 inline typename Submatrix<MT,aligned,false,true>::Pointer
6616  Submatrix<MT,aligned,false,true>::data( size_t i ) noexcept
6617 {
6618  return matrix_.data() + (row_+i)*spacing() + column_;
6619 }
6621 //*************************************************************************************************
6622 
6623 
6624 //*************************************************************************************************
6633 template< typename MT > // Type of the dense matrix
6634 inline typename Submatrix<MT,aligned,false,true>::ConstPointer
6635  Submatrix<MT,aligned,false,true>::data( size_t i ) const noexcept
6636 {
6637  return matrix_.data() + (row_+i)*spacing() + column_;
6638 }
6640 //*************************************************************************************************
6641 
6642 
6643 //*************************************************************************************************
6655 template< typename MT > // Type of the dense matrix
6658 {
6659  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
6660  return ( matrix_.begin( row_ + i ) + column_ );
6661 }
6663 //*************************************************************************************************
6664 
6665 
6666 //*************************************************************************************************
6678 template< typename MT > // Type of the dense matrix
6680  Submatrix<MT,aligned,false,true>::begin( size_t i ) const
6681 {
6682  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
6683  return ( matrix_.cbegin( row_ + i ) + column_ );
6684 }
6686 //*************************************************************************************************
6687 
6688 
6689 //*************************************************************************************************
6701 template< typename MT > // Type of the dense matrix
6704 {
6705  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
6706  return ( matrix_.cbegin( row_ + i ) + column_ );
6707 }
6709 //*************************************************************************************************
6710 
6711 
6712 //*************************************************************************************************
6724 template< typename MT > // Type of the dense matrix
6727 {
6728  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
6729  return ( matrix_.begin( row_ + i ) + column_ + n_ );
6730 }
6732 //*************************************************************************************************
6733 
6734 
6735 //*************************************************************************************************
6747 template< typename MT > // Type of the dense matrix
6749  Submatrix<MT,aligned,false,true>::end( size_t i ) const
6750 {
6751  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
6752  return ( matrix_.cbegin( row_ + i ) + column_ + n_ );
6753 }
6755 //*************************************************************************************************
6756 
6757 
6758 //*************************************************************************************************
6770 template< typename MT > // Type of the dense matrix
6772  Submatrix<MT,aligned,false,true>::cend( size_t i ) const
6773 {
6774  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
6775  return ( matrix_.cbegin( row_ + i ) + column_ + n_ );
6776 }
6778 //*************************************************************************************************
6779 
6780 
6781 
6782 
6783 //=================================================================================================
6784 //
6785 // ASSIGNMENT OPERATORS
6786 //
6787 //=================================================================================================
6788 
6789 //*************************************************************************************************
6800 template< typename MT > // Type of the dense matrix
6801 inline Submatrix<MT,aligned,false,true>&
6802  Submatrix<MT,aligned,false,true>::operator=( const ElementType& rhs )
6803 {
6804  const size_t iend( row_ + m_ );
6805 
6806  for( size_t i=row_; i<iend; ++i )
6807  {
6808  const size_t jbegin( ( IsUpper<MT>::value )
6809  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
6810  ?( max( i+1UL, column_ ) )
6811  :( max( i, column_ ) ) )
6812  :( column_ ) );
6813  const size_t jend ( ( IsLower<MT>::value )
6814  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
6815  ?( min( i, column_+n_ ) )
6816  :( min( i+1UL, column_+n_ ) ) )
6817  :( column_+n_ ) );
6818 
6819  for( size_t j=jbegin; j<jend; ++j )
6820  matrix_(i,j) = rhs;
6821  }
6822 
6823  return *this;
6824 }
6826 //*************************************************************************************************
6827 
6828 
6829 //*************************************************************************************************
6842 template< typename MT > // Type of the dense matrix
6843 inline Submatrix<MT,aligned,false,true>&
6844  Submatrix<MT,aligned,false,true>::operator=( initializer_list< initializer_list<ElementType> > list )
6845 {
6846  if( list.size() != rows() || determineColumns( list ) > columns() ) {
6847  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to submatrix" );
6848  }
6849 
6850  size_t i( 0UL );
6851 
6852  for( const auto& rowList : list ) {
6853  std::fill( std::copy( rowList.begin(), rowList.end(), begin(i) ), end(i), ElementType() );
6854  ++i;
6855  }
6856 
6857  return *this;
6858 }
6860 //*************************************************************************************************
6861 
6862 
6863 //*************************************************************************************************
6878 template< typename MT > // Type of the dense matrix
6879 inline Submatrix<MT,aligned,false,true>&
6880  Submatrix<MT,aligned,false,true>::operator=( const Submatrix& rhs )
6881 {
6884 
6885  if( this == &rhs || ( &matrix_ == &rhs.matrix_ && row_ == rhs.row_ && column_ == rhs.column_ ) )
6886  return *this;
6887 
6888  if( rows() != rhs.rows() || columns() != rhs.columns() ) {
6889  BLAZE_THROW_INVALID_ARGUMENT( "Submatrix sizes do not match" );
6890  }
6891 
6892  if( !tryAssign( matrix_, rhs, row_, column_ ) ) {
6893  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
6894  }
6895 
6896  DerestrictTrait_<This> left( derestrict( *this ) );
6897 
6898  if( rhs.canAlias( &matrix_ ) ) {
6899  const ResultType tmp( rhs );
6900  smpAssign( left, tmp );
6901  }
6902  else {
6903  smpAssign( left, rhs );
6904  }
6905 
6906  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
6907 
6908  return *this;
6909 }
6911 //*************************************************************************************************
6912 
6913 
6914 //*************************************************************************************************
6929 template< typename MT > // Type of the dense matrix
6930 template< typename MT2 // Type of the right-hand side matrix
6931  , bool SO > // Storage order of the right-hand side matrix
6932 inline Submatrix<MT,aligned,false,true>&
6933  Submatrix<MT,aligned,false,true>::operator=( const Matrix<MT2,SO>& rhs )
6934 {
6936 
6937  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
6938  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
6939  }
6940 
6941  typedef If_< IsRestricted<MT>, CompositeType_<MT2>, const MT2& > Right;
6942  Right right( ~rhs );
6943 
6944  if( !tryAssign( matrix_, right, row_, column_ ) ) {
6945  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
6946  }
6947 
6948  if( IsSparseMatrix<MT2>::value )
6949  reset();
6950 
6951  DerestrictTrait_<This> left( derestrict( *this ) );
6952 
6953  if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
6954  const ResultType_<MT2> tmp( right );
6955  smpAssign( left, tmp );
6956  }
6957  else {
6958  smpAssign( left, right );
6959  }
6960 
6961  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
6962 
6963  return *this;
6964 }
6966 //*************************************************************************************************
6967 
6968 
6969 //*************************************************************************************************
6983 template< typename MT > // Type of the dense matrix
6984 template< typename MT2 // Type of the right-hand side matrix
6985  , bool SO > // Storage order of the right-hand side matrix
6986 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,false,true>& >
6987  Submatrix<MT,aligned,false,true>::operator+=( const Matrix<MT2,SO>& rhs )
6988 {
6992 
6993  typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
6994 
6997 
6998  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
6999  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
7000  }
7001 
7002  if( !tryAddAssign( matrix_, ~rhs, row_, column_ ) ) {
7003  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7004  }
7005 
7006  DerestrictTrait_<This> left( derestrict( *this ) );
7007 
7008  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
7009  (~rhs).canAlias( &matrix_ ) ) {
7010  const AddType tmp( *this + (~rhs) );
7011  smpAssign( left, tmp );
7012  }
7013  else {
7014  smpAddAssign( left, ~rhs );
7015  }
7016 
7017  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
7018 
7019  return *this;
7020 }
7022 //*************************************************************************************************
7023 
7024 
7025 //*************************************************************************************************
7039 template< typename MT > // Type of the dense matrix
7040 template< typename MT2 // Type of the right-hand side matrix
7041  , bool SO > // Storage order of the right-hand side matrix
7042 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,false,true>& >
7043  Submatrix<MT,aligned,false,true>::operator+=( const Matrix<MT2,SO>& rhs )
7044 {
7048 
7049  typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
7050 
7053 
7054  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
7055  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
7056  }
7057 
7058  const AddType tmp( *this + (~rhs) );
7059 
7060  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
7061  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7062  }
7063 
7064  DerestrictTrait_<This> left( derestrict( *this ) );
7065 
7066  smpAssign( left, tmp );
7067 
7068  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
7069 
7070  return *this;
7071 }
7073 //*************************************************************************************************
7074 
7075 
7076 //*************************************************************************************************
7090 template< typename MT > // Type of the dense matrix
7091 template< typename MT2 // Type of the right-hand side matrix
7092  , bool SO > // Storage order of the right-hand side matrix
7093 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,false,true>& >
7094  Submatrix<MT,aligned,false,true>::operator-=( const Matrix<MT2,SO>& rhs )
7095 {
7099 
7100  typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
7101 
7104 
7105  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
7106  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
7107  }
7108 
7109  if( !trySubAssign( matrix_, ~rhs, row_, column_ ) ) {
7110  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7111  }
7112 
7113  DerestrictTrait_<This> left( derestrict( *this ) );
7114 
7115  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
7116  (~rhs).canAlias( &matrix_ ) ) {
7117  const SubType tmp( *this - (~rhs ) );
7118  smpAssign( left, tmp );
7119  }
7120  else {
7121  smpSubAssign( left, ~rhs );
7122  }
7123 
7124  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
7125 
7126  return *this;
7127 }
7129 //*************************************************************************************************
7130 
7131 
7132 //*************************************************************************************************
7146 template< typename MT > // Type of the dense matrix
7147 template< typename MT2 // Type of the right-hand side matrix
7148  , bool SO > // Storage order of the right-hand side matrix
7149 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,false,true>& >
7150  Submatrix<MT,aligned,false,true>::operator-=( const Matrix<MT2,SO>& rhs )
7151 {
7155 
7156  typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
7157 
7160 
7161  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
7162  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
7163  }
7164 
7165  const SubType tmp( *this - (~rhs) );
7166 
7167  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
7168  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7169  }
7170 
7171  DerestrictTrait_<This> left( derestrict( *this ) );
7172 
7173  smpAssign( left, tmp );
7174 
7175  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
7176 
7177  return *this;
7178 }
7180 //*************************************************************************************************
7181 
7182 
7183 //*************************************************************************************************
7197 template< typename MT > // Type of the dense matrix
7198 template< typename MT2 // Type of the right-hand side matrix
7199  , bool SO > // Storage order of the right-hand side matrix
7200 inline Submatrix<MT,aligned,false,true>&
7201  Submatrix<MT,aligned,false,true>::operator*=( const Matrix<MT2,SO>& rhs )
7202 {
7206 
7207  typedef MultTrait_< ResultType, ResultType_<MT2> > MultType;
7208 
7211 
7212  if( columns() != (~rhs).rows() ) {
7213  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
7214  }
7215 
7216  const MultType tmp( *this * (~rhs) );
7217 
7218  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
7219  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7220  }
7221 
7222  DerestrictTrait_<This> left( derestrict( *this ) );
7223 
7224  smpAssign( left, tmp );
7225 
7226  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
7227 
7228  return *this;
7229 }
7231 //*************************************************************************************************
7232 
7233 
7234 //*************************************************************************************************
7245 template< typename MT > // Type of the dense matrix
7246 template< typename Other > // Data type of the right-hand side scalar
7247 inline EnableIf_< IsNumeric<Other>, Submatrix<MT,aligned,false,true> >&
7249 {
7251 
7252  DerestrictTrait_<This> left( derestrict( *this ) );
7253  smpAssign( left, (*this) * rhs );
7254 
7255  return *this;
7256 }
7258 //*************************************************************************************************
7259 
7260 
7261 //*************************************************************************************************
7274 template< typename MT > // Type of the dense matrix
7275 template< typename Other > // Data type of the right-hand side scalar
7276 inline EnableIf_< IsNumeric<Other>, Submatrix<MT,aligned,false,true> >&
7278 {
7280 
7281  BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
7282 
7283  DerestrictTrait_<This> left( derestrict( *this ) );
7284  smpAssign( left, (*this) / rhs );
7285 
7286  return *this;
7287 }
7289 //*************************************************************************************************
7290 
7291 
7292 
7293 
7294 //=================================================================================================
7295 //
7296 // UTILITY FUNCTIONS
7297 //
7298 //=================================================================================================
7299 
7300 //*************************************************************************************************
7306 template< typename MT > // Type of the dense matrix
7307 inline size_t Submatrix<MT,aligned,false,true>::row() const noexcept
7308 {
7309  return row_;
7310 }
7312 //*************************************************************************************************
7313 
7314 
7315 //*************************************************************************************************
7321 template< typename MT > // Type of the dense matrix
7322 inline size_t Submatrix<MT,aligned,false,true>::rows() const noexcept
7323 {
7324  return m_;
7325 }
7327 //*************************************************************************************************
7328 
7329 
7330 //*************************************************************************************************
7336 template< typename MT > // Type of the dense matrix
7337 inline size_t Submatrix<MT,aligned,false,true>::column() const noexcept
7338 {
7339  return column_;
7340 }
7342 //*************************************************************************************************
7343 
7344 
7345 //*************************************************************************************************
7351 template< typename MT > // Type of the dense matrix
7352 inline size_t Submatrix<MT,aligned,false,true>::columns() const noexcept
7353 {
7354  return n_;
7355 }
7357 //*************************************************************************************************
7358 
7359 
7360 //*************************************************************************************************
7371 template< typename MT > // Type of the dense matrix
7372 inline size_t Submatrix<MT,aligned,false,true>::spacing() const noexcept
7373 {
7374  return matrix_.spacing();
7375 }
7377 //*************************************************************************************************
7378 
7379 
7380 //*************************************************************************************************
7386 template< typename MT > // Type of the dense matrix
7387 inline size_t Submatrix<MT,aligned,false,true>::capacity() const noexcept
7388 {
7389  return rows() * columns();
7390 }
7392 //*************************************************************************************************
7393 
7394 
7395 //*************************************************************************************************
7407 template< typename MT > // Type of the dense matrix
7408 inline size_t Submatrix<MT,aligned,false,true>::capacity( size_t i ) const noexcept
7409 {
7410  UNUSED_PARAMETER( i );
7411 
7412  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
7413 
7414  return columns();
7415 }
7417 //*************************************************************************************************
7418 
7419 
7420 //*************************************************************************************************
7426 template< typename MT > // Type of the dense matrix
7427 inline size_t Submatrix<MT,aligned,false,true>::nonZeros() const
7428 {
7429  const size_t iend( row_ + m_ );
7430  const size_t jend( column_ + n_ );
7431  size_t nonzeros( 0UL );
7432 
7433  for( size_t i=row_; i<iend; ++i )
7434  for( size_t j=column_; j<jend; ++j )
7435  if( !isDefault( matrix_(i,j) ) )
7436  ++nonzeros;
7437 
7438  return nonzeros;
7439 }
7441 //*************************************************************************************************
7442 
7443 
7444 //*************************************************************************************************
7456 template< typename MT > // Type of the dense matrix
7457 inline size_t Submatrix<MT,aligned,false,true>::nonZeros( size_t i ) const
7458 {
7459  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
7460 
7461  const size_t jend( column_ + n_ );
7462  size_t nonzeros( 0UL );
7463 
7464  for( size_t j=column_; j<jend; ++j )
7465  if( !isDefault( matrix_(row_+i,j) ) )
7466  ++nonzeros;
7467 
7468  return nonzeros;
7469 }
7471 //*************************************************************************************************
7472 
7473 
7474 //*************************************************************************************************
7480 template< typename MT > // Type of the dense matrix
7482 {
7483  using blaze::clear;
7484 
7485  for( size_t i=row_; i<row_+m_; ++i )
7486  {
7487  const size_t jbegin( ( IsUpper<MT>::value )
7488  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
7489  ?( max( i+1UL, column_ ) )
7490  :( max( i, column_ ) ) )
7491  :( column_ ) );
7492  const size_t jend ( ( IsLower<MT>::value )
7493  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
7494  ?( min( i, column_+n_ ) )
7495  :( min( i+1UL, column_+n_ ) ) )
7496  :( column_+n_ ) );
7497 
7498  for( size_t j=jbegin; j<jend; ++j )
7499  clear( matrix_(i,j) );
7500  }
7501 }
7503 //*************************************************************************************************
7504 
7505 
7506 //*************************************************************************************************
7518 template< typename MT > // Type of the dense matrix
7519 inline void Submatrix<MT,aligned,false,true>::reset( size_t i )
7520 {
7521  using blaze::clear;
7522 
7523  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
7524 
7525  const size_t jbegin( ( IsUpper<MT>::value )
7526  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
7527  ?( max( i+1UL, column_ ) )
7528  :( max( i, column_ ) ) )
7529  :( column_ ) );
7530  const size_t jend ( ( IsLower<MT>::value )
7531  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
7532  ?( min( i, column_+n_ ) )
7533  :( min( i+1UL, column_+n_ ) ) )
7534  :( column_+n_ ) );
7535 
7536  for( size_t j=jbegin; j<jend; ++j )
7537  clear( matrix_(row_+i,j) );
7538 }
7540 //*************************************************************************************************
7541 
7542 
7543 //*************************************************************************************************
7553 template< typename MT > // Type of the dense matrix
7554 inline bool Submatrix<MT,aligned,false,true>::hasOverlap() const noexcept
7555 {
7556  BLAZE_INTERNAL_ASSERT( IsSymmetric<MT>::value || IsHermitian<MT>::value, "Invalid matrix detected" );
7557 
7558  if( ( row_ + m_ <= column_ ) || ( column_ + n_ <= row_ ) )
7559  return false;
7560  else return true;
7561 }
7563 //*************************************************************************************************
7564 
7565 
7566 
7567 
7568 //=================================================================================================
7569 //
7570 // NUMERIC FUNCTIONS
7571 //
7572 //=================================================================================================
7573 
7574 //*************************************************************************************************
7592 template< typename MT > // Type of the dense matrix
7593 inline Submatrix<MT,aligned,false,true>& Submatrix<MT,aligned,false,true>::transpose()
7594 {
7595  if( m_ != n_ ) {
7596  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
7597  }
7598 
7599  if( !tryAssign( matrix_, trans( *this ), row_, column_ ) ) {
7600  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
7601  }
7602 
7603  DerestrictTrait_<This> left( derestrict( *this ) );
7604  const ResultType tmp( trans( *this ) );
7605  smpAssign( left, tmp );
7606 
7607  return *this;
7608 }
7610 //*************************************************************************************************
7611 
7612 
7613 //*************************************************************************************************
7631 template< typename MT > // Type of the dense matrix
7632 inline Submatrix<MT,aligned,false,true>& Submatrix<MT,aligned,false,true>::ctranspose()
7633 {
7634  if( m_ != n_ ) {
7635  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
7636  }
7637 
7638  if( !tryAssign( matrix_, ctrans( *this ), row_, column_ ) ) {
7639  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
7640  }
7641 
7642  DerestrictTrait_<This> left( derestrict( *this ) );
7643  const ResultType tmp( ctrans( *this ) );
7644  smpAssign( left, tmp );
7645 
7646  return *this;
7647 }
7649 //*************************************************************************************************
7650 
7651 
7652 //*************************************************************************************************
7663 template< typename MT > // Type of the dense matrix
7664 template< typename Other > // Data type of the scalar value
7665 inline Submatrix<MT,aligned,false,true>& Submatrix<MT,aligned,false,true>::scale( const Other& scalar )
7666 {
7668 
7669  const size_t iend( row_ + m_ );
7670 
7671  for( size_t i=row_; i<iend; ++i )
7672  {
7673  const size_t jbegin( ( IsUpper<MT>::value )
7674  ?( ( IsStrictlyUpper<MT>::value )
7675  ?( max( i+1UL, column_ ) )
7676  :( max( i, column_ ) ) )
7677  :( column_ ) );
7678  const size_t jend ( ( IsLower<MT>::value )
7679  ?( ( IsStrictlyLower<MT>::value )
7680  ?( min( i, column_+n_ ) )
7681  :( min( i+1UL, column_+n_ ) ) )
7682  :( column_+n_ ) );
7683 
7684  for( size_t j=jbegin; j<jend; ++j )
7685  matrix_(i,j) *= scalar;
7686  }
7687 
7688  return *this;
7689 }
7691 //*************************************************************************************************
7692 
7693 
7694 
7695 
7696 //=================================================================================================
7697 //
7698 // EXPRESSION TEMPLATE EVALUATION FUNCTIONS
7699 //
7700 //=================================================================================================
7701 
7702 //*************************************************************************************************
7713 template< typename MT > // Type of the dense matrix
7714 template< typename Other > // Data type of the foreign expression
7715 inline bool Submatrix<MT,aligned,false,true>::canAlias( const Other* alias ) const noexcept
7716 {
7717  return matrix_.isAliased( alias );
7718 }
7720 //*************************************************************************************************
7721 
7722 
7723 //*************************************************************************************************
7734 template< typename MT > // Type of the dense matrix
7735 template< typename MT2 // Data type of the foreign dense submatrix
7736  , bool AF2 // Alignment flag of the foreign dense submatrix
7737  , bool SO2 > // Storage order of the foreign dense submatrix
7738 inline bool Submatrix<MT,aligned,false,true>::canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
7739 {
7740  return ( matrix_.isAliased( &alias->matrix_ ) &&
7741  ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
7742  ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
7743 }
7745 //*************************************************************************************************
7746 
7747 
7748 //*************************************************************************************************
7759 template< typename MT > // Type of the dense matrix
7760 template< typename Other > // Data type of the foreign expression
7761 inline bool Submatrix<MT,aligned,false,true>::isAliased( const Other* alias ) const noexcept
7762 {
7763  return matrix_.isAliased( alias );
7764 }
7766 //*************************************************************************************************
7767 
7768 
7769 //*************************************************************************************************
7780 template< typename MT > // Type of the dense matrix
7781 template< typename MT2 // Data type of the foreign dense submatrix
7782  , bool AF2 // Alignment flag of the foreign dense submatrix
7783  , bool SO2 > // Storage order of the foreign dense submatrix
7784 inline bool Submatrix<MT,aligned,false,true>::isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
7785 {
7786  return ( matrix_.isAliased( &alias->matrix_ ) &&
7787  ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
7788  ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
7789 }
7791 //*************************************************************************************************
7792 
7793 
7794 //*************************************************************************************************
7804 template< typename MT > // Type of the dense matrix
7805 inline bool Submatrix<MT,aligned,false,true>::isAligned() const noexcept
7806 {
7807  return true;
7808 }
7810 //*************************************************************************************************
7811 
7812 
7813 //*************************************************************************************************
7824 template< typename MT > // Type of the dense matrix
7825 inline bool Submatrix<MT,aligned,false,true>::canSMPAssign() const noexcept
7826 {
7827  return ( rows() * columns() >= SMP_DMATASSIGN_THRESHOLD );
7828 }
7830 //*************************************************************************************************
7831 
7832 
7833 //*************************************************************************************************
7849 template< typename MT > // Type of the dense matrix
7850 BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,false,true>::SIMDType
7851  Submatrix<MT,aligned,false,true>::load( size_t i, size_t j ) const noexcept
7852 {
7853  return loada( i, j );
7854 }
7856 //*************************************************************************************************
7857 
7858 
7859 //*************************************************************************************************
7875 template< typename MT > // Type of the dense matrix
7876 BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,false,true>::SIMDType
7877  Submatrix<MT,aligned,false,true>::loada( size_t i, size_t j ) const noexcept
7878 {
7880 
7881  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
7882  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
7883  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
7884  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
7885 
7886  return matrix_.loada( row_+i, column_+j );
7887 }
7889 //*************************************************************************************************
7890 
7891 
7892 //*************************************************************************************************
7908 template< typename MT > // Type of the dense matrix
7909 BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,false,true>::SIMDType
7910  Submatrix<MT,aligned,false,true>::loadu( size_t i, size_t j ) const noexcept
7911 {
7913 
7914  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
7915  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
7916  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
7917  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
7918 
7919  return matrix_.loadu( row_+i, column_+j );
7920 }
7922 //*************************************************************************************************
7923 
7924 
7925 //*************************************************************************************************
7942 template< typename MT > // Type of the dense matrix
7944  Submatrix<MT,aligned,false,true>::store( size_t i, size_t j, const SIMDType& value ) noexcept
7945 {
7946  return storea( i, j, value );
7947 }
7949 //*************************************************************************************************
7950 
7951 
7952 //*************************************************************************************************
7969 template< typename MT > // Type of the dense matrix
7971  Submatrix<MT,aligned,false,true>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
7972 {
7974 
7975  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
7976  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
7977  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
7978  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
7979 
7980  return matrix_.storea( row_+i, column_+j, value );
7981 }
7983 //*************************************************************************************************
7984 
7985 
7986 //*************************************************************************************************
8003 template< typename MT > // Type of the dense matrix
8005  Submatrix<MT,aligned,false,true>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
8006 {
8008 
8009  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
8010  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
8011  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
8012  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
8013 
8014  matrix_.storeu( row_+i, column_+j, value );
8015 }
8017 //*************************************************************************************************
8018 
8019 
8020 //*************************************************************************************************
8038 template< typename MT > // Type of the dense matrix
8040  Submatrix<MT,aligned,false,true>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
8041 {
8043 
8044  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
8045  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
8046  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
8047  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
8048 
8049  matrix_.stream( row_+i, column_+j, value );
8050 }
8052 //*************************************************************************************************
8053 
8054 
8055 //*************************************************************************************************
8067 template< typename MT > // Type of the dense matrix
8068 template< typename MT2 > // Type of the right-hand side dense matrix
8069 inline DisableIf_< typename Submatrix<MT,aligned,false,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
8070  Submatrix<MT,aligned,false,true>::assign( const DenseMatrix<MT2,false>& rhs )
8071 {
8072  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8073  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8074 
8075  const size_t jpos( n_ & size_t(-2) );
8076  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
8077 
8078  for( size_t i=0UL; i<m_; ++i ) {
8079  for( size_t j=0UL; j<jpos; j+=2UL ) {
8080  matrix_(row_+i,column_+j ) = (~rhs)(i,j );
8081  matrix_(row_+i,column_+j+1UL) = (~rhs)(i,j+1UL);
8082  }
8083  if( jpos < n_ ) {
8084  matrix_(row_+i,column_+jpos) = (~rhs)(i,jpos);
8085  }
8086  }
8087 }
8089 //*************************************************************************************************
8090 
8091 
8092 //*************************************************************************************************
8104 template< typename MT > // Type of the dense matrix
8105 template< typename MT2 > // Type of the right-hand side dense matrix
8106 inline EnableIf_< typename Submatrix<MT,aligned,false,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
8107  Submatrix<MT,aligned,false,true>::assign( const DenseMatrix<MT2,false>& rhs )
8108 {
8110 
8111  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8112  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8113 
8114  const size_t jpos( n_ & size_t(-SIMDSIZE) );
8115  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
8116 
8117  if( useStreaming &&
8118  m_*n_ > ( cacheSize / ( sizeof(ElementType) * 3UL ) ) &&
8119  !(~rhs).isAliased( &matrix_ ) )
8120  {
8121  for( size_t i=0UL; i<m_; ++i )
8122  {
8123  size_t j( 0UL );
8124  Iterator left( begin(i) );
8125  ConstIterator_<MT2> right( (~rhs).begin(i) );
8126 
8127  for( ; j<jpos; j+=SIMDSIZE ) {
8128  left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8129  }
8130  for( ; j<n_; ++j ) {
8131  *left = *right; ++left; ++right;
8132  }
8133  }
8134  }
8135  else
8136  {
8137  for( size_t i=0UL; i<m_; ++i )
8138  {
8139  size_t j( 0UL );
8140  Iterator left( begin(i) );
8141  ConstIterator_<MT2> right( (~rhs).begin(i) );
8142 
8143  for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
8144  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8145  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8146  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8147  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8148  }
8149  for( ; j<jpos; j+=SIMDSIZE ) {
8150  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8151  }
8152  for( ; j<n_; ++j ) {
8153  *left = *right; ++left; ++right;
8154  }
8155  }
8156  }
8157 }
8159 //*************************************************************************************************
8160 
8161 
8162 //*************************************************************************************************
8174 template< typename MT > // Type of the dense matrix
8175 template< typename MT2 > // Type of the right-hand side dense matrix
8176 inline void Submatrix<MT,aligned,false,true>::assign( const DenseMatrix<MT2,true>& rhs )
8177 {
8179 
8180  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8181  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8182 
8183  constexpr size_t block( BLOCK_SIZE );
8184 
8185  for( size_t ii=0UL; ii<m_; ii+=block ) {
8186  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
8187  for( size_t jj=0UL; jj<n_; jj+=block ) {
8188  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
8189  for( size_t i=ii; i<iend; ++i ) {
8190  for( size_t j=jj; j<jend; ++j ) {
8191  matrix_(row_+i,column_+j) = (~rhs)(i,j);
8192  }
8193  }
8194  }
8195  }
8196 }
8198 //*************************************************************************************************
8199 
8200 
8201 //*************************************************************************************************
8213 template< typename MT > // Type of the dense matrix
8214 template< typename MT2 > // Type of the right-hand side sparse matrix
8215 inline void Submatrix<MT,aligned,false,true>::assign( const SparseMatrix<MT2,false>& rhs )
8216 {
8217  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8218  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8219 
8220  for( size_t i=0UL; i<m_; ++i )
8221  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
8222  matrix_(row_+i,column_+element->index()) = element->value();
8223 }
8225 //*************************************************************************************************
8226 
8227 
8228 //*************************************************************************************************
8240 template< typename MT > // Type of the dense matrix
8241 template< typename MT2 > // Type of the right-hand side sparse matrix
8242 inline void Submatrix<MT,aligned,false,true>::assign( const SparseMatrix<MT2,true>& rhs )
8243 {
8245 
8246  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8247  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8248 
8249  for( size_t j=0UL; j<n_; ++j )
8250  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
8251  matrix_(row_+element->index(),column_+j) = element->value();
8252 }
8254 //*************************************************************************************************
8255 
8256 
8257 //*************************************************************************************************
8269 template< typename MT > // Type of the dense matrix
8270 template< typename MT2 > // Type of the right-hand side dense matrix
8271 inline DisableIf_< typename Submatrix<MT,aligned,false,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
8272  Submatrix<MT,aligned,false,true>::addAssign( const DenseMatrix<MT2,false>& rhs )
8273 {
8274  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8275  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8276 
8277  const size_t jpos( n_ & size_t(-2) );
8278  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
8279 
8280  for( size_t i=0UL; i<m_; ++i )
8281  {
8282  if( IsDiagonal<MT2>::value ) {
8283  matrix_(row_+i,column_+i) += (~rhs)(i,i);
8284  }
8285  else {
8286  for( size_t j=0UL; j<jpos; j+=2UL ) {
8287  matrix_(row_+i,column_+j ) += (~rhs)(i,j );
8288  matrix_(row_+i,column_+j+1UL) += (~rhs)(i,j+1UL);
8289  }
8290  if( jpos < n_ ) {
8291  matrix_(row_+i,column_+jpos) += (~rhs)(i,jpos);
8292  }
8293  }
8294  }
8295 }
8297 //*************************************************************************************************
8298 
8299 
8300 //*************************************************************************************************
8312 template< typename MT > // Type of the dense matrix
8313 template< typename MT2 > // Type of the right-hand side dense matrix
8314 inline EnableIf_< typename Submatrix<MT,aligned,false,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
8315  Submatrix<MT,aligned,false,true>::addAssign( const DenseMatrix<MT2,false>& rhs )
8316 {
8318 
8319  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8320  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8321 
8322  for( size_t i=0UL; i<m_; ++i )
8323  {
8324  const size_t jbegin( ( IsUpper<MT2>::value )
8325  ?( ( IsStrictlyUpper<MT2>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
8326  :( 0UL ) );
8327  const size_t jend ( ( IsLower<MT2>::value )
8328  ?( IsStrictlyLower<MT2>::value ? i : i+1UL )
8329  :( n_ ) );
8330  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
8331 
8332  const size_t jpos( jend & size_t(-SIMDSIZE) );
8333  BLAZE_INTERNAL_ASSERT( ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
8334 
8335  size_t j( jbegin );
8336  Iterator left( begin(i) + jbegin );
8337  ConstIterator_<MT2> right( (~rhs).begin(i) + jbegin );
8338 
8339  for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
8340  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8341  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8342  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8343  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8344  }
8345  for( ; j<jpos; j+=SIMDSIZE ) {
8346  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8347  }
8348  for( ; j<jend; ++j ) {
8349  *left += *right; ++left; ++right;
8350  }
8351  }
8352 }
8354 //*************************************************************************************************
8355 
8356 
8357 //*************************************************************************************************
8369 template< typename MT > // Type of the dense matrix
8370 template< typename MT2 > // Type of the right-hand side dense matrix
8371 inline void Submatrix<MT,aligned,false,true>::addAssign( const DenseMatrix<MT2,true>& rhs )
8372 {
8374 
8375  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8376  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8377 
8378  constexpr size_t block( BLOCK_SIZE );
8379 
8380  for( size_t ii=0UL; ii<m_; ii+=block ) {
8381  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
8382  for( size_t jj=0UL; jj<n_; jj+=block ) {
8383  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
8384  for( size_t i=ii; i<iend; ++i ) {
8385  for( size_t j=jj; j<jend; ++j ) {
8386  matrix_(row_+i,column_+j) += (~rhs)(i,j);
8387  }
8388  }
8389  }
8390  }
8391 }
8393 //*************************************************************************************************
8394 
8395 
8396 //*************************************************************************************************
8408 template< typename MT > // Type of the dense matrix
8409 template< typename MT2 > // Type of the right-hand side sparse matrix
8410 inline void Submatrix<MT,aligned,false,true>::addAssign( const SparseMatrix<MT2,false>& rhs )
8411 {
8412  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8413  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8414 
8415  for( size_t i=0UL; i<m_; ++i )
8416  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
8417  matrix_(row_+i,column_+element->index()) += element->value();
8418 }
8420 //*************************************************************************************************
8421 
8422 
8423 //*************************************************************************************************
8435 template< typename MT > // Type of the dense matrix
8436 template< typename MT2 > // Type of the right-hand side sparse matrix
8437 inline void Submatrix<MT,aligned,false,true>::addAssign( const SparseMatrix<MT2,true>& rhs )
8438 {
8440 
8441  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8442  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8443 
8444  for( size_t j=0UL; j<n_; ++j )
8445  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
8446  matrix_(row_+element->index(),column_+j) += element->value();
8447 }
8449 //*************************************************************************************************
8450 
8451 
8452 //*************************************************************************************************
8464 template< typename MT > // Type of the dense matrix
8465 template< typename MT2 > // Type of the right-hand side dense matrix
8466 inline DisableIf_< typename Submatrix<MT,aligned,false,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
8467  Submatrix<MT,aligned,false,true>::subAssign( const DenseMatrix<MT2,false>& rhs )
8468 {
8469  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8470  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8471 
8472  const size_t jpos( n_ & size_t(-2) );
8473  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
8474 
8475  for( size_t i=0UL; i<m_; ++i )
8476  {
8477  if( IsDiagonal<MT2>::value ) {
8478  matrix_(row_+i,column_+i) -= (~rhs)(i,i);
8479  }
8480  else {
8481  for( size_t j=0UL; j<jpos; j+=2UL ) {
8482  matrix_(row_+i,column_+j ) -= (~rhs)(i,j );
8483  matrix_(row_+i,column_+j+1UL) -= (~rhs)(i,j+1UL);
8484  }
8485  if( jpos < n_ ) {
8486  matrix_(row_+i,column_+jpos) -= (~rhs)(i,jpos);
8487  }
8488  }
8489  }
8490 }
8492 //*************************************************************************************************
8493 
8494 
8495 //*************************************************************************************************
8507 template< typename MT > // Type of the dense matrix
8508 template< typename MT2 > // Type of the right-hand side dense matrix
8509 inline EnableIf_< typename Submatrix<MT,aligned,false,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
8510  Submatrix<MT,aligned,false,true>::subAssign( const DenseMatrix<MT2,false>& rhs )
8511 {
8513 
8514  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8515  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8516 
8517  for( size_t i=0UL; i<m_; ++i )
8518  {
8519  const size_t jbegin( ( IsUpper<MT2>::value )
8520  ?( ( IsStrictlyUpper<MT2>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
8521  :( 0UL ) );
8522  const size_t jend ( ( IsLower<MT2>::value )
8523  ?( IsStrictlyLower<MT2>::value ? i : i+1UL )
8524  :( n_ ) );
8525  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
8526 
8527  const size_t jpos( jend & size_t(-SIMDSIZE) );
8528  BLAZE_INTERNAL_ASSERT( ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
8529 
8530  size_t j( jbegin );
8531  Iterator left( begin(i) + jbegin );
8532  ConstIterator_<MT2> right( (~rhs).begin(i) + jbegin );
8533 
8534  for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
8535  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8536  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8537  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8538  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8539  }
8540  for( ; j<jpos; j+=SIMDSIZE ) {
8541  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8542  }
8543  for( ; j<jend; ++j ) {
8544  *left -= *right; ++left; ++right;
8545  }
8546  }
8547 }
8549 //*************************************************************************************************
8550 
8551 
8552 //*************************************************************************************************
8564 template< typename MT > // Type of the dense matrix
8565 template< typename MT2 > // Type of the right-hand side dense matrix
8566 inline void Submatrix<MT,aligned,false,true>::subAssign( const DenseMatrix<MT2,true>& rhs )
8567 {
8569 
8570  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8571  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8572 
8573  constexpr size_t block( BLOCK_SIZE );
8574 
8575  for( size_t ii=0UL; ii<m_; ii+=block ) {
8576  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
8577  for( size_t jj=0UL; jj<n_; jj+=block ) {
8578  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
8579  for( size_t i=ii; i<iend; ++i ) {
8580  for( size_t j=jj; j<jend; ++j ) {
8581  matrix_(row_+i,column_+j) -= (~rhs)(i,j);
8582  }
8583  }
8584  }
8585  }
8586 }
8588 //*************************************************************************************************
8589 
8590 
8591 //*************************************************************************************************
8603 template< typename MT > // Type of the dense matrix
8604 template< typename MT2 > // Type of the right-hand side sparse matrix
8605 inline void Submatrix<MT,aligned,false,true>::subAssign( const SparseMatrix<MT2,false>& rhs )
8606 {
8607  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8608  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8609 
8610  for( size_t i=0UL; i<m_; ++i )
8611  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
8612  matrix_(row_+i,column_+element->index()) -= element->value();
8613 }
8615 //*************************************************************************************************
8616 
8617 
8618 //*************************************************************************************************
8630 template< typename MT > // Type of the dense matrix
8631 template< typename MT2 > // Type of the right-hand side sparse matrix
8632 inline void Submatrix<MT,aligned,false,true>::subAssign( const SparseMatrix<MT2,true>& rhs )
8633 {
8635 
8636  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8637  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8638 
8639  for( size_t j=0UL; j<n_; ++j )
8640  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
8641  matrix_(row_+element->index(),column_+j) -= element->value();
8642 }
8644 //*************************************************************************************************
8645 
8646 
8647 
8648 
8649 
8650 
8651 
8652 
8653 //=================================================================================================
8654 //
8655 // CLASS TEMPLATE SPECIALIZATION FOR ALIGNED COLUMN-MAJOR DENSE SUBMATRICES
8656 //
8657 //=================================================================================================
8658 
8659 //*************************************************************************************************
8667 template< typename MT > // Type of the dense matrix
8668 class Submatrix<MT,aligned,true,true>
8669  : public DenseMatrix< Submatrix<MT,aligned,true,true>, true >
8670  , private View
8671 {
8672  private:
8673  //**Type definitions****************************************************************************
8675  typedef If_< IsExpression<MT>, MT, MT& > Operand;
8676  //**********************************************************************************************
8677 
8678  public:
8679  //**Type definitions****************************************************************************
8680  typedef Submatrix<MT,aligned,true,true> This;
8681  typedef DenseMatrix<This,true> BaseType;
8682  typedef SubmatrixTrait_<MT> ResultType;
8683  typedef OppositeType_<ResultType> OppositeType;
8684  typedef TransposeType_<ResultType> TransposeType;
8685  typedef ElementType_<MT> ElementType;
8686  typedef SIMDTrait_<ElementType> SIMDType;
8687  typedef ReturnType_<MT> ReturnType;
8688  typedef const Submatrix& CompositeType;
8689 
8691  typedef ConstReference_<MT> ConstReference;
8692 
8694  typedef If_< IsConst<MT>, ConstReference, Reference_<MT> > Reference;
8695 
8697  typedef const ElementType* ConstPointer;
8698 
8700  typedef If_< Or< IsConst<MT>, Not< HasMutableDataAccess<MT> > >, ConstPointer, ElementType* > Pointer;
8701 
8703  typedef ConstIterator_<MT> ConstIterator;
8704 
8706  typedef If_< IsConst<MT>, ConstIterator, Iterator_<MT> > Iterator;
8707  //**********************************************************************************************
8708 
8709  //**Compilation flags***************************************************************************
8711  enum : bool { simdEnabled = MT::simdEnabled };
8712 
8714  enum : bool { smpAssignable = MT::smpAssignable };
8715  //**********************************************************************************************
8716 
8717  //**Constructors********************************************************************************
8720  explicit inline Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n );
8721  // No explicitly declared copy constructor.
8723  //**********************************************************************************************
8724 
8725  //**Destructor**********************************************************************************
8726  // No explicitly declared destructor.
8727  //**********************************************************************************************
8728 
8729  //**Data access functions***********************************************************************
8732  inline Reference operator()( size_t i, size_t j );
8733  inline ConstReference operator()( size_t i, size_t j ) const;
8734  inline Reference at( size_t i, size_t j );
8735  inline ConstReference at( size_t i, size_t j ) const;
8736  inline Pointer data () noexcept;
8737  inline ConstPointer data () const noexcept;
8738  inline Pointer data ( size_t j ) noexcept;
8739  inline ConstPointer data ( size_t j ) const noexcept;
8740  inline Iterator begin ( size_t j );
8741  inline ConstIterator begin ( size_t j ) const;
8742  inline ConstIterator cbegin( size_t j ) const;
8743  inline Iterator end ( size_t j );
8744  inline ConstIterator end ( size_t j ) const;
8745  inline ConstIterator cend ( size_t j ) const;
8747  //**********************************************************************************************
8748 
8749  //**Assignment operators************************************************************************
8752  inline Submatrix& operator=( const ElementType& rhs );
8753  inline Submatrix& operator=( initializer_list< initializer_list<ElementType> > list );
8754  inline Submatrix& operator=( const Submatrix& rhs );
8755 
8756  template< typename MT2, bool SO >
8757  inline Submatrix& operator=( const Matrix<MT2,SO>& rhs );
8758 
8759  template< typename MT2, bool SO >
8760  inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
8761  operator+=( const Matrix<MT2,SO>& rhs );
8762 
8763  template< typename MT2, bool SO >
8764  inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
8765  operator+=( const Matrix<MT2,SO>& rhs );
8766 
8767  template< typename MT2, bool SO >
8768  inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
8769  operator-=( const Matrix<MT2,SO>& rhs );
8770 
8771  template< typename MT2, bool SO >
8772  inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
8773  operator-=( const Matrix<MT2,SO>& rhs );
8774 
8775  template< typename MT2, bool SO >
8776  inline Submatrix& operator*=( const Matrix<MT2,SO>& rhs );
8777 
8778  template< typename Other >
8779  inline EnableIf_< IsNumeric<Other>, Submatrix >& operator*=( Other rhs );
8780 
8781  template< typename Other >
8782  inline EnableIf_< IsNumeric<Other>, Submatrix >& operator/=( Other rhs );
8784  //**********************************************************************************************
8785 
8786  //**Utility functions***************************************************************************
8789  inline size_t row() const noexcept;
8790  inline size_t rows() const noexcept;
8791  inline size_t column() const noexcept;
8792  inline size_t columns() const noexcept;
8793  inline size_t spacing() const noexcept;
8794  inline size_t capacity() const noexcept;
8795  inline size_t capacity( size_t i ) const noexcept;
8796  inline size_t nonZeros() const;
8797  inline size_t nonZeros( size_t i ) const;
8798  inline void reset();
8799  inline void reset( size_t i );
8801  //**********************************************************************************************
8802 
8803  //**Numeric functions***************************************************************************
8806  inline Submatrix& transpose();
8807  inline Submatrix& ctranspose();
8808 
8809  template< typename Other > inline Submatrix& scale( const Other& scalar );
8811  //**********************************************************************************************
8812 
8813  private:
8814  //**********************************************************************************************
8816  template< typename MT2 >
8817  struct VectorizedAssign {
8818  enum : bool { value = useOptimizedKernels &&
8819  simdEnabled && MT2::simdEnabled &&
8820  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value };
8821  };
8822  //**********************************************************************************************
8823 
8824  //**********************************************************************************************
8826  template< typename MT2 >
8827  struct VectorizedAddAssign {
8828  enum : bool { value = useOptimizedKernels &&
8829  simdEnabled && MT2::simdEnabled &&
8830  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
8831  HasSIMDAdd< ElementType, ElementType_<MT2> >::value &&
8832  !IsDiagonal<MT2>::value };
8833  };
8834  //**********************************************************************************************
8835 
8836  //**********************************************************************************************
8838  template< typename MT2 >
8839  struct VectorizedSubAssign {
8840  enum : bool { value = useOptimizedKernels &&
8841  simdEnabled && MT2::simdEnabled &&
8842  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
8843  HasSIMDSub< ElementType, ElementType_<MT2> >::value &&
8844  !IsDiagonal<MT2>::value };
8845  };
8846  //**********************************************************************************************
8847 
8848  //**SIMD properties*****************************************************************************
8850  enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
8851  //**********************************************************************************************
8852 
8853  public:
8854  //**Expression template evaluation functions****************************************************
8857  template< typename Other >
8858  inline bool canAlias( const Other* alias ) const noexcept;
8859 
8860  template< typename MT2, bool AF2, bool SO2 >
8861  inline bool canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
8862 
8863  template< typename Other >
8864  inline bool isAliased( const Other* alias ) const noexcept;
8865 
8866  template< typename MT2, bool AF2, bool SO2 >
8867  inline bool isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
8868 
8869  inline bool isAligned () const noexcept;
8870  inline bool canSMPAssign() const noexcept;
8871 
8872  BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
8873  BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
8874  BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
8875 
8876  BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
8877  BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
8878  BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
8879  BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
8880 
8881  template< typename MT2 >
8882  inline DisableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,true>& rhs );
8883 
8884  template< typename MT2 >
8885  inline EnableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,true>& rhs );
8886 
8887  template< typename MT2 > inline void assign( const DenseMatrix<MT2,false>& rhs );
8888  template< typename MT2 > inline void assign( const SparseMatrix<MT2,true>& rhs );
8889  template< typename MT2 > inline void assign( const SparseMatrix<MT2,false>& rhs );
8890 
8891  template< typename MT2 >
8892  inline DisableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,true>& rhs );
8893 
8894  template< typename MT2 >
8895  inline EnableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,true>& rhs );
8896 
8897  template< typename MT2 > inline void addAssign( const DenseMatrix<MT2,false>& rhs );
8898  template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,true>& rhs );
8899  template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,false>& rhs );
8900 
8901  template< typename MT2 >
8902  inline DisableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,true>& rhs );
8903 
8904  template< typename MT2 >
8905  inline EnableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,true>& rhs );
8906 
8907  template< typename MT2 > inline void subAssign( const DenseMatrix<MT2,false>& rhs );
8908  template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,true>& rhs );
8909  template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,false>& rhs );
8911  //**********************************************************************************************
8912 
8913  private:
8914  //**Utility functions***************************************************************************
8917  inline bool hasOverlap() const noexcept;
8919  //**********************************************************************************************
8920 
8921  //**Member variables****************************************************************************
8924  Operand matrix_;
8925  const size_t row_;
8926  const size_t column_;
8927  const size_t m_;
8928  const size_t n_;
8929 
8930  //**********************************************************************************************
8931 
8932  //**Friend declarations*************************************************************************
8933  template< typename MT2, bool AF2, bool SO2, bool DF2 > friend class Submatrix;
8934 
8935  template< bool AF1, typename MT2, bool AF2, bool SO2, bool DF2 >
8936  friend const Submatrix<MT2,AF1,SO2,DF2>
8937  submatrix( const Submatrix<MT2,AF2,SO2,DF2>& sm, size_t row, size_t column, size_t m, size_t n );
8938 
8939  template< typename MT2, bool AF2, bool SO2, bool DF2 >
8940  friend bool isIntact( const Submatrix<MT2,AF2,SO2,DF2>& sm ) noexcept;
8941 
8942  template< typename MT2, bool AF2, bool SO2, bool DF2 >
8943  friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Matrix<MT2,SO2>& b ) noexcept;
8944 
8945  template< typename MT2, bool AF2, bool SO2, bool DF2 >
8946  friend bool isSame( const Matrix<MT2,SO2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
8947 
8948  template< typename MT2, bool AF2, bool SO2, bool DF2 >
8949  friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
8950 
8951  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
8952  friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
8953  size_t row, size_t column );
8954 
8955  template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
8956  friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
8957  size_t row, size_t column );
8958 
8959  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
8960  friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
8961  size_t row, size_t column );
8962 
8963  template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
8964  friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
8965  size_t row, size_t column );
8966 
8967  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
8968  friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
8969  size_t row, size_t column );
8970 
8971  template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
8972  friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
8973  size_t row, size_t column );
8974 
8975  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
8976  friend bool tryMultAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
8977  size_t row, size_t column );
8978 
8979  template< typename MT2, bool AF2, bool SO2, bool DF2 >
8980  friend DerestrictTrait_< Submatrix<MT2,AF2,SO2,DF2> > derestrict( Submatrix<MT2,AF2,SO2,DF2>& sm );
8981  //**********************************************************************************************
8982 
8983  //**Compile time checks*************************************************************************
8991  //**********************************************************************************************
8992 };
8994 //*************************************************************************************************
8995 
8996 
8997 
8998 
8999 //=================================================================================================
9000 //
9001 // CONSTRUCTOR
9002 //
9003 //=================================================================================================
9004 
9005 //*************************************************************************************************
9019 template< typename MT > // Type of the dense matrix
9020 inline Submatrix<MT,aligned,true,true>::Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n )
9021  : matrix_( matrix ) // The dense matrix containing the submatrix
9022  , row_ ( rindex ) // The first row of the submatrix
9023  , column_( cindex ) // The first column of the submatrix
9024  , m_ ( m ) // The number of rows of the submatrix
9025  , n_ ( n ) // The number of columns of the submatrix
9026 {
9027  if( ( row_ + m_ > matrix_.rows() ) || ( column_ + n_ > matrix_.columns() ) ) {
9028  BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix specification" );
9029  }
9030 
9031  if( ( simdEnabled && matrix_.data() != nullptr && !checkAlignment( data() ) ) ||
9032  ( n_ > 1UL && matrix_.spacing() % SIMDSIZE != 0UL ) ) {
9033  BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix alignment" );
9034  }
9035 }
9037 //*************************************************************************************************
9038 
9039 
9040 
9041 
9042 //=================================================================================================
9043 //
9044 // DATA ACCESS FUNCTIONS
9045 //
9046 //=================================================================================================
9047 
9048 //*************************************************************************************************
9059 template< typename MT > // Type of the dense matrix
9061  Submatrix<MT,aligned,true,true>::operator()( size_t i, size_t j )
9062 {
9063  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
9064  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
9065 
9066  return matrix_(row_+i,column_+j);
9067 }
9069 //*************************************************************************************************
9070 
9071 
9072 //*************************************************************************************************
9083 template< typename MT > // Type of the dense matrix
9085  Submatrix<MT,aligned,true,true>::operator()( size_t i, size_t j ) const
9086 {
9087  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
9088  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
9089 
9090  return const_cast<const MT&>( matrix_ )(row_+i,column_+j);
9091 }
9093 //*************************************************************************************************
9094 
9095 
9096 //*************************************************************************************************
9108 template< typename MT > // Type of the dense matrix
9110  Submatrix<MT,aligned,true,true>::at( size_t i, size_t j )
9111 {
9112  if( i >= rows() ) {
9113  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
9114  }
9115  if( j >= columns() ) {
9116  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
9117  }
9118  return (*this)(i,j);
9119 }
9121 //*************************************************************************************************
9122 
9123 
9124 //*************************************************************************************************
9136 template< typename MT > // Type of the dense matrix
9138  Submatrix<MT,aligned,true,true>::at( size_t i, size_t j ) const
9139 {
9140  if( i >= rows() ) {
9141  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
9142  }
9143  if( j >= columns() ) {
9144  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
9145  }
9146  return (*this)(i,j);
9147 }
9149 //*************************************************************************************************
9150 
9151 
9152 //*************************************************************************************************
9162 template< typename MT > // Type of the dense matrix
9163 inline typename Submatrix<MT,aligned,true,true>::Pointer
9164  Submatrix<MT,aligned,true,true>::data() noexcept
9165 {
9166  return matrix_.data() + row_ + column_*spacing();
9167 }
9169 //*************************************************************************************************
9170 
9171 
9172 //*************************************************************************************************
9182 template< typename MT > // Type of the dense matrix
9183 inline typename Submatrix<MT,aligned,true,true>::ConstPointer
9184  Submatrix<MT,aligned,true,true>::data() const noexcept
9185 {
9186  return matrix_.data() + row_ + column_*spacing();
9187 }
9189 //*************************************************************************************************
9190 
9191 
9192 //*************************************************************************************************
9201 template< typename MT > // Type of the dense matrix
9202 inline typename Submatrix<MT,aligned,true,true>::Pointer
9203  Submatrix<MT,aligned,true,true>::data( size_t j ) noexcept
9204 {
9205  return matrix_.data() + row_ + (column_+j)*spacing();
9206 }
9208 //*************************************************************************************************
9209 
9210 
9211 //*************************************************************************************************
9220 template< typename MT > // Type of the dense matrix
9221 inline typename Submatrix<MT,aligned,true,true>::ConstPointer
9222  Submatrix<MT,aligned,true,true>::data( size_t j ) const noexcept
9223 {
9224  return matrix_.data() + row_ + (column_+j)*spacing();
9225 }
9227 //*************************************************************************************************
9228 
9229 
9230 //*************************************************************************************************
9237 template< typename MT > // Type of the dense matrix
9240 {
9241  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
9242  return ( matrix_.begin( column_ + j ) + row_ );
9243 }
9245 //*************************************************************************************************
9246 
9247 
9248 //*************************************************************************************************
9255 template< typename MT > // Type of the dense matrix
9257  Submatrix<MT,aligned,true,true>::begin( size_t j ) const
9258 {
9259  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
9260  return ( matrix_.cbegin( column_ + j ) + row_ );
9261 }
9263 //*************************************************************************************************
9264 
9265 
9266 //*************************************************************************************************
9273 template< typename MT > // Type of the dense matrix
9275  Submatrix<MT,aligned,true,true>::cbegin( size_t j ) const
9276 {
9277  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
9278  return ( matrix_.cbegin( column_ + j ) + row_ );
9279 }
9281 //*************************************************************************************************
9282 
9283 
9284 //*************************************************************************************************
9291 template< typename MT > // Type of the dense matrix
9294 {
9295  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
9296  return ( matrix_.begin( column_ + j ) + row_ + m_ );
9297 }
9299 //*************************************************************************************************
9300 
9301 
9302 //*************************************************************************************************
9309 template< typename MT > // Type of the dense matrix
9311  Submatrix<MT,aligned,true,true>::end( size_t j ) const
9312 {
9313  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
9314  return ( matrix_.cbegin( column_ + j ) + row_ + m_ );
9315 }
9317 //*************************************************************************************************
9318 
9319 
9320 //*************************************************************************************************
9327 template< typename MT > // Type of the dense matrix
9329  Submatrix<MT,aligned,true,true>::cend( size_t j ) const
9330 {
9331  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
9332  return ( matrix_.cbegin( column_ + j ) + row_ + m_ );
9333 }
9335 //*************************************************************************************************
9336 
9337 
9338 
9339 
9340 //=================================================================================================
9341 //
9342 // ASSIGNMENT OPERATORS
9343 //
9344 //=================================================================================================
9345 
9346 //*************************************************************************************************
9357 template< typename MT > // Type of the dense matrix
9358 inline Submatrix<MT,aligned,true,true>&
9359  Submatrix<MT,aligned,true,true>::operator=( const ElementType& rhs )
9360 {
9361  const size_t jend( column_ + n_ );
9362 
9363  for( size_t j=column_; j<jend; ++j )
9364  {
9365  const size_t ibegin( ( IsLower<MT>::value )
9366  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
9367  ?( max( j+1UL, row_ ) )
9368  :( max( j, row_ ) ) )
9369  :( row_ ) );
9370  const size_t iend ( ( IsUpper<MT>::value )
9371  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
9372  ?( min( j, row_+m_ ) )
9373  :( min( j+1UL, row_+m_ ) ) )
9374  :( row_+m_ ) );
9375 
9376  for( size_t i=ibegin; i<iend; ++i )
9377  matrix_(i,j) = rhs;
9378  }
9379 
9380  return *this;
9381 }
9383 //*************************************************************************************************
9384 
9385 
9386 //*************************************************************************************************
9399 template< typename MT > // Type of the dense matrix
9400 inline Submatrix<MT,aligned,true,true>&
9401  Submatrix<MT,aligned,true,true>::operator=( initializer_list< initializer_list<ElementType> > list )
9402 {
9403  if( list.size() != rows() || determineColumns( list ) > columns() ) {
9404  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to submatrix" );
9405  }
9406 
9407  size_t i( 0UL );
9408 
9409  for( const auto& rowList : list ) {
9410  size_t j( 0UL );
9411  for( const auto& element : rowList ) {
9412  matrix_(row_+i,column_+j) = element;
9413  ++j;
9414  }
9415  for( ; j<n_; ++j ) {
9416  matrix_(row_+i,column_+j) = ElementType();
9417  }
9418  ++i;
9419  }
9420 
9421  return *this;
9422 }
9424 //*************************************************************************************************
9425 
9426 
9427 //*************************************************************************************************
9442 template< typename MT > // Type of the dense matrix
9443 inline Submatrix<MT,aligned,true,true>&
9444  Submatrix<MT,aligned,true,true>::operator=( const Submatrix& rhs )
9445 {
9448 
9449  if( this == &rhs || ( &matrix_ == &rhs.matrix_ && row_ == rhs.row_ && column_ == rhs.column_ ) )
9450  return *this;
9451 
9452  if( rows() != rhs.rows() || columns() != rhs.columns() ) {
9453  BLAZE_THROW_INVALID_ARGUMENT( "Submatrix sizes do not match" );
9454  }
9455 
9456  if( !tryAssign( matrix_, rhs, row_, column_ ) ) {
9457  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
9458  }
9459 
9460  DerestrictTrait_<This> left( derestrict( *this ) );
9461 
9462  if( rhs.canAlias( &matrix_ ) ) {
9463  const ResultType tmp( rhs );
9464  smpAssign( left, tmp );
9465  }
9466  else {
9467  smpAssign( left, rhs );
9468  }
9469 
9470  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
9471 
9472  return *this;
9473 }
9475 //*************************************************************************************************
9476 
9477 
9478 //*************************************************************************************************
9492 template< typename MT > // Type of the dense matrix
9493 template< typename MT2 // Type of the right-hand side matrix
9494  , bool SO > // Storage order of the right-hand side matrix
9495 inline Submatrix<MT,aligned,true,true>&
9496  Submatrix<MT,aligned,true,true>::operator=( const Matrix<MT2,SO>& rhs )
9497 {
9499 
9500  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
9501  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
9502  }
9503 
9504  typedef If_< IsRestricted<MT>, CompositeType_<MT2>, const MT2& > Right;
9505  Right right( ~rhs );
9506 
9507  if( !tryAssign( matrix_, right, row_, column_ ) ) {
9508  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
9509  }
9510 
9511  if( IsSparseMatrix<MT2>::value )
9512  reset();
9513 
9514  DerestrictTrait_<This> left( derestrict( *this ) );
9515 
9516  if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
9517  const ResultType_<MT2> tmp( right );
9518  smpAssign( left, tmp );
9519  }
9520  else {
9521  smpAssign( left, right );
9522  }
9523 
9524  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
9525 
9526  return *this;
9527 }
9529 //*************************************************************************************************
9530 
9531 
9532 //*************************************************************************************************
9546 template< typename MT > // Type of the dense matrix
9547 template< typename MT2 // Type of the right-hand side matrix
9548  , bool SO > // Storage order of the right-hand side matrix
9549 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,true,true>& >
9550  Submatrix<MT,aligned,true,true>::operator+=( const Matrix<MT2,SO>& rhs )
9551 {
9555 
9556  typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
9557 
9560 
9561  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
9562  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
9563  }
9564 
9565  if( !tryAddAssign( matrix_, ~rhs, row_, column_ ) ) {
9566  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
9567  }
9568 
9569  DerestrictTrait_<This> left( derestrict( *this ) );
9570 
9571  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
9572  (~rhs).canAlias( &matrix_ ) ) {
9573  const AddType tmp( *this + (~rhs) );
9574  smpAssign( left, tmp );
9575  }
9576  else {
9577  smpAddAssign( left, ~rhs );
9578  }
9579 
9580  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
9581 
9582  return *this;
9583 }
9585 //*************************************************************************************************
9586 
9587 
9588 //*************************************************************************************************
9602 template< typename MT > // Type of the dense matrix
9603 template< typename MT2 // Type of the right-hand side matrix
9604  , bool SO > // Storage order of the right-hand side matrix
9605 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,true,true>& >
9606  Submatrix<MT,aligned,true,true>::operator+=( const Matrix<MT2,SO>& rhs )
9607 {
9611 
9612  typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
9613 
9616 
9617  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
9618  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
9619  }
9620 
9621  const AddType tmp( *this + (~rhs) );
9622 
9623  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
9624  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
9625  }
9626 
9627  DerestrictTrait_<This> left( derestrict( *this ) );
9628 
9629  smpAssign( left, tmp );
9630 
9631  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
9632 
9633  return *this;
9634 }
9636 //*************************************************************************************************
9637 
9638 
9639 //*************************************************************************************************
9653 template< typename MT > // Type of the dense matrix
9654 template< typename MT2 // Type of the right-hand side matrix
9655  , bool SO > // Storage order of the right-hand side matrix
9656 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,true,true>& >
9657  Submatrix<MT,aligned,true,true>::operator-=( const Matrix<MT2,SO>& rhs )
9658 {
9662 
9663  typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
9664 
9667 
9668  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
9669  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
9670  }
9671 
9672  if( !trySubAssign( matrix_, ~rhs, row_, column_ ) ) {
9673  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
9674  }
9675 
9676  DerestrictTrait_<This> left( derestrict( *this ) );
9677 
9678  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
9679  (~rhs).canAlias( &matrix_ ) ) {
9680  const SubType tmp( *this - (~rhs ) );
9681  smpAssign( left, tmp );
9682  }
9683  else {
9684  smpSubAssign( left, ~rhs );
9685  }
9686 
9687  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
9688 
9689  return *this;
9690 }
9692 //*************************************************************************************************
9693 
9694 
9695 //*************************************************************************************************
9709 template< typename MT > // Type of the dense matrix
9710 template< typename MT2 // Type of the right-hand side matrix
9711  , bool SO > // Storage order of the right-hand side matrix
9712 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,true,true>& >
9713  Submatrix<MT,aligned,true,true>::operator-=( const Matrix<MT2,SO>& rhs )
9714 {
9718 
9719  typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
9720 
9723 
9724  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
9725  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
9726  }
9727 
9728  const SubType tmp( *this - (~rhs) );
9729 
9730  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
9731  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
9732  }
9733 
9734  DerestrictTrait_<This> left( derestrict( *this ) );
9735 
9736  smpAssign( left, tmp );
9737 
9738  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
9739 
9740  return *this;
9741 }
9743 //*************************************************************************************************
9744 
9745 
9746 //*************************************************************************************************
9760 template< typename MT > // Type of the dense matrix
9761 template< typename MT2 // Type of the right-hand side matrix
9762  , bool SO > // Storage order of the right-hand side matrix
9763 inline Submatrix<MT,aligned,true,true>&
9764  Submatrix<MT,aligned,true,true>::operator*=( const Matrix<MT2,SO>& rhs )
9765 {
9769 
9770  typedef MultTrait_< ResultType, ResultType_<MT2> > MultType;
9771 
9774 
9775  if( columns() != (~rhs).rows() ) {
9776  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
9777  }
9778 
9779  const MultType tmp( *this * (~rhs) );
9780 
9781  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
9782  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
9783  }
9784 
9785  DerestrictTrait_<This> left( derestrict( *this ) );
9786 
9787  smpAssign( left, tmp );
9788 
9789  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
9790 
9791  return *this;
9792 }
9794 //*************************************************************************************************
9795 
9796 
9797 //*************************************************************************************************
9808 template< typename MT > // Type of the dense matrix
9809 template< typename Other > // Data type of the right-hand side scalar
9810 inline EnableIf_< IsNumeric<Other>, Submatrix<MT,aligned,true,true> >&
9812 {
9814 
9815  DerestrictTrait_<This> left( derestrict( *this ) );
9816  smpAssign( left, (*this) * rhs );
9817 
9818  return *this;
9819 }
9821 //*************************************************************************************************
9822 
9823 
9824 //*************************************************************************************************
9837 template< typename MT > // Type of the dense matrix
9838 template< typename Other > // Data type of the right-hand side scalar
9839 inline EnableIf_< IsNumeric<Other>, Submatrix<MT,aligned,true,true> >&
9841 {
9843 
9844  BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
9845 
9846  DerestrictTrait_<This> left( derestrict( *this ) );
9847  smpAssign( left, (*this) / rhs );
9848 
9849  return *this;
9850 }
9852 //*************************************************************************************************
9853 
9854 
9855 
9856 
9857 //=================================================================================================
9858 //
9859 // UTILITY FUNCTIONS
9860 //
9861 //=================================================================================================
9862 
9863 //*************************************************************************************************
9869 template< typename MT > // Type of the dense matrix
9870 inline size_t Submatrix<MT,aligned,true,true>::row() const noexcept
9871 {
9872  return row_;
9873 }
9875 //*************************************************************************************************
9876 
9877 
9878 //*************************************************************************************************
9884 template< typename MT > // Type of the dense matrix
9885 inline size_t Submatrix<MT,aligned,true,true>::rows() const noexcept
9886 {
9887  return m_;
9888 }
9890 //*************************************************************************************************
9891 
9892 
9893 //*************************************************************************************************
9899 template< typename MT > // Type of the dense matrix
9900 inline size_t Submatrix<MT,aligned,true,true>::column() const noexcept
9901 {
9902  return column_;
9903 }
9905 //*************************************************************************************************
9906 
9907 
9908 //*************************************************************************************************
9914 template< typename MT > // Type of the dense matrix
9915 inline size_t Submatrix<MT,aligned,true,true>::columns() const noexcept
9916 {
9917  return n_;
9918 }
9920 //*************************************************************************************************
9921 
9922 
9923 //*************************************************************************************************
9932 template< typename MT > // Type of the dense matrix
9933 inline size_t Submatrix<MT,aligned,true,true>::spacing() const noexcept
9934 {
9935  return matrix_.spacing();
9936 }
9938 //*************************************************************************************************
9939 
9940 
9941 //*************************************************************************************************
9947 template< typename MT > // Type of the dense matrix
9948 inline size_t Submatrix<MT,aligned,true,true>::capacity() const noexcept
9949 {
9950  return rows() * columns();
9951 }
9953 //*************************************************************************************************
9954 
9955 
9956 //*************************************************************************************************
9963 template< typename MT > // Type of the dense matrix
9964 inline size_t Submatrix<MT,aligned,true,true>::capacity( size_t j ) const noexcept
9965 {
9966  UNUSED_PARAMETER( j );
9967 
9968  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
9969 
9970  return rows();
9971 }
9973 //*************************************************************************************************
9974 
9975 
9976 //*************************************************************************************************
9982 template< typename MT > // Type of the dense matrix
9983 inline size_t Submatrix<MT,aligned,true,true>::nonZeros() const
9984 {
9985  const size_t iend( row_ + m_ );
9986  const size_t jend( column_ + n_ );
9987  size_t nonzeros( 0UL );
9988 
9989  for( size_t j=column_; j<jend; ++j )
9990  for( size_t i=row_; i<iend; ++i )
9991  if( !isDefault( matrix_(i,j) ) )
9992  ++nonzeros;
9993 
9994  return nonzeros;
9995 }
9997 //*************************************************************************************************
9998 
9999 
10000 //*************************************************************************************************
10007 template< typename MT > // Type of the dense matrix
10008 inline size_t Submatrix<MT,aligned,true,true>::nonZeros( size_t j ) const
10009 {
10010  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
10011 
10012  const size_t iend( row_ + m_ );
10013  size_t nonzeros( 0UL );
10014 
10015  for( size_t i=row_; i<iend; ++i )
10016  if( !isDefault( matrix_(i,column_+j) ) )
10017  ++nonzeros;
10018 
10019  return nonzeros;
10020 }
10022 //*************************************************************************************************
10023 
10024 
10025 //*************************************************************************************************
10031 template< typename MT > // Type of the dense matrix
10033 {
10034  using blaze::clear;
10035 
10036  for( size_t j=column_; j<column_+n_; ++j )
10037  {
10038  const size_t ibegin( ( IsLower<MT>::value )
10039  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
10040  ?( max( j+1UL, row_ ) )
10041  :( max( j, row_ ) ) )
10042  :( row_ ) );
10043  const size_t iend ( ( IsUpper<MT>::value )
10044  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
10045  ?( min( j, row_+m_ ) )
10046  :( min( j+1UL, row_+m_ ) ) )
10047  :( row_+m_ ) );
10048 
10049  for( size_t i=ibegin; i<iend; ++i )
10050  clear( matrix_(i,j) );
10051  }
10052 }
10054 //*************************************************************************************************
10055 
10056 
10057 //*************************************************************************************************
10064 template< typename MT > // Type of the dense matrix
10065 inline void Submatrix<MT,aligned,true,true>::reset( size_t j )
10066 {
10067  using blaze::clear;
10068 
10069  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
10070 
10071  const size_t ibegin( ( IsLower<MT>::value )
10072  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
10073  ?( max( j+1UL, row_ ) )
10074  :( max( j, row_ ) ) )
10075  :( row_ ) );
10076  const size_t iend ( ( IsUpper<MT>::value )
10077  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
10078  ?( min( j, row_+m_ ) )
10079  :( min( j+1UL, row_+m_ ) ) )
10080  :( row_+m_ ) );
10081 
10082  for( size_t i=ibegin; i<iend; ++i )
10083  clear( matrix_(i,column_+j) );
10084 }
10086 //*************************************************************************************************
10087 
10088 
10089 //*************************************************************************************************
10099 template< typename MT > // Type of the dense matrix
10100 inline bool Submatrix<MT,aligned,true,true>::hasOverlap() const noexcept
10101 {
10102  BLAZE_INTERNAL_ASSERT( IsSymmetric<MT>::value || IsHermitian<MT>::value, "Invalid matrix detected" );
10103 
10104  if( ( row_ + m_ <= column_ ) || ( column_ + n_ <= row_ ) )
10105  return false;
10106  else return true;
10107 }
10109 //*************************************************************************************************
10110 
10111 
10112 
10113 
10114 //=================================================================================================
10115 //
10116 // NUMERIC FUNCTIONS
10117 //
10118 //=================================================================================================
10119 
10120 //*************************************************************************************************
10138 template< typename MT > // Type of the dense matrix
10139 inline Submatrix<MT,aligned,true,true>& Submatrix<MT,aligned,true,true>::transpose()
10140 {
10141  if( m_ != n_ ) {
10142  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
10143  }
10144 
10145  if( !tryAssign( matrix_, trans( *this ), row_, column_ ) ) {
10146  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
10147  }
10148 
10149  DerestrictTrait_<This> left( derestrict( *this ) );
10150  const ResultType tmp( trans( *this ) );
10151  smpAssign( left, tmp );
10152 
10153  return *this;
10154 }
10156 //*************************************************************************************************
10157 
10158 
10159 //*************************************************************************************************
10177 template< typename MT > // Type of the dense matrix
10178 inline Submatrix<MT,aligned,true,true>& Submatrix<MT,aligned,true,true>::ctranspose()
10179 {
10180  if( m_ != n_ ) {
10181  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
10182  }
10183 
10184  if( !tryAssign( matrix_, ctrans( *this ), row_, column_ ) ) {
10185  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
10186  }
10187 
10188  DerestrictTrait_<This> left( derestrict( *this ) );
10189  const ResultType tmp( ctrans( *this ) );
10190  smpAssign( left, tmp );
10191 
10192  return *this;
10193 }
10195 //*************************************************************************************************
10196 
10197 
10198 //*************************************************************************************************
10209 template< typename MT > // Type of the dense matrix
10210 template< typename Other > // Data type of the scalar value
10211 inline Submatrix<MT,aligned,true,true>& Submatrix<MT,aligned,true,true>::scale( const Other& scalar )
10212 {
10214 
10215  const size_t jend( column_ + n_ );
10216 
10217  for( size_t j=column_; j<jend; ++j )
10218  {
10219  const size_t ibegin( ( IsLower<MT>::value )
10220  ?( ( IsStrictlyLower<MT>::value )
10221  ?( max( j+1UL, row_ ) )
10222  :( max( j, row_ ) ) )
10223  :( row_ ) );
10224  const size_t iend ( ( IsUpper<MT>::value )
10225  ?( ( IsStrictlyUpper<MT>::value )
10226  ?( min( j, row_+m_ ) )
10227  :( min( j+1UL, row_+m_ ) ) )
10228  :( row_+m_ ) );
10229 
10230  for( size_t i=ibegin; i<iend; ++i )
10231  matrix_(i,j) *= scalar;
10232  }
10233 
10234  return *this;
10235 }
10237 //*************************************************************************************************
10238 
10239 
10240 
10241 
10242 //=================================================================================================
10243 //
10244 // EXPRESSION TEMPLATE EVALUATION FUNCTIONS
10245 //
10246 //=================================================================================================
10247 
10248 //*************************************************************************************************
10259 template< typename MT > // Type of the dense matrix
10260 template< typename Other > // Data type of the foreign expression
10261 inline bool Submatrix<MT,aligned,true,true>::canAlias( const Other* alias ) const noexcept
10262 {
10263  return matrix_.isAliased( alias );
10264 }
10266 //*************************************************************************************************
10267 
10268 
10269 //*************************************************************************************************
10280 template< typename MT > // Type of the dense matrix
10281 template< typename MT2 // Data type of the foreign dense submatrix
10282  , bool AF2 // Alignment flag of the foreign dense submatrix
10283  , bool SO2 > // Storage order of the foreign dense submatrix
10284 inline bool Submatrix<MT,aligned,true,true>::canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
10285 {
10286  return ( matrix_.isAliased( &alias->matrix_ ) &&
10287  ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
10288  ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
10289 }
10291 //*************************************************************************************************
10292 
10293 
10294 //*************************************************************************************************
10305 template< typename MT > // Type of the dense matrix
10306 template< typename Other > // Data type of the foreign expression
10307 inline bool Submatrix<MT,aligned,true,true>::isAliased( const Other* alias ) const noexcept
10308 {
10309  return matrix_.isAliased( alias );
10310 }
10312 //*************************************************************************************************
10313 
10314 
10315 //*************************************************************************************************
10326 template< typename MT > // Type of the dense matrix
10327 template< typename MT2 // Data type of the foreign dense submatrix
10328  , bool AF2 // Alignment flag of the foreign dense submatrix
10329  , bool SO2 > // Storage order of the foreign dense submatrix
10330 inline bool Submatrix<MT,aligned,true,true>::isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
10331 {
10332  return ( matrix_.isAliased( &alias->matrix_ ) &&
10333  ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
10334  ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
10335 }
10337 //*************************************************************************************************
10338 
10339 
10340 //*************************************************************************************************
10350 template< typename MT > // Type of the dense matrix
10351 inline bool Submatrix<MT,aligned,true,true>::isAligned() const noexcept
10352 {
10353  return true;
10354 }
10356 //*************************************************************************************************
10357 
10358 
10359 //*************************************************************************************************
10370 template< typename MT > // Type of the dense matrix
10371 inline bool Submatrix<MT,aligned,true,true>::canSMPAssign() const noexcept
10372 {
10373  return ( rows() * columns() >= SMP_DMATASSIGN_THRESHOLD );
10374 }
10376 //*************************************************************************************************
10377 
10378 
10379 //*************************************************************************************************
10394 template< typename MT > // Type of the dense matrix
10395 BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,true,true>::SIMDType
10396  Submatrix<MT,aligned,true,true>::load( size_t i, size_t j ) const noexcept
10397 {
10398  return loada( i, j );
10399 }
10401 //*************************************************************************************************
10402 
10403 
10404 //*************************************************************************************************
10419 template< typename MT > // Type of the dense matrix
10420 BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,true,true>::SIMDType
10421  Submatrix<MT,aligned,true,true>::loada( size_t i, size_t j ) const noexcept
10422 {
10424 
10425  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
10426  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
10427  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
10428  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
10429 
10430  return matrix_.loada( row_+i, column_+j );
10431 }
10433 //*************************************************************************************************
10434 
10435 
10436 //*************************************************************************************************
10451 template< typename MT > // Type of the dense matrix
10452 BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,true,true>::SIMDType
10453  Submatrix<MT,aligned,true,true>::loadu( size_t i, size_t j ) const noexcept
10454 {
10456 
10457  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
10458  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
10459  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
10460  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
10461 
10462  return matrix_.loadu( row_+i, column_+j );
10463 }
10465 //*************************************************************************************************
10466 
10467 
10468 //*************************************************************************************************
10484 template< typename MT > // Type of the dense matrix
10486  Submatrix<MT,aligned,true,true>::store( size_t i, size_t j, const SIMDType& value ) noexcept
10487 {
10488  storea( i, j, value );
10489 }
10491 //*************************************************************************************************
10492 
10493 
10494 //*************************************************************************************************
10510 template< typename MT > // Type of the dense matrix
10512  Submatrix<MT,aligned,true,true>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
10513 {
10515 
10516  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
10517  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
10518  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
10519  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
10520 
10521  matrix_.storea( row_+i, column_+j, value );
10522 }
10524 //*************************************************************************************************
10525 
10526 
10527 //*************************************************************************************************
10543 template< typename MT > // Type of the dense matrix
10545  Submatrix<MT,aligned,true,true>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
10546 {
10548 
10549  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
10550  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
10551  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
10552  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
10553 
10554  matrix_.storeu( row_+i, column_+j, value );
10555 }
10557 //*************************************************************************************************
10558 
10559 
10560 //*************************************************************************************************
10577 template< typename MT > // Type of the dense matrix
10579  Submatrix<MT,aligned,true,true>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
10580 {
10582 
10583  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
10584  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
10585  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
10586  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
10587 
10588  matrix_.stream( row_+i, column_+j, value );
10589 }
10591 //*************************************************************************************************
10592 
10593 
10594 //*************************************************************************************************
10606 template< typename MT > // Type of the dense matrix
10607 template< typename MT2 > // Type of the right-hand side dense matrix
10608 inline DisableIf_< typename Submatrix<MT,aligned,true,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
10609  Submatrix<MT,aligned,true,true>::assign( const DenseMatrix<MT2,true>& rhs )
10610 {
10611  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
10612  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
10613 
10614  const size_t ipos( m_ & size_t(-2) );
10615  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
10616 
10617  for( size_t j=0UL; j<n_; ++j ) {
10618  for( size_t i=0UL; i<ipos; i+=2UL ) {
10619  matrix_(row_+i ,column_+j) = (~rhs)(i ,j);
10620  matrix_(row_+i+1UL,column_+j) = (~rhs)(i+1UL,j);
10621  }
10622  if( ipos < m_ ) {
10623  matrix_(row_+ipos,column_+j) = (~rhs)(ipos,j);
10624  }
10625  }
10626 }
10628 //*************************************************************************************************
10629 
10630 
10631 //*************************************************************************************************
10643 template< typename MT > // Type of the dense matrix
10644 template< typename MT2 > // Type of the right-hand side dense matrix
10645 inline EnableIf_< typename Submatrix<MT,aligned,true,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
10646  Submatrix<MT,aligned,true,true>::assign( const DenseMatrix<MT2,true>& rhs )
10647 {
10649 
10650  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
10651  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
10652 
10653  const size_t ipos( m_ & size_t(-SIMDSIZE) );
10654  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
10655 
10656  if( useStreaming &&
10657  m_*n_ > ( cacheSize / ( sizeof(ElementType) * 3UL ) ) &&
10658  !(~rhs).isAliased( &matrix_ ) )
10659  {
10660  for( size_t j=0UL; j<n_; ++j )
10661  {
10662  size_t i( 0UL );
10663  Iterator left( begin(j) );
10664  ConstIterator_<MT2> right( (~rhs).begin(j) );
10665 
10666  for( ; i<ipos; i+=SIMDSIZE ) {
10667  left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
10668  }
10669  for( ; i<m_; ++i ) {
10670  *left = *right; ++left; ++right;
10671  }
10672  }
10673  }
10674  else
10675  {
10676  for( size_t j=0UL; j<n_; ++j )
10677  {
10678  size_t i( 0UL );
10679  Iterator left( begin(j) );
10680  ConstIterator_<MT2> right( (~rhs).begin(j) );
10681 
10682  for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
10683  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
10684  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
10685  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
10686  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
10687  }
10688  for( ; i<ipos; i+=SIMDSIZE ) {
10689  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
10690  }
10691  for( ; i<m_; ++i ) {
10692  *left = *right; ++left; ++right;
10693  }
10694  }
10695  }
10696 }
10698 //*************************************************************************************************
10699 
10700 
10701 //*************************************************************************************************
10713 template< typename MT > // Type of the dense matrix
10714 template< typename MT2 > // Type of the right-hand side dense matrix
10715 inline void Submatrix<MT,aligned,true,true>::assign( const DenseMatrix<MT2,false>& rhs )
10716 {
10718 
10719  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
10720  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
10721 
10722  constexpr size_t block( BLOCK_SIZE );
10723 
10724  for( size_t jj=0UL; jj<n_; jj+=block ) {
10725  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
10726  for( size_t ii=0UL; ii<m_; ii+=block ) {
10727  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
10728  for( size_t j=jj; j<jend; ++j ) {
10729  for( size_t i=ii; i<iend; ++i ) {
10730  matrix_(row_+i,column_+j) = (~rhs)(i,j);
10731  }
10732  }
10733  }
10734  }
10735 }
10737 //*************************************************************************************************
10738 
10739 
10740 //*************************************************************************************************
10752 template< typename MT > // Type of the dense matrix
10753 template< typename MT2 > // Type of the right-hand side sparse matrix
10754 inline void Submatrix<MT,aligned,true,true>::assign( const SparseMatrix<MT2,true>& rhs )
10755 {
10756  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
10757  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
10758 
10759  for( size_t j=0UL; j<n_; ++j )
10760  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
10761  matrix_(row_+element->index(),column_+j) = element->value();
10762 }
10764 //*************************************************************************************************
10765 
10766 
10767 //*************************************************************************************************
10779 template< typename MT > // Type of the dense matrix
10780 template< typename MT2 > // Type of the right-hand side sparse matrix
10781 inline void Submatrix<MT,aligned,true,true>::assign( const SparseMatrix<MT2,false>& rhs )
10782 {
10784 
10785  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
10786  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
10787 
10788  for( size_t i=0UL; i<m_; ++i )
10789  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
10790  matrix_(row_+i,column_+element->index()) = element->value();
10791 }
10793 //*************************************************************************************************
10794 
10795 
10796 //*************************************************************************************************
10808 template< typename MT > // Type of the dense matrix
10809 template< typename MT2 > // Type of the right-hand side dense matrix
10810 inline DisableIf_< typename Submatrix<MT,aligned,true,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
10811  Submatrix<MT,aligned,true,true>::addAssign( const DenseMatrix<MT2,true>& rhs )
10812 {
10813  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
10814  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
10815 
10816  const size_t ipos( m_ & size_t(-2) );
10817  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
10818 
10819  for( size_t j=0UL; j<n_; ++j )
10820  {
10821  if( IsDiagonal<MT2>::value ) {
10822  matrix_(row_+j,column_+j) += (~rhs)(j,j);
10823  }
10824  else {
10825  for( size_t i=0UL; i<ipos; i+=2UL ) {
10826  matrix_(row_+i ,column_+j) += (~rhs)(i ,j);
10827  matrix_(row_+i+1UL,column_+j) += (~rhs)(i+1UL,j);
10828  }
10829  if( ipos < m_ ) {
10830  matrix_(row_+ipos,column_+j) += (~rhs)(ipos,j);
10831  }
10832  }
10833  }
10834 }
10836 //*************************************************************************************************
10837 
10838 
10839 //*************************************************************************************************
10851 template< typename MT > // Type of the dense matrix
10852 template< typename MT2 > // Type of the right-hand side dense matrix
10853 inline EnableIf_< typename Submatrix<MT,aligned,true,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
10854  Submatrix<MT,aligned,true,true>::addAssign( const DenseMatrix<MT2,true>& rhs )
10855 {
10857 
10858  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
10859  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
10860 
10861  for( size_t j=0UL; j<n_; ++j )
10862  {
10863  const size_t ibegin( ( IsLower<MT>::value )
10864  ?( ( IsStrictlyLower<MT>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
10865  :( 0UL ) );
10866  const size_t iend ( ( IsUpper<MT>::value )
10867  ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
10868  :( m_ ) );
10869  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
10870 
10871  const size_t ipos( iend & size_t(-SIMDSIZE) );
10872  BLAZE_INTERNAL_ASSERT( ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
10873 
10874  size_t i( ibegin );
10875  Iterator left( begin(j) + ibegin );
10876  ConstIterator_<MT2> right( (~rhs).begin(j) + ibegin );
10877 
10878  for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
10879  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
10880  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
10881  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
10882  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
10883  }
10884  for( ; i<ipos; i+=SIMDSIZE ) {
10885  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
10886  }
10887  for( ; i<iend; ++i ) {
10888  *left += *right; ++left; ++right;
10889  }
10890  }
10891 }
10893 //*************************************************************************************************
10894 
10895 
10896 //*************************************************************************************************
10908 template< typename MT > // Type of the dense matrix
10909 template< typename MT2 > // Type of the right-hand side dense matrix
10910 inline void Submatrix<MT,aligned,true,true>::addAssign( const DenseMatrix<MT2,false>& rhs )
10911 {
10913 
10914  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
10915  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
10916 
10917  constexpr size_t block( BLOCK_SIZE );
10918 
10919  for( size_t jj=0UL; jj<n_; jj+=block ) {
10920  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
10921  for( size_t ii=0UL; ii<m_; ii+=block ) {
10922  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
10923  for( size_t j=jj; j<jend; ++j ) {
10924  for( size_t i=ii; i<iend; ++i ) {
10925  matrix_(row_+i,column_+j) += (~rhs)(i,j);
10926  }
10927  }
10928  }
10929  }
10930 }
10932 //*************************************************************************************************
10933 
10934 
10935 //*************************************************************************************************
10947 template< typename MT > // Type of the dense matrix
10948 template< typename MT2 > // Type of the right-hand side sparse matrix
10949 inline void Submatrix<MT,aligned,true,true>::addAssign( const SparseMatrix<MT2,true>& rhs )
10950 {
10951  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
10952  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
10953 
10954  for( size_t j=0UL; j<n_; ++j )
10955  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
10956  matrix_(row_+element->index(),column_+j) += element->value();
10957 }
10959 //*************************************************************************************************
10960 
10961 
10962 //*************************************************************************************************
10974 template< typename MT > // Type of the dense matrix
10975 template< typename MT2 > // Type of the right-hand side sparse matrix
10976 inline void Submatrix<MT,aligned,true,true>::addAssign( const SparseMatrix<MT2,false>& rhs )
10977 {
10979 
10980  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
10981  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
10982 
10983  for( size_t i=0UL; i<m_; ++i )
10984  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
10985  matrix_(row_+i,column_+element->index()) += element->value();
10986 }
10988 //*************************************************************************************************
10989 
10990 
10991 //*************************************************************************************************
11003 template< typename MT > // Type of the dense matrix
11004 template< typename MT2 > // Type of the right-hand side dense matrix
11005 inline DisableIf_< typename Submatrix<MT,aligned,true,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
11006  Submatrix<MT,aligned,true,true>::subAssign( const DenseMatrix<MT2,true>& rhs )
11007 {
11008  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
11009  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
11010 
11011  const size_t ipos( m_ & size_t(-2) );
11012  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
11013 
11014  for( size_t j=0UL; j<n_; ++j )
11015  {
11016  if( IsDiagonal<MT2>::value ) {
11017  matrix_(row_+j,column_+j) -= (~rhs)(j,j);
11018  }
11019  else {
11020  for( size_t i=0UL; i<ipos; i+=2UL ) {
11021  matrix_(row_+i ,column_+j) -= (~rhs)(i ,j);
11022  matrix_(row_+i+1UL,column_+j) -= (~rhs)(i+1UL,j);
11023  }
11024  if( ipos < m_ ) {
11025  matrix_(row_+ipos,column_+j) -= (~rhs)(ipos,j);
11026  }
11027  }
11028  }
11029 }
11031 //*************************************************************************************************
11032 
11033 
11034 //*************************************************************************************************
11046 template< typename MT > // Type of the dense matrix
11047 template< typename MT2 > // Type of the right-hand side dense matrix
11048 inline EnableIf_< typename Submatrix<MT,aligned,true,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
11049  Submatrix<MT,aligned,true,true>::subAssign( const DenseMatrix<MT2,true>& rhs )
11050 {
11052 
11053  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
11054  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
11055 
11056  for( size_t j=0UL; j<n_; ++j )
11057  {
11058  const size_t ibegin( ( IsLower<MT>::value )
11059  ?( ( IsStrictlyLower<MT>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
11060  :( 0UL ) );
11061  const size_t iend ( ( IsUpper<MT>::value )
11062  ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
11063  :( m_ ) );
11064  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
11065 
11066  const size_t ipos( iend & size_t(-SIMDSIZE) );
11067  BLAZE_INTERNAL_ASSERT( ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
11068 
11069  size_t i( ibegin );
11070  Iterator left( begin(j) + ibegin );
11071  ConstIterator_<MT2> right( (~rhs).begin(j) + ibegin );
11072 
11073  for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
11074  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11075  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11076  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11077  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11078  }
11079  for( ; i<ipos; i+=SIMDSIZE ) {
11080  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11081  }
11082  for( ; i<iend; ++i ) {
11083  *left -= *right; ++left; ++right;
11084  }
11085  }
11086 }
11088 //*************************************************************************************************
11089 
11090 
11091 //*************************************************************************************************
11103 template< typename MT > // Type of the dense matrix
11104 template< typename MT2 > // Type of the right-hand side dense matrix
11105 inline void Submatrix<MT,aligned,true,true>::subAssign( const DenseMatrix<MT2,false>& rhs )
11106 {
11108 
11109  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
11110  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
11111 
11112  constexpr size_t block( BLOCK_SIZE );
11113 
11114  for( size_t jj=0UL; jj<n_; jj+=block ) {
11115  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
11116  for( size_t ii=0UL; ii<m_; ii+=block ) {
11117  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
11118  for( size_t j=jj; j<jend; ++j ) {
11119  for( size_t i=ii; i<iend; ++i ) {
11120  matrix_(row_+i,column_+j) -= (~rhs)(i,j);
11121  }
11122  }
11123  }
11124  }
11125 }
11127 //*************************************************************************************************
11128 
11129 
11130 //*************************************************************************************************
11142 template< typename MT > // Type of the dense matrix
11143 template< typename MT2 > // Type of the right-hand side sparse matrix
11144 inline void Submatrix<MT,aligned,true,true>::subAssign( const SparseMatrix<MT2,true>& rhs )
11145 {
11146  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
11147  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
11148 
11149  for( size_t j=0UL; j<n_; ++j )
11150  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
11151  matrix_(row_+element->index(),column_+j) -= element->value();
11152 }
11154 //*************************************************************************************************
11155 
11156 
11157 //*************************************************************************************************
11169 template< typename MT > // Type of the dense matrix
11170 template< typename MT2 > // Type of the right-hand side sparse matrix
11171 inline void Submatrix<MT,aligned,true,true>::subAssign( const SparseMatrix<MT2,false>& rhs )
11172 {
11174 
11175  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
11176  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
11177 
11178  for( size_t i=0UL; i<m_; ++i )
11179  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
11180  matrix_(row_+i,column_+element->index()) -= element->value();
11181 }
11183 //*************************************************************************************************
11184 
11185 } // namespace blaze
11186 
11187 #endif
Constraint on the data type.
#define BLAZE_THROW_INVALID_ARGUMENT(MESSAGE)
Macro for the emission of a std::invalid_argument exception.This macro encapsulates the default way o...
Definition: Exception.h:235
Constraint on the data type.
BLAZE_ALWAYS_INLINE size_t spacing(const DenseMatrix< MT, SO > &dm) noexcept
Returns the spacing between the beginning of two rows/columns.
Definition: DenseMatrix.h:102
Header file for auxiliary alias declarations.
Header file for kernel specific block sizes.
Header file for mathematical functions.
constexpr bool useOptimizedKernels
Configuration switch for optimized kernels.This configuration switch enables/disables all optimized c...
Definition: Optimizations.h:84
typename DerestrictTrait< T >::Type DerestrictTrait_
Auxiliary alias declaration for the DerestrictTrait type trait.The DerestrictTrait_ alias declaration...
Definition: DerestrictTrait.h:110
#define BLAZE_USER_ASSERT(expr, msg)
Run time assertion macro for user checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_USER_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERT flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:117
Header file for the alignment flag values.
Header file for the UNUSED_PARAMETER function template.
Header file for the IsUniUpper type trait.
Header file for the subtraction trait.
BLAZE_ALWAYS_INLINE size_t capacity(const Matrix< MT, SO > &matrix) noexcept
Returns the maximum capacity of the matrix.
Definition: Matrix.h:352
BLAZE_ALWAYS_INLINE bool isSame(const Matrix< MT1, SO1 > &a, const Matrix< MT2, SO2 > &b) noexcept
Returns whether the two given matrices represent the same observable state.
Definition: Matrix.h:721
Header file for basic type definitions.
Header file for the View base class.
BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral< T1 >, HasSize< T1, 1UL > > > storea(T1 *address, const SIMDi8< T2 > &value) noexcept
Aligned store of a vector of 1-byte integral values.
Definition: Storea.h:79
EnableIf_< IsDenseMatrix< MT1 > > smpSubAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP subtraction assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:160
Header file for the IsSparseMatrix type trait.
Header file for the IsDiagonal type trait.
BLAZE_ALWAYS_INLINE size_t size(const Vector< VT, TF > &vector) noexcept
Returns the current size/dimension of the vector.
Definition: Vector.h:261
const CTransExprTrait_< MT > ctrans(const DenseMatrix< MT, SO > &dm)
Returns the conjugate transpose matrix of dm.
Definition: DMatForEachExpr.h:1251
#define BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE(T)
Constraint on the data type.In case the given data type T is a computational expression (i...
Definition: Computation.h:81
constexpr size_t cacheSize
Cache size of the target architecture.This setting specifies the available cache size in Byte of the ...
Definition: CacheSize.h:48
#define BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a dense, N-dimensional matrix type...
Definition: DenseMatrix.h:61
constexpr bool operator<(const NegativeAccuracy< A > &lhs, const T &rhs)
Less-than comparison between a NegativeAccuracy object and a floating point value.
Definition: Accuracy.h:329
BLAZE_ALWAYS_INLINE T1 & operator/=(SIMDPack< T1 > &lhs, const SIMDPack< T2 > &rhs)
Division assignment operator for the division of two SIMD packs.
Definition: BasicTypes.h:1339
const bool aligned
Alignment flag for aligned vectors and matrices.Via this flag it is possible to specify subvectors...
Definition: AlignmentFlag.h:85
BLAZE_ALWAYS_INLINE MT::Iterator begin(Matrix< MT, SO > &matrix, size_t i)
Returns an iterator to the first element of row/column i.
Definition: Matrix.h:194
void reset(const DiagonalProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: DiagonalProxy.h:533
const DenseIterator< Type, AF > operator+(const DenseIterator< Type, AF > &it, ptrdiff_t inc) noexcept
Addition between a DenseIterator and an integral value.
Definition: DenseIterator.h:699
size_t m_
The current number of rows of the compressed matrix.
Definition: CompressedMatrix.h:3135
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:2935
typename DisableIf< Condition, T >::Type DisableIf_
Auxiliary type for the DisableIf class template.The DisableIf_ alias declaration provides a convenien...
Definition: DisableIf.h:223
Header file for the And class template.
const ElementType_< MT > min(const DenseMatrix< MT, SO > &dm)
Returns the smallest element of the dense matrix.
Definition: DenseMatrix.h:1755
#define BLAZE_CONSTRAINT_MUST_NOT_BE_SUBMATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is a submatrix type (i.e. a dense or sparse submatrix), a compilation error is created.
Definition: Submatrix.h:81
BLAZE_ALWAYS_INLINE void ctranspose(Matrix< MT, SO > &matrix)
In-place conjugate transpose of the given matrix.
Definition: Matrix.h:596
CompressedMatrix< Type, true > This
Type of this CompressedMatrix instance.
Definition: CompressedMatrix.h:2928
#define BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is a lower or upper unitriangular matrix ty...
Definition: UniTriangular.h:81
BLAZE_ALWAYS_INLINE size_t nonZeros(const Matrix< MT, SO > &matrix)
Returns the total number of non-zero elements in the matrix.
Definition: Matrix.h:390
const DenseIterator< Type, AF > operator-(const DenseIterator< Type, AF > &it, ptrdiff_t inc) noexcept
Subtraction between a DenseIterator and an integral value.
Definition: DenseIterator.h:731
Constraints on the storage order of matrix types.
#define BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE(T)
Constraint on the data type.In case the given data type T is a transposition expression (i...
Definition: TransExpr.h:81
Header file for the RequiresEvaluation type trait.
System settings for performance optimizations.
BLAZE_ALWAYS_INLINE T1 & operator*=(SIMDPack< T1 > &lhs, const SIMDPack< T2 > &rhs)
Multiplication assignment operator for the multiplication of two SIMD packs.
Definition: BasicTypes.h:1321
BLAZE_ALWAYS_INLINE const EnableIf_< And< IsIntegral< T >, HasSize< T, 1UL > >, If_< IsSigned< T >, SIMDint8, SIMDuint8 > > loadu(const T *address) noexcept
Loads a vector of 1-byte integral values.
Definition: Loadu.h:77
Header file for the IsUniLower type trait.
const ElementType_< MT > max(const DenseMatrix< MT, SO > &dm)
Returns the largest element of the dense matrix.
Definition: DenseMatrix.h:1802
EnableIf_< IsDenseMatrix< MT1 > > smpAddAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP addition assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:129
CompressedMatrix< Type, false > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: CompressedMatrix.h:2931
BLAZE_ALWAYS_INLINE MT::ConstIterator cend(const Matrix< MT, SO > &matrix, size_t i)
Returns an iterator just past the last element of row/column i.
Definition: Matrix.h:304
BLAZE_ALWAYS_INLINE MT::ConstIterator cbegin(const Matrix< MT, SO > &matrix, size_t i)
Returns an iterator to the first element of row/column i.
Definition: Matrix.h:238
Constraint on the data type.
Header file for the std::initializer_list aliases.
Header file for the matrix storage order types.
Constraint on the data type.
Header file for the DisableIf class template.
Header file for the multiplication trait.
Header file for the IsStrictlyUpper type trait.
Header file for the IsSymmetric type trait.
Header file for the clear shim.
Namespace of the Blaze C++ math library.
Definition: Blaze.h:57
#define BLAZE_ALWAYS_INLINE
Platform dependent setup of an enforced inline keyword.
Definition: Inline.h:85
Header file for nested template disabiguation.
Header file for the If class template.
constexpr bool useStreaming
Configuration of the streaming behavior.For large vectors and matrices non-temporal stores can provid...
Definition: Optimizations.h:68
#define BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a column-major dense or sparse matri...
Definition: ColumnMajorMatrix.h:61
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:2939
#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
EnableIf_< IsDenseMatrix< MT1 > > smpAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP assignment of a matrix to a dense matrix.
Definition: DenseMatrix.h:98
Header file for the Or class template.
#define BLAZE_THROW_OUT_OF_RANGE(MESSAGE)
Macro for the emission of a std::out_of_range exception.This macro encapsulates the default way of Bl...
Definition: Exception.h:331
Header file for the implementation of the Submatrix base template.
Header file for the HasSIMDAdd type trait.
Header file for the DenseMatrix base class.
constexpr bool operator>(const NegativeAccuracy< A > &lhs, const T &rhs)
Greater-than comparison between a NegativeAccuracy object and a floating point value.
Definition: Accuracy.h:367
constexpr bool operator>=(const NegativeAccuracy< A > &, const T &rhs)
Greater-or-equal-than comparison between a NegativeAccuracy object and a floating point value...
Definition: Accuracy.h:443
Header file for the Not class template.
constexpr bool operator==(const NegativeAccuracy< A > &lhs, const T &rhs)
Equality comparison between a NegativeAccuracy object and a floating point value. ...
Definition: Accuracy.h:250
Header file for all SIMD functionality.
Header file for the IsLower type trait.
BLAZE_ALWAYS_INLINE size_t columns(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of columns of the matrix.
Definition: Matrix.h:336
BLAZE_ALWAYS_INLINE const EnableIf_< And< IsIntegral< T >, HasSize< T, 1UL > >, If_< IsSigned< T >, SIMDint8, SIMDuint8 > > loada(const T *address) noexcept
Loads a vector of 1-byte integral values.
Definition: Loada.h:80
Constraint on the data type.
DisableIf_< Or< IsComputation< MT >, IsTransExpr< MT >, IsDeclExpr< MT > >, RowExprTrait_< MT > > row(Matrix< MT, SO > &matrix, size_t index)
Creating a view on a specific row of the given matrix.
Definition: Row.h:128
#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
CompressedMatrix< Type, false > TransposeType
Transpose type for expression template evaluations.
Definition: CompressedMatrix.h:2932
Header file for the exception macros of the math module.
BLAZE_ALWAYS_INLINE 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:260
Type ElementType
Type of the compressed matrix elements.
Definition: CompressedMatrix.h:2933
const bool unaligned
Alignment flag for unaligned vectors and matrices.Via this flag it is possible to specify subvectors...
Definition: AlignmentFlag.h:64
constexpr bool operator!=(const NegativeAccuracy< A > &lhs, const T &rhs)
Inequality comparison between a NegativeAccuracy object and a floating point value.
Definition: Accuracy.h:290
Constraint on the data type.
const Type & ConstReference
Reference to a constant matrix value.
Definition: CompressedMatrix.h:2937
DisableIf_< Or< IsComputation< MT >, IsTransExpr< MT >, IsDeclExpr< MT > >, ColumnExprTrait_< MT > > column(Matrix< MT, SO > &matrix, size_t index)
Creating a view on a specific column of the given matrix.
Definition: Column.h:128
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:553
Header file for the DerestrictTrait class template.
Constraint on the data type.
Header file for the IsNumeric type trait.
BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral< T1 >, HasSize< 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:75
Header file for the IsSIMDCombinable type trait.
#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, a compilation error is created.
Definition: Symmetric.h:79
#define BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a row-major dense or sparse matrix t...
Definition: RowMajorMatrix.h:61
const Type & ReturnType
Return type for expression template evaluations.
Definition: CompressedMatrix.h:2934
Header file for the IsConst type trait.
BLAZE_ALWAYS_INLINE T1 & operator+=(SIMDPack< T1 > &lhs, const SIMDPack< T2 > &rhs)
Addition assignment operator for the addition of two SIMD packs.
Definition: BasicTypes.h:1285
size_t determineColumns(initializer_list< initializer_list< Type > > list) noexcept
Determine the maximum number of columns specified by the given initializer list.
Definition: InitializerList.h:80
Header file for run time assertion macros.
Header file for the addition trait.
Header file for the submatrix trait.
Header file for the cache size of the target architecture.
#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, a compilation error is created.
Definition: Reference.h:79
Element * Iterator
Iterator over non-constant elements.
Definition: CompressedMatrix.h:2938
Header file for the isDefault shim.
Constraint on the data type.
Constraint on the data type.
Header file for the HasSIMDSub type trait.
Constraints on the storage order of matrix types.
constexpr bool operator<=(const NegativeAccuracy< A > &, const T &rhs)
Less-or-equal-than comparison between a NegativeAccuracy object and a floating point value...
Definition: Accuracy.h:405
#define BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION(T)
Constraint on the data type.In case the given data type T requires an intermediate evaluation within ...
Definition: RequiresEvaluation.h:81
Header file for the IsReference type trait.
typename EnableIf< Condition, T >::Type EnableIf_
Auxiliary alias declaration for the EnableIf class template.The EnableIf_ alias declaration provides ...
Definition: EnableIf.h:223
BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral< T1 >, HasSize< T1, 1UL > > > storeu(T1 *address, const SIMDi8< T2 > &value) noexcept
Unaligned store of a vector of 1-byte integral values.
Definition: Storeu.h:76
BLAZE_ALWAYS_INLINE bool checkAlignment(const T *address)
Checks the alignment of the given address.
Definition: AlignmentCheck.h:68
BLAZE_ALWAYS_INLINE size_t rows(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of rows of the matrix.
Definition: Matrix.h:320
SparseMatrix< This, true > BaseType
Base type of this CompressedMatrix instance.
Definition: CompressedMatrix.h:2929
size_t n_
The current number of columns of the compressed matrix.
Definition: CompressedMatrix.h:3136
const DMatTransExpr< MT,!SO > trans(const DenseMatrix< MT, SO > &dm)
Calculation of the transpose of the given dense matrix.
Definition: DMatTransExpr.h:733
Header file for the alignment check function.
This ResultType
Result type for expression template evaluations.
Definition: CompressedMatrix.h:2930
bool isIntact(const DiagonalMatrix< MT, SO, DF > &m)
Returns whether the invariants of the given diagonal matrix are intact.
Definition: DiagonalMatrix.h:249
bool isDefault(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is in default state.
Definition: DiagonalProxy.h:573
MatrixAccessProxy< This > Reference
Reference to a non-constant matrix value.
Definition: CompressedMatrix.h:2936
#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
BLAZE_ALWAYS_INLINE T1 & operator-=(SIMDPack< T1 > &lhs, const SIMDPack< T2 > &rhs)
Subtraction assignment operator for the subtraction of two SIMD packs.
Definition: BasicTypes.h:1303
Header file for the IsUpper type trait.
void UNUSED_PARAMETER(const Args &...)
Suppression of unused parameter warnings.
Definition: Unused.h:81
SubmatrixExprTrait_< MT, unaligned > submatrix(Matrix< MT, SO > &matrix, size_t row, size_t column, size_t m, size_t n)
Creating a view on a specific submatrix of the given matrix.
Definition: Submatrix.h:168
Header file for the IsHermitian type trait.
Header file for the IsRestricted type trait.
const DMatDMatMultExpr< T1, T2, false, false, false, false > operator*(const DenseMatrix< T1, false > &lhs, const DenseMatrix< T2, false > &rhs)
Multiplication operator for the multiplication of two row-major dense matrices ( ).
Definition: DMatDMatMultExpr.h:7505
System settings for the inline keywords.
Header file for the thresholds for matrix/vector and matrix/matrix multiplications.
#define BLAZE_INTERNAL_ASSERT(expr, msg)
Run time assertion macro for internal checks.In case of an invalid run time expression, the program execution is terminated. The BLAZE_INTERNAL_ASSERT macro can be disabled by setting the BLAZE_USER_ASSERTION flag to zero or by defining NDEBUG during the compilation.
Definition: Assert.h:101
Header file for the IsExpression type trait class.
Constraint on the data type.
BLAZE_ALWAYS_INLINE void transpose(Matrix< MT, SO > &matrix)
In-place transpose of the given matrix.
Definition: Matrix.h:570