1 //=================================================================================================
2 /*!
3 //  \file blaze/math/views/submatrix/Dense.h
4 //  \brief Submatrix specialization for dense matrices
5 //
6 //  Copyright (C) 2012-2020 Klaus Iglberger - All Rights Reserved
7 //
8 //  This file is part of the Blaze library. You can redistribute it and/or modify it under
9 //  the terms of the New (Revised) BSD License. Redistribution and use in source and binary
10 //  forms, with or without modification, are permitted provided that the following conditions
11 //  are met:
12 //
13 //  1. Redistributions of source code must retain the above copyright notice, this list of
14 //     conditions and the following disclaimer.
15 //  2. Redistributions in binary form must reproduce the above copyright notice, this list
16 //     of conditions and the following disclaimer in the documentation and/or other materials
17 //     provided with the distribution.
18 //  3. Neither the names of the Blaze development group nor the names of its contributors
19 //     may be used to endorse or promote products derived from this software without specific
20 //     prior written permission.
21 //
22 //  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
23 //  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 //  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25 //  SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 //  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27 //  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 //  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 //  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 //  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31 //  DAMAGE.
32 */
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>
46 #include <blaze/math/AlignmentFlag.h>
47 #include <blaze/math/constraints/ColumnMajorMatrix.h>
48 #include <blaze/math/constraints/Computation.h>
49 #include <blaze/math/constraints/DenseMatrix.h>
50 #include <blaze/math/constraints/RequiresEvaluation.h>
51 #include <blaze/math/constraints/RowMajorMatrix.h>
52 #include <blaze/math/constraints/Submatrix.h>
53 #include <blaze/math/constraints/Symmetric.h>
54 #include <blaze/math/constraints/TransExpr.h>
55 #include <blaze/math/constraints/UniTriangular.h>
56 #include <blaze/math/dense/InitializerMatrix.h>
57 #include <blaze/math/Exception.h>
58 #include <blaze/math/expressions/DenseMatrix.h>
59 #include <blaze/math/expressions/View.h>
60 #include <blaze/math/InitializerList.h>
61 #include <blaze/math/shims/Clear.h>
62 #include <blaze/math/shims/IsDefault.h>
63 #include <blaze/math/shims/PrevMultiple.h>
64 #include <blaze/math/shims/Reset.h>
65 #include <blaze/math/SIMD.h>
66 #include <blaze/math/StorageOrder.h>
67 #include <blaze/math/traits/AddTrait.h>
68 #include <blaze/math/traits/SchurTrait.h>
69 #include <blaze/math/traits/SubmatrixTrait.h>
70 #include <blaze/math/traits/SubTrait.h>
71 #include <blaze/math/typetraits/HasMutableDataAccess.h>
72 #include <blaze/math/typetraits/HasSIMDAdd.h>
73 #include <blaze/math/typetraits/HasSIMDMult.h>
74 #include <blaze/math/typetraits/HasSIMDSub.h>
75 #include <blaze/math/typetraits/IsContiguous.h>
76 #include <blaze/math/typetraits/IsDiagonal.h>
77 #include <blaze/math/typetraits/IsExpression.h>
78 #include <blaze/math/typetraits/IsHermitian.h>
79 #include <blaze/math/typetraits/IsLower.h>
80 #include <blaze/math/typetraits/IsRestricted.h>
81 #include <blaze/math/typetraits/IsSIMDCombinable.h>
82 #include <blaze/math/typetraits/IsSparseMatrix.h>
83 #include <blaze/math/typetraits/IsStrictlyLower.h>
84 #include <blaze/math/typetraits/IsStrictlyUpper.h>
85 #include <blaze/math/typetraits/IsSymmetric.h>
86 #include <blaze/math/typetraits/IsTriangular.h>
87 #include <blaze/math/typetraits/IsUniLower.h>
88 #include <blaze/math/typetraits/IsUniUpper.h>
89 #include <blaze/math/typetraits/IsUpper.h>
90 #include <blaze/math/typetraits/RequiresEvaluation.h>
91 #include <blaze/math/views/Check.h>
92 #include <blaze/math/views/submatrix/BaseTemplate.h>
93 #include <blaze/math/views/submatrix/SubmatrixData.h>
94 #include <blaze/system/Blocking.h>
95 #include <blaze/system/CacheSize.h>
96 #include <blaze/system/Inline.h>
97 #include <blaze/system/Optimizations.h>
98 #include <blaze/system/Thresholds.h>
99 #include <blaze/util/algorithms/Max.h>
100 #include <blaze/util/algorithms/Min.h>
101 #include <blaze/util/AlignmentCheck.h>
102 #include <blaze/util/Assert.h>
103 #include <blaze/util/constraints/Pointer.h>
104 #include <blaze/util/constraints/Reference.h>
105 #include <blaze/util/constraints/Vectorizable.h>
106 #include <blaze/util/EnableIf.h>
107 #include <blaze/util/MaybeUnused.h>
108 #include <blaze/util/mpl/If.h>
109 #include <blaze/util/Types.h>
110 #include <blaze/util/typetraits/IsConst.h>
111 #include <blaze/util/typetraits/IsReference.h>
112 
113 
114 namespace blaze {
115 
116 //=================================================================================================
117 //
118 //  CLASS TEMPLATE SPECIALIZATION FOR UNALIGNED ROW-MAJOR DENSE SUBMATRICES
119 //
120 //=================================================================================================
121 
122 //*************************************************************************************************
123 /*! \cond BLAZE_INTERNAL */
124 /*!\brief Specialization of Submatrix for unaligned row-major dense submatrices.
125 // \ingroup submatrix
126 //
127 // This Specialization of Submatrix adapts the class template to the requirements of unaligned
128 // row-major dense submatrices.
129 */
130 template< typename MT       // Type of the dense matrix
131         , size_t... CSAs >  // Compile time submatrix arguments
132 class Submatrix<MT,unaligned,false,true,CSAs...>
133    : public View< DenseMatrix< Submatrix<MT,unaligned,false,true,CSAs...>, false > >
134    , private SubmatrixData<CSAs...>
135 {
136  private:
137    //**Type definitions****************************************************************************
138    using DataType = SubmatrixData<CSAs...>;               //!< The type of the SubmatrixData base class.
139    using Operand  = If_t< IsExpression_v<MT>, MT, MT& >;  //!< Composite data type of the matrix expression.
140    //**********************************************************************************************
141 
142    //**********************************************************************************************
143    //! Helper variable template for the explicit application of the SFINAE principle.
144    template< typename MT1, typename MT2 >
145    static constexpr bool EnforceEvaluation_v =
146       ( IsRestricted_v<MT1> && RequiresEvaluation_v<MT2> );
147    //**********************************************************************************************
148 
149  public:
150    //**Type definitions****************************************************************************
151    //! Type of this Submatrix instance.
152    using This = Submatrix<MT,unaligned,false,true,CSAs...>;
153 
154    //! Base type of this Submatrix instance.
155    using BaseType = View< DenseMatrix<This,false> >;
156 
157    using ViewedType    = MT;                            //!< The type viewed by this Submatrix instance.
158    using ResultType    = SubmatrixTrait_t<MT,CSAs...>;  //!< Result type for expression template evaluations.
159    using OppositeType  = OppositeType_t<ResultType>;    //!< Result type with opposite storage order for expression template evaluations.
160    using TransposeType = TransposeType_t<ResultType>;   //!< Transpose type for expression template evaluations.
161    using ElementType   = ElementType_t<MT>;             //!< Type of the submatrix elements.
162    using SIMDType      = SIMDTrait_t<ElementType>;      //!< SIMD type of the submatrix elements.
163    using ReturnType    = ReturnType_t<MT>;              //!< Return type for expression template evaluations
164    using CompositeType = const Submatrix&;              //!< Data type for composite expression templates.
165 
166    //! Reference to a constant submatrix value.
167    using ConstReference = ConstReference_t<MT>;
168 
169    //! Reference to a non-constant submatrix value.
170    using Reference = If_t< IsConst_v<MT>, ConstReference, Reference_t<MT> >;
171 
172    //! Pointer to a constant submatrix value.
173    using ConstPointer = ConstPointer_t<MT>;
174 
175    //! Pointer to a non-constant submatrix value.
176    using Pointer = If_t< IsConst_v<MT> || !HasMutableDataAccess_v<MT>, ConstPointer, Pointer_t<MT> >;
177    //**********************************************************************************************
178 
179    //**SubmatrixIterator class definition**********************************************************
180    /*!\brief Iterator over the elements of the sparse submatrix.
181    */
182    template< typename IteratorType >  // Type of the dense matrix iterator
183    class SubmatrixIterator
184    {
185     public:
186       //**Type definitions*************************************************************************
187       //! The iterator category.
188       using IteratorCategory = typename std::iterator_traits<IteratorType>::iterator_category;
189 
190       //! Type of the underlying elements.
191       using ValueType = typename std::iterator_traits<IteratorType>::value_type;
192 
193       //! Pointer return type.
194       using PointerType = typename std::iterator_traits<IteratorType>::pointer;
195 
196       //! Reference return type.
197       using ReferenceType = typename std::iterator_traits<IteratorType>::reference;
198 
199       //! Difference between two iterators.
200       using DifferenceType = typename std::iterator_traits<IteratorType>::difference_type;
201 
202       // STL iterator requirements
203       using iterator_category = IteratorCategory;  //!< The iterator category.
204       using value_type        = ValueType;         //!< Type of the underlying elements.
205       using pointer           = PointerType;       //!< Pointer return type.
206       using reference         = ReferenceType;     //!< Reference return type.
207       using difference_type   = DifferenceType;    //!< Difference between two iterators.
208       //*******************************************************************************************
209 
210       //**Constructor******************************************************************************
211       /*!\brief Default constructor of the SubmatrixIterator class.
212       */
SubmatrixIterator()213       inline SubmatrixIterator()
214          : iterator_ (       )  // Iterator to the current submatrix element
215          , isAligned_( false )  // Memory alignment flag
216       {}
217       //*******************************************************************************************
218 
219       //**Constructor******************************************************************************
220       /*!\brief Constructor of the SubmatrixIterator class.
221       //
222       // \param iterator Iterator to the initial element.
223       // \param isMemoryAligned Memory alignment flag.
224       */
SubmatrixIterator(IteratorType iterator,bool isMemoryAligned)225       inline SubmatrixIterator( IteratorType iterator, bool isMemoryAligned )
226          : iterator_ ( iterator        )  // Iterator to the current submatrix element
227          , isAligned_( isMemoryAligned )  // Memory alignment flag
228       {}
229       //*******************************************************************************************
230 
231       //**Constructor******************************************************************************
232       /*!\brief Conversion constructor from different SubmatrixIterator instances.
233       //
234       // \param it The submatrix iterator to be copied.
235       */
236       template< typename IteratorType2 >
SubmatrixIterator(const SubmatrixIterator<IteratorType2> & it)237       inline SubmatrixIterator( const SubmatrixIterator<IteratorType2>& it )
238          : iterator_ ( it.base()      )  // Iterator to the current submatrix element
239          , isAligned_( it.isAligned() )  // Memory alignment flag
240       {}
241       //*******************************************************************************************
242 
243       //**Addition assignment operator*************************************************************
244       /*!\brief Addition assignment operator.
245       //
246       // \param inc The increment of the iterator.
247       // \return The incremented iterator.
248       */
249       inline SubmatrixIterator& operator+=( size_t inc ) {
250          iterator_ += inc;
251          return *this;
252       }
253       //*******************************************************************************************
254 
255       //**Subtraction assignment operator**********************************************************
256       /*!\brief Subtraction assignment operator.
257       //
258       // \param dec The decrement of the iterator.
259       // \return The decremented iterator.
260       */
261       inline SubmatrixIterator& operator-=( size_t dec ) {
262          iterator_ -= dec;
263          return *this;
264       }
265       //*******************************************************************************************
266 
267       //**Prefix increment operator****************************************************************
268       /*!\brief Pre-increment operator.
269       //
270       // \return Reference to the incremented iterator.
271       */
272       inline SubmatrixIterator& operator++() {
273          ++iterator_;
274          return *this;
275       }
276       //*******************************************************************************************
277 
278       //**Postfix increment operator***************************************************************
279       /*!\brief Post-increment operator.
280       //
281       // \return The previous position of the iterator.
282       */
283       inline const SubmatrixIterator operator++( int ) {
284          return SubmatrixIterator( iterator_++, isAligned_ );
285       }
286       //*******************************************************************************************
287 
288       //**Prefix decrement operator****************************************************************
289       /*!\brief Pre-decrement operator.
290       //
291       // \return Reference to the decremented iterator.
292       */
293       inline SubmatrixIterator& operator--() {
294          --iterator_;
295          return *this;
296       }
297       //*******************************************************************************************
298 
299       //**Postfix decrement operator***************************************************************
300       /*!\brief Post-decrement operator.
301       //
302       // \return The previous position of the iterator.
303       */
304       inline const SubmatrixIterator operator--( int ) {
305          return SubmatrixIterator( iterator_--, isAligned_ );
306       }
307       //*******************************************************************************************
308 
309       //**Element access operator******************************************************************
310       /*!\brief Direct access to the element at the current iterator position.
311       //
312       // \return The resulting value.
313       */
314       inline ReferenceType operator*() const {
315          return *iterator_;
316       }
317       //*******************************************************************************************
318 
319       //**Element access operator******************************************************************
320       /*!\brief Direct access to the element at the current iterator position.
321       //
322       // \return Pointer to the element at the current iterator position.
323       */
324       inline IteratorType operator->() const {
325          return iterator_;
326       }
327       //*******************************************************************************************
328 
329       //**Load function****************************************************************************
330       /*!\brief Load of a SIMD element of the dense submatrix.
331       //
332       // \return The loaded SIMD element.
333       //
334       // This function performs a load of the current SIMD element of the submatrix iterator.
335       // This function must \b NOT be called explicitly! It is used internally for the performance
336       // optimized evaluation of expression templates. Calling this function explicitly might
337       // result in erroneous results and/or in compilation errors.
338       */
load()339       inline SIMDType load() const noexcept {
340          if( isAligned_ )
341             return loada();
342          else
343             return loadu();
344       }
345       //*******************************************************************************************
346 
347       //**Loada function***************************************************************************
348       /*!\brief Aligned load of a SIMD element of the dense submatrix.
349       //
350       // \return The loaded SIMD element.
351       //
352       // This function performs an aligned load of the current SIMD element of the submatrix
353       // iterator. This function must \b NOT be called explicitly! It is used internally for
354       // the performance optimized evaluation of expression templates. Calling this function
355       // explicitly might result in erroneous results and/or in compilation errors.
356       */
loada()357       inline SIMDType loada() const noexcept {
358          return iterator_.loada();
359       }
360       //*******************************************************************************************
361 
362       //**Loadu function***************************************************************************
363       /*!\brief Unaligned load of a SIMD element of the dense submatrix.
364       //
365       // \return The loaded SIMD element.
366       //
367       // This function performs an unaligned load of the current SIMD element of the submatrix
368       // iterator. This function must \b NOT be called explicitly! It is used internally for the
369       // performance optimized evaluation of expression templates. Calling this function explicitly
370       // might result in erroneous results and/or in compilation errors.
371       */
loadu()372       inline SIMDType loadu() const noexcept {
373          return iterator_.loadu();
374       }
375       //*******************************************************************************************
376 
377       //**Store function***************************************************************************
378       /*!\brief Store of a SIMD element of the dense submatrix.
379       //
380       // \param value The SIMD element to be stored.
381       // \return void
382       //
383       // This function performs a store of the current SIMD element of the submatrix iterator.
384       // This function must \b NOT be called explicitly! It is used internally for the performance
385       // optimized evaluation of expression templates. Calling this function explicitly might
386       // result in erroneous results and/or in compilation errors.
387       */
store(const SIMDType & value)388       inline void store( const SIMDType& value ) const {
389          if( isAligned_ ) {
390             storea( value );
391          }
392          else {
393             storeu( value );
394          }
395       }
396       //*******************************************************************************************
397 
398       //**Storea function**************************************************************************
399       /*!\brief Aligned store of a SIMD element of the dense submatrix.
400       //
401       // \param value The SIMD element to be stored.
402       // \return void
403       //
404       // This function performs an aligned store of the current SIMD element of the submatrix
405       // iterator. This function must \b NOT be called explicitly! It is used internally for the
406       // performance optimized evaluation of expression templates. Calling this function explicitly
407       // might result in erroneous results and/or in compilation errors.
408       */
storea(const SIMDType & value)409       inline void storea( const SIMDType& value ) const {
410          iterator_.storea( value );
411       }
412       //*******************************************************************************************
413 
414       //**Storeu function**************************************************************************
415       /*!\brief Unaligned store of a SIMD element of the dense submatrix.
416       //
417       // \param value The SIMD element to be stored.
418       // \return void
419       //
420       // This function performs an unaligned store of the current SIMD element of the submatrix
421       // iterator. This function must \b NOT be called explicitly! It is used internally for the
422       // performance optimized evaluation of expression templates. Calling this function explicitly
423       // might result in erroneous results and/or in compilation errors.
424       */
storeu(const SIMDType & value)425       inline void storeu( const SIMDType& value ) const {
426          iterator_.storeu( value );
427       }
428       //*******************************************************************************************
429 
430       //**Stream function**************************************************************************
431       /*!\brief Aligned, non-temporal store of a SIMD element of the dense submatrix.
432       //
433       // \param value The SIMD element to be stored.
434       // \return void
435       //
436       // This function performs an aligned, non-temporal store of the current SIMD element of the
437       // submatrix iterator. This function must \b NOT be called explicitly! It is used internally
438       // for the performance optimized evaluation of expression templates. Calling this function
439       // explicitly might result in erroneous results and/or in compilation errors.
440       */
stream(const SIMDType & value)441       inline void stream( const SIMDType& value ) const {
442          iterator_.stream( value );
443       }
444       //*******************************************************************************************
445 
446       //**Equality operator************************************************************************
447       /*!\brief Equality comparison between two SubmatrixIterator objects.
448       //
449       // \param rhs The right-hand side iterator.
450       // \return \a true if the iterators refer to the same element, \a false if not.
451       */
452       inline bool operator==( const SubmatrixIterator& rhs ) const {
453          return iterator_ == rhs.iterator_;
454       }
455       //*******************************************************************************************
456 
457       //**Inequality operator**********************************************************************
458       /*!\brief Inequality comparison between two SubmatrixIterator objects.
459       //
460       // \param rhs The right-hand side iterator.
461       // \return \a true if the iterators don't refer to the same element, \a false if they do.
462       */
463       inline bool operator!=( const SubmatrixIterator& rhs ) const {
464          return iterator_ != rhs.iterator_;
465       }
466       //*******************************************************************************************
467 
468       //**Less-than operator***********************************************************************
469       /*!\brief Less-than comparison between two SubmatrixIterator objects.
470       //
471       // \param rhs The right-hand side iterator.
472       // \return \a true if the left-hand side iterator is smaller, \a false if not.
473       */
474       inline bool operator<( const SubmatrixIterator& rhs ) const {
475          return iterator_ < rhs.iterator_;
476       }
477       //*******************************************************************************************
478 
479       //**Greater-than operator********************************************************************
480       /*!\brief Greater-than comparison between two SubmatrixIterator objects.
481       //
482       // \param rhs The right-hand side iterator.
483       // \return \a true if the left-hand side iterator is greater, \a false if not.
484       */
485       inline bool operator>( const SubmatrixIterator& rhs ) const {
486          return iterator_ > rhs.iterator_;
487       }
488       //*******************************************************************************************
489 
490       //**Less-or-equal-than operator**************************************************************
491       /*!\brief Less-than comparison between two SubmatrixIterator objects.
492       //
493       // \param rhs The right-hand side iterator.
494       // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
495       */
496       inline bool operator<=( const SubmatrixIterator& rhs ) const {
497          return iterator_ <= rhs.iterator_;
498       }
499       //*******************************************************************************************
500 
501       //**Greater-or-equal-than operator***********************************************************
502       /*!\brief Greater-than comparison between two SubmatrixIterator objects.
503       //
504       // \param rhs The right-hand side iterator.
505       // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
506       */
507       inline bool operator>=( const SubmatrixIterator& rhs ) const {
508          return iterator_ >= rhs.iterator_;
509       }
510       //*******************************************************************************************
511 
512       //**Subtraction operator*********************************************************************
513       /*!\brief Calculating the number of elements between two iterators.
514       //
515       // \param rhs The right-hand side iterator.
516       // \return The number of elements between the two iterators.
517       */
518       inline DifferenceType operator-( const SubmatrixIterator& rhs ) const {
519          return iterator_ - rhs.iterator_;
520       }
521       //*******************************************************************************************
522 
523       //**Addition operator************************************************************************
524       /*!\brief Addition between a SubmatrixIterator and an integral value.
525       //
526       // \param it The iterator to be incremented.
527       // \param inc The number of elements the iterator is incremented.
528       // \return The incremented iterator.
529       */
530       friend inline const SubmatrixIterator operator+( const SubmatrixIterator& it, size_t inc ) {
531          return SubmatrixIterator( it.iterator_ + inc, it.isAligned_ );
532       }
533       //*******************************************************************************************
534 
535       //**Addition operator************************************************************************
536       /*!\brief Addition between an integral value and a SubmatrixIterator.
537       //
538       // \param inc The number of elements the iterator is incremented.
539       // \param it The iterator to be incremented.
540       // \return The incremented iterator.
541       */
542       friend inline const SubmatrixIterator operator+( size_t inc, const SubmatrixIterator& it ) {
543          return SubmatrixIterator( it.iterator_ + inc, it.isAligned_ );
544       }
545       //*******************************************************************************************
546 
547       //**Subtraction operator*********************************************************************
548       /*!\brief Subtraction between a SubmatrixIterator and an integral value.
549       //
550       // \param it The iterator to be decremented.
551       // \param dec The number of elements the iterator is decremented.
552       // \return The decremented iterator.
553       */
554       friend inline const SubmatrixIterator operator-( const SubmatrixIterator& it, size_t dec ) {
555          return SubmatrixIterator( it.iterator_ - dec, it.isAligned_ );
556       }
557       //*******************************************************************************************
558 
559       //**Base function****************************************************************************
560       /*!\brief Access to the current position of the submatrix iterator.
561       //
562       // \return The current position of the submatrix iterator.
563       */
base()564       inline IteratorType base() const {
565          return iterator_;
566       }
567       //*******************************************************************************************
568 
569       //**IsAligned function***********************************************************************
570       /*!\brief Access to the iterator's memory alignment flag.
571       //
572       // \return \a true in case the iterator is aligned, \a false if it is not.
573       */
isAligned()574       inline bool isAligned() const noexcept {
575          return isAligned_;
576       }
577       //*******************************************************************************************
578 
579     private:
580       //**Member variables*************************************************************************
581       IteratorType iterator_;   //!< Iterator to the current submatrix element.
582       bool         isAligned_;  //!< Memory alignment flag.
583       //*******************************************************************************************
584    };
585    //**********************************************************************************************
586 
587    //**Type definitions****************************************************************************
588    //! Iterator over constant elements.
589    using ConstIterator = SubmatrixIterator< ConstIterator_t<MT> >;
590 
591    //! Iterator over non-constant elements.
592    using Iterator = If_t< IsConst_v<MT>, ConstIterator, SubmatrixIterator< Iterator_t<MT> > >;
593    //**********************************************************************************************
594 
595    //**Compilation flags***************************************************************************
596    //! Compilation switch for the expression template evaluation strategy.
597    static constexpr bool simdEnabled = MT::simdEnabled;
598 
599    //! Compilation switch for the expression template assignment strategy.
600    static constexpr bool smpAssignable = MT::smpAssignable;
601 
602    //! Compilation switch for the expression template evaluation strategy.
603    static constexpr bool compileTimeArgs = DataType::compileTimeArgs;
604    //**********************************************************************************************
605 
606    //**Constructors********************************************************************************
607    /*!\name Constructors */
608    //@{
609    template< typename... RSAs >
610    explicit inline Submatrix( MT& matrix, RSAs... args );
611 
612    Submatrix( const Submatrix& ) = default;
613    //@}
614    //**********************************************************************************************
615 
616    //**Destructor**********************************************************************************
617    /*!\name Destructor */
618    //@{
619    ~Submatrix() = default;
620    //@}
621    //**********************************************************************************************
622 
623    //**Data access functions***********************************************************************
624    /*!\name Data access functions */
625    //@{
626    inline Reference      operator()( size_t i, size_t j );
627    inline ConstReference operator()( size_t i, size_t j ) const;
628    inline Reference      at( size_t i, size_t j );
629    inline ConstReference at( size_t i, size_t j ) const;
630    inline Pointer        data  () noexcept;
631    inline ConstPointer   data  () const noexcept;
632    inline Pointer        data  ( size_t i ) noexcept;
633    inline ConstPointer   data  ( size_t i ) const noexcept;
634    inline Iterator       begin ( size_t i );
635    inline ConstIterator  begin ( size_t i ) const;
636    inline ConstIterator  cbegin( size_t i ) const;
637    inline Iterator       end   ( size_t i );
638    inline ConstIterator  end   ( size_t i ) const;
639    inline ConstIterator  cend  ( size_t i ) const;
640    //@}
641    //**********************************************************************************************
642 
643    //**Assignment operators************************************************************************
644    /*!\name Assignment operators */
645    //@{
646    inline Submatrix& operator=( const ElementType& rhs );
647    inline Submatrix& operator=( initializer_list< initializer_list<ElementType> > list );
648    inline Submatrix& operator=( const Submatrix& rhs );
649 
650    template< typename MT2, bool SO2 >
651    inline Submatrix& operator=( const Matrix<MT2,SO2>& rhs );
652 
653    template< typename MT2, bool SO2 >
654    inline auto operator+=( const Matrix<MT2,SO2>& rhs )
655       -> DisableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >;
656 
657    template< typename MT2, bool SO2 >
658    inline auto operator+=( const Matrix<MT2,SO2>& rhs )
659       -> EnableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >;
660 
661    template< typename MT2, bool SO2 >
662    inline auto operator-=( const Matrix<MT2,SO2>& rhs )
663       -> DisableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >;
664 
665    template< typename MT2, bool SO2 >
666    inline auto operator-=( const Matrix<MT2,SO2>& rhs )
667       -> EnableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >;
668 
669    template< typename MT2, bool SO2 >
670    inline auto operator%=( const Matrix<MT2,SO2>& rhs )
671       -> DisableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >;
672 
673    template< typename MT2, bool SO2 >
674    inline auto operator%=( const Matrix<MT2,SO2>& rhs )
675       -> EnableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >;
676    //@}
677    //**********************************************************************************************
678 
679    //**Utility functions***************************************************************************
680    /*!\name Utility functions */
681    //@{
682    using DataType::row;
683    using DataType::column;
684    using DataType::rows;
685    using DataType::columns;
686 
687    inline MT&       operand() noexcept;
688    inline const MT& operand() const noexcept;
689 
690    inline size_t spacing() const noexcept;
691    inline size_t capacity() const noexcept;
692    inline size_t capacity( size_t i ) const noexcept;
693    inline size_t nonZeros() const;
694    inline size_t nonZeros( size_t i ) const;
695    inline void   reset();
696    inline void   reset( size_t i );
697    //@}
698    //**********************************************************************************************
699 
700    //**Numeric functions***************************************************************************
701    /*!\name Numeric functions */
702    //@{
703    inline Submatrix& transpose();
704    inline Submatrix& ctranspose();
705 
706    template< typename Other > inline Submatrix& scale( const Other& scalar );
707    //@}
708    //**********************************************************************************************
709 
710  private:
711    //**********************************************************************************************
712    //! Helper variable template for the explicit application of the SFINAE principle.
713    template< typename MT2 >
714    static constexpr bool VectorizedAssign_v =
715       ( useOptimizedKernels &&
716         simdEnabled && MT2::simdEnabled &&
717         IsSIMDCombinable_v< ElementType, ElementType_t<MT2> > );
718    //**********************************************************************************************
719 
720    //**********************************************************************************************
721    //! Helper variable template for the explicit application of the SFINAE principle.
722    template< typename MT2 >
723    static constexpr bool VectorizedAddAssign_v =
724       ( VectorizedAssign_v<MT2> &&
725         HasSIMDAdd_v< ElementType, ElementType_t<MT2> > &&
726         !IsDiagonal_v<MT2> );
727    //**********************************************************************************************
728 
729    //**********************************************************************************************
730    //! Helper variable template for the explicit application of the SFINAE principle.
731    template< typename MT2 >
732    static constexpr bool VectorizedSubAssign_v =
733       ( VectorizedAssign_v<MT2> &&
734         HasSIMDSub_v< ElementType, ElementType_t<MT2> > &&
735         !IsDiagonal_v<MT2> );
736    //**********************************************************************************************
737 
738    //**********************************************************************************************
739    //! Helper variable template for the explicit application of the SFINAE principle.
740    template< typename MT2 >
741    static constexpr bool VectorizedSchurAssign_v =
742       ( VectorizedAssign_v<MT2> &&
743         HasSIMDMult_v< ElementType, ElementType_t<MT2> > );
744    //**********************************************************************************************
745 
746    //**SIMD properties*****************************************************************************
747    //! The number of elements packed within a single SIMD element.
748    static constexpr size_t SIMDSIZE = SIMDTrait<ElementType>::size;
749    //**********************************************************************************************
750 
751  public:
752    //**Expression template evaluation functions****************************************************
753    /*!\name Expression template evaluation functions */
754    //@{
755    template< typename Other >
756    inline bool canAlias( const Other* alias ) const noexcept;
757 
758    template< typename MT2, AlignmentFlag AF2, bool SO2, size_t... CSAs2 >
759    inline bool canAlias( const Submatrix<MT2,AF2,SO2,true,CSAs2...>* alias ) const noexcept;
760 
761    template< typename Other >
762    inline bool isAliased( const Other* alias ) const noexcept;
763 
764    template< typename MT2, AlignmentFlag AF2, bool SO2, size_t... CSAs2 >
765    inline bool isAliased( const Submatrix<MT2,AF2,SO2,true,CSAs2...>* alias ) const noexcept;
766 
767    inline bool isAligned   () const noexcept;
768    inline bool canSMPAssign() const noexcept;
769 
770    BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
771    BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
772    BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
773 
774    BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
775    BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
776    BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
777    BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
778 
779    template< typename MT2 >
780    inline auto assign( const DenseMatrix<MT2,false>& rhs ) -> DisableIf_t< VectorizedAssign_v<MT2> >;
781 
782    template< typename MT2 >
783    inline auto assign( const DenseMatrix<MT2,false>& rhs ) -> EnableIf_t< VectorizedAssign_v<MT2> >;
784 
785    template< typename MT2 > inline void assign( const DenseMatrix<MT2,true>&  rhs );
786    template< typename MT2 > inline void assign( const SparseMatrix<MT2,false>&  rhs );
787    template< typename MT2 > inline void assign( const SparseMatrix<MT2,true>& rhs );
788 
789    template< typename MT2 >
790    inline auto addAssign( const DenseMatrix<MT2,false>& rhs ) -> DisableIf_t< VectorizedAddAssign_v<MT2> >;
791 
792    template< typename MT2 >
793    inline auto addAssign( const DenseMatrix<MT2,false>& rhs ) -> EnableIf_t< VectorizedAddAssign_v<MT2> >;
794 
795    template< typename MT2 > inline void addAssign( const DenseMatrix<MT2,true>&  rhs );
796    template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,false>&  rhs );
797    template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,true>& rhs );
798 
799    template< typename MT2 >
800    inline auto subAssign( const DenseMatrix<MT2,false>& rhs ) -> DisableIf_t< VectorizedSubAssign_v<MT2> >;
801 
802    template< typename MT2 >
803    inline auto subAssign( const DenseMatrix<MT2,false>& rhs ) -> EnableIf_t< VectorizedSubAssign_v<MT2> >;
804 
805    template< typename MT2 > inline void subAssign( const DenseMatrix<MT2,true>&  rhs );
806    template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,false>&  rhs );
807    template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,true>& rhs );
808 
809    template< typename MT2 >
810    inline auto schurAssign( const DenseMatrix<MT2,false>& rhs ) -> DisableIf_t< VectorizedSchurAssign_v<MT2> >;
811 
812    template< typename MT2 >
813    inline auto schurAssign( const DenseMatrix<MT2,false>& rhs ) -> EnableIf_t< VectorizedSchurAssign_v<MT2> >;
814 
815    template< typename MT2 > inline void schurAssign( const DenseMatrix<MT2,true>&  rhs );
816    template< typename MT2 > inline void schurAssign( const SparseMatrix<MT2,false>&  rhs );
817    template< typename MT2 > inline void schurAssign( const SparseMatrix<MT2,true>& rhs );
818    //@}
819    //**********************************************************************************************
820 
821  private:
822    //**Utility functions***************************************************************************
823    /*!\name Utility functions */
824    //@{
825    inline bool hasOverlap() const noexcept;
826    //@}
827    //**********************************************************************************************
828 
829    //**Member variables****************************************************************************
830    /*!\name Member variables */
831    //@{
832    Operand matrix_;        //!< The matrix containing the submatrix.
833    const bool isAligned_;  //!< Memory alignment flag.
834                            /*!< The alignment flag indicates whether the submatrix is fully aligned
835                                 with respect to the given element type and the available instruction
836                                 set. In case the submatrix is fully aligned it is possible to use
837                                 aligned loads and stores instead of unaligned loads and stores. In
838                                 order to be aligned, the first element of each row/column must be
839                                 aligned. */
840    //@}
841    //**********************************************************************************************
842 
843    //**Friend declarations*************************************************************************
844    template< typename MT2, AlignmentFlag AF2, bool SO2, bool DF2, size_t... CSAs2 > friend class Submatrix;
845    //**********************************************************************************************
846 
847    //**Compile time checks*************************************************************************
848    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE    ( MT );
849    BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE ( MT );
850    BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE   ( MT );
851    BLAZE_CONSTRAINT_MUST_NOT_BE_SUBMATRIX_TYPE   ( MT );
852    BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT );
853    BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE     ( MT );
854    BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE   ( MT );
855    //**********************************************************************************************
856 };
857 /*! \endcond */
858 //*************************************************************************************************
859 
860 
861 
862 
863 //=================================================================================================
864 //
865 //  CONSTRUCTORS
866 //
867 //=================================================================================================
868 
869 //*************************************************************************************************
870 /*! \cond BLAZE_INTERNAL */
871 /*!\brief Constructor for unaligned row-major dense submatrices.
872 //
873 // \param matrix The dense matrix containing the submatrix.
874 // \param args The runtime submatrix arguments.
875 // \exception std::invalid_argument Invalid submatrix specification.
876 //
877 // By default, the provided submatrix arguments are checked at runtime. In case the submatrix is
878 // not properly specified (i.e. if the specified submatrix is not contained in the given dense
879 // matrix) a \a std::invalid_argument exception is thrown. The checks can be skipped by providing
880 // the optional \a blaze::unchecked argument.
881 */
882 template< typename MT         // Type of the dense matrix
883         , size_t... CSAs >    // Compile time submatrix arguments
884 template< typename... RSAs >  // Runtime submatrix arguments
Submatrix(MT & matrix,RSAs...args)885 inline Submatrix<MT,unaligned,false,true,CSAs...>::Submatrix( MT& matrix, RSAs... args )
886    : DataType  ( args... )  // Base class initialization
887    , matrix_   ( matrix  )  // The matrix containing the submatrix
888    , isAligned_( simdEnabled && IsContiguous_v<MT> &&
889                  matrix.data() != nullptr && checkAlignment( data() ) &&
890                  ( rows() < 2UL || ( matrix.spacing() % SIMDSIZE ) == 0UL ) )
891 {
892    if( isChecked( args... ) ) {
893       if( ( row() + rows() > matrix_.rows() ) || ( column() + columns() > matrix_.columns() ) ) {
894          BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix specification" );
895       }
896    }
897    else {
898       BLAZE_USER_ASSERT( row()    + rows()    <= matrix_.rows()   , "Invalid submatrix specification" );
899       BLAZE_USER_ASSERT( column() + columns() <= matrix_.columns(), "Invalid submatrix specification" );
900    }
901 }
902 /*! \endcond */
903 //*************************************************************************************************
904 
905 
906 
907 
908 //=================================================================================================
909 //
910 //  DATA ACCESS FUNCTIONS
911 //
912 //=================================================================================================
913 
914 //*************************************************************************************************
915 /*! \cond BLAZE_INTERNAL */
916 /*!\brief 2D-access to the dense submatrix elements.
917 //
918 // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
919 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
920 // \return Reference to the accessed value.
921 //
922 // This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
923 // the at() function is guaranteed to perform a check of the given access indices.
924 */
925 template< typename MT       // Type of the dense matrix
926         , size_t... CSAs >  // Compile time submatrix arguments
927 inline typename Submatrix<MT,unaligned,false,true,CSAs...>::Reference
operator()928    Submatrix<MT,unaligned,false,true,CSAs...>::operator()( size_t i, size_t j )
929 {
930    BLAZE_USER_ASSERT( i < rows()   , "Invalid row access index"    );
931    BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
932 
933    return matrix_(row()+i,column()+j);
934 }
935 /*! \endcond */
936 //*************************************************************************************************
937 
938 
939 //*************************************************************************************************
940 /*! \cond BLAZE_INTERNAL */
941 /*!\brief 2D-access to the dense submatrix elements.
942 //
943 // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
944 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
945 // \return Reference to the accessed value.
946 //
947 // This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
948 // the at() function is guaranteed to perform a check of the given access indices.
949 */
950 template< typename MT       // Type of the dense matrix
951         , size_t... CSAs >  // Compile time submatrix arguments
952 inline typename Submatrix<MT,unaligned,false,true,CSAs...>::ConstReference
operator()953    Submatrix<MT,unaligned,false,true,CSAs...>::operator()( size_t i, size_t j ) const
954 {
955    BLAZE_USER_ASSERT( i < rows()   , "Invalid row access index"    );
956    BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
957 
958    return const_cast<const MT&>( matrix_ )(row()+i,column()+j);
959 }
960 /*! \endcond */
961 //*************************************************************************************************
962 
963 
964 //*************************************************************************************************
965 /*! \cond BLAZE_INTERNAL */
966 /*!\brief Checked access to the submatrix elements.
967 //
968 // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
969 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
970 // \return Reference to the accessed value.
971 // \exception std::out_of_range Invalid matrix access index.
972 //
973 // In contrast to the function call operator this function always performs a check of the given
974 // access indices.
975 */
976 template< typename MT       // Type of the dense matrix
977         , size_t... CSAs >  // Compile time submatrix arguments
978 inline typename Submatrix<MT,unaligned,false,true,CSAs...>::Reference
at(size_t i,size_t j)979    Submatrix<MT,unaligned,false,true,CSAs...>::at( size_t i, size_t j )
980 {
981    if( i >= rows() ) {
982       BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
983    }
984    if( j >= columns() ) {
985       BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
986    }
987    return (*this)(i,j);
988 }
989 /*! \endcond */
990 //*************************************************************************************************
991 
992 
993 //*************************************************************************************************
994 /*! \cond BLAZE_INTERNAL */
995 /*!\brief Checked access to the submatrix elements.
996 //
997 // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
998 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
999 // \return Reference to the accessed value.
1000 // \exception std::out_of_range Invalid matrix access index.
1001 //
1002 // In contrast to the function call operator this function always performs a check of the given
1003 // access indices.
1004 */
1005 template< typename MT       // Type of the dense matrix
1006         , size_t... CSAs >  // Compile time submatrix arguments
1007 inline typename Submatrix<MT,unaligned,false,true,CSAs...>::ConstReference
at(size_t i,size_t j)1008    Submatrix<MT,unaligned,false,true,CSAs...>::at( size_t i, size_t j ) const
1009 {
1010    if( i >= rows() ) {
1011       BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
1012    }
1013    if( j >= columns() ) {
1014       BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
1015    }
1016    return (*this)(i,j);
1017 }
1018 /*! \endcond */
1019 //*************************************************************************************************
1020 
1021 
1022 //*************************************************************************************************
1023 /*! \cond BLAZE_INTERNAL */
1024 /*!\brief Low-level data access to the submatrix elements.
1025 //
1026 // \return Pointer to the internal element storage.
1027 //
1028 // This function returns a pointer to the internal storage of the dense submatrix. Note that
1029 // you can NOT assume that all matrix elements lie adjacent to each other! The dense submatrix
1030 // may use techniques such as padding to improve the alignment of the data.
1031 */
1032 template< typename MT       // Type of the dense matrix
1033         , size_t... CSAs >  // Compile time submatrix arguments
1034 inline typename Submatrix<MT,unaligned,false,true,CSAs...>::Pointer
data()1035    Submatrix<MT,unaligned,false,true,CSAs...>::data() noexcept
1036 {
1037    return matrix_.data() + row()*spacing() + column();
1038 }
1039 /*! \endcond */
1040 //*************************************************************************************************
1041 
1042 
1043 //*************************************************************************************************
1044 /*! \cond BLAZE_INTERNAL */
1045 /*!\brief Low-level data access to the submatrix elements.
1046 //
1047 // \return Pointer to the internal element storage.
1048 //
1049 // This function returns a pointer to the internal storage of the dense submatrix. Note that
1050 // you can NOT assume that all matrix elements lie adjacent to each other! The dense submatrix
1051 // may use techniques such as padding to improve the alignment of the data.
1052 */
1053 template< typename MT       // Type of the dense matrix
1054         , size_t... CSAs >  // Compile time submatrix arguments
1055 inline typename Submatrix<MT,unaligned,false,true,CSAs...>::ConstPointer
data()1056    Submatrix<MT,unaligned,false,true,CSAs...>::data() const noexcept
1057 {
1058    return matrix_.data() + row()*spacing() + column();
1059 }
1060 /*! \endcond */
1061 //*************************************************************************************************
1062 
1063 
1064 //*************************************************************************************************
1065 /*! \cond BLAZE_INTERNAL */
1066 /*!\brief Low-level data access to the submatrix elements of row/column \a i.
1067 //
1068 // \param i The row/column index.
1069 // \return Pointer to the internal element storage.
1070 //
1071 // This function returns a pointer to the internal storage for the elements in row/column \a i.
1072 */
1073 template< typename MT       // Type of the dense matrix
1074         , size_t... CSAs >  // Compile time submatrix arguments
1075 inline typename Submatrix<MT,unaligned,false,true,CSAs...>::Pointer
data(size_t i)1076    Submatrix<MT,unaligned,false,true,CSAs...>::data( size_t i ) noexcept
1077 {
1078    return matrix_.data() + (row()+i)*spacing() + column();
1079 }
1080 /*! \endcond */
1081 //*************************************************************************************************
1082 
1083 
1084 //*************************************************************************************************
1085 /*! \cond BLAZE_INTERNAL */
1086 /*!\brief Low-level data access to the submatrix elements of row/column \a i.
1087 //
1088 // \param i The row/column index.
1089 // \return Pointer to the internal element storage.
1090 //
1091 // This function returns a pointer to the internal storage for the elements in row/column \a i.
1092 */
1093 template< typename MT       // Type of the dense matrix
1094         , size_t... CSAs >  // Compile time submatrix arguments
1095 inline typename Submatrix<MT,unaligned,false,true,CSAs...>::ConstPointer
data(size_t i)1096    Submatrix<MT,unaligned,false,true,CSAs...>::data( size_t i ) const noexcept
1097 {
1098    return matrix_.data() + (row()+i)*spacing() + column();
1099 }
1100 /*! \endcond */
1101 //*************************************************************************************************
1102 
1103 
1104 //*************************************************************************************************
1105 /*! \cond BLAZE_INTERNAL */
1106 /*!\brief Returns an iterator to the first non-zero element of row/column \a i.
1107 //
1108 // \param i The row/column index.
1109 // \return Iterator to the first non-zero element of row/column \a i.
1110 //
1111 // This function returns a row/column iterator to the first non-zero element of row/column \a i.
1112 // In case the storage order is set to \a rowMajor the function returns an iterator to the first
1113 // non-zero element of row \a i, in case the storage flag is set to \a columnMajor the function
1114 // returns an iterator to the first non-zero element of column \a i.
1115 */
1116 template< typename MT       // Type of the dense matrix
1117         , size_t... CSAs >  // Compile time submatrix arguments
1118 inline typename Submatrix<MT,unaligned,false,true,CSAs...>::Iterator
begin(size_t i)1119    Submatrix<MT,unaligned,false,true,CSAs...>::begin( size_t i )
1120 {
1121    BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
1122    return Iterator( matrix_.begin( row() + i ) + column(), isAligned_ );
1123 }
1124 /*! \endcond */
1125 //*************************************************************************************************
1126 
1127 
1128 //*************************************************************************************************
1129 /*! \cond BLAZE_INTERNAL */
1130 /*!\brief Returns an iterator to the first non-zero element of row/column \a i.
1131 //
1132 // \param i The row/column index.
1133 // \return Iterator to the first non-zero element of row/column \a i.
1134 //
1135 // This function returns a row/column iterator to the first non-zero element of row/column \a i.
1136 // In case the storage order is set to \a rowMajor the function returns an iterator to the first
1137 // non-zero element of row \a i, in case the storage flag is set to \a columnMajor the function
1138 // returns an iterator to the first non-zero element of column \a i.
1139 */
1140 template< typename MT       // Type of the dense matrix
1141         , size_t... CSAs >  // Compile time submatrix arguments
1142 inline typename Submatrix<MT,unaligned,false,true,CSAs...>::ConstIterator
begin(size_t i)1143    Submatrix<MT,unaligned,false,true,CSAs...>::begin( size_t i ) const
1144 {
1145    BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
1146    return ConstIterator( matrix_.cbegin( row() + i ) + column(), isAligned_ );
1147 }
1148 /*! \endcond */
1149 //*************************************************************************************************
1150 
1151 
1152 //*************************************************************************************************
1153 /*! \cond BLAZE_INTERNAL */
1154 /*!\brief Returns an iterator to the first non-zero element of row/column \a i.
1155 //
1156 // \param i The row/column index.
1157 // \return Iterator to the first non-zero element of row/column \a i.
1158 //
1159 // This function returns a row/column iterator to the first non-zero element of row/column \a i.
1160 // In case the storage order is set to \a rowMajor the function returns an iterator to the first
1161 // non-zero element of row \a i, in case the storage flag is set to \a columnMajor the function
1162 // returns an iterator to the first non-zero element of column \a i.
1163 */
1164 template< typename MT       // Type of the dense matrix
1165         , size_t... CSAs >  // Compile time submatrix arguments
1166 inline typename Submatrix<MT,unaligned,false,true,CSAs...>::ConstIterator
cbegin(size_t i)1167    Submatrix<MT,unaligned,false,true,CSAs...>::cbegin( size_t i ) const
1168 {
1169    BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
1170    return ConstIterator( matrix_.cbegin( row() + i ) + column(), isAligned_ );
1171 }
1172 /*! \endcond */
1173 //*************************************************************************************************
1174 
1175 
1176 //*************************************************************************************************
1177 /*! \cond BLAZE_INTERNAL */
1178 /*!\brief Returns an iterator just past the last non-zero element of row/column \a i.
1179 //
1180 // \param i The row/column index.
1181 // \return Iterator just past the last non-zero element of row/column \a i.
1182 //
1183 // This function returns an row/column iterator just past the last non-zero element of row/column
1184 // \a i. In case the storage order is set to \a rowMajor the function returns an iterator just
1185 // past the last non-zero element of row \a i, in case the storage flag is set to \a columnMajor
1186 // the function returns an iterator just past the last non-zero element of column \a i.
1187 */
1188 template< typename MT       // Type of the dense matrix
1189         , size_t... CSAs >  // Compile time submatrix arguments
1190 inline typename Submatrix<MT,unaligned,false,true,CSAs...>::Iterator
end(size_t i)1191    Submatrix<MT,unaligned,false,true,CSAs...>::end( size_t i )
1192 {
1193    BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
1194    return Iterator( matrix_.begin( row() + i ) + column() + columns(), isAligned_ );
1195 }
1196 /*! \endcond */
1197 //*************************************************************************************************
1198 
1199 
1200 //*************************************************************************************************
1201 /*! \cond BLAZE_INTERNAL */
1202 /*!\brief Returns an iterator just past the last non-zero element of row/column \a i.
1203 //
1204 // \param i The row/column index.
1205 // \return Iterator just past the last non-zero element of row/column \a i.
1206 //
1207 // This function returns an row/column iterator just past the last non-zero element of row/column
1208 // \a i. In case the storage order is set to \a rowMajor the function returns an iterator just
1209 // past the last non-zero element of row \a i, in case the storage flag is set to \a columnMajor
1210 // the function returns an iterator just past the last non-zero element of column \a i.
1211 */
1212 template< typename MT       // Type of the dense matrix
1213         , size_t... CSAs >  // Compile time submatrix arguments
1214 inline typename Submatrix<MT,unaligned,false,true,CSAs...>::ConstIterator
end(size_t i)1215    Submatrix<MT,unaligned,false,true,CSAs...>::end( size_t i ) const
1216 {
1217    BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
1218    return ConstIterator( matrix_.cbegin( row() + i ) + column() + columns(), isAligned_ );
1219 }
1220 /*! \endcond */
1221 //*************************************************************************************************
1222 
1223 
1224 //*************************************************************************************************
1225 /*! \cond BLAZE_INTERNAL */
1226 /*!\brief Returns an iterator just past the last non-zero element of row/column \a i.
1227 //
1228 // \param i The row/column index.
1229 // \return Iterator just past the last non-zero element of row/column \a i.
1230 //
1231 // This function returns an row/column iterator just past the last non-zero element of row/column
1232 // \a i. In case the storage order is set to \a rowMajor the function returns an iterator just
1233 // past the last non-zero element of row \a i, in case the storage flag is set to \a columnMajor
1234 // the function returns an iterator just past the last non-zero element of column \a i.
1235 */
1236 template< typename MT       // Type of the dense matrix
1237         , size_t... CSAs >  // Compile time submatrix arguments
1238 inline typename Submatrix<MT,unaligned,false,true,CSAs...>::ConstIterator
cend(size_t i)1239    Submatrix<MT,unaligned,false,true,CSAs...>::cend( size_t i ) const
1240 {
1241    BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
1242    return ConstIterator( matrix_.cbegin( row() + i ) + column() + columns(), isAligned_ );
1243 }
1244 /*! \endcond */
1245 //*************************************************************************************************
1246 
1247 
1248 
1249 
1250 //=================================================================================================
1251 //
1252 //  ASSIGNMENT OPERATORS
1253 //
1254 //=================================================================================================
1255 
1256 //*************************************************************************************************
1257 /*! \cond BLAZE_INTERNAL */
1258 /*!\brief Homogenous assignment to all submatrix elements.
1259 //
1260 // \param rhs Scalar value to be assigned to all submatrix elements.
1261 // \return Reference to the assigned submatrix.
1262 //
1263 // This function homogeneously assigns the given value to all dense matrix elements. Note that in
1264 // case the underlying dense matrix is a lower/upper matrix only lower/upper and diagonal elements
1265 // of the underlying matrix are modified.
1266 */
1267 template< typename MT       // Type of the dense matrix
1268         , size_t... CSAs >  // Compile time submatrix arguments
1269 inline Submatrix<MT,unaligned,false,true,CSAs...>&
1270    Submatrix<MT,unaligned,false,true,CSAs...>::operator=( const ElementType& rhs )
1271 {
1272    const size_t iend( row() + rows() );
1273    decltype(auto) left( derestrict( matrix_ ) );
1274 
1275    for( size_t i=row(); i<iend; ++i )
1276    {
1277       const size_t jbegin( ( IsUpper_v<MT> )
1278                            ?( ( IsUniUpper_v<MT> || IsStrictlyUpper_v<MT> )
1279                               ?( max( i+1UL, column() ) )
1280                               :( max( i, column() ) ) )
1281                            :( column() ) );
1282       const size_t jend  ( ( IsLower_v<MT> )
1283                            ?( ( IsUniLower_v<MT> || IsStrictlyLower_v<MT> )
1284                               ?( min( i, column()+columns() ) )
1285                               :( min( i+1UL, column()+columns() ) ) )
1286                            :( column()+columns() ) );
1287 
1288       for( size_t j=jbegin; j<jend; ++j ) {
1289          if( !IsRestricted_v<MT> || IsTriangular_v<MT> || trySet( matrix_, i, j, rhs ) )
1290             left(i,j) = rhs;
1291       }
1292    }
1293 
1294    return *this;
1295 }
1296 /*! \endcond */
1297 //*************************************************************************************************
1298 
1299 
1300 //*************************************************************************************************
1301 /*! \cond BLAZE_INTERNAL */
1302 /*!\brief List assignment to all submatrix elements.
1303 //
1304 // \param list The initializer list.
1305 // \exception std::invalid_argument Invalid initializer list dimension.
1306 // \exception std::invalid_argument Invalid assignment to restricted matrix.
1307 //
1308 // This assignment operator offers the option to directly assign to all elements of the submatrix
1309 // by means of an initializer list. The submatrix elements are assigned the values from the given
1310 // initializer list. Missing values are initialized as default. Note that in case the size of the
1311 // top-level initializer list does not match the number of rows of the submatrix or the size of
1312 // any nested list exceeds the number of columns, a \a std::invalid_argument exception is thrown.
1313 // Also, if the underlying matrix \a MT is restricted and the assignment would violate an
1314 // invariant of the matrix, a \a std::invalid_argument exception is thrown.
1315 */
1316 template< typename MT       // Type of the dense matrix
1317         , size_t... CSAs >  // Compile time submatrix arguments
1318 inline Submatrix<MT,unaligned,false,true,CSAs...>&
1319    Submatrix<MT,unaligned,false,true,CSAs...>::operator=( initializer_list< initializer_list<ElementType> > list )
1320 {
1321    if( list.size() != rows() ) {
1322       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to submatrix" );
1323    }
1324 
1325    if( IsRestricted_v<MT> ) {
1326       const InitializerMatrix<ElementType> tmp( list, columns() );
1327       if( !tryAssign( matrix_, tmp, row(), column() ) ) {
1328          BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1329       }
1330    }
1331 
1332    decltype(auto) left( derestrict( *this ) );
1333    size_t i( 0UL );
1334 
1335    for( const auto& rowList : list ) {
1336       std::fill( std::copy( rowList.begin(), rowList.end(), left.begin(i) ), left.end(i), ElementType() );
1337       ++i;
1338    }
1339 
1340    return *this;
1341 }
1342 /*! \endcond */
1343 //*************************************************************************************************
1344 
1345 
1346 //*************************************************************************************************
1347 /*! \cond BLAZE_INTERNAL */
1348 /*!\brief Copy assignment operator for Submatrix.
1349 //
1350 // \param rhs Dense submatrix to be copied.
1351 // \return Reference to the assigned submatrix.
1352 // \exception std::invalid_argument Submatrix sizes do not match.
1353 // \exception std::invalid_argument Invalid assignment to restricted matrix.
1354 //
1355 // The dense submatrix is initialized as a copy of the given dense submatrix. In case the current
1356 // sizes of the two submatrices don't match, a \a std::invalid_argument exception is thrown. Also,
1357 // if the underlying matrix \a MT is a lower triangular, upper triangular, or symmetric matrix
1358 // and the assignment would violate its lower, upper, or symmetry property, respectively, a
1359 // \a std::invalid_argument exception is thrown.
1360 */
1361 template< typename MT       // Type of the dense matrix
1362         , size_t... CSAs >  // Compile time submatrix arguments
1363 inline Submatrix<MT,unaligned,false,true,CSAs...>&
1364    Submatrix<MT,unaligned,false,true,CSAs...>::operator=( const Submatrix& rhs )
1365 {
1366    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
1367    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
1368 
1369    if( this == &rhs || ( &matrix_ == &rhs.matrix_ && row() == rhs.row() && column() == rhs.column() ) )
1370       return *this;
1371 
1372    if( rows() != rhs.rows() || columns() != rhs.columns() ) {
1373       BLAZE_THROW_INVALID_ARGUMENT( "Submatrix sizes do not match" );
1374    }
1375 
1376    if( !tryAssign( matrix_, rhs, row(), column() ) ) {
1377       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1378    }
1379 
1380    decltype(auto) left( derestrict( *this ) );
1381 
1382    if( rhs.canAlias( this ) ) {
1383       const ResultType tmp( rhs );
1384       smpAssign( left, tmp );
1385    }
1386    else {
1387       smpAssign( left, rhs );
1388    }
1389 
1390    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1391 
1392    return *this;
1393 }
1394 /*! \endcond */
1395 //*************************************************************************************************
1396 
1397 
1398 //*************************************************************************************************
1399 /*! \cond BLAZE_INTERNAL */
1400 /*!\brief Assignment operator for different matrices.
1401 //
1402 // \param rhs Matrix to be assigned.
1403 // \return Reference to the assigned submatrix.
1404 // \exception std::invalid_argument Matrix sizes do not match.
1405 // \exception std::invalid_argument Invalid assignment to restricted matrix.
1406 //
1407 // The dense submatrix is initialized as a copy of the given matrix. In case the current sizes
1408 // of the two matrices don't match, a \a std::invalid_argument exception is thrown. Also, if
1409 // the underlying matrix \a MT is a lower triangular, upper triangular, or symmetric matrix
1410 // and the assignment would violate its lower, upper, or symmetry property, respectively, a
1411 // \a std::invalid_argument exception is thrown.
1412 */
1413 template< typename MT       // Type of the dense matrix
1414         , size_t... CSAs >  // Compile time submatrix arguments
1415 template< typename MT2      // Type of the right-hand side matrix
1416         , bool SO2 >        // Storage order of the right-hand side matrix
1417 inline Submatrix<MT,unaligned,false,true,CSAs...>&
1418    Submatrix<MT,unaligned,false,true,CSAs...>::operator=( const Matrix<MT2,SO2>& rhs )
1419 {
1420    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
1421 
1422    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
1423       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1424    }
1425 
1426    using Right = If_t< IsRestricted_v<MT>, CompositeType_t<MT2>, const MT2& >;
1427    Right right( *rhs );
1428 
1429    if( !tryAssign( matrix_, right, row(), column() ) ) {
1430       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1431    }
1432 
1433    decltype(auto) left( derestrict( *this ) );
1434 
1435    if( IsReference_v<Right> && right.canAlias( this ) ) {
1436       const ResultType_t<MT2> tmp( right );
1437       if( IsSparseMatrix_v<MT2> )
1438          reset();
1439       smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
1440    }
1441    else {
1442       if( IsSparseMatrix_v<MT2> )
1443          reset();
1444       smpAssign( left, transIf< IsSymmetric_v<This> >( right ) );
1445    }
1446 
1447    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1448 
1449    return *this;
1450 }
1451 /*! \endcond */
1452 //*************************************************************************************************
1453 
1454 
1455 //*************************************************************************************************
1456 /*! \cond BLAZE_INTERNAL */
1457 /*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
1458 //
1459 // \param rhs The right-hand side matrix to be added to the submatrix.
1460 // \return Reference to the dense submatrix.
1461 // \exception std::invalid_argument Matrix sizes do not match.
1462 // \exception std::invalid_argument Invalid assignment to restricted matrix.
1463 //
1464 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
1465 // is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
1466 // symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
1467 // respectively, a \a std::invalid_argument exception is thrown.
1468 */
1469 template< typename MT       // Type of the dense matrix
1470         , size_t... CSAs >  // Compile time submatrix arguments
1471 template< typename MT2      // Type of the right-hand side matrix
1472         , bool SO2 >        // Storage order of the right-hand side matrix
1473 inline auto Submatrix<MT,unaligned,false,true,CSAs...>::operator+=( const Matrix<MT2,SO2>& rhs )
1474    -> DisableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >
1475 {
1476    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
1477    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
1478    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
1479 
1480    using AddType = AddTrait_t< ResultType, ResultType_t<MT2> >;
1481 
1482    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( AddType );
1483    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
1484 
1485    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
1486       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1487    }
1488 
1489    if( !tryAddAssign( matrix_, *rhs, row(), column() ) ) {
1490       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1491    }
1492 
1493    decltype(auto) left( derestrict( *this ) );
1494 
1495    if( ( ( IsSymmetric_v<MT> || IsHermitian_v<MT> ) && hasOverlap() ) || (*rhs).canAlias( this ) ) {
1496       const AddType tmp( *this + (*rhs) );
1497       smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
1498    }
1499    else {
1500       smpAddAssign( left, transIf< IsSymmetric_v<This> >( *rhs ) );
1501    }
1502 
1503    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1504 
1505    return *this;
1506 }
1507 /*! \endcond */
1508 //*************************************************************************************************
1509 
1510 
1511 //*************************************************************************************************
1512 /*! \cond BLAZE_INTERNAL */
1513 /*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
1514 //
1515 // \param rhs The right-hand side matrix to be added to the submatrix.
1516 // \return Reference to the dense submatrix.
1517 // \exception std::invalid_argument Matrix sizes do not match.
1518 // \exception std::invalid_argument Invalid assignment to restricted matrix.
1519 //
1520 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
1521 // is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
1522 // symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
1523 // respectively, a \a std::invalid_argument exception is thrown.
1524 */
1525 template< typename MT       // Type of the dense matrix
1526         , size_t... CSAs >  // Compile time submatrix arguments
1527 template< typename MT2      // Type of the right-hand side matrix
1528         , bool SO2 >        // Storage order of the right-hand side matrix
1529 inline auto Submatrix<MT,unaligned,false,true,CSAs...>::operator+=( const Matrix<MT2,SO2>& rhs )
1530    -> EnableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >
1531 {
1532    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
1533    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
1534    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
1535 
1536    using AddType = AddTrait_t< ResultType, ResultType_t<MT2> >;
1537 
1538    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( AddType );
1539    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
1540 
1541    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
1542       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1543    }
1544 
1545    const AddType tmp( *this + (*rhs) );
1546 
1547    if( !tryAssign( matrix_, tmp, row(), column() ) ) {
1548       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1549    }
1550 
1551    decltype(auto) left( derestrict( *this ) );
1552 
1553    smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
1554 
1555    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1556 
1557    return *this;
1558 }
1559 /*! \endcond */
1560 //*************************************************************************************************
1561 
1562 
1563 //*************************************************************************************************
1564 /*! \cond BLAZE_INTERNAL */
1565 /*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
1566 //
1567 // \param rhs The right-hand side matrix to be subtracted from the submatrix.
1568 // \return Reference to the dense submatrix.
1569 // \exception std::invalid_argument Matrix sizes do not match.
1570 // \exception std::invalid_argument Invalid assignment to restricted matrix.
1571 //
1572 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
1573 // is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
1574 // symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
1575 // respectively, a \a std::invalid_argument exception is thrown.
1576 */
1577 template< typename MT       // Type of the dense matrix
1578         , size_t... CSAs >  // Compile time submatrix arguments
1579 template< typename MT2      // Type of the right-hand side matrix
1580         , bool SO2 >        // Storage order of the right-hand side matrix
1581 inline auto Submatrix<MT,unaligned,false,true,CSAs...>::operator-=( const Matrix<MT2,SO2>& rhs )
1582    -> DisableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >
1583 {
1584    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
1585    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
1586    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
1587 
1588    using SubType = SubTrait_t< ResultType, ResultType_t<MT2> >;
1589 
1590    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( SubType );
1591    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
1592 
1593    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
1594       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1595    }
1596 
1597    if( !trySubAssign( matrix_, *rhs, row(), column() ) ) {
1598       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1599    }
1600 
1601    decltype(auto) left( derestrict( *this ) );
1602 
1603    if( ( ( IsSymmetric_v<MT> || IsHermitian_v<MT> ) && hasOverlap() ) || (*rhs).canAlias( this ) ) {
1604       const SubType tmp( *this - (*rhs ) );
1605       smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
1606    }
1607    else {
1608       smpSubAssign( left, transIf< IsSymmetric_v<This> >( *rhs ) );
1609    }
1610 
1611    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1612 
1613    return *this;
1614 }
1615 /*! \endcond */
1616 //*************************************************************************************************
1617 
1618 
1619 //*************************************************************************************************
1620 /*! \cond BLAZE_INTERNAL */
1621 /*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
1622 //
1623 // \param rhs The right-hand side matrix to be subtracted from the submatrix.
1624 // \return Reference to the dense submatrix.
1625 // \exception std::invalid_argument Matrix sizes do not match.
1626 // \exception std::invalid_argument Invalid assignment to restricted matrix.
1627 //
1628 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
1629 // is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
1630 // symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
1631 // respectively, a \a std::invalid_argument exception is thrown.
1632 */
1633 template< typename MT       // Type of the dense matrix
1634         , size_t... CSAs >  // Compile time submatrix arguments
1635 template< typename MT2      // Type of the right-hand side matrix
1636         , bool SO2 >        // Storage order of the right-hand side matrix
1637 inline auto Submatrix<MT,unaligned,false,true,CSAs...>::operator-=( const Matrix<MT2,SO2>& rhs )
1638    -> EnableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >
1639 {
1640    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
1641    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
1642    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
1643 
1644    using SubType = SubTrait_t< ResultType, ResultType_t<MT2> >;
1645 
1646    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( SubType );
1647    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
1648 
1649    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
1650       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1651    }
1652 
1653    const SubType tmp( *this - (*rhs) );
1654 
1655    if( !tryAssign( matrix_, tmp, row(), column() ) ) {
1656       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1657    }
1658 
1659    decltype(auto) left( derestrict( *this ) );
1660 
1661    smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
1662 
1663    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1664 
1665    return *this;
1666 }
1667 /*! \endcond */
1668 //*************************************************************************************************
1669 
1670 
1671 //*************************************************************************************************
1672 /*! \cond BLAZE_INTERNAL */
1673 /*!\brief Schur product assignment operator for the multiplication of a matrix (\f$ A=B \f$).
1674 //
1675 // \param rhs The right-hand side matrix for the Schur product.
1676 // \return Reference to the dense submatrix.
1677 // \exception std::invalid_argument Matrix sizes do not match.
1678 // \exception std::invalid_argument Invalid assignment to restricted matrix.
1679 //
1680 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
1681 // is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
1682 // symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
1683 // respectively, a \a std::invalid_argument exception is thrown.
1684 */
1685 template< typename MT       // Type of the dense matrix
1686         , size_t... CSAs >  // Compile time submatrix arguments
1687 template< typename MT2      // Type of the right-hand side matrix
1688         , bool SO2 >        // Storage order of the right-hand side matrix
1689 inline auto Submatrix<MT,unaligned,false,true,CSAs...>::operator%=( const Matrix<MT2,SO2>& rhs )
1690    -> DisableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >
1691 {
1692    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
1693    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
1694    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
1695 
1696    using SchurType = SchurTrait_t< ResultType, ResultType_t<MT2> >;
1697 
1698    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SchurType );
1699 
1700    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
1701       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1702    }
1703 
1704    if( !trySchurAssign( matrix_, *rhs, row(), column() ) ) {
1705       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1706    }
1707 
1708    decltype(auto) left( derestrict( *this ) );
1709 
1710    if( ( ( IsSymmetric_v<MT> || IsHermitian_v<MT> ) && hasOverlap() ) || (*rhs).canAlias( this ) ) {
1711       const SchurType tmp( *this % (*rhs) );
1712       if( IsSparseMatrix_v<SchurType> )
1713          reset();
1714       smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
1715    }
1716    else {
1717       smpSchurAssign( left, transIf< IsSymmetric_v<This> >( *rhs ) );
1718    }
1719 
1720    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1721 
1722    return *this;
1723 }
1724 /*! \endcond */
1725 //*************************************************************************************************
1726 
1727 
1728 //*************************************************************************************************
1729 /*! \cond BLAZE_INTERNAL */
1730 /*!\brief Schur product assignment operator for the multiplication of a matrix (\f$ A=B \f$).
1731 //
1732 // \param rhs The right-hand side matrix for the Schur product.
1733 // \return Reference to the dense submatrix.
1734 // \exception std::invalid_argument Matrix sizes do not match.
1735 // \exception std::invalid_argument Invalid assignment to restricted matrix.
1736 //
1737 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
1738 // is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
1739 // symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
1740 // respectively, a \a std::invalid_argument exception is thrown.
1741 */
1742 template< typename MT       // Type of the dense matrix
1743         , size_t... CSAs >  // Compile time submatrix arguments
1744 template< typename MT2      // Type of the right-hand side matrix
1745         , bool SO2 >        // Storage order of the right-hand side matrix
1746 inline auto Submatrix<MT,unaligned,false,true,CSAs...>::operator%=( const Matrix<MT2,SO2>& rhs )
1747    -> EnableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >
1748 {
1749    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
1750    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
1751    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
1752 
1753    using SchurType = SchurTrait_t< ResultType, ResultType_t<MT2> >;
1754 
1755    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SchurType );
1756 
1757    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
1758       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1759    }
1760 
1761    const SchurType tmp( *this % (*rhs) );
1762 
1763    if( !tryAssign( matrix_, tmp, row(), column() ) ) {
1764       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
1765    }
1766 
1767    decltype(auto) left( derestrict( *this ) );
1768 
1769    if( IsSparseMatrix_v<SchurType> ) {
1770       reset();
1771    }
1772 
1773    smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
1774 
1775    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
1776 
1777    return *this;
1778 }
1779 /*! \endcond */
1780 //*************************************************************************************************
1781 
1782 
1783 
1784 
1785 //=================================================================================================
1786 //
1787 //  UTILITY FUNCTIONS
1788 //
1789 //=================================================================================================
1790 
1791 //*************************************************************************************************
1792 /*! \cond BLAZE_INTERNAL */
1793 /*!\brief Returns the matrix containing the submatrix.
1794 //
1795 // \return The matrix containing the submatrix.
1796 */
1797 template< typename MT       // Type of the dense matrix
1798         , size_t... CSAs >  // Compile time submatrix arguments
operand()1799 inline MT& Submatrix<MT,unaligned,false,true,CSAs...>::operand() noexcept
1800 {
1801    return matrix_;
1802 }
1803 /*! \endcond */
1804 //*************************************************************************************************
1805 
1806 
1807 //*************************************************************************************************
1808 /*! \cond BLAZE_INTERNAL */
1809 /*!\brief Returns the matrix containing the submatrix.
1810 //
1811 // \return The matrix containing the submatrix.
1812 */
1813 template< typename MT       // Type of the dense matrix
1814         , size_t... CSAs >  // Compile time submatrix arguments
operand()1815 inline const MT& Submatrix<MT,unaligned,false,true,CSAs...>::operand() const noexcept
1816 {
1817    return matrix_;
1818 }
1819 /*! \endcond */
1820 //*************************************************************************************************
1821 
1822 
1823 //*************************************************************************************************
1824 /*! \cond BLAZE_INTERNAL */
1825 /*!\brief Returns the spacing between the beginning of two rows/columns.
1826 //
1827 // \return The spacing between the beginning of two rows/columns.
1828 //
1829 // This function returns the spacing between the beginning of two rows/columns, i.e. the
1830 // total number of elements of a row/column. In case the storage order is set to \a rowMajor
1831 // the function returns the spacing between two rows, in case the storage flag is set to
1832 // \a columnMajor the function returns the spacing between two columns.
1833 */
1834 template< typename MT       // Type of the dense matrix
1835         , size_t... CSAs >  // Compile time submatrix arguments
spacing()1836 inline size_t Submatrix<MT,unaligned,false,true,CSAs...>::spacing() const noexcept
1837 {
1838    return matrix_.spacing();
1839 }
1840 /*! \endcond */
1841 //*************************************************************************************************
1842 
1843 
1844 //*************************************************************************************************
1845 /*! \cond BLAZE_INTERNAL */
1846 /*!\brief Returns the maximum capacity of the dense submatrix.
1847 //
1848 // \return The capacity of the dense submatrix.
1849 */
1850 template< typename MT       // Type of the dense matrix
1851         , size_t... CSAs >  // Compile time submatrix arguments
capacity()1852 inline size_t Submatrix<MT,unaligned,false,true,CSAs...>::capacity() const noexcept
1853 {
1854    return rows() * columns();
1855 }
1856 /*! \endcond */
1857 //*************************************************************************************************
1858 
1859 
1860 //*************************************************************************************************
1861 /*! \cond BLAZE_INTERNAL */
1862 /*!\brief Returns the current capacity of the specified row/column.
1863 //
1864 // \param i The index of the row/column.
1865 // \return The current capacity of row/column \a i.
1866 //
1867 // This function returns the current capacity of the specified row/column. In case the
1868 // storage order is set to \a rowMajor the function returns the capacity of row \a i,
1869 // in case the storage flag is set to \a columnMajor the function returns the capacity
1870 // of column \a i.
1871 */
1872 template< typename MT       // Type of the dense matrix
1873         , size_t... CSAs >  // Compile time submatrix arguments
capacity(size_t i)1874 inline size_t Submatrix<MT,unaligned,false,true,CSAs...>::capacity( size_t i ) const noexcept
1875 {
1876    MAYBE_UNUSED( i );
1877 
1878    BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
1879 
1880    return columns();
1881 }
1882 /*! \endcond */
1883 //*************************************************************************************************
1884 
1885 
1886 //*************************************************************************************************
1887 /*! \cond BLAZE_INTERNAL */
1888 /*!\brief Returns the number of non-zero elements in the dense submatrix
1889 //
1890 // \return The number of non-zero elements in the dense submatrix.
1891 */
1892 template< typename MT       // Type of the dense matrix
1893         , size_t... CSAs >  // Compile time submatrix arguments
nonZeros()1894 inline size_t Submatrix<MT,unaligned,false,true,CSAs...>::nonZeros() const
1895 {
1896    const size_t iend( row() + rows() );
1897    const size_t jend( column() + columns() );
1898    size_t nonzeros( 0UL );
1899 
1900    for( size_t i=row(); i<iend; ++i )
1901       for( size_t j=column(); j<jend; ++j )
1902          if( !isDefault( matrix_(i,j) ) )
1903             ++nonzeros;
1904 
1905    return nonzeros;
1906 }
1907 /*! \endcond */
1908 //*************************************************************************************************
1909 
1910 
1911 //*************************************************************************************************
1912 /*! \cond BLAZE_INTERNAL */
1913 /*!\brief Returns the number of non-zero elements in the specified row/column.
1914 //
1915 // \param i The index of the row/column.
1916 // \return The number of non-zero elements of row/column \a i.
1917 //
1918 // This function returns the current number of non-zero elements in the specified row/column.
1919 // In case the storage order is set to \a rowMajor the function returns the number of non-zero
1920 // elements in row \a i, in case the storage flag is set to \a columnMajor the function returns
1921 // the number of non-zero elements in column \a i.
1922 */
1923 template< typename MT       // Type of the dense matrix
1924         , size_t... CSAs >  // Compile time submatrix arguments
nonZeros(size_t i)1925 inline size_t Submatrix<MT,unaligned,false,true,CSAs...>::nonZeros( size_t i ) const
1926 {
1927    BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
1928 
1929    const size_t jend( column() + columns() );
1930    size_t nonzeros( 0UL );
1931 
1932    for( size_t j=column(); j<jend; ++j )
1933       if( !isDefault( matrix_(row()+i,j) ) )
1934          ++nonzeros;
1935 
1936    return nonzeros;
1937 }
1938 /*! \endcond */
1939 //*************************************************************************************************
1940 
1941 
1942 //*************************************************************************************************
1943 /*! \cond BLAZE_INTERNAL */
1944 /*!\brief Reset to the default initial values.
1945 //
1946 // \return void
1947 */
1948 template< typename MT       // Type of the dense matrix
1949         , size_t... CSAs >  // Compile time submatrix arguments
reset()1950 inline void Submatrix<MT,unaligned,false,true,CSAs...>::reset()
1951 {
1952    using blaze::clear;
1953 
1954    for( size_t i=row(); i<row()+rows(); ++i )
1955    {
1956       const size_t jbegin( ( IsUpper_v<MT> )
1957                            ?( ( IsUniUpper_v<MT> || IsStrictlyUpper_v<MT> )
1958                               ?( max( i+1UL, column() ) )
1959                               :( max( i, column() ) ) )
1960                            :( column() ) );
1961       const size_t jend  ( ( IsLower_v<MT> )
1962                            ?( ( IsUniLower_v<MT> || IsStrictlyLower_v<MT> )
1963                               ?( min( i, column()+columns() ) )
1964                               :( min( i+1UL, column()+columns() ) ) )
1965                            :( column()+columns() ) );
1966 
1967       for( size_t j=jbegin; j<jend; ++j )
1968          clear( matrix_(i,j) );
1969    }
1970 }
1971 /*! \endcond */
1972 //*************************************************************************************************
1973 
1974 
1975 //*************************************************************************************************
1976 /*! \cond BLAZE_INTERNAL */
1977 /*!\brief Reset the specified row/column to the default initial values.
1978 //
1979 // \param i The index of the row/column.
1980 // \return void
1981 //
1982 // This function resets the values in the specified row/column to their default value. In case
1983 // the storage order is set to \a rowMajor the function resets the values in row \a i, in case
1984 // the storage order is set to \a columnMajor the function resets the values in column \a i.
1985 // Note that the capacity of the row/column remains unchanged.
1986 */
1987 template< typename MT       // Type of the dense matrix
1988         , size_t... CSAs >  // Compile time submatrix arguments
reset(size_t i)1989 inline void Submatrix<MT,unaligned,false,true,CSAs...>::reset( size_t i )
1990 {
1991    using blaze::clear;
1992 
1993    BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
1994 
1995    const size_t jbegin( ( IsUpper_v<MT> )
1996                         ?( ( IsUniUpper_v<MT> || IsStrictlyUpper_v<MT> )
1997                            ?( max( i+1UL, column() ) )
1998                            :( max( i, column() ) ) )
1999                         :( column() ) );
2000    const size_t jend  ( ( IsLower_v<MT> )
2001                         ?( ( IsUniLower_v<MT> || IsStrictlyLower_v<MT> )
2002                            ?( min( i, column()+columns() ) )
2003                            :( min( i+1UL, column()+columns() ) ) )
2004                         :( column()+columns() ) );
2005 
2006    for( size_t j=jbegin; j<jend; ++j )
2007       clear( matrix_(row()+i,j) );
2008 }
2009 /*! \endcond */
2010 //*************************************************************************************************
2011 
2012 
2013 //*************************************************************************************************
2014 /*! \cond BLAZE_INTERNAL */
2015 /*!\brief Checking whether there exists an overlap in the context of a symmetric matrix.
2016 //
2017 // \return \a true in case an overlap exists, \a false if not.
2018 //
2019 // This function checks if in the context of a symmetric matrix the submatrix has an overlap with
2020 // its counterpart. In case an overlap exists, the function return \a true, otherwise it returns
2021 // \a false.
2022 */
2023 template< typename MT       // Type of the dense matrix
2024         , size_t... CSAs >  // Compile time submatrix arguments
hasOverlap()2025 inline bool Submatrix<MT,unaligned,false,true,CSAs...>::hasOverlap() const noexcept
2026 {
2027    BLAZE_INTERNAL_ASSERT( IsSymmetric_v<MT> || IsHermitian_v<MT>, "Invalid matrix detected" );
2028 
2029    if( ( row() + rows() <= column() ) || ( column() + columns() <= row() ) )
2030       return false;
2031    else return true;
2032 }
2033 /*! \endcond */
2034 //*************************************************************************************************
2035 
2036 
2037 
2038 
2039 //=================================================================================================
2040 //
2041 //  NUMERIC FUNCTIONS
2042 //
2043 //=================================================================================================
2044 
2045 //*************************************************************************************************
2046 /*! \cond BLAZE_INTERNAL */
2047 /*!\brief In-place transpose of the submatrix.
2048 //
2049 // \return Reference to the transposed submatrix.
2050 // \exception std::logic_error Invalid transpose of a non-quadratic submatrix.
2051 // \exception std::logic_error Invalid transpose operation.
2052 //
2053 // This function transposes the dense submatrix in-place. Note that this function can only be used
2054 // for quadratic submatrices, i.e. if the number of rows is equal to the number of columns. Also,
2055 // the function fails if ...
2056 //
2057 //  - ... the submatrix contains elements from the upper part of the underlying lower matrix;
2058 //  - ... the submatrix contains elements from the lower part of the underlying upper matrix;
2059 //  - ... the result would be non-deterministic in case of a symmetric or Hermitian matrix.
2060 //
2061 // In all cases, a \a std::logic_error is thrown.
2062 */
2063 template< typename MT       // Type of the dense matrix
2064         , size_t... CSAs >  // Compile time submatrix arguments
2065 inline Submatrix<MT,unaligned,false,true,CSAs...>&
transpose()2066    Submatrix<MT,unaligned,false,true,CSAs...>::transpose()
2067 {
2068    if( rows() != columns() ) {
2069       BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
2070    }
2071 
2072    if( !tryAssign( matrix_, trans( *this ), row(), column() ) ) {
2073       BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
2074    }
2075 
2076    decltype(auto) left( derestrict( *this ) );
2077    const ResultType tmp( trans( *this ) );
2078 
2079    smpAssign( left, tmp );
2080 
2081    return *this;
2082 }
2083 /*! \endcond */
2084 //*************************************************************************************************
2085 
2086 
2087 //*************************************************************************************************
2088 /*! \cond BLAZE_INTERNAL */
2089 /*!\brief In-place conjugate transpose of the submatrix.
2090 //
2091 // \return Reference to the transposed submatrix.
2092 // \exception std::logic_error Invalid transpose of a non-quadratic submatrix.
2093 // \exception std::logic_error Invalid transpose operation.
2094 //
2095 // This function transposes the dense submatrix in-place. Note that this function can only be used
2096 // for quadratic submatrices, i.e. if the number of rows is equal to the number of columns. Also,
2097 // the function fails if ...
2098 //
2099 //  - ... the submatrix contains elements from the upper part of the underlying lower matrix;
2100 //  - ... the submatrix contains elements from the lower part of the underlying upper matrix;
2101 //  - ... the result would be non-deterministic in case of a symmetric or Hermitian matrix.
2102 //
2103 // In all cases, a \a std::logic_error is thrown.
2104 */
2105 template< typename MT       // Type of the dense matrix
2106         , size_t... CSAs >  // Compile time submatrix arguments
2107 inline Submatrix<MT,unaligned,false,true,CSAs...>&
ctranspose()2108    Submatrix<MT,unaligned,false,true,CSAs...>::ctranspose()
2109 {
2110    if( rows() != columns() ) {
2111       BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
2112    }
2113 
2114    if( !tryAssign( matrix_, ctrans( *this ), row(), column() ) ) {
2115       BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
2116    }
2117 
2118    decltype(auto) left( derestrict( *this ) );
2119    const ResultType tmp( ctrans( *this ) );
2120 
2121    smpAssign( left, tmp );
2122 
2123    return *this;
2124 }
2125 /*! \endcond */
2126 //*************************************************************************************************
2127 
2128 
2129 //*************************************************************************************************
2130 /*! \cond BLAZE_INTERNAL */
2131 /*!\brief Scaling of the dense submatrix by the scalar value \a scalar (\f$ A=B*s \f$).
2132 //
2133 // \param scalar The scalar value for the submatrix scaling.
2134 // \return Reference to the dense submatrix.
2135 //
2136 // This function scales the submatrix by applying the given scalar value \a scalar to each
2137 // element of the submatrix. For built-in and \c complex data types it has the same effect
2138 // as using the multiplication assignment operator. Note that the function cannot be used
2139 // to scale a submatrix on a lower or upper unitriangular matrix. The attempt to scale
2140 // such a submatrix results in a compile time error!
2141 */
2142 template< typename MT       // Type of the dense matrix
2143         , size_t... CSAs >  // Compile time submatrix arguments
2144 template< typename Other >  // Data type of the scalar value
2145 inline Submatrix<MT,unaligned,false,true,CSAs...>&
scale(const Other & scalar)2146    Submatrix<MT,unaligned,false,true,CSAs...>::scale( const Other& scalar )
2147 {
2148    BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
2149 
2150    const size_t iend( row() + rows() );
2151 
2152    for( size_t i=row(); i<iend; ++i )
2153    {
2154       const size_t jbegin( ( IsUpper_v<MT> )
2155                            ?( ( IsStrictlyUpper_v<MT> )
2156                               ?( max( i+1UL, column() ) )
2157                               :( max( i, column() ) ) )
2158                            :( column() ) );
2159       const size_t jend  ( ( IsLower_v<MT> )
2160                            ?( ( IsStrictlyLower_v<MT> )
2161                               ?( min( i, column()+columns() ) )
2162                               :( min( i+1UL, column()+columns() ) ) )
2163                            :( column()+columns() ) );
2164 
2165       for( size_t j=jbegin; j<jend; ++j )
2166          matrix_(i,j) *= scalar;
2167    }
2168 
2169    return *this;
2170 }
2171 /*! \endcond */
2172 //*************************************************************************************************
2173 
2174 
2175 
2176 
2177 //=================================================================================================
2178 //
2179 //  EXPRESSION TEMPLATE EVALUATION FUNCTIONS
2180 //
2181 //=================================================================================================
2182 
2183 //*************************************************************************************************
2184 /*! \cond BLAZE_INTERNAL */
2185 /*!\brief Returns whether the submatrix can alias with the given address \a alias.
2186 //
2187 // \param alias The alias to be checked.
2188 // \return \a true in case the alias corresponds to this submatrix, \a false if not.
2189 //
2190 // This function returns whether the given address can alias with the submatrix. In contrast
2191 // to the isAliased() function this function is allowed to use compile time expressions to
2192 // optimize the evaluation.
2193 */
2194 template< typename MT       // Type of the dense matrix
2195         , size_t... CSAs >  // Compile time submatrix arguments
2196 template< typename Other >  // Data type of the foreign expression
canAlias(const Other * alias)2197 inline bool Submatrix<MT,unaligned,false,true,CSAs...>::canAlias( const Other* alias ) const noexcept
2198 {
2199    return matrix_.isAliased( &unview( *alias ) );
2200 }
2201 /*! \endcond */
2202 //*************************************************************************************************
2203 
2204 
2205 //*************************************************************************************************
2206 /*! \cond BLAZE_INTERNAL */
2207 /*!\brief Returns whether the submatrix can alias with the given dense submatrix \a alias.
2208 //
2209 // \param alias The alias to be checked.
2210 // \return \a true in case the alias corresponds to this submatrix, \a false if not.
2211 //
2212 // This function returns whether the given address can alias with the submatrix. In contrast
2213 // to the isAliased() function this function is allowed to use compile time expressions to
2214 // optimize the evaluation.
2215 */
2216 template< typename MT        // Type of the dense matrix
2217         , size_t... CSAs >   // Compile time submatrix arguments
2218 template< typename MT2       // Data type of the foreign dense submatrix
2219         , AlignmentFlag AF2  // Alignment flag of the foreign dense submatrix
2220         , bool SO2           // Storage order of the foreign dense submatrix
2221         , size_t... CSAs2 >  // Compile time submatrix arguments of the foreign dense submatrix
2222 inline bool
canAlias(const Submatrix<MT2,AF2,SO2,true,CSAs2...> * alias)2223    Submatrix<MT,unaligned,false,true,CSAs...>::canAlias( const Submatrix<MT2,AF2,SO2,true,CSAs2...>* alias ) const noexcept
2224 {
2225    return ( matrix_.isAliased( &alias->matrix_ ) &&
2226             ( row() + rows() > alias->row() ) &&
2227             ( row() < alias->row() + alias->rows() ) &&
2228             ( column() + columns() > alias->column() ) &&
2229             ( column() < alias->column() + alias->columns() ) );
2230 }
2231 /*! \endcond */
2232 //*************************************************************************************************
2233 
2234 
2235 //*************************************************************************************************
2236 /*! \cond BLAZE_INTERNAL */
2237 /*!\brief Returns whether the submatrix is aliased with the given address \a alias.
2238 //
2239 // \param alias The alias to be checked.
2240 // \return \a true in case the alias corresponds to this submatrix, \a false if not.
2241 //
2242 // This function returns whether the given address is aliased with the submatrix. In contrast
2243 // to the canAlias() function this function is not allowed to use compile time expressions to
2244 // optimize the evaluation.
2245 */
2246 template< typename MT       // Type of the dense matrix
2247         , size_t... CSAs >  // Compile time submatrix arguments
2248 template< typename Other >  // Data type of the foreign expression
isAliased(const Other * alias)2249 inline bool Submatrix<MT,unaligned,false,true,CSAs...>::isAliased( const Other* alias ) const noexcept
2250 {
2251    return matrix_.isAliased( &unview( *alias ) );
2252 }
2253 /*! \endcond */
2254 //*************************************************************************************************
2255 
2256 
2257 //*************************************************************************************************
2258 /*! \cond BLAZE_INTERNAL */
2259 /*!\brief Returns whether the submatrix is aliased with the given dense submatrix \a alias.
2260 //
2261 // \param alias The alias to be checked.
2262 // \return \a true in case the alias corresponds to this submatrix, \a false if not.
2263 //
2264 // This function returns whether the given address is aliased with the submatrix. In contrast
2265 // to the canAlias() function this function is not allowed to use compile time expressions to
2266 // optimize the evaluation.
2267 */
2268 template< typename MT        // Type of the dense matrix
2269         , size_t... CSAs >   // Compile time submatrix arguments
2270 template< typename MT2       // Data type of the foreign dense submatrix
2271         , AlignmentFlag AF2  // Alignment flag of the foreign dense submatrix
2272         , bool SO2           // Storage order of the foreign dense submatrix
2273         , size_t... CSAs2 >  // Compile time submatrix arguments of the foreign dense submatrix
2274 inline bool
isAliased(const Submatrix<MT2,AF2,SO2,true,CSAs2...> * alias)2275    Submatrix<MT,unaligned,false,true,CSAs...>::isAliased( const Submatrix<MT2,AF2,SO2,true,CSAs2...>* alias ) const noexcept
2276 {
2277    return ( matrix_.isAliased( &alias->matrix_ ) &&
2278             ( row() + rows() > alias->row() ) &&
2279             ( row() < alias->row() + alias->rows() ) &&
2280             ( column() + columns() > alias->column() ) &&
2281             ( column() < alias->column() + alias->columns() ) );
2282 }
2283 /*! \endcond */
2284 //*************************************************************************************************
2285 
2286 
2287 //*************************************************************************************************
2288 /*! \cond BLAZE_INTERNAL */
2289 /*!\brief Returns whether the submatrix is properly aligned in memory.
2290 //
2291 // \return \a true in case the submatrix is aligned, \a false if not.
2292 //
2293 // This function returns whether the submatrix is guaranteed to be properly aligned in memory,
2294 // i.e. whether the beginning and the end of each row/column of the submatrix are guaranteed to
2295 // conform to the alignment restrictions of the underlying element type.
2296 */
2297 template< typename MT       // Type of the dense matrix
2298         , size_t... CSAs >  // Compile time submatrix arguments
isAligned()2299 inline bool Submatrix<MT,unaligned,false,true,CSAs...>::isAligned() const noexcept
2300 {
2301    return isAligned_;
2302 }
2303 /*! \endcond */
2304 //*************************************************************************************************
2305 
2306 
2307 //*************************************************************************************************
2308 /*! \cond BLAZE_INTERNAL */
2309 /*!\brief Returns whether the submatrix can be used in SMP assignments.
2310 //
2311 // \return \a true in case the submatrix can be used in SMP assignments, \a false if not.
2312 //
2313 // This function returns whether the submatrix can be used in SMP assignments. In contrast to the
2314 // \a smpAssignable member enumeration, which is based solely on compile time information, this
2315 // function additionally provides runtime information (as for instance the current number of
2316 // rows and/or columns of the submatrix).
2317 */
2318 template< typename MT       // Type of the dense matrix
2319         , size_t... CSAs >  // Compile time submatrix arguments
canSMPAssign()2320 inline bool Submatrix<MT,unaligned,false,true,CSAs...>::canSMPAssign() const noexcept
2321 {
2322    return ( rows() * columns() >= SMP_DMATASSIGN_THRESHOLD );
2323 }
2324 /*! \endcond */
2325 //*************************************************************************************************
2326 
2327 
2328 //*************************************************************************************************
2329 /*! \cond BLAZE_INTERNAL */
2330 /*!\brief Load of a SIMD element of the submatrix.
2331 //
2332 // \param i Access index for the row. The index has to be in the range [0..M-1].
2333 // \param j Access index for the column. The index has to be in the range [0..N-1].
2334 // \return The loaded SIMD element.
2335 //
2336 // This function performs a load of a specific SIMD element of the dense submatrix. The row
2337 // index must be smaller than the number of rows and the column index must be smaller than
2338 // the number of columns. Additionally, the column index (in case of a row-major matrix) or
2339 // the row index (in case of a column-major matrix) must be a multiple of the number of
2340 // values inside the SIMD element. This function must \b NOT be called explicitly! It is
2341 // used internally for the performance optimized evaluation of expression templates. Calling
2342 // this function explicitly might result in erroneous results and/or in compilation errors.
2343 */
2344 template< typename MT       // Type of the dense matrix
2345         , size_t... CSAs >  // Compile time submatrix arguments
2346 BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,false,true,CSAs...>::SIMDType
load(size_t i,size_t j)2347    Submatrix<MT,unaligned,false,true,CSAs...>::load( size_t i, size_t j ) const noexcept
2348 {
2349    if( isAligned_ )
2350       return loada( i, j );
2351    else
2352       return loadu( i, j );
2353 }
2354 /*! \endcond */
2355 //*************************************************************************************************
2356 
2357 
2358 //*************************************************************************************************
2359 /*! \cond BLAZE_INTERNAL */
2360 /*!\brief Aligned load of a SIMD element of the submatrix.
2361 //
2362 // \param i Access index for the row. The index has to be in the range [0..M-1].
2363 // \param j Access index for the column. The index has to be in the range [0..N-1].
2364 // \return The loaded SIMD element.
2365 //
2366 // This function performs an aligned load of a specific SIMD element of the dense submatrix.
2367 // The row index must be smaller than the number of rows and the column index must be smaller
2368 // than the number of columns. Additionally, the column index (in case of a row-major matrix)
2369 // or the row index (in case of a column-major matrix) must be a multiple of the number of
2370 // values inside the SIMD element. This function must \b NOT be called explicitly! It is used
2371 // internally for the performance optimized evaluation of expression templates. Calling this
2372 // function explicitly might result in erroneous results and/or in compilation errors.
2373 */
2374 template< typename MT       // Type of the dense matrix
2375         , size_t... CSAs >  // Compile time submatrix arguments
2376 BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,false,true,CSAs...>::SIMDType
loada(size_t i,size_t j)2377    Submatrix<MT,unaligned,false,true,CSAs...>::loada( size_t i, size_t j ) const noexcept
2378 {
2379    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
2380 
2381    BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
2382    BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
2383    BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
2384    BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
2385 
2386    return matrix_.loada( row()+i, column()+j );
2387 }
2388 /*! \endcond */
2389 //*************************************************************************************************
2390 
2391 
2392 //*************************************************************************************************
2393 /*! \cond BLAZE_INTERNAL */
2394 /*!\brief Unaligned load of a SIMD element of the submatrix.
2395 //
2396 // \param i Access index for the row. The index has to be in the range [0..M-1].
2397 // \param j Access index for the column. The index has to be in the range [0..N-1].
2398 // \return The loaded SIMD element.
2399 //
2400 // This function performs an unaligned load of a specific SIMD element of the dense submatrix.
2401 // The row index must be smaller than the number of rows and the column index must be smaller
2402 // than the number of columns. Additionally, the column index (in case of a row-major matrix)
2403 // or the row index (in case of a column-major matrix) must be a multiple of the number of
2404 // values inside the SIMD element. This function must \b NOT be called explicitly! It is used
2405 // internally for the performance optimized evaluation of expression templates. Calling this
2406 // function explicitly might result in erroneous results and/or in compilation errors.
2407 */
2408 template< typename MT       // Type of the dense matrix
2409         , size_t... CSAs >  // Compile time submatrix arguments
2410 BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,false,true,CSAs...>::SIMDType
loadu(size_t i,size_t j)2411    Submatrix<MT,unaligned,false,true,CSAs...>::loadu( size_t i, size_t j ) const noexcept
2412 {
2413    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
2414 
2415    BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
2416    BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
2417    BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
2418 
2419    return matrix_.loadu( row()+i, column()+j );
2420 }
2421 /*! \endcond */
2422 //*************************************************************************************************
2423 
2424 
2425 //*************************************************************************************************
2426 /*! \cond BLAZE_INTERNAL */
2427 /*!\brief Store of a SIMD element of the submatrix.
2428 //
2429 // \param i Access index for the row. The index has to be in the range [0..M-1].
2430 // \param j Access index for the column. The index has to be in the range [0..N-1].
2431 // \param value The SIMD element to be stored.
2432 // \return void
2433 //
2434 // This function performs a store of a specific SIMD element of the dense submatrix. The row
2435 // index must be smaller than the number of rows and the column index must be smaller than the
2436 // number of columns. Additionally, the column index (in case of a row-major matrix) or the row
2437 // index (in case of a column-major matrix) must be a multiple of the number of values inside
2438 // the SIMD element. This function must \b NOT be called explicitly! It is used internally
2439 // for the performance optimized evaluation of expression templates. Calling this function
2440 // explicitly might result in erroneous results and/or in compilation errors.
2441 */
2442 template< typename MT       // Type of the dense matrix
2443         , size_t... CSAs >  // Compile time submatrix arguments
2444 BLAZE_ALWAYS_INLINE void
store(size_t i,size_t j,const SIMDType & value)2445    Submatrix<MT,unaligned,false,true,CSAs...>::store( size_t i, size_t j, const SIMDType& value ) noexcept
2446 {
2447    if( isAligned_ )
2448       storea( i, j, value );
2449    else
2450       storeu( i, j, value );
2451 }
2452 /*! \endcond */
2453 //*************************************************************************************************
2454 
2455 
2456 //*************************************************************************************************
2457 /*! \cond BLAZE_INTERNAL */
2458 /*!\brief Aligned store of a SIMD element of the submatrix.
2459 //
2460 // \param i Access index for the row. The index has to be in the range [0..M-1].
2461 // \param j Access index for the column. The index has to be in the range [0..N-1].
2462 // \param value The SIMD element to be stored.
2463 // \return void
2464 //
2465 // This function performs an aligned store of a specific SIMD element of the dense submatrix.
2466 // The row index must be smaller than the number of rows and the column index must be smaller
2467 // than the number of columns. Additionally, the column index (in case of a row-major matrix)
2468 // or the row index (in case of a column-major matrix) must be a multiple of the number of
2469 // values inside the SIMD element. This function must \b NOT be called explicitly! It is used
2470 // internally for the performance optimized evaluation of expression templates. Calling this
2471 // function explicitly might result in erroneous results and/or in compilation errors.
2472 */
2473 template< typename MT       // Type of the dense matrix
2474         , size_t... CSAs >  // Compile time submatrix arguments
2475 BLAZE_ALWAYS_INLINE void
storea(size_t i,size_t j,const SIMDType & value)2476    Submatrix<MT,unaligned,false,true,CSAs...>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
2477 {
2478    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
2479 
2480    BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
2481    BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
2482    BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
2483    BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
2484 
2485    matrix_.storea( row()+i, column()+j, value );
2486 }
2487 /*! \endcond */
2488 //*************************************************************************************************
2489 
2490 
2491 //*************************************************************************************************
2492 /*! \cond BLAZE_INTERNAL */
2493 /*!\brief Unaligned store of a SIMD element of the submatrix.
2494 //
2495 // \param i Access index for the row. The index has to be in the range [0..M-1].
2496 // \param j Access index for the column. The index has to be in the range [0..N-1].
2497 // \param value The SIMD element to be stored.
2498 // \return void
2499 //
2500 // This function performs an unaligned store of a specific SIMD element of the dense submatrix.
2501 // The row index must be smaller than the number of rows and the column index must be smaller
2502 // than the number of columns. Additionally, the column index (in case of a row-major matrix)
2503 // or the row index (in case of a column-major matrix) must be a multiple of the number of
2504 // values inside the SIMD element. This function must \b NOT be called explicitly! It is used
2505 // internally for the performance optimized evaluation of expression templates. Calling this
2506 // function explicitly might result in erroneous results and/or in compilation errors.
2507 */
2508 template< typename MT       // Type of the dense matrix
2509         , size_t... CSAs >  // Compile time submatrix arguments
2510 BLAZE_ALWAYS_INLINE void
storeu(size_t i,size_t j,const SIMDType & value)2511    Submatrix<MT,unaligned,false,true,CSAs...>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
2512 {
2513    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
2514 
2515    BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
2516    BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
2517    BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
2518 
2519    matrix_.storeu( row()+i, column()+j, value );
2520 }
2521 /*! \endcond */
2522 //*************************************************************************************************
2523 
2524 
2525 //*************************************************************************************************
2526 /*! \cond BLAZE_INTERNAL */
2527 /*!\brief Aligned, non-temporal store of a SIMD element of the submatrix.
2528 //
2529 // \param i Access index for the row. The index has to be in the range [0..M-1].
2530 // \param j Access index for the column. The index has to be in the range [0..N-1].
2531 // \param value The SIMD element to be stored.
2532 // \return void
2533 //
2534 // This function performs an aligned, non-temporal store of a specific SIMD element of the dense
2535 // submatrix. The row index must be smaller than the number of rows and the column index must be
2536 // smaller than the number of columns. Additionally, the column index (in case of a row-major
2537 // matrix) or the row index (in case of a column-major matrix) must be a multiple of the number
2538 // of values inside the SIMD element. This function must \b NOT be called explicitly! It is used
2539 // internally for the performance optimized evaluation of expression templates. Calling this
2540 // function explicitly might result in erroneous results and/or in compilation errors.
2541 */
2542 template< typename MT       // Type of the dense matrix
2543         , size_t... CSAs >  // Compile time submatrix arguments
2544 BLAZE_ALWAYS_INLINE void
stream(size_t i,size_t j,const SIMDType & value)2545    Submatrix<MT,unaligned,false,true,CSAs...>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
2546 {
2547    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
2548 
2549    BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
2550    BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
2551    BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
2552    BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
2553 
2554    if( isAligned_ )
2555       matrix_.stream( row()+i, column()+j, value );
2556    else
2557       matrix_.storeu( row()+i, column()+j, value );
2558 }
2559 /*! \endcond */
2560 //*************************************************************************************************
2561 
2562 
2563 //*************************************************************************************************
2564 /*! \cond BLAZE_INTERNAL */
2565 /*!\brief Default implementation of the assignment of a row-major dense matrix.
2566 //
2567 // \param rhs The right-hand side dense matrix to be assigned.
2568 // \return void
2569 //
2570 // This function must \b NOT be called explicitly! It is used internally for the performance
2571 // optimized evaluation of expression templates. Calling this function explicitly might result
2572 // in erroneous results and/or in compilation errors. Instead of using this function use the
2573 // assignment operator.
2574 */
2575 template< typename MT       // Type of the dense matrix
2576         , size_t... CSAs >  // Compile time submatrix arguments
2577 template< typename MT2 >    // Type of the right-hand side dense matrix
2578 inline auto Submatrix<MT,unaligned,false,true,CSAs...>::assign( const DenseMatrix<MT2,false>& rhs )
2579    -> DisableIf_t< VectorizedAssign_v<MT2> >
2580 {
2581    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
2582    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
2583 
2584    const size_t jpos( prevMultiple( columns(), 2UL ) );
2585    BLAZE_INTERNAL_ASSERT( jpos <= columns(), "Invalid end calculation" );
2586 
2587    for( size_t i=0UL; i<rows(); ++i ) {
2588       for( size_t j=0UL; j<jpos; j+=2UL ) {
2589          matrix_(row()+i,column()+j    ) = (*rhs)(i,j    );
2590          matrix_(row()+i,column()+j+1UL) = (*rhs)(i,j+1UL);
2591       }
2592       if( jpos < columns() ) {
2593          matrix_(row()+i,column()+jpos) = (*rhs)(i,jpos);
2594       }
2595    }
2596 }
2597 /*! \endcond */
2598 //*************************************************************************************************
2599 
2600 
2601 //*************************************************************************************************
2602 /*! \cond BLAZE_INTERNAL */
2603 /*!\brief SIMD optimized implementation of the assignment of a row-major dense matrix.
2604 //
2605 // \param rhs The right-hand side dense matrix to be assigned.
2606 // \return void
2607 //
2608 // This function must \b NOT be called explicitly! It is used internally for the performance
2609 // optimized evaluation of expression templates. Calling this function explicitly might result
2610 // in erroneous results and/or in compilation errors. Instead of using this function use the
2611 // assignment operator.
2612 */
2613 template< typename MT       // Type of the dense matrix
2614         , size_t... CSAs >  // Compile time submatrix arguments
2615 template< typename MT2 >    // Type of the right-hand side dense matrix
2616 inline auto Submatrix<MT,unaligned,false,true,CSAs...>::assign( const DenseMatrix<MT2,false>& rhs )
2617    -> EnableIf_t< VectorizedAssign_v<MT2> >
2618 {
2619    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
2620 
2621    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
2622    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
2623 
2624    const size_t jpos( prevMultiple( columns(), SIMDSIZE ) );
2625    BLAZE_INTERNAL_ASSERT( jpos <= columns(), "Invalid end calculation" );
2626 
2627    if( useStreaming && isAligned_ &&
2628        rows()*columns() > ( cacheSize / ( sizeof(ElementType) * 3UL ) ) &&
2629        !(*rhs).isAliased( this ) )
2630    {
2631       for( size_t i=0UL; i<rows(); ++i )
2632       {
2633          size_t j( 0UL );
2634          Iterator left( begin(i) );
2635          ConstIterator_t<MT2> right( (*rhs).begin(i) );
2636 
2637          for( ; j<jpos; j+=SIMDSIZE ) {
2638             left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2639          }
2640          for( ; j<columns(); ++j ) {
2641             *left = *right; ++left; ++right;
2642          }
2643       }
2644    }
2645    else
2646    {
2647       for( size_t i=0UL; i<rows(); ++i )
2648       {
2649          size_t j( 0UL );
2650          Iterator left( begin(i) );
2651          ConstIterator_t<MT2> right( (*rhs).begin(i) );
2652 
2653          for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
2654             left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2655             left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2656             left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2657             left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2658          }
2659          for( ; j<jpos; j+=SIMDSIZE ) {
2660             left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2661          }
2662          for( ; j<columns(); ++j ) {
2663             *left = *right; ++left; ++right;
2664          }
2665       }
2666    }
2667 }
2668 /*! \endcond */
2669 //*************************************************************************************************
2670 
2671 
2672 //*************************************************************************************************
2673 /*! \cond BLAZE_INTERNAL */
2674 /*!\brief Default implementation of the assignment of a column-major dense matrix.
2675 //
2676 // \param rhs The right-hand side dense matrix to be assigned.
2677 // \return void
2678 //
2679 // This function must \b NOT be called explicitly! It is used internally for the performance
2680 // optimized evaluation of expression templates. Calling this function explicitly might result
2681 // in erroneous results and/or in compilation errors. Instead of using this function use the
2682 // assignment operator.
2683 */
2684 template< typename MT       // Type of the dense matrix
2685         , size_t... CSAs >  // Compile time submatrix arguments
2686 template< typename MT2 >    // Type of the right-hand side dense matrix
assign(const DenseMatrix<MT2,true> & rhs)2687 inline void Submatrix<MT,unaligned,false,true,CSAs...>::assign( const DenseMatrix<MT2,true>& rhs )
2688 {
2689    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
2690 
2691    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
2692    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
2693 
2694    constexpr size_t block( BLOCK_SIZE );
2695 
2696    for( size_t ii=0UL; ii<rows(); ii+=block ) {
2697       const size_t iend( ( rows()<(ii+block) )?( rows() ):( ii+block ) );
2698       for( size_t jj=0UL; jj<columns(); jj+=block ) {
2699          const size_t jend( ( columns()<(jj+block) )?( columns() ):( jj+block ) );
2700          for( size_t i=ii; i<iend; ++i ) {
2701             for( size_t j=jj; j<jend; ++j ) {
2702                matrix_(row()+i,column()+j) = (*rhs)(i,j);
2703             }
2704          }
2705       }
2706    }
2707 }
2708 /*! \endcond */
2709 //*************************************************************************************************
2710 
2711 
2712 //*************************************************************************************************
2713 /*! \cond BLAZE_INTERNAL */
2714 /*!\brief Default implementation of the assignment of a row-major sparse matrix.
2715 //
2716 // \param rhs The right-hand side sparse matrix to be assigned.
2717 // \return void
2718 //
2719 // This function must \b NOT be called explicitly! It is used internally for the performance
2720 // optimized evaluation of expression templates. Calling this function explicitly might result
2721 // in erroneous results and/or in compilation errors. Instead of using this function use the
2722 // assignment operator.
2723 */
2724 template< typename MT       // Type of the dense matrix
2725         , size_t... CSAs >  // Compile time submatrix arguments
2726 template< typename MT2 >    // Type of the right-hand side sparse matrix
assign(const SparseMatrix<MT2,false> & rhs)2727 inline void Submatrix<MT,unaligned,false,true,CSAs...>::assign( const SparseMatrix<MT2,false>& rhs )
2728 {
2729    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
2730    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
2731 
2732    for( size_t i=0UL; i<rows(); ++i )
2733       for( ConstIterator_t<MT2> element=(*rhs).begin(i); element!=(*rhs).end(i); ++element )
2734          matrix_(row()+i,column()+element->index()) = element->value();
2735 }
2736 /*! \endcond */
2737 //*************************************************************************************************
2738 
2739 
2740 //*************************************************************************************************
2741 /*! \cond BLAZE_INTERNAL */
2742 /*!\brief Default implementation of the assignment of a column-major sparse matrix.
2743 //
2744 // \param rhs The right-hand side sparse matrix to be assigned.
2745 // \return void
2746 //
2747 // This function must \b NOT be called explicitly! It is used internally for the performance
2748 // optimized evaluation of expression templates. Calling this function explicitly might result
2749 // in erroneous results and/or in compilation errors. Instead of using this function use the
2750 // assignment operator.
2751 */
2752 template< typename MT       // Type of the dense matrix
2753         , size_t... CSAs >  // Compile time submatrix arguments
2754 template< typename MT2 >    // Type of the right-hand side sparse matrix
assign(const SparseMatrix<MT2,true> & rhs)2755 inline void Submatrix<MT,unaligned,false,true,CSAs...>::assign( const SparseMatrix<MT2,true>& rhs )
2756 {
2757    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
2758 
2759    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
2760    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
2761 
2762    for( size_t j=0UL; j<columns(); ++j )
2763       for( ConstIterator_t<MT2> element=(*rhs).begin(j); element!=(*rhs).end(j); ++element )
2764          matrix_(row()+element->index(),column()+j) = element->value();
2765 }
2766 /*! \endcond */
2767 //*************************************************************************************************
2768 
2769 
2770 //*************************************************************************************************
2771 /*! \cond BLAZE_INTERNAL */
2772 /*!\brief Default implementation of the addition assignment of a row-major dense matrix.
2773 //
2774 // \param rhs The right-hand side dense matrix to be added.
2775 // \return void
2776 //
2777 // This function must \b NOT be called explicitly! It is used internally for the performance
2778 // optimized evaluation of expression templates. Calling this function explicitly might result
2779 // in erroneous results and/or in compilation errors. Instead of using this function use the
2780 // assignment operator.
2781 */
2782 template< typename MT       // Type of the dense matrix
2783         , size_t... CSAs >  // Compile time submatrix arguments
2784 template< typename MT2 >    // Type of the right-hand side dense matrix
2785 inline auto Submatrix<MT,unaligned,false,true,CSAs...>::addAssign( const DenseMatrix<MT2,false>& rhs )
2786    -> DisableIf_t< VectorizedAddAssign_v<MT2> >
2787 {
2788    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
2789    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
2790 
2791    const size_t jpos( prevMultiple( columns(), 2UL ) );
2792    BLAZE_INTERNAL_ASSERT( jpos <= columns(), "Invalid end calculation" );
2793 
2794    for( size_t i=0UL; i<rows(); ++i )
2795    {
2796       if( IsDiagonal_v<MT2> ) {
2797          matrix_(row()+i,column()+i) += (*rhs)(i,i);
2798       }
2799       else {
2800          for( size_t j=0UL; j<jpos; j+=2UL ) {
2801             matrix_(row()+i,column()+j    ) += (*rhs)(i,j    );
2802             matrix_(row()+i,column()+j+1UL) += (*rhs)(i,j+1UL);
2803          }
2804          if( jpos < columns() ) {
2805             matrix_(row()+i,column()+jpos) += (*rhs)(i,jpos);
2806          }
2807       }
2808    }
2809 }
2810 /*! \endcond */
2811 //*************************************************************************************************
2812 
2813 
2814 //*************************************************************************************************
2815 /*! \cond BLAZE_INTERNAL */
2816 /*!\brief SIMD optimized implementation of the addition assignment of a row-major dense matrix.
2817 //
2818 // \param rhs The right-hand side dense matrix to be added.
2819 // \return void
2820 //
2821 // This function must \b NOT be called explicitly! It is used internally for the performance
2822 // optimized evaluation of expression templates. Calling this function explicitly might result
2823 // in erroneous results and/or in compilation errors. Instead of using this function use the
2824 // assignment operator.
2825 */
2826 template< typename MT       // Type of the dense matrix
2827         , size_t... CSAs >  // Compile time submatrix arguments
2828 template< typename MT2 >    // Type of the right-hand side dense matrix
2829 inline auto Submatrix<MT,unaligned,false,true,CSAs...>::addAssign( const DenseMatrix<MT2,false>& rhs )
2830    -> EnableIf_t< VectorizedAddAssign_v<MT2> >
2831 {
2832    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
2833 
2834    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
2835    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
2836 
2837    for( size_t i=0UL; i<rows(); ++i )
2838    {
2839       const size_t jbegin( ( IsUpper_v<MT2> )
2840                            ?( prevMultiple( ( IsStrictlyUpper_v<MT2> ? i+1UL : i ), SIMDSIZE ) )
2841                            :( 0UL ) );
2842       const size_t jend  ( ( IsLower_v<MT2> )
2843                            ?( IsStrictlyLower_v<MT2> ? i : i+1UL )
2844                            :( columns() ) );
2845       BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
2846 
2847       const size_t jpos( prevMultiple( jend, SIMDSIZE ) );
2848       BLAZE_INTERNAL_ASSERT( jpos <= jend, "Invalid end calculation" );
2849 
2850       size_t j( jbegin );
2851       Iterator left( begin(i) + jbegin );
2852       ConstIterator_t<MT2> right( (*rhs).begin(i) + jbegin );
2853 
2854       for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
2855          left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2856          left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2857          left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2858          left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2859       }
2860       for( ; j<jpos; j+=SIMDSIZE ) {
2861          left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2862       }
2863       for( ; j<jend; ++j ) {
2864          *left += *right; ++left; ++right;
2865       }
2866    }
2867 }
2868 /*! \endcond */
2869 //*************************************************************************************************
2870 
2871 
2872 //*************************************************************************************************
2873 /*! \cond BLAZE_INTERNAL */
2874 /*!\brief Default implementation of the addition assignment of a column-major dense matrix.
2875 //
2876 // \param rhs The right-hand side dense matrix to be added.
2877 // \return void
2878 //
2879 // This function must \b NOT be called explicitly! It is used internally for the performance
2880 // optimized evaluation of expression templates. Calling this function explicitly might result
2881 // in erroneous results and/or in compilation errors. Instead of using this function use the
2882 // assignment operator.
2883 */
2884 template< typename MT       // Type of the dense matrix
2885         , size_t... CSAs >  // Compile time submatrix arguments
2886 template< typename MT2 >    // Type of the right-hand side dense matrix
addAssign(const DenseMatrix<MT2,true> & rhs)2887 inline void Submatrix<MT,unaligned,false,true,CSAs...>::addAssign( const DenseMatrix<MT2,true>& rhs )
2888 {
2889    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
2890 
2891    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
2892    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
2893 
2894    constexpr size_t block( BLOCK_SIZE );
2895 
2896    for( size_t ii=0UL; ii<rows(); ii+=block ) {
2897       const size_t iend( ( rows()<(ii+block) )?( rows() ):( ii+block ) );
2898       for( size_t jj=0UL; jj<columns(); jj+=block ) {
2899          const size_t jend( ( columns()<(jj+block) )?( columns() ):( jj+block ) );
2900          for( size_t i=ii; i<iend; ++i ) {
2901             for( size_t j=jj; j<jend; ++j ) {
2902                matrix_(row()+i,column()+j) += (*rhs)(i,j);
2903             }
2904          }
2905       }
2906    }
2907 }
2908 /*! \endcond */
2909 //*************************************************************************************************
2910 
2911 
2912 //*************************************************************************************************
2913 /*! \cond BLAZE_INTERNAL */
2914 /*!\brief Default implementation of the addition assignment of a row-major sparse matrix.
2915 //
2916 // \param rhs The right-hand side sparse matrix to be added.
2917 // \return void
2918 //
2919 // This function must \b NOT be called explicitly! It is used internally for the performance
2920 // optimized evaluation of expression templates. Calling this function explicitly might result
2921 // in erroneous results and/or in compilation errors. Instead of using this function use the
2922 // assignment operator.
2923 */
2924 template< typename MT       // Type of the dense matrix
2925         , size_t... CSAs >  // Compile time submatrix arguments
2926 template< typename MT2 >    // Type of the right-hand side sparse matrix
addAssign(const SparseMatrix<MT2,false> & rhs)2927 inline void Submatrix<MT,unaligned,false,true,CSAs...>::addAssign( const SparseMatrix<MT2,false>& rhs )
2928 {
2929    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
2930    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
2931 
2932    for( size_t i=0UL; i<rows(); ++i )
2933       for( ConstIterator_t<MT2> element=(*rhs).begin(i); element!=(*rhs).end(i); ++element )
2934          matrix_(row()+i,column()+element->index()) += element->value();
2935 }
2936 /*! \endcond */
2937 //*************************************************************************************************
2938 
2939 
2940 //*************************************************************************************************
2941 /*! \cond BLAZE_INTERNAL */
2942 /*!\brief Default implementation of the addition assignment of a column-major sparse matrix.
2943 //
2944 // \param rhs The right-hand side sparse matrix to be added.
2945 // \return void
2946 //
2947 // This function must \b NOT be called explicitly! It is used internally for the performance
2948 // optimized evaluation of expression templates. Calling this function explicitly might result
2949 // in erroneous results and/or in compilation errors. Instead of using this function use the
2950 // assignment operator.
2951 */
2952 template< typename MT       // Type of the dense matrix
2953         , size_t... CSAs >  // Compile time submatrix arguments
2954 template< typename MT2 >    // Type of the right-hand side sparse matrix
addAssign(const SparseMatrix<MT2,true> & rhs)2955 inline void Submatrix<MT,unaligned,false,true,CSAs...>::addAssign( const SparseMatrix<MT2,true>& rhs )
2956 {
2957    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
2958 
2959    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
2960    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
2961 
2962    for( size_t j=0UL; j<columns(); ++j )
2963       for( ConstIterator_t<MT2> element=(*rhs).begin(j); element!=(*rhs).end(j); ++element )
2964          matrix_(row()+element->index(),column()+j) += element->value();
2965 }
2966 /*! \endcond */
2967 //*************************************************************************************************
2968 
2969 
2970 //*************************************************************************************************
2971 /*! \cond BLAZE_INTERNAL */
2972 /*!\brief Default implementation of the subtraction assignment of a row-major dense matrix.
2973 //
2974 // \param rhs The right-hand side dense matrix to be subtracted.
2975 // \return void
2976 //
2977 // This function must \b NOT be called explicitly! It is used internally for the performance
2978 // optimized evaluation of expression templates. Calling this function explicitly might result
2979 // in erroneous results and/or in compilation errors. Instead of using this function use the
2980 // assignment operator.
2981 */
2982 template< typename MT       // Type of the dense matrix
2983         , size_t... CSAs >  // Compile time submatrix arguments
2984 template< typename MT2 >    // Type of the right-hand side dense matrix
2985 inline auto Submatrix<MT,unaligned,false,true,CSAs...>::subAssign( const DenseMatrix<MT2,false>& rhs )
2986    -> DisableIf_t< VectorizedSubAssign_v<MT2> >
2987 {
2988    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
2989    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
2990 
2991    const size_t jpos( prevMultiple( columns(), 2UL ) );
2992    BLAZE_INTERNAL_ASSERT( jpos <= columns(), "Invalid end calculation" );
2993 
2994    for( size_t i=0UL; i<rows(); ++i )
2995    {
2996       if( IsDiagonal_v<MT2> ) {
2997          matrix_(row()+i,column()+i) -= (*rhs)(i,i);
2998       }
2999       else {
3000          for( size_t j=0UL; j<jpos; j+=2UL ) {
3001             matrix_(row()+i,column()+j    ) -= (*rhs)(i,j    );
3002             matrix_(row()+i,column()+j+1UL) -= (*rhs)(i,j+1UL);
3003          }
3004          if( jpos < columns() ) {
3005             matrix_(row()+i,column()+jpos) -= (*rhs)(i,jpos);
3006          }
3007       }
3008    }
3009 }
3010 /*! \endcond */
3011 //*************************************************************************************************
3012 
3013 
3014 //*************************************************************************************************
3015 /*! \cond BLAZE_INTERNAL */
3016 /*!\brief SIMD optimized implementation of the subtraction assignment of a row-major dense matrix.
3017 //
3018 // \param rhs The right-hand side dense matrix to be subtracted.
3019 // \return void
3020 //
3021 // This function must \b NOT be called explicitly! It is used internally for the performance
3022 // optimized evaluation of expression templates. Calling this function explicitly might result
3023 // in erroneous results and/or in compilation errors. Instead of using this function use the
3024 // assignment operator.
3025 */
3026 template< typename MT       // Type of the dense matrix
3027         , size_t... CSAs >  // Compile time submatrix arguments
3028 template< typename MT2 >    // Type of the right-hand side dense matrix
3029 inline auto Submatrix<MT,unaligned,false,true,CSAs...>::subAssign( const DenseMatrix<MT2,false>& rhs )
3030    -> EnableIf_t< VectorizedSubAssign_v<MT2> >
3031 {
3032    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
3033 
3034    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
3035    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
3036 
3037    for( size_t i=0UL; i<rows(); ++i )
3038    {
3039       const size_t jbegin( ( IsUpper_v<MT2> )
3040                            ?( prevMultiple( ( IsStrictlyUpper_v<MT2> ? i+1UL : i ), SIMDSIZE ) )
3041                            :( 0UL ) );
3042       const size_t jend  ( ( IsLower_v<MT2> )
3043                            ?( IsStrictlyLower_v<MT2> ? i : i+1UL )
3044                            :( columns() ) );
3045       BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
3046 
3047       const size_t jpos( prevMultiple( jend, SIMDSIZE ) );
3048       BLAZE_INTERNAL_ASSERT( jpos <= jend, "Invalid end calculation" );
3049 
3050       size_t j( jbegin );
3051       Iterator left( begin(i) + jbegin );
3052       ConstIterator_t<MT2> right( (*rhs).begin(i) + jbegin );
3053 
3054       for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
3055          left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3056          left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3057          left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3058          left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3059       }
3060       for( ; j<jpos; j+=SIMDSIZE ) {
3061          left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3062       }
3063       for( ; j<jend; ++j ) {
3064          *left -= *right; ++left; ++right;
3065       }
3066    }
3067 }
3068 /*! \endcond */
3069 //*************************************************************************************************
3070 
3071 
3072 //*************************************************************************************************
3073 /*! \cond BLAZE_INTERNAL */
3074 /*!\brief Default implementation of the subtraction assignment of a column-major dense matrix.
3075 //
3076 // \param rhs The right-hand side dense matrix to be subtracted.
3077 // \return void
3078 //
3079 // This function must \b NOT be called explicitly! It is used internally for the performance
3080 // optimized evaluation of expression templates. Calling this function explicitly might result
3081 // in erroneous results and/or in compilation errors. Instead of using this function use the
3082 // assignment operator.
3083 */
3084 template< typename MT       // Type of the dense matrix
3085         , size_t... CSAs >  // Compile time submatrix arguments
3086 template< typename MT2 >    // Type of the right-hand side dense matrix
subAssign(const DenseMatrix<MT2,true> & rhs)3087 inline void Submatrix<MT,unaligned,false,true,CSAs...>::subAssign( const DenseMatrix<MT2,true>& rhs )
3088 {
3089    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
3090 
3091    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
3092    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
3093 
3094    constexpr size_t block( BLOCK_SIZE );
3095 
3096    for( size_t ii=0UL; ii<rows(); ii+=block ) {
3097       const size_t iend( ( rows()<(ii+block) )?( rows() ):( ii+block ) );
3098       for( size_t jj=0UL; jj<columns(); jj+=block ) {
3099          const size_t jend( ( columns()<(jj+block) )?( columns() ):( jj+block ) );
3100          for( size_t i=ii; i<iend; ++i ) {
3101             for( size_t j=jj; j<jend; ++j ) {
3102                matrix_(row()+i,column()+j) -= (*rhs)(i,j);
3103             }
3104          }
3105       }
3106    }
3107 }
3108 /*! \endcond */
3109 //*************************************************************************************************
3110 
3111 
3112 //*************************************************************************************************
3113 /*! \cond BLAZE_INTERNAL */
3114 /*!\brief Default implementation of the subtraction assignment of a row-major sparse matrix.
3115 //
3116 // \param rhs The right-hand side sparse matrix to be subtracted.
3117 // \return void
3118 //
3119 // This function must \b NOT be called explicitly! It is used internally for the performance
3120 // optimized evaluation of expression templates. Calling this function explicitly might result
3121 // in erroneous results and/or in compilation errors. Instead of using this function use the
3122 // assignment operator.
3123 */
3124 template< typename MT       // Type of the dense matrix
3125         , size_t... CSAs >  // Compile time submatrix arguments
3126 template< typename MT2 >    // Type of the right-hand side sparse matrix
subAssign(const SparseMatrix<MT2,false> & rhs)3127 inline void Submatrix<MT,unaligned,false,true,CSAs...>::subAssign( const SparseMatrix<MT2,false>& rhs )
3128 {
3129    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
3130    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
3131 
3132    for( size_t i=0UL; i<rows(); ++i )
3133       for( ConstIterator_t<MT2> element=(*rhs).begin(i); element!=(*rhs).end(i); ++element )
3134          matrix_(row()+i,column()+element->index()) -= element->value();
3135 }
3136 /*! \endcond */
3137 //*************************************************************************************************
3138 
3139 
3140 //*************************************************************************************************
3141 /*! \cond BLAZE_INTERNAL */
3142 /*!\brief Default implementation of the subtraction assignment of a column-major sparse matrix.
3143 //
3144 // \param rhs The right-hand side sparse matrix to be subtracted.
3145 // \return void
3146 //
3147 // This function must \b NOT be called explicitly! It is used internally for the performance
3148 // optimized evaluation of expression templates. Calling this function explicitly might result
3149 // in erroneous results and/or in compilation errors. Instead of using this function use the
3150 // assignment operator.
3151 */
3152 template< typename MT       // Type of the dense matrix
3153         , size_t... CSAs >  // Compile time submatrix arguments
3154 template< typename MT2 >    // Type of the right-hand side sparse matrix
subAssign(const SparseMatrix<MT2,true> & rhs)3155 inline void Submatrix<MT,unaligned,false,true,CSAs...>::subAssign( const SparseMatrix<MT2,true>& rhs )
3156 {
3157    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
3158 
3159    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
3160    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
3161 
3162    for( size_t j=0UL; j<columns(); ++j )
3163       for( ConstIterator_t<MT2> element=(*rhs).begin(j); element!=(*rhs).end(j); ++element )
3164          matrix_(row()+element->index(),column()+j) -= element->value();
3165 }
3166 /*! \endcond */
3167 //*************************************************************************************************
3168 
3169 
3170 //*************************************************************************************************
3171 /*! \cond BLAZE_INTERNAL */
3172 /*!\brief Default implementation of the Schur product assignment of a row-major dense matrix.
3173 //
3174 // \param rhs The right-hand side dense matrix for the Schur product.
3175 // \return void
3176 //
3177 // This function must \b NOT be called explicitly! It is used internally for the performance
3178 // optimized evaluation of expression templates. Calling this function explicitly might result
3179 // in erroneous results and/or in compilation errors. Instead of using this function use the
3180 // assignment operator.
3181 */
3182 template< typename MT       // Type of the dense matrix
3183         , size_t... CSAs >  // Compile time submatrix arguments
3184 template< typename MT2 >    // Type of the right-hand side dense matrix
3185 inline auto Submatrix<MT,unaligned,false,true,CSAs...>::schurAssign( const DenseMatrix<MT2,false>& rhs )
3186    -> DisableIf_t< VectorizedSchurAssign_v<MT2> >
3187 {
3188    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
3189    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
3190 
3191    const size_t jpos( prevMultiple( columns(), 2UL ) );
3192    BLAZE_INTERNAL_ASSERT( jpos <= columns(), "Invalid end calculation" );
3193 
3194    for( size_t i=0UL; i<rows(); ++i ) {
3195       for( size_t j=0UL; j<jpos; j+=2UL ) {
3196          matrix_(row()+i,column()+j    ) *= (*rhs)(i,j    );
3197          matrix_(row()+i,column()+j+1UL) *= (*rhs)(i,j+1UL);
3198       }
3199       if( jpos < columns() ) {
3200          matrix_(row()+i,column()+jpos) *= (*rhs)(i,jpos);
3201       }
3202    }
3203 }
3204 /*! \endcond */
3205 //*************************************************************************************************
3206 
3207 
3208 //*************************************************************************************************
3209 /*! \cond BLAZE_INTERNAL */
3210 /*!\brief SIMD optimized implementation of the Schur product assignment of a row-major dense matrix.
3211 //
3212 // \param rhs The right-hand side dense matrix for the Schur product.
3213 // \return void
3214 //
3215 // This function must \b NOT be called explicitly! It is used internally for the performance
3216 // optimized evaluation of expression templates. Calling this function explicitly might result
3217 // in erroneous results and/or in compilation errors. Instead of using this function use the
3218 // assignment operator.
3219 */
3220 template< typename MT       // Type of the dense matrix
3221         , size_t... CSAs >  // Compile time submatrix arguments
3222 template< typename MT2 >    // Type of the right-hand side dense matrix
3223 inline auto Submatrix<MT,unaligned,false,true,CSAs...>::schurAssign( const DenseMatrix<MT2,false>& rhs )
3224    -> EnableIf_t< VectorizedSchurAssign_v<MT2> >
3225 {
3226    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
3227 
3228    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
3229    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
3230 
3231    for( size_t i=0UL; i<rows(); ++i )
3232    {
3233       const size_t jpos( prevMultiple( columns(), SIMDSIZE ) );
3234       BLAZE_INTERNAL_ASSERT( jpos <= columns(), "Invalid end calculation" );
3235 
3236       size_t j( 0UL );
3237       Iterator left( begin(i) );
3238       ConstIterator_t<MT2> right( (*rhs).begin(i) );
3239 
3240       for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
3241          left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3242          left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3243          left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3244          left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3245       }
3246       for( ; j<jpos; j+=SIMDSIZE ) {
3247          left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3248       }
3249       for( ; j<columns(); ++j ) {
3250          *left *= *right; ++left; ++right;
3251       }
3252    }
3253 }
3254 /*! \endcond */
3255 //*************************************************************************************************
3256 
3257 
3258 //*************************************************************************************************
3259 /*! \cond BLAZE_INTERNAL */
3260 /*!\brief Default implementation of the Schur product assignment of a column-major dense matrix.
3261 //
3262 // \param rhs The right-hand side dense matrix for the Schur product.
3263 // \return void
3264 //
3265 // This function must \b NOT be called explicitly! It is used internally for the performance
3266 // optimized evaluation of expression templates. Calling this function explicitly might result
3267 // in erroneous results and/or in compilation errors. Instead of using this function use the
3268 // assignment operator.
3269 */
3270 template< typename MT       // Type of the dense matrix
3271         , size_t... CSAs >  // Compile time submatrix arguments
3272 template< typename MT2 >    // Type of the right-hand side dense matrix
schurAssign(const DenseMatrix<MT2,true> & rhs)3273 inline void Submatrix<MT,unaligned,false,true,CSAs...>::schurAssign( const DenseMatrix<MT2,true>& rhs )
3274 {
3275    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
3276 
3277    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
3278    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
3279 
3280    constexpr size_t block( BLOCK_SIZE );
3281 
3282    for( size_t ii=0UL; ii<rows(); ii+=block ) {
3283       const size_t iend( ( rows()<(ii+block) )?( rows() ):( ii+block ) );
3284       for( size_t jj=0UL; jj<columns(); jj+=block ) {
3285          const size_t jend( ( columns()<(jj+block) )?( columns() ):( jj+block ) );
3286          for( size_t i=ii; i<iend; ++i ) {
3287             for( size_t j=jj; j<jend; ++j ) {
3288                matrix_(row()+i,column()+j) *= (*rhs)(i,j);
3289             }
3290          }
3291       }
3292    }
3293 }
3294 /*! \endcond */
3295 //*************************************************************************************************
3296 
3297 
3298 //*************************************************************************************************
3299 /*! \cond BLAZE_INTERNAL */
3300 /*!\brief Default implementation of the Schur product assignment of a row-major sparse matrix.
3301 //
3302 // \param rhs The right-hand side sparse matrix for the Schur product.
3303 // \return void
3304 //
3305 // This function must \b NOT be called explicitly! It is used internally for the performance
3306 // optimized evaluation of expression templates. Calling this function explicitly might result
3307 // in erroneous results and/or in compilation errors. Instead of using this function use the
3308 // assignment operator.
3309 */
3310 template< typename MT       // Type of the dense matrix
3311         , size_t... CSAs >  // Compile time submatrix arguments
3312 template< typename MT2 >    // Type of the right-hand side sparse matrix
schurAssign(const SparseMatrix<MT2,false> & rhs)3313 inline void Submatrix<MT,unaligned,false,true,CSAs...>::schurAssign( const SparseMatrix<MT2,false>& rhs )
3314 {
3315    using blaze::reset;
3316 
3317    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
3318    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
3319 
3320    for( size_t i=0UL; i<rows(); ++i )
3321    {
3322       size_t j( 0UL );
3323 
3324       for( ConstIterator_t<MT2> element=(*rhs).begin(i); element!=(*rhs).end(i); ++element ) {
3325          for( ; j<element->index(); ++j )
3326             reset( matrix_(row()+i,column()+j) );
3327          matrix_(row()+i,column()+j) *= element->value();
3328          ++j;
3329       }
3330 
3331       for( ; j<columns(); ++j ) {
3332          reset( matrix_(row()+i,column()+j) );
3333       }
3334    }
3335 }
3336 /*! \endcond */
3337 //*************************************************************************************************
3338 
3339 
3340 //*************************************************************************************************
3341 /*! \cond BLAZE_INTERNAL */
3342 /*!\brief Default implementation of the Schur product assignment of a column-major sparse matrix.
3343 //
3344 // \param rhs The right-hand side sparse matrix for the Schur product.
3345 // \return void
3346 //
3347 // This function must \b NOT be called explicitly! It is used internally for the performance
3348 // optimized evaluation of expression templates. Calling this function explicitly might result
3349 // in erroneous results and/or in compilation errors. Instead of using this function use the
3350 // assignment operator.
3351 */
3352 template< typename MT       // Type of the dense matrix
3353         , size_t... CSAs >  // Compile time submatrix arguments
3354 template< typename MT2 >    // Type of the right-hand side sparse matrix
schurAssign(const SparseMatrix<MT2,true> & rhs)3355 inline void Submatrix<MT,unaligned,false,true,CSAs...>::schurAssign( const SparseMatrix<MT2,true>& rhs )
3356 {
3357    using blaze::reset;
3358 
3359    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
3360 
3361    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
3362    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
3363 
3364    for( size_t j=0UL; j<columns(); ++j )
3365    {
3366       size_t i( 0UL );
3367 
3368       for( ConstIterator_t<MT2> element=(*rhs).begin(j); element!=(*rhs).end(j); ++element ) {
3369          for( ; i<element->index(); ++i )
3370             reset( matrix_(row()+i,column()+j) );
3371          matrix_(row()+i,column()+j) *= element->value();
3372          ++i;
3373       }
3374 
3375       for( ; i<rows(); ++i ) {
3376          reset( matrix_(row()+i,column()+j) );
3377       }
3378    }
3379 }
3380 /*! \endcond */
3381 //*************************************************************************************************
3382 
3383 
3384 
3385 
3386 
3387 
3388 
3389 
3390 //=================================================================================================
3391 //
3392 //  CLASS TEMPLATE SPECIALIZATION FOR UNALIGNED COLUMN-MAJOR DENSE SUBMATRICES
3393 //
3394 //=================================================================================================
3395 
3396 //*************************************************************************************************
3397 /*! \cond BLAZE_INTERNAL */
3398 /*!\brief Specialization of Submatrix for unaligned column-major dense submatrices.
3399 // \ingroup submatrix
3400 //
3401 // This Specialization of Submatrix adapts the class template to the requirements of unaligned
3402 // column-major dense submatrices.
3403 */
3404 template< typename MT       // Type of the dense matrix
3405         , size_t... CSAs >  // Compile time submatrix arguments
3406 class Submatrix<MT,unaligned,true,true,CSAs...>
3407    : public View< DenseMatrix< Submatrix<MT,unaligned,true,true,CSAs...>, true > >
3408    , private SubmatrixData<CSAs...>
3409 {
3410  private:
3411    //**Type definitions****************************************************************************
3412    using DataType = SubmatrixData<CSAs...>;               //!< The type of the SubmatrixData base class.
3413    using Operand  = If_t< IsExpression_v<MT>, MT, MT& >;  //!< Composite data type of the matrix expression.
3414    //**********************************************************************************************
3415 
3416    //**********************************************************************************************
3417    //! Helper variable template for the explicit application of the SFINAE principle.
3418    template< typename MT1, typename MT2 >
3419    static constexpr bool EnforceEvaluation_v =
3420       ( IsRestricted_v<MT1> && RequiresEvaluation_v<MT2> );
3421    //**********************************************************************************************
3422 
3423  public:
3424    //**Type definitions****************************************************************************
3425    //! Type of this Submatrix instance.
3426    using This = Submatrix<MT,unaligned,true,true,CSAs...>;
3427 
3428    //! Base type of this Submatrix instance.
3429    using BaseType = View< DenseMatrix<This,true> >;
3430 
3431    using ViewedType    = MT;                            //!< The type viewed by this Submatrix instance.
3432    using ResultType    = SubmatrixTrait_t<MT,CSAs...>;  //!< Result type for expression template evaluations.
3433    using OppositeType  = OppositeType_t<ResultType>;    //!< Result type with opposite storage order for expression template evaluations.
3434    using TransposeType = TransposeType_t<ResultType>;   //!< Transpose type for expression template evaluations.
3435    using ElementType   = ElementType_t<MT>;             //!< Type of the submatrix elements.
3436    using SIMDType      = SIMDTrait_t<ElementType>;      //!< SIMD type of the submatrix elements.
3437    using ReturnType    = ReturnType_t<MT>;              //!< Return type for expression template evaluations
3438    using CompositeType = const Submatrix&;              //!< Data type for composite expression templates.
3439 
3440    //! Reference to a constant submatrix value.
3441    using ConstReference = ConstReference_t<MT>;
3442 
3443    //! Reference to a non-constant submatrix value.
3444    using Reference = If_t< IsConst_v<MT>, ConstReference, Reference_t<MT> >;
3445 
3446    //! Pointer to a constant submatrix value.
3447    using ConstPointer = ConstPointer_t<MT>;
3448 
3449    //! Pointer to a non-constant submatrix value.
3450    using Pointer = If_t< IsConst_v<MT> || !HasMutableDataAccess_v<MT>, ConstPointer, Pointer_t<MT> >;
3451    //**********************************************************************************************
3452 
3453    //**SubmatrixIterator class definition**********************************************************
3454    /*!\brief Iterator over the elements of the sparse submatrix.
3455    */
3456    template< typename IteratorType >  // Type of the dense matrix iterator
3457    class SubmatrixIterator
3458    {
3459     public:
3460       //**Type definitions*************************************************************************
3461       //! The iterator category.
3462       using IteratorCategory = typename std::iterator_traits<IteratorType>::iterator_category;
3463 
3464       //! Type of the underlying elements.
3465       using ValueType = typename std::iterator_traits<IteratorType>::value_type;
3466 
3467       //! Pointer return type.
3468       using PointerType = typename std::iterator_traits<IteratorType>::pointer;
3469 
3470       //! Reference return type.
3471       using ReferenceType = typename std::iterator_traits<IteratorType>::reference;
3472 
3473       //! Difference between two iterators.
3474       using DifferenceType = typename std::iterator_traits<IteratorType>::difference_type;
3475 
3476       // STL iterator requirements
3477       using iterator_category = IteratorCategory;  //!< The iterator category.
3478       using value_type        = ValueType;         //!< Type of the underlying elements.
3479       using pointer           = PointerType;       //!< Pointer return type.
3480       using reference         = ReferenceType;     //!< Reference return type.
3481       using difference_type   = DifferenceType;    //!< Difference between two iterators.
3482       //*******************************************************************************************
3483 
3484       //**Constructor******************************************************************************
3485       /*!\brief Default constructor of the SubmatrixIterator class.
3486       */
SubmatrixIterator()3487       inline SubmatrixIterator()
3488          : iterator_ (       )  // Iterator to the current submatrix element
3489          , isAligned_( false )  // Memory alignment flag
3490       {}
3491       //*******************************************************************************************
3492 
3493       //**Constructor******************************************************************************
3494       /*!\brief Constructor of the SubmatrixIterator class.
3495       //
3496       // \param iterator Iterator to the initial element.
3497       // \param finalIterator The final iterator for SIMD operations.
3498       // \param remainingElements The number of remaining elements beyond the final iterator.
3499       // \param isMemoryAligned Memory alignment flag.
3500       */
SubmatrixIterator(IteratorType iterator,bool isMemoryAligned)3501       inline SubmatrixIterator( IteratorType iterator, bool isMemoryAligned )
3502          : iterator_ ( iterator        )  // Iterator to the current submatrix element
3503          , isAligned_( isMemoryAligned )  // Memory alignment flag
3504       {}
3505       //*******************************************************************************************
3506 
3507       //**Constructor******************************************************************************
3508       /*!\brief Conversion constructor from different SubmatrixIterator instances.
3509       //
3510       // \param it The submatrix iterator to be copied.
3511       */
3512       template< typename IteratorType2 >
SubmatrixIterator(const SubmatrixIterator<IteratorType2> & it)3513       inline SubmatrixIterator( const SubmatrixIterator<IteratorType2>& it )
3514          : iterator_ ( it.base()      )  // Iterator to the current submatrix element
3515          , isAligned_( it.isAligned() )  // Memory alignment flag
3516       {}
3517       //*******************************************************************************************
3518 
3519       //**Addition assignment operator*************************************************************
3520       /*!\brief Addition assignment operator.
3521       //
3522       // \param inc The increment of the iterator.
3523       // \return The incremented iterator.
3524       */
3525       inline SubmatrixIterator& operator+=( size_t inc ) {
3526          iterator_ += inc;
3527          return *this;
3528       }
3529       //*******************************************************************************************
3530 
3531       //**Subtraction assignment operator**********************************************************
3532       /*!\brief Subtraction assignment operator.
3533       //
3534       // \param dec The decrement of the iterator.
3535       // \return The decremented iterator.
3536       */
3537       inline SubmatrixIterator& operator-=( size_t dec ) {
3538          iterator_ -= dec;
3539          return *this;
3540       }
3541       //*******************************************************************************************
3542 
3543       //**Prefix increment operator****************************************************************
3544       /*!\brief Pre-increment operator.
3545       //
3546       // \return Reference to the incremented iterator.
3547       */
3548       inline SubmatrixIterator& operator++() {
3549          ++iterator_;
3550          return *this;
3551       }
3552       //*******************************************************************************************
3553 
3554       //**Postfix increment operator***************************************************************
3555       /*!\brief Post-increment operator.
3556       //
3557       // \return The previous position of the iterator.
3558       */
3559       inline const SubmatrixIterator operator++( int ) {
3560          return SubmatrixIterator( iterator_++, isAligned_ );
3561       }
3562       //*******************************************************************************************
3563 
3564       //**Prefix decrement operator****************************************************************
3565       /*!\brief Pre-decrement operator.
3566       //
3567       // \return Reference to the decremented iterator.
3568       */
3569       inline SubmatrixIterator& operator--() {
3570          --iterator_;
3571          return *this;
3572       }
3573       //*******************************************************************************************
3574 
3575       //**Postfix decrement operator***************************************************************
3576       /*!\brief Post-decrement operator.
3577       //
3578       // \return The previous position of the iterator.
3579       */
3580       inline const SubmatrixIterator operator--( int ) {
3581          return SubmatrixIterator( iterator_--, isAligned_ );
3582       }
3583       //*******************************************************************************************
3584 
3585       //**Element access operator******************************************************************
3586       /*!\brief Direct access to the element at the current iterator position.
3587       //
3588       // \return The resulting value.
3589       */
3590       inline ReferenceType operator*() const {
3591          return *iterator_;
3592       }
3593       //*******************************************************************************************
3594 
3595       //**Element access operator******************************************************************
3596       /*!\brief Direct access to the element at the current iterator position.
3597       //
3598       // \return Pointer to the element at the current iterator position.
3599       */
3600       inline IteratorType operator->() const {
3601          return iterator_;
3602       }
3603       //*******************************************************************************************
3604 
3605       //**Load function****************************************************************************
3606       /*!\brief Load of a SIMD element of the dense submatrix.
3607       //
3608       // \return The loaded SIMD element.
3609       //
3610       // This function performs a load of the current SIMD element of the submatrix iterator.
3611       // This function must \b NOT be called explicitly! It is used internally for the performance
3612       // optimized evaluation of expression templates. Calling this function explicitly might
3613       // result in erroneous results and/or in compilation errors.
3614       */
load()3615       inline SIMDType load() const noexcept {
3616          if( isAligned_ )
3617             return loada();
3618          else
3619             return loadu();
3620       }
3621       //*******************************************************************************************
3622 
3623       //**Loada function***************************************************************************
3624       /*!\brief Aligned load of a SIMD element of the dense submatrix.
3625       //
3626       // \return The loaded SIMD element.
3627       //
3628       // This function performs an aligned load of the current SIMD element of the submatrix
3629       // iterator. This function must \b NOT be called explicitly! It is used internally for the
3630       // performance optimized evaluation of expression templates. Calling this function explicitly
3631       // might result in erroneous results and/or in compilation errors.
3632       */
loada()3633       inline SIMDType loada() const noexcept {
3634          return iterator_.loada();
3635       }
3636       //*******************************************************************************************
3637 
3638       //**Loadu function***************************************************************************
3639       /*!\brief Unaligned load of a SIMD element of the dense submatrix.
3640       //
3641       // \return The loaded SIMD element.
3642       //
3643       // This function performs an unaligned load of the current SIMD element of the submatrix
3644       // iterator. This function must \b NOT be called explicitly! It is used internally for the
3645       // performance optimized evaluation of expression templates. Calling this function explicitly
3646       // might result in erroneous results and/or in compilation errors.
3647       */
loadu()3648       inline SIMDType loadu() const noexcept {
3649          return iterator_.loadu();
3650       }
3651       //*******************************************************************************************
3652 
3653       //**Store function***************************************************************************
3654       /*!\brief Store of a SIMD element of the dense submatrix.
3655       //
3656       // \param value The SIMD element to be stored.
3657       // \return void
3658       //
3659       // This function performs a store of the current SIMD element of the submatrix iterator.
3660       // This function must \b NOT be called explicitly! It is used internally for the performance
3661       // optimized evaluation of expression templates. Calling this function explicitly might
3662       // result in erroneous results and/or in compilation errors.
3663       */
store(const SIMDType & value)3664       inline void store( const SIMDType& value ) const {
3665          if( isAligned_ ) {
3666             storea( value );
3667          }
3668          else {
3669             storeu( value );
3670          }
3671       }
3672       //*******************************************************************************************
3673 
3674       //**Storea function**************************************************************************
3675       /*!\brief Aligned store of a SIMD element of the dense submatrix.
3676       //
3677       // \param value The SIMD element to be stored.
3678       // \return void
3679       //
3680       // This function performs an aligned store of the current SIMD element of the submatrix
3681       // iterator. This function must \b NOT be called explicitly! It is used internally for the
3682       // performance optimized evaluation of expression templates. Calling this function explicitly
3683       // might result in erroneous results and/or in compilation errors.
3684       */
storea(const SIMDType & value)3685       inline void storea( const SIMDType& value ) const {
3686          iterator_.storea( value );
3687       }
3688       //*******************************************************************************************
3689 
3690       //**Storeu function**************************************************************************
3691       /*!\brief Unaligned store of a SIMD element of the dense submatrix.
3692       //
3693       // \param value The SIMD element to be stored.
3694       // \return void
3695       //
3696       // This function performs an unaligned store of the current SIMD element of the submatrix
3697       // iterator. This function must \b NOT be called explicitly! It is used internally for the
3698       // performance optimized evaluation of expression templates. Calling this function explicitly
3699       // might result in erroneous results and/or in compilation errors.
3700       */
storeu(const SIMDType & value)3701       inline void storeu( const SIMDType& value ) const {
3702          iterator_.storeu( value );
3703       }
3704       //*******************************************************************************************
3705 
3706       //**Stream function**************************************************************************
3707       /*!\brief Aligned, non-temporal store of a SIMD element of the dense submatrix.
3708       //
3709       // \param value The SIMD element to be stored.
3710       // \return void
3711       //
3712       // This function performs an aligned, non-temporal store of the current SIMD element of the
3713       // submatrix iterator. This function must \b NOT be called explicitly! It is used internally
3714       // for the performance optimized evaluation of expression templates. Calling this function
3715       // explicitly might result in erroneous results and/or in compilation errors.
3716       */
stream(const SIMDType & value)3717       inline void stream( const SIMDType& value ) const {
3718          iterator_.stream( value );
3719       }
3720       //*******************************************************************************************
3721 
3722       //**Equality operator************************************************************************
3723       /*!\brief Equality comparison between two SubmatrixIterator objects.
3724       //
3725       // \param rhs The right-hand side iterator.
3726       // \return \a true if the iterators refer to the same element, \a false if not.
3727       */
3728       inline bool operator==( const SubmatrixIterator& rhs ) const {
3729          return iterator_ == rhs.iterator_;
3730       }
3731       //*******************************************************************************************
3732 
3733       //**Inequality operator**********************************************************************
3734       /*!\brief Inequality comparison between two SubmatrixIterator objects.
3735       //
3736       // \param rhs The right-hand side iterator.
3737       // \return \a true if the iterators don't refer to the same element, \a false if they do.
3738       */
3739       inline bool operator!=( const SubmatrixIterator& rhs ) const {
3740          return iterator_ != rhs.iterator_;
3741       }
3742       //*******************************************************************************************
3743 
3744       //**Less-than operator***********************************************************************
3745       /*!\brief Less-than comparison between two SubmatrixIterator objects.
3746       //
3747       // \param rhs The right-hand side iterator.
3748       // \return \a true if the left-hand side iterator is smaller, \a false if not.
3749       */
3750       inline bool operator<( const SubmatrixIterator& rhs ) const {
3751          return iterator_ < rhs.iterator_;
3752       }
3753       //*******************************************************************************************
3754 
3755       //**Greater-than operator********************************************************************
3756       /*!\brief Greater-than comparison between two SubmatrixIterator objects.
3757       //
3758       // \param rhs The right-hand side iterator.
3759       // \return \a true if the left-hand side iterator is greater, \a false if not.
3760       */
3761       inline bool operator>( const SubmatrixIterator& rhs ) const {
3762          return iterator_ > rhs.iterator_;
3763       }
3764       //*******************************************************************************************
3765 
3766       //**Less-or-equal-than operator**************************************************************
3767       /*!\brief Less-than comparison between two SubmatrixIterator objects.
3768       //
3769       // \param rhs The right-hand side iterator.
3770       // \return \a true if the left-hand side iterator is smaller or equal, \a false if not.
3771       */
3772       inline bool operator<=( const SubmatrixIterator& rhs ) const {
3773          return iterator_ <= rhs.iterator_;
3774       }
3775       //*******************************************************************************************
3776 
3777       //**Greater-or-equal-than operator***********************************************************
3778       /*!\brief Greater-than comparison between two SubmatrixIterator objects.
3779       //
3780       // \param rhs The right-hand side iterator.
3781       // \return \a true if the left-hand side iterator is greater or equal, \a false if not.
3782       */
3783       inline bool operator>=( const SubmatrixIterator& rhs ) const {
3784          return iterator_ >= rhs.iterator_;
3785       }
3786       //*******************************************************************************************
3787 
3788       //**Subtraction operator*********************************************************************
3789       /*!\brief Calculating the number of elements between two iterators.
3790       //
3791       // \param rhs The right-hand side iterator.
3792       // \return The number of elements between the two iterators.
3793       */
3794       inline DifferenceType operator-( const SubmatrixIterator& rhs ) const {
3795          return iterator_ - rhs.iterator_;
3796       }
3797       //*******************************************************************************************
3798 
3799       //**Addition operator************************************************************************
3800       /*!\brief Addition between a SubmatrixIterator and an integral value.
3801       //
3802       // \param it The iterator to be incremented.
3803       // \param inc The number of elements the iterator is incremented.
3804       // \return The incremented iterator.
3805       */
3806       friend inline const SubmatrixIterator operator+( const SubmatrixIterator& it, size_t inc ) {
3807          return SubmatrixIterator( it.iterator_ + inc, it.isAligned_ );
3808       }
3809       //*******************************************************************************************
3810 
3811       //**Addition operator************************************************************************
3812       /*!\brief Addition between an integral value and a SubmatrixIterator.
3813       //
3814       // \param inc The number of elements the iterator is incremented.
3815       // \param it The iterator to be incremented.
3816       // \return The incremented iterator.
3817       */
3818       friend inline const SubmatrixIterator operator+( size_t inc, const SubmatrixIterator& it ) {
3819          return SubmatrixIterator( it.iterator_ + inc, it.isAligned_ );
3820       }
3821       //*******************************************************************************************
3822 
3823       //**Subtraction operator*********************************************************************
3824       /*!\brief Subtraction between a SubmatrixIterator and an integral value.
3825       //
3826       // \param it The iterator to be decremented.
3827       // \param inc The number of elements the iterator is decremented.
3828       // \return The decremented iterator.
3829       */
3830       friend inline const SubmatrixIterator operator-( const SubmatrixIterator& it, size_t dec ) {
3831          return SubmatrixIterator( it.iterator_ - dec, it.isAligned_ );
3832       }
3833       //*******************************************************************************************
3834 
3835       //**Base function****************************************************************************
3836       /*!\brief Access to the current position of the submatrix iterator.
3837       //
3838       // \return The current position of the submatrix iterator.
3839       */
base()3840       inline IteratorType base() const {
3841          return iterator_;
3842       }
3843       //*******************************************************************************************
3844 
3845       //**IsAligned function***********************************************************************
3846       /*!\brief Access to the iterator's memory alignment flag.
3847       //
3848       // \return \a true in case the iterator is aligned, \a false if it is not.
3849       */
isAligned()3850       inline bool isAligned() const noexcept {
3851          return isAligned_;
3852       }
3853       //*******************************************************************************************
3854 
3855     private:
3856       //**Member variables*************************************************************************
3857       IteratorType iterator_;   //!< Iterator to the current submatrix element.
3858       bool         isAligned_;  //!< Memory alignment flag.
3859       //*******************************************************************************************
3860    };
3861    //**********************************************************************************************
3862 
3863    //**Type definitions****************************************************************************
3864    //! Iterator over constant elements.
3865    using ConstIterator = SubmatrixIterator< ConstIterator_t<MT> >;
3866 
3867    //! Iterator over non-constant elements.
3868    using Iterator = If_t< IsConst_v<MT>, ConstIterator, SubmatrixIterator< Iterator_t<MT> > >;
3869    //**********************************************************************************************
3870 
3871    //**Compilation flags***************************************************************************
3872    //! Compilation switch for the expression template evaluation strategy.
3873    static constexpr bool simdEnabled = MT::simdEnabled;
3874 
3875    //! Compilation switch for the expression template assignment strategy.
3876    static constexpr bool smpAssignable = MT::smpAssignable;
3877 
3878    //! Compilation switch for the expression template evaluation strategy.
3879    static constexpr bool compileTimeArgs = DataType::compileTimeArgs;
3880    //**********************************************************************************************
3881 
3882    //**Constructors********************************************************************************
3883    /*!\name Constructors */
3884    //@{
3885    template< typename... RSAs >
3886    explicit inline Submatrix( MT& matrix, RSAs... args );
3887 
3888    Submatrix( const Submatrix& ) = default;
3889    //@}
3890    //**********************************************************************************************
3891 
3892    //**Destructor**********************************************************************************
3893    /*!\name Destructor */
3894    //@{
3895    ~Submatrix() = default;
3896    //@}
3897    //**********************************************************************************************
3898 
3899    //**Data access functions***********************************************************************
3900    /*!\name Data access functions */
3901    //@{
3902    inline Reference      operator()( size_t i, size_t j );
3903    inline ConstReference operator()( size_t i, size_t j ) const;
3904    inline Reference      at( size_t i, size_t j );
3905    inline ConstReference at( size_t i, size_t j ) const;
3906    inline Pointer        data  () noexcept;
3907    inline ConstPointer   data  () const noexcept;
3908    inline Pointer        data  ( size_t j ) noexcept;
3909    inline ConstPointer   data  ( size_t j ) const noexcept;
3910    inline Iterator       begin ( size_t j );
3911    inline ConstIterator  begin ( size_t j ) const;
3912    inline ConstIterator  cbegin( size_t j ) const;
3913    inline Iterator       end   ( size_t j );
3914    inline ConstIterator  end   ( size_t j ) const;
3915    inline ConstIterator  cend  ( size_t j ) const;
3916    //@}
3917    //**********************************************************************************************
3918 
3919    //**Assignment operators************************************************************************
3920    /*!\name Assignment operators */
3921    //@{
3922    inline Submatrix& operator=( const ElementType& rhs );
3923    inline Submatrix& operator=( initializer_list< initializer_list<ElementType> > list );
3924    inline Submatrix& operator=( const Submatrix& rhs );
3925 
3926    template< typename MT2, bool SO >
3927    inline Submatrix& operator=( const Matrix<MT2,SO>& rhs );
3928 
3929    template< typename MT2, bool SO >
3930    inline auto operator+=( const Matrix<MT2,SO>& rhs )
3931       -> DisableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >;
3932 
3933    template< typename MT2, bool SO >
3934    inline auto operator+=( const Matrix<MT2,SO>& rhs )
3935       -> EnableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >;
3936 
3937    template< typename MT2, bool SO >
3938    inline auto operator-=( const Matrix<MT2,SO>& rhs )
3939       -> DisableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >;
3940 
3941    template< typename MT2, bool SO >
3942    inline auto operator-=( const Matrix<MT2,SO>& rhs )
3943       -> EnableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >;
3944 
3945    template< typename MT2, bool SO >
3946    inline auto operator%=( const Matrix<MT2,SO>& rhs )
3947       -> DisableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >;
3948 
3949    template< typename MT2, bool SO >
3950    inline auto operator%=( const Matrix<MT2,SO>& rhs )
3951       -> EnableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >;
3952    //@}
3953    //**********************************************************************************************
3954 
3955    //**Utility functions***************************************************************************
3956    /*!\name Utility functions */
3957    //@{
3958    using DataType::row;
3959    using DataType::column;
3960    using DataType::rows;
3961    using DataType::columns;
3962 
3963    inline MT&       operand() noexcept;
3964    inline const MT& operand() const noexcept;
3965 
3966    inline size_t spacing() const noexcept;
3967    inline size_t capacity() const noexcept;
3968    inline size_t capacity( size_t i ) const noexcept;
3969    inline size_t nonZeros() const;
3970    inline size_t nonZeros( size_t i ) const;
3971    inline void   reset();
3972    inline void   reset( size_t i );
3973    //@}
3974    //**********************************************************************************************
3975 
3976    //**Numeric functions***************************************************************************
3977    /*!\name Numeric functions */
3978    //@{
3979    inline Submatrix& transpose();
3980    inline Submatrix& ctranspose();
3981 
3982    template< typename Other > inline Submatrix& scale( const Other& scalar );
3983    //@}
3984    //**********************************************************************************************
3985 
3986  private:
3987    //**********************************************************************************************
3988    //! Helper variable template for the explicit application of the SFINAE principle.
3989    template< typename MT2 >
3990    static constexpr bool VectorizedAssign_v =
3991       ( useOptimizedKernels &&
3992         simdEnabled && MT2::simdEnabled &&
3993         IsSIMDCombinable_v< ElementType, ElementType_t<MT2> > );
3994    //**********************************************************************************************
3995 
3996    //**********************************************************************************************
3997    //! Helper variable template for the explicit application of the SFINAE principle.
3998    template< typename MT2 >
3999    static constexpr bool VectorizedAddAssign_v =
4000       ( VectorizedAssign_v<MT2> &&
4001         HasSIMDAdd_v< ElementType, ElementType_t<MT2> > &&
4002         !IsDiagonal_v<MT2> );
4003    //**********************************************************************************************
4004 
4005    //**********************************************************************************************
4006    //! Helper variable template for the explicit application of the SFINAE principle.
4007    template< typename MT2 >
4008    static constexpr bool VectorizedSubAssign_v =
4009       ( VectorizedAssign_v<MT2> &&
4010         HasSIMDSub_v< ElementType, ElementType_t<MT2> > &&
4011         !IsDiagonal_v<MT2> );
4012    //**********************************************************************************************
4013 
4014    //**********************************************************************************************
4015    //! Helper variable template for the explicit application of the SFINAE principle.
4016    template< typename MT2 >
4017    static constexpr bool VectorizedSchurAssign_v =
4018       ( VectorizedAssign_v<MT2> &&
4019         HasSIMDMult_v< ElementType, ElementType_t<MT2> > );
4020    //**********************************************************************************************
4021 
4022    //**SIMD properties*****************************************************************************
4023    //! The number of elements packed within a single SIMD element.
4024    static constexpr size_t SIMDSIZE = SIMDTrait<ElementType>::size;
4025    //**********************************************************************************************
4026 
4027  public:
4028    //**Expression template evaluation functions****************************************************
4029    /*!\name Expression template evaluation functions */
4030    //@{
4031    template< typename Other >
4032    inline bool canAlias( const Other* alias ) const noexcept;
4033 
4034    template< typename MT2, AlignmentFlag AF2, bool SO2, size_t... CSAs2 >
4035    inline bool canAlias( const Submatrix<MT2,AF2,SO2,true,CSAs2...>* alias ) const noexcept;
4036 
4037    template< typename Other >
4038    inline bool isAliased( const Other* alias ) const noexcept;
4039 
4040    template< typename MT2, AlignmentFlag AF2, bool SO2, size_t... CSAs2 >
4041    inline bool isAliased( const Submatrix<MT2,AF2,SO2,true,CSAs2...>* alias ) const noexcept;
4042 
4043    inline bool isAligned   () const noexcept;
4044    inline bool canSMPAssign() const noexcept;
4045 
4046    BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
4047    BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
4048    BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
4049 
4050    BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
4051    BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
4052    BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
4053    BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
4054 
4055    template< typename MT2 >
4056    inline auto assign( const DenseMatrix<MT2,true>& rhs ) -> DisableIf_t< VectorizedAssign_v<MT2> >;
4057 
4058    template< typename MT2 >
4059    inline auto assign( const DenseMatrix<MT2,true>& rhs ) -> EnableIf_t< VectorizedAssign_v<MT2> >;
4060 
4061    template< typename MT2 > inline void assign( const DenseMatrix<MT2,false>&  rhs );
4062    template< typename MT2 > inline void assign( const SparseMatrix<MT2,true>&  rhs );
4063    template< typename MT2 > inline void assign( const SparseMatrix<MT2,false>& rhs );
4064 
4065    template< typename MT2 >
4066    inline auto addAssign( const DenseMatrix<MT2,true>& rhs ) -> DisableIf_t< VectorizedAddAssign_v<MT2> >;
4067 
4068    template< typename MT2 >
4069    inline auto addAssign( const DenseMatrix<MT2,true>& rhs ) -> EnableIf_t< VectorizedAddAssign_v<MT2> >;
4070 
4071    template< typename MT2 > inline void addAssign( const DenseMatrix<MT2,false>&  rhs );
4072    template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,true>&  rhs );
4073    template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,false>& rhs );
4074 
4075    template< typename MT2 >
4076    inline auto subAssign( const DenseMatrix<MT2,true>& rhs ) -> DisableIf_t< VectorizedSubAssign_v<MT2> >;
4077 
4078    template< typename MT2 >
4079    inline auto subAssign( const DenseMatrix<MT2,true>& rhs ) -> EnableIf_t< VectorizedSubAssign_v<MT2> >;
4080 
4081    template< typename MT2 > inline void subAssign( const DenseMatrix<MT2,false>&  rhs );
4082    template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,true>&  rhs );
4083    template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,false>& rhs );
4084 
4085    template< typename MT2 >
4086    inline auto schurAssign( const DenseMatrix<MT2,true>& rhs ) -> DisableIf_t< VectorizedSchurAssign_v<MT2> >;
4087 
4088    template< typename MT2 >
4089    inline auto schurAssign( const DenseMatrix<MT2,true>& rhs ) -> EnableIf_t< VectorizedSchurAssign_v<MT2> >;
4090 
4091    template< typename MT2 > inline void schurAssign( const DenseMatrix<MT2,false>&  rhs );
4092    template< typename MT2 > inline void schurAssign( const SparseMatrix<MT2,true>&  rhs );
4093    template< typename MT2 > inline void schurAssign( const SparseMatrix<MT2,false>& rhs );
4094    //@}
4095    //**********************************************************************************************
4096 
4097  private:
4098    //**Utility functions***************************************************************************
4099    /*!\name Utility functions */
4100    //@{
4101    inline bool hasOverlap() const noexcept;
4102    //@}
4103    //**********************************************************************************************
4104 
4105    //**Member variables****************************************************************************
4106    /*!\name Member variables */
4107    //@{
4108    Operand matrix_;        //!< The matrix containing the submatrix.
4109    const bool isAligned_;  //!< Memory alignment flag.
4110                            /*!< The alignment flag indicates whether the submatrix is fully aligned
4111                                 with respect to the given element type and the available instruction
4112                                 set. In case the submatrix is fully aligned it is possible to use
4113                                 aligned loads and stores instead of unaligned loads and stores. In
4114                                 order to be aligned, the first element of each row/column must be
4115                                 aligned. */
4116    //@}
4117    //**********************************************************************************************
4118 
4119    //**Friend declarations*************************************************************************
4120    template< typename MT2, AlignmentFlag AF2, bool SO2, bool DF2, size_t... CSAs2 > friend class Submatrix;
4121    //**********************************************************************************************
4122 
4123    //**Compile time checks*************************************************************************
4124    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE       ( MT );
4125    BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE    ( MT );
4126    BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE      ( MT );
4127    BLAZE_CONSTRAINT_MUST_NOT_BE_SUBMATRIX_TYPE      ( MT );
4128    BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT );
4129    BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE        ( MT );
4130    BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE      ( MT );
4131    //**********************************************************************************************
4132 };
4133 /*! \endcond */
4134 //*************************************************************************************************
4135 
4136 
4137 
4138 
4139 //=================================================================================================
4140 //
4141 //  CONSTRUCTORS
4142 //
4143 //=================================================================================================
4144 
4145 //*************************************************************************************************
4146 /*! \cond BLAZE_INTERNAL */
4147 /*!\brief The constructor for unaligned column-major dense submatrices.
4148 //
4149 // \param matrix The dense matrix containing the submatrix.
4150 // \param args The runtime submatrix arguments.
4151 // \exception std::invalid_argument Invalid submatrix specification.
4152 //
4153 // By default, the provided submatrix arguments are checked at runtime. In case the submatrix is
4154 // not properly specified (i.e. if the specified submatrix is not contained in the given dense
4155 // matrix) a \a std::invalid_argument exception is thrown. The checks can be skipped by providing
4156 // the optional \a blaze::unchecked argument.
4157 */
4158 template< typename MT         // Type of the dense matrix
4159         , size_t... CSAs >    // Compile time submatrix arguments
4160 template< typename... RSAs >  // Runtime submatrix arguments
Submatrix(MT & matrix,RSAs...args)4161 inline Submatrix<MT,unaligned,true,true,CSAs...>::Submatrix( MT& matrix, RSAs... args )
4162    : DataType  ( args... )  // Base class initialization
4163    , matrix_   ( matrix  )  // The matrix containing the submatrix
4164    , isAligned_( simdEnabled && IsContiguous_v<MT> &&
4165                  matrix.data() != nullptr && checkAlignment( data() ) &&
4166                  ( columns() < 2UL || ( matrix.spacing() % SIMDSIZE ) == 0UL ) )
4167 {
4168    if( isChecked( args... ) ) {
4169       if( ( row() + rows() > matrix_.rows() ) || ( column() + columns() > matrix_.columns() ) ) {
4170          BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix specification" );
4171       }
4172    }
4173    else {
4174       BLAZE_USER_ASSERT( row()    + rows()    <= matrix_.rows()   , "Invalid submatrix specification" );
4175       BLAZE_USER_ASSERT( column() + columns() <= matrix_.columns(), "Invalid submatrix specification" );
4176    }
4177 }
4178 /*! \endcond */
4179 //*************************************************************************************************
4180 
4181 
4182 
4183 
4184 //=================================================================================================
4185 //
4186 //  DATA ACCESS FUNCTIONS
4187 //
4188 //=================================================================================================
4189 
4190 //*************************************************************************************************
4191 /*! \cond BLAZE_INTERNAL */
4192 /*!\brief 2D-access to the dense submatrix elements.
4193 //
4194 // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
4195 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
4196 // \return Reference to the accessed value.
4197 //
4198 // This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
4199 // the at() function is guaranteed to perform a check of the given access indices.
4200 */
4201 template< typename MT       // Type of the dense matrix
4202         , size_t... CSAs >  // Compile time submatrix arguments
4203 inline typename Submatrix<MT,unaligned,true,true,CSAs...>::Reference
operator()4204    Submatrix<MT,unaligned,true,true,CSAs...>::operator()( size_t i, size_t j )
4205 {
4206    BLAZE_USER_ASSERT( i < rows()   , "Invalid row access index"    );
4207    BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
4208 
4209    return matrix_(row()+i,column()+j);
4210 }
4211 /*! \endcond */
4212 //*************************************************************************************************
4213 
4214 
4215 //*************************************************************************************************
4216 /*! \cond BLAZE_INTERNAL */
4217 /*!\brief 2D-access to the dense submatrix elements.
4218 //
4219 // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
4220 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
4221 // \return Reference to the accessed value.
4222 //
4223 // This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
4224 // the at() function is guaranteed to perform a check of the given access indices.
4225 */
4226 template< typename MT       // Type of the dense matrix
4227         , size_t... CSAs >  // Compile time submatrix arguments
4228 inline typename Submatrix<MT,unaligned,true,true,CSAs...>::ConstReference
operator()4229    Submatrix<MT,unaligned,true,true,CSAs...>::operator()( size_t i, size_t j ) const
4230 {
4231    BLAZE_USER_ASSERT( i < rows()   , "Invalid row access index"    );
4232    BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
4233 
4234    return const_cast<const MT&>( matrix_ )(row()+i,column()+j);
4235 }
4236 /*! \endcond */
4237 //*************************************************************************************************
4238 
4239 
4240 //*************************************************************************************************
4241 /*! \cond BLAZE_INTERNAL */
4242 /*!\brief Checked access to the submatrix elements.
4243 //
4244 // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
4245 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
4246 // \return Reference to the accessed value.
4247 // \exception std::out_of_range Invalid matrix access index.
4248 //
4249 // In contrast to the function call operator this function always performs a check of the given
4250 // access indices.
4251 */
4252 template< typename MT       // Type of the dense matrix
4253         , size_t... CSAs >  // Compile time submatrix arguments
4254 inline typename Submatrix<MT,unaligned,true,true,CSAs...>::Reference
at(size_t i,size_t j)4255    Submatrix<MT,unaligned,true,true,CSAs...>::at( size_t i, size_t j )
4256 {
4257    if( i >= rows() ) {
4258       BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
4259    }
4260    if( j >= columns() ) {
4261       BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
4262    }
4263    return (*this)(i,j);
4264 }
4265 /*! \endcond */
4266 //*************************************************************************************************
4267 
4268 
4269 //*************************************************************************************************
4270 /*! \cond BLAZE_INTERNAL */
4271 /*!\brief Checked access to the submatrix elements.
4272 //
4273 // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
4274 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
4275 // \return Reference to the accessed value.
4276 // \exception std::out_of_range Invalid matrix access index.
4277 //
4278 // In contrast to the function call operator this function always performs a check of the given
4279 // access indices.
4280 */
4281 template< typename MT       // Type of the dense matrix
4282         , size_t... CSAs >  // Compile time submatrix arguments
4283 inline typename Submatrix<MT,unaligned,true,true,CSAs...>::ConstReference
at(size_t i,size_t j)4284    Submatrix<MT,unaligned,true,true,CSAs...>::at( size_t i, size_t j ) const
4285 {
4286    if( i >= rows() ) {
4287       BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
4288    }
4289    if( j >= columns() ) {
4290       BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
4291    }
4292    return (*this)(i,j);
4293 }
4294 /*! \endcond */
4295 //*************************************************************************************************
4296 
4297 
4298 //*************************************************************************************************
4299 /*! \cond BLAZE_INTERNAL */
4300 /*!\brief Low-level data access to the submatrix elements.
4301 //
4302 // \return Pointer to the internal element storage.
4303 //
4304 // This function returns a pointer to the internal storage of the dense submatrix. Note that
4305 // you can NOT assume that all matrix elements lie adjacent to each other! The dense submatrix
4306 // may use techniques such as padding to improve the alignment of the data.
4307 */
4308 template< typename MT       // Type of the dense matrix
4309         , size_t... CSAs >  // Compile time submatrix arguments
4310 inline typename Submatrix<MT,unaligned,true,true,CSAs...>::Pointer
data()4311    Submatrix<MT,unaligned,true,true,CSAs...>::data() noexcept
4312 {
4313    return matrix_.data() + row() + column()*spacing();
4314 }
4315 /*! \endcond */
4316 //*************************************************************************************************
4317 
4318 
4319 //*************************************************************************************************
4320 /*! \cond BLAZE_INTERNAL */
4321 /*!\brief Low-level data access to the submatrix elements.
4322 //
4323 // \return Pointer to the internal element storage.
4324 //
4325 // This function returns a pointer to the internal storage of the dense submatrix. Note that
4326 // you can NOT assume that all matrix elements lie adjacent to each other! The dense submatrix
4327 // may use techniques such as padding to improve the alignment of the data.
4328 */
4329 template< typename MT       // Type of the dense matrix
4330         , size_t... CSAs >  // Compile time submatrix arguments
4331 inline typename Submatrix<MT,unaligned,true,true,CSAs...>::ConstPointer
data()4332    Submatrix<MT,unaligned,true,true,CSAs...>::data() const noexcept
4333 {
4334    return matrix_.data() + row() + column()*spacing();
4335 }
4336 /*! \endcond */
4337 //*************************************************************************************************
4338 
4339 
4340 //*************************************************************************************************
4341 /*! \cond BLAZE_INTERNAL */
4342 /*!\brief Low-level data access to the submatrix elements of column \a j.
4343 //
4344 // \param j The column index.
4345 // \return Pointer to the internal element storage.
4346 //
4347 // This function returns a pointer to the internal storage for the elements in column \a j.
4348 */
4349 template< typename MT       // Type of the dense matrix
4350         , size_t... CSAs >  // Compile time submatrix arguments
4351 inline typename Submatrix<MT,unaligned,true,true,CSAs...>::Pointer
data(size_t j)4352    Submatrix<MT,unaligned,true,true,CSAs...>::data( size_t j ) noexcept
4353 {
4354    return matrix_.data() + row() + (column()+j)*spacing();
4355 }
4356 /*! \endcond */
4357 //*************************************************************************************************
4358 
4359 
4360 //*************************************************************************************************
4361 /*! \cond BLAZE_INTERNAL */
4362 /*!\brief Low-level data access to the submatrix elements of column \a j.
4363 //
4364 // \param j The column index.
4365 // \return Pointer to the internal element storage.
4366 //
4367 // This function returns a pointer to the internal storage for the elements in column \a j.
4368 */
4369 template< typename MT       // Type of the dense matrix
4370         , size_t... CSAs >  // Compile time submatrix arguments
4371 inline typename Submatrix<MT,unaligned,true,true,CSAs...>::ConstPointer
data(size_t j)4372    Submatrix<MT,unaligned,true,true,CSAs...>::data( size_t j ) const noexcept
4373 {
4374    return matrix_.data() + row() + (column()+j)*spacing();
4375 }
4376 /*! \endcond */
4377 //*************************************************************************************************
4378 
4379 
4380 //*************************************************************************************************
4381 /*! \cond BLAZE_INTERNAL */
4382 /*!\brief Returns an iterator to the first non-zero element of column \a j.
4383 //
4384 // \param j The column index.
4385 // \return Iterator to the first non-zero element of column \a j.
4386 */
4387 template< typename MT       // Type of the dense matrix
4388         , size_t... CSAs >  // Compile time submatrix arguments
4389 inline typename Submatrix<MT,unaligned,true,true,CSAs...>::Iterator
begin(size_t j)4390    Submatrix<MT,unaligned,true,true,CSAs...>::begin( size_t j )
4391 {
4392    BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
4393    return Iterator( matrix_.begin( column() + j ) + row(), isAligned_ );
4394 }
4395 /*! \endcond */
4396 //*************************************************************************************************
4397 
4398 
4399 //*************************************************************************************************
4400 /*! \cond BLAZE_INTERNAL */
4401 /*!\brief Returns an iterator to the first non-zero element of column \a j.
4402 //
4403 // \param j The column index.
4404 // \return Iterator to the first non-zero element of column \a j.
4405 */
4406 template< typename MT       // Type of the dense matrix
4407         , size_t... CSAs >  // Compile time submatrix arguments
4408 inline typename Submatrix<MT,unaligned,true,true,CSAs...>::ConstIterator
begin(size_t j)4409    Submatrix<MT,unaligned,true,true,CSAs...>::begin( size_t j ) const
4410 {
4411    BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
4412    return ConstIterator( matrix_.cbegin( column() + j ) + row(), isAligned_ );
4413 }
4414 /*! \endcond */
4415 //*************************************************************************************************
4416 
4417 
4418 //*************************************************************************************************
4419 /*! \cond BLAZE_INTERNAL */
4420 /*!\brief Returns an iterator to the first non-zero element of column \a j.
4421 //
4422 // \param j The column index.
4423 // \return Iterator to the first non-zero element of column \a j.
4424 */
4425 template< typename MT       // Type of the dense matrix
4426         , size_t... CSAs >  // Compile time submatrix arguments
4427 inline typename Submatrix<MT,unaligned,true,true,CSAs...>::ConstIterator
cbegin(size_t j)4428    Submatrix<MT,unaligned,true,true,CSAs...>::cbegin( size_t j ) const
4429 {
4430    BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
4431    return ConstIterator( matrix_.cbegin( column() + j ) + row(), isAligned_ );
4432 }
4433 /*! \endcond */
4434 //*************************************************************************************************
4435 
4436 
4437 //*************************************************************************************************
4438 /*! \cond BLAZE_INTERNAL */
4439 /*!\brief Returns an iterator just past the last non-zero element of column \a j.
4440 //
4441 // \param j The column index.
4442 // \return Iterator just past the last non-zero element of column \a j.
4443 */
4444 template< typename MT       // Type of the dense matrix
4445         , size_t... CSAs >  // Compile time submatrix arguments
4446 inline typename Submatrix<MT,unaligned,true,true,CSAs...>::Iterator
end(size_t j)4447    Submatrix<MT,unaligned,true,true,CSAs...>::end( size_t j )
4448 {
4449    BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
4450    return Iterator( matrix_.begin( column() + j ) + row() + rows(), isAligned_ );
4451 }
4452 /*! \endcond */
4453 //*************************************************************************************************
4454 
4455 
4456 //*************************************************************************************************
4457 /*! \cond BLAZE_INTERNAL */
4458 /*!\brief Returns an iterator just past the last non-zero element of column \a j.
4459 //
4460 // \param j The column index.
4461 // \return Iterator just past the last non-zero element of column \a j.
4462 */
4463 template< typename MT       // Type of the dense matrix
4464         , size_t... CSAs >  // Compile time submatrix arguments
4465 inline typename Submatrix<MT,unaligned,true,true,CSAs...>::ConstIterator
end(size_t j)4466    Submatrix<MT,unaligned,true,true,CSAs...>::end( size_t j ) const
4467 {
4468    BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
4469    return ConstIterator( matrix_.cbegin( column() + j ) + row() + rows(), isAligned_ );
4470 }
4471 /*! \endcond */
4472 //*************************************************************************************************
4473 
4474 
4475 //*************************************************************************************************
4476 /*! \cond BLAZE_INTERNAL */
4477 /*!\brief Returns an iterator just past the last non-zero element of column \a j.
4478 //
4479 // \param j The column index.
4480 // \return Iterator just past the last non-zero element of column \a j.
4481 */
4482 template< typename MT       // Type of the dense matrix
4483         , size_t... CSAs >  // Compile time submatrix arguments
4484 inline typename Submatrix<MT,unaligned,true,true,CSAs...>::ConstIterator
cend(size_t j)4485    Submatrix<MT,unaligned,true,true,CSAs...>::cend( size_t j ) const
4486 {
4487    BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
4488    return ConstIterator( matrix_.cbegin( column() + j ) + row() + rows(), isAligned_ );
4489 }
4490 /*! \endcond */
4491 //*************************************************************************************************
4492 
4493 
4494 
4495 
4496 //=================================================================================================
4497 //
4498 //  ASSIGNMENT OPERATORS
4499 //
4500 //=================================================================================================
4501 
4502 //*************************************************************************************************
4503 /*! \cond BLAZE_INTERNAL */
4504 /*!\brief Homogenous assignment to all submatrix elements.
4505 //
4506 // \param rhs Scalar value to be assigned to all submatrix elements.
4507 // \return Reference to the assigned submatrix.
4508 //
4509 // This function homogeneously assigns the given value to all dense matrix elements. Note that in
4510 // case the underlying dense matrix is a lower/upper matrix only lower/upper and diagonal elements
4511 // of the underlying matrix are modified.
4512 */
4513 template< typename MT       // Type of the dense matrix
4514         , size_t... CSAs >  // Compile time submatrix arguments
4515 inline Submatrix<MT,unaligned,true,true,CSAs...>&
4516    Submatrix<MT,unaligned,true,true,CSAs...>::operator=( const ElementType& rhs )
4517 {
4518    const size_t jend( column() + columns() );
4519    decltype(auto) left( derestrict( matrix_ ) );
4520 
4521    for( size_t j=column(); j<jend; ++j )
4522    {
4523       const size_t ibegin( ( IsLower_v<MT> )
4524                            ?( ( IsUniLower_v<MT> || IsStrictlyLower_v<MT> )
4525                               ?( max( j+1UL, row() ) )
4526                               :( max( j, row() ) ) )
4527                            :( row() ) );
4528       const size_t iend  ( ( IsUpper_v<MT> )
4529                            ?( ( IsUniUpper_v<MT> || IsStrictlyUpper_v<MT> )
4530                               ?( min( j, row()+rows() ) )
4531                               :( min( j+1UL, row()+rows() ) ) )
4532                            :( row()+rows() ) );
4533 
4534       for( size_t i=ibegin; i<iend; ++i ) {
4535          if( !IsRestricted_v<MT> || IsTriangular_v<MT> || trySet( matrix_, i, j, rhs ) )
4536             left(i,j) = rhs;
4537       }
4538    }
4539 
4540    return *this;
4541 }
4542 /*! \endcond */
4543 //*************************************************************************************************
4544 
4545 
4546 //*************************************************************************************************
4547 /*! \cond BLAZE_INTERNAL */
4548 /*!\brief List assignment to all submatrix elements.
4549 //
4550 // \param list The initializer list.
4551 // \exception std::invalid_argument Invalid assignment to submatrix.
4552 // \exception std::invalid_argument Invalid assignment to restricted matrix.
4553 //
4554 // This assignment operator offers the option to directly assign to all elements of the submatrix
4555 // by means of an initializer list. The submatrix elements are assigned the values from the given
4556 // initializer list. Missing values are initialized as default. Note that in case the size of the
4557 // top-level initializer list does not match the number of rows of the submatrix or the size of
4558 // any nested list exceeds the number of columns, a \a std::invalid_argument exception is thrown.
4559 // Also, if the underlying matrix \a MT is restricted and the assignment would violate an
4560 // invariant of the matrix, a \a std::invalid_argument exception is thrown.
4561 */
4562 template< typename MT       // Type of the dense matrix
4563         , size_t... CSAs >  // Compile time submatrix arguments
4564 inline Submatrix<MT,unaligned,true,true,CSAs...>&
4565    Submatrix<MT,unaligned,true,true,CSAs...>::operator=( initializer_list< initializer_list<ElementType> > list )
4566 {
4567    using blaze::reset;
4568 
4569    if( list.size() != rows() ) {
4570       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to submatrix" );
4571    }
4572 
4573    if( IsRestricted_v<MT> ) {
4574       const InitializerMatrix<ElementType> tmp( list, columns() );
4575       if( !tryAssign( matrix_, tmp, row(), column() ) ) {
4576          BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4577       }
4578    }
4579 
4580    decltype(auto) left( derestrict( *this ) );
4581    size_t i( 0UL );
4582 
4583    for( const auto& rowList : list ) {
4584       size_t j( 0UL );
4585       for( const auto& element : rowList ) {
4586          left(i,j) = element;
4587          ++j;
4588       }
4589       for( ; j<columns(); ++j ) {
4590          reset( left(i,j) );
4591       }
4592       ++i;
4593    }
4594 
4595    return *this;
4596 }
4597 /*! \endcond */
4598 //*************************************************************************************************
4599 
4600 
4601 //*************************************************************************************************
4602 /*! \cond BLAZE_INTERNAL */
4603 /*!\brief Copy assignment operator for Submatrix.
4604 //
4605 // \param rhs Sparse submatrix to be copied.
4606 // \return Reference to the assigned submatrix.
4607 // \exception std::invalid_argument Submatrix sizes do not match.
4608 // \exception std::invalid_argument Invalid assignment to restricted matrix.
4609 //
4610 // The dense submatrix is initialized as a copy of the given dense submatrix. In case the current
4611 // sizes of the two submatrices don't match, a \a std::invalid_argument exception is thrown. Also,
4612 // if the underlying matrix \a MT is a lower triangular, upper triangular, or symmetric matrix
4613 // and the assignment would violate its lower, upper, or symmetry property, respectively, a
4614 // \a std::invalid_argument exception is thrown.
4615 */
4616 template< typename MT       // Type of the dense matrix
4617         , size_t... CSAs >  // Compile time submatrix arguments
4618 inline Submatrix<MT,unaligned,true,true,CSAs...>&
4619    Submatrix<MT,unaligned,true,true,CSAs...>::operator=( const Submatrix& rhs )
4620 {
4621    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
4622    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
4623 
4624    if( this == &rhs || ( &matrix_ == &rhs.matrix_ && row() == rhs.row() && column() == rhs.column() ) )
4625       return *this;
4626 
4627    if( rows() != rhs.rows() || columns() != rhs.columns() ) {
4628       BLAZE_THROW_INVALID_ARGUMENT( "Submatrix sizes do not match" );
4629    }
4630 
4631    if( !tryAssign( matrix_, rhs, row(), column() ) ) {
4632       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4633    }
4634 
4635    decltype(auto) left( derestrict( *this ) );
4636 
4637    if( rhs.canAlias( this ) ) {
4638       const ResultType tmp( rhs );
4639       smpAssign( left, tmp );
4640    }
4641    else {
4642       smpAssign( left, rhs );
4643    }
4644 
4645    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4646 
4647    return *this;
4648 }
4649 /*! \endcond */
4650 //*************************************************************************************************
4651 
4652 
4653 //*************************************************************************************************
4654 /*! \cond BLAZE_INTERNAL */
4655 /*!\brief Assignment operator for different matrices.
4656 //
4657 // \param rhs Matrix to be assigned.
4658 // \return Reference to the assigned submatrix.
4659 // \exception std::invalid_argument Matrix sizes do not match.
4660 // \exception std::invalid_argument Invalid assignment to restricted matrix.
4661 //
4662 // The dense submatrix is initialized as a copy of the given matrix. In case the current sizes
4663 // of the two matrices don't match, a \a std::invalid_argument exception is thrown. Also, if
4664 // the underlying matrix \a MT is a lower triangular, upper triangular, or symmetric matrix
4665 // and the assignment would violate its lower, upper, or symmetry property, respectively, a
4666 // \a std::invalid_argument exception is thrown.
4667 */
4668 template< typename MT       // Type of the dense matrix
4669         , size_t... CSAs >  // Compile time submatrix arguments
4670 template< typename MT2      // Type of the right-hand side matrix
4671         , bool SO >         // Storage order of the right-hand side matrix
4672 inline Submatrix<MT,unaligned,true,true,CSAs...>&
4673    Submatrix<MT,unaligned,true,true,CSAs...>::operator=( const Matrix<MT2,SO>& rhs )
4674 {
4675    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
4676 
4677    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
4678       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4679    }
4680 
4681    using Right = If_t< IsRestricted_v<MT>, CompositeType_t<MT2>, const MT2& >;
4682    Right right( *rhs );
4683 
4684    if( !tryAssign( matrix_, right, row(), column() ) ) {
4685       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4686    }
4687 
4688    decltype(auto) left( derestrict( *this ) );
4689 
4690    if( IsReference_v<Right> && right.canAlias( this ) ) {
4691       const ResultType_t<MT2> tmp( right );
4692       if( IsSparseMatrix_v<MT2> )
4693          reset();
4694       smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
4695    }
4696    else {
4697       if( IsSparseMatrix_v<MT2> )
4698          reset();
4699       smpAssign( left, transIf< IsSymmetric_v<This> >( right ) );
4700    }
4701 
4702    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4703 
4704    return *this;
4705 }
4706 /*! \endcond */
4707 //*************************************************************************************************
4708 
4709 
4710 //*************************************************************************************************
4711 /*! \cond BLAZE_INTERNAL */
4712 /*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
4713 //
4714 // \param rhs The right-hand side matrix to be added to the submatrix.
4715 // \return Reference to the dense submatrix.
4716 // \exception std::invalid_argument Matrix sizes do not match.
4717 // \exception std::invalid_argument Invalid assignment to restricted matrix.
4718 //
4719 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
4720 // is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
4721 // symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
4722 // respectively, a \a std::invalid_argument exception is thrown.
4723 */
4724 template< typename MT       // Type of the dense matrix
4725         , size_t... CSAs >  // Compile time submatrix arguments
4726 template< typename MT2      // Type of the right-hand side matrix
4727         , bool SO  >        // Storage order of the right-hand side matrix
4728 inline auto Submatrix<MT,unaligned,true,true,CSAs...>::operator+=( const Matrix<MT2,SO>& rhs )
4729    -> DisableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >
4730 {
4731    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
4732    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
4733    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
4734 
4735    using AddType = AddTrait_t< ResultType, ResultType_t<MT2> >;
4736 
4737    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( AddType );
4738    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
4739 
4740    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
4741       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4742    }
4743 
4744    if( !tryAddAssign( matrix_, *rhs, row(), column() ) ) {
4745       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4746    }
4747 
4748    decltype(auto) left( derestrict( *this ) );
4749 
4750    if( ( ( IsSymmetric_v<MT> || IsHermitian_v<MT> ) && hasOverlap() ) || (*rhs).canAlias( this ) ) {
4751       const AddType tmp( *this + (*rhs) );
4752       smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
4753    }
4754    else {
4755       smpAddAssign( left, transIf< IsSymmetric_v<This> >( *rhs ) );
4756    }
4757 
4758    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4759 
4760    return *this;
4761 }
4762 /*! \endcond */
4763 //*************************************************************************************************
4764 
4765 
4766 //*************************************************************************************************
4767 /*! \cond BLAZE_INTERNAL */
4768 /*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
4769 //
4770 // \param rhs The right-hand side matrix to be added to the submatrix.
4771 // \return Reference to the dense submatrix.
4772 // \exception std::invalid_argument Matrix sizes do not match.
4773 // \exception std::invalid_argument Invalid assignment to restricted matrix.
4774 //
4775 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
4776 // is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
4777 // symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
4778 // respectively, a \a std::invalid_argument exception is thrown.
4779 */
4780 template< typename MT       // Type of the dense matrix
4781         , size_t... CSAs >  // Compile time submatrix arguments
4782 template< typename MT2      // Type of the right-hand side matrix
4783         , bool SO  >        // Storage order of the right-hand side matrix
4784 inline auto Submatrix<MT,unaligned,true,true,CSAs...>::operator+=( const Matrix<MT2,SO>& rhs )
4785    -> EnableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >
4786 {
4787    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
4788    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
4789    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
4790 
4791    using AddType = AddTrait_t< ResultType, ResultType_t<MT2> >;
4792 
4793    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( AddType );
4794    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
4795 
4796    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
4797       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4798    }
4799 
4800    const AddType tmp( *this + (*rhs) );
4801 
4802    if( !tryAssign( matrix_, tmp, row(), column() ) ) {
4803       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4804    }
4805 
4806    decltype(auto) left( derestrict( *this ) );
4807 
4808    smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
4809 
4810    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4811 
4812    return *this;
4813 }
4814 /*! \endcond */
4815 //*************************************************************************************************
4816 
4817 
4818 //*************************************************************************************************
4819 /*! \cond BLAZE_INTERNAL */
4820 /*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
4821 //
4822 // \param rhs The right-hand side matrix to be subtracted from the submatrix.
4823 // \return Reference to the dense submatrix.
4824 // \exception std::invalid_argument Matrix sizes do not match.
4825 // \exception std::invalid_argument Invalid assignment to restricted matrix.
4826 //
4827 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
4828 // is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
4829 // symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
4830 // respectively, a \a std::invalid_argument exception is thrown.
4831 */
4832 template< typename MT       // Type of the dense matrix
4833         , size_t... CSAs >  // Compile time submatrix arguments
4834 template< typename MT2      // Type of the right-hand side matrix
4835         , bool SO >         // Storage order of the right-hand side matrix
4836 inline auto Submatrix<MT,unaligned,true,true,CSAs...>::operator-=( const Matrix<MT2,SO>& rhs )
4837    -> DisableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >
4838 {
4839    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
4840    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
4841    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
4842 
4843    using SubType = SubTrait_t< ResultType, ResultType_t<MT2> >;
4844 
4845    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( SubType );
4846    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
4847 
4848    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
4849       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4850    }
4851 
4852    if( !trySubAssign( matrix_, *rhs, row(), column() ) ) {
4853       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4854    }
4855 
4856    decltype(auto) left( derestrict( *this ) );
4857 
4858    if( ( ( IsSymmetric_v<MT> || IsHermitian_v<MT> ) && hasOverlap() ) || (*rhs).canAlias( this ) ) {
4859       const SubType tmp( *this - (*rhs ) );
4860       smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
4861    }
4862    else {
4863       smpSubAssign( left, transIf< IsSymmetric_v<This> >( *rhs ) );
4864    }
4865 
4866    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4867 
4868    return *this;
4869 }
4870 /*! \endcond */
4871 //*************************************************************************************************
4872 
4873 
4874 //*************************************************************************************************
4875 /*! \cond BLAZE_INTERNAL */
4876 /*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
4877 //
4878 // \param rhs The right-hand side matrix to be subtracted from the submatrix.
4879 // \return Reference to the dense submatrix.
4880 // \exception std::invalid_argument Matrix sizes do not match.
4881 // \exception std::invalid_argument Invalid assignment to restricted matrix.
4882 //
4883 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
4884 // is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
4885 // symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
4886 // respectively, a \a std::invalid_argument exception is thrown.
4887 */
4888 template< typename MT       // Type of the dense matrix
4889         , size_t... CSAs >  // Compile time submatrix arguments
4890 template< typename MT2      // Type of the right-hand side matrix
4891         , bool SO >         // Storage order of the right-hand side matrix
4892 inline auto Submatrix<MT,unaligned,true,true,CSAs...>::operator-=( const Matrix<MT2,SO>& rhs )
4893    -> EnableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >
4894 {
4895    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
4896    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
4897    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
4898 
4899    using SubType = SubTrait_t< ResultType, ResultType_t<MT2> >;
4900 
4901    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( SubType );
4902    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
4903 
4904    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
4905       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4906    }
4907 
4908    const SubType tmp( *this - (*rhs) );
4909 
4910    if( !tryAssign( matrix_, tmp, row(), column() ) ) {
4911       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4912    }
4913 
4914    decltype(auto) left( derestrict( *this ) );
4915 
4916    smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
4917 
4918    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4919 
4920    return *this;
4921 }
4922 /*! \endcond */
4923 //*************************************************************************************************
4924 
4925 
4926 //*************************************************************************************************
4927 /*! \cond BLAZE_INTERNAL */
4928 /*!\brief Schur product assignment operator for the multiplication of a matrix (\f$ A=B \f$).
4929 //
4930 // \param rhs The right-hand side matrix for the Schur product.
4931 // \return Reference to the dense submatrix.
4932 // \exception std::invalid_argument Matrix sizes do not match.
4933 // \exception std::invalid_argument Invalid assignment to restricted matrix.
4934 //
4935 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
4936 // is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
4937 // symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
4938 // respectively, a \a std::invalid_argument exception is thrown.
4939 */
4940 template< typename MT       // Type of the dense matrix
4941         , size_t... CSAs >  // Compile time submatrix arguments
4942 template< typename MT2      // Type of the right-hand side matrix
4943         , bool SO  >        // Storage order of the right-hand side matrix
4944 inline auto Submatrix<MT,unaligned,true,true,CSAs...>::operator%=( const Matrix<MT2,SO>& rhs )
4945    -> DisableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >
4946 {
4947    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
4948    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
4949    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
4950 
4951    using SchurType = SchurTrait_t< ResultType, ResultType_t<MT2> >;
4952 
4953    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SchurType );
4954 
4955    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
4956       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
4957    }
4958 
4959    if( !trySchurAssign( matrix_, *rhs, row(), column() ) ) {
4960       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
4961    }
4962 
4963    decltype(auto) left( derestrict( *this ) );
4964 
4965    if( ( ( IsSymmetric_v<MT> || IsHermitian_v<MT> ) && hasOverlap() ) || (*rhs).canAlias( this ) ) {
4966       const SchurType tmp( *this % (*rhs) );
4967       if( IsSparseMatrix_v<SchurType> )
4968          reset();
4969       smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
4970    }
4971    else {
4972       smpSchurAssign( left, transIf< IsSymmetric_v<This> >( *rhs ) );
4973    }
4974 
4975    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
4976 
4977    return *this;
4978 }
4979 /*! \endcond */
4980 //*************************************************************************************************
4981 
4982 
4983 //*************************************************************************************************
4984 /*! \cond BLAZE_INTERNAL */
4985 /*!\brief Schur product assignment operator for the multiplication of a matrix (\f$ A=B \f$).
4986 //
4987 // \param rhs The right-hand side matrix for the Schur product.
4988 // \return Reference to the dense submatrix.
4989 // \exception std::invalid_argument Matrix sizes do not match.
4990 // \exception std::invalid_argument Invalid assignment to restricted matrix.
4991 //
4992 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
4993 // is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
4994 // symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
4995 // respectively, a \a std::invalid_argument exception is thrown.
4996 */
4997 template< typename MT       // Type of the dense matrix
4998         , size_t... CSAs >  // Compile time submatrix arguments
4999 template< typename MT2      // Type of the right-hand side matrix
5000         , bool SO  >        // Storage order of the right-hand side matrix
5001 inline auto Submatrix<MT,unaligned,true,true,CSAs...>::operator%=( const Matrix<MT2,SO>& rhs )
5002    -> EnableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >
5003 {
5004    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
5005    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
5006    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
5007 
5008    using SchurType = SchurTrait_t< ResultType, ResultType_t<MT2> >;
5009 
5010    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SchurType );
5011 
5012    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
5013       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
5014    }
5015 
5016    const SchurType tmp( *this % (*rhs) );
5017 
5018    if( !tryAssign( matrix_, tmp, row(), column() ) ) {
5019       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
5020    }
5021 
5022    decltype(auto) left( derestrict( *this ) );
5023 
5024    if( IsSparseMatrix_v<SchurType> ) {
5025       reset();
5026    }
5027 
5028    smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
5029 
5030    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
5031 
5032    return *this;
5033 }
5034 /*! \endcond */
5035 //*************************************************************************************************
5036 
5037 
5038 
5039 
5040 //=================================================================================================
5041 //
5042 //  UTILITY FUNCTIONS
5043 //
5044 //=================================================================================================
5045 
5046 //*************************************************************************************************
5047 /*! \cond BLAZE_INTERNAL */
5048 /*!\brief Returns the matrix containing the submatrix.
5049 //
5050 // \return The matrix containing the submatrix.
5051 */
5052 template< typename MT       // Type of the dense matrix
5053         , size_t... CSAs >  // Compile time submatrix arguments
operand()5054 inline MT& Submatrix<MT,unaligned,true,true,CSAs...>::operand() noexcept
5055 {
5056    return matrix_;
5057 }
5058 /*! \endcond */
5059 //*************************************************************************************************
5060 
5061 
5062 //*************************************************************************************************
5063 /*! \cond BLAZE_INTERNAL */
5064 /*!\brief Returns the matrix containing the submatrix.
5065 //
5066 // \return The matrix containing the submatrix.
5067 */
5068 template< typename MT       // Type of the dense matrix
5069         , size_t... CSAs >  // Compile time submatrix arguments
operand()5070 inline const MT& Submatrix<MT,unaligned,true,true,CSAs...>::operand() const noexcept
5071 {
5072    return matrix_;
5073 }
5074 /*! \endcond */
5075 //*************************************************************************************************
5076 
5077 
5078 //*************************************************************************************************
5079 /*! \cond BLAZE_INTERNAL */
5080 /*!\brief Returns the spacing between the beginning of two columns.
5081 //
5082 // \return The spacing between the beginning of two columns.
5083 //
5084 // This function returns the spacing between the beginning of two columns, i.e. the total
5085 // number of elements of a column.
5086 */
5087 template< typename MT       // Type of the dense matrix
5088         , size_t... CSAs >  // Compile time submatrix arguments
spacing()5089 inline size_t Submatrix<MT,unaligned,true,true,CSAs...>::spacing() const noexcept
5090 {
5091    return matrix_.spacing();
5092 }
5093 /*! \endcond */
5094 //*************************************************************************************************
5095 
5096 
5097 //*************************************************************************************************
5098 /*! \cond BLAZE_INTERNAL */
5099 /*!\brief Returns the maximum capacity of the dense submatrix.
5100 //
5101 // \return The capacity of the dense submatrix.
5102 */
5103 template< typename MT       // Type of the dense matrix
5104         , size_t... CSAs >  // Compile time submatrix arguments
capacity()5105 inline size_t Submatrix<MT,unaligned,true,true,CSAs...>::capacity() const noexcept
5106 {
5107    return rows() * columns();
5108 }
5109 /*! \endcond */
5110 //*************************************************************************************************
5111 
5112 
5113 //*************************************************************************************************
5114 /*! \cond BLAZE_INTERNAL */
5115 /*!\brief Returns the current capacity of the specified column.
5116 //
5117 // \param j The index of the column.
5118 // \return The current capacity of column \a j.
5119 */
5120 template< typename MT       // Type of the dense matrix
5121         , size_t... CSAs >  // Compile time submatrix arguments
capacity(size_t j)5122 inline size_t Submatrix<MT,unaligned,true,true,CSAs...>::capacity( size_t j ) const noexcept
5123 {
5124    MAYBE_UNUSED( j );
5125 
5126    BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
5127 
5128    return rows();
5129 }
5130 /*! \endcond */
5131 //*************************************************************************************************
5132 
5133 
5134 //*************************************************************************************************
5135 /*! \cond BLAZE_INTERNAL */
5136 /*!\brief Returns the number of non-zero elements in the dense submatrix
5137 //
5138 // \return The number of non-zero elements in the dense submatrix.
5139 */
5140 template< typename MT       // Type of the dense matrix
5141         , size_t... CSAs >  // Compile time submatrix arguments
nonZeros()5142 inline size_t Submatrix<MT,unaligned,true,true,CSAs...>::nonZeros() const
5143 {
5144    const size_t iend( row() + rows() );
5145    const size_t jend( column() + columns() );
5146    size_t nonzeros( 0UL );
5147 
5148    for( size_t j=column(); j<jend; ++j )
5149       for( size_t i=row(); i<iend; ++i )
5150          if( !isDefault( matrix_(i,j) ) )
5151             ++nonzeros;
5152 
5153    return nonzeros;
5154 }
5155 /*! \endcond */
5156 //*************************************************************************************************
5157 
5158 
5159 //*************************************************************************************************
5160 /*! \cond BLAZE_INTERNAL */
5161 /*!\brief Returns the number of non-zero elements in the specified column.
5162 //
5163 // \param j The index of the column.
5164 // \return The number of non-zero elements of column \a j.
5165 */
5166 template< typename MT       // Type of the dense matrix
5167         , size_t... CSAs >  // Compile time submatrix arguments
nonZeros(size_t j)5168 inline size_t Submatrix<MT,unaligned,true,true,CSAs...>::nonZeros( size_t j ) const
5169 {
5170    BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
5171 
5172    const size_t iend( row() + rows() );
5173    size_t nonzeros( 0UL );
5174 
5175    for( size_t i=row(); i<iend; ++i )
5176       if( !isDefault( matrix_(i,column()+j) ) )
5177          ++nonzeros;
5178 
5179    return nonzeros;
5180 }
5181 /*! \endcond */
5182 //*************************************************************************************************
5183 
5184 
5185 //*************************************************************************************************
5186 /*! \cond BLAZE_INTERNAL */
5187 /*!\brief Reset to the default initial values.
5188 //
5189 // \return void
5190 */
5191 template< typename MT       // Type of the dense matrix
5192         , size_t... CSAs >  // Compile time submatrix arguments
reset()5193 inline void Submatrix<MT,unaligned,true,true,CSAs...>::reset()
5194 {
5195    using blaze::clear;
5196 
5197    for( size_t j=column(); j<column()+columns(); ++j )
5198    {
5199       const size_t ibegin( ( IsLower_v<MT> )
5200                            ?( ( IsUniLower_v<MT> || IsStrictlyLower_v<MT> )
5201                               ?( max( j+1UL, row() ) )
5202                               :( max( j, row() ) ) )
5203                            :( row() ) );
5204       const size_t iend  ( ( IsUpper_v<MT> )
5205                            ?( ( IsUniUpper_v<MT> || IsStrictlyUpper_v<MT> )
5206                               ?( min( j, row()+rows() ) )
5207                               :( min( j+1UL, row()+rows() ) ) )
5208                            :( row()+rows() ) );
5209 
5210       for( size_t i=ibegin; i<iend; ++i )
5211          clear( matrix_(i,j) );
5212    }
5213 }
5214 /*! \endcond */
5215 //*************************************************************************************************
5216 
5217 
5218 //*************************************************************************************************
5219 /*! \cond BLAZE_INTERNAL */
5220 /*!\brief Reset the specified column to the default initial values.
5221 //
5222 // \param j The index of the column.
5223 // \return void
5224 */
5225 template< typename MT       // Type of the dense matrix
5226         , size_t... CSAs >  // Compile time submatrix arguments
reset(size_t j)5227 inline void Submatrix<MT,unaligned,true,true,CSAs...>::reset( size_t j )
5228 {
5229    using blaze::clear;
5230 
5231    BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
5232 
5233    const size_t ibegin( ( IsLower_v<MT> )
5234                         ?( ( IsUniLower_v<MT> || IsStrictlyLower_v<MT> )
5235                            ?( max( j+1UL, row() ) )
5236                            :( max( j, row() ) ) )
5237                         :( row() ) );
5238    const size_t iend  ( ( IsUpper_v<MT> )
5239                         ?( ( IsUniUpper_v<MT> || IsStrictlyUpper_v<MT> )
5240                            ?( min( j, row()+rows() ) )
5241                            :( min( j+1UL, row()+rows() ) ) )
5242                         :( row()+rows() ) );
5243 
5244    for( size_t i=ibegin; i<iend; ++i )
5245       clear( matrix_(i,column()+j) );
5246 }
5247 /*! \endcond */
5248 //*************************************************************************************************
5249 
5250 
5251 //*************************************************************************************************
5252 /*! \cond BLAZE_INTERNAL */
5253 /*!\brief Checking whether there exists an overlap in the context of a symmetric matrix.
5254 //
5255 // \return \a true in case an overlap exists, \a false if not.
5256 //
5257 // This function checks if in the context of a symmetric matrix the submatrix has an overlap with
5258 // its counterpart. In case an overlap exists, the function return \a true, otherwise it returns
5259 // \a false.
5260 */
5261 template< typename MT       // Type of the dense matrix
5262         , size_t... CSAs >  // Compile time submatrix arguments
hasOverlap()5263 inline bool Submatrix<MT,unaligned,true,true,CSAs...>::hasOverlap() const noexcept
5264 {
5265    BLAZE_INTERNAL_ASSERT( IsSymmetric_v<MT> || IsHermitian_v<MT>, "Invalid matrix detected" );
5266 
5267    if( ( row() + rows() <= column() ) || ( column() + columns() <= row() ) )
5268       return false;
5269    else return true;
5270 }
5271 /*! \endcond */
5272 //*************************************************************************************************
5273 
5274 
5275 
5276 
5277 //=================================================================================================
5278 //
5279 //  NUMERIC FUNCTIONS
5280 //
5281 //=================================================================================================
5282 
5283 //*************************************************************************************************
5284 /*! \cond BLAZE_INTERNAL */
5285 /*!\brief In-place transpose of the submatrix.
5286 //
5287 // \return Reference to the transposed submatrix.
5288 // \exception std::logic_error Invalid transpose of a non-quadratic submatrix.
5289 // \exception std::logic_error Invalid transpose operation.
5290 //
5291 // This function transposes the dense submatrix in-place. Note that this function can only be used
5292 // for quadratic submatrices, i.e. if the number of rows is equal to the number of columns. Also,
5293 // the function fails if ...
5294 //
5295 //  - ... the submatrix contains elements from the upper part of the underlying lower matrix;
5296 //  - ... the submatrix contains elements from the lower part of the underlying upper matrix;
5297 //  - ... the result would be non-deterministic in case of a symmetric or Hermitian matrix.
5298 //
5299 // In all cases, a \a std::logic_error is thrown.
5300 */
5301 template< typename MT       // Type of the dense matrix
5302         , size_t... CSAs >  // Compile time submatrix arguments
5303 inline Submatrix<MT,unaligned,true,true,CSAs...>&
transpose()5304    Submatrix<MT,unaligned,true,true,CSAs...>::transpose()
5305 {
5306    if( rows() != columns() ) {
5307       BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
5308    }
5309 
5310    if( !tryAssign( matrix_, trans( *this ), row(), column() ) ) {
5311       BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
5312    }
5313 
5314    decltype(auto) left( derestrict( *this ) );
5315    const ResultType tmp( trans( *this ) );
5316 
5317    smpAssign( left, tmp );
5318 
5319    return *this;
5320 }
5321 /*! \endcond */
5322 //*************************************************************************************************
5323 
5324 
5325 //*************************************************************************************************
5326 /*! \cond BLAZE_INTERNAL */
5327 /*!\brief In-place conjugate transpose of the submatrix.
5328 //
5329 // \return Reference to the transposed submatrix.
5330 // \exception std::logic_error Invalid transpose of a non-quadratic submatrix.
5331 // \exception std::logic_error Invalid transpose operation.
5332 //
5333 // This function transposes the dense submatrix in-place. Note that this function can only be used
5334 // for quadratic submatrices, i.e. if the number of rows is equal to the number of columns. Also,
5335 // the function fails if ...
5336 //
5337 //  - ... the submatrix contains elements from the upper part of the underlying lower matrix;
5338 //  - ... the submatrix contains elements from the lower part of the underlying upper matrix;
5339 //  - ... the result would be non-deterministic in case of a symmetric or Hermitian matrix.
5340 //
5341 // In all cases, a \a std::logic_error is thrown.
5342 */
5343 template< typename MT       // Type of the dense matrix
5344         , size_t... CSAs >  // Compile time submatrix arguments
5345 inline Submatrix<MT,unaligned,true,true,CSAs...>&
ctranspose()5346    Submatrix<MT,unaligned,true,true,CSAs...>::ctranspose()
5347 {
5348    if( rows() != columns() ) {
5349       BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
5350    }
5351 
5352    if( !tryAssign( matrix_, ctrans( *this ), row(), column() ) ) {
5353       BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
5354    }
5355 
5356    decltype(auto) left( derestrict( *this ) );
5357    const ResultType tmp( ctrans( *this ) );
5358 
5359    smpAssign( left, tmp );
5360 
5361    return *this;
5362 }
5363 /*! \endcond */
5364 //*************************************************************************************************
5365 
5366 
5367 //*************************************************************************************************
5368 /*! \cond BLAZE_INTERNAL */
5369 /*!\brief Scaling of the dense submatrix by the scalar value \a scalar (\f$ A=B*s \f$).
5370 //
5371 // \param scalar The scalar value for the submatrix scaling.
5372 // \return Reference to the dense submatrix.
5373 //
5374 // This function scales the submatrix by applying the given scalar value \a scalar to each
5375 // element of the submatrix. For built-in and \c complex data types it has the same effect
5376 // as using the multiplication assignment operator. Note that the function cannot be used
5377 // to scale a submatrix on a lower or upper unitriangular matrix. The attempt to scale
5378 // such a submatrix results in a compile time error!
5379 */
5380 template< typename MT       // Type of the dense matrix
5381         , size_t... CSAs >  // Compile time submatrix arguments
5382 template< typename Other >  // Data type of the scalar value
5383 inline Submatrix<MT,unaligned,true,true,CSAs...>&
scale(const Other & scalar)5384    Submatrix<MT,unaligned,true,true,CSAs...>::scale( const Other& scalar )
5385 {
5386    BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
5387 
5388    const size_t jend( column() + columns() );
5389 
5390    for( size_t j=column(); j<jend; ++j )
5391    {
5392       const size_t ibegin( ( IsLower_v<MT> )
5393                            ?( ( IsStrictlyLower_v<MT> )
5394                               ?( max( j+1UL, row() ) )
5395                               :( max( j, row() ) ) )
5396                            :( row() ) );
5397       const size_t iend  ( ( IsUpper_v<MT> )
5398                            ?( ( IsStrictlyUpper_v<MT> )
5399                               ?( min( j, row()+rows() ) )
5400                               :( min( j+1UL, row()+rows() ) ) )
5401                            :( row()+rows() ) );
5402 
5403       for( size_t i=ibegin; i<iend; ++i )
5404          matrix_(i,j) *= scalar;
5405    }
5406 
5407    return *this;
5408 }
5409 /*! \endcond */
5410 //*************************************************************************************************
5411 
5412 
5413 
5414 
5415 //=================================================================================================
5416 //
5417 //  EXPRESSION TEMPLATE EVALUATION FUNCTIONS
5418 //
5419 //=================================================================================================
5420 
5421 //*************************************************************************************************
5422 /*! \cond BLAZE_INTERNAL */
5423 /*!\brief Returns whether the submatrix can alias with the given address \a alias.
5424 //
5425 // \param alias The alias to be checked.
5426 // \return \a true in case the alias corresponds to this submatrix, \a false if not.
5427 //
5428 // This function returns whether the given address can alias with the submatrix. In contrast
5429 // to the isAliased() function this function is allowed to use compile time expressions to
5430 // optimize the evaluation.
5431 */
5432 template< typename MT       // Type of the dense matrix
5433         , size_t... CSAs >  // Compile time submatrix arguments
5434 template< typename Other >  // Data type of the foreign expression
canAlias(const Other * alias)5435 inline bool Submatrix<MT,unaligned,true,true,CSAs...>::canAlias( const Other* alias ) const noexcept
5436 {
5437    return matrix_.isAliased( &unview( *alias ) );
5438 }
5439 /*! \endcond */
5440 //*************************************************************************************************
5441 
5442 
5443 //*************************************************************************************************
5444 /*! \cond BLAZE_INTERNAL */
5445 /*!\brief Returns whether the submatrix can alias with the given dense submatrix \a alias.
5446 //
5447 // \param alias The alias to be checked.
5448 // \return \a true in case the alias corresponds to this submatrix, \a false if not.
5449 //
5450 // This function returns whether the given address can alias with the submatrix. In contrast
5451 // to the isAliased() function this function is allowed to use compile time expressions to
5452 // optimize the evaluation.
5453 */
5454 template< typename MT        // Type of the dense matrix
5455         , size_t... CSAs >   // Compile time submatrix arguments
5456 template< typename MT2       // Data type of the foreign dense submatrix
5457         , AlignmentFlag AF2  // Alignment flag of the foreign dense submatrix
5458         , bool SO2           // Storage order of the foreign dense submatrix
5459         , size_t... CSAs2 >  // Compile time submatrix arguments of the foreign dense submatrix
5460 inline bool
canAlias(const Submatrix<MT2,AF2,SO2,true,CSAs2...> * alias)5461    Submatrix<MT,unaligned,true,true,CSAs...>::canAlias( const Submatrix<MT2,AF2,SO2,true,CSAs2...>* alias ) const noexcept
5462 {
5463    return ( matrix_.isAliased( &alias->matrix_ ) &&
5464             ( row() + rows() > alias->row() ) &&
5465             ( row() < alias->row() + alias->rows() ) &&
5466             ( column() + columns() > alias->column() ) &&
5467             ( column() < alias->column() + alias->columns() ) );
5468 }
5469 /*! \endcond */
5470 //*************************************************************************************************
5471 
5472 
5473 //*************************************************************************************************
5474 /*! \cond BLAZE_INTERNAL */
5475 /*!\brief Returns whether the submatrix is aliased with the given address \a alias.
5476 //
5477 // \param alias The alias to be checked.
5478 // \return \a true in case the alias corresponds to this submatrix, \a false if not.
5479 //
5480 // This function returns whether the given address is aliased with the submatrix. In contrast
5481 // to the canAlias() function this function is not allowed to use compile time expressions to
5482 // optimize the evaluation.
5483 */
5484 template< typename MT       // Type of the dense matrix
5485         , size_t... CSAs >  // Compile time submatrix arguments
5486 template< typename Other >  // Data type of the foreign expression
isAliased(const Other * alias)5487 inline bool Submatrix<MT,unaligned,true,true,CSAs...>::isAliased( const Other* alias ) const noexcept
5488 {
5489    return matrix_.isAliased( &unview( *alias ) );
5490 }
5491 /*! \endcond */
5492 //*************************************************************************************************
5493 
5494 
5495 //*************************************************************************************************
5496 /*! \cond BLAZE_INTERNAL */
5497 /*!\brief Returns whether the submatrix is aliased with the given dense submatrix \a alias.
5498 //
5499 // \param alias The alias to be checked.
5500 // \return \a true in case the alias corresponds to this submatrix, \a false if not.
5501 //
5502 // This function returns whether the given address is aliased with the submatrix. In contrast
5503 // to the canAlias() function this function is not allowed to use compile time expressions to
5504 // optimize the evaluation.
5505 */
5506 template< typename MT        // Type of the dense matrix
5507         , size_t... CSAs >   // Compile time submatrix arguments
5508 template< typename MT2       // Data type of the foreign dense submatrix
5509         , AlignmentFlag AF2  // Alignment flag of the foreign dense submatrix
5510         , bool SO2           // Storage order of the foreign dense submatrix
5511         , size_t... CSAs2 >  // Compile time submatrix arguments of the foreign dense submatrix
5512 inline bool
isAliased(const Submatrix<MT2,AF2,SO2,true,CSAs2...> * alias)5513    Submatrix<MT,unaligned,true,true,CSAs...>::isAliased( const Submatrix<MT2,AF2,SO2,true,CSAs2...>* alias ) const noexcept
5514 {
5515    return ( matrix_.isAliased( &alias->matrix_ ) &&
5516             ( row() + rows() > alias->row() ) &&
5517             ( row() < alias->row() + alias->rows() ) &&
5518             ( column() + columns() > alias->column() ) &&
5519             ( column() < alias->column() + alias->columns() ) );
5520 }
5521 /*! \endcond */
5522 //*************************************************************************************************
5523 
5524 
5525 //*************************************************************************************************
5526 /*! \cond BLAZE_INTERNAL */
5527 /*!\brief Returns whether the submatrix is properly aligned in memory.
5528 //
5529 // \return \a true in case the submatrix is aligned, \a false if not.
5530 //
5531 // This function returns whether the submatrix is guaranteed to be properly aligned in memory,
5532 // i.e. whether the beginning and the end of each column of the submatrix are guaranteed to
5533 // conform to the alignment restrictions of the underlying element type.
5534 */
5535 template< typename MT       // Type of the dense matrix
5536         , size_t... CSAs >  // Compile time submatrix arguments
isAligned()5537 inline bool Submatrix<MT,unaligned,true,true,CSAs...>::isAligned() const noexcept
5538 {
5539    return isAligned_;
5540 }
5541 /*! \endcond */
5542 //*************************************************************************************************
5543 
5544 
5545 //*************************************************************************************************
5546 /*! \cond BLAZE_INTERNAL */
5547 /*!\brief Returns whether the submatrix can be used in SMP assignments.
5548 //
5549 // \return \a true in case the submatrix can be used in SMP assignments, \a false if not.
5550 //
5551 // This function returns whether the submatrix can be used in SMP assignments. In contrast to the
5552 // \a smpAssignable member enumeration, which is based solely on compile time information, this
5553 // function additionally provides runtime information (as for instance the current number of
5554 // rows and/or columns of the submatrix).
5555 */
5556 template< typename MT       // Type of the dense matrix
5557         , size_t... CSAs >  // Compile time submatrix arguments
canSMPAssign()5558 inline bool Submatrix<MT,unaligned,true,true,CSAs...>::canSMPAssign() const noexcept
5559 {
5560    return ( rows() * columns() >= SMP_DMATASSIGN_THRESHOLD );
5561 }
5562 /*! \endcond */
5563 //*************************************************************************************************
5564 
5565 
5566 //*************************************************************************************************
5567 /*! \cond BLAZE_INTERNAL */
5568 /*!\brief Load of a SIMD element of the submatrix.
5569 //
5570 // \param i Access index for the row. The index has to be in the range [0..M-1].
5571 // \param j Access index for the column. The index has to be in the range [0..N-1].
5572 // \return The loaded SIMD element.
5573 //
5574 // This function performs a load of a specific SIMD element of the dense submatrix. The row
5575 // index must be smaller than the number of rows and the column index must be smaller than
5576 // the number of columns. Additionally, the row index must be a multiple of the number of
5577 // values inside the SIMD element. This function must \b NOT be called explicitly! It is
5578 // used internally for the performance optimized evaluation of expression templates. Calling
5579 // this function explicitly might result in erroneous results and/or in compilation errors.
5580 */
5581 template< typename MT       // Type of the dense matrix
5582         , size_t... CSAs >  // Compile time submatrix arguments
5583 BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,true,true,CSAs...>::SIMDType
load(size_t i,size_t j)5584    Submatrix<MT,unaligned,true,true,CSAs...>::load( size_t i, size_t j ) const noexcept
5585 {
5586    if( isAligned_ )
5587       return loada( i, j );
5588    else
5589       return loadu( i, j );
5590 }
5591 /*! \endcond */
5592 //*************************************************************************************************
5593 
5594 
5595 //*************************************************************************************************
5596 /*! \cond BLAZE_INTERNAL */
5597 /*!\brief Aligned load of a SIMD element of the submatrix.
5598 //
5599 // \param i Access index for the row. The index has to be in the range [0..M-1].
5600 // \param j Access index for the column. The index has to be in the range [0..N-1].
5601 // \return The loaded SIMD element.
5602 //
5603 // This function performs an aligned load of a specific SIMD element of the dense submatrix.
5604 // The row index must be smaller than the number of rows and the column index must be smaller
5605 // than the number of columns. Additionally, the row index must be a multiple of the number
5606 // of values inside the SIMD element. This function must \b NOT be called explicitly! It is
5607 // used internally for the performance optimized evaluation of expression templates. Calling
5608 // this function explicitly might result in erroneous results and/or in compilation errors.
5609 */
5610 template< typename MT       // Type of the dense matrix
5611         , size_t... CSAs >  // Compile time submatrix arguments
5612 BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,true,true,CSAs...>::SIMDType
loada(size_t i,size_t j)5613    Submatrix<MT,unaligned,true,true,CSAs...>::loada( size_t i, size_t j ) const noexcept
5614 {
5615    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
5616 
5617    BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
5618    BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
5619    BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
5620    BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
5621 
5622    return matrix_.loada( row()+i, column()+j );
5623 }
5624 /*! \endcond */
5625 //*************************************************************************************************
5626 
5627 
5628 //*************************************************************************************************
5629 /*! \cond BLAZE_INTERNAL */
5630 /*!\brief Unaligned load of a SIMD element of the submatrix.
5631 //
5632 // \param i Access index for the row. The index has to be in the range [0..M-1].
5633 // \param j Access index for the column. The index has to be in the range [0..N-1].
5634 // \return The loaded SIMD element.
5635 //
5636 // This function performs an unaligned load of a specific SIMD element of the dense submatrix.
5637 // The row index must be smaller than the number of rows and the column index must be smaller
5638 // than the number of columns. Additionally, the row index must be a multiple of the number
5639 // of values inside the SIMD element. This function must \b NOT be called explicitly! It is
5640 // used internally for the performance optimized evaluation of expression templates. Calling
5641 // this function explicitly might result in erroneous results and/or in compilation errors.
5642 */
5643 template< typename MT       // Type of the dense matrix
5644         , size_t... CSAs >  // Compile time submatrix arguments
5645 BLAZE_ALWAYS_INLINE typename Submatrix<MT,unaligned,true,true,CSAs...>::SIMDType
loadu(size_t i,size_t j)5646    Submatrix<MT,unaligned,true,true,CSAs...>::loadu( size_t i, size_t j ) const noexcept
5647 {
5648    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
5649 
5650    BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
5651    BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
5652    BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
5653 
5654    return matrix_.loadu( row()+i, column()+j );
5655 }
5656 /*! \endcond */
5657 //*************************************************************************************************
5658 
5659 
5660 //*************************************************************************************************
5661 /*! \cond BLAZE_INTERNAL */
5662 /*!\brief Store of a SIMD element of the submatrix.
5663 //
5664 // \param i Access index for the row. The index has to be in the range [0..M-1].
5665 // \param j Access index for the column. The index has to be in the range [0..N-1].
5666 // \param value The SIMD element to be stored.
5667 // \return void
5668 //
5669 // This function performs a store of a specific SIMD element of the dense submatrix. The
5670 // row index must be smaller than the number of rows and the column index must be smaller
5671 // than the number of columns. Additionally, the row index must be a multiple of the number
5672 // of values inside the SIMD element. This function must \b NOT be called explicitly! It is
5673 // used internally for the performance optimized evaluation of expression templates. Calling
5674 // this function explicitly might result in erroneous results and/or in compilation errors.
5675 */
5676 template< typename MT       // Type of the dense matrix
5677         , size_t... CSAs >  // Compile time submatrix arguments
5678 BLAZE_ALWAYS_INLINE void
store(size_t i,size_t j,const SIMDType & value)5679    Submatrix<MT,unaligned,true,true,CSAs...>::store( size_t i, size_t j, const SIMDType& value ) noexcept
5680 {
5681    if( isAligned_ )
5682       storea( i, j, value );
5683    else
5684       storeu( i, j, value );
5685 }
5686 /*! \endcond */
5687 //*************************************************************************************************
5688 
5689 
5690 //*************************************************************************************************
5691 /*! \cond BLAZE_INTERNAL */
5692 /*!\brief Aligned store of a SIMD element of the submatrix.
5693 //
5694 // \param i Access index for the row. The index has to be in the range [0..M-1].
5695 // \param j Access index for the column. The index has to be in the range [0..N-1].
5696 // \param value The SIMD element to be stored.
5697 // \return void
5698 //
5699 // This function performs an aligned store of a specific SIMD element of the dense submatrix.
5700 // The row index must be smaller than the number of rows and the column index must be smaller
5701 // than the number of columns. Additionally, the row index must be a multiple of the number of
5702 // values inside the SIMD element. This function must \b NOT be called explicitly! It is used
5703 // internally for the performance optimized evaluation of expression templates. Calling this
5704 // function explicitly might result in erroneous results and/or in compilation errors.
5705 */
5706 template< typename MT       // Type of the dense matrix
5707         , size_t... CSAs >  // Compile time submatrix arguments
5708 BLAZE_ALWAYS_INLINE void
storea(size_t i,size_t j,const SIMDType & value)5709    Submatrix<MT,unaligned,true,true,CSAs...>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
5710 {
5711    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
5712 
5713    BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
5714    BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
5715    BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
5716    BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
5717 
5718    matrix_.storea( row()+i, column()+j, value );
5719 }
5720 /*! \endcond */
5721 //*************************************************************************************************
5722 
5723 
5724 //*************************************************************************************************
5725 /*! \cond BLAZE_INTERNAL */
5726 /*!\brief Unaligned store of a SIMD element of the submatrix.
5727 //
5728 // \param i Access index for the row. The index has to be in the range [0..M-1].
5729 // \param j Access index for the column. The index has to be in the range [0..N-1].
5730 // \param value The SIMD element to be stored.
5731 // \return void
5732 //
5733 // This function performs an unaligned store of a specific SIMD element of the dense submatrix.
5734 // The row index must be smaller than the number of rows and the column index must be smaller
5735 // than the number of columns. Additionally, the row index must be a multiple of the number of
5736 // values inside the SIMD element. This function must \b NOT be called explicitly! It is used
5737 // internally for the performance optimized evaluation of expression templates. Calling this
5738 // function explicitly might result in erroneous results and/or in compilation errors.
5739 */
5740 template< typename MT       // Type of the dense matrix
5741         , size_t... CSAs >  // Compile time submatrix arguments
5742 BLAZE_ALWAYS_INLINE void
storeu(size_t i,size_t j,const SIMDType & value)5743    Submatrix<MT,unaligned,true,true,CSAs...>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
5744 {
5745    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
5746 
5747    BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
5748    BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
5749    BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
5750 
5751    matrix_.storeu( row()+i, column()+j, value );
5752 }
5753 /*! \endcond */
5754 //*************************************************************************************************
5755 
5756 
5757 //*************************************************************************************************
5758 /*! \cond BLAZE_INTERNAL */
5759 /*!\brief Aligned, non-temporal store of a SIMD element of the submatrix.
5760 //
5761 // \param i Access index for the row. The index has to be in the range [0..M-1].
5762 // \param j Access index for the column. The index has to be in the range [0..N-1].
5763 // \param value The SIMD element to be stored.
5764 // \return void
5765 //
5766 // This function performs an aligned, non-temporal store of a specific SIMD element of the
5767 // dense submatrix. The row index must be smaller than the number of rows and the column
5768 // index must be smaller than the number of columns. Additionally, the row index must be a
5769 // multiple of the number of values inside the SIMD element. This function must \b NOT
5770 // be called explicitly! It is used internally for the performance optimized evaluation of
5771 // expression templates. Calling this function explicitly might result in erroneous results
5772 // and/or in compilation errors.
5773 */
5774 template< typename MT       // Type of the dense matrix
5775         , size_t... CSAs >  // Compile time submatrix arguments
5776 BLAZE_ALWAYS_INLINE void
stream(size_t i,size_t j,const SIMDType & value)5777    Submatrix<MT,unaligned,true,true,CSAs...>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
5778 {
5779    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
5780 
5781    BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
5782    BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
5783    BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
5784    BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
5785 
5786    if( isAligned_ )
5787       matrix_.stream( row()+i, column()+j, value );
5788    else
5789       matrix_.storeu( row()+i, column()+j, value );
5790 }
5791 /*! \endcond */
5792 //*************************************************************************************************
5793 
5794 
5795 //*************************************************************************************************
5796 /*! \cond BLAZE_INTERNAL */
5797 /*!\brief Default implementation of the assignment of a column-major dense matrix.
5798 //
5799 // \param rhs The right-hand side dense matrix to be assigned.
5800 // \return void
5801 //
5802 // This function must \b NOT be called explicitly! It is used internally for the performance
5803 // optimized evaluation of expression templates. Calling this function explicitly might result
5804 // in erroneous results and/or in compilation errors. Instead of using this function use the
5805 // assignment operator.
5806 */
5807 template< typename MT       // Type of the dense matrix
5808         , size_t... CSAs >  // Compile time submatrix arguments
5809 template< typename MT2 >    // Type of the right-hand side dense matrix
5810 inline auto Submatrix<MT,unaligned,true,true,CSAs...>::assign( const DenseMatrix<MT2,true>& rhs )
5811    -> DisableIf_t< VectorizedAssign_v<MT2> >
5812 {
5813    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
5814    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
5815 
5816    const size_t ipos( prevMultiple( rows(), 2UL ) );
5817    BLAZE_INTERNAL_ASSERT( ipos <= rows(), "Invalid end calculation" );
5818 
5819    for( size_t j=0UL; j<columns(); ++j ) {
5820       for( size_t i=0UL; i<ipos; i+=2UL ) {
5821          matrix_(row()+i    ,column()+j) = (*rhs)(i    ,j);
5822          matrix_(row()+i+1UL,column()+j) = (*rhs)(i+1UL,j);
5823       }
5824       if( ipos < rows() ) {
5825          matrix_(row()+ipos,column()+j) = (*rhs)(ipos,j);
5826       }
5827    }
5828 }
5829 /*! \endcond */
5830 //*************************************************************************************************
5831 
5832 
5833 //*************************************************************************************************
5834 /*! \cond BLAZE_INTERNAL */
5835 /*!\brief SIMD optimized implementation of the assignment of a column-major dense matrix.
5836 //
5837 // \param rhs The right-hand side dense matrix to be assigned.
5838 // \return void
5839 //
5840 // This function must \b NOT be called explicitly! It is used internally for the performance
5841 // optimized evaluation of expression templates. Calling this function explicitly might result
5842 // in erroneous results and/or in compilation errors. Instead of using this function use the
5843 // assignment operator.
5844 */
5845 template< typename MT       // Type of the dense matrix
5846         , size_t... CSAs >  // Compile time submatrix arguments
5847 template< typename MT2 >    // Type of the right-hand side dense matrix
5848 inline auto Submatrix<MT,unaligned,true,true,CSAs...>::assign( const DenseMatrix<MT2,true>& rhs )
5849    -> EnableIf_t< VectorizedAssign_v<MT2> >
5850 {
5851    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
5852 
5853    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
5854    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
5855 
5856    const size_t ipos( prevMultiple( rows(), SIMDSIZE ) );
5857    BLAZE_INTERNAL_ASSERT( ipos <= rows(), "Invalid end calculation" );
5858 
5859    if( useStreaming && isAligned_ &&
5860        rows()*columns() > ( cacheSize / ( sizeof(ElementType) * 3UL ) ) &&
5861        !(*rhs).isAliased( this ) )
5862    {
5863       for( size_t j=0UL; j<columns(); ++j )
5864       {
5865          size_t i( 0UL );
5866          Iterator left( begin(j) );
5867          ConstIterator_t<MT2> right( (*rhs).begin(j) );
5868 
5869          for( ; i<ipos; i+=SIMDSIZE ) {
5870             left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5871          }
5872          for( ; i<rows(); ++i ) {
5873             *left = *right; ++left; ++right;
5874          }
5875       }
5876    }
5877    else
5878    {
5879       for( size_t j=0UL; j<columns(); ++j )
5880       {
5881          size_t i( 0UL );
5882          Iterator left( begin(j) );
5883          ConstIterator_t<MT2> right( (*rhs).begin(j) );
5884 
5885          for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
5886             left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5887             left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5888             left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5889             left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5890          }
5891          for( ; i<ipos; i+=SIMDSIZE ) {
5892             left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
5893          }
5894          for( ; i<rows(); ++i ) {
5895             *left = *right; ++left; ++right;
5896          }
5897       }
5898    }
5899 }
5900 /*! \endcond */
5901 //*************************************************************************************************
5902 
5903 
5904 //*************************************************************************************************
5905 /*! \cond BLAZE_INTERNAL */
5906 /*!\brief Default implementation of the assignment of a row-major dense matrix.
5907 //
5908 // \param rhs The right-hand side dense matrix to be assigned.
5909 // \return void
5910 //
5911 // This function must \b NOT be called explicitly! It is used internally for the performance
5912 // optimized evaluation of expression templates. Calling this function explicitly might result
5913 // in erroneous results and/or in compilation errors. Instead of using this function use the
5914 // assignment operator.
5915 */
5916 template< typename MT       // Type of the dense matrix
5917         , size_t... CSAs >  // Compile time submatrix arguments
5918 template< typename MT2 >    // Type of the right-hand side dense matrix
assign(const DenseMatrix<MT2,false> & rhs)5919 inline void Submatrix<MT,unaligned,true,true,CSAs...>::assign( const DenseMatrix<MT2,false>& rhs )
5920 {
5921    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
5922 
5923    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
5924    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
5925 
5926    constexpr size_t block( BLOCK_SIZE );
5927 
5928    for( size_t jj=0UL; jj<columns(); jj+=block ) {
5929       const size_t jend( ( columns()<(jj+block) )?( columns() ):( jj+block ) );
5930       for( size_t ii=0UL; ii<rows(); ii+=block ) {
5931          const size_t iend( ( rows()<(ii+block) )?( rows() ):( ii+block ) );
5932          for( size_t j=jj; j<jend; ++j ) {
5933             for( size_t i=ii; i<iend; ++i ) {
5934                matrix_(row()+i,column()+j) = (*rhs)(i,j);
5935             }
5936          }
5937       }
5938    }
5939 }
5940 /*! \endcond */
5941 //*************************************************************************************************
5942 
5943 
5944 //*************************************************************************************************
5945 /*! \cond BLAZE_INTERNAL */
5946 /*!\brief Default implementation of the assignment of a column-major sparse matrix.
5947 //
5948 // \param rhs The right-hand side sparse matrix to be assigned.
5949 // \return void
5950 //
5951 // This function must \b NOT be called explicitly! It is used internally for the performance
5952 // optimized evaluation of expression templates. Calling this function explicitly might result
5953 // in erroneous results and/or in compilation errors. Instead of using this function use the
5954 // assignment operator.
5955 */
5956 template< typename MT       // Type of the dense matrix
5957         , size_t... CSAs >  // Compile time submatrix arguments
5958 template< typename MT2 >    // Type of the right-hand side sparse matrix
assign(const SparseMatrix<MT2,true> & rhs)5959 inline void Submatrix<MT,unaligned,true,true,CSAs...>::assign( const SparseMatrix<MT2,true>& rhs )
5960 {
5961    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
5962    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
5963 
5964    for( size_t j=0UL; j<columns(); ++j )
5965       for( ConstIterator_t<MT2> element=(*rhs).begin(j); element!=(*rhs).end(j); ++element )
5966          matrix_(row()+element->index(),column()+j) = element->value();
5967 }
5968 /*! \endcond */
5969 //*************************************************************************************************
5970 
5971 
5972 //*************************************************************************************************
5973 /*! \cond BLAZE_INTERNAL */
5974 /*!\brief Default implementation of the assignment of a row-major sparse matrix.
5975 //
5976 // \param rhs The right-hand side sparse matrix to be assigned.
5977 // \return void
5978 //
5979 // This function must \b NOT be called explicitly! It is used internally for the performance
5980 // optimized evaluation of expression templates. Calling this function explicitly might result
5981 // in erroneous results and/or in compilation errors. Instead of using this function use the
5982 // assignment operator.
5983 */
5984 template< typename MT       // Type of the dense matrix
5985         , size_t... CSAs >  // Compile time submatrix arguments
5986 template< typename MT2 >    // Type of the right-hand side sparse matrix
assign(const SparseMatrix<MT2,false> & rhs)5987 inline void Submatrix<MT,unaligned,true,true,CSAs...>::assign( const SparseMatrix<MT2,false>& rhs )
5988 {
5989    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
5990 
5991    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
5992    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
5993 
5994    for( size_t i=0UL; i<rows(); ++i )
5995       for( ConstIterator_t<MT2> element=(*rhs).begin(i); element!=(*rhs).end(i); ++element )
5996          matrix_(row()+i,column()+element->index()) = element->value();
5997 }
5998 /*! \endcond */
5999 //*************************************************************************************************
6000 
6001 
6002 //*************************************************************************************************
6003 /*! \cond BLAZE_INTERNAL */
6004 /*!\brief Default implementation of the addition assignment of a column-major dense matrix.
6005 //
6006 // \param rhs The right-hand side dense matrix to be added.
6007 // \return void
6008 //
6009 // This function must \b NOT be called explicitly! It is used internally for the performance
6010 // optimized evaluation of expression templates. Calling this function explicitly might result
6011 // in erroneous results and/or in compilation errors. Instead of using this function use the
6012 // assignment operator.
6013 */
6014 template< typename MT       // Type of the dense matrix
6015         , size_t... CSAs >  // Compile time submatrix arguments
6016 template< typename MT2 >    // Type of the right-hand side dense matrix
6017 inline auto Submatrix<MT,unaligned,true,true,CSAs...>::addAssign( const DenseMatrix<MT2,true>& rhs )
6018    -> DisableIf_t< VectorizedAddAssign_v<MT2> >
6019 {
6020    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
6021    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
6022 
6023    const size_t ipos( prevMultiple( rows(), 2UL ) );
6024    BLAZE_INTERNAL_ASSERT( ipos <= rows(), "Invalid end calculation" );
6025 
6026    for( size_t j=0UL; j<columns(); ++j )
6027    {
6028       if( IsDiagonal_v<MT2> ) {
6029          matrix_(row()+j,column()+j) += (*rhs)(j,j);
6030       }
6031       else {
6032          for( size_t i=0UL; i<ipos; i+=2UL ) {
6033             matrix_(row()+i    ,column()+j) += (*rhs)(i    ,j);
6034             matrix_(row()+i+1UL,column()+j) += (*rhs)(i+1UL,j);
6035          }
6036          if( ipos < rows() ) {
6037             matrix_(row()+ipos,column()+j) += (*rhs)(ipos,j);
6038          }
6039       }
6040    }
6041 }
6042 /*! \endcond */
6043 //*************************************************************************************************
6044 
6045 
6046 //*************************************************************************************************
6047 /*! \cond BLAZE_INTERNAL */
6048 /*!\brief SIMD optimized implementation of the addition assignment of a column-major dense matrix.
6049 //
6050 // \param rhs The right-hand side dense matrix to be added.
6051 // \return void
6052 //
6053 // This function must \b NOT be called explicitly! It is used internally for the performance
6054 // optimized evaluation of expression templates. Calling this function explicitly might result
6055 // in erroneous results and/or in compilation errors. Instead of using this function use the
6056 // assignment operator.
6057 */
6058 template< typename MT       // Type of the dense matrix
6059         , size_t... CSAs >  // Compile time submatrix arguments
6060 template< typename MT2 >    // Type of the right-hand side dense matrix
6061 inline auto Submatrix<MT,unaligned,true,true,CSAs...>::addAssign( const DenseMatrix<MT2,true>& rhs )
6062    -> EnableIf_t< VectorizedAddAssign_v<MT2> >
6063 {
6064    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
6065 
6066    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
6067    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
6068 
6069    for( size_t j=0UL; j<columns(); ++j )
6070    {
6071       const size_t ibegin( ( IsLower_v<MT> )
6072                            ?( prevMultiple( ( IsStrictlyLower_v<MT> ? j+1UL : j ), SIMDSIZE ) )
6073                            :( 0UL ) );
6074       const size_t iend  ( ( IsUpper_v<MT> )
6075                            ?( IsStrictlyUpper_v<MT> ? j : j+1UL )
6076                            :( rows() ) );
6077       BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
6078 
6079       const size_t ipos( prevMultiple( iend, SIMDSIZE ) );
6080       BLAZE_INTERNAL_ASSERT( ipos <= iend, "Invalid end calculation" );
6081 
6082       size_t i( ibegin );
6083       Iterator left( begin(j) + ibegin );
6084       ConstIterator_t<MT2> right( (*rhs).begin(j) + ibegin );
6085 
6086       for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
6087          left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6088          left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6089          left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6090          left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6091       }
6092       for( ; i<ipos; i+=SIMDSIZE ) {
6093          left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6094       }
6095       for( ; i<iend; ++i ) {
6096          *left += *right; ++left; ++right;
6097       }
6098    }
6099 }
6100 /*! \endcond */
6101 //*************************************************************************************************
6102 
6103 
6104 //*************************************************************************************************
6105 /*! \cond BLAZE_INTERNAL */
6106 /*!\brief Default implementation of the addition assignment of a row-major dense matrix.
6107 //
6108 // \param rhs The right-hand side dense matrix to be added.
6109 // \return void
6110 //
6111 // This function must \b NOT be called explicitly! It is used internally for the performance
6112 // optimized evaluation of expression templates. Calling this function explicitly might result
6113 // in erroneous results and/or in compilation errors. Instead of using this function use the
6114 // assignment operator.
6115 */
6116 template< typename MT       // Type of the dense matrix
6117         , size_t... CSAs >  // Compile time submatrix arguments
6118 template< typename MT2 >    // Type of the right-hand side dense matrix
addAssign(const DenseMatrix<MT2,false> & rhs)6119 inline void Submatrix<MT,unaligned,true,true,CSAs...>::addAssign( const DenseMatrix<MT2,false>& rhs )
6120 {
6121    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
6122 
6123    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
6124    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
6125 
6126    constexpr size_t block( BLOCK_SIZE );
6127 
6128    for( size_t jj=0UL; jj<columns(); jj+=block ) {
6129       const size_t jend( ( columns()<(jj+block) )?( columns() ):( jj+block ) );
6130       for( size_t ii=0UL; ii<rows(); ii+=block ) {
6131          const size_t iend( ( rows()<(ii+block) )?( rows() ):( ii+block ) );
6132          for( size_t j=jj; j<jend; ++j ) {
6133             for( size_t i=ii; i<iend; ++i ) {
6134                matrix_(row()+i,column()+j) += (*rhs)(i,j);
6135             }
6136          }
6137       }
6138    }
6139 }
6140 /*! \endcond */
6141 //*************************************************************************************************
6142 
6143 
6144 //*************************************************************************************************
6145 /*! \cond BLAZE_INTERNAL */
6146 /*!\brief Default implementation of the addition assignment of a column-major sparse matrix.
6147 //
6148 // \param rhs The right-hand side sparse matrix to be added.
6149 // \return void
6150 //
6151 // This function must \b NOT be called explicitly! It is used internally for the performance
6152 // optimized evaluation of expression templates. Calling this function explicitly might result
6153 // in erroneous results and/or in compilation errors. Instead of using this function use the
6154 // assignment operator.
6155 */
6156 template< typename MT       // Type of the dense matrix
6157         , size_t... CSAs >  // Compile time submatrix arguments
6158 template< typename MT2 >    // Type of the right-hand side sparse matrix
addAssign(const SparseMatrix<MT2,true> & rhs)6159 inline void Submatrix<MT,unaligned,true,true,CSAs...>::addAssign( const SparseMatrix<MT2,true>& rhs )
6160 {
6161    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
6162    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
6163 
6164    for( size_t j=0UL; j<columns(); ++j )
6165       for( ConstIterator_t<MT2> element=(*rhs).begin(j); element!=(*rhs).end(j); ++element )
6166          matrix_(row()+element->index(),column()+j) += element->value();
6167 }
6168 /*! \endcond */
6169 //*************************************************************************************************
6170 
6171 
6172 //*************************************************************************************************
6173 /*! \cond BLAZE_INTERNAL */
6174 /*!\brief Default implementation of the addition assignment of a row-major sparse matrix.
6175 //
6176 // \param rhs The right-hand side sparse matrix to be added.
6177 // \return void
6178 //
6179 // This function must \b NOT be called explicitly! It is used internally for the performance
6180 // optimized evaluation of expression templates. Calling this function explicitly might result
6181 // in erroneous results and/or in compilation errors. Instead of using this function use the
6182 // assignment operator.
6183 */
6184 template< typename MT       // Type of the dense matrix
6185         , size_t... CSAs >  // Compile time submatrix arguments
6186 template< typename MT2 >    // Type of the right-hand side sparse matrix
addAssign(const SparseMatrix<MT2,false> & rhs)6187 inline void Submatrix<MT,unaligned,true,true,CSAs...>::addAssign( const SparseMatrix<MT2,false>& rhs )
6188 {
6189    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
6190 
6191    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
6192    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
6193 
6194    for( size_t i=0UL; i<rows(); ++i )
6195       for( ConstIterator_t<MT2> element=(*rhs).begin(i); element!=(*rhs).end(i); ++element )
6196          matrix_(row()+i,column()+element->index()) += element->value();
6197 }
6198 /*! \endcond */
6199 //*************************************************************************************************
6200 
6201 
6202 //*************************************************************************************************
6203 /*! \cond BLAZE_INTERNAL */
6204 /*!\brief Default implementation of the subtraction assignment of a column-major dense matrix.
6205 //
6206 // \param rhs The right-hand side dense matrix to be subtracted.
6207 // \return void
6208 //
6209 // This function must \b NOT be called explicitly! It is used internally for the performance
6210 // optimized evaluation of expression templates. Calling this function explicitly might result
6211 // in erroneous results and/or in compilation errors. Instead of using this function use the
6212 // assignment operator.
6213 */
6214 template< typename MT       // Type of the dense matrix
6215         , size_t... CSAs >  // Compile time submatrix arguments
6216 template< typename MT2 >    // Type of the right-hand side dense matrix
6217 inline auto Submatrix<MT,unaligned,true,true,CSAs...>::subAssign( const DenseMatrix<MT2,true>& rhs )
6218    -> DisableIf_t< VectorizedSubAssign_v<MT2> >
6219 {
6220    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
6221    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
6222 
6223    const size_t ipos( prevMultiple( rows(), 2UL ) );
6224    BLAZE_INTERNAL_ASSERT( ipos <= rows(), "Invalid end calculation" );
6225 
6226    for( size_t j=0UL; j<columns(); ++j )
6227    {
6228       if( IsDiagonal_v<MT2> ) {
6229          matrix_(row()+j,column()+j) -= (*rhs)(j,j);
6230       }
6231       else {
6232          for( size_t i=0UL; i<ipos; i+=2UL ) {
6233             matrix_(row()+i    ,column()+j) -= (*rhs)(i    ,j);
6234             matrix_(row()+i+1UL,column()+j) -= (*rhs)(i+1UL,j);
6235          }
6236          if( ipos < rows() ) {
6237             matrix_(row()+ipos,column()+j) -= (*rhs)(ipos,j);
6238          }
6239       }
6240    }
6241 }
6242 /*! \endcond */
6243 //*************************************************************************************************
6244 
6245 
6246 //*************************************************************************************************
6247 /*! \cond BLAZE_INTERNAL */
6248 /*!\brief SIMD optimized implementation of the subtraction assignment of a column-major dense matrix.
6249 //
6250 // \param rhs The right-hand side dense matrix to be subtracted.
6251 // \return void
6252 //
6253 // This function must \b NOT be called explicitly! It is used internally for the performance
6254 // optimized evaluation of expression templates. Calling this function explicitly might result
6255 // in erroneous results and/or in compilation errors. Instead of using this function use the
6256 // assignment operator.
6257 */
6258 template< typename MT       // Type of the dense matrix
6259         , size_t... CSAs >  // Compile time submatrix arguments
6260 template< typename MT2 >    // Type of the right-hand side dense matrix
6261 inline auto Submatrix<MT,unaligned,true,true,CSAs...>::subAssign( const DenseMatrix<MT2,true>& rhs )
6262    -> EnableIf_t< VectorizedSubAssign_v<MT2> >
6263 {
6264    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
6265 
6266    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
6267    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
6268 
6269    for( size_t j=0UL; j<columns(); ++j )
6270    {
6271       const size_t ibegin( ( IsLower_v<MT> )
6272                            ?( prevMultiple( ( IsStrictlyLower_v<MT> ? j+1UL : j ), SIMDSIZE ) )
6273                            :( 0UL ) );
6274       const size_t iend  ( ( IsUpper_v<MT> )
6275                            ?( IsStrictlyUpper_v<MT> ? j : j+1UL )
6276                            :( rows() ) );
6277       BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
6278 
6279       const size_t ipos( prevMultiple( iend, SIMDSIZE ) );
6280       BLAZE_INTERNAL_ASSERT( ipos <= iend, "Invalid end calculation" );
6281 
6282       size_t i( ibegin );
6283       Iterator left( begin(j) + ibegin );
6284       ConstIterator_t<MT2> right( (*rhs).begin(j) + ibegin );
6285 
6286       for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
6287          left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6288          left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6289          left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6290          left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6291       }
6292       for( ; i<ipos; i+=SIMDSIZE ) {
6293          left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6294       }
6295       for( ; i<iend; ++i ) {
6296          *left -= *right; ++left; ++right;
6297       }
6298    }
6299 }
6300 /*! \endcond */
6301 //*************************************************************************************************
6302 
6303 
6304 //*************************************************************************************************
6305 /*! \cond BLAZE_INTERNAL */
6306 /*!\brief Default implementation of the subtraction assignment of a row-major dense matrix.
6307 //
6308 // \param rhs The right-hand side dense matrix to be subtracted.
6309 // \return void
6310 //
6311 // This function must \b NOT be called explicitly! It is used internally for the performance
6312 // optimized evaluation of expression templates. Calling this function explicitly might result
6313 // in erroneous results and/or in compilation errors. Instead of using this function use the
6314 // assignment operator.
6315 */
6316 template< typename MT       // Type of the dense matrix
6317         , size_t... CSAs >  // Compile time submatrix arguments
6318 template< typename MT2 >    // Type of the right-hand side dense matrix
subAssign(const DenseMatrix<MT2,false> & rhs)6319 inline void Submatrix<MT,unaligned,true,true,CSAs...>::subAssign( const DenseMatrix<MT2,false>& rhs )
6320 {
6321    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
6322 
6323    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
6324    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
6325 
6326    constexpr size_t block( BLOCK_SIZE );
6327 
6328    for( size_t jj=0UL; jj<columns(); jj+=block ) {
6329       const size_t jend( ( columns()<(jj+block) )?( columns() ):( jj+block ) );
6330       for( size_t ii=0UL; ii<rows(); ii+=block ) {
6331          const size_t iend( ( rows()<(ii+block) )?( rows() ):( ii+block ) );
6332          for( size_t j=jj; j<jend; ++j ) {
6333             for( size_t i=ii; i<iend; ++i ) {
6334                matrix_(row()+i,column()+j) -= (*rhs)(i,j);
6335             }
6336          }
6337       }
6338    }
6339 }
6340 /*! \endcond */
6341 //*************************************************************************************************
6342 
6343 
6344 //*************************************************************************************************
6345 /*! \cond BLAZE_INTERNAL */
6346 /*!\brief Default implementation of the subtraction assignment of a column-major sparse matrix.
6347 //
6348 // \param rhs The right-hand side sparse matrix to be subtracted.
6349 // \return void
6350 //
6351 // This function must \b NOT be called explicitly! It is used internally for the performance
6352 // optimized evaluation of expression templates. Calling this function explicitly might result
6353 // in erroneous results and/or in compilation errors. Instead of using this function use the
6354 // assignment operator.
6355 */
6356 template< typename MT       // Type of the dense matrix
6357         , size_t... CSAs >  // Compile time submatrix arguments
6358 template< typename MT2 >    // Type of the right-hand side sparse matrix
subAssign(const SparseMatrix<MT2,true> & rhs)6359 inline void Submatrix<MT,unaligned,true,true,CSAs...>::subAssign( const SparseMatrix<MT2,true>& rhs )
6360 {
6361    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
6362    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
6363 
6364    for( size_t j=0UL; j<columns(); ++j )
6365       for( ConstIterator_t<MT2> element=(*rhs).begin(j); element!=(*rhs).end(j); ++element )
6366          matrix_(row()+element->index(),column()+j) -= element->value();
6367 }
6368 /*! \endcond */
6369 //*************************************************************************************************
6370 
6371 
6372 //*************************************************************************************************
6373 /*! \cond BLAZE_INTERNAL */
6374 /*!\brief Default implementation of the subtraction assignment of a row-major sparse matrix.
6375 //
6376 // \param rhs The right-hand side sparse matrix to be subtracted.
6377 // \return void
6378 //
6379 // This function must \b NOT be called explicitly! It is used internally for the performance
6380 // optimized evaluation of expression templates. Calling this function explicitly might result
6381 // in erroneous results and/or in compilation errors. Instead of using this function use the
6382 // assignment operator.
6383 */
6384 template< typename MT       // Type of the dense matrix
6385         , size_t... CSAs >  // Compile time submatrix arguments
6386 template< typename MT2 >    // Type of the right-hand side sparse matrix
subAssign(const SparseMatrix<MT2,false> & rhs)6387 inline void Submatrix<MT,unaligned,true,true,CSAs...>::subAssign( const SparseMatrix<MT2,false>& rhs )
6388 {
6389    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
6390 
6391    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
6392    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
6393 
6394    for( size_t i=0UL; i<rows(); ++i )
6395       for( ConstIterator_t<MT2> element=(*rhs).begin(i); element!=(*rhs).end(i); ++element )
6396          matrix_(row()+i,column()+element->index()) -= element->value();
6397 }
6398 /*! \endcond */
6399 //*************************************************************************************************
6400 
6401 
6402 //*************************************************************************************************
6403 /*! \cond BLAZE_INTERNAL */
6404 /*!\brief Default implementation of the Schur product assignment of a column-major dense matrix.
6405 //
6406 // \param rhs The right-hand side dense matrix for the Schur product.
6407 // \return void
6408 //
6409 // This function must \b NOT be called explicitly! It is used internally for the performance
6410 // optimized evaluation of expression templates. Calling this function explicitly might result
6411 // in erroneous results and/or in compilation errors. Instead of using this function use the
6412 // assignment operator.
6413 */
6414 template< typename MT       // Type of the dense matrix
6415         , size_t... CSAs >  // Compile time submatrix arguments
6416 template< typename MT2 >    // Type of the right-hand side dense matrix
6417 inline auto Submatrix<MT,unaligned,true,true,CSAs...>::schurAssign( const DenseMatrix<MT2,true>& rhs )
6418    -> DisableIf_t< VectorizedSchurAssign_v<MT2> >
6419 {
6420    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
6421    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
6422 
6423    const size_t ipos( prevMultiple( rows(), 2UL ) );
6424    BLAZE_INTERNAL_ASSERT( ipos <= rows(), "Invalid end calculation" );
6425 
6426    for( size_t j=0UL; j<columns(); ++j ) {
6427       for( size_t i=0UL; i<ipos; i+=2UL ) {
6428          matrix_(row()+i    ,column()+j) *= (*rhs)(i    ,j);
6429          matrix_(row()+i+1UL,column()+j) *= (*rhs)(i+1UL,j);
6430       }
6431       if( ipos < rows() ) {
6432          matrix_(row()+ipos,column()+j) *= (*rhs)(ipos,j);
6433       }
6434    }
6435 }
6436 /*! \endcond */
6437 //*************************************************************************************************
6438 
6439 
6440 //*************************************************************************************************
6441 /*! \cond BLAZE_INTERNAL */
6442 /*!\brief SIMD optimized implementation of the Schur product assignment of a column-major dense
6443 //        matrix.
6444 //
6445 // \param rhs The right-hand side dense matrix for the Schur product.
6446 // \return void
6447 //
6448 // This function must \b NOT be called explicitly! It is used internally for the performance
6449 // optimized evaluation of expression templates. Calling this function explicitly might result
6450 // in erroneous results and/or in compilation errors. Instead of using this function use the
6451 // assignment operator.
6452 */
6453 template< typename MT       // Type of the dense matrix
6454         , size_t... CSAs >  // Compile time submatrix arguments
6455 template< typename MT2 >    // Type of the right-hand side dense matrix
6456 inline auto Submatrix<MT,unaligned,true,true,CSAs...>::schurAssign( const DenseMatrix<MT2,true>& rhs )
6457    -> EnableIf_t< VectorizedSchurAssign_v<MT2> >
6458 {
6459    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
6460 
6461    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
6462    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
6463 
6464    for( size_t j=0UL; j<columns(); ++j )
6465    {
6466       const size_t ipos( prevMultiple( rows(), SIMDSIZE ) );
6467       BLAZE_INTERNAL_ASSERT( ipos <= rows(), "Invalid end calculation" );
6468 
6469       size_t i( 0UL );
6470       Iterator left( begin(j) );
6471       ConstIterator_t<MT2> right( (*rhs).begin(j) );
6472 
6473       for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
6474          left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6475          left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6476          left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6477          left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6478       }
6479       for( ; i<ipos; i+=SIMDSIZE ) {
6480          left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6481       }
6482       for( ; i<rows(); ++i ) {
6483          *left *= *right; ++left; ++right;
6484       }
6485    }
6486 }
6487 /*! \endcond */
6488 //*************************************************************************************************
6489 
6490 
6491 //*************************************************************************************************
6492 /*! \cond BLAZE_INTERNAL */
6493 /*!\brief Default implementation of the Schur product assignment of a row-major dense matrix.
6494 //
6495 // \param rhs The right-hand side dense matrix for the Schur product.
6496 // \return void
6497 //
6498 // This function must \b NOT be called explicitly! It is used internally for the performance
6499 // optimized evaluation of expression templates. Calling this function explicitly might result
6500 // in erroneous results and/or in compilation errors. Instead of using this function use the
6501 // assignment operator.
6502 */
6503 template< typename MT       // Type of the dense matrix
6504         , size_t... CSAs >  // Compile time submatrix arguments
6505 template< typename MT2 >    // Type of the right-hand side dense matrix
schurAssign(const DenseMatrix<MT2,false> & rhs)6506 inline void Submatrix<MT,unaligned,true,true,CSAs...>::schurAssign( const DenseMatrix<MT2,false>& rhs )
6507 {
6508    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
6509 
6510    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
6511    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
6512 
6513    constexpr size_t block( BLOCK_SIZE );
6514 
6515    for( size_t jj=0UL; jj<columns(); jj+=block ) {
6516       const size_t jend( ( columns()<(jj+block) )?( columns() ):( jj+block ) );
6517       for( size_t ii=0UL; ii<rows(); ii+=block ) {
6518          const size_t iend( ( rows()<(ii+block) )?( rows() ):( ii+block ) );
6519          for( size_t j=jj; j<jend; ++j ) {
6520             for( size_t i=ii; i<iend; ++i ) {
6521                matrix_(row()+i,column()+j) *= (*rhs)(i,j);
6522             }
6523          }
6524       }
6525    }
6526 }
6527 /*! \endcond */
6528 //*************************************************************************************************
6529 
6530 
6531 //*************************************************************************************************
6532 /*! \cond BLAZE_INTERNAL */
6533 /*!\brief Default implementation of the Schur product assignment of a column-major sparse matrix.
6534 //
6535 // \param rhs The right-hand side sparse matrix for the Schur product.
6536 // \return void
6537 //
6538 // This function must \b NOT be called explicitly! It is used internally for the performance
6539 // optimized evaluation of expression templates. Calling this function explicitly might result
6540 // in erroneous results and/or in compilation errors. Instead of using this function use the
6541 // assignment operator.
6542 */
6543 template< typename MT       // Type of the dense matrix
6544         , size_t... CSAs >  // Compile time submatrix arguments
6545 template< typename MT2 >    // Type of the right-hand side sparse matrix
schurAssign(const SparseMatrix<MT2,true> & rhs)6546 inline void Submatrix<MT,unaligned,true,true,CSAs...>::schurAssign( const SparseMatrix<MT2,true>& rhs )
6547 {
6548    using blaze::reset;
6549 
6550    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
6551    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
6552 
6553    for( size_t j=0UL; j<columns(); ++j )
6554    {
6555       size_t i( 0UL );
6556 
6557       for( ConstIterator_t<MT2> element=(*rhs).begin(j); element!=(*rhs).end(j); ++element ) {
6558          for( ; i<element->index(); ++i )
6559             reset( matrix_(row()+i,column()+j) );
6560          matrix_(row()+i,column()+j) *= element->value();
6561          ++i;
6562       }
6563 
6564       for( ; i<rows(); ++i ) {
6565          reset( matrix_(row()+i,column()+j) );
6566       }
6567    }
6568 }
6569 /*! \endcond */
6570 //*************************************************************************************************
6571 
6572 
6573 //*************************************************************************************************
6574 /*! \cond BLAZE_INTERNAL */
6575 /*!\brief Default implementation of the Schur product assignment of a row-major sparse matrix.
6576 //
6577 // \param rhs The right-hand side sparse matrix for the Schur product.
6578 // \return void
6579 //
6580 // This function must \b NOT be called explicitly! It is used internally for the performance
6581 // optimized evaluation of expression templates. Calling this function explicitly might result
6582 // in erroneous results and/or in compilation errors. Instead of using this function use the
6583 // assignment operator.
6584 */
6585 template< typename MT       // Type of the dense matrix
6586         , size_t... CSAs >  // Compile time submatrix arguments
6587 template< typename MT2 >    // Type of the right-hand side sparse matrix
schurAssign(const SparseMatrix<MT2,false> & rhs)6588 inline void Submatrix<MT,unaligned,true,true,CSAs...>::schurAssign( const SparseMatrix<MT2,false>& rhs )
6589 {
6590    using blaze::reset;
6591 
6592    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
6593 
6594    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
6595    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
6596 
6597    for( size_t i=0UL; i<rows(); ++i )
6598    {
6599       size_t j( 0UL );
6600 
6601       for( ConstIterator_t<MT2> element=(*rhs).begin(i); element!=(*rhs).end(i); ++element ) {
6602          for( ; j<element->index(); ++j )
6603             reset( matrix_(row()+i,column()+j) );
6604          matrix_(row()+i,column()+j) *= element->value();
6605          ++j;
6606       }
6607 
6608       for( ; j<columns(); ++j ) {
6609          reset( matrix_(row()+i,column()+j) );
6610       }
6611    }
6612 }
6613 /*! \endcond */
6614 //*************************************************************************************************
6615 
6616 
6617 
6618 
6619 
6620 
6621 
6622 
6623 //=================================================================================================
6624 //
6625 //  CLASS TEMPLATE SPECIALIZATION FOR ALIGNED ROW-MAJOR DENSE SUBMATRICES
6626 //
6627 //=================================================================================================
6628 
6629 //*************************************************************************************************
6630 /*! \cond BLAZE_INTERNAL */
6631 /*!\brief Specialization of Submatrix for aligned row-major dense submatrices.
6632 // \ingroup submatrix
6633 //
6634 // This Specialization of Submatrix adapts the class template to the requirements of aligned
6635 // row-major dense submatrices.
6636 */
6637 template< typename MT       // Type of the dense matrix
6638         , size_t... CSAs >  // Compile time submatrix arguments
6639 class Submatrix<MT,aligned,false,true,CSAs...>
6640    : public View< DenseMatrix< Submatrix<MT,aligned,false,true,CSAs...>, false > >
6641    , private SubmatrixData<CSAs...>
6642 {
6643  private:
6644    //**Type definitions****************************************************************************
6645    using DataType = SubmatrixData<CSAs...>;               //!< The type of the SubmatrixData base class.
6646    using Operand  = If_t< IsExpression_v<MT>, MT, MT& >;  //!< Composite data type of the matrix expression.
6647    //**********************************************************************************************
6648 
6649    //**********************************************************************************************
6650    //! Helper variable template for the explicit application of the SFINAE principle.
6651    template< typename MT1, typename MT2 >
6652    static constexpr bool EnforceEvaluation_v =
6653       ( IsRestricted_v<MT1> && RequiresEvaluation_v<MT2> );
6654    //**********************************************************************************************
6655 
6656  public:
6657    //**Type definitions****************************************************************************
6658    //! Type of this Submatrix instance.
6659    using This = Submatrix<MT,aligned,false,true,CSAs...>;
6660 
6661    //! Base type of this Submatrix instance.
6662    using BaseType = View< DenseMatrix<This,false> >;
6663 
6664    using ViewedType    = MT;                            //!< The type viewed by this Submatrix instance.
6665    using ResultType    = SubmatrixTrait_t<MT,CSAs...>;  //!< Result type for expression template evaluations.
6666    using OppositeType  = OppositeType_t<ResultType>;    //!< Result type with opposite storage order for expression template evaluations.
6667    using TransposeType = TransposeType_t<ResultType>;   //!< Transpose type for expression template evaluations.
6668    using ElementType   = ElementType_t<MT>;             //!< Type of the submatrix elements.
6669    using SIMDType      = SIMDTrait_t<ElementType>;      //!< SIMD type of the submatrix elements.
6670    using ReturnType    = ReturnType_t<MT>;              //!< Return type for expression template evaluations
6671    using CompositeType = const Submatrix&;              //!< Data type for composite expression templates.
6672 
6673    //! Reference to a constant submatrix value.
6674    using ConstReference = ConstReference_t<MT>;
6675 
6676    //! Reference to a non-constant submatrix value.
6677    using Reference = If_t< IsConst_v<MT>, ConstReference, Reference_t<MT> >;
6678 
6679    //! Pointer to a constant submatrix value.
6680    using ConstPointer = ConstPointer_t<MT>;
6681 
6682    //! Pointer to a non-constant submatrix value.
6683    using Pointer = If_t< IsConst_v<MT> || !HasMutableDataAccess_v<MT>, ConstPointer, Pointer_t<MT> >;
6684 
6685    //! Iterator over constant elements.
6686    using ConstIterator = ConstIterator_t<MT>;
6687 
6688    //! Iterator over non-constant elements.
6689    using Iterator = If_t< IsConst_v<MT>, ConstIterator, Iterator_t<MT> >;
6690    //**********************************************************************************************
6691 
6692    //**Compilation flags***************************************************************************
6693    //! Compilation switch for the expression template evaluation strategy.
6694    static constexpr bool simdEnabled = MT::simdEnabled;
6695 
6696    //! Compilation switch for the expression template assignment strategy.
6697    static constexpr bool smpAssignable = MT::smpAssignable;
6698 
6699    //! Compilation switch for the expression template evaluation strategy.
6700    static constexpr bool compileTimeArgs = DataType::compileTimeArgs;
6701    //**********************************************************************************************
6702 
6703    //**Constructors********************************************************************************
6704    /*!\name Constructors */
6705    //@{
6706    template< typename... RSAs >
6707    explicit inline Submatrix( MT& matrix, RSAs... args );
6708 
6709    Submatrix( const Submatrix& ) = default;
6710    //@}
6711    //**********************************************************************************************
6712 
6713    //**Destructor**********************************************************************************
6714    /*!\name Destructor */
6715    //@{
6716    ~Submatrix() = default;
6717    //@}
6718    //**********************************************************************************************
6719 
6720    //**Data access functions***********************************************************************
6721    /*!\name Data access functions */
6722    //@{
6723    inline Reference      operator()( size_t i, size_t j );
6724    inline ConstReference operator()( size_t i, size_t j ) const;
6725    inline Reference      at( size_t i, size_t j );
6726    inline ConstReference at( size_t i, size_t j ) const;
6727    inline Pointer        data  () noexcept;
6728    inline ConstPointer   data  () const noexcept;
6729    inline Pointer        data  ( size_t i ) noexcept;
6730    inline ConstPointer   data  ( size_t i ) const noexcept;
6731    inline Iterator       begin ( size_t i );
6732    inline ConstIterator  begin ( size_t i ) const;
6733    inline ConstIterator  cbegin( size_t i ) const;
6734    inline Iterator       end   ( size_t i );
6735    inline ConstIterator  end   ( size_t i ) const;
6736    inline ConstIterator  cend  ( size_t i ) const;
6737    //@}
6738    //**********************************************************************************************
6739 
6740    //**Assignment operators************************************************************************
6741    /*!\name Assignment operators */
6742    //@{
6743    inline Submatrix& operator=( const ElementType& rhs );
6744    inline Submatrix& operator=( initializer_list< initializer_list<ElementType> > list );
6745    inline Submatrix& operator=( const Submatrix& rhs );
6746 
6747    template< typename MT2, bool SO >
6748    inline Submatrix& operator=( const Matrix<MT2,SO>& rhs );
6749 
6750    template< typename MT2, bool SO >
6751    inline auto operator+=( const Matrix<MT2,SO>& rhs )
6752       -> DisableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >;
6753 
6754    template< typename MT2, bool SO >
6755    inline auto operator+=( const Matrix<MT2,SO>& rhs )
6756       -> EnableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >;
6757 
6758    template< typename MT2, bool SO >
6759    inline auto operator-=( const Matrix<MT2,SO>& rhs )
6760       -> DisableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >;
6761 
6762    template< typename MT2, bool SO >
6763    inline auto operator-=( const Matrix<MT2,SO>& rhs )
6764       -> EnableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >;
6765 
6766    template< typename MT2, bool SO >
6767    inline auto operator%=( const Matrix<MT2,SO>& rhs )
6768       -> DisableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >;
6769 
6770    template< typename MT2, bool SO >
6771    inline auto operator%=( const Matrix<MT2,SO>& rhs )
6772       -> EnableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >;
6773    //@}
6774    //**********************************************************************************************
6775 
6776    //**Utility functions***************************************************************************
6777    /*!\name Utility functions */
6778    //@{
6779    using DataType::row;
6780    using DataType::column;
6781    using DataType::rows;
6782    using DataType::columns;
6783 
6784    inline MT&       operand() noexcept;
6785    inline const MT& operand() const noexcept;
6786 
6787    inline size_t spacing() const noexcept;
6788    inline size_t capacity() const noexcept;
6789    inline size_t capacity( size_t i ) const noexcept;
6790    inline size_t nonZeros() const;
6791    inline size_t nonZeros( size_t i ) const;
6792    inline void   reset();
6793    inline void   reset( size_t i );
6794    //@}
6795    //**********************************************************************************************
6796 
6797    //**Numeric functions***************************************************************************
6798    /*!\name Numeric functions */
6799    //@{
6800    inline Submatrix& transpose();
6801    inline Submatrix& ctranspose();
6802 
6803    template< typename Other > inline Submatrix& scale( const Other& scalar );
6804    //@}
6805    //**********************************************************************************************
6806 
6807  private:
6808    //**********************************************************************************************
6809    //! Helper variable template for the explicit application of the SFINAE principle.
6810    template< typename MT2 >
6811    static constexpr bool VectorizedAssign_v =
6812       ( useOptimizedKernels &&
6813         simdEnabled && MT2::simdEnabled &&
6814         IsSIMDCombinable_v< ElementType, ElementType_t<MT2> > );
6815    //**********************************************************************************************
6816 
6817    //**********************************************************************************************
6818    //! Helper variable template for the explicit application of the SFINAE principle.
6819    template< typename MT2 >
6820    static constexpr bool VectorizedAddAssign_v =
6821       ( VectorizedAssign_v<MT2> &&
6822         HasSIMDAdd_v< ElementType, ElementType_t<MT2> > &&
6823         !IsDiagonal_v<MT2> );
6824    //**********************************************************************************************
6825 
6826    //**********************************************************************************************
6827    //! Helper variable template for the explicit application of the SFINAE principle.
6828    template< typename MT2 >
6829    static constexpr bool VectorizedSubAssign_v =
6830       ( VectorizedAssign_v<MT2> &&
6831         HasSIMDSub_v< ElementType, ElementType_t<MT2> > &&
6832         !IsDiagonal_v<MT2> );
6833    //**********************************************************************************************
6834 
6835    //**********************************************************************************************
6836    //! Helper variable template for the explicit application of the SFINAE principle.
6837    template< typename MT2 >
6838    static constexpr bool VectorizedSchurAssign_v =
6839       ( VectorizedAssign_v<MT2> &&
6840         HasSIMDMult_v< ElementType, ElementType_t<MT2> > );
6841    //**********************************************************************************************
6842 
6843    //**SIMD properties*****************************************************************************
6844    //! The number of elements packed within a single SIMD element.
6845    static constexpr size_t SIMDSIZE = SIMDTrait<ElementType>::size;
6846    //**********************************************************************************************
6847 
6848  public:
6849    //**Expression template evaluation functions****************************************************
6850    /*!\name Expression template evaluation functions */
6851    //@{
6852    template< typename Other >
6853    inline bool canAlias( const Other* alias ) const noexcept;
6854 
6855    template< typename MT2, AlignmentFlag AF2, bool SO2, size_t... CSAs2 >
6856    inline bool canAlias( const Submatrix<MT2,AF2,SO2,true,CSAs2...>* alias ) const noexcept;
6857 
6858    template< typename Other >
6859    inline bool isAliased( const Other* alias ) const noexcept;
6860 
6861    template< typename MT2, AlignmentFlag AF2, bool SO2, size_t... CSAs2 >
6862    inline bool isAliased( const Submatrix<MT2,AF2,SO2,true,CSAs2...>* alias ) const noexcept;
6863 
6864    inline bool isAligned   () const noexcept;
6865    inline bool canSMPAssign() const noexcept;
6866 
6867    BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
6868    BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
6869    BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
6870 
6871    BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
6872    BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
6873    BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
6874    BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
6875 
6876    template< typename MT2 >
6877    inline auto assign( const DenseMatrix<MT2,false>& rhs ) -> DisableIf_t< VectorizedAssign_v<MT2> >;
6878 
6879    template< typename MT2 >
6880    inline auto assign( const DenseMatrix<MT2,false>& rhs ) -> EnableIf_t< VectorizedAssign_v<MT2> >;
6881 
6882    template< typename MT2 > inline void assign( const DenseMatrix<MT2,true>&  rhs );
6883    template< typename MT2 > inline void assign( const SparseMatrix<MT2,false>&  rhs );
6884    template< typename MT2 > inline void assign( const SparseMatrix<MT2,true>& rhs );
6885 
6886    template< typename MT2 >
6887    inline auto addAssign( const DenseMatrix<MT2,false>& rhs ) -> DisableIf_t< VectorizedAddAssign_v<MT2> >;
6888 
6889    template< typename MT2 >
6890    inline auto addAssign( const DenseMatrix<MT2,false>& rhs ) -> EnableIf_t< VectorizedAddAssign_v<MT2> >;
6891 
6892    template< typename MT2 > inline void addAssign( const DenseMatrix<MT2,true>&  rhs );
6893    template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,false>&  rhs );
6894    template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,true>& rhs );
6895 
6896    template< typename MT2 >
6897    inline auto subAssign( const DenseMatrix<MT2,false>& rhs ) -> DisableIf_t< VectorizedSubAssign_v<MT2> >;
6898 
6899    template< typename MT2 >
6900    inline auto subAssign( const DenseMatrix<MT2,false>& rhs ) -> EnableIf_t< VectorizedSubAssign_v<MT2> >;
6901 
6902    template< typename MT2 > inline void subAssign( const DenseMatrix<MT2,true>&  rhs );
6903    template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,false>&  rhs );
6904    template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,true>& rhs );
6905 
6906    template< typename MT2 >
6907    inline auto schurAssign( const DenseMatrix<MT2,false>& rhs ) -> DisableIf_t< VectorizedSchurAssign_v<MT2> >;
6908 
6909    template< typename MT2 >
6910    inline auto schurAssign( const DenseMatrix<MT2,false>& rhs ) -> EnableIf_t< VectorizedSchurAssign_v<MT2> >;
6911 
6912    template< typename MT2 > inline void schurAssign( const DenseMatrix<MT2,true>&  rhs );
6913    template< typename MT2 > inline void schurAssign( const SparseMatrix<MT2,false>&  rhs );
6914    template< typename MT2 > inline void schurAssign( const SparseMatrix<MT2,true>& rhs );
6915    //@}
6916    //**********************************************************************************************
6917 
6918  private:
6919    //**Utility functions***************************************************************************
6920    /*!\name Utility functions */
6921    //@{
6922    inline bool hasOverlap() const noexcept;
6923    //@}
6924    //**********************************************************************************************
6925 
6926    //**Member variables****************************************************************************
6927    /*!\name Member variables */
6928    //@{
6929    Operand matrix_;  //!< The matrix containing the submatrix.
6930    //@}
6931    //**********************************************************************************************
6932 
6933    //**Friend declarations*************************************************************************
6934    template< typename MT2, AlignmentFlag AF2, bool SO2, bool DF2, size_t... CSAs2 > friend class Submatrix;
6935    //**********************************************************************************************
6936 
6937    //**Compile time checks*************************************************************************
6938    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE    ( MT );
6939    BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE ( MT );
6940    BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE   ( MT );
6941    BLAZE_CONSTRAINT_MUST_NOT_BE_SUBMATRIX_TYPE   ( MT );
6942    BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT );
6943    BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE     ( MT );
6944    BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE   ( MT );
6945    //**********************************************************************************************
6946 };
6947 /*! \endcond */
6948 //*************************************************************************************************
6949 
6950 
6951 
6952 
6953 //=================================================================================================
6954 //
6955 //  CONSTRUCTORS
6956 //
6957 //=================================================================================================
6958 
6959 //*************************************************************************************************
6960 /*! \cond BLAZE_INTERNAL */
6961 /*!\brief Constructor for aligned row-major dense submatrices.
6962 //
6963 // \param matrix The dense matrix containing the submatrix.
6964 // \param args The runtime submatrix arguments.
6965 // \exception std::invalid_argument Invalid submatrix specification.
6966 //
6967 // By default, the provided submatrix arguments are checked at runtime. In case the submatrix is
6968 // not properly specified (i.e. if the specified submatrix is not contained in the given dense
6969 // matrix) a \a std::invalid_argument exception is thrown. The checks can be skipped by providing
6970 // the optional \a blaze::unchecked argument.
6971 */
6972 template< typename MT         // Type of the dense matrix
6973         , size_t... CSAs >    // Compile time submatrix arguments
6974 template< typename... RSAs >  // Runtime submatrix arguments
Submatrix(MT & matrix,RSAs...args)6975 inline Submatrix<MT,aligned,false,true,CSAs...>::Submatrix( MT& matrix, RSAs... args )
6976    : DataType( args... )  // Base class initialization
6977    , matrix_ ( matrix  )  // The matrix containing the submatrix
6978 {
6979    if( isChecked( args... ) )
6980    {
6981       if( ( row() + rows() > matrix_.rows() ) || ( column() + columns() > matrix_.columns() ) ) {
6982          BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix specification" );
6983       }
6984 
6985       if( simdEnabled && IsContiguous_v<MT> &&
6986           ( !checkAlignment( data() ) ||
6987             ( rows() > 1UL && matrix_.spacing() % SIMDSIZE != 0UL ) ) ) {
6988          BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix alignment" );
6989       }
6990    }
6991    else
6992    {
6993       BLAZE_USER_ASSERT( row()    + rows()    <= matrix_.rows()   , "Invalid submatrix specification" );
6994       BLAZE_USER_ASSERT( column() + columns() <= matrix_.columns(), "Invalid submatrix specification" );
6995 
6996       BLAZE_USER_ASSERT( !simdEnabled || !IsContiguous_v<MT> || checkAlignment( data() ), "Invalid submatrix alignment" );
6997       BLAZE_USER_ASSERT( !simdEnabled || !IsContiguous_v<MT> || rows() <= 1UL || matrix_.spacing() % SIMDSIZE == 0UL, "Invalid submatrix alignment" );
6998    }
6999 }
7000 /*! \endcond */
7001 //*************************************************************************************************
7002 
7003 
7004 
7005 
7006 //=================================================================================================
7007 //
7008 //  DATA ACCESS FUNCTIONS
7009 //
7010 //=================================================================================================
7011 
7012 //*************************************************************************************************
7013 /*! \cond BLAZE_INTERNAL */
7014 /*!\brief 2D-access to the dense submatrix elements.
7015 //
7016 // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
7017 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
7018 // \return Reference to the accessed value.
7019 //
7020 // This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
7021 // the at() function is guaranteed to perform a check of the given access indices.
7022 */
7023 template< typename MT       // Type of the dense matrix
7024         , size_t... CSAs >  // Compile time submatrix arguments
7025 inline typename Submatrix<MT,aligned,false,true,CSAs...>::Reference
operator()7026    Submatrix<MT,aligned,false,true,CSAs...>::operator()( size_t i, size_t j )
7027 {
7028    BLAZE_USER_ASSERT( i < rows()   , "Invalid row access index"    );
7029    BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
7030 
7031    return matrix_(row()+i,column()+j);
7032 }
7033 /*! \endcond */
7034 //*************************************************************************************************
7035 
7036 
7037 //*************************************************************************************************
7038 /*! \cond BLAZE_INTERNAL */
7039 /*!\brief 2D-access to the dense submatrix elements.
7040 //
7041 // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
7042 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
7043 // \return Reference to the accessed value.
7044 //
7045 // This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
7046 // the at() function is guaranteed to perform a check of the given access indices.
7047 */
7048 template< typename MT       // Type of the dense matrix
7049         , size_t... CSAs >  // Compile time submatrix arguments
7050 inline typename Submatrix<MT,aligned,false,true,CSAs...>::ConstReference
operator()7051    Submatrix<MT,aligned,false,true,CSAs...>::operator()( size_t i, size_t j ) const
7052 {
7053    BLAZE_USER_ASSERT( i < rows()   , "Invalid row access index"    );
7054    BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
7055 
7056    return const_cast<const MT&>( matrix_ )(row()+i,column()+j);
7057 }
7058 /*! \endcond */
7059 //*************************************************************************************************
7060 
7061 
7062 //*************************************************************************************************
7063 /*! \cond BLAZE_INTERNAL */
7064 /*!\brief Checked access to the submatrix elements.
7065 //
7066 // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
7067 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
7068 // \return Reference to the accessed value.
7069 // \exception std::out_of_range Invalid matrix access index.
7070 //
7071 // In contrast to the function call operator this function always performs a check of the given
7072 // access indices.
7073 */
7074 template< typename MT       // Type of the dense matrix
7075         , size_t... CSAs >  // Compile time submatrix arguments
7076 inline typename Submatrix<MT,aligned,false,true,CSAs...>::Reference
at(size_t i,size_t j)7077    Submatrix<MT,aligned,false,true,CSAs...>::at( size_t i, size_t j )
7078 {
7079    if( i >= rows() ) {
7080       BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
7081    }
7082    if( j >= columns() ) {
7083       BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
7084    }
7085    return (*this)(i,j);
7086 }
7087 /*! \endcond */
7088 //*************************************************************************************************
7089 
7090 
7091 //*************************************************************************************************
7092 /*! \cond BLAZE_INTERNAL */
7093 /*!\brief Checked access to the submatrix elements.
7094 //
7095 // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
7096 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
7097 // \return Reference to the accessed value.
7098 // \exception std::out_of_range Invalid matrix access index.
7099 //
7100 // In contrast to the function call operator this function always performs a check of the given
7101 // access indices.
7102 */
7103 template< typename MT       // Type of the dense matrix
7104         , size_t... CSAs >  // Compile time submatrix arguments
7105 inline typename Submatrix<MT,aligned,false,true,CSAs...>::ConstReference
at(size_t i,size_t j)7106    Submatrix<MT,aligned,false,true,CSAs...>::at( size_t i, size_t j ) const
7107 {
7108    if( i >= rows() ) {
7109       BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
7110    }
7111    if( j >= columns() ) {
7112       BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
7113    }
7114    return (*this)(i,j);
7115 }
7116 /*! \endcond */
7117 //*************************************************************************************************
7118 
7119 
7120 //*************************************************************************************************
7121 /*! \cond BLAZE_INTERNAL */
7122 /*!\brief Low-level data access to the submatrix elements.
7123 //
7124 // \return Pointer to the internal element storage.
7125 //
7126 // This function returns a pointer to the internal storage of the dense submatrix. Note that
7127 // you can NOT assume that all matrix elements lie adjacent to each other! The dense submatrix
7128 // may use techniques such as padding to improve the alignment of the data.
7129 */
7130 template< typename MT       // Type of the dense matrix
7131         , size_t... CSAs >  // Compile time submatrix arguments
7132 inline typename Submatrix<MT,aligned,false,true,CSAs...>::Pointer
data()7133    Submatrix<MT,aligned,false,true,CSAs...>::data() noexcept
7134 {
7135    return matrix_.data() + row()*spacing() + column();
7136 }
7137 /*! \endcond */
7138 //*************************************************************************************************
7139 
7140 
7141 //*************************************************************************************************
7142 /*! \cond BLAZE_INTERNAL */
7143 /*!\brief Low-level data access to the submatrix elements.
7144 //
7145 // \return Pointer to the internal element storage.
7146 //
7147 // This function returns a pointer to the internal storage of the dense submatrix. Note that
7148 // you can NOT assume that all matrix elements lie adjacent to each other! The dense submatrix
7149 // may use techniques such as padding to improve the alignment of the data.
7150 */
7151 template< typename MT       // Type of the dense matrix
7152         , size_t... CSAs >  // Compile time submatrix arguments
7153 inline typename Submatrix<MT,aligned,false,true,CSAs...>::ConstPointer
data()7154    Submatrix<MT,aligned,false,true,CSAs...>::data() const noexcept
7155 {
7156    return matrix_.data() + row()*spacing() + column();
7157 }
7158 /*! \endcond */
7159 //*************************************************************************************************
7160 
7161 
7162 //*************************************************************************************************
7163 /*! \cond BLAZE_INTERNAL */
7164 /*!\brief Low-level data access to the submatrix elements of row \a i.
7165 //
7166 // \param i The row index.
7167 // \return Pointer to the internal element storage.
7168 //
7169 // This function returns a pointer to the internal storage of the dense submatrix in row \a i.
7170 */
7171 template< typename MT       // Type of the dense matrix
7172         , size_t... CSAs >  // Compile time submatrix arguments
7173 inline typename Submatrix<MT,aligned,false,true,CSAs...>::Pointer
data(size_t i)7174    Submatrix<MT,aligned,false,true,CSAs...>::data( size_t i ) noexcept
7175 {
7176    return matrix_.data() + (row()+i)*spacing() + column();
7177 }
7178 /*! \endcond */
7179 //*************************************************************************************************
7180 
7181 
7182 //*************************************************************************************************
7183 /*! \cond BLAZE_INTERNAL */
7184 /*!\brief Low-level data access to the submatrix elements of row \a i.
7185 //
7186 // \param i The row index.
7187 // \return Pointer to the internal element storage.
7188 //
7189 // This function returns a pointer to the internal storage of the dense submatrix in row \a i.
7190 */
7191 template< typename MT       // Type of the dense matrix
7192         , size_t... CSAs >  // Compile time submatrix arguments
7193 inline typename Submatrix<MT,aligned,false,true,CSAs...>::ConstPointer
data(size_t i)7194    Submatrix<MT,aligned,false,true,CSAs...>::data( size_t i ) const noexcept
7195 {
7196    return matrix_.data() + (row()+i)*spacing() + column();
7197 }
7198 /*! \endcond */
7199 //*************************************************************************************************
7200 
7201 
7202 //*************************************************************************************************
7203 /*! \cond BLAZE_INTERNAL */
7204 /*!\brief Returns an iterator to the first non-zero element of row/column \a i.
7205 //
7206 // \param i The row/column index.
7207 // \return Iterator to the first non-zero element of row/column \a i.
7208 //
7209 // This function returns a row/column iterator to the first non-zero element of row/column \a i.
7210 // In case the storage order is set to \a rowMajor the function returns an iterator to the first
7211 // non-zero element of row \a i, in case the storage flag is set to \a columnMajor the function
7212 // returns an iterator to the first non-zero element of column \a i.
7213 */
7214 template< typename MT       // Type of the dense matrix
7215         , size_t... CSAs >  // Compile time submatrix arguments
7216 inline typename Submatrix<MT,aligned,false,true,CSAs...>::Iterator
begin(size_t i)7217    Submatrix<MT,aligned,false,true,CSAs...>::begin( size_t i )
7218 {
7219    BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
7220    return ( matrix_.begin( row() + i ) + column() );
7221 }
7222 /*! \endcond */
7223 //*************************************************************************************************
7224 
7225 
7226 //*************************************************************************************************
7227 /*! \cond BLAZE_INTERNAL */
7228 /*!\brief Returns an iterator to the first non-zero element of row/column \a i.
7229 //
7230 // \param i The row/column index.
7231 // \return Iterator to the first non-zero element of row/column \a i.
7232 //
7233 // This function returns a row/column iterator to the first non-zero element of row/column \a i.
7234 // In case the storage order is set to \a rowMajor the function returns an iterator to the first
7235 // non-zero element of row \a i, in case the storage flag is set to \a columnMajor the function
7236 // returns an iterator to the first non-zero element of column \a i.
7237 */
7238 template< typename MT       // Type of the dense matrix
7239         , size_t... CSAs >  // Compile time submatrix arguments
7240 inline typename Submatrix<MT,aligned,false,true,CSAs...>::ConstIterator
begin(size_t i)7241    Submatrix<MT,aligned,false,true,CSAs...>::begin( size_t i ) const
7242 {
7243    BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
7244    return ( matrix_.cbegin( row() + i ) + column() );
7245 }
7246 /*! \endcond */
7247 //*************************************************************************************************
7248 
7249 
7250 //*************************************************************************************************
7251 /*! \cond BLAZE_INTERNAL */
7252 /*!\brief Returns an iterator to the first non-zero element of row/column \a i.
7253 //
7254 // \param i The row/column index.
7255 // \return Iterator to the first non-zero element of row/column \a i.
7256 //
7257 // This function returns a row/column iterator to the first non-zero element of row/column \a i.
7258 // In case the storage order is set to \a rowMajor the function returns an iterator to the first
7259 // non-zero element of row \a i, in case the storage flag is set to \a columnMajor the function
7260 // returns an iterator to the first non-zero element of column \a i.
7261 */
7262 template< typename MT       // Type of the dense matrix
7263         , size_t... CSAs >  // Compile time submatrix arguments
7264 inline typename Submatrix<MT,aligned,false,true,CSAs...>::ConstIterator
cbegin(size_t i)7265    Submatrix<MT,aligned,false,true,CSAs...>::cbegin( size_t i ) const
7266 {
7267    BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
7268    return ( matrix_.cbegin( row() + i ) + column() );
7269 }
7270 /*! \endcond */
7271 //*************************************************************************************************
7272 
7273 
7274 //*************************************************************************************************
7275 /*! \cond BLAZE_INTERNAL */
7276 /*!\brief Returns an iterator just past the last non-zero element of row/column \a i.
7277 //
7278 // \param i The row/column index.
7279 // \return Iterator just past the last non-zero element of row/column \a i.
7280 //
7281 // This function returns an row/column iterator just past the last non-zero element of row/column
7282 // \a i. In case the storage order is set to \a rowMajor the function returns an iterator just
7283 // past the last non-zero element of row \a i, in case the storage flag is set to \a columnMajor
7284 // the function returns an iterator just past the last non-zero element of column \a i.
7285 */
7286 template< typename MT       // Type of the dense matrix
7287         , size_t... CSAs >  // Compile time submatrix arguments
7288 inline typename Submatrix<MT,aligned,false,true,CSAs...>::Iterator
end(size_t i)7289    Submatrix<MT,aligned,false,true,CSAs...>::end( size_t i )
7290 {
7291    BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
7292    return ( matrix_.begin( row() + i ) + column() + columns() );
7293 }
7294 /*! \endcond */
7295 //*************************************************************************************************
7296 
7297 
7298 //*************************************************************************************************
7299 /*! \cond BLAZE_INTERNAL */
7300 /*!\brief Returns an iterator just past the last non-zero element of row/column \a i.
7301 //
7302 // \param i The row/column index.
7303 // \return Iterator just past the last non-zero element of row/column \a i.
7304 //
7305 // This function returns an row/column iterator just past the last non-zero element of row/column
7306 // \a i. In case the storage order is set to \a rowMajor the function returns an iterator just
7307 // past the last non-zero element of row \a i, in case the storage flag is set to \a columnMajor
7308 // the function returns an iterator just past the last non-zero element of column \a i.
7309 */
7310 template< typename MT       // Type of the dense matrix
7311         , size_t... CSAs >  // Compile time submatrix arguments
7312 inline typename Submatrix<MT,aligned,false,true,CSAs...>::ConstIterator
end(size_t i)7313    Submatrix<MT,aligned,false,true,CSAs...>::end( size_t i ) const
7314 {
7315    BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
7316    return ( matrix_.cbegin( row() + i ) + column() + columns() );
7317 }
7318 /*! \endcond */
7319 //*************************************************************************************************
7320 
7321 
7322 //*************************************************************************************************
7323 /*! \cond BLAZE_INTERNAL */
7324 /*!\brief Returns an iterator just past the last non-zero element of row/column \a i.
7325 //
7326 // \param i The row/column index.
7327 // \return Iterator just past the last non-zero element of row/column \a i.
7328 //
7329 // This function returns an row/column iterator just past the last non-zero element of row/column
7330 // \a i. In case the storage order is set to \a rowMajor the function returns an iterator just
7331 // past the last non-zero element of row \a i, in case the storage flag is set to \a columnMajor
7332 // the function returns an iterator just past the last non-zero element of column \a i.
7333 */
7334 template< typename MT       // Type of the dense matrix
7335         , size_t... CSAs >  // Compile time submatrix arguments
7336 inline typename Submatrix<MT,aligned,false,true,CSAs...>::ConstIterator
cend(size_t i)7337    Submatrix<MT,aligned,false,true,CSAs...>::cend( size_t i ) const
7338 {
7339    BLAZE_USER_ASSERT( i < rows(), "Invalid dense submatrix row access index" );
7340    return ( matrix_.cbegin( row() + i ) + column() + columns() );
7341 }
7342 /*! \endcond */
7343 //*************************************************************************************************
7344 
7345 
7346 
7347 
7348 //=================================================================================================
7349 //
7350 //  ASSIGNMENT OPERATORS
7351 //
7352 //=================================================================================================
7353 
7354 //*************************************************************************************************
7355 /*! \cond BLAZE_INTERNAL */
7356 /*!\brief Homogenous assignment to all submatrix elements.
7357 //
7358 // \param rhs Scalar value to be assigned to all submatrix elements.
7359 // \return Reference to the assigned submatrix.
7360 //
7361 // This function homogeneously assigns the given value to all dense matrix elements. Note that in
7362 // case the underlying dense matrix is a lower/upper matrix only lower/upper and diagonal elements
7363 // of the underlying matrix are modified.
7364 */
7365 template< typename MT       // Type of the dense matrix
7366         , size_t... CSAs >  // Compile time submatrix arguments
7367 inline Submatrix<MT,aligned,false,true,CSAs...>&
7368    Submatrix<MT,aligned,false,true,CSAs...>::operator=( const ElementType& rhs )
7369 {
7370    const size_t iend( row() + rows() );
7371    decltype(auto) left( derestrict( matrix_ ) );
7372 
7373    for( size_t i=row(); i<iend; ++i )
7374    {
7375       const size_t jbegin( ( IsUpper_v<MT> )
7376                            ?( ( IsUniUpper_v<MT> || IsStrictlyUpper_v<MT> )
7377                               ?( max( i+1UL, column() ) )
7378                               :( max( i, column() ) ) )
7379                            :( column() ) );
7380       const size_t jend  ( ( IsLower_v<MT> )
7381                            ?( ( IsUniLower_v<MT> || IsStrictlyLower_v<MT> )
7382                               ?( min( i, column()+columns() ) )
7383                               :( min( i+1UL, column()+columns() ) ) )
7384                            :( column()+columns() ) );
7385 
7386       for( size_t j=jbegin; j<jend; ++j ) {
7387          if( !IsRestricted_v<MT> || IsTriangular_v<MT> || trySet( matrix_, i, j, rhs ) )
7388             left(i,j) = rhs;
7389       }
7390    }
7391 
7392    return *this;
7393 }
7394 /*! \endcond */
7395 //*************************************************************************************************
7396 
7397 
7398 //*************************************************************************************************
7399 /*! \cond BLAZE_INTERNAL */
7400 /*!\brief List assignment to all submatrix elements.
7401 //
7402 // \param list The initializer list.
7403 // \exception std::invalid_argument Invalid assignment to submatrix.
7404 // \exception std::invalid_argument Invalid assignment to restricted matrix.
7405 //
7406 // This assignment operator offers the option to directly assign to all elements of the submatrix
7407 // by means of an initializer list. The submatrix elements are assigned the values from the given
7408 // initializer list. Missing values are initialized as default. Note that in case the size of the
7409 // top-level initializer list does not match the number of rows of the submatrix or the size of
7410 // any nested list exceeds the number of columns, a \a std::invalid_argument exception is thrown.
7411 // Also, if the underlying matrix \a MT is restricted and the assignment would violate an
7412 // invariant of the matrix, a \a std::invalid_argument exception is thrown.
7413 */
7414 template< typename MT       // Type of the dense matrix
7415         , size_t... CSAs >  // Compile time submatrix arguments
7416 inline Submatrix<MT,aligned,false,true,CSAs...>&
7417    Submatrix<MT,aligned,false,true,CSAs...>::operator=( initializer_list< initializer_list<ElementType> > list )
7418 {
7419    if( list.size() != rows() ) {
7420       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to submatrix" );
7421    }
7422 
7423    if( IsRestricted_v<MT> ) {
7424       const InitializerMatrix<ElementType> tmp( list, columns() );
7425       if( !tryAssign( matrix_, tmp, row(), column() ) ) {
7426          BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7427       }
7428    }
7429 
7430    decltype(auto) left( derestrict( *this ) );
7431    size_t i( 0UL );
7432 
7433    for( const auto& rowList : list ) {
7434       std::fill( std::copy( rowList.begin(), rowList.end(), left.begin(i) ), left.end(i), ElementType() );
7435       ++i;
7436    }
7437 
7438    return *this;
7439 }
7440 /*! \endcond */
7441 //*************************************************************************************************
7442 
7443 
7444 //*************************************************************************************************
7445 /*! \cond BLAZE_INTERNAL */
7446 /*!\brief Copy assignment operator for Submatrix.
7447 //
7448 // \param rhs Sparse submatrix to be copied.
7449 // \return Reference to the assigned submatrix.
7450 // \exception std::invalid_argument Submatrix sizes do not match.
7451 // \exception std::invalid_argument Invalid assignment to restricted matrix.
7452 //
7453 // The dense submatrix is initialized as a copy of the given dense submatrix. In case the current
7454 // sizes of the two submatrices don't match, a \a std::invalid_argument exception is thrown. Also,
7455 // if the underlying matrix \a MT is a lower triangular, upper triangular, or symmetric matrix
7456 // and the assignment would violate its lower, upper, or symmetry property, respectively, a
7457 // \a std::invalid_argument exception is thrown.
7458 */
7459 template< typename MT       // Type of the dense matrix
7460         , size_t... CSAs >  // Compile time submatrix arguments
7461 inline Submatrix<MT,aligned,false,true,CSAs...>&
7462    Submatrix<MT,aligned,false,true,CSAs...>::operator=( const Submatrix& rhs )
7463 {
7464    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
7465    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
7466 
7467    if( this == &rhs || ( &matrix_ == &rhs.matrix_ && row() == rhs.row() && column() == rhs.column() ) )
7468       return *this;
7469 
7470    if( rows() != rhs.rows() || columns() != rhs.columns() ) {
7471       BLAZE_THROW_INVALID_ARGUMENT( "Submatrix sizes do not match" );
7472    }
7473 
7474    if( !tryAssign( matrix_, rhs, row(), column() ) ) {
7475       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7476    }
7477 
7478    decltype(auto) left( derestrict( *this ) );
7479 
7480    if( rhs.canAlias( this ) ) {
7481       const ResultType tmp( rhs );
7482       smpAssign( left, tmp );
7483    }
7484    else {
7485       smpAssign( left, rhs );
7486    }
7487 
7488    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
7489 
7490    return *this;
7491 }
7492 /*! \endcond */
7493 //*************************************************************************************************
7494 
7495 
7496 //*************************************************************************************************
7497 /*! \cond BLAZE_INTERNAL */
7498 /*!\brief Assignment operator for different matrices.
7499 //
7500 // \param rhs Matrix to be assigned.
7501 // \return Reference to the assigned submatrix.
7502 // \exception std::invalid_argument Matrix sizes do not match.
7503 // \exception std::invalid_argument Invalid assignment to restricted matrix.
7504 //
7505 // The dense submatrix is initialized as a copy of the given matrix. In case the current sizes
7506 // of the two matrices don't match, a \a std::invalid_argument exception is thrown. Also, if
7507 // the underlying matrix \a MT is a lower triangular, upper triangular, or symmetric matrix
7508 // and the assignment would violate its lower, upper, or symmetry property, respectively, a
7509 // \a std::invalid_argument exception is thrown.
7510 */
7511 template< typename MT       // Type of the dense matrix
7512         , size_t... CSAs >  // Compile time submatrix arguments
7513 template< typename MT2      // Type of the right-hand side matrix
7514         , bool SO >         // Storage order of the right-hand side matrix
7515 inline Submatrix<MT,aligned,false,true,CSAs...>&
7516    Submatrix<MT,aligned,false,true,CSAs...>::operator=( const Matrix<MT2,SO>& rhs )
7517 {
7518    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
7519 
7520    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
7521       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
7522    }
7523 
7524    using Right = If_t< IsRestricted_v<MT>, CompositeType_t<MT2>, const MT2& >;
7525    Right right( *rhs );
7526 
7527    if( !tryAssign( matrix_, right, row(), column() ) ) {
7528       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7529    }
7530 
7531    decltype(auto) left( derestrict( *this ) );
7532 
7533    if( IsReference_v<Right> && right.canAlias( this ) ) {
7534       const ResultType_t<MT2> tmp( right );
7535       if( IsSparseMatrix_v<MT2> )
7536          reset();
7537       smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
7538    }
7539    else {
7540       if( IsSparseMatrix_v<MT2> )
7541          reset();
7542       smpAssign( left, transIf< IsSymmetric_v<This> >( right ) );
7543    }
7544 
7545    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
7546 
7547    return *this;
7548 }
7549 /*! \endcond */
7550 //*************************************************************************************************
7551 
7552 
7553 //*************************************************************************************************
7554 /*! \cond BLAZE_INTERNAL */
7555 /*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
7556 //
7557 // \param rhs The right-hand side matrix to be added to the submatrix.
7558 // \return Reference to the dense submatrix.
7559 // \exception std::invalid_argument Matrix sizes do not match.
7560 // \exception std::invalid_argument Invalid assignment to restricted matrix.
7561 //
7562 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
7563 // is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
7564 // symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
7565 // respectively, a \a std::invalid_argument exception is thrown.
7566 */
7567 template< typename MT       // Type of the dense matrix
7568         , size_t... CSAs >  // Compile time submatrix arguments
7569 template< typename MT2      // Type of the right-hand side matrix
7570         , bool SO >         // Storage order of the right-hand side matrix
7571 inline auto Submatrix<MT,aligned,false,true,CSAs...>::operator+=( const Matrix<MT2,SO>& rhs )
7572    -> DisableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >
7573 {
7574    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
7575    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
7576    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
7577 
7578    using AddType = AddTrait_t< ResultType, ResultType_t<MT2> >;
7579 
7580    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( AddType );
7581    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
7582 
7583    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
7584       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
7585    }
7586 
7587    if( !tryAddAssign( matrix_, *rhs, row(), column() ) ) {
7588       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7589    }
7590 
7591    decltype(auto) left( derestrict( *this ) );
7592 
7593    if( ( ( IsSymmetric_v<MT> || IsHermitian_v<MT> ) && hasOverlap() ) || (*rhs).canAlias( this ) ) {
7594       const AddType tmp( *this + (*rhs) );
7595       smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
7596    }
7597    else {
7598       smpAddAssign( left, transIf< IsSymmetric_v<This> >( *rhs ) );
7599    }
7600 
7601    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
7602 
7603    return *this;
7604 }
7605 /*! \endcond */
7606 //*************************************************************************************************
7607 
7608 
7609 //*************************************************************************************************
7610 /*! \cond BLAZE_INTERNAL */
7611 /*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
7612 //
7613 // \param rhs The right-hand side matrix to be added to the submatrix.
7614 // \return Reference to the dense submatrix.
7615 // \exception std::invalid_argument Matrix sizes do not match.
7616 // \exception std::invalid_argument Invalid assignment to restricted matrix.
7617 //
7618 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
7619 // is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
7620 // symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
7621 // respectively, a \a std::invalid_argument exception is thrown.
7622 */
7623 template< typename MT       // Type of the dense matrix
7624         , size_t... CSAs >  // Compile time submatrix arguments
7625 template< typename MT2      // Type of the right-hand side matrix
7626         , bool SO >         // Storage order of the right-hand side matrix
7627 inline auto Submatrix<MT,aligned,false,true,CSAs...>::operator+=( const Matrix<MT2,SO>& rhs )
7628    -> EnableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >
7629 {
7630    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
7631    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
7632    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
7633 
7634    using AddType = AddTrait_t< ResultType, ResultType_t<MT2> >;
7635 
7636    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( AddType );
7637    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
7638 
7639    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
7640       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
7641    }
7642 
7643    const AddType tmp( *this + (*rhs) );
7644 
7645    if( !tryAssign( matrix_, tmp, row(), column() ) ) {
7646       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7647    }
7648 
7649    decltype(auto) left( derestrict( *this ) );
7650 
7651    smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
7652 
7653    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
7654 
7655    return *this;
7656 }
7657 /*! \endcond */
7658 //*************************************************************************************************
7659 
7660 
7661 //*************************************************************************************************
7662 /*! \cond BLAZE_INTERNAL */
7663 /*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
7664 //
7665 // \param rhs The right-hand side matrix to be subtracted from the submatrix.
7666 // \return Reference to the dense submatrix.
7667 // \exception std::invalid_argument Matrix sizes do not match.
7668 // \exception std::invalid_argument Invalid assignment to restricted matrix.
7669 //
7670 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
7671 // is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
7672 // symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
7673 // respectively, a \a std::invalid_argument exception is thrown.
7674 */
7675 template< typename MT       // Type of the dense matrix
7676         , size_t... CSAs >  // Compile time submatrix arguments
7677 template< typename MT2      // Type of the right-hand side matrix
7678         , bool SO >         // Storage order of the right-hand side matrix
7679 inline auto Submatrix<MT,aligned,false,true,CSAs...>::operator-=( const Matrix<MT2,SO>& rhs )
7680    -> DisableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >
7681 {
7682    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
7683    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
7684    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
7685 
7686    using SubType = SubTrait_t< ResultType, ResultType_t<MT2> >;
7687 
7688    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( SubType );
7689    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
7690 
7691    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
7692       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
7693    }
7694 
7695    if( !trySubAssign( matrix_, *rhs, row(), column() ) ) {
7696       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7697    }
7698 
7699    decltype(auto) left( derestrict( *this ) );
7700 
7701    if( ( ( IsSymmetric_v<MT> || IsHermitian_v<MT> ) && hasOverlap() ) || (*rhs).canAlias( this ) ) {
7702       const SubType tmp( *this - (*rhs ) );
7703       smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
7704    }
7705    else {
7706       smpSubAssign( left, transIf< IsSymmetric_v<This> >( *rhs ) );
7707    }
7708 
7709    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
7710 
7711    return *this;
7712 }
7713 /*! \endcond */
7714 //*************************************************************************************************
7715 
7716 
7717 //*************************************************************************************************
7718 /*! \cond BLAZE_INTERNAL */
7719 /*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
7720 //
7721 // \param rhs The right-hand side matrix to be subtracted from the submatrix.
7722 // \return Reference to the dense submatrix.
7723 // \exception std::invalid_argument Matrix sizes do not match.
7724 // \exception std::invalid_argument Invalid assignment to restricted matrix.
7725 //
7726 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
7727 // is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
7728 // symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
7729 // respectively, a \a std::invalid_argument exception is thrown.
7730 */
7731 template< typename MT       // Type of the dense matrix
7732         , size_t... CSAs >  // Compile time submatrix arguments
7733 template< typename MT2      // Type of the right-hand side matrix
7734         , bool SO >         // Storage order of the right-hand side matrix
7735 inline auto Submatrix<MT,aligned,false,true,CSAs...>::operator-=( const Matrix<MT2,SO>& rhs )
7736    -> EnableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >
7737 {
7738    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
7739    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
7740    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
7741 
7742    using SubType = SubTrait_t< ResultType, ResultType_t<MT2> >;
7743 
7744    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( SubType );
7745    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
7746 
7747    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
7748       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
7749    }
7750 
7751    const SubType tmp( *this - (*rhs) );
7752 
7753    if( !tryAssign( matrix_, tmp, row(), column() ) ) {
7754       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7755    }
7756 
7757    decltype(auto) left( derestrict( *this ) );
7758 
7759    smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
7760 
7761    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
7762 
7763    return *this;
7764 }
7765 /*! \endcond */
7766 //*************************************************************************************************
7767 
7768 
7769 //*************************************************************************************************
7770 /*! \cond BLAZE_INTERNAL */
7771 /*!\brief Schur product assignment operator for the multiplication of a matrix (\f$ A=B \f$).
7772 //
7773 // \param rhs The right-hand side matrix for the Schur product.
7774 // \return Reference to the dense submatrix.
7775 // \exception std::invalid_argument Matrix sizes do not match.
7776 // \exception std::invalid_argument Invalid assignment to restricted matrix.
7777 //
7778 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
7779 // is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
7780 // symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
7781 // respectively, a \a std::invalid_argument exception is thrown.
7782 */
7783 template< typename MT       // Type of the dense matrix
7784         , size_t... CSAs >  // Compile time submatrix arguments
7785 template< typename MT2      // Type of the right-hand side matrix
7786         , bool SO >         // Storage order of the right-hand side matrix
7787 inline auto Submatrix<MT,aligned,false,true,CSAs...>::operator%=( const Matrix<MT2,SO>& rhs )
7788    -> DisableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >
7789 {
7790    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
7791    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
7792    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
7793 
7794    using SchurType = SchurTrait_t< ResultType, ResultType_t<MT2> >;
7795 
7796    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SchurType );
7797 
7798    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
7799       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
7800    }
7801 
7802    if( !trySchurAssign( matrix_, *rhs, row(), column() ) ) {
7803       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7804    }
7805 
7806    decltype(auto) left( derestrict( *this ) );
7807 
7808    if( ( ( IsSymmetric_v<MT> || IsHermitian_v<MT> ) && hasOverlap() ) || (*rhs).canAlias( this ) ) {
7809       const SchurType tmp( *this % (*rhs) );
7810       if( IsSparseMatrix_v<SchurType> )
7811          reset();
7812       smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
7813    }
7814    else {
7815       smpSchurAssign( left, transIf< IsSymmetric_v<This> >( *rhs ) );
7816    }
7817 
7818    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
7819 
7820    return *this;
7821 }
7822 /*! \endcond */
7823 //*************************************************************************************************
7824 
7825 
7826 //*************************************************************************************************
7827 /*! \cond BLAZE_INTERNAL */
7828 /*!\brief Schur product assignment operator for the multiplication of a matrix (\f$ A=B \f$).
7829 //
7830 // \param rhs The right-hand side matrix for the Schur product.
7831 // \return Reference to the dense submatrix.
7832 // \exception std::invalid_argument Matrix sizes do not match.
7833 // \exception std::invalid_argument Invalid assignment to restricted matrix.
7834 //
7835 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
7836 // is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
7837 // symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
7838 // respectively, a \a std::invalid_argument exception is thrown.
7839 */
7840 template< typename MT       // Type of the dense matrix
7841         , size_t... CSAs >  // Compile time submatrix arguments
7842 template< typename MT2      // Type of the right-hand side matrix
7843         , bool SO >         // Storage order of the right-hand side matrix
7844 inline auto Submatrix<MT,aligned,false,true,CSAs...>::operator%=( const Matrix<MT2,SO>& rhs )
7845    -> EnableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >
7846 {
7847    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
7848    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
7849    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
7850 
7851    using SchurType = SchurTrait_t< ResultType, ResultType_t<MT2> >;
7852 
7853    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SchurType );
7854 
7855    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
7856       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
7857    }
7858 
7859    const SchurType tmp( *this % (*rhs) );
7860 
7861    if( !tryAssign( matrix_, tmp, row(), column() ) ) {
7862       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
7863    }
7864 
7865    decltype(auto) left( derestrict( *this ) );
7866 
7867    if( IsSparseMatrix_v<SchurType> ) {
7868       reset();
7869    }
7870 
7871    smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
7872 
7873    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
7874 
7875    return *this;
7876 }
7877 /*! \endcond */
7878 //*************************************************************************************************
7879 
7880 
7881 
7882 
7883 //=================================================================================================
7884 //
7885 //  UTILITY FUNCTIONS
7886 //
7887 //=================================================================================================
7888 
7889 //*************************************************************************************************
7890 /*! \cond BLAZE_INTERNAL */
7891 /*!\brief Returns the matrix containing the submatrix.
7892 //
7893 // \return The matrix containing the submatrix.
7894 */
7895 template< typename MT       // Type of the dense matrix
7896         , size_t... CSAs >  // Compile time submatrix arguments
operand()7897 inline MT& Submatrix<MT,aligned,false,true,CSAs...>::operand() noexcept
7898 {
7899    return matrix_;
7900 }
7901 /*! \endcond */
7902 //*************************************************************************************************
7903 
7904 
7905 //*************************************************************************************************
7906 /*! \cond BLAZE_INTERNAL */
7907 /*!\brief Returns the matrix containing the submatrix.
7908 //
7909 // \return The matrix containing the submatrix.
7910 */
7911 template< typename MT       // Type of the dense matrix
7912         , size_t... CSAs >  // Compile time submatrix arguments
operand()7913 inline const MT& Submatrix<MT,aligned,false,true,CSAs...>::operand() const noexcept
7914 {
7915    return matrix_;
7916 }
7917 /*! \endcond */
7918 //*************************************************************************************************
7919 
7920 
7921 //*************************************************************************************************
7922 /*! \cond BLAZE_INTERNAL */
7923 /*!\brief Returns the spacing between the beginning of two rows/columns.
7924 //
7925 // \return The spacing between the beginning of two rows/columns.
7926 //
7927 // This function returns the spacing between the beginning of two rows/columns, i.e. the
7928 // total number of elements of a row/column. In case the storage order is set to \a rowMajor
7929 // the function returns the spacing between two rows, in case the storage flag is set to
7930 // \a columnMajor the function returns the spacing between two columns.
7931 */
7932 template< typename MT       // Type of the dense matrix
7933         , size_t... CSAs >  // Compile time submatrix arguments
spacing()7934 inline size_t Submatrix<MT,aligned,false,true,CSAs...>::spacing() const noexcept
7935 {
7936    return matrix_.spacing();
7937 }
7938 /*! \endcond */
7939 //*************************************************************************************************
7940 
7941 
7942 //*************************************************************************************************
7943 /*! \cond BLAZE_INTERNAL */
7944 /*!\brief Returns the maximum capacity of the dense submatrix.
7945 //
7946 // \return The capacity of the dense submatrix.
7947 */
7948 template< typename MT       // Type of the dense matrix
7949         , size_t... CSAs >  // Compile time submatrix arguments
capacity()7950 inline size_t Submatrix<MT,aligned,false,true,CSAs...>::capacity() const noexcept
7951 {
7952    return rows() * columns();
7953 }
7954 /*! \endcond */
7955 //*************************************************************************************************
7956 
7957 
7958 //*************************************************************************************************
7959 /*! \cond BLAZE_INTERNAL */
7960 /*!\brief Returns the current capacity of the specified row/column.
7961 //
7962 // \param i The index of the row/column.
7963 // \return The current capacity of row/column \a i.
7964 //
7965 // This function returns the current capacity of the specified row/column. In case the
7966 // storage order is set to \a rowMajor the function returns the capacity of row \a i,
7967 // in case the storage flag is set to \a columnMajor the function returns the capacity
7968 // of column \a i.
7969 */
7970 template< typename MT       // Type of the dense matrix
7971         , size_t... CSAs >  // Compile time submatrix arguments
capacity(size_t i)7972 inline size_t Submatrix<MT,aligned,false,true,CSAs...>::capacity( size_t i ) const noexcept
7973 {
7974    MAYBE_UNUSED( i );
7975 
7976    BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
7977 
7978    return columns();
7979 }
7980 /*! \endcond */
7981 //*************************************************************************************************
7982 
7983 
7984 //*************************************************************************************************
7985 /*! \cond BLAZE_INTERNAL */
7986 /*!\brief Returns the number of non-zero elements in the dense submatrix
7987 //
7988 // \return The number of non-zero elements in the dense submatrix.
7989 */
7990 template< typename MT       // Type of the dense matrix
7991         , size_t... CSAs >  // Compile time submatrix arguments
nonZeros()7992 inline size_t Submatrix<MT,aligned,false,true,CSAs...>::nonZeros() const
7993 {
7994    const size_t iend( row() + rows() );
7995    const size_t jend( column() + columns() );
7996    size_t nonzeros( 0UL );
7997 
7998    for( size_t i=row(); i<iend; ++i )
7999       for( size_t j=column(); j<jend; ++j )
8000          if( !isDefault( matrix_(i,j) ) )
8001             ++nonzeros;
8002 
8003    return nonzeros;
8004 }
8005 /*! \endcond */
8006 //*************************************************************************************************
8007 
8008 
8009 //*************************************************************************************************
8010 /*! \cond BLAZE_INTERNAL */
8011 /*!\brief Returns the number of non-zero elements in the specified row/column.
8012 //
8013 // \param i The index of the row/column.
8014 // \return The number of non-zero elements of row/column \a i.
8015 //
8016 // This function returns the current number of non-zero elements in the specified row/column.
8017 // In case the storage order is set to \a rowMajor the function returns the number of non-zero
8018 // elements in row \a i, in case the storage flag is set to \a columnMajor the function returns
8019 // the number of non-zero elements in column \a i.
8020 */
8021 template< typename MT       // Type of the dense matrix
8022         , size_t... CSAs >  // Compile time submatrix arguments
nonZeros(size_t i)8023 inline size_t Submatrix<MT,aligned,false,true,CSAs...>::nonZeros( size_t i ) const
8024 {
8025    BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
8026 
8027    const size_t jend( column() + columns() );
8028    size_t nonzeros( 0UL );
8029 
8030    for( size_t j=column(); j<jend; ++j )
8031       if( !isDefault( matrix_(row()+i,j) ) )
8032          ++nonzeros;
8033 
8034    return nonzeros;
8035 }
8036 /*! \endcond */
8037 //*************************************************************************************************
8038 
8039 
8040 //*************************************************************************************************
8041 /*! \cond BLAZE_INTERNAL */
8042 /*!\brief Reset to the default initial values.
8043 //
8044 // \return void
8045 */
8046 template< typename MT       // Type of the dense matrix
8047         , size_t... CSAs >  // Compile time submatrix arguments
reset()8048 inline void Submatrix<MT,aligned,false,true,CSAs...>::reset()
8049 {
8050    using blaze::clear;
8051 
8052    for( size_t i=row(); i<row()+rows(); ++i )
8053    {
8054       const size_t jbegin( ( IsUpper_v<MT> )
8055                            ?( ( IsUniUpper_v<MT> || IsStrictlyUpper_v<MT> )
8056                               ?( max( i+1UL, column() ) )
8057                               :( max( i, column() ) ) )
8058                            :( column() ) );
8059       const size_t jend  ( ( IsLower_v<MT> )
8060                            ?( ( IsUniLower_v<MT> || IsStrictlyLower_v<MT> )
8061                               ?( min( i, column()+columns() ) )
8062                               :( min( i+1UL, column()+columns() ) ) )
8063                            :( column()+columns() ) );
8064 
8065       for( size_t j=jbegin; j<jend; ++j )
8066          clear( matrix_(i,j) );
8067    }
8068 }
8069 /*! \endcond */
8070 //*************************************************************************************************
8071 
8072 
8073 //*************************************************************************************************
8074 /*! \cond BLAZE_INTERNAL */
8075 /*!\brief Reset the specified row/column to the default initial values.
8076 //
8077 // \param i The index of the row/column.
8078 // \return void
8079 //
8080 // This function resets the values in the specified row/column to their default value. In case
8081 // the storage order is set to \a rowMajor the function resets the values in row \a i, in case
8082 // the storage order is set to \a columnMajor the function resets the values in column \a i.
8083 // Note that the capacity of the row/column remains unchanged.
8084 */
8085 template< typename MT       // Type of the dense matrix
8086         , size_t... CSAs >  // Compile time submatrix arguments
reset(size_t i)8087 inline void Submatrix<MT,aligned,false,true,CSAs...>::reset( size_t i )
8088 {
8089    using blaze::clear;
8090 
8091    BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
8092 
8093    const size_t jbegin( ( IsUpper_v<MT> )
8094                         ?( ( IsUniUpper_v<MT> || IsStrictlyUpper_v<MT> )
8095                            ?( max( i+1UL, column() ) )
8096                            :( max( i, column() ) ) )
8097                         :( column() ) );
8098    const size_t jend  ( ( IsLower_v<MT> )
8099                         ?( ( IsUniLower_v<MT> || IsStrictlyLower_v<MT> )
8100                            ?( min( i, column()+columns() ) )
8101                            :( min( i+1UL, column()+columns() ) ) )
8102                         :( column()+columns() ) );
8103 
8104    for( size_t j=jbegin; j<jend; ++j )
8105       clear( matrix_(row()+i,j) );
8106 }
8107 /*! \endcond */
8108 //*************************************************************************************************
8109 
8110 
8111 //*************************************************************************************************
8112 /*! \cond BLAZE_INTERNAL */
8113 /*!\brief Checking whether there exists an overlap in the context of a symmetric matrix.
8114 //
8115 // \return \a true in case an overlap exists, \a false if not.
8116 //
8117 // This function checks if in the context of a symmetric matrix the submatrix has an overlap with
8118 // its counterpart. In case an overlap exists, the function return \a true, otherwise it returns
8119 // \a false.
8120 */
8121 template< typename MT       // Type of the dense matrix
8122         , size_t... CSAs >  // Compile time submatrix arguments
hasOverlap()8123 inline bool Submatrix<MT,aligned,false,true,CSAs...>::hasOverlap() const noexcept
8124 {
8125    BLAZE_INTERNAL_ASSERT( IsSymmetric_v<MT> || IsHermitian_v<MT>, "Invalid matrix detected" );
8126 
8127    if( ( row() + rows() <= column() ) || ( column() + columns() <= row() ) )
8128       return false;
8129    else return true;
8130 }
8131 /*! \endcond */
8132 //*************************************************************************************************
8133 
8134 
8135 
8136 
8137 //=================================================================================================
8138 //
8139 //  NUMERIC FUNCTIONS
8140 //
8141 //=================================================================================================
8142 
8143 //*************************************************************************************************
8144 /*! \cond BLAZE_INTERNAL */
8145 /*!\brief In-place transpose of the submatrix.
8146 //
8147 // \return Reference to the transposed submatrix.
8148 // \exception std::logic_error Invalid transpose of a non-quadratic submatrix.
8149 // \exception std::logic_error Invalid transpose operation.
8150 //
8151 // This function transposes the dense submatrix in-place. Note that this function can only be used
8152 // for quadratic submatrices, i.e. if the number of rows is equal to the number of columns. Also,
8153 // the function fails if ...
8154 //
8155 //  - ... the submatrix contains elements from the upper part of the underlying lower matrix;
8156 //  - ... the submatrix contains elements from the lower part of the underlying upper matrix;
8157 //  - ... the result would be non-deterministic in case of a symmetric or Hermitian matrix.
8158 //
8159 // In all cases, a \a std::logic_error is thrown.
8160 */
8161 template< typename MT       // Type of the dense matrix
8162         , size_t... CSAs >  // Compile time submatrix arguments
8163 inline Submatrix<MT,aligned,false,true,CSAs...>&
transpose()8164    Submatrix<MT,aligned,false,true,CSAs...>::transpose()
8165 {
8166    if( rows() != columns() ) {
8167       BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
8168    }
8169 
8170    if( !tryAssign( matrix_, trans( *this ), row(), column() ) ) {
8171       BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
8172    }
8173 
8174    decltype(auto) left( derestrict( *this ) );
8175    const ResultType tmp( trans( *this ) );
8176 
8177    smpAssign( left, tmp );
8178 
8179    return *this;
8180 }
8181 /*! \endcond */
8182 //*************************************************************************************************
8183 
8184 
8185 //*************************************************************************************************
8186 /*! \cond BLAZE_INTERNAL */
8187 /*!\brief In-place conjugate transpose of the submatrix.
8188 //
8189 // \return Reference to the transposed submatrix.
8190 // \exception std::logic_error Invalid transpose of a non-quadratic submatrix.
8191 // \exception std::logic_error Invalid transpose operation.
8192 //
8193 // This function transposes the dense submatrix in-place. Note that this function can only be used
8194 // for quadratic submatrices, i.e. if the number of rows is equal to the number of columns. Also,
8195 // the function fails if ...
8196 //
8197 //  - ... the submatrix contains elements from the upper part of the underlying lower matrix;
8198 //  - ... the submatrix contains elements from the lower part of the underlying upper matrix;
8199 //  - ... the result would be non-deterministic in case of a symmetric or Hermitian matrix.
8200 //
8201 // In all cases, a \a std::logic_error is thrown.
8202 */
8203 template< typename MT       // Type of the dense matrix
8204         , size_t... CSAs >  // Compile time submatrix arguments
8205 inline Submatrix<MT,aligned,false,true,CSAs...>&
ctranspose()8206    Submatrix<MT,aligned,false,true,CSAs...>::ctranspose()
8207 {
8208    if( rows() != columns() ) {
8209       BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
8210    }
8211 
8212    if( !tryAssign( matrix_, ctrans( *this ), row(), column() ) ) {
8213       BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
8214    }
8215 
8216    decltype(auto) left( derestrict( *this ) );
8217    const ResultType tmp( ctrans( *this ) );
8218 
8219    smpAssign( left, tmp );
8220 
8221    return *this;
8222 }
8223 /*! \endcond */
8224 //*************************************************************************************************
8225 
8226 
8227 //*************************************************************************************************
8228 /*! \cond BLAZE_INTERNAL */
8229 /*!\brief Scaling of the dense submatrix by the scalar value \a scalar (\f$ A=B*s \f$).
8230 //
8231 // \param scalar The scalar value for the submatrix scaling.
8232 // \return Reference to the dense submatrix.
8233 //
8234 // This function scales the submatrix by applying the given scalar value \a scalar to each
8235 // element of the submatrix. For built-in and \c complex data types it has the same effect
8236 // as using the multiplication assignment operator. Note that the function cannot be used
8237 // to scale a submatrix on a lower or upper unitriangular matrix. The attempt to scale
8238 // such a submatrix results in a compile time error!
8239 */
8240 template< typename MT       // Type of the dense matrix
8241         , size_t... CSAs >  // Compile time submatrix arguments
8242 template< typename Other >  // Data type of the scalar value
8243 inline Submatrix<MT,aligned,false,true,CSAs...>&
scale(const Other & scalar)8244    Submatrix<MT,aligned,false,true,CSAs...>::scale( const Other& scalar )
8245 {
8246    BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
8247 
8248    const size_t iend( row() + rows() );
8249 
8250    for( size_t i=row(); i<iend; ++i )
8251    {
8252       const size_t jbegin( ( IsUpper_v<MT> )
8253                            ?( ( IsStrictlyUpper_v<MT> )
8254                               ?( max( i+1UL, column() ) )
8255                               :( max( i, column() ) ) )
8256                            :( column() ) );
8257       const size_t jend  ( ( IsLower_v<MT> )
8258                            ?( ( IsStrictlyLower_v<MT> )
8259                               ?( min( i, column()+columns() ) )
8260                               :( min( i+1UL, column()+columns() ) ) )
8261                            :( column()+columns() ) );
8262 
8263       for( size_t j=jbegin; j<jend; ++j )
8264          matrix_(i,j) *= scalar;
8265    }
8266 
8267    return *this;
8268 }
8269 /*! \endcond */
8270 //*************************************************************************************************
8271 
8272 
8273 
8274 
8275 //=================================================================================================
8276 //
8277 //  EXPRESSION TEMPLATE EVALUATION FUNCTIONS
8278 //
8279 //=================================================================================================
8280 
8281 //*************************************************************************************************
8282 /*! \cond BLAZE_INTERNAL */
8283 /*!\brief Returns whether the submatrix can alias with the given address \a alias.
8284 //
8285 // \param alias The alias to be checked.
8286 // \return \a true in case the alias corresponds to this submatrix, \a false if not.
8287 //
8288 // This function returns whether the given address can alias with the submatrix. In contrast
8289 // to the isAliased() function this function is allowed to use compile time expressions to
8290 // optimize the evaluation.
8291 */
8292 template< typename MT       // Type of the dense matrix
8293         , size_t... CSAs >  // Compile time submatrix arguments
8294 template< typename Other >  // Data type of the foreign expression
canAlias(const Other * alias)8295 inline bool Submatrix<MT,aligned,false,true,CSAs...>::canAlias( const Other* alias ) const noexcept
8296 {
8297    return matrix_.isAliased( &unview( *alias ) );
8298 }
8299 /*! \endcond */
8300 //*************************************************************************************************
8301 
8302 
8303 //*************************************************************************************************
8304 /*! \cond BLAZE_INTERNAL */
8305 /*!\brief Returns whether the submatrix can alias with the given dense submatrix \a alias.
8306 //
8307 // \param alias The alias to be checked.
8308 // \return \a true in case the alias corresponds to this submatrix, \a false if not.
8309 //
8310 // This function returns whether the given address can alias with the submatrix. In contrast
8311 // to the isAliased() function this function is allowed to use compile time expressions to
8312 // optimize the evaluation.
8313 */
8314 template< typename MT        // Type of the dense matrix
8315         , size_t... CSAs >   // Compile time submatrix arguments
8316 template< typename MT2       // Data type of the foreign dense submatrix
8317         , AlignmentFlag AF2  // Alignment flag of the foreign dense submatrix
8318         , bool SO2           // Storage order of the foreign dense submatrix
8319         , size_t... CSAs2 >  // Compile time submatrix arguments of the foreign dense submatrix
8320 inline bool
canAlias(const Submatrix<MT2,AF2,SO2,true,CSAs2...> * alias)8321    Submatrix<MT,aligned,false,true,CSAs...>::canAlias( const Submatrix<MT2,AF2,SO2,true,CSAs2...>* alias ) const noexcept
8322 {
8323    return ( matrix_.isAliased( &alias->matrix_ ) &&
8324             ( row() + rows() > alias->row() ) &&
8325             ( row() < alias->row() + alias->rows() ) &&
8326             ( column() + columns() > alias->column() ) &&
8327             ( column() < alias->column() + alias->columns() ) );
8328 }
8329 /*! \endcond */
8330 //*************************************************************************************************
8331 
8332 
8333 //*************************************************************************************************
8334 /*! \cond BLAZE_INTERNAL */
8335 /*!\brief Returns whether the submatrix is aliased with the given address \a alias.
8336 //
8337 // \param alias The alias to be checked.
8338 // \return \a true in case the alias corresponds to this submatrix, \a false if not.
8339 //
8340 // This function returns whether the given address is aliased with the submatrix. In contrast
8341 // to the canAlias() function this function is not allowed to use compile time expressions to
8342 // optimize the evaluation.
8343 */
8344 template< typename MT       // Type of the dense matrix
8345         , size_t... CSAs >  // Compile time submatrix arguments
8346 template< typename Other >  // Data type of the foreign expression
isAliased(const Other * alias)8347 inline bool Submatrix<MT,aligned,false,true,CSAs...>::isAliased( const Other* alias ) const noexcept
8348 {
8349    return matrix_.isAliased( &unview( *alias ) );
8350 }
8351 /*! \endcond */
8352 //*************************************************************************************************
8353 
8354 
8355 //*************************************************************************************************
8356 /*! \cond BLAZE_INTERNAL */
8357 /*!\brief Returns whether the submatrix is aliased with the given dense submatrix \a alias.
8358 //
8359 // \param alias The alias to be checked.
8360 // \return \a true in case the alias corresponds to this submatrix, \a false if not.
8361 //
8362 // This function returns whether the given address is aliased with the submatrix. In contrast
8363 // to the canAlias() function this function is not allowed to use compile time expressions to
8364 // optimize the evaluation.
8365 */
8366 template< typename MT        // Type of the dense matrix
8367         , size_t... CSAs >   // Compile time submatrix arguments
8368 template< typename MT2       // Data type of the foreign dense submatrix
8369         , AlignmentFlag AF2  // Alignment flag of the foreign dense submatrix
8370         , bool SO2           // Storage order of the foreign dense submatrix
8371         , size_t... CSAs2 >  // Compile time submatrix arguments of the foreign dense submatrix
8372 inline bool
isAliased(const Submatrix<MT2,AF2,SO2,true,CSAs2...> * alias)8373    Submatrix<MT,aligned,false,true,CSAs...>::isAliased( const Submatrix<MT2,AF2,SO2,true,CSAs2...>* alias ) const noexcept
8374 {
8375    return ( matrix_.isAliased( &alias->matrix_ ) &&
8376             ( row() + rows() > alias->row() ) &&
8377             ( row() < alias->row() + alias->rows() ) &&
8378             ( column() + columns() > alias->column() ) &&
8379             ( column() < alias->column() + alias->columns() ) );
8380 }
8381 /*! \endcond */
8382 //*************************************************************************************************
8383 
8384 
8385 //*************************************************************************************************
8386 /*! \cond BLAZE_INTERNAL */
8387 /*!\brief Returns whether the submatrix is properly aligned in memory.
8388 //
8389 // \return \a true in case the submatrix is aligned, \a false if not.
8390 //
8391 // This function returns whether the submatrix is guaranteed to be properly aligned in memory,
8392 // i.e. whether the beginning and the end of each row of the submatrix are guaranteed to conform
8393 // to the alignment restrictions of the underlying element type.
8394 */
8395 template< typename MT       // Type of the dense matrix
8396         , size_t... CSAs >  // Compile time submatrix arguments
isAligned()8397 inline bool Submatrix<MT,aligned,false,true,CSAs...>::isAligned() const noexcept
8398 {
8399    return true;
8400 }
8401 /*! \endcond */
8402 //*************************************************************************************************
8403 
8404 
8405 //*************************************************************************************************
8406 /*! \cond BLAZE_INTERNAL */
8407 /*!\brief Returns whether the submatrix can be used in SMP assignments.
8408 //
8409 // \return \a true in case the submatrix can be used in SMP assignments, \a false if not.
8410 //
8411 // This function returns whether the submatrix can be used in SMP assignments. In contrast to the
8412 // \a smpAssignable member enumeration, which is based solely on compile time information, this
8413 // function additionally provides runtime information (as for instance the current number of
8414 // rows and/or columns of the submatrix).
8415 */
8416 template< typename MT       // Type of the dense matrix
8417         , size_t... CSAs >  // Compile time submatrix arguments
canSMPAssign()8418 inline bool Submatrix<MT,aligned,false,true,CSAs...>::canSMPAssign() const noexcept
8419 {
8420    return ( rows() * columns() >= SMP_DMATASSIGN_THRESHOLD );
8421 }
8422 /*! \endcond */
8423 //*************************************************************************************************
8424 
8425 
8426 //*************************************************************************************************
8427 /*! \cond BLAZE_INTERNAL */
8428 /*!\brief Load of a SIMD element of the submatrix.
8429 //
8430 // \param i Access index for the row. The index has to be in the range [0..M-1].
8431 // \param j Access index for the column. The index has to be in the range [0..N-1].
8432 // \return The loaded SIMD element.
8433 //
8434 // This function performs a load of a specific SIMD element of the dense submatrix. The row
8435 // index must be smaller than the number of rows and the column index must be smaller than
8436 // the number of columns. Additionally, the column index (in case of a row-major matrix) or
8437 // the row index (in case of a column-major matrix) must be a multiple of the number of values
8438 // inside the SIMD element. This function must \b NOT be called explicitly! It is used
8439 // internally for the performance optimized evaluation of expression templates. Calling this
8440 // function explicitly might result in erroneous results and/or in compilation errors.
8441 */
8442 template< typename MT       // Type of the dense matrix
8443         , size_t... CSAs >  // Compile time submatrix arguments
8444 BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,false,true,CSAs...>::SIMDType
load(size_t i,size_t j)8445    Submatrix<MT,aligned,false,true,CSAs...>::load( size_t i, size_t j ) const noexcept
8446 {
8447    return loada( i, j );
8448 }
8449 /*! \endcond */
8450 //*************************************************************************************************
8451 
8452 
8453 //*************************************************************************************************
8454 /*! \cond BLAZE_INTERNAL */
8455 /*!\brief Aligned load of a SIMD element of the submatrix.
8456 //
8457 // \param i Access index for the row. The index has to be in the range [0..M-1].
8458 // \param j Access index for the column. The index has to be in the range [0..N-1].
8459 // \return The loaded SIMD element.
8460 //
8461 // This function performs an aligned load of a specific SIMD element of the dense submatrix.
8462 // The row index must be smaller than the number of rows and the column index must be smaller
8463 // than the number of columns. Additionally, the column index (in case of a row-major matrix)
8464 // or the row index (in case of a column-major matrix) must be a multiple of the number of
8465 // values inside the SIMD element. This function must \b NOT be called explicitly! It is used
8466 // internally for the performance optimized evaluation of expression templates. Calling this
8467 // function explicitly might result in erroneous results and/or in compilation errors.
8468 */
8469 template< typename MT       // Type of the dense matrix
8470         , size_t... CSAs >  // Compile time submatrix arguments
8471 BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,false,true,CSAs...>::SIMDType
loada(size_t i,size_t j)8472    Submatrix<MT,aligned,false,true,CSAs...>::loada( size_t i, size_t j ) const noexcept
8473 {
8474    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
8475 
8476    BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
8477    BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
8478    BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
8479    BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
8480 
8481    return matrix_.loada( row()+i, column()+j );
8482 }
8483 /*! \endcond */
8484 //*************************************************************************************************
8485 
8486 
8487 //*************************************************************************************************
8488 /*! \cond BLAZE_INTERNAL */
8489 /*!\brief Unaligned load of a SIMD element of the submatrix.
8490 //
8491 // \param i Access index for the row. The index has to be in the range [0..M-1].
8492 // \param j Access index for the column. The index has to be in the range [0..N-1].
8493 // \return The loaded SIMD element.
8494 //
8495 // This function performs an unaligned load of a specific SIMD element of the dense submatrix.
8496 // The row index must be smaller than the number of rows and the column index must be smaller
8497 // than the number of columns. Additionally, the column index (in case of a row-major matrix)
8498 // or the row index (in case of a column-major matrix) must be a multiple of the number of
8499 // values inside the SIMD element. This function must \b NOT be called explicitly! It is used
8500 // internally for the performance optimized evaluation of expression templates. Calling this
8501 // function explicitly might result in erroneous results and/or in compilation errors.
8502 */
8503 template< typename MT       // Type of the dense matrix
8504         , size_t... CSAs >  // Compile time submatrix arguments
8505 BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,false,true,CSAs...>::SIMDType
loadu(size_t i,size_t j)8506    Submatrix<MT,aligned,false,true,CSAs...>::loadu( size_t i, size_t j ) const noexcept
8507 {
8508    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
8509 
8510    BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
8511    BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
8512    BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
8513 
8514    return matrix_.loadu( row()+i, column()+j );
8515 }
8516 /*! \endcond */
8517 //*************************************************************************************************
8518 
8519 
8520 //*************************************************************************************************
8521 /*! \cond BLAZE_INTERNAL */
8522 /*!\brief Store of a SIMD element of the submatrix.
8523 //
8524 // \param i Access index for the row. The index has to be in the range [0..M-1].
8525 // \param j Access index for the column. The index has to be in the range [0..N-1].
8526 // \param value The SIMD element to be stored.
8527 // \return void
8528 //
8529 // This function performs a store of a specific SIMD element of the dense submatrix. The
8530 // row index must be smaller than the number of rows and the column index must be smaller
8531 // than the number of columns. Additionally, the column index (in case of a row-major matrix)
8532 // or the row index (in case of a column-major matrix) must be a multiple of the number of
8533 // values inside the SIMD element. This function must \b NOT be called explicitly! It is used
8534 // internally for the performance optimized evaluation of expression templates. Calling this
8535 // function explicitly might result in erroneous results and/or in compilation errors.
8536 */
8537 template< typename MT       // Type of the dense matrix
8538         , size_t... CSAs >  // Compile time submatrix arguments
8539 BLAZE_ALWAYS_INLINE void
store(size_t i,size_t j,const SIMDType & value)8540    Submatrix<MT,aligned,false,true,CSAs...>::store( size_t i, size_t j, const SIMDType& value ) noexcept
8541 {
8542    return storea( i, j, value );
8543 }
8544 /*! \endcond */
8545 //*************************************************************************************************
8546 
8547 
8548 //*************************************************************************************************
8549 /*! \cond BLAZE_INTERNAL */
8550 /*!\brief Aligned store of a SIMD element of the submatrix.
8551 //
8552 // \param i Access index for the row. The index has to be in the range [0..M-1].
8553 // \param j Access index for the column. The index has to be in the range [0..N-1].
8554 // \param value The SIMD element to be stored.
8555 // \return void
8556 //
8557 // This function performs an aligned store of a specific SIMD element of the dense submatrix.
8558 // The row index must be smaller than the number of rows and the column index must be smaller than
8559 // the number of columns. Additionally, the column index (in case of a row-major matrix) or the
8560 // row index (in case of a column-major matrix) must be a multiple of the number of values inside
8561 // the SIMD element. This function must \b NOT be called explicitly! It is used internally for
8562 // the performance optimized evaluation of expression templates. Calling this function explicitly
8563 // might result in erroneous results and/or in compilation errors.
8564 */
8565 template< typename MT       // Type of the dense matrix
8566         , size_t... CSAs >  // Compile time submatrix arguments
8567 BLAZE_ALWAYS_INLINE void
storea(size_t i,size_t j,const SIMDType & value)8568    Submatrix<MT,aligned,false,true,CSAs...>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
8569 {
8570    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
8571 
8572    BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
8573    BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
8574    BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
8575    BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
8576 
8577    return matrix_.storea( row()+i, column()+j, value );
8578 }
8579 /*! \endcond */
8580 //*************************************************************************************************
8581 
8582 
8583 //*************************************************************************************************
8584 /*! \cond BLAZE_INTERNAL */
8585 /*!\brief Unaligned store of a SIMD element of the submatrix.
8586 //
8587 // \param i Access index for the row. The index has to be in the range [0..M-1].
8588 // \param j Access index for the column. The index has to be in the range [0..N-1].
8589 // \param value The SIMD element to be stored.
8590 // \return void
8591 //
8592 // This function performs an unaligned store of a specific SIMD element of the dense
8593 // submatrix. The row index must be smaller than the number of rows and the column index must
8594 // be smaller than the number of columns. Additionally, the column index (in case of a row-major
8595 // matrix) or the row index (in case of a column-major matrix) must be a multiple of the number
8596 // of values inside the SIMD element. This function must \b NOT be called explicitly! It is used
8597 // internally for the performance optimized evaluation of expression templates. Calling this
8598 // function explicitly might result in erroneous results and/or in compilation errors.
8599 */
8600 template< typename MT       // Type of the dense matrix
8601         , size_t... CSAs >  // Compile time submatrix arguments
8602 BLAZE_ALWAYS_INLINE void
storeu(size_t i,size_t j,const SIMDType & value)8603    Submatrix<MT,aligned,false,true,CSAs...>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
8604 {
8605    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
8606 
8607    BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
8608    BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
8609    BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
8610 
8611    matrix_.storeu( row()+i, column()+j, value );
8612 }
8613 /*! \endcond */
8614 //*************************************************************************************************
8615 
8616 
8617 //*************************************************************************************************
8618 /*! \cond BLAZE_INTERNAL */
8619 /*!\brief Aligned, non-temporal store of a SIMD element of the submatrix.
8620 //
8621 // \param i Access index for the row. The index has to be in the range [0..M-1].
8622 // \param j Access index for the column. The index has to be in the range [0..N-1].
8623 // \param value The SIMD element to be stored.
8624 // \return void
8625 //
8626 // This function performs an aligned, non-temporal store of a specific SIMD element of the
8627 // dense submatrix. The row index must be smaller than the number of rows and the column index
8628 // must be smaller than the number of columns. Additionally, the column index (in case of a
8629 // row-major matrix) or the row index (in case of a column-major matrix) must be a multiple
8630 // of the number of values inside the SIMD element. This function must \b NOT be called
8631 // explicitly! It is used internally for the performance optimized evaluation of expression
8632 // templates. Calling this function explicitly might result in erroneous results and/or in
8633 // compilation errors.
8634 */
8635 template< typename MT       // Type of the dense matrix
8636         , size_t... CSAs >  // Compile time submatrix arguments
8637 BLAZE_ALWAYS_INLINE void
stream(size_t i,size_t j,const SIMDType & value)8638    Submatrix<MT,aligned,false,true,CSAs...>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
8639 {
8640    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
8641 
8642    BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
8643    BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
8644    BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= columns(), "Invalid column access index" );
8645    BLAZE_INTERNAL_ASSERT( j % SIMDSIZE == 0UL, "Invalid column access index" );
8646 
8647    matrix_.stream( row()+i, column()+j, value );
8648 }
8649 /*! \endcond */
8650 //*************************************************************************************************
8651 
8652 
8653 //*************************************************************************************************
8654 /*! \cond BLAZE_INTERNAL */
8655 /*!\brief Default implementation of the assignment of a row-major dense matrix.
8656 //
8657 // \param rhs The right-hand side dense matrix to be assigned.
8658 // \return void
8659 //
8660 // This function must \b NOT be called explicitly! It is used internally for the performance
8661 // optimized evaluation of expression templates. Calling this function explicitly might result
8662 // in erroneous results and/or in compilation errors. Instead of using this function use the
8663 // assignment operator.
8664 */
8665 template< typename MT       // Type of the dense matrix
8666         , size_t... CSAs >  // Compile time submatrix arguments
8667 template< typename MT2 >    // Type of the right-hand side dense matrix
8668 inline auto Submatrix<MT,aligned,false,true,CSAs...>::assign( const DenseMatrix<MT2,false>& rhs )
8669    -> DisableIf_t< VectorizedAssign_v<MT2> >
8670 {
8671    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
8672    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
8673 
8674    const size_t jpos( prevMultiple( columns(), 2UL ) );
8675    BLAZE_INTERNAL_ASSERT( jpos <= columns(), "Invalid end calculation" );
8676 
8677    for( size_t i=0UL; i<rows(); ++i ) {
8678       for( size_t j=0UL; j<jpos; j+=2UL ) {
8679          matrix_(row()+i,column()+j    ) = (*rhs)(i,j    );
8680          matrix_(row()+i,column()+j+1UL) = (*rhs)(i,j+1UL);
8681       }
8682       if( jpos < columns() ) {
8683          matrix_(row()+i,column()+jpos) = (*rhs)(i,jpos);
8684       }
8685    }
8686 }
8687 /*! \endcond */
8688 //*************************************************************************************************
8689 
8690 
8691 //*************************************************************************************************
8692 /*! \cond BLAZE_INTERNAL */
8693 /*!\brief SIMD optimized implementation of the assignment of a row-major dense matrix.
8694 //
8695 // \param rhs The right-hand side dense matrix to be assigned.
8696 // \return void
8697 //
8698 // This function must \b NOT be called explicitly! It is used internally for the performance
8699 // optimized evaluation of expression templates. Calling this function explicitly might result
8700 // in erroneous results and/or in compilation errors. Instead of using this function use the
8701 // assignment operator.
8702 */
8703 template< typename MT       // Type of the dense matrix
8704         , size_t... CSAs >  // Compile time submatrix arguments
8705 template< typename MT2 >    // Type of the right-hand side dense matrix
8706 inline auto Submatrix<MT,aligned,false,true,CSAs...>::assign( const DenseMatrix<MT2,false>& rhs )
8707    -> EnableIf_t< VectorizedAssign_v<MT2> >
8708 {
8709    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
8710 
8711    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
8712    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
8713 
8714    const size_t jpos( prevMultiple( columns(), SIMDSIZE ) );
8715    BLAZE_INTERNAL_ASSERT( jpos <= columns(), "Invalid end calculation" );
8716 
8717    if( useStreaming &&
8718        rows()*columns() > ( cacheSize / ( sizeof(ElementType) * 3UL ) ) &&
8719        !(*rhs).isAliased( this ) )
8720    {
8721       for( size_t i=0UL; i<rows(); ++i )
8722       {
8723          size_t j( 0UL );
8724          Iterator left( begin(i) );
8725          ConstIterator_t<MT2> right( (*rhs).begin(i) );
8726 
8727          for( ; j<jpos; j+=SIMDSIZE ) {
8728             left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8729          }
8730          for( ; j<columns(); ++j ) {
8731             *left = *right; ++left; ++right;
8732          }
8733       }
8734    }
8735    else
8736    {
8737       for( size_t i=0UL; i<rows(); ++i )
8738       {
8739          size_t j( 0UL );
8740          Iterator left( begin(i) );
8741          ConstIterator_t<MT2> right( (*rhs).begin(i) );
8742 
8743          for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
8744             left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8745             left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8746             left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8747             left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8748          }
8749          for( ; j<jpos; j+=SIMDSIZE ) {
8750             left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8751          }
8752          for( ; j<columns(); ++j ) {
8753             *left = *right; ++left; ++right;
8754          }
8755       }
8756    }
8757 }
8758 /*! \endcond */
8759 //*************************************************************************************************
8760 
8761 
8762 //*************************************************************************************************
8763 /*! \cond BLAZE_INTERNAL */
8764 /*!\brief Default implementation of the assignment of a column-major dense matrix.
8765 //
8766 // \param rhs The right-hand side dense matrix to be assigned.
8767 // \return void
8768 //
8769 // This function must \b NOT be called explicitly! It is used internally for the performance
8770 // optimized evaluation of expression templates. Calling this function explicitly might result
8771 // in erroneous results and/or in compilation errors. Instead of using this function use the
8772 // assignment operator.
8773 */
8774 template< typename MT       // Type of the dense matrix
8775         , size_t... CSAs >  // Compile time submatrix arguments
8776 template< typename MT2 >    // Type of the right-hand side dense matrix
assign(const DenseMatrix<MT2,true> & rhs)8777 inline void Submatrix<MT,aligned,false,true,CSAs...>::assign( const DenseMatrix<MT2,true>& rhs )
8778 {
8779    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
8780 
8781    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
8782    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
8783 
8784    constexpr size_t block( BLOCK_SIZE );
8785 
8786    for( size_t ii=0UL; ii<rows(); ii+=block ) {
8787       const size_t iend( ( rows()<(ii+block) )?( rows() ):( ii+block ) );
8788       for( size_t jj=0UL; jj<columns(); jj+=block ) {
8789          const size_t jend( ( columns()<(jj+block) )?( columns() ):( jj+block ) );
8790          for( size_t i=ii; i<iend; ++i ) {
8791             for( size_t j=jj; j<jend; ++j ) {
8792                matrix_(row()+i,column()+j) = (*rhs)(i,j);
8793             }
8794          }
8795       }
8796    }
8797 }
8798 /*! \endcond */
8799 //*************************************************************************************************
8800 
8801 
8802 //*************************************************************************************************
8803 /*! \cond BLAZE_INTERNAL */
8804 /*!\brief Default implementation of the assignment of a row-major sparse matrix.
8805 //
8806 // \param rhs The right-hand side sparse matrix to be assigned.
8807 // \return void
8808 //
8809 // This function must \b NOT be called explicitly! It is used internally for the performance
8810 // optimized evaluation of expression templates. Calling this function explicitly might result
8811 // in erroneous results and/or in compilation errors. Instead of using this function use the
8812 // assignment operator.
8813 */
8814 template< typename MT       // Type of the dense matrix
8815         , size_t... CSAs >  // Compile time submatrix arguments
8816 template< typename MT2 >    // Type of the right-hand side sparse matrix
assign(const SparseMatrix<MT2,false> & rhs)8817 inline void Submatrix<MT,aligned,false,true,CSAs...>::assign( const SparseMatrix<MT2,false>& rhs )
8818 {
8819    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
8820    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
8821 
8822    for( size_t i=0UL; i<rows(); ++i )
8823       for( ConstIterator_t<MT2> element=(*rhs).begin(i); element!=(*rhs).end(i); ++element )
8824          matrix_(row()+i,column()+element->index()) = element->value();
8825 }
8826 /*! \endcond */
8827 //*************************************************************************************************
8828 
8829 
8830 //*************************************************************************************************
8831 /*! \cond BLAZE_INTERNAL */
8832 /*!\brief Default implementation of the assignment of a column-major sparse matrix.
8833 //
8834 // \param rhs The right-hand side sparse matrix to be assigned.
8835 // \return void
8836 //
8837 // This function must \b NOT be called explicitly! It is used internally for the performance
8838 // optimized evaluation of expression templates. Calling this function explicitly might result
8839 // in erroneous results and/or in compilation errors. Instead of using this function use the
8840 // assignment operator.
8841 */
8842 template< typename MT       // Type of the dense matrix
8843         , size_t... CSAs >  // Compile time submatrix arguments
8844 template< typename MT2 >    // Type of the right-hand side sparse matrix
assign(const SparseMatrix<MT2,true> & rhs)8845 inline void Submatrix<MT,aligned,false,true,CSAs...>::assign( const SparseMatrix<MT2,true>& rhs )
8846 {
8847    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
8848 
8849    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
8850    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
8851 
8852    for( size_t j=0UL; j<columns(); ++j )
8853       for( ConstIterator_t<MT2> element=(*rhs).begin(j); element!=(*rhs).end(j); ++element )
8854          matrix_(row()+element->index(),column()+j) = element->value();
8855 }
8856 /*! \endcond */
8857 //*************************************************************************************************
8858 
8859 
8860 //*************************************************************************************************
8861 /*! \cond BLAZE_INTERNAL */
8862 /*!\brief Default implementation of the addition assignment of a row-major dense matrix.
8863 //
8864 // \param rhs The right-hand side dense matrix to be added.
8865 // \return void
8866 //
8867 // This function must \b NOT be called explicitly! It is used internally for the performance
8868 // optimized evaluation of expression templates. Calling this function explicitly might result
8869 // in erroneous results and/or in compilation errors. Instead of using this function use the
8870 // assignment operator.
8871 */
8872 template< typename MT       // Type of the dense matrix
8873         , size_t... CSAs >  // Compile time submatrix arguments
8874 template< typename MT2 >    // Type of the right-hand side dense matrix
8875 inline auto Submatrix<MT,aligned,false,true,CSAs...>::addAssign( const DenseMatrix<MT2,false>& rhs )
8876    -> DisableIf_t< VectorizedAddAssign_v<MT2> >
8877 {
8878    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
8879    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
8880 
8881    const size_t jpos( prevMultiple( columns(), 2UL ) );
8882    BLAZE_INTERNAL_ASSERT( jpos <= columns(), "Invalid end calculation" );
8883 
8884    for( size_t i=0UL; i<rows(); ++i )
8885    {
8886       if( IsDiagonal_v<MT2> ) {
8887          matrix_(row()+i,column()+i) += (*rhs)(i,i);
8888       }
8889       else {
8890          for( size_t j=0UL; j<jpos; j+=2UL ) {
8891             matrix_(row()+i,column()+j    ) += (*rhs)(i,j    );
8892             matrix_(row()+i,column()+j+1UL) += (*rhs)(i,j+1UL);
8893          }
8894          if( jpos < columns() ) {
8895             matrix_(row()+i,column()+jpos) += (*rhs)(i,jpos);
8896          }
8897       }
8898    }
8899 }
8900 /*! \endcond */
8901 //*************************************************************************************************
8902 
8903 
8904 //*************************************************************************************************
8905 /*! \cond BLAZE_INTERNAL */
8906 /*!\brief SIMD optimized implementation of the addition assignment of a row-major dense matrix.
8907 //
8908 // \param rhs The right-hand side dense matrix to be added.
8909 // \return void
8910 //
8911 // This function must \b NOT be called explicitly! It is used internally for the performance
8912 // optimized evaluation of expression templates. Calling this function explicitly might result
8913 // in erroneous results and/or in compilation errors. Instead of using this function use the
8914 // assignment operator.
8915 */
8916 template< typename MT       // Type of the dense matrix
8917         , size_t... CSAs >  // Compile time submatrix arguments
8918 template< typename MT2 >    // Type of the right-hand side dense matrix
8919 inline auto Submatrix<MT,aligned,false,true,CSAs...>::addAssign( const DenseMatrix<MT2,false>& rhs )
8920    -> EnableIf_t< VectorizedAddAssign_v<MT2> >
8921 {
8922    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
8923 
8924    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
8925    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
8926 
8927    for( size_t i=0UL; i<rows(); ++i )
8928    {
8929       const size_t jbegin( ( IsUpper_v<MT2> )
8930                            ?( prevMultiple( ( IsStrictlyUpper_v<MT2> ? i+1UL : i ), SIMDSIZE ) )
8931                            :( 0UL ) );
8932       const size_t jend  ( ( IsLower_v<MT2> )
8933                            ?( IsStrictlyLower_v<MT2> ? i : i+1UL )
8934                            :( columns() ) );
8935       BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
8936 
8937       const size_t jpos( prevMultiple( jend, SIMDSIZE ) );
8938       BLAZE_INTERNAL_ASSERT( jpos <= jend, "Invalid end calculation" );
8939 
8940       size_t j( jbegin );
8941       Iterator left( begin(i) + jbegin );
8942       ConstIterator_t<MT2> right( (*rhs).begin(i) + jbegin );
8943 
8944       for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
8945          left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8946          left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8947          left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8948          left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8949       }
8950       for( ; j<jpos; j+=SIMDSIZE ) {
8951          left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
8952       }
8953       for( ; j<jend; ++j ) {
8954          *left += *right; ++left; ++right;
8955       }
8956    }
8957 }
8958 /*! \endcond */
8959 //*************************************************************************************************
8960 
8961 
8962 //*************************************************************************************************
8963 /*! \cond BLAZE_INTERNAL */
8964 /*!\brief Default implementation of the addition assignment of a column-major dense matrix.
8965 //
8966 // \param rhs The right-hand side dense matrix to be added.
8967 // \return void
8968 //
8969 // This function must \b NOT be called explicitly! It is used internally for the performance
8970 // optimized evaluation of expression templates. Calling this function explicitly might result
8971 // in erroneous results and/or in compilation errors. Instead of using this function use the
8972 // assignment operator.
8973 */
8974 template< typename MT       // Type of the dense matrix
8975         , size_t... CSAs >  // Compile time submatrix arguments
8976 template< typename MT2 >    // Type of the right-hand side dense matrix
addAssign(const DenseMatrix<MT2,true> & rhs)8977 inline void Submatrix<MT,aligned,false,true,CSAs...>::addAssign( const DenseMatrix<MT2,true>& rhs )
8978 {
8979    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
8980 
8981    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
8982    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
8983 
8984    constexpr size_t block( BLOCK_SIZE );
8985 
8986    for( size_t ii=0UL; ii<rows(); ii+=block ) {
8987       const size_t iend( ( rows()<(ii+block) )?( rows() ):( ii+block ) );
8988       for( size_t jj=0UL; jj<columns(); jj+=block ) {
8989          const size_t jend( ( columns()<(jj+block) )?( columns() ):( jj+block ) );
8990          for( size_t i=ii; i<iend; ++i ) {
8991             for( size_t j=jj; j<jend; ++j ) {
8992                matrix_(row()+i,column()+j) += (*rhs)(i,j);
8993             }
8994          }
8995       }
8996    }
8997 }
8998 /*! \endcond */
8999 //*************************************************************************************************
9000 
9001 
9002 //*************************************************************************************************
9003 /*! \cond BLAZE_INTERNAL */
9004 /*!\brief Default implementation of the addition assignment of a row-major sparse matrix.
9005 //
9006 // \param rhs The right-hand side sparse matrix to be added.
9007 // \return void
9008 //
9009 // This function must \b NOT be called explicitly! It is used internally for the performance
9010 // optimized evaluation of expression templates. Calling this function explicitly might result
9011 // in erroneous results and/or in compilation errors. Instead of using this function use the
9012 // assignment operator.
9013 */
9014 template< typename MT       // Type of the dense matrix
9015         , size_t... CSAs >  // Compile time submatrix arguments
9016 template< typename MT2 >    // Type of the right-hand side sparse matrix
addAssign(const SparseMatrix<MT2,false> & rhs)9017 inline void Submatrix<MT,aligned,false,true,CSAs...>::addAssign( const SparseMatrix<MT2,false>& rhs )
9018 {
9019    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
9020    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
9021 
9022    for( size_t i=0UL; i<rows(); ++i )
9023       for( ConstIterator_t<MT2> element=(*rhs).begin(i); element!=(*rhs).end(i); ++element )
9024          matrix_(row()+i,column()+element->index()) += element->value();
9025 }
9026 /*! \endcond */
9027 //*************************************************************************************************
9028 
9029 
9030 //*************************************************************************************************
9031 /*! \cond BLAZE_INTERNAL */
9032 /*!\brief Default implementation of the addition assignment of a column-major sparse matrix.
9033 //
9034 // \param rhs The right-hand side sparse matrix to be added.
9035 // \return void
9036 //
9037 // This function must \b NOT be called explicitly! It is used internally for the performance
9038 // optimized evaluation of expression templates. Calling this function explicitly might result
9039 // in erroneous results and/or in compilation errors. Instead of using this function use the
9040 // assignment operator.
9041 */
9042 template< typename MT       // Type of the dense matrix
9043         , size_t... CSAs >  // Compile time submatrix arguments
9044 template< typename MT2 >    // Type of the right-hand side sparse matrix
addAssign(const SparseMatrix<MT2,true> & rhs)9045 inline void Submatrix<MT,aligned,false,true,CSAs...>::addAssign( const SparseMatrix<MT2,true>& rhs )
9046 {
9047    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
9048 
9049    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
9050    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
9051 
9052    for( size_t j=0UL; j<columns(); ++j )
9053       for( ConstIterator_t<MT2> element=(*rhs).begin(j); element!=(*rhs).end(j); ++element )
9054          matrix_(row()+element->index(),column()+j) += element->value();
9055 }
9056 /*! \endcond */
9057 //*************************************************************************************************
9058 
9059 
9060 //*************************************************************************************************
9061 /*! \cond BLAZE_INTERNAL */
9062 /*!\brief Default implementation of the subtraction assignment of a row-major dense matrix.
9063 //
9064 // \param rhs The right-hand side dense matrix to be subtracted.
9065 // \return void
9066 //
9067 // This function must \b NOT be called explicitly! It is used internally for the performance
9068 // optimized evaluation of expression templates. Calling this function explicitly might result
9069 // in erroneous results and/or in compilation errors. Instead of using this function use the
9070 // assignment operator.
9071 */
9072 template< typename MT       // Type of the dense matrix
9073         , size_t... CSAs >  // Compile time submatrix arguments
9074 template< typename MT2 >    // Type of the right-hand side dense matrix
9075 inline auto Submatrix<MT,aligned,false,true,CSAs...>::subAssign( const DenseMatrix<MT2,false>& rhs )
9076    -> DisableIf_t< VectorizedSubAssign_v<MT2> >
9077 {
9078    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
9079    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
9080 
9081    const size_t jpos( prevMultiple( columns(), 2UL ) );
9082    BLAZE_INTERNAL_ASSERT( jpos <= columns(), "Invalid end calculation" );
9083 
9084    for( size_t i=0UL; i<rows(); ++i )
9085    {
9086       if( IsDiagonal_v<MT2> ) {
9087          matrix_(row()+i,column()+i) -= (*rhs)(i,i);
9088       }
9089       else {
9090          for( size_t j=0UL; j<jpos; j+=2UL ) {
9091             matrix_(row()+i,column()+j    ) -= (*rhs)(i,j    );
9092             matrix_(row()+i,column()+j+1UL) -= (*rhs)(i,j+1UL);
9093          }
9094          if( jpos < columns() ) {
9095             matrix_(row()+i,column()+jpos) -= (*rhs)(i,jpos);
9096          }
9097       }
9098    }
9099 }
9100 /*! \endcond */
9101 //*************************************************************************************************
9102 
9103 
9104 //*************************************************************************************************
9105 /*! \cond BLAZE_INTERNAL */
9106 /*!\brief SIMD optimized implementation of the subtraction assignment of a row-major dense matrix.
9107 //
9108 // \param rhs The right-hand side dense matrix to be subtracted.
9109 // \return void
9110 //
9111 // This function must \b NOT be called explicitly! It is used internally for the performance
9112 // optimized evaluation of expression templates. Calling this function explicitly might result
9113 // in erroneous results and/or in compilation errors. Instead of using this function use the
9114 // assignment operator.
9115 */
9116 template< typename MT       // Type of the dense matrix
9117         , size_t... CSAs >  // Compile time submatrix arguments
9118 template< typename MT2 >    // Type of the right-hand side dense matrix
9119 inline auto Submatrix<MT,aligned,false,true,CSAs...>::subAssign( const DenseMatrix<MT2,false>& rhs )
9120    -> EnableIf_t< VectorizedSubAssign_v<MT2> >
9121 {
9122    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
9123 
9124    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
9125    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
9126 
9127    for( size_t i=0UL; i<rows(); ++i )
9128    {
9129       const size_t jbegin( ( IsUpper_v<MT2> )
9130                            ?( prevMultiple( ( IsStrictlyUpper_v<MT2> ? i+1UL : i ), SIMDSIZE ) )
9131                            :( 0UL ) );
9132       const size_t jend  ( ( IsLower_v<MT2> )
9133                            ?( IsStrictlyLower_v<MT2> ? i : i+1UL )
9134                            :( columns() ) );
9135       BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
9136 
9137       const size_t jpos( prevMultiple( jend, SIMDSIZE ) );
9138       BLAZE_INTERNAL_ASSERT( jpos <= jend, "Invalid end calculation" );
9139 
9140       size_t j( jbegin );
9141       Iterator left( begin(i) + jbegin );
9142       ConstIterator_t<MT2> right( (*rhs).begin(i) + jbegin );
9143 
9144       for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
9145          left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
9146          left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
9147          left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
9148          left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
9149       }
9150       for( ; j<jpos; j+=SIMDSIZE ) {
9151          left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
9152       }
9153       for( ; j<jend; ++j ) {
9154          *left -= *right; ++left; ++right;
9155       }
9156    }
9157 }
9158 /*! \endcond */
9159 //*************************************************************************************************
9160 
9161 
9162 //*************************************************************************************************
9163 /*! \cond BLAZE_INTERNAL */
9164 /*!\brief Default implementation of the subtraction assignment of a column-major dense matrix.
9165 //
9166 // \param rhs The right-hand side dense matrix to be subtracted.
9167 // \return void
9168 //
9169 // This function must \b NOT be called explicitly! It is used internally for the performance
9170 // optimized evaluation of expression templates. Calling this function explicitly might result
9171 // in erroneous results and/or in compilation errors. Instead of using this function use the
9172 // assignment operator.
9173 */
9174 template< typename MT       // Type of the dense matrix
9175         , size_t... CSAs >  // Compile time submatrix arguments
9176 template< typename MT2 >    // Type of the right-hand side dense matrix
subAssign(const DenseMatrix<MT2,true> & rhs)9177 inline void Submatrix<MT,aligned,false,true,CSAs...>::subAssign( const DenseMatrix<MT2,true>& rhs )
9178 {
9179    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
9180 
9181    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
9182    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
9183 
9184    constexpr size_t block( BLOCK_SIZE );
9185 
9186    for( size_t ii=0UL; ii<rows(); ii+=block ) {
9187       const size_t iend( ( rows()<(ii+block) )?( rows() ):( ii+block ) );
9188       for( size_t jj=0UL; jj<columns(); jj+=block ) {
9189          const size_t jend( ( columns()<(jj+block) )?( columns() ):( jj+block ) );
9190          for( size_t i=ii; i<iend; ++i ) {
9191             for( size_t j=jj; j<jend; ++j ) {
9192                matrix_(row()+i,column()+j) -= (*rhs)(i,j);
9193             }
9194          }
9195       }
9196    }
9197 }
9198 /*! \endcond */
9199 //*************************************************************************************************
9200 
9201 
9202 //*************************************************************************************************
9203 /*! \cond BLAZE_INTERNAL */
9204 /*!\brief Default implementation of the subtraction assignment of a row-major sparse matrix.
9205 //
9206 // \param rhs The right-hand side sparse matrix to be subtracted.
9207 // \return void
9208 //
9209 // This function must \b NOT be called explicitly! It is used internally for the performance
9210 // optimized evaluation of expression templates. Calling this function explicitly might result
9211 // in erroneous results and/or in compilation errors. Instead of using this function use the
9212 // assignment operator.
9213 */
9214 template< typename MT       // Type of the dense matrix
9215         , size_t... CSAs >  // Compile time submatrix arguments
9216 template< typename MT2 >    // Type of the right-hand side sparse matrix
subAssign(const SparseMatrix<MT2,false> & rhs)9217 inline void Submatrix<MT,aligned,false,true,CSAs...>::subAssign( const SparseMatrix<MT2,false>& rhs )
9218 {
9219    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
9220    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
9221 
9222    for( size_t i=0UL; i<rows(); ++i )
9223       for( ConstIterator_t<MT2> element=(*rhs).begin(i); element!=(*rhs).end(i); ++element )
9224          matrix_(row()+i,column()+element->index()) -= element->value();
9225 }
9226 /*! \endcond */
9227 //*************************************************************************************************
9228 
9229 
9230 //*************************************************************************************************
9231 /*! \cond BLAZE_INTERNAL */
9232 /*!\brief Default implementation of the subtraction assignment of a column-major sparse matrix.
9233 //
9234 // \param rhs The right-hand side sparse matrix to be subtracted.
9235 // \return void
9236 //
9237 // This function must \b NOT be called explicitly! It is used internally for the performance
9238 // optimized evaluation of expression templates. Calling this function explicitly might result
9239 // in erroneous results and/or in compilation errors. Instead of using this function use the
9240 // assignment operator.
9241 */
9242 template< typename MT       // Type of the dense matrix
9243         , size_t... CSAs >  // Compile time submatrix arguments
9244 template< typename MT2 >    // Type of the right-hand side sparse matrix
subAssign(const SparseMatrix<MT2,true> & rhs)9245 inline void Submatrix<MT,aligned,false,true,CSAs...>::subAssign( const SparseMatrix<MT2,true>& rhs )
9246 {
9247    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
9248 
9249    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
9250    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
9251 
9252    for( size_t j=0UL; j<columns(); ++j )
9253       for( ConstIterator_t<MT2> element=(*rhs).begin(j); element!=(*rhs).end(j); ++element )
9254          matrix_(row()+element->index(),column()+j) -= element->value();
9255 }
9256 /*! \endcond */
9257 //*************************************************************************************************
9258 
9259 
9260 //*************************************************************************************************
9261 /*! \cond BLAZE_INTERNAL */
9262 /*!\brief Default implementation of the Schur product assignment of a row-major dense matrix.
9263 //
9264 // \param rhs The right-hand side dense matrix for the Schur product.
9265 // \return void
9266 //
9267 // This function must \b NOT be called explicitly! It is used internally for the performance
9268 // optimized evaluation of expression templates. Calling this function explicitly might result
9269 // in erroneous results and/or in compilation errors. Instead of using this function use the
9270 // assignment operator.
9271 */
9272 template< typename MT       // Type of the dense matrix
9273         , size_t... CSAs >  // Compile time submatrix arguments
9274 template< typename MT2 >    // Type of the right-hand side dense matrix
9275 inline auto Submatrix<MT,aligned,false,true,CSAs...>::schurAssign( const DenseMatrix<MT2,false>& rhs )
9276    -> DisableIf_t< VectorizedSchurAssign_v<MT2> >
9277 {
9278    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
9279    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
9280 
9281    const size_t jpos( prevMultiple( columns(), 2UL ) );
9282    BLAZE_INTERNAL_ASSERT( jpos <= columns(), "Invalid end calculation" );
9283 
9284    for( size_t i=0UL; i<rows(); ++i ) {
9285       for( size_t j=0UL; j<jpos; j+=2UL ) {
9286          matrix_(row()+i,column()+j    ) *= (*rhs)(i,j    );
9287          matrix_(row()+i,column()+j+1UL) *= (*rhs)(i,j+1UL);
9288       }
9289       if( jpos < columns() ) {
9290          matrix_(row()+i,column()+jpos) *= (*rhs)(i,jpos);
9291       }
9292    }
9293 }
9294 /*! \endcond */
9295 //*************************************************************************************************
9296 
9297 
9298 //*************************************************************************************************
9299 /*! \cond BLAZE_INTERNAL */
9300 /*!\brief SIMD optimized implementation of the Schur product assignment of a row-major dense matrix.
9301 //
9302 // \param rhs The right-hand side dense matrix for the Schur product.
9303 // \return void
9304 //
9305 // This function must \b NOT be called explicitly! It is used internally for the performance
9306 // optimized evaluation of expression templates. Calling this function explicitly might result
9307 // in erroneous results and/or in compilation errors. Instead of using this function use the
9308 // assignment operator.
9309 */
9310 template< typename MT       // Type of the dense matrix
9311         , size_t... CSAs >  // Compile time submatrix arguments
9312 template< typename MT2 >    // Type of the right-hand side dense matrix
9313 inline auto Submatrix<MT,aligned,false,true,CSAs...>::schurAssign( const DenseMatrix<MT2,false>& rhs )
9314    -> EnableIf_t< VectorizedSchurAssign_v<MT2> >
9315 {
9316    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
9317 
9318    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
9319    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
9320 
9321    for( size_t i=0UL; i<rows(); ++i )
9322    {
9323       const size_t jpos( prevMultiple( columns(), SIMDSIZE ) );
9324       BLAZE_INTERNAL_ASSERT( jpos <= columns(), "Invalid end calculation" );
9325 
9326       size_t j( 0UL );
9327       Iterator left( begin(i) );
9328       ConstIterator_t<MT2> right( (*rhs).begin(i) );
9329 
9330       for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
9331          left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
9332          left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
9333          left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
9334          left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
9335       }
9336       for( ; j<jpos; j+=SIMDSIZE ) {
9337          left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
9338       }
9339       for( ; j<columns(); ++j ) {
9340          *left *= *right; ++left; ++right;
9341       }
9342    }
9343 }
9344 /*! \endcond */
9345 //*************************************************************************************************
9346 
9347 
9348 //*************************************************************************************************
9349 /*! \cond BLAZE_INTERNAL */
9350 /*!\brief Default implementation of the Schur product assignment of a column-major dense matrix.
9351 //
9352 // \param rhs The right-hand side dense matrix for the Schur product.
9353 // \return void
9354 //
9355 // This function must \b NOT be called explicitly! It is used internally for the performance
9356 // optimized evaluation of expression templates. Calling this function explicitly might result
9357 // in erroneous results and/or in compilation errors. Instead of using this function use the
9358 // assignment operator.
9359 */
9360 template< typename MT       // Type of the dense matrix
9361         , size_t... CSAs >  // Compile time submatrix arguments
9362 template< typename MT2 >    // Type of the right-hand side dense matrix
schurAssign(const DenseMatrix<MT2,true> & rhs)9363 inline void Submatrix<MT,aligned,false,true,CSAs...>::schurAssign( const DenseMatrix<MT2,true>& rhs )
9364 {
9365    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
9366 
9367    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
9368    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
9369 
9370    constexpr size_t block( BLOCK_SIZE );
9371 
9372    for( size_t ii=0UL; ii<rows(); ii+=block ) {
9373       const size_t iend( ( rows()<(ii+block) )?( rows() ):( ii+block ) );
9374       for( size_t jj=0UL; jj<columns(); jj+=block ) {
9375          const size_t jend( ( columns()<(jj+block) )?( columns() ):( jj+block ) );
9376          for( size_t i=ii; i<iend; ++i ) {
9377             for( size_t j=jj; j<jend; ++j ) {
9378                matrix_(row()+i,column()+j) *= (*rhs)(i,j);
9379             }
9380          }
9381       }
9382    }
9383 }
9384 /*! \endcond */
9385 //*************************************************************************************************
9386 
9387 
9388 //*************************************************************************************************
9389 /*! \cond BLAZE_INTERNAL */
9390 /*!\brief Default implementation of the Schur product assignment of a row-major sparse matrix.
9391 //
9392 // \param rhs The right-hand side sparse matrix for the Schur product.
9393 // \return void
9394 //
9395 // This function must \b NOT be called explicitly! It is used internally for the performance
9396 // optimized evaluation of expression templates. Calling this function explicitly might result
9397 // in erroneous results and/or in compilation errors. Instead of using this function use the
9398 // assignment operator.
9399 */
9400 template< typename MT       // Type of the dense matrix
9401         , size_t... CSAs >  // Compile time submatrix arguments
9402 template< typename MT2 >    // Type of the right-hand side sparse matrix
schurAssign(const SparseMatrix<MT2,false> & rhs)9403 inline void Submatrix<MT,aligned,false,true,CSAs...>::schurAssign( const SparseMatrix<MT2,false>& rhs )
9404 {
9405    using blaze::reset;
9406 
9407    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
9408    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
9409 
9410    for( size_t i=0UL; i<rows(); ++i )
9411    {
9412       size_t j( 0UL );
9413 
9414       for( ConstIterator_t<MT2> element=(*rhs).begin(i); element!=(*rhs).end(i); ++element ) {
9415          for( ; j<element->index(); ++j )
9416             reset( matrix_(row()+i,column()+j) );
9417          matrix_(row()+i,column()+j) *= element->value();
9418          ++j;
9419       }
9420 
9421       for( ; j<columns(); ++j ) {
9422          reset( matrix_(row()+i,column()+j) );
9423       }
9424    }
9425 }
9426 /*! \endcond */
9427 //*************************************************************************************************
9428 
9429 
9430 //*************************************************************************************************
9431 /*! \cond BLAZE_INTERNAL */
9432 /*!\brief Default implementation of the Schur product assignment of a column-major sparse matrix.
9433 //
9434 // \param rhs The right-hand side sparse matrix for the Schur product.
9435 // \return void
9436 //
9437 // This function must \b NOT be called explicitly! It is used internally for the performance
9438 // optimized evaluation of expression templates. Calling this function explicitly might result
9439 // in erroneous results and/or in compilation errors. Instead of using this function use the
9440 // assignment operator.
9441 */
9442 template< typename MT       // Type of the dense matrix
9443         , size_t... CSAs >  // Compile time submatrix arguments
9444 template< typename MT2 >    // Type of the right-hand side sparse matrix
schurAssign(const SparseMatrix<MT2,true> & rhs)9445 inline void Submatrix<MT,aligned,false,true,CSAs...>::schurAssign( const SparseMatrix<MT2,true>& rhs )
9446 {
9447    using blaze::reset;
9448 
9449    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
9450 
9451    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
9452    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
9453 
9454    for( size_t j=0UL; j<columns(); ++j )
9455    {
9456       size_t i( 0UL );
9457 
9458       for( ConstIterator_t<MT2> element=(*rhs).begin(j); element!=(*rhs).end(j); ++element ) {
9459          for( ; i<element->index(); ++i )
9460             reset( matrix_(row()+i,column()+j) );
9461          matrix_(row()+element->index(),column()+j) *= element->value();
9462          ++i;
9463       }
9464 
9465       for( ; i<rows(); ++i ) {
9466          reset( matrix_(row()+i,column()+j) );
9467       }
9468    }
9469 }
9470 /*! \endcond */
9471 //*************************************************************************************************
9472 
9473 
9474 
9475 
9476 
9477 
9478 
9479 
9480 //=================================================================================================
9481 //
9482 //  CLASS TEMPLATE SPECIALIZATION FOR ALIGNED COLUMN-MAJOR DENSE SUBMATRICES
9483 //
9484 //=================================================================================================
9485 
9486 //*************************************************************************************************
9487 /*! \cond BLAZE_INTERNAL */
9488 /*!\brief Specialization of Submatrix for aligned column-major dense submatrices.
9489 // \ingroup submatrix
9490 //
9491 // This Specialization of Submatrix adapts the class template to the requirements of aligned
9492 // column-major dense submatrices.
9493 */
9494 template< typename MT       // Type of the dense matrix
9495         , size_t... CSAs >  // Compile time submatrix arguments
9496 class Submatrix<MT,aligned,true,true,CSAs...>
9497    : public View< DenseMatrix< Submatrix<MT,aligned,true,true,CSAs...>, true > >
9498    , private SubmatrixData<CSAs...>
9499 {
9500  private:
9501    //**Type definitions****************************************************************************
9502    using DataType = SubmatrixData<CSAs...>;               //!< The type of the SubmatrixData base class.
9503    using Operand  = If_t< IsExpression_v<MT>, MT, MT& >;  //!< Composite data type of the matrix expression.
9504    //**********************************************************************************************
9505 
9506    //**********************************************************************************************
9507    //! Helper variable template for the explicit application of the SFINAE principle.
9508    template< typename MT1, typename MT2 >
9509    static constexpr bool EnforceEvaluation_v =
9510       ( IsRestricted_v<MT1> && RequiresEvaluation_v<MT2> );
9511    //**********************************************************************************************
9512 
9513  public:
9514    //**Type definitions****************************************************************************
9515    //! Type of this Submatrix instance.
9516    using This = Submatrix<MT,aligned,true,true,CSAs...>;
9517 
9518    //! Base type of this Submatrix instance.
9519    using BaseType = View< DenseMatrix<This,true> >;
9520 
9521    using ViewedType    = MT;                            //!< The type viewed by this Submatrix instance.
9522    using ResultType    = SubmatrixTrait_t<MT,CSAs...>;  //!< Result type for expression template evaluations.
9523    using OppositeType  = OppositeType_t<ResultType>;    //!< Result type with opposite storage order for expression template evaluations.
9524    using TransposeType = TransposeType_t<ResultType>;   //!< Transpose type for expression template evaluations.
9525    using ElementType   = ElementType_t<MT>;             //!< Type of the submatrix elements.
9526    using SIMDType      = SIMDTrait_t<ElementType>;      //!< SIMD type of the submatrix elements.
9527    using ReturnType    = ReturnType_t<MT>;              //!< Return type for expression template evaluations
9528    using CompositeType = const Submatrix&;              //!< Data type for composite expression templates.
9529 
9530    //! Reference to a constant submatrix value.
9531    using ConstReference = ConstReference_t<MT>;
9532 
9533    //! Reference to a non-constant submatrix value.
9534    using Reference = If_t< IsConst_v<MT>, ConstReference, Reference_t<MT> >;
9535 
9536    //! Pointer to a constant submatrix value.
9537    using ConstPointer = ConstPointer_t<MT>;
9538 
9539    //! Pointer to a non-constant submatrix value.
9540    using Pointer = If_t< IsConst_v<MT> || !HasMutableDataAccess_v<MT>, ConstPointer, Pointer_t<MT> >;
9541 
9542    //! Iterator over constant elements.
9543    using ConstIterator = ConstIterator_t<MT>;
9544 
9545    //! Iterator over non-constant elements.
9546    using Iterator = If_t< IsConst_v<MT>, ConstIterator, Iterator_t<MT> >;
9547    //**********************************************************************************************
9548 
9549    //**Compilation flags***************************************************************************
9550    //! Compilation switch for the expression template evaluation strategy.
9551    static constexpr bool simdEnabled = MT::simdEnabled;
9552 
9553    //! Compilation switch for the expression template assignment strategy.
9554    static constexpr bool smpAssignable = MT::smpAssignable;
9555 
9556    //! Compilation switch for the expression template evaluation strategy.
9557    static constexpr bool compileTimeArgs = DataType::compileTimeArgs;
9558    //**********************************************************************************************
9559 
9560    //**Constructors********************************************************************************
9561    /*!\name Constructors */
9562    //@{
9563    template< typename... RSAs >
9564    explicit inline Submatrix( MT& matrix, RSAs... args );
9565 
9566    Submatrix( const Submatrix& ) = default;
9567    //@}
9568    //**********************************************************************************************
9569 
9570    //**Destructor**********************************************************************************
9571    /*!\name Destructor */
9572    //@{
9573    ~Submatrix() = default;
9574    //@}
9575    //**********************************************************************************************
9576 
9577    //**Data access functions***********************************************************************
9578    /*!\name Data access functions */
9579    //@{
9580    inline Reference      operator()( size_t i, size_t j );
9581    inline ConstReference operator()( size_t i, size_t j ) const;
9582    inline Reference      at( size_t i, size_t j );
9583    inline ConstReference at( size_t i, size_t j ) const;
9584    inline Pointer        data  () noexcept;
9585    inline ConstPointer   data  () const noexcept;
9586    inline Pointer        data  ( size_t j ) noexcept;
9587    inline ConstPointer   data  ( size_t j ) const noexcept;
9588    inline Iterator       begin ( size_t j );
9589    inline ConstIterator  begin ( size_t j ) const;
9590    inline ConstIterator  cbegin( size_t j ) const;
9591    inline Iterator       end   ( size_t j );
9592    inline ConstIterator  end   ( size_t j ) const;
9593    inline ConstIterator  cend  ( size_t j ) const;
9594    //@}
9595    //**********************************************************************************************
9596 
9597    //**Assignment operators************************************************************************
9598    /*!\name Assignment operators */
9599    //@{
9600    inline Submatrix& operator=( const ElementType& rhs );
9601    inline Submatrix& operator=( initializer_list< initializer_list<ElementType> > list );
9602    inline Submatrix& operator=( const Submatrix& rhs );
9603 
9604    template< typename MT2, bool SO >
9605    inline Submatrix& operator=( const Matrix<MT2,SO>& rhs );
9606 
9607    template< typename MT2, bool SO >
9608    inline auto operator+=( const Matrix<MT2,SO>& rhs )
9609       -> DisableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >;
9610 
9611    template< typename MT2, bool SO >
9612    inline auto operator+=( const Matrix<MT2,SO>& rhs )
9613       -> EnableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >;
9614 
9615    template< typename MT2, bool SO >
9616    inline auto operator-=( const Matrix<MT2,SO>& rhs )
9617       -> DisableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >;
9618 
9619    template< typename MT2, bool SO >
9620    inline auto operator-=( const Matrix<MT2,SO>& rhs )
9621       -> EnableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >;
9622 
9623    template< typename MT2, bool SO >
9624    inline auto operator%=( const Matrix<MT2,SO>& rhs )
9625       -> DisableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >;
9626 
9627    template< typename MT2, bool SO >
9628    inline auto operator%=( const Matrix<MT2,SO>& rhs )
9629       -> EnableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >;
9630    //@}
9631    //**********************************************************************************************
9632 
9633    //**Utility functions***************************************************************************
9634    /*!\name Utility functions */
9635    //@{
9636    using DataType::row;
9637    using DataType::column;
9638    using DataType::rows;
9639    using DataType::columns;
9640 
9641    inline MT&       operand() noexcept;
9642    inline const MT& operand() const noexcept;
9643 
9644    inline size_t spacing() const noexcept;
9645    inline size_t capacity() const noexcept;
9646    inline size_t capacity( size_t i ) const noexcept;
9647    inline size_t nonZeros() const;
9648    inline size_t nonZeros( size_t i ) const;
9649    inline void   reset();
9650    inline void   reset( size_t i );
9651    //@}
9652    //**********************************************************************************************
9653 
9654    //**Numeric functions***************************************************************************
9655    /*!\name Numeric functions */
9656    //@{
9657    inline Submatrix& transpose();
9658    inline Submatrix& ctranspose();
9659 
9660    template< typename Other > inline Submatrix& scale( const Other& scalar );
9661    //@}
9662    //**********************************************************************************************
9663 
9664  private:
9665    //**********************************************************************************************
9666    //! Helper variable template for the explicit application of the SFINAE principle.
9667    template< typename MT2 >
9668    static constexpr bool VectorizedAssign_v =
9669       ( useOptimizedKernels &&
9670         simdEnabled && MT2::simdEnabled &&
9671         IsSIMDCombinable_v< ElementType, ElementType_t<MT2> > );
9672    //**********************************************************************************************
9673 
9674    //**********************************************************************************************
9675    //! Helper variable template for the explicit application of the SFINAE principle.
9676    template< typename MT2 >
9677    static constexpr bool VectorizedAddAssign_v =
9678       ( VectorizedAssign_v<MT2> &&
9679         HasSIMDAdd_v< ElementType, ElementType_t<MT2> > &&
9680         !IsDiagonal_v<MT2> );
9681    //**********************************************************************************************
9682 
9683    //**********************************************************************************************
9684    //! Helper variable template for the explicit application of the SFINAE principle.
9685    template< typename MT2 >
9686    static constexpr bool VectorizedSubAssign_v =
9687       ( VectorizedAssign_v<MT2> &&
9688         HasSIMDSub_v< ElementType, ElementType_t<MT2> > &&
9689         !IsDiagonal_v<MT2> );
9690    //**********************************************************************************************
9691 
9692    //**********************************************************************************************
9693    //! Helper variable template for the explicit application of the SFINAE principle.
9694    template< typename MT2 >
9695    static constexpr bool VectorizedSchurAssign_v =
9696       ( VectorizedAssign_v<MT2> &&
9697         HasSIMDMult_v< ElementType, ElementType_t<MT2> > );
9698    //**********************************************************************************************
9699 
9700    //**SIMD properties*****************************************************************************
9701    //! The number of elements packed within a single SIMD element.
9702    static constexpr size_t SIMDSIZE = SIMDTrait<ElementType>::size;
9703    //**********************************************************************************************
9704 
9705  public:
9706    //**Expression template evaluation functions****************************************************
9707    /*!\name Expression template evaluation functions */
9708    //@{
9709    template< typename Other >
9710    inline bool canAlias( const Other* alias ) const noexcept;
9711 
9712    template< typename MT2, AlignmentFlag AF2, bool SO2, size_t... CSAs2 >
9713    inline bool canAlias( const Submatrix<MT2,AF2,SO2,true,CSAs2...>* alias ) const noexcept;
9714 
9715    template< typename Other >
9716    inline bool isAliased( const Other* alias ) const noexcept;
9717 
9718    template< typename MT2, AlignmentFlag AF2, bool SO2, size_t... CSAs2 >
9719    inline bool isAliased( const Submatrix<MT2,AF2,SO2,true,CSAs2...>* alias ) const noexcept;
9720 
9721    inline bool isAligned   () const noexcept;
9722    inline bool canSMPAssign() const noexcept;
9723 
9724    BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
9725    BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
9726    BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
9727 
9728    BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
9729    BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
9730    BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
9731    BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
9732 
9733    template< typename MT2 >
9734    inline auto assign( const DenseMatrix<MT2,true>& rhs ) -> DisableIf_t< VectorizedAssign_v<MT2> >;
9735 
9736    template< typename MT2 >
9737    inline auto assign( const DenseMatrix<MT2,true>& rhs ) -> EnableIf_t< VectorizedAssign_v<MT2> >;
9738 
9739    template< typename MT2 > inline void assign( const DenseMatrix<MT2,false>&  rhs );
9740    template< typename MT2 > inline void assign( const SparseMatrix<MT2,true>&  rhs );
9741    template< typename MT2 > inline void assign( const SparseMatrix<MT2,false>& rhs );
9742 
9743    template< typename MT2 >
9744    inline auto addAssign( const DenseMatrix<MT2,true>& rhs ) -> DisableIf_t< VectorizedAddAssign_v<MT2> >;
9745 
9746    template< typename MT2 >
9747    inline auto addAssign( const DenseMatrix<MT2,true>& rhs ) -> EnableIf_t< VectorizedAddAssign_v<MT2> >;
9748 
9749    template< typename MT2 > inline void addAssign( const DenseMatrix<MT2,false>&  rhs );
9750    template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,true>&  rhs );
9751    template< typename MT2 > inline void addAssign( const SparseMatrix<MT2,false>& rhs );
9752 
9753    template< typename MT2 >
9754    inline auto subAssign( const DenseMatrix<MT2,true>& rhs ) -> DisableIf_t< VectorizedSubAssign_v<MT2> >;
9755 
9756    template< typename MT2 >
9757    inline auto subAssign( const DenseMatrix<MT2,true>& rhs ) -> EnableIf_t< VectorizedSubAssign_v<MT2> >;
9758 
9759    template< typename MT2 > inline void subAssign( const DenseMatrix<MT2,false>&  rhs );
9760    template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,true>&  rhs );
9761    template< typename MT2 > inline void subAssign( const SparseMatrix<MT2,false>& rhs );
9762 
9763    template< typename MT2 >
9764    inline auto schurAssign( const DenseMatrix<MT2,true>& rhs ) -> DisableIf_t< VectorizedSchurAssign_v<MT2> >;
9765 
9766    template< typename MT2 >
9767    inline auto schurAssign( const DenseMatrix<MT2,true>& rhs ) -> EnableIf_t< VectorizedSchurAssign_v<MT2> >;
9768 
9769    template< typename MT2 > inline void schurAssign( const DenseMatrix<MT2,false>&  rhs );
9770    template< typename MT2 > inline void schurAssign( const SparseMatrix<MT2,true>&  rhs );
9771    template< typename MT2 > inline void schurAssign( const SparseMatrix<MT2,false>& rhs );
9772    //@}
9773    //**********************************************************************************************
9774 
9775  private:
9776    //**Utility functions***************************************************************************
9777    /*!\name Utility functions */
9778    //@{
9779    inline bool hasOverlap() const noexcept;
9780    //@}
9781    //**********************************************************************************************
9782 
9783    //**Member variables****************************************************************************
9784    /*!\name Member variables */
9785    //@{
9786    Operand matrix_;  //!< The matrix containing the submatrix.
9787    //@}
9788    //**********************************************************************************************
9789 
9790    //**Friend declarations*************************************************************************
9791    template< typename MT2, AlignmentFlag AF2, bool SO2, bool DF2, size_t... CSAs2 > friend class Submatrix;
9792    //**********************************************************************************************
9793 
9794    //**Compile time checks*************************************************************************
9795    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE       ( MT );
9796    BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE    ( MT );
9797    BLAZE_CONSTRAINT_MUST_NOT_BE_TRANSEXPR_TYPE      ( MT );
9798    BLAZE_CONSTRAINT_MUST_NOT_BE_SUBMATRIX_TYPE      ( MT );
9799    BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT );
9800    BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE        ( MT );
9801    BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE      ( MT );
9802    //**********************************************************************************************
9803 };
9804 /*! \endcond */
9805 //*************************************************************************************************
9806 
9807 
9808 
9809 
9810 //=================================================================================================
9811 //
9812 //  CONSTRUCTORS
9813 //
9814 //=================================================================================================
9815 
9816 //*************************************************************************************************
9817 /*! \cond BLAZE_INTERNAL */
9818 /*!\brief Constructor for aligned column-major dense submatrices.
9819 //
9820 // \param matrix The dense matrix containing the submatrix.
9821 // \param args The runtime submatrix arguments.
9822 // \exception std::invalid_argument Invalid submatrix specification.
9823 //
9824 // By default, the provided submatrix arguments are checked at runtime. In case the submatrix is
9825 // not properly specified (i.e. if the specified submatrix is not contained in the given dense
9826 // matrix) a \a std::invalid_argument exception is thrown. The checks can be skipped by providing
9827 // the optional \a blaze::unchecked argument.
9828 */
9829 template< typename MT         // Type of the dense matrix
9830         , size_t... CSAs >    // Compile time submatrix arguments
9831 template< typename... RSAs >  // Runtime submatrix arguments
Submatrix(MT & matrix,RSAs...args)9832 inline Submatrix<MT,aligned,true,true,CSAs...>::Submatrix( MT& matrix, RSAs... args )
9833    : DataType( args... )  // Base class initialization
9834    , matrix_ ( matrix  )  // The matrix containing the submatrix
9835 {
9836    if( isChecked( args... ) )
9837    {
9838       if( ( row() + rows() > matrix_.rows() ) || ( column() + columns() > matrix_.columns() ) ) {
9839          BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix specification" );
9840       }
9841 
9842       if( simdEnabled && IsContiguous_v<MT> &&
9843           ( !checkAlignment( data() ) ||
9844             ( columns() > 1UL && matrix_.spacing() % SIMDSIZE != 0UL ) ) ) {
9845          BLAZE_THROW_INVALID_ARGUMENT( "Invalid submatrix alignment" );
9846       }
9847    }
9848    else
9849    {
9850       BLAZE_USER_ASSERT( row()    + rows()    <= matrix_.rows()   , "Invalid submatrix specification" );
9851       BLAZE_USER_ASSERT( column() + columns() <= matrix_.columns(), "Invalid submatrix specification" );
9852 
9853       BLAZE_USER_ASSERT( !simdEnabled || !IsContiguous_v<MT> || checkAlignment( data() ), "Invalid submatrix alignment" );
9854       BLAZE_USER_ASSERT( !simdEnabled || !IsContiguous_v<MT> || columns() <= 1UL || matrix_.spacing() % SIMDSIZE == 0UL, "Invalid submatrix alignment" );
9855    }
9856 }
9857 /*! \endcond */
9858 //*************************************************************************************************
9859 
9860 
9861 
9862 
9863 //=================================================================================================
9864 //
9865 //  DATA ACCESS FUNCTIONS
9866 //
9867 //=================================================================================================
9868 
9869 //*************************************************************************************************
9870 /*! \cond BLAZE_INTERNAL */
9871 /*!\brief 2D-access to the dense submatrix elements.
9872 //
9873 // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
9874 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
9875 // \return Reference to the accessed value.
9876 //
9877 // This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
9878 // the at() function is guaranteed to perform a check of the given access indices.
9879 */
9880 template< typename MT       // Type of the dense matrix
9881         , size_t... CSAs >  // Compile time submatrix arguments
9882 inline typename Submatrix<MT,aligned,true,true,CSAs...>::Reference
operator()9883    Submatrix<MT,aligned,true,true,CSAs...>::operator()( size_t i, size_t j )
9884 {
9885    BLAZE_USER_ASSERT( i < rows()   , "Invalid row access index"    );
9886    BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
9887 
9888    return matrix_(row()+i,column()+j);
9889 }
9890 /*! \endcond */
9891 //*************************************************************************************************
9892 
9893 
9894 //*************************************************************************************************
9895 /*! \cond BLAZE_INTERNAL */
9896 /*!\brief 2D-access to the dense submatrix elements.
9897 //
9898 // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
9899 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
9900 // \return Reference to the accessed value.
9901 //
9902 // This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
9903 // the at() function is guaranteed to perform a check of the given access indices.
9904 */
9905 template< typename MT       // Type of the dense matrix
9906         , size_t... CSAs >  // Compile time submatrix arguments
9907 inline typename Submatrix<MT,aligned,true,true,CSAs...>::ConstReference
operator()9908    Submatrix<MT,aligned,true,true,CSAs...>::operator()( size_t i, size_t j ) const
9909 {
9910    BLAZE_USER_ASSERT( i < rows()   , "Invalid row access index"    );
9911    BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
9912 
9913    return const_cast<const MT&>( matrix_ )(row()+i,column()+j);
9914 }
9915 /*! \endcond */
9916 //*************************************************************************************************
9917 
9918 
9919 //*************************************************************************************************
9920 /*! \cond BLAZE_INTERNAL */
9921 /*!\brief Checked access to the submatrix elements.
9922 //
9923 // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
9924 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
9925 // \return Reference to the accessed value.
9926 // \exception std::out_of_range Invalid matrix access index.
9927 //
9928 // In contrast to the function call operator this function always performs a check of the given
9929 // access indices.
9930 */
9931 template< typename MT       // Type of the dense matrix
9932         , size_t... CSAs >  // Compile time submatrix arguments
9933 inline typename Submatrix<MT,aligned,true,true,CSAs...>::Reference
at(size_t i,size_t j)9934    Submatrix<MT,aligned,true,true,CSAs...>::at( size_t i, size_t j )
9935 {
9936    if( i >= rows() ) {
9937       BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
9938    }
9939    if( j >= columns() ) {
9940       BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
9941    }
9942    return (*this)(i,j);
9943 }
9944 /*! \endcond */
9945 //*************************************************************************************************
9946 
9947 
9948 //*************************************************************************************************
9949 /*! \cond BLAZE_INTERNAL */
9950 /*!\brief Checked access to the submatrix elements.
9951 //
9952 // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
9953 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
9954 // \return Reference to the accessed value.
9955 // \exception std::out_of_range Invalid matrix access index.
9956 //
9957 // In contrast to the function call operator this function always performs a check of the given
9958 // access indices.
9959 */
9960 template< typename MT       // Type of the dense matrix
9961         , size_t... CSAs >  // Compile time submatrix arguments
9962 inline typename Submatrix<MT,aligned,true,true,CSAs...>::ConstReference
at(size_t i,size_t j)9963    Submatrix<MT,aligned,true,true,CSAs...>::at( size_t i, size_t j ) const
9964 {
9965    if( i >= rows() ) {
9966       BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
9967    }
9968    if( j >= columns() ) {
9969       BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
9970    }
9971    return (*this)(i,j);
9972 }
9973 /*! \endcond */
9974 //*************************************************************************************************
9975 
9976 
9977 //*************************************************************************************************
9978 /*! \cond BLAZE_INTERNAL */
9979 /*!\brief Low-level data access to the submatrix elements.
9980 //
9981 // \return Pointer to the internal element storage.
9982 //
9983 // This function returns a pointer to the internal storage of the dense submatrix. Note that
9984 // you can NOT assume that all matrix elements lie adjacent to each other! The dense submatrix
9985 // may use techniques such as padding to improve the alignment of the data.
9986 */
9987 template< typename MT       // Type of the dense matrix
9988         , size_t... CSAs >  // Compile time submatrix arguments
9989 inline typename Submatrix<MT,aligned,true,true,CSAs...>::Pointer
data()9990    Submatrix<MT,aligned,true,true,CSAs...>::data() noexcept
9991 {
9992    return matrix_.data() + row() + column()*spacing();
9993 }
9994 /*! \endcond */
9995 //*************************************************************************************************
9996 
9997 
9998 //*************************************************************************************************
9999 /*! \cond BLAZE_INTERNAL */
10000 /*!\brief Low-level data access to the submatrix elements.
10001 //
10002 // \return Pointer to the internal element storage.
10003 //
10004 // This function returns a pointer to the internal storage of the dense submatrix. Note that
10005 // you can NOT assume that all matrix elements lie adjacent to each other! The dense submatrix
10006 // may use techniques such as padding to improve the alignment of the data.
10007 */
10008 template< typename MT       // Type of the dense matrix
10009         , size_t... CSAs >  // Compile time submatrix arguments
10010 inline typename Submatrix<MT,aligned,true,true,CSAs...>::ConstPointer
data()10011    Submatrix<MT,aligned,true,true,CSAs...>::data() const noexcept
10012 {
10013    return matrix_.data() + row() + column()*spacing();
10014 }
10015 /*! \endcond */
10016 //*************************************************************************************************
10017 
10018 
10019 //*************************************************************************************************
10020 /*! \cond BLAZE_INTERNAL */
10021 /*!\brief Low-level data access to the submatrix elements of column \a j.
10022 //
10023 // \param j The column index.
10024 // \return Pointer to the internal element storage.
10025 //
10026 // This function returns a pointer to the internal storage for the elements in column \a j.
10027 */
10028 template< typename MT       // Type of the dense matrix
10029         , size_t... CSAs >  // Compile time submatrix arguments
10030 inline typename Submatrix<MT,aligned,true,true,CSAs...>::Pointer
data(size_t j)10031    Submatrix<MT,aligned,true,true,CSAs...>::data( size_t j ) noexcept
10032 {
10033    return matrix_.data() + row() + (column()+j)*spacing();
10034 }
10035 /*! \endcond */
10036 //*************************************************************************************************
10037 
10038 
10039 //*************************************************************************************************
10040 /*! \cond BLAZE_INTERNAL */
10041 /*!\brief Low-level data access to the submatrix elements of column \a j.
10042 //
10043 // \param j The column index.
10044 // \return Pointer to the internal element storage.
10045 //
10046 // This function returns a pointer to the internal storage for the elements in column \a j.
10047 */
10048 template< typename MT       // Type of the dense matrix
10049         , size_t... CSAs >  // Compile time submatrix arguments
10050 inline typename Submatrix<MT,aligned,true,true,CSAs...>::ConstPointer
data(size_t j)10051    Submatrix<MT,aligned,true,true,CSAs...>::data( size_t j ) const noexcept
10052 {
10053    return matrix_.data() + row() + (column()+j)*spacing();
10054 }
10055 /*! \endcond */
10056 //*************************************************************************************************
10057 
10058 
10059 //*************************************************************************************************
10060 /*! \cond BLAZE_INTERNAL */
10061 /*!\brief Returns an iterator to the first non-zero element of column \a j.
10062 //
10063 // \param j The column index.
10064 // \return Iterator to the first non-zero element of column \a j.
10065 */
10066 template< typename MT       // Type of the dense matrix
10067         , size_t... CSAs >  // Compile time submatrix arguments
10068 inline typename Submatrix<MT,aligned,true,true,CSAs...>::Iterator
begin(size_t j)10069    Submatrix<MT,aligned,true,true,CSAs...>::begin( size_t j )
10070 {
10071    BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
10072    return ( matrix_.begin( column() + j ) + row() );
10073 }
10074 /*! \endcond */
10075 //*************************************************************************************************
10076 
10077 
10078 //*************************************************************************************************
10079 /*! \cond BLAZE_INTERNAL */
10080 /*!\brief Returns an iterator to the first non-zero element of column \a j.
10081 //
10082 // \param j The column index.
10083 // \return Iterator to the first non-zero element of column \a j.
10084 */
10085 template< typename MT       // Type of the dense matrix
10086         , size_t... CSAs >  // Compile time submatrix arguments
10087 inline typename Submatrix<MT,aligned,true,true,CSAs...>::ConstIterator
begin(size_t j)10088    Submatrix<MT,aligned,true,true,CSAs...>::begin( size_t j ) const
10089 {
10090    BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
10091    return ( matrix_.cbegin( column() + j ) + row() );
10092 }
10093 /*! \endcond */
10094 //*************************************************************************************************
10095 
10096 
10097 //*************************************************************************************************
10098 /*! \cond BLAZE_INTERNAL */
10099 /*!\brief Returns an iterator to the first non-zero element of column \a j.
10100 //
10101 // \param j The column index.
10102 // \return Iterator to the first non-zero element of column \a j.
10103 */
10104 template< typename MT       // Type of the dense matrix
10105         , size_t... CSAs >  // Compile time submatrix arguments
10106 inline typename Submatrix<MT,aligned,true,true,CSAs...>::ConstIterator
cbegin(size_t j)10107    Submatrix<MT,aligned,true,true,CSAs...>::cbegin( size_t j ) const
10108 {
10109    BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
10110    return ( matrix_.cbegin( column() + j ) + row() );
10111 }
10112 /*! \endcond */
10113 //*************************************************************************************************
10114 
10115 
10116 //*************************************************************************************************
10117 /*! \cond BLAZE_INTERNAL */
10118 /*!\brief Returns an iterator just past the last non-zero element of column \a j.
10119 //
10120 // \param j The column index.
10121 // \return Iterator just past the last non-zero element of column \a j.
10122 */
10123 template< typename MT       // Type of the dense matrix
10124         , size_t... CSAs >  // Compile time submatrix arguments
10125 inline typename Submatrix<MT,aligned,true,true,CSAs...>::Iterator
end(size_t j)10126    Submatrix<MT,aligned,true,true,CSAs...>::end( size_t j )
10127 {
10128    BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
10129    return ( matrix_.begin( column() + j ) + row() + rows() );
10130 }
10131 /*! \endcond */
10132 //*************************************************************************************************
10133 
10134 
10135 //*************************************************************************************************
10136 /*! \cond BLAZE_INTERNAL */
10137 /*!\brief Returns an iterator just past the last non-zero element of column \a j.
10138 //
10139 // \param j The column index.
10140 // \return Iterator just past the last non-zero element of column \a j.
10141 */
10142 template< typename MT       // Type of the dense matrix
10143         , size_t... CSAs >  // Compile time submatrix arguments
10144 inline typename Submatrix<MT,aligned,true,true,CSAs...>::ConstIterator
end(size_t j)10145    Submatrix<MT,aligned,true,true,CSAs...>::end( size_t j ) const
10146 {
10147    BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
10148    return ( matrix_.cbegin( column() + j ) + row() + rows() );
10149 }
10150 /*! \endcond */
10151 //*************************************************************************************************
10152 
10153 
10154 //*************************************************************************************************
10155 /*! \cond BLAZE_INTERNAL */
10156 /*!\brief Returns an iterator just past the last non-zero element of column \a j.
10157 //
10158 // \param j The column index.
10159 // \return Iterator just past the last non-zero element of column \a j.
10160 */
10161 template< typename MT       // Type of the dense matrix
10162         , size_t... CSAs >  // Compile time submatrix arguments
10163 inline typename Submatrix<MT,aligned,true,true,CSAs...>::ConstIterator
cend(size_t j)10164    Submatrix<MT,aligned,true,true,CSAs...>::cend( size_t j ) const
10165 {
10166    BLAZE_USER_ASSERT( j < columns(), "Invalid dense submatrix column access index" );
10167    return ( matrix_.cbegin( column() + j ) + row() + rows() );
10168 }
10169 /*! \endcond */
10170 //*************************************************************************************************
10171 
10172 
10173 
10174 
10175 //=================================================================================================
10176 //
10177 //  ASSIGNMENT OPERATORS
10178 //
10179 //=================================================================================================
10180 
10181 //*************************************************************************************************
10182 /*! \cond BLAZE_INTERNAL */
10183 /*!\brief Homogenous assignment to all submatrix elements.
10184 //
10185 // \param rhs Scalar value to be assigned to all submatrix elements.
10186 // \return Reference to the assigned submatrix.
10187 //
10188 // This function homogeneously assigns the given value to all dense matrix elements. Note that in
10189 // case the underlying dense matrix is a lower/upper matrix only lower/upper and diagonal elements
10190 // of the underlying matrix are modified.
10191 */
10192 template< typename MT       // Type of the dense matrix
10193         , size_t... CSAs >  // Compile time submatrix arguments
10194 inline Submatrix<MT,aligned,true,true,CSAs...>&
10195    Submatrix<MT,aligned,true,true,CSAs...>::operator=( const ElementType& rhs )
10196 {
10197    const size_t jend( column() + columns() );
10198    decltype(auto) left( derestrict( matrix_ ) );
10199 
10200    for( size_t j=column(); j<jend; ++j )
10201    {
10202       const size_t ibegin( ( IsLower_v<MT> )
10203                            ?( ( IsUniLower_v<MT> || IsStrictlyLower_v<MT> )
10204                               ?( max( j+1UL, row() ) )
10205                               :( max( j, row() ) ) )
10206                            :( row() ) );
10207       const size_t iend  ( ( IsUpper_v<MT> )
10208                            ?( ( IsUniUpper_v<MT> || IsStrictlyUpper_v<MT> )
10209                               ?( min( j, row()+rows() ) )
10210                               :( min( j+1UL, row()+rows() ) ) )
10211                            :( row()+rows() ) );
10212 
10213       for( size_t i=ibegin; i<iend; ++i ) {
10214          if( !IsRestricted_v<MT> || IsTriangular_v<MT> || trySet( matrix_, i, j, rhs ) )
10215             left(i,j) = rhs;
10216       }
10217    }
10218 
10219    return *this;
10220 }
10221 /*! \endcond */
10222 //*************************************************************************************************
10223 
10224 
10225 //*************************************************************************************************
10226 /*! \cond BLAZE_INTERNAL */
10227 /*!\brief List assignment to all submatrix elements.
10228 //
10229 // \param list The initializer list.
10230 // \exception std::invalid_argument Invalid assignment to submatrix.
10231 // \exception std::invalid_argument Invalid assignment to restricted matrix.
10232 //
10233 // This assignment operator offers the option to directly assign to all elements of the submatrix
10234 // by means of an initializer list. The submatrix elements are assigned the values from the given
10235 // initializer list. Missing values are initialized as default. Note that in case the size of the
10236 // top-level initializer list does not match the number of rows of the submatrix or the size of
10237 // any nested list exceeds the number of columns, a \a std::invalid_argument exception is thrown.
10238 // Also, if the underlying matrix \a MT is restricted and the assignment would violate an
10239 // invariant of the matrix, a \a std::invalid_argument exception is thrown.
10240 */
10241 template< typename MT       // Type of the dense matrix
10242         , size_t... CSAs >  // Compile time submatrix arguments
10243 inline Submatrix<MT,aligned,true,true,CSAs...>&
10244    Submatrix<MT,aligned,true,true,CSAs...>::operator=( initializer_list< initializer_list<ElementType> > list )
10245 {
10246    using blaze::reset;
10247 
10248    if( list.size() != rows() ) {
10249       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to submatrix" );
10250    }
10251 
10252    if( IsRestricted_v<MT> ) {
10253       const InitializerMatrix<ElementType> tmp( list, columns() );
10254       if( !tryAssign( matrix_, tmp, row(), column() ) ) {
10255          BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
10256       }
10257    }
10258 
10259    decltype(auto) left( derestrict( *this ) );
10260    size_t i( 0UL );
10261 
10262    for( const auto& rowList : list ) {
10263       size_t j( 0UL );
10264       for( const auto& element : rowList ) {
10265          left(i,j) = element;
10266          ++j;
10267       }
10268       for( ; j<columns(); ++j ) {
10269          reset( left(i,j) );
10270       }
10271       ++i;
10272    }
10273 
10274    return *this;
10275 }
10276 /*! \endcond */
10277 //*************************************************************************************************
10278 
10279 
10280 //*************************************************************************************************
10281 /*! \cond BLAZE_INTERNAL */
10282 /*!\brief Copy assignment operator for Submatrix.
10283 //
10284 // \param rhs Sparse submatrix to be copied.
10285 // \return Reference to the assigned submatrix.
10286 // \exception std::invalid_argument Submatrix sizes do not match.
10287 // \exception std::invalid_argument Invalid assignment to restricted matrix.
10288 //
10289 // The dense submatrix is initialized as a copy of the given dense submatrix. In case the current
10290 // sizes of the two submatrices don't match, a \a std::invalid_argument exception is thrown. Also,
10291 // if the underlying matrix \a MT is a lower triangular, upper triangular, or symmetric matrix
10292 // and the assignment would violate its lower, upper, or symmetry property, respectively, a
10293 // \a std::invalid_argument exception is thrown.
10294 */
10295 template< typename MT       // Type of the dense matrix
10296         , size_t... CSAs >  // Compile time submatrix arguments
10297 inline Submatrix<MT,aligned,true,true,CSAs...>&
10298    Submatrix<MT,aligned,true,true,CSAs...>::operator=( const Submatrix& rhs )
10299 {
10300    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
10301    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
10302 
10303    if( this == &rhs || ( &matrix_ == &rhs.matrix_ && row() == rhs.row() && column() == rhs.column() ) )
10304       return *this;
10305 
10306    if( rows() != rhs.rows() || columns() != rhs.columns() ) {
10307       BLAZE_THROW_INVALID_ARGUMENT( "Submatrix sizes do not match" );
10308    }
10309 
10310    if( !tryAssign( matrix_, rhs, row(), column() ) ) {
10311       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
10312    }
10313 
10314    decltype(auto) left( derestrict( *this ) );
10315 
10316    if( rhs.canAlias( this ) ) {
10317       const ResultType tmp( rhs );
10318       smpAssign( left, tmp );
10319    }
10320    else {
10321       smpAssign( left, rhs );
10322    }
10323 
10324    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
10325 
10326    return *this;
10327 }
10328 /*! \endcond */
10329 //*************************************************************************************************
10330 
10331 
10332 //*************************************************************************************************
10333 /*! \cond BLAZE_INTERNAL */
10334 /*!\brief Assignment operator for different matrices.
10335 //
10336 // \param rhs Matrix to be assigned.
10337 // \return Reference to the assigned submatrix.
10338 // \exception std::invalid_argument Matrix sizes do not match.
10339 // \exception std::invalid_argument Invalid assignment to restricted matrix.
10340 //
10341 // The dense submatrix is initialized as a copy of the given dense submatrix. In case the
10342 // current sizes of the two matrices don't match, a \a std::invalid_argument exception is
10343 // thrown. Also, if the underlying matrix \a MT is a symmetric matrix and the assignment
10344 // would violate its symmetry, a \a std::invalid_argument exception is thrown.
10345 */
10346 template< typename MT       // Type of the dense matrix
10347         , size_t... CSAs >  // Compile time submatrix arguments
10348 template< typename MT2      // Type of the right-hand side matrix
10349         , bool SO >         // Storage order of the right-hand side matrix
10350 inline Submatrix<MT,aligned,true,true,CSAs...>&
10351    Submatrix<MT,aligned,true,true,CSAs...>::operator=( const Matrix<MT2,SO>& rhs )
10352 {
10353    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
10354 
10355    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
10356       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
10357    }
10358 
10359    using Right = If_t< IsRestricted_v<MT>, CompositeType_t<MT2>, const MT2& >;
10360    Right right( *rhs );
10361 
10362    if( !tryAssign( matrix_, right, row(), column() ) ) {
10363       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
10364    }
10365 
10366    decltype(auto) left( derestrict( *this ) );
10367 
10368    if( IsReference_v<Right> && right.canAlias( this ) ) {
10369       const ResultType_t<MT2> tmp( right );
10370       if( IsSparseMatrix_v<MT2> )
10371          reset();
10372       smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
10373    }
10374    else {
10375       if( IsSparseMatrix_v<MT2> )
10376          reset();
10377       smpAssign( left, transIf< IsSymmetric_v<This> >( right ) );
10378    }
10379 
10380    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
10381 
10382    return *this;
10383 }
10384 /*! \endcond */
10385 //*************************************************************************************************
10386 
10387 
10388 //*************************************************************************************************
10389 /*! \cond BLAZE_INTERNAL */
10390 /*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
10391 //
10392 // \param rhs The right-hand side matrix to be added to the submatrix.
10393 // \return Reference to the dense submatrix.
10394 // \exception std::invalid_argument Matrix sizes do not match.
10395 // \exception std::invalid_argument Invalid assignment to restricted matrix.
10396 //
10397 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
10398 // is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
10399 // symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
10400 // respectively, a \a std::invalid_argument exception is thrown.
10401 */
10402 template< typename MT       // Type of the dense matrix
10403         , size_t... CSAs >  // Compile time submatrix arguments
10404 template< typename MT2      // Type of the right-hand side matrix
10405         , bool SO  >        // Storage order of the right-hand side matrix
10406 inline auto Submatrix<MT,aligned,true,true,CSAs...>::operator+=( const Matrix<MT2,SO>& rhs )
10407    -> DisableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >
10408 {
10409    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
10410    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
10411    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
10412 
10413    using AddType = AddTrait_t< ResultType, ResultType_t<MT2> >;
10414 
10415    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( AddType );
10416    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
10417 
10418    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
10419       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
10420    }
10421 
10422    if( !tryAddAssign( matrix_, *rhs, row(), column() ) ) {
10423       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
10424    }
10425 
10426    decltype(auto) left( derestrict( *this ) );
10427 
10428    if( ( ( IsSymmetric_v<MT> || IsHermitian_v<MT> ) && hasOverlap() ) || (*rhs).canAlias( this ) ) {
10429       const AddType tmp( *this + (*rhs) );
10430       smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
10431    }
10432    else {
10433       smpAddAssign( left, transIf< IsSymmetric_v<This> >( *rhs ) );
10434    }
10435 
10436    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
10437 
10438    return *this;
10439 }
10440 /*! \endcond */
10441 //*************************************************************************************************
10442 
10443 
10444 //*************************************************************************************************
10445 /*! \cond BLAZE_INTERNAL */
10446 /*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
10447 //
10448 // \param rhs The right-hand side matrix to be added to the submatrix.
10449 // \return Reference to the dense submatrix.
10450 // \exception std::invalid_argument Matrix sizes do not match.
10451 // \exception std::invalid_argument Invalid assignment to restricted matrix.
10452 //
10453 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
10454 // is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
10455 // symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
10456 // respectively, a \a std::invalid_argument exception is thrown.
10457 */
10458 template< typename MT       // Type of the dense matrix
10459         , size_t... CSAs >  // Compile time submatrix arguments
10460 template< typename MT2      // Type of the right-hand side matrix
10461         , bool SO  >        // Storage order of the right-hand side matrix
10462 inline auto Submatrix<MT,aligned,true,true,CSAs...>::operator+=( const Matrix<MT2,SO>& rhs )
10463    -> EnableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >
10464 {
10465    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
10466    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
10467    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
10468 
10469    using AddType = AddTrait_t< ResultType, ResultType_t<MT2> >;
10470 
10471    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( AddType );
10472    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( AddType );
10473 
10474    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
10475       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
10476    }
10477 
10478    const AddType tmp( *this + (*rhs) );
10479 
10480    if( !tryAssign( matrix_, tmp, row(), column() ) ) {
10481       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
10482    }
10483 
10484    decltype(auto) left( derestrict( *this ) );
10485 
10486    smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
10487 
10488    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
10489 
10490    return *this;
10491 }
10492 /*! \endcond */
10493 //*************************************************************************************************
10494 
10495 
10496 //*************************************************************************************************
10497 /*! \cond BLAZE_INTERNAL */
10498 /*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
10499 //
10500 // \param rhs The right-hand side matrix to be subtracted from the submatrix.
10501 // \return Reference to the dense submatrix.
10502 // \exception std::invalid_argument Matrix sizes do not match.
10503 // \exception std::invalid_argument Invalid assignment to restricted matrix.
10504 //
10505 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
10506 // is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
10507 // symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
10508 // respectively, a \a std::invalid_argument exception is thrown.
10509 */
10510 template< typename MT       // Type of the dense matrix
10511         , size_t... CSAs >  // Compile time submatrix arguments
10512 template< typename MT2      // Type of the right-hand side matrix
10513         , bool SO >         // Storage order of the right-hand side matrix
10514 inline auto Submatrix<MT,aligned,true,true,CSAs...>::operator-=( const Matrix<MT2,SO>& rhs )
10515    -> DisableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >
10516 {
10517    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
10518    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
10519    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
10520 
10521    using SubType = SubTrait_t< ResultType, ResultType_t<MT2> >;
10522 
10523    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( SubType );
10524    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
10525 
10526    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
10527       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
10528    }
10529 
10530    if( !trySubAssign( matrix_, *rhs, row(), column() ) ) {
10531       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
10532    }
10533 
10534    decltype(auto) left( derestrict( *this ) );
10535 
10536    if( ( ( IsSymmetric_v<MT> || IsHermitian_v<MT> ) && hasOverlap() ) || (*rhs).canAlias( this ) ) {
10537       const SubType tmp( *this - (*rhs ) );
10538       smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
10539    }
10540    else {
10541       smpSubAssign( left, transIf< IsSymmetric_v<This> >( *rhs ) );
10542    }
10543 
10544    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
10545 
10546    return *this;
10547 }
10548 /*! \endcond */
10549 //*************************************************************************************************
10550 
10551 
10552 //*************************************************************************************************
10553 /*! \cond BLAZE_INTERNAL */
10554 /*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
10555 //
10556 // \param rhs The right-hand side matrix to be subtracted from the submatrix.
10557 // \return Reference to the dense submatrix.
10558 // \exception std::invalid_argument Matrix sizes do not match.
10559 // \exception std::invalid_argument Invalid assignment to restricted matrix.
10560 //
10561 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
10562 // is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
10563 // symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
10564 // respectively, a \a std::invalid_argument exception is thrown.
10565 */
10566 template< typename MT       // Type of the dense matrix
10567         , size_t... CSAs >  // Compile time submatrix arguments
10568 template< typename MT2      // Type of the right-hand side matrix
10569         , bool SO >         // Storage order of the right-hand side matrix
10570 inline auto Submatrix<MT,aligned,true,true,CSAs...>::operator-=( const Matrix<MT2,SO>& rhs )
10571    -> EnableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >
10572 {
10573    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
10574    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
10575    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
10576 
10577    using SubType = SubTrait_t< ResultType, ResultType_t<MT2> >;
10578 
10579    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( SubType );
10580    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SubType );
10581 
10582    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
10583       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
10584    }
10585 
10586    const SubType tmp( *this - (*rhs) );
10587 
10588    if( !tryAssign( matrix_, tmp, row(), column() ) ) {
10589       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
10590    }
10591 
10592    decltype(auto) left( derestrict( *this ) );
10593 
10594    smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
10595 
10596    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
10597 
10598    return *this;
10599 }
10600 /*! \endcond */
10601 //*************************************************************************************************
10602 
10603 
10604 //*************************************************************************************************
10605 /*! \cond BLAZE_INTERNAL */
10606 /*!\brief Schur product assignment operator for the multiplication of a matrix (\f$ A=B \f$).
10607 //
10608 // \param rhs The right-hand side matrix for the Schur product.
10609 // \return Reference to the dense submatrix.
10610 // \exception std::invalid_argument Matrix sizes do not match.
10611 // \exception std::invalid_argument Invalid assignment to restricted matrix.
10612 //
10613 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
10614 // is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
10615 // symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
10616 // respectively, a \a std::invalid_argument exception is thrown.
10617 */
10618 template< typename MT       // Type of the dense matrix
10619         , size_t... CSAs >  // Compile time submatrix arguments
10620 template< typename MT2      // Type of the right-hand side matrix
10621         , bool SO  >        // Storage order of the right-hand side matrix
10622 inline auto Submatrix<MT,aligned,true,true,CSAs...>::operator%=( const Matrix<MT2,SO>& rhs )
10623    -> DisableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >
10624 {
10625    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
10626    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
10627    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
10628 
10629    using SchurType = SchurTrait_t< ResultType, ResultType_t<MT2> >;
10630 
10631    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SchurType );
10632 
10633    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
10634       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
10635    }
10636 
10637    if( !trySchurAssign( matrix_, *rhs, row(), column() ) ) {
10638       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
10639    }
10640 
10641    decltype(auto) left( derestrict( *this ) );
10642 
10643    if( ( ( IsSymmetric_v<MT> || IsHermitian_v<MT> ) && hasOverlap() ) || (*rhs).canAlias( this ) ) {
10644       const SchurType tmp( *this % (*rhs) );
10645       if( IsSparseMatrix_v<SchurType> )
10646          reset();
10647       smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
10648    }
10649    else {
10650       smpSchurAssign( left, transIf< IsSymmetric_v<This> >( *rhs ) );
10651    }
10652 
10653    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
10654 
10655    return *this;
10656 }
10657 /*! \endcond */
10658 //*************************************************************************************************
10659 
10660 
10661 //*************************************************************************************************
10662 /*! \cond BLAZE_INTERNAL */
10663 /*!\brief Schur product assignment operator for the multiplication of a matrix (\f$ A=B \f$).
10664 //
10665 // \param rhs The right-hand side matrix for the Schur product.
10666 // \return Reference to the dense submatrix.
10667 // \exception std::invalid_argument Matrix sizes do not match.
10668 // \exception std::invalid_argument Invalid assignment to restricted matrix.
10669 //
10670 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
10671 // is thrown. Also, if the underlying matrix \a MT is a lower triangular, upper triangular, or
10672 // symmetric matrix and the assignment would violate its lower, upper, or symmetry property,
10673 // respectively, a \a std::invalid_argument exception is thrown.
10674 */
10675 template< typename MT       // Type of the dense matrix
10676         , size_t... CSAs >  // Compile time submatrix arguments
10677 template< typename MT2      // Type of the right-hand side matrix
10678         , bool SO  >        // Storage order of the right-hand side matrix
10679 inline auto Submatrix<MT,aligned,true,true,CSAs...>::operator%=( const Matrix<MT2,SO>& rhs )
10680    -> EnableIf_t< EnforceEvaluation_v<MT,MT2>, Submatrix& >
10681 {
10682    BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE  ( ResultType );
10683    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType );
10684    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_t<MT2> );
10685 
10686    using SchurType = SchurTrait_t< ResultType, ResultType_t<MT2> >;
10687 
10688    BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( SchurType );
10689 
10690    if( rows() != (*rhs).rows() || columns() != (*rhs).columns() ) {
10691       BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
10692    }
10693 
10694    const SchurType tmp( *this % (*rhs) );
10695 
10696    if( !tryAssign( matrix_, tmp, row(), column() ) ) {
10697       BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" );
10698    }
10699 
10700    decltype(auto) left( derestrict( *this ) );
10701 
10702    if( IsSparseMatrix_v<SchurType> ) {
10703       reset();
10704    }
10705 
10706    smpAssign( left, transIf< IsSymmetric_v<This> >( tmp ) );
10707 
10708    BLAZE_INTERNAL_ASSERT( isIntact( matrix_ ), "Invariant violation detected" );
10709 
10710    return *this;
10711 }
10712 /*! \endcond */
10713 //*************************************************************************************************
10714 
10715 
10716 
10717 
10718 //=================================================================================================
10719 //
10720 //  UTILITY FUNCTIONS
10721 //
10722 //=================================================================================================
10723 
10724 //*************************************************************************************************
10725 /*! \cond BLAZE_INTERNAL */
10726 /*!\brief Returns the matrix containing the submatrix.
10727 //
10728 // \return The matrix containing the submatrix.
10729 */
10730 template< typename MT       // Type of the dense matrix
10731         , size_t... CSAs >  // Compile time submatrix arguments
operand()10732 inline MT& Submatrix<MT,aligned,true,true,CSAs...>::operand() noexcept
10733 {
10734    return matrix_;
10735 }
10736 /*! \endcond */
10737 //*************************************************************************************************
10738 
10739 
10740 //*************************************************************************************************
10741 /*! \cond BLAZE_INTERNAL */
10742 /*!\brief Returns the matrix containing the submatrix.
10743 //
10744 // \return The matrix containing the submatrix.
10745 */
10746 template< typename MT       // Type of the dense matrix
10747         , size_t... CSAs >  // Compile time submatrix arguments
operand()10748 inline const MT& Submatrix<MT,aligned,true,true,CSAs...>::operand() const noexcept
10749 {
10750    return matrix_;
10751 }
10752 /*! \endcond */
10753 //*************************************************************************************************
10754 
10755 
10756 //*************************************************************************************************
10757 /*! \cond BLAZE_INTERNAL */
10758 /*!\brief Returns the spacing between the beginning of two columns.
10759 //
10760 // \return The spacing between the beginning of two columns.
10761 //
10762 // This function returns the spacing between the beginning of two columns, i.e. the total
10763 // number of elements of a column.
10764 */
10765 template< typename MT       // Type of the dense matrix
10766         , size_t... CSAs >  // Compile time submatrix arguments
spacing()10767 inline size_t Submatrix<MT,aligned,true,true,CSAs...>::spacing() const noexcept
10768 {
10769    return matrix_.spacing();
10770 }
10771 /*! \endcond */
10772 //*************************************************************************************************
10773 
10774 
10775 //*************************************************************************************************
10776 /*! \cond BLAZE_INTERNAL */
10777 /*!\brief Returns the maximum capacity of the dense submatrix.
10778 //
10779 // \return The capacity of the dense submatrix.
10780 */
10781 template< typename MT       // Type of the dense matrix
10782         , size_t... CSAs >  // Compile time submatrix arguments
capacity()10783 inline size_t Submatrix<MT,aligned,true,true,CSAs...>::capacity() const noexcept
10784 {
10785    return rows() * columns();
10786 }
10787 /*! \endcond */
10788 //*************************************************************************************************
10789 
10790 
10791 //*************************************************************************************************
10792 /*! \cond BLAZE_INTERNAL */
10793 /*!\brief Returns the current capacity of the specified column.
10794 //
10795 // \param j The index of the column.
10796 // \return The current capacity of column \a j.
10797 */
10798 template< typename MT       // Type of the dense matrix
10799         , size_t... CSAs >  // Compile time submatrix arguments
capacity(size_t j)10800 inline size_t Submatrix<MT,aligned,true,true,CSAs...>::capacity( size_t j ) const noexcept
10801 {
10802    MAYBE_UNUSED( j );
10803 
10804    BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
10805 
10806    return rows();
10807 }
10808 /*! \endcond */
10809 //*************************************************************************************************
10810 
10811 
10812 //*************************************************************************************************
10813 /*! \cond BLAZE_INTERNAL */
10814 /*!\brief Returns the number of non-zero elements in the dense submatrix
10815 //
10816 // \return The number of non-zero elements in the dense submatrix.
10817 */
10818 template< typename MT       // Type of the dense matrix
10819         , size_t... CSAs >  // Compile time submatrix arguments
nonZeros()10820 inline size_t Submatrix<MT,aligned,true,true,CSAs...>::nonZeros() const
10821 {
10822    const size_t iend( row() + rows() );
10823    const size_t jend( column() + columns() );
10824    size_t nonzeros( 0UL );
10825 
10826    for( size_t j=column(); j<jend; ++j )
10827       for( size_t i=row(); i<iend; ++i )
10828          if( !isDefault( matrix_(i,j) ) )
10829             ++nonzeros;
10830 
10831    return nonzeros;
10832 }
10833 /*! \endcond */
10834 //*************************************************************************************************
10835 
10836 
10837 //*************************************************************************************************
10838 /*! \cond BLAZE_INTERNAL */
10839 /*!\brief Returns the number of non-zero elements in the specified column.
10840 //
10841 // \param j The index of the column.
10842 // \return The number of non-zero elements of column \a j.
10843 */
10844 template< typename MT       // Type of the dense matrix
10845         , size_t... CSAs >  // Compile time submatrix arguments
nonZeros(size_t j)10846 inline size_t Submatrix<MT,aligned,true,true,CSAs...>::nonZeros( size_t j ) const
10847 {
10848    BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
10849 
10850    const size_t iend( row() + rows() );
10851    size_t nonzeros( 0UL );
10852 
10853    for( size_t i=row(); i<iend; ++i )
10854       if( !isDefault( matrix_(i,column()+j) ) )
10855          ++nonzeros;
10856 
10857    return nonzeros;
10858 }
10859 /*! \endcond */
10860 //*************************************************************************************************
10861 
10862 
10863 //*************************************************************************************************
10864 /*! \cond BLAZE_INTERNAL */
10865 /*!\brief Reset to the default initial values.
10866 //
10867 // \return void
10868 */
10869 template< typename MT       // Type of the dense matrix
10870         , size_t... CSAs >  // Compile time submatrix arguments
reset()10871 inline void Submatrix<MT,aligned,true,true,CSAs...>::reset()
10872 {
10873    using blaze::clear;
10874 
10875    for( size_t j=column(); j<column()+columns(); ++j )
10876    {
10877       const size_t ibegin( ( IsLower_v<MT> )
10878                            ?( ( IsUniLower_v<MT> || IsStrictlyLower_v<MT> )
10879                               ?( max( j+1UL, row() ) )
10880                               :( max( j, row() ) ) )
10881                            :( row() ) );
10882       const size_t iend  ( ( IsUpper_v<MT> )
10883                            ?( ( IsUniUpper_v<MT> || IsStrictlyUpper_v<MT> )
10884                               ?( min( j, row()+rows() ) )
10885                               :( min( j+1UL, row()+rows() ) ) )
10886                            :( row()+rows() ) );
10887 
10888       for( size_t i=ibegin; i<iend; ++i )
10889          clear( matrix_(i,j) );
10890    }
10891 }
10892 /*! \endcond */
10893 //*************************************************************************************************
10894 
10895 
10896 //*************************************************************************************************
10897 /*! \cond BLAZE_INTERNAL */
10898 /*!\brief Reset the specified column to the default initial values.
10899 //
10900 // \param j The index of the column.
10901 // \return void
10902 */
10903 template< typename MT       // Type of the dense matrix
10904         , size_t... CSAs >  // Compile time submatrix arguments
reset(size_t j)10905 inline void Submatrix<MT,aligned,true,true,CSAs...>::reset( size_t j )
10906 {
10907    using blaze::clear;
10908 
10909    BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
10910 
10911    const size_t ibegin( ( IsLower_v<MT> )
10912                         ?( ( IsUniLower_v<MT> || IsStrictlyLower_v<MT> )
10913                            ?( max( j+1UL, row() ) )
10914                            :( max( j, row() ) ) )
10915                         :( row() ) );
10916    const size_t iend  ( ( IsUpper_v<MT> )
10917                         ?( ( IsUniUpper_v<MT> || IsStrictlyUpper_v<MT> )
10918                            ?( min( j, row()+rows() ) )
10919                            :( min( j+1UL, row()+rows() ) ) )
10920                         :( row()+rows() ) );
10921 
10922    for( size_t i=ibegin; i<iend; ++i )
10923       clear( matrix_(i,column()+j) );
10924 }
10925 /*! \endcond */
10926 //*************************************************************************************************
10927 
10928 
10929 //*************************************************************************************************
10930 /*! \cond BLAZE_INTERNAL */
10931 /*!\brief Checking whether there exists an overlap in the context of a symmetric matrix.
10932 //
10933 // \return \a true in case an overlap exists, \a false if not.
10934 //
10935 // This function checks if in the context of a symmetric matrix the submatrix has an overlap with
10936 // its counterpart. In case an overlap exists, the function return \a true, otherwise it returns
10937 // \a false.
10938 */
10939 template< typename MT       // Type of the dense matrix
10940         , size_t... CSAs >  // Compile time submatrix arguments
hasOverlap()10941 inline bool Submatrix<MT,aligned,true,true,CSAs...>::hasOverlap() const noexcept
10942 {
10943    BLAZE_INTERNAL_ASSERT( IsSymmetric_v<MT> || IsHermitian_v<MT>, "Invalid matrix detected" );
10944 
10945    if( ( row() + rows() <= column() ) || ( column() + columns() <= row() ) )
10946       return false;
10947    else return true;
10948 }
10949 /*! \endcond */
10950 //*************************************************************************************************
10951 
10952 
10953 
10954 
10955 //=================================================================================================
10956 //
10957 //  NUMERIC FUNCTIONS
10958 //
10959 //=================================================================================================
10960 
10961 //*************************************************************************************************
10962 /*! \cond BLAZE_INTERNAL */
10963 /*!\brief In-place transpose of the submatrix.
10964 //
10965 // \return Reference to the transposed submatrix.
10966 // \exception std::logic_error Invalid transpose of a non-quadratic submatrix.
10967 // \exception std::logic_error Invalid transpose operation.
10968 //
10969 // This function transposes the dense submatrix in-place. Note that this function can only be used
10970 // for quadratic submatrices, i.e. if the number of rows is equal to the number of columns. Also,
10971 // the function fails if ...
10972 //
10973 //  - ... the submatrix contains elements from the upper part of the underlying lower matrix;
10974 //  - ... the submatrix contains elements from the lower part of the underlying upper matrix;
10975 //  - ... the result would be non-deterministic in case of a symmetric or Hermitian matrix.
10976 //
10977 // In all cases, a \a std::logic_error is thrown.
10978 */
10979 template< typename MT       // Type of the dense matrix
10980         , size_t... CSAs >  // Compile time submatrix arguments
10981 inline Submatrix<MT,aligned,true,true,CSAs...>&
transpose()10982    Submatrix<MT,aligned,true,true,CSAs...>::transpose()
10983 {
10984    if( rows() != columns() ) {
10985       BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
10986    }
10987 
10988    if( !tryAssign( matrix_, trans( *this ), row(), column() ) ) {
10989       BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
10990    }
10991 
10992    decltype(auto) left( derestrict( *this ) );
10993    const ResultType tmp( trans( *this ) );
10994 
10995    smpAssign( left, tmp );
10996 
10997    return *this;
10998 }
10999 /*! \endcond */
11000 //*************************************************************************************************
11001 
11002 
11003 //*************************************************************************************************
11004 /*! \cond BLAZE_INTERNAL */
11005 /*!\brief In-place conjugate transpose of the submatrix.
11006 //
11007 // \return Reference to the transposed submatrix.
11008 // \exception std::logic_error Invalid transpose of a non-quadratic submatrix.
11009 // \exception std::logic_error Invalid transpose operation.
11010 //
11011 // This function transposes the dense submatrix in-place. Note that this function can only be used
11012 // for quadratic submatrices, i.e. if the number of rows is equal to the number of columns. Also,
11013 // the function fails if ...
11014 //
11015 //  - ... the submatrix contains elements from the upper part of the underlying lower matrix;
11016 //  - ... the submatrix contains elements from the lower part of the underlying upper matrix;
11017 //  - ... the result would be non-deterministic in case of a symmetric or Hermitian matrix.
11018 //
11019 // In all cases, a \a std::logic_error is thrown.
11020 */
11021 template< typename MT       // Type of the dense matrix
11022         , size_t... CSAs >  // Compile time submatrix arguments
11023 inline Submatrix<MT,aligned,true,true,CSAs...>&
ctranspose()11024    Submatrix<MT,aligned,true,true,CSAs...>::ctranspose()
11025 {
11026    if( rows() != columns() ) {
11027       BLAZE_THROW_LOGIC_ERROR( "Invalid transpose of a non-quadratic submatrix" );
11028    }
11029 
11030    if( !tryAssign( matrix_, ctrans( *this ), row(), column() ) ) {
11031       BLAZE_THROW_LOGIC_ERROR( "Invalid transpose operation" );
11032    }
11033 
11034    decltype(auto) left( derestrict( *this ) );
11035    const ResultType tmp( ctrans( *this ) );
11036 
11037    smpAssign( left, tmp );
11038 
11039    return *this;
11040 }
11041 /*! \endcond */
11042 //*************************************************************************************************
11043 
11044 
11045 //*************************************************************************************************
11046 /*! \cond BLAZE_INTERNAL */
11047 /*!\brief Scaling of the dense submatrix by the scalar value \a scalar (\f$ A=B*s \f$).
11048 //
11049 // \param scalar The scalar value for the submatrix scaling.
11050 // \return Reference to the dense submatrix.
11051 //
11052 // This function scales the submatrix by applying the given scalar value \a scalar to each
11053 // element of the submatrix. For built-in and \c complex data types it has the same effect
11054 // as using the multiplication assignment operator. Note that the function cannot be used
11055 // to scale a submatrix on a lower or upper unitriangular matrix. The attempt to scale
11056 // such a submatrix results in a compile time error!
11057 */
11058 template< typename MT       // Type of the dense matrix
11059         , size_t... CSAs >  // Compile time submatrix arguments
11060 template< typename Other >  // Data type of the scalar value
11061 inline Submatrix<MT,aligned,true,true,CSAs...>&
scale(const Other & scalar)11062    Submatrix<MT,aligned,true,true,CSAs...>::scale( const Other& scalar )
11063 {
11064    BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT );
11065 
11066    const size_t jend( column() + columns() );
11067 
11068    for( size_t j=column(); j<jend; ++j )
11069    {
11070       const size_t ibegin( ( IsLower_v<MT> )
11071                            ?( ( IsStrictlyLower_v<MT> )
11072                               ?( max( j+1UL, row() ) )
11073                               :( max( j, row() ) ) )
11074                            :( row() ) );
11075       const size_t iend  ( ( IsUpper_v<MT> )
11076                            ?( ( IsStrictlyUpper_v<MT> )
11077                               ?( min( j, row()+rows() ) )
11078                               :( min( j+1UL, row()+rows() ) ) )
11079                            :( row()+rows() ) );
11080 
11081       for( size_t i=ibegin; i<iend; ++i )
11082          matrix_(i,j) *= scalar;
11083    }
11084 
11085    return *this;
11086 }
11087 /*! \endcond */
11088 //*************************************************************************************************
11089 
11090 
11091 
11092 
11093 //=================================================================================================
11094 //
11095 //  EXPRESSION TEMPLATE EVALUATION FUNCTIONS
11096 //
11097 //=================================================================================================
11098 
11099 //*************************************************************************************************
11100 /*! \cond BLAZE_INTERNAL */
11101 /*!\brief Returns whether the submatrix can alias with the given address \a alias.
11102 //
11103 // \param alias The alias to be checked.
11104 // \return \a true in case the alias corresponds to this submatrix, \a false if not.
11105 //
11106 // This function returns whether the given address can alias with the submatrix. In contrast
11107 // to the isAliased() function this function is allowed to use compile time expressions to
11108 // optimize the evaluation.
11109 */
11110 template< typename MT       // Type of the dense matrix
11111         , size_t... CSAs >  // Compile time submatrix arguments
11112 template< typename Other >  // Data type of the foreign expression
canAlias(const Other * alias)11113 inline bool Submatrix<MT,aligned,true,true,CSAs...>::canAlias( const Other* alias ) const noexcept
11114 {
11115    return matrix_.isAliased( &unview( *alias ) );
11116 }
11117 /*! \endcond */
11118 //*************************************************************************************************
11119 
11120 
11121 //*************************************************************************************************
11122 /*! \cond BLAZE_INTERNAL */
11123 /*!\brief Returns whether the submatrix can alias with the given dense submatrix \a alias.
11124 //
11125 // \param alias The alias to be checked.
11126 // \return \a true in case the alias corresponds to this submatrix, \a false if not.
11127 //
11128 // This function returns whether the given address can alias with the submatrix. In contrast
11129 // to the isAliased() function this function is allowed to use compile time expressions to
11130 // optimize the evaluation.
11131 */
11132 template< typename MT        // Type of the dense matrix
11133         , size_t... CSAs >   // Compile time submatrix arguments
11134 template< typename MT2       // Data type of the foreign dense submatrix
11135         , AlignmentFlag AF2  // Alignment flag of the foreign dense submatrix
11136         , bool SO2           // Storage order of the foreign dense submatrix
11137         , size_t... CSAs2 >  // Compile time submatrix arguments of the foreign dense submatrix
11138 inline bool
canAlias(const Submatrix<MT2,AF2,SO2,true,CSAs2...> * alias)11139    Submatrix<MT,aligned,true,true,CSAs...>::canAlias( const Submatrix<MT2,AF2,SO2,true,CSAs2...>* alias ) const noexcept
11140 {
11141    return ( matrix_.isAliased( &alias->matrix_ ) &&
11142             ( row() + rows() > alias->row() ) &&
11143             ( row() < alias->row() + alias->rows() ) &&
11144             ( column() + columns() > alias->column() ) &&
11145             ( column() < alias->column() + alias->columns() ) );
11146 }
11147 /*! \endcond */
11148 //*************************************************************************************************
11149 
11150 
11151 //*************************************************************************************************
11152 /*! \cond BLAZE_INTERNAL */
11153 /*!\brief Returns whether the submatrix is aliased with the given address \a alias.
11154 //
11155 // \param alias The alias to be checked.
11156 // \return \a true in case the alias corresponds to this submatrix, \a false if not.
11157 //
11158 // This function returns whether the given address is aliased with the submatrix. In contrast
11159 // to the canAlias() function this function is not allowed to use compile time expressions to
11160 // optimize the evaluation.
11161 */
11162 template< typename MT       // Type of the dense matrix
11163         , size_t... CSAs >  // Compile time submatrix arguments
11164 template< typename Other >  // Data type of the foreign expression
isAliased(const Other * alias)11165 inline bool Submatrix<MT,aligned,true,true,CSAs...>::isAliased( const Other* alias ) const noexcept
11166 {
11167    return matrix_.isAliased( &unview( *alias ) );
11168 }
11169 /*! \endcond */
11170 //*************************************************************************************************
11171 
11172 
11173 //*************************************************************************************************
11174 /*! \cond BLAZE_INTERNAL */
11175 /*!\brief Returns whether the submatrix is aliased with the given dense submatrix \a alias.
11176 //
11177 // \param alias The alias to be checked.
11178 // \return \a true in case the alias corresponds to this submatrix, \a false if not.
11179 //
11180 // This function returns whether the given address is aliased with the submatrix. In contrast
11181 // to the canAlias() function this function is not allowed to use compile time expressions to
11182 // optimize the evaluation.
11183 */
11184 template< typename MT        // Type of the dense matrix
11185         , size_t... CSAs >   // Compile time submatrix arguments
11186 template< typename MT2       // Data type of the foreign dense submatrix
11187         , AlignmentFlag AF2  // Alignment flag of the foreign dense submatrix
11188         , bool SO2           // Storage order of the foreign dense submatrix
11189         , size_t... CSAs2 >  // Compile time submatrix arguments of the foreign dense submatrix
11190 inline bool
isAliased(const Submatrix<MT2,AF2,SO2,true,CSAs2...> * alias)11191    Submatrix<MT,aligned,true,true,CSAs...>::isAliased( const Submatrix<MT2,AF2,SO2,true,CSAs2...>* alias ) const noexcept
11192 {
11193    return ( matrix_.isAliased( &alias->matrix_ ) &&
11194             ( row() + rows() > alias->row() ) &&
11195             ( row() < alias->row() + alias->rows() ) &&
11196             ( column() + columns() > alias->column() ) &&
11197             ( column() < alias->column() + alias->columns() ) );
11198 }
11199 /*! \endcond */
11200 //*************************************************************************************************
11201 
11202 
11203 //*************************************************************************************************
11204 /*! \cond BLAZE_INTERNAL */
11205 /*!\brief Returns whether the submatrix is properly aligned in memory.
11206 //
11207 // \return \a true in case the submatrix is aligned, \a false if not.
11208 //
11209 // This function returns whether the submatrix is guaranteed to be properly aligned in memory,
11210 // i.e. whether the beginning and the end of each column of the submatrix are guaranteed to
11211 // conform to the alignment restrictions of the underlying element type.
11212 */
11213 template< typename MT       // Type of the dense matrix
11214         , size_t... CSAs >  // Compile time submatrix arguments
isAligned()11215 inline bool Submatrix<MT,aligned,true,true,CSAs...>::isAligned() const noexcept
11216 {
11217    return true;
11218 }
11219 /*! \endcond */
11220 //*************************************************************************************************
11221 
11222 
11223 //*************************************************************************************************
11224 /*! \cond BLAZE_INTERNAL */
11225 /*!\brief Returns whether the submatrix can be used in SMP assignments.
11226 //
11227 // \return \a true in case the submatrix can be used in SMP assignments, \a false if not.
11228 //
11229 // This function returns whether the submatrix can be used in SMP assignments. In contrast to the
11230 // \a smpAssignable member enumeration, which is based solely on compile time information, this
11231 // function additionally provides runtime information (as for instance the current number of
11232 // rows and/or columns of the submatrix).
11233 */
11234 template< typename MT       // Type of the dense matrix
11235         , size_t... CSAs >  // Compile time submatrix arguments
canSMPAssign()11236 inline bool Submatrix<MT,aligned,true,true,CSAs...>::canSMPAssign() const noexcept
11237 {
11238    return ( rows() * columns() >= SMP_DMATASSIGN_THRESHOLD );
11239 }
11240 /*! \endcond */
11241 //*************************************************************************************************
11242 
11243 
11244 //*************************************************************************************************
11245 /*! \cond BLAZE_INTERNAL */
11246 /*!\brief Load of a SIMD element of the submatrix.
11247 //
11248 // \param i Access index for the row. The index has to be in the range [0..M-1].
11249 // \param j Access index for the column. The index has to be in the range [0..N-1].
11250 // \return The loaded SIMD element.
11251 //
11252 // This function performs a load of a specific SIMD element of the dense submatrix. The row
11253 // index must be smaller than the number of rows and the column index must be smaller than
11254 // the number of columns. Additionally, the row index must be a multiple of the number of
11255 // values inside the SIMD element. This function must \b NOT be called explicitly! It is
11256 // used internally for the performance optimized evaluation of expression templates. Calling
11257 // this function explicitly might result in erroneous results and/or in compilation errors.
11258 */
11259 template< typename MT       // Type of the dense matrix
11260         , size_t... CSAs >  // Compile time submatrix arguments
11261 BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,true,true,CSAs...>::SIMDType
load(size_t i,size_t j)11262    Submatrix<MT,aligned,true,true,CSAs...>::load( size_t i, size_t j ) const noexcept
11263 {
11264    return loada( i, j );
11265 }
11266 /*! \endcond */
11267 //*************************************************************************************************
11268 
11269 
11270 //*************************************************************************************************
11271 /*! \cond BLAZE_INTERNAL */
11272 /*!\brief Aligned load of a SIMD element of the submatrix.
11273 //
11274 // \param i Access index for the row. The index has to be in the range [0..M-1].
11275 // \param j Access index for the column. The index has to be in the range [0..N-1].
11276 // \return The loaded SIMD element.
11277 //
11278 // This function performs an aligned load of a specific SIMD element of the dense submatrix.
11279 // The row index must be smaller than the number of rows and the column index must be smaller
11280 // than the number of columns. Additionally, the row index must be a multiple of the number
11281 // of values inside the SIMD element. This function must \b NOT be called explicitly! It is
11282 // used internally for the performance optimized evaluation of expression templates. Calling
11283 // this function explicitly might result in erroneous results and/or in compilation errors.
11284 */
11285 template< typename MT       // Type of the dense matrix
11286         , size_t... CSAs >  // Compile time submatrix arguments
11287 BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,true,true,CSAs...>::SIMDType
loada(size_t i,size_t j)11288    Submatrix<MT,aligned,true,true,CSAs...>::loada( size_t i, size_t j ) const noexcept
11289 {
11290    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
11291 
11292    BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
11293    BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
11294    BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
11295    BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
11296 
11297    return matrix_.loada( row()+i, column()+j );
11298 }
11299 /*! \endcond */
11300 //*************************************************************************************************
11301 
11302 
11303 //*************************************************************************************************
11304 /*! \cond BLAZE_INTERNAL */
11305 /*!\brief Unaligned load of a SIMD element of the submatrix.
11306 //
11307 // \param i Access index for the row. The index has to be in the range [0..M-1].
11308 // \param j Access index for the column. The index has to be in the range [0..N-1].
11309 // \return The loaded SIMD element.
11310 //
11311 // This function performs an unaligned load of a specific SIMD element of the dense submatrix.
11312 // The row index must be smaller than the number of rows and the column index must be smaller
11313 // than the number of columns. Additionally, the row index must be a multiple of the number of
11314 // values inside the SIMD element. This function must \b NOT be called explicitly! It is used
11315 // internally for the performance optimized evaluation of expression templates. Calling this
11316 // function explicitly might result in erroneous results and/or in compilation errors.
11317 */
11318 template< typename MT       // Type of the dense matrix
11319         , size_t... CSAs >  // Compile time submatrix arguments
11320 BLAZE_ALWAYS_INLINE typename Submatrix<MT,aligned,true,true,CSAs...>::SIMDType
loadu(size_t i,size_t j)11321    Submatrix<MT,aligned,true,true,CSAs...>::loadu( size_t i, size_t j ) const noexcept
11322 {
11323    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
11324 
11325    BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
11326    BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
11327    BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
11328 
11329    return matrix_.loadu( row()+i, column()+j );
11330 }
11331 /*! \endcond */
11332 //*************************************************************************************************
11333 
11334 
11335 //*************************************************************************************************
11336 /*! \cond BLAZE_INTERNAL */
11337 /*!\brief Store of a SIMD element of the submatrix.
11338 //
11339 // \param i Access index for the row. The index has to be in the range [0..M-1].
11340 // \param j Access index for the column. The index has to be in the range [0..N-1].
11341 // \param value The SIMD element to be stored.
11342 // \return void
11343 //
11344 // This function performs a store of a specific SIMD element of the dense submatrix. The row
11345 // index must be smaller than the number of rows and the column index must be smaller than
11346 // the number of columns. Additionally, the row index must be a multiple of the number of
11347 // values inside the SIMD element. This function must \b NOT be called explicitly! It is used
11348 // internally for the performance optimized evaluation of expression templates. Calling this
11349 // function explicitly might result in erroneous results and/or in compilation errors.
11350 */
11351 template< typename MT       // Type of the dense matrix
11352         , size_t... CSAs >  // Compile time submatrix arguments
11353 BLAZE_ALWAYS_INLINE void
store(size_t i,size_t j,const SIMDType & value)11354    Submatrix<MT,aligned,true,true,CSAs...>::store( size_t i, size_t j, const SIMDType& value ) noexcept
11355 {
11356    storea( i, j, value );
11357 }
11358 /*! \endcond */
11359 //*************************************************************************************************
11360 
11361 
11362 //*************************************************************************************************
11363 /*! \cond BLAZE_INTERNAL */
11364 /*!\brief Aligned store of a SIMD element of the submatrix.
11365 //
11366 // \param i Access index for the row. The index has to be in the range [0..M-1].
11367 // \param j Access index for the column. The index has to be in the range [0..N-1].
11368 // \param value The SIMD element to be stored.
11369 // \return void
11370 //
11371 // This function performs an aligned store of a specific SIMD element of the dense submatrix.
11372 // The row index must be smaller than the number of rows and the column index must be smaller
11373 // than the number of columns. Additionally, the row index must be a multiple of the number of
11374 // values inside the SIMD element. This function must \b NOT be called explicitly! It is used
11375 // internally for the performance optimized evaluation of expression templates. Calling this
11376 // function explicitly might result in erroneous results and/or in compilation errors.
11377 */
11378 template< typename MT       // Type of the dense matrix
11379         , size_t... CSAs >  // Compile time submatrix arguments
11380 BLAZE_ALWAYS_INLINE void
storea(size_t i,size_t j,const SIMDType & value)11381    Submatrix<MT,aligned,true,true,CSAs...>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
11382 {
11383    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
11384 
11385    BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
11386    BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
11387    BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
11388    BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
11389 
11390    matrix_.storea( row()+i, column()+j, value );
11391 }
11392 /*! \endcond */
11393 //*************************************************************************************************
11394 
11395 
11396 //*************************************************************************************************
11397 /*! \cond BLAZE_INTERNAL */
11398 /*!\brief Unaligned store of a SIMD element of the submatrix.
11399 //
11400 // \param i Access index for the row. The index has to be in the range [0..M-1].
11401 // \param j Access index for the column. The index has to be in the range [0..N-1].
11402 // \param value The SIMD element to be stored.
11403 // \return void
11404 //
11405 // This function performs an unaligned store of a specific SIMD element of the dense submatrix.
11406 // The row index must be smaller than the number of rows and the column index must be smaller
11407 // than the number of columns. Additionally, the row index must be a multiple of the number of
11408 // values inside the SIMD element. This function must \b NOT be called explicitly! It is used
11409 // internally for the performance optimized evaluation of expression templates. Calling this
11410 // function explicitly might result in erroneous results and/or in compilation errors.
11411 */
11412 template< typename MT       // Type of the dense matrix
11413         , size_t... CSAs >  // Compile time submatrix arguments
11414 BLAZE_ALWAYS_INLINE void
storeu(size_t i,size_t j,const SIMDType & value)11415    Submatrix<MT,aligned,true,true,CSAs...>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
11416 {
11417    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
11418 
11419    BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
11420    BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
11421    BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
11422 
11423    matrix_.storeu( row()+i, column()+j, value );
11424 }
11425 /*! \endcond */
11426 //*************************************************************************************************
11427 
11428 
11429 //*************************************************************************************************
11430 /*! \cond BLAZE_INTERNAL */
11431 /*!\brief Aligned, non-temporal store of a SIMD element of the submatrix.
11432 //
11433 // \param i Access index for the row. The index has to be in the range [0..M-1].
11434 // \param j Access index for the column. The index has to be in the range [0..N-1].
11435 // \param value The SIMD element to be stored.
11436 // \return void
11437 //
11438 // This function performs an aligned, non-temporal store of a specific SIMD element of the
11439 // dense submatrix. The row index must be smaller than the number of rows and the column
11440 // index must be smaller than the number of columns. Additionally, the row index must be
11441 // a multiple of the number of values inside the SIMD element. This function must \b NOT
11442 // be called explicitly! It is used internally for the performance optimized evaluation of
11443 // expression templates. Calling this function explicitly might result in erroneous results
11444 // and/or in compilation errors.
11445 */
11446 template< typename MT       // Type of the dense matrix
11447         , size_t... CSAs >  // Compile time submatrix arguments
11448 BLAZE_ALWAYS_INLINE void
stream(size_t i,size_t j,const SIMDType & value)11449    Submatrix<MT,aligned,true,true,CSAs...>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
11450 {
11451    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
11452 
11453    BLAZE_INTERNAL_ASSERT( i < rows(), "Invalid row access index" );
11454    BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= rows(), "Invalid row access index" );
11455    BLAZE_INTERNAL_ASSERT( i % SIMDSIZE == 0UL, "Invalid row access index" );
11456    BLAZE_INTERNAL_ASSERT( j < columns(), "Invalid column access index" );
11457 
11458    matrix_.stream( row()+i, column()+j, value );
11459 }
11460 /*! \endcond */
11461 //*************************************************************************************************
11462 
11463 
11464 //*************************************************************************************************
11465 /*! \cond BLAZE_INTERNAL */
11466 /*!\brief Default implementation of the assignment of a column-major dense matrix.
11467 //
11468 // \param rhs The right-hand side dense matrix to be assigned.
11469 // \return void
11470 //
11471 // This function must \b NOT be called explicitly! It is used internally for the performance
11472 // optimized evaluation of expression templates. Calling this function explicitly might result
11473 // in erroneous results and/or in compilation errors. Instead of using this function use the
11474 // assignment operator.
11475 */
11476 template< typename MT       // Type of the dense matrix
11477         , size_t... CSAs >  // Compile time submatrix arguments
11478 template< typename MT2 >   // Type of the right-hand side dense matrix
11479 inline auto Submatrix<MT,aligned,true,true,CSAs...>::assign( const DenseMatrix<MT2,true>& rhs )
11480    -> DisableIf_t< VectorizedAssign_v<MT2> >
11481 {
11482    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
11483    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
11484 
11485    const size_t ipos( prevMultiple( rows(), 2UL ) );
11486    BLAZE_INTERNAL_ASSERT( ipos <= rows(), "Invalid end calculation" );
11487 
11488    for( size_t j=0UL; j<columns(); ++j ) {
11489       for( size_t i=0UL; i<ipos; i+=2UL ) {
11490          matrix_(row()+i    ,column()+j) = (*rhs)(i    ,j);
11491          matrix_(row()+i+1UL,column()+j) = (*rhs)(i+1UL,j);
11492       }
11493       if( ipos < rows() ) {
11494          matrix_(row()+ipos,column()+j) = (*rhs)(ipos,j);
11495       }
11496    }
11497 }
11498 /*! \endcond */
11499 //*************************************************************************************************
11500 
11501 
11502 //*************************************************************************************************
11503 /*! \cond BLAZE_INTERNAL */
11504 /*!\brief SIMD optimized implementation of the assignment of a column-major dense matrix.
11505 //
11506 // \param rhs The right-hand side dense matrix to be assigned.
11507 // \return void
11508 //
11509 // This function must \b NOT be called explicitly! It is used internally for the performance
11510 // optimized evaluation of expression templates. Calling this function explicitly might result
11511 // in erroneous results and/or in compilation errors. Instead of using this function use the
11512 // assignment operator.
11513 */
11514 template< typename MT       // Type of the dense matrix
11515         , size_t... CSAs >  // Compile time submatrix arguments
11516 template< typename MT2 >    // Type of the right-hand side dense matrix
11517 inline auto Submatrix<MT,aligned,true,true,CSAs...>::assign( const DenseMatrix<MT2,true>& rhs )
11518    -> EnableIf_t< VectorizedAssign_v<MT2> >
11519 {
11520    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
11521 
11522    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
11523    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
11524 
11525    const size_t ipos( prevMultiple( rows(), SIMDSIZE ) );
11526    BLAZE_INTERNAL_ASSERT( ipos <= rows(), "Invalid end calculation" );
11527 
11528    if( useStreaming &&
11529        rows()*columns() > ( cacheSize / ( sizeof(ElementType) * 3UL ) ) &&
11530        !(*rhs).isAliased( this ) )
11531    {
11532       for( size_t j=0UL; j<columns(); ++j )
11533       {
11534          size_t i( 0UL );
11535          Iterator left( begin(j) );
11536          ConstIterator_t<MT2> right( (*rhs).begin(j) );
11537 
11538          for( ; i<ipos; i+=SIMDSIZE ) {
11539             left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11540          }
11541          for( ; i<rows(); ++i ) {
11542             *left = *right; ++left; ++right;
11543          }
11544       }
11545    }
11546    else
11547    {
11548       for( size_t j=0UL; j<columns(); ++j )
11549       {
11550          size_t i( 0UL );
11551          Iterator left( begin(j) );
11552          ConstIterator_t<MT2> right( (*rhs).begin(j) );
11553 
11554          for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
11555             left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11556             left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11557             left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11558             left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11559          }
11560          for( ; i<ipos; i+=SIMDSIZE ) {
11561             left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11562          }
11563          for( ; i<rows(); ++i ) {
11564             *left = *right; ++left; ++right;
11565          }
11566       }
11567    }
11568 }
11569 /*! \endcond */
11570 //*************************************************************************************************
11571 
11572 
11573 //*************************************************************************************************
11574 /*! \cond BLAZE_INTERNAL */
11575 /*!\brief Default implementation of the assignment of a row-major dense matrix.
11576 //
11577 // \param rhs The right-hand side dense matrix to be assigned.
11578 // \return void
11579 //
11580 // This function must \b NOT be called explicitly! It is used internally for the performance
11581 // optimized evaluation of expression templates. Calling this function explicitly might result
11582 // in erroneous results and/or in compilation errors. Instead of using this function use the
11583 // assignment operator.
11584 */
11585 template< typename MT       // Type of the dense matrix
11586         , size_t... CSAs >  // Compile time submatrix arguments
11587 template< typename MT2 >    // Type of the right-hand side dense matrix
assign(const DenseMatrix<MT2,false> & rhs)11588 inline void Submatrix<MT,aligned,true,true,CSAs...>::assign( const DenseMatrix<MT2,false>& rhs )
11589 {
11590    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
11591 
11592    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
11593    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
11594 
11595    constexpr size_t block( BLOCK_SIZE );
11596 
11597    for( size_t jj=0UL; jj<columns(); jj+=block ) {
11598       const size_t jend( ( columns()<(jj+block) )?( columns() ):( jj+block ) );
11599       for( size_t ii=0UL; ii<rows(); ii+=block ) {
11600          const size_t iend( ( rows()<(ii+block) )?( rows() ):( ii+block ) );
11601          for( size_t j=jj; j<jend; ++j ) {
11602             for( size_t i=ii; i<iend; ++i ) {
11603                matrix_(row()+i,column()+j) = (*rhs)(i,j);
11604             }
11605          }
11606       }
11607    }
11608 }
11609 /*! \endcond */
11610 //*************************************************************************************************
11611 
11612 
11613 //*************************************************************************************************
11614 /*! \cond BLAZE_INTERNAL */
11615 /*!\brief Default implementation of the assignment of a column-major sparse matrix.
11616 //
11617 // \param rhs The right-hand side sparse matrix to be assigned.
11618 // \return void
11619 //
11620 // This function must \b NOT be called explicitly! It is used internally for the performance
11621 // optimized evaluation of expression templates. Calling this function explicitly might result
11622 // in erroneous results and/or in compilation errors. Instead of using this function use the
11623 // assignment operator.
11624 */
11625 template< typename MT       // Type of the dense matrix
11626         , size_t... CSAs >  // Compile time submatrix arguments
11627 template< typename MT2 >    // Type of the right-hand side sparse matrix
assign(const SparseMatrix<MT2,true> & rhs)11628 inline void Submatrix<MT,aligned,true,true,CSAs...>::assign( const SparseMatrix<MT2,true>& rhs )
11629 {
11630    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
11631    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
11632 
11633    for( size_t j=0UL; j<columns(); ++j )
11634       for( ConstIterator_t<MT2> element=(*rhs).begin(j); element!=(*rhs).end(j); ++element )
11635          matrix_(row()+element->index(),column()+j) = element->value();
11636 }
11637 /*! \endcond */
11638 //*************************************************************************************************
11639 
11640 
11641 //*************************************************************************************************
11642 /*! \cond BLAZE_INTERNAL */
11643 /*!\brief Default implementation of the assignment of a row-major sparse matrix.
11644 //
11645 // \param rhs The right-hand side sparse matrix to be assigned.
11646 // \return void
11647 //
11648 // This function must \b NOT be called explicitly! It is used internally for the performance
11649 // optimized evaluation of expression templates. Calling this function explicitly might result
11650 // in erroneous results and/or in compilation errors. Instead of using this function use the
11651 // assignment operator.
11652 */
11653 template< typename MT       // Type of the dense matrix
11654         , size_t... CSAs >  // Compile time submatrix arguments
11655 template< typename MT2 >    // Type of the right-hand side sparse matrix
assign(const SparseMatrix<MT2,false> & rhs)11656 inline void Submatrix<MT,aligned,true,true,CSAs...>::assign( const SparseMatrix<MT2,false>& rhs )
11657 {
11658    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
11659 
11660    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
11661    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
11662 
11663    for( size_t i=0UL; i<rows(); ++i )
11664       for( ConstIterator_t<MT2> element=(*rhs).begin(i); element!=(*rhs).end(i); ++element )
11665          matrix_(row()+i,column()+element->index()) = element->value();
11666 }
11667 /*! \endcond */
11668 //*************************************************************************************************
11669 
11670 
11671 //*************************************************************************************************
11672 /*! \cond BLAZE_INTERNAL */
11673 /*!\brief Default implementation of the addition assignment of a column-major dense matrix.
11674 //
11675 // \param rhs The right-hand side dense matrix to be added.
11676 // \return void
11677 //
11678 // This function must \b NOT be called explicitly! It is used internally for the performance
11679 // optimized evaluation of expression templates. Calling this function explicitly might result
11680 // in erroneous results and/or in compilation errors. Instead of using this function use the
11681 // assignment operator.
11682 */
11683 template< typename MT       // Type of the dense matrix
11684         , size_t... CSAs >  // Compile time submatrix arguments
11685 template< typename MT2 >    // Type of the right-hand side dense matrix
11686 inline auto Submatrix<MT,aligned,true,true,CSAs...>::addAssign( const DenseMatrix<MT2,true>& rhs )
11687    -> DisableIf_t< VectorizedAddAssign_v<MT2> >
11688 {
11689    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
11690    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
11691 
11692    const size_t ipos( prevMultiple( rows(), 2UL ) );
11693    BLAZE_INTERNAL_ASSERT( ipos <= rows(), "Invalid end calculation" );
11694 
11695    for( size_t j=0UL; j<columns(); ++j )
11696    {
11697       if( IsDiagonal_v<MT2> ) {
11698          matrix_(row()+j,column()+j) += (*rhs)(j,j);
11699       }
11700       else {
11701          for( size_t i=0UL; i<ipos; i+=2UL ) {
11702             matrix_(row()+i    ,column()+j) += (*rhs)(i    ,j);
11703             matrix_(row()+i+1UL,column()+j) += (*rhs)(i+1UL,j);
11704          }
11705          if( ipos < rows() ) {
11706             matrix_(row()+ipos,column()+j) += (*rhs)(ipos,j);
11707          }
11708       }
11709    }
11710 }
11711 /*! \endcond */
11712 //*************************************************************************************************
11713 
11714 
11715 //*************************************************************************************************
11716 /*! \cond BLAZE_INTERNAL */
11717 /*!\brief SIMD optimized implementation of the addition assignment of a column-major dense matrix.
11718 //
11719 // \param rhs The right-hand side dense matrix to be added.
11720 // \return void
11721 //
11722 // This function must \b NOT be called explicitly! It is used internally for the performance
11723 // optimized evaluation of expression templates. Calling this function explicitly might result
11724 // in erroneous results and/or in compilation errors. Instead of using this function use the
11725 // assignment operator.
11726 */
11727 template< typename MT       // Type of the dense matrix
11728         , size_t... CSAs >  // Compile time submatrix arguments
11729 template< typename MT2 >    // Type of the right-hand side dense matrix
11730 inline auto Submatrix<MT,aligned,true,true,CSAs...>::addAssign( const DenseMatrix<MT2,true>& rhs )
11731    -> EnableIf_t< VectorizedAddAssign_v<MT2> >
11732 {
11733    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
11734 
11735    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
11736    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
11737 
11738    for( size_t j=0UL; j<columns(); ++j )
11739    {
11740       const size_t ibegin( ( IsLower_v<MT> )
11741                            ?( prevMultiple( ( IsStrictlyLower_v<MT> ? j+1UL : j ), SIMDSIZE ) )
11742                            :( 0UL ) );
11743       const size_t iend  ( ( IsUpper_v<MT> )
11744                            ?( IsStrictlyUpper_v<MT> ? j : j+1UL )
11745                            :( rows() ) );
11746       BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
11747 
11748       const size_t ipos( prevMultiple( iend, SIMDSIZE ) );
11749       BLAZE_INTERNAL_ASSERT( ipos <= iend, "Invalid end calculation" );
11750 
11751       size_t i( ibegin );
11752       Iterator left( begin(j) + ibegin );
11753       ConstIterator_t<MT2> right( (*rhs).begin(j) + ibegin );
11754 
11755       for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
11756          left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11757          left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11758          left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11759          left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11760       }
11761       for( ; i<ipos; i+=SIMDSIZE ) {
11762          left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11763       }
11764       for( ; i<iend; ++i ) {
11765          *left += *right; ++left; ++right;
11766       }
11767    }
11768 }
11769 /*! \endcond */
11770 //*************************************************************************************************
11771 
11772 
11773 //*************************************************************************************************
11774 /*! \cond BLAZE_INTERNAL */
11775 /*!\brief Default implementation of the addition assignment of a row-major dense matrix.
11776 //
11777 // \param rhs The right-hand side dense matrix to be added.
11778 // \return void
11779 //
11780 // This function must \b NOT be called explicitly! It is used internally for the performance
11781 // optimized evaluation of expression templates. Calling this function explicitly might result
11782 // in erroneous results and/or in compilation errors. Instead of using this function use the
11783 // assignment operator.
11784 */
11785 template< typename MT       // Type of the dense matrix
11786         , size_t... CSAs >  // Compile time submatrix arguments
11787 template< typename MT2 >    // Type of the right-hand side dense matrix
addAssign(const DenseMatrix<MT2,false> & rhs)11788 inline void Submatrix<MT,aligned,true,true,CSAs...>::addAssign( const DenseMatrix<MT2,false>& rhs )
11789 {
11790    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
11791 
11792    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
11793    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
11794 
11795    constexpr size_t block( BLOCK_SIZE );
11796 
11797    for( size_t jj=0UL; jj<columns(); jj+=block ) {
11798       const size_t jend( ( columns()<(jj+block) )?( columns() ):( jj+block ) );
11799       for( size_t ii=0UL; ii<rows(); ii+=block ) {
11800          const size_t iend( ( rows()<(ii+block) )?( rows() ):( ii+block ) );
11801          for( size_t j=jj; j<jend; ++j ) {
11802             for( size_t i=ii; i<iend; ++i ) {
11803                matrix_(row()+i,column()+j) += (*rhs)(i,j);
11804             }
11805          }
11806       }
11807    }
11808 }
11809 /*! \endcond */
11810 //*************************************************************************************************
11811 
11812 
11813 //*************************************************************************************************
11814 /*! \cond BLAZE_INTERNAL */
11815 /*!\brief Default implementation of the addition assignment of a column-major sparse matrix.
11816 //
11817 // \param rhs The right-hand side sparse matrix to be added.
11818 // \return void
11819 //
11820 // This function must \b NOT be called explicitly! It is used internally for the performance
11821 // optimized evaluation of expression templates. Calling this function explicitly might result
11822 // in erroneous results and/or in compilation errors. Instead of using this function use the
11823 // assignment operator.
11824 */
11825 template< typename MT       // Type of the dense matrix
11826         , size_t... CSAs >  // Compile time submatrix arguments
11827 template< typename MT2 >    // Type of the right-hand side sparse matrix
addAssign(const SparseMatrix<MT2,true> & rhs)11828 inline void Submatrix<MT,aligned,true,true,CSAs...>::addAssign( const SparseMatrix<MT2,true>& rhs )
11829 {
11830    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
11831    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
11832 
11833    for( size_t j=0UL; j<columns(); ++j )
11834       for( ConstIterator_t<MT2> element=(*rhs).begin(j); element!=(*rhs).end(j); ++element )
11835          matrix_(row()+element->index(),column()+j) += element->value();
11836 }
11837 /*! \endcond */
11838 //*************************************************************************************************
11839 
11840 
11841 //*************************************************************************************************
11842 /*! \cond BLAZE_INTERNAL */
11843 /*!\brief Default implementation of the addition assignment of a row-major sparse matrix.
11844 //
11845 // \param rhs The right-hand side sparse matrix to be added.
11846 // \return void
11847 //
11848 // This function must \b NOT be called explicitly! It is used internally for the performance
11849 // optimized evaluation of expression templates. Calling this function explicitly might result
11850 // in erroneous results and/or in compilation errors. Instead of using this function use the
11851 // assignment operator.
11852 */
11853 template< typename MT       // Type of the dense matrix
11854         , size_t... CSAs >  // Compile time submatrix arguments
11855 template< typename MT2 >    // Type of the right-hand side sparse matrix
addAssign(const SparseMatrix<MT2,false> & rhs)11856 inline void Submatrix<MT,aligned,true,true,CSAs...>::addAssign( const SparseMatrix<MT2,false>& rhs )
11857 {
11858    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
11859 
11860    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
11861    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
11862 
11863    for( size_t i=0UL; i<rows(); ++i )
11864       for( ConstIterator_t<MT2> element=(*rhs).begin(i); element!=(*rhs).end(i); ++element )
11865          matrix_(row()+i,column()+element->index()) += element->value();
11866 }
11867 /*! \endcond */
11868 //*************************************************************************************************
11869 
11870 
11871 //*************************************************************************************************
11872 /*! \cond BLAZE_INTERNAL */
11873 /*!\brief Default implementation of the subtraction assignment of a column-major dense matrix.
11874 //
11875 // \param rhs The right-hand side dense matrix to be subtracted.
11876 // \return void
11877 //
11878 // This function must \b NOT be called explicitly! It is used internally for the performance
11879 // optimized evaluation of expression templates. Calling this function explicitly might result
11880 // in erroneous results and/or in compilation errors. Instead of using this function use the
11881 // assignment operator.
11882 */
11883 template< typename MT       // Type of the dense matrix
11884         , size_t... CSAs >  // Compile time submatrix arguments
11885 template< typename MT2 >    // Type of the right-hand side dense matrix
11886 inline auto Submatrix<MT,aligned,true,true,CSAs...>::subAssign( const DenseMatrix<MT2,true>& rhs )
11887    -> DisableIf_t< VectorizedSubAssign_v<MT2> >
11888 {
11889    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
11890    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
11891 
11892    const size_t ipos( prevMultiple( rows(), 2UL ) );
11893    BLAZE_INTERNAL_ASSERT( ipos <= rows(), "Invalid end calculation" );
11894 
11895    for( size_t j=0UL; j<columns(); ++j )
11896    {
11897       if( IsDiagonal_v<MT2> ) {
11898          matrix_(row()+j,column()+j) -= (*rhs)(j,j);
11899       }
11900       else {
11901          for( size_t i=0UL; i<ipos; i+=2UL ) {
11902             matrix_(row()+i    ,column()+j) -= (*rhs)(i    ,j);
11903             matrix_(row()+i+1UL,column()+j) -= (*rhs)(i+1UL,j);
11904          }
11905          if( ipos < rows() ) {
11906             matrix_(row()+ipos,column()+j) -= (*rhs)(ipos,j);
11907          }
11908       }
11909    }
11910 }
11911 /*! \endcond */
11912 //*************************************************************************************************
11913 
11914 
11915 //*************************************************************************************************
11916 /*! \cond BLAZE_INTERNAL */
11917 /*!\brief SIMD optimized implementation of the subtraction assignment of a column-major dense matrix.
11918 //
11919 // \param rhs The right-hand side dense matrix to be subtracted.
11920 // \return void
11921 //
11922 // This function must \b NOT be called explicitly! It is used internally for the performance
11923 // optimized evaluation of expression templates. Calling this function explicitly might result
11924 // in erroneous results and/or in compilation errors. Instead of using this function use the
11925 // assignment operator.
11926 */
11927 template< typename MT       // Type of the dense matrix
11928         , size_t... CSAs >  // Compile time submatrix arguments
11929 template< typename MT2 >    // Type of the right-hand side dense matrix
11930 inline auto Submatrix<MT,aligned,true,true,CSAs...>::subAssign( const DenseMatrix<MT2,true>& rhs )
11931    -> EnableIf_t< VectorizedSubAssign_v<MT2> >
11932 {
11933    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
11934 
11935    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
11936    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
11937 
11938    for( size_t j=0UL; j<columns(); ++j )
11939    {
11940       const size_t ibegin( ( IsLower_v<MT> )
11941                            ?( prevMultiple( ( IsStrictlyLower_v<MT> ? j+1UL : j ), SIMDSIZE ) )
11942                            :( 0UL ) );
11943       const size_t iend  ( ( IsUpper_v<MT> )
11944                            ?( IsStrictlyUpper_v<MT> ? j : j+1UL )
11945                            :( rows() ) );
11946       BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
11947 
11948       const size_t ipos( prevMultiple( iend, SIMDSIZE ) );
11949       BLAZE_INTERNAL_ASSERT( ipos <= iend, "Invalid end calculation" );
11950 
11951       size_t i( ibegin );
11952       Iterator left( begin(j) + ibegin );
11953       ConstIterator_t<MT2> right( (*rhs).begin(j) + ibegin );
11954 
11955       for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
11956          left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11957          left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11958          left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11959          left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11960       }
11961       for( ; i<ipos; i+=SIMDSIZE ) {
11962          left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
11963       }
11964       for( ; i<iend; ++i ) {
11965          *left -= *right; ++left; ++right;
11966       }
11967    }
11968 }
11969 /*! \endcond */
11970 //*************************************************************************************************
11971 
11972 
11973 //*************************************************************************************************
11974 /*! \cond BLAZE_INTERNAL */
11975 /*!\brief Default implementation of the subtraction assignment of a row-major dense matrix.
11976 //
11977 // \param rhs The right-hand side dense matrix to be subtracted.
11978 // \return void
11979 //
11980 // This function must \b NOT be called explicitly! It is used internally for the performance
11981 // optimized evaluation of expression templates. Calling this function explicitly might result
11982 // in erroneous results and/or in compilation errors. Instead of using this function use the
11983 // assignment operator.
11984 */
11985 template< typename MT       // Type of the dense matrix
11986         , size_t... CSAs >  // Compile time submatrix arguments
11987 template< typename MT2 >    // Type of the right-hand side dense matrix
subAssign(const DenseMatrix<MT2,false> & rhs)11988 inline void Submatrix<MT,aligned,true,true,CSAs...>::subAssign( const DenseMatrix<MT2,false>& rhs )
11989 {
11990    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
11991 
11992    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
11993    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
11994 
11995    constexpr size_t block( BLOCK_SIZE );
11996 
11997    for( size_t jj=0UL; jj<columns(); jj+=block ) {
11998       const size_t jend( ( columns()<(jj+block) )?( columns() ):( jj+block ) );
11999       for( size_t ii=0UL; ii<rows(); ii+=block ) {
12000          const size_t iend( ( rows()<(ii+block) )?( rows() ):( ii+block ) );
12001          for( size_t j=jj; j<jend; ++j ) {
12002             for( size_t i=ii; i<iend; ++i ) {
12003                matrix_(row()+i,column()+j) -= (*rhs)(i,j);
12004             }
12005          }
12006       }
12007    }
12008 }
12009 /*! \endcond */
12010 //*************************************************************************************************
12011 
12012 
12013 //*************************************************************************************************
12014 /*! \cond BLAZE_INTERNAL */
12015 /*!\brief Default implementation of the subtraction assignment of a column-major sparse matrix.
12016 //
12017 // \param rhs The right-hand side sparse matrix to be subtracted.
12018 // \return void
12019 //
12020 // This function must \b NOT be called explicitly! It is used internally for the performance
12021 // optimized evaluation of expression templates. Calling this function explicitly might result
12022 // in erroneous results and/or in compilation errors. Instead of using this function use the
12023 // assignment operator.
12024 */
12025 template< typename MT       // Type of the dense matrix
12026         , size_t... CSAs >  // Compile time submatrix arguments
12027 template< typename MT2 >    // Type of the right-hand side sparse matrix
subAssign(const SparseMatrix<MT2,true> & rhs)12028 inline void Submatrix<MT,aligned,true,true,CSAs...>::subAssign( const SparseMatrix<MT2,true>& rhs )
12029 {
12030    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
12031    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
12032 
12033    for( size_t j=0UL; j<columns(); ++j )
12034       for( ConstIterator_t<MT2> element=(*rhs).begin(j); element!=(*rhs).end(j); ++element )
12035          matrix_(row()+element->index(),column()+j) -= element->value();
12036 }
12037 /*! \endcond */
12038 //*************************************************************************************************
12039 
12040 
12041 //*************************************************************************************************
12042 /*! \cond BLAZE_INTERNAL */
12043 /*!\brief Default implementation of the subtraction assignment of a row-major sparse matrix.
12044 //
12045 // \param rhs The right-hand side sparse matrix to be subtracted.
12046 // \return void
12047 //
12048 // This function must \b NOT be called explicitly! It is used internally for the performance
12049 // optimized evaluation of expression templates. Calling this function explicitly might result
12050 // in erroneous results and/or in compilation errors. Instead of using this function use the
12051 // assignment operator.
12052 */
12053 template< typename MT       // Type of the dense matrix
12054         , size_t... CSAs >  // Compile time submatrix arguments
12055 template< typename MT2 >    // Type of the right-hand side sparse matrix
subAssign(const SparseMatrix<MT2,false> & rhs)12056 inline void Submatrix<MT,aligned,true,true,CSAs...>::subAssign( const SparseMatrix<MT2,false>& rhs )
12057 {
12058    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
12059 
12060    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
12061    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
12062 
12063    for( size_t i=0UL; i<rows(); ++i )
12064       for( ConstIterator_t<MT2> element=(*rhs).begin(i); element!=(*rhs).end(i); ++element )
12065          matrix_(row()+i,column()+element->index()) -= element->value();
12066 }
12067 /*! \endcond */
12068 //*************************************************************************************************
12069 
12070 
12071 //*************************************************************************************************
12072 /*! \cond BLAZE_INTERNAL */
12073 /*!\brief Default implementation of the Schur product assignment of a column-major dense matrix.
12074 //
12075 // \param rhs The right-hand side dense matrix for the Schur product.
12076 // \return void
12077 //
12078 // This function must \b NOT be called explicitly! It is used internally for the performance
12079 // optimized evaluation of expression templates. Calling this function explicitly might result
12080 // in erroneous results and/or in compilation errors. Instead of using this function use the
12081 // assignment operator.
12082 */
12083 template< typename MT       // Type of the dense matrix
12084         , size_t... CSAs >  // Compile time submatrix arguments
12085 template< typename MT2 >    // Type of the right-hand side dense matrix
12086 inline auto Submatrix<MT,aligned,true,true,CSAs...>::schurAssign( const DenseMatrix<MT2,true>& rhs )
12087    -> DisableIf_t< VectorizedSchurAssign_v<MT2> >
12088 {
12089    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
12090    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
12091 
12092    const size_t ipos( prevMultiple( rows(), 2UL ) );
12093    BLAZE_INTERNAL_ASSERT( ipos <= rows(), "Invalid end calculation" );
12094 
12095    for( size_t j=0UL; j<columns(); ++j ) {
12096       for( size_t i=0UL; i<ipos; i+=2UL ) {
12097          matrix_(row()+i    ,column()+j) *= (*rhs)(i    ,j);
12098          matrix_(row()+i+1UL,column()+j) *= (*rhs)(i+1UL,j);
12099       }
12100       if( ipos < rows() ) {
12101          matrix_(row()+ipos,column()+j) *= (*rhs)(ipos,j);
12102       }
12103    }
12104 }
12105 /*! \endcond */
12106 //*************************************************************************************************
12107 
12108 
12109 //*************************************************************************************************
12110 /*! \cond BLAZE_INTERNAL */
12111 /*!\brief SIMD optimized implementation of the Schur product assignment of a column-major dense
12112 //        matrix.
12113 //
12114 // \param rhs The right-hand side dense matrix for the Schur product.
12115 // \return void
12116 //
12117 // This function must \b NOT be called explicitly! It is used internally for the performance
12118 // optimized evaluation of expression templates. Calling this function explicitly might result
12119 // in erroneous results and/or in compilation errors. Instead of using this function use the
12120 // assignment operator.
12121 */
12122 template< typename MT       // Type of the dense matrix
12123         , size_t... CSAs >  // Compile time submatrix arguments
12124 template< typename MT2 >    // Type of the right-hand side dense matrix
12125 inline auto Submatrix<MT,aligned,true,true,CSAs...>::schurAssign( const DenseMatrix<MT2,true>& rhs )
12126    -> EnableIf_t< VectorizedSchurAssign_v<MT2> >
12127 {
12128    BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType );
12129 
12130    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
12131    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
12132 
12133    for( size_t j=0UL; j<columns(); ++j )
12134    {
12135       const size_t ipos( prevMultiple( rows(), SIMDSIZE ) );
12136       BLAZE_INTERNAL_ASSERT( ipos <= rows(), "Invalid end calculation" );
12137 
12138       size_t i( 0UL );
12139       Iterator left( begin(j) );
12140       ConstIterator_t<MT2> right( (*rhs).begin(j) );
12141 
12142       for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
12143          left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
12144          left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
12145          left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
12146          left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
12147       }
12148       for( ; i<ipos; i+=SIMDSIZE ) {
12149          left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
12150       }
12151       for( ; i<rows(); ++i ) {
12152          *left *= *right; ++left; ++right;
12153       }
12154    }
12155 }
12156 /*! \endcond */
12157 //*************************************************************************************************
12158 
12159 
12160 //*************************************************************************************************
12161 /*! \cond BLAZE_INTERNAL */
12162 /*!\brief Default implementation of the Schur product assignment of a row-major dense matrix.
12163 //
12164 // \param rhs The right-hand side dense matrix for the Schur product.
12165 // \return void
12166 //
12167 // This function must \b NOT be called explicitly! It is used internally for the performance
12168 // optimized evaluation of expression templates. Calling this function explicitly might result
12169 // in erroneous results and/or in compilation errors. Instead of using this function use the
12170 // assignment operator.
12171 */
12172 template< typename MT       // Type of the dense matrix
12173         , size_t... CSAs >  // Compile time submatrix arguments
12174 template< typename MT2 >    // Type of the right-hand side dense matrix
schurAssign(const DenseMatrix<MT2,false> & rhs)12175 inline void Submatrix<MT,aligned,true,true,CSAs...>::schurAssign( const DenseMatrix<MT2,false>& rhs )
12176 {
12177    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
12178 
12179    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
12180    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
12181 
12182    constexpr size_t block( BLOCK_SIZE );
12183 
12184    for( size_t jj=0UL; jj<columns(); jj+=block ) {
12185       const size_t jend( ( columns()<(jj+block) )?( columns() ):( jj+block ) );
12186       for( size_t ii=0UL; ii<rows(); ii+=block ) {
12187          const size_t iend( ( rows()<(ii+block) )?( rows() ):( ii+block ) );
12188          for( size_t j=jj; j<jend; ++j ) {
12189             for( size_t i=ii; i<iend; ++i ) {
12190                matrix_(row()+i,column()+j) *= (*rhs)(i,j);
12191             }
12192          }
12193       }
12194    }
12195 }
12196 /*! \endcond */
12197 //*************************************************************************************************
12198 
12199 
12200 //*************************************************************************************************
12201 /*! \cond BLAZE_INTERNAL */
12202 /*!\brief Default implementation of the Schur product assignment of a column-major sparse matrix.
12203 //
12204 // \param rhs The right-hand side sparse matrix for the Schur product.
12205 // \return void
12206 //
12207 // This function must \b NOT be called explicitly! It is used internally for the performance
12208 // optimized evaluation of expression templates. Calling this function explicitly might result
12209 // in erroneous results and/or in compilation errors. Instead of using this function use the
12210 // assignment operator.
12211 */
12212 template< typename MT       // Type of the dense matrix
12213         , size_t... CSAs >  // Compile time submatrix arguments
12214 template< typename MT2 >    // Type of the right-hand side sparse matrix
schurAssign(const SparseMatrix<MT2,true> & rhs)12215 inline void Submatrix<MT,aligned,true,true,CSAs...>::schurAssign( const SparseMatrix<MT2,true>& rhs )
12216 {
12217    using blaze::reset;
12218 
12219    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
12220    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
12221 
12222    for( size_t j=0UL; j<columns(); ++j )
12223    {
12224       size_t i( 0UL );
12225 
12226       for( ConstIterator_t<MT2> element=(*rhs).begin(j); element!=(*rhs).end(j); ++element ) {
12227          for( ; i<element->index(); ++i )
12228             reset( matrix_(row()+i,column()+j) );
12229          matrix_(row()+i,column()+j) *= element->value();
12230          ++i;
12231       }
12232 
12233       for( ; i<rows(); ++i ) {
12234          reset( matrix_(row()+i,column()+j) );
12235       }
12236    }
12237 }
12238 /*! \endcond */
12239 //*************************************************************************************************
12240 
12241 
12242 //*************************************************************************************************
12243 /*! \cond BLAZE_INTERNAL */
12244 /*!\brief Default implementation of the Schur product assignment of a row-major sparse matrix.
12245 //
12246 // \param rhs The right-hand side sparse matrix for the Schur product.
12247 // \return void
12248 //
12249 // This function must \b NOT be called explicitly! It is used internally for the performance
12250 // optimized evaluation of expression templates. Calling this function explicitly might result
12251 // in erroneous results and/or in compilation errors. Instead of using this function use the
12252 // assignment operator.
12253 */
12254 template< typename MT       // Type of the dense matrix
12255         , size_t... CSAs >  // Compile time submatrix arguments
12256 template< typename MT2 >    // Type of the right-hand side sparse matrix
schurAssign(const SparseMatrix<MT2,false> & rhs)12257 inline void Submatrix<MT,aligned,true,true,CSAs...>::schurAssign( const SparseMatrix<MT2,false>& rhs )
12258 {
12259    using blaze::reset;
12260 
12261    BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT2 );
12262 
12263    BLAZE_INTERNAL_ASSERT( rows()    == (*rhs).rows()   , "Invalid number of rows"    );
12264    BLAZE_INTERNAL_ASSERT( columns() == (*rhs).columns(), "Invalid number of columns" );
12265 
12266    for( size_t i=0UL; i<rows(); ++i )
12267    {
12268       size_t j( 0UL );
12269 
12270       for( ConstIterator_t<MT2> element=(*rhs).begin(i); element!=(*rhs).end(i); ++element ) {
12271          for( ; j<element->index(); ++j )
12272             reset( matrix_(row()+i,column()+j) );
12273          matrix_(row()+i,column()+j) *= element->value();
12274          ++j;
12275       }
12276 
12277       for( ; j<columns(); ++j ) {
12278          reset( matrix_(row()+i,column()+j) );
12279       }
12280    }
12281 }
12282 /*! \endcond */
12283 //*************************************************************************************************
12284 
12285 } // namespace blaze
12286 
12287 #endif
12288