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>
60 #include <blaze/math/shims/Clear.h>
62 #include <blaze/math/shims/Reset.h>
63 #include <blaze/math/SIMD.h>
88 #include <blaze/system/Blocking.h>
89 #include <blaze/system/CacheSize.h>
90 #include <blaze/system/Inline.h>
96 #include <blaze/util/Assert.h>
100 #include <blaze/util/DisableIf.h>
101 #include <blaze/util/EnableIf.h>
102 #include <blaze/util/mpl/And.h>
103 #include <blaze/util/mpl/If.h>
104 #include <blaze/util/mpl/Not.h>
105 #include <blaze/util/mpl/Or.h>
106 #include <blaze/util/Template.h>
107 #include <blaze/util/Types.h>
111 #include <blaze/util/Unused.h>
112 
113 
114 namespace blaze {
115 
116 //=================================================================================================
117 //
118 // CLASS TEMPLATE SPECIALIZATION FOR UNALIGNED ROW-MAJOR DENSE SUBMATRICES
119 //
120 //=================================================================================================
121 
122 //*************************************************************************************************
130 template< typename MT > // Type of the dense matrix
131 class Submatrix<MT,unaligned,false,true>
132  : public View< DenseMatrix< Submatrix<MT,unaligned,false,true>, false > >
133 {
134  private:
135  //**Type definitions****************************************************************************
137  using Operand = If_< IsExpression<MT>, MT, MT& >;
138  //**********************************************************************************************
139 
140  public:
141  //**Type definitions****************************************************************************
142  using This = Submatrix<MT,unaligned,false,true>;
143  using BaseType = DenseMatrix<This,false>;
144  using ResultType = SubmatrixTrait_<MT>;
145  using OppositeType = OppositeType_<ResultType>;
146  using TransposeType = TransposeType_<ResultType>;
147  using ElementType = ElementType_<MT>;
148  using SIMDType = SIMDTrait_<ElementType>;
149  using ReturnType = ReturnType_<MT>;
150  using CompositeType = const Submatrix&;
151 
153  using ConstReference = ConstReference_<MT>;
154 
156  using Reference = If_< IsConst<MT>, ConstReference, Reference_<MT> >;
157 
159  using ConstPointer = const ElementType*;
160 
162  using Pointer = If_< Or< IsConst<MT>, Not< HasMutableDataAccess<MT> > >, ConstPointer, ElementType* >;
163  //**********************************************************************************************
164 
165  //**SubmatrixIterator class definition**********************************************************
168  template< typename IteratorType > // Type of the dense matrix iterator
169  class SubmatrixIterator
170  {
171  public:
172  //**Type definitions*************************************************************************
174  using IteratorCategory = typename std::iterator_traits<IteratorType>::iterator_category;
175 
177  using ValueType = typename std::iterator_traits<IteratorType>::value_type;
178 
180  using PointerType = typename std::iterator_traits<IteratorType>::pointer;
181 
183  using ReferenceType = typename std::iterator_traits<IteratorType>::reference;
184 
186  using DifferenceType = typename std::iterator_traits<IteratorType>::difference_type;
187 
188  // STL iterator requirements
189  using iterator_category = IteratorCategory;
190  using value_type = ValueType;
191  using pointer = PointerType;
192  using reference = ReferenceType;
193  using difference_type = DifferenceType;
194  //*******************************************************************************************
195 
196  //**Constructor******************************************************************************
199  inline SubmatrixIterator()
200  : iterator_ ( ) // Iterator to the current submatrix element
201  , isAligned_( false ) // Memory alignment flag
202  {}
203  //*******************************************************************************************
204 
205  //**Constructor******************************************************************************
211  inline SubmatrixIterator( IteratorType iterator, bool isMemoryAligned )
212  : iterator_ ( iterator ) // Iterator to the current submatrix element
213  , isAligned_( isMemoryAligned ) // Memory alignment flag
214  {}
215  //*******************************************************************************************
216 
217  //**Constructor******************************************************************************
222  template< typename IteratorType2 >
223  inline SubmatrixIterator( const SubmatrixIterator<IteratorType2>& it )
224  : iterator_ ( it.base() ) // Iterator to the current submatrix element
225  , isAligned_( it.isAligned() ) // Memory alignment flag
226  {}
227  //*******************************************************************************************
228 
229  //**Addition assignment operator*************************************************************
235  inline SubmatrixIterator& operator+=( size_t inc ) {
236  iterator_ += inc;
237  return *this;
238  }
239  //*******************************************************************************************
240 
241  //**Subtraction assignment operator**********************************************************
247  inline SubmatrixIterator& operator-=( size_t dec ) {
248  iterator_ -= dec;
249  return *this;
250  }
251  //*******************************************************************************************
252 
253  //**Prefix increment operator****************************************************************
258  inline SubmatrixIterator& operator++() {
259  ++iterator_;
260  return *this;
261  }
262  //*******************************************************************************************
263 
264  //**Postfix increment operator***************************************************************
269  inline const SubmatrixIterator operator++( int ) {
270  return SubmatrixIterator( iterator_++, isAligned_ );
271  }
272  //*******************************************************************************************
273 
274  //**Prefix decrement operator****************************************************************
279  inline SubmatrixIterator& operator--() {
280  --iterator_;
281  return *this;
282  }
283  //*******************************************************************************************
284 
285  //**Postfix decrement operator***************************************************************
290  inline const SubmatrixIterator operator--( int ) {
291  return SubmatrixIterator( iterator_--, isAligned_ );
292  }
293  //*******************************************************************************************
294 
295  //**Element access operator******************************************************************
300  inline ReferenceType operator*() const {
301  return *iterator_;
302  }
303  //*******************************************************************************************
304 
305  //**Load function****************************************************************************
315  inline SIMDType load() const noexcept {
316  if( isAligned_ )
317  return loada();
318  else
319  return loadu();
320  }
321  //*******************************************************************************************
322 
323  //**Loada function***************************************************************************
333  inline SIMDType loada() const noexcept {
334  return iterator_.loada();
335  }
336  //*******************************************************************************************
337 
338  //**Loadu function***************************************************************************
348  inline SIMDType loadu() const noexcept {
349  return iterator_.loadu();
350  }
351  //*******************************************************************************************
352 
353  //**Store function***************************************************************************
364  inline void store( const SIMDType& value ) const {
365  storeu( value );
366  }
367  //*******************************************************************************************
368 
369  //**Storea function**************************************************************************
380  inline void storea( const SIMDType& value ) const {
381  iterator_.storea( value );
382  }
383  //*******************************************************************************************
384 
385  //**Storeu function**************************************************************************
396  inline void storeu( const SIMDType& value ) const {
397  if( isAligned_ ) {
398  iterator_.storea( value );
399  }
400  else {
401  iterator_.storeu( value );
402  }
403  }
404  //*******************************************************************************************
405 
406  //**Stream function**************************************************************************
417  inline void stream( const SIMDType& value ) const {
418  iterator_.stream( value );
419  }
420  //*******************************************************************************************
421 
422  //**Equality operator************************************************************************
428  inline bool operator==( const SubmatrixIterator& rhs ) const {
429  return iterator_ == rhs.iterator_;
430  }
431  //*******************************************************************************************
432 
433  //**Inequality operator**********************************************************************
439  inline bool operator!=( const SubmatrixIterator& rhs ) const {
440  return iterator_ != rhs.iterator_;
441  }
442  //*******************************************************************************************
443 
444  //**Less-than operator***********************************************************************
450  inline bool operator<( const SubmatrixIterator& rhs ) const {
451  return iterator_ < rhs.iterator_;
452  }
453  //*******************************************************************************************
454 
455  //**Greater-than operator********************************************************************
461  inline bool operator>( const SubmatrixIterator& rhs ) const {
462  return iterator_ > rhs.iterator_;
463  }
464  //*******************************************************************************************
465 
466  //**Less-or-equal-than operator**************************************************************
472  inline bool operator<=( const SubmatrixIterator& rhs ) const {
473  return iterator_ <= rhs.iterator_;
474  }
475  //*******************************************************************************************
476 
477  //**Greater-or-equal-than operator***********************************************************
483  inline bool operator>=( const SubmatrixIterator& rhs ) const {
484  return iterator_ >= rhs.iterator_;
485  }
486  //*******************************************************************************************
487 
488  //**Subtraction operator*********************************************************************
494  inline DifferenceType operator-( const SubmatrixIterator& rhs ) const {
495  return iterator_ - rhs.iterator_;
496  }
497  //*******************************************************************************************
498 
499  //**Addition operator************************************************************************
506  friend inline const SubmatrixIterator operator+( const SubmatrixIterator& it, size_t inc ) {
507  return SubmatrixIterator( it.iterator_ + inc, it.isAligned_ );
508  }
509  //*******************************************************************************************
510 
511  //**Addition operator************************************************************************
518  friend inline const SubmatrixIterator operator+( size_t inc, const SubmatrixIterator& it ) {
519  return SubmatrixIterator( it.iterator_ + inc, it.isAligned_ );
520  }
521  //*******************************************************************************************
522 
523  //**Subtraction operator*********************************************************************
530  friend inline const SubmatrixIterator operator-( const SubmatrixIterator& it, size_t dec ) {
531  return SubmatrixIterator( it.iterator_ - dec, it.isAligned_ );
532  }
533  //*******************************************************************************************
534 
535  //**Base function****************************************************************************
540  inline IteratorType base() const {
541  return iterator_;
542  }
543  //*******************************************************************************************
544 
545  //**IsAligned function***********************************************************************
550  inline bool isAligned() const noexcept {
551  return isAligned_;
552  }
553  //*******************************************************************************************
554 
555  private:
556  //**Member variables*************************************************************************
557  IteratorType iterator_;
558  bool isAligned_;
559  //*******************************************************************************************
560  };
561  //**********************************************************************************************
562 
563  //**Type definitions****************************************************************************
565  using ConstIterator = SubmatrixIterator< ConstIterator_<MT> >;
566 
568  using Iterator = If_< IsConst<MT>, ConstIterator, SubmatrixIterator< Iterator_<MT> > >;
569  //**********************************************************************************************
570 
571  //**Compilation flags***************************************************************************
573  enum : bool { simdEnabled = MT::simdEnabled };
574 
576  enum : bool { smpAssignable = MT::smpAssignable };
577  //**********************************************************************************************
578 
579  //**Constructors********************************************************************************
582  explicit inline Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n );
583  // No explicitly declared copy constructor.
585  //**********************************************************************************************
586 
587  //**Destructor**********************************************************************************
588  // No explicitly declared destructor.
589  //**********************************************************************************************
590 
591  //**Data access functions***********************************************************************
594  inline Reference operator()( size_t i, size_t j );
595  inline ConstReference operator()( size_t i, size_t j ) const;
596  inline Reference at( size_t i, size_t j );
597  inline ConstReference at( size_t i, size_t j ) const;
598  inline Pointer data () noexcept;
599  inline ConstPointer data () const noexcept;
600  inline Pointer data ( size_t i ) noexcept;
601  inline ConstPointer data ( size_t i ) const noexcept;
602  inline Iterator begin ( size_t i );
603  inline ConstIterator begin ( size_t i ) const;
604  inline ConstIterator cbegin( size_t i ) const;
605  inline Iterator end ( size_t i );
606  inline ConstIterator end ( size_t i ) const;
607  inline ConstIterator cend ( size_t i ) const;
609  //**********************************************************************************************
610 
611  //**Assignment operators************************************************************************
614  inline Submatrix& operator=( const ElementType& rhs );
615  inline Submatrix& operator=( initializer_list< initializer_list<ElementType> > list );
616  inline Submatrix& operator=( const Submatrix& rhs );
617 
618  template< typename MT2, bool SO2 >
619  inline Submatrix& operator=( const Matrix<MT2,SO2>& rhs );
620 
621  template< typename MT2, bool SO2 >
622  inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
623  operator+=( const Matrix<MT2,SO2>& rhs );
624 
625  template< typename MT2, bool SO2 >
626  inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
627  operator+=( const Matrix<MT2,SO2>& rhs );
628 
629  template< typename MT2, bool SO2 >
630  inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
631  operator-=( const Matrix<MT2,SO2>& rhs );
632 
633  template< typename MT2, bool SO2 >
634  inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
635  operator-=( const Matrix<MT2,SO2>& rhs );
636 
637  template< typename MT2, bool SO2 >
638  inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
639  operator%=( const Matrix<MT2,SO2>& rhs );
640 
641  template< typename MT2, bool SO2 >
642  inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
643  operator%=( const Matrix<MT2,SO2>& rhs );
644 
645  template< typename MT2, bool SO2 >
646  inline Submatrix& operator*=( const Matrix<MT2,SO2>& rhs );
647 
648  template< typename Other >
649  inline EnableIf_< IsNumeric<Other>, Submatrix >& operator*=( Other rhs );
650 
651  template< typename Other >
652  inline EnableIf_< IsNumeric<Other>, Submatrix >& operator/=( Other rhs );
654  //**********************************************************************************************
655 
656  //**Utility functions***************************************************************************
659  inline Operand operand() const noexcept;
660  inline size_t row() const noexcept;
661  inline size_t column() const noexcept;
662  inline size_t rows() const noexcept;
663  inline size_t columns() const noexcept;
664  inline size_t spacing() const noexcept;
665  inline size_t capacity() const noexcept;
666  inline size_t capacity( size_t i ) const noexcept;
667  inline size_t nonZeros() const;
668  inline size_t nonZeros( size_t i ) const;
669  inline void reset();
670  inline void reset( size_t i );
672  //**********************************************************************************************
673 
674  //**Numeric functions***************************************************************************
677  inline Submatrix& transpose();
678  inline Submatrix& ctranspose();
679 
680  template< typename Other > inline Submatrix& scale( const Other& scalar );
682  //**********************************************************************************************
683 
684  private:
685  //**********************************************************************************************
687  template< typename MT2 >
688  struct VectorizedAssign {
689  enum : bool { value = useOptimizedKernels &&
690  simdEnabled && MT2::simdEnabled &&
691  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value };
692  };
693  //**********************************************************************************************
694 
695  //**********************************************************************************************
697  template< typename MT2 >
698  struct VectorizedAddAssign {
699  enum : bool { value = useOptimizedKernels &&
700  simdEnabled && MT2::simdEnabled &&
701  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
702  HasSIMDAdd< ElementType, ElementType_<MT2> >::value &&
703  !IsDiagonal<MT2>::value };
704  };
705  //**********************************************************************************************
706 
707  //**********************************************************************************************
709  template< typename MT2 >
710  struct VectorizedSubAssign {
711  enum : bool { value = useOptimizedKernels &&
712  simdEnabled && MT2::simdEnabled &&
713  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
714  HasSIMDSub< ElementType, ElementType_<MT2> >::value &&
715  !IsDiagonal<MT2>::value };
716  };
717  //**********************************************************************************************
718 
719  //**********************************************************************************************
721  template< typename MT2 >
722  struct VectorizedSchurAssign {
723  enum : bool { value = useOptimizedKernels &&
724  simdEnabled && MT2::simdEnabled &&
725  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
726  HasSIMDMult< ElementType, ElementType_<MT2> >::value };
727  };
728  //**********************************************************************************************
729 
730  //**SIMD properties*****************************************************************************
732  enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
733  //**********************************************************************************************
734 
735  public:
736  //**Expression template evaluation functions****************************************************
739  template< typename Other >
740  inline bool canAlias( const Other* alias ) const noexcept;
741 
742  template< typename MT2, bool AF2, bool SO2 >
743  inline bool canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
744 
745  template< typename Other >
746  inline bool isAliased( const Other* alias ) const noexcept;
747 
748  template< typename MT2, bool AF2, bool SO2 >
749  inline bool isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
750 
751  inline bool isAligned () const noexcept;
752  inline bool canSMPAssign() const noexcept;
753 
754  BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
755  BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
756  BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
757 
758  BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
759  BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
760  BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
761  BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
762 
763  template< typename MT2 >
764  inline DisableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,false>& rhs );
765 
766  template< typename MT2 >
767  inline EnableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,false>& rhs );
768 
769  template< typename MT2 > inline void assign( const DenseMatrix<MT2,true>& rhs );
770  template< typename MT2 > inline void assign( const SparseMatrix<MT2,false>& rhs );
771  template< typename MT2 > inline void assign( const SparseMatrix<MT2,true>& rhs );
772 
773  template< typename MT2 >
774  inline DisableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,false>& rhs );
775 
776  template< typename MT2 >
777  inline EnableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,false>& rhs );
778 
779  template< typename MT2 > inline void addAssign( const DenseMatrix<MT2,true>& rhs );
780  template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,false>& rhs );
781  template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,true>& rhs );
782 
783  template< typename MT2 >
784  inline DisableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,false>& rhs );
785 
786  template< typename MT2 >
787  inline EnableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,false>& rhs );
788 
789  template< typename MT2 > inline void subAssign( const DenseMatrix<MT2,true>& rhs );
790  template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,false>& rhs );
791  template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,true>& rhs );
792 
793  template< typename MT2 >
794  inline DisableIf_< VectorizedSchurAssign<MT2> > schurAssign( const DenseMatrix<MT2,false>& rhs );
795 
796  template< typename MT2 >
797  inline EnableIf_< VectorizedSchurAssign<MT2> > schurAssign( const DenseMatrix<MT2,false>& rhs );
798 
799  template< typename MT2 > inline void schurAssign( const DenseMatrix<MT2,true>& rhs );
800  template< typename MT2 > inline void schurAssign( const SparseMatrix<MT2,false>& rhs );
801  template< typename MT2 > inline void schurAssign( const SparseMatrix<MT2,true>& rhs );
803  //**********************************************************************************************
804 
805  private:
806  //**Utility functions***************************************************************************
809  inline bool hasOverlap() const noexcept;
811  //**********************************************************************************************
812 
813  //**Member variables****************************************************************************
816  Operand matrix_;
817  const size_t row_;
818  const size_t column_;
819  const size_t m_;
820  const size_t n_;
821  const bool isAligned_;
822 
829  //**********************************************************************************************
830 
831  //**Friend declarations*************************************************************************
832  template< typename MT2, bool AF2, bool SO2, bool DF2 > friend class Submatrix;
833  //**********************************************************************************************
834 
835  //**Compile time checks*************************************************************************
843  //**********************************************************************************************
844 };
846 //*************************************************************************************************
847 
848 
849 
850 
851 //=================================================================================================
852 //
853 // CONSTRUCTOR
854 //
855 //=================================================================================================
856 
857 //*************************************************************************************************
871 template< typename MT > // Type of the dense matrix
872 inline Submatrix<MT,unaligned,false,true>::Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n )
873  : matrix_ ( matrix ) // The dense matrix containing the submatrix
874  , row_ ( rindex ) // The first row of the submatrix
875  , column_ ( cindex ) // The first column of the submatrix
876  , m_ ( m ) // The number of rows of the submatrix
877  , n_ ( n ) // The number of columns of the submatrix
878  , isAligned_( simdEnabled && matrix.data() != nullptr && checkAlignment( data() ) &&
879  ( m < 2UL || ( matrix.spacing() & size_t(-SIMDSIZE) ) == 0UL ) )
880 {
881  if( ( row_ + m_ > matrix_.rows() ) || ( column_ + n_ > matrix_.columns() ) ) {
882  BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix specification" );
883  }
884 }
886 //*************************************************************************************************
887 
888 
889 
890 
891 //=================================================================================================
892 //
893 // DATA ACCESS FUNCTIONS
894 //
895 //=================================================================================================
896 
897 //*************************************************************************************************
908 template< typename MT > // Type of the dense matrix
910  Submatrix<MT,unaligned,false,true>::operator()( size_t i, size_t j )
911 {
912  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
913  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
914 
915  return matrix_(row_+i,column_+j);
916 }
918 //*************************************************************************************************
919 
920 
921 //*************************************************************************************************
932 template< typename MT > // Type of the dense matrix
934  Submatrix<MT,unaligned,false,true>::operator()( size_t i, size_t j ) const
935 {
936  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
937  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
938 
939  return const_cast<const MT&>( matrix_ )(row_+i,column_+j);
940 }
942 //*************************************************************************************************
943 
944 
945 //*************************************************************************************************
957 template< typename MT > // Type of the dense matrix
959  Submatrix<MT,unaligned,false,true>::at( size_t i, size_t j )
960 {
961  if( i >= rows() ) {
962  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
963  }
964  if( j >= columns() ) {
965  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
966  }
967  return (*this)(i,j);
968 }
970 //*************************************************************************************************
971 
972 
973 //*************************************************************************************************
985 template< typename MT > // Type of the dense matrix
987  Submatrix<MT,unaligned,false,true>::at( size_t i, size_t j ) const
988 {
989  if( i >= rows() ) {
990  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
991  }
992  if( j >= columns() ) {
993  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
994  }
995  return (*this)(i,j);
996 }
998 //*************************************************************************************************
999 
1000 
1001 //*************************************************************************************************
1011 template< typename MT > // Type of the dense matrix
1012 inline typename Submatrix<MT,unaligned,false,true>::Pointer
1013  Submatrix<MT,unaligned,false,true>::data() noexcept
1014 {
1015  return matrix_.data() + row_*spacing() + column_;
1016 }
1018 //*************************************************************************************************
1019 
1020 
1021 //*************************************************************************************************
1031 template< typename MT > // Type of the dense matrix
1032 inline typename Submatrix<MT,unaligned,false,true>::ConstPointer
1033  Submatrix<MT,unaligned,false,true>::data() const noexcept
1034 {
1035  return matrix_.data() + row_*spacing() + column_;
1036 }
1038 //*************************************************************************************************
1039 
1040 
1041 //*************************************************************************************************
1050 template< typename MT > // Type of the dense matrix
1051 inline typename Submatrix<MT,unaligned,false,true>::Pointer
1052  Submatrix<MT,unaligned,false,true>::data( size_t i ) noexcept
1053 {
1054  return matrix_.data() + (row_+i)*spacing() + column_;
1055 }
1057 //*************************************************************************************************
1058 
1059 
1060 //*************************************************************************************************
1069 template< typename MT > // Type of the dense matrix
1070 inline typename Submatrix<MT,unaligned,false,true>::ConstPointer
1071  Submatrix<MT,unaligned,false,true>::data( size_t i ) const noexcept
1072 {
1073  return matrix_.data() + (row_+i)*spacing() + column_;
1074 }
1076 //*************************************************************************************************
1077 
1078 
1079 //*************************************************************************************************
1091 template< typename MT > // Type of the dense matrix
1094 {
1095  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
1096  return Iterator( matrix_.begin( row_ + i ) + column_, isAligned_ );
1097 }
1099 //*************************************************************************************************
1100 
1101 
1102 //*************************************************************************************************
1114 template< typename MT > // Type of the dense matrix
1117 {
1118  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
1119  return ConstIterator( matrix_.cbegin( row_ + i ) + column_, isAligned_ );
1120 }
1122 //*************************************************************************************************
1123 
1124 
1125 //*************************************************************************************************
1137 template< typename MT > // Type of the dense matrix
1140 {
1141  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
1142  return ConstIterator( matrix_.cbegin( row_ + i ) + column_, isAligned_ );
1143 }
1145 //*************************************************************************************************
1146 
1147 
1148 //*************************************************************************************************
1160 template< typename MT > // Type of the dense matrix
1163 {
1164  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
1165  return Iterator( matrix_.begin( row_ + i ) + column_ + n_, isAligned_ );
1166 }
1168 //*************************************************************************************************
1169 
1170 
1171 //*************************************************************************************************
1183 template< typename MT > // Type of the dense matrix
1185  Submatrix<MT,unaligned,false,true>::end( size_t i ) const
1186 {
1187  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
1188  return ConstIterator( matrix_.cbegin( row_ + i ) + column_ + n_, isAligned_ );
1189 }
1191 //*************************************************************************************************
1192 
1193 
1194 //*************************************************************************************************
1206 template< typename MT > // Type of the dense matrix
1209 {
1210  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
1211  return ConstIterator( matrix_.cbegin( row_ + i ) + column_ + n_, isAligned_ );
1212 }
1214 //*************************************************************************************************
1215 
1216 
1217 
1218 
1219 //=================================================================================================
1220 //
1221 // ASSIGNMENT OPERATORS
1222 //
1223 //=================================================================================================
1224 
1225 //*************************************************************************************************
1236 template< typename MT > // Type of the dense matrix
1237 inline Submatrix<MT,unaligned,false,true>&
1238  Submatrix<MT,unaligned,false,true>::operator=( const ElementType& rhs )
1239 {
1240  const size_t iend( row_ + m_ );
1241 
1242  for( size_t i=row_; i<iend; ++i )
1243  {
1244  const size_t jbegin( ( IsUpper<MT>::value )
1245  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
1246  ?( max( i+1UL, column_ ) )
1247  :( max( i, column_ ) ) )
1248  :( column_ ) );
1249  const size_t jend ( ( IsLower<MT>::value )
1250  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
1251  ?( min( i, column_+n_ ) )
1252  :( min( i+1UL, column_+n_ ) ) )
1253  :( column_+n_ ) );
1254 
1255  for( size_t j=jbegin; j<jend; ++j )
1256  matrix_(i,j) = rhs;
1257  }
1258 
1259  return *this;
1260 }
1262 //*************************************************************************************************
1263 
1264 
1265 //*************************************************************************************************
1278 template< typename MT > // Type of the dense matrix
1279 inline Submatrix<MT,unaligned,false,true>&
1280  Submatrix<MT,unaligned,false,true>::operator=( initializer_list< initializer_list<ElementType> > list )
1281 {
1282  if( list.size() != rows() || determineColumns( list ) > columns() ) {
1283  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to submatrix" );
1284  }
1285 
1286  size_t i( 0UL );
1287 
1288  for( const auto& rowList : list ) {
1289  std::fill( std::copy( rowList.begin(), rowList.end(), begin(i) ), end(i), ElementType() );
1290  ++i;
1291  }
1292 
1293  return *this;
1294 }
1296 //*************************************************************************************************
1297 
1298 
1299 //*************************************************************************************************
1314 template< typename MT > // Type of the dense matrix
1315 inline Submatrix<MT,unaligned,false,true>&
1316  Submatrix<MT,unaligned,false,true>::operator=( const Submatrix& rhs )
1317 {
1320 
1321  if( this == &rhs || ( &matrix_ == &rhs.matrix_ && row_ == rhs.row_ && column_ == rhs.column_ ) )
1322  return *this;
1323 
1324  if( rows() != rhs.rows() || columns() != rhs.columns() ) {
1325  BLAZE_THROW_INVALID_ARGUMENT( "Submatrix sizes do not match" );
1326  }
1327 
1328  if( !tryAssign( matrix_, rhs, row_, column_ ) ) {
1329  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1330  }
1331 
1332  decltype(auto) left( derestrict( *this ) );
1333 
1334  if( rhs.canAlias( &matrix_ ) ) {
1335  const ResultType tmp( rhs );
1336  smpAssign( left, tmp );
1337  }
1338  else {
1339  smpAssign( left, rhs );
1340  }
1341 
1342  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1343 
1344  return *this;
1345 }
1347 //*************************************************************************************************
1348 
1349 
1350 //*************************************************************************************************
1365 template< typename MT > // Type of the dense matrix
1366 template< typename MT2 // Type of the right-hand side matrix
1367  , bool SO2 > // Storage order of the right-hand side matrix
1368 inline Submatrix<MT,unaligned,false,true>&
1369  Submatrix<MT,unaligned,false,true>::operator=( const Matrix<MT2,SO2>& rhs )
1370 {
1372 
1373  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
1374  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1375  }
1376 
1377  using Right = If_< IsRestricted<MT>, CompositeType_<MT2>, const MT2& >;
1378  Right right( ~rhs );
1379 
1380  if( !tryAssign( matrix_, right, row_, column_ ) ) {
1381  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1382  }
1383 
1384  if( IsSparseMatrix<MT2>::value ) {
1385  reset();
1386  }
1387 
1388  decltype(auto) left( derestrict( *this ) );
1389 
1390  if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
1391  const ResultType_<MT2> tmp( right );
1392  smpAssign( left, tmp );
1393  }
1394  else {
1395  smpAssign( left, right );
1396  }
1397 
1398  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1399 
1400  return *this;
1401 }
1403 //*************************************************************************************************
1404 
1405 
1406 //*************************************************************************************************
1420 template< typename MT > // Type of the dense matrix
1421 template< typename MT2 // Type of the right-hand side matrix
1422  , bool SO2 > // Storage order of the right-hand side matrix
1423 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,false,true>& >
1424  Submatrix<MT,unaligned,false,true>::operator+=( const Matrix<MT2,SO2>& rhs )
1425 {
1429 
1430  using AddType = AddTrait_< ResultType, ResultType_<MT2> >;
1431 
1434 
1435  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
1436  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1437  }
1438 
1439  if( !tryAddAssign( matrix_, ~rhs, row_, column_ ) ) {
1440  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1441  }
1442 
1443  decltype(auto) left( derestrict( *this ) );
1444 
1445  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
1446  (~rhs).canAlias( &matrix_ ) ) {
1447  const AddType tmp( *this + (~rhs) );
1448  smpAssign( left, tmp );
1449  }
1450  else {
1451  smpAddAssign( left, ~rhs );
1452  }
1453 
1454  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1455 
1456  return *this;
1457 }
1459 //*************************************************************************************************
1460 
1461 
1462 //*************************************************************************************************
1476 template< typename MT > // Type of the dense matrix
1477 template< typename MT2 // Type of the right-hand side matrix
1478  , bool SO2 > // Storage order of the right-hand side matrix
1479 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,false,true>& >
1480  Submatrix<MT,unaligned,false,true>::operator+=( const Matrix<MT2,SO2>& rhs )
1481 {
1485 
1486  using AddType = AddTrait_< ResultType, ResultType_<MT2> >;
1487 
1490 
1491  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
1492  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1493  }
1494 
1495  const AddType tmp( *this + (~rhs) );
1496 
1497  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
1498  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1499  }
1500 
1501  decltype(auto) left( derestrict( *this ) );
1502 
1503  smpAssign( left, tmp );
1504 
1505  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1506 
1507  return *this;
1508 }
1510 //*************************************************************************************************
1511 
1512 
1513 //*************************************************************************************************
1527 template< typename MT > // Type of the dense matrix
1528 template< typename MT2 // Type of the right-hand side matrix
1529  , bool SO2 > // Storage order of the right-hand side matrix
1530 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,false,true>& >
1531  Submatrix<MT,unaligned,false,true>::operator-=( const Matrix<MT2,SO2>& rhs )
1532 {
1536 
1537  using SubType = SubTrait_< ResultType, ResultType_<MT2> >;
1538 
1541 
1542  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
1543  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1544  }
1545 
1546  if( !trySubAssign( matrix_, ~rhs, row_, column_ ) ) {
1547  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1548  }
1549 
1550  decltype(auto) left( derestrict( *this ) );
1551 
1552  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
1553  (~rhs).canAlias( &matrix_ ) ) {
1554  const SubType tmp( *this - (~rhs ) );
1555  smpAssign( left, tmp );
1556  }
1557  else {
1558  smpSubAssign( left, ~rhs );
1559  }
1560 
1561  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1562 
1563  return *this;
1564 }
1566 //*************************************************************************************************
1567 
1568 
1569 //*************************************************************************************************
1583 template< typename MT > // Type of the dense matrix
1584 template< typename MT2 // Type of the right-hand side matrix
1585  , bool SO2 > // Storage order of the right-hand side matrix
1586 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,false,true>& >
1587  Submatrix<MT,unaligned,false,true>::operator-=( const Matrix<MT2,SO2>& rhs )
1588 {
1592 
1593  using SubType = SubTrait_< ResultType, ResultType_<MT2> >;
1594 
1597 
1598  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
1599  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1600  }
1601 
1602  const SubType tmp( *this - (~rhs) );
1603 
1604  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
1605  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1606  }
1607 
1608  decltype(auto) left( derestrict( *this ) );
1609 
1610  smpAssign( left, tmp );
1611 
1612  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1613 
1614  return *this;
1615 }
1617 //*************************************************************************************************
1618 
1619 
1620 //*************************************************************************************************
1634 template< typename MT > // Type of the dense matrix
1635 template< typename MT2 // Type of the right-hand side matrix
1636  , bool SO2 > // Storage order of the right-hand side matrix
1637 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,false,true>& >
1638  Submatrix<MT,unaligned,false,true>::operator%=( const Matrix<MT2,SO2>& rhs )
1639 {
1643 
1644  using SchurType = SchurTrait_< ResultType, ResultType_<MT2> >;
1645 
1647 
1648  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
1649  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1650  }
1651 
1652  if( !trySchurAssign( matrix_, ~rhs, row_, column_ ) ) {
1653  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1654  }
1655 
1656  decltype(auto) left( derestrict( *this ) );
1657 
1658  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
1659  (~rhs).canAlias( &matrix_ ) ) {
1660  const SchurType tmp( *this % (~rhs) );
1661  if( IsSparseMatrix<SchurType>::value )
1662  reset();
1663  smpAssign( left, tmp );
1664  }
1665  else {
1666  smpSchurAssign( left, ~rhs );
1667  }
1668 
1669  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1670 
1671  return *this;
1672 }
1674 //*************************************************************************************************
1675 
1676 
1677 //*************************************************************************************************
1691 template< typename MT > // Type of the dense matrix
1692 template< typename MT2 // Type of the right-hand side matrix
1693  , bool SO2 > // Storage order of the right-hand side matrix
1694 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,false,true>& >
1695  Submatrix<MT,unaligned,false,true>::operator%=( const Matrix<MT2,SO2>& rhs )
1696 {
1700 
1701  using SchurType = SchurTrait_< ResultType, ResultType_<MT2> >;
1702 
1704 
1705  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
1706  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1707  }
1708 
1709  const SchurType tmp( *this % (~rhs) );
1710 
1711  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
1712  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1713  }
1714 
1715  if( IsSparseMatrix<SchurType>::value ) {
1716  reset();
1717  }
1718 
1719  decltype(auto) left( derestrict( *this ) );
1720 
1721  smpAssign( left, tmp );
1722 
1723  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1724 
1725  return *this;
1726 }
1728 //*************************************************************************************************
1729 
1730 
1731 //*************************************************************************************************
1745 template< typename MT > // Type of the dense matrix
1746 template< typename MT2 // Type of the right-hand side matrix
1747  , bool SO2 > // Storage order of the right-hand side matrix
1748 inline Submatrix<MT,unaligned,false,true>&
1749  Submatrix<MT,unaligned,false,true>::operator*=( const Matrix<MT2,SO2>& rhs )
1750 {
1754 
1755  using MultType = MultTrait_< ResultType, ResultType_<MT2> >;
1756 
1759 
1760  if( columns() != (~rhs).rows() ) {
1761  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1762  }
1763 
1764  const MultType tmp( *this * (~rhs) );
1765 
1766  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
1767  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1768  }
1769 
1770  decltype(auto) left( derestrict( *this ) );
1771 
1772  smpAssign( left, tmp );
1773 
1774  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1775 
1776  return *this;
1777 }
1779 //*************************************************************************************************
1780 
1781 
1782 //*************************************************************************************************
1793 template< typename MT > // Type of the dense matrix
1794 template< typename Other > // Data type of the right-hand side scalar
1795 inline EnableIf_< IsNumeric<Other>, Submatrix<MT,unaligned,false,true> >&
1796  Submatrix<MT,unaligned,false,true>::operator*=( Other rhs )
1797 {
1799 
1800  decltype(auto) left( derestrict( *this ) );
1801  smpAssign( left, (*this) * rhs );
1802 
1803  return *this;
1804 }
1806 //*************************************************************************************************
1807 
1808 
1809 //*************************************************************************************************
1822 template< typename MT > // Type of the dense matrix
1823 template< typename Other > // Data type of the right-hand side scalar
1824 inline EnableIf_< IsNumeric<Other>, Submatrix<MT,unaligned,false,true> >&
1825  Submatrix<MT,unaligned,false,true>::operator/=( Other rhs )
1826 {
1828 
1829  BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
1830 
1831  decltype(auto) left( derestrict( *this ) );
1832  smpAssign( left, (*this) / rhs );
1833 
1834  return *this;
1835 }
1837 //*************************************************************************************************
1838 
1839 
1840 
1841 
1842 //=================================================================================================
1843 //
1844 // UTILITY FUNCTIONS
1845 //
1846 //=================================================================================================
1847 
1848 //*************************************************************************************************
1854 template< typename MT > // Type of the dense matrix
1855 inline typename Submatrix<MT,unaligned,false,true>::Operand
1856  Submatrix<MT,unaligned,false,true>::operand() const noexcept
1857 {
1858  return matrix_;
1859 }
1861 //*************************************************************************************************
1862 
1863 
1864 //*************************************************************************************************
1870 template< typename MT > // Type of the dense matrix
1871 inline size_t Submatrix<MT,unaligned,false,true>::row() const noexcept
1872 {
1873  return row_;
1874 }
1876 //*************************************************************************************************
1877 
1878 
1879 //*************************************************************************************************
1885 template< typename MT > // Type of the dense matrix
1886 inline size_t Submatrix<MT,unaligned,false,true>::column() const noexcept
1887 {
1888  return column_;
1889 }
1890 //*************************************************************************************************
1891 
1892 
1893 //*************************************************************************************************
1899 template< typename MT > // Type of the dense matrix
1900 inline size_t Submatrix<MT,unaligned,false,true>::rows() const noexcept
1901 {
1902  return m_;
1903 }
1905 //*************************************************************************************************
1906 
1907 
1908 //*************************************************************************************************
1914 template< typename MT > // Type of the dense matrix
1915 inline size_t Submatrix<MT,unaligned,false,true>::columns() const noexcept
1916 {
1917  return n_;
1918 }
1920 //*************************************************************************************************
1921 
1922 
1923 //*************************************************************************************************
1934 template< typename MT > // Type of the dense matrix
1935 inline size_t Submatrix<MT,unaligned,false,true>::spacing() const noexcept
1936 {
1937  return matrix_.spacing();
1938 }
1939 //*************************************************************************************************
1940 
1941 
1942 //*************************************************************************************************
1948 template< typename MT > // Type of the dense matrix
1949 inline size_t Submatrix<MT,unaligned,false,true>::capacity() const noexcept
1950 {
1951  return rows() * columns();
1952 }
1954 //*************************************************************************************************
1955 
1956 
1957 //*************************************************************************************************
1969 template< typename MT > // Type of the dense matrix
1970 inline size_t Submatrix<MT,unaligned,false,true>::capacity( size_t i ) const noexcept
1971 {
1972  UNUSED_PARAMETER( i );
1973 
1974  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
1975 
1976  return columns();
1977 }
1979 //*************************************************************************************************
1980 
1981 
1982 //*************************************************************************************************
1988 template< typename MT > // Type of the dense matrix
1990 {
1991  const size_t iend( row_ + m_ );
1992  const size_t jend( column_ + n_ );
1993  size_t nonzeros( 0UL );
1994 
1995  for( size_t i=row_; i<iend; ++i )
1996  for( size_t j=column_; j<jend; ++j )
1997  if( !isDefault( matrix_(i,j) ) )
1998  ++nonzeros;
1999 
2000  return nonzeros;
2001 }
2003 //*************************************************************************************************
2004 
2005 
2006 //*************************************************************************************************
2018 template< typename MT > // Type of the dense matrix
2019 inline size_t Submatrix<MT,unaligned,false,true>::nonZeros( size_t i ) const
2020 {
2021  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
2022 
2023  const size_t jend( column_ + n_ );
2024  size_t nonzeros( 0UL );
2025 
2026  for( size_t j=column_; j<jend; ++j )
2027  if( !isDefault( matrix_(row_+i,j) ) )
2028  ++nonzeros;
2029 
2030  return nonzeros;
2031 }
2033 //*************************************************************************************************
2034 
2035 
2036 //*************************************************************************************************
2042 template< typename MT > // Type of the dense matrix
2044 {
2045  using blaze::clear;
2046 
2047  for( size_t i=row_; i<row_+m_; ++i )
2048  {
2049  const size_t jbegin( ( IsUpper<MT>::value )
2050  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
2051  ?( max( i+1UL, column_ ) )
2052  :( max( i, column_ ) ) )
2053  :( column_ ) );
2054  const size_t jend ( ( IsLower<MT>::value )
2055  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
2056  ?( min( i, column_+n_ ) )
2057  :( min( i+1UL, column_+n_ ) ) )
2058  :( column_+n_ ) );
2059 
2060  for( size_t j=jbegin; j<jend; ++j )
2061  clear( matrix_(i,j) );
2062  }
2063 }
2065 //*************************************************************************************************
2066 
2067 
2068 //*************************************************************************************************
2080 template< typename MT > // Type of the dense matrix
2081 inline void Submatrix<MT,unaligned,false,true>::reset( size_t i )
2082 {
2083  using blaze::clear;
2084 
2085  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
2086 
2087  const size_t jbegin( ( IsUpper<MT>::value )
2088  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
2089  ?( max( i+1UL, column_ ) )
2090  :( max( i, column_ ) ) )
2091  :( column_ ) );
2092  const size_t jend ( ( IsLower<MT>::value )
2093  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
2094  ?( min( i, column_+n_ ) )
2095  :( min( i+1UL, column_+n_ ) ) )
2096  :( column_+n_ ) );
2097 
2098  for( size_t j=jbegin; j<jend; ++j )
2099  clear( matrix_(row_+i,j) );
2100 }
2102 //*************************************************************************************************
2103 
2104 
2105 //*************************************************************************************************
2115 template< typename MT > // Type of the dense matrix
2116 inline bool Submatrix<MT,unaligned,false,true>::hasOverlap() const noexcept
2117 {
2118  BLAZE_INTERNAL_ASSERT( IsSymmetric<MT>::value || IsHermitian<MT>::value, "Invalid matrix detected" );
2119 
2120  if( ( row_ + m_ <= column_ ) || ( column_ + n_ <= row_ ) )
2121  return false;
2122  else return true;
2123 }
2125 //*************************************************************************************************
2126 
2127 
2128 
2129 
2130 //=================================================================================================
2131 //
2132 // NUMERIC FUNCTIONS
2133 //
2134 //=================================================================================================
2135 
2136 //*************************************************************************************************
2154 template< typename MT > // Type of the dense matrix
2155 inline Submatrix<MT,unaligned,false,true>& Submatrix<MT,unaligned,false,true>::transpose()
2156 {
2157  if( m_ != n_ ) {
2158  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
2159  }
2160 
2161  if( !tryAssign( matrix_, trans( *this ), row_, column_ ) ) {
2162  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
2163  }
2164 
2165  decltype(auto) left( derestrict( *this ) );
2166  const ResultType tmp( trans( *this ) );
2167  smpAssign( left, tmp );
2168 
2169  return *this;
2170 }
2172 //*************************************************************************************************
2173 
2174 
2175 //*************************************************************************************************
2193 template< typename MT > // Type of the dense matrix
2194 inline Submatrix<MT,unaligned,false,true>& Submatrix<MT,unaligned,false,true>::ctranspose()
2195 {
2196  if( m_ != n_ ) {
2197  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
2198  }
2199 
2200  if( !tryAssign( matrix_, ctrans( *this ), row_, column_ ) ) {
2201  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
2202  }
2203 
2204  decltype(auto) left( derestrict( *this ) );
2205  const ResultType tmp( ctrans( *this ) );
2206  smpAssign( left, tmp );
2207 
2208  return *this;
2209 }
2211 //*************************************************************************************************
2212 
2213 
2214 //*************************************************************************************************
2227 template< typename MT > // Type of the dense matrix
2228 template< typename Other > // Data type of the scalar value
2229 inline Submatrix<MT,unaligned,false,true>&
2230  Submatrix<MT,unaligned,false,true>::scale( const Other& scalar )
2231 {
2233 
2234  const size_t iend( row_ + m_ );
2235 
2236  for( size_t i=row_; i<iend; ++i )
2237  {
2238  const size_t jbegin( ( IsUpper<MT>::value )
2239  ?( ( IsStrictlyUpper<MT>::value )
2240  ?( max( i+1UL, column_ ) )
2241  :( max( i, column_ ) ) )
2242  :( column_ ) );
2243  const size_t jend ( ( IsLower<MT>::value )
2244  ?( ( IsStrictlyLower<MT>::value )
2245  ?( min( i, column_+n_ ) )
2246  :( min( i+1UL, column_+n_ ) ) )
2247  :( column_+n_ ) );
2248 
2249  for( size_t j=jbegin; j<jend; ++j )
2250  matrix_(i,j) *= scalar;
2251  }
2252 
2253  return *this;
2254 }
2256 //*************************************************************************************************
2257 
2258 
2259 
2260 
2261 //=================================================================================================
2262 //
2263 // EXPRESSION TEMPLATE EVALUATION FUNCTIONS
2264 //
2265 //=================================================================================================
2266 
2267 //*************************************************************************************************
2278 template< typename MT > // Type of the dense matrix
2279 template< typename Other > // Data type of the foreign expression
2280 inline bool Submatrix<MT,unaligned,false,true>::canAlias( const Other* alias ) const noexcept
2281 {
2282  return matrix_.isAliased( alias );
2283 }
2285 //*************************************************************************************************
2286 
2287 
2288 //*************************************************************************************************
2299 template< typename MT > // Type of the dense matrix
2300 template< typename MT2 // Data type of the foreign dense submatrix
2301  , bool AF2 // Alignment flag of the foreign dense submatrix
2302  , bool SO2 > // Storage order of the foreign dense submatrix
2303 inline bool Submatrix<MT,unaligned,false,true>::canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
2304 {
2305  return ( matrix_.isAliased( &alias->matrix_ ) &&
2306  ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
2307  ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
2308 }
2310 //*************************************************************************************************
2311 
2312 
2313 //*************************************************************************************************
2324 template< typename MT > // Type of the dense matrix
2325 template< typename Other > // Data type of the foreign expression
2326 inline bool Submatrix<MT,unaligned,false,true>::isAliased( const Other* alias ) const noexcept
2327 {
2328  return matrix_.isAliased( alias );
2329 }
2331 //*************************************************************************************************
2332 
2333 
2334 //*************************************************************************************************
2345 template< typename MT > // Type of the dense matrix
2346 template< typename MT2 // Data type of the foreign dense submatrix
2347  , bool AF2 // Alignment flag of the foreign dense submatrix
2348  , bool SO2 > // Storage order of the foreign dense submatrix
2349 inline bool Submatrix<MT,unaligned,false,true>::isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
2350 {
2351  return ( matrix_.isAliased( &alias->matrix_ ) &&
2352  ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
2353  ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
2354 }
2356 //*************************************************************************************************
2357 
2358 
2359 //*************************************************************************************************
2369 template< typename MT > // Type of the dense matrix
2370 inline bool Submatrix<MT,unaligned,false,true>::isAligned() const noexcept
2371 {
2372  return isAligned_;
2373 }
2375 //*************************************************************************************************
2376 
2377 
2378 //*************************************************************************************************
2389 template< typename MT > // Type of the dense matrix
2390 inline bool Submatrix<MT,unaligned,false,true>::canSMPAssign() const noexcept
2391 {
2392  return ( rows() * columns() >= SMP_DMATASSIGN_THRESHOLD );
2393 }
2395 //*************************************************************************************************
2396 
2397 
2398 //*************************************************************************************************
2414 template< typename MT > // Type of the dense matrix
2415 BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,false,true>::SIMDType
2416  Submatrix<MT,unaligned,false,true>::load( size_t i, size_t j ) const noexcept
2417 {
2418  if( isAligned_ )
2419  return loada( i, j );
2420  else
2421  return loadu( i, j );
2422 }
2424 //*************************************************************************************************
2425 
2426 
2427 //*************************************************************************************************
2443 template< typename MT > // Type of the dense matrix
2444 BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,false,true>::SIMDType
2445  Submatrix<MT,unaligned,false,true>::loada( size_t i, size_t j ) const noexcept
2446 {
2448 
2449  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
2450  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
2451  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
2452  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
2453 
2454  return matrix_.loada( row_+i, column_+j );
2455 }
2457 //*************************************************************************************************
2458 
2459 
2460 //*************************************************************************************************
2476 template< typename MT > // Type of the dense matrix
2477 BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,false,true>::SIMDType
2478  Submatrix<MT,unaligned,false,true>::loadu( size_t i, size_t j ) const noexcept
2479 {
2481 
2482  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
2483  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
2484  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
2485  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
2486 
2487  return matrix_.loadu( row_+i, column_+j );
2488 }
2490 //*************************************************************************************************
2491 
2492 
2493 //*************************************************************************************************
2510 template< typename MT > // Type of the dense matrix
2512  Submatrix<MT,unaligned,false,true>::store( size_t i, size_t j, const SIMDType& value ) noexcept
2513 {
2514  if( isAligned_ )
2515  storea( i, j, value );
2516  else
2517  storeu( i, j, value );
2518 }
2520 //*************************************************************************************************
2521 
2522 
2523 //*************************************************************************************************
2540 template< typename MT > // Type of the dense matrix
2542  Submatrix<MT,unaligned,false,true>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
2543 {
2545 
2546  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
2547  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
2548  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
2549  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
2550 
2551  matrix_.storea( row_+i, column_+j, value );
2552 }
2554 //*************************************************************************************************
2555 
2556 
2557 //*************************************************************************************************
2574 template< typename MT > // Type of the dense matrix
2576  Submatrix<MT,unaligned,false,true>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
2577 {
2579 
2580  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
2581  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
2582  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
2583  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
2584 
2585  matrix_.storeu( row_+i, column_+j, value );
2586 }
2588 //*************************************************************************************************
2589 
2590 
2591 //*************************************************************************************************
2608 template< typename MT > // Type of the dense matrix
2610  Submatrix<MT,unaligned,false,true>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
2611 {
2613 
2614  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
2615  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
2616  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
2617  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
2618 
2619  if( isAligned_ )
2620  matrix_.stream( row_+i, column_+j, value );
2621  else
2622  matrix_.storeu( row_+i, column_+j, value );
2623 }
2625 //*************************************************************************************************
2626 
2627 
2628 //*************************************************************************************************
2640 template< typename MT > // Type of the dense matrix
2641 template< typename MT2 > // Type of the right-hand side dense matrix
2642 inline DisableIf_< typename Submatrix<MT,unaligned,false,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
2643  Submatrix<MT,unaligned,false,true>::assign( const DenseMatrix<MT2,false>& rhs )
2644 {
2645  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2646  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2647 
2648  const size_t jpos( n_ & size_t(-2) );
2649  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
2650 
2651  for( size_t i=0UL; i<m_; ++i ) {
2652  for( size_t j=0UL; j<jpos; j+=2UL ) {
2653  matrix_(row_+i,column_+j ) = (~rhs)(i,j );
2654  matrix_(row_+i,column_+j+1UL) = (~rhs)(i,j+1UL);
2655  }
2656  if( jpos < n_ ) {
2657  matrix_(row_+i,column_+jpos) = (~rhs)(i,jpos);
2658  }
2659  }
2660 }
2662 //*************************************************************************************************
2663 
2664 
2665 //*************************************************************************************************
2677 template< typename MT > // Type of the dense matrix
2678 template< typename MT2 > // Type of the right-hand side dense matrix
2679 inline EnableIf_< typename Submatrix<MT,unaligned,false,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
2680  Submatrix<MT,unaligned,false,true>::assign( const DenseMatrix<MT2,false>& rhs )
2681 {
2683 
2684  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2685  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2686 
2687  const size_t jpos( n_ & size_t(-SIMDSIZE) );
2688  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
2689 
2690  if( useStreaming && isAligned_ &&
2691  m_*n_ > ( cacheSize / ( sizeof(ElementType) * 3UL ) ) &&
2692  !(~rhs).isAliased( &matrix_ ) )
2693  {
2694  for( size_t i=0UL; i<m_; ++i )
2695  {
2696  size_t j( 0UL );
2697  Iterator left( begin(i) );
2698  ConstIterator_<MT2> right( (~rhs).begin(i) );
2699 
2700  for( ; j<jpos; j+=SIMDSIZE ) {
2701  left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2702  }
2703  for( ; j<n_; ++j ) {
2704  *left = *right;
2705  }
2706  }
2707  }
2708  else
2709  {
2710  for( size_t i=0UL; i<m_; ++i )
2711  {
2712  size_t j( 0UL );
2713  Iterator left( begin(i) );
2714  ConstIterator_<MT2> right( (~rhs).begin(i) );
2715 
2716  for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
2717  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2718  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2719  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2720  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2721  }
2722  for( ; j<jpos; j+=SIMDSIZE ) {
2723  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2724  }
2725  for( ; j<n_; ++j ) {
2726  *left = *right; ++left; ++right;
2727  }
2728  }
2729  }
2730 }
2732 //*************************************************************************************************
2733 
2734 
2735 //*************************************************************************************************
2747 template< typename MT > // Type of the dense matrix
2748 template< typename MT2 > // Type of the right-hand side dense matrix
2749 inline void Submatrix<MT,unaligned,false,true>::assign( const DenseMatrix<MT2,true>& rhs )
2750 {
2752 
2753  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2754  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2755 
2756  constexpr size_t block( BLOCK_SIZE );
2757 
2758  for( size_t ii=0UL; ii<m_; ii+=block ) {
2759  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
2760  for( size_t jj=0UL; jj<n_; jj+=block ) {
2761  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
2762  for( size_t i=ii; i<iend; ++i ) {
2763  for( size_t j=jj; j<jend; ++j ) {
2764  matrix_(row_+i,column_+j) = (~rhs)(i,j);
2765  }
2766  }
2767  }
2768  }
2769 }
2771 //*************************************************************************************************
2772 
2773 
2774 //*************************************************************************************************
2786 template< typename MT > // Type of the dense matrix
2787 template< typename MT2 > // Type of the right-hand side sparse matrix
2788 inline void Submatrix<MT,unaligned,false,true>::assign( const SparseMatrix<MT2,false>& rhs )
2789 {
2790  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2791  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2792 
2793  for( size_t i=0UL; i<m_; ++i )
2794  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
2795  matrix_(row_+i,column_+element->index()) = element->value();
2796 }
2798 //*************************************************************************************************
2799 
2800 
2801 //*************************************************************************************************
2813 template< typename MT > // Type of the dense matrix
2814 template< typename MT2 > // Type of the right-hand side sparse matrix
2815 inline void Submatrix<MT,unaligned,false,true>::assign( const SparseMatrix<MT2,true>& rhs )
2816 {
2818 
2819  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2820  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2821 
2822  for( size_t j=0UL; j<n_; ++j )
2823  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
2824  matrix_(row_+element->index(),column_+j) = element->value();
2825 }
2827 //*************************************************************************************************
2828 
2829 
2830 //*************************************************************************************************
2842 template< typename MT > // Type of the dense matrix
2843 template< typename MT2 > // Type of the right-hand side dense matrix
2844 inline DisableIf_< typename Submatrix<MT,unaligned,false,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
2845  Submatrix<MT,unaligned,false,true>::addAssign( const DenseMatrix<MT2,false>& rhs )
2846 {
2847  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2848  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2849 
2850  const size_t jpos( n_ & size_t(-2) );
2851  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
2852 
2853  for( size_t i=0UL; i<m_; ++i )
2854  {
2855  if( IsDiagonal<MT2>::value ) {
2856  matrix_(row_+i,column_+i) += (~rhs)(i,i);
2857  }
2858  else {
2859  for( size_t j=0UL; j<jpos; j+=2UL ) {
2860  matrix_(row_+i,column_+j ) += (~rhs)(i,j );
2861  matrix_(row_+i,column_+j+1UL) += (~rhs)(i,j+1UL);
2862  }
2863  if( jpos < n_ ) {
2864  matrix_(row_+i,column_+jpos) += (~rhs)(i,jpos);
2865  }
2866  }
2867  }
2868 }
2870 //*************************************************************************************************
2871 
2872 
2873 //*************************************************************************************************
2885 template< typename MT > // Type of the dense matrix
2886 template< typename MT2 > // Type of the right-hand side dense matrix
2887 inline EnableIf_< typename Submatrix<MT,unaligned,false,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
2888  Submatrix<MT,unaligned,false,true>::addAssign( const DenseMatrix<MT2,false>& rhs )
2889 {
2891 
2892  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2893  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2894 
2895  for( size_t i=0UL; i<m_; ++i )
2896  {
2897  const size_t jbegin( ( IsUpper<MT2>::value )
2898  ?( ( IsStrictlyUpper<MT2>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
2899  :( 0UL ) );
2900  const size_t jend ( ( IsLower<MT2>::value )
2901  ?( IsStrictlyLower<MT2>::value ? i : i+1UL )
2902  :( n_ ) );
2903  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
2904 
2905  const size_t jpos( jend & size_t(-SIMDSIZE) );
2906  BLAZE_INTERNAL_ASSERT( ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
2907 
2908  size_t j( jbegin );
2909  Iterator left( begin(i) + jbegin );
2910  ConstIterator_<MT2> right( (~rhs).begin(i) + jbegin );
2911 
2912  for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
2913  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2914  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2915  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2916  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2917  }
2918  for( ; j<jpos; j+=SIMDSIZE ) {
2919  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2920  }
2921  for( ; j<jend; ++j ) {
2922  *left += *right; ++left; ++right;
2923  }
2924  }
2925 }
2927 //*************************************************************************************************
2928 
2929 
2930 //*************************************************************************************************
2942 template< typename MT > // Type of the dense matrix
2943 template< typename MT2 > // Type of the right-hand side dense matrix
2944 inline void Submatrix<MT,unaligned,false,true>::addAssign( const DenseMatrix<MT2,true>& rhs )
2945 {
2947 
2948  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2949  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2950 
2951  constexpr size_t block( BLOCK_SIZE );
2952 
2953  for( size_t ii=0UL; ii<m_; ii+=block ) {
2954  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
2955  for( size_t jj=0UL; jj<n_; jj+=block ) {
2956  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
2957  for( size_t i=ii; i<iend; ++i ) {
2958  for( size_t j=jj; j<jend; ++j ) {
2959  matrix_(row_+i,column_+j) += (~rhs)(i,j);
2960  }
2961  }
2962  }
2963  }
2964 }
2966 //*************************************************************************************************
2967 
2968 
2969 //*************************************************************************************************
2981 template< typename MT > // Type of the dense matrix
2982 template< typename MT2 > // Type of the right-hand side sparse matrix
2983 inline void Submatrix<MT,unaligned,false,true>::addAssign( const SparseMatrix<MT2,false>& rhs )
2984 {
2985  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
2986  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
2987 
2988  for( size_t i=0UL; i<m_; ++i )
2989  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
2990  matrix_(row_+i,column_+element->index()) += element->value();
2991 }
2993 //*************************************************************************************************
2994 
2995 
2996 //*************************************************************************************************
3008 template< typename MT > // Type of the dense matrix
3009 template< typename MT2 > // Type of the right-hand side sparse matrix
3010 inline void Submatrix<MT,unaligned,false,true>::addAssign( const SparseMatrix<MT2,true>& rhs )
3011 {
3013 
3014  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
3015  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
3016 
3017  for( size_t j=0UL; j<n_; ++j )
3018  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
3019  matrix_(row_+element->index(),column_+j) += element->value();
3020 }
3022 //*************************************************************************************************
3023 
3024 
3025 //*************************************************************************************************
3037 template< typename MT > // Type of the dense matrix
3038 template< typename MT2 > // Type of the right-hand side dense matrix
3039 inline DisableIf_< typename Submatrix<MT,unaligned,false,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
3040  Submatrix<MT,unaligned,false,true>::subAssign( const DenseMatrix<MT2,false>& rhs )
3041 {
3042  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
3043  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
3044 
3045  const size_t jpos( n_ & size_t(-2) );
3046  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
3047 
3048  for( size_t i=0UL; i<m_; ++i )
3049  {
3050  if( IsDiagonal<MT2>::value ) {
3051  matrix_(row_+i,column_+i) -= (~rhs)(i,i);
3052  }
3053  else {
3054  for( size_t j=0UL; j<jpos; j+=2UL ) {
3055  matrix_(row_+i,column_+j ) -= (~rhs)(i,j );
3056  matrix_(row_+i,column_+j+1UL) -= (~rhs)(i,j+1UL);
3057  }
3058  if( jpos < n_ ) {
3059  matrix_(row_+i,column_+jpos) -= (~rhs)(i,jpos);
3060  }
3061  }
3062  }
3063 }
3065 //*************************************************************************************************
3066 
3067 
3068 //*************************************************************************************************
3080 template< typename MT > // Type of the dense matrix
3081 template< typename MT2 > // Type of the right-hand side dense matrix
3082 inline EnableIf_< typename Submatrix<MT,unaligned,false,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
3083  Submatrix<MT,unaligned,false,true>::subAssign( const DenseMatrix<MT2,false>& rhs )
3084 {
3086 
3087  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
3088  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
3089 
3090  for( size_t i=0UL; i<m_; ++i )
3091  {
3092  const size_t jbegin( ( IsUpper<MT2>::value )
3093  ?( ( IsStrictlyUpper<MT2>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
3094  :( 0UL ) );
3095  const size_t jend ( ( IsLower<MT2>::value )
3096  ?( IsStrictlyLower<MT2>::value ? i : i+1UL )
3097  :( n_ ) );
3098  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
3099 
3100  const size_t jpos( jend & size_t(-SIMDSIZE) );
3101  BLAZE_INTERNAL_ASSERT( ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
3102 
3103  size_t j( jbegin );
3104  Iterator left( begin(i) + jbegin );
3105  ConstIterator_<MT2> right( (~rhs).begin(i) + jbegin );
3106 
3107  for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
3108  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3109  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3110  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3111  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3112  }
3113  for( ; j<jpos; j+=SIMDSIZE ) {
3114  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3115  }
3116  for( ; j<jend; ++j ) {
3117  *left -= *right; ++left; ++right;
3118  }
3119  }
3120 }
3122 //*************************************************************************************************
3123 
3124 
3125 //*************************************************************************************************
3137 template< typename MT > // Type of the dense matrix
3138 template< typename MT2 > // Type of the right-hand side dense matrix
3139 inline void Submatrix<MT,unaligned,false,true>::subAssign( const DenseMatrix<MT2,true>& rhs )
3140 {
3142 
3143  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
3144  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
3145 
3146  constexpr size_t block( BLOCK_SIZE );
3147 
3148  for( size_t ii=0UL; ii<m_; ii+=block ) {
3149  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
3150  for( size_t jj=0UL; jj<n_; jj+=block ) {
3151  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
3152  for( size_t i=ii; i<iend; ++i ) {
3153  for( size_t j=jj; j<jend; ++j ) {
3154  matrix_(row_+i,column_+j) -= (~rhs)(i,j);
3155  }
3156  }
3157  }
3158  }
3159 }
3161 //*************************************************************************************************
3162 
3163 
3164 //*************************************************************************************************
3176 template< typename MT > // Type of the dense matrix
3177 template< typename MT2 > // Type of the right-hand side sparse matrix
3178 inline void Submatrix<MT,unaligned,false,true>::subAssign( const SparseMatrix<MT2,false>& rhs )
3179 {
3180  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
3181  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
3182 
3183  for( size_t i=0UL; i<m_; ++i )
3184  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
3185  matrix_(row_+i,column_+element->index()) -= element->value();
3186 }
3188 //*************************************************************************************************
3189 
3190 
3191 //*************************************************************************************************
3203 template< typename MT > // Type of the dense matrix
3204 template< typename MT2 > // Type of the right-hand side sparse matrix
3205 inline void Submatrix<MT,unaligned,false,true>::subAssign( const SparseMatrix<MT2,true>& rhs )
3206 {
3208 
3209  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
3210  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
3211 
3212  for( size_t j=0UL; j<n_; ++j )
3213  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
3214  matrix_(row_+element->index(),column_+j) -= element->value();
3215 }
3217 //*************************************************************************************************
3218 
3219 
3220 //*************************************************************************************************
3232 template< typename MT > // Type of the dense matrix
3233 template< typename MT2 > // Type of the right-hand side dense matrix
3234 inline DisableIf_< typename Submatrix<MT,unaligned,false,true>::BLAZE_TEMPLATE VectorizedSchurAssign<MT2> >
3235  Submatrix<MT,unaligned,false,true>::schurAssign( const DenseMatrix<MT2,false>& rhs )
3236 {
3237  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
3238  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
3239 
3240  const size_t jpos( n_ & size_t(-2) );
3241  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
3242 
3243  for( size_t i=0UL; i<m_; ++i ) {
3244  for( size_t j=0UL; j<jpos; j+=2UL ) {
3245  matrix_(row_+i,column_+j ) *= (~rhs)(i,j );
3246  matrix_(row_+i,column_+j+1UL) *= (~rhs)(i,j+1UL);
3247  }
3248  if( jpos < n_ ) {
3249  matrix_(row_+i,column_+jpos) *= (~rhs)(i,jpos);
3250  }
3251  }
3252 }
3254 //*************************************************************************************************
3255 
3256 
3257 //*************************************************************************************************
3269 template< typename MT > // Type of the dense matrix
3270 template< typename MT2 > // Type of the right-hand side dense matrix
3271 inline EnableIf_< typename Submatrix<MT,unaligned,false,true>::BLAZE_TEMPLATE VectorizedSchurAssign<MT2> >
3272  Submatrix<MT,unaligned,false,true>::schurAssign( const DenseMatrix<MT2,false>& rhs )
3273 {
3275 
3276  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
3277  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
3278 
3279  for( size_t i=0UL; i<m_; ++i )
3280  {
3281  const size_t jpos( n_ & size_t(-SIMDSIZE) );
3282  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
3283 
3284  size_t j( 0UL );
3285  Iterator left( begin(i) );
3286  ConstIterator_<MT2> right( (~rhs).begin(i) );
3287 
3288  for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
3289  left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3290  left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3291  left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3292  left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3293  }
3294  for( ; j<jpos; j+=SIMDSIZE ) {
3295  left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3296  }
3297  for( ; j<n_; ++j ) {
3298  *left *= *right; ++left; ++right;
3299  }
3300  }
3301 }
3303 //*************************************************************************************************
3304 
3305 
3306 //*************************************************************************************************
3318 template< typename MT > // Type of the dense matrix
3319 template< typename MT2 > // Type of the right-hand side dense matrix
3320 inline void Submatrix<MT,unaligned,false,true>::schurAssign( const DenseMatrix<MT2,true>& rhs )
3321 {
3323 
3324  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
3325  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
3326 
3327  constexpr size_t block( BLOCK_SIZE );
3328 
3329  for( size_t ii=0UL; ii<m_; ii+=block ) {
3330  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
3331  for( size_t jj=0UL; jj<n_; jj+=block ) {
3332  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
3333  for( size_t i=ii; i<iend; ++i ) {
3334  for( size_t j=jj; j<jend; ++j ) {
3335  matrix_(row_+i,column_+j) *= (~rhs)(i,j);
3336  }
3337  }
3338  }
3339  }
3340 }
3342 //*************************************************************************************************
3343 
3344 
3345 //*************************************************************************************************
3357 template< typename MT > // Type of the dense matrix
3358 template< typename MT2 > // Type of the right-hand side sparse matrix
3359 inline void Submatrix<MT,unaligned,false,true>::schurAssign( const SparseMatrix<MT2,false>& rhs )
3360 {
3361  using blaze::reset;
3362 
3363  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
3364  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
3365 
3366  for( size_t i=0UL; i<m_; ++i )
3367  {
3368  size_t j( 0UL );
3369 
3370  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element ) {
3371  for( ; j<element->index(); ++j )
3372  reset( matrix_(row_+i,column_+j) );
3373  matrix_(row_+i,column_+j) *= element->value();
3374  ++j;
3375  }
3376 
3377  for( ; j<n_; ++j ) {
3378  reset( matrix_(row_+i,column_+j) );
3379  }
3380  }
3381 }
3383 //*************************************************************************************************
3384 
3385 
3386 //*************************************************************************************************
3398 template< typename MT > // Type of the dense matrix
3399 template< typename MT2 > // Type of the right-hand side sparse matrix
3400 inline void Submatrix<MT,unaligned,false,true>::schurAssign( const SparseMatrix<MT2,true>& rhs )
3401 {
3402  using blaze::reset;
3403 
3405 
3406  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
3407  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
3408 
3409  for( size_t j=0UL; j<n_; ++j )
3410  {
3411  size_t i( 0UL );
3412 
3413  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element ) {
3414  for( ; i<element->index(); ++i )
3415  reset( matrix_(row_+i,column_+j) );
3416  matrix_(row_+i,column_+j) *= element->value();
3417  ++i;
3418  }
3419 
3420  for( ; i<m_; ++i ) {
3421  reset( matrix_(row_+i,column_+j) );
3422  }
3423  }
3424 }
3426 //*************************************************************************************************
3427 
3428 
3429 
3430 
3431 
3432 
3433 
3434 
3435 //=================================================================================================
3436 //
3437 // CLASS TEMPLATE SPECIALIZATION FOR UNALIGNED COLUMN-MAJOR DENSE SUBMATRICES
3438 //
3439 //=================================================================================================
3440 
3441 //*************************************************************************************************
3449 template< typename MT > // Type of the dense matrix
3450 class Submatrix<MT,unaligned,true,true>
3451  : public View< DenseMatrix< Submatrix<MT,unaligned,true,true>, true > >
3452 {
3453  private:
3454  //**Type definitions****************************************************************************
3456  using Operand = If_< IsExpression<MT>, MT, MT& >;
3457  //**********************************************************************************************
3458 
3459  public:
3460  //**Type definitions****************************************************************************
3461  using This = Submatrix<MT,unaligned,true,true>;
3462  using BaseType = DenseMatrix<This,true>;
3463  using ResultType = SubmatrixTrait_<MT>;
3464  using OppositeType = OppositeType_<ResultType>;
3465  using TransposeType = TransposeType_<ResultType>;
3466  using ElementType = ElementType_<MT>;
3467  using SIMDType = SIMDTrait_<ElementType>;
3468  using ReturnType = ReturnType_<MT>;
3469  using CompositeType = const Submatrix&;
3470 
3472  using ConstReference = ConstReference_<MT>;
3473 
3475  using Reference = If_< IsConst<MT>, ConstReference, Reference_<MT> >;
3476 
3478  using ConstPointer = const ElementType*;
3479 
3481  using Pointer = If_< Or< IsConst<MT>, Not< HasMutableDataAccess<MT> > >, ConstPointer, ElementType* >;
3482  //**********************************************************************************************
3483 
3484  //**SubmatrixIterator class definition**********************************************************
3487  template< typename IteratorType > // Type of the dense matrix iterator
3488  class SubmatrixIterator
3489  {
3490  public:
3491  //**Type definitions*************************************************************************
3493  using IteratorCategory = typename std::iterator_traits<IteratorType>::iterator_category;
3494 
3496  using ValueType = typename std::iterator_traits<IteratorType>::value_type;
3497 
3499  using PointerType = typename std::iterator_traits<IteratorType>::pointer;
3500 
3502  using ReferenceType = typename std::iterator_traits<IteratorType>::reference;
3503 
3505  using DifferenceType = typename std::iterator_traits<IteratorType>::difference_type;
3506 
3507  // STL iterator requirements
3508  using iterator_category = IteratorCategory;
3509  using value_type = ValueType;
3510  using pointer = PointerType;
3511  using reference = ReferenceType;
3512  using difference_type = DifferenceType;
3513  //*******************************************************************************************
3514 
3515  //**Constructor******************************************************************************
3518  inline SubmatrixIterator()
3519  : iterator_ ( ) // Iterator to the current submatrix element
3520  , isAligned_( false ) // Memory alignment flag
3521  {}
3522  //*******************************************************************************************
3523 
3524  //**Constructor******************************************************************************
3532  inline SubmatrixIterator( IteratorType iterator, bool isMemoryAligned )
3533  : iterator_ ( iterator ) // Iterator to the current submatrix element
3534  , isAligned_( isMemoryAligned ) // Memory alignment flag
3535  {}
3536  //*******************************************************************************************
3537 
3538  //**Constructor******************************************************************************
3543  template< typename IteratorType2 >
3544  inline SubmatrixIterator( const SubmatrixIterator<IteratorType2>& it )
3545  : iterator_ ( it.base() ) // Iterator to the current submatrix element
3546  , isAligned_( it.isAligned() ) // Memory alignment flag
3547  {}
3548  //*******************************************************************************************
3549 
3550  //**Addition assignment operator*************************************************************
3556  inline SubmatrixIterator& operator+=( size_t inc ) {
3557  iterator_ += inc;
3558  return *this;
3559  }
3560  //*******************************************************************************************
3561 
3562  //**Subtraction assignment operator**********************************************************
3568  inline SubmatrixIterator& operator-=( size_t dec ) {
3569  iterator_ -= dec;
3570  return *this;
3571  }
3572  //*******************************************************************************************
3573 
3574  //**Prefix increment operator****************************************************************
3579  inline SubmatrixIterator& operator++() {
3580  ++iterator_;
3581  return *this;
3582  }
3583  //*******************************************************************************************
3584 
3585  //**Postfix increment operator***************************************************************
3590  inline const SubmatrixIterator operator++( int ) {
3591  return SubmatrixIterator( iterator_++, isAligned_ );
3592  }
3593  //*******************************************************************************************
3594 
3595  //**Prefix decrement operator****************************************************************
3600  inline SubmatrixIterator& operator--() {
3601  --iterator_;
3602  return *this;
3603  }
3604  //*******************************************************************************************
3605 
3606  //**Postfix decrement operator***************************************************************
3611  inline const SubmatrixIterator operator--( int ) {
3612  return SubmatrixIterator( iterator_--, isAligned_ );
3613  }
3614  //*******************************************************************************************
3615 
3616  //**Element access operator******************************************************************
3621  inline ReferenceType operator*() const {
3622  return *iterator_;
3623  }
3624  //*******************************************************************************************
3625 
3626  //**Load function****************************************************************************
3636  inline SIMDType load() const noexcept {
3637  if( isAligned_ )
3638  return loada();
3639  else
3640  return loadu();
3641  }
3642  //*******************************************************************************************
3643 
3644  //**Loada function***************************************************************************
3654  inline SIMDType loada() const noexcept {
3655  return iterator_.loada();
3656  }
3657  //*******************************************************************************************
3658 
3659  //**Loadu function***************************************************************************
3669  inline SIMDType loadu() const noexcept {
3670  return iterator_.loadu();
3671  }
3672  //*******************************************************************************************
3673 
3674  //**Store function***************************************************************************
3685  inline void store( const SIMDType& value ) const {
3686  storeu( value );
3687  }
3688  //*******************************************************************************************
3689 
3690  //**Storea function**************************************************************************
3701  inline void storea( const SIMDType& value ) const {
3702  iterator_.storea( value );
3703  }
3704  //*******************************************************************************************
3705 
3706  //**Storeu function**************************************************************************
3717  inline void storeu( const SIMDType& value ) const {
3718  if( isAligned_ ) {
3719  iterator_.storea( value );
3720  }
3721  else {
3722  iterator_.storeu( value );
3723  }
3724  }
3725  //*******************************************************************************************
3726 
3727  //**Stream function**************************************************************************
3738  inline void stream( const SIMDType& value ) const {
3739  iterator_.stream( value );
3740  }
3741  //*******************************************************************************************
3742 
3743  //**Equality operator************************************************************************
3749  inline bool operator==( const SubmatrixIterator& rhs ) const {
3750  return iterator_ == rhs.iterator_;
3751  }
3752  //*******************************************************************************************
3753 
3754  //**Inequality operator**********************************************************************
3760  inline bool operator!=( const SubmatrixIterator& rhs ) const {
3761  return iterator_ != rhs.iterator_;
3762  }
3763  //*******************************************************************************************
3764 
3765  //**Less-than operator***********************************************************************
3771  inline bool operator<( const SubmatrixIterator& rhs ) const {
3772  return iterator_ < rhs.iterator_;
3773  }
3774  //*******************************************************************************************
3775 
3776  //**Greater-than operator********************************************************************
3782  inline bool operator>( const SubmatrixIterator& rhs ) const {
3783  return iterator_ > rhs.iterator_;
3784  }
3785  //*******************************************************************************************
3786 
3787  //**Less-or-equal-than operator**************************************************************
3793  inline bool operator<=( const SubmatrixIterator& rhs ) const {
3794  return iterator_ <= rhs.iterator_;
3795  }
3796  //*******************************************************************************************
3797 
3798  //**Greater-or-equal-than operator***********************************************************
3804  inline bool operator>=( const SubmatrixIterator& rhs ) const {
3805  return iterator_ >= rhs.iterator_;
3806  }
3807  //*******************************************************************************************
3808 
3809  //**Subtraction operator*********************************************************************
3815  inline DifferenceType operator-( const SubmatrixIterator& rhs ) const {
3816  return iterator_ - rhs.iterator_;
3817  }
3818  //*******************************************************************************************
3819 
3820  //**Addition operator************************************************************************
3827  friend inline const SubmatrixIterator operator+( const SubmatrixIterator& it, size_t inc ) {
3828  return SubmatrixIterator( it.iterator_ + inc, it.isAligned_ );
3829  }
3830  //*******************************************************************************************
3831 
3832  //**Addition operator************************************************************************
3839  friend inline const SubmatrixIterator operator+( size_t inc, const SubmatrixIterator& it ) {
3840  return SubmatrixIterator( it.iterator_ + inc, it.isAligned_ );
3841  }
3842  //*******************************************************************************************
3843 
3844  //**Subtraction operator*********************************************************************
3851  friend inline const SubmatrixIterator operator-( const SubmatrixIterator& it, size_t dec ) {
3852  return SubmatrixIterator( it.iterator_ - dec, it.isAligned_ );
3853  }
3854  //*******************************************************************************************
3855 
3856  //**Base function****************************************************************************
3861  inline IteratorType base() const {
3862  return iterator_;
3863  }
3864  //*******************************************************************************************
3865 
3866  //**IsAligned function***********************************************************************
3871  inline bool isAligned() const noexcept {
3872  return isAligned_;
3873  }
3874  //*******************************************************************************************
3875 
3876  private:
3877  //**Member variables*************************************************************************
3878  IteratorType iterator_;
3879  bool isAligned_;
3880  //*******************************************************************************************
3881  };
3882  //**********************************************************************************************
3883 
3884  //**Type definitions****************************************************************************
3886  using ConstIterator = SubmatrixIterator< ConstIterator_<MT> >;
3887 
3889  using Iterator = If_< IsConst<MT>, ConstIterator, SubmatrixIterator< Iterator_<MT> > >;
3890  //**********************************************************************************************
3891 
3892  //**Compilation flags***************************************************************************
3894  enum : bool { simdEnabled = MT::simdEnabled };
3895 
3897  enum : bool { smpAssignable = MT::smpAssignable };
3898  //**********************************************************************************************
3899 
3900  //**Constructors********************************************************************************
3903  explicit inline Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n );
3904  // No explicitly declared copy constructor.
3906  //**********************************************************************************************
3907 
3908  //**Destructor**********************************************************************************
3909  // No explicitly declared destructor.
3910  //**********************************************************************************************
3911 
3912  //**Data access functions***********************************************************************
3915  inline Reference operator()( size_t i, size_t j );
3916  inline ConstReference operator()( size_t i, size_t j ) const;
3917  inline Reference at( size_t i, size_t j );
3918  inline ConstReference at( size_t i, size_t j ) const;
3919  inline Pointer data () noexcept;
3920  inline ConstPointer data () const noexcept;
3921  inline Pointer data ( size_t j ) noexcept;
3922  inline ConstPointer data ( size_t j ) const noexcept;
3923  inline Iterator begin ( size_t j );
3924  inline ConstIterator begin ( size_t j ) const;
3925  inline ConstIterator cbegin( size_t j ) const;
3926  inline Iterator end ( size_t j );
3927  inline ConstIterator end ( size_t j ) const;
3928  inline ConstIterator cend ( size_t j ) const;
3930  //**********************************************************************************************
3931 
3932  //**Assignment operators************************************************************************
3935  inline Submatrix& operator=( const ElementType& rhs );
3936  inline Submatrix& operator=( initializer_list< initializer_list<ElementType> > list );
3937  inline Submatrix& operator=( const Submatrix& rhs );
3938 
3939  template< typename MT2, bool SO >
3940  inline Submatrix& operator=( const Matrix<MT2,SO>& rhs );
3941 
3942  template< typename MT2, bool SO >
3943  inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
3944  operator+=( const Matrix<MT2,SO>& rhs );
3945 
3946  template< typename MT2, bool SO >
3947  inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
3948  operator+=( const Matrix<MT2,SO>& rhs );
3949 
3950  template< typename MT2, bool SO >
3951  inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
3952  operator-=( const Matrix<MT2,SO>& rhs );
3953 
3954  template< typename MT2, bool SO >
3955  inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
3956  operator-=( const Matrix<MT2,SO>& rhs );
3957 
3958  template< typename MT2, bool SO >
3959  inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
3960  operator%=( const Matrix<MT2,SO>& rhs );
3961 
3962  template< typename MT2, bool SO >
3963  inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
3964  operator%=( const Matrix<MT2,SO>& rhs );
3965 
3966  template< typename MT2, bool SO >
3967  inline Submatrix& operator*=( const Matrix<MT2,SO>& rhs );
3968 
3969  template< typename Other >
3970  inline EnableIf_< IsNumeric<Other>, Submatrix >& operator*=( Other rhs );
3971 
3972  template< typename Other >
3973  inline EnableIf_< IsNumeric<Other>, Submatrix >& operator/=( Other rhs );
3975  //**********************************************************************************************
3976 
3977  //**Utility functions***************************************************************************
3980  inline Operand operand() const noexcept;
3981  inline size_t row() const noexcept;
3982  inline size_t column() const noexcept;
3983  inline size_t rows() const noexcept;
3984  inline size_t columns() const noexcept;
3985  inline size_t spacing() const noexcept;
3986  inline size_t capacity() const noexcept;
3987  inline size_t capacity( size_t i ) const noexcept;
3988  inline size_t nonZeros() const;
3989  inline size_t nonZeros( size_t i ) const;
3990  inline void reset();
3991  inline void reset( size_t i );
3993  //**********************************************************************************************
3994 
3995  //**Numeric functions***************************************************************************
3998  inline Submatrix& transpose();
3999  inline Submatrix& ctranspose();
4000 
4001  template< typename Other > inline Submatrix& scale( const Other& scalar );
4003  //**********************************************************************************************
4004 
4005  private:
4006  //**********************************************************************************************
4008  template< typename MT2 >
4009  struct VectorizedAssign {
4010  enum : bool { value = useOptimizedKernels &&
4011  simdEnabled && MT2::simdEnabled &&
4012  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value };
4013  };
4014  //**********************************************************************************************
4015 
4016  //**********************************************************************************************
4018  template< typename MT2 >
4019  struct VectorizedAddAssign {
4020  enum : bool { value = useOptimizedKernels &&
4021  simdEnabled && MT2::simdEnabled &&
4022  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
4023  HasSIMDAdd< ElementType, ElementType_<MT2> >::value &&
4024  !IsDiagonal<MT2>::value };
4025  };
4026  //**********************************************************************************************
4027 
4028  //**********************************************************************************************
4030  template< typename MT2 >
4031  struct VectorizedSubAssign {
4032  enum : bool { value = useOptimizedKernels &&
4033  simdEnabled && MT2::simdEnabled &&
4034  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
4035  HasSIMDSub< ElementType, ElementType_<MT2> >::value &&
4036  !IsDiagonal<MT2>::value };
4037  };
4038  //**********************************************************************************************
4039 
4040  //**********************************************************************************************
4042  template< typename MT2 >
4043  struct VectorizedSchurAssign {
4044  enum : bool { value = useOptimizedKernels &&
4045  simdEnabled && MT2::simdEnabled &&
4046  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
4047  HasSIMDMult< ElementType, ElementType_<MT2> >::value };
4048  };
4049  //**********************************************************************************************
4050 
4051  //**SIMD properties*****************************************************************************
4053  enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
4054  //**********************************************************************************************
4055 
4056  public:
4057  //**Expression template evaluation functions****************************************************
4060  template< typename Other >
4061  inline bool canAlias( const Other* alias ) const noexcept;
4062 
4063  template< typename MT2, bool AF2, bool SO2 >
4064  inline bool canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
4065 
4066  template< typename Other >
4067  inline bool isAliased( const Other* alias ) const noexcept;
4068 
4069  template< typename MT2, bool AF2, bool SO2 >
4070  inline bool isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
4071 
4072  inline bool isAligned () const noexcept;
4073  inline bool canSMPAssign() const noexcept;
4074 
4075  BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
4076  BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
4077  BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
4078 
4079  BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
4080  BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
4081  BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
4082  BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
4083 
4084  template< typename MT2 >
4085  inline DisableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,true>& rhs );
4086 
4087  template< typename MT2 >
4088  inline EnableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,true>& rhs );
4089 
4090  template< typename MT2 > inline void assign( const DenseMatrix<MT2,false>& rhs );
4091  template< typename MT2 > inline void assign( const SparseMatrix<MT2,true>& rhs );
4092  template< typename MT2 > inline void assign( const SparseMatrix<MT2,false>& rhs );
4093 
4094  template< typename MT2 >
4095  inline DisableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,true>& rhs );
4096 
4097  template< typename MT2 >
4098  inline EnableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,true>& rhs );
4099 
4100  template< typename MT2 > inline void addAssign( const DenseMatrix<MT2,false>& rhs );
4101  template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,true>& rhs );
4102  template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,false>& rhs );
4103 
4104  template< typename MT2 >
4105  inline DisableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,true>& rhs );
4106 
4107  template< typename MT2 >
4108  inline EnableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,true>& rhs );
4109 
4110  template< typename MT2 > inline void subAssign( const DenseMatrix<MT2,false>& rhs );
4111  template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,true>& rhs );
4112  template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,false>& rhs );
4113 
4114  template< typename MT2 >
4115  inline DisableIf_< VectorizedSchurAssign<MT2> > schurAssign( const DenseMatrix<MT2,true>& rhs );
4116 
4117  template< typename MT2 >
4118  inline EnableIf_< VectorizedSchurAssign<MT2> > schurAssign( const DenseMatrix<MT2,true>& rhs );
4119 
4120  template< typename MT2 > inline void schurAssign( const DenseMatrix<MT2,false>& rhs );
4121  template< typename MT2 > inline void schurAssign( const SparseMatrix<MT2,true>& rhs );
4122  template< typename MT2 > inline void schurAssign( const SparseMatrix<MT2,false>& rhs );
4124  //**********************************************************************************************
4125 
4126  private:
4127  //**Utility functions***************************************************************************
4130  inline bool hasOverlap() const noexcept;
4132  //**********************************************************************************************
4133 
4134  //**Member variables****************************************************************************
4137  Operand matrix_;
4138  const size_t row_;
4139  const size_t column_;
4140  const size_t m_;
4141  const size_t n_;
4142  const bool isAligned_;
4143 
4150  //**********************************************************************************************
4151 
4152  //**Friend declarations*************************************************************************
4153  template< typename MT2, bool AF2, bool SO2, bool DF2 > friend class Submatrix;
4154  //**********************************************************************************************
4155 
4156  //**Compile time checks*************************************************************************
4164  //**********************************************************************************************
4165 };
4167 //*************************************************************************************************
4168 
4169 
4170 
4171 
4172 //=================================================================================================
4173 //
4174 // CONSTRUCTOR
4175 //
4176 //=================================================================================================
4177 
4178 //*************************************************************************************************
4192 template< typename MT > // Type of the dense matrix
4193 inline Submatrix<MT,unaligned,true,true>::Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n )
4194  : matrix_ ( matrix ) // The dense matrix containing the submatrix
4195  , row_ ( rindex ) // The first row of the submatrix
4196  , column_ ( cindex ) // The first column of the submatrix
4197  , m_ ( m ) // The number of rows of the submatrix
4198  , n_ ( n ) // The number of columns of the submatrix
4199  , isAligned_( simdEnabled && matrix.data() != nullptr && checkAlignment( data() ) &&
4200  ( n < 2UL || ( matrix.spacing() & size_t(-SIMDSIZE) ) == 0UL ) )
4201 {
4202  if( ( row_ + m_ > matrix_.rows() ) || ( column_ + n_ > matrix_.columns() ) ) {
4203  BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix specification" );
4204  }
4205 }
4207 //*************************************************************************************************
4208 
4209 
4210 
4211 
4212 //=================================================================================================
4213 //
4214 // DATA ACCESS FUNCTIONS
4215 //
4216 //=================================================================================================
4217 
4218 //*************************************************************************************************
4229 template< typename MT > // Type of the dense matrix
4231  Submatrix<MT,unaligned,true,true>::operator()( size_t i, size_t j )
4232 {
4233  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
4234  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
4235 
4236  return matrix_(row_+i,column_+j);
4237 }
4239 //*************************************************************************************************
4240 
4241 
4242 //*************************************************************************************************
4253 template< typename MT > // Type of the dense matrix
4255  Submatrix<MT,unaligned,true,true>::operator()( size_t i, size_t j ) const
4256 {
4257  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
4258  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
4259 
4260  return const_cast<const MT&>( matrix_ )(row_+i,column_+j);
4261 }
4263 //*************************************************************************************************
4264 
4265 
4266 //*************************************************************************************************
4278 template< typename MT > // Type of the dense matrix
4280  Submatrix<MT,unaligned,true,true>::at( size_t i, size_t j )
4281 {
4282  if( i >= rows() ) {
4283  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
4284  }
4285  if( j >= columns() ) {
4286  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
4287  }
4288  return (*this)(i,j);
4289 }
4291 //*************************************************************************************************
4292 
4293 
4294 //*************************************************************************************************
4306 template< typename MT > // Type of the dense matrix
4308  Submatrix<MT,unaligned,true,true>::at( size_t i, size_t j ) const
4309 {
4310  if( i >= rows() ) {
4311  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
4312  }
4313  if( j >= columns() ) {
4314  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
4315  }
4316  return (*this)(i,j);
4317 }
4319 //*************************************************************************************************
4320 
4321 
4322 //*************************************************************************************************
4332 template< typename MT > // Type of the dense matrix
4333 inline typename Submatrix<MT,unaligned,true,true>::Pointer
4334  Submatrix<MT,unaligned,true,true>::data() noexcept
4335 {
4336  return matrix_.data() + row_ + column_*spacing();
4337 }
4339 //*************************************************************************************************
4340 
4341 
4342 //*************************************************************************************************
4352 template< typename MT > // Type of the dense matrix
4353 inline typename Submatrix<MT,unaligned,true,true>::ConstPointer
4354  Submatrix<MT,unaligned,true,true>::data() const noexcept
4355 {
4356  return matrix_.data() + row_ + column_*spacing();
4357 }
4359 //*************************************************************************************************
4360 
4361 
4362 //*************************************************************************************************
4371 template< typename MT > // Type of the dense matrix
4372 inline typename Submatrix<MT,unaligned,true,true>::Pointer
4373  Submatrix<MT,unaligned,true,true>::data( size_t j ) noexcept
4374 {
4375  return matrix_.data() + row_ + (column_+j)*spacing();
4376 }
4378 //*************************************************************************************************
4379 
4380 
4381 //*************************************************************************************************
4390 template< typename MT > // Type of the dense matrix
4391 inline typename Submatrix<MT,unaligned,true,true>::ConstPointer
4392  Submatrix<MT,unaligned,true,true>::data( size_t j ) const noexcept
4393 {
4394  return matrix_.data() + row_ + (column_+j)*spacing();
4395 }
4397 //*************************************************************************************************
4398 
4399 
4400 //*************************************************************************************************
4407 template< typename MT > // Type of the dense matrix
4410 {
4411  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
4412  return Iterator( matrix_.begin( column_ + j ) + row_, isAligned_ );
4413 }
4415 //*************************************************************************************************
4416 
4417 
4418 //*************************************************************************************************
4425 template< typename MT > // Type of the dense matrix
4428 {
4429  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
4430  return ConstIterator( matrix_.cbegin( column_ + j ) + row_, isAligned_ );
4431 }
4433 //*************************************************************************************************
4434 
4435 
4436 //*************************************************************************************************
4443 template< typename MT > // Type of the dense matrix
4446 {
4447  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
4448  return ConstIterator( matrix_.cbegin( column_ + j ) + row_, isAligned_ );
4449 }
4451 //*************************************************************************************************
4452 
4453 
4454 //*************************************************************************************************
4461 template< typename MT > // Type of the dense matrix
4464 {
4465  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
4466  return Iterator( matrix_.begin( column_ + j ) + row_ + m_, isAligned_ );
4467 }
4469 //*************************************************************************************************
4470 
4471 
4472 //*************************************************************************************************
4479 template< typename MT > // Type of the dense matrix
4481  Submatrix<MT,unaligned,true,true>::end( size_t j ) const
4482 {
4483  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
4484  return ConstIterator( matrix_.cbegin( column_ + j ) + row_ + m_, isAligned_ );
4485 }
4487 //*************************************************************************************************
4488 
4489 
4490 //*************************************************************************************************
4497 template< typename MT > // Type of the dense matrix
4499  Submatrix<MT,unaligned,true,true>::cend( size_t j ) const
4500 {
4501  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
4502  return ConstIterator( matrix_.cbegin( column_ + j ) + row_ + m_, isAligned_ );
4503 }
4505 //*************************************************************************************************
4506 
4507 
4508 
4509 
4510 //=================================================================================================
4511 //
4512 // ASSIGNMENT OPERATORS
4513 //
4514 //=================================================================================================
4515 
4516 //*************************************************************************************************
4527 template< typename MT > // Type of the dense matrix
4528 inline Submatrix<MT,unaligned,true,true>&
4529  Submatrix<MT,unaligned,true,true>::operator=( const ElementType& rhs )
4530 {
4531  const size_t jend( column_ + n_ );
4532 
4533  for( size_t j=column_; j<jend; ++j )
4534  {
4535  const size_t ibegin( ( IsLower<MT>::value )
4536  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
4537  ?( max( j+1UL, row_ ) )
4538  :( max( j, row_ ) ) )
4539  :( row_ ) );
4540  const size_t iend ( ( IsUpper<MT>::value )
4541  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
4542  ?( min( j, row_+m_ ) )
4543  :( min( j+1UL, row_+m_ ) ) )
4544  :( row_+m_ ) );
4545 
4546  for( size_t i=ibegin; i<iend; ++i )
4547  matrix_(i,j) = rhs;
4548  }
4549 
4550  return *this;
4551 }
4553 //*************************************************************************************************
4554 
4555 
4556 //*************************************************************************************************
4569 template< typename MT > // Type of the dense matrix
4570 inline Submatrix<MT,unaligned,true,true>&
4571  Submatrix<MT,unaligned,true,true>::operator=( initializer_list< initializer_list<ElementType> > list )
4572 {
4573  if( list.size() != rows() || determineColumns( list ) > columns() ) {
4574  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to submatrix" );
4575  }
4576 
4577  size_t i( 0UL );
4578 
4579  for( const auto& rowList : list ) {
4580  size_t j( 0UL );
4581  for( const auto& element : rowList ) {
4582  matrix_(row_+i,column_+j) = element;
4583  ++j;
4584  }
4585  for( ; j<n_; ++j ) {
4586  matrix_(row_+i,column_+j) = ElementType();
4587  }
4588  ++i;
4589  }
4590 
4591  return *this;
4592 }
4594 //*************************************************************************************************
4595 
4596 
4597 //*************************************************************************************************
4612 template< typename MT > // Type of the dense matrix
4613 inline Submatrix<MT,unaligned,true,true>&
4614  Submatrix<MT,unaligned,true,true>::operator=( const Submatrix& rhs )
4615 {
4618 
4619  if( this == &rhs || ( &matrix_ == &rhs.matrix_ && row_ == rhs.row_ && column_ == rhs.column_ ) )
4620  return *this;
4621 
4622  if( rows() != rhs.rows() || columns() != rhs.columns() ) {
4623  BLAZE_THROW_INVALID_ARGUMENT( "Submatrix sizes do not match" );
4624  }
4625 
4626  if( !tryAssign( matrix_, rhs, row_, column_ ) ) {
4627  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4628  }
4629 
4630  decltype(auto) left( derestrict( *this ) );
4631 
4632  if( rhs.canAlias( &matrix_ ) ) {
4633  const ResultType tmp( rhs );
4634  smpAssign( left, tmp );
4635  }
4636  else {
4637  smpAssign( left, rhs );
4638  }
4639 
4640  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4641 
4642  return *this;
4643 }
4645 //*************************************************************************************************
4646 
4647 
4648 //*************************************************************************************************
4663 template< typename MT > // Type of the dense matrix
4664 template< typename MT2 // Type of the right-hand side matrix
4665  , bool SO > // Storage order of the right-hand side matrix
4666 inline Submatrix<MT,unaligned,true,true>&
4667  Submatrix<MT,unaligned,true,true>::operator=( const Matrix<MT2,SO>& rhs )
4668 {
4670 
4671  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
4672  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4673  }
4674 
4675  using Right = If_< IsRestricted<MT>, CompositeType_<MT2>, const MT2& >;
4676  Right right( ~rhs );
4677 
4678  if( !tryAssign( matrix_, right, row_, column_ ) ) {
4679  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4680  }
4681 
4682  if( IsSparseMatrix<MT2>::value ) {
4683  reset();
4684  }
4685 
4686  decltype(auto) left( derestrict( *this ) );
4687 
4688  if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
4689  const ResultType_<MT2> tmp( right );
4690  smpAssign( left, tmp );
4691  }
4692  else {
4693  smpAssign( left, right );
4694  }
4695 
4696  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4697 
4698  return *this;
4699 }
4701 //*************************************************************************************************
4702 
4703 
4704 //*************************************************************************************************
4718 template< typename MT > // Type of the dense matrix
4719 template< typename MT2 // Type of the right-hand side matrix
4720  , bool SO > // Storage order of the right-hand side matrix
4721 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,true,true>& >
4722  Submatrix<MT,unaligned,true,true>::operator+=( const Matrix<MT2,SO>& rhs )
4723 {
4727 
4728  using AddType = AddTrait_< ResultType, ResultType_<MT2> >;
4729 
4732 
4733  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
4734  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4735  }
4736 
4737  if( !tryAddAssign( matrix_, ~rhs, row_, column_ ) ) {
4738  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4739  }
4740 
4741  decltype(auto) left( derestrict( *this ) );
4742 
4743  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
4744  (~rhs).canAlias( &matrix_ ) ) {
4745  const AddType tmp( *this + (~rhs) );
4746  smpAssign( left, tmp );
4747  }
4748  else {
4749  smpAddAssign( left, ~rhs );
4750  }
4751 
4752  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4753 
4754  return *this;
4755 }
4757 //*************************************************************************************************
4758 
4759 
4760 //*************************************************************************************************
4774 template< typename MT > // Type of the dense matrix
4775 template< typename MT2 // Type of the right-hand side matrix
4776  , bool SO > // Storage order of the right-hand side matrix
4777 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,true,true>& >
4778  Submatrix<MT,unaligned,true,true>::operator+=( const Matrix<MT2,SO>& rhs )
4779 {
4783 
4784  using AddType = AddTrait_< ResultType, ResultType_<MT2> >;
4785 
4788 
4789  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
4790  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4791  }
4792 
4793  const AddType tmp( *this + (~rhs) );
4794 
4795  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
4796  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4797  }
4798 
4799  decltype(auto) left( derestrict( *this ) );
4800 
4801  smpAssign( left, tmp );
4802 
4803  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4804 
4805  return *this;
4806 }
4808 //*************************************************************************************************
4809 
4810 
4811 //*************************************************************************************************
4825 template< typename MT > // Type of the dense matrix
4826 template< typename MT2 // Type of the right-hand side matrix
4827  , bool SO > // Storage order of the right-hand side matrix
4828 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,true,true>& >
4829  Submatrix<MT,unaligned,true,true>::operator-=( const Matrix<MT2,SO>& rhs )
4830 {
4834 
4835  using SubType = SubTrait_< ResultType, ResultType_<MT2> >;
4836 
4839 
4840  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
4841  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4842  }
4843 
4844  if( !trySubAssign( matrix_, ~rhs, row_, column_ ) ) {
4845  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4846  }
4847 
4848  decltype(auto) left( derestrict( *this ) );
4849 
4850  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
4851  (~rhs).canAlias( &matrix_ ) ) {
4852  const SubType tmp( *this - (~rhs ) );
4853  smpAssign( left, tmp );
4854  }
4855  else {
4856  smpSubAssign( left, ~rhs );
4857  }
4858 
4859  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4860 
4861  return *this;
4862 }
4864 //*************************************************************************************************
4865 
4866 
4867 //*************************************************************************************************
4881 template< typename MT > // Type of the dense matrix
4882 template< typename MT2 // Type of the right-hand side matrix
4883  , bool SO > // Storage order of the right-hand side matrix
4884 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,true,true>& >
4885  Submatrix<MT,unaligned,true,true>::operator-=( const Matrix<MT2,SO>& rhs )
4886 {
4890 
4891  using SubType = SubTrait_< ResultType, ResultType_<MT2> >;
4892 
4895 
4896  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
4897  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4898  }
4899 
4900  const SubType tmp( *this - (~rhs) );
4901 
4902  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
4903  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4904  }
4905 
4906  decltype(auto) left( derestrict( *this ) );
4907 
4908  smpAssign( left, tmp );
4909 
4910  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4911 
4912  return *this;
4913 }
4915 //*************************************************************************************************
4916 
4917 
4918 //*************************************************************************************************
4932 template< typename MT > // Type of the dense matrix
4933 template< typename MT2 // Type of the right-hand side matrix
4934  , bool SO > // Storage order of the right-hand side matrix
4935 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,true,true>& >
4936  Submatrix<MT,unaligned,true,true>::operator%=( const Matrix<MT2,SO>& rhs )
4937 {
4941 
4942  using SchurType = SchurTrait_< ResultType, ResultType_<MT2> >;
4943 
4945 
4946  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
4947  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4948  }
4949 
4950  if( !trySchurAssign( matrix_, ~rhs, row_, column_ ) ) {
4951  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4952  }
4953 
4954  decltype(auto) left( derestrict( *this ) );
4955 
4956  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
4957  (~rhs).canAlias( &matrix_ ) ) {
4958  const SchurType tmp( *this % (~rhs) );
4959  if( IsSparseMatrix<SchurType>::value )
4960  reset();
4961  smpAssign( left, tmp );
4962  }
4963  else {
4964  smpSchurAssign( left, ~rhs );
4965  }
4966 
4967  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4968 
4969  return *this;
4970 }
4972 //*************************************************************************************************
4973 
4974 
4975 //*************************************************************************************************
4989 template< typename MT > // Type of the dense matrix
4990 template< typename MT2 // Type of the right-hand side matrix
4991  , bool SO > // Storage order of the right-hand side matrix
4992 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,unaligned,true,true>& >
4993  Submatrix<MT,unaligned,true,true>::operator%=( const Matrix<MT2,SO>& rhs )
4994 {
4998 
4999  using SchurType = SchurTrait_< ResultType, ResultType_<MT2> >;
5000 
5002 
5003  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
5004  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
5005  }
5006 
5007  const SchurType tmp( *this % (~rhs) );
5008 
5009  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
5010  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
5011  }
5012 
5013  if( IsSparseMatrix<SchurType>::value ) {
5014  reset();
5015  }
5016 
5017  decltype(auto) left( derestrict( *this ) );
5018 
5019  smpAssign( left, tmp );
5020 
5021  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
5022 
5023  return *this;
5024 }
5026 //*************************************************************************************************
5027 
5028 
5029 //*************************************************************************************************
5043 template< typename MT > // Type of the dense matrix
5044 template< typename MT2 // Type of the right-hand side matrix
5045  , bool SO > // Storage order of the right-hand side matrix
5046 inline Submatrix<MT,unaligned,true,true>&
5047  Submatrix<MT,unaligned,true,true>::operator*=( const Matrix<MT2,SO>& rhs )
5048 {
5052 
5053  using MultType = MultTrait_< ResultType, ResultType_<MT2> >;
5054 
5057 
5058  if( columns() != (~rhs).rows() ) {
5059  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
5060  }
5061 
5062  const MultType tmp( *this * (~rhs) );
5063 
5064  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
5065  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
5066  }
5067 
5068  decltype(auto) left( derestrict( *this ) );
5069 
5070  smpAssign( left, tmp );
5071 
5072  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
5073 
5074  return *this;
5075 }
5077 //*************************************************************************************************
5078 
5079 
5080 //*************************************************************************************************
5091 template< typename MT > // Type of the dense matrix
5092 template< typename Other > // Data type of the right-hand side scalar
5093 inline EnableIf_< IsNumeric<Other>, Submatrix<MT,unaligned,true,true> >&
5094  Submatrix<MT,unaligned,true,true>::operator*=( Other rhs )
5095 {
5097 
5098  decltype(auto) left( derestrict( *this ) );
5099  smpAssign( left, (*this) * rhs );
5100 
5101  return *this;
5102 }
5104 //*************************************************************************************************
5105 
5106 
5107 //*************************************************************************************************
5120 template< typename MT > // Type of the dense matrix
5121 template< typename Other > // Data type of the right-hand side scalar
5122 inline EnableIf_< IsNumeric<Other>, Submatrix<MT,unaligned,true,true> >&
5123  Submatrix<MT,unaligned,true,true>::operator/=( Other rhs )
5124 {
5126 
5127  BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
5128 
5129  decltype(auto) left( derestrict( *this ) );
5130  smpAssign( left, (*this) / rhs );
5131 
5132  return *this;
5133 }
5135 //*************************************************************************************************
5136 
5137 
5138 
5139 
5140 //=================================================================================================
5141 //
5142 // UTILITY FUNCTIONS
5143 //
5144 //=================================================================================================
5145 
5146 //*************************************************************************************************
5152 template< typename MT > // Type of the dense matrix
5153 inline typename Submatrix<MT,unaligned,true,true>::Operand
5154  Submatrix<MT,unaligned,true,true>::operand() const noexcept
5155 {
5156  return matrix_;
5157 }
5159 //*************************************************************************************************
5160 
5161 
5162 //*************************************************************************************************
5168 template< typename MT > // Type of the dense matrix
5169 inline size_t Submatrix<MT,unaligned,true,true>::row() const noexcept
5170 {
5171  return row_;
5172 }
5174 //*************************************************************************************************
5175 
5176 
5177 //*************************************************************************************************
5183 template< typename MT > // Type of the dense matrix
5184 inline size_t Submatrix<MT,unaligned,true,true>::column() const noexcept
5185 {
5186  return column_;
5187 }
5189 //*************************************************************************************************
5190 
5191 
5192 //*************************************************************************************************
5198 template< typename MT > // Type of the dense matrix
5199 inline size_t Submatrix<MT,unaligned,true,true>::rows() const noexcept
5200 {
5201  return m_;
5202 }
5204 //*************************************************************************************************
5205 
5206 
5207 //*************************************************************************************************
5213 template< typename MT > // Type of the dense matrix
5214 inline size_t Submatrix<MT,unaligned,true,true>::columns() const noexcept
5215 {
5216  return n_;
5217 }
5219 //*************************************************************************************************
5220 
5221 
5222 //*************************************************************************************************
5231 template< typename MT > // Type of the dense matrix
5232 inline size_t Submatrix<MT,unaligned,true,true>::spacing() const noexcept
5233 {
5234  return matrix_.spacing();
5235 }
5237 //*************************************************************************************************
5238 
5239 
5240 //*************************************************************************************************
5246 template< typename MT > // Type of the dense matrix
5247 inline size_t Submatrix<MT,unaligned,true,true>::capacity() const noexcept
5248 {
5249  return rows() * columns();
5250 }
5252 //*************************************************************************************************
5253 
5254 
5255 //*************************************************************************************************
5262 template< typename MT > // Type of the dense matrix
5263 inline size_t Submatrix<MT,unaligned,true,true>::capacity( size_t j ) const noexcept
5264 {
5265  UNUSED_PARAMETER( j );
5266 
5267  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
5268 
5269  return rows();
5270 }
5272 //*************************************************************************************************
5273 
5274 
5275 //*************************************************************************************************
5281 template< typename MT > // Type of the dense matrix
5282 inline size_t Submatrix<MT,unaligned,true,true>::nonZeros() const
5283 {
5284  const size_t iend( row_ + m_ );
5285  const size_t jend( column_ + n_ );
5286  size_t nonzeros( 0UL );
5287 
5288  for( size_t j=column_; j<jend; ++j )
5289  for( size_t i=row_; i<iend; ++i )
5290  if( !isDefault( matrix_(i,j) ) )
5291  ++nonzeros;
5292 
5293  return nonzeros;
5294 }
5296 //*************************************************************************************************
5297 
5298 
5299 //*************************************************************************************************
5306 template< typename MT > // Type of the dense matrix
5307 inline size_t Submatrix<MT,unaligned,true,true>::nonZeros( size_t j ) const
5308 {
5309  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
5310 
5311  const size_t iend( row_ + m_ );
5312  size_t nonzeros( 0UL );
5313 
5314  for( size_t i=row_; i<iend; ++i )
5315  if( !isDefault( matrix_(i,column_+j) ) )
5316  ++nonzeros;
5317 
5318  return nonzeros;
5319 }
5321 //*************************************************************************************************
5322 
5323 
5324 //*************************************************************************************************
5330 template< typename MT > // Type of the dense matrix
5332 {
5333  using blaze::clear;
5334 
5335  for( size_t j=column_; j<column_+n_; ++j )
5336  {
5337  const size_t ibegin( ( IsLower<MT>::value )
5338  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
5339  ?( max( j+1UL, row_ ) )
5340  :( max( j, row_ ) ) )
5341  :( row_ ) );
5342  const size_t iend ( ( IsUpper<MT>::value )
5343  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
5344  ?( min( j, row_+m_ ) )
5345  :( min( j+1UL, row_+m_ ) ) )
5346  :( row_+m_ ) );
5347 
5348  for( size_t i=ibegin; i<iend; ++i )
5349  clear( matrix_(i,j) );
5350  }
5351 }
5353 //*************************************************************************************************
5354 
5355 
5356 //*************************************************************************************************
5363 template< typename MT > // Type of the dense matrix
5364 inline void Submatrix<MT,unaligned,true,true>::reset( size_t j )
5365 {
5366  using blaze::clear;
5367 
5368  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
5369 
5370  const size_t ibegin( ( IsLower<MT>::value )
5371  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
5372  ?( max( j+1UL, row_ ) )
5373  :( max( j, row_ ) ) )
5374  :( row_ ) );
5375  const size_t iend ( ( IsUpper<MT>::value )
5376  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
5377  ?( min( j, row_+m_ ) )
5378  :( min( j+1UL, row_+m_ ) ) )
5379  :( row_+m_ ) );
5380 
5381  for( size_t i=ibegin; i<iend; ++i )
5382  clear( matrix_(i,column_+j) );
5383 }
5385 //*************************************************************************************************
5386 
5387 
5388 //*************************************************************************************************
5398 template< typename MT > // Type of the dense matrix
5399 inline bool Submatrix<MT,unaligned,true,true>::hasOverlap() const noexcept
5400 {
5401  BLAZE_INTERNAL_ASSERT( IsSymmetric<MT>::value || IsHermitian<MT>::value, "Invalid matrix detected" );
5402 
5403  if( ( row_ + m_ <= column_ ) || ( column_ + n_ <= row_ ) )
5404  return false;
5405  else return true;
5406 }
5408 //*************************************************************************************************
5409 
5410 
5411 
5412 
5413 //=================================================================================================
5414 //
5415 // NUMERIC FUNCTIONS
5416 //
5417 //=================================================================================================
5418 
5419 //*************************************************************************************************
5437 template< typename MT > // Type of the dense matrix
5438 inline Submatrix<MT,unaligned,true,true>& Submatrix<MT,unaligned,true,true>::transpose()
5439 {
5440  if( m_ != n_ ) {
5441  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
5442  }
5443 
5444  if( !tryAssign( matrix_, trans( *this ), row_, column_ ) ) {
5445  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
5446  }
5447 
5448  decltype(auto) left( derestrict( *this ) );
5449  const ResultType tmp( trans( *this ) );
5450  smpAssign( left, tmp );
5451 
5452  return *this;
5453 }
5455 //*************************************************************************************************
5456 
5457 
5458 //*************************************************************************************************
5476 template< typename MT > // Type of the dense matrix
5477 inline Submatrix<MT,unaligned,true,true>& Submatrix<MT,unaligned,true,true>::ctranspose()
5478 {
5479  if( m_ != n_ ) {
5480  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
5481  }
5482 
5483  if( !tryAssign( matrix_, ctrans( *this ), row_, column_ ) ) {
5484  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
5485  }
5486 
5487  decltype(auto) left( derestrict( *this ) );
5488  const ResultType tmp( ctrans( *this ) );
5489  smpAssign( left, tmp );
5490 
5491  return *this;
5492 }
5494 //*************************************************************************************************
5495 
5496 
5497 //*************************************************************************************************
5510 template< typename MT > // Type of the dense matrix
5511 template< typename Other > // Data type of the scalar value
5512 inline Submatrix<MT,unaligned,true,true>& Submatrix<MT,unaligned,true,true>::scale( const Other& scalar )
5513 {
5515 
5516  const size_t jend( column_ + n_ );
5517 
5518  for( size_t j=column_; j<jend; ++j )
5519  {
5520  const size_t ibegin( ( IsLower<MT>::value )
5521  ?( ( IsStrictlyLower<MT>::value )
5522  ?( max( j+1UL, row_ ) )
5523  :( max( j, row_ ) ) )
5524  :( row_ ) );
5525  const size_t iend ( ( IsUpper<MT>::value )
5526  ?( ( IsStrictlyUpper<MT>::value )
5527  ?( min( j, row_+m_ ) )
5528  :( min( j+1UL, row_+m_ ) ) )
5529  :( row_+m_ ) );
5530 
5531  for( size_t i=ibegin; i<iend; ++i )
5532  matrix_(i,j) *= scalar;
5533  }
5534 
5535  return *this;
5536 }
5538 //*************************************************************************************************
5539 
5540 
5541 
5542 
5543 //=================================================================================================
5544 //
5545 // EXPRESSION TEMPLATE EVALUATION FUNCTIONS
5546 //
5547 //=================================================================================================
5548 
5549 //*************************************************************************************************
5560 template< typename MT > // Type of the dense matrix
5561 template< typename Other > // Data type of the foreign expression
5562 inline bool Submatrix<MT,unaligned,true,true>::canAlias( const Other* alias ) const noexcept
5563 {
5564  return matrix_.isAliased( alias );
5565 }
5567 //*************************************************************************************************
5568 
5569 
5570 //*************************************************************************************************
5581 template< typename MT > // Type of the dense matrix
5582 template< typename MT2 // Data type of the foreign dense submatrix
5583  , bool AF2 // Alignment flag of the foreign dense submatrix
5584  , bool SO2 > // Storage order of the foreign dense submatrix
5585 inline bool Submatrix<MT,unaligned,true,true>::canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
5586 {
5587  return ( matrix_.isAliased( &alias->matrix_ ) &&
5588  ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
5589  ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
5590 }
5592 //*************************************************************************************************
5593 
5594 
5595 //*************************************************************************************************
5606 template< typename MT > // Type of the dense matrix
5607 template< typename Other > // Data type of the foreign expression
5608 inline bool Submatrix<MT,unaligned,true,true>::isAliased( const Other* alias ) const noexcept
5609 {
5610  return matrix_.isAliased( alias );
5611 }
5613 //*************************************************************************************************
5614 
5615 
5616 //*************************************************************************************************
5627 template< typename MT > // Type of the dense matrix
5628 template< typename MT2 // Data type of the foreign dense submatrix
5629  , bool AF2 // Alignment flag of the foreign dense submatrix
5630  , bool SO2 > // Storage order of the foreign dense submatrix
5631 inline bool Submatrix<MT,unaligned,true,true>::isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
5632 {
5633  return ( matrix_.isAliased( &alias->matrix_ ) &&
5634  ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
5635  ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
5636 }
5638 //*************************************************************************************************
5639 
5640 
5641 //*************************************************************************************************
5651 template< typename MT > // Type of the dense matrix
5652 inline bool Submatrix<MT,unaligned,true,true>::isAligned() const noexcept
5653 {
5654  return isAligned_;
5655 }
5657 //*************************************************************************************************
5658 
5659 
5660 //*************************************************************************************************
5671 template< typename MT > // Type of the dense matrix
5672 inline bool Submatrix<MT,unaligned,true,true>::canSMPAssign() const noexcept
5673 {
5674  return ( rows() * columns() >= SMP_DMATASSIGN_THRESHOLD );
5675 }
5677 //*************************************************************************************************
5678 
5679 
5680 //*************************************************************************************************
5695 template< typename MT > // Type of the dense matrix
5696 BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,true,true>::SIMDType
5697  Submatrix<MT,unaligned,true,true>::load( size_t i, size_t j ) const noexcept
5698 {
5699  if( isAligned_ )
5700  return loada( i, j );
5701  else
5702  return loadu( i, j );
5703 }
5705 //*************************************************************************************************
5706 
5707 
5708 //*************************************************************************************************
5723 template< typename MT > // Type of the dense matrix
5724 BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,true,true>::SIMDType
5725  Submatrix<MT,unaligned,true,true>::loada( size_t i, size_t j ) const noexcept
5726 {
5728 
5729  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
5730  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
5731  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
5732  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
5733 
5734  return matrix_.loada( row_+i, column_+j );
5735 }
5737 //*************************************************************************************************
5738 
5739 
5740 //*************************************************************************************************
5755 template< typename MT > // Type of the dense matrix
5756 BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,true,true>::SIMDType
5757  Submatrix<MT,unaligned,true,true>::loadu( size_t i, size_t j ) const noexcept
5758 {
5760 
5761  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
5762  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
5763  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
5764  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
5765 
5766  return matrix_.loadu( row_+i, column_+j );
5767 }
5769 //*************************************************************************************************
5770 
5771 
5772 //*************************************************************************************************
5788 template< typename MT > // Type of the dense matrix
5790  Submatrix<MT,unaligned,true,true>::store( size_t i, size_t j, const SIMDType& value ) noexcept
5791 {
5792  if( isAligned_ )
5793  storea( i, j, value );
5794  else
5795  storeu( i, j, value );
5796 }
5798 //*************************************************************************************************
5799 
5800 
5801 //*************************************************************************************************
5817 template< typename MT > // Type of the dense matrix
5819  Submatrix<MT,unaligned,true,true>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
5820 {
5822 
5823  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
5824  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
5825  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
5826  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
5827 
5828  matrix_.storea( row_+i, column_+j, value );
5829 }
5831 //*************************************************************************************************
5832 
5833 
5834 //*************************************************************************************************
5850 template< typename MT > // Type of the dense matrix
5852  Submatrix<MT,unaligned,true,true>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
5853 {
5855 
5856  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
5857  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
5858  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
5859  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
5860 
5861  matrix_.storeu( row_+i, column_+j, value );
5862 }
5864 //*************************************************************************************************
5865 
5866 
5867 //*************************************************************************************************
5884 template< typename MT > // Type of the dense matrix
5886  Submatrix<MT,unaligned,true,true>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
5887 {
5889 
5890  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
5891  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
5892  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
5893  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
5894 
5895  if( isAligned_ )
5896  matrix_.stream( row_+i, column_+j, value );
5897  else
5898  matrix_.storeu( row_+i, column_+j, value );
5899 }
5901 //*************************************************************************************************
5902 
5903 
5904 //*************************************************************************************************
5916 template< typename MT > // Type of the dense matrix
5917 template< typename MT2 > // Type of the right-hand side dense matrix
5918 inline DisableIf_< typename Submatrix<MT,unaligned,true,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
5919  Submatrix<MT,unaligned,true,true>::assign( const DenseMatrix<MT2,true>& rhs )
5920 {
5921  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5922  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5923 
5924  const size_t ipos( m_ & size_t(-2) );
5925  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
5926 
5927  for( size_t j=0UL; j<n_; ++j ) {
5928  for( size_t i=0UL; i<ipos; i+=2UL ) {
5929  matrix_(row_+i ,column_+j) = (~rhs)(i ,j);
5930  matrix_(row_+i+1UL,column_+j) = (~rhs)(i+1UL,j);
5931  }
5932  if( ipos < m_ ) {
5933  matrix_(row_+ipos,column_+j) = (~rhs)(ipos,j);
5934  }
5935  }
5936 }
5938 //*************************************************************************************************
5939 
5940 
5941 //*************************************************************************************************
5953 template< typename MT > // Type of the dense matrix
5954 template< typename MT2 > // Type of the right-hand side dense matrix
5955 inline EnableIf_< typename Submatrix<MT,unaligned,true,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
5956  Submatrix<MT,unaligned,true,true>::assign( const DenseMatrix<MT2,true>& rhs )
5957 {
5959 
5960  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
5961  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
5962 
5963  const size_t ipos( m_ & size_t(-SIMDSIZE) );
5964  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
5965 
5966  if( useStreaming && isAligned_ &&
5967  m_*n_ > ( cacheSize / ( sizeof(ElementType) * 3UL ) ) &&
5968  !(~rhs).isAliased( &matrix_ ) )
5969  {
5970  for( size_t j=0UL; j<n_; ++j )
5971  {
5972  size_t i( 0UL );
5973  Iterator left( begin(j) );
5974  ConstIterator_<MT2> right( (~rhs).begin(j) );
5975 
5976  for( ; i<ipos; i+=SIMDSIZE ) {
5977  left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5978  }
5979  for( ; i<m_; ++i ) {
5980  *left = *right; ++left; ++right;
5981  }
5982  }
5983  }
5984  else
5985  {
5986  for( size_t j=0UL; j<n_; ++j )
5987  {
5988  size_t i( 0UL );
5989  Iterator left( begin(j) );
5990  ConstIterator_<MT2> right( (~rhs).begin(j) );
5991 
5992  for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
5993  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5994  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5995  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5996  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5997  }
5998  for( ; i<ipos; i+=SIMDSIZE ) {
5999  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6000  }
6001  for( ; i<m_; ++i ) {
6002  *left = *right; ++left; ++right;
6003  }
6004  }
6005  }
6006 }
6008 //*************************************************************************************************
6009 
6010 
6011 //*************************************************************************************************
6023 template< typename MT > // Type of the dense matrix
6024 template< typename MT2 > // Type of the right-hand side dense matrix
6025 inline void Submatrix<MT,unaligned,true,true>::assign( const DenseMatrix<MT2,false>& rhs )
6026 {
6028 
6029  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
6030  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
6031 
6032  constexpr size_t block( BLOCK_SIZE );
6033 
6034  for( size_t jj=0UL; jj<n_; jj+=block ) {
6035  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
6036  for( size_t ii=0UL; ii<m_; ii+=block ) {
6037  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
6038  for( size_t j=jj; j<jend; ++j ) {
6039  for( size_t i=ii; i<iend; ++i ) {
6040  matrix_(row_+i,column_+j) = (~rhs)(i,j);
6041  }
6042  }
6043  }
6044  }
6045 }
6047 //*************************************************************************************************
6048 
6049 
6050 //*************************************************************************************************
6062 template< typename MT > // Type of the dense matrix
6063 template< typename MT2 > // Type of the right-hand side sparse matrix
6064 inline void Submatrix<MT,unaligned,true,true>::assign( const SparseMatrix<MT2,true>& rhs )
6065 {
6066  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
6067  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
6068 
6069  for( size_t j=0UL; j<n_; ++j )
6070  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
6071  matrix_(row_+element->index(),column_+j) = element->value();
6072 }
6074 //*************************************************************************************************
6075 
6076 
6077 //*************************************************************************************************
6089 template< typename MT > // Type of the dense matrix
6090 template< typename MT2 > // Type of the right-hand side sparse matrix
6091 inline void Submatrix<MT,unaligned,true,true>::assign( const SparseMatrix<MT2,false>& rhs )
6092 {
6094 
6095  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
6096  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
6097 
6098  for( size_t i=0UL; i<m_; ++i )
6099  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
6100  matrix_(row_+i,column_+element->index()) = element->value();
6101 }
6103 //*************************************************************************************************
6104 
6105 
6106 //*************************************************************************************************
6118 template< typename MT > // Type of the dense matrix
6119 template< typename MT2 > // Type of the right-hand side dense matrix
6120 inline DisableIf_< typename Submatrix<MT,unaligned,true,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
6121  Submatrix<MT,unaligned,true,true>::addAssign( const DenseMatrix<MT2,true>& rhs )
6122 {
6123  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
6124  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
6125 
6126  const size_t ipos( m_ & size_t(-2) );
6127  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
6128 
6129  for( size_t j=0UL; j<n_; ++j )
6130  {
6131  if( IsDiagonal<MT2>::value ) {
6132  matrix_(row_+j,column_+j) += (~rhs)(j,j);
6133  }
6134  else {
6135  for( size_t i=0UL; i<ipos; i+=2UL ) {
6136  matrix_(row_+i ,column_+j) += (~rhs)(i ,j);
6137  matrix_(row_+i+1UL,column_+j) += (~rhs)(i+1UL,j);
6138  }
6139  if( ipos < m_ ) {
6140  matrix_(row_+ipos,column_+j) += (~rhs)(ipos,j);
6141  }
6142  }
6143  }
6144 }
6146 //*************************************************************************************************
6147 
6148 
6149 //*************************************************************************************************
6161 template< typename MT > // Type of the dense matrix
6162 template< typename MT2 > // Type of the right-hand side dense matrix
6163 inline EnableIf_< typename Submatrix<MT,unaligned,true,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
6164  Submatrix<MT,unaligned,true,true>::addAssign( const DenseMatrix<MT2,true>& rhs )
6165 {
6167 
6168  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
6169  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
6170 
6171  for( size_t j=0UL; j<n_; ++j )
6172  {
6173  const size_t ibegin( ( IsLower<MT>::value )
6174  ?( ( IsStrictlyLower<MT>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
6175  :( 0UL ) );
6176  const size_t iend ( ( IsUpper<MT>::value )
6177  ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
6178  :( m_ ) );
6179  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
6180 
6181  const size_t ipos( iend & size_t(-SIMDSIZE) );
6182  BLAZE_INTERNAL_ASSERT( ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
6183 
6184  size_t i( ibegin );
6185  Iterator left( begin(j) + ibegin );
6186  ConstIterator_<MT2> right( (~rhs).begin(j) + ibegin );
6187 
6188  for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
6189  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6190  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6191  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6192  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6193  }
6194  for( ; i<ipos; i+=SIMDSIZE ) {
6195  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6196  }
6197  for( ; i<iend; ++i ) {
6198  *left += *right; ++left; ++right;
6199  }
6200  }
6201 }
6203 //*************************************************************************************************
6204 
6205 
6206 //*************************************************************************************************
6218 template< typename MT > // Type of the dense matrix
6219 template< typename MT2 > // Type of the right-hand side dense matrix
6220 inline void Submatrix<MT,unaligned,true,true>::addAssign( const DenseMatrix<MT2,false>& rhs )
6221 {
6223 
6224  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
6225  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
6226 
6227  constexpr size_t block( BLOCK_SIZE );
6228 
6229  for( size_t jj=0UL; jj<n_; jj+=block ) {
6230  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
6231  for( size_t ii=0UL; ii<m_; ii+=block ) {
6232  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
6233  for( size_t j=jj; j<jend; ++j ) {
6234  for( size_t i=ii; i<iend; ++i ) {
6235  matrix_(row_+i,column_+j) += (~rhs)(i,j);
6236  }
6237  }
6238  }
6239  }
6240 }
6242 //*************************************************************************************************
6243 
6244 
6245 //*************************************************************************************************
6257 template< typename MT > // Type of the dense matrix
6258 template< typename MT2 > // Type of the right-hand side sparse matrix
6259 inline void Submatrix<MT,unaligned,true,true>::addAssign( const SparseMatrix<MT2,true>& rhs )
6260 {
6261  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
6262  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
6263 
6264  for( size_t j=0UL; j<n_; ++j )
6265  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
6266  matrix_(row_+element->index(),column_+j) += element->value();
6267 }
6269 //*************************************************************************************************
6270 
6271 
6272 //*************************************************************************************************
6284 template< typename MT > // Type of the dense matrix
6285 template< typename MT2 > // Type of the right-hand side sparse matrix
6286 inline void Submatrix<MT,unaligned,true,true>::addAssign( const SparseMatrix<MT2,false>& rhs )
6287 {
6289 
6290  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
6291  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
6292 
6293  for( size_t i=0UL; i<m_; ++i )
6294  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
6295  matrix_(row_+i,column_+element->index()) += element->value();
6296 }
6298 //*************************************************************************************************
6299 
6300 
6301 //*************************************************************************************************
6313 template< typename MT > // Type of the dense matrix
6314 template< typename MT2 > // Type of the right-hand side dense matrix
6315 inline DisableIf_< typename Submatrix<MT,unaligned,true,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
6316  Submatrix<MT,unaligned,true,true>::subAssign( const DenseMatrix<MT2,true>& rhs )
6317 {
6318  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
6319  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
6320 
6321  const size_t ipos( m_ & size_t(-2) );
6322  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
6323 
6324  for( size_t j=0UL; j<n_; ++j )
6325  {
6326  if( IsDiagonal<MT2>::value ) {
6327  matrix_(row_+j,column_+j) -= (~rhs)(j,j);
6328  }
6329  else {
6330  for( size_t i=0UL; i<ipos; i+=2UL ) {
6331  matrix_(row_+i ,column_+j) -= (~rhs)(i ,j);
6332  matrix_(row_+i+1UL,column_+j) -= (~rhs)(i+1UL,j);
6333  }
6334  if( ipos < m_ ) {
6335  matrix_(row_+ipos,column_+j) -= (~rhs)(ipos,j);
6336  }
6337  }
6338  }
6339 }
6341 //*************************************************************************************************
6342 
6343 
6344 //*************************************************************************************************
6356 template< typename MT > // Type of the dense matrix
6357 template< typename MT2 > // Type of the right-hand side dense matrix
6358 inline EnableIf_< typename Submatrix<MT,unaligned,true,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
6359  Submatrix<MT,unaligned,true,true>::subAssign( const DenseMatrix<MT2,true>& rhs )
6360 {
6362 
6363  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
6364  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
6365 
6366  for( size_t j=0UL; j<n_; ++j )
6367  {
6368  const size_t ibegin( ( IsLower<MT>::value )
6369  ?( ( IsStrictlyLower<MT>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
6370  :( 0UL ) );
6371  const size_t iend ( ( IsUpper<MT>::value )
6372  ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
6373  :( m_ ) );
6374  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
6375 
6376  const size_t ipos( iend & size_t(-SIMDSIZE) );
6377  BLAZE_INTERNAL_ASSERT( ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
6378 
6379  size_t i( ibegin );
6380  Iterator left( begin(j) + ibegin );
6381  ConstIterator_<MT2> right( (~rhs).begin(j) + ibegin );
6382 
6383  for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
6384  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6385  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6386  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6387  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6388  }
6389  for( ; i<ipos; i+=SIMDSIZE ) {
6390  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6391  }
6392  for( ; i<iend; ++i ) {
6393  *left -= *right; ++left; ++right;
6394  }
6395  }
6396 }
6398 //*************************************************************************************************
6399 
6400 
6401 //*************************************************************************************************
6413 template< typename MT > // Type of the dense matrix
6414 template< typename MT2 > // Type of the right-hand side dense matrix
6415 inline void Submatrix<MT,unaligned,true,true>::subAssign( const DenseMatrix<MT2,false>& rhs )
6416 {
6418 
6419  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
6420  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
6421 
6422  constexpr size_t block( BLOCK_SIZE );
6423 
6424  for( size_t jj=0UL; jj<n_; jj+=block ) {
6425  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
6426  for( size_t ii=0UL; ii<m_; ii+=block ) {
6427  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
6428  for( size_t j=jj; j<jend; ++j ) {
6429  for( size_t i=ii; i<iend; ++i ) {
6430  matrix_(row_+i,column_+j) -= (~rhs)(i,j);
6431  }
6432  }
6433  }
6434  }
6435 }
6437 //*************************************************************************************************
6438 
6439 
6440 //*************************************************************************************************
6452 template< typename MT > // Type of the dense matrix
6453 template< typename MT2 > // Type of the right-hand side sparse matrix
6454 inline void Submatrix<MT,unaligned,true,true>::subAssign( const SparseMatrix<MT2,true>& rhs )
6455 {
6456  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
6457  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
6458 
6459  for( size_t j=0UL; j<n_; ++j )
6460  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
6461  matrix_(row_+element->index(),column_+j) -= element->value();
6462 }
6464 //*************************************************************************************************
6465 
6466 
6467 //*************************************************************************************************
6479 template< typename MT > // Type of the dense matrix
6480 template< typename MT2 > // Type of the right-hand side sparse matrix
6481 inline void Submatrix<MT,unaligned,true,true>::subAssign( const SparseMatrix<MT2,false>& rhs )
6482 {
6484 
6485  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
6486  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
6487 
6488  for( size_t i=0UL; i<m_; ++i )
6489  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
6490  matrix_(row_+i,column_+element->index()) -= element->value();
6491 }
6493 //*************************************************************************************************
6494 
6495 
6496 //*************************************************************************************************
6508 template< typename MT > // Type of the dense matrix
6509 template< typename MT2 > // Type of the right-hand side dense matrix
6510 inline DisableIf_< typename Submatrix<MT,unaligned,true,true>::BLAZE_TEMPLATE VectorizedSchurAssign<MT2> >
6511  Submatrix<MT,unaligned,true,true>::schurAssign( const DenseMatrix<MT2,true>& rhs )
6512 {
6513  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
6514  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
6515 
6516  const size_t ipos( m_ & size_t(-2) );
6517  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
6518 
6519  for( size_t j=0UL; j<n_; ++j ) {
6520  for( size_t i=0UL; i<ipos; i+=2UL ) {
6521  matrix_(row_+i ,column_+j) *= (~rhs)(i ,j);
6522  matrix_(row_+i+1UL,column_+j) *= (~rhs)(i+1UL,j);
6523  }
6524  if( ipos < m_ ) {
6525  matrix_(row_+ipos,column_+j) *= (~rhs)(ipos,j);
6526  }
6527  }
6528 }
6530 //*************************************************************************************************
6531 
6532 
6533 //*************************************************************************************************
6546 template< typename MT > // Type of the dense matrix
6547 template< typename MT2 > // Type of the right-hand side dense matrix
6548 inline EnableIf_< typename Submatrix<MT,unaligned,true,true>::BLAZE_TEMPLATE VectorizedSchurAssign<MT2> >
6549  Submatrix<MT,unaligned,true,true>::schurAssign( const DenseMatrix<MT2,true>& rhs )
6550 {
6552 
6553  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
6554  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
6555 
6556  for( size_t j=0UL; j<n_; ++j )
6557  {
6558  const size_t ipos( m_ & size_t(-SIMDSIZE) );
6559  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
6560 
6561  size_t i( 0UL );
6562  Iterator left( begin(j) );
6563  ConstIterator_<MT2> right( (~rhs).begin(j) );
6564 
6565  for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
6566  left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6567  left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6568  left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6569  left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6570  }
6571  for( ; i<ipos; i+=SIMDSIZE ) {
6572  left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6573  }
6574  for( ; i<m_; ++i ) {
6575  *left *= *right; ++left; ++right;
6576  }
6577  }
6578 }
6580 //*************************************************************************************************
6581 
6582 
6583 //*************************************************************************************************
6595 template< typename MT > // Type of the dense matrix
6596 template< typename MT2 > // Type of the right-hand side dense matrix
6597 inline void Submatrix<MT,unaligned,true,true>::schurAssign( const DenseMatrix<MT2,false>& rhs )
6598 {
6600 
6601  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
6602  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
6603 
6604  constexpr size_t block( BLOCK_SIZE );
6605 
6606  for( size_t jj=0UL; jj<n_; jj+=block ) {
6607  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
6608  for( size_t ii=0UL; ii<m_; ii+=block ) {
6609  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
6610  for( size_t j=jj; j<jend; ++j ) {
6611  for( size_t i=ii; i<iend; ++i ) {
6612  matrix_(row_+i,column_+j) *= (~rhs)(i,j);
6613  }
6614  }
6615  }
6616  }
6617 }
6619 //*************************************************************************************************
6620 
6621 
6622 //*************************************************************************************************
6634 template< typename MT > // Type of the dense matrix
6635 template< typename MT2 > // Type of the right-hand side sparse matrix
6636 inline void Submatrix<MT,unaligned,true,true>::schurAssign( const SparseMatrix<MT2,true>& rhs )
6637 {
6638  using blaze::reset;
6639 
6640  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
6641  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
6642 
6643  for( size_t j=0UL; j<n_; ++j )
6644  {
6645  size_t i( 0UL );
6646 
6647  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element ) {
6648  for( ; i<element->index(); ++i )
6649  reset( matrix_(row_+i,column_+j) );
6650  matrix_(row_+i,column_+j) *= element->value();
6651  ++i;
6652  }
6653 
6654  for( ; i<m_; ++i ) {
6655  reset( matrix_(row_+i,column_+j) );
6656  }
6657  }
6658 }
6660 //*************************************************************************************************
6661 
6662 
6663 //*************************************************************************************************
6675 template< typename MT > // Type of the dense matrix
6676 template< typename MT2 > // Type of the right-hand side sparse matrix
6677 inline void Submatrix<MT,unaligned,true,true>::schurAssign( const SparseMatrix<MT2,false>& rhs )
6678 {
6679  using blaze::reset;
6680 
6682 
6683  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
6684  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
6685 
6686  for( size_t i=0UL; i<m_; ++i )
6687  {
6688  size_t j( 0UL );
6689 
6690  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element ) {
6691  for( ; j<element->index(); ++j )
6692  reset( matrix_(row_+i,column_+j) );
6693  matrix_(row_+i,column_+j) *= element->value();
6694  ++j;
6695  }
6696 
6697  for( ; j<n_; ++j ) {
6698  reset( matrix_(row_+i,column_+j) );
6699  }
6700  }
6701 }
6703 //*************************************************************************************************
6704 
6705 
6706 
6707 
6708 
6709 
6710 
6711 
6712 //=================================================================================================
6713 //
6714 // CLASS TEMPLATE SPECIALIZATION FOR ALIGNED ROW-MAJOR DENSE SUBMATRICES
6715 //
6716 //=================================================================================================
6717 
6718 //*************************************************************************************************
6726 template< typename MT > // Type of the dense matrix
6727 class Submatrix<MT,aligned,false,true>
6728  : public View< DenseMatrix< Submatrix<MT,aligned,false,true>, false > >
6729 {
6730  private:
6731  //**Type definitions****************************************************************************
6733  using Operand = If_< IsExpression<MT>, MT, MT& >;
6734  //**********************************************************************************************
6735 
6736  public:
6737  //**Type definitions****************************************************************************
6738  using This = Submatrix<MT,aligned,false,true>;
6739  using BaseType = DenseMatrix<This,false>;
6740  using ResultType = SubmatrixTrait_<MT>;
6741  using OppositeType = OppositeType_<ResultType>;
6742  using TransposeType = TransposeType_<ResultType>;
6743  using ElementType = ElementType_<MT>;
6744  using SIMDType = SIMDTrait_<ElementType>;
6745  using ReturnType = ReturnType_<MT>;
6746  using CompositeType = const Submatrix&;
6747 
6749  using ConstReference = ConstReference_<MT>;
6750 
6752  using Reference = If_< IsConst<MT>, ConstReference, Reference_<MT> >;
6753 
6755  using ConstPointer = const ElementType*;
6756 
6758  using Pointer = If_< Or< IsConst<MT>, Not< HasMutableDataAccess<MT> > >, ConstPointer, ElementType* >;
6759 
6761  using ConstIterator = ConstIterator_<MT>;
6762 
6764  using Iterator = If_< IsConst<MT>, ConstIterator, Iterator_<MT> >;
6765  //**********************************************************************************************
6766 
6767  //**Compilation flags***************************************************************************
6769  enum : bool { simdEnabled = MT::simdEnabled };
6770 
6772  enum : bool { smpAssignable = MT::smpAssignable };
6773  //**********************************************************************************************
6774 
6775  //**Constructors********************************************************************************
6778  explicit inline Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n );
6779  // No explicitly declared copy constructor.
6781  //**********************************************************************************************
6782 
6783  //**Destructor**********************************************************************************
6784  // No explicitly declared destructor.
6785  //**********************************************************************************************
6786 
6787  //**Data access functions***********************************************************************
6790  inline Reference operator()( size_t i, size_t j );
6791  inline ConstReference operator()( size_t i, size_t j ) const;
6792  inline Reference at( size_t i, size_t j );
6793  inline ConstReference at( size_t i, size_t j ) const;
6794  inline Pointer data () noexcept;
6795  inline ConstPointer data () const noexcept;
6796  inline Pointer data ( size_t i ) noexcept;
6797  inline ConstPointer data ( size_t i ) const noexcept;
6798  inline Iterator begin ( size_t i );
6799  inline ConstIterator begin ( size_t i ) const;
6800  inline ConstIterator cbegin( size_t i ) const;
6801  inline Iterator end ( size_t i );
6802  inline ConstIterator end ( size_t i ) const;
6803  inline ConstIterator cend ( size_t i ) const;
6805  //**********************************************************************************************
6806 
6807  //**Assignment operators************************************************************************
6810  inline Submatrix& operator=( const ElementType& rhs );
6811  inline Submatrix& operator=( initializer_list< initializer_list<ElementType> > list );
6812  inline Submatrix& operator=( const Submatrix& rhs );
6813 
6814  template< typename MT2, bool SO >
6815  inline Submatrix& operator=( const Matrix<MT2,SO>& rhs );
6816 
6817  template< typename MT2, bool SO >
6818  inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
6819  operator+=( const Matrix<MT2,SO>& rhs );
6820 
6821  template< typename MT2, bool SO >
6822  inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
6823  operator+=( const Matrix<MT2,SO>& rhs );
6824 
6825  template< typename MT2, bool SO >
6826  inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
6827  operator-=( const Matrix<MT2,SO>& rhs );
6828 
6829  template< typename MT2, bool SO >
6830  inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
6831  operator-=( const Matrix<MT2,SO>& rhs );
6832 
6833  template< typename MT2, bool SO >
6834  inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
6835  operator%=( const Matrix<MT2,SO>& rhs );
6836 
6837  template< typename MT2, bool SO >
6838  inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
6839  operator%=( const Matrix<MT2,SO>& rhs );
6840 
6841  template< typename MT2, bool SO >
6842  inline Submatrix& operator*=( const Matrix<MT2,SO>& rhs );
6843 
6844  template< typename Other >
6845  inline EnableIf_< IsNumeric<Other>, Submatrix >& operator*=( Other rhs );
6846 
6847  template< typename Other >
6848  inline EnableIf_< IsNumeric<Other>, Submatrix >& operator/=( Other rhs );
6850  //**********************************************************************************************
6851 
6852  //**Utility functions***************************************************************************
6855  inline Operand operand() const noexcept;
6856  inline size_t row() const noexcept;
6857  inline size_t column() const noexcept;
6858  inline size_t rows() const noexcept;
6859  inline size_t columns() const noexcept;
6860  inline size_t spacing() const noexcept;
6861  inline size_t capacity() const noexcept;
6862  inline size_t capacity( size_t i ) const noexcept;
6863  inline size_t nonZeros() const;
6864  inline size_t nonZeros( size_t i ) const;
6865  inline void reset();
6866  inline void reset( size_t i );
6868  //**********************************************************************************************
6869 
6870  //**Numeric functions***************************************************************************
6873  inline Submatrix& transpose();
6874  inline Submatrix& ctranspose();
6875 
6876  template< typename Other > inline Submatrix& scale( const Other& scalar );
6878  //**********************************************************************************************
6879 
6880  private:
6881  //**********************************************************************************************
6883  template< typename MT2 >
6884  struct VectorizedAssign {
6885  enum : bool { value = useOptimizedKernels &&
6886  simdEnabled && MT2::simdEnabled &&
6887  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value };
6888  };
6889  //**********************************************************************************************
6890 
6891  //**********************************************************************************************
6893  template< typename MT2 >
6894  struct VectorizedAddAssign {
6895  enum : bool { value = useOptimizedKernels &&
6896  simdEnabled && MT2::simdEnabled &&
6897  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
6898  HasSIMDAdd< ElementType, ElementType_<MT2> >::value &&
6899  !IsDiagonal<MT2>::value };
6900  };
6901  //**********************************************************************************************
6902 
6903  //**********************************************************************************************
6905  template< typename MT2 >
6906  struct VectorizedSubAssign {
6907  enum : bool { value = useOptimizedKernels &&
6908  simdEnabled && MT2::simdEnabled &&
6909  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
6910  HasSIMDSub< ElementType, ElementType_<MT2> >::value &&
6911  !IsDiagonal<MT2>::value };
6912  };
6913  //**********************************************************************************************
6914 
6915  //**********************************************************************************************
6917  template< typename MT2 >
6918  struct VectorizedSchurAssign {
6919  enum : bool { value = useOptimizedKernels &&
6920  simdEnabled && MT2::simdEnabled &&
6921  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
6922  HasSIMDMult< ElementType, ElementType_<MT2> >::value };
6923  };
6924  //**********************************************************************************************
6925 
6926  //**SIMD properties*****************************************************************************
6928  enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
6929  //**********************************************************************************************
6930 
6931  public:
6932  //**Expression template evaluation functions****************************************************
6935  template< typename Other >
6936  inline bool canAlias( const Other* alias ) const noexcept;
6937 
6938  template< typename MT2, bool AF2, bool SO2 >
6939  inline bool canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
6940 
6941  template< typename Other >
6942  inline bool isAliased( const Other* alias ) const noexcept;
6943 
6944  template< typename MT2, bool AF2, bool SO2 >
6945  inline bool isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
6946 
6947  inline bool isAligned () const noexcept;
6948  inline bool canSMPAssign() const noexcept;
6949 
6950  BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
6951  BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
6952  BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
6953 
6954  BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
6955  BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
6956  BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
6957  BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
6958 
6959  template< typename MT2 >
6960  inline DisableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,false>& rhs );
6961 
6962  template< typename MT2 >
6963  inline EnableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,false>& rhs );
6964 
6965  template< typename MT2 > inline void assign( const DenseMatrix<MT2,true>& rhs );
6966  template< typename MT2 > inline void assign( const SparseMatrix<MT2,false>& rhs );
6967  template< typename MT2 > inline void assign( const SparseMatrix<MT2,true>& rhs );
6968 
6969  template< typename MT2 >
6970  inline DisableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,false>& rhs );
6971 
6972  template< typename MT2 >
6973  inline EnableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,false>& rhs );
6974 
6975  template< typename MT2 > inline void addAssign( const DenseMatrix<MT2,true>& rhs );
6976  template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,false>& rhs );
6977  template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,true>& rhs );
6978 
6979  template< typename MT2 >
6980  inline DisableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,false>& rhs );
6981 
6982  template< typename MT2 >
6983  inline EnableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,false>& rhs );
6984 
6985  template< typename MT2 > inline void subAssign( const DenseMatrix<MT2,true>& rhs );
6986  template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,false>& rhs );
6987  template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,true>& rhs );
6988 
6989  template< typename MT2 >
6990  inline DisableIf_< VectorizedSchurAssign<MT2> > schurAssign( const DenseMatrix<MT2,false>& rhs );
6991 
6992  template< typename MT2 >
6993  inline EnableIf_< VectorizedSchurAssign<MT2> > schurAssign( const DenseMatrix<MT2,false>& rhs );
6994 
6995  template< typename MT2 > inline void schurAssign( const DenseMatrix<MT2,true>& rhs );
6996  template< typename MT2 > inline void schurAssign( const SparseMatrix<MT2,false>& rhs );
6997  template< typename MT2 > inline void schurAssign( const SparseMatrix<MT2,true>& rhs );
6999  //**********************************************************************************************
7000 
7001  private:
7002  //**Utility functions***************************************************************************
7005  inline bool hasOverlap() const noexcept;
7007  //**********************************************************************************************
7008 
7009  //**Member variables****************************************************************************
7012  Operand matrix_;
7013  const size_t row_;
7014  const size_t column_;
7015  const size_t m_;
7016  const size_t n_;
7017 
7018  //**********************************************************************************************
7019 
7020  //**Friend declarations*************************************************************************
7021  template< typename MT2, bool AF2, bool SO2, bool DF2 > friend class Submatrix;
7022  //**********************************************************************************************
7023 
7024  //**Compile time checks*************************************************************************
7032  //**********************************************************************************************
7033 };
7035 //*************************************************************************************************
7036 
7037 
7038 
7039 
7040 //=================================================================================================
7041 //
7042 // CONSTRUCTOR
7043 //
7044 //=================================================================================================
7045 
7046 //*************************************************************************************************
7060 template< typename MT > // Type of the dense matrix
7061 inline Submatrix<MT,aligned,false,true>::Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n )
7062  : matrix_( matrix ) // The dense matrix containing the submatrix
7063  , row_ ( rindex ) // The first row of the submatrix
7064  , column_( cindex ) // The first column of the submatrix
7065  , m_ ( m ) // The number of rows of the submatrix
7066  , n_ ( n ) // The number of columns of the submatrix
7067 {
7068  if( ( row_ + m_ > matrix_.rows() ) || ( column_ + n_ > matrix_.columns() ) ) {
7069  BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix specification" );
7070  }
7071 
7072  if( ( simdEnabled && matrix_.data() != nullptr && !checkAlignment( data() ) ) ||
7073  ( m_ > 1UL && matrix_.spacing() % SIMDSIZE != 0UL ) ) {
7074  BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix alignment" );
7075  }
7076 }
7078 //*************************************************************************************************
7079 
7080 
7081 
7082 
7083 //=================================================================================================
7084 //
7085 // DATA ACCESS FUNCTIONS
7086 //
7087 //=================================================================================================
7088 
7089 //*************************************************************************************************
7100 template< typename MT > // Type of the dense matrix
7102  Submatrix<MT,aligned,false,true>::operator()( size_t i, size_t j )
7103 {
7104  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
7105  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
7106 
7107  return matrix_(row_+i,column_+j);
7108 }
7110 //*************************************************************************************************
7111 
7112 
7113 //*************************************************************************************************
7124 template< typename MT > // Type of the dense matrix
7126  Submatrix<MT,aligned,false,true>::operator()( size_t i, size_t j ) const
7127 {
7128  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
7129  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
7130 
7131  return const_cast<const MT&>( matrix_ )(row_+i,column_+j);
7132 }
7134 //*************************************************************************************************
7135 
7136 
7137 //*************************************************************************************************
7149 template< typename MT > // Type of the dense matrix
7151  Submatrix<MT,aligned,false,true>::at( size_t i, size_t j )
7152 {
7153  if( i >= rows() ) {
7154  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
7155  }
7156  if( j >= columns() ) {
7157  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
7158  }
7159  return (*this)(i,j);
7160 }
7162 //*************************************************************************************************
7163 
7164 
7165 //*************************************************************************************************
7177 template< typename MT > // Type of the dense matrix
7179  Submatrix<MT,aligned,false,true>::at( size_t i, size_t j ) const
7180 {
7181  if( i >= rows() ) {
7182  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
7183  }
7184  if( j >= columns() ) {
7185  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
7186  }
7187  return (*this)(i,j);
7188 }
7190 //*************************************************************************************************
7191 
7192 
7193 //*************************************************************************************************
7203 template< typename MT > // Type of the dense matrix
7204 inline typename Submatrix<MT,aligned,false,true>::Pointer
7205  Submatrix<MT,aligned,false,true>::data() noexcept
7206 {
7207  return matrix_.data() + row_*spacing() + column_;
7208 }
7210 //*************************************************************************************************
7211 
7212 
7213 //*************************************************************************************************
7223 template< typename MT > // Type of the dense matrix
7224 inline typename Submatrix<MT,aligned,false,true>::ConstPointer
7225  Submatrix<MT,aligned,false,true>::data() const noexcept
7226 {
7227  return matrix_.data() + row_*spacing() + column_;
7228 }
7230 //*************************************************************************************************
7231 
7232 
7233 //*************************************************************************************************
7242 template< typename MT > // Type of the dense matrix
7243 inline typename Submatrix<MT,aligned,false,true>::Pointer
7244  Submatrix<MT,aligned,false,true>::data( size_t i ) noexcept
7245 {
7246  return matrix_.data() + (row_+i)*spacing() + column_;
7247 }
7249 //*************************************************************************************************
7250 
7251 
7252 //*************************************************************************************************
7261 template< typename MT > // Type of the dense matrix
7262 inline typename Submatrix<MT,aligned,false,true>::ConstPointer
7263  Submatrix<MT,aligned,false,true>::data( size_t i ) const noexcept
7264 {
7265  return matrix_.data() + (row_+i)*spacing() + column_;
7266 }
7268 //*************************************************************************************************
7269 
7270 
7271 //*************************************************************************************************
7283 template< typename MT > // Type of the dense matrix
7286 {
7287  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
7288  return ( matrix_.begin( row_ + i ) + column_ );
7289 }
7291 //*************************************************************************************************
7292 
7293 
7294 //*************************************************************************************************
7306 template< typename MT > // Type of the dense matrix
7308  Submatrix<MT,aligned,false,true>::begin( size_t i ) const
7309 {
7310  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
7311  return ( matrix_.cbegin( row_ + i ) + column_ );
7312 }
7314 //*************************************************************************************************
7315 
7316 
7317 //*************************************************************************************************
7329 template< typename MT > // Type of the dense matrix
7332 {
7333  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
7334  return ( matrix_.cbegin( row_ + i ) + column_ );
7335 }
7337 //*************************************************************************************************
7338 
7339 
7340 //*************************************************************************************************
7352 template< typename MT > // Type of the dense matrix
7355 {
7356  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
7357  return ( matrix_.begin( row_ + i ) + column_ + n_ );
7358 }
7360 //*************************************************************************************************
7361 
7362 
7363 //*************************************************************************************************
7375 template< typename MT > // Type of the dense matrix
7377  Submatrix<MT,aligned,false,true>::end( size_t i ) const
7378 {
7379  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
7380  return ( matrix_.cbegin( row_ + i ) + column_ + n_ );
7381 }
7383 //*************************************************************************************************
7384 
7385 
7386 //*************************************************************************************************
7398 template< typename MT > // Type of the dense matrix
7400  Submatrix<MT,aligned,false,true>::cend( size_t i ) const
7401 {
7402  BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
7403  return ( matrix_.cbegin( row_ + i ) + column_ + n_ );
7404 }
7406 //*************************************************************************************************
7407 
7408 
7409 
7410 
7411 //=================================================================================================
7412 //
7413 // ASSIGNMENT OPERATORS
7414 //
7415 //=================================================================================================
7416 
7417 //*************************************************************************************************
7428 template< typename MT > // Type of the dense matrix
7429 inline Submatrix<MT,aligned,false,true>&
7430  Submatrix<MT,aligned,false,true>::operator=( const ElementType& rhs )
7431 {
7432  const size_t iend( row_ + m_ );
7433 
7434  for( size_t i=row_; i<iend; ++i )
7435  {
7436  const size_t jbegin( ( IsUpper<MT>::value )
7437  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
7438  ?( max( i+1UL, column_ ) )
7439  :( max( i, column_ ) ) )
7440  :( column_ ) );
7441  const size_t jend ( ( IsLower<MT>::value )
7442  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
7443  ?( min( i, column_+n_ ) )
7444  :( min( i+1UL, column_+n_ ) ) )
7445  :( column_+n_ ) );
7446 
7447  for( size_t j=jbegin; j<jend; ++j )
7448  matrix_(i,j) = rhs;
7449  }
7450 
7451  return *this;
7452 }
7454 //*************************************************************************************************
7455 
7456 
7457 //*************************************************************************************************
7470 template< typename MT > // Type of the dense matrix
7471 inline Submatrix<MT,aligned,false,true>&
7472  Submatrix<MT,aligned,false,true>::operator=( initializer_list< initializer_list<ElementType> > list )
7473 {
7474  if( list.size() != rows() || determineColumns( list ) > columns() ) {
7475  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to submatrix" );
7476  }
7477 
7478  size_t i( 0UL );
7479 
7480  for( const auto& rowList : list ) {
7481  std::fill( std::copy( rowList.begin(), rowList.end(), begin(i) ), end(i), ElementType() );
7482  ++i;
7483  }
7484 
7485  return *this;
7486 }
7488 //*************************************************************************************************
7489 
7490 
7491 //*************************************************************************************************
7506 template< typename MT > // Type of the dense matrix
7507 inline Submatrix<MT,aligned,false,true>&
7508  Submatrix<MT,aligned,false,true>::operator=( const Submatrix& rhs )
7509 {
7512 
7513  if( this == &rhs || ( &matrix_ == &rhs.matrix_ && row_ == rhs.row_ && column_ == rhs.column_ ) )
7514  return *this;
7515 
7516  if( rows() != rhs.rows() || columns() != rhs.columns() ) {
7517  BLAZE_THROW_INVALID_ARGUMENT( "Submatrix sizes do not match" );
7518  }
7519 
7520  if( !tryAssign( matrix_, rhs, row_, column_ ) ) {
7521  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7522  }
7523 
7524  decltype(auto) left( derestrict( *this ) );
7525 
7526  if( rhs.canAlias( &matrix_ ) ) {
7527  const ResultType tmp( rhs );
7528  smpAssign( left, tmp );
7529  }
7530  else {
7531  smpAssign( left, rhs );
7532  }
7533 
7534  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
7535 
7536  return *this;
7537 }
7539 //*************************************************************************************************
7540 
7541 
7542 //*************************************************************************************************
7557 template< typename MT > // Type of the dense matrix
7558 template< typename MT2 // Type of the right-hand side matrix
7559  , bool SO > // Storage order of the right-hand side matrix
7560 inline Submatrix<MT,aligned,false,true>&
7561  Submatrix<MT,aligned,false,true>::operator=( const Matrix<MT2,SO>& rhs )
7562 {
7564 
7565  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
7566  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
7567  }
7568 
7569  using Right = If_< IsRestricted<MT>, CompositeType_<MT2>, const MT2& >;
7570  Right right( ~rhs );
7571 
7572  if( !tryAssign( matrix_, right, row_, column_ ) ) {
7573  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7574  }
7575 
7576  if( IsSparseMatrix<MT2>::value ) {
7577  reset();
7578  }
7579 
7580  decltype(auto) left( derestrict( *this ) );
7581 
7582  if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
7583  const ResultType_<MT2> tmp( right );
7584  smpAssign( left, tmp );
7585  }
7586  else {
7587  smpAssign( left, right );
7588  }
7589 
7590  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
7591 
7592  return *this;
7593 }
7595 //*************************************************************************************************
7596 
7597 
7598 //*************************************************************************************************
7612 template< typename MT > // Type of the dense matrix
7613 template< typename MT2 // Type of the right-hand side matrix
7614  , bool SO > // Storage order of the right-hand side matrix
7615 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,false,true>& >
7616  Submatrix<MT,aligned,false,true>::operator+=( const Matrix<MT2,SO>& rhs )
7617 {
7621 
7622  using AddType = AddTrait_< ResultType, ResultType_<MT2> >;
7623 
7626 
7627  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
7628  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
7629  }
7630 
7631  if( !tryAddAssign( matrix_, ~rhs, row_, column_ ) ) {
7632  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7633  }
7634 
7635  decltype(auto) left( derestrict( *this ) );
7636 
7637  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
7638  (~rhs).canAlias( &matrix_ ) ) {
7639  const AddType tmp( *this + (~rhs) );
7640  smpAssign( left, tmp );
7641  }
7642  else {
7643  smpAddAssign( left, ~rhs );
7644  }
7645 
7646  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
7647 
7648  return *this;
7649 }
7651 //*************************************************************************************************
7652 
7653 
7654 //*************************************************************************************************
7668 template< typename MT > // Type of the dense matrix
7669 template< typename MT2 // Type of the right-hand side matrix
7670  , bool SO > // Storage order of the right-hand side matrix
7671 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,false,true>& >
7672  Submatrix<MT,aligned,false,true>::operator+=( const Matrix<MT2,SO>& rhs )
7673 {
7677 
7678  using AddType = AddTrait_< ResultType, ResultType_<MT2> >;
7679 
7682 
7683  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
7684  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
7685  }
7686 
7687  const AddType tmp( *this + (~rhs) );
7688 
7689  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
7690  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7691  }
7692 
7693  decltype(auto) left( derestrict( *this ) );
7694 
7695  smpAssign( left, tmp );
7696 
7697  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
7698 
7699  return *this;
7700 }
7702 //*************************************************************************************************
7703 
7704 
7705 //*************************************************************************************************
7719 template< typename MT > // Type of the dense matrix
7720 template< typename MT2 // Type of the right-hand side matrix
7721  , bool SO > // Storage order of the right-hand side matrix
7722 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,false,true>& >
7723  Submatrix<MT,aligned,false,true>::operator-=( const Matrix<MT2,SO>& rhs )
7724 {
7728 
7729  using SubType = SubTrait_< ResultType, ResultType_<MT2> >;
7730 
7733 
7734  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
7735  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
7736  }
7737 
7738  if( !trySubAssign( matrix_, ~rhs, row_, column_ ) ) {
7739  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7740  }
7741 
7742  decltype(auto) left( derestrict( *this ) );
7743 
7744  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
7745  (~rhs).canAlias( &matrix_ ) ) {
7746  const SubType tmp( *this - (~rhs ) );
7747  smpAssign( left, tmp );
7748  }
7749  else {
7750  smpSubAssign( left, ~rhs );
7751  }
7752 
7753  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
7754 
7755  return *this;
7756 }
7758 //*************************************************************************************************
7759 
7760 
7761 //*************************************************************************************************
7775 template< typename MT > // Type of the dense matrix
7776 template< typename MT2 // Type of the right-hand side matrix
7777  , bool SO > // Storage order of the right-hand side matrix
7778 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,false,true>& >
7779  Submatrix<MT,aligned,false,true>::operator-=( const Matrix<MT2,SO>& rhs )
7780 {
7784 
7785  using SubType = SubTrait_< ResultType, ResultType_<MT2> >;
7786 
7789 
7790  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
7791  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
7792  }
7793 
7794  const SubType tmp( *this - (~rhs) );
7795 
7796  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
7797  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7798  }
7799 
7800  decltype(auto) left( derestrict( *this ) );
7801 
7802  smpAssign( left, tmp );
7803 
7804  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
7805 
7806  return *this;
7807 }
7809 //*************************************************************************************************
7810 
7811 
7812 //*************************************************************************************************
7826 template< typename MT > // Type of the dense matrix
7827 template< typename MT2 // Type of the right-hand side matrix
7828  , bool SO > // Storage order of the right-hand side matrix
7829 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,false,true>& >
7830  Submatrix<MT,aligned,false,true>::operator%=( const Matrix<MT2,SO>& rhs )
7831 {
7835 
7836  using SchurType = SchurTrait_< ResultType, ResultType_<MT2> >;
7837 
7839 
7840  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
7841  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
7842  }
7843 
7844  if( !trySchurAssign( matrix_, ~rhs, row_, column_ ) ) {
7845  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7846  }
7847 
7848  decltype(auto) left( derestrict( *this ) );
7849 
7850  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
7851  (~rhs).canAlias( &matrix_ ) ) {
7852  const SchurType tmp( *this % (~rhs) );
7853  if( IsSparseMatrix<SchurType>::value )
7854  reset();
7855  smpAssign( left, tmp );
7856  }
7857  else {
7858  smpSchurAssign( left, ~rhs );
7859  }
7860 
7861  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
7862 
7863  return *this;
7864 }
7866 //*************************************************************************************************
7867 
7868 
7869 //*************************************************************************************************
7883 template< typename MT > // Type of the dense matrix
7884 template< typename MT2 // Type of the right-hand side matrix
7885  , bool SO > // Storage order of the right-hand side matrix
7886 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,false,true>& >
7887  Submatrix<MT,aligned,false,true>::operator%=( const Matrix<MT2,SO>& rhs )
7888 {
7892 
7893  using SchurType = SchurTrait_< ResultType, ResultType_<MT2> >;
7894 
7896 
7897  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
7898  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
7899  }
7900 
7901  const SchurType tmp( *this % (~rhs) );
7902 
7903  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
7904  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7905  }
7906 
7907  if( IsSparseMatrix<SchurType>::value ) {
7908  reset();
7909  }
7910 
7911  decltype(auto) left( derestrict( *this ) );
7912 
7913  smpAssign( left, tmp );
7914 
7915  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
7916 
7917  return *this;
7918 }
7920 //*************************************************************************************************
7921 
7922 
7923 //*************************************************************************************************
7937 template< typename MT > // Type of the dense matrix
7938 template< typename MT2 // Type of the right-hand side matrix
7939  , bool SO > // Storage order of the right-hand side matrix
7940 inline Submatrix<MT,aligned,false,true>&
7941  Submatrix<MT,aligned,false,true>::operator*=( const Matrix<MT2,SO>& rhs )
7942 {
7946 
7947  using MultType = MultTrait_< ResultType, ResultType_<MT2> >;
7948 
7951 
7952  if( columns() != (~rhs).rows() ) {
7953  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
7954  }
7955 
7956  const MultType tmp( *this * (~rhs) );
7957 
7958  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
7959  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7960  }
7961 
7962  decltype(auto) left( derestrict( *this ) );
7963 
7964  smpAssign( left, tmp );
7965 
7966  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
7967 
7968  return *this;
7969 }
7971 //*************************************************************************************************
7972 
7973 
7974 //*************************************************************************************************
7985 template< typename MT > // Type of the dense matrix
7986 template< typename Other > // Data type of the right-hand side scalar
7987 inline EnableIf_< IsNumeric<Other>, Submatrix<MT,aligned,false,true> >&
7988  Submatrix<MT,aligned,false,true>::operator*=( Other rhs )
7989 {
7991 
7992  decltype(auto) left( derestrict( *this ) );
7993  smpAssign( left, (*this) * rhs );
7994 
7995  return *this;
7996 }
7998 //*************************************************************************************************
7999 
8000 
8001 //*************************************************************************************************
8014 template< typename MT > // Type of the dense matrix
8015 template< typename Other > // Data type of the right-hand side scalar
8016 inline EnableIf_< IsNumeric<Other>, Submatrix<MT,aligned,false,true> >&
8017  Submatrix<MT,aligned,false,true>::operator/=( Other rhs )
8018 {
8020 
8021  BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
8022 
8023  decltype(auto) left( derestrict( *this ) );
8024  smpAssign( left, (*this) / rhs );
8025 
8026  return *this;
8027 }
8029 //*************************************************************************************************
8030 
8031 
8032 
8033 
8034 //=================================================================================================
8035 //
8036 // UTILITY FUNCTIONS
8037 //
8038 //=================================================================================================
8039 
8040 //*************************************************************************************************
8046 template< typename MT > // Type of the dense matrix
8047 inline typename Submatrix<MT,aligned,false,true>::Operand
8048  Submatrix<MT,aligned,false,true>::operand() const noexcept
8049 {
8050  return matrix_;
8051 }
8053 //*************************************************************************************************
8054 
8055 
8056 //*************************************************************************************************
8062 template< typename MT > // Type of the dense matrix
8063 inline size_t Submatrix<MT,aligned,false,true>::row() const noexcept
8064 {
8065  return row_;
8066 }
8068 //*************************************************************************************************
8069 
8070 
8071 //*************************************************************************************************
8077 template< typename MT > // Type of the dense matrix
8078 inline size_t Submatrix<MT,aligned,false,true>::column() const noexcept
8079 {
8080  return column_;
8081 }
8083 //*************************************************************************************************
8084 
8085 
8086 //*************************************************************************************************
8092 template< typename MT > // Type of the dense matrix
8093 inline size_t Submatrix<MT,aligned,false,true>::rows() const noexcept
8094 {
8095  return m_;
8096 }
8098 //*************************************************************************************************
8099 
8100 
8101 //*************************************************************************************************
8107 template< typename MT > // Type of the dense matrix
8108 inline size_t Submatrix<MT,aligned,false,true>::columns() const noexcept
8109 {
8110  return n_;
8111 }
8113 //*************************************************************************************************
8114 
8115 
8116 //*************************************************************************************************
8127 template< typename MT > // Type of the dense matrix
8128 inline size_t Submatrix<MT,aligned,false,true>::spacing() const noexcept
8129 {
8130  return matrix_.spacing();
8131 }
8133 //*************************************************************************************************
8134 
8135 
8136 //*************************************************************************************************
8142 template< typename MT > // Type of the dense matrix
8143 inline size_t Submatrix<MT,aligned,false,true>::capacity() const noexcept
8144 {
8145  return rows() * columns();
8146 }
8148 //*************************************************************************************************
8149 
8150 
8151 //*************************************************************************************************
8163 template< typename MT > // Type of the dense matrix
8164 inline size_t Submatrix<MT,aligned,false,true>::capacity( size_t i ) const noexcept
8165 {
8166  UNUSED_PARAMETER( i );
8167 
8168  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
8169 
8170  return columns();
8171 }
8173 //*************************************************************************************************
8174 
8175 
8176 //*************************************************************************************************
8182 template< typename MT > // Type of the dense matrix
8183 inline size_t Submatrix<MT,aligned,false,true>::nonZeros() const
8184 {
8185  const size_t iend( row_ + m_ );
8186  const size_t jend( column_ + n_ );
8187  size_t nonzeros( 0UL );
8188 
8189  for( size_t i=row_; i<iend; ++i )
8190  for( size_t j=column_; j<jend; ++j )
8191  if( !isDefault( matrix_(i,j) ) )
8192  ++nonzeros;
8193 
8194  return nonzeros;
8195 }
8197 //*************************************************************************************************
8198 
8199 
8200 //*************************************************************************************************
8212 template< typename MT > // Type of the dense matrix
8213 inline size_t Submatrix<MT,aligned,false,true>::nonZeros( size_t i ) const
8214 {
8215  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
8216 
8217  const size_t jend( column_ + n_ );
8218  size_t nonzeros( 0UL );
8219 
8220  for( size_t j=column_; j<jend; ++j )
8221  if( !isDefault( matrix_(row_+i,j) ) )
8222  ++nonzeros;
8223 
8224  return nonzeros;
8225 }
8227 //*************************************************************************************************
8228 
8229 
8230 //*************************************************************************************************
8236 template< typename MT > // Type of the dense matrix
8238 {
8239  using blaze::clear;
8240 
8241  for( size_t i=row_; i<row_+m_; ++i )
8242  {
8243  const size_t jbegin( ( IsUpper<MT>::value )
8244  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
8245  ?( max( i+1UL, column_ ) )
8246  :( max( i, column_ ) ) )
8247  :( column_ ) );
8248  const size_t jend ( ( IsLower<MT>::value )
8249  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
8250  ?( min( i, column_+n_ ) )
8251  :( min( i+1UL, column_+n_ ) ) )
8252  :( column_+n_ ) );
8253 
8254  for( size_t j=jbegin; j<jend; ++j )
8255  clear( matrix_(i,j) );
8256  }
8257 }
8259 //*************************************************************************************************
8260 
8261 
8262 //*************************************************************************************************
8274 template< typename MT > // Type of the dense matrix
8275 inline void Submatrix<MT,aligned,false,true>::reset( size_t i )
8276 {
8277  using blaze::clear;
8278 
8279  BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
8280 
8281  const size_t jbegin( ( IsUpper<MT>::value )
8282  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
8283  ?( max( i+1UL, column_ ) )
8284  :( max( i, column_ ) ) )
8285  :( column_ ) );
8286  const size_t jend ( ( IsLower<MT>::value )
8287  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
8288  ?( min( i, column_+n_ ) )
8289  :( min( i+1UL, column_+n_ ) ) )
8290  :( column_+n_ ) );
8291 
8292  for( size_t j=jbegin; j<jend; ++j )
8293  clear( matrix_(row_+i,j) );
8294 }
8296 //*************************************************************************************************
8297 
8298 
8299 //*************************************************************************************************
8309 template< typename MT > // Type of the dense matrix
8310 inline bool Submatrix<MT,aligned,false,true>::hasOverlap() const noexcept
8311 {
8312  BLAZE_INTERNAL_ASSERT( IsSymmetric<MT>::value || IsHermitian<MT>::value, "Invalid matrix detected" );
8313 
8314  if( ( row_ + m_ <= column_ ) || ( column_ + n_ <= row_ ) )
8315  return false;
8316  else return true;
8317 }
8319 //*************************************************************************************************
8320 
8321 
8322 
8323 
8324 //=================================================================================================
8325 //
8326 // NUMERIC FUNCTIONS
8327 //
8328 //=================================================================================================
8329 
8330 //*************************************************************************************************
8348 template< typename MT > // Type of the dense matrix
8349 inline Submatrix<MT,aligned,false,true>& Submatrix<MT,aligned,false,true>::transpose()
8350 {
8351  if( m_ != n_ ) {
8352  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
8353  }
8354 
8355  if( !tryAssign( matrix_, trans( *this ), row_, column_ ) ) {
8356  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
8357  }
8358 
8359  decltype(auto) left( derestrict( *this ) );
8360  const ResultType tmp( trans( *this ) );
8361  smpAssign( left, tmp );
8362 
8363  return *this;
8364 }
8366 //*************************************************************************************************
8367 
8368 
8369 //*************************************************************************************************
8387 template< typename MT > // Type of the dense matrix
8388 inline Submatrix<MT,aligned,false,true>& Submatrix<MT,aligned,false,true>::ctranspose()
8389 {
8390  if( m_ != n_ ) {
8391  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
8392  }
8393 
8394  if( !tryAssign( matrix_, ctrans( *this ), row_, column_ ) ) {
8395  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
8396  }
8397 
8398  decltype(auto) left( derestrict( *this ) );
8399  const ResultType tmp( ctrans( *this ) );
8400  smpAssign( left, tmp );
8401 
8402  return *this;
8403 }
8405 //*************************************************************************************************
8406 
8407 
8408 //*************************************************************************************************
8421 template< typename MT > // Type of the dense matrix
8422 template< typename Other > // Data type of the scalar value
8423 inline Submatrix<MT,aligned,false,true>& Submatrix<MT,aligned,false,true>::scale( const Other& scalar )
8424 {
8426 
8427  const size_t iend( row_ + m_ );
8428 
8429  for( size_t i=row_; i<iend; ++i )
8430  {
8431  const size_t jbegin( ( IsUpper<MT>::value )
8432  ?( ( IsStrictlyUpper<MT>::value )
8433  ?( max( i+1UL, column_ ) )
8434  :( max( i, column_ ) ) )
8435  :( column_ ) );
8436  const size_t jend ( ( IsLower<MT>::value )
8437  ?( ( IsStrictlyLower<MT>::value )
8438  ?( min( i, column_+n_ ) )
8439  :( min( i+1UL, column_+n_ ) ) )
8440  :( column_+n_ ) );
8441 
8442  for( size_t j=jbegin; j<jend; ++j )
8443  matrix_(i,j) *= scalar;
8444  }
8445 
8446  return *this;
8447 }
8449 //*************************************************************************************************
8450 
8451 
8452 
8453 
8454 //=================================================================================================
8455 //
8456 // EXPRESSION TEMPLATE EVALUATION FUNCTIONS
8457 //
8458 //=================================================================================================
8459 
8460 //*************************************************************************************************
8471 template< typename MT > // Type of the dense matrix
8472 template< typename Other > // Data type of the foreign expression
8473 inline bool Submatrix<MT,aligned,false,true>::canAlias( const Other* alias ) const noexcept
8474 {
8475  return matrix_.isAliased( alias );
8476 }
8478 //*************************************************************************************************
8479 
8480 
8481 //*************************************************************************************************
8492 template< typename MT > // Type of the dense matrix
8493 template< typename MT2 // Data type of the foreign dense submatrix
8494  , bool AF2 // Alignment flag of the foreign dense submatrix
8495  , bool SO2 > // Storage order of the foreign dense submatrix
8496 inline bool Submatrix<MT,aligned,false,true>::canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
8497 {
8498  return ( matrix_.isAliased( &alias->matrix_ ) &&
8499  ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
8500  ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
8501 }
8503 //*************************************************************************************************
8504 
8505 
8506 //*************************************************************************************************
8517 template< typename MT > // Type of the dense matrix
8518 template< typename Other > // Data type of the foreign expression
8519 inline bool Submatrix<MT,aligned,false,true>::isAliased( const Other* alias ) const noexcept
8520 {
8521  return matrix_.isAliased( alias );
8522 }
8524 //*************************************************************************************************
8525 
8526 
8527 //*************************************************************************************************
8538 template< typename MT > // Type of the dense matrix
8539 template< typename MT2 // Data type of the foreign dense submatrix
8540  , bool AF2 // Alignment flag of the foreign dense submatrix
8541  , bool SO2 > // Storage order of the foreign dense submatrix
8542 inline bool Submatrix<MT,aligned,false,true>::isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
8543 {
8544  return ( matrix_.isAliased( &alias->matrix_ ) &&
8545  ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
8546  ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
8547 }
8549 //*************************************************************************************************
8550 
8551 
8552 //*************************************************************************************************
8562 template< typename MT > // Type of the dense matrix
8563 inline bool Submatrix<MT,aligned,false,true>::isAligned() const noexcept
8564 {
8565  return true;
8566 }
8568 //*************************************************************************************************
8569 
8570 
8571 //*************************************************************************************************
8582 template< typename MT > // Type of the dense matrix
8583 inline bool Submatrix<MT,aligned,false,true>::canSMPAssign() const noexcept
8584 {
8585  return ( rows() * columns() >= SMP_DMATASSIGN_THRESHOLD );
8586 }
8588 //*************************************************************************************************
8589 
8590 
8591 //*************************************************************************************************
8607 template< typename MT > // Type of the dense matrix
8608 BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,false,true>::SIMDType
8609  Submatrix<MT,aligned,false,true>::load( size_t i, size_t j ) const noexcept
8610 {
8611  return loada( i, j );
8612 }
8614 //*************************************************************************************************
8615 
8616 
8617 //*************************************************************************************************
8633 template< typename MT > // Type of the dense matrix
8634 BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,false,true>::SIMDType
8635  Submatrix<MT,aligned,false,true>::loada( size_t i, size_t j ) const noexcept
8636 {
8638 
8639  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
8640  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
8641  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
8642  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
8643 
8644  return matrix_.loada( row_+i, column_+j );
8645 }
8647 //*************************************************************************************************
8648 
8649 
8650 //*************************************************************************************************
8666 template< typename MT > // Type of the dense matrix
8667 BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,false,true>::SIMDType
8668  Submatrix<MT,aligned,false,true>::loadu( size_t i, size_t j ) const noexcept
8669 {
8671 
8672  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
8673  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
8674  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
8675  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
8676 
8677  return matrix_.loadu( row_+i, column_+j );
8678 }
8680 //*************************************************************************************************
8681 
8682 
8683 //*************************************************************************************************
8700 template< typename MT > // Type of the dense matrix
8702  Submatrix<MT,aligned,false,true>::store( size_t i, size_t j, const SIMDType& value ) noexcept
8703 {
8704  return storea( i, j, value );
8705 }
8707 //*************************************************************************************************
8708 
8709 
8710 //*************************************************************************************************
8727 template< typename MT > // Type of the dense matrix
8729  Submatrix<MT,aligned,false,true>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
8730 {
8732 
8733  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
8734  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
8735  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
8736  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
8737 
8738  return matrix_.storea( row_+i, column_+j, value );
8739 }
8741 //*************************************************************************************************
8742 
8743 
8744 //*************************************************************************************************
8761 template< typename MT > // Type of the dense matrix
8763  Submatrix<MT,aligned,false,true>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
8764 {
8766 
8767  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
8768  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
8769  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
8770  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
8771 
8772  matrix_.storeu( row_+i, column_+j, value );
8773 }
8775 //*************************************************************************************************
8776 
8777 
8778 //*************************************************************************************************
8796 template< typename MT > // Type of the dense matrix
8798  Submatrix<MT,aligned,false,true>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
8799 {
8801 
8802  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
8803  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
8804  BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
8805  BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
8806 
8807  matrix_.stream( row_+i, column_+j, value );
8808 }
8810 //*************************************************************************************************
8811 
8812 
8813 //*************************************************************************************************
8825 template< typename MT > // Type of the dense matrix
8826 template< typename MT2 > // Type of the right-hand side dense matrix
8827 inline DisableIf_< typename Submatrix<MT,aligned,false,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
8828  Submatrix<MT,aligned,false,true>::assign( const DenseMatrix<MT2,false>& rhs )
8829 {
8830  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8831  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8832 
8833  const size_t jpos( n_ & size_t(-2) );
8834  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
8835 
8836  for( size_t i=0UL; i<m_; ++i ) {
8837  for( size_t j=0UL; j<jpos; j+=2UL ) {
8838  matrix_(row_+i,column_+j ) = (~rhs)(i,j );
8839  matrix_(row_+i,column_+j+1UL) = (~rhs)(i,j+1UL);
8840  }
8841  if( jpos < n_ ) {
8842  matrix_(row_+i,column_+jpos) = (~rhs)(i,jpos);
8843  }
8844  }
8845 }
8847 //*************************************************************************************************
8848 
8849 
8850 //*************************************************************************************************
8862 template< typename MT > // Type of the dense matrix
8863 template< typename MT2 > // Type of the right-hand side dense matrix
8864 inline EnableIf_< typename Submatrix<MT,aligned,false,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
8865  Submatrix<MT,aligned,false,true>::assign( const DenseMatrix<MT2,false>& rhs )
8866 {
8868 
8869  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8870  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8871 
8872  const size_t jpos( n_ & size_t(-SIMDSIZE) );
8873  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
8874 
8875  if( useStreaming &&
8876  m_*n_ > ( cacheSize / ( sizeof(ElementType) * 3UL ) ) &&
8877  !(~rhs).isAliased( &matrix_ ) )
8878  {
8879  for( size_t i=0UL; i<m_; ++i )
8880  {
8881  size_t j( 0UL );
8882  Iterator left( begin(i) );
8883  ConstIterator_<MT2> right( (~rhs).begin(i) );
8884 
8885  for( ; j<jpos; j+=SIMDSIZE ) {
8886  left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8887  }
8888  for( ; j<n_; ++j ) {
8889  *left = *right; ++left; ++right;
8890  }
8891  }
8892  }
8893  else
8894  {
8895  for( size_t i=0UL; i<m_; ++i )
8896  {
8897  size_t j( 0UL );
8898  Iterator left( begin(i) );
8899  ConstIterator_<MT2> right( (~rhs).begin(i) );
8900 
8901  for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
8902  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8903  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8904  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8905  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8906  }
8907  for( ; j<jpos; j+=SIMDSIZE ) {
8908  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8909  }
8910  for( ; j<n_; ++j ) {
8911  *left = *right; ++left; ++right;
8912  }
8913  }
8914  }
8915 }
8917 //*************************************************************************************************
8918 
8919 
8920 //*************************************************************************************************
8932 template< typename MT > // Type of the dense matrix
8933 template< typename MT2 > // Type of the right-hand side dense matrix
8934 inline void Submatrix<MT,aligned,false,true>::assign( const DenseMatrix<MT2,true>& rhs )
8935 {
8937 
8938  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8939  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8940 
8941  constexpr size_t block( BLOCK_SIZE );
8942 
8943  for( size_t ii=0UL; ii<m_; ii+=block ) {
8944  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
8945  for( size_t jj=0UL; jj<n_; jj+=block ) {
8946  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
8947  for( size_t i=ii; i<iend; ++i ) {
8948  for( size_t j=jj; j<jend; ++j ) {
8949  matrix_(row_+i,column_+j) = (~rhs)(i,j);
8950  }
8951  }
8952  }
8953  }
8954 }
8956 //*************************************************************************************************
8957 
8958 
8959 //*************************************************************************************************
8971 template< typename MT > // Type of the dense matrix
8972 template< typename MT2 > // Type of the right-hand side sparse matrix
8973 inline void Submatrix<MT,aligned,false,true>::assign( const SparseMatrix<MT2,false>& rhs )
8974 {
8975  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
8976  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
8977 
8978  for( size_t i=0UL; i<m_; ++i )
8979  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
8980  matrix_(row_+i,column_+element->index()) = element->value();
8981 }
8983 //*************************************************************************************************
8984 
8985 
8986 //*************************************************************************************************
8998 template< typename MT > // Type of the dense matrix
8999 template< typename MT2 > // Type of the right-hand side sparse matrix
9000 inline void Submatrix<MT,aligned,false,true>::assign( const SparseMatrix<MT2,true>& rhs )
9001 {
9003 
9004  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
9005  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
9006 
9007  for( size_t j=0UL; j<n_; ++j )
9008  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
9009  matrix_(row_+element->index(),column_+j) = element->value();
9010 }
9012 //*************************************************************************************************
9013 
9014 
9015 //*************************************************************************************************
9027 template< typename MT > // Type of the dense matrix
9028 template< typename MT2 > // Type of the right-hand side dense matrix
9029 inline DisableIf_< typename Submatrix<MT,aligned,false,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
9030  Submatrix<MT,aligned,false,true>::addAssign( const DenseMatrix<MT2,false>& rhs )
9031 {
9032  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
9033  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
9034 
9035  const size_t jpos( n_ & size_t(-2) );
9036  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
9037 
9038  for( size_t i=0UL; i<m_; ++i )
9039  {
9040  if( IsDiagonal<MT2>::value ) {
9041  matrix_(row_+i,column_+i) += (~rhs)(i,i);
9042  }
9043  else {
9044  for( size_t j=0UL; j<jpos; j+=2UL ) {
9045  matrix_(row_+i,column_+j ) += (~rhs)(i,j );
9046  matrix_(row_+i,column_+j+1UL) += (~rhs)(i,j+1UL);
9047  }
9048  if( jpos < n_ ) {
9049  matrix_(row_+i,column_+jpos) += (~rhs)(i,jpos);
9050  }
9051  }
9052  }
9053 }
9055 //*************************************************************************************************
9056 
9057 
9058 //*************************************************************************************************
9070 template< typename MT > // Type of the dense matrix
9071 template< typename MT2 > // Type of the right-hand side dense matrix
9072 inline EnableIf_< typename Submatrix<MT,aligned,false,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
9073  Submatrix<MT,aligned,false,true>::addAssign( const DenseMatrix<MT2,false>& rhs )
9074 {
9076 
9077  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
9078  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
9079 
9080  for( size_t i=0UL; i<m_; ++i )
9081  {
9082  const size_t jbegin( ( IsUpper<MT2>::value )
9083  ?( ( IsStrictlyUpper<MT2>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
9084  :( 0UL ) );
9085  const size_t jend ( ( IsLower<MT2>::value )
9086  ?( IsStrictlyLower<MT2>::value ? i : i+1UL )
9087  :( n_ ) );
9088  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
9089 
9090  const size_t jpos( jend & size_t(-SIMDSIZE) );
9091  BLAZE_INTERNAL_ASSERT( ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
9092 
9093  size_t j( jbegin );
9094  Iterator left( begin(i) + jbegin );
9095  ConstIterator_<MT2> right( (~rhs).begin(i) + jbegin );
9096 
9097  for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
9098  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
9099  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
9100  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
9101  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
9102  }
9103  for( ; j<jpos; j+=SIMDSIZE ) {
9104  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
9105  }
9106  for( ; j<jend; ++j ) {
9107  *left += *right; ++left; ++right;
9108  }
9109  }
9110 }
9112 //*************************************************************************************************
9113 
9114 
9115 //*************************************************************************************************
9127 template< typename MT > // Type of the dense matrix
9128 template< typename MT2 > // Type of the right-hand side dense matrix
9129 inline void Submatrix<MT,aligned,false,true>::addAssign( const DenseMatrix<MT2,true>& rhs )
9130 {
9132 
9133  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
9134  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
9135 
9136  constexpr size_t block( BLOCK_SIZE );
9137 
9138  for( size_t ii=0UL; ii<m_; ii+=block ) {
9139  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
9140  for( size_t jj=0UL; jj<n_; jj+=block ) {
9141  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
9142  for( size_t i=ii; i<iend; ++i ) {
9143  for( size_t j=jj; j<jend; ++j ) {
9144  matrix_(row_+i,column_+j) += (~rhs)(i,j);
9145  }
9146  }
9147  }
9148  }
9149 }
9151 //*************************************************************************************************
9152 
9153 
9154 //*************************************************************************************************
9166 template< typename MT > // Type of the dense matrix
9167 template< typename MT2 > // Type of the right-hand side sparse matrix
9168 inline void Submatrix<MT,aligned,false,true>::addAssign( const SparseMatrix<MT2,false>& rhs )
9169 {
9170  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
9171  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
9172 
9173  for( size_t i=0UL; i<m_; ++i )
9174  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
9175  matrix_(row_+i,column_+element->index()) += element->value();
9176 }
9178 //*************************************************************************************************
9179 
9180 
9181 //*************************************************************************************************
9193 template< typename MT > // Type of the dense matrix
9194 template< typename MT2 > // Type of the right-hand side sparse matrix
9195 inline void Submatrix<MT,aligned,false,true>::addAssign( const SparseMatrix<MT2,true>& rhs )
9196 {
9198 
9199  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
9200  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
9201 
9202  for( size_t j=0UL; j<n_; ++j )
9203  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
9204  matrix_(row_+element->index(),column_+j) += element->value();
9205 }
9207 //*************************************************************************************************
9208 
9209 
9210 //*************************************************************************************************
9222 template< typename MT > // Type of the dense matrix
9223 template< typename MT2 > // Type of the right-hand side dense matrix
9224 inline DisableIf_< typename Submatrix<MT,aligned,false,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
9225  Submatrix<MT,aligned,false,true>::subAssign( const DenseMatrix<MT2,false>& rhs )
9226 {
9227  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
9228  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
9229 
9230  const size_t jpos( n_ & size_t(-2) );
9231  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
9232 
9233  for( size_t i=0UL; i<m_; ++i )
9234  {
9235  if( IsDiagonal<MT2>::value ) {
9236  matrix_(row_+i,column_+i) -= (~rhs)(i,i);
9237  }
9238  else {
9239  for( size_t j=0UL; j<jpos; j+=2UL ) {
9240  matrix_(row_+i,column_+j ) -= (~rhs)(i,j );
9241  matrix_(row_+i,column_+j+1UL) -= (~rhs)(i,j+1UL);
9242  }
9243  if( jpos < n_ ) {
9244  matrix_(row_+i,column_+jpos) -= (~rhs)(i,jpos);
9245  }
9246  }
9247  }
9248 }
9250 //*************************************************************************************************
9251 
9252 
9253 //*************************************************************************************************
9265 template< typename MT > // Type of the dense matrix
9266 template< typename MT2 > // Type of the right-hand side dense matrix
9267 inline EnableIf_< typename Submatrix<MT,aligned,false,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
9268  Submatrix<MT,aligned,false,true>::subAssign( const DenseMatrix<MT2,false>& rhs )
9269 {
9271 
9272  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
9273  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
9274 
9275  for( size_t i=0UL; i<m_; ++i )
9276  {
9277  const size_t jbegin( ( IsUpper<MT2>::value )
9278  ?( ( IsStrictlyUpper<MT2>::value ? i+1UL : i ) & size_t(-SIMDSIZE) )
9279  :( 0UL ) );
9280  const size_t jend ( ( IsLower<MT2>::value )
9281  ?( IsStrictlyLower<MT2>::value ? i : i+1UL )
9282  :( n_ ) );
9283  BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
9284 
9285  const size_t jpos( jend & size_t(-SIMDSIZE) );
9286  BLAZE_INTERNAL_ASSERT( ( jend - ( jend % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
9287 
9288  size_t j( jbegin );
9289  Iterator left( begin(i) + jbegin );
9290  ConstIterator_<MT2> right( (~rhs).begin(i) + jbegin );
9291 
9292  for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
9293  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
9294  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
9295  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
9296  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
9297  }
9298  for( ; j<jpos; j+=SIMDSIZE ) {
9299  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
9300  }
9301  for( ; j<jend; ++j ) {
9302  *left -= *right; ++left; ++right;
9303  }
9304  }
9305 }
9307 //*************************************************************************************************
9308 
9309 
9310 //*************************************************************************************************
9322 template< typename MT > // Type of the dense matrix
9323 template< typename MT2 > // Type of the right-hand side dense matrix
9324 inline void Submatrix<MT,aligned,false,true>::subAssign( const DenseMatrix<MT2,true>& rhs )
9325 {
9327 
9328  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
9329  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
9330 
9331  constexpr size_t block( BLOCK_SIZE );
9332 
9333  for( size_t ii=0UL; ii<m_; ii+=block ) {
9334  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
9335  for( size_t jj=0UL; jj<n_; jj+=block ) {
9336  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
9337  for( size_t i=ii; i<iend; ++i ) {
9338  for( size_t j=jj; j<jend; ++j ) {
9339  matrix_(row_+i,column_+j) -= (~rhs)(i,j);
9340  }
9341  }
9342  }
9343  }
9344 }
9346 //*************************************************************************************************
9347 
9348 
9349 //*************************************************************************************************
9361 template< typename MT > // Type of the dense matrix
9362 template< typename MT2 > // Type of the right-hand side sparse matrix
9363 inline void Submatrix<MT,aligned,false,true>::subAssign( const SparseMatrix<MT2,false>& rhs )
9364 {
9365  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
9366  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
9367 
9368  for( size_t i=0UL; i<m_; ++i )
9369  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
9370  matrix_(row_+i,column_+element->index()) -= element->value();
9371 }
9373 //*************************************************************************************************
9374 
9375 
9376 //*************************************************************************************************
9388 template< typename MT > // Type of the dense matrix
9389 template< typename MT2 > // Type of the right-hand side sparse matrix
9390 inline void Submatrix<MT,aligned,false,true>::subAssign( const SparseMatrix<MT2,true>& rhs )
9391 {
9393 
9394  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
9395  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
9396 
9397  for( size_t j=0UL; j<n_; ++j )
9398  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
9399  matrix_(row_+element->index(),column_+j) -= element->value();
9400 }
9402 //*************************************************************************************************
9403 
9404 
9405 //*************************************************************************************************
9417 template< typename MT > // Type of the dense matrix
9418 template< typename MT2 > // Type of the right-hand side dense matrix
9419 inline DisableIf_< typename Submatrix<MT,aligned,false,true>::BLAZE_TEMPLATE VectorizedSchurAssign<MT2> >
9420  Submatrix<MT,aligned,false,true>::schurAssign( const DenseMatrix<MT2,false>& rhs )
9421 {
9422  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
9423  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
9424 
9425  const size_t jpos( n_ & size_t(-2) );
9426  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % 2UL ) ) == jpos, "Invalid end calculation" );
9427 
9428  for( size_t i=0UL; i<m_; ++i ) {
9429  for( size_t j=0UL; j<jpos; j+=2UL ) {
9430  matrix_(row_+i,column_+j ) *= (~rhs)(i,j );
9431  matrix_(row_+i,column_+j+1UL) *= (~rhs)(i,j+1UL);
9432  }
9433  if( jpos < n_ ) {
9434  matrix_(row_+i,column_+jpos) *= (~rhs)(i,jpos);
9435  }
9436  }
9437 }
9439 //*************************************************************************************************
9440 
9441 
9442 //*************************************************************************************************
9454 template< typename MT > // Type of the dense matrix
9455 template< typename MT2 > // Type of the right-hand side dense matrix
9456 inline EnableIf_< typename Submatrix<MT,aligned,false,true>::BLAZE_TEMPLATE VectorizedSchurAssign<MT2> >
9457  Submatrix<MT,aligned,false,true>::schurAssign( const DenseMatrix<MT2,false>& rhs )
9458 {
9460 
9461  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
9462  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
9463 
9464  for( size_t i=0UL; i<m_; ++i )
9465  {
9466  const size_t jpos( n_ & size_t(-SIMDSIZE) );
9467  BLAZE_INTERNAL_ASSERT( ( n_ - ( n_ % (SIMDSIZE) ) ) == jpos, "Invalid end calculation" );
9468 
9469  size_t j( 0UL );
9470  Iterator left( begin(i) );
9471  ConstIterator_<MT2> right( (~rhs).begin(i) );
9472 
9473  for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
9474  left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
9475  left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
9476  left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
9477  left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
9478  }
9479  for( ; j<jpos; j+=SIMDSIZE ) {
9480  left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
9481  }
9482  for( ; j<n_; ++j ) {
9483  *left *= *right; ++left; ++right;
9484  }
9485  }
9486 }
9488 //*************************************************************************************************
9489 
9490 
9491 //*************************************************************************************************
9503 template< typename MT > // Type of the dense matrix
9504 template< typename MT2 > // Type of the right-hand side dense matrix
9505 inline void Submatrix<MT,aligned,false,true>::schurAssign( const DenseMatrix<MT2,true>& rhs )
9506 {
9508 
9509  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
9510  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
9511 
9512  constexpr size_t block( BLOCK_SIZE );
9513 
9514  for( size_t ii=0UL; ii<m_; ii+=block ) {
9515  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
9516  for( size_t jj=0UL; jj<n_; jj+=block ) {
9517  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
9518  for( size_t i=ii; i<iend; ++i ) {
9519  for( size_t j=jj; j<jend; ++j ) {
9520  matrix_(row_+i,column_+j) *= (~rhs)(i,j);
9521  }
9522  }
9523  }
9524  }
9525 }
9527 //*************************************************************************************************
9528 
9529 
9530 //*************************************************************************************************
9542 template< typename MT > // Type of the dense matrix
9543 template< typename MT2 > // Type of the right-hand side sparse matrix
9544 inline void Submatrix<MT,aligned,false,true>::schurAssign( const SparseMatrix<MT2,false>& rhs )
9545 {
9546  using blaze::reset;
9547 
9548  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
9549  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
9550 
9551  for( size_t i=0UL; i<m_; ++i )
9552  {
9553  size_t j( 0UL );
9554 
9555  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element ) {
9556  for( ; j<element->index(); ++j )
9557  reset( matrix_(row_+i,column_+j) );
9558  matrix_(row_+i,column_+j) *= element->value();
9559  ++j;
9560  }
9561 
9562  for( ; j<n_; ++j ) {
9563  reset( matrix_(row_+i,column_+j) );
9564  }
9565  }
9566 }
9568 //*************************************************************************************************
9569 
9570 
9571 //*************************************************************************************************
9583 template< typename MT > // Type of the dense matrix
9584 template< typename MT2 > // Type of the right-hand side sparse matrix
9585 inline void Submatrix<MT,aligned,false,true>::schurAssign( const SparseMatrix<MT2,true>& rhs )
9586 {
9587  using blaze::reset;
9588 
9590 
9591  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
9592  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
9593 
9594  for( size_t j=0UL; j<n_; ++j )
9595  {
9596  size_t i( 0UL );
9597 
9598  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element ) {
9599  for( ; i<element->index(); ++i )
9600  reset( matrix_(row_+i,column_+j) );
9601  matrix_(row_+element->index(),column_+j) *= element->value();
9602  ++i;
9603  }
9604 
9605  for( ; i<m_; ++i ) {
9606  reset( matrix_(row_+i,column_+j) );
9607  }
9608  }
9609 }
9611 //*************************************************************************************************
9612 
9613 
9614 
9615 
9616 
9617 
9618 
9619 
9620 //=================================================================================================
9621 //
9622 // CLASS TEMPLATE SPECIALIZATION FOR ALIGNED COLUMN-MAJOR DENSE SUBMATRICES
9623 //
9624 //=================================================================================================
9625 
9626 //*************************************************************************************************
9634 template< typename MT > // Type of the dense matrix
9635 class Submatrix<MT,aligned,true,true>
9636  : public View< DenseMatrix< Submatrix<MT,aligned,true,true>, true > >
9637 {
9638  private:
9639  //**Type definitions****************************************************************************
9641  using Operand = If_< IsExpression<MT>, MT, MT& >;
9642  //**********************************************************************************************
9643 
9644  public:
9645  //**Type definitions****************************************************************************
9646  using This = Submatrix<MT,aligned,true,true>;
9647  using BaseType = DenseMatrix<This,true>;
9648  using ResultType = SubmatrixTrait_<MT>;
9649  using OppositeType = OppositeType_<ResultType>;
9650  using TransposeType = TransposeType_<ResultType>;
9651  using ElementType = ElementType_<MT>;
9652  using SIMDType = SIMDTrait_<ElementType>;
9653  using ReturnType = ReturnType_<MT>;
9654  using CompositeType = const Submatrix&;
9655 
9657  using ConstReference = ConstReference_<MT>;
9658 
9660  using Reference = If_< IsConst<MT>, ConstReference, Reference_<MT> >;
9661 
9663  using ConstPointer = const ElementType*;
9664 
9666  using Pointer = If_< Or< IsConst<MT>, Not< HasMutableDataAccess<MT> > >, ConstPointer, ElementType* >;
9667 
9669  using ConstIterator = ConstIterator_<MT>;
9670 
9672  using Iterator = If_< IsConst<MT>, ConstIterator, Iterator_<MT> >;
9673  //**********************************************************************************************
9674 
9675  //**Compilation flags***************************************************************************
9677  enum : bool { simdEnabled = MT::simdEnabled };
9678 
9680  enum : bool { smpAssignable = MT::smpAssignable };
9681  //**********************************************************************************************
9682 
9683  //**Constructors********************************************************************************
9686  explicit inline Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n );
9687  // No explicitly declared copy constructor.
9689  //**********************************************************************************************
9690 
9691  //**Destructor**********************************************************************************
9692  // No explicitly declared destructor.
9693  //**********************************************************************************************
9694 
9695  //**Data access functions***********************************************************************
9698  inline Reference operator()( size_t i, size_t j );
9699  inline ConstReference operator()( size_t i, size_t j ) const;
9700  inline Reference at( size_t i, size_t j );
9701  inline ConstReference at( size_t i, size_t j ) const;
9702  inline Pointer data () noexcept;
9703  inline ConstPointer data () const noexcept;
9704  inline Pointer data ( size_t j ) noexcept;
9705  inline ConstPointer data ( size_t j ) const noexcept;
9706  inline Iterator begin ( size_t j );
9707  inline ConstIterator begin ( size_t j ) const;
9708  inline ConstIterator cbegin( size_t j ) const;
9709  inline Iterator end ( size_t j );
9710  inline ConstIterator end ( size_t j ) const;
9711  inline ConstIterator cend ( size_t j ) const;
9713  //**********************************************************************************************
9714 
9715  //**Assignment operators************************************************************************
9718  inline Submatrix& operator=( const ElementType& rhs );
9719  inline Submatrix& operator=( initializer_list< initializer_list<ElementType> > list );
9720  inline Submatrix& operator=( const Submatrix& rhs );
9721 
9722  template< typename MT2, bool SO >
9723  inline Submatrix& operator=( const Matrix<MT2,SO>& rhs );
9724 
9725  template< typename MT2, bool SO >
9726  inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
9727  operator+=( const Matrix<MT2,SO>& rhs );
9728 
9729  template< typename MT2, bool SO >
9730  inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
9731  operator+=( const Matrix<MT2,SO>& rhs );
9732 
9733  template< typename MT2, bool SO >
9734  inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
9735  operator-=( const Matrix<MT2,SO>& rhs );
9736 
9737  template< typename MT2, bool SO >
9738  inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
9739  operator-=( const Matrix<MT2,SO>& rhs );
9740 
9741  template< typename MT2, bool SO >
9742  inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
9743  operator%=( const Matrix<MT2,SO>& rhs );
9744 
9745  template< typename MT2, bool SO >
9746  inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix& >
9747  operator%=( const Matrix<MT2,SO>& rhs );
9748 
9749  template< typename MT2, bool SO >
9750  inline Submatrix& operator*=( const Matrix<MT2,SO>& rhs );
9751 
9752  template< typename Other >
9753  inline EnableIf_< IsNumeric<Other>, Submatrix >& operator*=( Other rhs );
9754 
9755  template< typename Other >
9756  inline EnableIf_< IsNumeric<Other>, Submatrix >& operator/=( Other rhs );
9758  //**********************************************************************************************
9759 
9760  //**Utility functions***************************************************************************
9763  inline Operand operand() const noexcept;
9764  inline size_t row() const noexcept;
9765  inline size_t column() const noexcept;
9766  inline size_t rows() const noexcept;
9767  inline size_t columns() const noexcept;
9768  inline size_t spacing() const noexcept;
9769  inline size_t capacity() const noexcept;
9770  inline size_t capacity( size_t i ) const noexcept;
9771  inline size_t nonZeros() const;
9772  inline size_t nonZeros( size_t i ) const;
9773  inline void reset();
9774  inline void reset( size_t i );
9776  //**********************************************************************************************
9777 
9778  //**Numeric functions***************************************************************************
9781  inline Submatrix& transpose();
9782  inline Submatrix& ctranspose();
9783 
9784  template< typename Other > inline Submatrix& scale( const Other& scalar );
9786  //**********************************************************************************************
9787 
9788  private:
9789  //**********************************************************************************************
9791  template< typename MT2 >
9792  struct VectorizedAssign {
9793  enum : bool { value = useOptimizedKernels &&
9794  simdEnabled && MT2::simdEnabled &&
9795  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value };
9796  };
9797  //**********************************************************************************************
9798 
9799  //**********************************************************************************************
9801  template< typename MT2 >
9802  struct VectorizedAddAssign {
9803  enum : bool { value = useOptimizedKernels &&
9804  simdEnabled && MT2::simdEnabled &&
9805  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
9806  HasSIMDAdd< ElementType, ElementType_<MT2> >::value &&
9807  !IsDiagonal<MT2>::value };
9808  };
9809  //**********************************************************************************************
9810 
9811  //**********************************************************************************************
9813  template< typename MT2 >
9814  struct VectorizedSubAssign {
9815  enum : bool { value = useOptimizedKernels &&
9816  simdEnabled && MT2::simdEnabled &&
9817  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
9818  HasSIMDSub< ElementType, ElementType_<MT2> >::value &&
9819  !IsDiagonal<MT2>::value };
9820  };
9821  //**********************************************************************************************
9822 
9823  //**********************************************************************************************
9825  template< typename MT2 >
9826  struct VectorizedSchurAssign {
9827  enum : bool { value = useOptimizedKernels &&
9828  simdEnabled && MT2::simdEnabled &&
9829  IsSIMDCombinable< ElementType, ElementType_<MT2> >::value &&
9830  HasSIMDMult< ElementType, ElementType_<MT2> >::value };
9831  };
9832  //**********************************************************************************************
9833 
9834  //**SIMD properties*****************************************************************************
9836  enum : size_t { SIMDSIZE = SIMDTrait<ElementType>::size };
9837  //**********************************************************************************************
9838 
9839  public:
9840  //**Expression template evaluation functions****************************************************
9843  template< typename Other >
9844  inline bool canAlias( const Other* alias ) const noexcept;
9845 
9846  template< typename MT2, bool AF2, bool SO2 >
9847  inline bool canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
9848 
9849  template< typename Other >
9850  inline bool isAliased( const Other* alias ) const noexcept;
9851 
9852  template< typename MT2, bool AF2, bool SO2 >
9853  inline bool isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept;
9854 
9855  inline bool isAligned () const noexcept;
9856  inline bool canSMPAssign() const noexcept;
9857 
9858  BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
9859  BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
9860  BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
9861 
9862  BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
9863  BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
9864  BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
9865  BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
9866 
9867  template< typename MT2 >
9868  inline DisableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,true>& rhs );
9869 
9870  template< typename MT2 >
9871  inline EnableIf_< VectorizedAssign<MT2> > assign( const DenseMatrix<MT2,true>& rhs );
9872 
9873  template< typename MT2 > inline void assign( const DenseMatrix<MT2,false>& rhs );
9874  template< typename MT2 > inline void assign( const SparseMatrix<MT2,true>& rhs );
9875  template< typename MT2 > inline void assign( const SparseMatrix<MT2,false>& rhs );
9876 
9877  template< typename MT2 >
9878  inline DisableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,true>& rhs );
9879 
9880  template< typename MT2 >
9881  inline EnableIf_< VectorizedAddAssign<MT2> > addAssign( const DenseMatrix<MT2,true>& rhs );
9882 
9883  template< typename MT2 > inline void addAssign( const DenseMatrix<MT2,false>& rhs );
9884  template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,true>& rhs );
9885  template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,false>& rhs );
9886 
9887  template< typename MT2 >
9888  inline DisableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,true>& rhs );
9889 
9890  template< typename MT2 >
9891  inline EnableIf_< VectorizedSubAssign<MT2> > subAssign( const DenseMatrix<MT2,true>& rhs );
9892 
9893  template< typename MT2 > inline void subAssign( const DenseMatrix<MT2,false>& rhs );
9894  template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,true>& rhs );
9895  template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,false>& rhs );
9896 
9897  template< typename MT2 >
9898  inline DisableIf_< VectorizedSchurAssign<MT2> > schurAssign( const DenseMatrix<MT2,true>& rhs );
9899 
9900  template< typename MT2 >
9901  inline EnableIf_< VectorizedSchurAssign<MT2> > schurAssign( const DenseMatrix<MT2,true>& rhs );
9902 
9903  template< typename MT2 > inline void schurAssign( const DenseMatrix<MT2,false>& rhs );
9904  template< typename MT2 > inline void schurAssign( const SparseMatrix<MT2,true>& rhs );
9905  template< typename MT2 > inline void schurAssign( const SparseMatrix<MT2,false>& rhs );
9907  //**********************************************************************************************
9908 
9909  private:
9910  //**Utility functions***************************************************************************
9913  inline bool hasOverlap() const noexcept;
9915  //**********************************************************************************************
9916 
9917  //**Member variables****************************************************************************
9920  Operand matrix_;
9921  const size_t row_;
9922  const size_t column_;
9923  const size_t m_;
9924  const size_t n_;
9925 
9926  //**********************************************************************************************
9927 
9928  //**Friend declarations*************************************************************************
9929  template< typename MT2, bool AF2, bool SO2, bool DF2 > friend class Submatrix;
9930  //**********************************************************************************************
9931 
9932  //**Compile time checks*************************************************************************
9940  //**********************************************************************************************
9941 };
9943 //*************************************************************************************************
9944 
9945 
9946 
9947 
9948 //=================================================================================================
9949 //
9950 // CONSTRUCTOR
9951 //
9952 //=================================================================================================
9953 
9954 //*************************************************************************************************
9968 template< typename MT > // Type of the dense matrix
9969 inline Submatrix<MT,aligned,true,true>::Submatrix( Operand matrix, size_t rindex, size_t cindex, size_t m, size_t n )
9970  : matrix_( matrix ) // The dense matrix containing the submatrix
9971  , row_ ( rindex ) // The first row of the submatrix
9972  , column_( cindex ) // The first column of the submatrix
9973  , m_ ( m ) // The number of rows of the submatrix
9974  , n_ ( n ) // The number of columns of the submatrix
9975 {
9976  if( ( row_ + m_ > matrix_.rows() ) || ( column_ + n_ > matrix_.columns() ) ) {
9977  BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix specification" );
9978  }
9979 
9980  if( ( simdEnabled && matrix_.data() != nullptr && !checkAlignment( data() ) ) ||
9981  ( n_ > 1UL && matrix_.spacing() % SIMDSIZE != 0UL ) ) {
9982  BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix alignment" );
9983  }
9984 }
9986 //*************************************************************************************************
9987 
9988 
9989 
9990 
9991 //=================================================================================================
9992 //
9993 // DATA ACCESS FUNCTIONS
9994 //
9995 //=================================================================================================
9996 
9997 //*************************************************************************************************
10008 template< typename MT > // Type of the dense matrix
10010  Submatrix<MT,aligned,true,true>::operator()( size_t i, size_t j )
10011 {
10012  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
10013  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
10014 
10015  return matrix_(row_+i,column_+j);
10016 }
10018 //*************************************************************************************************
10019 
10020 
10021 //*************************************************************************************************
10032 template< typename MT > // Type of the dense matrix
10034  Submatrix<MT,aligned,true,true>::operator()( size_t i, size_t j ) const
10035 {
10036  BLAZE_USER_ASSERT( i < rows() , "Invalid row access index" );
10037  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
10038 
10039  return const_cast<const MT&>( matrix_ )(row_+i,column_+j);
10040 }
10042 //*************************************************************************************************
10043 
10044 
10045 //*************************************************************************************************
10057 template< typename MT > // Type of the dense matrix
10059  Submatrix<MT,aligned,true,true>::at( size_t i, size_t j )
10060 {
10061  if( i >= rows() ) {
10062  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
10063  }
10064  if( j >= columns() ) {
10065  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
10066  }
10067  return (*this)(i,j);
10068 }
10070 //*************************************************************************************************
10071 
10072 
10073 //*************************************************************************************************
10085 template< typename MT > // Type of the dense matrix
10087  Submatrix<MT,aligned,true,true>::at( size_t i, size_t j ) const
10088 {
10089  if( i >= rows() ) {
10090  BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
10091  }
10092  if( j >= columns() ) {
10093  BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
10094  }
10095  return (*this)(i,j);
10096 }
10098 //*************************************************************************************************
10099 
10100 
10101 //*************************************************************************************************
10111 template< typename MT > // Type of the dense matrix
10112 inline typename Submatrix<MT,aligned,true,true>::Pointer
10113  Submatrix<MT,aligned,true,true>::data() noexcept
10114 {
10115  return matrix_.data() + row_ + column_*spacing();
10116 }
10118 //*************************************************************************************************
10119 
10120 
10121 //*************************************************************************************************
10131 template< typename MT > // Type of the dense matrix
10132 inline typename Submatrix<MT,aligned,true,true>::ConstPointer
10133  Submatrix<MT,aligned,true,true>::data() const noexcept
10134 {
10135  return matrix_.data() + row_ + column_*spacing();
10136 }
10138 //*************************************************************************************************
10139 
10140 
10141 //*************************************************************************************************
10150 template< typename MT > // Type of the dense matrix
10151 inline typename Submatrix<MT,aligned,true,true>::Pointer
10152  Submatrix<MT,aligned,true,true>::data( size_t j ) noexcept
10153 {
10154  return matrix_.data() + row_ + (column_+j)*spacing();
10155 }
10157 //*************************************************************************************************
10158 
10159 
10160 //*************************************************************************************************
10169 template< typename MT > // Type of the dense matrix
10170 inline typename Submatrix<MT,aligned,true,true>::ConstPointer
10171  Submatrix<MT,aligned,true,true>::data( size_t j ) const noexcept
10172 {
10173  return matrix_.data() + row_ + (column_+j)*spacing();
10174 }
10176 //*************************************************************************************************
10177 
10178 
10179 //*************************************************************************************************
10186 template< typename MT > // Type of the dense matrix
10189 {
10190  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
10191  return ( matrix_.begin( column_ + j ) + row_ );
10192 }
10194 //*************************************************************************************************
10195 
10196 
10197 //*************************************************************************************************
10204 template< typename MT > // Type of the dense matrix
10206  Submatrix<MT,aligned,true,true>::begin( size_t j ) const
10207 {
10208  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
10209  return ( matrix_.cbegin( column_ + j ) + row_ );
10210 }
10212 //*************************************************************************************************
10213 
10214 
10215 //*************************************************************************************************
10222 template< typename MT > // Type of the dense matrix
10224  Submatrix<MT,aligned,true,true>::cbegin( size_t j ) const
10225 {
10226  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
10227  return ( matrix_.cbegin( column_ + j ) + row_ );
10228 }
10230 //*************************************************************************************************
10231 
10232 
10233 //*************************************************************************************************
10240 template< typename MT > // Type of the dense matrix
10243 {
10244  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
10245  return ( matrix_.begin( column_ + j ) + row_ + m_ );
10246 }
10248 //*************************************************************************************************
10249 
10250 
10251 //*************************************************************************************************
10258 template< typename MT > // Type of the dense matrix
10260  Submatrix<MT,aligned,true,true>::end( size_t j ) const
10261 {
10262  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
10263  return ( matrix_.cbegin( column_ + j ) + row_ + m_ );
10264 }
10266 //*************************************************************************************************
10267 
10268 
10269 //*************************************************************************************************
10276 template< typename MT > // Type of the dense matrix
10278  Submatrix<MT,aligned,true,true>::cend( size_t j ) const
10279 {
10280  BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
10281  return ( matrix_.cbegin( column_ + j ) + row_ + m_ );
10282 }
10284 //*************************************************************************************************
10285 
10286 
10287 
10288 
10289 //=================================================================================================
10290 //
10291 // ASSIGNMENT OPERATORS
10292 //
10293 //=================================================================================================
10294 
10295 //*************************************************************************************************
10306 template< typename MT > // Type of the dense matrix
10307 inline Submatrix<MT,aligned,true,true>&
10308  Submatrix<MT,aligned,true,true>::operator=( const ElementType& rhs )
10309 {
10310  const size_t jend( column_ + n_ );
10311 
10312  for( size_t j=column_; j<jend; ++j )
10313  {
10314  const size_t ibegin( ( IsLower<MT>::value )
10315  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
10316  ?( max( j+1UL, row_ ) )
10317  :( max( j, row_ ) ) )
10318  :( row_ ) );
10319  const size_t iend ( ( IsUpper<MT>::value )
10320  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
10321  ?( min( j, row_+m_ ) )
10322  :( min( j+1UL, row_+m_ ) ) )
10323  :( row_+m_ ) );
10324 
10325  for( size_t i=ibegin; i<iend; ++i )
10326  matrix_(i,j) = rhs;
10327  }
10328 
10329  return *this;
10330 }
10332 //*************************************************************************************************
10333 
10334 
10335 //*************************************************************************************************
10348 template< typename MT > // Type of the dense matrix
10349 inline Submatrix<MT,aligned,true,true>&
10350  Submatrix<MT,aligned,true,true>::operator=( initializer_list< initializer_list<ElementType> > list )
10351 {
10352  if( list.size() != rows() || determineColumns( list ) > columns() ) {
10353  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to submatrix" );
10354  }
10355 
10356  size_t i( 0UL );
10357 
10358  for( const auto& rowList : list ) {
10359  size_t j( 0UL );
10360  for( const auto& element : rowList ) {
10361  matrix_(row_+i,column_+j) = element;
10362  ++j;
10363  }
10364  for( ; j<n_; ++j ) {
10365  matrix_(row_+i,column_+j) = ElementType();
10366  }
10367  ++i;
10368  }
10369 
10370  return *this;
10371 }
10373 //*************************************************************************************************
10374 
10375 
10376 //*************************************************************************************************
10391 template< typename MT > // Type of the dense matrix
10392 inline Submatrix<MT,aligned,true,true>&
10393  Submatrix<MT,aligned,true,true>::operator=( const Submatrix& rhs )
10394 {
10397 
10398  if( this == &rhs || ( &matrix_ == &rhs.matrix_ && row_ == rhs.row_ && column_ == rhs.column_ ) )
10399  return *this;
10400 
10401  if( rows() != rhs.rows() || columns() != rhs.columns() ) {
10402  BLAZE_THROW_INVALID_ARGUMENT( "Submatrix sizes do not match" );
10403  }
10404 
10405  if( !tryAssign( matrix_, rhs, row_, column_ ) ) {
10406  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
10407  }
10408 
10409  decltype(auto) left( derestrict( *this ) );
10410 
10411  if( rhs.canAlias( &matrix_ ) ) {
10412  const ResultType tmp( rhs );
10413  smpAssign( left, tmp );
10414  }
10415  else {
10416  smpAssign( left, rhs );
10417  }
10418 
10419  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
10420 
10421  return *this;
10422 }
10424 //*************************************************************************************************
10425 
10426 
10427 //*************************************************************************************************
10441 template< typename MT > // Type of the dense matrix
10442 template< typename MT2 // Type of the right-hand side matrix
10443  , bool SO > // Storage order of the right-hand side matrix
10444 inline Submatrix<MT,aligned,true,true>&
10445  Submatrix<MT,aligned,true,true>::operator=( const Matrix<MT2,SO>& rhs )
10446 {
10448 
10449  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
10450  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
10451  }
10452 
10453  using Right = If_< IsRestricted<MT>, CompositeType_<MT2>, const MT2& >;
10454  Right right( ~rhs );
10455 
10456  if( !tryAssign( matrix_, right, row_, column_ ) ) {
10457  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
10458  }
10459 
10460  if( IsSparseMatrix<MT2>::value ) {
10461  reset();
10462  }
10463 
10464  decltype(auto) left( derestrict( *this ) );
10465 
10466  if( IsReference<Right>::value && right.canAlias( &matrix_ ) ) {
10467  const ResultType_<MT2> tmp( right );
10468  smpAssign( left, tmp );
10469  }
10470  else {
10471  smpAssign( left, right );
10472  }
10473 
10474  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
10475 
10476  return *this;
10477 }
10479 //*************************************************************************************************
10480 
10481 
10482 //*************************************************************************************************
10496 template< typename MT > // Type of the dense matrix
10497 template< typename MT2 // Type of the right-hand side matrix
10498  , bool SO > // Storage order of the right-hand side matrix
10499 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,true,true>& >
10500  Submatrix<MT,aligned,true,true>::operator+=( const Matrix<MT2,SO>& rhs )
10501 {
10505 
10506  using AddType = AddTrait_< ResultType, ResultType_<MT2> >;
10507 
10510 
10511  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
10512  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
10513  }
10514 
10515  if( !tryAddAssign( matrix_, ~rhs, row_, column_ ) ) {
10516  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
10517  }
10518 
10519  decltype(auto) left( derestrict( *this ) );
10520 
10521  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
10522  (~rhs).canAlias( &matrix_ ) ) {
10523  const AddType tmp( *this + (~rhs) );
10524  smpAssign( left, tmp );
10525  }
10526  else {
10527  smpAddAssign( left, ~rhs );
10528  }
10529 
10530  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
10531 
10532  return *this;
10533 }
10535 //*************************************************************************************************
10536 
10537 
10538 //*************************************************************************************************
10552 template< typename MT > // Type of the dense matrix
10553 template< typename MT2 // Type of the right-hand side matrix
10554  , bool SO > // Storage order of the right-hand side matrix
10555 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,true,true>& >
10556  Submatrix<MT,aligned,true,true>::operator+=( const Matrix<MT2,SO>& rhs )
10557 {
10561 
10562  using AddType = AddTrait_< ResultType, ResultType_<MT2> >;
10563 
10566 
10567  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
10568  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
10569  }
10570 
10571  const AddType tmp( *this + (~rhs) );
10572 
10573  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
10574  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
10575  }
10576 
10577  decltype(auto) left( derestrict( *this ) );
10578 
10579  smpAssign( left, tmp );
10580 
10581  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
10582 
10583  return *this;
10584 }
10586 //*************************************************************************************************
10587 
10588 
10589 //*************************************************************************************************
10603 template< typename MT > // Type of the dense matrix
10604 template< typename MT2 // Type of the right-hand side matrix
10605  , bool SO > // Storage order of the right-hand side matrix
10606 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,true,true>& >
10607  Submatrix<MT,aligned,true,true>::operator-=( const Matrix<MT2,SO>& rhs )
10608 {
10612 
10613  using SubType = SubTrait_< ResultType, ResultType_<MT2> >;
10614 
10617 
10618  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
10619  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
10620  }
10621 
10622  if( !trySubAssign( matrix_, ~rhs, row_, column_ ) ) {
10623  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
10624  }
10625 
10626  decltype(auto) left( derestrict( *this ) );
10627 
10628  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
10629  (~rhs).canAlias( &matrix_ ) ) {
10630  const SubType tmp( *this - (~rhs ) );
10631  smpAssign( left, tmp );
10632  }
10633  else {
10634  smpSubAssign( left, ~rhs );
10635  }
10636 
10637  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
10638 
10639  return *this;
10640 }
10642 //*************************************************************************************************
10643 
10644 
10645 //*************************************************************************************************
10659 template< typename MT > // Type of the dense matrix
10660 template< typename MT2 // Type of the right-hand side matrix
10661  , bool SO > // Storage order of the right-hand side matrix
10662 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,true,true>& >
10663  Submatrix<MT,aligned,true,true>::operator-=( const Matrix<MT2,SO>& rhs )
10664 {
10668 
10669  using SubType = SubTrait_< ResultType, ResultType_<MT2> >;
10670 
10673 
10674  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
10675  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
10676  }
10677 
10678  const SubType tmp( *this - (~rhs) );
10679 
10680  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
10681  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
10682  }
10683 
10684  decltype(auto) left( derestrict( *this ) );
10685 
10686  smpAssign( left, tmp );
10687 
10688  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
10689 
10690  return *this;
10691 }
10693 //*************************************************************************************************
10694 
10695 
10696 //*************************************************************************************************
10710 template< typename MT > // Type of the dense matrix
10711 template< typename MT2 // Type of the right-hand side matrix
10712  , bool SO > // Storage order of the right-hand side matrix
10713 inline DisableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,true,true>& >
10714  Submatrix<MT,aligned,true,true>::operator%=( const Matrix<MT2,SO>& rhs )
10715 {
10719 
10720  using SchurType = SchurTrait_< ResultType, ResultType_<MT2> >;
10721 
10723 
10724  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
10725  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
10726  }
10727 
10728  if( !trySchurAssign( matrix_, ~rhs, row_, column_ ) ) {
10729  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
10730  }
10731 
10732  decltype(auto) left( derestrict( *this ) );
10733 
10734  if( ( ( IsSymmetric<MT>::value || IsHermitian<MT>::value ) && hasOverlap() ) ||
10735  (~rhs).canAlias( &matrix_ ) ) {
10736  const SchurType tmp( *this % (~rhs) );
10737  if( IsSparseMatrix<SchurType>::value )
10738  reset();
10739  smpAssign( left, tmp );
10740  }
10741  else {
10742  smpSchurAssign( left, ~rhs );
10743  }
10744 
10745  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
10746 
10747  return *this;
10748 }
10750 //*************************************************************************************************
10751 
10752 
10753 //*************************************************************************************************
10767 template< typename MT > // Type of the dense matrix
10768 template< typename MT2 // Type of the right-hand side matrix
10769  , bool SO > // Storage order of the right-hand side matrix
10770 inline EnableIf_< And< IsRestricted<MT>, RequiresEvaluation<MT2> >, Submatrix<MT,aligned,true,true>& >
10771  Submatrix<MT,aligned,true,true>::operator%=( const Matrix<MT2,SO>& rhs )
10772 {
10776 
10777  using SchurType = SchurTrait_< ResultType, ResultType_<MT2> >;
10778 
10780 
10781  if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) {
10782  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
10783  }
10784 
10785  const SchurType tmp( *this % (~rhs) );
10786 
10787  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
10788  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
10789  }
10790 
10791  if( IsSparseMatrix<SchurType>::value ) {
10792  reset();
10793  }
10794 
10795  decltype(auto) left( derestrict( *this ) );
10796 
10797  smpAssign( left, tmp );
10798 
10799  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
10800 
10801  return *this;
10802 }
10804 //*************************************************************************************************
10805 
10806 
10807 //*************************************************************************************************
10821 template< typename MT > // Type of the dense matrix
10822 template< typename MT2 // Type of the right-hand side matrix
10823  , bool SO > // Storage order of the right-hand side matrix
10824 inline Submatrix<MT,aligned,true,true>&
10825  Submatrix<MT,aligned,true,true>::operator*=( const Matrix<MT2,SO>& rhs )
10826 {
10830 
10831  using MultType = MultTrait_< ResultType, ResultType_<MT2> >;
10832 
10835 
10836  if( columns() != (~rhs).rows() ) {
10837  BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
10838  }
10839 
10840  const MultType tmp( *this * (~rhs) );
10841 
10842  if( !tryAssign( matrix_, tmp, row_, column_ ) ) {
10843  BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
10844  }
10845 
10846  decltype(auto) left( derestrict( *this ) );
10847 
10848  smpAssign( left, tmp );
10849 
10850  BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
10851 
10852  return *this;
10853 }
10855 //*************************************************************************************************
10856 
10857 
10858 //*************************************************************************************************
10869 template< typename MT > // Type of the dense matrix
10870 template< typename Other > // Data type of the right-hand side scalar
10871 inline EnableIf_< IsNumeric<Other>, Submatrix<MT,aligned,true,true> >&
10872  Submatrix<MT,aligned,true,true>::operator*=( Other rhs )
10873 {
10875 
10876  decltype(auto) left( derestrict( *this ) );
10877  smpAssign( left, (*this) * rhs );
10878 
10879  return *this;
10880 }
10882 //*************************************************************************************************
10883 
10884 
10885 //*************************************************************************************************
10898 template< typename MT > // Type of the dense matrix
10899 template< typename Other > // Data type of the right-hand side scalar
10900 inline EnableIf_< IsNumeric<Other>, Submatrix<MT,aligned,true,true> >&
10901  Submatrix<MT,aligned,true,true>::operator/=( Other rhs )
10902 {
10904 
10905  BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" );
10906 
10907  decltype(auto) left( derestrict( *this ) );
10908  smpAssign( left, (*this) / rhs );
10909 
10910  return *this;
10911 }
10913 //*************************************************************************************************
10914 
10915 
10916 
10917 
10918 //=================================================================================================
10919 //
10920 // UTILITY FUNCTIONS
10921 //
10922 //=================================================================================================
10923 
10924 //*************************************************************************************************
10930 template< typename MT > // Type of the dense matrix
10931 inline typename Submatrix<MT,aligned,true,true>::Operand
10932  Submatrix<MT,aligned,true,true>::operand() const noexcept
10933 {
10934  return matrix_;
10935 }
10937 //*************************************************************************************************
10938 
10939 
10940 //*************************************************************************************************
10946 template< typename MT > // Type of the dense matrix
10947 inline size_t Submatrix<MT,aligned,true,true>::row() const noexcept
10948 {
10949  return row_;
10950 }
10952 //*************************************************************************************************
10953 
10954 
10955 //*************************************************************************************************
10961 template< typename MT > // Type of the dense matrix
10962 inline size_t Submatrix<MT,aligned,true,true>::column() const noexcept
10963 {
10964  return column_;
10965 }
10967 //*************************************************************************************************
10968 
10969 
10970 //*************************************************************************************************
10976 template< typename MT > // Type of the dense matrix
10977 inline size_t Submatrix<MT,aligned,true,true>::rows() const noexcept
10978 {
10979  return m_;
10980 }
10982 //*************************************************************************************************
10983 
10984 
10985 //*************************************************************************************************
10991 template< typename MT > // Type of the dense matrix
10992 inline size_t Submatrix<MT,aligned,true,true>::columns() const noexcept
10993 {
10994  return n_;
10995 }
10997 //*************************************************************************************************
10998 
10999 
11000 //*************************************************************************************************
11009 template< typename MT > // Type of the dense matrix
11010 inline size_t Submatrix<MT,aligned,true,true>::spacing() const noexcept
11011 {
11012  return matrix_.spacing();
11013 }
11015 //*************************************************************************************************
11016 
11017 
11018 //*************************************************************************************************
11024 template< typename MT > // Type of the dense matrix
11025 inline size_t Submatrix<MT,aligned,true,true>::capacity() const noexcept
11026 {
11027  return rows() * columns();
11028 }
11030 //*************************************************************************************************
11031 
11032 
11033 //*************************************************************************************************
11040 template< typename MT > // Type of the dense matrix
11041 inline size_t Submatrix<MT,aligned,true,true>::capacity( size_t j ) const noexcept
11042 {
11043  UNUSED_PARAMETER( j );
11044 
11045  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
11046 
11047  return rows();
11048 }
11050 //*************************************************************************************************
11051 
11052 
11053 //*************************************************************************************************
11059 template< typename MT > // Type of the dense matrix
11060 inline size_t Submatrix<MT,aligned,true,true>::nonZeros() const
11061 {
11062  const size_t iend( row_ + m_ );
11063  const size_t jend( column_ + n_ );
11064  size_t nonzeros( 0UL );
11065 
11066  for( size_t j=column_; j<jend; ++j )
11067  for( size_t i=row_; i<iend; ++i )
11068  if( !isDefault( matrix_(i,j) ) )
11069  ++nonzeros;
11070 
11071  return nonzeros;
11072 }
11074 //*************************************************************************************************
11075 
11076 
11077 //*************************************************************************************************
11084 template< typename MT > // Type of the dense matrix
11085 inline size_t Submatrix<MT,aligned,true,true>::nonZeros( size_t j ) const
11086 {
11087  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
11088 
11089  const size_t iend( row_ + m_ );
11090  size_t nonzeros( 0UL );
11091 
11092  for( size_t i=row_; i<iend; ++i )
11093  if( !isDefault( matrix_(i,column_+j) ) )
11094  ++nonzeros;
11095 
11096  return nonzeros;
11097 }
11099 //*************************************************************************************************
11100 
11101 
11102 //*************************************************************************************************
11108 template< typename MT > // Type of the dense matrix
11110 {
11111  using blaze::clear;
11112 
11113  for( size_t j=column_; j<column_+n_; ++j )
11114  {
11115  const size_t ibegin( ( IsLower<MT>::value )
11116  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
11117  ?( max( j+1UL, row_ ) )
11118  :( max( j, row_ ) ) )
11119  :( row_ ) );
11120  const size_t iend ( ( IsUpper<MT>::value )
11121  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
11122  ?( min( j, row_+m_ ) )
11123  :( min( j+1UL, row_+m_ ) ) )
11124  :( row_+m_ ) );
11125 
11126  for( size_t i=ibegin; i<iend; ++i )
11127  clear( matrix_(i,j) );
11128  }
11129 }
11131 //*************************************************************************************************
11132 
11133 
11134 //*************************************************************************************************
11141 template< typename MT > // Type of the dense matrix
11142 inline void Submatrix<MT,aligned,true,true>::reset( size_t j )
11143 {
11144  using blaze::clear;
11145 
11146  BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
11147 
11148  const size_t ibegin( ( IsLower<MT>::value )
11149  ?( ( IsUniLower<MT>::value || IsStrictlyLower<MT>::value )
11150  ?( max( j+1UL, row_ ) )
11151  :( max( j, row_ ) ) )
11152  :( row_ ) );
11153  const size_t iend ( ( IsUpper<MT>::value )
11154  ?( ( IsUniUpper<MT>::value || IsStrictlyUpper<MT>::value )
11155  ?( min( j, row_+m_ ) )
11156  :( min( j+1UL, row_+m_ ) ) )
11157  :( row_+m_ ) );
11158 
11159  for( size_t i=ibegin; i<iend; ++i )
11160  clear( matrix_(i,column_+j) );
11161 }
11163 //*************************************************************************************************
11164 
11165 
11166 //*************************************************************************************************
11176 template< typename MT > // Type of the dense matrix
11177 inline bool Submatrix<MT,aligned,true,true>::hasOverlap() const noexcept
11178 {
11179  BLAZE_INTERNAL_ASSERT( IsSymmetric<MT>::value || IsHermitian<MT>::value, "Invalid matrix detected" );
11180 
11181  if( ( row_ + m_ <= column_ ) || ( column_ + n_ <= row_ ) )
11182  return false;
11183  else return true;
11184 }
11186 //*************************************************************************************************
11187 
11188 
11189 
11190 
11191 //=================================================================================================
11192 //
11193 // NUMERIC FUNCTIONS
11194 //
11195 //=================================================================================================
11196 
11197 //*************************************************************************************************
11215 template< typename MT > // Type of the dense matrix
11216 inline Submatrix<MT,aligned,true,true>& Submatrix<MT,aligned,true,true>::transpose()
11217 {
11218  if( m_ != n_ ) {
11219  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
11220  }
11221 
11222  if( !tryAssign( matrix_, trans( *this ), row_, column_ ) ) {
11223  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
11224  }
11225 
11226  decltype(auto) left( derestrict( *this ) );
11227  const ResultType tmp( trans( *this ) );
11228  smpAssign( left, tmp );
11229 
11230  return *this;
11231 }
11233 //*************************************************************************************************
11234 
11235 
11236 //*************************************************************************************************
11254 template< typename MT > // Type of the dense matrix
11255 inline Submatrix<MT,aligned,true,true>& Submatrix<MT,aligned,true,true>::ctranspose()
11256 {
11257  if( m_ != n_ ) {
11258  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
11259  }
11260 
11261  if( !tryAssign( matrix_, ctrans( *this ), row_, column_ ) ) {
11262  BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
11263  }
11264 
11265  decltype(auto) left( derestrict( *this ) );
11266  const ResultType tmp( ctrans( *this ) );
11267  smpAssign( left, tmp );
11268 
11269  return *this;
11270 }
11272 //*************************************************************************************************
11273 
11274 
11275 //*************************************************************************************************
11288 template< typename MT > // Type of the dense matrix
11289 template< typename Other > // Data type of the scalar value
11290 inline Submatrix<MT,aligned,true,true>& Submatrix<MT,aligned,true,true>::scale( const Other& scalar )
11291 {
11293 
11294  const size_t jend( column_ + n_ );
11295 
11296  for( size_t j=column_; j<jend; ++j )
11297  {
11298  const size_t ibegin( ( IsLower<MT>::value )
11299  ?( ( IsStrictlyLower<MT>::value )
11300  ?( max( j+1UL, row_ ) )
11301  :( max( j, row_ ) ) )
11302  :( row_ ) );
11303  const size_t iend ( ( IsUpper<MT>::value )
11304  ?( ( IsStrictlyUpper<MT>::value )
11305  ?( min( j, row_+m_ ) )
11306  :( min( j+1UL, row_+m_ ) ) )
11307  :( row_+m_ ) );
11308 
11309  for( size_t i=ibegin; i<iend; ++i )
11310  matrix_(i,j) *= scalar;
11311  }
11312 
11313  return *this;
11314 }
11316 //*************************************************************************************************
11317 
11318 
11319 
11320 
11321 //=================================================================================================
11322 //
11323 // EXPRESSION TEMPLATE EVALUATION FUNCTIONS
11324 //
11325 //=================================================================================================
11326 
11327 //*************************************************************************************************
11338 template< typename MT > // Type of the dense matrix
11339 template< typename Other > // Data type of the foreign expression
11340 inline bool Submatrix<MT,aligned,true,true>::canAlias( const Other* alias ) const noexcept
11341 {
11342  return matrix_.isAliased( alias );
11343 }
11345 //*************************************************************************************************
11346 
11347 
11348 //*************************************************************************************************
11359 template< typename MT > // Type of the dense matrix
11360 template< typename MT2 // Data type of the foreign dense submatrix
11361  , bool AF2 // Alignment flag of the foreign dense submatrix
11362  , bool SO2 > // Storage order of the foreign dense submatrix
11363 inline bool Submatrix<MT,aligned,true,true>::canAlias( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
11364 {
11365  return ( matrix_.isAliased( &alias->matrix_ ) &&
11366  ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
11367  ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
11368 }
11370 //*************************************************************************************************
11371 
11372 
11373 //*************************************************************************************************
11384 template< typename MT > // Type of the dense matrix
11385 template< typename Other > // Data type of the foreign expression
11386 inline bool Submatrix<MT,aligned,true,true>::isAliased( const Other* alias ) const noexcept
11387 {
11388  return matrix_.isAliased( alias );
11389 }
11391 //*************************************************************************************************
11392 
11393 
11394 //*************************************************************************************************
11405 template< typename MT > // Type of the dense matrix
11406 template< typename MT2 // Data type of the foreign dense submatrix
11407  , bool AF2 // Alignment flag of the foreign dense submatrix
11408  , bool SO2 > // Storage order of the foreign dense submatrix
11409 inline bool Submatrix<MT,aligned,true,true>::isAliased( const Submatrix<MT2,AF2,SO2,true>* alias ) const noexcept
11410 {
11411  return ( matrix_.isAliased( &alias->matrix_ ) &&
11412  ( row_ + m_ > alias->row_ ) && ( row_ < alias->row_ + alias->m_ ) &&
11413  ( column_ + n_ > alias->column_ ) && ( column_ < alias->column_ + alias->n_ ) );
11414 }
11416 //*************************************************************************************************
11417 
11418 
11419 //*************************************************************************************************
11429 template< typename MT > // Type of the dense matrix
11430 inline bool Submatrix<MT,aligned,true,true>::isAligned() const noexcept
11431 {
11432  return true;
11433 }
11435 //*************************************************************************************************
11436 
11437 
11438 //*************************************************************************************************
11449 template< typename MT > // Type of the dense matrix
11450 inline bool Submatrix<MT,aligned,true,true>::canSMPAssign() const noexcept
11451 {
11452  return ( rows() * columns() >= SMP_DMATASSIGN_THRESHOLD );
11453 }
11455 //*************************************************************************************************
11456 
11457 
11458 //*************************************************************************************************
11473 template< typename MT > // Type of the dense matrix
11474 BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,true,true>::SIMDType
11475  Submatrix<MT,aligned,true,true>::load( size_t i, size_t j ) const noexcept
11476 {
11477  return loada( i, j );
11478 }
11480 //*************************************************************************************************
11481 
11482 
11483 //*************************************************************************************************
11498 template< typename MT > // Type of the dense matrix
11499 BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,true,true>::SIMDType
11500  Submatrix<MT,aligned,true,true>::loada( size_t i, size_t j ) const noexcept
11501 {
11503 
11504  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
11505  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
11506  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
11507  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
11508 
11509  return matrix_.loada( row_+i, column_+j );
11510 }
11512 //*************************************************************************************************
11513 
11514 
11515 //*************************************************************************************************
11530 template< typename MT > // Type of the dense matrix
11531 BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,true,true>::SIMDType
11532  Submatrix<MT,aligned,true,true>::loadu( size_t i, size_t j ) const noexcept
11533 {
11535 
11536  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
11537  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
11538  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
11539  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
11540 
11541  return matrix_.loadu( row_+i, column_+j );
11542 }
11544 //*************************************************************************************************
11545 
11546 
11547 //*************************************************************************************************
11563 template< typename MT > // Type of the dense matrix
11565  Submatrix<MT,aligned,true,true>::store( size_t i, size_t j, const SIMDType& value ) noexcept
11566 {
11567  storea( i, j, value );
11568 }
11570 //*************************************************************************************************
11571 
11572 
11573 //*************************************************************************************************
11589 template< typename MT > // Type of the dense matrix
11591  Submatrix<MT,aligned,true,true>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
11592 {
11594 
11595  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
11596  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
11597  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
11598  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
11599 
11600  matrix_.storea( row_+i, column_+j, value );
11601 }
11603 //*************************************************************************************************
11604 
11605 
11606 //*************************************************************************************************
11622 template< typename MT > // Type of the dense matrix
11624  Submatrix<MT,aligned,true,true>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
11625 {
11627 
11628  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
11629  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
11630  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
11631  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
11632 
11633  matrix_.storeu( row_+i, column_+j, value );
11634 }
11636 //*************************************************************************************************
11637 
11638 
11639 //*************************************************************************************************
11656 template< typename MT > // Type of the dense matrix
11658  Submatrix<MT,aligned,true,true>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
11659 {
11661 
11662  BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
11663  BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
11664  BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
11665  BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
11666 
11667  matrix_.stream( row_+i, column_+j, value );
11668 }
11670 //*************************************************************************************************
11671 
11672 
11673 //*************************************************************************************************
11685 template< typename MT > // Type of the dense matrix
11686 template< typename MT2 > // Type of the right-hand side dense matrix
11687 inline DisableIf_< typename Submatrix<MT,aligned,true,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
11688  Submatrix<MT,aligned,true,true>::assign( const DenseMatrix<MT2,true>& rhs )
11689 {
11690  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
11691  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
11692 
11693  const size_t ipos( m_ & size_t(-2) );
11694  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
11695 
11696  for( size_t j=0UL; j<n_; ++j ) {
11697  for( size_t i=0UL; i<ipos; i+=2UL ) {
11698  matrix_(row_+i ,column_+j) = (~rhs)(i ,j);
11699  matrix_(row_+i+1UL,column_+j) = (~rhs)(i+1UL,j);
11700  }
11701  if( ipos < m_ ) {
11702  matrix_(row_+ipos,column_+j) = (~rhs)(ipos,j);
11703  }
11704  }
11705 }
11707 //*************************************************************************************************
11708 
11709 
11710 //*************************************************************************************************
11722 template< typename MT > // Type of the dense matrix
11723 template< typename MT2 > // Type of the right-hand side dense matrix
11724 inline EnableIf_< typename Submatrix<MT,aligned,true,true>::BLAZE_TEMPLATE VectorizedAssign<MT2> >
11725  Submatrix<MT,aligned,true,true>::assign( const DenseMatrix<MT2,true>& rhs )
11726 {
11728 
11729  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
11730  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
11731 
11732  const size_t ipos( m_ & size_t(-SIMDSIZE) );
11733  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
11734 
11735  if( useStreaming &&
11736  m_*n_ > ( cacheSize / ( sizeof(ElementType) * 3UL ) ) &&
11737  !(~rhs).isAliased( &matrix_ ) )
11738  {
11739  for( size_t j=0UL; j<n_; ++j )
11740  {
11741  size_t i( 0UL );
11742  Iterator left( begin(j) );
11743  ConstIterator_<MT2> right( (~rhs).begin(j) );
11744 
11745  for( ; i<ipos; i+=SIMDSIZE ) {
11746  left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11747  }
11748  for( ; i<m_; ++i ) {
11749  *left = *right; ++left; ++right;
11750  }
11751  }
11752  }
11753  else
11754  {
11755  for( size_t j=0UL; j<n_; ++j )
11756  {
11757  size_t i( 0UL );
11758  Iterator left( begin(j) );
11759  ConstIterator_<MT2> right( (~rhs).begin(j) );
11760 
11761  for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
11762  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11763  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11764  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11765  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11766  }
11767  for( ; i<ipos; i+=SIMDSIZE ) {
11768  left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11769  }
11770  for( ; i<m_; ++i ) {
11771  *left = *right; ++left; ++right;
11772  }
11773  }
11774  }
11775 }
11777 //*************************************************************************************************
11778 
11779 
11780 //*************************************************************************************************
11792 template< typename MT > // Type of the dense matrix
11793 template< typename MT2 > // Type of the right-hand side dense matrix
11794 inline void Submatrix<MT,aligned,true,true>::assign( const DenseMatrix<MT2,false>& rhs )
11795 {
11797 
11798  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
11799  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
11800 
11801  constexpr size_t block( BLOCK_SIZE );
11802 
11803  for( size_t jj=0UL; jj<n_; jj+=block ) {
11804  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
11805  for( size_t ii=0UL; ii<m_; ii+=block ) {
11806  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
11807  for( size_t j=jj; j<jend; ++j ) {
11808  for( size_t i=ii; i<iend; ++i ) {
11809  matrix_(row_+i,column_+j) = (~rhs)(i,j);
11810  }
11811  }
11812  }
11813  }
11814 }
11816 //*************************************************************************************************
11817 
11818 
11819 //*************************************************************************************************
11831 template< typename MT > // Type of the dense matrix
11832 template< typename MT2 > // Type of the right-hand side sparse matrix
11833 inline void Submatrix<MT,aligned,true,true>::assign( const SparseMatrix<MT2,true>& rhs )
11834 {
11835  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
11836  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
11837 
11838  for( size_t j=0UL; j<n_; ++j )
11839  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
11840  matrix_(row_+element->index(),column_+j) = element->value();
11841 }
11843 //*************************************************************************************************
11844 
11845 
11846 //*************************************************************************************************
11858 template< typename MT > // Type of the dense matrix
11859 template< typename MT2 > // Type of the right-hand side sparse matrix
11860 inline void Submatrix<MT,aligned,true,true>::assign( const SparseMatrix<MT2,false>& rhs )
11861 {
11863 
11864  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
11865  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
11866 
11867  for( size_t i=0UL; i<m_; ++i )
11868  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
11869  matrix_(row_+i,column_+element->index()) = element->value();
11870 }
11872 //*************************************************************************************************
11873 
11874 
11875 //*************************************************************************************************
11887 template< typename MT > // Type of the dense matrix
11888 template< typename MT2 > // Type of the right-hand side dense matrix
11889 inline DisableIf_< typename Submatrix<MT,aligned,true,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
11890  Submatrix<MT,aligned,true,true>::addAssign( const DenseMatrix<MT2,true>& rhs )
11891 {
11892  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
11893  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
11894 
11895  const size_t ipos( m_ & size_t(-2) );
11896  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
11897 
11898  for( size_t j=0UL; j<n_; ++j )
11899  {
11900  if( IsDiagonal<MT2>::value ) {
11901  matrix_(row_+j,column_+j) += (~rhs)(j,j);
11902  }
11903  else {
11904  for( size_t i=0UL; i<ipos; i+=2UL ) {
11905  matrix_(row_+i ,column_+j) += (~rhs)(i ,j);
11906  matrix_(row_+i+1UL,column_+j) += (~rhs)(i+1UL,j);
11907  }
11908  if( ipos < m_ ) {
11909  matrix_(row_+ipos,column_+j) += (~rhs)(ipos,j);
11910  }
11911  }
11912  }
11913 }
11915 //*************************************************************************************************
11916 
11917 
11918 //*************************************************************************************************
11930 template< typename MT > // Type of the dense matrix
11931 template< typename MT2 > // Type of the right-hand side dense matrix
11932 inline EnableIf_< typename Submatrix<MT,aligned,true,true>::BLAZE_TEMPLATE VectorizedAddAssign<MT2> >
11933  Submatrix<MT,aligned,true,true>::addAssign( const DenseMatrix<MT2,true>& rhs )
11934 {
11936 
11937  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
11938  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
11939 
11940  for( size_t j=0UL; j<n_; ++j )
11941  {
11942  const size_t ibegin( ( IsLower<MT>::value )
11943  ?( ( IsStrictlyLower<MT>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
11944  :( 0UL ) );
11945  const size_t iend ( ( IsUpper<MT>::value )
11946  ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
11947  :( m_ ) );
11948  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
11949 
11950  const size_t ipos( iend & size_t(-SIMDSIZE) );
11951  BLAZE_INTERNAL_ASSERT( ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
11952 
11953  size_t i( ibegin );
11954  Iterator left( begin(j) + ibegin );
11955  ConstIterator_<MT2> right( (~rhs).begin(j) + ibegin );
11956 
11957  for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
11958  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11959  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11960  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11961  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11962  }
11963  for( ; i<ipos; i+=SIMDSIZE ) {
11964  left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11965  }
11966  for( ; i<iend; ++i ) {
11967  *left += *right; ++left; ++right;
11968  }
11969  }
11970 }
11972 //*************************************************************************************************
11973 
11974 
11975 //*************************************************************************************************
11987 template< typename MT > // Type of the dense matrix
11988 template< typename MT2 > // Type of the right-hand side dense matrix
11989 inline void Submatrix<MT,aligned,true,true>::addAssign( const DenseMatrix<MT2,false>& rhs )
11990 {
11992 
11993  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
11994  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
11995 
11996  constexpr size_t block( BLOCK_SIZE );
11997 
11998  for( size_t jj=0UL; jj<n_; jj+=block ) {
11999  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
12000  for( size_t ii=0UL; ii<m_; ii+=block ) {
12001  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
12002  for( size_t j=jj; j<jend; ++j ) {
12003  for( size_t i=ii; i<iend; ++i ) {
12004  matrix_(row_+i,column_+j) += (~rhs)(i,j);
12005  }
12006  }
12007  }
12008  }
12009 }
12011 //*************************************************************************************************
12012 
12013 
12014 //*************************************************************************************************
12026 template< typename MT > // Type of the dense matrix
12027 template< typename MT2 > // Type of the right-hand side sparse matrix
12028 inline void Submatrix<MT,aligned,true,true>::addAssign( const SparseMatrix<MT2,true>& rhs )
12029 {
12030  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
12031  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
12032 
12033  for( size_t j=0UL; j<n_; ++j )
12034  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
12035  matrix_(row_+element->index(),column_+j) += element->value();
12036 }
12038 //*************************************************************************************************
12039 
12040 
12041 //*************************************************************************************************
12053 template< typename MT > // Type of the dense matrix
12054 template< typename MT2 > // Type of the right-hand side sparse matrix
12055 inline void Submatrix<MT,aligned,true,true>::addAssign( const SparseMatrix<MT2,false>& rhs )
12056 {
12058 
12059  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
12060  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
12061 
12062  for( size_t i=0UL; i<m_; ++i )
12063  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
12064  matrix_(row_+i,column_+element->index()) += element->value();
12065 }
12067 //*************************************************************************************************
12068 
12069 
12070 //*************************************************************************************************
12082 template< typename MT > // Type of the dense matrix
12083 template< typename MT2 > // Type of the right-hand side dense matrix
12084 inline DisableIf_< typename Submatrix<MT,aligned,true,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
12085  Submatrix<MT,aligned,true,true>::subAssign( const DenseMatrix<MT2,true>& rhs )
12086 {
12087  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
12088  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
12089 
12090  const size_t ipos( m_ & size_t(-2) );
12091  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
12092 
12093  for( size_t j=0UL; j<n_; ++j )
12094  {
12095  if( IsDiagonal<MT2>::value ) {
12096  matrix_(row_+j,column_+j) -= (~rhs)(j,j);
12097  }
12098  else {
12099  for( size_t i=0UL; i<ipos; i+=2UL ) {
12100  matrix_(row_+i ,column_+j) -= (~rhs)(i ,j);
12101  matrix_(row_+i+1UL,column_+j) -= (~rhs)(i+1UL,j);
12102  }
12103  if( ipos < m_ ) {
12104  matrix_(row_+ipos,column_+j) -= (~rhs)(ipos,j);
12105  }
12106  }
12107  }
12108 }
12110 //*************************************************************************************************
12111 
12112 
12113 //*************************************************************************************************
12125 template< typename MT > // Type of the dense matrix
12126 template< typename MT2 > // Type of the right-hand side dense matrix
12127 inline EnableIf_< typename Submatrix<MT,aligned,true,true>::BLAZE_TEMPLATE VectorizedSubAssign<MT2> >
12128  Submatrix<MT,aligned,true,true>::subAssign( const DenseMatrix<MT2,true>& rhs )
12129 {
12131 
12132  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
12133  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
12134 
12135  for( size_t j=0UL; j<n_; ++j )
12136  {
12137  const size_t ibegin( ( IsLower<MT>::value )
12138  ?( ( IsStrictlyLower<MT>::value ? j+1UL : j ) & size_t(-SIMDSIZE) )
12139  :( 0UL ) );
12140  const size_t iend ( ( IsUpper<MT>::value )
12141  ?( IsStrictlyUpper<MT>::value ? j : j+1UL )
12142  :( m_ ) );
12143  BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
12144 
12145  const size_t ipos( iend & size_t(-SIMDSIZE) );
12146  BLAZE_INTERNAL_ASSERT( ( iend - ( iend % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
12147 
12148  size_t i( ibegin );
12149  Iterator left( begin(j) + ibegin );
12150  ConstIterator_<MT2> right( (~rhs).begin(j) + ibegin );
12151 
12152  for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
12153  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
12154  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
12155  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
12156  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
12157  }
12158  for( ; i<ipos; i+=SIMDSIZE ) {
12159  left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
12160  }
12161  for( ; i<iend; ++i ) {
12162  *left -= *right; ++left; ++right;
12163  }
12164  }
12165 }
12167 //*************************************************************************************************
12168 
12169 
12170 //*************************************************************************************************
12182 template< typename MT > // Type of the dense matrix
12183 template< typename MT2 > // Type of the right-hand side dense matrix
12184 inline void Submatrix<MT,aligned,true,true>::subAssign( const DenseMatrix<MT2,false>& rhs )
12185 {
12187 
12188  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
12189  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
12190 
12191  constexpr size_t block( BLOCK_SIZE );
12192 
12193  for( size_t jj=0UL; jj<n_; jj+=block ) {
12194  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
12195  for( size_t ii=0UL; ii<m_; ii+=block ) {
12196  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
12197  for( size_t j=jj; j<jend; ++j ) {
12198  for( size_t i=ii; i<iend; ++i ) {
12199  matrix_(row_+i,column_+j) -= (~rhs)(i,j);
12200  }
12201  }
12202  }
12203  }
12204 }
12206 //*************************************************************************************************
12207 
12208 
12209 //*************************************************************************************************
12221 template< typename MT > // Type of the dense matrix
12222 template< typename MT2 > // Type of the right-hand side sparse matrix
12223 inline void Submatrix<MT,aligned,true,true>::subAssign( const SparseMatrix<MT2,true>& rhs )
12224 {
12225  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
12226  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
12227 
12228  for( size_t j=0UL; j<n_; ++j )
12229  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element )
12230  matrix_(row_+element->index(),column_+j) -= element->value();
12231 }
12233 //*************************************************************************************************
12234 
12235 
12236 //*************************************************************************************************
12248 template< typename MT > // Type of the dense matrix
12249 template< typename MT2 > // Type of the right-hand side sparse matrix
12250 inline void Submatrix<MT,aligned,true,true>::subAssign( const SparseMatrix<MT2,false>& rhs )
12251 {
12253 
12254  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
12255  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
12256 
12257  for( size_t i=0UL; i<m_; ++i )
12258  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element )
12259  matrix_(row_+i,column_+element->index()) -= element->value();
12260 }
12262 //*************************************************************************************************
12263 
12264 
12265 //*************************************************************************************************
12277 template< typename MT > // Type of the dense matrix
12278 template< typename MT2 > // Type of the right-hand side dense matrix
12279 inline DisableIf_< typename Submatrix<MT,aligned,true,true>::BLAZE_TEMPLATE VectorizedSchurAssign<MT2> >
12280  Submatrix<MT,aligned,true,true>::schurAssign( const DenseMatrix<MT2,true>& rhs )
12281 {
12282  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
12283  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
12284 
12285  const size_t ipos( m_ & size_t(-2) );
12286  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % 2UL ) ) == ipos, "Invalid end calculation" );
12287 
12288  for( size_t j=0UL; j<n_; ++j ) {
12289  for( size_t i=0UL; i<ipos; i+=2UL ) {
12290  matrix_(row_+i ,column_+j) *= (~rhs)(i ,j);
12291  matrix_(row_+i+1UL,column_+j) *= (~rhs)(i+1UL,j);
12292  }
12293  if( ipos < m_ ) {
12294  matrix_(row_+ipos,column_+j) *= (~rhs)(ipos,j);
12295  }
12296  }
12297 }
12299 //*************************************************************************************************
12300 
12301 
12302 //*************************************************************************************************
12315 template< typename MT > // Type of the dense matrix
12316 template< typename MT2 > // Type of the right-hand side dense matrix
12317 inline EnableIf_< typename Submatrix<MT,aligned,true,true>::BLAZE_TEMPLATE VectorizedSchurAssign<MT2> >
12318  Submatrix<MT,aligned,true,true>::schurAssign( const DenseMatrix<MT2,true>& rhs )
12319 {
12321 
12322  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
12323  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
12324 
12325  for( size_t j=0UL; j<n_; ++j )
12326  {
12327  const size_t ipos( m_ & size_t(-SIMDSIZE) );
12328  BLAZE_INTERNAL_ASSERT( ( m_ - ( m_ % (SIMDSIZE) ) ) == ipos, "Invalid end calculation" );
12329 
12330  size_t i( 0UL );
12331  Iterator left( begin(j) );
12332  ConstIterator_<MT2> right( (~rhs).begin(j) );
12333 
12334  for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
12335  left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
12336  left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
12337  left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
12338  left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
12339  }
12340  for( ; i<ipos; i+=SIMDSIZE ) {
12341  left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
12342  }
12343  for( ; i<m_; ++i ) {
12344  *left *= *right; ++left; ++right;
12345  }
12346  }
12347 }
12349 //*************************************************************************************************
12350 
12351 
12352 //*************************************************************************************************
12364 template< typename MT > // Type of the dense matrix
12365 template< typename MT2 > // Type of the right-hand side dense matrix
12366 inline void Submatrix<MT,aligned,true,true>::schurAssign( const DenseMatrix<MT2,false>& rhs )
12367 {
12369 
12370  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
12371  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
12372 
12373  constexpr size_t block( BLOCK_SIZE );
12374 
12375  for( size_t jj=0UL; jj<n_; jj+=block ) {
12376  const size_t jend( ( n_<(jj+block) )?( n_ ):( jj+block ) );
12377  for( size_t ii=0UL; ii<m_; ii+=block ) {
12378  const size_t iend( ( m_<(ii+block) )?( m_ ):( ii+block ) );
12379  for( size_t j=jj; j<jend; ++j ) {
12380  for( size_t i=ii; i<iend; ++i ) {
12381  matrix_(row_+i,column_+j) *= (~rhs)(i,j);
12382  }
12383  }
12384  }
12385  }
12386 }
12388 //*************************************************************************************************
12389 
12390 
12391 //*************************************************************************************************
12403 template< typename MT > // Type of the dense matrix
12404 template< typename MT2 > // Type of the right-hand side sparse matrix
12405 inline void Submatrix<MT,aligned,true,true>::schurAssign( const SparseMatrix<MT2,true>& rhs )
12406 {
12407  using blaze::reset;
12408 
12409  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
12410  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
12411 
12412  for( size_t j=0UL; j<n_; ++j )
12413  {
12414  size_t i( 0UL );
12415 
12416  for( ConstIterator_<MT2> element=(~rhs).begin(j); element!=(~rhs).end(j); ++element ) {
12417  for( ; i<element->index(); ++i )
12418  reset( matrix_(row_+i,column_+j) );
12419  matrix_(row_+i,column_+j) *= element->value();
12420  ++i;
12421  }
12422 
12423  for( ; i<m_; ++i ) {
12424  reset( matrix_(row_+i,column_+j) );
12425  }
12426  }
12427 }
12429 //*************************************************************************************************
12430 
12431 
12432 //*************************************************************************************************
12444 template< typename MT > // Type of the dense matrix
12445 template< typename MT2 > // Type of the right-hand side sparse matrix
12446 inline void Submatrix<MT,aligned,true,true>::schurAssign( const SparseMatrix<MT2,false>& rhs )
12447 {
12448  using blaze::reset;
12449 
12451 
12452  BLAZE_INTERNAL_ASSERT( m_ == (~rhs).rows() , "Invalid number of rows" );
12453  BLAZE_INTERNAL_ASSERT( n_ == (~rhs).columns(), "Invalid number of columns" );
12454 
12455  for( size_t i=0UL; i<m_; ++i )
12456  {
12457  size_t j( 0UL );
12458 
12459  for( ConstIterator_<MT2> element=(~rhs).begin(i); element!=(~rhs).end(i); ++element ) {
12460  for( ; j<element->index(); ++j )
12461  reset( matrix_(row_+i,column_+j) );
12462  matrix_(row_+i,column_+j) *= element->value();
12463  ++j;
12464  }
12465 
12466  for( ; j<n_; ++j ) {
12467  reset( matrix_(row_+i,column_+j) );
12468  }
12469  }
12470 }
12472 //*************************************************************************************************
12473 
12474 } // namespace blaze
12475 
12476 #endif
constexpr bool aligned
Alignment flag for aligned vectors and matrices.Via this flag it is possible to specify subvectors...
Definition: AlignmentFlag.h:85
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.
Headerfile for the generic min algorithm.
Header file for kernel specific block sizes.
CompressedMatrix< Type, false > OppositeType
Result type with opposite storage order for expression template evaluations.
Definition: CompressedMatrix.h:3079
Header file for the Schur product trait.
#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.
EnableIf_< IsDenseMatrix< MT1 > > smpSchurAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP Schur product assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:196
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:356
Header file for basic type definitions.
Header file for the View base class.
BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral< T1 >, HasSize< T1, 1UL > > > storea(T1 *address, const SIMDi8< T2 > &value) noexcept
Aligned store of a vector of 1-byte integral values.
Definition: Storea.h:79
EnableIf_< IsDenseMatrix< MT1 > > smpSubAssign(Matrix< MT1, SO1 > &lhs, const Matrix< MT2, SO2 > &rhs)
Default implementation of the SMP subtraction assignment of a matrix to dense matrix.
Definition: DenseMatrix.h:164
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:265
#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
#define BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a dense, N-dimensional matrix type...
Definition: DenseMatrix.h:61
constexpr bool operator<(const NegativeAccuracy< A > &lhs, const T &rhs)
Less-than comparison between a NegativeAccuracy object and a floating point value.
Definition: Accuracy.h:329
This ResultType
Result type for expression template evaluations.
Definition: CompressedMatrix.h:3078
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:198
CompressedMatrix< Type, true > This
Type of this CompressedMatrix instance.
Definition: CompressedMatrix.h:3076
void reset(const DiagonalProxy< MT > &proxy)
Resetting the represented element to the default initial values.
Definition: DiagonalProxy.h:560
const DenseIterator< Type, AF > operator+(const DenseIterator< Type, AF > &it, ptrdiff_t inc) noexcept
Addition between a DenseIterator and an integral value.
Definition: DenseIterator.h:699
size_t m_
The current number of rows of the compressed matrix.
Definition: CompressedMatrix.h:3287
typename DisableIf< Condition, T >::Type DisableIf_
Auxiliary type for the DisableIf class template.The DisableIf_ alias declaration provides a convenien...
Definition: DisableIf.h:224
CompressedMatrix< Type, false > TransposeType
Transpose type for expression template evaluations.
Definition: CompressedMatrix.h:3080
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:1762
#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:661
#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
const Type & ConstReference
Reference to a constant matrix value.
Definition: CompressedMatrix.h:3085
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:394
Column< MT > column(Matrix< MT, SO > &matrix, size_t index)
Creating a view on a specific column of the given matrix.
Definition: Column.h:124
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
Element * Iterator
Iterator over non-constant elements.
Definition: CompressedMatrix.h:3086
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 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:1809
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:133
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:308
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:242
Constraint on the data type.
BLAZE_ALWAYS_INLINE size_t spacing(const DenseMatrix< MT, SO > &dm) noexcept
Returns the spacing between the beginning of two rows/columns.
Definition: DenseMatrix.h:110
Header file for the std::initializer_list aliases.
Row< MT > row(Matrix< MT, SO > &matrix, size_t index)
Creating a view on a specific row of the given matrix.
Definition: Row.h:124
Header file for the matrix storage order types.
Constraint on the data type.
Headerfile for the generic max algorithm.
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.
MatrixAccessProxy< This > Reference
Reference to a non-constant matrix value.
Definition: CompressedMatrix.h:3084
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
decltype(auto) ctrans(const DenseMatrix< MT, SO > &dm)
Returns the conjugate transpose matrix of dm.
Definition: DMatMapExpr.h:1359
Header file for nested template disabiguation.
Header file for the If class template.
#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
SparseMatrix< This, true > BaseType
Base type of this CompressedMatrix instance.
Definition: CompressedMatrix.h:3077
#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:102
Type ElementType
Type of the compressed matrix elements.
Definition: CompressedMatrix.h:3081
Header file for the Or class template.
#define BLAZE_THROW_OUT_OF_RANGE(MESSAGE)
Macro for the emission of a std::out_of_range exception.This macro encapsulates the default way of Bl...
Definition: Exception.h:331
Header file for the implementation of the Submatrix base template.
Header file for the HasSIMDAdd type trait.
Header file for the DenseMatrix base class.
constexpr bool operator>(const NegativeAccuracy< A > &lhs, const T &rhs)
Greater-than comparison between a NegativeAccuracy object and a floating point value.
Definition: Accuracy.h:367
constexpr bool operator>=(const NegativeAccuracy< A > &, const T &rhs)
Greater-or-equal-than comparison between a NegativeAccuracy object and a floating point value...
Definition: Accuracy.h:443
Header file for the Not class template.
const Element * ConstIterator
Iterator over constant elements.
Definition: CompressedMatrix.h:3087
constexpr bool operator==(const NegativeAccuracy< A > &lhs, const T &rhs)
Equality comparison between a NegativeAccuracy object and a floating point value. ...
Definition: Accuracy.h:250
Header file for all SIMD functionality.
Header file for the IsLower type trait.
BLAZE_ALWAYS_INLINE size_t columns(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of columns of the matrix.
Definition: Matrix.h:340
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
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:264
decltype(auto) operator*(const DenseMatrix< MT1, false > &lhs, const DenseMatrix< MT2, false > &rhs)
Multiplication operator for the multiplication of two row-major dense matrices ( ).
Definition: DMatDMatMultExpr.h:8893
constexpr bool operator!=(const NegativeAccuracy< A > &lhs, const T &rhs)
Inequality comparison between a NegativeAccuracy object and a floating point value.
Definition: Accuracy.h:290
Constraint on the data type.
constexpr bool unaligned
Alignment flag for unaligned vectors and matrices.Via this flag it is possible to specify subvectors...
Definition: AlignmentFlag.h:64
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:580
Constraint on the data type.
Header file for the IsNumeric type trait.
BLAZE_ALWAYS_INLINE EnableIf_< And< IsIntegral< T1 >, HasSize< T1, 1UL > > > stream(T1 *address, const SIMDi8< T2 > &value) noexcept
Aligned, non-temporal store of a vector of 1-byte integral values.
Definition: Stream.h:75
Header file for the IsSIMDCombinable type trait.
#define BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is a symmetric matrix type, a compilation error is created.
Definition: Symmetric.h:79
#define BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE(T)
Constraint on the data type.In case the given data type T is not a row-major dense or sparse matrix t...
Definition: RowMajorMatrix.h:61
Header file for the HasSIMDMult type trait.
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:1357
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 reset shim.
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
Header file for the isDefault shim.
Constraint on the data type.
Constraint on the data type.
Header file for the HasSIMDSub type trait.
Constraints on the storage order of matrix types.
constexpr bool operator<=(const NegativeAccuracy< A > &, const T &rhs)
Less-or-equal-than comparison between a NegativeAccuracy object and a floating point value...
Definition: Accuracy.h:405
#define BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION(T)
Constraint on the data type.In case the given data type T requires an intermediate evaluation within ...
Definition: RequiresEvaluation.h:81
Header file for the IsReference type trait.
typename EnableIf< Condition, T >::Type EnableIf_
Auxiliary alias declaration for the EnableIf class template.The EnableIf_ alias declaration provides ...
Definition: EnableIf.h:224
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:324
const Type & ReturnType
Return type for expression template evaluations.
Definition: CompressedMatrix.h:3082
decltype(auto) trans(const DenseMatrix< MT, SO > &dm)
Calculation of the transpose of the given dense matrix.
Definition: DMatTransExpr.h:790
size_t n_
The current number of columns of the compressed matrix.
Definition: CompressedMatrix.h:3288
const This & CompositeType
Data type for composite expression templates.
Definition: CompressedMatrix.h:3083
Header file for the alignment check function.
bool isIntact(const DiagonalMatrix< MT, SO, DF > &m)
Returns whether the invariants of the given diagonal matrix are intact.
Definition: DiagonalMatrix.h:252
bool isDefault(const DiagonalProxy< MT > &proxy)
Returns whether the represented element is in default state.
Definition: DiagonalProxy.h:600
#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:1375
Header file for the IsUpper type trait.
void UNUSED_PARAMETER(const Args &...)
Suppression of unused parameter warnings.
Definition: Unused.h:81
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:635