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