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 );
660  inline Submatrix& transpose();
661  inline Submatrix& ctranspose();
662  template< typename Other > inline Submatrix& scale( const Other& scalar );
664  //**********************************************************************************************
665 
666  private:
667  //**********************************************************************************************
669  template< typename MT2 >
670  struct VectorizedAssign {
671  enum : bool { value = useOptimizedKernels &&
672  simdEnabled && MT2::simdEnabled &&
673  AreSIMDCombinable< ElementType, ElementType_<MT2> >::value };
674  };
675  //**********************************************************************************************
676 
677  //**********************************************************************************************
679  template< typename MT2 >
680  struct VectorizedAddAssign {
681  enum : bool { value = useOptimizedKernels &&
682  simdEnabled && MT2::simdEnabled &&
683  AreSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
684  HasSIMDAdd< ElementType, ElementType_<MT2> >::value &&
685  !IsDiagonal<MT2>::value };
686  };
687  //**********************************************************************************************
688 
689  //**********************************************************************************************
691  template< typename MT2 >
692  struct VectorizedSubAssign {
693  enum : bool { value = useOptimizedKernels &&
694  simdEnabled && MT2::simdEnabled &&
695  AreSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
696  HasSIMDSub< ElementType, ElementType_<MT2> >::value &&
697  !IsDiagonal<MT2>::value };
698  };
699  //**********************************************************************************************
700 
701  //**SIMD properties*****************************************************************************
703  enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
704  //**********************************************************************************************
705 
706  public:
707  //**Expression template evaluation functions****************************************************
710  template< typename Other >
711  inline bool canAlias( const Other* alias ) const noexcept;
712 
713  template< typename MT2, bool AF2, bool SO2 >
714  inline bool canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
715 
716  template< typename Other >
717  inline bool isAliased( const Other* alias ) const noexcept;
718 
719  template< typename MT2, bool AF2, bool SO2 >
720  inline bool isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
721 
722  inline bool isAligned () const noexcept;
723  inline bool canSMPAssign() const noexcept;
724 
725  BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
726  BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
727  BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
728 
729  BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
730  BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
731  BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
732  BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
733 
734  template< typename MT2 >
735  inline DisableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,false>& rhs );
736 
737  template< typename MT2 >
738  inline EnableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,false>& rhs );
739 
740  template< typename MT2 > inline void assign( const DenseMatrix<MT2,true>& rhs );
741  template< typename MT2 > inline void assign( const SparseMatrix<MT2,false>& rhs );
742  template< typename MT2 > inline void assign( const SparseMatrix<MT2,true>& rhs );
743 
744  template< typename MT2 >
745  inline DisableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,false>& rhs );
746 
747  template< typename MT2 >
748  inline EnableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,false>& rhs );
749 
750  template< typename MT2 > inline void addAssign( const DenseMatrix<MT2,true>& rhs );
751  template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,false>& rhs );
752  template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,true>& rhs );
753 
754  template< typename MT2 >
755  inline DisableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,false>& rhs );
756 
757  template< typename MT2 >
758  inline EnableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,false>& rhs );
759 
760  template< typename MT2 > inline void subAssign( const DenseMatrix<MT2,true>& rhs );
761  template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,false>& rhs );
762  template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,true>& rhs );
764  //**********************************************************************************************
765 
766  private:
767  //**Utility functions***************************************************************************
770  inline bool hasOverlap() const noexcept;
772  //**********************************************************************************************
773 
774  //**Member variables****************************************************************************
777  Operand matrix_;
778  const size_t row_;
779  const size_t column_;
780  const size_t m_;
781  const size_t n_;
782  const bool isAligned_;
783 
790  //**********************************************************************************************
791 
792  //**Friend declarations*************************************************************************
793  template< typename MT2, bool AF2, bool SO2, bool DF2 > friend class Submatrix;
794 
795  template< bool AF1, typename MT2, bool AF2, bool SO2, bool DF2 >
796  friend const Submatrix<MT2,AF1,SO2,DF2>
797  submatrix( const Submatrix<MT2,AF2,SO2,DF2>& sm, size_t row, size_t column, size_t m, size_t n );
798 
799  template< typename MT2, bool AF2, bool SO2, bool DF2 >
800  friend bool isIntact( const Submatrix<MT2,AF2,SO2,DF2>& sm ) noexcept;
801 
802  template< typename MT2, bool AF2, bool SO2, bool DF2 >
803  friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Matrix<MT2,SO2>& b ) noexcept;
804 
805  template< typename MT2, bool AF2, bool SO2, bool DF2 >
806  friend bool isSame( const Matrix<MT2,SO2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
807 
808  template< typename MT2, bool AF2, bool SO2, bool DF2 >
809  friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
810 
811  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
812  friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
813  size_t row, size_t column );
814 
815  template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
816  friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
817  size_t row, size_t column );
818 
819  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
820  friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
821  size_t row, size_t column );
822 
823  template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
824  friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
825  size_t row, size_t column );
826 
827  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
828  friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
829  size_t row, size_t column );
830 
831  template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
832  friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
833  size_t row, size_t column );
834 
835  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
836  friend bool tryMultAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
837  size_t row, size_t column );
838 
839  template< typename MT2, bool AF2, bool SO2, bool DF2 >
840  friend DerestrictTrait_< Submatrix<MT2,AF2,SO2,DF2> > derestrict( Submatrix<MT2,AF2,SO2,DF2>& sm );
841  //**********************************************************************************************
842 
843  //**Compile time checks*************************************************************************
851  //**********************************************************************************************
852 };
854 //*************************************************************************************************
855 
856 
857 
858 
859 //=================================================================================================
860 //
861 // CONSTRUCTOR
862 //
863 //=================================================================================================
864 
865 //*************************************************************************************************
879 template< typename MT > // Type of the dense matrix
880 inline Submatrix<MT,unaligned,false,true>::Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n )
881  : matrix_ ( matrix ) // The dense matrix containing the submatrix
882  , row_ ( rindex ) // The first row of the submatrix
883  , column_ ( cindex ) // The first column of the submatrix
884  , m_ ( m ) // The number of rows of the submatrix
885  , n_ ( n ) // The number of columns of the submatrix
886  , isAligned_( simdEnabled && matrix.data() != nullptr && checkAlignment( data() ) &&
887  ( m < 2UL || ( matrix.spacing() & size_t(-SIMDSIZE) ) == 0UL ) )
888 {
889  if( ( row_ + m_ > matrix_.rows() ) || ( column_ + n_ > matrix_.columns() ) ) {
890  BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix specification" );
891  }
892 }
894 //*************************************************************************************************
895 
896 
897 
898 
899 //=================================================================================================
900 //
901 // DATA ACCESS FUNCTIONS
902 //
903 //=================================================================================================
904 
905 //*************************************************************************************************
916 template< typename MT > // Type of the dense matrix
918  Submatrix<MT,unaligned,false,true>::operator()( size_t i, size_t j )
919 {
920  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
921  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
922 
923  return matrix_(row_+i,column_+j);
924 }
926 //*************************************************************************************************
927 
928 
929 //*************************************************************************************************
940 template< typename MT > // Type of the dense matrix
942  Submatrix<MT,unaligned,false,true>::operator()( size_t i, size_t j ) const
943 {
944  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
945  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
946 
947  return const_cast<const MT&>( matrix_ )(row_+i,column_+j);
948 }
950 //*************************************************************************************************
951 
952 
953 //*************************************************************************************************
965 template< typename MT > // Type of the dense matrix
967  Submatrix<MT,unaligned,false,true>::at( size_t i, size_t j )
968 {
969  if( i >= rows() ) {
970  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
971  }
972  if( j >= columns() ) {
973  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
974  }
975  return (*this)(i,j);
976 }
978 //*************************************************************************************************
979 
980 
981 //*************************************************************************************************
993 template< typename MT > // Type of the dense matrix
995  Submatrix<MT,unaligned,false,true>::at( size_t i, size_t j ) const
996 {
997  if( i >= rows() ) {
998  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
999  }
1000  if( j >= columns() ) {
1001  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
1002  }
1003  return (*this)(i,j);
1004 }
1006 //*************************************************************************************************
1007 
1008 
1009 //*************************************************************************************************
1019 template< typename MT > // Type of the dense matrix
1020 inline typename Submatrix<MT,unaligned,false,true>::Pointer
1021  Submatrix<MT,unaligned,false,true>::data() noexcept
1022 {
1023  return matrix_.data() + row_*spacing() + column_;
1024 }
1026 //*************************************************************************************************
1027 
1028 
1029 //*************************************************************************************************
1039 template< typename MT > // Type of the dense matrix
1040 inline typename Submatrix<MT,unaligned,false,true>::ConstPointer
1041  Submatrix<MT,unaligned,false,true>::data() const noexcept
1042 {
1043  return matrix_.data() + row_*spacing() + column_;
1044 }
1046 //*************************************************************************************************
1047 
1048 
1049 //*************************************************************************************************
1058 template< typename MT > // Type of the dense matrix
1059 inline typename Submatrix<MT,unaligned,false,true>::Pointer
1060  Submatrix<MT,unaligned,false,true>::data( size_t i ) noexcept
1061 {
1062  return matrix_.data() + (row_+i)*spacing() + column_;
1063 }
1065 //*************************************************************************************************
1066 
1067 
1068 //*************************************************************************************************
1077 template< typename MT > // Type of the dense matrix
1078 inline typename Submatrix<MT,unaligned,false,true>::ConstPointer
1079  Submatrix<MT,unaligned,false,true>::data( size_t i ) const noexcept
1080 {
1081  return matrix_.data() + (row_+i)*spacing() + column_;
1082 }
1084 //*************************************************************************************************
1085 
1086 
1087 //*************************************************************************************************
1099 template< typename MT > // Type of the dense matrix
1102 {
1103  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
1104  return Iterator( matrix_.begin( row_ + i ) + column_, isAligned_ );
1105 }
1107 //*************************************************************************************************
1108 
1109 
1110 //*************************************************************************************************
1122 template< typename MT > // Type of the dense matrix
1125 {
1126  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
1127  return ConstIterator( matrix_.cbegin( row_ + i ) + column_, isAligned_ );
1128 }
1130 //*************************************************************************************************
1131 
1132 
1133 //*************************************************************************************************
1145 template< typename MT > // Type of the dense matrix
1148 {
1149  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
1150  return ConstIterator( matrix_.cbegin( row_ + i ) + column_, isAligned_ );
1151 }
1153 //*************************************************************************************************
1154 
1155 
1156 //*************************************************************************************************
1168 template< typename MT > // Type of the dense matrix
1171 {
1172  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
1173  return Iterator( matrix_.begin( row_ + i ) + column_ + n_, isAligned_ );
1174 }
1176 //*************************************************************************************************
1177 
1178 
1179 //*************************************************************************************************
1191 template< typename MT > // Type of the dense matrix
1193  Submatrix<MT,unaligned,false,true>::end( size_t i ) const
1194 {
1195  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
1196  return ConstIterator( matrix_.cbegin( row_ + i ) + column_ + n_, isAligned_ );
1197 }
1199 //*************************************************************************************************
1200 
1201 
1202 //*************************************************************************************************
1214 template< typename MT > // Type of the dense matrix
1217 {
1218  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
1219  return ConstIterator( matrix_.cbegin( row_ + i ) + column_ + n_, isAligned_ );
1220 }
1222 //*************************************************************************************************
1223 
1224 
1225 
1226 
1227 //=================================================================================================
1228 //
1229 // ASSIGNMENT OPERATORS
1230 //
1231 //=================================================================================================
1232 
1233 //*************************************************************************************************
1244 template< typename MT > // Type of the dense matrix
1245 inline Submatrix<MT,unaligned,false,true>&
1246  Submatrix<MT,unaligned,false,true>::operator=( const ElementType& rhs )
1247 {
1248  const size_t iend( row_ + m_ );
1249 
1250  for( size_t i=row_; i<iend; ++i )
1251  {
1252  const size_t jbegin( ( IsUpper<MT>::value )
1253  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
1254  ?( max( i+1UL, column_ ) )
1255  :( max( i, column_ ) ) )
1256  :( column_ ) );
1257  const size_t jend ( ( IsLower<MT>::value )
1258  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
1259  ?( min( i, column_+n_ ) )
1260  :( min( i+1UL, column_+n_ ) ) )
1261  :( column_+n_ ) );
1262 
1263  for( size_t j=jbegin; j<jend; ++j )
1264  matrix_(i,j) = rhs;
1265  }
1266 
1267  return *this;
1268 }
1270 //*************************************************************************************************
1271 
1272 
1273 //*************************************************************************************************
1286 template< typename MT > // Type of the dense matrix
1287 inline Submatrix<MT,unaligned,false,true>&
1288  Submatrix<MT,unaligned,false,true>::operator=( initializer_list< initializer_list<ElementType> > list )
1289 {
1290  if( list.size() != rows() || determineColumns( list ) > columns() ) {
1291  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to submatrix" );
1292  }
1293 
1294  size_t i( 0UL );
1295 
1296  for( const auto& rowList : list ) {
1297  std::fill( std::copy( rowList.begin(), rowList.end(), begin(i) ), end(i), ElementType() );
1298  ++i;
1299  }
1300 
1301  return *this;
1302 }
1304 //*************************************************************************************************
1305 
1306 
1307 //*************************************************************************************************
1322 template< typename MT > // Type of the dense matrix
1323 inline Submatrix<MT,unaligned,false,true>&
1324  Submatrix<MT,unaligned,false,true>::operator=( const Submatrix& rhs )
1325 {
1328 
1329  if( this == &rhs || ( &matrix_ == &rhs.matrix_ && row_ == rhs.row_ && column_ == rhs.column_ ) )
1330  return *this;
1331 
1332  if( rows() != rhs.rows() || columns() != rhs.columns() ) {
1333  BLAZE_THROW_INVALID_ARGUMENT( "Submatrix sizes do not match" );
1334  }
1335 
1336  if( !tryAssign( matrix_, rhs, row_, column_ ) ) {
1337  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1338  }
1339 
1340  DerestrictTrait_<This> left( derestrict( *this ) );
1341 
1342  if( rhs.canAlias( &matrix_ ) ) {
1343  const ResultType tmp( rhs );
1344  smpAssign( left, tmp );
1345  }
1346  else {
1347  smpAssign( left, rhs );
1348  }
1349 
1350  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1351 
1352  return *this;
1353 }
1355 //*************************************************************************************************
1356 
1357 
1358 //*************************************************************************************************
1373 template< typename MT > // Type of the dense matrix
1374 template< typename MT2 // Type of the right-hand side matrix
1375  , bool SO2 > // Storage order of the right-hand side matrix
1376 inline Submatrix<MT,unaligned,false,true>&
1377  Submatrix<MT,unaligned,false,true>::operator=( const Matrix<MT2,SO2>& rhs )
1378 {
1380 
1381  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
1382  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1383  }
1384 
1385  typedef If_< IsRestricted<MT>, CompositeType_<MT2>, const MT2& > Right;
1386  Right right( ~rhs );
1387 
1388  if( !tryAssign( matrix_, right, row_, column_ ) ) {
1389  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1390  }
1391 
1392  if( IsSparseMatrix<MT2>::value )
1393  reset();
1394 
1395  DerestrictTrait_<This> left( derestrict( *this ) );
1396 
1397  if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
1398  const ResultType_<MT2> tmp( right );
1399  smpAssign( left, tmp );
1400  }
1401  else {
1402  smpAssign( left, right );
1403  }
1404 
1405  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1406 
1407  return *this;
1408 }
1410 //*************************************************************************************************
1411 
1412 
1413 //*************************************************************************************************
1427 template< typename MT > // Type of the dense matrix
1428 template< typename MT2 // Type of the right-hand side matrix
1429  , bool SO2 > // Storage order of the right-hand side matrix
1430 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,false,true>& >
1431  Submatrix<MT,unaligned,false,true>::operator+=( const Matrix<MT2,SO2>& rhs )
1432 {
1436 
1437  typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
1438 
1441 
1442  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
1443  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1444  }
1445 
1446  if( !tryAddAssign( matrix_, ~rhs, row_, column_ ) ) {
1447  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1448  }
1449 
1450  DerestrictTrait_<This> left( derestrict( *this ) );
1451 
1452  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
1453  (~rhs).canAlias( &matrix_ ) ) {
1454  const AddType tmp( *this + (~rhs) );
1455  smpAssign( left, tmp );
1456  }
1457  else {
1458  smpAddAssign( left, ~rhs );
1459  }
1460 
1461  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1462 
1463  return *this;
1464 }
1466 //*************************************************************************************************
1467 
1468 
1469 //*************************************************************************************************
1483 template< typename MT > // Type of the dense matrix
1484 template< typename MT2 // Type of the right-hand side matrix
1485  , bool SO2 > // Storage order of the right-hand side matrix
1486 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,false,true>& >
1487  Submatrix<MT,unaligned,false,true>::operator+=( const Matrix<MT2,SO2>& rhs )
1488 {
1492 
1493  typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
1494 
1497 
1498  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
1499  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1500  }
1501 
1502  const AddType tmp( *this + (~rhs) );
1503 
1504  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
1505  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1506  }
1507 
1508  DerestrictTrait_<This> left( derestrict( *this ) );
1509 
1510  smpAssign( left, tmp );
1511 
1512  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1513 
1514  return *this;
1515 }
1517 //*************************************************************************************************
1518 
1519 
1520 //*************************************************************************************************
1534 template< typename MT > // Type of the dense matrix
1535 template< typename MT2 // Type of the right-hand side matrix
1536  , bool SO2 > // Storage order of the right-hand side matrix
1537 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,false,true>& >
1538  Submatrix<MT,unaligned,false,true>::operator-=( const Matrix<MT2,SO2>& rhs )
1539 {
1543 
1544  typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
1545 
1548 
1549  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
1550  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1551  }
1552 
1553  if( !trySubAssign( matrix_, ~rhs, row_, column_ ) ) {
1554  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1555  }
1556 
1557  DerestrictTrait_<This> left( derestrict( *this ) );
1558 
1559  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
1560  (~rhs).canAlias( &matrix_ ) ) {
1561  const SubType tmp( *this - (~rhs ) );
1562  smpAssign( left, tmp );
1563  }
1564  else {
1565  smpSubAssign( left, ~rhs );
1566  }
1567 
1568  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1569 
1570  return *this;
1571 }
1573 //*************************************************************************************************
1574 
1575 
1576 //*************************************************************************************************
1590 template< typename MT > // Type of the dense matrix
1591 template< typename MT2 // Type of the right-hand side matrix
1592  , bool SO2 > // Storage order of the right-hand side matrix
1593 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,false,true>& >
1594  Submatrix<MT,unaligned,false,true>::operator-=( const Matrix<MT2,SO2>& rhs )
1595 {
1599 
1600  typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
1601 
1604 
1605  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
1606  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1607  }
1608 
1609  const SubType tmp( *this - (~rhs) );
1610 
1611  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
1612  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1613  }
1614 
1615  DerestrictTrait_<This> left( derestrict( *this ) );
1616 
1617  smpAssign( left, tmp );
1618 
1619  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1620 
1621  return *this;
1622 }
1624 //*************************************************************************************************
1625 
1626 
1627 //*************************************************************************************************
1641 template< typename MT > // Type of the dense matrix
1642 template< typename MT2 // Type of the right-hand side matrix
1643  , bool SO2 > // Storage order of the right-hand side matrix
1644 inline Submatrix<MT,unaligned,false,true>&
1645  Submatrix<MT,unaligned,false,true>::operator*=( const Matrix<MT2,SO2>& rhs )
1646 {
1650 
1651  typedef MultTrait_< ResultType, ResultType_<MT2> > MultType;
1652 
1655 
1656  if( columns() != (~rhs).rows() ) {
1657  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1658  }
1659 
1660  const MultType tmp( *this * (~rhs) );
1661 
1662  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
1663  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1664  }
1665 
1666  DerestrictTrait_<This> left( derestrict( *this ) );
1667 
1668  smpAssign( left, tmp );
1669 
1670  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1671 
1672  return *this;
1673 }
1675 //*************************************************************************************************
1676 
1677 
1678 //*************************************************************************************************
1689 template< typename MT > // Type of the dense matrix
1690 template< typename Other > // Data type of the right-hand side scalar
1691 inline EnableIf_< IsNumeric<Other>, Submatrix<MT,unaligned,false,true> >&
1693 {
1695 
1696  DerestrictTrait_<This> left( derestrict( *this ) );
1697  smpAssign( left, (*this) * rhs );
1698 
1699  return *this;
1700 }
1702 //*************************************************************************************************
1703 
1704 
1705 //*************************************************************************************************
1718 template< typename MT > // Type of the dense matrix
1719 template< typename Other > // Data type of the right-hand side scalar
1720 inline EnableIf_< IsNumeric<Other>, Submatrix<MT,unaligned,false,true> >&
1722 {
1724 
1725  BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
1726 
1727  DerestrictTrait_<This> left( derestrict( *this ) );
1728  smpAssign( left, (*this) / rhs );
1729 
1730  return *this;
1731 }
1733 //*************************************************************************************************
1734 
1735 
1736 
1737 
1738 //=================================================================================================
1739 //
1740 // UTILITY FUNCTIONS
1741 //
1742 //=================================================================================================
1743 
1744 //*************************************************************************************************
1750 template< typename MT > // Type of the dense matrix
1751 inline size_t Submatrix<MT,unaligned,false,true>::row() const noexcept
1752 {
1753  return row_;
1754 }
1756 //*************************************************************************************************
1757 
1758 
1759 //*************************************************************************************************
1765 template< typename MT > // Type of the dense matrix
1766 inline size_t Submatrix<MT,unaligned,false,true>::rows() const noexcept
1767 {
1768  return m_;
1769 }
1771 //*************************************************************************************************
1772 
1773 
1774 //*************************************************************************************************
1780 template< typename MT > // Type of the dense matrix
1781 inline size_t Submatrix<MT,unaligned,false,true>::column() const noexcept
1782 {
1783  return column_;
1784 }
1785 //*************************************************************************************************
1786 
1787 
1788 //*************************************************************************************************
1794 template< typename MT > // Type of the dense matrix
1795 inline size_t Submatrix<MT,unaligned,false,true>::columns() const noexcept
1796 {
1797  return n_;
1798 }
1800 //*************************************************************************************************
1801 
1802 
1803 //*************************************************************************************************
1814 template< typename MT > // Type of the dense matrix
1815 inline size_t Submatrix<MT,unaligned,false,true>::spacing() const noexcept
1816 {
1817  return matrix_.spacing();
1818 }
1819 //*************************************************************************************************
1820 
1821 
1822 //*************************************************************************************************
1828 template< typename MT > // Type of the dense matrix
1829 inline size_t Submatrix<MT,unaligned,false,true>::capacity() const noexcept
1830 {
1831  return rows() * columns();
1832 }
1834 //*************************************************************************************************
1835 
1836 
1837 //*************************************************************************************************
1849 template< typename MT > // Type of the dense matrix
1850 inline size_t Submatrix<MT,unaligned,false,true>::capacity( size_t i ) const noexcept
1851 {
1852  UNUSED_PARAMETER( i );
1853 
1854  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
1855 
1856  return columns();
1857 }
1859 //*************************************************************************************************
1860 
1861 
1862 //*************************************************************************************************
1868 template< typename MT > // Type of the dense matrix
1870 {
1871  const size_t iend( row_ + m_ );
1872  const size_t jend( column_ + n_ );
1873  size_t nonzeros( 0UL );
1874 
1875  for( size_t i=row_; i<iend; ++i )
1876  for( size_t j=column_; j<jend; ++j )
1877  if( !isDefault( matrix_(i,j) ) )
1878  ++nonzeros;
1879 
1880  return nonzeros;
1881 }
1883 //*************************************************************************************************
1884 
1885 
1886 //*************************************************************************************************
1898 template< typename MT > // Type of the dense matrix
1899 inline size_t Submatrix<MT,unaligned,false,true>::nonZeros( size_t i ) const
1900 {
1901  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
1902 
1903  const size_t jend( column_ + n_ );
1904  size_t nonzeros( 0UL );
1905 
1906  for( size_t j=column_; j<jend; ++j )
1907  if( !isDefault( matrix_(row_+i,j) ) )
1908  ++nonzeros;
1909 
1910  return nonzeros;
1911 }
1913 //*************************************************************************************************
1914 
1915 
1916 //*************************************************************************************************
1922 template< typename MT > // Type of the dense matrix
1924 {
1925  using blaze::clear;
1926 
1927  for( size_t i=row_; i<row_+m_; ++i )
1928  {
1929  const size_t jbegin( ( IsUpper<MT>::value )
1930  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
1931  ?( max( i+1UL, column_ ) )
1932  :( max( i, column_ ) ) )
1933  :( column_ ) );
1934  const size_t jend ( ( IsLower<MT>::value )
1935  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
1936  ?( min( i, column_+n_ ) )
1937  :( min( i+1UL, column_+n_ ) ) )
1938  :( column_+n_ ) );
1939 
1940  for( size_t j=jbegin; j<jend; ++j )
1941  clear( matrix_(i,j) );
1942  }
1943 }
1945 //*************************************************************************************************
1946 
1947 
1948 //*************************************************************************************************
1960 template< typename MT > // Type of the dense matrix
1961 inline void Submatrix<MT,unaligned,false,true>::reset( size_t i )
1962 {
1963  using blaze::clear;
1964 
1965  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
1966 
1967  const size_t jbegin( ( IsUpper<MT>::value )
1968  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
1969  ?( max( i+1UL, column_ ) )
1970  :( max( i, column_ ) ) )
1971  :( column_ ) );
1972  const size_t jend ( ( IsLower<MT>::value )
1973  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
1974  ?( min( i, column_+n_ ) )
1975  :( min( i+1UL, column_+n_ ) ) )
1976  :( column_+n_ ) );
1977 
1978  for( size_t j=jbegin; j<jend; ++j )
1979  clear( matrix_(row_+i,j) );
1980 }
1982 //*************************************************************************************************
1983 
1984 
1985 //*************************************************************************************************
2003 template< typename MT > // Type of the dense matrix
2004 inline Submatrix<MT,unaligned,false,true>& Submatrix<MT,unaligned,false,true>::transpose()
2005 {
2006  if( m_ != n_ ) {
2007  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
2008  }
2009 
2010  if( !tryAssign( matrix_, trans( *this ), row_, column_ ) ) {
2011  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
2012  }
2013 
2014  DerestrictTrait_<This> left( derestrict( *this ) );
2015  const ResultType tmp( trans( *this ) );
2016  smpAssign( left, tmp );
2017 
2018  return *this;
2019 }
2021 //*************************************************************************************************
2022 
2023 
2024 //*************************************************************************************************
2042 template< typename MT > // Type of the dense matrix
2043 inline Submatrix<MT,unaligned,false,true>& Submatrix<MT,unaligned,false,true>::ctranspose()
2044 {
2045  if( m_ != n_ ) {
2046  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
2047  }
2048 
2049  if( !tryAssign( matrix_, ctrans( *this ), row_, column_ ) ) {
2050  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
2051  }
2052 
2053  DerestrictTrait_<This> left( derestrict( *this ) );
2054  const ResultType tmp( ctrans( *this ) );
2055  smpAssign( left, tmp );
2056 
2057  return *this;
2058 }
2060 //*************************************************************************************************
2061 
2062 
2063 //*************************************************************************************************
2074 template< typename MT > // Type of the dense matrix
2075 template< typename Other > // Data type of the scalar value
2076 inline Submatrix<MT,unaligned,false,true>&
2077  Submatrix<MT,unaligned,false,true>::scale( const Other& scalar )
2078 {
2080 
2081  const size_t iend( row_ + m_ );
2082 
2083  for( size_t i=row_; i<iend; ++i )
2084  {
2085  const size_t jbegin( ( IsUpper<MT>::value )
2086  ?( ( IsStrictlyUpper<MT>::value )
2087  ?( max( i+1UL, column_ ) )
2088  :( max( i, column_ ) ) )
2089  :( column_ ) );
2090  const size_t jend ( ( IsLower<MT>::value )
2091  ?( ( IsStrictlyLower<MT>::value )
2092  ?( min( i, column_+n_ ) )
2093  :( min( i+1UL, column_+n_ ) ) )
2094  :( column_+n_ ) );
2095 
2096  for( size_t j=jbegin; j<jend; ++j )
2097  matrix_(i,j) *= scalar;
2098  }
2099 
2100  return *this;
2101 }
2103 //*************************************************************************************************
2104 
2105 
2106 //*************************************************************************************************
2116 template< typename MT > // Type of the dense matrix
2117 inline bool Submatrix<MT,unaligned,false,true>::hasOverlap() const noexcept
2118 {
2119  BLAZE_INTERNAL_ASSERT( IsSymmetric<MT>::value || IsHermitian<MT>::value, "Invalid matrix detected" );
2120 
2121  if( ( row_ + m_ <= column_ ) || ( column_ + n_ <= row_ ) )
2122  return false;
2123  else return true;
2124 }
2126 //*************************************************************************************************
2127 
2128 
2129 
2130 
2131 //=================================================================================================
2132 //
2133 // EXPRESSION TEMPLATE EVALUATION FUNCTIONS
2134 //
2135 //=================================================================================================
2136 
2137 //*************************************************************************************************
2148 template< typename MT > // Type of the dense matrix
2149 template< typename Other > // Data type of the foreign expression
2150 inline bool Submatrix<MT,unaligned,false,true>::canAlias( const Other* alias ) const noexcept
2151 {
2152  return matrix_.isAliased( alias );
2153 }
2155 //*************************************************************************************************
2156 
2157 
2158 //*************************************************************************************************
2169 template< typename MT > // Type of the dense matrix
2170 template< typename MT2 // Data type of the foreign dense submatrix
2171  , bool AF2 // Alignment flag of the foreign dense submatrix
2172  , bool SO2 > // Storage order of the foreign dense submatrix
2173 inline bool Submatrix<MT,unaligned,false,true>::canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
2174 {
2175  return ( matrix_.isAliased( &alias->matrix_ ) &&
2176  ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
2177  ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
2178 }
2180 //*************************************************************************************************
2181 
2182 
2183 //*************************************************************************************************
2194 template< typename MT > // Type of the dense matrix
2195 template< typename Other > // Data type of the foreign expression
2196 inline bool Submatrix<MT,unaligned,false,true>::isAliased( const Other* alias ) const noexcept
2197 {
2198  return matrix_.isAliased( alias );
2199 }
2201 //*************************************************************************************************
2202 
2203 
2204 //*************************************************************************************************
2215 template< typename MT > // Type of the dense matrix
2216 template< typename MT2 // Data type of the foreign dense submatrix
2217  , bool AF2 // Alignment flag of the foreign dense submatrix
2218  , bool SO2 > // Storage order of the foreign dense submatrix
2219 inline bool Submatrix<MT,unaligned,false,true>::isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
2220 {
2221  return ( matrix_.isAliased( &alias->matrix_ ) &&
2222  ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
2223  ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
2224 }
2226 //*************************************************************************************************
2227 
2228 
2229 //*************************************************************************************************
2239 template< typename MT > // Type of the dense matrix
2240 inline bool Submatrix<MT,unaligned,false,true>::isAligned() const noexcept
2241 {
2242  return isAligned_;
2243 }
2245 //*************************************************************************************************
2246 
2247 
2248 //*************************************************************************************************
2259 template< typename MT > // Type of the dense matrix
2260 inline bool Submatrix<MT,unaligned,false,true>::canSMPAssign() const noexcept
2261 {
2262  return ( rows() * columns() >= SMP_DMATASSIGN_THRESHOLD );
2263 }
2265 //*************************************************************************************************
2266 
2267 
2268 //*************************************************************************************************
2284 template< typename MT > // Type of the dense matrix
2285 BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,false,true>::SIMDType
2286  Submatrix<MT,unaligned,false,true>::load( size_t i, size_t j ) const noexcept
2287 {
2288  if( isAligned_ )
2289  return loada( i, j );
2290  else
2291  return loadu( i, j );
2292 }
2294 //*************************************************************************************************
2295 
2296 
2297 //*************************************************************************************************
2313 template< typename MT > // Type of the dense matrix
2314 BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,false,true>::SIMDType
2315  Submatrix<MT,unaligned,false,true>::loada( size_t i, size_t j ) const noexcept
2316 {
2318 
2319  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
2320  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
2321  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
2322  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
2323 
2324  return matrix_.loada( row_+i, column_+j );
2325 }
2327 //*************************************************************************************************
2328 
2329 
2330 //*************************************************************************************************
2346 template< typename MT > // Type of the dense matrix
2347 BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,false,true>::SIMDType
2348  Submatrix<MT,unaligned,false,true>::loadu( size_t i, size_t j ) const noexcept
2349 {
2351 
2352  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
2353  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
2354  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
2355  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
2356 
2357  return matrix_.loadu( row_+i, column_+j );
2358 }
2360 //*************************************************************************************************
2361 
2362 
2363 //*************************************************************************************************
2380 template< typename MT > // Type of the dense matrix
2382  Submatrix<MT,unaligned,false,true>::store( size_t i, size_t j, const SIMDType& value ) noexcept
2383 {
2384  if( isAligned_ )
2385  storea( i, j, value );
2386  else
2387  storeu( i, j, value );
2388 }
2390 //*************************************************************************************************
2391 
2392 
2393 //*************************************************************************************************
2410 template< typename MT > // Type of the dense matrix
2412  Submatrix<MT,unaligned,false,true>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
2413 {
2415 
2416  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
2417  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
2418  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
2419  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
2420 
2421  matrix_.storea( row_+i, column_+j, value );
2422 }
2424 //*************************************************************************************************
2425 
2426 
2427 //*************************************************************************************************
2444 template< typename MT > // Type of the dense matrix
2446  Submatrix<MT,unaligned,false,true>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
2447 {
2449 
2450  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
2451  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
2452  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
2453  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
2454 
2455  matrix_.storeu( row_+i, column_+j, value );
2456 }
2458 //*************************************************************************************************
2459 
2460 
2461 //*************************************************************************************************
2478 template< typename MT > // Type of the dense matrix
2480  Submatrix<MT,unaligned,false,true>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
2481 {
2483 
2484  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
2485  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
2486  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
2487  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
2488 
2489  if( isAligned_ )
2490  matrix_.stream( row_+i, column_+j, value );
2491  else
2492  matrix_.storeu( row_+i, column_+j, value );
2493 }
2495 //*************************************************************************************************
2496 
2497 
2498 //*************************************************************************************************
2510 template< typename MT > // Type of the dense matrix
2511 template< typename MT2 > // Type of the right-hand side dense matrix
2512 inline DisableIf_< typename Submatrix<MT,unaligned,false,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
2513  Submatrix<MT,unaligned,false,true>::assign( const DenseMatrix<MT2,false>& rhs )
2514 {
2515  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2516  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2517 
2518  const size_t jpos( n_ & size_t(-2) );
2519  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
2520 
2521  for( size_t i=0UL; i<m_; ++i ) {
2522  for( size_t j=0UL; j<jpos; j+=2UL ) {
2523  matrix_(row_+i,column_+j ) = (~rhs)(i,j );
2524  matrix_(row_+i,column_+j+1UL) = (~rhs)(i,j+1UL);
2525  }
2526  if( jpos < n_ ) {
2527  matrix_(row_+i,column_+jpos) = (~rhs)(i,jpos);
2528  }
2529  }
2530 }
2532 //*************************************************************************************************
2533 
2534 
2535 //*************************************************************************************************
2547 template< typename MT > // Type of the dense matrix
2548 template< typename MT2 > // Type of the right-hand side dense matrix
2549 inline EnableIf_< typename Submatrix<MT,unaligned,false,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
2550  Submatrix<MT,unaligned,false,true>::assign( const DenseMatrix<MT2,false>& rhs )
2551 {
2553 
2554  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2555  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2556 
2557  const size_t jpos( n_ & size_t(-SIMDSIZE) );
2558  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
2559 
2560  if( useStreaming && isAligned_ &&
2561  m_*n_ > ( cacheSize / ( sizeof(ElementType) * 3UL ) ) &&
2562  !(~rhs).isAliased( &matrix_ ) )
2563  {
2564  for( size_t i=0UL; i<m_; ++i )
2565  {
2566  size_t j( 0UL );
2567  Iterator left( begin(i) );
2568  ConstIterator_<MT2> right( (~rhs).begin(i) );
2569 
2570  for( ; j<jpos; j+=SIMDSIZE ) {
2571  left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2572  }
2573  for( ; j<n_; ++j ) {
2574  *left = *right;
2575  }
2576  }
2577  }
2578  else
2579  {
2580  for( size_t i=0UL; i<m_; ++i )
2581  {
2582  size_t j( 0UL );
2583  Iterator left( begin(i) );
2584  ConstIterator_<MT2> right( (~rhs).begin(i) );
2585 
2586  for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
2587  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2588  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2589  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2590  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2591  }
2592  for( ; j<jpos; j+=SIMDSIZE ) {
2593  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2594  }
2595  for( ; j<n_; ++j ) {
2596  *left = *right; ++left; ++right;
2597  }
2598  }
2599  }
2600 }
2602 //*************************************************************************************************
2603 
2604 
2605 //*************************************************************************************************
2617 template< typename MT > // Type of the dense matrix
2618 template< typename MT2 > // Type of the right-hand side dense matrix
2619 inline void Submatrix<MT,unaligned,false,true>::assign( const DenseMatrix<MT2,true>& rhs )
2620 {
2622 
2623  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2624  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2625 
2626  const size_t block( BLOCK_SIZE );
2627 
2628  for( size_t ii=0UL; ii<m_; ii+=block ) {
2629  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
2630  for( size_t jj=0UL; jj<n_; jj+=block ) {
2631  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
2632  for( size_t i=ii; i<iend; ++i ) {
2633  for( size_t j=jj; j<jend; ++j ) {
2634  matrix_(row_+i,column_+j) = (~rhs)(i,j);
2635  }
2636  }
2637  }
2638  }
2639 }
2641 //*************************************************************************************************
2642 
2643 
2644 //*************************************************************************************************
2656 template< typename MT > // Type of the dense matrix
2657 template< typename MT2 > // Type of the right-hand side sparse matrix
2658 inline void Submatrix<MT,unaligned,false,true>::assign( const SparseMatrix<MT2,false>& rhs )
2659 {
2660  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2661  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2662 
2663  for( size_t i=0UL; i<m_; ++i )
2664  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
2665  matrix_(row_+i,column_+element->index()) = element->value();
2666 }
2668 //*************************************************************************************************
2669 
2670 
2671 //*************************************************************************************************
2683 template< typename MT > // Type of the dense matrix
2684 template< typename MT2 > // Type of the right-hand side sparse matrix
2685 inline void Submatrix<MT,unaligned,false,true>::assign( const SparseMatrix<MT2,true>& rhs )
2686 {
2688 
2689  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2690  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2691 
2692  for( size_t j=0UL; j<n_; ++j )
2693  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
2694  matrix_(row_+element->index(),column_+j) = element->value();
2695 }
2697 //*************************************************************************************************
2698 
2699 
2700 //*************************************************************************************************
2712 template< typename MT > // Type of the dense matrix
2713 template< typename MT2 > // Type of the right-hand side dense matrix
2714 inline DisableIf_< typename Submatrix<MT,unaligned,false,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
2715  Submatrix<MT,unaligned,false,true>::addAssign( const DenseMatrix<MT2,false>& rhs )
2716 {
2717  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2718  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2719 
2720  const size_t jpos( n_ & size_t(-2) );
2721  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
2722 
2723  for( size_t i=0UL; i<m_; ++i )
2724  {
2725  if( IsDiagonal<MT2>::value ) {
2726  matrix_(row_+i,column_+i) += (~rhs)(i,i);
2727  }
2728  else {
2729  for( size_t j=0UL; j<jpos; j+=2UL ) {
2730  matrix_(row_+i,column_+j ) += (~rhs)(i,j );
2731  matrix_(row_+i,column_+j+1UL) += (~rhs)(i,j+1UL);
2732  }
2733  if( jpos < n_ ) {
2734  matrix_(row_+i,column_+jpos) += (~rhs)(i,jpos);
2735  }
2736  }
2737  }
2738 }
2740 //*************************************************************************************************
2741 
2742 
2743 //*************************************************************************************************
2755 template< typename MT > // Type of the dense matrix
2756 template< typename MT2 > // Type of the right-hand side dense matrix
2757 inline EnableIf_< typename Submatrix<MT,unaligned,false,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
2758  Submatrix<MT,unaligned,false,true>::addAssign( const DenseMatrix<MT2,false>& rhs )
2759 {
2761 
2762  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2763  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2764 
2765  for( size_t i=0UL; i<m_; ++i )
2766  {
2767  const size_t jbegin( ( IsUpper<MT2>::value )
2768  ?( ( IsStrictlyUpper<MT2>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
2769  :( 0UL ) );
2770  const size_t jend ( ( IsLower<MT2>::value )
2771  ?( IsStrictlyLower<MT2>::value ? i : i+1UL )
2772  :( n_ ) );
2773  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
2774 
2775  const size_t jpos( jend & size_t(-SIMDSIZE) );
2776  BLAZE_INTERNAL_ASSERT( ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
2777 
2778  size_t j( jbegin );
2779  Iterator left( begin(i) + jbegin );
2780  ConstIterator_<MT2> right( (~rhs).begin(i) + jbegin );
2781 
2782  for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
2783  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2784  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2785  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2786  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2787  }
2788  for( ; j<jpos; j+=SIMDSIZE ) {
2789  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2790  }
2791  for( ; j<jend; ++j ) {
2792  *left += *right; ++left; ++right;
2793  }
2794  }
2795 }
2797 //*************************************************************************************************
2798 
2799 
2800 //*************************************************************************************************
2812 template< typename MT > // Type of the dense matrix
2813 template< typename MT2 > // Type of the right-hand side dense matrix
2814 inline void Submatrix<MT,unaligned,false,true>::addAssign( const DenseMatrix<MT2,true>& rhs )
2815 {
2817 
2818  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2819  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2820 
2821  const size_t block( BLOCK_SIZE );
2822 
2823  for( size_t ii=0UL; ii<m_; ii+=block ) {
2824  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
2825  for( size_t jj=0UL; jj<n_; jj+=block ) {
2826  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
2827  for( size_t i=ii; i<iend; ++i ) {
2828  for( size_t j=jj; j<jend; ++j ) {
2829  matrix_(row_+i,column_+j) += (~rhs)(i,j);
2830  }
2831  }
2832  }
2833  }
2834 }
2836 //*************************************************************************************************
2837 
2838 
2839 //*************************************************************************************************
2851 template< typename MT > // Type of the dense matrix
2852 template< typename MT2 > // Type of the right-hand side sparse matrix
2853 inline void Submatrix<MT,unaligned,false,true>::addAssign( const SparseMatrix<MT2,false>& rhs )
2854 {
2855  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2856  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2857 
2858  for( size_t i=0UL; i<m_; ++i )
2859  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
2860  matrix_(row_+i,column_+element->index()) += element->value();
2861 }
2863 //*************************************************************************************************
2864 
2865 
2866 //*************************************************************************************************
2878 template< typename MT > // Type of the dense matrix
2879 template< typename MT2 > // Type of the right-hand side sparse matrix
2880 inline void Submatrix<MT,unaligned,false,true>::addAssign( const SparseMatrix<MT2,true>& rhs )
2881 {
2883 
2884  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2885  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2886 
2887  for( size_t j=0UL; j<n_; ++j )
2888  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
2889  matrix_(row_+element->index(),column_+j) += element->value();
2890 }
2892 //*************************************************************************************************
2893 
2894 
2895 //*************************************************************************************************
2907 template< typename MT > // Type of the dense matrix
2908 template< typename MT2 > // Type of the right-hand side dense matrix
2909 inline DisableIf_< typename Submatrix<MT,unaligned,false,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
2910  Submatrix<MT,unaligned,false,true>::subAssign( const DenseMatrix<MT2,false>& rhs )
2911 {
2912  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2913  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2914 
2915  const size_t jpos( n_ & size_t(-2) );
2916  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
2917 
2918  for( size_t i=0UL; i<m_; ++i )
2919  {
2920  if( IsDiagonal<MT2>::value ) {
2921  matrix_(row_+i,column_+i) -= (~rhs)(i,i);
2922  }
2923  else {
2924  for( size_t j=0UL; j<jpos; j+=2UL ) {
2925  matrix_(row_+i,column_+j ) -= (~rhs)(i,j );
2926  matrix_(row_+i,column_+j+1UL) -= (~rhs)(i,j+1UL);
2927  }
2928  if( jpos < n_ ) {
2929  matrix_(row_+i,column_+jpos) -= (~rhs)(i,jpos);
2930  }
2931  }
2932  }
2933 }
2935 //*************************************************************************************************
2936 
2937 
2938 //*************************************************************************************************
2950 template< typename MT > // Type of the dense matrix
2951 template< typename MT2 > // Type of the right-hand side dense matrix
2952 inline EnableIf_< typename Submatrix<MT,unaligned,false,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
2953  Submatrix<MT,unaligned,false,true>::subAssign( const DenseMatrix<MT2,false>& rhs )
2954 {
2956 
2957  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2958  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2959 
2960  for( size_t i=0UL; i<m_; ++i )
2961  {
2962  const size_t jbegin( ( IsUpper<MT2>::value )
2963  ?( ( IsStrictlyUpper<MT2>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
2964  :( 0UL ) );
2965  const size_t jend ( ( IsLower<MT2>::value )
2966  ?( IsStrictlyLower<MT2>::value ? i : i+1UL )
2967  :( n_ ) );
2968  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
2969 
2970  const size_t jpos( jend & size_t(-SIMDSIZE) );
2971  BLAZE_INTERNAL_ASSERT( ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
2972 
2973  size_t j( jbegin );
2974  Iterator left( begin(i) + jbegin );
2975  ConstIterator_<MT2> right( (~rhs).begin(i) + jbegin );
2976 
2977  for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
2978  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2979  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2980  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2981  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2982  }
2983  for( ; j<jpos; j+=SIMDSIZE ) {
2984  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2985  }
2986  for( ; j<jend; ++j ) {
2987  *left -= *right; ++left; ++right;
2988  }
2989  }
2990 }
2992 //*************************************************************************************************
2993 
2994 
2995 //*************************************************************************************************
3007 template< typename MT > // Type of the dense matrix
3008 template< typename MT2 > // Type of the right-hand side dense matrix
3009 inline void Submatrix<MT,unaligned,false,true>::subAssign( const DenseMatrix<MT2,true>& rhs )
3010 {
3012 
3013  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
3014  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
3015 
3016  const size_t block( BLOCK_SIZE );
3017 
3018  for( size_t ii=0UL; ii<m_; ii+=block ) {
3019  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
3020  for( size_t jj=0UL; jj<n_; jj+=block ) {
3021  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
3022  for( size_t i=ii; i<iend; ++i ) {
3023  for( size_t j=jj; j<jend; ++j ) {
3024  matrix_(row_+i,column_+j) -= (~rhs)(i,j);
3025  }
3026  }
3027  }
3028  }
3029 }
3031 //*************************************************************************************************
3032 
3033 
3034 //*************************************************************************************************
3046 template< typename MT > // Type of the dense matrix
3047 template< typename MT2 > // Type of the right-hand side sparse matrix
3048 inline void Submatrix<MT,unaligned,false,true>::subAssign( const SparseMatrix<MT2,false>& rhs )
3049 {
3050  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
3051  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
3052 
3053  for( size_t i=0UL; i<m_; ++i )
3054  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
3055  matrix_(row_+i,column_+element->index()) -= element->value();
3056 }
3058 //*************************************************************************************************
3059 
3060 
3061 //*************************************************************************************************
3073 template< typename MT > // Type of the dense matrix
3074 template< typename MT2 > // Type of the right-hand side sparse matrix
3075 inline void Submatrix<MT,unaligned,false,true>::subAssign( const SparseMatrix<MT2,true>& rhs )
3076 {
3078 
3079  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
3080  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
3081 
3082  for( size_t j=0UL; j<n_; ++j )
3083  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
3084  matrix_(row_+element->index(),column_+j) -= element->value();
3085 }
3087 //*************************************************************************************************
3088 
3089 
3090 
3091 
3092 
3093 
3094 
3095 
3096 //=================================================================================================
3097 //
3098 // CLASS TEMPLATE SPECIALIZATION FOR UNALIGNED COLUMN-MAJOR DENSE SUBMATRICES
3099 //
3100 //=================================================================================================
3101 
3102 //*************************************************************************************************
3110 template< typename MT > // Type of the dense matrix
3111 class Submatrix<MT,unaligned,true,true>
3112  : public DenseMatrix< Submatrix<MT,unaligned,true,true>, true >
3113  , private View
3114 {
3115  private:
3116  //**Type definitions****************************************************************************
3118  typedef If_< IsExpression<MT>, MT, MT& > Operand;
3119  //**********************************************************************************************
3120 
3121  public:
3122  //**Type definitions****************************************************************************
3123  typedef Submatrix<MT,unaligned,true,true> This;
3124  typedef DenseMatrix<This,true> BaseType;
3125  typedef SubmatrixTrait_<MT> ResultType;
3126  typedef OppositeType_<ResultType> OppositeType;
3127  typedef TransposeType_<ResultType> TransposeType;
3128  typedef ElementType_<MT> ElementType;
3129  typedef SIMDTrait_<ElementType> SIMDType;
3130  typedef ReturnType_<MT> ReturnType;
3131  typedef const Submatrix& CompositeType;
3132 
3134  typedef ConstReference_<MT> ConstReference;
3135 
3137  typedef If_< IsConst<MT>, ConstReference, Reference_<MT> > Reference;
3138 
3140  typedef const ElementType* ConstPointer;
3141 
3143  typedef If_< Or< IsConst<MT>, Not< HasMutableDataAccess<MT> > >, ConstPointer, ElementType* > Pointer;
3144  //**********************************************************************************************
3145 
3146  //**SubmatrixIterator class definition**********************************************************
3149  template< typename IteratorType > // Type of the dense matrix iterator
3150  class SubmatrixIterator
3151  {
3152  public:
3153  //**Type definitions*************************************************************************
3155  typedef typename std::iterator_traits<IteratorType>::iterator_category IteratorCategory;
3156 
3158  typedef typename std::iterator_traits<IteratorType>::value_type ValueType;
3159 
3161  typedef typename std::iterator_traits<IteratorType>::pointer PointerType;
3162 
3164  typedef typename std::iterator_traits<IteratorType>::reference ReferenceType;
3165 
3167  typedef typename std::iterator_traits<IteratorType>::difference_type DifferenceType;
3168 
3169  // STL iterator requirements
3170  typedef IteratorCategory iterator_category;
3171  typedef ValueType value_type;
3172  typedef PointerType pointer;
3173  typedef ReferenceType reference;
3174  typedef DifferenceType difference_type;
3175  //*******************************************************************************************
3176 
3177  //**Constructor******************************************************************************
3180  inline SubmatrixIterator()
3181  : iterator_ ( ) // Iterator to the current submatrix element
3182  , isAligned_( false ) // Memory alignment flag
3183  {}
3184  //*******************************************************************************************
3185 
3186  //**Constructor******************************************************************************
3194  inline SubmatrixIterator( IteratorType iterator, bool isMemoryAligned )
3195  : iterator_ ( iterator ) // Iterator to the current submatrix element
3196  , isAligned_( isMemoryAligned ) // Memory alignment flag
3197  {}
3198  //*******************************************************************************************
3199 
3200  //**Constructor******************************************************************************
3205  template< typename IteratorType2 >
3206  inline SubmatrixIterator( const SubmatrixIterator<IteratorType2>& it )
3207  : iterator_ ( it.base() ) // Iterator to the current submatrix element
3208  , isAligned_( it.isAligned() ) // Memory alignment flag
3209  {}
3210  //*******************************************************************************************
3211 
3212  //**Addition assignment operator*************************************************************
3218  inline SubmatrixIterator& operator+=( size_t inc ) {
3219  iterator_ += inc;
3220  return *this;
3221  }
3222  //*******************************************************************************************
3223 
3224  //**Subtraction assignment operator**********************************************************
3230  inline SubmatrixIterator& operator-=( size_t dec ) {
3231  iterator_ -= dec;
3232  return *this;
3233  }
3234  //*******************************************************************************************
3235 
3236  //**Prefix increment operator****************************************************************
3241  inline SubmatrixIterator& operator++() {
3242  ++iterator_;
3243  return *this;
3244  }
3245  //*******************************************************************************************
3246 
3247  //**Postfix increment operator***************************************************************
3252  inline const SubmatrixIterator operator++( int ) {
3253  return SubmatrixIterator( iterator_++, isAligned_ );
3254  }
3255  //*******************************************************************************************
3256 
3257  //**Prefix decrement operator****************************************************************
3262  inline SubmatrixIterator& operator--() {
3263  --iterator_;
3264  return *this;
3265  }
3266  //*******************************************************************************************
3267 
3268  //**Postfix decrement operator***************************************************************
3273  inline const SubmatrixIterator operator--( int ) {
3274  return SubmatrixIterator( iterator_--, isAligned_ );
3275  }
3276  //*******************************************************************************************
3277 
3278  //**Element access operator******************************************************************
3283  inline ReferenceType operator*() const {
3284  return *iterator_;
3285  }
3286  //*******************************************************************************************
3287 
3288  //**Load function****************************************************************************
3298  inline SIMDType load() const noexcept {
3299  if( isAligned_ )
3300  return loada();
3301  else
3302  return loadu();
3303  }
3304  //*******************************************************************************************
3305 
3306  //**Loada function***************************************************************************
3316  inline SIMDType loada() const noexcept {
3317  return iterator_.loada();
3318  }
3319  //*******************************************************************************************
3320 
3321  //**Loadu function***************************************************************************
3331  inline SIMDType loadu() const noexcept {
3332  return iterator_.loadu();
3333  }
3334  //*******************************************************************************************
3335 
3336  //**Store function***************************************************************************
3347  inline void store( const SIMDType& value ) const {
3348  storeu( value );
3349  }
3350  //*******************************************************************************************
3351 
3352  //**Storea function**************************************************************************
3363  inline void storea( const SIMDType& value ) const {
3364  iterator_.storea( value );
3365  }
3366  //*******************************************************************************************
3367 
3368  //**Storeu function**************************************************************************
3379  inline void storeu( const SIMDType& value ) const {
3380  if( isAligned_ ) {
3381  iterator_.storea( value );
3382  }
3383  else {
3384  iterator_.storeu( value );
3385  }
3386  }
3387  //*******************************************************************************************
3388 
3389  //**Stream function**************************************************************************
3400  inline void stream( const SIMDType& value ) const {
3401  iterator_.stream( value );
3402  }
3403  //*******************************************************************************************
3404 
3405  //**Equality operator************************************************************************
3411  inline bool operator==( const SubmatrixIterator& rhs ) const {
3412  return iterator_ == rhs.iterator_;
3413  }
3414  //*******************************************************************************************
3415 
3416  //**Inequality operator**********************************************************************
3422  inline bool operator!=( const SubmatrixIterator& rhs ) const {
3423  return iterator_ != rhs.iterator_;
3424  }
3425  //*******************************************************************************************
3426 
3427  //**Less-than operator***********************************************************************
3433  inline bool operator<( const SubmatrixIterator& rhs ) const {
3434  return iterator_ < rhs.iterator_;
3435  }
3436  //*******************************************************************************************
3437 
3438  //**Greater-than operator********************************************************************
3444  inline bool operator>( const SubmatrixIterator& rhs ) const {
3445  return iterator_ > rhs.iterator_;
3446  }
3447  //*******************************************************************************************
3448 
3449  //**Less-or-equal-than operator**************************************************************
3455  inline bool operator<=( const SubmatrixIterator& rhs ) const {
3456  return iterator_ <= rhs.iterator_;
3457  }
3458  //*******************************************************************************************
3459 
3460  //**Greater-or-equal-than operator***********************************************************
3466  inline bool operator>=( const SubmatrixIterator& rhs ) const {
3467  return iterator_ >= rhs.iterator_;
3468  }
3469  //*******************************************************************************************
3470 
3471  //**Subtraction operator*********************************************************************
3477  inline DifferenceType operator-( const SubmatrixIterator& rhs ) const {
3478  return iterator_ - rhs.iterator_;
3479  }
3480  //*******************************************************************************************
3481 
3482  //**Addition operator************************************************************************
3489  friend inline const SubmatrixIterator operator+( const SubmatrixIterator& it, size_t inc ) {
3490  return SubmatrixIterator( it.iterator_ + inc, it.isAligned_ );
3491  }
3492  //*******************************************************************************************
3493 
3494  //**Addition operator************************************************************************
3501  friend inline const SubmatrixIterator operator+( size_t inc, const SubmatrixIterator& it ) {
3502  return SubmatrixIterator( it.iterator_ + inc, it.isAligned_ );
3503  }
3504  //*******************************************************************************************
3505 
3506  //**Subtraction operator*********************************************************************
3513  friend inline const SubmatrixIterator operator-( const SubmatrixIterator& it, size_t dec ) {
3514  return SubmatrixIterator( it.iterator_ - dec, it.isAligned_ );
3515  }
3516  //*******************************************************************************************
3517 
3518  //**Base function****************************************************************************
3523  inline IteratorType base() const {
3524  return iterator_;
3525  }
3526  //*******************************************************************************************
3527 
3528  //**IsAligned function***********************************************************************
3533  inline bool isAligned() const noexcept {
3534  return isAligned_;
3535  }
3536  //*******************************************************************************************
3537 
3538  private:
3539  //**Member variables*************************************************************************
3540  IteratorType iterator_;
3541  bool isAligned_;
3542  //*******************************************************************************************
3543  };
3544  //**********************************************************************************************
3545 
3546  //**Type definitions****************************************************************************
3548  typedef SubmatrixIterator< ConstIterator_<MT> > ConstIterator;
3549 
3551  typedef If_< IsConst<MT>, ConstIterator, SubmatrixIterator< Iterator_<MT> > > Iterator;
3552  //**********************************************************************************************
3553 
3554  //**Compilation flags***************************************************************************
3556  enum : bool { simdEnabled = MT::simdEnabled };
3557 
3559  enum : bool { smpAssignable = MT::smpAssignable };
3560  //**********************************************************************************************
3561 
3562  //**Constructors********************************************************************************
3565  explicit inline Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n );
3566  // No explicitly declared copy constructor.
3568  //**********************************************************************************************
3569 
3570  //**Destructor**********************************************************************************
3571  // No explicitly declared destructor.
3572  //**********************************************************************************************
3573 
3574  //**Data access functions***********************************************************************
3577  inline Reference operator()( size_t i, size_t j );
3578  inline ConstReference operator()( size_t i, size_t j ) const;
3579  inline Reference at( size_t i, size_t j );
3580  inline ConstReference at( size_t i, size_t j ) const;
3581  inline Pointer data () noexcept;
3582  inline ConstPointer data () const noexcept;
3583  inline Pointer data ( size_t j ) noexcept;
3584  inline ConstPointer data ( size_t j ) const noexcept;
3585  inline Iterator begin ( size_t j );
3586  inline ConstIterator begin ( size_t j ) const;
3587  inline ConstIterator cbegin( size_t j ) const;
3588  inline Iterator end ( size_t j );
3589  inline ConstIterator end ( size_t j ) const;
3590  inline ConstIterator cend ( size_t j ) const;
3592  //**********************************************************************************************
3593 
3594  //**Assignment operators************************************************************************
3597  inline Submatrix& operator=( const ElementType& rhs );
3598  inline Submatrix& operator=( initializer_list< initializer_list<ElementType> > list );
3599  inline Submatrix& operator=( const Submatrix& rhs );
3600 
3601  template< typename MT2, bool SO >
3602  inline Submatrix& operator=( const Matrix<MT2,SO>& rhs );
3603 
3604  template< typename MT2, bool SO >
3605  inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
3606  operator+=( const Matrix<MT2,SO>& rhs );
3607 
3608  template< typename MT2, bool SO >
3609  inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
3610  operator+=( const Matrix<MT2,SO>& rhs );
3611 
3612  template< typename MT2, bool SO >
3613  inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
3614  operator-=( const Matrix<MT2,SO>& rhs );
3615 
3616  template< typename MT2, bool SO >
3617  inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
3618  operator-=( const Matrix<MT2,SO>& rhs );
3619 
3620  template< typename MT2, bool SO >
3621  inline Submatrix& operator*=( const Matrix<MT2,SO>& rhs );
3622 
3623  template< typename Other >
3624  inline EnableIf_< IsNumeric<Other>, Submatrix >& operator*=( Other rhs );
3625 
3626  template< typename Other >
3627  inline EnableIf_< IsNumeric<Other>, Submatrix >& operator/=( Other rhs );
3629  //**********************************************************************************************
3630 
3631  //**Utility functions***************************************************************************
3634  inline size_t row() const noexcept;
3635  inline size_t rows() const noexcept;
3636  inline size_t column() const noexcept;
3637  inline size_t columns() const noexcept;
3638  inline size_t spacing() const noexcept;
3639  inline size_t capacity() const noexcept;
3640  inline size_t capacity( size_t i ) const noexcept;
3641  inline size_t nonZeros() const;
3642  inline size_t nonZeros( size_t i ) const;
3643  inline void reset();
3644  inline void reset( size_t i );
3645  inline Submatrix& transpose();
3646  inline Submatrix& ctranspose();
3647  template< typename Other > inline Submatrix& scale( const Other& scalar );
3649  //**********************************************************************************************
3650 
3651  private:
3652  //**********************************************************************************************
3654  template< typename MT2 >
3655  struct VectorizedAssign {
3656  enum : bool { value = useOptimizedKernels &&
3657  simdEnabled && MT2::simdEnabled &&
3658  AreSIMDCombinable< ElementType, ElementType_<MT2> >::value };
3659  };
3660  //**********************************************************************************************
3661 
3662  //**********************************************************************************************
3664  template< typename MT2 >
3665  struct VectorizedAddAssign {
3666  enum : bool { value = useOptimizedKernels &&
3667  simdEnabled && MT2::simdEnabled &&
3668  AreSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
3669  HasSIMDAdd< ElementType, ElementType_<MT2> >::value &&
3670  !IsDiagonal<MT2>::value };
3671  };
3672  //**********************************************************************************************
3673 
3674  //**********************************************************************************************
3676  template< typename MT2 >
3677  struct VectorizedSubAssign {
3678  enum : bool { value = useOptimizedKernels &&
3679  simdEnabled && MT2::simdEnabled &&
3680  AreSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
3681  HasSIMDSub< ElementType, ElementType_<MT2> >::value &&
3682  !IsDiagonal<MT2>::value };
3683  };
3684  //**********************************************************************************************
3685 
3686  //**SIMD properties*****************************************************************************
3688  enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
3689  //**********************************************************************************************
3690 
3691  public:
3692  //**Expression template evaluation functions****************************************************
3695  template< typename Other >
3696  inline bool canAlias( const Other* alias ) const noexcept;
3697 
3698  template< typename MT2, bool AF2, bool SO2 >
3699  inline bool canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
3700 
3701  template< typename Other >
3702  inline bool isAliased( const Other* alias ) const noexcept;
3703 
3704  template< typename MT2, bool AF2, bool SO2 >
3705  inline bool isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
3706 
3707  inline bool isAligned () const noexcept;
3708  inline bool canSMPAssign() const noexcept;
3709 
3710  BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
3711  BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
3712  BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
3713 
3714  BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
3715  BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
3716  BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
3717  BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
3718 
3719  template< typename MT2 >
3720  inline DisableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,true>& rhs );
3721 
3722  template< typename MT2 >
3723  inline EnableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,true>& rhs );
3724 
3725  template< typename MT2 > inline void assign( const DenseMatrix<MT2,false>& rhs );
3726  template< typename MT2 > inline void assign( const SparseMatrix<MT2,true>& rhs );
3727  template< typename MT2 > inline void assign( const SparseMatrix<MT2,false>& rhs );
3728 
3729  template< typename MT2 >
3730  inline DisableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,true>& rhs );
3731 
3732  template< typename MT2 >
3733  inline EnableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,true>& rhs );
3734 
3735  template< typename MT2 > inline void addAssign( const DenseMatrix<MT2,false>& rhs );
3736  template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,true>& rhs );
3737  template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,false>& rhs );
3738 
3739  template< typename MT2 >
3740  inline DisableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,true>& rhs );
3741 
3742  template< typename MT2 >
3743  inline EnableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,true>& rhs );
3744 
3745  template< typename MT2 > inline void subAssign( const DenseMatrix<MT2,false>& rhs );
3746  template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,true>& rhs );
3747  template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,false>& rhs );
3749  //**********************************************************************************************
3750 
3751  private:
3752  //**Utility functions***************************************************************************
3755  inline bool hasOverlap() const noexcept;
3757  //**********************************************************************************************
3758 
3759  //**Member variables****************************************************************************
3762  Operand matrix_;
3763  const size_t row_;
3764  const size_t column_;
3765  const size_t m_;
3766  const size_t n_;
3767  const bool isAligned_;
3768 
3775  //**********************************************************************************************
3776 
3777  //**Friend declarations*************************************************************************
3778  template< typename MT2, bool AF2, bool SO2, bool DF2 > friend class Submatrix;
3779 
3780  template< bool AF1, typename MT2, bool AF2, bool SO2, bool DF2 >
3781  friend const Submatrix<MT2,AF1,SO2,DF2>
3782  submatrix( const Submatrix<MT2,AF2,SO2,DF2>& sm, size_t row, size_t column, size_t m, size_t n );
3783 
3784  template< typename MT2, bool AF2, bool SO2, bool DF2 >
3785  friend bool isIntact( const Submatrix<MT2,AF2,SO2,DF2>& sm ) noexcept;
3786 
3787  template< typename MT2, bool AF2, bool SO2, bool DF2 >
3788  friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Matrix<MT2,SO2>& b ) noexcept;
3789 
3790  template< typename MT2, bool AF2, bool SO2, bool DF2 >
3791  friend bool isSame( const Matrix<MT2,SO2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
3792 
3793  template< typename MT2, bool AF2, bool SO2, bool DF2 >
3794  friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
3795 
3796  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
3797  friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
3798  size_t row, size_t column );
3799 
3800  template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
3801  friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
3802  size_t row, size_t column );
3803 
3804  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
3805  friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
3806  size_t row, size_t column );
3807 
3808  template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
3809  friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
3810  size_t row, size_t column );
3811 
3812  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
3813  friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
3814  size_t row, size_t column );
3815 
3816  template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
3817  friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
3818  size_t row, size_t column );
3819 
3820  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
3821  friend bool tryMultAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
3822  size_t row, size_t column );
3823 
3824  template< typename MT2, bool AF2, bool SO2, bool DF2 >
3825  friend DerestrictTrait_< Submatrix<MT2,AF2,SO2,DF2> > derestrict( Submatrix<MT2,AF2,SO2,DF2>& sm );
3826  //**********************************************************************************************
3827 
3828  //**Compile time checks*************************************************************************
3836  //**********************************************************************************************
3837 };
3839 //*************************************************************************************************
3840 
3841 
3842 
3843 
3844 //=================================================================================================
3845 //
3846 // CONSTRUCTOR
3847 //
3848 //=================================================================================================
3849 
3850 //*************************************************************************************************
3864 template< typename MT > // Type of the dense matrix
3865 inline Submatrix<MT,unaligned,true,true>::Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n )
3866  : matrix_ ( matrix ) // The dense matrix containing the submatrix
3867  , row_ ( rindex ) // The first row of the submatrix
3868  , column_ ( cindex ) // The first column of the submatrix
3869  , m_ ( m ) // The number of rows of the submatrix
3870  , n_ ( n ) // The number of columns of the submatrix
3871  , isAligned_( simdEnabled && matrix.data() != nullptr && checkAlignment( data() ) &&
3872  ( n < 2UL || ( matrix.spacing() & size_t(-SIMDSIZE) ) == 0UL ) )
3873 {
3874  if( ( row_ + m_ > matrix_.rows() ) || ( column_ + n_ > matrix_.columns() ) ) {
3875  BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix specification" );
3876  }
3877 }
3879 //*************************************************************************************************
3880 
3881 
3882 
3883 
3884 //=================================================================================================
3885 //
3886 // DATA ACCESS FUNCTIONS
3887 //
3888 //=================================================================================================
3889 
3890 //*************************************************************************************************
3901 template< typename MT > // Type of the dense matrix
3903  Submatrix<MT,unaligned,true,true>::operator()( size_t i, size_t j )
3904 {
3905  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
3906  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
3907 
3908  return matrix_(row_+i,column_+j);
3909 }
3911 //*************************************************************************************************
3912 
3913 
3914 //*************************************************************************************************
3925 template< typename MT > // Type of the dense matrix
3927  Submatrix<MT,unaligned,true,true>::operator()( size_t i, size_t j ) const
3928 {
3929  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
3930  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
3931 
3932  return const_cast<const MT&>( matrix_ )(row_+i,column_+j);
3933 }
3935 //*************************************************************************************************
3936 
3937 
3938 //*************************************************************************************************
3950 template< typename MT > // Type of the dense matrix
3952  Submatrix<MT,unaligned,true,true>::at( size_t i, size_t j )
3953 {
3954  if( i >= rows() ) {
3955  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
3956  }
3957  if( j >= columns() ) {
3958  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
3959  }
3960  return (*this)(i,j);
3961 }
3963 //*************************************************************************************************
3964 
3965 
3966 //*************************************************************************************************
3978 template< typename MT > // Type of the dense matrix
3980  Submatrix<MT,unaligned,true,true>::at( size_t i, size_t j ) const
3981 {
3982  if( i >= rows() ) {
3983  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
3984  }
3985  if( j >= columns() ) {
3986  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
3987  }
3988  return (*this)(i,j);
3989 }
3991 //*************************************************************************************************
3992 
3993 
3994 //*************************************************************************************************
4004 template< typename MT > // Type of the dense matrix
4005 inline typename Submatrix<MT,unaligned,true,true>::Pointer
4006  Submatrix<MT,unaligned,true,true>::data() noexcept
4007 {
4008  return matrix_.data() + row_ + column_*spacing();
4009 }
4011 //*************************************************************************************************
4012 
4013 
4014 //*************************************************************************************************
4024 template< typename MT > // Type of the dense matrix
4025 inline typename Submatrix<MT,unaligned,true,true>::ConstPointer
4026  Submatrix<MT,unaligned,true,true>::data() const noexcept
4027 {
4028  return matrix_.data() + row_ + column_*spacing();
4029 }
4031 //*************************************************************************************************
4032 
4033 
4034 //*************************************************************************************************
4043 template< typename MT > // Type of the dense matrix
4044 inline typename Submatrix<MT,unaligned,true,true>::Pointer
4045  Submatrix<MT,unaligned,true,true>::data( size_t j ) noexcept
4046 {
4047  return matrix_.data() + row_ + (column_+j)*spacing();
4048 }
4050 //*************************************************************************************************
4051 
4052 
4053 //*************************************************************************************************
4062 template< typename MT > // Type of the dense matrix
4063 inline typename Submatrix<MT,unaligned,true,true>::ConstPointer
4064  Submatrix<MT,unaligned,true,true>::data( size_t j ) const noexcept
4065 {
4066  return matrix_.data() + row_ + (column_+j)*spacing();
4067 }
4069 //*************************************************************************************************
4070 
4071 
4072 //*************************************************************************************************
4079 template< typename MT > // Type of the dense matrix
4082 {
4083  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
4084  return Iterator( matrix_.begin( column_ + j ) + row_, isAligned_ );
4085 }
4087 //*************************************************************************************************
4088 
4089 
4090 //*************************************************************************************************
4097 template< typename MT > // Type of the dense matrix
4100 {
4101  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
4102  return ConstIterator( matrix_.cbegin( column_ + j ) + row_, isAligned_ );
4103 }
4105 //*************************************************************************************************
4106 
4107 
4108 //*************************************************************************************************
4115 template< typename MT > // Type of the dense matrix
4118 {
4119  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
4120  return ConstIterator( matrix_.cbegin( column_ + j ) + row_, isAligned_ );
4121 }
4123 //*************************************************************************************************
4124 
4125 
4126 //*************************************************************************************************
4133 template< typename MT > // Type of the dense matrix
4136 {
4137  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
4138  return Iterator( matrix_.begin( column_ + j ) + row_ + m_, isAligned_ );
4139 }
4141 //*************************************************************************************************
4142 
4143 
4144 //*************************************************************************************************
4151 template< typename MT > // Type of the dense matrix
4153  Submatrix<MT,unaligned,true,true>::end( size_t j ) const
4154 {
4155  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
4156  return ConstIterator( matrix_.cbegin( column_ + j ) + row_ + m_, isAligned_ );
4157 }
4159 //*************************************************************************************************
4160 
4161 
4162 //*************************************************************************************************
4169 template< typename MT > // Type of the dense matrix
4171  Submatrix<MT,unaligned,true,true>::cend( size_t j ) const
4172 {
4173  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
4174  return ConstIterator( matrix_.cbegin( column_ + j ) + row_ + m_, isAligned_ );
4175 }
4177 //*************************************************************************************************
4178 
4179 
4180 
4181 
4182 //=================================================================================================
4183 //
4184 // ASSIGNMENT OPERATORS
4185 //
4186 //=================================================================================================
4187 
4188 //*************************************************************************************************
4199 template< typename MT > // Type of the dense matrix
4200 inline Submatrix<MT,unaligned,true,true>&
4201  Submatrix<MT,unaligned,true,true>::operator=( const ElementType& rhs )
4202 {
4203  const size_t jend( column_ + n_ );
4204 
4205  for( size_t j=column_; j<jend; ++j )
4206  {
4207  const size_t ibegin( ( IsLower<MT>::value )
4208  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
4209  ?( max( j+1UL, row_ ) )
4210  :( max( j, row_ ) ) )
4211  :( row_ ) );
4212  const size_t iend ( ( IsUpper<MT>::value )
4213  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
4214  ?( min( j, row_+m_ ) )
4215  :( min( j+1UL, row_+m_ ) ) )
4216  :( row_+m_ ) );
4217 
4218  for( size_t i=ibegin; i<iend; ++i )
4219  matrix_(i,j) = rhs;
4220  }
4221 
4222  return *this;
4223 }
4225 //*************************************************************************************************
4226 
4227 
4228 //*************************************************************************************************
4241 template< typename MT > // Type of the dense matrix
4242 inline Submatrix<MT,unaligned,true,true>&
4243  Submatrix<MT,unaligned,true,true>::operator=( initializer_list< initializer_list<ElementType> > list )
4244 {
4245  if( list.size() != rows() || determineColumns( list ) > columns() ) {
4246  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to submatrix" );
4247  }
4248 
4249  size_t i( 0UL );
4250 
4251  for( const auto& rowList : list ) {
4252  size_t j( 0UL );
4253  for( const auto& element : rowList ) {
4254  matrix_(row_+i,column_+j) = element;
4255  ++j;
4256  }
4257  for( ; j<n_; ++j ) {
4258  matrix_(row_+i,column_+j) = ElementType();
4259  }
4260  ++i;
4261  }
4262 
4263  return *this;
4264 }
4266 //*************************************************************************************************
4267 
4268 
4269 //*************************************************************************************************
4284 template< typename MT > // Type of the dense matrix
4285 inline Submatrix<MT,unaligned,true,true>&
4286  Submatrix<MT,unaligned,true,true>::operator=( const Submatrix& rhs )
4287 {
4290 
4291  if( this == &rhs || ( &matrix_ == &rhs.matrix_ && row_ == rhs.row_ && column_ == rhs.column_ ) )
4292  return *this;
4293 
4294  if( rows() != rhs.rows() || columns() != rhs.columns() ) {
4295  BLAZE_THROW_INVALID_ARGUMENT( "Submatrix sizes do not match" );
4296  }
4297 
4298  if( !tryAssign( matrix_, rhs, row_, column_ ) ) {
4299  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4300  }
4301 
4302  DerestrictTrait_<This> left( derestrict( *this ) );
4303 
4304  if( rhs.canAlias( &matrix_ ) ) {
4305  const ResultType tmp( rhs );
4306  smpAssign( left, tmp );
4307  }
4308  else {
4309  smpAssign( left, rhs );
4310  }
4311 
4312  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4313 
4314  return *this;
4315 }
4317 //*************************************************************************************************
4318 
4319 
4320 //*************************************************************************************************
4335 template< typename MT > // Type of the dense matrix
4336 template< typename MT2 // Type of the right-hand side matrix
4337  , bool SO > // Storage order of the right-hand side matrix
4338 inline Submatrix<MT,unaligned,true,true>&
4339  Submatrix<MT,unaligned,true,true>::operator=( const Matrix<MT2,SO>& rhs )
4340 {
4342 
4343  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
4344  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4345  }
4346 
4347  typedef If_< IsRestricted<MT>, CompositeType_<MT2>, const MT2& > Right;
4348  Right right( ~rhs );
4349 
4350  if( !tryAssign( matrix_, right, row_, column_ ) ) {
4351  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4352  }
4353 
4354  if( IsSparseMatrix<MT2>::value )
4355  reset();
4356 
4357  DerestrictTrait_<This> left( derestrict( *this ) );
4358 
4359  if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
4360  const ResultType_<MT2> tmp( right );
4361  smpAssign( left, tmp );
4362  }
4363  else {
4364  smpAssign( left, right );
4365  }
4366 
4367  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4368 
4369  return *this;
4370 }
4372 //*************************************************************************************************
4373 
4374 
4375 //*************************************************************************************************
4389 template< typename MT > // Type of the dense matrix
4390 template< typename MT2 // Type of the right-hand side matrix
4391  , bool SO > // Storage order of the right-hand side matrix
4392 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,true,true>& >
4393  Submatrix<MT,unaligned,true,true>::operator+=( const Matrix<MT2,SO>& rhs )
4394 {
4398 
4399  typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
4400 
4403 
4404  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
4405  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4406  }
4407 
4408  if( !tryAddAssign( matrix_, ~rhs, row_, column_ ) ) {
4409  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4410  }
4411 
4412  DerestrictTrait_<This> left( derestrict( *this ) );
4413 
4414  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
4415  (~rhs).canAlias( &matrix_ ) ) {
4416  const AddType tmp( *this + (~rhs) );
4417  smpAssign( left, tmp );
4418  }
4419  else {
4420  smpAddAssign( left, ~rhs );
4421  }
4422 
4423  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4424 
4425  return *this;
4426 }
4428 //*************************************************************************************************
4429 
4430 
4431 //*************************************************************************************************
4445 template< typename MT > // Type of the dense matrix
4446 template< typename MT2 // Type of the right-hand side matrix
4447  , bool SO > // Storage order of the right-hand side matrix
4448 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,true,true>& >
4449  Submatrix<MT,unaligned,true,true>::operator+=( const Matrix<MT2,SO>& rhs )
4450 {
4454 
4455  typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
4456 
4459 
4460  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
4461  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4462  }
4463 
4464  const AddType tmp( *this + (~rhs) );
4465 
4466  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
4467  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4468  }
4469 
4470  DerestrictTrait_<This> left( derestrict( *this ) );
4471 
4472  smpAssign( left, tmp );
4473 
4474  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4475 
4476  return *this;
4477 }
4479 //*************************************************************************************************
4480 
4481 
4482 //*************************************************************************************************
4496 template< typename MT > // Type of the dense matrix
4497 template< typename MT2 // Type of the right-hand side matrix
4498  , bool SO > // Storage order of the right-hand side matrix
4499 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,true,true>& >
4500  Submatrix<MT,unaligned,true,true>::operator-=( const Matrix<MT2,SO>& rhs )
4501 {
4505 
4506  typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
4507 
4510 
4511  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
4512  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4513  }
4514 
4515  if( !trySubAssign( matrix_, ~rhs, row_, column_ ) ) {
4516  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4517  }
4518 
4519  DerestrictTrait_<This> left( derestrict( *this ) );
4520 
4521  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
4522  (~rhs).canAlias( &matrix_ ) ) {
4523  const SubType tmp( *this - (~rhs ) );
4524  smpAssign( left, tmp );
4525  }
4526  else {
4527  smpSubAssign( left, ~rhs );
4528  }
4529 
4530  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4531 
4532  return *this;
4533 }
4535 //*************************************************************************************************
4536 
4537 
4538 //*************************************************************************************************
4552 template< typename MT > // Type of the dense matrix
4553 template< typename MT2 // Type of the right-hand side matrix
4554  , bool SO > // Storage order of the right-hand side matrix
4555 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,true,true>& >
4556  Submatrix<MT,unaligned,true,true>::operator-=( const Matrix<MT2,SO>& rhs )
4557 {
4561 
4562  typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
4563 
4566 
4567  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
4568  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4569  }
4570 
4571  const SubType tmp( *this - (~rhs) );
4572 
4573  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
4574  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4575  }
4576 
4577  DerestrictTrait_<This> left( derestrict( *this ) );
4578 
4579  smpAssign( left, tmp );
4580 
4581  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4582 
4583  return *this;
4584 }
4586 //*************************************************************************************************
4587 
4588 
4589 //*************************************************************************************************
4603 template< typename MT > // Type of the dense matrix
4604 template< typename MT2 // Type of the right-hand side matrix
4605  , bool SO > // Storage order of the right-hand side matrix
4606 inline Submatrix<MT,unaligned,true,true>&
4607  Submatrix<MT,unaligned,true,true>::operator*=( const Matrix<MT2,SO>& rhs )
4608 {
4612 
4613  typedef MultTrait_< ResultType, ResultType_<MT2> > MultType;
4614 
4617 
4618  if( columns() != (~rhs).rows() ) {
4619  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4620  }
4621 
4622  const MultType tmp( *this * (~rhs) );
4623 
4624  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
4625  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4626  }
4627 
4628  DerestrictTrait_<This> left( derestrict( *this ) );
4629 
4630  smpAssign( left, tmp );
4631 
4632  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4633 
4634  return *this;
4635 }
4637 //*************************************************************************************************
4638 
4639 
4640 //*************************************************************************************************
4651 template< typename MT > // Type of the dense matrix
4652 template< typename Other > // Data type of the right-hand side scalar
4653 inline EnableIf_< IsNumeric<Other>, Submatrix<MT,unaligned,true,true> >&
4655 {
4657 
4658  DerestrictTrait_<This> left( derestrict( *this ) );
4659  smpAssign( left, (*this) * rhs );
4660 
4661  return *this;
4662 }
4664 //*************************************************************************************************
4665 
4666 
4667 //*************************************************************************************************
4680 template< typename MT > // Type of the dense matrix
4681 template< typename Other > // Data type of the right-hand side scalar
4682 inline EnableIf_< IsNumeric<Other>, Submatrix<MT,unaligned,true,true> >&
4684 {
4686 
4687  BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
4688 
4689  DerestrictTrait_<This> left( derestrict( *this ) );
4690  smpAssign( left, (*this) / rhs );
4691 
4692  return *this;
4693 }
4695 //*************************************************************************************************
4696 
4697 
4698 
4699 
4700 //=================================================================================================
4701 //
4702 // UTILITY FUNCTIONS
4703 //
4704 //=================================================================================================
4705 
4706 //*************************************************************************************************
4712 template< typename MT > // Type of the dense matrix
4713 inline size_t Submatrix<MT,unaligned,true,true>::row() const noexcept
4714 {
4715  return row_;
4716 }
4718 //*************************************************************************************************
4719 
4720 
4721 //*************************************************************************************************
4727 template< typename MT > // Type of the dense matrix
4728 inline size_t Submatrix<MT,unaligned,true,true>::rows() const noexcept
4729 {
4730  return m_;
4731 }
4733 //*************************************************************************************************
4734 
4735 
4736 //*************************************************************************************************
4742 template< typename MT > // Type of the dense matrix
4743 inline size_t Submatrix<MT,unaligned,true,true>::column() const noexcept
4744 {
4745  return column_;
4746 }
4748 //*************************************************************************************************
4749 
4750 
4751 //*************************************************************************************************
4757 template< typename MT > // Type of the dense matrix
4758 inline size_t Submatrix<MT,unaligned,true,true>::columns() const noexcept
4759 {
4760  return n_;
4761 }
4763 //*************************************************************************************************
4764 
4765 
4766 //*************************************************************************************************
4775 template< typename MT > // Type of the dense matrix
4776 inline size_t Submatrix<MT,unaligned,true,true>::spacing() const noexcept
4777 {
4778  return matrix_.spacing();
4779 }
4781 //*************************************************************************************************
4782 
4783 
4784 //*************************************************************************************************
4790 template< typename MT > // Type of the dense matrix
4791 inline size_t Submatrix<MT,unaligned,true,true>::capacity() const noexcept
4792 {
4793  return rows() * columns();
4794 }
4796 //*************************************************************************************************
4797 
4798 
4799 //*************************************************************************************************
4806 template< typename MT > // Type of the dense matrix
4807 inline size_t Submatrix<MT,unaligned,true,true>::capacity( size_t j ) const noexcept
4808 {
4809  UNUSED_PARAMETER( j );
4810 
4811  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
4812 
4813  return rows();
4814 }
4816 //*************************************************************************************************
4817 
4818 
4819 //*************************************************************************************************
4825 template< typename MT > // Type of the dense matrix
4826 inline size_t Submatrix<MT,unaligned,true,true>::nonZeros() const
4827 {
4828  const size_t iend( row_ + m_ );
4829  const size_t jend( column_ + n_ );
4830  size_t nonzeros( 0UL );
4831 
4832  for( size_t j=column_; j<jend; ++j )
4833  for( size_t i=row_; i<iend; ++i )
4834  if( !isDefault( matrix_(i,j) ) )
4835  ++nonzeros;
4836 
4837  return nonzeros;
4838 }
4840 //*************************************************************************************************
4841 
4842 
4843 //*************************************************************************************************
4850 template< typename MT > // Type of the dense matrix
4851 inline size_t Submatrix<MT,unaligned,true,true>::nonZeros( size_t j ) const
4852 {
4853  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
4854 
4855  const size_t iend( row_ + m_ );
4856  size_t nonzeros( 0UL );
4857 
4858  for( size_t i=row_; i<iend; ++i )
4859  if( !isDefault( matrix_(i,column_+j) ) )
4860  ++nonzeros;
4861 
4862  return nonzeros;
4863 }
4865 //*************************************************************************************************
4866 
4867 
4868 //*************************************************************************************************
4874 template< typename MT > // Type of the dense matrix
4876 {
4877  using blaze::clear;
4878 
4879  for( size_t j=column_; j<column_+n_; ++j )
4880  {
4881  const size_t ibegin( ( IsLower<MT>::value )
4882  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
4883  ?( max( j+1UL, row_ ) )
4884  :( max( j, row_ ) ) )
4885  :( row_ ) );
4886  const size_t iend ( ( IsUpper<MT>::value )
4887  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
4888  ?( min( j, row_+m_ ) )
4889  :( min( j+1UL, row_+m_ ) ) )
4890  :( row_+m_ ) );
4891 
4892  for( size_t i=ibegin; i<iend; ++i )
4893  clear( matrix_(i,j) );
4894  }
4895 }
4897 //*************************************************************************************************
4898 
4899 
4900 //*************************************************************************************************
4907 template< typename MT > // Type of the dense matrix
4908 inline void Submatrix<MT,unaligned,true,true>::reset( size_t j )
4909 {
4910  using blaze::clear;
4911 
4912  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
4913 
4914  const size_t ibegin( ( IsLower<MT>::value )
4915  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
4916  ?( max( j+1UL, row_ ) )
4917  :( max( j, row_ ) ) )
4918  :( row_ ) );
4919  const size_t iend ( ( IsUpper<MT>::value )
4920  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
4921  ?( min( j, row_+m_ ) )
4922  :( min( j+1UL, row_+m_ ) ) )
4923  :( row_+m_ ) );
4924 
4925  for( size_t i=ibegin; i<iend; ++i )
4926  clear( matrix_(i,column_+j) );
4927 }
4929 //*************************************************************************************************
4930 
4931 
4932 //*************************************************************************************************
4950 template< typename MT > // Type of the dense matrix
4951 inline Submatrix<MT,unaligned,true,true>& Submatrix<MT,unaligned,true,true>::transpose()
4952 {
4953  if( m_ != n_ ) {
4954  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
4955  }
4956 
4957  if( !tryAssign( matrix_, trans( *this ), row_, column_ ) ) {
4958  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
4959  }
4960 
4961  DerestrictTrait_<This> left( derestrict( *this ) );
4962  const ResultType tmp( trans( *this ) );
4963  smpAssign( left, tmp );
4964 
4965  return *this;
4966 }
4968 //*************************************************************************************************
4969 
4970 
4971 //*************************************************************************************************
4989 template< typename MT > // Type of the dense matrix
4990 inline Submatrix<MT,unaligned,true,true>& Submatrix<MT,unaligned,true,true>::ctranspose()
4991 {
4992  if( m_ != n_ ) {
4993  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
4994  }
4995 
4996  if( !tryAssign( matrix_, ctrans( *this ), row_, column_ ) ) {
4997  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
4998  }
4999 
5000  DerestrictTrait_<This> left( derestrict( *this ) );
5001  const ResultType tmp( ctrans( *this ) );
5002  smpAssign( left, tmp );
5003 
5004  return *this;
5005 }
5007 //*************************************************************************************************
5008 
5009 
5010 //*************************************************************************************************
5021 template< typename MT > // Type of the dense matrix
5022 template< typename Other > // Data type of the scalar value
5023 inline Submatrix<MT,unaligned,true,true>& Submatrix<MT,unaligned,true,true>::scale( const Other& scalar )
5024 {
5026 
5027  const size_t jend( column_ + n_ );
5028 
5029  for( size_t j=column_; j<jend; ++j )
5030  {
5031  const size_t ibegin( ( IsLower<MT>::value )
5032  ?( ( IsStrictlyLower<MT>::value )
5033  ?( max( j+1UL, row_ ) )
5034  :( max( j, row_ ) ) )
5035  :( row_ ) );
5036  const size_t iend ( ( IsUpper<MT>::value )
5037  ?( ( IsStrictlyUpper<MT>::value )
5038  ?( min( j, row_+m_ ) )
5039  :( min( j+1UL, row_+m_ ) ) )
5040  :( row_+m_ ) );
5041 
5042  for( size_t i=ibegin; i<iend; ++i )
5043  matrix_(i,j) *= scalar;
5044  }
5045 
5046  return *this;
5047 }
5049 //*************************************************************************************************
5050 
5051 
5052 //*************************************************************************************************
5062 template< typename MT > // Type of the dense matrix
5063 inline bool Submatrix<MT,unaligned,true,true>::hasOverlap() const noexcept
5064 {
5065  BLAZE_INTERNAL_ASSERT( IsSymmetric<MT>::value || IsHermitian<MT>::value, "Invalid matrix detected" );
5066 
5067  if( ( row_ + m_ <= column_ ) || ( column_ + n_ <= row_ ) )
5068  return false;
5069  else return true;
5070 }
5072 //*************************************************************************************************
5073 
5074 
5075 
5076 
5077 //=================================================================================================
5078 //
5079 // EXPRESSION TEMPLATE EVALUATION FUNCTIONS
5080 //
5081 //=================================================================================================
5082 
5083 //*************************************************************************************************
5094 template< typename MT > // Type of the dense matrix
5095 template< typename Other > // Data type of the foreign expression
5096 inline bool Submatrix<MT,unaligned,true,true>::canAlias( const Other* alias ) const noexcept
5097 {
5098  return matrix_.isAliased( alias );
5099 }
5101 //*************************************************************************************************
5102 
5103 
5104 //*************************************************************************************************
5115 template< typename MT > // Type of the dense matrix
5116 template< typename MT2 // Data type of the foreign dense submatrix
5117  , bool AF2 // Alignment flag of the foreign dense submatrix
5118  , bool SO2 > // Storage order of the foreign dense submatrix
5119 inline bool Submatrix<MT,unaligned,true,true>::canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
5120 {
5121  return ( matrix_.isAliased( &alias->matrix_ ) &&
5122  ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
5123  ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
5124 }
5126 //*************************************************************************************************
5127 
5128 
5129 //*************************************************************************************************
5140 template< typename MT > // Type of the dense matrix
5141 template< typename Other > // Data type of the foreign expression
5142 inline bool Submatrix<MT,unaligned,true,true>::isAliased( const Other* alias ) const noexcept
5143 {
5144  return matrix_.isAliased( alias );
5145 }
5147 //*************************************************************************************************
5148 
5149 
5150 //*************************************************************************************************
5161 template< typename MT > // Type of the dense matrix
5162 template< typename MT2 // Data type of the foreign dense submatrix
5163  , bool AF2 // Alignment flag of the foreign dense submatrix
5164  , bool SO2 > // Storage order of the foreign dense submatrix
5165 inline bool Submatrix<MT,unaligned,true,true>::isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
5166 {
5167  return ( matrix_.isAliased( &alias->matrix_ ) &&
5168  ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
5169  ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
5170 }
5172 //*************************************************************************************************
5173 
5174 
5175 //*************************************************************************************************
5185 template< typename MT > // Type of the dense matrix
5186 inline bool Submatrix<MT,unaligned,true,true>::isAligned() const noexcept
5187 {
5188  return isAligned_;
5189 }
5191 //*************************************************************************************************
5192 
5193 
5194 //*************************************************************************************************
5205 template< typename MT > // Type of the dense matrix
5206 inline bool Submatrix<MT,unaligned,true,true>::canSMPAssign() const noexcept
5207 {
5208  return ( rows() * columns() >= SMP_DMATASSIGN_THRESHOLD );
5209 }
5211 //*************************************************************************************************
5212 
5213 
5214 //*************************************************************************************************
5229 template< typename MT > // Type of the dense matrix
5230 BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,true,true>::SIMDType
5231  Submatrix<MT,unaligned,true,true>::load( size_t i, size_t j ) const noexcept
5232 {
5233  if( isAligned_ )
5234  return loada( i, j );
5235  else
5236  return loadu( i, j );
5237 }
5239 //*************************************************************************************************
5240 
5241 
5242 //*************************************************************************************************
5257 template< typename MT > // Type of the dense matrix
5258 BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,true,true>::SIMDType
5259  Submatrix<MT,unaligned,true,true>::loada( size_t i, size_t j ) const noexcept
5260 {
5262 
5263  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
5264  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
5265  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
5266  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
5267 
5268  return matrix_.loada( row_+i, column_+j );
5269 }
5271 //*************************************************************************************************
5272 
5273 
5274 //*************************************************************************************************
5289 template< typename MT > // Type of the dense matrix
5290 BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,true,true>::SIMDType
5291  Submatrix<MT,unaligned,true,true>::loadu( size_t i, size_t j ) const noexcept
5292 {
5294 
5295  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
5296  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
5297  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
5298  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
5299 
5300  return matrix_.loadu( row_+i, column_+j );
5301 }
5303 //*************************************************************************************************
5304 
5305 
5306 //*************************************************************************************************
5322 template< typename MT > // Type of the dense matrix
5324  Submatrix<MT,unaligned,true,true>::store( size_t i, size_t j, const SIMDType& value ) noexcept
5325 {
5326  if( isAligned_ )
5327  storea( i, j, value );
5328  else
5329  storeu( i, j, value );
5330 }
5332 //*************************************************************************************************
5333 
5334 
5335 //*************************************************************************************************
5351 template< typename MT > // Type of the dense matrix
5353  Submatrix<MT,unaligned,true,true>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
5354 {
5356 
5357  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
5358  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
5359  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
5360  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
5361 
5362  matrix_.storea( row_+i, column_+j, value );
5363 }
5365 //*************************************************************************************************
5366 
5367 
5368 //*************************************************************************************************
5384 template< typename MT > // Type of the dense matrix
5386  Submatrix<MT,unaligned,true,true>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
5387 {
5389 
5390  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
5391  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
5392  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
5393  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
5394 
5395  matrix_.storeu( row_+i, column_+j, value );
5396 }
5398 //*************************************************************************************************
5399 
5400 
5401 //*************************************************************************************************
5418 template< typename MT > // Type of the dense matrix
5420  Submatrix<MT,unaligned,true,true>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
5421 {
5423 
5424  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
5425  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
5426  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
5427  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
5428 
5429  if( isAligned_ )
5430  matrix_.stream( row_+i, column_+j, value );
5431  else
5432  matrix_.storeu( row_+i, column_+j, value );
5433 }
5435 //*************************************************************************************************
5436 
5437 
5438 //*************************************************************************************************
5450 template< typename MT > // Type of the dense matrix
5451 template< typename MT2 > // Type of the right-hand side dense matrix
5452 inline DisableIf_< typename Submatrix<MT,unaligned,true,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
5453  Submatrix<MT,unaligned,true,true>::assign( const DenseMatrix<MT2,true>& rhs )
5454 {
5455  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5456  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5457 
5458  const size_t ipos( m_ & size_t(-2) );
5459  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
5460 
5461  for( size_t j=0UL; j<n_; ++j ) {
5462  for( size_t i=0UL; i<ipos; i+=2UL ) {
5463  matrix_(row_+i ,column_+j) = (~rhs)(i ,j);
5464  matrix_(row_+i+1UL,column_+j) = (~rhs)(i+1UL,j);
5465  }
5466  if( ipos < m_ ) {
5467  matrix_(row_+ipos,column_+j) = (~rhs)(ipos,j);
5468  }
5469  }
5470 }
5472 //*************************************************************************************************
5473 
5474 
5475 //*************************************************************************************************
5487 template< typename MT > // Type of the dense matrix
5488 template< typename MT2 > // Type of the right-hand side dense matrix
5489 inline EnableIf_< typename Submatrix<MT,unaligned,true,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
5490  Submatrix<MT,unaligned,true,true>::assign( const DenseMatrix<MT2,true>& rhs )
5491 {
5493 
5494  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5495  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5496 
5497  const size_t ipos( m_ & size_t(-SIMDSIZE) );
5498  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
5499 
5500  if( useStreaming && isAligned_ &&
5501  m_*n_ > ( cacheSize / ( sizeof(ElementType) * 3UL ) ) &&
5502  !(~rhs).isAliased( &matrix_ ) )
5503  {
5504  for( size_t j=0UL; j<n_; ++j )
5505  {
5506  size_t i( 0UL );
5507  Iterator left( begin(j) );
5508  ConstIterator_<MT2> right( (~rhs).begin(j) );
5509 
5510  for( ; i<ipos; i+=SIMDSIZE ) {
5511  left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5512  }
5513  for( ; i<m_; ++i ) {
5514  *left = *right; ++left; ++right;
5515  }
5516  }
5517  }
5518  else
5519  {
5520  for( size_t j=0UL; j<n_; ++j )
5521  {
5522  size_t i( 0UL );
5523  Iterator left( begin(j) );
5524  ConstIterator_<MT2> right( (~rhs).begin(j) );
5525 
5526  for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
5527  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5528  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5529  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5530  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5531  }
5532  for( ; i<ipos; i+=SIMDSIZE ) {
5533  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5534  }
5535  for( ; i<m_; ++i ) {
5536  *left = *right; ++left; ++right;
5537  }
5538  }
5539  }
5540 }
5542 //*************************************************************************************************
5543 
5544 
5545 //*************************************************************************************************
5557 template< typename MT > // Type of the dense matrix
5558 template< typename MT2 > // Type of the right-hand side dense matrix
5559 inline void Submatrix<MT,unaligned,true,true>::assign( const DenseMatrix<MT2,false>& rhs )
5560 {
5562 
5563  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5564  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5565 
5566  const size_t block( BLOCK_SIZE );
5567 
5568  for( size_t jj=0UL; jj<n_; jj+=block ) {
5569  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
5570  for( size_t ii=0UL; ii<m_; ii+=block ) {
5571  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
5572  for( size_t j=jj; j<jend; ++j ) {
5573  for( size_t i=ii; i<iend; ++i ) {
5574  matrix_(row_+i,column_+j) = (~rhs)(i,j);
5575  }
5576  }
5577  }
5578  }
5579 }
5581 //*************************************************************************************************
5582 
5583 
5584 //*************************************************************************************************
5596 template< typename MT > // Type of the dense matrix
5597 template< typename MT2 > // Type of the right-hand side sparse matrix
5598 inline void Submatrix<MT,unaligned,true,true>::assign( const SparseMatrix<MT2,true>& rhs )
5599 {
5600  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5601  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5602 
5603  for( size_t j=0UL; j<n_; ++j )
5604  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
5605  matrix_(row_+element->index(),column_+j) = element->value();
5606 }
5608 //*************************************************************************************************
5609 
5610 
5611 //*************************************************************************************************
5623 template< typename MT > // Type of the dense matrix
5624 template< typename MT2 > // Type of the right-hand side sparse matrix
5625 inline void Submatrix<MT,unaligned,true,true>::assign( const SparseMatrix<MT2,false>& rhs )
5626 {
5628 
5629  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5630  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5631 
5632  for( size_t i=0UL; i<m_; ++i )
5633  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
5634  matrix_(row_+i,column_+element->index()) = element->value();
5635 }
5637 //*************************************************************************************************
5638 
5639 
5640 //*************************************************************************************************
5652 template< typename MT > // Type of the dense matrix
5653 template< typename MT2 > // Type of the right-hand side dense matrix
5654 inline DisableIf_< typename Submatrix<MT,unaligned,true,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
5655  Submatrix<MT,unaligned,true,true>::addAssign( const DenseMatrix<MT2,true>& rhs )
5656 {
5657  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5658  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5659 
5660  const size_t ipos( m_ & size_t(-2) );
5661  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
5662 
5663  for( size_t j=0UL; j<n_; ++j )
5664  {
5665  if( IsDiagonal<MT2>::value ) {
5666  matrix_(row_+j,column_+j) += (~rhs)(j,j);
5667  }
5668  else {
5669  for( size_t i=0UL; i<ipos; i+=2UL ) {
5670  matrix_(row_+i ,column_+j) += (~rhs)(i ,j);
5671  matrix_(row_+i+1UL,column_+j) += (~rhs)(i+1UL,j);
5672  }
5673  if( ipos < m_ ) {
5674  matrix_(row_+ipos,column_+j) += (~rhs)(ipos,j);
5675  }
5676  }
5677  }
5678 }
5680 //*************************************************************************************************
5681 
5682 
5683 //*************************************************************************************************
5695 template< typename MT > // Type of the dense matrix
5696 template< typename MT2 > // Type of the right-hand side dense matrix
5697 inline EnableIf_< typename Submatrix<MT,unaligned,true,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
5698  Submatrix<MT,unaligned,true,true>::addAssign( const DenseMatrix<MT2,true>& rhs )
5699 {
5701 
5702  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5703  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5704 
5705  for( size_t j=0UL; j<n_; ++j )
5706  {
5707  const size_t ibegin( ( IsLower<MT>::value )
5708  ?( ( IsStrictlyLower<MT>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
5709  :( 0UL ) );
5710  const size_t iend ( ( IsUpper<MT>::value )
5711  ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
5712  :( m_ ) );
5713  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
5714 
5715  const size_t ipos( iend & size_t(-SIMDSIZE) );
5716  BLAZE_INTERNAL_ASSERT( ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
5717 
5718  size_t i( ibegin );
5719  Iterator left( begin(j) + ibegin );
5720  ConstIterator_<MT2> right( (~rhs).begin(j) + ibegin );
5721 
5722  for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
5723  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5724  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5725  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5726  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5727  }
5728  for( ; i<ipos; i+=SIMDSIZE ) {
5729  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5730  }
5731  for( ; i<iend; ++i ) {
5732  *left += *right; ++left; ++right;
5733  }
5734  }
5735 }
5737 //*************************************************************************************************
5738 
5739 
5740 //*************************************************************************************************
5752 template< typename MT > // Type of the dense matrix
5753 template< typename MT2 > // Type of the right-hand side dense matrix
5754 inline void Submatrix<MT,unaligned,true,true>::addAssign( const DenseMatrix<MT2,false>& rhs )
5755 {
5757 
5758  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5759  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5760 
5761  const size_t block( BLOCK_SIZE );
5762 
5763  for( size_t jj=0UL; jj<n_; jj+=block ) {
5764  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
5765  for( size_t ii=0UL; ii<m_; ii+=block ) {
5766  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
5767  for( size_t j=jj; j<jend; ++j ) {
5768  for( size_t i=ii; i<iend; ++i ) {
5769  matrix_(row_+i,column_+j) += (~rhs)(i,j);
5770  }
5771  }
5772  }
5773  }
5774 }
5776 //*************************************************************************************************
5777 
5778 
5779 //*************************************************************************************************
5791 template< typename MT > // Type of the dense matrix
5792 template< typename MT2 > // Type of the right-hand side sparse matrix
5793 inline void Submatrix<MT,unaligned,true,true>::addAssign( const SparseMatrix<MT2,true>& rhs )
5794 {
5795  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5796  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5797 
5798  for( size_t j=0UL; j<n_; ++j )
5799  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
5800  matrix_(row_+element->index(),column_+j) += element->value();
5801 }
5803 //*************************************************************************************************
5804 
5805 
5806 //*************************************************************************************************
5818 template< typename MT > // Type of the dense matrix
5819 template< typename MT2 > // Type of the right-hand side sparse matrix
5820 inline void Submatrix<MT,unaligned,true,true>::addAssign( const SparseMatrix<MT2,false>& rhs )
5821 {
5823 
5824  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5825  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5826 
5827  for( size_t i=0UL; i<m_; ++i )
5828  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
5829  matrix_(row_+i,column_+element->index()) += element->value();
5830 }
5832 //*************************************************************************************************
5833 
5834 
5835 //*************************************************************************************************
5847 template< typename MT > // Type of the dense matrix
5848 template< typename MT2 > // Type of the right-hand side dense matrix
5849 inline DisableIf_< typename Submatrix<MT,unaligned,true,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
5850  Submatrix<MT,unaligned,true,true>::subAssign( const DenseMatrix<MT2,true>& rhs )
5851 {
5852  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5853  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5854 
5855  const size_t ipos( m_ & size_t(-2) );
5856  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
5857 
5858  for( size_t j=0UL; j<n_; ++j )
5859  {
5860  if( IsDiagonal<MT2>::value ) {
5861  matrix_(row_+j,column_+j) -= (~rhs)(j,j);
5862  }
5863  else {
5864  for( size_t i=0UL; i<ipos; i+=2UL ) {
5865  matrix_(row_+i ,column_+j) -= (~rhs)(i ,j);
5866  matrix_(row_+i+1UL,column_+j) -= (~rhs)(i+1UL,j);
5867  }
5868  if( ipos < m_ ) {
5869  matrix_(row_+ipos,column_+j) -= (~rhs)(ipos,j);
5870  }
5871  }
5872  }
5873 }
5875 //*************************************************************************************************
5876 
5877 
5878 //*************************************************************************************************
5890 template< typename MT > // Type of the dense matrix
5891 template< typename MT2 > // Type of the right-hand side dense matrix
5892 inline EnableIf_< typename Submatrix<MT,unaligned,true,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
5893  Submatrix<MT,unaligned,true,true>::subAssign( const DenseMatrix<MT2,true>& rhs )
5894 {
5896 
5897  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5898  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5899 
5900  for( size_t j=0UL; j<n_; ++j )
5901  {
5902  const size_t ibegin( ( IsLower<MT>::value )
5903  ?( ( IsStrictlyLower<MT>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
5904  :( 0UL ) );
5905  const size_t iend ( ( IsUpper<MT>::value )
5906  ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
5907  :( m_ ) );
5908  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
5909 
5910  const size_t ipos( iend & size_t(-SIMDSIZE) );
5911  BLAZE_INTERNAL_ASSERT( ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
5912 
5913  size_t i( ibegin );
5914  Iterator left( begin(j) + ibegin );
5915  ConstIterator_<MT2> right( (~rhs).begin(j) + ibegin );
5916 
5917  for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
5918  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5919  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5920  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5921  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5922  }
5923  for( ; i<ipos; i+=SIMDSIZE ) {
5924  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5925  }
5926  for( ; i<iend; ++i ) {
5927  *left -= *right; ++left; ++right;
5928  }
5929  }
5930 }
5932 //*************************************************************************************************
5933 
5934 
5935 //*************************************************************************************************
5947 template< typename MT > // Type of the dense matrix
5948 template< typename MT2 > // Type of the right-hand side dense matrix
5949 inline void Submatrix<MT,unaligned,true,true>::subAssign( const DenseMatrix<MT2,false>& rhs )
5950 {
5952 
5953  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5954  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5955 
5956  const size_t block( BLOCK_SIZE );
5957 
5958  for( size_t jj=0UL; jj<n_; jj+=block ) {
5959  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
5960  for( size_t ii=0UL; ii<m_; ii+=block ) {
5961  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
5962  for( size_t j=jj; j<jend; ++j ) {
5963  for( size_t i=ii; i<iend; ++i ) {
5964  matrix_(row_+i,column_+j) -= (~rhs)(i,j);
5965  }
5966  }
5967  }
5968  }
5969 }
5971 //*************************************************************************************************
5972 
5973 
5974 //*************************************************************************************************
5986 template< typename MT > // Type of the dense matrix
5987 template< typename MT2 > // Type of the right-hand side sparse matrix
5988 inline void Submatrix<MT,unaligned,true,true>::subAssign( const SparseMatrix<MT2,true>& rhs )
5989 {
5990  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5991  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5992 
5993  for( size_t j=0UL; j<n_; ++j )
5994  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
5995  matrix_(row_+element->index(),column_+j) -= element->value();
5996 }
5998 //*************************************************************************************************
5999 
6000 
6001 //*************************************************************************************************
6013 template< typename MT > // Type of the dense matrix
6014 template< typename MT2 > // Type of the right-hand side sparse matrix
6015 inline void Submatrix<MT,unaligned,true,true>::subAssign( const SparseMatrix<MT2,false>& rhs )
6016 {
6018 
6019  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
6020  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
6021 
6022  for( size_t i=0UL; i<m_; ++i )
6023  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
6024  matrix_(row_+i,column_+element->index()) -= element->value();
6025 }
6027 //*************************************************************************************************
6028 
6029 
6030 
6031 
6032 
6033 
6034 
6035 
6036 //=================================================================================================
6037 //
6038 // CLASS TEMPLATE SPECIALIZATION FOR ALIGNED ROW-MAJOR DENSE SUBMATRICES
6039 //
6040 //=================================================================================================
6041 
6042 //*************************************************************************************************
6050 template< typename MT > // Type of the dense matrix
6051 class Submatrix<MT,aligned,false,true>
6052  : public DenseMatrix< Submatrix<MT,aligned,false,true>, false >
6053  , private View
6054 {
6055  private:
6056  //**Type definitions****************************************************************************
6058  typedef If_< IsExpression<MT>, MT, MT& > Operand;
6059  //**********************************************************************************************
6060 
6061  public:
6062  //**Type definitions****************************************************************************
6063  typedef Submatrix<MT,aligned,false,true> This;
6064  typedef DenseMatrix<This,false> BaseType;
6065  typedef SubmatrixTrait_<MT> ResultType;
6066  typedef OppositeType_<ResultType> OppositeType;
6067  typedef TransposeType_<ResultType> TransposeType;
6068  typedef ElementType_<MT> ElementType;
6069  typedef SIMDTrait_<ElementType> SIMDType;
6070  typedef ReturnType_<MT> ReturnType;
6071  typedef const Submatrix& CompositeType;
6072 
6074  typedef ConstReference_<MT> ConstReference;
6075 
6077  typedef If_< IsConst<MT>, ConstReference, Reference_<MT> > Reference;
6078 
6080  typedef const ElementType* ConstPointer;
6081 
6083  typedef If_< Or< IsConst<MT>, Not< HasMutableDataAccess<MT> > >, ConstPointer, ElementType* > Pointer;
6084 
6086  typedef ConstIterator_<MT> ConstIterator;
6087 
6089  typedef If_< IsConst<MT>, ConstIterator, Iterator_<MT> > Iterator;
6090  //**********************************************************************************************
6091 
6092  //**Compilation flags***************************************************************************
6094  enum : bool { simdEnabled = MT::simdEnabled };
6095 
6097  enum : bool { smpAssignable = MT::smpAssignable };
6098  //**********************************************************************************************
6099 
6100  //**Constructors********************************************************************************
6103  explicit inline Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n );
6104  // No explicitly declared copy constructor.
6106  //**********************************************************************************************
6107 
6108  //**Destructor**********************************************************************************
6109  // No explicitly declared destructor.
6110  //**********************************************************************************************
6111 
6112  //**Data access functions***********************************************************************
6115  inline Reference operator()( size_t i, size_t j );
6116  inline ConstReference operator()( size_t i, size_t j ) const;
6117  inline Reference at( size_t i, size_t j );
6118  inline ConstReference at( size_t i, size_t j ) const;
6119  inline Pointer data () noexcept;
6120  inline ConstPointer data () const noexcept;
6121  inline Pointer data ( size_t i ) noexcept;
6122  inline ConstPointer data ( size_t i ) const noexcept;
6123  inline Iterator begin ( size_t i );
6124  inline ConstIterator begin ( size_t i ) const;
6125  inline ConstIterator cbegin( size_t i ) const;
6126  inline Iterator end ( size_t i );
6127  inline ConstIterator end ( size_t i ) const;
6128  inline ConstIterator cend ( size_t i ) const;
6130  //**********************************************************************************************
6131 
6132  //**Assignment operators************************************************************************
6135  inline Submatrix& operator=( const ElementType& rhs );
6136  inline Submatrix& operator=( initializer_list< initializer_list<ElementType> > list );
6137  inline Submatrix& operator=( const Submatrix& rhs );
6138 
6139  template< typename MT2, bool SO >
6140  inline Submatrix& operator=( const Matrix<MT2,SO>& rhs );
6141 
6142  template< typename MT2, bool SO >
6143  inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
6144  operator+=( const Matrix<MT2,SO>& rhs );
6145 
6146  template< typename MT2, bool SO >
6147  inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
6148  operator+=( const Matrix<MT2,SO>& rhs );
6149 
6150  template< typename MT2, bool SO >
6151  inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
6152  operator-=( const Matrix<MT2,SO>& rhs );
6153 
6154  template< typename MT2, bool SO >
6155  inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
6156  operator-=( const Matrix<MT2,SO>& rhs );
6157 
6158  template< typename MT2, bool SO >
6159  inline Submatrix& operator*=( const Matrix<MT2,SO>& rhs );
6160 
6161  template< typename Other >
6162  inline EnableIf_< IsNumeric<Other>, Submatrix >& operator*=( Other rhs );
6163 
6164  template< typename Other >
6165  inline EnableIf_< IsNumeric<Other>, Submatrix >& operator/=( Other rhs );
6167  //**********************************************************************************************
6168 
6169  //**Utility functions***************************************************************************
6172  inline size_t row() const noexcept;
6173  inline size_t rows() const noexcept;
6174  inline size_t column() const noexcept;
6175  inline size_t columns() const noexcept;
6176  inline size_t spacing() const noexcept;
6177  inline size_t capacity() const noexcept;
6178  inline size_t capacity( size_t i ) const noexcept;
6179  inline size_t nonZeros() const;
6180  inline size_t nonZeros( size_t i ) const;
6181  inline void reset();
6182  inline void reset( size_t i );
6183  inline Submatrix& transpose();
6184  inline Submatrix& ctranspose();
6185  template< typename Other > inline Submatrix& scale( const Other& scalar );
6187  //**********************************************************************************************
6188 
6189  private:
6190  //**********************************************************************************************
6192  template< typename MT2 >
6193  struct VectorizedAssign {
6194  enum : bool { value = useOptimizedKernels &&
6195  simdEnabled && MT2::simdEnabled &&
6196  AreSIMDCombinable< ElementType, ElementType_<MT2> >::value };
6197  };
6198  //**********************************************************************************************
6199 
6200  //**********************************************************************************************
6202  template< typename MT2 >
6203  struct VectorizedAddAssign {
6204  enum : bool { value = useOptimizedKernels &&
6205  simdEnabled && MT2::simdEnabled &&
6206  AreSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
6207  HasSIMDAdd< ElementType, ElementType_<MT2> >::value &&
6208  !IsDiagonal<MT2>::value };
6209  };
6210  //**********************************************************************************************
6211 
6212  //**********************************************************************************************
6214  template< typename MT2 >
6215  struct VectorizedSubAssign {
6216  enum : bool { value = useOptimizedKernels &&
6217  simdEnabled && MT2::simdEnabled &&
6218  AreSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
6219  HasSIMDSub< ElementType, ElementType_<MT2> >::value &&
6220  !IsDiagonal<MT2>::value };
6221  };
6222  //**********************************************************************************************
6223 
6224  //**SIMD properties*****************************************************************************
6226  enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
6227  //**********************************************************************************************
6228 
6229  public:
6230  //**Expression template evaluation functions****************************************************
6233  template< typename Other >
6234  inline bool canAlias( const Other* alias ) const noexcept;
6235 
6236  template< typename MT2, bool AF2, bool SO2 >
6237  inline bool canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
6238 
6239  template< typename Other >
6240  inline bool isAliased( const Other* alias ) const noexcept;
6241 
6242  template< typename MT2, bool AF2, bool SO2 >
6243  inline bool isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
6244 
6245  inline bool isAligned () const noexcept;
6246  inline bool canSMPAssign() const noexcept;
6247 
6248  BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
6249  BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
6250  BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
6251 
6252  BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
6253  BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
6254  BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
6255  BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
6256 
6257  template< typename MT2 >
6258  inline DisableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,false>& rhs );
6259 
6260  template< typename MT2 >
6261  inline EnableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,false>& rhs );
6262 
6263  template< typename MT2 > inline void assign( const DenseMatrix<MT2,true>& rhs );
6264  template< typename MT2 > inline void assign( const SparseMatrix<MT2,false>& rhs );
6265  template< typename MT2 > inline void assign( const SparseMatrix<MT2,true>& rhs );
6266 
6267  template< typename MT2 >
6268  inline DisableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,false>& rhs );
6269 
6270  template< typename MT2 >
6271  inline EnableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,false>& rhs );
6272 
6273  template< typename MT2 > inline void addAssign( const DenseMatrix<MT2,true>& rhs );
6274  template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,false>& rhs );
6275  template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,true>& rhs );
6276 
6277  template< typename MT2 >
6278  inline DisableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,false>& rhs );
6279 
6280  template< typename MT2 >
6281  inline EnableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,false>& rhs );
6282 
6283  template< typename MT2 > inline void subAssign( const DenseMatrix<MT2,true>& rhs );
6284  template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,false>& rhs );
6285  template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,true>& rhs );
6287  //**********************************************************************************************
6288 
6289  private:
6290  //**Utility functions***************************************************************************
6293  inline bool hasOverlap() const noexcept;
6295  //**********************************************************************************************
6296 
6297  //**Member variables****************************************************************************
6300  Operand matrix_;
6301  const size_t row_;
6302  const size_t column_;
6303  const size_t m_;
6304  const size_t n_;
6305 
6306  //**********************************************************************************************
6307 
6308  //**Friend declarations*************************************************************************
6309  template< typename MT2, bool AF2, bool SO2, bool DF2 > friend class Submatrix;
6310 
6311  template< bool AF1, typename MT2, bool AF2, bool SO2, bool DF2 >
6312  friend const Submatrix<MT2,AF1,SO2,DF2>
6313  submatrix( const Submatrix<MT2,AF2,SO2,DF2>& sm, size_t row, size_t column, size_t m, size_t n );
6314 
6315  template< typename MT2, bool AF2, bool SO2, bool DF2 >
6316  friend bool isIntact( const Submatrix<MT2,AF2,SO2,DF2>& sm ) noexcept;
6317 
6318  template< typename MT2, bool AF2, bool SO2, bool DF2 >
6319  friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Matrix<MT2,SO2>& b ) noexcept;
6320 
6321  template< typename MT2, bool AF2, bool SO2, bool DF2 >
6322  friend bool isSame( const Matrix<MT2,SO2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
6323 
6324  template< typename MT2, bool AF2, bool SO2, bool DF2 >
6325  friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
6326 
6327  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
6328  friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
6329  size_t row, size_t column );
6330 
6331  template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
6332  friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
6333  size_t row, size_t column );
6334 
6335  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
6336  friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
6337  size_t row, size_t column );
6338 
6339  template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
6340  friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
6341  size_t row, size_t column );
6342 
6343  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
6344  friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
6345  size_t row, size_t column );
6346 
6347  template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
6348  friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
6349  size_t row, size_t column );
6350 
6351  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
6352  friend bool tryMultAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
6353  size_t row, size_t column );
6354 
6355  template< typename MT2, bool AF2, bool SO2, bool DF2 >
6356  friend DerestrictTrait_< Submatrix<MT2,AF2,SO2,DF2> > derestrict( Submatrix<MT2,AF2,SO2,DF2>& sm );
6357  //**********************************************************************************************
6358 
6359  //**Compile time checks*************************************************************************
6367  //**********************************************************************************************
6368 };
6370 //*************************************************************************************************
6371 
6372 
6373 
6374 
6375 //=================================================================================================
6376 //
6377 // CONSTRUCTOR
6378 //
6379 //=================================================================================================
6380 
6381 //*************************************************************************************************
6395 template< typename MT > // Type of the dense matrix
6396 inline Submatrix<MT,aligned,false,true>::Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n )
6397  : matrix_( matrix ) // The dense matrix containing the submatrix
6398  , row_ ( rindex ) // The first row of the submatrix
6399  , column_( cindex ) // The first column of the submatrix
6400  , m_ ( m ) // The number of rows of the submatrix
6401  , n_ ( n ) // The number of columns of the submatrix
6402 {
6403  if( ( row_ + m_ > matrix_.rows() ) || ( column_ + n_ > matrix_.columns() ) ) {
6404  BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix specification" );
6405  }
6406 
6407  if( ( simdEnabled && matrix_.data() != nullptr && !checkAlignment( data() ) ) ||
6408  ( m_ > 1UL && matrix_.spacing() % SIMDSIZE != 0UL ) ) {
6409  BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix alignment" );
6410  }
6411 }
6413 //*************************************************************************************************
6414 
6415 
6416 
6417 
6418 //=================================================================================================
6419 //
6420 // DATA ACCESS FUNCTIONS
6421 //
6422 //=================================================================================================
6423 
6424 //*************************************************************************************************
6435 template< typename MT > // Type of the dense matrix
6437  Submatrix<MT,aligned,false,true>::operator()( size_t i, size_t j )
6438 {
6439  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
6440  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
6441 
6442  return matrix_(row_+i,column_+j);
6443 }
6445 //*************************************************************************************************
6446 
6447 
6448 //*************************************************************************************************
6459 template< typename MT > // Type of the dense matrix
6461  Submatrix<MT,aligned,false,true>::operator()( size_t i, size_t j ) const
6462 {
6463  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
6464  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
6465 
6466  return const_cast<const MT&>( matrix_ )(row_+i,column_+j);
6467 }
6469 //*************************************************************************************************
6470 
6471 
6472 //*************************************************************************************************
6484 template< typename MT > // Type of the dense matrix
6486  Submatrix<MT,aligned,false,true>::at( size_t i, size_t j )
6487 {
6488  if( i >= rows() ) {
6489  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
6490  }
6491  if( j >= columns() ) {
6492  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
6493  }
6494  return (*this)(i,j);
6495 }
6497 //*************************************************************************************************
6498 
6499 
6500 //*************************************************************************************************
6512 template< typename MT > // Type of the dense matrix
6514  Submatrix<MT,aligned,false,true>::at( size_t i, size_t j ) const
6515 {
6516  if( i >= rows() ) {
6517  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
6518  }
6519  if( j >= columns() ) {
6520  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
6521  }
6522  return (*this)(i,j);
6523 }
6525 //*************************************************************************************************
6526 
6527 
6528 //*************************************************************************************************
6538 template< typename MT > // Type of the dense matrix
6539 inline typename Submatrix<MT,aligned,false,true>::Pointer
6540  Submatrix<MT,aligned,false,true>::data() noexcept
6541 {
6542  return matrix_.data() + row_*spacing() + column_;
6543 }
6545 //*************************************************************************************************
6546 
6547 
6548 //*************************************************************************************************
6558 template< typename MT > // Type of the dense matrix
6559 inline typename Submatrix<MT,aligned,false,true>::ConstPointer
6560  Submatrix<MT,aligned,false,true>::data() const noexcept
6561 {
6562  return matrix_.data() + row_*spacing() + column_;
6563 }
6565 //*************************************************************************************************
6566 
6567 
6568 //*************************************************************************************************
6577 template< typename MT > // Type of the dense matrix
6578 inline typename Submatrix<MT,aligned,false,true>::Pointer
6579  Submatrix<MT,aligned,false,true>::data( size_t i ) noexcept
6580 {
6581  return matrix_.data() + (row_+i)*spacing() + column_;
6582 }
6584 //*************************************************************************************************
6585 
6586 
6587 //*************************************************************************************************
6596 template< typename MT > // Type of the dense matrix
6597 inline typename Submatrix<MT,aligned,false,true>::ConstPointer
6598  Submatrix<MT,aligned,false,true>::data( size_t i ) const noexcept
6599 {
6600  return matrix_.data() + (row_+i)*spacing() + column_;
6601 }
6603 //*************************************************************************************************
6604 
6605 
6606 //*************************************************************************************************
6618 template< typename MT > // Type of the dense matrix
6621 {
6622  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
6623  return ( matrix_.begin( row_ + i ) + column_ );
6624 }
6626 //*************************************************************************************************
6627 
6628 
6629 //*************************************************************************************************
6641 template< typename MT > // Type of the dense matrix
6643  Submatrix<MT,aligned,false,true>::begin( size_t i ) const
6644 {
6645  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
6646  return ( matrix_.cbegin( row_ + i ) + column_ );
6647 }
6649 //*************************************************************************************************
6650 
6651 
6652 //*************************************************************************************************
6664 template< typename MT > // Type of the dense matrix
6667 {
6668  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
6669  return ( matrix_.cbegin( row_ + i ) + column_ );
6670 }
6672 //*************************************************************************************************
6673 
6674 
6675 //*************************************************************************************************
6687 template< typename MT > // Type of the dense matrix
6690 {
6691  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
6692  return ( matrix_.begin( row_ + i ) + column_ + n_ );
6693 }
6695 //*************************************************************************************************
6696 
6697 
6698 //*************************************************************************************************
6710 template< typename MT > // Type of the dense matrix
6712  Submatrix<MT,aligned,false,true>::end( size_t i ) const
6713 {
6714  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
6715  return ( matrix_.cbegin( row_ + i ) + column_ + n_ );
6716 }
6718 //*************************************************************************************************
6719 
6720 
6721 //*************************************************************************************************
6733 template< typename MT > // Type of the dense matrix
6735  Submatrix<MT,aligned,false,true>::cend( size_t i ) const
6736 {
6737  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
6738  return ( matrix_.cbegin( row_ + i ) + column_ + n_ );
6739 }
6741 //*************************************************************************************************
6742 
6743 
6744 
6745 
6746 //=================================================================================================
6747 //
6748 // ASSIGNMENT OPERATORS
6749 //
6750 //=================================================================================================
6751 
6752 //*************************************************************************************************
6763 template< typename MT > // Type of the dense matrix
6764 inline Submatrix<MT,aligned,false,true>&
6765  Submatrix<MT,aligned,false,true>::operator=( const ElementType& rhs )
6766 {
6767  const size_t iend( row_ + m_ );
6768 
6769  for( size_t i=row_; i<iend; ++i )
6770  {
6771  const size_t jbegin( ( IsUpper<MT>::value )
6772  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
6773  ?( max( i+1UL, column_ ) )
6774  :( max( i, column_ ) ) )
6775  :( column_ ) );
6776  const size_t jend ( ( IsLower<MT>::value )
6777  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
6778  ?( min( i, column_+n_ ) )
6779  :( min( i+1UL, column_+n_ ) ) )
6780  :( column_+n_ ) );
6781 
6782  for( size_t j=jbegin; j<jend; ++j )
6783  matrix_(i,j) = rhs;
6784  }
6785 
6786  return *this;
6787 }
6789 //*************************************************************************************************
6790 
6791 
6792 //*************************************************************************************************
6805 template< typename MT > // Type of the dense matrix
6806 inline Submatrix<MT,aligned,false,true>&
6807  Submatrix<MT,aligned,false,true>::operator=( initializer_list< initializer_list<ElementType> > list )
6808 {
6809  if( list.size() != rows() || determineColumns( list ) > columns() ) {
6810  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to submatrix" );
6811  }
6812 
6813  size_t i( 0UL );
6814 
6815  for( const auto& rowList : list ) {
6816  std::fill( std::copy( rowList.begin(), rowList.end(), begin(i) ), end(i), ElementType() );
6817  ++i;
6818  }
6819 
6820  return *this;
6821 }
6823 //*************************************************************************************************
6824 
6825 
6826 //*************************************************************************************************
6841 template< typename MT > // Type of the dense matrix
6842 inline Submatrix<MT,aligned,false,true>&
6843  Submatrix<MT,aligned,false,true>::operator=( const Submatrix& rhs )
6844 {
6847 
6848  if( this == &rhs || ( &matrix_ == &rhs.matrix_ && row_ == rhs.row_ && column_ == rhs.column_ ) )
6849  return *this;
6850 
6851  if( rows() != rhs.rows() || columns() != rhs.columns() ) {
6852  BLAZE_THROW_INVALID_ARGUMENT( "Submatrix sizes do not match" );
6853  }
6854 
6855  if( !tryAssign( matrix_, rhs, row_, column_ ) ) {
6856  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
6857  }
6858 
6859  DerestrictTrait_<This> left( derestrict( *this ) );
6860 
6861  if( rhs.canAlias( &matrix_ ) ) {
6862  const ResultType tmp( rhs );
6863  smpAssign( left, tmp );
6864  }
6865  else {
6866  smpAssign( left, rhs );
6867  }
6868 
6869  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
6870 
6871  return *this;
6872 }
6874 //*************************************************************************************************
6875 
6876 
6877 //*************************************************************************************************
6892 template< typename MT > // Type of the dense matrix
6893 template< typename MT2 // Type of the right-hand side matrix
6894  , bool SO > // Storage order of the right-hand side matrix
6895 inline Submatrix<MT,aligned,false,true>&
6896  Submatrix<MT,aligned,false,true>::operator=( const Matrix<MT2,SO>& rhs )
6897 {
6899 
6900  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
6901  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
6902  }
6903 
6904  typedef If_< IsRestricted<MT>, CompositeType_<MT2>, const MT2& > Right;
6905  Right right( ~rhs );
6906 
6907  if( !tryAssign( matrix_, right, row_, column_ ) ) {
6908  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
6909  }
6910 
6911  if( IsSparseMatrix<MT2>::value )
6912  reset();
6913 
6914  DerestrictTrait_<This> left( derestrict( *this ) );
6915 
6916  if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
6917  const ResultType_<MT2> tmp( right );
6918  smpAssign( left, tmp );
6919  }
6920  else {
6921  smpAssign( left, right );
6922  }
6923 
6924  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
6925 
6926  return *this;
6927 }
6929 //*************************************************************************************************
6930 
6931 
6932 //*************************************************************************************************
6946 template< typename MT > // Type of the dense matrix
6947 template< typename MT2 // Type of the right-hand side matrix
6948  , bool SO > // Storage order of the right-hand side matrix
6949 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,false,true>& >
6950  Submatrix<MT,aligned,false,true>::operator+=( const Matrix<MT2,SO>& rhs )
6951 {
6955 
6956  typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
6957 
6960 
6961  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
6962  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
6963  }
6964 
6965  if( !tryAddAssign( matrix_, ~rhs, row_, column_ ) ) {
6966  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
6967  }
6968 
6969  DerestrictTrait_<This> left( derestrict( *this ) );
6970 
6971  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
6972  (~rhs).canAlias( &matrix_ ) ) {
6973  const AddType tmp( *this + (~rhs) );
6974  smpAssign( left, tmp );
6975  }
6976  else {
6977  smpAddAssign( left, ~rhs );
6978  }
6979 
6980  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
6981 
6982  return *this;
6983 }
6985 //*************************************************************************************************
6986 
6987 
6988 //*************************************************************************************************
7002 template< typename MT > // Type of the dense matrix
7003 template< typename MT2 // Type of the right-hand side matrix
7004  , bool SO > // Storage order of the right-hand side matrix
7005 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,false,true>& >
7006  Submatrix<MT,aligned,false,true>::operator+=( const Matrix<MT2,SO>& rhs )
7007 {
7011 
7012  typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
7013 
7016 
7017  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
7018  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
7019  }
7020 
7021  const AddType tmp( *this + (~rhs) );
7022 
7023  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
7024  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7025  }
7026 
7027  DerestrictTrait_<This> left( derestrict( *this ) );
7028 
7029  smpAssign( left, tmp );
7030 
7031  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
7032 
7033  return *this;
7034 }
7036 //*************************************************************************************************
7037 
7038 
7039 //*************************************************************************************************
7053 template< typename MT > // Type of the dense matrix
7054 template< typename MT2 // Type of the right-hand side matrix
7055  , bool SO > // Storage order of the right-hand side matrix
7056 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,false,true>& >
7057  Submatrix<MT,aligned,false,true>::operator-=( const Matrix<MT2,SO>& rhs )
7058 {
7062 
7063  typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
7064 
7067 
7068  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
7069  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
7070  }
7071 
7072  if( !trySubAssign( matrix_, ~rhs, row_, column_ ) ) {
7073  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7074  }
7075 
7076  DerestrictTrait_<This> left( derestrict( *this ) );
7077 
7078  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
7079  (~rhs).canAlias( &matrix_ ) ) {
7080  const SubType tmp( *this - (~rhs ) );
7081  smpAssign( left, tmp );
7082  }
7083  else {
7084  smpSubAssign( left, ~rhs );
7085  }
7086 
7087  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
7088 
7089  return *this;
7090 }
7092 //*************************************************************************************************
7093 
7094 
7095 //*************************************************************************************************
7109 template< typename MT > // Type of the dense matrix
7110 template< typename MT2 // Type of the right-hand side matrix
7111  , bool SO > // Storage order of the right-hand side matrix
7112 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,false,true>& >
7113  Submatrix<MT,aligned,false,true>::operator-=( const Matrix<MT2,SO>& rhs )
7114 {
7118 
7119  typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
7120 
7123 
7124  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
7125  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
7126  }
7127 
7128  const SubType tmp( *this - (~rhs) );
7129 
7130  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
7131  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7132  }
7133 
7134  DerestrictTrait_<This> left( derestrict( *this ) );
7135 
7136  smpAssign( left, tmp );
7137 
7138  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
7139 
7140  return *this;
7141 }
7143 //*************************************************************************************************
7144 
7145 
7146 //*************************************************************************************************
7160 template< typename MT > // Type of the dense matrix
7161 template< typename MT2 // Type of the right-hand side matrix
7162  , bool SO > // Storage order of the right-hand side matrix
7163 inline Submatrix<MT,aligned,false,true>&
7164  Submatrix<MT,aligned,false,true>::operator*=( const Matrix<MT2,SO>& rhs )
7165 {
7169 
7170  typedef MultTrait_< ResultType, ResultType_<MT2> > MultType;
7171 
7174 
7175  if( columns() != (~rhs).rows() ) {
7176  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
7177  }
7178 
7179  const MultType tmp( *this * (~rhs) );
7180 
7181  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
7182  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7183  }
7184 
7185  DerestrictTrait_<This> left( derestrict( *this ) );
7186 
7187  smpAssign( left, tmp );
7188 
7189  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
7190 
7191  return *this;
7192 }
7194 //*************************************************************************************************
7195 
7196 
7197 //*************************************************************************************************
7208 template< typename MT > // Type of the dense matrix
7209 template< typename Other > // Data type of the right-hand side scalar
7210 inline EnableIf_< IsNumeric<Other>, Submatrix<MT,aligned,false,true> >&
7212 {
7214 
7215  DerestrictTrait_<This> left( derestrict( *this ) );
7216  smpAssign( left, (*this) * rhs );
7217 
7218  return *this;
7219 }
7221 //*************************************************************************************************
7222 
7223 
7224 //*************************************************************************************************
7237 template< typename MT > // Type of the dense matrix
7238 template< typename Other > // Data type of the right-hand side scalar
7239 inline EnableIf_< IsNumeric<Other>, Submatrix<MT,aligned,false,true> >&
7241 {
7243 
7244  BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
7245 
7246  DerestrictTrait_<This> left( derestrict( *this ) );
7247  smpAssign( left, (*this) / rhs );
7248 
7249  return *this;
7250 }
7252 //*************************************************************************************************
7253 
7254 
7255 
7256 
7257 //=================================================================================================
7258 //
7259 // UTILITY FUNCTIONS
7260 //
7261 //=================================================================================================
7262 
7263 //*************************************************************************************************
7269 template< typename MT > // Type of the dense matrix
7270 inline size_t Submatrix<MT,aligned,false,true>::row() const noexcept
7271 {
7272  return row_;
7273 }
7275 //*************************************************************************************************
7276 
7277 
7278 //*************************************************************************************************
7284 template< typename MT > // Type of the dense matrix
7285 inline size_t Submatrix<MT,aligned,false,true>::rows() const noexcept
7286 {
7287  return m_;
7288 }
7290 //*************************************************************************************************
7291 
7292 
7293 //*************************************************************************************************
7299 template< typename MT > // Type of the dense matrix
7300 inline size_t Submatrix<MT,aligned,false,true>::column() const noexcept
7301 {
7302  return column_;
7303 }
7305 //*************************************************************************************************
7306 
7307 
7308 //*************************************************************************************************
7314 template< typename MT > // Type of the dense matrix
7315 inline size_t Submatrix<MT,aligned,false,true>::columns() const noexcept
7316 {
7317  return n_;
7318 }
7320 //*************************************************************************************************
7321 
7322 
7323 //*************************************************************************************************
7334 template< typename MT > // Type of the dense matrix
7335 inline size_t Submatrix<MT,aligned,false,true>::spacing() const noexcept
7336 {
7337  return matrix_.spacing();
7338 }
7340 //*************************************************************************************************
7341 
7342 
7343 //*************************************************************************************************
7349 template< typename MT > // Type of the dense matrix
7350 inline size_t Submatrix<MT,aligned,false,true>::capacity() const noexcept
7351 {
7352  return rows() * columns();
7353 }
7355 //*************************************************************************************************
7356 
7357 
7358 //*************************************************************************************************
7370 template< typename MT > // Type of the dense matrix
7371 inline size_t Submatrix<MT,aligned,false,true>::capacity( size_t i ) const noexcept
7372 {
7373  UNUSED_PARAMETER( i );
7374 
7375  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
7376 
7377  return columns();
7378 }
7380 //*************************************************************************************************
7381 
7382 
7383 //*************************************************************************************************
7389 template< typename MT > // Type of the dense matrix
7390 inline size_t Submatrix<MT,aligned,false,true>::nonZeros() const
7391 {
7392  const size_t iend( row_ + m_ );
7393  const size_t jend( column_ + n_ );
7394  size_t nonzeros( 0UL );
7395 
7396  for( size_t i=row_; i<iend; ++i )
7397  for( size_t j=column_; j<jend; ++j )
7398  if( !isDefault( matrix_(i,j) ) )
7399  ++nonzeros;
7400 
7401  return nonzeros;
7402 }
7404 //*************************************************************************************************
7405 
7406 
7407 //*************************************************************************************************
7419 template< typename MT > // Type of the dense matrix
7420 inline size_t Submatrix<MT,aligned,false,true>::nonZeros( size_t i ) const
7421 {
7422  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
7423 
7424  const size_t jend( column_ + n_ );
7425  size_t nonzeros( 0UL );
7426 
7427  for( size_t j=column_; j<jend; ++j )
7428  if( !isDefault( matrix_(row_+i,j) ) )
7429  ++nonzeros;
7430 
7431  return nonzeros;
7432 }
7434 //*************************************************************************************************
7435 
7436 
7437 //*************************************************************************************************
7443 template< typename MT > // Type of the dense matrix
7445 {
7446  using blaze::clear;
7447 
7448  for( size_t i=row_; i<row_+m_; ++i )
7449  {
7450  const size_t jbegin( ( IsUpper<MT>::value )
7451  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
7452  ?( max( i+1UL, column_ ) )
7453  :( max( i, column_ ) ) )
7454  :( column_ ) );
7455  const size_t jend ( ( IsLower<MT>::value )
7456  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
7457  ?( min( i, column_+n_ ) )
7458  :( min( i+1UL, column_+n_ ) ) )
7459  :( column_+n_ ) );
7460 
7461  for( size_t j=jbegin; j<jend; ++j )
7462  clear( matrix_(i,j) );
7463  }
7464 }
7466 //*************************************************************************************************
7467 
7468 
7469 //*************************************************************************************************
7481 template< typename MT > // Type of the dense matrix
7482 inline void Submatrix<MT,aligned,false,true>::reset( size_t i )
7483 {
7484  using blaze::clear;
7485 
7486  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
7487 
7488  const size_t jbegin( ( IsUpper<MT>::value )
7489  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
7490  ?( max( i+1UL, column_ ) )
7491  :( max( i, column_ ) ) )
7492  :( column_ ) );
7493  const size_t jend ( ( IsLower<MT>::value )
7494  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
7495  ?( min( i, column_+n_ ) )
7496  :( min( i+1UL, column_+n_ ) ) )
7497  :( column_+n_ ) );
7498 
7499  for( size_t j=jbegin; j<jend; ++j )
7500  clear( matrix_(row_+i,j) );
7501 }
7503 //*************************************************************************************************
7504 
7505 
7506 //*************************************************************************************************
7524 template< typename MT > // Type of the dense matrix
7525 inline Submatrix<MT,aligned,false,true>& Submatrix<MT,aligned,false,true>::transpose()
7526 {
7527  if( m_ != n_ ) {
7528  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
7529  }
7530 
7531  if( !tryAssign( matrix_, trans( *this ), row_, column_ ) ) {
7532  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
7533  }
7534 
7535  DerestrictTrait_<This> left( derestrict( *this ) );
7536  const ResultType tmp( trans( *this ) );
7537  smpAssign( left, tmp );
7538 
7539  return *this;
7540 }
7542 //*************************************************************************************************
7543 
7544 
7545 //*************************************************************************************************
7563 template< typename MT > // Type of the dense matrix
7564 inline Submatrix<MT,aligned,false,true>& Submatrix<MT,aligned,false,true>::ctranspose()
7565 {
7566  if( m_ != n_ ) {
7567  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
7568  }
7569 
7570  if( !tryAssign( matrix_, ctrans( *this ), row_, column_ ) ) {
7571  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
7572  }
7573 
7574  DerestrictTrait_<This> left( derestrict( *this ) );
7575  const ResultType tmp( ctrans( *this ) );
7576  smpAssign( left, tmp );
7577 
7578  return *this;
7579 }
7581 //*************************************************************************************************
7582 
7583 
7584 //*************************************************************************************************
7595 template< typename MT > // Type of the dense matrix
7596 template< typename Other > // Data type of the scalar value
7597 inline Submatrix<MT,aligned,false,true>& Submatrix<MT,aligned,false,true>::scale( const Other& scalar )
7598 {
7600 
7601  const size_t iend( row_ + m_ );
7602 
7603  for( size_t i=row_; i<iend; ++i )
7604  {
7605  const size_t jbegin( ( IsUpper<MT>::value )
7606  ?( ( IsStrictlyUpper<MT>::value )
7607  ?( max( i+1UL, column_ ) )
7608  :( max( i, column_ ) ) )
7609  :( column_ ) );
7610  const size_t jend ( ( IsLower<MT>::value )
7611  ?( ( IsStrictlyLower<MT>::value )
7612  ?( min( i, column_+n_ ) )
7613  :( min( i+1UL, column_+n_ ) ) )
7614  :( column_+n_ ) );
7615 
7616  for( size_t j=jbegin; j<jend; ++j )
7617  matrix_(i,j) *= scalar;
7618  }
7619 
7620  return *this;
7621 }
7623 //*************************************************************************************************
7624 
7625 
7626 //*************************************************************************************************
7636 template< typename MT > // Type of the dense matrix
7637 inline bool Submatrix<MT,aligned,false,true>::hasOverlap() const noexcept
7638 {
7639  BLAZE_INTERNAL_ASSERT( IsSymmetric<MT>::value || IsHermitian<MT>::value, "Invalid matrix detected" );
7640 
7641  if( ( row_ + m_ <= column_ ) || ( column_ + n_ <= row_ ) )
7642  return false;
7643  else return true;
7644 }
7646 //*************************************************************************************************
7647 
7648 
7649 
7650 
7651 //=================================================================================================
7652 //
7653 // EXPRESSION TEMPLATE EVALUATION FUNCTIONS
7654 //
7655 //=================================================================================================
7656 
7657 //*************************************************************************************************
7668 template< typename MT > // Type of the dense matrix
7669 template< typename Other > // Data type of the foreign expression
7670 inline bool Submatrix<MT,aligned,false,true>::canAlias( const Other* alias ) const noexcept
7671 {
7672  return matrix_.isAliased( alias );
7673 }
7675 //*************************************************************************************************
7676 
7677 
7678 //*************************************************************************************************
7689 template< typename MT > // Type of the dense matrix
7690 template< typename MT2 // Data type of the foreign dense submatrix
7691  , bool AF2 // Alignment flag of the foreign dense submatrix
7692  , bool SO2 > // Storage order of the foreign dense submatrix
7693 inline bool Submatrix<MT,aligned,false,true>::canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
7694 {
7695  return ( matrix_.isAliased( &alias->matrix_ ) &&
7696  ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
7697  ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
7698 }
7700 //*************************************************************************************************
7701 
7702 
7703 //*************************************************************************************************
7714 template< typename MT > // Type of the dense matrix
7715 template< typename Other > // Data type of the foreign expression
7716 inline bool Submatrix<MT,aligned,false,true>::isAliased( const Other* alias ) const noexcept
7717 {
7718  return matrix_.isAliased( alias );
7719 }
7721 //*************************************************************************************************
7722 
7723 
7724 //*************************************************************************************************
7735 template< typename MT > // Type of the dense matrix
7736 template< typename MT2 // Data type of the foreign dense submatrix
7737  , bool AF2 // Alignment flag of the foreign dense submatrix
7738  , bool SO2 > // Storage order of the foreign dense submatrix
7739 inline bool Submatrix<MT,aligned,false,true>::isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
7740 {
7741  return ( matrix_.isAliased( &alias->matrix_ ) &&
7742  ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
7743  ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
7744 }
7746 //*************************************************************************************************
7747 
7748 
7749 //*************************************************************************************************
7759 template< typename MT > // Type of the dense matrix
7760 inline bool Submatrix<MT,aligned,false,true>::isAligned() const noexcept
7761 {
7762  return true;
7763 }
7765 //*************************************************************************************************
7766 
7767 
7768 //*************************************************************************************************
7779 template< typename MT > // Type of the dense matrix
7780 inline bool Submatrix<MT,aligned,false,true>::canSMPAssign() const noexcept
7781 {
7782  return ( rows() * columns() >= SMP_DMATASSIGN_THRESHOLD );
7783 }
7785 //*************************************************************************************************
7786 
7787 
7788 //*************************************************************************************************
7804 template< typename MT > // Type of the dense matrix
7805 BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,false,true>::SIMDType
7806  Submatrix<MT,aligned,false,true>::load( size_t i, size_t j ) const noexcept
7807 {
7808  return loada( i, j );
7809 }
7811 //*************************************************************************************************
7812 
7813 
7814 //*************************************************************************************************
7830 template< typename MT > // Type of the dense matrix
7831 BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,false,true>::SIMDType
7832  Submatrix<MT,aligned,false,true>::loada( size_t i, size_t j ) const noexcept
7833 {
7835 
7836  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
7837  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
7838  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
7839  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
7840 
7841  return matrix_.loada( row_+i, column_+j );
7842 }
7844 //*************************************************************************************************
7845 
7846 
7847 //*************************************************************************************************
7863 template< typename MT > // Type of the dense matrix
7864 BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,false,true>::SIMDType
7865  Submatrix<MT,aligned,false,true>::loadu( size_t i, size_t j ) const noexcept
7866 {
7868 
7869  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
7870  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
7871  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
7872  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
7873 
7874  return matrix_.loadu( row_+i, column_+j );
7875 }
7877 //*************************************************************************************************
7878 
7879 
7880 //*************************************************************************************************
7897 template< typename MT > // Type of the dense matrix
7899  Submatrix<MT,aligned,false,true>::store( size_t i, size_t j, const SIMDType& value ) noexcept
7900 {
7901  return storea( i, j, value );
7902 }
7904 //*************************************************************************************************
7905 
7906 
7907 //*************************************************************************************************
7924 template< typename MT > // Type of the dense matrix
7926  Submatrix<MT,aligned,false,true>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
7927 {
7929 
7930  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
7931  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
7932  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
7933  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
7934 
7935  return matrix_.storea( row_+i, column_+j, value );
7936 }
7938 //*************************************************************************************************
7939 
7940 
7941 //*************************************************************************************************
7958 template< typename MT > // Type of the dense matrix
7960  Submatrix<MT,aligned,false,true>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
7961 {
7963 
7964  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
7965  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
7966  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
7967  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
7968 
7969  matrix_.storeu( row_+i, column_+j, value );
7970 }
7972 //*************************************************************************************************
7973 
7974 
7975 //*************************************************************************************************
7993 template< typename MT > // Type of the dense matrix
7995  Submatrix<MT,aligned,false,true>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
7996 {
7998 
7999  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
8000  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
8001  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
8002  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
8003 
8004  matrix_.stream( row_+i, column_+j, value );
8005 }
8007 //*************************************************************************************************
8008 
8009 
8010 //*************************************************************************************************
8022 template< typename MT > // Type of the dense matrix
8023 template< typename MT2 > // Type of the right-hand side dense matrix
8024 inline DisableIf_< typename Submatrix<MT,aligned,false,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
8025  Submatrix<MT,aligned,false,true>::assign( const DenseMatrix<MT2,false>& rhs )
8026 {
8027  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8028  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8029 
8030  const size_t jpos( n_ & size_t(-2) );
8031  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
8032 
8033  for( size_t i=0UL; i<m_; ++i ) {
8034  for( size_t j=0UL; j<jpos; j+=2UL ) {
8035  matrix_(row_+i,column_+j ) = (~rhs)(i,j );
8036  matrix_(row_+i,column_+j+1UL) = (~rhs)(i,j+1UL);
8037  }
8038  if( jpos < n_ ) {
8039  matrix_(row_+i,column_+jpos) = (~rhs)(i,jpos);
8040  }
8041  }
8042 }
8044 //*************************************************************************************************
8045 
8046 
8047 //*************************************************************************************************
8059 template< typename MT > // Type of the dense matrix
8060 template< typename MT2 > // Type of the right-hand side dense matrix
8061 inline EnableIf_< typename Submatrix<MT,aligned,false,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
8062  Submatrix<MT,aligned,false,true>::assign( const DenseMatrix<MT2,false>& rhs )
8063 {
8065 
8066  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8067  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8068 
8069  const size_t jpos( n_ & size_t(-SIMDSIZE) );
8070  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
8071 
8072  if( useStreaming &&
8073  m_*n_ > ( cacheSize / ( sizeof(ElementType) * 3UL ) ) &&
8074  !(~rhs).isAliased( &matrix_ ) )
8075  {
8076  for( size_t i=0UL; i<m_; ++i )
8077  {
8078  size_t j( 0UL );
8079  Iterator left( begin(i) );
8080  ConstIterator_<MT2> right( (~rhs).begin(i) );
8081 
8082  for( ; j<jpos; j+=SIMDSIZE ) {
8083  left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8084  }
8085  for( ; j<n_; ++j ) {
8086  *left = *right; ++left; ++right;
8087  }
8088  }
8089  }
8090  else
8091  {
8092  for( size_t i=0UL; i<m_; ++i )
8093  {
8094  size_t j( 0UL );
8095  Iterator left( begin(i) );
8096  ConstIterator_<MT2> right( (~rhs).begin(i) );
8097 
8098  for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
8099  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8100  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8101  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8102  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8103  }
8104  for( ; j<jpos; j+=SIMDSIZE ) {
8105  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8106  }
8107  for( ; j<n_; ++j ) {
8108  *left = *right; ++left; ++right;
8109  }
8110  }
8111  }
8112 }
8114 //*************************************************************************************************
8115 
8116 
8117 //*************************************************************************************************
8129 template< typename MT > // Type of the dense matrix
8130 template< typename MT2 > // Type of the right-hand side dense matrix
8131 inline void Submatrix<MT,aligned,false,true>::assign( const DenseMatrix<MT2,true>& rhs )
8132 {
8134 
8135  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8136  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8137 
8138  const size_t block( BLOCK_SIZE );
8139 
8140  for( size_t ii=0UL; ii<m_; ii+=block ) {
8141  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
8142  for( size_t jj=0UL; jj<n_; jj+=block ) {
8143  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
8144  for( size_t i=ii; i<iend; ++i ) {
8145  for( size_t j=jj; j<jend; ++j ) {
8146  matrix_(row_+i,column_+j) = (~rhs)(i,j);
8147  }
8148  }
8149  }
8150  }
8151 }
8153 //*************************************************************************************************
8154 
8155 
8156 //*************************************************************************************************
8168 template< typename MT > // Type of the dense matrix
8169 template< typename MT2 > // Type of the right-hand side sparse matrix
8170 inline void Submatrix<MT,aligned,false,true>::assign( const SparseMatrix<MT2,false>& rhs )
8171 {
8172  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8173  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8174 
8175  for( size_t i=0UL; i<m_; ++i )
8176  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
8177  matrix_(row_+i,column_+element->index()) = element->value();
8178 }
8180 //*************************************************************************************************
8181 
8182 
8183 //*************************************************************************************************
8195 template< typename MT > // Type of the dense matrix
8196 template< typename MT2 > // Type of the right-hand side sparse matrix
8197 inline void Submatrix<MT,aligned,false,true>::assign( const SparseMatrix<MT2,true>& rhs )
8198 {
8200 
8201  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8202  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8203 
8204  for( size_t j=0UL; j<n_; ++j )
8205  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
8206  matrix_(row_+element->index(),column_+j) = element->value();
8207 }
8209 //*************************************************************************************************
8210 
8211 
8212 //*************************************************************************************************
8224 template< typename MT > // Type of the dense matrix
8225 template< typename MT2 > // Type of the right-hand side dense matrix
8226 inline DisableIf_< typename Submatrix<MT,aligned,false,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
8227  Submatrix<MT,aligned,false,true>::addAssign( const DenseMatrix<MT2,false>& rhs )
8228 {
8229  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8230  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8231 
8232  const size_t jpos( n_ & size_t(-2) );
8233  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
8234 
8235  for( size_t i=0UL; i<m_; ++i )
8236  {
8237  if( IsDiagonal<MT2>::value ) {
8238  matrix_(row_+i,column_+i) += (~rhs)(i,i);
8239  }
8240  else {
8241  for( size_t j=0UL; j<jpos; j+=2UL ) {
8242  matrix_(row_+i,column_+j ) += (~rhs)(i,j );
8243  matrix_(row_+i,column_+j+1UL) += (~rhs)(i,j+1UL);
8244  }
8245  if( jpos < n_ ) {
8246  matrix_(row_+i,column_+jpos) += (~rhs)(i,jpos);
8247  }
8248  }
8249  }
8250 }
8252 //*************************************************************************************************
8253 
8254 
8255 //*************************************************************************************************
8267 template< typename MT > // Type of the dense matrix
8268 template< typename MT2 > // Type of the right-hand side dense matrix
8269 inline EnableIf_< typename Submatrix<MT,aligned,false,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
8270  Submatrix<MT,aligned,false,true>::addAssign( const DenseMatrix<MT2,false>& rhs )
8271 {
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  for( size_t i=0UL; i<m_; ++i )
8278  {
8279  const size_t jbegin( ( IsUpper<MT2>::value )
8280  ?( ( IsStrictlyUpper<MT2>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
8281  :( 0UL ) );
8282  const size_t jend ( ( IsLower<MT2>::value )
8283  ?( IsStrictlyLower<MT2>::value ? i : i+1UL )
8284  :( n_ ) );
8285  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
8286 
8287  const size_t jpos( jend & size_t(-SIMDSIZE) );
8288  BLAZE_INTERNAL_ASSERT( ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
8289 
8290  size_t j( jbegin );
8291  Iterator left( begin(i) + jbegin );
8292  ConstIterator_<MT2> right( (~rhs).begin(i) + jbegin );
8293 
8294  for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
8295  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8296  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8297  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8298  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8299  }
8300  for( ; j<jpos; j+=SIMDSIZE ) {
8301  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8302  }
8303  for( ; j<jend; ++j ) {
8304  *left += *right; ++left; ++right;
8305  }
8306  }
8307 }
8309 //*************************************************************************************************
8310 
8311 
8312 //*************************************************************************************************
8324 template< typename MT > // Type of the dense matrix
8325 template< typename MT2 > // Type of the right-hand side dense matrix
8326 inline void Submatrix<MT,aligned,false,true>::addAssign( const DenseMatrix<MT2,true>& rhs )
8327 {
8329 
8330  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8331  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8332 
8333  const size_t block( BLOCK_SIZE );
8334 
8335  for( size_t ii=0UL; ii<m_; ii+=block ) {
8336  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
8337  for( size_t jj=0UL; jj<n_; jj+=block ) {
8338  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
8339  for( size_t i=ii; i<iend; ++i ) {
8340  for( size_t j=jj; j<jend; ++j ) {
8341  matrix_(row_+i,column_+j) += (~rhs)(i,j);
8342  }
8343  }
8344  }
8345  }
8346 }
8348 //*************************************************************************************************
8349 
8350 
8351 //*************************************************************************************************
8363 template< typename MT > // Type of the dense matrix
8364 template< typename MT2 > // Type of the right-hand side sparse matrix
8365 inline void Submatrix<MT,aligned,false,true>::addAssign( const SparseMatrix<MT2,false>& rhs )
8366 {
8367  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8368  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8369 
8370  for( size_t i=0UL; i<m_; ++i )
8371  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
8372  matrix_(row_+i,column_+element->index()) += element->value();
8373 }
8375 //*************************************************************************************************
8376 
8377 
8378 //*************************************************************************************************
8390 template< typename MT > // Type of the dense matrix
8391 template< typename MT2 > // Type of the right-hand side sparse matrix
8392 inline void Submatrix<MT,aligned,false,true>::addAssign( const SparseMatrix<MT2,true>& rhs )
8393 {
8395 
8396  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8397  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8398 
8399  for( size_t j=0UL; j<n_; ++j )
8400  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
8401  matrix_(row_+element->index(),column_+j) += element->value();
8402 }
8404 //*************************************************************************************************
8405 
8406 
8407 //*************************************************************************************************
8419 template< typename MT > // Type of the dense matrix
8420 template< typename MT2 > // Type of the right-hand side dense matrix
8421 inline DisableIf_< typename Submatrix<MT,aligned,false,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
8422  Submatrix<MT,aligned,false,true>::subAssign( const DenseMatrix<MT2,false>& rhs )
8423 {
8424  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8425  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8426 
8427  const size_t jpos( n_ & size_t(-2) );
8428  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
8429 
8430  for( size_t i=0UL; i<m_; ++i )
8431  {
8432  if( IsDiagonal<MT2>::value ) {
8433  matrix_(row_+i,column_+i) -= (~rhs)(i,i);
8434  }
8435  else {
8436  for( size_t j=0UL; j<jpos; j+=2UL ) {
8437  matrix_(row_+i,column_+j ) -= (~rhs)(i,j );
8438  matrix_(row_+i,column_+j+1UL) -= (~rhs)(i,j+1UL);
8439  }
8440  if( jpos < n_ ) {
8441  matrix_(row_+i,column_+jpos) -= (~rhs)(i,jpos);
8442  }
8443  }
8444  }
8445 }
8447 //*************************************************************************************************
8448 
8449 
8450 //*************************************************************************************************
8462 template< typename MT > // Type of the dense matrix
8463 template< typename MT2 > // Type of the right-hand side dense matrix
8464 inline EnableIf_< typename Submatrix<MT,aligned,false,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
8465  Submatrix<MT,aligned,false,true>::subAssign( const DenseMatrix<MT2,false>& rhs )
8466 {
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  for( size_t i=0UL; i<m_; ++i )
8473  {
8474  const size_t jbegin( ( IsUpper<MT2>::value )
8475  ?( ( IsStrictlyUpper<MT2>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
8476  :( 0UL ) );
8477  const size_t jend ( ( IsLower<MT2>::value )
8478  ?( IsStrictlyLower<MT2>::value ? i : i+1UL )
8479  :( n_ ) );
8480  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
8481 
8482  const size_t jpos( jend & size_t(-SIMDSIZE) );
8483  BLAZE_INTERNAL_ASSERT( ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
8484 
8485  size_t j( jbegin );
8486  Iterator left( begin(i) + jbegin );
8487  ConstIterator_<MT2> right( (~rhs).begin(i) + jbegin );
8488 
8489  for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
8490  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8491  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8492  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8493  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8494  }
8495  for( ; j<jpos; j+=SIMDSIZE ) {
8496  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8497  }
8498  for( ; j<jend; ++j ) {
8499  *left -= *right; ++left; ++right;
8500  }
8501  }
8502 }
8504 //*************************************************************************************************
8505 
8506 
8507 //*************************************************************************************************
8519 template< typename MT > // Type of the dense matrix
8520 template< typename MT2 > // Type of the right-hand side dense matrix
8521 inline void Submatrix<MT,aligned,false,true>::subAssign( const DenseMatrix<MT2,true>& rhs )
8522 {
8524 
8525  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8526  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8527 
8528  const size_t block( BLOCK_SIZE );
8529 
8530  for( size_t ii=0UL; ii<m_; ii+=block ) {
8531  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
8532  for( size_t jj=0UL; jj<n_; jj+=block ) {
8533  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
8534  for( size_t i=ii; i<iend; ++i ) {
8535  for( size_t j=jj; j<jend; ++j ) {
8536  matrix_(row_+i,column_+j) -= (~rhs)(i,j);
8537  }
8538  }
8539  }
8540  }
8541 }
8543 //*************************************************************************************************
8544 
8545 
8546 //*************************************************************************************************
8558 template< typename MT > // Type of the dense matrix
8559 template< typename MT2 > // Type of the right-hand side sparse matrix
8560 inline void Submatrix<MT,aligned,false,true>::subAssign( const SparseMatrix<MT2,false>& rhs )
8561 {
8562  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8563  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8564 
8565  for( size_t i=0UL; i<m_; ++i )
8566  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
8567  matrix_(row_+i,column_+element->index()) -= element->value();
8568 }
8570 //*************************************************************************************************
8571 
8572 
8573 //*************************************************************************************************
8585 template< typename MT > // Type of the dense matrix
8586 template< typename MT2 > // Type of the right-hand side sparse matrix
8587 inline void Submatrix<MT,aligned,false,true>::subAssign( const SparseMatrix<MT2,true>& rhs )
8588 {
8590 
8591  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8592  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8593 
8594  for( size_t j=0UL; j<n_; ++j )
8595  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
8596  matrix_(row_+element->index(),column_+j) -= element->value();
8597 }
8599 //*************************************************************************************************
8600 
8601 
8602 
8603 
8604 
8605 
8606 
8607 
8608 //=================================================================================================
8609 //
8610 // CLASS TEMPLATE SPECIALIZATION FOR ALIGNED COLUMN-MAJOR DENSE SUBMATRICES
8611 //
8612 //=================================================================================================
8613 
8614 //*************************************************************************************************
8622 template< typename MT > // Type of the dense matrix
8623 class Submatrix<MT,aligned,true,true>
8624  : public DenseMatrix< Submatrix<MT,aligned,true,true>, true >
8625  , private View
8626 {
8627  private:
8628  //**Type definitions****************************************************************************
8630  typedef If_< IsExpression<MT>, MT, MT& > Operand;
8631  //**********************************************************************************************
8632 
8633  public:
8634  //**Type definitions****************************************************************************
8635  typedef Submatrix<MT,aligned,true,true> This;
8636  typedef DenseMatrix<This,true> BaseType;
8637  typedef SubmatrixTrait_<MT> ResultType;
8638  typedef OppositeType_<ResultType> OppositeType;
8639  typedef TransposeType_<ResultType> TransposeType;
8640  typedef ElementType_<MT> ElementType;
8641  typedef SIMDTrait_<ElementType> SIMDType;
8642  typedef ReturnType_<MT> ReturnType;
8643  typedef const Submatrix& CompositeType;
8644 
8646  typedef ConstReference_<MT> ConstReference;
8647 
8649  typedef If_< IsConst<MT>, ConstReference, Reference_<MT> > Reference;
8650 
8652  typedef const ElementType* ConstPointer;
8653 
8655  typedef If_< Or< IsConst<MT>, Not< HasMutableDataAccess<MT> > >, ConstPointer, ElementType* > Pointer;
8656 
8658  typedef ConstIterator_<MT> ConstIterator;
8659 
8661  typedef If_< IsConst<MT>, ConstIterator, Iterator_<MT> > Iterator;
8662  //**********************************************************************************************
8663 
8664  //**Compilation flags***************************************************************************
8666  enum : bool { simdEnabled = MT::simdEnabled };
8667 
8669  enum : bool { smpAssignable = MT::smpAssignable };
8670  //**********************************************************************************************
8671 
8672  //**Constructors********************************************************************************
8675  explicit inline Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n );
8676  // No explicitly declared copy constructor.
8678  //**********************************************************************************************
8679 
8680  //**Destructor**********************************************************************************
8681  // No explicitly declared destructor.
8682  //**********************************************************************************************
8683 
8684  //**Data access functions***********************************************************************
8687  inline Reference operator()( size_t i, size_t j );
8688  inline ConstReference operator()( size_t i, size_t j ) const;
8689  inline Reference at( size_t i, size_t j );
8690  inline ConstReference at( size_t i, size_t j ) const;
8691  inline Pointer data () noexcept;
8692  inline ConstPointer data () const noexcept;
8693  inline Pointer data ( size_t j ) noexcept;
8694  inline ConstPointer data ( size_t j ) const noexcept;
8695  inline Iterator begin ( size_t j );
8696  inline ConstIterator begin ( size_t j ) const;
8697  inline ConstIterator cbegin( size_t j ) const;
8698  inline Iterator end ( size_t j );
8699  inline ConstIterator end ( size_t j ) const;
8700  inline ConstIterator cend ( size_t j ) const;
8702  //**********************************************************************************************
8703 
8704  //**Assignment operators************************************************************************
8707  inline Submatrix& operator=( const ElementType& rhs );
8708  inline Submatrix& operator=( initializer_list< initializer_list<ElementType> > list );
8709  inline Submatrix& operator=( const Submatrix& rhs );
8710 
8711  template< typename MT2, bool SO >
8712  inline Submatrix& operator=( const Matrix<MT2,SO>& rhs );
8713 
8714  template< typename MT2, bool SO >
8715  inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
8716  operator+=( const Matrix<MT2,SO>& rhs );
8717 
8718  template< typename MT2, bool SO >
8719  inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
8720  operator+=( const Matrix<MT2,SO>& rhs );
8721 
8722  template< typename MT2, bool SO >
8723  inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
8724  operator-=( const Matrix<MT2,SO>& rhs );
8725 
8726  template< typename MT2, bool SO >
8727  inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
8728  operator-=( const Matrix<MT2,SO>& rhs );
8729 
8730  template< typename MT2, bool SO >
8731  inline Submatrix& operator*=( const Matrix<MT2,SO>& rhs );
8732 
8733  template< typename Other >
8734  inline EnableIf_< IsNumeric<Other>, Submatrix >& operator*=( Other rhs );
8735 
8736  template< typename Other >
8737  inline EnableIf_< IsNumeric<Other>, Submatrix >& operator/=( Other rhs );
8739  //**********************************************************************************************
8740 
8741  //**Utility functions***************************************************************************
8744  inline size_t row() const noexcept;
8745  inline size_t rows() const noexcept;
8746  inline size_t column() const noexcept;
8747  inline size_t columns() const noexcept;
8748  inline size_t spacing() const noexcept;
8749  inline size_t capacity() const noexcept;
8750  inline size_t capacity( size_t i ) const noexcept;
8751  inline size_t nonZeros() const;
8752  inline size_t nonZeros( size_t i ) const;
8753  inline void reset();
8754  inline void reset( size_t i );
8755  inline Submatrix& transpose();
8756  inline Submatrix& ctranspose();
8757  template< typename Other > inline Submatrix& scale( const Other& scalar );
8759  //**********************************************************************************************
8760 
8761  private:
8762  //**********************************************************************************************
8764  template< typename MT2 >
8765  struct VectorizedAssign {
8766  enum : bool { value = useOptimizedKernels &&
8767  simdEnabled && MT2::simdEnabled &&
8768  AreSIMDCombinable< ElementType, ElementType_<MT2> >::value };
8769  };
8770  //**********************************************************************************************
8771 
8772  //**********************************************************************************************
8774  template< typename MT2 >
8775  struct VectorizedAddAssign {
8776  enum : bool { value = useOptimizedKernels &&
8777  simdEnabled && MT2::simdEnabled &&
8778  AreSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
8779  HasSIMDAdd< ElementType, ElementType_<MT2> >::value &&
8780  !IsDiagonal<MT2>::value };
8781  };
8782  //**********************************************************************************************
8783 
8784  //**********************************************************************************************
8786  template< typename MT2 >
8787  struct VectorizedSubAssign {
8788  enum : bool { value = useOptimizedKernels &&
8789  simdEnabled && MT2::simdEnabled &&
8790  AreSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
8791  HasSIMDSub< ElementType, ElementType_<MT2> >::value &&
8792  !IsDiagonal<MT2>::value };
8793  };
8794  //**********************************************************************************************
8795 
8796  //**SIMD properties*****************************************************************************
8798  enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
8799  //**********************************************************************************************
8800 
8801  public:
8802  //**Expression template evaluation functions****************************************************
8805  template< typename Other >
8806  inline bool canAlias( const Other* alias ) const noexcept;
8807 
8808  template< typename MT2, bool AF2, bool SO2 >
8809  inline bool canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
8810 
8811  template< typename Other >
8812  inline bool isAliased( const Other* alias ) const noexcept;
8813 
8814  template< typename MT2, bool AF2, bool SO2 >
8815  inline bool isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
8816 
8817  inline bool isAligned () const noexcept;
8818  inline bool canSMPAssign() const noexcept;
8819 
8820  BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
8821  BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
8822  BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
8823 
8824  BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
8825  BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
8826  BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
8827  BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
8828 
8829  template< typename MT2 >
8830  inline DisableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,true>& rhs );
8831 
8832  template< typename MT2 >
8833  inline EnableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,true>& rhs );
8834 
8835  template< typename MT2 > inline void assign( const DenseMatrix<MT2,false>& rhs );
8836  template< typename MT2 > inline void assign( const SparseMatrix<MT2,true>& rhs );
8837  template< typename MT2 > inline void assign( const SparseMatrix<MT2,false>& rhs );
8838 
8839  template< typename MT2 >
8840  inline DisableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,true>& rhs );
8841 
8842  template< typename MT2 >
8843  inline EnableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,true>& rhs );
8844 
8845  template< typename MT2 > inline void addAssign( const DenseMatrix<MT2,false>& rhs );
8846  template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,true>& rhs );
8847  template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,false>& rhs );
8848 
8849  template< typename MT2 >
8850  inline DisableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,true>& rhs );
8851 
8852  template< typename MT2 >
8853  inline EnableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,true>& rhs );
8854 
8855  template< typename MT2 > inline void subAssign( const DenseMatrix<MT2,false>& rhs );
8856  template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,true>& rhs );
8857  template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,false>& rhs );
8859  //**********************************************************************************************
8860 
8861  private:
8862  //**Utility functions***************************************************************************
8865  inline bool hasOverlap() const noexcept;
8867  //**********************************************************************************************
8868 
8869  //**Member variables****************************************************************************
8872  Operand matrix_;
8873  const size_t row_;
8874  const size_t column_;
8875  const size_t m_;
8876  const size_t n_;
8877 
8878  //**********************************************************************************************
8879 
8880  //**Friend declarations*************************************************************************
8881  template< typename MT2, bool AF2, bool SO2, bool DF2 > friend class Submatrix;
8882 
8883  template< bool AF1, typename MT2, bool AF2, bool SO2, bool DF2 >
8884  friend const Submatrix<MT2,AF1,SO2,DF2>
8885  submatrix( const Submatrix<MT2,AF2,SO2,DF2>& sm, size_t row, size_t column, size_t m, size_t n );
8886 
8887  template< typename MT2, bool AF2, bool SO2, bool DF2 >
8888  friend bool isIntact( const Submatrix<MT2,AF2,SO2,DF2>& sm ) noexcept;
8889 
8890  template< typename MT2, bool AF2, bool SO2, bool DF2 >
8891  friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Matrix<MT2,SO2>& b ) noexcept;
8892 
8893  template< typename MT2, bool AF2, bool SO2, bool DF2 >
8894  friend bool isSame( const Matrix<MT2,SO2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
8895 
8896  template< typename MT2, bool AF2, bool SO2, bool DF2 >
8897  friend bool isSame( const Submatrix<MT2,AF2,SO2,DF2>& a, const Submatrix<MT2,AF2,SO2,DF2>& b ) noexcept;
8898 
8899  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
8900  friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
8901  size_t row, size_t column );
8902 
8903  template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
8904  friend bool tryAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
8905  size_t row, size_t column );
8906 
8907  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
8908  friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
8909  size_t row, size_t column );
8910 
8911  template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
8912  friend bool tryAddAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
8913  size_t row, size_t column );
8914 
8915  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
8916  friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
8917  size_t row, size_t column );
8918 
8919  template< typename MT2, bool AF2, bool SO2, bool DF2, typename MT3, bool SO3 >
8920  friend bool trySubAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Matrix<MT3,SO3>& rhs,
8921  size_t row, size_t column );
8922 
8923  template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF >
8924  friend bool tryMultAssign( const Submatrix<MT2,AF2,SO2,DF2>& lhs, const Vector<VT,TF>& rhs,
8925  size_t row, size_t column );
8926 
8927  template< typename MT2, bool AF2, bool SO2, bool DF2 >
8928  friend DerestrictTrait_< Submatrix<MT2,AF2,SO2,DF2> > derestrict( Submatrix<MT2,AF2,SO2,DF2>& sm );
8929  //**********************************************************************************************
8930 
8931  //**Compile time checks*************************************************************************
8939  //**********************************************************************************************
8940 };
8942 //*************************************************************************************************
8943 
8944 
8945 
8946 
8947 //=================================================================================================
8948 //
8949 // CONSTRUCTOR
8950 //
8951 //=================================================================================================
8952 
8953 //*************************************************************************************************
8967 template< typename MT > // Type of the dense matrix
8968 inline Submatrix<MT,aligned,true,true>::Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n )
8969  : matrix_( matrix ) // The dense matrix containing the submatrix
8970  , row_ ( rindex ) // The first row of the submatrix
8971  , column_( cindex ) // The first column of the submatrix
8972  , m_ ( m ) // The number of rows of the submatrix
8973  , n_ ( n ) // The number of columns of the submatrix
8974 {
8975  if( ( row_ + m_ > matrix_.rows() ) || ( column_ + n_ > matrix_.columns() ) ) {
8976  BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix specification" );
8977  }
8978 
8979  if( ( simdEnabled && matrix_.data() != nullptr && !checkAlignment( data() ) ) ||
8980  ( n_ > 1UL && matrix_.spacing() % SIMDSIZE != 0UL ) ) {
8981  BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix alignment" );
8982  }
8983 }
8985 //*************************************************************************************************
8986 
8987 
8988 
8989 
8990 //=================================================================================================
8991 //
8992 // DATA ACCESS FUNCTIONS
8993 //
8994 //=================================================================================================
8995 
8996 //*************************************************************************************************
9007 template< typename MT > // Type of the dense matrix
9009  Submatrix<MT,aligned,true,true>::operator()( size_t i, size_t j )
9010 {
9011  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
9012  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
9013 
9014  return matrix_(row_+i,column_+j);
9015 }
9017 //*************************************************************************************************
9018 
9019 
9020 //*************************************************************************************************
9031 template< typename MT > // Type of the dense matrix
9033  Submatrix<MT,aligned,true,true>::operator()( size_t i, size_t j ) const
9034 {
9035  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
9036  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
9037 
9038  return const_cast<const MT&>( matrix_ )(row_+i,column_+j);
9039 }
9041 //*************************************************************************************************
9042 
9043 
9044 //*************************************************************************************************
9056 template< typename MT > // Type of the dense matrix
9058  Submatrix<MT,aligned,true,true>::at( size_t i, size_t j )
9059 {
9060  if( i >= rows() ) {
9061  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
9062  }
9063  if( j >= columns() ) {
9064  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
9065  }
9066  return (*this)(i,j);
9067 }
9069 //*************************************************************************************************
9070 
9071 
9072 //*************************************************************************************************
9084 template< typename MT > // Type of the dense matrix
9086  Submatrix<MT,aligned,true,true>::at( size_t i, size_t j ) const
9087 {
9088  if( i >= rows() ) {
9089  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
9090  }
9091  if( j >= columns() ) {
9092  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
9093  }
9094  return (*this)(i,j);
9095 }
9097 //*************************************************************************************************
9098 
9099 
9100 //*************************************************************************************************
9110 template< typename MT > // Type of the dense matrix
9111 inline typename Submatrix<MT,aligned,true,true>::Pointer
9112  Submatrix<MT,aligned,true,true>::data() noexcept
9113 {
9114  return matrix_.data() + row_ + column_*spacing();
9115 }
9117 //*************************************************************************************************
9118 
9119 
9120 //*************************************************************************************************
9130 template< typename MT > // Type of the dense matrix
9131 inline typename Submatrix<MT,aligned,true,true>::ConstPointer
9132  Submatrix<MT,aligned,true,true>::data() const noexcept
9133 {
9134  return matrix_.data() + row_ + column_*spacing();
9135 }
9137 //*************************************************************************************************
9138 
9139 
9140 //*************************************************************************************************
9149 template< typename MT > // Type of the dense matrix
9150 inline typename Submatrix<MT,aligned,true,true>::Pointer
9151  Submatrix<MT,aligned,true,true>::data( size_t j ) noexcept
9152 {
9153  return matrix_.data() + row_ + (column_+j)*spacing();
9154 }
9156 //*************************************************************************************************
9157 
9158 
9159 //*************************************************************************************************
9168 template< typename MT > // Type of the dense matrix
9169 inline typename Submatrix<MT,aligned,true,true>::ConstPointer
9170  Submatrix<MT,aligned,true,true>::data( size_t j ) const noexcept
9171 {
9172  return matrix_.data() + row_ + (column_+j)*spacing();
9173 }
9175 //*************************************************************************************************
9176 
9177 
9178 //*************************************************************************************************
9185 template< typename MT > // Type of the dense matrix
9188 {
9189  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
9190  return ( matrix_.begin( column_ + j ) + row_ );
9191 }
9193 //*************************************************************************************************
9194 
9195 
9196 //*************************************************************************************************
9203 template< typename MT > // Type of the dense matrix
9205  Submatrix<MT,aligned,true,true>::begin( size_t j ) const
9206 {
9207  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
9208  return ( matrix_.cbegin( column_ + j ) + row_ );
9209 }
9211 //*************************************************************************************************
9212 
9213 
9214 //*************************************************************************************************
9221 template< typename MT > // Type of the dense matrix
9223  Submatrix<MT,aligned,true,true>::cbegin( size_t j ) const
9224 {
9225  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
9226  return ( matrix_.cbegin( column_ + j ) + row_ );
9227 }
9229 //*************************************************************************************************
9230 
9231 
9232 //*************************************************************************************************
9239 template< typename MT > // Type of the dense matrix
9242 {
9243  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
9244  return ( matrix_.begin( column_ + j ) + row_ + m_ );
9245 }
9247 //*************************************************************************************************
9248 
9249 
9250 //*************************************************************************************************
9257 template< typename MT > // Type of the dense matrix
9259  Submatrix<MT,aligned,true,true>::end( size_t j ) const
9260 {
9261  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
9262  return ( matrix_.cbegin( column_ + j ) + row_ + m_ );
9263 }
9265 //*************************************************************************************************
9266 
9267 
9268 //*************************************************************************************************
9275 template< typename MT > // Type of the dense matrix
9277  Submatrix<MT,aligned,true,true>::cend( size_t j ) const
9278 {
9279  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
9280  return ( matrix_.cbegin( column_ + j ) + row_ + m_ );
9281 }
9283 //*************************************************************************************************
9284 
9285 
9286 
9287 
9288 //=================================================================================================
9289 //
9290 // ASSIGNMENT OPERATORS
9291 //
9292 //=================================================================================================
9293 
9294 //*************************************************************************************************
9305 template< typename MT > // Type of the dense matrix
9306 inline Submatrix<MT,aligned,true,true>&
9307  Submatrix<MT,aligned,true,true>::operator=( const ElementType& rhs )
9308 {
9309  const size_t jend( column_ + n_ );
9310 
9311  for( size_t j=column_; j<jend; ++j )
9312  {
9313  const size_t ibegin( ( IsLower<MT>::value )
9314  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
9315  ?( max( j+1UL, row_ ) )
9316  :( max( j, row_ ) ) )
9317  :( row_ ) );
9318  const size_t iend ( ( IsUpper<MT>::value )
9319  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
9320  ?( min( j, row_+m_ ) )
9321  :( min( j+1UL, row_+m_ ) ) )
9322  :( row_+m_ ) );
9323 
9324  for( size_t i=ibegin; i<iend; ++i )
9325  matrix_(i,j) = rhs;
9326  }
9327 
9328  return *this;
9329 }
9331 //*************************************************************************************************
9332 
9333 
9334 //*************************************************************************************************
9347 template< typename MT > // Type of the dense matrix
9348 inline Submatrix<MT,aligned,true,true>&
9349  Submatrix<MT,aligned,true,true>::operator=( initializer_list< initializer_list<ElementType> > list )
9350 {
9351  if( list.size() != rows() || determineColumns( list ) > columns() ) {
9352  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to submatrix" );
9353  }
9354 
9355  size_t i( 0UL );
9356 
9357  for( const auto& rowList : list ) {
9358  size_t j( 0UL );
9359  for( const auto& element : rowList ) {
9360  matrix_(row_+i,column_+j) = element;
9361  ++j;
9362  }
9363  for( ; j<n_; ++j ) {
9364  matrix_(row_+i,column_+j) = ElementType();
9365  }
9366  ++i;
9367  }
9368 
9369  return *this;
9370 }
9372 //*************************************************************************************************
9373 
9374 
9375 //*************************************************************************************************
9390 template< typename MT > // Type of the dense matrix
9391 inline Submatrix<MT,aligned,true,true>&
9392  Submatrix<MT,aligned,true,true>::operator=( const Submatrix& rhs )
9393 {
9396 
9397  if( this == &rhs || ( &matrix_ == &rhs.matrix_ && row_ == rhs.row_ && column_ == rhs.column_ ) )
9398  return *this;
9399 
9400  if( rows() != rhs.rows() || columns() != rhs.columns() ) {
9401  BLAZE_THROW_INVALID_ARGUMENT( "Submatrix sizes do not match" );
9402  }
9403 
9404  if( !tryAssign( matrix_, rhs, row_, column_ ) ) {
9405  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
9406  }
9407 
9408  DerestrictTrait_<This> left( derestrict( *this ) );
9409 
9410  if( rhs.canAlias( &matrix_ ) ) {
9411  const ResultType tmp( rhs );
9412  smpAssign( left, tmp );
9413  }
9414  else {
9415  smpAssign( left, rhs );
9416  }
9417 
9418  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
9419 
9420  return *this;
9421 }
9423 //*************************************************************************************************
9424 
9425 
9426 //*************************************************************************************************
9440 template< typename MT > // Type of the dense matrix
9441 template< typename MT2 // Type of the right-hand side matrix
9442  , bool SO > // Storage order of the right-hand side matrix
9443 inline Submatrix<MT,aligned,true,true>&
9444  Submatrix<MT,aligned,true,true>::operator=( const Matrix<MT2,SO>& rhs )
9445 {
9447 
9448  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
9449  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
9450  }
9451 
9452  typedef If_< IsRestricted<MT>, CompositeType_<MT2>, const MT2& > Right;
9453  Right right( ~rhs );
9454 
9455  if( !tryAssign( matrix_, right, row_, column_ ) ) {
9456  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
9457  }
9458 
9459  if( IsSparseMatrix<MT2>::value )
9460  reset();
9461 
9462  DerestrictTrait_<This> left( derestrict( *this ) );
9463 
9464  if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
9465  const ResultType_<MT2> tmp( right );
9466  smpAssign( left, tmp );
9467  }
9468  else {
9469  smpAssign( left, right );
9470  }
9471 
9472  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
9473 
9474  return *this;
9475 }
9477 //*************************************************************************************************
9478 
9479 
9480 //*************************************************************************************************
9494 template< typename MT > // Type of the dense matrix
9495 template< typename MT2 // Type of the right-hand side matrix
9496  , bool SO > // Storage order of the right-hand side matrix
9497 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,true,true>& >
9498  Submatrix<MT,aligned,true,true>::operator+=( const Matrix<MT2,SO>& rhs )
9499 {
9503 
9504  typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
9505 
9508 
9509  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
9510  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
9511  }
9512 
9513  if( !tryAddAssign( matrix_, ~rhs, row_, column_ ) ) {
9514  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
9515  }
9516 
9517  DerestrictTrait_<This> left( derestrict( *this ) );
9518 
9519  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
9520  (~rhs).canAlias( &matrix_ ) ) {
9521  const AddType tmp( *this + (~rhs) );
9522  smpAssign( left, tmp );
9523  }
9524  else {
9525  smpAddAssign( left, ~rhs );
9526  }
9527 
9528  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
9529 
9530  return *this;
9531 }
9533 //*************************************************************************************************
9534 
9535 
9536 //*************************************************************************************************
9550 template< typename MT > // Type of the dense matrix
9551 template< typename MT2 // Type of the right-hand side matrix
9552  , bool SO > // Storage order of the right-hand side matrix
9553 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,true,true>& >
9554  Submatrix<MT,aligned,true,true>::operator+=( const Matrix<MT2,SO>& rhs )
9555 {
9559 
9560  typedef AddTrait_< ResultType, ResultType_<MT2> > AddType;
9561 
9564 
9565  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
9566  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
9567  }
9568 
9569  const AddType tmp( *this + (~rhs) );
9570 
9571  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
9572  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
9573  }
9574 
9575  DerestrictTrait_<This> left( derestrict( *this ) );
9576 
9577  smpAssign( left, tmp );
9578 
9579  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
9580 
9581  return *this;
9582 }
9584 //*************************************************************************************************
9585 
9586 
9587 //*************************************************************************************************
9601 template< typename MT > // Type of the dense matrix
9602 template< typename MT2 // Type of the right-hand side matrix
9603  , bool SO > // Storage order of the right-hand side matrix
9604 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,true,true>& >
9605  Submatrix<MT,aligned,true,true>::operator-=( const Matrix<MT2,SO>& rhs )
9606 {
9610 
9611  typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
9612 
9615 
9616  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
9617  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
9618  }
9619 
9620  if( !trySubAssign( matrix_, ~rhs, row_, column_ ) ) {
9621  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
9622  }
9623 
9624  DerestrictTrait_<This> left( derestrict( *this ) );
9625 
9626  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
9627  (~rhs).canAlias( &matrix_ ) ) {
9628  const SubType tmp( *this - (~rhs ) );
9629  smpAssign( left, tmp );
9630  }
9631  else {
9632  smpSubAssign( left, ~rhs );
9633  }
9634 
9635  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
9636 
9637  return *this;
9638 }
9640 //*************************************************************************************************
9641 
9642 
9643 //*************************************************************************************************
9657 template< typename MT > // Type of the dense matrix
9658 template< typename MT2 // Type of the right-hand side matrix
9659  , bool SO > // Storage order of the right-hand side matrix
9660 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,true,true>& >
9661  Submatrix<MT,aligned,true,true>::operator-=( const Matrix<MT2,SO>& rhs )
9662 {
9666 
9667  typedef SubTrait_< ResultType, ResultType_<MT2> > SubType;
9668 
9671 
9672  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
9673  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
9674  }
9675 
9676  const SubType tmp( *this - (~rhs) );
9677 
9678  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
9679  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
9680  }
9681 
9682  DerestrictTrait_<This> left( derestrict( *this ) );
9683 
9684  smpAssign( left, tmp );
9685 
9686  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
9687 
9688  return *this;
9689 }
9691 //*************************************************************************************************
9692 
9693 
9694 //*************************************************************************************************
9708 template< typename MT > // Type of the dense matrix
9709 template< typename MT2 // Type of the right-hand side matrix
9710  , bool SO > // Storage order of the right-hand side matrix
9711 inline Submatrix<MT,aligned,true,true>&
9712  Submatrix<MT,aligned,true,true>::operator*=( const Matrix<MT2,SO>& rhs )
9713 {
9717 
9718  typedef MultTrait_< ResultType, ResultType_<MT2> > MultType;
9719 
9722 
9723  if( columns() != (~rhs).rows() ) {
9724  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
9725  }
9726 
9727  const MultType tmp( *this * (~rhs) );
9728 
9729  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
9730  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
9731  }
9732 
9733  DerestrictTrait_<This> left( derestrict( *this ) );
9734 
9735  smpAssign( left, tmp );
9736 
9737  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
9738 
9739  return *this;
9740 }
9742 //*************************************************************************************************
9743 
9744 
9745 //*************************************************************************************************
9756 template< typename MT > // Type of the dense matrix
9757 template< typename Other > // Data type of the right-hand side scalar
9758 inline EnableIf_< IsNumeric<Other>, Submatrix<MT,aligned,true,true> >&
9760 {
9762 
9763  DerestrictTrait_<This> left( derestrict( *this ) );
9764  smpAssign( left, (*this) * rhs );
9765 
9766  return *this;
9767 }
9769 //*************************************************************************************************
9770 
9771 
9772 //*************************************************************************************************
9785 template< typename MT > // Type of the dense matrix
9786 template< typename Other > // Data type of the right-hand side scalar
9787 inline EnableIf_< IsNumeric<Other>, Submatrix<MT,aligned,true,true> >&
9789 {
9791 
9792  BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
9793 
9794  DerestrictTrait_<This> left( derestrict( *this ) );
9795  smpAssign( left, (*this) / rhs );
9796 
9797  return *this;
9798 }
9800 //*************************************************************************************************
9801 
9802 
9803 
9804 
9805 //=================================================================================================
9806 //
9807 // UTILITY FUNCTIONS
9808 //
9809 //=================================================================================================
9810 
9811 //*************************************************************************************************
9817 template< typename MT > // Type of the dense matrix
9818 inline size_t Submatrix<MT,aligned,true,true>::row() const noexcept
9819 {
9820  return row_;
9821 }
9823 //*************************************************************************************************
9824 
9825 
9826 //*************************************************************************************************
9832 template< typename MT > // Type of the dense matrix
9833 inline size_t Submatrix<MT,aligned,true,true>::rows() const noexcept
9834 {
9835  return m_;
9836 }
9838 //*************************************************************************************************
9839 
9840 
9841 //*************************************************************************************************
9847 template< typename MT > // Type of the dense matrix
9848 inline size_t Submatrix<MT,aligned,true,true>::column() const noexcept
9849 {
9850  return column_;
9851 }
9853 //*************************************************************************************************
9854 
9855 
9856 //*************************************************************************************************
9862 template< typename MT > // Type of the dense matrix
9863 inline size_t Submatrix<MT,aligned,true,true>::columns() const noexcept
9864 {
9865  return n_;
9866 }
9868 //*************************************************************************************************
9869 
9870 
9871 //*************************************************************************************************
9880 template< typename MT > // Type of the dense matrix
9881 inline size_t Submatrix<MT,aligned,true,true>::spacing() const noexcept
9882 {
9883  return matrix_.spacing();
9884 }
9886 //*************************************************************************************************
9887 
9888 
9889 //*************************************************************************************************
9895 template< typename MT > // Type of the dense matrix
9896 inline size_t Submatrix<MT,aligned,true,true>::capacity() const noexcept
9897 {
9898  return rows() * columns();
9899 }
9901 //*************************************************************************************************
9902 
9903 
9904 //*************************************************************************************************
9911 template< typename MT > // Type of the dense matrix
9912 inline size_t Submatrix<MT,aligned,true,true>::capacity( size_t j ) const noexcept
9913 {
9914  UNUSED_PARAMETER( j );
9915 
9916  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
9917 
9918  return rows();
9919 }
9921 //*************************************************************************************************
9922 
9923 
9924 //*************************************************************************************************
9930 template< typename MT > // Type of the dense matrix
9931 inline size_t Submatrix<MT,aligned,true,true>::nonZeros() const
9932 {
9933  const size_t iend( row_ + m_ );
9934  const size_t jend( column_ + n_ );
9935  size_t nonzeros( 0UL );
9936 
9937  for( size_t j=column_; j<jend; ++j )
9938  for( size_t i=row_; i<iend; ++i )
9939  if( !isDefault( matrix_(i,j) ) )
9940  ++nonzeros;
9941 
9942  return nonzeros;
9943 }
9945 //*************************************************************************************************
9946 
9947 
9948 //*************************************************************************************************
9955 template< typename MT > // Type of the dense matrix
9956 inline size_t Submatrix<MT,aligned,true,true>::nonZeros( size_t j ) const
9957 {
9958  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
9959 
9960  const size_t iend( row_ + m_ );
9961  size_t nonzeros( 0UL );
9962 
9963  for( size_t i=row_; i<iend; ++i )
9964  if( !isDefault( matrix_(i,column_+j) ) )
9965  ++nonzeros;
9966 
9967  return nonzeros;
9968 }
9970 //*************************************************************************************************
9971 
9972 
9973 //*************************************************************************************************
9979 template< typename MT > // Type of the dense matrix
9981 {
9982  using blaze::clear;
9983 
9984  for( size_t j=column_; j<column_+n_; ++j )
9985  {
9986  const size_t ibegin( ( IsLower<MT>::value )
9987  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
9988  ?( max( j+1UL, row_ ) )
9989  :( max( j, row_ ) ) )
9990  :( row_ ) );
9991  const size_t iend ( ( IsUpper<MT>::value )
9992  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
9993  ?( min( j, row_+m_ ) )
9994  :( min( j+1UL, row_+m_ ) ) )
9995  :( row_+m_ ) );
9996 
9997  for( size_t i=ibegin; i<iend; ++i )
9998  clear( matrix_(i,j) );
9999  }
10000 }
10002 //*************************************************************************************************
10003 
10004 
10005 //*************************************************************************************************
10012 template< typename MT > // Type of the dense matrix
10013 inline void Submatrix<MT,aligned,true,true>::reset( size_t j )
10014 {
10015  using blaze::clear;
10016 
10017  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
10018 
10019  const size_t ibegin( ( IsLower<MT>::value )
10020  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
10021  ?( max( j+1UL, row_ ) )
10022  :( max( j, row_ ) ) )
10023  :( row_ ) );
10024  const size_t iend ( ( IsUpper<MT>::value )
10025  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
10026  ?( min( j, row_+m_ ) )
10027  :( min( j+1UL, row_+m_ ) ) )
10028  :( row_+m_ ) );
10029 
10030  for( size_t i=ibegin; i<iend; ++i )
10031  clear( matrix_(i,column_+j) );
10032 }
10034 //*************************************************************************************************
10035 
10036 
10037 //*************************************************************************************************
10055 template< typename MT > // Type of the dense matrix
10056 inline Submatrix<MT,aligned,true,true>& Submatrix<MT,aligned,true,true>::transpose()
10057 {
10058  if( m_ != n_ ) {
10059  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
10060  }
10061 
10062  if( !tryAssign( matrix_, trans( *this ), row_, column_ ) ) {
10063  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
10064  }
10065 
10066  DerestrictTrait_<This> left( derestrict( *this ) );
10067  const ResultType tmp( trans( *this ) );
10068  smpAssign( left, tmp );
10069 
10070  return *this;
10071 }
10073 //*************************************************************************************************
10074 
10075 
10076 //*************************************************************************************************
10094 template< typename MT > // Type of the dense matrix
10095 inline Submatrix<MT,aligned,true,true>& Submatrix<MT,aligned,true,true>::ctranspose()
10096 {
10097  if( m_ != n_ ) {
10098  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
10099  }
10100 
10101  if( !tryAssign( matrix_, ctrans( *this ), row_, column_ ) ) {
10102  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
10103  }
10104 
10105  DerestrictTrait_<This> left( derestrict( *this ) );
10106  const ResultType tmp( ctrans( *this ) );
10107  smpAssign( left, tmp );
10108 
10109  return *this;
10110 }
10112 //*************************************************************************************************
10113 
10114 
10115 //*************************************************************************************************
10126 template< typename MT > // Type of the dense matrix
10127 template< typename Other > // Data type of the scalar value
10128 inline Submatrix<MT,aligned,true,true>& Submatrix<MT,aligned,true,true>::scale( const Other& scalar )
10129 {
10131 
10132  const size_t jend( column_ + n_ );
10133 
10134  for( size_t j=column_; j<jend; ++j )
10135  {
10136  const size_t ibegin( ( IsLower<MT>::value )
10137  ?( ( IsStrictlyLower<MT>::value )
10138  ?( max( j+1UL, row_ ) )
10139  :( max( j, row_ ) ) )
10140  :( row_ ) );
10141  const size_t iend ( ( IsUpper<MT>::value )
10142  ?( ( IsStrictlyUpper<MT>::value )
10143  ?( min( j, row_+m_ ) )
10144  :( min( j+1UL, row_+m_ ) ) )
10145  :( row_+m_ ) );
10146 
10147  for( size_t i=ibegin; i<iend; ++i )
10148  matrix_(i,j) *= scalar;
10149  }
10150 
10151  return *this;
10152 }
10154 //*************************************************************************************************
10155 
10156 
10157 //*************************************************************************************************
10167 template< typename MT > // Type of the dense matrix
10168 inline bool Submatrix<MT,aligned,true,true>::hasOverlap() const noexcept
10169 {
10170  BLAZE_INTERNAL_ASSERT( IsSymmetric<MT>::value || IsHermitian<MT>::value, "Invalid matrix detected" );
10171 
10172  if( ( row_ + m_ <= column_ ) || ( column_ + n_ <= row_ ) )
10173  return false;
10174  else return true;
10175 }
10177 //*************************************************************************************************
10178 
10179 
10180 
10181 
10182 //=================================================================================================
10183 //
10184 // EXPRESSION TEMPLATE EVALUATION FUNCTIONS
10185 //
10186 //=================================================================================================
10187 
10188 //*************************************************************************************************
10199 template< typename MT > // Type of the dense matrix
10200 template< typename Other > // Data type of the foreign expression
10201 inline bool Submatrix<MT,aligned,true,true>::canAlias( const Other* alias ) const noexcept
10202 {
10203  return matrix_.isAliased( alias );
10204 }
10206 //*************************************************************************************************
10207 
10208 
10209 //*************************************************************************************************
10220 template< typename MT > // Type of the dense matrix
10221 template< typename MT2 // Data type of the foreign dense submatrix
10222  , bool AF2 // Alignment flag of the foreign dense submatrix
10223  , bool SO2 > // Storage order of the foreign dense submatrix
10224 inline bool Submatrix<MT,aligned,true,true>::canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
10225 {
10226  return ( matrix_.isAliased( &alias->matrix_ ) &&
10227  ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
10228  ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
10229 }
10231 //*************************************************************************************************
10232 
10233 
10234 //*************************************************************************************************
10245 template< typename MT > // Type of the dense matrix
10246 template< typename Other > // Data type of the foreign expression
10247 inline bool Submatrix<MT,aligned,true,true>::isAliased( const Other* alias ) const noexcept
10248 {
10249  return matrix_.isAliased( alias );
10250 }
10252 //*************************************************************************************************
10253 
10254 
10255 //*************************************************************************************************
10266 template< typename MT > // Type of the dense matrix
10267 template< typename MT2 // Data type of the foreign dense submatrix
10268  , bool AF2 // Alignment flag of the foreign dense submatrix
10269  , bool SO2 > // Storage order of the foreign dense submatrix
10270 inline bool Submatrix<MT,aligned,true,true>::isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
10271 {
10272  return ( matrix_.isAliased( &alias->matrix_ ) &&
10273  ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
10274  ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
10275 }
10277 //*************************************************************************************************
10278 
10279 
10280 //*************************************************************************************************
10290 template< typename MT > // Type of the dense matrix
10291 inline bool Submatrix<MT,aligned,true,true>::isAligned() const noexcept
10292 {
10293  return true;
10294 }
10296 //*************************************************************************************************
10297 
10298 
10299 //*************************************************************************************************
10310 template< typename MT > // Type of the dense matrix
10311 inline bool Submatrix<MT,aligned,true,true>::canSMPAssign() const noexcept
10312 {
10313  return ( rows() * columns() >= SMP_DMATASSIGN_THRESHOLD );
10314 }
10316 //*************************************************************************************************
10317 
10318 
10319 //*************************************************************************************************
10334 template< typename MT > // Type of the dense matrix
10335 BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,true,true>::SIMDType
10336  Submatrix<MT,aligned,true,true>::load( size_t i, size_t j ) const noexcept
10337 {
10338  return loada( i, j );
10339 }
10341 //*************************************************************************************************
10342 
10343 
10344 //*************************************************************************************************
10359 template< typename MT > // Type of the dense matrix
10360 BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,true,true>::SIMDType
10361  Submatrix<MT,aligned,true,true>::loada( size_t i, size_t j ) const noexcept
10362 {
10364 
10365  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
10366  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
10367  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
10368  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
10369 
10370  return matrix_.loada( row_+i, column_+j );
10371 }
10373 //*************************************************************************************************
10374 
10375 
10376 //*************************************************************************************************
10391 template< typename MT > // Type of the dense matrix
10392 BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,true,true>::SIMDType
10393  Submatrix<MT,aligned,true,true>::loadu( size_t i, size_t j ) const noexcept
10394 {
10396 
10397  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
10398  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
10399  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
10400  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
10401 
10402  return matrix_.loadu( row_+i, column_+j );
10403 }
10405 //*************************************************************************************************
10406 
10407 
10408 //*************************************************************************************************
10424 template< typename MT > // Type of the dense matrix
10426  Submatrix<MT,aligned,true,true>::store( size_t i, size_t j, const SIMDType& value ) noexcept
10427 {
10428  storea( i, j, value );
10429 }
10431 //*************************************************************************************************
10432 
10433 
10434 //*************************************************************************************************
10450 template< typename MT > // Type of the dense matrix
10452  Submatrix<MT,aligned,true,true>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
10453 {
10455 
10456  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
10457  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
10458  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
10459  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
10460 
10461  matrix_.storea( row_+i, column_+j, value );
10462 }
10464 //*************************************************************************************************
10465 
10466 
10467 //*************************************************************************************************
10483 template< typename MT > // Type of the dense matrix
10485  Submatrix<MT,aligned,true,true>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
10486 {
10488 
10489  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
10490  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
10491  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
10492  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
10493 
10494  matrix_.storeu( row_+i, column_+j, value );
10495 }
10497 //*************************************************************************************************
10498 
10499 
10500 //*************************************************************************************************
10517 template< typename MT > // Type of the dense matrix
10519  Submatrix<MT,aligned,true,true>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
10520 {
10522 
10523  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
10524  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
10525  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
10526  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
10527 
10528  matrix_.stream( row_+i, column_+j, value );
10529 }
10531 //*************************************************************************************************
10532 
10533 
10534 //*************************************************************************************************
10546 template< typename MT > // Type of the dense matrix
10547 template< typename MT2 > // Type of the right-hand side dense matrix
10548 inline DisableIf_< typename Submatrix<MT,aligned,true,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
10549  Submatrix<MT,aligned,true,true>::assign( const DenseMatrix<MT2,true>& rhs )
10550 {
10551  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
10552  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
10553 
10554  const size_t ipos( m_ & size_t(-2) );
10555  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
10556 
10557  for( size_t j=0UL; j<n_; ++j ) {
10558  for( size_t i=0UL; i<ipos; i+=2UL ) {
10559  matrix_(row_+i ,column_+j) = (~rhs)(i ,j);
10560  matrix_(row_+i+1UL,column_+j) = (~rhs)(i+1UL,j);
10561  }
10562  if( ipos < m_ ) {
10563  matrix_(row_+ipos,column_+j) = (~rhs)(ipos,j);
10564  }
10565  }
10566 }
10568 //*************************************************************************************************
10569 
10570 
10571 //*************************************************************************************************
10583 template< typename MT > // Type of the dense matrix
10584 template< typename MT2 > // Type of the right-hand side dense matrix
10585 inline EnableIf_< typename Submatrix<MT,aligned,true,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
10586  Submatrix<MT,aligned,true,true>::assign( const DenseMatrix<MT2,true>& rhs )
10587 {
10589 
10590  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
10591  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
10592 
10593  const size_t ipos( m_ & size_t(-SIMDSIZE) );
10594  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
10595 
10596  if( useStreaming &&
10597  m_*n_ > ( cacheSize / ( sizeof(ElementType) * 3UL ) ) &&
10598  !(~rhs).isAliased( &matrix_ ) )
10599  {
10600  for( size_t j=0UL; j<n_; ++j )
10601  {
10602  size_t i( 0UL );
10603  Iterator left( begin(j) );
10604  ConstIterator_<MT2> right( (~rhs).begin(j) );
10605 
10606  for( ; i<ipos; i+=SIMDSIZE ) {
10607  left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
10608  }
10609  for( ; i<m_; ++i ) {
10610  *left = *right; ++left; ++right;
10611  }
10612  }
10613  }
10614  else
10615  {
10616  for( size_t j=0UL; j<n_; ++j )
10617  {
10618  size_t i( 0UL );
10619  Iterator left( begin(j) );
10620  ConstIterator_<MT2> right( (~rhs).begin(j) );
10621 
10622  for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
10623  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
10624  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
10625  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
10626  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
10627  }
10628  for( ; i<ipos; i+=SIMDSIZE ) {
10629  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
10630  }
10631  for( ; i<m_; ++i ) {
10632  *left = *right; ++left; ++right;
10633  }
10634  }
10635  }
10636 }
10638 //*************************************************************************************************
10639 
10640 
10641 //*************************************************************************************************
10653 template< typename MT > // Type of the dense matrix
10654 template< typename MT2 > // Type of the right-hand side dense matrix
10655 inline void Submatrix<MT,aligned,true,true>::assign( const DenseMatrix<MT2,false>& rhs )
10656 {
10658 
10659  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
10660  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
10661 
10662  const size_t block( BLOCK_SIZE );
10663 
10664  for( size_t jj=0UL; jj<n_; jj+=block ) {
10665  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
10666  for( size_t ii=0UL; ii<m_; ii+=block ) {
10667  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
10668  for( size_t j=jj; j<jend; ++j ) {
10669  for( size_t i=ii; i<iend; ++i ) {
10670  matrix_(row_+i,column_+j) = (~rhs)(i,j);
10671  }
10672  }
10673  }
10674  }
10675 }
10677 //*************************************************************************************************
10678 
10679 
10680 //*************************************************************************************************
10692 template< typename MT > // Type of the dense matrix
10693 template< typename MT2 > // Type of the right-hand side sparse matrix
10694 inline void Submatrix<MT,aligned,true,true>::assign( const SparseMatrix<MT2,true>& rhs )
10695 {
10696  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
10697  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
10698 
10699  for( size_t j=0UL; j<n_; ++j )
10700  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
10701  matrix_(row_+element->index(),column_+j) = element->value();
10702 }
10704 //*************************************************************************************************
10705 
10706 
10707 //*************************************************************************************************
10719 template< typename MT > // Type of the dense matrix
10720 template< typename MT2 > // Type of the right-hand side sparse matrix
10721 inline void Submatrix<MT,aligned,true,true>::assign( const SparseMatrix<MT2,false>& rhs )
10722 {
10724 
10725  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
10726  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
10727 
10728  for( size_t i=0UL; i<m_; ++i )
10729  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
10730  matrix_(row_+i,column_+element->index()) = element->value();
10731 }
10733 //*************************************************************************************************
10734 
10735 
10736 //*************************************************************************************************
10748 template< typename MT > // Type of the dense matrix
10749 template< typename MT2 > // Type of the right-hand side dense matrix
10750 inline DisableIf_< typename Submatrix<MT,aligned,true,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
10751  Submatrix<MT,aligned,true,true>::addAssign( const DenseMatrix<MT2,true>& rhs )
10752 {
10753  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
10754  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
10755 
10756  const size_t ipos( m_ & size_t(-2) );
10757  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
10758 
10759  for( size_t j=0UL; j<n_; ++j )
10760  {
10761  if( IsDiagonal<MT2>::value ) {
10762  matrix_(row_+j,column_+j) += (~rhs)(j,j);
10763  }
10764  else {
10765  for( size_t i=0UL; i<ipos; i+=2UL ) {
10766  matrix_(row_+i ,column_+j) += (~rhs)(i ,j);
10767  matrix_(row_+i+1UL,column_+j) += (~rhs)(i+1UL,j);
10768  }
10769  if( ipos < m_ ) {
10770  matrix_(row_+ipos,column_+j) += (~rhs)(ipos,j);
10771  }
10772  }
10773  }
10774 }
10776 //*************************************************************************************************
10777 
10778 
10779 //*************************************************************************************************
10791 template< typename MT > // Type of the dense matrix
10792 template< typename MT2 > // Type of the right-hand side dense matrix
10793 inline EnableIf_< typename Submatrix<MT,aligned,true,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
10794  Submatrix<MT,aligned,true,true>::addAssign( const DenseMatrix<MT2,true>& rhs )
10795 {
10797 
10798  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
10799  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
10800 
10801  for( size_t j=0UL; j<n_; ++j )
10802  {
10803  const size_t ibegin( ( IsLower<MT>::value )
10804  ?( ( IsStrictlyLower<MT>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
10805  :( 0UL ) );
10806  const size_t iend ( ( IsUpper<MT>::value )
10807  ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
10808  :( m_ ) );
10809  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
10810 
10811  const size_t ipos( iend & size_t(-SIMDSIZE) );
10812  BLAZE_INTERNAL_ASSERT( ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
10813 
10814  size_t i( ibegin );
10815  Iterator left( begin(j) + ibegin );
10816  ConstIterator_<MT2> right( (~rhs).begin(j) + ibegin );
10817 
10818  for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
10819  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
10820  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
10821  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
10822  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
10823  }
10824  for( ; i<ipos; i+=SIMDSIZE ) {
10825  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
10826  }
10827  for( ; i<iend; ++i ) {
10828  *left += *right; ++left; ++right;
10829  }
10830  }
10831 }
10833 //*************************************************************************************************
10834 
10835 
10836 //*************************************************************************************************
10848 template< typename MT > // Type of the dense matrix
10849 template< typename MT2 > // Type of the right-hand side dense matrix
10850 inline void Submatrix<MT,aligned,true,true>::addAssign( const DenseMatrix<MT2,false>& rhs )
10851 {
10853 
10854  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
10855  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
10856 
10857  const size_t block( BLOCK_SIZE );
10858 
10859  for( size_t jj=0UL; jj<n_; jj+=block ) {
10860  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
10861  for( size_t ii=0UL; ii<m_; ii+=block ) {
10862  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
10863  for( size_t j=jj; j<jend; ++j ) {
10864  for( size_t i=ii; i<iend; ++i ) {
10865  matrix_(row_+i,column_+j) += (~rhs)(i,j);
10866  }
10867  }
10868  }
10869  }
10870 }
10872 //*************************************************************************************************
10873 
10874 
10875 //*************************************************************************************************
10887 template< typename MT > // Type of the dense matrix
10888 template< typename MT2 > // Type of the right-hand side sparse matrix
10889 inline void Submatrix<MT,aligned,true,true>::addAssign( const SparseMatrix<MT2,true>& rhs )
10890 {
10891  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
10892  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
10893 
10894  for( size_t j=0UL; j<n_; ++j )
10895  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
10896  matrix_(row_+element->index(),column_+j) += element->value();
10897 }
10899 //*************************************************************************************************
10900 
10901 
10902 //*************************************************************************************************
10914 template< typename MT > // Type of the dense matrix
10915 template< typename MT2 > // Type of the right-hand side sparse matrix
10916 inline void Submatrix<MT,aligned,true,true>::addAssign( const SparseMatrix<MT2,false>& rhs )
10917 {
10919 
10920  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
10921  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
10922 
10923  for( size_t i=0UL; i<m_; ++i )
10924  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
10925  matrix_(row_+i,column_+element->index()) += element->value();
10926 }
10928 //*************************************************************************************************
10929 
10930 
10931 //*************************************************************************************************
10943 template< typename MT > // Type of the dense matrix
10944 template< typename MT2 > // Type of the right-hand side dense matrix
10945 inline DisableIf_< typename Submatrix<MT,aligned,true,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
10946  Submatrix<MT,aligned,true,true>::subAssign( const DenseMatrix<MT2,true>& rhs )
10947 {
10948  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
10949  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
10950 
10951  const size_t ipos( m_ & size_t(-2) );
10952  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
10953 
10954  for( size_t j=0UL; j<n_; ++j )
10955  {
10956  if( IsDiagonal<MT2>::value ) {
10957  matrix_(row_+j,column_+j) -= (~rhs)(j,j);
10958  }
10959  else {
10960  for( size_t i=0UL; i<ipos; i+=2UL ) {
10961  matrix_(row_+i ,column_+j) -= (~rhs)(i ,j);
10962  matrix_(row_+i+1UL,column_+j) -= (~rhs)(i+1UL,j);
10963  }
10964  if( ipos < m_ ) {
10965  matrix_(row_+ipos,column_+j) -= (~rhs)(ipos,j);
10966  }
10967  }
10968  }
10969 }
10971 //*************************************************************************************************
10972 
10973 
10974 //*************************************************************************************************
10986 template< typename MT > // Type of the dense matrix
10987 template< typename MT2 > // Type of the right-hand side dense matrix
10988 inline EnableIf_< typename Submatrix<MT,aligned,true,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
10989  Submatrix<MT,aligned,true,true>::subAssign( const DenseMatrix<MT2,true>& rhs )
10990 {
10992 
10993  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
10994  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
10995 
10996  for( size_t j=0UL; j<n_; ++j )
10997  {
10998  const size_t ibegin( ( IsLower<MT>::value )
10999  ?( ( IsStrictlyLower<MT>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
11000  :( 0UL ) );
11001  const size_t iend ( ( IsUpper<MT>::value )
11002  ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
11003  :( m_ ) );
11004  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
11005 
11006  const size_t ipos( iend & size_t(-SIMDSIZE) );
11007  BLAZE_INTERNAL_ASSERT( ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
11008 
11009  size_t i( ibegin );
11010  Iterator left( begin(j) + ibegin );
11011  ConstIterator_<MT2> right( (~rhs).begin(j) + ibegin );
11012 
11013  for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
11014  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11015  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11016  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11017  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11018  }
11019  for( ; i<ipos; i+=SIMDSIZE ) {
11020  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11021  }
11022  for( ; i<iend; ++i ) {
11023  *left -= *right; ++left; ++right;
11024  }
11025  }
11026 }
11028 //*************************************************************************************************
11029 
11030 
11031 //*************************************************************************************************
11043 template< typename MT > // Type of the dense matrix
11044 template< typename MT2 > // Type of the right-hand side dense matrix
11045 inline void Submatrix<MT,aligned,true,true>::subAssign( const DenseMatrix<MT2,false>& rhs )
11046 {
11048 
11049  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
11050  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
11051 
11052  const size_t block( BLOCK_SIZE );
11053 
11054  for( size_t jj=0UL; jj<n_; jj+=block ) {
11055  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
11056  for( size_t ii=0UL; ii<m_; ii+=block ) {
11057  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
11058  for( size_t j=jj; j<jend; ++j ) {
11059  for( size_t i=ii; i<iend; ++i ) {
11060  matrix_(row_+i,column_+j) -= (~rhs)(i,j);
11061  }
11062  }
11063  }
11064  }
11065 }
11067 //*************************************************************************************************
11068 
11069 
11070 //*************************************************************************************************
11082 template< typename MT > // Type of the dense matrix
11083 template< typename MT2 > // Type of the right-hand side sparse matrix
11084 inline void Submatrix<MT,aligned,true,true>::subAssign( const SparseMatrix<MT2,true>& rhs )
11085 {
11086  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
11087  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
11088 
11089  for( size_t j=0UL; j<n_; ++j )
11090  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
11091  matrix_(row_+element->index(),column_+j) -= element->value();
11092 }
11094 //*************************************************************************************************
11095 
11096 
11097 //*************************************************************************************************
11109 template< typename MT > // Type of the dense matrix
11110 template< typename MT2 > // Type of the right-hand side sparse matrix
11111 inline void Submatrix<MT,aligned,true,true>::subAssign( const SparseMatrix<MT2,false>& rhs )
11112 {
11114 
11115  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
11116  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
11117 
11118  for( size_t i=0UL; i<m_; ++i )
11119  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
11120  matrix_(row_+i,column_+element->index()) -= element->value();
11121 }
11123 //*************************************************************************************************
11124 
11125 } // namespace blaze
11126 
11127 #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.
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.
const DMatDMatMultExpr< T1, T2 > 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:7800
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:346
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:653
Header file for basic type definitions.
Header file for the View base class.
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:404
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:258
const CTransExprTrait_< MT > ctrans(const DenseMatrix< MT, SO > &dm)
Returns the conjugate transpose matrix of dm.
Definition: DMatForEachExpr.h:1195
#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
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:188
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 sparse matrix.
Definition: CompressedMatrix.h:2805
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:2643
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:1669
bool operator>(const NegativeAccuracy< A > &lhs, const T &rhs)
Greater-than comparison between a NegativeAccuracy object and a floating point value.
Definition: Accuracy.h:366
#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:590
CompressedMatrix< Type, true > This
Type of this CompressedMatrix instance.
Definition: CompressedMatrix.h:2636
#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
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:442
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:384
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:1716
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:2639
DisableIf_< Or< IsComputation< MT >, IsTransExpr< 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:126
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:298
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:232
bool isDefault(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is in default state.
Definition: DiagonalProxy.h:573
Constraint on the data type.
constexpr bool spacing
Adding an additional spacing line between two log messages.This setting gives the opportunity to add ...
Definition: Logging.h:70
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:2647
#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.
Header file for the Not class template.
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:330
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.
#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:2640
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:254
Type ElementType
Type of the sparse matrix elements.
Definition: CompressedMatrix.h:2641
const bool unaligned
Alignment flag for unaligned vectors and matrices.Via this flag it is possible to specify subvectors...
Definition: AlignmentFlag.h:64
Constraint on the data type.
const Type & ConstReference
Reference to a constant matrix value.
Definition: CompressedMatrix.h:2645
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.
DisableIf_< Or< IsComputation< MT >, IsTransExpr< 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:126
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
#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:2642
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:2646
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.
#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:314
SparseMatrix< This, true > BaseType
Base type of this CompressedMatrix instance.
Definition: CompressedMatrix.h:2637
size_t n_
The current number of columns of the sparse matrix.
Definition: CompressedMatrix.h:2806
Header file for the AreSIMDCombinable type trait.
bool operator<(const NegativeAccuracy< A > &lhs, const T &rhs)
Less-than comparison between a NegativeAccuracy object and a floating point value.
Definition: Accuracy.h:328
const DMatTransExpr< MT,!SO > trans(const DenseMatrix< MT, SO > &dm)
Calculation of the transpose of the given dense matrix.
Definition: DMatTransExpr.h:950
Header file for the alignment check function.
bool operator==(const NegativeAccuracy< A > &lhs, const T &rhs)
Equality comparison between a NegativeAccuracy object and a floating point value. ...
Definition: Accuracy.h:249
This ResultType
Result type for expression template evaluations.
Definition: CompressedMatrix.h:2638
bool operator!=(const NegativeAccuracy< A > &lhs, const T &rhs)
Inequality comparison between a NegativeAccuracy object and a floating point value.
Definition: Accuracy.h:289
bool isIntact(const DiagonalMatrix< MT, SO, DF > &m)
Returns whether the invariants of the given diagonal matrix are intact.
Definition: DiagonalMatrix.h:240
MatrixAccessProxy< This > Reference
Reference to a non-constant matrix value.
Definition: CompressedMatrix.h:2644
#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:167
Header file for the IsHermitian type trait.
Header file for the IsRestricted type trait.
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:564