1 //=================================================================================================
2 /*!
3 // \file blaze/math/dense/DynamicMatrix.h
4 // \brief Header file for the implementation of a dynamic MxN matrix
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_DENSE_DYNAMICMATRIX_H_
36 #define _BLAZE_MATH_DENSE_DYNAMICMATRIX_H_
37
38
39 //*************************************************************************************************
40 // Includes
41 //*************************************************************************************************
42
43 #include <array>
44 #include <algorithm>
45 #include <memory>
46 #include <utility>
47 #include <blaze/math/Aliases.h>
48 #include <blaze/math/AlignmentFlag.h>
49 #include <blaze/math/constraints/Diagonal.h>
50 #include <blaze/math/constraints/SameTag.h>
51 #include <blaze/math/constraints/Symmetric.h>
52 #include <blaze/math/dense/DenseIterator.h>
53 #include <blaze/math/dense/Forward.h>
54 #include <blaze/math/Exception.h>
55 #include <blaze/math/expressions/DenseMatrix.h>
56 #include <blaze/math/expressions/SparseMatrix.h>
57 #include <blaze/math/Forward.h>
58 #include <blaze/math/InitializerList.h>
59 #include <blaze/math/RelaxationFlag.h>
60 #include <blaze/math/shims/Clear.h>
61 #include <blaze/math/shims/Conjugate.h>
62 #include <blaze/math/shims/IsDefault.h>
63 #include <blaze/math/shims/NextMultiple.h>
64 #include <blaze/math/shims/PrevMultiple.h>
65 #include <blaze/math/shims/Reset.h>
66 #include <blaze/math/SIMD.h>
67 #include <blaze/math/traits/AddTrait.h>
68 #include <blaze/math/traits/ColumnsTrait.h>
69 #include <blaze/math/traits/DivTrait.h>
70 #include <blaze/math/traits/EvaluateTrait.h>
71 #include <blaze/math/traits/ExpandTrait.h>
72 #include <blaze/math/traits/KronTrait.h>
73 #include <blaze/math/traits/MapTrait.h>
74 #include <blaze/math/traits/MultTrait.h>
75 #include <blaze/math/traits/RepeatTrait.h>
76 #include <blaze/math/traits/RowsTrait.h>
77 #include <blaze/math/traits/SchurTrait.h>
78 #include <blaze/math/traits/SolveTrait.h>
79 #include <blaze/math/traits/SubmatrixTrait.h>
80 #include <blaze/math/traits/SubTrait.h>
81 #include <blaze/math/typetraits/DynamicAllocator.h>
82 #include <blaze/math/typetraits/GetAllocator.h>
83 #include <blaze/math/typetraits/HasConstDataAccess.h>
84 #include <blaze/math/typetraits/HasMutableDataAccess.h>
85 #include <blaze/math/typetraits/HasSIMDAdd.h>
86 #include <blaze/math/typetraits/HasSIMDMult.h>
87 #include <blaze/math/typetraits/HasSIMDSub.h>
88 #include <blaze/math/typetraits/HighType.h>
89 #include <blaze/math/typetraits/IsAligned.h>
90 #include <blaze/math/typetraits/IsColumnVector.h>
91 #include <blaze/math/typetraits/IsContiguous.h>
92 #include <blaze/math/typetraits/IsDenseMatrix.h>
93 #include <blaze/math/typetraits/IsDenseVector.h>
94 #include <blaze/math/typetraits/IsDiagonal.h>
95 #include <blaze/math/typetraits/IsLower.h>
96 #include <blaze/math/typetraits/IsMatrix.h>
97 #include <blaze/math/typetraits/IsPadded.h>
98 #include <blaze/math/typetraits/IsResizable.h>
99 #include <blaze/math/typetraits/IsRowVector.h>
100 #include <blaze/math/typetraits/IsScalar.h>
101 #include <blaze/math/typetraits/IsShrinkable.h>
102 #include <blaze/math/typetraits/IsSIMDCombinable.h>
103 #include <blaze/math/typetraits/IsSMPAssignable.h>
104 #include <blaze/math/typetraits/IsSparseMatrix.h>
105 #include <blaze/math/typetraits/IsSquare.h>
106 #include <blaze/math/typetraits/IsStrictlyLower.h>
107 #include <blaze/math/typetraits/IsStrictlyUpper.h>
108 #include <blaze/math/typetraits/IsSymmetric.h>
109 #include <blaze/math/typetraits/IsUpper.h>
110 #include <blaze/math/typetraits/LowType.h>
111 #include <blaze/math/typetraits/MaxSize.h>
112 #include <blaze/math/typetraits/Size.h>
113 #include <blaze/math/typetraits/StorageOrder.h>
114 #include <blaze/system/Blocking.h>
115 #include <blaze/system/CacheSize.h>
116 #include <blaze/system/Inline.h>
117 #include <blaze/system/NoUniqueAddress.h>
118 #include <blaze/system/Optimizations.h>
119 #include <blaze/system/Restrict.h>
120 #include <blaze/system/Thresholds.h>
121 #include <blaze/util/Algorithms.h>
122 #include <blaze/util/AlignedAllocator.h>
123 #include <blaze/util/AlignmentCheck.h>
124 #include <blaze/util/Assert.h>
125 #include <blaze/util/constraints/Const.h>
126 #include <blaze/util/constraints/Pointer.h>
127 #include <blaze/util/constraints/Reference.h>
128 #include <blaze/util/constraints/Vectorizable.h>
129 #include <blaze/util/constraints/Volatile.h>
130 #include <blaze/util/EnableIf.h>
131 #include <blaze/util/IntegralConstant.h>
132 #include <blaze/util/MaybeUnused.h>
133 #include <blaze/util/Memory.h>
134 #include <blaze/util/Types.h>
135 #include <blaze/util/typetraits/IsBuiltin.h>
136 #include <blaze/util/typetraits/IsSame.h>
137 #include <blaze/util/typetraits/IsVectorizable.h>
138 #include <blaze/util/typetraits/RemoveConst.h>
139 #include <blaze/util/typetraits/RemoveCV.h>
140
141
142 namespace blaze {
143
144 //=================================================================================================
145 //
146 // CLASS DEFINITION
147 //
148 //=================================================================================================
149
150 //*************************************************************************************************
151 /*!\defgroup dynamic_matrix DynamicMatrix
152 // \ingroup dense_matrix
153 */
154 /*!\brief Efficient implementation of a dynamic \f$ M \times N \f$ matrix.
155 // \ingroup dynamic_matrix
156 //
157 // The DynamicMatrix class template is the representation of an arbitrary sized matrix with
158 // \f$ M \times N \f$ dynamically allocated elements of arbitrary type. The type of the elements,
159 // the storage order, the type of the allocator, and the group tag of the matrix can be specified
160 // via the four template parameters:
161
162 \code
163 namespace blaze {
164
165 template< typename Type, bool SO, typename Alloc, typename Tag >
166 class DynamicMatrix;
167
168 } // namespace blaze
169 \endcode
170
171 // - Type : specifies the type of the matrix elements. DynamicMatrix can be used with any
172 // non-cv-qualified, non-reference, non-pointer element type.
173 // - SO : specifies the storage order (blaze::rowMajor, blaze::columnMajor) of the matrix.
174 // The default value is blaze::defaultStorageOrder.
175 // - Alloc: specifies the type of allocator used to allocate dynamic memory. The default type
176 // of allocator is \c blaze::AlignedAllocator.
177 // - Tag : optional type parameter to tag the matrix. The default type is \c blaze::Group0.
178 // See \ref grouping_tagging for details.
179 //
180 // Depending on the storage order, the matrix elements are either stored in a row-wise fashion
181 // or in a column-wise fashion. Given the 2x3 matrix
182
183 \f[\left(\begin{array}{*{3}{c}}
184 1 & 2 & 3 \\
185 4 & 5 & 6 \\
186 \end{array}\right)\f]\n
187
188 // in case of row-major order the elements are stored in the order
189
190 \f[\left(\begin{array}{*{6}{c}}
191 1 & 2 & 3 & 4 & 5 & 6. \\
192 \end{array}\right)\f]
193
194 // In case of column-major order the elements are stored in the order
195
196 \f[\left(\begin{array}{*{6}{c}}
197 1 & 4 & 2 & 5 & 3 & 6. \\
198 \end{array}\right)\f]
199
200 // The use of DynamicMatrix is very natural and intuitive. All operations (addition, subtraction,
201 // multiplication, scaling, ...) can be performed on all possible combinations of row-major and
202 // column-major dense and sparse matrices with fitting element types. The following example gives
203 // an impression of the use of DynamicMatrix:
204
205 \code
206 using blaze::DynamicMatrix;
207 using blaze::CompressedMatrix;
208 using blaze::rowMajor;
209 using blaze::columnMajor;
210
211 DynamicMatrix<double,rowMajor> A( 2, 3 ); // Default constructed, non-initialized, row-major 2x3 matrix
212 A(0,0) = 1.0; A(0,1) = 2.0; A(0,2) = 3.0; // Initialization of the first row
213 A(1,0) = 4.0; A(1,1) = 5.0; A(1,2) = 6.0; // Initialization of the second row
214
215 DynamicMatrix<float,columnMajor> B( 2, 3 ); // Default constructed column-major single precision 2x3 matrix
216 B(0,0) = 1.0; B(0,1) = 3.0; B(0,2) = 5.0; // Initialization of the first row
217 B(1,0) = 2.0; B(1,1) = 4.0; B(1,2) = 6.0; // Initialization of the second row
218
219 CompressedMatrix<float> C( 2, 3 ); // Empty row-major sparse single precision matrix
220 DynamicMatrix<float> D( 3, 2, 4.0F ); // Directly, homogeneously initialized single precision 3x2 matrix
221
222 DynamicMatrix<double,rowMajor> E( A ); // Creation of a new row-major matrix as a copy of A
223 DynamicMatrix<double,columnMajor> F; // Creation of a default column-major matrix
224
225 E = A + B; // Matrix addition and assignment to a row-major matrix
226 F = A - C; // Matrix subtraction and assignment to a column-major matrix
227 F = A * D; // Matrix multiplication between two matrices of different element types
228
229 A *= 2.0; // In-place scaling of matrix A
230 E = 2.0 * B; // Scaling of matrix B
231 F = D * 2.0; // Scaling of matrix D
232
233 E += A - B; // Addition assignment
234 E -= A + C; // Subtraction assignment
235 F *= A * D; // Multiplication assignment
236 \endcode
237 */
238 template< typename Type // Data type of the matrix
239 , bool SO // Storage order
240 , typename Alloc // Type of the allocator
241 , typename Tag > // Type tag
242 class DynamicMatrix
243 : public DenseMatrix< DynamicMatrix<Type,SO,Alloc,Tag>, SO >
244 {
245 private:
246 //**********************************************************************************************
247 //! Compilation switch for the choice of alignment.
248 static constexpr AlignmentFlag align = ( usePadding ? aligned : unaligned );
249 //**********************************************************************************************
250
251 public:
252 //**Type definitions****************************************************************************
253 using This = DynamicMatrix<Type,SO,Alloc,Tag>; //!< Type of this DynamicMatrix instance.
254 using BaseType = DenseMatrix<This,SO>; //!< Base type of this DynamicMatrix instance.
255 using ResultType = This; //!< Result type for expression template evaluations.
256
257 //! Result type with opposite storage order for expression template evaluations.
258 using OppositeType = DynamicMatrix<Type,!SO,Alloc,Tag>;
259
260 //! Transpose type for expression template evaluations.
261 using TransposeType = DynamicMatrix<Type,!SO,Alloc,Tag>;
262
263 using ElementType = Type; //!< Type of the matrix elements.
264 using SIMDType = SIMDTrait_t<ElementType>; //!< SIMD type of the matrix elements.
265 using AllocatorType = AlignedAllocator<Type>; //!< Allocator type of this DynamicMatrix instance.
266 using TagType = Tag; //!< Tag type of this DynamicMatrix instance.
267 using ReturnType = const Type&; //!< Return type for expression template evaluations.
268 using CompositeType = const This&; //!< Data type for composite expression templates.
269
270 using Reference = Type&; //!< Reference to a non-constant matrix value.
271 using ConstReference = const Type&; //!< Reference to a constant matrix value.
272 using Pointer = Type*; //!< Pointer to a non-constant matrix value.
273 using ConstPointer = const Type*; //!< Pointer to a constant matrix value.
274
275 using Iterator = DenseIterator<Type,align>; //!< Iterator over non-constant elements.
276 using ConstIterator = DenseIterator<const Type,align>; //!< Iterator over constant elements.
277 //**********************************************************************************************
278
279 //**Rebind struct definition********************************************************************
280 /*!\brief Rebind mechanism to obtain a DynamicMatrix with different data/element type.
281 */
282 template< typename NewType > // Data type of the other matrix
283 struct Rebind
284 {
285 //! The new type of allocator.
286 using NewAlloc = typename std::allocator_traits<Alloc>::template rebind_alloc<NewType>;
287
288 //! The type of the other DynamicMatrix.
289 using Other = DynamicMatrix<NewType,SO,NewAlloc,Tag>;
290 };
291 //**********************************************************************************************
292
293 //**Resize struct definition********************************************************************
294 /*!\brief Resize mechanism to obtain a DynamicMatrix with different fixed dimensions.
295 */
296 template< size_t NewM // Number of rows of the other matrix
297 , size_t NewN > // Number of columns of the other matrix
298 struct Resize
299 {
300 using Other = DynamicMatrix<Type,SO,Alloc,Tag>; //!< The type of the other DynamicMatrix.
301 };
302 //**********************************************************************************************
303
304 //**Compilation flags***************************************************************************
305 //! Compilation flag for SIMD optimization.
306 /*! The \a simdEnabled compilation flag indicates whether expressions the matrix is involved
307 in can be optimized via SIMD operations. In case the element type of the matrix is a
308 vectorizable data type, the \a simdEnabled compilation flag is set to \a true, otherwise
309 it is set to \a false. */
310 static constexpr bool simdEnabled = IsVectorizable_v<Type>;
311
312 //! Compilation flag for SMP assignments.
313 /*! The \a smpAssignable compilation flag indicates whether the matrix can be used in SMP
314 (shared memory parallel) assignments (both on the left-hand and right-hand side of the
315 assignment). */
316 static constexpr bool smpAssignable = !IsSMPAssignable_v<Type>;
317 //**********************************************************************************************
318
319 //**Constructors********************************************************************************
320 /*!\name Constructors */
321 //@{
322 inline DynamicMatrix( const Alloc& alloc = Alloc{} ) noexcept;
323 inline DynamicMatrix( size_t m, size_t n, const Alloc& alloc = Alloc{} );
324 inline DynamicMatrix( size_t m, size_t n, const Type& init, const Alloc& alloc = Alloc{} );
325 inline DynamicMatrix( initializer_list< initializer_list<Type> > list, const Alloc& alloc = Alloc{} );
326
327 template< typename Other >
328 inline DynamicMatrix( size_t m, size_t n, const Other* array, const Alloc& alloc = Alloc{} );
329
330 template< typename Other, size_t Rows, size_t Cols >
331 inline DynamicMatrix( const Other (&array)[Rows][Cols], const Alloc& alloc = Alloc{} );
332
333 template< typename Other, size_t Rows, size_t Cols >
334 inline DynamicMatrix( const std::array<std::array<Other,Cols>,Rows>& array, const Alloc& alloc = Alloc{} );
335
336 inline DynamicMatrix( const DynamicMatrix& m );
337 inline DynamicMatrix( DynamicMatrix&& m ) noexcept;
338
339 template< typename MT, bool SO2 >
340 inline DynamicMatrix( const Matrix<MT,SO2>& m );
341 //@}
342 //**********************************************************************************************
343
344 //**Destructor**********************************************************************************
345 /*!\name Destructor */
346 //@{
347 inline ~DynamicMatrix();
348 //@}
349 //**********************************************************************************************
350
351 //**Data access functions***********************************************************************
352 /*!\name Data access functions */
353 //@{
354 inline Reference operator()( size_t i, size_t j ) noexcept;
355 inline ConstReference operator()( size_t i, size_t j ) const noexcept;
356 inline Reference at( size_t i, size_t j );
357 inline ConstReference at( size_t i, size_t j ) const;
358 inline Pointer data () noexcept;
359 inline ConstPointer data () const noexcept;
360 inline Pointer data ( size_t i ) noexcept;
361 inline ConstPointer data ( size_t i ) const noexcept;
362 inline Iterator begin ( size_t i ) noexcept;
363 inline ConstIterator begin ( size_t i ) const noexcept;
364 inline ConstIterator cbegin( size_t i ) const noexcept;
365 inline Iterator end ( size_t i ) noexcept;
366 inline ConstIterator end ( size_t i ) const noexcept;
367 inline ConstIterator cend ( size_t i ) const noexcept;
368 //@}
369 //**********************************************************************************************
370
371 //**Assignment operators************************************************************************
372 /*!\name Assignment operators */
373 //@{
374 inline DynamicMatrix& operator=( const Type& rhs ) &;
375 inline DynamicMatrix& operator=( initializer_list< initializer_list<Type> > list ) &;
376
377 template< typename Other, size_t Rows, size_t Cols >
378 inline DynamicMatrix& operator=( const Other (&array)[Rows][Cols] ) &;
379
380 template< typename Other, size_t Rows, size_t Cols >
381 inline DynamicMatrix& operator=( const std::array<std::array<Other,Cols>,Rows>& array ) &;
382
383 inline DynamicMatrix& operator=( const DynamicMatrix& rhs ) &;
384 inline DynamicMatrix& operator=( DynamicMatrix&& rhs ) & noexcept;
385
386 template< typename MT, bool SO2 > inline DynamicMatrix& operator= ( const Matrix<MT,SO2>& rhs ) &;
387 template< typename MT, bool SO2 > inline DynamicMatrix& operator+=( const Matrix<MT,SO2>& rhs ) &;
388 template< typename MT, bool SO2 > inline DynamicMatrix& operator-=( const Matrix<MT,SO2>& rhs ) &;
389 template< typename MT, bool SO2 > inline DynamicMatrix& operator%=( const Matrix<MT,SO2>& rhs ) &;
390 //@}
391 //**********************************************************************************************
392
393 //**Utility functions***************************************************************************
394 /*!\name Utility functions */
395 //@{
396 inline size_t rows() const noexcept;
397 inline size_t columns() const noexcept;
398 inline size_t spacing() const noexcept;
399 inline size_t capacity() const noexcept;
400 inline size_t capacity( size_t i ) const noexcept;
401 inline size_t nonZeros() const;
402 inline size_t nonZeros( size_t i ) const;
403 inline void reset();
404 inline void reset( size_t i );
405 inline void clear();
406 void resize ( size_t m, size_t n, bool preserve=true );
407 inline void extend ( size_t m, size_t n, bool preserve=true );
408 inline void reserve( size_t elements );
409 inline void shrinkToFit();
410 inline void swap( DynamicMatrix& m ) noexcept;
411 //@}
412 //**********************************************************************************************
413
414 //**Numeric functions***************************************************************************
415 /*!\name Numeric functions */
416 //@{
417 inline DynamicMatrix& transpose();
418 inline DynamicMatrix& ctranspose();
419
420 template< typename Other > inline DynamicMatrix& scale( const Other& scalar );
421 //@}
422 //**********************************************************************************************
423
424 private:
425 //**********************************************************************************************
426 /*! \cond BLAZE_INTERNAL */
427 //! Helper variable template for the explicit application of the SFINAE principle.
428 template< typename MT >
429 static constexpr bool VectorizedAssign_v =
430 ( useOptimizedKernels &&
431 simdEnabled && MT::simdEnabled &&
432 IsSIMDCombinable_v< Type, ElementType_t<MT> > );
433 /*! \endcond */
434 //**********************************************************************************************
435
436 //**********************************************************************************************
437 /*! \cond BLAZE_INTERNAL */
438 //! Helper variable template for the explicit application of the SFINAE principle.
439 template< typename MT >
440 static constexpr bool VectorizedAddAssign_v =
441 ( VectorizedAssign_v<MT> &&
442 HasSIMDAdd_v< Type, ElementType_t<MT> > &&
443 !IsDiagonal_v<MT> );
444 /*! \endcond */
445 //**********************************************************************************************
446
447 //**********************************************************************************************
448 /*! \cond BLAZE_INTERNAL */
449 //! Helper variable template for the explicit application of the SFINAE principle.
450 template< typename MT >
451 static constexpr bool VectorizedSubAssign_v =
452 ( VectorizedAssign_v<MT> &&
453 HasSIMDSub_v< Type, ElementType_t<MT> > &&
454 !IsDiagonal_v<MT> );
455 /*! \endcond */
456 //**********************************************************************************************
457
458 //**********************************************************************************************
459 /*! \cond BLAZE_INTERNAL */
460 //! Helper variable template for the explicit application of the SFINAE principle.
461 template< typename MT >
462 static constexpr bool VectorizedSchurAssign_v =
463 ( VectorizedAssign_v<MT> &&
464 HasSIMDMult_v< Type, ElementType_t<MT> > );
465 /*! \endcond */
466 //**********************************************************************************************
467
468 //**********************************************************************************************
469 //! The number of elements packed within a single SIMD element.
470 static constexpr size_t SIMDSIZE = SIMDTrait<ElementType>::size;
471 //**********************************************************************************************
472
473 public:
474 //**Debugging functions*************************************************************************
475 /*!\name Debugging functions */
476 //@{
477 inline bool isIntact() const noexcept;
478 //@}
479 //**********************************************************************************************
480
481 //**Expression template evaluation functions****************************************************
482 /*!\name Expression template evaluation functions */
483 //@{
484 template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
485 template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
486
487 inline bool isAligned () const noexcept;
488 inline bool canSMPAssign() const noexcept;
489
490 BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
491 BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
492 BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
493
494 BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
495 BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
496 BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
497 BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
498
499 template< typename MT >
500 inline auto assign( const DenseMatrix<MT,SO>& rhs ) -> DisableIf_t< VectorizedAssign_v<MT> >;
501
502 template< typename MT >
503 inline auto assign( const DenseMatrix<MT,SO>& rhs ) -> EnableIf_t< VectorizedAssign_v<MT> >;
504
505 template< typename MT > inline void assign( const DenseMatrix<MT,!SO>& rhs );
506 template< typename MT > inline void assign( const SparseMatrix<MT,SO>& rhs );
507 template< typename MT > inline void assign( const SparseMatrix<MT,!SO>& rhs );
508
509 template< typename MT >
510 inline auto addAssign( const DenseMatrix<MT,SO>& rhs ) -> DisableIf_t< VectorizedAddAssign_v<MT> >;
511
512 template< typename MT >
513 inline auto addAssign( const DenseMatrix<MT,SO>& rhs ) -> EnableIf_t< VectorizedAddAssign_v<MT> >;
514
515 template< typename MT > inline void addAssign( const DenseMatrix<MT,!SO>& rhs );
516 template< typename MT > inline void addAssign( const SparseMatrix<MT,SO>& rhs );
517 template< typename MT > inline void addAssign( const SparseMatrix<MT,!SO>& rhs );
518
519 template< typename MT >
520 inline auto subAssign( const DenseMatrix<MT,SO>& rhs ) -> DisableIf_t< VectorizedSubAssign_v<MT> >;
521
522 template< typename MT >
523 inline auto subAssign( const DenseMatrix<MT,SO>& rhs ) -> EnableIf_t< VectorizedSubAssign_v<MT> >;
524
525 template< typename MT > inline void subAssign( const DenseMatrix<MT,!SO>& rhs );
526 template< typename MT > inline void subAssign( const SparseMatrix<MT,SO>& rhs );
527 template< typename MT > inline void subAssign( const SparseMatrix<MT,!SO>& rhs );
528
529 template< typename MT >
530 inline auto schurAssign( const DenseMatrix<MT,SO>& rhs ) -> DisableIf_t< VectorizedSchurAssign_v<MT> >;
531
532 template< typename MT >
533 inline auto schurAssign( const DenseMatrix<MT,SO>& rhs ) -> EnableIf_t< VectorizedSchurAssign_v<MT> >;
534
535 template< typename MT > inline void schurAssign( const DenseMatrix<MT,!SO>& rhs );
536 template< typename MT > inline void schurAssign( const SparseMatrix<MT,SO>& rhs );
537 template< typename MT > inline void schurAssign( const SparseMatrix<MT,!SO>& rhs );
538 //@}
539 //**********************************************************************************************
540
541 private:
542 //**Uninitialized struct definition*************************************************************
543 /*!\brief Definition of the nested auxiliary struct Uninitialized.
544 */
545 struct Uninitialized {};
546 //**********************************************************************************************
547
548 //**Constructors********************************************************************************
549 /*!\name Constructors */
550 //@{
551 inline DynamicMatrix( size_t m, size_t n, size_t nn, const Alloc& alloc, Uninitialized );
552 inline DynamicMatrix( size_t m, size_t n, size_t nn, size_t capa, const Alloc& alloc, Uninitialized );
553 //@}
554 //**********************************************************************************************
555
556 //**Utility functions***************************************************************************
557 /*!\name Utility functions */
558 //@{
559 inline size_t addPadding( size_t value ) const noexcept;
560 //@}
561 //**********************************************************************************************
562
563 //**Member variables****************************************************************************
564 /*!\name Member variables */
565 //@{
566 size_t m_; //!< The current number of rows of the matrix.
567 size_t n_; //!< The current number of columns of the matrix.
568 size_t nn_; //!< The alignment adjusted number of columns.
569 size_t capacity_; //!< The maximum capacity of the matrix.
570
571 Type* BLAZE_RESTRICT v_; //!< The dynamically allocated matrix elements.
572 /*!< Access to the matrix elements is gained via the function call
573 operator. In case of row-major order the memory layout of the
574 elements is
575 \f[\left(\begin{array}{*{5}{c}}
576 0 & 1 & 2 & \cdots & N-1 \\
577 N & N+1 & N+2 & \cdots & 2 \cdot N-1 \\
578 \vdots & \vdots & \vdots & \ddots & \vdots \\
579 M \cdot N-N & M \cdot N-N+1 & M \cdot N-N+2 & \cdots & M \cdot N-1 \\
580 \end{array}\right)\f]. */
581
582 BLAZE_NO_UNIQUE_ADDRESS Alloc alloc_; //!< The allocator of the matrix.
583 //@}
584 //**********************************************************************************************
585
586 //**Compile time checks*************************************************************************
587 /*! \cond BLAZE_INTERNAL */
588 BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( Type );
589 BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE( Type );
590 BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( Type );
591 BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( Type );
592 /*! \endcond */
593 //**********************************************************************************************
594 };
595 //*************************************************************************************************
596
597
598
599
600 //=================================================================================================
601 //
602 // DEDUCTION GUIDES
603 //
604 //=================================================================================================
605
606 //*************************************************************************************************
607 #if BLAZE_CPP17_MODE
608
609 template< typename Type >
610 DynamicMatrix( size_t, size_t, Type* ) -> DynamicMatrix< RemoveCV_t<Type> >;
611
612 template< typename Type, size_t M, size_t N >
613 DynamicMatrix( Type (&)[M][N] ) -> DynamicMatrix< RemoveCV_t<Type> >;
614
615 template< typename Type, size_t M, size_t N >
616 DynamicMatrix( std::array<std::array<Type,N>,M> ) -> DynamicMatrix<Type>;
617
618 #endif
619 //*************************************************************************************************
620
621
622
623
624 //=================================================================================================
625 //
626 // CONSTRUCTORS
627 //
628 //=================================================================================================
629
630 //*************************************************************************************************
631 /*!\brief The (default) constructor for DynamicMatrix.
632 //
633 // \param alloc Allocator for all memory allocations of this matrix.
634 */
635 template< typename Type // Data type of the matrix
636 , bool SO // Storage order
637 , typename Alloc // Type of the allocator
638 , typename Tag > // Type tag
DynamicMatrix(const Alloc & alloc)639 inline DynamicMatrix<Type,SO,Alloc,Tag>::DynamicMatrix( const Alloc& alloc ) noexcept
640 : m_ ( 0UL ) // The current number of rows of the matrix
641 , n_ ( 0UL ) // The current number of columns of the matrix
642 , nn_ ( 0UL ) // The alignment adjusted number of columns
643 , capacity_( 0UL ) // The maximum capacity of the matrix
644 , v_ ( nullptr ) // The matrix elements
645 , alloc_ ( alloc ) // The allocator of the matrix
646 {}
647 //*************************************************************************************************
648
649
650 //*************************************************************************************************
651 /*!\brief Auxiliary constructor for DynamicMatrix.
652 //
653 // \param m The number of rows of the matrix.
654 // \param n The number of columns of the matrix.
655 // \param nn The alignment adjusted number of columns.
656 // \param alloc Allocator for all memory allocations of this matrix.
657 // \exception std::bad_alloc Allocation failed.
658 */
659 template< typename Type // Data type of the matrix
660 , bool SO // Storage order
661 , typename Alloc // Type of the allocator
662 , typename Tag > // Type tag
DynamicMatrix(size_t m,size_t n,size_t nn,const Alloc & alloc,Uninitialized)663 inline DynamicMatrix<Type,SO,Alloc,Tag>::DynamicMatrix( size_t m, size_t n, size_t nn, const Alloc& alloc, Uninitialized )
664 : DynamicMatrix( m, n, nn, m*nn, alloc, Uninitialized{} )
665 {}
666 //*************************************************************************************************
667
668
669 //*************************************************************************************************
670 /*!\brief Auxiliary constructor for DynamicMatrix.
671 //
672 // \param m The number of rows of the matrix.
673 // \param n The number of columns of the matrix.
674 // \param nn The alignment adjusted number of columns.
675 // \param capa The initial capacity of the matrix.
676 // \param alloc Allocator for all memory allocations of this matrix.
677 // \exception std::bad_alloc Allocation failed.
678 */
679 template< typename Type // Data type of the matrix
680 , bool SO // Storage order
681 , typename Alloc // Type of the allocator
682 , typename Tag > // Type tag
DynamicMatrix(size_t m,size_t n,size_t nn,size_t capa,const Alloc & alloc,Uninitialized)683 inline DynamicMatrix<Type,SO,Alloc,Tag>::DynamicMatrix( size_t m, size_t n, size_t nn, size_t capa, const Alloc& alloc, Uninitialized )
684 : m_ ( m ) // The current number of rows of the matrix
685 , n_ ( n ) // The current number of columns of the matrix
686 , nn_ ( nn ) // The alignment adjusted number of columns
687 , capacity_( capa ) // The maximum capacity of the matrix
688 , v_ ( nullptr ) // The matrix elements
689 , alloc_ ( alloc ) // The allocator of the matrix
690 {
691 v_ = alloc_.allocate( capacity_ );
692
693 if( !checkAlignment( v_ ) ) {
694 alloc_.deallocate( v_, capacity_ );
695 BLAZE_THROW_BAD_ALLOC;
696 }
697 }
698 //*************************************************************************************************
699
700
701 //*************************************************************************************************
702 /*!\brief Constructor for a matrix of size \f$ m \times n \f$. For built-in types no initialization
703 // is performed!
704 //
705 // \param m The number of rows of the matrix.
706 // \param n The number of columns of the matrix.
707 // \param alloc Allocator for all memory allocations of this matrix.
708 //
709 // \note This constructor is only responsible to allocate the required dynamic memory. For
710 // built-in types no initialization of the elements is performed!
711 */
712 template< typename Type // Data type of the matrix
713 , bool SO // Storage order
714 , typename Alloc // Type of the allocator
715 , typename Tag > // Type tag
DynamicMatrix(size_t m,size_t n,const Alloc & alloc)716 inline DynamicMatrix<Type,SO,Alloc,Tag>::DynamicMatrix( size_t m, size_t n, const Alloc& alloc )
717 : DynamicMatrix( m, n, addPadding(n), alloc, Uninitialized{} )
718 {
719 using blaze::clear;
720
721 blaze::uninitialized_default_construct_n( v_, capacity_ );
722
723 if( IsVectorizable_v<Type> && IsBuiltin_v<Type> ) {
724 for( size_t i=0UL; i<m_; ++i ) {
725 for( size_t j=n_; j<nn_; ++j ) {
726 clear( v_[i*nn_+j] );
727 }
728 }
729 }
730
731 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
732 }
733 //*************************************************************************************************
734
735
736 //*************************************************************************************************
737 /*!\brief Constructor for a homogenous initialization of all \f$ m \times n \f$ matrix elements.
738 //
739 // \param m The number of rows of the matrix.
740 // \param n The number of columns of the matrix.
741 // \param init The initial value of the matrix elements.
742 // \param alloc Allocator for all memory allocations of this matrix.
743 //
744 // All matrix elements are initialized with the specified value.
745 */
746 template< typename Type // Data type of the matrix
747 , bool SO // Storage order
748 , typename Alloc // Type of the allocator
749 , typename Tag > // Type tag
DynamicMatrix(size_t m,size_t n,const Type & init,const Alloc & alloc)750 inline DynamicMatrix<Type,SO,Alloc,Tag>::DynamicMatrix( size_t m, size_t n, const Type& init, const Alloc& alloc )
751 : DynamicMatrix( m, n, alloc )
752 {
753 for( size_t i=0UL; i<m; ++i ) {
754 for( size_t j=0UL; j<n_; ++j ) {
755 v_[i*nn_+j] = init;
756 }
757 }
758
759 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
760 }
761 //*************************************************************************************************
762
763
764 //*************************************************************************************************
765 /*!\brief List initialization of all matrix elements.
766 //
767 // \param list The initializer list.
768 // \param alloc Allocator for all memory allocations of this matrix.
769 //
770 // This constructor provides the option to explicitly initialize the elements of the matrix by
771 // means of an initializer list:
772
773 \code
774 using blaze::rowMajor;
775
776 blaze::DynamicMatrix<int,rowMajor> A{ { 1, 2, 3 },
777 { 4, 5 },
778 { 7, 8, 9 } };
779 \endcode
780
781 // The matrix is sized according to the size of the initializer list and all its elements are
782 // (copy) assigned the values of the given initializer list. Missing values are initialized as
783 // default (as e.g. the value 6 in the example).
784 */
785 template< typename Type // Data type of the matrix
786 , bool SO // Storage order
787 , typename Alloc // Type of the allocator
788 , typename Tag > // Type tag
DynamicMatrix(initializer_list<initializer_list<Type>> list,const Alloc & alloc)789 inline DynamicMatrix<Type,SO,Alloc,Tag>::DynamicMatrix( initializer_list< initializer_list<Type> > list, const Alloc& alloc )
790 : DynamicMatrix( list.size(), determineColumns( list ), alloc )
791 {
792 size_t i( 0UL );
793
794 for( const auto& rowList : list ) {
795 std::fill( std::copy( rowList.begin(), rowList.end(), begin(i) ), end(i), Type() );
796 ++i;
797 }
798
799 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
800 }
801 //*************************************************************************************************
802
803
804 //*************************************************************************************************
805 /*!\brief Array initialization of all matrix elements.
806 //
807 // \param m The number of rows of the matrix.
808 // \param n The number of columns of the matrix.
809 // \param array Dynamic array for the initialization.
810 // \param alloc Allocator for all memory allocations of this matrix.
811 //
812 // This constructor offers the option to directly initialize the elements of the matrix with
813 // a dynamic array:
814
815 \code
816 using blaze::rowMajor;
817
818 int* array = new int[20];
819 // ... Initialization of the dynamic array
820 blaze::DynamicMatrix<int,rowMajor> v( 4UL, 5UL, array );
821 delete[] array;
822 \endcode
823
824 // The matrix is sized according to the given size of the array and initialized with the values
825 // from the given array. Note that it is expected that the given \a array has at least \a m by
826 // \a n elements. Providing an array with less elements results in undefined behavior!
827 */
828 template< typename Type // Data type of the matrix
829 , bool SO // Storage order
830 , typename Alloc // Type of the allocator
831 , typename Tag > // Type tag
832 template< typename Other > // Data type of the initialization array
DynamicMatrix(size_t m,size_t n,const Other * array,const Alloc & alloc)833 inline DynamicMatrix<Type,SO,Alloc,Tag>::DynamicMatrix( size_t m, size_t n, const Other* array, const Alloc& alloc )
834 : DynamicMatrix( m, n, alloc )
835 {
836 for( size_t i=0UL; i<m; ++i ) {
837 for( size_t j=0UL; j<n; ++j ) {
838 v_[i*nn_+j] = array[i*n+j];
839 }
840 }
841
842 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
843 }
844 //*************************************************************************************************
845
846
847 //*************************************************************************************************
848 /*!\brief Array initialization of all matrix elements.
849 //
850 // \param array Static array for the initialization.
851 // \param alloc Allocator for all memory allocations of this matrix.
852 //
853 // This constructor offers the option to directly initialize the elements of the matrix with
854 // a static array:
855
856 \code
857 using blaze::rowMajor;
858
859 const int init[3][3] = { { 1, 2, 3 },
860 { 4, 5 },
861 { 7, 8, 9 } };
862 blaze::DynamicMatrix<int,rowMajor> A( init );
863 \endcode
864
865 // The matrix is sized according to the size of the static array and initialized with the values
866 // from the given static array. Missing values are initialized with default values (as e.g. the
867 // value 6 in the example).
868 */
869 template< typename Type // Data type of the matrix
870 , bool SO // Storage order
871 , typename Alloc // Type of the allocator
872 , typename Tag > // Type tag
873 template< typename Other // Data type of the static array
874 , size_t Rows // Number of rows of the static array
875 , size_t Cols > // Number of columns of the static array
DynamicMatrix(const Other (& array)[Rows][Cols],const Alloc & alloc)876 inline DynamicMatrix<Type,SO,Alloc,Tag>::DynamicMatrix( const Other (&array)[Rows][Cols], const Alloc& alloc )
877 : DynamicMatrix( Rows, Cols, alloc )
878 {
879 for( size_t i=0UL; i<Rows; ++i ) {
880 for( size_t j=0UL; j<Cols; ++j ) {
881 v_[i*nn_+j] = array[i][j];
882 }
883 }
884
885 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
886 }
887 //*************************************************************************************************
888
889
890 //*************************************************************************************************
891 /*!\brief Initialization of all matrix elements from the given std::array.
892 //
893 // \param array The given std::array for the initialization.
894 // \param alloc Allocator for all memory allocations of this matrix.
895 //
896 // This constructor offers the option to directly initialize the elements of the matrix with
897 // a std::array:
898
899 \code
900 using blaze::rowMajor;
901
902 const std::array<std::array<int,3UL>,3UL> init{ { { 1, 2, 3 },
903 { 4, 5 },
904 { 7, 8, 9 } } };
905 blaze::DynamicMatrix<int,rowMajor> A( init );
906 \endcode
907
908 // The matrix is sized according to the size of the std::array and initialized with the values
909 // from the given std::array. Missing values are initialized with default values (as e.g. the
910 // value 6 in the example).
911 */
912 template< typename Type // Data type of the matrix
913 , bool SO // Storage order
914 , typename Alloc // Type of the allocator
915 , typename Tag > // Type tag
916 template< typename Other // Data type of the std::array
917 , size_t Rows // Number of rows of the std::array
918 , size_t Cols > // Number of columns of the std::array
DynamicMatrix(const std::array<std::array<Other,Cols>,Rows> & array,const Alloc & alloc)919 inline DynamicMatrix<Type,SO,Alloc,Tag>::DynamicMatrix( const std::array<std::array<Other,Cols>,Rows>& array, const Alloc& alloc )
920 : DynamicMatrix( Rows, Cols, alloc )
921 {
922 for( size_t i=0UL; i<Rows; ++i ) {
923 for( size_t j=0UL; j<Cols; ++j ) {
924 v_[i*nn_+j] = array[i][j];
925 }
926 }
927
928 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
929 }
930 //*************************************************************************************************
931
932
933 //*************************************************************************************************
934 /*!\brief The copy constructor for DynamicMatrix.
935 //
936 // \param m Matrix to be copied.
937 //
938 // The copy constructor is explicitly defined due to the required dynamic memory management
939 // and in order to enable/facilitate NRV optimization.
940 */
941 template< typename Type // Data type of the matrix
942 , bool SO // Storage order
943 , typename Alloc // Type of the allocator
944 , typename Tag > // Type tag
DynamicMatrix(const DynamicMatrix & m)945 inline DynamicMatrix<Type,SO,Alloc,Tag>::DynamicMatrix( const DynamicMatrix& m )
946 : DynamicMatrix( m.m_, m.n_ )
947 {
948 BLAZE_INTERNAL_ASSERT( capacity_ <= m.capacity_, "Invalid capacity estimation" );
949
950 smpAssign( *this, m );
951
952 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
953 }
954 //*************************************************************************************************
955
956
957 //*************************************************************************************************
958 /*!\brief The move constructor for DynamicMatrix.
959 //
960 // \param m The matrix to be move into this instance.
961 */
962 template< typename Type // Data type of the matrix
963 , bool SO // Storage order
964 , typename Alloc // Type of the allocator
965 , typename Tag > // Type tag
DynamicMatrix(DynamicMatrix && m)966 inline DynamicMatrix<Type,SO,Alloc,Tag>::DynamicMatrix( DynamicMatrix&& m ) noexcept
967 : m_ ( m.m_ ) // The current number of rows of the matrix
968 , n_ ( m.n_ ) // The current number of columns of the matrix
969 , nn_ ( m.nn_ ) // The alignment adjusted number of columns
970 , capacity_( m.capacity_ ) // The maximum capacity of the matrix
971 , v_ ( m.v_ ) // The matrix elements
972 {
973 m.m_ = 0UL;
974 m.n_ = 0UL;
975 m.nn_ = 0UL;
976 m.capacity_ = 0UL;
977 m.v_ = nullptr;
978 }
979 //*************************************************************************************************
980
981
982 //*************************************************************************************************
983 /*!\brief Conversion constructor from different matrices.
984 //
985 // \param m Matrix to be copied.
986 */
987 template< typename Type // Data type of the matrix
988 , bool SO // Storage order
989 , typename Alloc // Type of the allocator
990 , typename Tag > // Type tag
991 template< typename MT // Type of the foreign matrix
992 , bool SO2 > // Storage order of the foreign matrix
DynamicMatrix(const Matrix<MT,SO2> & m)993 inline DynamicMatrix<Type,SO,Alloc,Tag>::DynamicMatrix( const Matrix<MT,SO2>& m )
994 : DynamicMatrix( (*m).rows(), (*m).columns() )
995 {
996 BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<MT> );
997
998 if( IsSparseMatrix_v<MT> && IsBuiltin_v<Type> ) {
999 reset();
1000 }
1001
1002 smpAssign( *this, *m );
1003
1004 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
1005 }
1006 //*************************************************************************************************
1007
1008
1009
1010
1011 //=================================================================================================
1012 //
1013 // DESTRUCTOR
1014 //
1015 //=================================================================================================
1016
1017 //*************************************************************************************************
1018 /*!\brief The destructor for DynamicMatrix.
1019 */
1020 template< typename Type // Data type of the matrix
1021 , bool SO // Storage order
1022 , typename Alloc // Type of the allocator
1023 , typename Tag > // Type tag
~DynamicMatrix()1024 inline DynamicMatrix<Type,SO,Alloc,Tag>::~DynamicMatrix()
1025 {
1026 blaze::destroy_n( v_, capacity_ );
1027 alloc_.deallocate( v_, capacity_ );
1028 }
1029 //*************************************************************************************************
1030
1031
1032
1033
1034 //=================================================================================================
1035 //
1036 // DATA ACCESS FUNCTIONS
1037 //
1038 //=================================================================================================
1039
1040 //*************************************************************************************************
1041 /*!\brief 2D-access to the matrix elements.
1042 //
1043 // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
1044 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
1045 // \return Reference to the accessed value.
1046 //
1047 // This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
1048 // the at() function is guaranteed to perform a check of the given access indices.
1049 */
1050 template< typename Type // Data type of the matrix
1051 , bool SO // Storage order
1052 , typename Alloc // Type of the allocator
1053 , typename Tag > // Type tag
1054 inline typename DynamicMatrix<Type,SO,Alloc,Tag>::Reference
operator()1055 DynamicMatrix<Type,SO,Alloc,Tag>::operator()( size_t i, size_t j ) noexcept
1056 {
1057 BLAZE_USER_ASSERT( i<m_, "Invalid row access index" );
1058 BLAZE_USER_ASSERT( j<n_, "Invalid column access index" );
1059 return v_[i*nn_+j];
1060 }
1061 //*************************************************************************************************
1062
1063
1064 //*************************************************************************************************
1065 /*!\brief 2D-access to the matrix elements.
1066 //
1067 // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
1068 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
1069 // \return Reference to the accessed value.
1070 //
1071 // This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
1072 // the at() function is guaranteed to perform a check of the given access indices.
1073 */
1074 template< typename Type // Data type of the matrix
1075 , bool SO // Storage order
1076 , typename Alloc // Type of the allocator
1077 , typename Tag > // Type tag
1078 inline typename DynamicMatrix<Type,SO,Alloc,Tag>::ConstReference
operator()1079 DynamicMatrix<Type,SO,Alloc,Tag>::operator()( size_t i, size_t j ) const noexcept
1080 {
1081 BLAZE_USER_ASSERT( i<m_, "Invalid row access index" );
1082 BLAZE_USER_ASSERT( j<n_, "Invalid column access index" );
1083 return v_[i*nn_+j];
1084 }
1085 //*************************************************************************************************
1086
1087
1088 //*************************************************************************************************
1089 /*!\brief Checked access to the matrix elements.
1090 //
1091 // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
1092 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
1093 // \return Reference to the accessed value.
1094 // \exception std::out_of_range Invalid matrix access index.
1095 //
1096 // In contrast to the subscript operator this function always performs a check of the given
1097 // access indices.
1098 */
1099 template< typename Type // Data type of the matrix
1100 , bool SO // Storage order
1101 , typename Alloc // Type of the allocator
1102 , typename Tag > // Type tag
1103 inline typename DynamicMatrix<Type,SO,Alloc,Tag>::Reference
at(size_t i,size_t j)1104 DynamicMatrix<Type,SO,Alloc,Tag>::at( size_t i, size_t j )
1105 {
1106 if( i >= m_ ) {
1107 BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
1108 }
1109 if( j >= n_ ) {
1110 BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
1111 }
1112 return (*this)(i,j);
1113 }
1114 //*************************************************************************************************
1115
1116
1117 //*************************************************************************************************
1118 /*!\brief Checked access to the matrix elements.
1119 //
1120 // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
1121 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
1122 // \return Reference to the accessed value.
1123 // \exception std::out_of_range Invalid matrix access index.
1124 //
1125 // In contrast to the subscript operator this function always performs a check of the given
1126 // access indices.
1127 */
1128 template< typename Type // Data type of the matrix
1129 , bool SO // Storage order
1130 , typename Alloc // Type of the allocator
1131 , typename Tag > // Type tag
1132 inline typename DynamicMatrix<Type,SO,Alloc,Tag>::ConstReference
at(size_t i,size_t j)1133 DynamicMatrix<Type,SO,Alloc,Tag>::at( size_t i, size_t j ) const
1134 {
1135 if( i >= m_ ) {
1136 BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
1137 }
1138 if( j >= n_ ) {
1139 BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
1140 }
1141 return (*this)(i,j);
1142 }
1143 //*************************************************************************************************
1144
1145
1146 //*************************************************************************************************
1147 /*!\brief Low-level data access to the matrix elements.
1148 //
1149 // \return Pointer to the internal element storage.
1150 //
1151 // This function returns a pointer to the internal storage of the dynamic matrix. Note that you
1152 // can NOT assume that all matrix elements lie adjacent to each other! The dynamic matrix may
1153 // use techniques such as padding to improve the alignment of the data. Whereas the number of
1154 // elements within a row/column are given by the \c rows() and \c columns() member functions,
1155 // respectively, the total number of elements including padding is given by the \c spacing()
1156 // member function.
1157 */
1158 template< typename Type // Data type of the matrix
1159 , bool SO // Storage order
1160 , typename Alloc // Type of the allocator
1161 , typename Tag > // Type tag
1162 inline typename DynamicMatrix<Type,SO,Alloc,Tag>::Pointer
data()1163 DynamicMatrix<Type,SO,Alloc,Tag>::data() noexcept
1164 {
1165 return v_;
1166 }
1167 //*************************************************************************************************
1168
1169
1170 //*************************************************************************************************
1171 /*!\brief Low-level data access to the matrix elements.
1172 //
1173 // \return Pointer to the internal element storage.
1174 //
1175 // This function returns a pointer to the internal storage of the dynamic matrix. Note that you
1176 // can NOT assume that all matrix elements lie adjacent to each other! The dynamic matrix may
1177 // use techniques such as padding to improve the alignment of the data. Whereas the number of
1178 // elements within a row/column are given by the \c rows() and \c columns() member functions,
1179 // respectively, the total number of elements including padding is given by the \c spacing()
1180 // member function.
1181 */
1182 template< typename Type // Data type of the matrix
1183 , bool SO // Storage order
1184 , typename Alloc // Type of the allocator
1185 , typename Tag > // Type tag
1186 inline typename DynamicMatrix<Type,SO,Alloc,Tag>::ConstPointer
data()1187 DynamicMatrix<Type,SO,Alloc,Tag>::data() const noexcept
1188 {
1189 return v_;
1190 }
1191 //*************************************************************************************************
1192
1193
1194 //*************************************************************************************************
1195 /*!\brief Low-level data access to the matrix elements of row/column \a i.
1196 //
1197 // \param i The row/column index.
1198 // \return Pointer to the internal element storage.
1199 //
1200 // This function returns a pointer to the internal storage for the elements in row/column \a i.
1201 */
1202 template< typename Type // Data type of the matrix
1203 , bool SO // Storage order
1204 , typename Alloc // Type of the allocator
1205 , typename Tag > // Type tag
1206 inline typename DynamicMatrix<Type,SO,Alloc,Tag>::Pointer
data(size_t i)1207 DynamicMatrix<Type,SO,Alloc,Tag>::data( size_t i ) noexcept
1208 {
1209 BLAZE_USER_ASSERT( i < m_, "Invalid dense matrix row access index" );
1210 return v_ + i*nn_;
1211 }
1212 //*************************************************************************************************
1213
1214
1215 //*************************************************************************************************
1216 /*!\brief Low-level data access to the matrix elements of row/column \a i.
1217 //
1218 // \param i The row/column index.
1219 // \return Pointer to the internal element storage.
1220 //
1221 // This function returns a pointer to the internal storage for the elements in row/column \a i.
1222 */
1223 template< typename Type // Data type of the matrix
1224 , bool SO // Storage order
1225 , typename Alloc // Type of the allocator
1226 , typename Tag > // Type tag
1227 inline typename DynamicMatrix<Type,SO,Alloc,Tag>::ConstPointer
data(size_t i)1228 DynamicMatrix<Type,SO,Alloc,Tag>::data( size_t i ) const noexcept
1229 {
1230 BLAZE_USER_ASSERT( i < m_, "Invalid dense matrix row access index" );
1231 return v_ + i*nn_;
1232 }
1233 //*************************************************************************************************
1234
1235
1236 //*************************************************************************************************
1237 /*!\brief Returns an iterator to the first element of row/column \a i.
1238 //
1239 // \param i The row/column index.
1240 // \return Iterator to the first element of row/column \a i.
1241 //
1242 // This function returns a row/column iterator to the first element of row/column \a i. In case
1243 // the storage order is set to \a rowMajor the function returns an iterator to the first element
1244 // of row \a i, in case the storage flag is set to \a columnMajor the function returns an iterator
1245 // to the first element of column \a i.
1246 */
1247 template< typename Type // Data type of the matrix
1248 , bool SO // Storage order
1249 , typename Alloc // Type of the allocator
1250 , typename Tag > // Type tag
1251 inline typename DynamicMatrix<Type,SO,Alloc,Tag>::Iterator
begin(size_t i)1252 DynamicMatrix<Type,SO,Alloc,Tag>::begin( size_t i ) noexcept
1253 {
1254 BLAZE_USER_ASSERT( i < m_, "Invalid dense matrix row access index" );
1255 return Iterator( v_ + i*nn_ );
1256 }
1257 //*************************************************************************************************
1258
1259
1260 //*************************************************************************************************
1261 /*!\brief Returns an iterator to the first element of row/column \a i.
1262 //
1263 // \param i The row/column index.
1264 // \return Iterator to the first element of row/column \a i.
1265 //
1266 // This function returns a row/column iterator to the first element of row/column \a i. In case
1267 // the storage order is set to \a rowMajor the function returns an iterator to the first element
1268 // of row \a i, in case the storage flag is set to \a columnMajor the function returns an iterator
1269 // to the first element of column \a i.
1270 */
1271 template< typename Type // Data type of the matrix
1272 , bool SO // Storage order
1273 , typename Alloc // Type of the allocator
1274 , typename Tag > // Type tag
1275 inline typename DynamicMatrix<Type,SO,Alloc,Tag>::ConstIterator
begin(size_t i)1276 DynamicMatrix<Type,SO,Alloc,Tag>::begin( size_t i ) const noexcept
1277 {
1278 BLAZE_USER_ASSERT( i < m_, "Invalid dense matrix row access index" );
1279 return ConstIterator( v_ + i*nn_ );
1280 }
1281 //*************************************************************************************************
1282
1283
1284 //*************************************************************************************************
1285 /*!\brief Returns an iterator to the first element of row/column \a i.
1286 //
1287 // \param i The row/column index.
1288 // \return Iterator to the first element of row/column \a i.
1289 //
1290 // This function returns a row/column iterator to the first element of row/column \a i. In case
1291 // the storage order is set to \a rowMajor the function returns an iterator to the first element
1292 // of row \a i, in case the storage flag is set to \a columnMajor the function returns an iterator
1293 // to the first element of column \a i.
1294 */
1295 template< typename Type // Data type of the matrix
1296 , bool SO // Storage order
1297 , typename Alloc // Type of the allocator
1298 , typename Tag > // Type tag
1299 inline typename DynamicMatrix<Type,SO,Alloc,Tag>::ConstIterator
cbegin(size_t i)1300 DynamicMatrix<Type,SO,Alloc,Tag>::cbegin( size_t i ) const noexcept
1301 {
1302 BLAZE_USER_ASSERT( i < m_, "Invalid dense matrix row access index" );
1303 return ConstIterator( v_ + i*nn_ );
1304 }
1305 //*************************************************************************************************
1306
1307
1308 //*************************************************************************************************
1309 /*!\brief Returns an iterator just past the last element of row/column \a i.
1310 //
1311 // \param i The row/column index.
1312 // \return Iterator just past the last element of row/column \a i.
1313 //
1314 // This function returns an row/column iterator just past the last element of row/column \a i.
1315 // In case the storage order is set to \a rowMajor the function returns an iterator just past
1316 // the last element of row \a i, in case the storage flag is set to \a columnMajor the function
1317 // returns an iterator just past the last element of column \a i.
1318 */
1319 template< typename Type // Data type of the matrix
1320 , bool SO // Storage order
1321 , typename Alloc // Type of the allocator
1322 , typename Tag > // Type tag
1323 inline typename DynamicMatrix<Type,SO,Alloc,Tag>::Iterator
end(size_t i)1324 DynamicMatrix<Type,SO,Alloc,Tag>::end( size_t i ) noexcept
1325 {
1326 BLAZE_USER_ASSERT( i < m_, "Invalid dense matrix row access index" );
1327 return Iterator( v_ + i*nn_ + n_ );
1328 }
1329 //*************************************************************************************************
1330
1331
1332 //*************************************************************************************************
1333 /*!\brief Returns an iterator just past the last element of row/column \a i.
1334 //
1335 // \param i The row/column index.
1336 // \return Iterator just past the last element of row/column \a i.
1337 //
1338 // This function returns an row/column iterator just past the last element of row/column \a i.
1339 // In case the storage order is set to \a rowMajor the function returns an iterator just past
1340 // the last element of row \a i, in case the storage flag is set to \a columnMajor the function
1341 // returns an iterator just past the last element of column \a i.
1342 */
1343 template< typename Type // Data type of the matrix
1344 , bool SO // Storage order
1345 , typename Alloc // Type of the allocator
1346 , typename Tag > // Type tag
1347 inline typename DynamicMatrix<Type,SO,Alloc,Tag>::ConstIterator
end(size_t i)1348 DynamicMatrix<Type,SO,Alloc,Tag>::end( size_t i ) const noexcept
1349 {
1350 BLAZE_USER_ASSERT( i < m_, "Invalid dense matrix row access index" );
1351 return ConstIterator( v_ + i*nn_ + n_ );
1352 }
1353 //*************************************************************************************************
1354
1355
1356 //*************************************************************************************************
1357 /*!\brief Returns an iterator just past the last element of row/column \a i.
1358 //
1359 // \param i The row/column index.
1360 // \return Iterator just past the last element of row/column \a i.
1361 //
1362 // This function returns an row/column iterator just past the last element of row/column \a i.
1363 // In case the storage order is set to \a rowMajor the function returns an iterator just past
1364 // the last element of row \a i, in case the storage flag is set to \a columnMajor the function
1365 // returns an iterator just past the last element of column \a i.
1366 */
1367 template< typename Type // Data type of the matrix
1368 , bool SO // Storage order
1369 , typename Alloc // Type of the allocator
1370 , typename Tag > // Type tag
1371 inline typename DynamicMatrix<Type,SO,Alloc,Tag>::ConstIterator
cend(size_t i)1372 DynamicMatrix<Type,SO,Alloc,Tag>::cend( size_t i ) const noexcept
1373 {
1374 BLAZE_USER_ASSERT( i < m_, "Invalid dense matrix row access index" );
1375 return ConstIterator( v_ + i*nn_ + n_ );
1376 }
1377 //*************************************************************************************************
1378
1379
1380
1381
1382 //=================================================================================================
1383 //
1384 // ASSIGNMENT OPERATORS
1385 //
1386 //=================================================================================================
1387
1388 //*************************************************************************************************
1389 /*!\brief Homogenous assignment to all matrix elements.
1390 //
1391 // \param rhs Scalar value to be assigned to all matrix elements.
1392 // \return Reference to the assigned matrix.
1393 */
1394 template< typename Type // Data type of the matrix
1395 , bool SO // Storage order
1396 , typename Alloc // Type of the allocator
1397 , typename Tag > // Type tag
1398 inline DynamicMatrix<Type,SO,Alloc,Tag>&
1399 DynamicMatrix<Type,SO,Alloc,Tag>::operator=( const Type& rhs ) &
1400 {
1401 for( size_t i=0UL; i<m_; ++i )
1402 for( size_t j=0UL; j<n_; ++j )
1403 v_[i*nn_+j] = rhs;
1404
1405 return *this;
1406 }
1407 //*************************************************************************************************
1408
1409
1410 //*************************************************************************************************
1411 /*!\brief List assignment to all matrix elements.
1412 //
1413 // \param list The initializer list.
1414 //
1415 // This assignment operator offers the option to directly assign to all elements of the matrix
1416 // by means of an initializer list:
1417
1418 \code
1419 using blaze::rowMajor;
1420
1421 blaze::DynamicMatrix<int,rowMajor> A;
1422 A = { { 1, 2, 3 },
1423 { 4, 5 },
1424 { 7, 8, 9 } };
1425 \endcode
1426
1427 // The matrix is resized according to the given initializer list and all its elements are
1428 // (copy) assigned the values from the given initializer list. Missing values are initialized
1429 // as default (as e.g. the value 6 in the example).
1430 */
1431 template< typename Type // Data type of the matrix
1432 , bool SO // Storage order
1433 , typename Alloc // Type of the allocator
1434 , typename Tag > // Type tag
1435 inline DynamicMatrix<Type,SO,Alloc,Tag>&
1436 DynamicMatrix<Type,SO,Alloc,Tag>::operator=( initializer_list< initializer_list<Type> > list ) &
1437 {
1438 resize( list.size(), determineColumns( list ), false );
1439
1440 size_t i( 0UL );
1441
1442 for( const auto& rowList : list ) {
1443 std::fill( std::copy( rowList.begin(), rowList.end(), v_+i*nn_ ), v_+(i+1UL)*nn_, Type() );
1444 ++i;
1445 }
1446
1447 return *this;
1448 }
1449 //*************************************************************************************************
1450
1451
1452 //*************************************************************************************************
1453 /*!\brief Array assignment to all matrix elements.
1454 //
1455 // \param array Static array for the assignment.
1456 // \return Reference to the assigned matrix.
1457 //
1458 // This assignment operator offers the option to directly set all elements of the matrix:
1459
1460 \code
1461 using blaze::rowMajor;
1462
1463 const int init[3][3] = { { 1, 2, 3 },
1464 { 4, 5 },
1465 { 7, 8, 9 } };
1466 blaze::DynamicMatrix<int,rowMajor> A;
1467 A = init;
1468 \endcode
1469
1470 // The matrix is resized according to the size of the static array and assigned the values of the
1471 // given static array. Missing values are initialized with default values (as e.g. the value 6 in
1472 // the example).
1473 */
1474 template< typename Type // Data type of the matrix
1475 , bool SO // Storage order
1476 , typename Alloc // Type of the allocator
1477 , typename Tag > // Type tag
1478 template< typename Other // Data type of the static array
1479 , size_t Rows // Number of rows of the static array
1480 , size_t Cols > // Number of columns of the static array
1481 inline DynamicMatrix<Type,SO,Alloc,Tag>&
1482 DynamicMatrix<Type,SO,Alloc,Tag>::operator=( const Other (&array)[Rows][Cols] ) &
1483 {
1484 resize( Rows, Cols, false );
1485
1486 for( size_t i=0UL; i<Rows; ++i )
1487 for( size_t j=0UL; j<Cols; ++j )
1488 v_[i*nn_+j] = array[i][j];
1489
1490 return *this;
1491 }
1492 //*************************************************************************************************
1493
1494
1495 //*************************************************************************************************
1496 /*!\brief Array assignment to all matrix elements.
1497 //
1498 // \param array The given std::array for the assignment.
1499 // \return Reference to the assigned matrix.
1500 //
1501 // This assignment operator offers the option to directly set all elements of the matrix:
1502
1503 \code
1504 using blaze::rowMajor;
1505
1506 const std::array<std::array<int,3UL>,3UL> init{ { { 1, 2, 3 },
1507 { 4, 5 },
1508 { 7, 8, 9 } } };
1509 blaze::DynamicMatrix<int,rowMajor> A;
1510 A = init;
1511 \endcode
1512
1513 // The matrix is resized according to the size of the std::array and assigned the values of the
1514 // given std::array. Missing values are initialized with default values (as e.g. the value 6 in
1515 // the example).
1516 */
1517 template< typename Type // Data type of the matrix
1518 , bool SO // Storage order
1519 , typename Alloc // Type of the allocator
1520 , typename Tag > // Type tag
1521 template< typename Other // Data type of the std::array
1522 , size_t Rows // Number of rows of the std::array
1523 , size_t Cols > // Number of columns of the std::array
1524 inline DynamicMatrix<Type,SO,Alloc,Tag>&
1525 DynamicMatrix<Type,SO,Alloc,Tag>::operator=( const std::array<std::array<Other,Cols>,Rows>& array ) &
1526 {
1527 resize( Rows, Cols, false );
1528
1529 for( size_t i=0UL; i<Rows; ++i )
1530 for( size_t j=0UL; j<Cols; ++j )
1531 v_[i*nn_+j] = array[i][j];
1532
1533 return *this;
1534 }
1535 //*************************************************************************************************
1536
1537
1538 //*************************************************************************************************
1539 /*!\brief Copy assignment operator for DynamicMatrix.
1540 //
1541 // \param rhs Matrix to be copied.
1542 // \return Reference to the assigned matrix.
1543 //
1544 // The matrix is resized according to the given \f$ M \times N \f$ matrix and initialized as a
1545 // copy of this matrix.
1546 */
1547 template< typename Type // Data type of the matrix
1548 , bool SO // Storage order
1549 , typename Alloc // Type of the allocator
1550 , typename Tag > // Type tag
1551 inline DynamicMatrix<Type,SO,Alloc,Tag>&
1552 DynamicMatrix<Type,SO,Alloc,Tag>::operator=( const DynamicMatrix& rhs ) &
1553 {
1554 if( &rhs == this ) return *this;
1555
1556 resize( rhs.m_, rhs.n_, false );
1557 smpAssign( *this, *rhs );
1558
1559 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
1560
1561 return *this;
1562 }
1563 //*************************************************************************************************
1564
1565
1566 //*************************************************************************************************
1567 /*!\brief Move assignment operator for DynamicMatrix.
1568 //
1569 // \param rhs The matrix to be moved into this instance.
1570 // \return Reference to the assigned matrix.
1571 */
1572 template< typename Type // Data type of the matrix
1573 , bool SO // Storage order
1574 , typename Alloc // Type of the allocator
1575 , typename Tag > // Type tag
1576 inline DynamicMatrix<Type,SO,Alloc,Tag>&
1577 DynamicMatrix<Type,SO,Alloc,Tag>::operator=( DynamicMatrix&& rhs ) & noexcept
1578 {
1579 blaze::destroy_n( v_, capacity_ );
1580 alloc_.deallocate( v_, capacity_ );
1581
1582 m_ = rhs.m_;
1583 n_ = rhs.n_;
1584 nn_ = rhs.nn_;
1585 capacity_ = rhs.capacity_;
1586 v_ = rhs.v_;
1587
1588 rhs.m_ = 0UL;
1589 rhs.n_ = 0UL;
1590 rhs.nn_ = 0UL;
1591 rhs.capacity_ = 0UL;
1592 rhs.v_ = nullptr;
1593
1594 return *this;
1595 }
1596 //*************************************************************************************************
1597
1598
1599 //*************************************************************************************************
1600 /*!\brief Assignment operator for different matrices.
1601 //
1602 // \param rhs Matrix to be copied.
1603 // \return Reference to the assigned matrix.
1604 //
1605 // The matrix is resized according to the given \f$ M \times N \f$ matrix and initialized as a
1606 // copy of this matrix.
1607 */
1608 template< typename Type // Data type of the matrix
1609 , bool SO // Storage order
1610 , typename Alloc // Type of the allocator
1611 , typename Tag > // Type tag
1612 template< typename MT // Type of the right-hand side matrix
1613 , bool SO2 > // Storage order of the right-hand side matrix
1614 inline DynamicMatrix<Type,SO,Alloc,Tag>&
1615 DynamicMatrix<Type,SO,Alloc,Tag>::operator=( const Matrix<MT,SO2>& rhs ) &
1616 {
1617 using TT = decltype( trans( *this ) );
1618 using CT = decltype( ctrans( *this ) );
1619 using IT = decltype( inv( *this ) );
1620
1621 BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<MT> );
1622
1623 if( IsSame_v<MT,TT> && (*rhs).isAliased( this ) ) {
1624 transpose();
1625 }
1626 else if( IsSame_v<MT,CT> && (*rhs).isAliased( this ) ) {
1627 ctranspose();
1628 }
1629 else if( !IsSame_v<MT,IT> && (*rhs).canAlias( this ) ) {
1630 DynamicMatrix tmp( *rhs );
1631 swap( tmp );
1632 }
1633 else {
1634 resize( (*rhs).rows(), (*rhs).columns(), false );
1635 if( IsSparseMatrix_v<MT> )
1636 reset();
1637 smpAssign( *this, *rhs );
1638 }
1639
1640 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
1641
1642 return *this;
1643 }
1644 //*************************************************************************************************
1645
1646
1647 //*************************************************************************************************
1648 /*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
1649 //
1650 // \param rhs The right-hand side matrix to be added to the matrix.
1651 // \return Reference to the matrix.
1652 // \exception std::invalid_argument Matrix sizes do not match.
1653 //
1654 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
1655 // is thrown.
1656 */
1657 template< typename Type // Data type of the matrix
1658 , bool SO // Storage order
1659 , typename Alloc // Type of the allocator
1660 , typename Tag > // Type tag
1661 template< typename MT // Type of the right-hand side matrix
1662 , bool SO2 > // Storage order of the right-hand side matrix
1663 inline DynamicMatrix<Type,SO,Alloc,Tag>&
1664 DynamicMatrix<Type,SO,Alloc,Tag>::operator+=( const Matrix<MT,SO2>& rhs ) &
1665 {
1666 BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<MT> );
1667
1668 if( (*rhs).rows() != m_ || (*rhs).columns() != n_ ) {
1669 BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1670 }
1671
1672 if( (*rhs).canAlias( this ) ) {
1673 const ResultType_t<MT> tmp( *rhs );
1674 smpAddAssign( *this, tmp );
1675 }
1676 else {
1677 smpAddAssign( *this, *rhs );
1678 }
1679
1680 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
1681
1682 return *this;
1683 }
1684 //*************************************************************************************************
1685
1686
1687 //*************************************************************************************************
1688 /*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
1689 //
1690 // \param rhs The right-hand side matrix to be subtracted from the matrix.
1691 // \return Reference to the matrix.
1692 // \exception std::invalid_argument Matrix sizes do not match.
1693 //
1694 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
1695 // is thrown.
1696 */
1697 template< typename Type // Data type of the matrix
1698 , bool SO // Storage order
1699 , typename Alloc // Type of the allocator
1700 , typename Tag > // Type tag
1701 template< typename MT // Type of the right-hand side matrix
1702 , bool SO2 > // Storage order of the right-hand side matrix
1703 inline DynamicMatrix<Type,SO,Alloc,Tag>&
1704 DynamicMatrix<Type,SO,Alloc,Tag>::operator-=( const Matrix<MT,SO2>& rhs ) &
1705 {
1706 BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<MT> );
1707
1708 if( (*rhs).rows() != m_ || (*rhs).columns() != n_ ) {
1709 BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1710 }
1711
1712 if( (*rhs).canAlias( this ) ) {
1713 const ResultType_t<MT> tmp( *rhs );
1714 smpSubAssign( *this, tmp );
1715 }
1716 else {
1717 smpSubAssign( *this, *rhs );
1718 }
1719
1720 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
1721
1722 return *this;
1723 }
1724 //*************************************************************************************************
1725
1726
1727 //*************************************************************************************************
1728 /*!\brief Schur product assignment operator for the multiplication of a matrix (\f$ A\circ=B \f$).
1729 //
1730 // \param rhs The right-hand side matrix for the Schur product.
1731 // \return Reference to the matrix.
1732 // \exception std::invalid_argument Matrix sizes do not match.
1733 //
1734 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
1735 // is thrown.
1736 */
1737 template< typename Type // Data type of the matrix
1738 , bool SO // Storage order
1739 , typename Alloc // Type of the allocator
1740 , typename Tag > // Type tag
1741 template< typename MT // Type of the right-hand side matrix
1742 , bool SO2 > // Storage order of the right-hand side matrix
1743 inline DynamicMatrix<Type,SO,Alloc,Tag>&
1744 DynamicMatrix<Type,SO,Alloc,Tag>::operator%=( const Matrix<MT,SO2>& rhs ) &
1745 {
1746 BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<MT> );
1747
1748 if( (*rhs).rows() != m_ || (*rhs).columns() != n_ ) {
1749 BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
1750 }
1751
1752 if( (*rhs).canAlias( this ) ) {
1753 const ResultType_t<MT> tmp( *rhs );
1754 smpSchurAssign( *this, tmp );
1755 }
1756 else {
1757 smpSchurAssign( *this, *rhs );
1758 }
1759
1760 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
1761
1762 return *this;
1763 }
1764 //*************************************************************************************************
1765
1766
1767
1768
1769 //=================================================================================================
1770 //
1771 // UTILITY FUNCTIONS
1772 //
1773 //=================================================================================================
1774
1775 //*************************************************************************************************
1776 /*!\brief Returns the current number of rows of the matrix.
1777 //
1778 // \return The number of rows of the matrix.
1779 */
1780 template< typename Type // Data type of the matrix
1781 , bool SO // Storage order
1782 , typename Alloc // Type of the allocator
1783 , typename Tag > // Type tag
rows()1784 inline size_t DynamicMatrix<Type,SO,Alloc,Tag>::rows() const noexcept
1785 {
1786 return m_;
1787 }
1788 //*************************************************************************************************
1789
1790
1791 //*************************************************************************************************
1792 /*!\brief Returns the current number of columns of the matrix.
1793 //
1794 // \return The number of columns of the matrix.
1795 */
1796 template< typename Type // Data type of the matrix
1797 , bool SO // Storage order
1798 , typename Alloc // Type of the allocator
1799 , typename Tag > // Type tag
columns()1800 inline size_t DynamicMatrix<Type,SO,Alloc,Tag>::columns() const noexcept
1801 {
1802 return n_;
1803 }
1804 //*************************************************************************************************
1805
1806
1807 //*************************************************************************************************
1808 /*!\brief Returns the spacing between the beginning of two rows/columns.
1809 //
1810 // \return The spacing between the beginning of two rows/columns.
1811 //
1812 // This function returns the spacing between the beginning of two rows/columns, i.e. the
1813 // total number of elements of a row/column. In case the storage order is set to \a rowMajor
1814 // the function returns the spacing between two rows, in case the storage flag is set to
1815 // \a columnMajor the function returns the spacing between two columns.
1816 */
1817 template< typename Type // Data type of the matrix
1818 , bool SO // Storage order
1819 , typename Alloc // Type of the allocator
1820 , typename Tag > // Type tag
spacing()1821 inline size_t DynamicMatrix<Type,SO,Alloc,Tag>::spacing() const noexcept
1822 {
1823 return nn_;
1824 }
1825 //*************************************************************************************************
1826
1827
1828 //*************************************************************************************************
1829 /*!\brief Returns the maximum capacity of the matrix.
1830 //
1831 // \return The capacity of the matrix.
1832 */
1833 template< typename Type // Data type of the matrix
1834 , bool SO // Storage order
1835 , typename Alloc // Type of the allocator
1836 , typename Tag > // Type tag
capacity()1837 inline size_t DynamicMatrix<Type,SO,Alloc,Tag>::capacity() const noexcept
1838 {
1839 return capacity_;
1840 }
1841 //*************************************************************************************************
1842
1843
1844 //*************************************************************************************************
1845 /*!\brief Returns the current capacity of the specified row/column.
1846 //
1847 // \param i The index of the row/column.
1848 // \return The current capacity of row/column \a i.
1849 //
1850 // This function returns the current capacity of the specified row/column. In case the
1851 // storage order is set to \a rowMajor the function returns the capacity of row \a i,
1852 // in case the storage flag is set to \a columnMajor the function returns the capacity
1853 // of column \a i.
1854 */
1855 template< typename Type // Data type of the matrix
1856 , bool SO // Storage order
1857 , typename Alloc // Type of the allocator
1858 , typename Tag > // Type tag
capacity(size_t i)1859 inline size_t DynamicMatrix<Type,SO,Alloc,Tag>::capacity( size_t i ) const noexcept
1860 {
1861 MAYBE_UNUSED( i );
1862 BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
1863 return nn_;
1864 }
1865 //*************************************************************************************************
1866
1867
1868 //*************************************************************************************************
1869 /*!\brief Returns the total number of non-zero elements in the matrix
1870 //
1871 // \return The number of non-zero elements in the dense matrix.
1872 //
1873 // This function returns the number of non-zero elements in the matrix (i.e. the elements that
1874 // compare unequal to their default value). Note that the number of non-zero elements is always
1875 // less than or equal to the total number of elements in the matrix.
1876 */
1877 template< typename Type // Data type of the matrix
1878 , bool SO // Storage order
1879 , typename Alloc // Type of the allocator
1880 , typename Tag > // Type tag
nonZeros()1881 inline size_t DynamicMatrix<Type,SO,Alloc,Tag>::nonZeros() const
1882 {
1883 size_t nonzeros( 0UL );
1884
1885 for( size_t i=0UL; i<m_; ++i )
1886 for( size_t j=0UL; j<n_; ++j )
1887 if( !isDefault<strict>( v_[i*nn_+j] ) )
1888 ++nonzeros;
1889
1890 return nonzeros;
1891 }
1892 //*************************************************************************************************
1893
1894
1895 //*************************************************************************************************
1896 /*!\brief Returns the number of non-zero elements in the specified row/column.
1897 //
1898 // \param i The index of the row/column.
1899 // \return The number of non-zero elements of row/column \a i.
1900 //
1901 // This function returns the current number of non-zero elements in the specified row/column
1902 // (i.e. the elements that compare unequal to their default value). In case the storage order
1903 // is set to \a rowMajor the function returns the number of non-zero elements in row \a i, in
1904 // case the storage flag is set to \a columnMajor the function returns the number of non-zero
1905 // elements in column \a i.
1906 */
1907 template< typename Type // Data type of the matrix
1908 , bool SO // Storage order
1909 , typename Alloc // Type of the allocator
1910 , typename Tag > // Type tag
nonZeros(size_t i)1911 inline size_t DynamicMatrix<Type,SO,Alloc,Tag>::nonZeros( size_t i ) const
1912 {
1913 BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
1914
1915 const size_t jend( i*nn_ + n_ );
1916 size_t nonzeros( 0UL );
1917
1918 for( size_t j=i*nn_; j<jend; ++j )
1919 if( !isDefault<strict>( v_[j] ) )
1920 ++nonzeros;
1921
1922 return nonzeros;
1923 }
1924 //*************************************************************************************************
1925
1926
1927 //*************************************************************************************************
1928 /*!\brief Reset to the default initial values.
1929 //
1930 // \return void
1931 */
1932 template< typename Type // Data type of the matrix
1933 , bool SO // Storage order
1934 , typename Alloc // Type of the allocator
1935 , typename Tag > // Type tag
reset()1936 inline void DynamicMatrix<Type,SO,Alloc,Tag>::reset()
1937 {
1938 using blaze::clear;
1939
1940 for( size_t i=0UL; i<m_; ++i )
1941 for( size_t j=0UL; j<n_; ++j )
1942 clear( v_[i*nn_+j] );
1943 }
1944 //*************************************************************************************************
1945
1946
1947 //*************************************************************************************************
1948 /*!\brief Reset the specified row/column to the default initial values.
1949 //
1950 // \param i The index of the row/column.
1951 // \return void
1952 //
1953 // This function resets the values in the specified row/column to their default value. In case
1954 // the storage order is set to \a rowMajor the function resets the values in row \a i, in case
1955 // the storage order is set to \a columnMajor the function resets the values in column \a i.
1956 // Note that the capacity of the row/column remains unchanged.
1957 */
1958 template< typename Type // Data type of the matrix
1959 , bool SO // Storage order
1960 , typename Alloc // Type of the allocator
1961 , typename Tag > // Type tag
reset(size_t i)1962 inline void DynamicMatrix<Type,SO,Alloc,Tag>::reset( size_t i )
1963 {
1964 using blaze::clear;
1965
1966 BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" );
1967 for( size_t j=0UL; j<n_; ++j )
1968 clear( v_[i*nn_+j] );
1969 }
1970 //*************************************************************************************************
1971
1972
1973 //*************************************************************************************************
1974 /*!\brief Clearing the \f$ M \times N \f$ matrix.
1975 //
1976 // \return void
1977 //
1978 // After the clear() function, the size of the matrix is 0.
1979 */
1980 template< typename Type // Data type of the matrix
1981 , bool SO // Storage order
1982 , typename Alloc // Type of the allocator
1983 , typename Tag > // Type tag
clear()1984 inline void DynamicMatrix<Type,SO,Alloc,Tag>::clear()
1985 {
1986 resize( 0UL, 0UL, false );
1987 }
1988 //*************************************************************************************************
1989
1990
1991 //*************************************************************************************************
1992 /*!\brief Changing the size of the matrix.
1993 //
1994 // \param m The new number of rows of the matrix.
1995 // \param n The new number of columns of the matrix.
1996 // \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
1997 // \return void
1998 //
1999 // This function resizes the matrix using the given size to \f$ m \times n \f$. During this
2000 // operation, new dynamic memory may be allocated in case the capacity of the matrix is too
2001 // small. Note that this function may invalidate all existing views (submatrices, rows, columns,
2002 // ...) on the matrix if it is used to shrink the matrix. Additionally, the resize operation
2003 // potentially changes all matrix elements. In order to preserve the old matrix values, the
2004 // \a preserve flag can be set to \a true. However, new matrix elements of built-in type are
2005 // not initialized!
2006 //
2007 // The following example illustrates the resize operation of a \f$ 2 \times 4 \f$ matrix to a
2008 // \f$ 4 \times 2 \f$ matrix. The new, uninitialized elements are marked with \a x:
2009
2010 \f[
2011 \left(\begin{array}{*{4}{c}}
2012 1 & 2 & 3 & 4 \\
2013 5 & 6 & 7 & 8 \\
2014 \end{array}\right)
2015
2016 \Longrightarrow
2017
2018 \left(\begin{array}{*{2}{c}}
2019 1 & 2 \\
2020 5 & 6 \\
2021 x & x \\
2022 x & x \\
2023 \end{array}\right)
2024 \f]
2025 */
2026 template< typename Type // Data type of the matrix
2027 , bool SO // Storage order
2028 , typename Alloc // Type of the allocator
2029 , typename Tag > // Type tag
resize(size_t m,size_t n,bool preserve)2030 void DynamicMatrix<Type,SO,Alloc,Tag>::resize( size_t m, size_t n, bool preserve )
2031 {
2032 using blaze::clear;
2033 using blaze::min;
2034
2035 if( m == m_ && n == n_ ) return;
2036
2037 const size_t nn( addPadding( n ) );
2038
2039 if( preserve )
2040 {
2041 const size_t min_m( min( m, m_ ) );
2042 const size_t min_n( min( n, n_ ) );
2043
2044 DynamicMatrix tmp( m, n, nn, Alloc{}, Uninitialized{} );
2045
2046 for( size_t i=0UL; i<min_m; ++i ) {
2047 blaze::uninitialized_transfer( v_+i*nn_, v_+i*nn_+min_n, tmp.v_+i*nn );
2048 blaze::uninitialized_default_construct( tmp.v_+i*nn+min_n, tmp.v_+i*nn+nn );
2049 }
2050 blaze::uninitialized_default_construct( tmp.v_+min_m*nn, tmp.v_+m*nn );
2051
2052 std::swap( capacity_, tmp.capacity_ );
2053 std::swap( v_, tmp.v_ );
2054 }
2055 else if( m*nn > capacity_ )
2056 {
2057 DynamicMatrix tmp( m, n, nn, Alloc{}, Uninitialized{} );
2058
2059 blaze::uninitialized_default_construct( tmp.v_, tmp.v_+tmp.capacity_ );
2060
2061 std::swap( capacity_, tmp.capacity_ );
2062 std::swap( v_, tmp.v_ );
2063 }
2064
2065 if( IsVectorizable_v<Type> ) {
2066 for( size_t i=0UL; i<m; ++i )
2067 for( size_t j=n; j<nn; ++j )
2068 clear( v_[i*nn+j] );
2069 }
2070
2071 m_ = m;
2072 n_ = n;
2073 nn_ = nn;
2074
2075 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
2076 }
2077 //*************************************************************************************************
2078
2079
2080 //*************************************************************************************************
2081 /*!\brief Extending the size of the matrix.
2082 //
2083 // \param m Number of additional rows.
2084 // \param n Number of additional columns.
2085 // \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
2086 // \return void
2087 //
2088 // This function increases the matrix size by \a m rows and \a n columns. During this operation,
2089 // new dynamic memory may be allocated in case the capacity of the matrix is too small. Therefore
2090 // this function potentially changes all matrix elements. In order to preserve the old matrix
2091 // values, the \a preserve flag can be set to \a true. However, new matrix elements of built-in
2092 // type are not initialized!
2093 */
2094 template< typename Type // Data type of the matrix
2095 , bool SO // Storage order
2096 , typename Alloc // Type of the allocator
2097 , typename Tag > // Type tag
extend(size_t m,size_t n,bool preserve)2098 inline void DynamicMatrix<Type,SO,Alloc,Tag>::extend( size_t m, size_t n, bool preserve )
2099 {
2100 resize( m_+m, n_+n, preserve );
2101 }
2102 //*************************************************************************************************
2103
2104
2105 //*************************************************************************************************
2106 /*!\brief Setting the minimum capacity of the matrix.
2107 //
2108 // \param elements The new minimum capacity of the dense matrix.
2109 // \return void
2110 //
2111 // This function increases the capacity of the dense matrix to at least \a elements elements.
2112 // The current values of the matrix elements are preserved.
2113 */
2114 template< typename Type // Data type of the matrix
2115 , bool SO // Storage order
2116 , typename Alloc // Type of the allocator
2117 , typename Tag > // Type tag
reserve(size_t elements)2118 inline void DynamicMatrix<Type,SO,Alloc,Tag>::reserve( size_t elements )
2119 {
2120 using blaze::clear;
2121
2122 if( elements > capacity_ )
2123 {
2124 DynamicMatrix tmp( m_, n_, nn_, elements, Alloc{}, Uninitialized{} );
2125
2126 blaze::uninitialized_transfer( v_, v_+capacity_, tmp.v_ );
2127 blaze::uninitialized_value_construct( tmp.v_+capacity_, tmp.v_+elements );
2128
2129 std::swap( capacity_, tmp.capacity_ );
2130 std::swap( v_, tmp.v_ );
2131 }
2132 }
2133 //*************************************************************************************************
2134
2135
2136 //*************************************************************************************************
2137 /*!\brief Requesting the removal of unused capacity.
2138 //
2139 // \return void
2140 //
2141 // This function minimizes the capacity of the matrix by removing unused capacity. Please note
2142 // that due to padding the capacity might not be reduced exactly to rows() times columns().
2143 // Please also note that in case a reallocation occurs, all iterators (including end() iterators),
2144 // all pointers and references to elements of this matrix are invalidated.
2145 */
2146 template< typename Type // Data type of the matrix
2147 , bool SO // Storage order
2148 , typename Alloc // Type of the allocator
2149 , typename Tag > // Type tag
shrinkToFit()2150 inline void DynamicMatrix<Type,SO,Alloc,Tag>::shrinkToFit()
2151 {
2152 if( ( m_ * nn_ ) < capacity_ ) {
2153 DynamicMatrix( *this ).swap( *this );
2154 }
2155 }
2156 //*************************************************************************************************
2157
2158
2159 //*************************************************************************************************
2160 /*!\brief Swapping the contents of two matrices.
2161 //
2162 // \param m The matrix to be swapped.
2163 // \return void
2164 */
2165 template< typename Type // Data type of the matrix
2166 , bool SO // Storage order
2167 , typename Alloc // Type of the allocator
2168 , typename Tag > // Type tag
swap(DynamicMatrix & m)2169 inline void DynamicMatrix<Type,SO,Alloc,Tag>::swap( DynamicMatrix& m ) noexcept
2170 {
2171 using std::swap;
2172
2173 swap( m_ , m.m_ );
2174 swap( n_ , m.n_ );
2175 swap( nn_, m.nn_ );
2176 swap( capacity_, m.capacity_ );
2177 swap( v_ , m.v_ );
2178 }
2179 //*************************************************************************************************
2180
2181
2182 //*************************************************************************************************
2183 /*!\brief Add the necessary amount of padding to the given value.
2184 //
2185 // \param value The value to be padded.
2186 // \return The padded value.
2187 //
2188 // This function increments the given \a value by the necessary amount of padding based on the
2189 // vector's data type \a Type.
2190 */
2191 template< typename Type // Data type of the matrix
2192 , bool SO // Storage order
2193 , typename Alloc // Type of the allocator
2194 , typename Tag > // Type tag
addPadding(size_t value)2195 inline size_t DynamicMatrix<Type,SO,Alloc,Tag>::addPadding( size_t value ) const noexcept
2196 {
2197 if( usePadding && IsVectorizable_v<Type> )
2198 return nextMultiple<size_t>( value, SIMDSIZE );
2199 else return value;
2200 }
2201 //*************************************************************************************************
2202
2203
2204
2205
2206 //=================================================================================================
2207 //
2208 // NUMERIC FUNCTIONS
2209 //
2210 //=================================================================================================
2211
2212 //*************************************************************************************************
2213 /*!\brief In-place transpose of the matrix.
2214 //
2215 // \return Reference to the transposed matrix.
2216 */
2217 template< typename Type // Data type of the matrix
2218 , bool SO // Storage order
2219 , typename Alloc // Type of the allocator
2220 , typename Tag > // Type tag
transpose()2221 inline DynamicMatrix<Type,SO,Alloc,Tag>& DynamicMatrix<Type,SO,Alloc,Tag>::transpose()
2222 {
2223 using std::swap;
2224
2225 constexpr size_t block( BLOCK_SIZE );
2226
2227 if( m_ == n_ )
2228 {
2229 for( size_t ii=0UL; ii<m_; ii+=block ) {
2230 const size_t iend( min( ii+block, m_ ) );
2231 for( size_t jj=0UL; jj<=ii; jj+=block ) {
2232 for( size_t i=ii; i<iend; ++i ) {
2233 const size_t jend( min( jj+block, n_, i ) );
2234 for( size_t j=jj; j<jend; ++j ) {
2235 swap( v_[i*nn_+j], v_[j*nn_+i] );
2236 }
2237 }
2238 }
2239 }
2240 }
2241 else
2242 {
2243 DynamicMatrix tmp( trans(*this) );
2244 this->swap( tmp );
2245 }
2246
2247 return *this;
2248 }
2249 //*************************************************************************************************
2250
2251
2252 //*************************************************************************************************
2253 /*!\brief In-place conjugate transpose of the matrix.
2254 //
2255 // \return Reference to the transposed matrix.
2256 */
2257 template< typename Type // Data type of the matrix
2258 , bool SO // Storage order
2259 , typename Alloc // Type of the allocator
2260 , typename Tag > // Type tag
ctranspose()2261 inline DynamicMatrix<Type,SO,Alloc,Tag>& DynamicMatrix<Type,SO,Alloc,Tag>::ctranspose()
2262 {
2263 constexpr size_t block( BLOCK_SIZE );
2264
2265 if( m_ == n_ )
2266 {
2267 for( size_t ii=0UL; ii<m_; ii+=block ) {
2268 const size_t iend( min( ii+block, m_ ) );
2269 for( size_t jj=0UL; jj<ii; jj+=block ) {
2270 const size_t jend( min( jj+block, n_ ) );
2271 for( size_t i=ii; i<iend; ++i ) {
2272 for( size_t j=jj; j<jend; ++j ) {
2273 cswap( v_[i*nn_+j], v_[j*nn_+i] );
2274 }
2275 }
2276 }
2277 for( size_t i=ii; i<iend; ++i ) {
2278 for( size_t j=ii; j<i; ++j ) {
2279 cswap( v_[i*nn_+j], v_[j*nn_+i] );
2280 }
2281 conjugate( v_[i*nn_+i] );
2282 }
2283 }
2284 }
2285 else
2286 {
2287 DynamicMatrix tmp( ctrans(*this) );
2288 swap( tmp );
2289 }
2290
2291 return *this;
2292 }
2293 //*************************************************************************************************
2294
2295
2296 //*************************************************************************************************
2297 /*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A=B*s \f$).
2298 //
2299 // \param scalar The scalar value for the matrix scaling.
2300 // \return Reference to the matrix.
2301 //
2302 // This function scales the matrix by applying the given scalar value \a scalar to each element
2303 // of the matrix. For built-in and \c complex data types it has the same effect as using the
2304 // multiplication assignment operator:
2305
2306 \code
2307 blaze::DynamicMatrix<int> A;
2308 // ... Resizing and initialization
2309 A *= 4; // Scaling of the matrix
2310 A.scale( 4 ); // Same effect as above
2311 \endcode
2312 */
2313 template< typename Type // Data type of the matrix
2314 , bool SO // Storage order
2315 , typename Alloc // Type of the allocator
2316 , typename Tag > // Type tag
2317 template< typename Other > // Data type of the scalar value
2318 inline DynamicMatrix<Type,SO,Alloc,Tag>&
scale(const Other & scalar)2319 DynamicMatrix<Type,SO,Alloc,Tag>::scale( const Other& scalar )
2320 {
2321 for( size_t i=0UL; i<m_; ++i )
2322 for( size_t j=0UL; j<n_; ++j )
2323 v_[i*nn_+j] *= scalar;
2324
2325 return *this;
2326 }
2327 //*************************************************************************************************
2328
2329
2330
2331
2332 //=================================================================================================
2333 //
2334 // DEBUGGING FUNCTIONS
2335 //
2336 //=================================================================================================
2337
2338 //*************************************************************************************************
2339 /*!\brief Returns whether the invariants of the dynamic matrix are intact.
2340 //
2341 // \return \a true in case the dynamic matrix's invariants are intact, \a false otherwise.
2342 //
2343 // This function checks whether the invariants of the dynamic matrix are intact, i.e. if its
2344 // state is valid. In case the invariants are intact, the function returns \a true, else it
2345 // will return \a false.
2346 */
2347 template< typename Type // Data type of the matrix
2348 , bool SO // Storage order
2349 , typename Alloc // Type of the allocator
2350 , typename Tag > // Type tag
isIntact()2351 inline bool DynamicMatrix<Type,SO,Alloc,Tag>::isIntact() const noexcept
2352 {
2353 if( n_ > nn_ || m_ * nn_ > capacity_ )
2354 return false;
2355
2356 if( IsVectorizable_v<Type> ) {
2357 for( size_t i=0UL; i<m_; ++i ) {
2358 for( size_t j=n_; j<nn_; ++j ) {
2359 if( !isDefault<strict>( v_[i*nn_+j] ) )
2360 return false;
2361 }
2362 }
2363 }
2364
2365 return true;
2366 }
2367 //*************************************************************************************************
2368
2369
2370
2371
2372 //=================================================================================================
2373 //
2374 // EXPRESSION TEMPLATE EVALUATION FUNCTIONS
2375 //
2376 //=================================================================================================
2377
2378 //*************************************************************************************************
2379 /*!\brief Returns whether the matrix can alias with the given address \a alias.
2380 //
2381 // \param alias The alias to be checked.
2382 // \return \a true in case the alias corresponds to this matrix, \a false if not.
2383 //
2384 // This function returns whether the given address can alias with the matrix. In contrast
2385 // to the isAliased() function this function is allowed to use compile time expressions
2386 // to optimize the evaluation.
2387 */
2388 template< typename Type // Data type of the matrix
2389 , bool SO // Storage order
2390 , typename Alloc // Type of the allocator
2391 , typename Tag > // Type tag
2392 template< typename Other > // Data type of the foreign expression
canAlias(const Other * alias)2393 inline bool DynamicMatrix<Type,SO,Alloc,Tag>::canAlias( const Other* alias ) const noexcept
2394 {
2395 return static_cast<const void*>( this ) == static_cast<const void*>( alias );
2396 }
2397 //*************************************************************************************************
2398
2399
2400 //*************************************************************************************************
2401 /*!\brief Returns whether the matrix is aliased with the given address \a alias.
2402 //
2403 // \param alias The alias to be checked.
2404 // \return \a true in case the alias corresponds to this matrix, \a false if not.
2405 //
2406 // This function returns whether the given address is aliased with the matrix. In contrast
2407 // to the canAlias() function this function is not allowed to use compile time expressions
2408 // to optimize the evaluation.
2409 */
2410 template< typename Type // Data type of the matrix
2411 , bool SO // Storage order
2412 , typename Alloc // Type of the allocator
2413 , typename Tag > // Type tag
2414 template< typename Other > // Data type of the foreign expression
isAliased(const Other * alias)2415 inline bool DynamicMatrix<Type,SO,Alloc,Tag>::isAliased( const Other* alias ) const noexcept
2416 {
2417 return static_cast<const void*>( this ) == static_cast<const void*>( alias );
2418 }
2419 //*************************************************************************************************
2420
2421
2422 //*************************************************************************************************
2423 /*!\brief Returns whether the matrix is properly aligned in memory.
2424 //
2425 // \return \a true in case the matrix is aligned, \a false if not.
2426 //
2427 // This function returns whether the matrix is guaranteed to be properly aligned in memory, i.e.
2428 // whether the beginning and the end of each row/column of the matrix are guaranteed to conform
2429 // to the alignment restrictions of the element type \a Type.
2430 */
2431 template< typename Type // Data type of the matrix
2432 , bool SO // Storage order
2433 , typename Alloc // Type of the allocator
2434 , typename Tag > // Type tag
isAligned()2435 inline bool DynamicMatrix<Type,SO,Alloc,Tag>::isAligned() const noexcept
2436 {
2437 return ( usePadding || columns() % SIMDSIZE == 0UL );
2438 }
2439 //*************************************************************************************************
2440
2441
2442 //*************************************************************************************************
2443 /*!\brief Returns whether the matrix can be used in SMP assignments.
2444 //
2445 // \return \a true in case the matrix can be used in SMP assignments, \a false if not.
2446 //
2447 // This function returns whether the matrix can be used in SMP assignments. In contrast to the
2448 // \a smpAssignable member enumeration, which is based solely on compile time information, this
2449 // function additionally provides runtime information (as for instance the current number of
2450 // rows and/or columns of the matrix).
2451 */
2452 template< typename Type // Data type of the matrix
2453 , bool SO // Storage order
2454 , typename Alloc // Type of the allocator
2455 , typename Tag > // Type tag
canSMPAssign()2456 inline bool DynamicMatrix<Type,SO,Alloc,Tag>::canSMPAssign() const noexcept
2457 {
2458 return ( rows() * columns() >= SMP_DMATASSIGN_THRESHOLD );
2459 }
2460 //*************************************************************************************************
2461
2462
2463 //*************************************************************************************************
2464 /*!\brief Load of a SIMD element of the matrix.
2465 //
2466 // \param i Access index for the row. The index has to be in the range [0..M-1].
2467 // \param j Access index for the column. The index has to be in the range [0..N-1].
2468 // \return The loaded SIMD element.
2469 //
2470 // This function performs a load of a specific SIMD element of the dense matrix. The row index
2471 // must be smaller than the number of rows and the column index must be smaller then the number
2472 // of columns. Additionally, the column index (in case of a row-major matrix) or the row index
2473 // (in case of a column-major matrix) must be a multiple of the number of values inside the
2474 // SIMD element. This function must \b NOT be called explicitly! It is used internally for the
2475 // performance optimized evaluation of expression templates. Calling this function explicitly
2476 // might result in erroneous results and/or in compilation errors.
2477 */
2478 template< typename Type // Data type of the matrix
2479 , bool SO // Storage order
2480 , typename Alloc // Type of the allocator
2481 , typename Tag > // Type tag
2482 BLAZE_ALWAYS_INLINE typename DynamicMatrix<Type,SO,Alloc,Tag>::SIMDType
load(size_t i,size_t j)2483 DynamicMatrix<Type,SO,Alloc,Tag>::load( size_t i, size_t j ) const noexcept
2484 {
2485 if( usePadding )
2486 return loada( i, j );
2487 else
2488 return loadu( i, j );
2489 }
2490 //*************************************************************************************************
2491
2492
2493 //*************************************************************************************************
2494 /*!\brief Aligned load of a SIMD element of the matrix.
2495 //
2496 // \param i Access index for the row. The index has to be in the range [0..M-1].
2497 // \param j Access index for the column. The index has to be in the range [0..N-1].
2498 // \return The loaded SIMD element.
2499 //
2500 // This function performs an aligned load of a specific SIMD element of the dense matrix.
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 Type // Data type of the matrix
2509 , bool SO // Storage order
2510 , typename Alloc // Type of the allocator
2511 , typename Tag > // Type tag
2512 BLAZE_ALWAYS_INLINE typename DynamicMatrix<Type,SO,Alloc,Tag>::SIMDType
loada(size_t i,size_t j)2513 DynamicMatrix<Type,SO,Alloc,Tag>::loada( size_t i, size_t j ) const noexcept
2514 {
2515 using blaze::loada;
2516
2517 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2518
2519 BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
2520 BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
2521 BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= nn_, "Invalid column access index" );
2522 BLAZE_INTERNAL_ASSERT( !usePadding || j % SIMDSIZE == 0UL, "Invalid column access index" );
2523 BLAZE_INTERNAL_ASSERT( checkAlignment( v_+i*nn_+j ), "Invalid alignment detected" );
2524
2525 return loada( v_+i*nn_+j );
2526 }
2527 //*************************************************************************************************
2528
2529
2530 //*************************************************************************************************
2531 /*!\brief Unaligned load of a SIMD element of the matrix.
2532 //
2533 // \param i Access index for the row. The index has to be in the range [0..M-1].
2534 // \param j Access index for the column. The index has to be in the range [0..N-1].
2535 // \return The loaded SIMD element.
2536 //
2537 // This function performs an unaligned load of a specific SIMD element of the dense matrix.
2538 // The row index must be smaller than the number of rows and the column index must be smaller
2539 // than the number of columns. Additionally, the column index (in case of a row-major matrix)
2540 // or the row index (in case of a column-major matrix) must be a multiple of the number of
2541 // values inside the SIMD element. This function must \b NOT be called explicitly! It is used
2542 // internally for the performance optimized evaluation of expression templates. Calling this
2543 // function explicitly might result in erroneous results and/or in compilation errors.
2544 */
2545 template< typename Type // Data type of the matrix
2546 , bool SO // Storage order
2547 , typename Alloc // Type of the allocator
2548 , typename Tag > // Type tag
2549 BLAZE_ALWAYS_INLINE typename DynamicMatrix<Type,SO,Alloc,Tag>::SIMDType
loadu(size_t i,size_t j)2550 DynamicMatrix<Type,SO,Alloc,Tag>::loadu( size_t i, size_t j ) const noexcept
2551 {
2552 using blaze::loadu;
2553
2554 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2555
2556 BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
2557 BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
2558 BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= nn_, "Invalid column access index" );
2559
2560 return loadu( v_+i*nn_+j );
2561 }
2562 //*************************************************************************************************
2563
2564
2565 //*************************************************************************************************
2566 /*!\brief Store of a SIMD element of the matrix.
2567 //
2568 // \param i Access index for the row. The index has to be in the range [0..M-1].
2569 // \param j Access index for the column. The index has to be in the range [0..N-1].
2570 // \param value The SIMD element to be stored.
2571 // \return void
2572 //
2573 // This function performs a store of a specific SIMD element of the dense matrix. The row index
2574 // must be smaller than the number of rows and the column index must be smaller than the number
2575 // of columns. Additionally, the column index (in case of a row-major matrix) or the row index
2576 // (in case of a column-major matrix) must be a multiple of the number of values inside the
2577 // SIMD element. This function must \b NOT be called explicitly! It is used internally for the
2578 // performance optimized evaluation of expression templates. Calling this function explicitly
2579 // might result in erroneous results and/or in compilation errors.
2580 */
2581 template< typename Type // Data type of the matrix
2582 , bool SO // Storage order
2583 , typename Alloc // Type of the allocator
2584 , typename Tag > // Type tag
2585 BLAZE_ALWAYS_INLINE void
store(size_t i,size_t j,const SIMDType & value)2586 DynamicMatrix<Type,SO,Alloc,Tag>::store( size_t i, size_t j, const SIMDType& value ) noexcept
2587 {
2588 if( usePadding )
2589 storea( i, j, value );
2590 else
2591 storeu( i, j, value );
2592 }
2593 //*************************************************************************************************
2594
2595
2596 //*************************************************************************************************
2597 /*!\brief Aligned store of a SIMD element of the matrix.
2598 //
2599 // \param i Access index for the row. The index has to be in the range [0..M-1].
2600 // \param j Access index for the column. The index has to be in the range [0..N-1].
2601 // \param value The SIMD element to be stored.
2602 // \return void
2603 //
2604 // This function performs an aligned store of a specific SIMD element of the dense matrix.
2605 // The row index must be smaller than the number of rows and the column index must be smaller
2606 // than the number of columns. Additionally, the column index (in case of a row-major matrix)
2607 // or the row index (in case of a column-major matrix) must be a multiple of the number of
2608 // values inside the SIMD element. This function must \b NOT be called explicitly! It is used
2609 // internally for the performance optimized evaluation of expression templates. Calling this
2610 // function explicitly might result in erroneous results and/or in compilation errors.
2611 */
2612 template< typename Type // Data type of the matrix
2613 , bool SO // Storage order
2614 , typename Alloc // Type of the allocator
2615 , typename Tag > // Type tag
2616 BLAZE_ALWAYS_INLINE void
storea(size_t i,size_t j,const SIMDType & value)2617 DynamicMatrix<Type,SO,Alloc,Tag>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
2618 {
2619 using blaze::storea;
2620
2621 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2622
2623 BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
2624 BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
2625 BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= nn_, "Invalid column access index" );
2626 BLAZE_INTERNAL_ASSERT( !usePadding || j % SIMDSIZE == 0UL, "Invalid column access index" );
2627 BLAZE_INTERNAL_ASSERT( checkAlignment( v_+i*nn_+j ), "Invalid alignment detected" );
2628
2629 storea( v_+i*nn_+j, value );
2630 }
2631 //*************************************************************************************************
2632
2633
2634 //*************************************************************************************************
2635 /*!\brief Unaligned store of a SIMD element of the matrix.
2636 //
2637 // \param i Access index for the row. The index has to be in the range [0..M-1].
2638 // \param j Access index for the column. The index has to be in the range [0..N-1].
2639 // \param value The SIMD element to be stored.
2640 // \return void
2641 //
2642 // This function performs an unaligned store of a specific SIMD element of the dense matrix.
2643 // The row index must be smaller than the number of rows and the column index must be smaller
2644 // than the number of columns. Additionally, the column index (in case of a row-major matrix)
2645 // or the row index (in case of a column-major matrix) must be a multiple of the number of
2646 // values inside the SIMD element. This function must \b NOT be called explicitly! It is used
2647 // internally for the performance optimized evaluation of expression templates. Calling this
2648 // function explicitly might result in erroneous results and/or in compilation errors.
2649 */
2650 template< typename Type // Data type of the matrix
2651 , bool SO // Storage order
2652 , typename Alloc // Type of the allocator
2653 , typename Tag > // Type tag
2654 BLAZE_ALWAYS_INLINE void
storeu(size_t i,size_t j,const SIMDType & value)2655 DynamicMatrix<Type,SO,Alloc,Tag>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
2656 {
2657 using blaze::storeu;
2658
2659 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2660
2661 BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
2662 BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
2663 BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= nn_, "Invalid column access index" );
2664
2665 storeu( v_+i*nn_+j, value );
2666 }
2667 //*************************************************************************************************
2668
2669
2670 //*************************************************************************************************
2671 /*!\brief Aligned, non-temporal store of a SIMD element of the matrix.
2672 //
2673 // \param i Access index for the row. The index has to be in the range [0..M-1].
2674 // \param j Access index for the column. The index has to be in the range [0..N-1].
2675 // \param value The SIMD element to be stored.
2676 // \return void
2677 //
2678 // This function performs an aligned, non-temporal store of a specific SIMD element of the
2679 // dense matrix. The row index must be smaller than the number of rows and the column index
2680 // must be smaller than the number of columns. Additionally, the column index (in case of a
2681 // row-major matrix) or the row index (in case of a column-major matrix) must be a multiple
2682 // of the number of values inside the SIMD element. This function must \b NOT be called
2683 // explicitly! It is used internally for the performance optimized evaluation of expression
2684 // templates. Calling this function explicitly might result in erroneous results and/or in
2685 // compilation errors.
2686 */
2687 template< typename Type // Data type of the matrix
2688 , bool SO // Storage order
2689 , typename Alloc // Type of the allocator
2690 , typename Tag > // Type tag
2691 BLAZE_ALWAYS_INLINE void
stream(size_t i,size_t j,const SIMDType & value)2692 DynamicMatrix<Type,SO,Alloc,Tag>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
2693 {
2694 using blaze::stream;
2695
2696 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2697
2698 BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
2699 BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
2700 BLAZE_INTERNAL_ASSERT( j + SIMDSIZE <= nn_, "Invalid column access index" );
2701 BLAZE_INTERNAL_ASSERT( !usePadding || j % SIMDSIZE == 0UL, "Invalid column access index" );
2702 BLAZE_INTERNAL_ASSERT( checkAlignment( v_+i*nn_+j ), "Invalid alignment detected" );
2703
2704 stream( v_+i*nn_+j, value );
2705 }
2706 //*************************************************************************************************
2707
2708
2709 //*************************************************************************************************
2710 /*!\brief Default implementation of the assignment of a row-major dense matrix.
2711 //
2712 // \param rhs The right-hand side dense matrix to be assigned.
2713 // \return void
2714 //
2715 // This function must \b NOT be called explicitly! It is used internally for the performance
2716 // optimized evaluation of expression templates. Calling this function explicitly might result
2717 // in erroneous results and/or in compilation errors. Instead of using this function use the
2718 // assignment operator.
2719 */
2720 template< typename Type // Data type of the matrix
2721 , bool SO // Storage order
2722 , typename Alloc // Type of the allocator
2723 , typename Tag > // Type tag
2724 template< typename MT > // Type of the right-hand side dense matrix
2725 inline auto DynamicMatrix<Type,SO,Alloc,Tag>::assign( const DenseMatrix<MT,SO>& rhs )
2726 -> DisableIf_t< VectorizedAssign_v<MT> >
2727 {
2728 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
2729 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
2730
2731 const size_t jpos( prevMultiple( n_, 2UL ) );
2732 BLAZE_INTERNAL_ASSERT( jpos <= n_, "Invalid end calculation" );
2733
2734 for( size_t i=0UL; i<m_; ++i ) {
2735 for( size_t j=0UL; j<jpos; j+=2UL ) {
2736 v_[i*nn_+j ] = (*rhs)(i,j );
2737 v_[i*nn_+j+1UL] = (*rhs)(i,j+1UL);
2738 }
2739 if( jpos < n_ ) {
2740 v_[i*nn_+jpos] = (*rhs)(i,jpos);
2741 }
2742 }
2743 }
2744 //*************************************************************************************************
2745
2746
2747 //*************************************************************************************************
2748 /*!\brief SIMD optimized implementation of the assignment of a row-major dense matrix.
2749 //
2750 // \param rhs The right-hand side dense matrix to be assigned.
2751 // \return void
2752 //
2753 // This function must \b NOT be called explicitly! It is used internally for the performance
2754 // optimized evaluation of expression templates. Calling this function explicitly might result
2755 // in erroneous results and/or in compilation errors. Instead of using this function use the
2756 // assignment operator.
2757 */
2758 template< typename Type // Data type of the matrix
2759 , bool SO // Storage order
2760 , typename Alloc // Type of the allocator
2761 , typename Tag > // Type tag
2762 template< typename MT > // Type of the right-hand side dense matrix
2763 inline auto DynamicMatrix<Type,SO,Alloc,Tag>::assign( const DenseMatrix<MT,SO>& rhs )
2764 -> EnableIf_t< VectorizedAssign_v<MT> >
2765 {
2766 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2767
2768 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
2769 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
2770
2771 constexpr bool remainder( !usePadding || !IsPadded_v<MT> );
2772
2773 const size_t jpos( remainder ? prevMultiple( n_, SIMDSIZE ) : n_ );
2774 BLAZE_INTERNAL_ASSERT( jpos <= n_, "Invalid end calculation" );
2775
2776 if( usePadding && useStreaming &&
2777 ( m_*n_ > ( cacheSize / ( sizeof(Type) * 3UL ) ) ) &&
2778 !(*rhs).isAliased( this ) )
2779 {
2780 for( size_t i=0UL; i<m_; ++i )
2781 {
2782 size_t j( 0UL );
2783 Iterator left( begin(i) );
2784 ConstIterator_t<MT> right( (*rhs).begin(i) );
2785
2786 for( ; j<jpos; j+=SIMDSIZE, left+=SIMDSIZE, right+=SIMDSIZE ) {
2787 left.stream( right.load() );
2788 }
2789 for( ; remainder && j<n_; ++j, ++left, ++right ) {
2790 *left = *right;
2791 }
2792 }
2793 }
2794 else
2795 {
2796 for( size_t i=0UL; i<m_; ++i )
2797 {
2798 size_t j( 0UL );
2799 Iterator left( begin(i) );
2800 ConstIterator_t<MT> right( (*rhs).begin(i) );
2801
2802 for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
2803 left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2804 left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2805 left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2806 left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
2807 }
2808 for( ; j<jpos; j+=SIMDSIZE ) {
2809 left.store( right.load() ); left+=SIMDSIZE, right+=SIMDSIZE;
2810 }
2811 for( ; remainder && j<n_; ++j ) {
2812 *left = *right; ++left; ++right;
2813 }
2814 }
2815 }
2816 }
2817 //*************************************************************************************************
2818
2819
2820 //*************************************************************************************************
2821 /*!\brief Default implementation of the assignment of a column-major dense matrix.
2822 //
2823 // \param rhs The right-hand side dense matrix to be assigned.
2824 // \return void
2825 //
2826 // This function must \b NOT be called explicitly! It is used internally for the performance
2827 // optimized evaluation of expression templates. Calling this function explicitly might result
2828 // in erroneous results and/or in compilation errors. Instead of using this function use the
2829 // assignment operator.
2830 */
2831 template< typename Type // Data type of the matrix
2832 , bool SO // Storage order
2833 , typename Alloc // Type of the allocator
2834 , typename Tag > // Type tag
2835 template< typename MT > // Type of the right-hand side dense matrix
assign(const DenseMatrix<MT,!SO> & rhs)2836 inline void DynamicMatrix<Type,SO,Alloc,Tag>::assign( const DenseMatrix<MT,!SO>& rhs )
2837 {
2838 BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
2839
2840 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
2841 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
2842
2843 constexpr size_t block( BLOCK_SIZE );
2844
2845 for( size_t ii=0UL; ii<m_; ii+=block ) {
2846 const size_t iend( min( m_, ii+block ) );
2847 for( size_t jj=0UL; jj<n_; jj+=block ) {
2848 const size_t jend( min( n_, jj+block ) );
2849 for( size_t i=ii; i<iend; ++i ) {
2850 for( size_t j=jj; j<jend; ++j ) {
2851 v_[i*nn_+j] = (*rhs)(i,j);
2852 }
2853 }
2854 }
2855 }
2856 }
2857 //*************************************************************************************************
2858
2859
2860 //*************************************************************************************************
2861 /*!\brief Default implementation of the assignment of a row-major sparse matrix.
2862 //
2863 // \param rhs The right-hand side sparse matrix to be assigned.
2864 // \return void
2865 //
2866 // This function must \b NOT be called explicitly! It is used internally for the performance
2867 // optimized evaluation of expression templates. Calling this function explicitly might result
2868 // in erroneous results and/or in compilation errors. Instead of using this function use the
2869 // assignment operator.
2870 */
2871 template< typename Type // Data type of the matrix
2872 , bool SO // Storage order
2873 , typename Alloc // Type of the allocator
2874 , typename Tag > // Type tag
2875 template< typename MT > // Type of the right-hand side sparse matrix
assign(const SparseMatrix<MT,SO> & rhs)2876 inline void DynamicMatrix<Type,SO,Alloc,Tag>::assign( const SparseMatrix<MT,SO>& rhs )
2877 {
2878 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
2879 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
2880
2881 for( size_t i=0UL; i<m_; ++i )
2882 for( auto element=(*rhs).begin(i); element!=(*rhs).end(i); ++element )
2883 v_[i*nn_+element->index()] = element->value();
2884 }
2885 //*************************************************************************************************
2886
2887
2888 //*************************************************************************************************
2889 /*!\brief Default implementation of the assignment of a column-major sparse matrix.
2890 //
2891 // \param rhs The right-hand side sparse matrix to be assigned.
2892 // \return void
2893 //
2894 // This function must \b NOT be called explicitly! It is used internally for the performance
2895 // optimized evaluation of expression templates. Calling this function explicitly might result
2896 // in erroneous results and/or in compilation errors. Instead of using this function use the
2897 // assignment operator.
2898 */
2899 template< typename Type // Data type of the matrix
2900 , bool SO // Storage order
2901 , typename Alloc // Type of the allocator
2902 , typename Tag > // Type tag
2903 template< typename MT > // Type of the right-hand side sparse matrix
assign(const SparseMatrix<MT,!SO> & rhs)2904 inline void DynamicMatrix<Type,SO,Alloc,Tag>::assign( const SparseMatrix<MT,!SO>& rhs )
2905 {
2906 BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
2907
2908 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
2909 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
2910
2911 for( size_t j=0UL; j<n_; ++j )
2912 for( auto element=(*rhs).begin(j); element!=(*rhs).end(j); ++element )
2913 v_[element->index()*nn_+j] = element->value();
2914 }
2915 //*************************************************************************************************
2916
2917
2918 //*************************************************************************************************
2919 /*!\brief Default implementation of the addition assignment of a row-major dense matrix.
2920 //
2921 // \param rhs The right-hand side dense matrix to be added.
2922 // \return void
2923 //
2924 // This function must \b NOT be called explicitly! It is used internally for the performance
2925 // optimized evaluation of expression templates. Calling this function explicitly might result
2926 // in erroneous results and/or in compilation errors. Instead of using this function use the
2927 // assignment operator.
2928 */
2929 template< typename Type // Data type of the matrix
2930 , bool SO // Storage order
2931 , typename Alloc // Type of the allocator
2932 , typename Tag > // Type tag
2933 template< typename MT > // Type of the right-hand side dense matrix
2934 inline auto DynamicMatrix<Type,SO,Alloc,Tag>::addAssign( const DenseMatrix<MT,SO>& rhs )
2935 -> DisableIf_t< VectorizedAddAssign_v<MT> >
2936 {
2937 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
2938 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
2939
2940 for( size_t i=0UL; i<m_; ++i )
2941 {
2942 if( IsDiagonal_v<MT> )
2943 {
2944 v_[i*nn_+i] += (*rhs)(i,i);
2945 }
2946 else
2947 {
2948 const size_t jbegin( ( IsUpper_v<MT> )
2949 ?( IsStrictlyUpper_v<MT> ? i+1UL : i )
2950 :( 0UL ) );
2951 const size_t jend ( ( IsLower_v<MT> )
2952 ?( IsStrictlyLower_v<MT> ? i : i+1UL )
2953 :( n_ ) );
2954 BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
2955
2956 size_t j( jbegin );
2957
2958 for( ; (j+2UL) <= jend; j+=2UL ) {
2959 v_[i*nn_+j ] += (*rhs)(i,j );
2960 v_[i*nn_+j+1UL] += (*rhs)(i,j+1UL);
2961 }
2962 if( j < jend ) {
2963 v_[i*nn_+j] += (*rhs)(i,j);
2964 }
2965 }
2966 }
2967 }
2968 //*************************************************************************************************
2969
2970
2971 //*************************************************************************************************
2972 /*!\brief SIMD optimized implementation of the addition assignment of a row-major dense matrix.
2973 //
2974 // \param rhs The right-hand side dense matrix to be added.
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 Type // Data type of the matrix
2983 , bool SO // Storage order
2984 , typename Alloc // Type of the allocator
2985 , typename Tag > // Type tag
2986 template< typename MT > // Type of the right-hand side dense matrix
2987 inline auto DynamicMatrix<Type,SO,Alloc,Tag>::addAssign( const DenseMatrix<MT,SO>& rhs )
2988 -> EnableIf_t< VectorizedAddAssign_v<MT> >
2989 {
2990 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
2991 BLAZE_CONSTRAINT_MUST_NOT_BE_DIAGONAL_MATRIX_TYPE( MT );
2992
2993 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
2994 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
2995
2996 constexpr bool remainder( !usePadding || !IsPadded_v<MT> );
2997
2998 for( size_t i=0UL; i<m_; ++i )
2999 {
3000 const size_t jbegin( ( IsUpper_v<MT> )
3001 ?( prevMultiple( ( IsStrictlyUpper_v<MT> ? i+1UL : i ), SIMDSIZE ) )
3002 :( 0UL ) );
3003 const size_t jend ( ( IsLower_v<MT> )
3004 ?( IsStrictlyLower_v<MT> ? i : i+1UL )
3005 :( n_ ) );
3006 BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
3007
3008 const size_t jpos( remainder ? prevMultiple( jend, SIMDSIZE ) : jend );
3009 BLAZE_INTERNAL_ASSERT( jpos <= jend, "Invalid end calculation" );
3010
3011 size_t j( jbegin );
3012 Iterator left( begin(i) + jbegin );
3013 ConstIterator_t<MT> right( (*rhs).begin(i) + jbegin );
3014
3015 for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
3016 left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3017 left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3018 left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3019 left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3020 }
3021 for( ; j<jpos; j+=SIMDSIZE ) {
3022 left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3023 }
3024 for( ; remainder && j<jend; ++j ) {
3025 *left += *right; ++left; ++right;
3026 }
3027 }
3028 }
3029 //*************************************************************************************************
3030
3031
3032 //*************************************************************************************************
3033 /*!\brief Default implementation of the addition assignment of a column-major dense matrix.
3034 //
3035 // \param rhs The right-hand side dense matrix to be added.
3036 // \return void
3037 //
3038 // This function must \b NOT be called explicitly! It is used internally for the performance
3039 // optimized evaluation of expression templates. Calling this function explicitly might result
3040 // in erroneous results and/or in compilation errors. Instead of using this function use the
3041 // assignment operator.
3042 */
3043 template< typename Type // Data type of the matrix
3044 , bool SO // Storage order
3045 , typename Alloc // Type of the allocator
3046 , typename Tag > // Type tag
3047 template< typename MT > // Type of the right-hand side dense matrix
addAssign(const DenseMatrix<MT,!SO> & rhs)3048 inline void DynamicMatrix<Type,SO,Alloc,Tag>::addAssign( const DenseMatrix<MT,!SO>& rhs )
3049 {
3050 BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
3051
3052 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
3053 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
3054
3055 constexpr size_t block( BLOCK_SIZE );
3056
3057 for( size_t ii=0UL; ii<m_; ii+=block ) {
3058 const size_t iend( min( m_, ii+block ) );
3059 for( size_t jj=0UL; jj<n_; jj+=block )
3060 {
3061 if( IsLower_v<MT> && ii < jj ) break;
3062 if( IsUpper_v<MT> && ii > jj ) continue;
3063
3064 for( size_t i=ii; i<iend; ++i )
3065 {
3066 const size_t jbegin( ( IsUpper_v<MT> )
3067 ?( max( ( IsStrictlyUpper_v<MT> ? i+1UL : i ), jj ) )
3068 :( jj ) );
3069 const size_t jend ( ( IsLower_v<MT> )
3070 ?( min( ( IsStrictlyLower_v<MT> ? i : i+1UL ), n_, jj+block ) )
3071 :( min( n_, jj+block ) ) );
3072 BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
3073
3074 for( size_t j=jbegin; j<jend; ++j ) {
3075 v_[i*nn_+j] += (*rhs)(i,j);
3076 }
3077 }
3078 }
3079 }
3080 }
3081 //*************************************************************************************************
3082
3083
3084 //*************************************************************************************************
3085 /*!\brief Default implementation of the addition assignment of a row-major sparse matrix.
3086 //
3087 // \param rhs The right-hand side sparse matrix to be added.
3088 // \return void
3089 //
3090 // This function must \b NOT be called explicitly! It is used internally for the performance
3091 // optimized evaluation of expression templates. Calling this function explicitly might result
3092 // in erroneous results and/or in compilation errors. Instead of using this function use the
3093 // assignment operator.
3094 */
3095 template< typename Type // Data type of the matrix
3096 , bool SO // Storage order
3097 , typename Alloc // Type of the allocator
3098 , typename Tag > // Type tag
3099 template< typename MT > // Type of the right-hand side sparse matrix
addAssign(const SparseMatrix<MT,SO> & rhs)3100 inline void DynamicMatrix<Type,SO,Alloc,Tag>::addAssign( const SparseMatrix<MT,SO>& rhs )
3101 {
3102 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
3103 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
3104
3105 for( size_t i=0UL; i<m_; ++i )
3106 for( auto element=(*rhs).begin(i); element!=(*rhs).end(i); ++element )
3107 v_[i*nn_+element->index()] += element->value();
3108 }
3109 //*************************************************************************************************
3110
3111
3112 //*************************************************************************************************
3113 /*!\brief Default implementation of the addition assignment of a column-major sparse matrix.
3114 //
3115 // \param rhs The right-hand side sparse matrix to be added.
3116 // \return void
3117 //
3118 // This function must \b NOT be called explicitly! It is used internally for the performance
3119 // optimized evaluation of expression templates. Calling this function explicitly might result
3120 // in erroneous results and/or in compilation errors. Instead of using this function use the
3121 // assignment operator.
3122 */
3123 template< typename Type // Data type of the matrix
3124 , bool SO // Storage order
3125 , typename Alloc // Type of the allocator
3126 , typename Tag > // Type tag
3127 template< typename MT > // Type of the right-hand side sparse matrix
addAssign(const SparseMatrix<MT,!SO> & rhs)3128 inline void DynamicMatrix<Type,SO,Alloc,Tag>::addAssign( const SparseMatrix<MT,!SO>& rhs )
3129 {
3130 BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
3131
3132 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
3133 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
3134
3135 for( size_t j=0UL; j<n_; ++j )
3136 for( auto element=(*rhs).begin(j); element!=(*rhs).end(j); ++element )
3137 v_[element->index()*nn_+j] += element->value();
3138 }
3139 //*************************************************************************************************
3140
3141
3142 //*************************************************************************************************
3143 /*!\brief Default implementation of the subtraction assignment of a row-major dense matrix.
3144 //
3145 // \param rhs The right-hand side dense matrix to be subtracted.
3146 // \return void
3147 //
3148 // This function must \b NOT be called explicitly! It is used internally for the performance
3149 // optimized evaluation of expression templates. Calling this function explicitly might result
3150 // in erroneous results and/or in compilation errors. Instead of using this function use the
3151 // assignment operator.
3152 */
3153 template< typename Type // Data type of the matrix
3154 , bool SO // Storage order
3155 , typename Alloc // Type of the allocator
3156 , typename Tag > // Type tag
3157 template< typename MT > // Type of the right-hand side dense matrix
3158 inline auto DynamicMatrix<Type,SO,Alloc,Tag>::subAssign( const DenseMatrix<MT,SO>& rhs )
3159 -> DisableIf_t< VectorizedSubAssign_v<MT> >
3160 {
3161 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
3162 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
3163
3164 for( size_t i=0UL; i<m_; ++i )
3165 {
3166 if( IsDiagonal_v<MT> )
3167 {
3168 v_[i*nn_+i] -= (*rhs)(i,i);
3169 }
3170 else
3171 {
3172 const size_t jbegin( ( IsUpper_v<MT> )
3173 ?( IsStrictlyUpper_v<MT> ? i+1UL : i )
3174 :( 0UL ) );
3175 const size_t jend ( ( IsLower_v<MT> )
3176 ?( IsStrictlyLower_v<MT> ? i : i+1UL )
3177 :( n_ ) );
3178 BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
3179
3180 size_t j( jbegin );
3181
3182 for( ; (j+2UL) <= jend; j+=2UL ) {
3183 v_[i*nn_+j ] -= (*rhs)(i,j );
3184 v_[i*nn_+j+1UL] -= (*rhs)(i,j+1UL);
3185 }
3186 if( j < jend ) {
3187 v_[i*nn_+j] -= (*rhs)(i,j);
3188 }
3189 }
3190 }
3191 }
3192 //*************************************************************************************************
3193
3194
3195 //*************************************************************************************************
3196 /*!\brief SIMD optimized implementation of the subtraction assignment of a row-major dense matrix.
3197 //
3198 // \param rhs The right-hand side dense matrix to be subtracted.
3199 // \return void
3200 //
3201 // This function must \b NOT be called explicitly! It is used internally for the performance
3202 // optimized evaluation of expression templates. Calling this function explicitly might result
3203 // in erroneous results and/or in compilation errors. Instead of using this function use the
3204 // assignment operator.
3205 */
3206 template< typename Type // Data type of the matrix
3207 , bool SO // Storage order
3208 , typename Alloc // Type of the allocator
3209 , typename Tag > // Type tag
3210 template< typename MT > // Type of the right-hand side dense matrix
3211 inline auto DynamicMatrix<Type,SO,Alloc,Tag>::subAssign( const DenseMatrix<MT,SO>& rhs )
3212 -> EnableIf_t< VectorizedSubAssign_v<MT> >
3213 {
3214 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
3215 BLAZE_CONSTRAINT_MUST_NOT_BE_DIAGONAL_MATRIX_TYPE( MT );
3216
3217 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
3218 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
3219
3220 constexpr bool remainder( !usePadding || !IsPadded_v<MT> );
3221
3222 for( size_t i=0UL; i<m_; ++i )
3223 {
3224 const size_t jbegin( ( IsUpper_v<MT> )
3225 ?( prevMultiple( ( IsStrictlyUpper_v<MT> ? i+1UL : i ), SIMDSIZE ) )
3226 :( 0UL ) );
3227 const size_t jend ( ( IsLower_v<MT> )
3228 ?( IsStrictlyLower_v<MT> ? i : i+1UL )
3229 :( n_ ) );
3230 BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
3231
3232 const size_t jpos( remainder ? prevMultiple( jend, SIMDSIZE ) : jend );
3233 BLAZE_INTERNAL_ASSERT( jpos <= jend, "Invalid end calculation" );
3234
3235 size_t j( jbegin );
3236 Iterator left( begin(i) + jbegin );
3237 ConstIterator_t<MT> right( (*rhs).begin(i) + jbegin );
3238
3239 for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
3240 left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
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 }
3245 for( ; j<jpos; j+=SIMDSIZE ) {
3246 left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3247 }
3248 for( ; remainder && j<jend; ++j ) {
3249 *left -= *right; ++left; ++right;
3250 }
3251 }
3252 }
3253 //*************************************************************************************************
3254
3255
3256 //*************************************************************************************************
3257 /*!\brief Default implementation of the subtraction assignment of a column-major dense matrix.
3258 //
3259 // \param rhs The right-hand side dense matrix to be subtracted.
3260 // \return void
3261 //
3262 // This function must \b NOT be called explicitly! It is used internally for the performance
3263 // optimized evaluation of expression templates. Calling this function explicitly might result
3264 // in erroneous results and/or in compilation errors. Instead of using this function use the
3265 // assignment operator.
3266 */
3267 template< typename Type // Data type of the matrix
3268 , bool SO // Storage order
3269 , typename Alloc // Type of the allocator
3270 , typename Tag > // Type tag
3271 template< typename MT > // Type of the right-hand side dense matrix
subAssign(const DenseMatrix<MT,!SO> & rhs)3272 inline void DynamicMatrix<Type,SO,Alloc,Tag>::subAssign( const DenseMatrix<MT,!SO>& rhs )
3273 {
3274 BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
3275
3276 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
3277 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
3278
3279 constexpr size_t block( BLOCK_SIZE );
3280
3281 for( size_t ii=0UL; ii<m_; ii+=block ) {
3282 const size_t iend( min( m_, ii+block ) );
3283 for( size_t jj=0UL; jj<n_; jj+=block )
3284 {
3285 if( IsLower_v<MT> && ii < jj ) break;
3286 if( IsUpper_v<MT> && ii > jj ) continue;
3287
3288 for( size_t i=ii; i<iend; ++i )
3289 {
3290 const size_t jbegin( ( IsUpper_v<MT> )
3291 ?( max( ( IsStrictlyUpper_v<MT> ? i+1UL : i ), jj ) )
3292 :( jj ) );
3293 const size_t jend ( ( IsLower_v<MT> )
3294 ?( min( ( IsStrictlyLower_v<MT> ? i : i+1UL ), n_, jj+block ) )
3295 :( min( n_, jj+block ) ) );
3296 BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" );
3297
3298 for( size_t j=jbegin; j<jend; ++j ) {
3299 v_[i*nn_+j] -= (*rhs)(i,j);
3300 }
3301 }
3302 }
3303 }
3304 }
3305 //*************************************************************************************************
3306
3307
3308 //*************************************************************************************************
3309 /*!\brief Default implementation of the subtraction assignment of a row-major sparse matrix.
3310 //
3311 // \param rhs The right-hand side sparse matrix to be subtracted.
3312 // \return void
3313 //
3314 // This function must \b NOT be called explicitly! It is used internally for the performance
3315 // optimized evaluation of expression templates. Calling this function explicitly might result
3316 // in erroneous results and/or in compilation errors. Instead of using this function use the
3317 // assignment operator.
3318 */
3319 template< typename Type // Data type of the matrix
3320 , bool SO // Storage order
3321 , typename Alloc // Type of the allocator
3322 , typename Tag > // Type tag
3323 template< typename MT > // Type of the right-hand side sparse matrix
subAssign(const SparseMatrix<MT,SO> & rhs)3324 inline void DynamicMatrix<Type,SO,Alloc,Tag>::subAssign( const SparseMatrix<MT,SO>& rhs )
3325 {
3326 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
3327 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
3328
3329 for( size_t i=0UL; i<m_; ++i )
3330 for( auto element=(*rhs).begin(i); element!=(*rhs).end(i); ++element )
3331 v_[i*nn_+element->index()] -= element->value();
3332 }
3333 //*************************************************************************************************
3334
3335
3336 //*************************************************************************************************
3337 /*!\brief Default implementation of the subtraction assignment of a column-major sparse matrix.
3338 //
3339 // \param rhs The right-hand side sparse matrix to be subtracted.
3340 // \return void
3341 //
3342 // This function must \b NOT be called explicitly! It is used internally for the performance
3343 // optimized evaluation of expression templates. Calling this function explicitly might result
3344 // in erroneous results and/or in compilation errors. Instead of using this function use the
3345 // assignment operator.
3346 */
3347 template< typename Type // Data type of the matrix
3348 , bool SO // Storage order
3349 , typename Alloc // Type of the allocator
3350 , typename Tag > // Type tag
3351 template< typename MT > // Type of the right-hand side sparse matrix
subAssign(const SparseMatrix<MT,!SO> & rhs)3352 inline void DynamicMatrix<Type,SO,Alloc,Tag>::subAssign( const SparseMatrix<MT,!SO>& rhs )
3353 {
3354 BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
3355
3356 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
3357 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
3358
3359 for( size_t j=0UL; j<n_; ++j )
3360 for( auto element=(*rhs).begin(j); element!=(*rhs).end(j); ++element )
3361 v_[element->index()*nn_+j] -= element->value();
3362 }
3363 //*************************************************************************************************
3364
3365
3366 //*************************************************************************************************
3367 /*!\brief Default implementation of the Schur product assignment of a row-major dense matrix.
3368 //
3369 // \param rhs The right-hand side dense matrix for the Schur product.
3370 // \return void
3371 //
3372 // This function must \b NOT be called explicitly! It is used internally for the performance
3373 // optimized evaluation of expression templates. Calling this function explicitly might result
3374 // in erroneous results and/or in compilation errors. Instead of using this function use the
3375 // assignment operator.
3376 */
3377 template< typename Type // Data type of the matrix
3378 , bool SO // Storage order
3379 , typename Alloc // Type of the allocator
3380 , typename Tag > // Type tag
3381 template< typename MT > // Type of the right-hand side dense matrix
3382 inline auto DynamicMatrix<Type,SO,Alloc,Tag>::schurAssign( const DenseMatrix<MT,SO>& rhs )
3383 -> DisableIf_t< VectorizedSchurAssign_v<MT> >
3384 {
3385 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
3386 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
3387
3388 const size_t jpos( prevMultiple( n_, 2UL ) );
3389 BLAZE_INTERNAL_ASSERT( jpos <= n_, "Invalid end calculation" );
3390
3391 for( size_t i=0UL; i<m_; ++i ) {
3392 for( size_t j=0UL; j<jpos; j+=2UL ) {
3393 v_[i*nn_+j ] *= (*rhs)(i,j );
3394 v_[i*nn_+j+1UL] *= (*rhs)(i,j+1UL);
3395 }
3396 if( jpos < n_ ) {
3397 v_[i*nn_+jpos] *= (*rhs)(i,jpos);
3398 }
3399 }
3400 }
3401 //*************************************************************************************************
3402
3403
3404 //*************************************************************************************************
3405 /*!\brief SIMD optimized implementation of the Schur product assignment of a row-major dense matrix.
3406 //
3407 // \param rhs The right-hand side dense matrix for the Schur product.
3408 // \return void
3409 //
3410 // This function must \b NOT be called explicitly! It is used internally for the performance
3411 // optimized evaluation of expression templates. Calling this function explicitly might result
3412 // in erroneous results and/or in compilation errors. Instead of using this function use the
3413 // assignment operator.
3414 */
3415 template< typename Type // Data type of the matrix
3416 , bool SO // Storage order
3417 , typename Alloc // Type of the allocator
3418 , typename Tag > // Type tag
3419 template< typename MT > // Type of the right-hand side dense matrix
3420 inline auto DynamicMatrix<Type,SO,Alloc,Tag>::schurAssign( const DenseMatrix<MT,SO>& rhs )
3421 -> EnableIf_t< VectorizedSchurAssign_v<MT> >
3422 {
3423 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
3424
3425 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
3426 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
3427
3428 constexpr bool remainder( !usePadding || !IsPadded_v<MT> );
3429
3430 for( size_t i=0UL; i<m_; ++i )
3431 {
3432 const size_t jpos( remainder ? prevMultiple( n_, SIMDSIZE ) : n_ );
3433 BLAZE_INTERNAL_ASSERT( jpos <= n_, "Invalid end calculation" );
3434
3435 size_t j( 0UL );
3436 Iterator left( begin(i) );
3437 ConstIterator_t<MT> right( (*rhs).begin(i) );
3438
3439 for( ; (j+SIMDSIZE*3UL) < jpos; j+=SIMDSIZE*4UL ) {
3440 left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3441 left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3442 left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3443 left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3444 }
3445 for( ; j<jpos; j+=SIMDSIZE ) {
3446 left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
3447 }
3448 for( ; remainder && j<n_; ++j ) {
3449 *left *= *right; ++left; ++right;
3450 }
3451 }
3452 }
3453 //*************************************************************************************************
3454
3455
3456 //*************************************************************************************************
3457 /*!\brief Default implementation of the Schur product assignment of a column-major dense matrix.
3458 //
3459 // \param rhs The right-hand side dense matrix for the Schur product.
3460 // \return void
3461 //
3462 // This function must \b NOT be called explicitly! It is used internally for the performance
3463 // optimized evaluation of expression templates. Calling this function explicitly might result
3464 // in erroneous results and/or in compilation errors. Instead of using this function use the
3465 // assignment operator.
3466 */
3467 template< typename Type // Data type of the matrix
3468 , bool SO // Storage order
3469 , typename Alloc // Type of the allocator
3470 , typename Tag > // Type tag
3471 template< typename MT > // Type of the right-hand side dense matrix
schurAssign(const DenseMatrix<MT,!SO> & rhs)3472 inline void DynamicMatrix<Type,SO,Alloc,Tag>::schurAssign( const DenseMatrix<MT,!SO>& rhs )
3473 {
3474 BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
3475
3476 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
3477 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
3478
3479 constexpr size_t block( BLOCK_SIZE );
3480
3481 for( size_t ii=0UL; ii<m_; ii+=block ) {
3482 const size_t iend( min( m_, ii+block ) );
3483 for( size_t jj=0UL; jj<n_; jj+=block ) {
3484 const size_t jend( min( n_, jj+block ) );
3485 for( size_t i=ii; i<iend; ++i ) {
3486 for( size_t j=jj; j<jend; ++j ) {
3487 v_[i*nn_+j] *= (*rhs)(i,j);
3488 }
3489 }
3490 }
3491 }
3492 }
3493 //*************************************************************************************************
3494
3495
3496 //*************************************************************************************************
3497 /*!\brief Default implementation of the Schur product assignment of a row-major sparse matrix.
3498 //
3499 // \param rhs The right-hand side sparse matrix for the Schur product.
3500 // \return void
3501 //
3502 // This function must \b NOT be called explicitly! It is used internally for the performance
3503 // optimized evaluation of expression templates. Calling this function explicitly might result
3504 // in erroneous results and/or in compilation errors. Instead of using this function use the
3505 // assignment operator.
3506 */
3507 template< typename Type // Data type of the matrix
3508 , bool SO // Storage order
3509 , typename Alloc // Type of the allocator
3510 , typename Tag > // Type tag
3511 template< typename MT > // Type of the right-hand side sparse matrix
schurAssign(const SparseMatrix<MT,SO> & rhs)3512 inline void DynamicMatrix<Type,SO,Alloc,Tag>::schurAssign( const SparseMatrix<MT,SO>& rhs )
3513 {
3514 using blaze::reset;
3515
3516 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
3517 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
3518
3519 for( size_t i=0UL; i<m_; ++i )
3520 {
3521 size_t j( 0UL );
3522
3523 for( auto element=(*rhs).begin(i); element!=(*rhs).end(i); ++element ) {
3524 for( ; j<element->index(); ++j )
3525 reset( v_[i*nn_+j] );
3526 v_[i*nn_+j] *= element->value();
3527 ++j;
3528 }
3529
3530 for( ; j<n_; ++j ) {
3531 reset( v_[i*nn_+j] );
3532 }
3533 }
3534 }
3535 //*************************************************************************************************
3536
3537
3538 //*************************************************************************************************
3539 /*!\brief Default implementation of the Schur product assignment of a column-major sparse matrix.
3540 //
3541 // \param rhs The right-hand side sparse matrix for the Schur product.
3542 // \return void
3543 //
3544 // This function must \b NOT be called explicitly! It is used internally for the performance
3545 // optimized evaluation of expression templates. Calling this function explicitly might result
3546 // in erroneous results and/or in compilation errors. Instead of using this function use the
3547 // assignment operator.
3548 */
3549 template< typename Type // Data type of the matrix
3550 , bool SO // Storage order
3551 , typename Alloc // Type of the allocator
3552 , typename Tag > // Type tag
3553 template< typename MT > // Type of the right-hand side sparse matrix
schurAssign(const SparseMatrix<MT,!SO> & rhs)3554 inline void DynamicMatrix<Type,SO,Alloc,Tag>::schurAssign( const SparseMatrix<MT,!SO>& rhs )
3555 {
3556 using blaze::reset;
3557
3558 BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
3559
3560 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
3561 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
3562
3563 for( size_t j=0UL; j<n_; ++j )
3564 {
3565 size_t i( 0UL );
3566
3567 for( auto element=(*rhs).begin(j); element!=(*rhs).end(j); ++element ) {
3568 for( ; i<element->index(); ++i )
3569 reset( v_[i*nn_+j] );
3570 v_[i*nn_+j] *= element->value();
3571 ++i;
3572 }
3573
3574 for( ; i<m_; ++i ) {
3575 reset( v_[i*nn_+j] );
3576 }
3577 }
3578 }
3579 //*************************************************************************************************
3580
3581
3582
3583
3584
3585
3586
3587
3588 //=================================================================================================
3589 //
3590 // CLASS TEMPLATE SPECIALIZATION FOR COLUMN-MAJOR MATRICES
3591 //
3592 //=================================================================================================
3593
3594 //*************************************************************************************************
3595 /*! \cond BLAZE_INTERNAL */
3596 /*!\brief Specialization of DynamicMatrix for column-major matrices.
3597 // \ingroup dynamic_matrix
3598 //
3599 // This specialization of DynamicMatrix adapts the class template to the requirements of
3600 // column-major matrices.
3601 */
3602 template< typename Type // Data type of the matrix
3603 , typename Alloc // Type of the allocator
3604 , typename Tag > // Type tag
3605 class DynamicMatrix<Type,true,Alloc,Tag>
3606 : public DenseMatrix< DynamicMatrix<Type,true,Alloc,Tag>, true >
3607 {
3608 private:
3609 //**********************************************************************************************
3610 //! Compilation switch for the choice of alignment.
3611 static constexpr AlignmentFlag align = ( usePadding ? aligned : unaligned );
3612 //**********************************************************************************************
3613
3614 public:
3615 //**Type definitions****************************************************************************
3616 using This = DynamicMatrix<Type,true,Alloc,Tag>; //!< Type of this DynamicMatrix instance.
3617 using BaseType = DenseMatrix<This,true>; //!< Base type of this DynamicMatrix instance.
3618 using ResultType = This; //!< Result type for expression template evaluations.
3619
3620 //! Result type with opposite storage order for expression template evaluations.
3621 using OppositeType = DynamicMatrix<Type,false,Alloc,Tag>;
3622
3623 //! Transpose type for expression template evaluations.
3624 using TransposeType = DynamicMatrix<Type,false,Alloc,Tag>;
3625
3626 using ElementType = Type; //!< Type of the matrix elements.
3627 using SIMDType = SIMDTrait_t<ElementType>; //!< SIMD type of the matrix elements.
3628 using AllocatorType = AlignedAllocator<Type>; //!< Allocator type of this DynamicMatrix instance.
3629 using TagType = Tag; //!< Tag type of this DynamicMatrix instance.
3630 using ReturnType = const Type&; //!< Return type for expression template evaluations.
3631 using CompositeType = const This&; //!< Data type for composite expression templates.
3632
3633 using Reference = Type&; //!< Reference to a non-constant matrix value.
3634 using ConstReference = const Type&; //!< Reference to a constant matrix value.
3635 using Pointer = Type*; //!< Pointer to a non-constant matrix value.
3636 using ConstPointer = const Type*; //!< Pointer to a constant matrix value.
3637
3638 using Iterator = DenseIterator<Type,align>; //!< Iterator over non-constant elements.
3639 using ConstIterator = DenseIterator<const Type,align>; //!< Iterator over constant elements.
3640 //**********************************************************************************************
3641
3642 //**Rebind struct definition********************************************************************
3643 /*!\brief Rebind mechanism to obtain a DynamicMatrix with different data/element type.
3644 */
3645 template< typename NewType > // Data type of the other matrix
3646 struct Rebind
3647 {
3648 //! The new type of allocator.
3649 using NewAlloc = typename std::allocator_traits<Alloc>::template rebind_alloc<NewType>;
3650
3651 //! The type of the other DynamicMatrix.
3652 using Other = DynamicMatrix<NewType,true,NewAlloc,Tag>;
3653 };
3654 //**********************************************************************************************
3655
3656 //**Resize struct definition********************************************************************
3657 /*!\brief Resize mechanism to obtain a DynamicMatrix with different fixed dimensions.
3658 */
3659 template< size_t NewM // Number of rows of the other matrix
3660 , size_t NewN > // Number of columns of the other matrix
3661 struct Resize
3662 {
3663 using Other = DynamicMatrix<Type,true,Alloc,Tag>; //!< The type of the other DynamicMatrix.
3664 };
3665 //**********************************************************************************************
3666
3667 //**Compilation flags***************************************************************************
3668 //! Compilation flag for SIMD optimization.
3669 /*! The \a simdEnabled compilation flag indicates whether expressions the matrix is involved
3670 in can be optimized via SIMD operations. In case the element type of the matrix is a
3671 vectorizable data type, the \a simdEnabled compilation flag is set to \a true, otherwise
3672 it is set to \a false. */
3673 static constexpr bool simdEnabled = IsVectorizable_v<Type>;
3674
3675 //! Compilation flag for SMP assignments.
3676 /*! The \a smpAssignable compilation flag indicates whether the matrix can be used in SMP
3677 (shared memory parallel) assignments (both on the left-hand and right-hand side of the
3678 assignment). */
3679 static constexpr bool smpAssignable = !IsSMPAssignable_v<Type>;
3680 //**********************************************************************************************
3681
3682 //**Constructors********************************************************************************
3683 /*!\name Constructors */
3684 //@{
3685 inline DynamicMatrix( const Alloc& alloc = Alloc{} ) noexcept;
3686 inline DynamicMatrix( size_t m, size_t n, const Alloc& alloc = Alloc{} );
3687 inline DynamicMatrix( size_t m, size_t n, const Type& init, const Alloc& alloc = Alloc{} );
3688 inline DynamicMatrix( initializer_list< initializer_list<Type> > list, const Alloc& alloc = Alloc{} );
3689
3690 template< typename Other >
3691 inline DynamicMatrix( size_t m, size_t n, const Other* array, const Alloc& alloc = Alloc{} );
3692
3693 template< typename Other, size_t Rows, size_t Cols >
3694 inline DynamicMatrix( const Other (&array)[Rows][Cols], const Alloc& alloc = Alloc{} );
3695
3696 template< typename Other, size_t Rows, size_t Cols >
3697 inline DynamicMatrix( const std::array<std::array<Other,Cols>,Rows>& array, const Alloc& alloc = Alloc{} );
3698
3699 inline DynamicMatrix( const DynamicMatrix& m );
3700 inline DynamicMatrix( DynamicMatrix&& m );
3701
3702 template< typename MT, bool SO >
3703 inline DynamicMatrix( const Matrix<MT,SO>& m );
3704 //@}
3705 //**********************************************************************************************
3706
3707 //**Destructor**********************************************************************************
3708 /*!\name Destructor */
3709 //@{
3710 inline ~DynamicMatrix();
3711 //@}
3712 //**********************************************************************************************
3713
3714 //**Data access functions***********************************************************************
3715 /*!\name Data access functions */
3716 //@{
3717 inline Reference operator()( size_t i, size_t j ) noexcept;
3718 inline ConstReference operator()( size_t i, size_t j ) const noexcept;
3719 inline Reference at( size_t i, size_t j );
3720 inline ConstReference at( size_t i, size_t j ) const;
3721 inline Pointer data () noexcept;
3722 inline ConstPointer data () const noexcept;
3723 inline Pointer data ( size_t j ) noexcept;
3724 inline ConstPointer data ( size_t j ) const noexcept;
3725 inline Iterator begin ( size_t j ) noexcept;
3726 inline ConstIterator begin ( size_t j ) const noexcept;
3727 inline ConstIterator cbegin( size_t j ) const noexcept;
3728 inline Iterator end ( size_t j ) noexcept;
3729 inline ConstIterator end ( size_t j ) const noexcept;
3730 inline ConstIterator cend ( size_t j ) const noexcept;
3731 //@}
3732 //**********************************************************************************************
3733
3734 //**Assignment operators************************************************************************
3735 /*!\name Assignment operators */
3736 //@{
3737 inline DynamicMatrix& operator=( const Type& rhs ) &;
3738 inline DynamicMatrix& operator=( initializer_list< initializer_list<Type> > list ) &;
3739
3740 template< typename Other, size_t Rows, size_t Cols >
3741 inline DynamicMatrix& operator=( const Other (&array)[Rows][Cols] ) &;
3742
3743 template< typename Other, size_t Rows, size_t Cols >
3744 inline DynamicMatrix& operator=( const std::array<std::array<Other,Cols>,Rows>& array ) &;
3745
3746 inline DynamicMatrix& operator=( const DynamicMatrix& rhs ) &;
3747 inline DynamicMatrix& operator=( DynamicMatrix&& rhs ) &;
3748
3749 template< typename MT, bool SO > inline DynamicMatrix& operator= ( const Matrix<MT,SO>& rhs ) &;
3750 template< typename MT, bool SO > inline DynamicMatrix& operator+=( const Matrix<MT,SO>& rhs ) &;
3751 template< typename MT, bool SO > inline DynamicMatrix& operator-=( const Matrix<MT,SO>& rhs ) &;
3752 template< typename MT, bool SO > inline DynamicMatrix& operator%=( const Matrix<MT,SO>& rhs ) &;
3753 //@}
3754 //**********************************************************************************************
3755
3756 //**Utility functions***************************************************************************
3757 /*!\name Utility functions */
3758 //@{
3759 inline size_t rows() const noexcept;
3760 inline size_t columns() const noexcept;
3761 inline size_t spacing() const noexcept;
3762 inline size_t capacity() const noexcept;
3763 inline size_t capacity( size_t j ) const noexcept;
3764 inline size_t nonZeros() const;
3765 inline size_t nonZeros( size_t j ) const;
3766 inline void reset();
3767 inline void reset( size_t j );
3768 inline void clear();
3769 void resize ( size_t m, size_t n, bool preserve=true );
3770 inline void extend ( size_t m, size_t n, bool preserve=true );
3771 inline void reserve( size_t elements );
3772 inline void shrinkToFit();
3773 inline void swap( DynamicMatrix& m ) noexcept;
3774 //@}
3775 //**********************************************************************************************
3776
3777 //**Numeric functions***************************************************************************
3778 /*!\name Numeric functions */
3779 //@{
3780 inline DynamicMatrix& transpose();
3781 inline DynamicMatrix& ctranspose();
3782
3783 template< typename Other > inline DynamicMatrix& scale( const Other& scalar );
3784 //@}
3785 //**********************************************************************************************
3786
3787 private:
3788 //**********************************************************************************************
3789 //! Helper variable template for the explicit application of the SFINAE principle.
3790 template< typename MT >
3791 static constexpr bool VectorizedAssign_v =
3792 ( useOptimizedKernels &&
3793 simdEnabled && MT::simdEnabled &&
3794 IsSIMDCombinable_v< Type, ElementType_t<MT> > );
3795 //**********************************************************************************************
3796
3797 //**********************************************************************************************
3798 //! Helper variable template for the explicit application of the SFINAE principle.
3799 template< typename MT >
3800 static constexpr bool VectorizedAddAssign_v =
3801 ( VectorizedAssign_v<MT> &&
3802 HasSIMDAdd_v< Type, ElementType_t<MT> > &&
3803 !IsDiagonal_v<MT> );
3804 //**********************************************************************************************
3805
3806 //**********************************************************************************************
3807 //! Helper variable template for the explicit application of the SFINAE principle.
3808 template< typename MT >
3809 static constexpr bool VectorizedSubAssign_v =
3810 ( VectorizedAssign_v<MT> &&
3811 HasSIMDSub_v< Type, ElementType_t<MT> > &&
3812 !IsDiagonal_v<MT> );
3813 //**********************************************************************************************
3814
3815 //**********************************************************************************************
3816 //! Helper variable template for the explicit application of the SFINAE principle.
3817 template< typename MT >
3818 static constexpr bool VectorizedSchurAssign_v =
3819 ( VectorizedAssign_v<MT> &&
3820 HasSIMDMult_v< Type, ElementType_t<MT> > );
3821 //**********************************************************************************************
3822
3823 //**********************************************************************************************
3824 //! The number of elements packed within a single SIMD element.
3825 static constexpr size_t SIMDSIZE = SIMDTrait<ElementType>::size;
3826 //**********************************************************************************************
3827
3828 public:
3829 //**Debugging functions*************************************************************************
3830 /*!\name Debugging functions */
3831 //@{
3832 inline bool isIntact() const noexcept;
3833 //@}
3834 //**********************************************************************************************
3835
3836 //**Expression template evaluation functions****************************************************
3837 /*!\name Expression template evaluation functions */
3838 //@{
3839 template< typename Other > inline bool canAlias ( const Other* alias ) const noexcept;
3840 template< typename Other > inline bool isAliased( const Other* alias ) const noexcept;
3841
3842 inline bool isAligned () const noexcept;
3843 inline bool canSMPAssign() const noexcept;
3844
3845 BLAZE_ALWAYS_INLINE SIMDType load ( size_t i, size_t j ) const noexcept;
3846 BLAZE_ALWAYS_INLINE SIMDType loada( size_t i, size_t j ) const noexcept;
3847 BLAZE_ALWAYS_INLINE SIMDType loadu( size_t i, size_t j ) const noexcept;
3848
3849 BLAZE_ALWAYS_INLINE void store ( size_t i, size_t j, const SIMDType& value ) noexcept;
3850 BLAZE_ALWAYS_INLINE void storea( size_t i, size_t j, const SIMDType& value ) noexcept;
3851 BLAZE_ALWAYS_INLINE void storeu( size_t i, size_t j, const SIMDType& value ) noexcept;
3852 BLAZE_ALWAYS_INLINE void stream( size_t i, size_t j, const SIMDType& value ) noexcept;
3853
3854 template< typename MT >
3855 inline auto assign( const DenseMatrix<MT,true>& rhs ) -> DisableIf_t< VectorizedAssign_v<MT> >;
3856
3857 template< typename MT >
3858 inline auto assign( const DenseMatrix<MT,true>& rhs ) -> EnableIf_t< VectorizedAssign_v<MT> >;
3859
3860 template< typename MT > inline void assign( const DenseMatrix<MT,false>& rhs );
3861 template< typename MT > inline void assign( const SparseMatrix<MT,true>& rhs );
3862 template< typename MT > inline void assign( const SparseMatrix<MT,false>& rhs );
3863
3864 template< typename MT >
3865 inline auto addAssign( const DenseMatrix<MT,true>& rhs ) -> DisableIf_t< VectorizedAddAssign_v<MT> >;
3866
3867 template< typename MT >
3868 inline auto addAssign( const DenseMatrix<MT,true>& rhs ) -> EnableIf_t< VectorizedAddAssign_v<MT> >;
3869
3870 template< typename MT > inline void addAssign( const DenseMatrix<MT,false>& rhs );
3871 template< typename MT > inline void addAssign( const SparseMatrix<MT,true>& rhs );
3872 template< typename MT > inline void addAssign( const SparseMatrix<MT,false>& rhs );
3873
3874 template< typename MT >
3875 inline auto subAssign ( const DenseMatrix<MT,true>& rhs ) -> DisableIf_t< VectorizedSubAssign_v<MT> >;
3876
3877 template< typename MT >
3878 inline auto subAssign ( const DenseMatrix<MT,true>& rhs ) -> EnableIf_t< VectorizedSubAssign_v<MT> >;
3879
3880 template< typename MT > inline void subAssign( const DenseMatrix<MT,false>& rhs );
3881 template< typename MT > inline void subAssign( const SparseMatrix<MT,true>& rhs );
3882 template< typename MT > inline void subAssign( const SparseMatrix<MT,false>& rhs );
3883
3884 template< typename MT >
3885 inline auto schurAssign ( const DenseMatrix<MT,true>& rhs ) -> DisableIf_t< VectorizedSchurAssign_v<MT> >;
3886
3887 template< typename MT >
3888 inline auto schurAssign ( const DenseMatrix<MT,true>& rhs ) -> EnableIf_t< VectorizedSchurAssign_v<MT> >;
3889
3890 template< typename MT > inline void schurAssign( const DenseMatrix<MT,false>& rhs );
3891 template< typename MT > inline void schurAssign( const SparseMatrix<MT,true>& rhs );
3892 template< typename MT > inline void schurAssign( const SparseMatrix<MT,false>& rhs );
3893 //@}
3894 //**********************************************************************************************
3895
3896 private:
3897 //**Uninitialized struct definition*************************************************************
3898 /*!\brief Definition of the nested auxiliary struct Uninitialized.
3899 */
3900 struct Uninitialized {};
3901 //**********************************************************************************************
3902
3903 //**Constructors********************************************************************************
3904 /*!\name Constructors */
3905 //@{
3906 inline DynamicMatrix( size_t m, size_t mm, size_t n, const Alloc& alloc, Uninitialized );
3907 inline DynamicMatrix( size_t m, size_t mm, size_t n, size_t capa, const Alloc& alloc, Uninitialized );
3908 //@}
3909 //**********************************************************************************************
3910
3911 //**Utility functions***************************************************************************
3912 /*!\name Utility functions */
3913 //@{
3914 inline size_t addPadding( size_t minRows ) const noexcept;
3915 //@}
3916 //**********************************************************************************************
3917
3918 //**Member variables****************************************************************************
3919 /*!\name Member variables */
3920 //@{
3921 size_t m_; //!< The current number of rows of the matrix.
3922 size_t mm_; //!< The alignment adjusted number of rows.
3923 size_t n_; //!< The current number of columns of the matrix.
3924 size_t capacity_; //!< The maximum capacity of the matrix.
3925
3926 Type* BLAZE_RESTRICT v_; //!< The dynamically allocated matrix elements.
3927 /*!< Access to the matrix elements is gained via the function
3928 call operator. */
3929
3930 BLAZE_NO_UNIQUE_ADDRESS Alloc alloc_; //!< The allocator of the matrix.
3931 //@}
3932 //**********************************************************************************************
3933
3934 //**Compile time checks*************************************************************************
3935 BLAZE_CONSTRAINT_MUST_NOT_BE_POINTER_TYPE ( Type );
3936 BLAZE_CONSTRAINT_MUST_NOT_BE_REFERENCE_TYPE( Type );
3937 BLAZE_CONSTRAINT_MUST_NOT_BE_CONST ( Type );
3938 BLAZE_CONSTRAINT_MUST_NOT_BE_VOLATILE ( Type );
3939 //**********************************************************************************************
3940 };
3941 /*! \endcond */
3942 //*************************************************************************************************
3943
3944
3945
3946
3947 //=================================================================================================
3948 //
3949 // CONSTRUCTORS
3950 //
3951 //=================================================================================================
3952
3953 //*************************************************************************************************
3954 /*! \cond BLAZE_INTERNAL */
3955 /*!\brief The (default) constructor for DynamicMatrix.
3956 //
3957 // \param alloc Allocator for all memory allocations of this matrix.
3958 */
3959 template< typename Type // Data type of the matrix
3960 , typename Alloc // Type of the allocator
3961 , typename Tag > // Type tag
DynamicMatrix(const Alloc & alloc)3962 inline DynamicMatrix<Type,true,Alloc,Tag>::DynamicMatrix( const Alloc& alloc ) noexcept
3963 : m_ ( 0UL ) // The current number of rows of the matrix
3964 , mm_ ( 0UL ) // The alignment adjusted number of rows
3965 , n_ ( 0UL ) // The current number of columns of the matrix
3966 , capacity_( 0UL ) // The maximum capacity of the matrix
3967 , v_ ( nullptr ) // The matrix elements
3968 , alloc_ ( alloc ) // The allocator of the matrix
3969 {}
3970 /*! \endcond */
3971 //*************************************************************************************************
3972
3973
3974 //*************************************************************************************************
3975 /*!\brief Auxiliary constructor for DynamicMatrix.
3976 //
3977 // \param m The number of rows of the matrix.
3978 // \param mm The alignment adjusted number of rows.
3979 // \param n The number of columns of the matrix.
3980 // \param alloc Allocator for all memory allocations of this matrix.
3981 // \exception std::bad_alloc Allocation failed.
3982 */
3983 template< typename Type // Data type of the matrix
3984 , typename Alloc // Type of the allocator
3985 , typename Tag > // Type tag
DynamicMatrix(size_t m,size_t mm,size_t n,const Alloc & alloc,Uninitialized)3986 inline DynamicMatrix<Type,true,Alloc,Tag>::DynamicMatrix( size_t m, size_t mm, size_t n, const Alloc& alloc, Uninitialized )
3987 : DynamicMatrix( m, mm, n, mm*n, alloc, Uninitialized{} )
3988 {}
3989 //*************************************************************************************************
3990
3991
3992 //*************************************************************************************************
3993 /*!\brief Auxiliary constructor for DynamicMatrix.
3994 //
3995 // \param m The number of rows of the matrix.
3996 // \param mm The alignment adjusted number of rows.
3997 // \param n The number of columns of the matrix.
3998 // \param capa The initial capacity of the matrix.
3999 // \param alloc Allocator for all memory allocations of this matrix.
4000 // \exception std::bad_alloc Allocation failed.
4001 */
4002 template< typename Type // Data type of the matrix
4003 , typename Alloc // Type of the allocator
4004 , typename Tag > // Type tag
DynamicMatrix(size_t m,size_t mm,size_t n,size_t capa,const Alloc & alloc,Uninitialized)4005 inline DynamicMatrix<Type,true,Alloc,Tag>::DynamicMatrix( size_t m, size_t mm, size_t n, size_t capa, const Alloc& alloc, Uninitialized )
4006 : m_ ( m ) // The current number of rows of the matrix
4007 , mm_ ( mm ) // The alignment adjusted number of rows
4008 , n_ ( n ) // The current number of columns of the matrix
4009 , capacity_( capa ) // The maximum capacity of the matrix
4010 , v_ ( nullptr ) // The matrix elements
4011 , alloc_ ( alloc ) // The allocator of the matrix
4012 {
4013 v_ = alloc_.allocate( capacity_ );
4014
4015 if( !checkAlignment( v_ ) ) {
4016 alloc_.deallocate( v_, capacity_ );
4017 BLAZE_THROW_BAD_ALLOC;
4018 }
4019 }
4020 //*************************************************************************************************
4021
4022
4023 //*************************************************************************************************
4024 /*! \cond BLAZE_INTERNAL */
4025 /*!\brief Constructor for a matrix of size \f$ m \times n \f$. For built-in types no initialization
4026 // is performed!
4027 //
4028 // \param m The number of rows of the matrix.
4029 // \param n The number of columns of the matrix.
4030 // \param alloc Allocator for all memory allocations of this matrix.
4031 //
4032 // \note This constructor is only responsible to allocate the required dynamic memory. For
4033 // built-in types no initialization of the elements is performed!
4034 */
4035 template< typename Type // Data type of the matrix
4036 , typename Alloc // Type of the allocator
4037 , typename Tag > // Type tag
DynamicMatrix(size_t m,size_t n,const Alloc & alloc)4038 inline DynamicMatrix<Type,true,Alloc,Tag>::DynamicMatrix( size_t m, size_t n, const Alloc& alloc )
4039 : DynamicMatrix( m, addPadding(m), n, alloc, Uninitialized{} )
4040 {
4041 using blaze::clear;
4042
4043 blaze::uninitialized_default_construct_n( v_, capacity_ );
4044
4045 if( IsVectorizable_v<Type> && IsBuiltin_v<Type> ) {
4046 for( size_t j=0UL; j<n_; ++j ) {
4047 for( size_t i=m_; i<mm_; ++i ) {
4048 clear( v_[i+j*mm_] );
4049 }
4050 }
4051 }
4052
4053 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
4054 }
4055 /*! \endcond */
4056 //*************************************************************************************************
4057
4058
4059 //*************************************************************************************************
4060 /*! \cond BLAZE_INTERNAL */
4061 /*!\brief Constructor for a homogenous initialization of all \f$ m \times n \f$ matrix elements.
4062 //
4063 // \param m The number of rows of the matrix.
4064 // \param n The number of columns of the matrix.
4065 // \param init The initial value of the matrix elements.
4066 // \param alloc Allocator for all memory allocations of this matrix.
4067 //
4068 // All matrix elements are initialized with the specified value.
4069 */
4070 template< typename Type // Data type of the matrix
4071 , typename Alloc // Type of the allocator
4072 , typename Tag > // Type tag
DynamicMatrix(size_t m,size_t n,const Type & init,const Alloc & alloc)4073 inline DynamicMatrix<Type,true,Alloc,Tag>::DynamicMatrix( size_t m, size_t n, const Type& init, const Alloc& alloc )
4074 : DynamicMatrix( m, n, alloc )
4075 {
4076 for( size_t j=0UL; j<n_; ++j ) {
4077 for( size_t i=0UL; i<m_; ++i ) {
4078 v_[i+j*mm_] = init;
4079 }
4080 }
4081
4082 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
4083 }
4084 /*! \endcond */
4085 //*************************************************************************************************
4086
4087
4088 //*************************************************************************************************
4089 /*! \cond BLAZE_INTERNAL */
4090 /*!\brief List initialization of all matrix elements.
4091 //
4092 // \param list The initializer list.
4093 // \param alloc Allocator for all memory allocations of this matrix.
4094 //
4095 // This constructor provides the option to explicitly initialize the elements of the matrix by
4096 // means of an initializer list:
4097
4098 \code
4099 using blaze::columnMajor;
4100
4101 blaze::DynamicMatrix<int,columnMajor> A{ { 1, 2, 3 },
4102 { 4, 5 },
4103 { 7, 8, 9 } };
4104 \endcode
4105
4106 // The matrix is sized according to the size of the initializer list and all its elements are
4107 // (copy) assigned the values of the given initializer list. Missing values are initialized as
4108 // default (as e.g. the value 6 in the example).
4109 */
4110 template< typename Type // Data type of the matrix
4111 , typename Alloc // Type of the allocator
4112 , typename Tag > // Type tag
DynamicMatrix(initializer_list<initializer_list<Type>> list,const Alloc & alloc)4113 inline DynamicMatrix<Type,true,Alloc,Tag>::DynamicMatrix( initializer_list< initializer_list<Type> > list, const Alloc& alloc )
4114 : DynamicMatrix( list.size(), determineColumns( list ), alloc )
4115 {
4116 using blaze::clear;
4117
4118 size_t i( 0UL );
4119
4120 for( const auto& rowList : list ) {
4121 size_t j( 0UL );
4122 for( const auto& element : rowList ) {
4123 v_[i+j*mm_] = element;
4124 ++j;
4125 }
4126 for( ; j<n_; ++j ) {
4127 clear( v_[i+j*mm_] );
4128 }
4129 ++i;
4130 }
4131
4132 BLAZE_INTERNAL_ASSERT( i == m_, "Invalid number of elements detected" );
4133 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
4134 }
4135 /*! \endcond */
4136 //*************************************************************************************************
4137
4138
4139 //*************************************************************************************************
4140 /*! \cond BLAZE_INTERNAL */
4141 /*!\brief Array initialization of all matrix elements.
4142 //
4143 // \param m The number of rows of the matrix.
4144 // \param n The number of columns of the matrix.
4145 // \param array Dynamic array for the initialization.
4146 // \param alloc Allocator for all memory allocations of this matrix.
4147 //
4148 // This constructor offers the option to directly initialize the elements of the matrix with
4149 // a dynamic array:
4150
4151 \code
4152 using blaze::columnMajor;
4153
4154 int* array = new int[20];
4155 // ... Initialization of the dynamic array
4156 blaze::DynamicMatrix<int,columnMajor> v( array, 5UL, 4UL );
4157 delete[] array;
4158 \endcode
4159
4160 // The matrix is sized according to the given size of the array and initialized with the values
4161 // from the given array. Note that it is expected that the given \a array has at least \a m by
4162 // \a n elements. Providing an array with less elements results in undefined behavior!
4163 */
4164 template< typename Type // Data type of the matrix
4165 , typename Alloc // Type of the allocator
4166 , typename Tag > // Type tag
4167 template< typename Other > // Data type of the initialization array
DynamicMatrix(size_t m,size_t n,const Other * array,const Alloc & alloc)4168 inline DynamicMatrix<Type,true,Alloc,Tag>::DynamicMatrix( size_t m, size_t n, const Other* array, const Alloc& alloc )
4169 : DynamicMatrix( m, n, alloc )
4170 {
4171 for( size_t j=0UL; j<n; ++j ) {
4172 for( size_t i=0UL; i<m; ++i ) {
4173 v_[i+j*mm_] = array[i+j*m];
4174 }
4175 }
4176
4177 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
4178 }
4179 /*! \endcond */
4180 //*************************************************************************************************
4181
4182
4183 //*************************************************************************************************
4184 /*! \cond BLAZE_INTERNAL */
4185 /*!\brief Array initialization of all matrix elements.
4186 //
4187 // \param array Static array for the initialization.
4188 // \param alloc Allocator for all memory allocations of this matrix.
4189 //
4190 // This constructor offers the option to directly initialize the elements of the matrix with
4191 // a static array:
4192
4193 \code
4194 using blaze::columnMajor;
4195
4196 const int init[3][3] = { { 1, 2, 3 },
4197 { 4, 5 },
4198 { 7, 8, 9 } };
4199 blaze::DynamicMatrix<int,columnMajor> A( init );
4200 \endcode
4201
4202 // The matrix is sized according to the size of the static array and initialized with the values
4203 // from the given static array. Missing values are initialized with default values (as e.g. the
4204 // value 6 in the example).
4205 */
4206 template< typename Type // Data type of the matrix
4207 , typename Alloc // Type of the allocator
4208 , typename Tag > // Type tag
4209 template< typename Other // Data type of the static array
4210 , size_t Rows // Number of rows of the static array
4211 , size_t Cols > // Number of columns of the static array
DynamicMatrix(const Other (& array)[Rows][Cols],const Alloc & alloc)4212 inline DynamicMatrix<Type,true,Alloc,Tag>::DynamicMatrix( const Other (&array)[Rows][Cols], const Alloc& alloc )
4213 : DynamicMatrix( Rows, Cols, alloc )
4214 {
4215 for( size_t j=0UL; j<Cols; ++j ) {
4216 for( size_t i=0UL; i<Rows; ++i ) {
4217 v_[i+j*mm_] = array[i][j];
4218 }
4219 }
4220
4221 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
4222 }
4223 /*! \endcond */
4224 //*************************************************************************************************
4225
4226
4227 //*************************************************************************************************
4228 /*! \cond BLAZE_INTERNAL */
4229 /*!\brief Initialization of all matrix elements from the given std::array.
4230 //
4231 // \param array The given std::array for the initialization.
4232 // \param alloc Allocator for all memory allocations of this matrix.
4233 //
4234 // This constructor offers the option to directly initialize the elements of the matrix with
4235 // a std::array:
4236
4237 \code
4238 using blaze::columnMajor;
4239
4240 const std::array<std::array<int,3UL>,3UL> init{ { { 1, 2, 3 },
4241 { 4, 5 },
4242 { 7, 8, 9 } } };
4243 blaze::DynamicMatrix<int,columnMajor> A( init );
4244 \endcode
4245
4246 // The matrix is sized according to the size of the std::array and initialized with the values
4247 // from the given std::array. Missing values are initialized with default values (as e.g. the
4248 // value 6 in the example).
4249 */
4250 template< typename Type // Data type of the matrix
4251 , typename Alloc // Type of the allocator
4252 , typename Tag > // Type tag
4253 template< typename Other // Data type of the std::array
4254 , size_t Rows // Number of rows of the std::array
4255 , size_t Cols > // Number of columns of the std::array
DynamicMatrix(const std::array<std::array<Other,Cols>,Rows> & array,const Alloc & alloc)4256 inline DynamicMatrix<Type,true,Alloc,Tag>::DynamicMatrix( const std::array<std::array<Other,Cols>,Rows>& array, const Alloc& alloc )
4257 : DynamicMatrix( Rows, Cols, alloc )
4258 {
4259 for( size_t j=0UL; j<Cols; ++j ) {
4260 for( size_t i=0UL; i<Rows; ++i ) {
4261 v_[i+j*mm_] = array[i][j];
4262 }
4263 }
4264
4265 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
4266 }
4267 /*! \endcond */
4268 //*************************************************************************************************
4269
4270
4271 //*************************************************************************************************
4272 /*! \cond BLAZE_INTERNAL */
4273 /*!\brief The copy constructor for DynamicMatrix.
4274 //
4275 // \param m Matrix to be copied.
4276 //
4277 // The copy constructor is explicitly defined due to the required dynamic memory management
4278 // and in order to enable/facilitate NRV optimization.
4279 */
4280 template< typename Type // Data type of the matrix
4281 , typename Alloc // Type of the allocator
4282 , typename Tag > // Type tag
DynamicMatrix(const DynamicMatrix & m)4283 inline DynamicMatrix<Type,true,Alloc,Tag>::DynamicMatrix( const DynamicMatrix& m )
4284 : DynamicMatrix( m.m_, m.n_ )
4285 {
4286 BLAZE_INTERNAL_ASSERT( capacity_ <= m.capacity_, "Invalid capacity estimation" );
4287
4288 smpAssign( *this, m );
4289
4290 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
4291 }
4292 /*! \endcond */
4293 //*************************************************************************************************
4294
4295
4296 //*************************************************************************************************
4297 /*! \cond BLAZE_INTERNAL */
4298 /*!\brief The move constructor for DynamicMatrix.
4299 //
4300 // \param m The matrix to be moved into this instance.
4301 */
4302 template< typename Type // Data type of the matrix
4303 , typename Alloc // Type of the allocator
4304 , typename Tag > // Type tag
DynamicMatrix(DynamicMatrix && m)4305 inline DynamicMatrix<Type,true,Alloc,Tag>::DynamicMatrix( DynamicMatrix&& m )
4306 : m_ ( m.m_ ) // The current number of rows of the matrix
4307 , mm_ ( m.mm_ ) // The alignment adjusted number of rows
4308 , n_ ( m.n_ ) // The current number of columns of the matrix
4309 , capacity_( m.capacity_ ) // The maximum capacity of the matrix
4310 , v_ ( m.v_ ) // The matrix elements
4311 {
4312 m.m_ = 0UL;
4313 m.mm_ = 0UL;
4314 m.n_ = 0UL;
4315 m.capacity_ = 0UL;
4316 m.v_ = nullptr;
4317 }
4318 /*! \endcond */
4319 //*************************************************************************************************
4320
4321
4322 //*************************************************************************************************
4323 /*! \cond BLAZE_INTERNAL */
4324 /*!\brief Conversion constructor from different matrices.
4325 //
4326 // \param m Matrix to be copied.
4327 */
4328 template< typename Type // Data type of the matrix
4329 , typename Alloc // Type of the allocator
4330 , typename Tag > // Type tag
4331 template< typename MT // Type of the foreign matrix
4332 , bool SO > // Storage order of the foreign matrix
DynamicMatrix(const Matrix<MT,SO> & m)4333 inline DynamicMatrix<Type,true,Alloc,Tag>::DynamicMatrix( const Matrix<MT,SO>& m )
4334 : DynamicMatrix( (*m).rows(), (*m).columns() )
4335 {
4336 BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<MT> );
4337
4338 if( IsSparseMatrix_v<MT> && IsBuiltin_v<Type> ) {
4339 reset();
4340 }
4341
4342 smpAssign( *this, *m );
4343
4344 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
4345 }
4346 /*! \endcond */
4347 //*************************************************************************************************
4348
4349
4350
4351
4352 //=================================================================================================
4353 //
4354 // DESTRUCTOR
4355 //
4356 //=================================================================================================
4357
4358 //*************************************************************************************************
4359 /*! \cond BLAZE_INTERNAL */
4360 /*!\brief The destructor for DynamicMatrix.
4361 */
4362 template< typename Type // Data type of the matrix
4363 , typename Alloc // Type of the allocator
4364 , typename Tag > // Type tag
~DynamicMatrix()4365 inline DynamicMatrix<Type,true,Alloc,Tag>::~DynamicMatrix()
4366 {
4367 blaze::destroy_n( v_, capacity_ );
4368 alloc_.deallocate( v_, capacity_ );
4369 }
4370 /*! \endcond */
4371 //*************************************************************************************************
4372
4373
4374
4375
4376 //=================================================================================================
4377 //
4378 // DATA ACCESS FUNCTIONS
4379 //
4380 //=================================================================================================
4381
4382 //*************************************************************************************************
4383 /*! \cond BLAZE_INTERNAL */
4384 /*!\brief 2D-access to the matrix elements.
4385 //
4386 // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
4387 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
4388 // \return Reference to the accessed value.
4389 //
4390 // This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
4391 // the at() function is guaranteed to perform a check of the given access indices.
4392 */
4393 template< typename Type // Data type of the matrix
4394 , typename Alloc // Type of the allocator
4395 , typename Tag > // Type tag
4396 inline typename DynamicMatrix<Type,true,Alloc,Tag>::Reference
operator()4397 DynamicMatrix<Type,true,Alloc,Tag>::operator()( size_t i, size_t j ) noexcept
4398 {
4399 BLAZE_USER_ASSERT( i<m_, "Invalid row access index" );
4400 BLAZE_USER_ASSERT( j<n_, "Invalid column access index" );
4401 return v_[i+j*mm_];
4402 }
4403 /*! \endcond */
4404 //*************************************************************************************************
4405
4406
4407 //*************************************************************************************************
4408 /*! \cond BLAZE_INTERNAL */
4409 /*!\brief 2D-access to the matrix elements.
4410 //
4411 // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
4412 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
4413 // \return Reference to the accessed value.
4414 //
4415 // This function only performs an index check in case BLAZE_USER_ASSERT() is active. In contrast,
4416 // the at() function is guaranteed to perform a check of the given access indices.
4417 */
4418 template< typename Type // Data type of the matrix
4419 , typename Alloc // Type of the allocator
4420 , typename Tag > // Type tag
4421 inline typename DynamicMatrix<Type,true,Alloc,Tag>::ConstReference
operator()4422 DynamicMatrix<Type,true,Alloc,Tag>::operator()( size_t i, size_t j ) const noexcept
4423 {
4424 BLAZE_USER_ASSERT( i<m_, "Invalid row access index" );
4425 BLAZE_USER_ASSERT( j<n_, "Invalid column access index" );
4426 return v_[i+j*mm_];
4427 }
4428 /*! \endcond */
4429 //*************************************************************************************************
4430
4431
4432 //*************************************************************************************************
4433 /*! \cond BLAZE_INTERNAL */
4434 /*!\brief Checked access to the matrix elements.
4435 //
4436 // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
4437 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
4438 // \return Reference to the accessed value.
4439 // \exception std::out_of_range Invalid matrix access index.
4440 //
4441 // In contrast to the subscript operator this function always performs a check of the given
4442 // access indices.
4443 */
4444 template< typename Type // Data type of the matrix
4445 , typename Alloc // Type of the allocator
4446 , typename Tag > // Type tag
4447 inline typename DynamicMatrix<Type,true,Alloc,Tag>::Reference
at(size_t i,size_t j)4448 DynamicMatrix<Type,true,Alloc,Tag>::at( size_t i, size_t j )
4449 {
4450 if( i >= m_ ) {
4451 BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
4452 }
4453 if( j >= n_ ) {
4454 BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
4455 }
4456 return (*this)(i,j);
4457 }
4458 /*! \endcond */
4459 //*************************************************************************************************
4460
4461
4462 //*************************************************************************************************
4463 /*! \cond BLAZE_INTERNAL */
4464 /*!\brief Checked access to the matrix elements.
4465 //
4466 // \param i Access index for the row. The index has to be in the range \f$[0..M-1]\f$.
4467 // \param j Access index for the column. The index has to be in the range \f$[0..N-1]\f$.
4468 // \return Reference to the accessed value.
4469 // \exception std::out_of_range Invalid matrix access index.
4470 //
4471 // In contrast to the subscript operator this function always performs a check of the given
4472 // access indices.
4473 */
4474 template< typename Type // Data type of the matrix
4475 , typename Alloc // Type of the allocator
4476 , typename Tag > // Type tag
4477 inline typename DynamicMatrix<Type,true,Alloc,Tag>::ConstReference
at(size_t i,size_t j)4478 DynamicMatrix<Type,true,Alloc,Tag>::at( size_t i, size_t j ) const
4479 {
4480 if( i >= m_ ) {
4481 BLAZE_THROW_OUT_OF_RANGE( "Invalid row access index" );
4482 }
4483 if( j >= n_ ) {
4484 BLAZE_THROW_OUT_OF_RANGE( "Invalid column access index" );
4485 }
4486 return (*this)(i,j);
4487 }
4488 /*! \endcond */
4489 //*************************************************************************************************
4490
4491
4492 //*************************************************************************************************
4493 /*! \cond BLAZE_INTERNAL */
4494 /*!\brief Low-level data access to the matrix elements.
4495 //
4496 // \return Pointer to the internal element storage.
4497 //
4498 // This function returns a pointer to the internal storage of the dynamic matrix. Note that you
4499 // can NOT assume that all matrix elements lie adjacent to each other! The dynamic matrix may
4500 // use techniques such as padding to improve the alignment of the data. Whereas the number of
4501 // elements within a column are given by the \c columns() member functions, the total number
4502 // of elements including padding is given by the \c spacing() member function.
4503 */
4504 template< typename Type // Data type of the matrix
4505 , typename Alloc // Type of the allocator
4506 , typename Tag > // Type tag
4507 inline typename DynamicMatrix<Type,true,Alloc,Tag>::Pointer
data()4508 DynamicMatrix<Type,true,Alloc,Tag>::data() noexcept
4509 {
4510 return v_;
4511 }
4512 /*! \endcond */
4513 //*************************************************************************************************
4514
4515
4516 //*************************************************************************************************
4517 /*! \cond BLAZE_INTERNAL */
4518 /*!\brief Low-level data access to the matrix elements.
4519 //
4520 // \return Pointer to the internal element storage.
4521 //
4522 // This function returns a pointer to the internal storage of the dynamic matrix. Note that you
4523 // can NOT assume that all matrix elements lie adjacent to each other! The dynamic matrix may
4524 // use techniques such as padding to improve the alignment of the data. Whereas the number of
4525 // elements within a column are given by the \c columns() member functions, the total number
4526 // of elements including padding is given by the \c spacing() member function.
4527 */
4528 template< typename Type // Data type of the matrix
4529 , typename Alloc // Type of the allocator
4530 , typename Tag > // Type tag
4531 inline typename DynamicMatrix<Type,true,Alloc,Tag>::ConstPointer
data()4532 DynamicMatrix<Type,true,Alloc,Tag>::data() const noexcept
4533 {
4534 return v_;
4535 }
4536 /*! \endcond */
4537 //*************************************************************************************************
4538
4539
4540 //*************************************************************************************************
4541 /*! \cond BLAZE_INTERNAL */
4542 /*!\brief Low-level data access to the matrix elements of column \a j.
4543 //
4544 // \param j The column index.
4545 // \return Pointer to the internal element storage.
4546 //
4547 // This function returns a pointer to the internal storage for the elements in column \a j.
4548 */
4549 template< typename Type // Data type of the matrix
4550 , typename Alloc // Type of the allocator
4551 , typename Tag > // Type tag
4552 inline typename DynamicMatrix<Type,true,Alloc,Tag>::Pointer
data(size_t j)4553 DynamicMatrix<Type,true,Alloc,Tag>::data( size_t j ) noexcept
4554 {
4555 BLAZE_USER_ASSERT( j < n_, "Invalid dense matrix column access index" );
4556 return v_ + j*mm_;
4557 }
4558 /*! \endcond */
4559 //*************************************************************************************************
4560
4561
4562 //*************************************************************************************************
4563 /*! \cond BLAZE_INTERNAL */
4564 /*!\brief Low-level data access to the matrix elements of column \a j.
4565 //
4566 // \param j The column index.
4567 // \return Pointer to the internal element storage.
4568 //
4569 // This function returns a pointer to the internal storage for the elements in column \a j.
4570 */
4571 template< typename Type // Data type of the matrix
4572 , typename Alloc // Type of the allocator
4573 , typename Tag > // Type tag
4574 inline typename DynamicMatrix<Type,true,Alloc,Tag>::ConstPointer
data(size_t j)4575 DynamicMatrix<Type,true,Alloc,Tag>::data( size_t j ) const noexcept
4576 {
4577 BLAZE_USER_ASSERT( j < n_, "Invalid dense matrix column access index" );
4578 return v_ + j*mm_;
4579 }
4580 /*! \endcond */
4581 //*************************************************************************************************
4582
4583
4584 //*************************************************************************************************
4585 /*! \cond BLAZE_INTERNAL */
4586 /*!\brief Returns an iterator to the first element of column \a j.
4587 //
4588 // \param j The column index.
4589 // \return Iterator to the first element of column \a j.
4590 */
4591 template< typename Type // Data type of the matrix
4592 , typename Alloc // Type of the allocator
4593 , typename Tag > // Type tag
4594 inline typename DynamicMatrix<Type,true,Alloc,Tag>::Iterator
begin(size_t j)4595 DynamicMatrix<Type,true,Alloc,Tag>::begin( size_t j ) noexcept
4596 {
4597 BLAZE_USER_ASSERT( j < n_, "Invalid dense matrix column access index" );
4598 return Iterator( v_ + j*mm_ );
4599 }
4600 /*! \endcond */
4601 //*************************************************************************************************
4602
4603
4604 //*************************************************************************************************
4605 /*! \cond BLAZE_INTERNAL */
4606 /*!\brief Returns an iterator to the first element of column \a j.
4607 //
4608 // \param j The column index.
4609 // \return Iterator to the first element of column \a j.
4610 */
4611 template< typename Type // Data type of the matrix
4612 , typename Alloc // Type of the allocator
4613 , typename Tag > // Type tag
4614 inline typename DynamicMatrix<Type,true,Alloc,Tag>::ConstIterator
begin(size_t j)4615 DynamicMatrix<Type,true,Alloc,Tag>::begin( size_t j ) const noexcept
4616 {
4617 BLAZE_USER_ASSERT( j < n_, "Invalid dense matrix column access index" );
4618 return ConstIterator( v_ + j*mm_ );
4619 }
4620 /*! \endcond */
4621 //*************************************************************************************************
4622
4623
4624 //*************************************************************************************************
4625 /*! \cond BLAZE_INTERNAL */
4626 /*!\brief Returns an iterator to the first element of column \a j.
4627 //
4628 // \param j The column index.
4629 // \return Iterator to the first element of column \a j.
4630 */
4631 template< typename Type // Data type of the matrix
4632 , typename Alloc // Type of the allocator
4633 , typename Tag > // Type tag
4634 inline typename DynamicMatrix<Type,true,Alloc,Tag>::ConstIterator
cbegin(size_t j)4635 DynamicMatrix<Type,true,Alloc,Tag>::cbegin( size_t j ) const noexcept
4636 {
4637 BLAZE_USER_ASSERT( j < n_, "Invalid dense matrix column access index" );
4638 return ConstIterator( v_ + j*mm_ );
4639 }
4640 /*! \endcond */
4641 //*************************************************************************************************
4642
4643
4644 //*************************************************************************************************
4645 /*! \cond BLAZE_INTERNAL */
4646 /*!\brief Returns an iterator just past the last element of column \a j.
4647 //
4648 // \param j The column index.
4649 // \return Iterator just past the last element of column \a j.
4650 */
4651 template< typename Type // Data type of the matrix
4652 , typename Alloc // Type of the allocator
4653 , typename Tag > // Type tag
4654 inline typename DynamicMatrix<Type,true,Alloc,Tag>::Iterator
end(size_t j)4655 DynamicMatrix<Type,true,Alloc,Tag>::end( size_t j ) noexcept
4656 {
4657 BLAZE_USER_ASSERT( j < n_, "Invalid dense matrix column access index" );
4658 return Iterator( v_ + j*mm_ + m_ );
4659 }
4660 /*! \endcond */
4661 //*************************************************************************************************
4662
4663
4664 //*************************************************************************************************
4665 /*! \cond BLAZE_INTERNAL */
4666 /*!\brief Returns an iterator just past the last element of column \a j.
4667 //
4668 // \param j The column index.
4669 // \return Iterator just past the last element of column \a j.
4670 */
4671 template< typename Type // Data type of the matrix
4672 , typename Alloc // Type of the allocator
4673 , typename Tag > // Type tag
4674 inline typename DynamicMatrix<Type,true,Alloc,Tag>::ConstIterator
end(size_t j)4675 DynamicMatrix<Type,true,Alloc,Tag>::end( size_t j ) const noexcept
4676 {
4677 BLAZE_USER_ASSERT( j < n_, "Invalid dense matrix column access index" );
4678 return ConstIterator( v_ + j*mm_ + m_ );
4679 }
4680 /*! \endcond */
4681 //*************************************************************************************************
4682
4683
4684 //*************************************************************************************************
4685 /*! \cond BLAZE_INTERNAL */
4686 /*!\brief Returns an iterator just past the last element of column \a j.
4687 //
4688 // \param j The column index.
4689 // \return Iterator just past the last element of column \a j.
4690 */
4691 template< typename Type // Data type of the matrix
4692 , typename Alloc // Type of the allocator
4693 , typename Tag > // Type tag
4694 inline typename DynamicMatrix<Type,true,Alloc,Tag>::ConstIterator
cend(size_t j)4695 DynamicMatrix<Type,true,Alloc,Tag>::cend( size_t j ) const noexcept
4696 {
4697 BLAZE_USER_ASSERT( j < n_, "Invalid dense matrix column access index" );
4698 return ConstIterator( v_ + j*mm_ + m_ );
4699 }
4700 /*! \endcond */
4701 //*************************************************************************************************
4702
4703
4704
4705
4706 //=================================================================================================
4707 //
4708 // ASSIGNMENT OPERATORS
4709 //
4710 //=================================================================================================
4711
4712 //*************************************************************************************************
4713 /*! \cond BLAZE_INTERNAL */
4714 /*!\brief Homogenous assignment to all matrix elements.
4715 //
4716 // \param rhs Scalar value to be assigned to all matrix elements.
4717 // \return Reference to the assigned matrix.
4718 */
4719 template< typename Type // Data type of the matrix
4720 , typename Alloc // Type of the allocator
4721 , typename Tag > // Type tag
4722 inline DynamicMatrix<Type,true,Alloc,Tag>&
4723 DynamicMatrix<Type,true,Alloc,Tag>::operator=( const Type& rhs ) &
4724 {
4725 for( size_t j=0UL; j<n_; ++j )
4726 for( size_t i=0UL; i<m_; ++i )
4727 v_[i+j*mm_] = rhs;
4728
4729 return *this;
4730 }
4731 /*! \endcond */
4732 //*************************************************************************************************
4733
4734
4735 //*************************************************************************************************
4736 /*! \cond BLAZE_INTERNAL */
4737 /*!\brief List assignment to all matrix elements.
4738 //
4739 // \param list The initializer list.
4740 //
4741 // This assignment operator offers the option to directly assign to all elements of the matrix
4742 // by means of an initializer list:
4743
4744 \code
4745 using blaze::columnMajor;
4746
4747 blaze::DynamicMatrix<int,columnMajor> A;
4748 A = { { 1, 2, 3 },
4749 { 4, 5 },
4750 { 7, 8, 9 } };
4751 \endcode
4752
4753 // The matrix is resized according to the given initializer list and all its elements are
4754 // (copy) assigned the values from the given initializer list. Missing values are initialized
4755 // as default (as e.g. the value 6 in the example).
4756 */
4757 template< typename Type // Data type of the matrix
4758 , typename Alloc // Type of the allocator
4759 , typename Tag > // Type tag
4760 inline DynamicMatrix<Type,true,Alloc,Tag>&
4761 DynamicMatrix<Type,true,Alloc,Tag>::operator=( initializer_list< initializer_list<Type> > list ) &
4762 {
4763 using blaze::clear;
4764
4765 resize( list.size(), determineColumns( list ), false );
4766
4767 size_t i( 0UL );
4768
4769 for( const auto& rowList : list ) {
4770 size_t j( 0UL );
4771 for( const auto& element : rowList ) {
4772 v_[i+j*mm_] = element;
4773 ++j;
4774 }
4775 for( ; j<n_; ++j ) {
4776 clear( v_[i+j*mm_] );
4777 }
4778 ++i;
4779 }
4780
4781 return *this;
4782 }
4783 /*! \endcond */
4784 //*************************************************************************************************
4785
4786
4787 //*************************************************************************************************
4788 /*! \cond BLAZE_INTERNAL */
4789 /*!\brief Array assignment to all matrix elements.
4790 //
4791 // \param array Static array for the assignment.
4792 // \return Reference to the assigned matrix.
4793 //
4794 // This assignment operator offers the option to directly set all elements of the matrix:
4795
4796 \code
4797 using blaze::columnMajor;
4798
4799 const int init[3][3] = { { 1, 2, 3 },
4800 { 4, 5 },
4801 { 7, 8, 9 } };
4802 blaze::DynamicMatrix<int,columnMajor> A;
4803 A = init;
4804 \endcode
4805
4806 // The matrix is resized according to the size of the static array and assigned the values of the
4807 // given static array. Missing values are initialized with default values (as e.g. the value 6 in
4808 // the example).
4809 */
4810 template< typename Type // Data type of the matrix
4811 , typename Alloc // Type of the allocator
4812 , typename Tag > // Type tag
4813 template< typename Other // Data type of the static array
4814 , size_t Rows // Number of rows of the static array
4815 , size_t Cols > // Number of columns of the static array
4816 inline DynamicMatrix<Type,true,Alloc,Tag>&
4817 DynamicMatrix<Type,true,Alloc,Tag>::operator=( const Other (&array)[Rows][Cols] ) &
4818 {
4819 resize( Rows, Cols, false );
4820
4821 for( size_t j=0UL; j<Cols; ++j )
4822 for( size_t i=0UL; i<Rows; ++i )
4823 v_[i+j*mm_] = array[i][j];
4824
4825 return *this;
4826 }
4827 /*! \endcond */
4828 //*************************************************************************************************
4829
4830
4831 //*************************************************************************************************
4832 /*! \cond BLAZE_INTERNAL */
4833 /*!\brief Array assignment to all matrix elements.
4834 //
4835 // \param array The given std::array for the assignment.
4836 // \return Reference to the assigned matrix.
4837 //
4838 // This assignment operator offers the option to directly set all elements of the matrix:
4839
4840 \code
4841 using blaze::columnMajor;
4842
4843 const std::array<std::array<int,3UL>,3UL> init{ { { 1, 2, 3 },
4844 { 4, 5 },
4845 { 7, 8, 9 } };
4846 blaze::DynamicMatrix<int,columnMajor> A;
4847 A = init;
4848 \endcode
4849
4850 // The matrix is resized according to the size of the std::array and assigned the values of the
4851 // given std::array. Missing values are initialized with default values (as e.g. the value 6 in
4852 // the example).
4853 */
4854 template< typename Type // Data type of the matrix
4855 , typename Alloc // Type of the allocator
4856 , typename Tag > // Type tag
4857 template< typename Other // Data type of the std::array
4858 , size_t Rows // Number of rows of the std::array
4859 , size_t Cols > // Number of columns of the std::array
4860 inline DynamicMatrix<Type,true,Alloc,Tag>&
4861 DynamicMatrix<Type,true,Alloc,Tag>::operator=( const std::array<std::array<Other,Cols>,Rows>& array ) &
4862 {
4863 resize( Rows, Cols, false );
4864
4865 for( size_t j=0UL; j<Cols; ++j )
4866 for( size_t i=0UL; i<Rows; ++i )
4867 v_[i+j*mm_] = array[i][j];
4868
4869 return *this;
4870 }
4871 /*! \endcond */
4872 //*************************************************************************************************
4873
4874
4875 //*************************************************************************************************
4876 /*! \cond BLAZE_INTERNAL */
4877 /*!\brief Copy assignment operator for DynamicMatrix.
4878 //
4879 // \param rhs Matrix to be copied.
4880 // \return Reference to the assigned matrix.
4881 //
4882 // The matrix is resized according to the given \f$ M \times N \f$ matrix and initialized as a
4883 // copy of this matrix.
4884 */
4885 template< typename Type // Data type of the matrix
4886 , typename Alloc // Type of the allocator
4887 , typename Tag > // Type tag
4888 inline DynamicMatrix<Type,true,Alloc,Tag>&
4889 DynamicMatrix<Type,true,Alloc,Tag>::operator=( const DynamicMatrix& rhs ) &
4890 {
4891 if( &rhs == this ) return *this;
4892
4893 resize( rhs.m_, rhs.n_, false );
4894 smpAssign( *this, *rhs );
4895
4896 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
4897
4898 return *this;
4899 }
4900 /*! \endcond */
4901 //*************************************************************************************************
4902
4903
4904 //*************************************************************************************************
4905 /*! \cond BLAZE_INTERNAL */
4906 /*!\brief Move assignment operator for DynamicMatrix.
4907 //
4908 // \param rhs The matrix to be moved into this instance.
4909 // \return Reference to the assigned matrix.
4910 */
4911 template< typename Type // Data type of the matrix
4912 , typename Alloc // Type of the allocator
4913 , typename Tag > // Type tag
4914 inline DynamicMatrix<Type,true,Alloc,Tag>&
4915 DynamicMatrix<Type,true,Alloc,Tag>::operator=( DynamicMatrix&& rhs ) &
4916 {
4917 blaze::destroy_n( v_, capacity_ );
4918 alloc_.deallocate( v_, capacity_ );
4919
4920 m_ = rhs.m_;
4921 mm_ = rhs.mm_;
4922 n_ = rhs.n_;
4923 capacity_ = rhs.capacity_;
4924 v_ = rhs.v_;
4925
4926 rhs.m_ = 0UL;
4927 rhs.mm_ = 0UL;
4928 rhs.n_ = 0UL;
4929 rhs.capacity_ = 0UL;
4930 rhs.v_ = nullptr;
4931
4932 return *this;
4933 }
4934 /*! \endcond */
4935 //*************************************************************************************************
4936
4937
4938 //*************************************************************************************************
4939 /*! \cond BLAZE_INTERNAL */
4940 /*!\brief Assignment operator for different matrices.
4941 //
4942 // \param rhs Matrix to be copied.
4943 // \return Reference to the assigned matrix.
4944 //
4945 // The matrix is resized according to the given \f$ M \times N \f$ matrix and initialized as a
4946 // copy of this matrix.
4947 */
4948 template< typename Type // Data type of the matrix
4949 , typename Alloc // Type of the allocator
4950 , typename Tag > // Type tag
4951 template< typename MT // Type of the right-hand side matrix
4952 , bool SO > // Storage order of the right-hand side matrix
4953 inline DynamicMatrix<Type,true,Alloc,Tag>&
4954 DynamicMatrix<Type,true,Alloc,Tag>::operator=( const Matrix<MT,SO>& rhs ) &
4955 {
4956 using TT = decltype( trans( *this ) );
4957 using CT = decltype( ctrans( *this ) );
4958 using IT = decltype( inv( *this ) );
4959
4960 BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<MT> );
4961
4962 if( IsSame_v<MT,TT> && (*rhs).isAliased( this ) ) {
4963 transpose();
4964 }
4965 else if( IsSame_v<MT,CT> && (*rhs).isAliased( this ) ) {
4966 ctranspose();
4967 }
4968 else if( !IsSame_v<MT,IT> && (*rhs).canAlias( this ) ) {
4969 DynamicMatrix tmp( *rhs );
4970 swap( tmp );
4971 }
4972 else {
4973 resize( (*rhs).rows(), (*rhs).columns(), false );
4974 if( IsSparseMatrix_v<MT> )
4975 reset();
4976 smpAssign( *this, *rhs );
4977 }
4978
4979 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
4980
4981 return *this;
4982 }
4983 /*! \endcond */
4984 //*************************************************************************************************
4985
4986
4987 //*************************************************************************************************
4988 /*! \cond BLAZE_INTERNAL */
4989 /*!\brief Addition assignment operator for the addition of a matrix (\f$ A+=B \f$).
4990 //
4991 // \param rhs The right-hand side matrix to be added to the matrix.
4992 // \return Reference to the matrix.
4993 // \exception std::invalid_argument Matrix sizes do not match.
4994 //
4995 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
4996 // is thrown.
4997 */
4998 template< typename Type // Data type of the matrix
4999 , typename Alloc // Type of the allocator
5000 , typename Tag > // Type tag
5001 template< typename MT // Type of the right-hand side matrix
5002 , bool SO > // Storage order of the right-hand side matrix
5003 inline DynamicMatrix<Type,true,Alloc,Tag>&
5004 DynamicMatrix<Type,true,Alloc,Tag>::operator+=( const Matrix<MT,SO>& rhs ) &
5005 {
5006 BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<MT> );
5007
5008 if( (*rhs).rows() != m_ || (*rhs).columns() != n_ ) {
5009 BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
5010 }
5011
5012 if( (*rhs).canAlias( this ) ) {
5013 const ResultType_t<MT> tmp( *rhs );
5014 smpAddAssign( *this, tmp );
5015 }
5016 else {
5017 smpAddAssign( *this, *rhs );
5018 }
5019
5020 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
5021
5022 return *this;
5023 }
5024 /*! \endcond */
5025 //*************************************************************************************************
5026
5027
5028 //*************************************************************************************************
5029 /*! \cond BLAZE_INTERNAL */
5030 /*!\brief Subtraction assignment operator for the subtraction of a matrix (\f$ A-=B \f$).
5031 //
5032 // \param rhs The right-hand side matrix to be subtracted from the matrix.
5033 // \return Reference to the matrix.
5034 // \exception std::invalid_argument Matrix sizes do not match.
5035 //
5036 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
5037 // is thrown.
5038 */
5039 template< typename Type // Data type of the matrix
5040 , typename Alloc // Type of the allocator
5041 , typename Tag > // Type tag
5042 template< typename MT // Type of the right-hand side matrix
5043 , bool SO > // Storage order of the right-hand side matrix
5044 inline DynamicMatrix<Type,true,Alloc,Tag>&
5045 DynamicMatrix<Type,true,Alloc,Tag>::operator-=( const Matrix<MT,SO>& rhs ) &
5046 {
5047 BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<MT> );
5048
5049 if( (*rhs).rows() != m_ || (*rhs).columns() != n_ ) {
5050 BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
5051 }
5052
5053 if( (*rhs).canAlias( this ) ) {
5054 const ResultType_t<MT> tmp( *rhs );
5055 smpSubAssign( *this, tmp );
5056 }
5057 else {
5058 smpSubAssign( *this, *rhs );
5059 }
5060
5061 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
5062
5063 return *this;
5064 }
5065 /*! \endcond */
5066 //*************************************************************************************************
5067
5068
5069 //*************************************************************************************************
5070 /*! \cond BLAZE_INTERNAL */
5071 /*!\brief Schur product assignment operator for the multiplication of a matrix (\f$ A\circ=B \f$).
5072 //
5073 // \param rhs The right-hand side matrix for the Schur product.
5074 // \return Reference to the matrix.
5075 // \exception std::invalid_argument Matrix sizes do not match.
5076 //
5077 // In case the current sizes of the two matrices don't match, a \a std::invalid_argument exception
5078 // is thrown.
5079 */
5080 template< typename Type // Data type of the matrix
5081 , typename Alloc // Type of the allocator
5082 , typename Tag > // Type tag
5083 template< typename MT // Type of the right-hand side matrix
5084 , bool SO > // Storage order of the right-hand side matrix
5085 inline DynamicMatrix<Type,true,Alloc,Tag>&
5086 DynamicMatrix<Type,true,Alloc,Tag>::operator%=( const Matrix<MT,SO>& rhs ) &
5087 {
5088 BLAZE_CONSTRAINT_MUST_BE_SAME_TAG( Tag, TagType_t<MT> );
5089
5090 if( (*rhs).rows() != m_ || (*rhs).columns() != n_ ) {
5091 BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" );
5092 }
5093
5094 if( (*rhs).canAlias( this ) ) {
5095 const ResultType_t<MT> tmp( *rhs );
5096 smpSchurAssign( *this, tmp );
5097 }
5098 else {
5099 smpSchurAssign( *this, *rhs );
5100 }
5101
5102 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
5103
5104 return *this;
5105 }
5106 /*! \endcond */
5107 //*************************************************************************************************
5108
5109
5110
5111
5112 //=================================================================================================
5113 //
5114 // UTILITY FUNCTIONS
5115 //
5116 //=================================================================================================
5117
5118 //*************************************************************************************************
5119 /*! \cond BLAZE_INTERNAL */
5120 /*!\brief Returns the current number of rows of the matrix.
5121 //
5122 // \return The number of rows of the matrix.
5123 */
5124 template< typename Type // Data type of the matrix
5125 , typename Alloc // Type of the allocator
5126 , typename Tag > // Type tag
rows()5127 inline size_t DynamicMatrix<Type,true,Alloc,Tag>::rows() const noexcept
5128 {
5129 return m_;
5130 }
5131 /*! \endcond */
5132 //*************************************************************************************************
5133
5134
5135 //*************************************************************************************************
5136 /*! \cond BLAZE_INTERNAL */
5137 /*!\brief Returns the current number of columns of the matrix.
5138 //
5139 // \return The number of columns of the matrix.
5140 */
5141 template< typename Type // Data type of the matrix
5142 , typename Alloc // Type of the allocator
5143 , typename Tag > // Type tag
columns()5144 inline size_t DynamicMatrix<Type,true,Alloc,Tag>::columns() const noexcept
5145 {
5146 return n_;
5147 }
5148 /*! \endcond */
5149 //*************************************************************************************************
5150
5151
5152 //*************************************************************************************************
5153 /*! \cond BLAZE_INTERNAL */
5154 /*!\brief Returns the spacing between the beginning of two columns.
5155 //
5156 // \return The spacing between the beginning of two columns.
5157 //
5158 // This function returns the spacing between the beginning of two column, i.e. the total number
5159 // of elements of a column.
5160 */
5161 template< typename Type // Data type of the matrix
5162 , typename Alloc // Type of the allocator
5163 , typename Tag > // Type tag
spacing()5164 inline size_t DynamicMatrix<Type,true,Alloc,Tag>::spacing() const noexcept
5165 {
5166 return mm_;
5167 }
5168 /*! \endcond */
5169 //*************************************************************************************************
5170
5171
5172 //*************************************************************************************************
5173 /*! \cond BLAZE_INTERNAL */
5174 /*!\brief Returns the maximum capacity of the matrix.
5175 //
5176 // \return The capacity of the matrix.
5177 */
5178 template< typename Type // Data type of the matrix
5179 , typename Alloc // Type of the allocator
5180 , typename Tag > // Type tag
capacity()5181 inline size_t DynamicMatrix<Type,true,Alloc,Tag>::capacity() const noexcept
5182 {
5183 return capacity_;
5184 }
5185 /*! \endcond */
5186 //*************************************************************************************************
5187
5188
5189 //*************************************************************************************************
5190 /*! \cond BLAZE_INTERNAL */
5191 /*!\brief Returns the current capacity of the specified column.
5192 //
5193 // \param j The index of the column.
5194 // \return The current capacity of column \a j.
5195 */
5196 template< typename Type // Data type of the matrix
5197 , typename Alloc // Type of the allocator
5198 , typename Tag > // Type tag
capacity(size_t j)5199 inline size_t DynamicMatrix<Type,true,Alloc,Tag>::capacity( size_t j ) const noexcept
5200 {
5201 MAYBE_UNUSED( j );
5202 BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
5203 return mm_;
5204 }
5205 /*! \endcond */
5206 //*************************************************************************************************
5207
5208
5209 //*************************************************************************************************
5210 /*! \cond BLAZE_INTERNAL */
5211 /*!\brief Returns the total number of non-zero elements in the matrix
5212 //
5213 // \return The number of non-zero elements in the dense matrix.
5214 //
5215 // This function returns the number of non-zero elements in the matrix (i.e. the elements that
5216 // compare unequal to their default value). Note that the number of non-zero elements is always
5217 // less than or equal to the total number of elements in the matrix.
5218 */
5219 template< typename Type // Data type of the matrix
5220 , typename Alloc // Type of the allocator
5221 , typename Tag > // Type tag
nonZeros()5222 inline size_t DynamicMatrix<Type,true,Alloc,Tag>::nonZeros() const
5223 {
5224 size_t nonzeros( 0UL );
5225
5226 for( size_t j=0UL; j<n_; ++j )
5227 for( size_t i=0UL; i<m_; ++i )
5228 if( !isDefault<strict>( v_[i+j*mm_] ) )
5229 ++nonzeros;
5230
5231 return nonzeros;
5232 }
5233 /*! \endcond */
5234 //*************************************************************************************************
5235
5236
5237 //*************************************************************************************************
5238 /*! \cond BLAZE_INTERNAL */
5239 /*!\brief Returns the number of non-zero elements in the specified column.
5240 //
5241 // \param j The index of the column.
5242 // \return The number of non-zero elements of column \a j.
5243 //
5244 // This function returns the current number of non-zero elements in the specified column (i.e.
5245 // the elements that compare unequal to their default value).
5246 */
5247 template< typename Type // Data type of the matrix
5248 , typename Alloc // Type of the allocator
5249 , typename Tag > // Type tag
nonZeros(size_t j)5250 inline size_t DynamicMatrix<Type,true,Alloc,Tag>::nonZeros( size_t j ) const
5251 {
5252 BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
5253
5254 const size_t iend( j*mm_ + m_ );
5255 size_t nonzeros( 0UL );
5256
5257 for( size_t i=j*mm_; i<iend; ++i )
5258 if( !isDefault<strict>( v_[i] ) )
5259 ++nonzeros;
5260
5261 return nonzeros;
5262 }
5263 /*! \endcond */
5264 //*************************************************************************************************
5265
5266
5267 //*************************************************************************************************
5268 /*! \cond BLAZE_INTERNAL */
5269 /*!\brief Reset to the default initial values.
5270 //
5271 // \return void
5272 */
5273 template< typename Type // Data type of the matrix
5274 , typename Alloc // Type of the allocator
5275 , typename Tag > // Type tag
reset()5276 inline void DynamicMatrix<Type,true,Alloc,Tag>::reset()
5277 {
5278 using blaze::clear;
5279
5280 for( size_t j=0UL; j<n_; ++j )
5281 for( size_t i=0UL; i<m_; ++i )
5282 clear( v_[i+j*mm_] );
5283 }
5284 /*! \endcond */
5285 //*************************************************************************************************
5286
5287
5288 //*************************************************************************************************
5289 /*! \cond BLAZE_INTERNAL */
5290 /*!\brief Reset the specified column to the default initial values.
5291 //
5292 // \param j The index of the column.
5293 // \return void
5294 //
5295 // This function reset the values in the specified column to their default value. Note that
5296 // the capacity of the column remains unchanged.
5297 */
5298 template< typename Type // Data type of the matrix
5299 , typename Alloc // Type of the allocator
5300 , typename Tag > // Type tag
reset(size_t j)5301 inline void DynamicMatrix<Type,true,Alloc,Tag>::reset( size_t j )
5302 {
5303 using blaze::clear;
5304
5305 BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" );
5306 for( size_t i=0UL; i<m_; ++i )
5307 clear( v_[i+j*mm_] );
5308 }
5309 /*! \endcond */
5310 //*************************************************************************************************
5311
5312
5313 //*************************************************************************************************
5314 /*! \cond BLAZE_INTERNAL */
5315 /*!\brief Clearing the \f$ M \times N \f$ matrix.
5316 //
5317 // \return void
5318 //
5319 // After the clear() function, the size of the matrix is 0.
5320 */
5321 template< typename Type // Data type of the matrix
5322 , typename Alloc // Type of the allocator
5323 , typename Tag > // Type tag
clear()5324 inline void DynamicMatrix<Type,true,Alloc,Tag>::clear()
5325 {
5326 resize( 0UL, 0UL, false );
5327 }
5328 /*! \endcond */
5329 //*************************************************************************************************
5330
5331
5332 //*************************************************************************************************
5333 /*! \cond BLAZE_INTERNAL */
5334 /*!\brief Changing the size of the matrix.
5335 //
5336 // \param m The new number of rows of the matrix.
5337 // \param n The new number of columns of the matrix.
5338 // \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
5339 // \return void
5340 //
5341 // This function resizes the matrix using the given size to \f$ m \times n \f$. During this
5342 // operation, new dynamic memory may be allocated in case the capacity of the matrix is too
5343 // small. Note that this function may invalidate all existing views (submatrices, rows, columns,
5344 // ...) on the matrix if it is used to shrink the matrix. Additionally, the resize operation
5345 // potentially changes all matrix elements. In order to preserve the old matrix values, the
5346 // \a preserve flag can be set to \a true. However, new matrix elements of built-in type are
5347 // not initialized!
5348 //
5349 // The following example illustrates the resize operation of a \f$ 2 \times 4 \f$ matrix to a
5350 // \f$ 4 \times 2 \f$ matrix. The new, uninitialized elements are marked with \a x:
5351
5352 \f[
5353 \left(\begin{array}{*{4}{c}}
5354 1 & 2 & 3 & 4 \\
5355 5 & 6 & 7 & 8 \\
5356 \end{array}\right)
5357
5358 \Longrightarrow
5359
5360 \left(\begin{array}{*{2}{c}}
5361 1 & 2 \\
5362 5 & 6 \\
5363 x & x \\
5364 x & x \\
5365 \end{array}\right)
5366 \f]
5367 */
5368 template< typename Type // Data type of the matrix
5369 , typename Alloc // Type of the allocator
5370 , typename Tag > // Type tag
resize(size_t m,size_t n,bool preserve)5371 void DynamicMatrix<Type,true,Alloc,Tag>::resize( size_t m, size_t n, bool preserve )
5372 {
5373 using blaze::clear;
5374 using blaze::min;
5375
5376 if( m == m_ && n == n_ ) return;
5377
5378 const size_t mm( addPadding( m ) );
5379
5380 if( preserve )
5381 {
5382 const size_t min_m( min( m, m_ ) );
5383 const size_t min_n( min( n, n_ ) );
5384
5385 DynamicMatrix tmp( m, mm, n, Alloc{}, Uninitialized{} );
5386
5387 for( size_t j=0UL; j<min_n; ++j ) {
5388 blaze::uninitialized_transfer( v_+j*mm_, v_+j*mm_+min_m, tmp.v_+j*mm );
5389 blaze::uninitialized_default_construct( tmp.v_+j*mm+min_m, tmp.v_+j*mm+mm );
5390 }
5391 blaze::uninitialized_default_construct( tmp.v_+min_n*mm, tmp.v_+mm*n );
5392
5393 std::swap( capacity_, tmp.capacity_ );
5394 std::swap( v_, tmp.v_ );
5395 }
5396 else if( mm*n > capacity_ )
5397 {
5398 DynamicMatrix tmp( m, mm, n, Alloc{}, Uninitialized{} );
5399
5400 blaze::uninitialized_default_construct( tmp.v_, tmp.v_+tmp.capacity_ );
5401
5402 std::swap( capacity_, tmp.capacity_ );
5403 std::swap( v_, tmp.v_ );
5404 }
5405
5406 if( IsVectorizable_v<Type> ) {
5407 for( size_t j=0UL; j<n; ++j )
5408 for( size_t i=m; i<mm; ++i )
5409 clear( v_[i+j*mm] );
5410 }
5411
5412 m_ = m;
5413 mm_ = mm;
5414 n_ = n;
5415
5416 BLAZE_INTERNAL_ASSERT( isIntact(), "Invariant violation detected" );
5417 }
5418 /*! \endcond */
5419 //*************************************************************************************************
5420
5421
5422 //*************************************************************************************************
5423 /*! \cond BLAZE_INTERNAL */
5424 /*!\brief Extending the size of the matrix.
5425 //
5426 // \param m Number of additional rows.
5427 // \param n Number of additional columns.
5428 // \param preserve \a true if the old values of the matrix should be preserved, \a false if not.
5429 // \return void
5430 //
5431 // This function increases the matrix size by \a m rows and \a n columns. During this operation,
5432 // new dynamic memory may be allocated in case the capacity of the matrix is too small. Therefore
5433 // this function potentially changes all matrix elements. In order to preserve the old matrix
5434 // values, the \a preserve flag can be set to \a true. However, new matrix elements of built-in
5435 // type are not initialized!
5436 */
5437 template< typename Type // Data type of the matrix
5438 , typename Alloc // Type of the allocator
5439 , typename Tag > // Type tag
extend(size_t m,size_t n,bool preserve)5440 inline void DynamicMatrix<Type,true,Alloc,Tag>::extend( size_t m, size_t n, bool preserve )
5441 {
5442 resize( m_+m, n_+n, preserve );
5443 }
5444 /*! \endcond */
5445 //*************************************************************************************************
5446
5447
5448 //*************************************************************************************************
5449 /*! \cond BLAZE_INTERNAL */
5450 /*!\brief Setting the minimum capacity of the matrix.
5451 //
5452 // \param elements The new minimum capacity of the dense matrix.
5453 // \return void
5454 //
5455 // This function increases the capacity of the dense matrix to at least \a elements elements.
5456 // The current values of the matrix elements are preserved.
5457 */
5458 template< typename Type // Data type of the matrix
5459 , typename Alloc // Type of the allocator
5460 , typename Tag > // Type tag
reserve(size_t elements)5461 inline void DynamicMatrix<Type,true,Alloc,Tag>::reserve( size_t elements )
5462 {
5463 using blaze::clear;
5464
5465 if( elements > capacity_ )
5466 {
5467 DynamicMatrix tmp( m_, mm_, n_, elements, Alloc{}, Uninitialized{} );
5468
5469 blaze::uninitialized_transfer( v_, v_+capacity_, tmp.v_ );
5470 blaze::uninitialized_value_construct( tmp.v_+capacity_, tmp.v_+elements );
5471
5472 std::swap( capacity_, tmp.capacity_ );
5473 std::swap( v_, tmp.v_ );
5474 }
5475 }
5476 /*! \endcond */
5477 //*************************************************************************************************
5478
5479
5480 //*************************************************************************************************
5481 /*! \cond BLAZE_INTERNAL */
5482 /*!\brief Requesting the removal of unused capacity.
5483 //
5484 // \return void
5485 //
5486 // This function minimizes the capacity of the matrix by removing unused capacity. Please note
5487 // that due to padding the capacity might not be reduced exactly to rows() times columns().
5488 // Please also note that in case a reallocation occurs, all iterators (including end() iterators),
5489 // all pointers and references to elements of this matrix are invalidated.
5490 */
5491 template< typename Type // Data type of the matrix
5492 , typename Alloc // Type of the allocator
5493 , typename Tag > // Type tag
shrinkToFit()5494 inline void DynamicMatrix<Type,true,Alloc,Tag>::shrinkToFit()
5495 {
5496 if( ( mm_ * n_ ) < capacity_ ) {
5497 DynamicMatrix( *this ).swap( *this );
5498 }
5499 }
5500 /*! \endcond */
5501 //*************************************************************************************************
5502
5503
5504 //*************************************************************************************************
5505 /*! \cond BLAZE_INTERNAL */
5506 /*!\brief Swapping the contents of two matrices.
5507 //
5508 // \param m The matrix to be swapped.
5509 // \return void
5510 */
5511 template< typename Type // Data type of the matrix
5512 , typename Alloc // Type of the allocator
5513 , typename Tag > // Type tag
swap(DynamicMatrix & m)5514 inline void DynamicMatrix<Type,true,Alloc,Tag>::swap( DynamicMatrix& m ) noexcept
5515 {
5516 using std::swap;
5517
5518 swap( m_ , m.m_ );
5519 swap( mm_, m.mm_ );
5520 swap( n_ , m.n_ );
5521 swap( capacity_, m.capacity_ );
5522 swap( v_ , m.v_ );
5523 }
5524 /*! \endcond */
5525 //*************************************************************************************************
5526
5527
5528 //*************************************************************************************************
5529 /*! \cond BLAZE_INTERNAL */
5530 /*!\brief Add the necessary amount of padding to the given value.
5531 //
5532 // \param value The value to be padded.
5533 // \return The padded value.
5534 //
5535 // This function increments the given \a value by the necessary amount of padding based on the
5536 // vector's data type \a Type.
5537 */
5538 template< typename Type // Data type of the matrix
5539 , typename Alloc // Type of the allocator
5540 , typename Tag > // Type tag
addPadding(size_t values)5541 inline size_t DynamicMatrix<Type,true,Alloc,Tag>::addPadding( size_t values ) const noexcept
5542 {
5543 if( usePadding && IsVectorizable_v<Type> )
5544 return nextMultiple<size_t>( values, SIMDSIZE );
5545 else return values;
5546 }
5547 /*! \endcond */
5548 //*************************************************************************************************
5549
5550
5551
5552
5553 //=================================================================================================
5554 //
5555 // NUMERIC FUNCTIONS
5556 //
5557 //=================================================================================================
5558
5559 //*************************************************************************************************
5560 /*! \cond BLAZE_INTERNAL */
5561 /*!\brief In-place transpose of the matrix.
5562 //
5563 // \return Reference to the transposed matrix.
5564 */
5565 template< typename Type // Data type of the matrix
5566 , typename Alloc // Type of the allocator
5567 , typename Tag > // Type tag
transpose()5568 inline DynamicMatrix<Type,true,Alloc,Tag>& DynamicMatrix<Type,true,Alloc,Tag>::transpose()
5569 {
5570 using std::swap;
5571
5572 constexpr size_t block( BLOCK_SIZE );
5573
5574 if( m_ == n_ )
5575 {
5576 for( size_t jj=0UL; jj<n_; jj+=block ) {
5577 const size_t jend( min( jj+block, n_ ) );
5578 for( size_t ii=0UL; ii<=jj; ii+=block ) {
5579 for( size_t j=jj; j<jend; ++j ) {
5580 const size_t iend( min( ii+block, m_, j ) );
5581 for( size_t i=ii; i<iend; ++i ) {
5582 swap( v_[i+j*mm_], v_[j+i*mm_] );
5583 }
5584 }
5585 }
5586 }
5587 }
5588 else
5589 {
5590 DynamicMatrix tmp( trans(*this) );
5591 this->swap( tmp );
5592 }
5593
5594 return *this;
5595 }
5596 /*! \endcond */
5597 //*************************************************************************************************
5598
5599
5600 //*************************************************************************************************
5601 /*! \cond BLAZE_INTERNAL */
5602 /*!\brief In-place conjugate transpose of the matrix.
5603 //
5604 // \return Reference to the transposed matrix.
5605 */
5606 template< typename Type // Data type of the matrix
5607 , typename Alloc // Type of the allocator
5608 , typename Tag > // Type tag
ctranspose()5609 inline DynamicMatrix<Type,true,Alloc,Tag>& DynamicMatrix<Type,true,Alloc,Tag>::ctranspose()
5610 {
5611 constexpr size_t block( BLOCK_SIZE );
5612
5613 if( m_ == n_ )
5614 {
5615 for( size_t jj=0UL; jj<n_; jj+=block ) {
5616 const size_t jend( min( jj+block, n_ ) );
5617 for( size_t ii=0UL; ii<jj; ii+=block ) {
5618 const size_t iend( min( ii+block, m_ ) );
5619 for( size_t j=jj; j<jend; ++j ) {
5620 for( size_t i=ii; i<iend; ++i ) {
5621 cswap( v_[i+j*mm_], v_[j+i*mm_] );
5622 }
5623 }
5624 }
5625 for( size_t j=jj; j<jend; ++j ) {
5626 for( size_t i=jj; i<j; ++i ) {
5627 cswap( v_[i+j*mm_], v_[j+i*mm_] );
5628 }
5629 conjugate( v_[j+j*mm_] );
5630 }
5631 }
5632 }
5633 else
5634 {
5635 DynamicMatrix tmp( ctrans(*this) );
5636 this->swap( tmp );
5637 }
5638
5639 return *this;
5640 }
5641 /*! \endcond */
5642 //*************************************************************************************************
5643
5644
5645 //*************************************************************************************************
5646 /*! \cond BLAZE_INTERNAL */
5647 /*!\brief Scaling of the matrix by the scalar value \a scalar (\f$ A=B*s \f$).
5648 //
5649 // \param scalar The scalar value for the matrix scaling.
5650 // \return Reference to the matrix.
5651 //
5652 // This function scales the matrix by applying the given scalar value \a scalar to each element
5653 // of the matrix. For built-in and \c complex data types it has the same effect as using the
5654 // multiplication assignment operator:
5655
5656 \code
5657 blaze::DynamicMatrix<int> A;
5658 // ... Resizing and initialization
5659 A *= 4; // Scaling of the matrix
5660 A.scale( 4 ); // Same effect as above
5661 \endcode
5662 */
5663 template< typename Type // Data type of the matrix
5664 , typename Alloc // Type of the allocator
5665 , typename Tag > // Type tag
5666 template< typename Other > // Data type of the scalar value
scale(const Other & scalar)5667 inline DynamicMatrix<Type,true,Alloc,Tag>& DynamicMatrix<Type,true,Alloc,Tag>::scale( const Other& scalar )
5668 {
5669 for( size_t j=0UL; j<n_; ++j )
5670 for( size_t i=0UL; i<m_; ++i )
5671 v_[i+j*mm_] *= scalar;
5672
5673 return *this;
5674 }
5675 /*! \endcond */
5676 //*************************************************************************************************
5677
5678
5679
5680
5681 //=================================================================================================
5682 //
5683 // DEBUGGING FUNCTIONS
5684 //
5685 //=================================================================================================
5686
5687 //*************************************************************************************************
5688 /*! \cond BLAZE_INTERNAL */
5689 /*!\brief Returns whether the invariants of the dynamic matrix are intact.
5690 //
5691 // \return \a true in case the dynamic matrix's invariants are intact, \a false otherwise.
5692 //
5693 // This function checks whether the invariants of the dynamic matrix are intact, i.e. if its
5694 // state is valid. In case the invariants are intact, the function returns \a true, else it
5695 // will return \a false.
5696 */
5697 template< typename Type // Data type of the matrix
5698 , typename Alloc // Type of the allocator
5699 , typename Tag > // Type tag
isIntact()5700 inline bool DynamicMatrix<Type,true,Alloc,Tag>::isIntact() const noexcept
5701 {
5702 if( m_ > mm_ || mm_ * n_ > capacity_ )
5703 return false;
5704
5705 if( IsVectorizable_v<Type> ) {
5706 for( size_t j=0UL; j<n_; ++j ) {
5707 for( size_t i=m_; i<mm_; ++i ) {
5708 if( !isDefault<strict>( v_[i+j*mm_] ) )
5709 return false;
5710 }
5711 }
5712 }
5713
5714 return true;
5715 }
5716 /*! \endcond */
5717 //*************************************************************************************************
5718
5719
5720
5721
5722 //=================================================================================================
5723 //
5724 // EXPRESSION TEMPLATE EVALUATION FUNCTIONS
5725 //
5726 //=================================================================================================
5727
5728 //*************************************************************************************************
5729 /*! \cond BLAZE_INTERNAL */
5730 /*!\brief Returns whether the matrix can alias with the given address \a alias.
5731 //
5732 // \param alias The alias to be checked.
5733 // \return \a true in case the alias corresponds to this matrix, \a false if not.
5734 //
5735 // This function returns whether the given address can alias with the matrix. In contrast
5736 // to the isAliased() function this function is allowed to use compile time expressions
5737 // to optimize the evaluation.
5738 */
5739 template< typename Type // Data type of the matrix
5740 , typename Alloc // Type of the allocator
5741 , typename Tag > // Type tag
5742 template< typename Other > // Data type of the foreign expression
canAlias(const Other * alias)5743 inline bool DynamicMatrix<Type,true,Alloc,Tag>::canAlias( const Other* alias ) const noexcept
5744 {
5745 return static_cast<const void*>( this ) == static_cast<const void*>( alias );
5746 }
5747 /*! \endcond */
5748 //*************************************************************************************************
5749
5750
5751 //*************************************************************************************************
5752 /*! \cond BLAZE_INTERNAL */
5753 /*!\brief Returns whether the matrix is aliased with the given address \a alias.
5754 //
5755 // \param alias The alias to be checked.
5756 // \return \a true in case the alias corresponds to this matrix, \a false if not.
5757 //
5758 // This function returns whether the given address is aliased with the matrix. In contrast
5759 // to the canAlias() function this function is not allowed to use compile time expressions
5760 // to optimize the evaluation.
5761 */
5762 template< typename Type // Data type of the matrix
5763 , typename Alloc // Type of the allocator
5764 , typename Tag > // Type tag
5765 template< typename Other > // Data type of the foreign expression
isAliased(const Other * alias)5766 inline bool DynamicMatrix<Type,true,Alloc,Tag>::isAliased( const Other* alias ) const noexcept
5767 {
5768 return static_cast<const void*>( this ) == static_cast<const void*>( alias );
5769 }
5770 /*! \endcond */
5771 //*************************************************************************************************
5772
5773
5774 //*************************************************************************************************
5775 /*! \cond BLAZE_INTERNAL */
5776 /*!\brief Returns whether the matrix is properly aligned in memory.
5777 //
5778 // \return \a true in case the matrix is aligned, \a false if not.
5779 //
5780 // This function returns whether the matrix is guaranteed to be properly aligned in memory, i.e.
5781 // whether the beginning and the end of each column of the matrix are guaranteed to conform to
5782 // the alignment restrictions of the element type \a Type.
5783 */
5784 template< typename Type // Data type of the matrix
5785 , typename Alloc // Type of the allocator
5786 , typename Tag > // Type tag
isAligned()5787 inline bool DynamicMatrix<Type,true,Alloc,Tag>::isAligned() const noexcept
5788 {
5789 return ( usePadding || rows() % SIMDSIZE == 0UL );
5790 }
5791 /*! \endcond */
5792 //*************************************************************************************************
5793
5794
5795 //*************************************************************************************************
5796 /*! \cond BLAZE_INTERNAL */
5797 /*!\brief Returns whether the matrix can be used in SMP assignments.
5798 //
5799 // \return \a true in case the matrix can be used in SMP assignments, \a false if not.
5800 //
5801 // This function returns whether the matrix can be used in SMP assignments. In contrast to the
5802 // \a smpAssignable member enumeration, which is based solely on compile time information, this
5803 // function additionally provides runtime information (as for instance the current number of
5804 // rows and/or columns of the matrix).
5805 */
5806 template< typename Type // Data type of the matrix
5807 , typename Alloc // Type of the allocator
5808 , typename Tag > // Type tag
canSMPAssign()5809 inline bool DynamicMatrix<Type,true,Alloc,Tag>::canSMPAssign() const noexcept
5810 {
5811 return ( rows() * columns() >= SMP_DMATASSIGN_THRESHOLD );
5812 }
5813 /*! \endcond */
5814 //*************************************************************************************************
5815
5816
5817 //*************************************************************************************************
5818 /*! \cond BLAZE_INTERNAL */
5819 /*!\brief Load of a SIMD element of the matrix.
5820 //
5821 // \param i Access index for the row. The index has to be in the range [0..M-1].
5822 // \param j Access index for the column. The index has to be in the range [0..N-1].
5823 // \return The loaded SIMD element.
5824 //
5825 // This function performs a load of a specific SIMD element of the dense matrix. The row index
5826 // must be smaller than the number of rows and the column index must be smaller than the number
5827 // of columns. Additionally, the row index must be a multiple of the number of values inside
5828 // the SIMD element. This function must \b NOT be called explicitly! It is used internally
5829 // for the performance optimized evaluation of expression templates. Calling this function
5830 // explicitly might result in erroneous results and/or in compilation errors.
5831 */
5832 template< typename Type // Data type of the matrix
5833 , typename Alloc // Type of the allocator
5834 , typename Tag > // Type tag
5835 BLAZE_ALWAYS_INLINE typename DynamicMatrix<Type,true,Alloc,Tag>::SIMDType
load(size_t i,size_t j)5836 DynamicMatrix<Type,true,Alloc,Tag>::load( size_t i, size_t j ) const noexcept
5837 {
5838 if( usePadding )
5839 return loada( i, j );
5840 else
5841 return loadu( i, j );
5842 }
5843 /*! \endcond */
5844 //*************************************************************************************************
5845
5846
5847 //*************************************************************************************************
5848 /*! \cond BLAZE_INTERNAL */
5849 /*!\brief Aligned load of a SIMD element of the matrix.
5850 //
5851 // \param i Access index for the row. The index has to be in the range [0..M-1].
5852 // \param j Access index for the column. The index has to be in the range [0..N-1].
5853 // \return The loaded SIMD element.
5854 //
5855 // This function performs an aligned load of a specific SIMD element of the dense matrix.
5856 // The row index must be smaller than the number of rows and the column index must be smaller
5857 // than the number of columns. Additionally, the row index must be a multiple of the number of
5858 // values inside the SIMD element. This function must \b NOT be called explicitly! It is used
5859 // internally for the performance optimized evaluation of expression templates. Calling this
5860 // function explicitly might result in erroneous results and/or in compilation errors.
5861 */
5862 template< typename Type // Data type of the matrix
5863 , typename Alloc // Type of the allocator
5864 , typename Tag > // Type tag
5865 BLAZE_ALWAYS_INLINE typename DynamicMatrix<Type,true,Alloc,Tag>::SIMDType
loada(size_t i,size_t j)5866 DynamicMatrix<Type,true,Alloc,Tag>::loada( size_t i, size_t j ) const noexcept
5867 {
5868 using blaze::loada;
5869
5870 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
5871
5872 BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
5873 BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= mm_, "Invalid row access index" );
5874 BLAZE_INTERNAL_ASSERT( !usePadding || i % SIMDSIZE == 0UL, "Invalid row access index" );
5875 BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
5876 BLAZE_INTERNAL_ASSERT( checkAlignment( v_+i+j*mm_ ), "Invalid alignment detected" );
5877
5878 return loada( v_+i+j*mm_ );
5879 }
5880 /*! \endcond */
5881 //*************************************************************************************************
5882
5883
5884 //*************************************************************************************************
5885 /*! \cond BLAZE_INTERNAL */
5886 /*!\brief Unaligned load of a SIMD element of the matrix.
5887 //
5888 // \param i Access index for the row. The index has to be in the range [0..M-1].
5889 // \param j Access index for the column. The index has to be in the range [0..N-1].
5890 // \return The loaded SIMD element.
5891 //
5892 // This function performs an unaligned load of a specific SIMD element of the dense matrix.
5893 // The row index must be smaller than the number of rows and the column index must be smaller
5894 // than the number of columns. Additionally, the row index must be a multiple of the number of
5895 // values inside the SIMD element. This function must \b NOT be called explicitly! It is used
5896 // internally for the performance optimized evaluation of expression templates. Calling this
5897 // function explicitly might result in erroneous results and/or in compilation errors.
5898 */
5899 template< typename Type // Data type of the matrix
5900 , typename Alloc // Type of the allocator
5901 , typename Tag > // Type tag
5902 BLAZE_ALWAYS_INLINE typename DynamicMatrix<Type,true,Alloc,Tag>::SIMDType
loadu(size_t i,size_t j)5903 DynamicMatrix<Type,true,Alloc,Tag>::loadu( size_t i, size_t j ) const noexcept
5904 {
5905 using blaze::loadu;
5906
5907 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
5908
5909 BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
5910 BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= mm_, "Invalid row access index" );
5911 BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
5912
5913 return loadu( v_+i+j*mm_ );
5914 }
5915 /*! \endcond */
5916 //*************************************************************************************************
5917
5918
5919 //*************************************************************************************************
5920 /*! \cond BLAZE_INTERNAL */
5921 /*!\brief Store of a SIMD element of the matrix.
5922 //
5923 // \param i Access index for the row. The index has to be in the range [0..M-1].
5924 // \param j Access index for the column. The index has to be in the range [0..N-1].
5925 // \param value The SIMD element to be stored.
5926 // \return void
5927 //
5928 // This function performs a store of a specific SIMD element of the dense matrix. The row index
5929 // must be smaller than the number of rows and the column index must be smaller then the number
5930 // of columns. Additionally, the row index must be a multiple of the number of values inside the
5931 // SIMD element. This function must \b NOT be called explicitly! It is used internally for the
5932 // performance optimized evaluation of expression templates. Calling this function explicitly
5933 // might result in erroneous results and/or in compilation errors.
5934 */
5935 template< typename Type // Data type of the matrix
5936 , typename Alloc // Type of the allocator
5937 , typename Tag > // Type tag
5938 BLAZE_ALWAYS_INLINE void
store(size_t i,size_t j,const SIMDType & value)5939 DynamicMatrix<Type,true,Alloc,Tag>::store( size_t i, size_t j, const SIMDType& value ) noexcept
5940 {
5941 if( usePadding )
5942 storea( i, j, value );
5943 else
5944 storeu( i, j, value );
5945 }
5946 /*! \endcond */
5947 //*************************************************************************************************
5948
5949
5950 //*************************************************************************************************
5951 /*! \cond BLAZE_INTERNAL */
5952 /*!\brief Aligned store of a SIMD element of the matrix.
5953 //
5954 // \param i Access index for the row. The index has to be in the range [0..M-1].
5955 // \param j Access index for the column. The index has to be in the range [0..N-1].
5956 // \param value The SIMD element to be stored.
5957 // \return void
5958 //
5959 // This function performs an aligned store of a specific SIMD element of the dense matrix.
5960 // The row index must be smaller than the number of rows and the column index must be smaller
5961 // than the number of columns. Additionally, the row index must be a multiple of the number of
5962 // values inside the SIMD element. This function must \b NOT be called explicitly! It is used
5963 // internally for the performance optimized evaluation of expression templates. Calling this
5964 // function explicitly might result in erroneous results and/or in compilation errors.
5965 */
5966 template< typename Type // Data type of the matrix
5967 , typename Alloc // Type of the allocator
5968 , typename Tag > // Type tag
5969 BLAZE_ALWAYS_INLINE void
storea(size_t i,size_t j,const SIMDType & value)5970 DynamicMatrix<Type,true,Alloc,Tag>::storea( size_t i, size_t j, const SIMDType& value ) noexcept
5971 {
5972 using blaze::storea;
5973
5974 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
5975
5976 BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
5977 BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= mm_, "Invalid row access index" );
5978 BLAZE_INTERNAL_ASSERT( !usePadding || i % SIMDSIZE == 0UL, "Invalid row access index" );
5979 BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
5980 BLAZE_INTERNAL_ASSERT( checkAlignment( v_+i+j*mm_ ), "Invalid alignment detected" );
5981
5982 storea( v_+i+j*mm_, value );
5983 }
5984 /*! \endcond */
5985 //*************************************************************************************************
5986
5987
5988 //*************************************************************************************************
5989 /*! \cond BLAZE_INTERNAL */
5990 /*!\brief Unaligned store of a SIMD element of the matrix.
5991 //
5992 // \param i Access index for the row. The index has to be in the range [0..M-1].
5993 // \param j Access index for the column. The index has to be in the range [0..N-1].
5994 // \param value The SIMD element to be stored.
5995 // \return void
5996 //
5997 // This function performs an unaligned store of a specific SIMD element of the dense matrix.
5998 // The row index must be smaller than the number of rows and the column index must be smaller
5999 // than the number of columns. Additionally, the row index must be a multiple of the number of
6000 // values inside the SIMD element. This function must \b NOT be called explicitly! It is used
6001 // internally for the performance optimized evaluation of expression templates. Calling this
6002 // function explicitly might result in erroneous results and/or in compilation errors.
6003 */
6004 template< typename Type // Data type of the matrix
6005 , typename Alloc // Type of the allocator
6006 , typename Tag > // Type tag
6007 BLAZE_ALWAYS_INLINE void
storeu(size_t i,size_t j,const SIMDType & value)6008 DynamicMatrix<Type,true,Alloc,Tag>::storeu( size_t i, size_t j, const SIMDType& value ) noexcept
6009 {
6010 using blaze::storeu;
6011
6012 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
6013
6014 BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
6015 BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= mm_, "Invalid row access index" );
6016 BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
6017
6018 storeu( v_+i+j*mm_, value );
6019 }
6020 /*! \endcond */
6021 //*************************************************************************************************
6022
6023
6024 //*************************************************************************************************
6025 /*! \cond BLAZE_INTERNAL */
6026 /*!\brief Aligned, non-temporal store of a SIMD element of the matrix.
6027 //
6028 // \param i Access index for the row. The index has to be in the range [0..M-1].
6029 // \param j Access index for the column. The index has to be in the range [0..N-1].
6030 // \param value The SIMD element to be stored.
6031 // \return void
6032 //
6033 // This function performs an aligned, non-temporal store of a specific SIMD element of the
6034 // dense matrix. The row index must be smaller than the number of rows and the column index
6035 // must be smaller than the number of columns. Additionally, the row index must be a multiple
6036 // of the number of values inside the SIMD element. This function must \b NOT be called
6037 // explicitly! It is used internally for the performance optimized evaluation of expression
6038 // templates. Calling this function explicitly might result in erroneous results and/or in
6039 // compilation errors.
6040 */
6041 template< typename Type // Data type of the matrix
6042 , typename Alloc // Type of the allocator
6043 , typename Tag > // Type tag
6044 BLAZE_ALWAYS_INLINE void
stream(size_t i,size_t j,const SIMDType & value)6045 DynamicMatrix<Type,true,Alloc,Tag>::stream( size_t i, size_t j, const SIMDType& value ) noexcept
6046 {
6047 using blaze::stream;
6048
6049 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
6050
6051 BLAZE_INTERNAL_ASSERT( i < m_, "Invalid row access index" );
6052 BLAZE_INTERNAL_ASSERT( i + SIMDSIZE <= mm_, "Invalid row access index" );
6053 BLAZE_INTERNAL_ASSERT( !usePadding || i % SIMDSIZE == 0UL, "Invalid row access index" );
6054 BLAZE_INTERNAL_ASSERT( j < n_, "Invalid column access index" );
6055 BLAZE_INTERNAL_ASSERT( checkAlignment( v_+i+j*mm_ ), "Invalid alignment detected" );
6056
6057 stream( v_+i+j*mm_, value );
6058 }
6059 /*! \endcond */
6060 //*************************************************************************************************
6061
6062
6063 //*************************************************************************************************
6064 /*! \cond BLAZE_INTERNAL */
6065 /*!\brief Default implementation of the assignment of a column-major dense matrix.
6066 //
6067 // \param rhs The right-hand side dense matrix to be assigned.
6068 // \return void
6069 //
6070 // This function must \b NOT be called explicitly! It is used internally for the performance
6071 // optimized evaluation of expression templates. Calling this function explicitly might result
6072 // in erroneous results and/or in compilation errors. Instead of using this function use the
6073 // assignment operator.
6074 */
6075 template< typename Type // Data type of the matrix
6076 , typename Alloc // Type of the allocator
6077 , typename Tag > // Type tag
6078 template< typename MT > // Type of the right-hand side dense matrix
6079 inline auto DynamicMatrix<Type,true,Alloc,Tag>::assign( const DenseMatrix<MT,true>& rhs )
6080 -> DisableIf_t< VectorizedAssign_v<MT> >
6081 {
6082 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
6083 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
6084
6085 const size_t ipos( prevMultiple( m_, 2UL ) );
6086 BLAZE_INTERNAL_ASSERT( ipos <= m_, "Invalid end calculation" );
6087
6088 for( size_t j=0UL; j<n_; ++j ) {
6089 for( size_t i=0UL; i<ipos; i+=2UL ) {
6090 v_[i +j*mm_] = (*rhs)(i ,j);
6091 v_[i+1UL+j*mm_] = (*rhs)(i+1UL,j);
6092 }
6093 if( ipos < m_ ) {
6094 v_[ipos+j*mm_] = (*rhs)(ipos,j);
6095 }
6096 }
6097 }
6098 /*! \endcond */
6099 //*************************************************************************************************
6100
6101
6102 //*************************************************************************************************
6103 /*! \cond BLAZE_INTERNAL */
6104 /*!\brief SIMD optimized implementation of the assignment of a column-major dense matrix.
6105 //
6106 // \param rhs The right-hand side dense matrix to be assigned.
6107 // \return void
6108 //
6109 // This function must \b NOT be called explicitly! It is used internally for the performance
6110 // optimized evaluation of expression templates. Calling this function explicitly might result
6111 // in erroneous results and/or in compilation errors. Instead of using this function use the
6112 // assignment operator.
6113 */
6114 template< typename Type // Data type of the matrix
6115 , typename Alloc // Type of the allocator
6116 , typename Tag > // Type tag
6117 template< typename MT > // Type of the right-hand side dense matrix
6118 inline auto DynamicMatrix<Type,true,Alloc,Tag>::assign( const DenseMatrix<MT,true>& rhs )
6119 -> EnableIf_t< VectorizedAssign_v<MT> >
6120 {
6121 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
6122
6123 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
6124 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
6125
6126 constexpr bool remainder( !usePadding || !IsPadded_v<MT> );
6127
6128 const size_t ipos( remainder ? prevMultiple( m_, SIMDSIZE ) : m_ );
6129 BLAZE_INTERNAL_ASSERT( ipos <= m_, "Invalid end calculation" );
6130
6131 if( usePadding && useStreaming &&
6132 ( m_*n_ > ( cacheSize / ( sizeof(Type) * 3UL ) ) ) &&
6133 !(*rhs).isAliased( this ) )
6134 {
6135 for( size_t j=0UL; j<n_; ++j )
6136 {
6137 size_t i( 0UL );
6138 Iterator left( begin(j) );
6139 ConstIterator_t<MT> right( (*rhs).begin(j) );
6140
6141 for( ; i<ipos; i+=SIMDSIZE ) {
6142 left.stream( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6143 }
6144 for( ; remainder && i<m_; ++i ) {
6145 *left = *right; ++left; ++right;
6146 }
6147 }
6148 }
6149 else
6150 {
6151 for( size_t j=0UL; j<n_; ++j )
6152 {
6153 size_t i( 0UL );
6154 Iterator left( begin(j) );
6155 ConstIterator_t<MT> right( (*rhs).begin(j) );
6156
6157 for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
6158 left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6159 left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6160 left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6161 left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6162 }
6163 for( ; i<ipos; i+=SIMDSIZE ) {
6164 left.store( right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6165 }
6166 for( ; remainder && i<m_; ++i ) {
6167 *left = *right; ++left; ++right;
6168 }
6169 }
6170 }
6171 }
6172 /*! \endcond */
6173 //*************************************************************************************************
6174
6175
6176 //*************************************************************************************************
6177 /*! \cond BLAZE_INTERNAL */
6178 /*!\brief Default implementation of the assignment of a row-major dense matrix.
6179 //
6180 // \param rhs The right-hand side dense matrix to be assigned.
6181 // \return void
6182 //
6183 // This function must \b NOT be called explicitly! It is used internally for the performance
6184 // optimized evaluation of expression templates. Calling this function explicitly might result
6185 // in erroneous results and/or in compilation errors. Instead of using this function use the
6186 // assignment operator.
6187 */
6188 template< typename Type // Data type of the matrix
6189 , typename Alloc // Type of the allocator
6190 , typename Tag > // Type tag
6191 template< typename MT > // Type of the right-hand side dense matrix
assign(const DenseMatrix<MT,false> & rhs)6192 inline void DynamicMatrix<Type,true,Alloc,Tag>::assign( const DenseMatrix<MT,false>& rhs )
6193 {
6194 BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
6195
6196 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
6197 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
6198
6199 constexpr size_t block( BLOCK_SIZE );
6200
6201 for( size_t jj=0UL; jj<n_; jj+=block ) {
6202 const size_t jend( min( n_, jj+block ) );
6203 for( size_t ii=0UL; ii<m_; ii+=block ) {
6204 const size_t iend( min( m_, ii+block ) );
6205 for( size_t j=jj; j<jend; ++j ) {
6206 for( size_t i=ii; i<iend; ++i ) {
6207 v_[i+j*mm_] = (*rhs)(i,j);
6208 }
6209 }
6210 }
6211 }
6212 }
6213 /*! \endcond */
6214 //*************************************************************************************************
6215
6216
6217 //*************************************************************************************************
6218 /*! \cond BLAZE_INTERNAL */
6219 /*!\brief Default implementation of the assignment of a column-major sparse matrix.
6220 //
6221 // \param rhs The right-hand side sparse matrix to be assigned.
6222 // \return void
6223 //
6224 // This function must \b NOT be called explicitly! It is used internally for the performance
6225 // optimized evaluation of expression templates. Calling this function explicitly might result
6226 // in erroneous results and/or in compilation errors. Instead of using this function use the
6227 // assignment operator.
6228 */
6229 template< typename Type // Data type of the matrix
6230 , typename Alloc // Type of the allocator
6231 , typename Tag > // Type tag
6232 template< typename MT > // Type of the right-hand side sparse matrix
assign(const SparseMatrix<MT,true> & rhs)6233 inline void DynamicMatrix<Type,true,Alloc,Tag>::assign( const SparseMatrix<MT,true>& rhs )
6234 {
6235 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
6236 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
6237
6238 for( size_t j=0UL; j<(*rhs).columns(); ++j )
6239 for( auto element=(*rhs).begin(j); element!=(*rhs).end(j); ++element )
6240 v_[element->index()+j*mm_] = element->value();
6241 }
6242 /*! \endcond */
6243 //*************************************************************************************************
6244
6245
6246 //*************************************************************************************************
6247 /*! \cond BLAZE_INTERNAL */
6248 /*!\brief Default implementation of the assignment of a row-major sparse matrix.
6249 //
6250 // \param rhs The right-hand side sparse matrix to be assigned.
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 Type // Data type of the matrix
6259 , typename Alloc // Type of the allocator
6260 , typename Tag > // Type tag
6261 template< typename MT > // Type of the right-hand side sparse matrix
assign(const SparseMatrix<MT,false> & rhs)6262 inline void DynamicMatrix<Type,true,Alloc,Tag>::assign( const SparseMatrix<MT,false>& rhs )
6263 {
6264 BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
6265
6266 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
6267 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
6268
6269 for( size_t i=0UL; i<(*rhs).rows(); ++i )
6270 for( auto element=(*rhs).begin(i); element!=(*rhs).end(i); ++element )
6271 v_[i+element->index()*mm_] = element->value();
6272 }
6273 /*! \endcond */
6274 //*************************************************************************************************
6275
6276
6277 //*************************************************************************************************
6278 /*! \cond BLAZE_INTERNAL */
6279 /*!\brief Default implementation of the addition assignment of a column-major dense matrix.
6280 //
6281 // \param rhs The right-hand side dense matrix to be added.
6282 // \return void
6283 //
6284 // This function must \b NOT be called explicitly! It is used internally for the performance
6285 // optimized evaluation of expression templates. Calling this function explicitly might result
6286 // in erroneous results and/or in compilation errors. Instead of using this function use the
6287 // assignment operator.
6288 */
6289 template< typename Type // Data type of the matrix
6290 , typename Alloc // Type of the allocator
6291 , typename Tag > // Type tag
6292 template< typename MT > // Type of the right-hand side dense matrix
6293 inline auto DynamicMatrix<Type,true,Alloc,Tag>::addAssign( const DenseMatrix<MT,true>& rhs )
6294 -> DisableIf_t< VectorizedAddAssign_v<MT> >
6295 {
6296 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
6297 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
6298
6299 for( size_t j=0UL; j<n_; ++j )
6300 {
6301 if( IsDiagonal_v<MT> )
6302 {
6303 v_[j+j*mm_] += (*rhs)(j,j);
6304 }
6305 else
6306 {
6307 const size_t ibegin( ( IsLower_v<MT> )
6308 ?( IsStrictlyLower_v<MT> ? j+1UL : j )
6309 :( 0UL ) );
6310 const size_t iend ( ( IsUpper_v<MT> )
6311 ?( IsStrictlyUpper_v<MT> ? j : j+1UL )
6312 :( m_ ) );
6313 BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
6314
6315 size_t i( ibegin );
6316
6317 for( ; (i+2UL) <= iend; i+=2UL ) {
6318 v_[i +j*mm_] += (*rhs)(i ,j);
6319 v_[i+1UL+j*mm_] += (*rhs)(i+1UL,j);
6320 }
6321 if( i < iend ) {
6322 v_[i+j*mm_] += (*rhs)(i,j);
6323 }
6324 }
6325 }
6326 }
6327 /*! \endcond */
6328 //*************************************************************************************************
6329
6330
6331 //*************************************************************************************************
6332 /*! \cond BLAZE_INTERNAL */
6333 /*!\brief SIMD optimized implementation of the addition assignment of a column-major dense matrix.
6334 //
6335 // \param rhs The right-hand side dense matrix to be added.
6336 // \return void
6337 //
6338 // This function must \b NOT be called explicitly! It is used internally for the performance
6339 // optimized evaluation of expression templates. Calling this function explicitly might result
6340 // in erroneous results and/or in compilation errors. Instead of using this function use the
6341 // assignment operator.
6342 */
6343 template< typename Type // Data type of the matrix
6344 , typename Alloc // Type of the allocator
6345 , typename Tag > // Type tag
6346 template< typename MT > // Type of the right-hand side dense matrix
6347 inline auto DynamicMatrix<Type,true,Alloc,Tag>::addAssign( const DenseMatrix<MT,true>& rhs )
6348 -> EnableIf_t< VectorizedAddAssign_v<MT> >
6349 {
6350 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
6351 BLAZE_CONSTRAINT_MUST_NOT_BE_DIAGONAL_MATRIX_TYPE( MT );
6352
6353 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
6354 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
6355
6356 constexpr bool remainder( !usePadding || !IsPadded_v<MT> );
6357
6358 for( size_t j=0UL; j<n_; ++j )
6359 {
6360 const size_t ibegin( ( IsLower_v<MT> )
6361 ?( prevMultiple( ( IsStrictlyLower_v<MT> ? j+1UL : j ), SIMDSIZE ) )
6362 :( 0UL ) );
6363 const size_t iend ( ( IsUpper_v<MT> )
6364 ?( IsStrictlyUpper_v<MT> ? j : j+1UL )
6365 :( m_ ) );
6366 BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
6367
6368 const size_t ipos( remainder ? prevMultiple( iend, SIMDSIZE ) : iend );
6369 BLAZE_INTERNAL_ASSERT( ipos <= iend, "Invalid end calculation" );
6370
6371 size_t i( ibegin );
6372 Iterator left( begin(j) + ibegin );
6373 ConstIterator_t<MT> right( (*rhs).begin(j) + ibegin );
6374
6375 for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
6376 left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6377 left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6378 left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6379 left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6380 }
6381 for( ; i<ipos; i+=SIMDSIZE ) {
6382 left.store( left.load() + right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6383 }
6384 for( ; remainder && i<iend; ++i ) {
6385 *left += *right; ++left; ++right;
6386 }
6387 }
6388 }
6389 /*! \endcond */
6390 //*************************************************************************************************
6391
6392
6393 //*************************************************************************************************
6394 /*! \cond BLAZE_INTERNAL */
6395 /*!\brief Default implementation of the addition assignment of a row-major dense matrix.
6396 //
6397 // \param rhs The right-hand side dense matrix to be added.
6398 // \return void
6399 //
6400 // This function must \b NOT be called explicitly! It is used internally for the performance
6401 // optimized evaluation of expression templates. Calling this function explicitly might result
6402 // in erroneous results and/or in compilation errors. Instead of using this function use the
6403 // assignment operator.
6404 */
6405 template< typename Type // Data type of the matrix
6406 , typename Alloc // Type of the allocator
6407 , typename Tag > // Type tag
6408 template< typename MT > // Type of the right-hand side dense matrix
addAssign(const DenseMatrix<MT,false> & rhs)6409 inline void DynamicMatrix<Type,true,Alloc,Tag>::addAssign( const DenseMatrix<MT,false>& rhs )
6410 {
6411 BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
6412
6413 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
6414 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
6415
6416 constexpr size_t block( BLOCK_SIZE );
6417
6418 for( size_t jj=0UL; jj<n_; jj+=block ) {
6419 const size_t jend( min( n_, jj+block ) );
6420 for( size_t ii=0UL; ii<m_; ii+=block )
6421 {
6422 if( IsLower_v<MT> && ii < jj ) continue;
6423 if( IsUpper_v<MT> && ii > jj ) break;
6424
6425 for( size_t j=jj; j<jend; ++j )
6426 {
6427 const size_t ibegin( ( IsLower_v<MT> )
6428 ?( max( ( IsStrictlyLower_v<MT> ? j+1UL : j ), ii ) )
6429 :( ii ) );
6430 const size_t iend ( ( IsUpper_v<MT> )
6431 ?( min( ( IsStrictlyUpper_v<MT> ? j : j+1UL ), m_, ii+block ) )
6432 :( min( m_, ii+block ) ) );
6433 BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
6434
6435 for( size_t i=ibegin; i<iend; ++i ) {
6436 v_[i+j*mm_] += (*rhs)(i,j);
6437 }
6438 }
6439 }
6440 }
6441 }
6442 /*! \endcond */
6443 //*************************************************************************************************
6444
6445
6446 //*************************************************************************************************
6447 /*! \cond BLAZE_INTERNAL */
6448 /*!\brief Default implementation of the addition assignment of a column-major sparse matrix.
6449 //
6450 // \param rhs The right-hand side sparse matrix to be added.
6451 // \return void
6452 //
6453 // This function must \b NOT be called explicitly! It is used internally for the performance
6454 // optimized evaluation of expression templates. Calling this function explicitly might result
6455 // in erroneous results and/or in compilation errors. Instead of using this function use the
6456 // assignment operator.
6457 */
6458 template< typename Type // Data type of the matrix
6459 , typename Alloc // Type of the allocator
6460 , typename Tag > // Type tag
6461 template< typename MT > // Type of the right-hand side sparse matrix
addAssign(const SparseMatrix<MT,true> & rhs)6462 inline void DynamicMatrix<Type,true,Alloc,Tag>::addAssign( const SparseMatrix<MT,true>& rhs )
6463 {
6464 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
6465 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
6466
6467 for( size_t j=0UL; j<(*rhs).columns(); ++j )
6468 for( auto element=(*rhs).begin(j); element!=(*rhs).end(j); ++element )
6469 v_[element->index()+j*mm_] += element->value();
6470 }
6471 /*! \endcond */
6472 //*************************************************************************************************
6473
6474
6475 //*************************************************************************************************
6476 /*! \cond BLAZE_INTERNAL */
6477 /*!\brief Default implementation of the addition assignment of a row-major sparse matrix.
6478 //
6479 // \param rhs The right-hand side sparse matrix to be added.
6480 // \return void
6481 //
6482 // This function must \b NOT be called explicitly! It is used internally for the performance
6483 // optimized evaluation of expression templates. Calling this function explicitly might result
6484 // in erroneous results and/or in compilation errors. Instead of using this function use the
6485 // assignment operator.
6486 */
6487 template< typename Type // Data type of the matrix
6488 , typename Alloc // Type of the allocator
6489 , typename Tag > // Type tag
6490 template< typename MT > // Type of the right-hand side sparse matrix
addAssign(const SparseMatrix<MT,false> & rhs)6491 inline void DynamicMatrix<Type,true,Alloc,Tag>::addAssign( const SparseMatrix<MT,false>& rhs )
6492 {
6493 BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
6494
6495 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
6496 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
6497
6498 for( size_t i=0UL; i<(*rhs).rows(); ++i )
6499 for( auto element=(*rhs).begin(i); element!=(*rhs).end(i); ++element )
6500 v_[i+element->index()*mm_] += element->value();
6501 }
6502 /*! \endcond */
6503 //*************************************************************************************************
6504
6505
6506 //*************************************************************************************************
6507 /*! \cond BLAZE_INTERNAL */
6508 /*!\brief Default implementation of the subtraction assignment of a column-major dense matrix.
6509 //
6510 // \param rhs The right-hand side dense matrix to be subtracted.
6511 // \return void
6512 //
6513 // This function must \b NOT be called explicitly! It is used internally for the performance
6514 // optimized evaluation of expression templates. Calling this function explicitly might result
6515 // in erroneous results and/or in compilation errors. Instead of using this function use the
6516 // assignment operator.
6517 */
6518 template< typename Type // Data type of the matrix
6519 , typename Alloc // Type of the allocator
6520 , typename Tag > // Type tag
6521 template< typename MT > // Type of the right-hand side dense matrix
6522 inline auto DynamicMatrix<Type,true,Alloc,Tag>::subAssign( const DenseMatrix<MT,true>& rhs )
6523 -> DisableIf_t< VectorizedSubAssign_v<MT> >
6524 {
6525 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
6526 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
6527
6528 for( size_t j=0UL; j<n_; ++j )
6529 {
6530 if( IsDiagonal_v<MT> )
6531 {
6532 v_[j+j*mm_] -= (*rhs)(j,j);
6533 }
6534 else
6535 {
6536 const size_t ibegin( ( IsLower_v<MT> )
6537 ?( IsStrictlyLower_v<MT> ? j+1UL : j )
6538 :( 0UL ) );
6539 const size_t iend ( ( IsUpper_v<MT> )
6540 ?( IsStrictlyUpper_v<MT> ? j : j+1UL )
6541 :( m_ ) );
6542 BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
6543
6544 size_t i( ibegin );
6545
6546 for( ; (i+2UL) <= iend; i+=2UL ) {
6547 v_[i +j*mm_] -= (*rhs)(i ,j);
6548 v_[i+1+j*mm_] -= (*rhs)(i+1,j);
6549 }
6550 if( i < iend ) {
6551 v_[i+j*mm_] -= (*rhs)(i,j);
6552 }
6553 }
6554 }
6555 }
6556 /*! \endcond */
6557 //*************************************************************************************************
6558
6559
6560 //*************************************************************************************************
6561 /*! \cond BLAZE_INTERNAL */
6562 /*!\brief SIMD optimized implementation of the subtraction assignment of a column-major dense matrix.
6563 //
6564 // \param rhs The right-hand side dense matrix to be subtracted.
6565 // \return void
6566 //
6567 // This function must \b NOT be called explicitly! It is used internally for the performance
6568 // optimized evaluation of expression templates. Calling this function explicitly might result
6569 // in erroneous results and/or in compilation errors. Instead of using this function use the
6570 // assignment operator.
6571 */
6572 template< typename Type // Data type of the matrix
6573 , typename Alloc // Type of the allocator
6574 , typename Tag > // Type tag
6575 template< typename MT > // Type of the right-hand side dense matrix
6576 inline auto DynamicMatrix<Type,true,Alloc,Tag>::subAssign( const DenseMatrix<MT,true>& rhs )
6577 -> EnableIf_t< VectorizedSubAssign_v<MT> >
6578 {
6579 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
6580 BLAZE_CONSTRAINT_MUST_NOT_BE_DIAGONAL_MATRIX_TYPE( MT );
6581
6582 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
6583 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
6584
6585 constexpr bool remainder( !usePadding || !IsPadded_v<MT> );
6586
6587 for( size_t j=0UL; j<n_; ++j )
6588 {
6589 const size_t ibegin( ( IsLower_v<MT> )
6590 ?( prevMultiple( ( IsStrictlyLower_v<MT> ? j+1UL : j ), SIMDSIZE ) )
6591 :( 0UL ) );
6592 const size_t iend ( ( IsUpper_v<MT> )
6593 ?( IsStrictlyUpper_v<MT> ? j : j+1UL )
6594 :( m_ ) );
6595 BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
6596
6597 const size_t ipos( remainder ? prevMultiple( iend, SIMDSIZE ) : iend );
6598 BLAZE_INTERNAL_ASSERT( ipos <= iend, "Invalid end calculation" );
6599
6600 size_t i( ibegin );
6601 Iterator left( begin(j) + ibegin );
6602 ConstIterator_t<MT> right( (*rhs).begin(j) + ibegin );
6603
6604 for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
6605 left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6606 left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6607 left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6608 left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6609 }
6610 for( ; i<ipos; i+=SIMDSIZE ) {
6611 left.store( left.load() - right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6612 }
6613 for( ; remainder && i<iend; ++i ) {
6614 *left -= *right; ++left; ++right;
6615 }
6616 }
6617 }
6618 /*! \endcond */
6619 //*************************************************************************************************
6620
6621
6622 //*************************************************************************************************
6623 /*! \cond BLAZE_INTERNAL */
6624 /*!\brief Default implementation of the subtraction assignment of a row-major dense matrix.
6625 //
6626 // \param rhs The right-hand side dense matrix to be subtracted.
6627 // \return void
6628 //
6629 // This function must \b NOT be called explicitly! It is used internally for the performance
6630 // optimized evaluation of expression templates. Calling this function explicitly might result
6631 // in erroneous results and/or in compilation errors. Instead of using this function use the
6632 // assignment operator.
6633 */
6634 template< typename Type // Data type of the matrix
6635 , typename Alloc // Type of the allocator
6636 , typename Tag > // Type tag
6637 template< typename MT > // Type of the right-hand side dense matrix
subAssign(const DenseMatrix<MT,false> & rhs)6638 inline void DynamicMatrix<Type,true,Alloc,Tag>::subAssign( const DenseMatrix<MT,false>& rhs )
6639 {
6640 BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
6641
6642 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
6643 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
6644
6645 constexpr size_t block( BLOCK_SIZE );
6646
6647 for( size_t jj=0UL; jj<n_; jj+=block ) {
6648 const size_t jend( min( n_, jj+block ) );
6649 for( size_t ii=0UL; ii<m_; ii+=block )
6650 {
6651 if( IsLower_v<MT> && ii < jj ) continue;
6652 if( IsUpper_v<MT> && ii > jj ) break;
6653
6654 for( size_t j=jj; j<jend; ++j )
6655 {
6656 const size_t ibegin( ( IsLower_v<MT> )
6657 ?( max( ( IsStrictlyLower_v<MT> ? j+1UL : j ), ii ) )
6658 :( ii ) );
6659 const size_t iend ( ( IsUpper_v<MT> )
6660 ?( min( ( IsStrictlyUpper_v<MT> ? j : j+1UL ), m_, ii+block ) )
6661 :( min( m_, ii+block ) ) );
6662 BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" );
6663
6664 for( size_t i=ibegin; i<iend; ++i ) {
6665 v_[i+j*mm_] -= (*rhs)(i,j);
6666 }
6667 }
6668 }
6669 }
6670 }
6671 /*! \endcond */
6672 //*************************************************************************************************
6673
6674
6675 //*************************************************************************************************
6676 /*! \cond BLAZE_INTERNAL */
6677 /*!\brief Default implementation of the subtraction assignment of a column-major sparse matrix.
6678 //
6679 // \param rhs The right-hand side sparse matrix to be subtracted.
6680 // \return void
6681 //
6682 // This function must \b NOT be called explicitly! It is used internally for the performance
6683 // optimized evaluation of expression templates. Calling this function explicitly might result
6684 // in erroneous results and/or in compilation errors. Instead of using this function use the
6685 // assignment operator.
6686 */
6687 template< typename Type // Data type of the matrix
6688 , typename Alloc // Type of the allocator
6689 , typename Tag > // Type tag
6690 template< typename MT > // Type of the right-hand side sparse matrix
subAssign(const SparseMatrix<MT,true> & rhs)6691 inline void DynamicMatrix<Type,true,Alloc,Tag>::subAssign( const SparseMatrix<MT,true>& rhs )
6692 {
6693 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
6694 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
6695
6696 for( size_t j=0UL; j<(*rhs).columns(); ++j )
6697 for( auto element=(*rhs).begin(j); element!=(*rhs).end(j); ++element )
6698 v_[element->index()+j*mm_] -= element->value();
6699 }
6700 /*! \endcond */
6701 //*************************************************************************************************
6702
6703
6704 //*************************************************************************************************
6705 /*! \cond BLAZE_INTERNAL */
6706 /*!\brief Default implementation of the subtraction assignment of a row-major sparse matrix.
6707 //
6708 // \param rhs The right-hand side sparse matrix to be subtracted.
6709 // \return void
6710 //
6711 // This function must \b NOT be called explicitly! It is used internally for the performance
6712 // optimized evaluation of expression templates. Calling this function explicitly might result
6713 // in erroneous results and/or in compilation errors. Instead of using this function use the
6714 // assignment operator.
6715 */
6716 template< typename Type // Data type of the matrix
6717 , typename Alloc // Type of the allocator
6718 , typename Tag > // Type tag
6719 template< typename MT > // Type of the right-hand side sparse matrix
subAssign(const SparseMatrix<MT,false> & rhs)6720 inline void DynamicMatrix<Type,true,Alloc,Tag>::subAssign( const SparseMatrix<MT,false>& rhs )
6721 {
6722 BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
6723
6724 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
6725 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
6726
6727 for( size_t i=0UL; i<(*rhs).rows(); ++i )
6728 for( auto element=(*rhs).begin(i); element!=(*rhs).end(i); ++element )
6729 v_[i+element->index()*mm_] -= element->value();
6730 }
6731 /*! \endcond */
6732 //*************************************************************************************************
6733
6734
6735 //*************************************************************************************************
6736 /*! \cond BLAZE_INTERNAL */
6737 /*!\brief Default implementation of the Schur product assignment of a column-major dense matrix.
6738 //
6739 // \param rhs The right-hand side dense matrix for the Schur product.
6740 // \return void
6741 //
6742 // This function must \b NOT be called explicitly! It is used internally for the performance
6743 // optimized evaluation of expression templates. Calling this function explicitly might result
6744 // in erroneous results and/or in compilation errors. Instead of using this function use the
6745 // assignment operator.
6746 */
6747 template< typename Type // Data type of the matrix
6748 , typename Alloc // Type of the allocator
6749 , typename Tag > // Type tag
6750 template< typename MT > // Type of the right-hand side dense matrix
6751 inline auto DynamicMatrix<Type,true,Alloc,Tag>::schurAssign( const DenseMatrix<MT,true>& rhs )
6752 -> DisableIf_t< VectorizedSchurAssign_v<MT> >
6753 {
6754 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
6755 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
6756
6757 const size_t ipos( prevMultiple( m_, 2UL ) );
6758 BLAZE_INTERNAL_ASSERT( ipos <= m_, "Invalid end calculation" );
6759
6760 for( size_t j=0UL; j<n_; ++j ) {
6761 for( size_t i=0UL; (i+2UL) <= ipos; i+=2UL ) {
6762 v_[i +j*mm_] *= (*rhs)(i ,j);
6763 v_[i+1+j*mm_] *= (*rhs)(i+1,j);
6764 }
6765 if( ipos < m_ ) {
6766 v_[ipos+j*mm_] *= (*rhs)(ipos,j);
6767 }
6768 }
6769 }
6770 /*! \endcond */
6771 //*************************************************************************************************
6772
6773
6774 //*************************************************************************************************
6775 /*! \cond BLAZE_INTERNAL */
6776 /*!\brief SIMD optimized implementation of the Schur product assignment of a column-major dense matrix.
6777 //
6778 // \param rhs The right-hand side dense matrix for the Schur product.
6779 // \return void
6780 //
6781 // This function must \b NOT be called explicitly! It is used internally for the performance
6782 // optimized evaluation of expression templates. Calling this function explicitly might result
6783 // in erroneous results and/or in compilation errors. Instead of using this function use the
6784 // assignment operator.
6785 */
6786 template< typename Type // Data type of the matrix
6787 , typename Alloc // Type of the allocator
6788 , typename Tag > // Type tag
6789 template< typename MT > // Type of the right-hand side dense matrix
6790 inline auto DynamicMatrix<Type,true,Alloc,Tag>::schurAssign( const DenseMatrix<MT,true>& rhs )
6791 -> EnableIf_t< VectorizedSchurAssign_v<MT> >
6792 {
6793 BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type );
6794
6795 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
6796 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
6797
6798 constexpr bool remainder( !usePadding || !IsPadded_v<MT> );
6799
6800 for( size_t j=0UL; j<n_; ++j )
6801 {
6802 const size_t ipos( remainder ? prevMultiple( m_, SIMDSIZE ) : m_ );
6803 BLAZE_INTERNAL_ASSERT( ipos <= m_, "Invalid end calculation" );
6804
6805 size_t i( 0UL );
6806 Iterator left( begin(j) );
6807 ConstIterator_t<MT> right( (*rhs).begin(j) );
6808
6809 for( ; (i+SIMDSIZE*3UL) < ipos; i+=SIMDSIZE*4UL ) {
6810 left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6811 left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6812 left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6813 left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6814 }
6815 for( ; i<ipos; i+=SIMDSIZE ) {
6816 left.store( left.load() * right.load() ); left += SIMDSIZE; right += SIMDSIZE;
6817 }
6818 for( ; remainder && i<m_; ++i ) {
6819 *left *= *right; ++left; ++right;
6820 }
6821 }
6822 }
6823 /*! \endcond */
6824 //*************************************************************************************************
6825
6826
6827 //*************************************************************************************************
6828 /*! \cond BLAZE_INTERNAL */
6829 /*!\brief Default implementation of the Schur product assignment of a row-major dense matrix.
6830 //
6831 // \param rhs The right-hand side dense matrix for the Schur product.
6832 // \return void
6833 //
6834 // This function must \b NOT be called explicitly! It is used internally for the performance
6835 // optimized evaluation of expression templates. Calling this function explicitly might result
6836 // in erroneous results and/or in compilation errors. Instead of using this function use the
6837 // assignment operator.
6838 */
6839 template< typename Type // Data type of the matrix
6840 , typename Alloc // Type of the allocator
6841 , typename Tag > // Type tag
6842 template< typename MT > // Type of the right-hand side dense matrix
schurAssign(const DenseMatrix<MT,false> & rhs)6843 inline void DynamicMatrix<Type,true,Alloc,Tag>::schurAssign( const DenseMatrix<MT,false>& rhs )
6844 {
6845 BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
6846
6847 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
6848 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
6849
6850 constexpr size_t block( BLOCK_SIZE );
6851
6852 for( size_t jj=0UL; jj<n_; jj+=block ) {
6853 const size_t jend( min( n_, jj+block ) );
6854 for( size_t ii=0UL; ii<m_; ii+=block ) {
6855 const size_t iend( min( m_, ii+block ) );
6856 for( size_t j=jj; j<jend; ++j ) {
6857 for( size_t i=ii; i<iend; ++i ) {
6858 v_[i+j*mm_] *= (*rhs)(i,j);
6859 }
6860 }
6861 }
6862 }
6863 }
6864 /*! \endcond */
6865 //*************************************************************************************************
6866
6867
6868 //*************************************************************************************************
6869 /*! \cond BLAZE_INTERNAL */
6870 /*!\brief Default implementation of the Schur product assignment of a column-major sparse matrix.
6871 //
6872 // \param rhs The right-hand side sparse matrix for the Schur product.
6873 // \return void
6874 //
6875 // This function must \b NOT be called explicitly! It is used internally for the performance
6876 // optimized evaluation of expression templates. Calling this function explicitly might result
6877 // in erroneous results and/or in compilation errors. Instead of using this function use the
6878 // assignment operator.
6879 */
6880 template< typename Type // Data type of the matrix
6881 , typename Alloc // Type of the allocator
6882 , typename Tag > // Type tag
6883 template< typename MT > // Type of the right-hand side sparse matrix
schurAssign(const SparseMatrix<MT,true> & rhs)6884 inline void DynamicMatrix<Type,true,Alloc,Tag>::schurAssign( const SparseMatrix<MT,true>& rhs )
6885 {
6886 using blaze::reset;
6887
6888 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
6889 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
6890
6891 for( size_t j=0UL; j<n_; ++j )
6892 {
6893 size_t i( 0UL );
6894
6895 for( auto element=(*rhs).begin(j); element!=(*rhs).end(j); ++element ) {
6896 for( ; i<element->index(); ++i )
6897 reset( v_[i+j*mm_] );
6898 v_[i+j*mm_] *= element->value();
6899 ++i;
6900 }
6901
6902 for( ; i<m_; ++i ) {
6903 reset( v_[i+j*mm_] );
6904 }
6905 }
6906 }
6907 /*! \endcond */
6908 //*************************************************************************************************
6909
6910
6911 //*************************************************************************************************
6912 /*! \cond BLAZE_INTERNAL */
6913 /*!\brief Default implementation of the Schur product assignment of a row-major sparse matrix.
6914 //
6915 // \param rhs The right-hand side sparse matrix for the Schur product.
6916 // \return void
6917 //
6918 // This function must \b NOT be called explicitly! It is used internally for the performance
6919 // optimized evaluation of expression templates. Calling this function explicitly might result
6920 // in erroneous results and/or in compilation errors. Instead of using this function use the
6921 // assignment operator.
6922 */
6923 template< typename Type // Data type of the matrix
6924 , typename Alloc // Type of the allocator
6925 , typename Tag > // Type tag
6926 template< typename MT > // Type of the right-hand side sparse matrix
schurAssign(const SparseMatrix<MT,false> & rhs)6927 inline void DynamicMatrix<Type,true,Alloc,Tag>::schurAssign( const SparseMatrix<MT,false>& rhs )
6928 {
6929 using blaze::reset;
6930
6931 BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT );
6932
6933 BLAZE_INTERNAL_ASSERT( m_ == (*rhs).rows() , "Invalid number of rows" );
6934 BLAZE_INTERNAL_ASSERT( n_ == (*rhs).columns(), "Invalid number of columns" );
6935
6936 for( size_t i=0UL; i<m_; ++i )
6937 {
6938 size_t j( 0UL );
6939
6940 for( auto element=(*rhs).begin(i); element!=(*rhs).end(i); ++element ) {
6941 for( ; j<element->index(); ++j )
6942 reset( v_[i+j*mm_] );
6943 v_[i+j*mm_] *= element->value();
6944 ++j;
6945 }
6946
6947 for( ; j<n_; ++j ) {
6948 reset( v_[i+j*mm_] );
6949 }
6950 }
6951 }
6952 /*! \endcond */
6953 //*************************************************************************************************
6954
6955
6956
6957
6958
6959
6960
6961
6962 //=================================================================================================
6963 //
6964 // DYNAMICMATRIX OPERATORS
6965 //
6966 //=================================================================================================
6967
6968 //*************************************************************************************************
6969 /*!\name DynamicMatrix operators */
6970 //@{
6971 template< typename Type, bool SO, typename Alloc, typename Tag >
6972 void reset( DynamicMatrix<Type,SO,Alloc,Tag>& m );
6973
6974 template< typename Type, bool SO, typename Alloc, typename Tag >
6975 void reset( DynamicMatrix<Type,SO,Alloc,Tag>& m, size_t i );
6976
6977 template< typename Type, bool SO, typename Alloc, typename Tag >
6978 void clear( DynamicMatrix<Type,SO,Alloc,Tag>& m );
6979
6980 template< RelaxationFlag RF, typename Type, bool SO, typename Alloc, typename Tag >
6981 bool isDefault( const DynamicMatrix<Type,SO,Alloc,Tag>& m );
6982
6983 template< typename Type, bool SO, typename Alloc, typename Tag >
6984 bool isIntact( const DynamicMatrix<Type,SO,Alloc,Tag>& m ) noexcept;
6985
6986 template< typename Type, bool SO, typename Alloc, typename Tag >
6987 void swap( DynamicMatrix<Type,SO,Alloc,Tag>& a, DynamicMatrix<Type,SO,Alloc,Tag>& b ) noexcept;
6988 //@}
6989 //*************************************************************************************************
6990
6991
6992 //*************************************************************************************************
6993 /*!\brief Resetting the given dynamic matrix.
6994 // \ingroup dynamic_matrix
6995 //
6996 // \param m The matrix to be resetted.
6997 // \return void
6998 */
6999 template< typename Type // Data type of the matrix
7000 , bool SO // Storage order
7001 , typename Alloc // Type of the allocator
7002 , typename Tag > // Type tag
reset(DynamicMatrix<Type,SO,Alloc,Tag> & m)7003 inline void reset( DynamicMatrix<Type,SO,Alloc,Tag>& m )
7004 {
7005 m.reset();
7006 }
7007 //*************************************************************************************************
7008
7009
7010 //*************************************************************************************************
7011 /*!\brief Reset the specified row/column of the given dynamic matrix.
7012 // \ingroup dynamic_matrix
7013 //
7014 // \param m The matrix to be resetted.
7015 // \param i The index of the row/column to be resetted.
7016 // \return void
7017 //
7018 // This function resets the values in the specified row/column of the given dynamic matrix to
7019 // their default value. In case the given matrix is a \a rowMajor matrix the function resets the
7020 // values in row \a i, if it is a \a columnMajor matrix the function resets the values in column
7021 // \a i. Note that the capacity of the row/column remains unchanged.
7022 */
7023 template< typename Type // Data type of the matrix
7024 , bool SO // Storage order
7025 , typename Alloc // Type of the allocator
7026 , typename Tag > // Type tag
reset(DynamicMatrix<Type,SO,Alloc,Tag> & m,size_t i)7027 inline void reset( DynamicMatrix<Type,SO,Alloc,Tag>& m, size_t i )
7028 {
7029 m.reset( i );
7030 }
7031 //*************************************************************************************************
7032
7033
7034 //*************************************************************************************************
7035 /*!\brief Clearing the given dynamic matrix.
7036 // \ingroup dynamic_matrix
7037 //
7038 // \param m The matrix to be cleared.
7039 // \return void
7040 */
7041 template< typename Type // Data type of the matrix
7042 , bool SO // Storage order
7043 , typename Alloc // Type of the allocator
7044 , typename Tag > // Type tag
clear(DynamicMatrix<Type,SO,Alloc,Tag> & m)7045 inline void clear( DynamicMatrix<Type,SO,Alloc,Tag>& m )
7046 {
7047 m.clear();
7048 }
7049 //*************************************************************************************************
7050
7051
7052 //*************************************************************************************************
7053 /*!\brief Returns whether the given dynamic matrix is in default state.
7054 // \ingroup dynamic_matrix
7055 //
7056 // \param m The matrix to be tested for its default state.
7057 // \return \a true in case the given matrix's rows and columns are zero, \a false otherwise.
7058 //
7059 // This function checks whether the dynamic matrix is in default (constructed) state, i.e. if
7060 // it's number of rows and columns is 0. In case it is in default state, the function returns
7061 // \a true, else it will return \a false. The following example demonstrates the use of the
7062 // \a isDefault() function:
7063
7064 \code
7065 blaze::DynamicMatrix<int> A;
7066 // ... Resizing and initialization
7067 if( isDefault( A ) ) { ... }
7068 \endcode
7069
7070 // Optionally, it is possible to switch between strict semantics (blaze::strict) and relaxed
7071 // semantics (blaze::relaxed):
7072
7073 \code
7074 if( isDefault<relaxed>( A ) ) { ... }
7075 \endcode
7076 */
7077 template< RelaxationFlag RF // Relaxation flag
7078 , typename Type // Data type of the matrix
7079 , bool SO // Storage order
7080 , typename Alloc // Type of the allocator
7081 , typename Tag > // Type tag
isDefault(const DynamicMatrix<Type,SO,Alloc,Tag> & m)7082 inline bool isDefault( const DynamicMatrix<Type,SO,Alloc,Tag>& m )
7083 {
7084 return ( m.rows() == 0UL && m.columns() == 0UL );
7085 }
7086 //*************************************************************************************************
7087
7088
7089 //*************************************************************************************************
7090 /*!\brief Returns whether the invariants of the given dynamic matrix are intact.
7091 // \ingroup dynamic_matrix
7092 //
7093 // \param m The dynamic matrix to be tested.
7094 // \return \a true in case the given matrix's invariants are intact, \a false otherwise.
7095 //
7096 // This function checks whether the invariants of the dynamic matrix are intact, i.e. if its
7097 // state is valid. In case the invariants are intact, the function returns \a true, else it
7098 // will return \a false. The following example demonstrates the use of the \a isIntact()
7099 // function:
7100
7101 \code
7102 blaze::DynamicMatrix<int> A;
7103 // ... Resizing and initialization
7104 if( isIntact( A ) ) { ... }
7105 \endcode
7106 */
7107 template< typename Type // Data type of the matrix
7108 , bool SO // Storage order
7109 , typename Alloc // Type of the allocator
7110 , typename Tag > // Type tag
isIntact(const DynamicMatrix<Type,SO,Alloc,Tag> & m)7111 inline bool isIntact( const DynamicMatrix<Type,SO,Alloc,Tag>& m ) noexcept
7112 {
7113 return m.isIntact();
7114 }
7115 //*************************************************************************************************
7116
7117
7118 //*************************************************************************************************
7119 /*!\brief Swapping the contents of two dynamic matrices.
7120 // \ingroup dynamic_matrix
7121 //
7122 // \param a The first matrix to be swapped.
7123 // \param b The second matrix to be swapped.
7124 // \return void
7125 */
7126 template< typename Type // Data type of the matrix
7127 , bool SO // Storage order
7128 , typename Alloc // Type of the allocator
7129 , typename Tag > // Type tag
swap(DynamicMatrix<Type,SO,Alloc,Tag> & a,DynamicMatrix<Type,SO,Alloc,Tag> & b)7130 inline void swap( DynamicMatrix<Type,SO,Alloc,Tag>& a, DynamicMatrix<Type,SO,Alloc,Tag>& b ) noexcept
7131 {
7132 a.swap( b );
7133 }
7134 //*************************************************************************************************
7135
7136
7137
7138
7139 //=================================================================================================
7140 //
7141 // HASCONSTDATAACCESS SPECIALIZATIONS
7142 //
7143 //=================================================================================================
7144
7145 //*************************************************************************************************
7146 /*! \cond BLAZE_INTERNAL */
7147 template< typename T, bool SO, typename Alloc, typename Tag >
7148 struct HasConstDataAccess< DynamicMatrix<T,SO,Alloc,Tag> >
7149 : public TrueType
7150 {};
7151 /*! \endcond */
7152 //*************************************************************************************************
7153
7154
7155
7156
7157 //=================================================================================================
7158 //
7159 // HASMUTABLEDATAACCESS SPECIALIZATIONS
7160 //
7161 //=================================================================================================
7162
7163 //*************************************************************************************************
7164 /*! \cond BLAZE_INTERNAL */
7165 template< typename T, bool SO, typename Alloc, typename Tag >
7166 struct HasMutableDataAccess< DynamicMatrix<T,SO,Alloc,Tag> >
7167 : public TrueType
7168 {};
7169 /*! \endcond */
7170 //*************************************************************************************************
7171
7172
7173
7174
7175 //=================================================================================================
7176 //
7177 // ISALIGNED SPECIALIZATIONS
7178 //
7179 //=================================================================================================
7180
7181 //*************************************************************************************************
7182 /*! \cond BLAZE_INTERNAL */
7183 template< typename T, bool SO, typename Alloc, typename Tag >
7184 struct IsAligned< DynamicMatrix<T,SO,Alloc,Tag> >
7185 : public BoolConstant<usePadding>
7186 {};
7187 /*! \endcond */
7188 //*************************************************************************************************
7189
7190
7191
7192
7193 //=================================================================================================
7194 //
7195 // ISCONTIGUOUS SPECIALIZATIONS
7196 //
7197 //=================================================================================================
7198
7199 //*************************************************************************************************
7200 /*! \cond BLAZE_INTERNAL */
7201 template< typename T, bool SO, typename Alloc, typename Tag >
7202 struct IsContiguous< DynamicMatrix<T,SO,Alloc,Tag> >
7203 : public TrueType
7204 {};
7205 /*! \endcond */
7206 //*************************************************************************************************
7207
7208
7209
7210
7211 //=================================================================================================
7212 //
7213 // ISPADDED SPECIALIZATIONS
7214 //
7215 //=================================================================================================
7216
7217 //*************************************************************************************************
7218 /*! \cond BLAZE_INTERNAL */
7219 template< typename T, bool SO, typename Alloc, typename Tag >
7220 struct IsPadded< DynamicMatrix<T,SO,Alloc,Tag> >
7221 : public BoolConstant<usePadding>
7222 {};
7223 /*! \endcond */
7224 //*************************************************************************************************
7225
7226
7227
7228
7229 //=================================================================================================
7230 //
7231 // ISRESIZABLE SPECIALIZATIONS
7232 //
7233 //=================================================================================================
7234
7235 //*************************************************************************************************
7236 /*! \cond BLAZE_INTERNAL */
7237 template< typename T, bool SO, typename Alloc, typename Tag >
7238 struct IsResizable< DynamicMatrix<T,SO,Alloc,Tag> >
7239 : public TrueType
7240 {};
7241 /*! \endcond */
7242 //*************************************************************************************************
7243
7244
7245
7246
7247 //=================================================================================================
7248 //
7249 // ISSHRINKABLE SPECIALIZATIONS
7250 //
7251 //=================================================================================================
7252
7253 //*************************************************************************************************
7254 /*! \cond BLAZE_INTERNAL */
7255 template< typename T, bool SO, typename Alloc, typename Tag >
7256 struct IsShrinkable< DynamicMatrix<T,SO,Alloc,Tag> >
7257 : public TrueType
7258 {};
7259 /*! \endcond */
7260 //*************************************************************************************************
7261
7262
7263
7264
7265 //=================================================================================================
7266 //
7267 // ADDTRAIT SPECIALIZATIONS
7268 //
7269 //=================================================================================================
7270
7271 //*************************************************************************************************
7272 /*! \cond BLAZE_INTERNAL */
7273 template< typename T1, typename T2 >
7274 struct AddTraitEval2< T1, T2
7275 , EnableIf_t< IsMatrix_v<T1> &&
7276 IsMatrix_v<T2> &&
7277 ( IsDenseMatrix_v<T1> || IsDenseMatrix_v<T2> ) &&
7278 ( Size_v<T1,0UL> == DefaultSize_v ) &&
7279 ( Size_v<T2,0UL> == DefaultSize_v ) &&
7280 ( Size_v<T1,1UL> == DefaultSize_v ) &&
7281 ( Size_v<T2,1UL> == DefaultSize_v ) &&
7282 ( MaxSize_v<T1,0UL> == DefaultMaxSize_v ) &&
7283 ( MaxSize_v<T2,0UL> == DefaultMaxSize_v ) &&
7284 ( MaxSize_v<T1,1UL> == DefaultMaxSize_v ) &&
7285 ( MaxSize_v<T2,1UL> == DefaultMaxSize_v ) > >
7286 {
7287 using ET = AddTrait_t< ElementType_t<T1>, ElementType_t<T2> >;
7288
7289 static constexpr bool SO1 = StorageOrder_v<T1>;
7290 static constexpr bool SO2 = StorageOrder_v<T2>;
7291
7292 static constexpr bool SO = ( IsDenseMatrix_v<T1> && IsDenseMatrix_v<T2>
7293 ? ( IsSymmetric_v<T1> ^ IsSymmetric_v<T2>
7294 ? ( IsSymmetric_v<T1>
7295 ? SO2
7296 : SO1 )
7297 : SO1 && SO2 )
7298 : ( IsDenseMatrix_v<T1>
7299 ? SO1
7300 : SO2 ) );
7301
7302 using Type = DynamicMatrix< ET
7303 , SO
7304 , DynamicAllocator_t< ET, GetAllocator_t<T1>, GetAllocator_t<T2> >
7305 , AddTrait_t< TagType_t<T1>, TagType_t<T2> > >;
7306 };
7307 /*! \endcond */
7308 //*************************************************************************************************
7309
7310
7311
7312
7313 //=================================================================================================
7314 //
7315 // SUBTRAIT SPECIALIZATIONS
7316 //
7317 //=================================================================================================
7318
7319 //*************************************************************************************************
7320 /*! \cond BLAZE_INTERNAL */
7321 template< typename T1, typename T2 >
7322 struct SubTraitEval2< T1, T2
7323 , EnableIf_t< IsMatrix_v<T1> &&
7324 IsMatrix_v<T2> &&
7325 ( IsDenseMatrix_v<T1> || IsDenseMatrix_v<T2> ) &&
7326 ( Size_v<T1,0UL> == DefaultSize_v ) &&
7327 ( Size_v<T2,0UL> == DefaultSize_v ) &&
7328 ( Size_v<T1,1UL> == DefaultSize_v ) &&
7329 ( Size_v<T2,1UL> == DefaultSize_v ) &&
7330 ( MaxSize_v<T1,0UL> == DefaultMaxSize_v ) &&
7331 ( MaxSize_v<T2,0UL> == DefaultMaxSize_v ) &&
7332 ( MaxSize_v<T1,1UL> == DefaultMaxSize_v ) &&
7333 ( MaxSize_v<T2,1UL> == DefaultMaxSize_v ) > >
7334 {
7335 using ET = SubTrait_t< ElementType_t<T1>, ElementType_t<T2> >;
7336
7337 static constexpr bool SO1 = StorageOrder_v<T1>;
7338 static constexpr bool SO2 = StorageOrder_v<T2>;
7339
7340 static constexpr bool SO = ( IsDenseMatrix_v<T1> && IsDenseMatrix_v<T2>
7341 ? ( IsSymmetric_v<T1> ^ IsSymmetric_v<T2>
7342 ? ( IsSymmetric_v<T1>
7343 ? SO2
7344 : SO1 )
7345 : SO1 && SO2 )
7346 : ( IsDenseMatrix_v<T1>
7347 ? SO1
7348 : SO2 ) );
7349
7350 using Type = DynamicMatrix< ET
7351 , SO
7352 , DynamicAllocator_t< ET, GetAllocator_t<T1>, GetAllocator_t<T2> >
7353 , SubTrait_t< TagType_t<T1>, TagType_t<T2> > >;
7354 };
7355 /*! \endcond */
7356 //*************************************************************************************************
7357
7358
7359
7360
7361 //=================================================================================================
7362 //
7363 // SCHURTRAIT SPECIALIZATIONS
7364 //
7365 //=================================================================================================
7366
7367 //*************************************************************************************************
7368 /*! \cond BLAZE_INTERNAL */
7369 template< typename T1, typename T2 >
7370 struct SchurTraitEval2< T1, T2
7371 , EnableIf_t< IsDenseMatrix_v<T1> &&
7372 IsDenseMatrix_v<T2> &&
7373 ( Size_v<T1,0UL> == DefaultSize_v ) &&
7374 ( Size_v<T2,0UL> == DefaultSize_v ) &&
7375 ( Size_v<T1,1UL> == DefaultSize_v ) &&
7376 ( Size_v<T2,1UL> == DefaultSize_v ) &&
7377 ( MaxSize_v<T1,0UL> == DefaultMaxSize_v ) &&
7378 ( MaxSize_v<T2,0UL> == DefaultMaxSize_v ) &&
7379 ( MaxSize_v<T1,1UL> == DefaultMaxSize_v ) &&
7380 ( MaxSize_v<T2,1UL> == DefaultMaxSize_v ) > >
7381 {
7382 using ET = MultTrait_t< ElementType_t<T1>, ElementType_t<T2> >;
7383
7384 static constexpr bool SO1 = StorageOrder_v<T1>;
7385 static constexpr bool SO2 = StorageOrder_v<T2>;
7386
7387 static constexpr bool SO = ( IsSymmetric_v<T1> ^ IsSymmetric_v<T2>
7388 ? ( IsSymmetric_v<T1>
7389 ? SO2
7390 : SO1 )
7391 : SO1 && SO2 );
7392
7393 using Type = DynamicMatrix< ET
7394 , SO
7395 , DynamicAllocator_t< ET, GetAllocator_t<T1>, GetAllocator_t<T2> >
7396 , MultTrait_t< TagType_t<T1>, TagType_t<T2> > >;
7397 };
7398 /*! \endcond */
7399 //*************************************************************************************************
7400
7401
7402
7403
7404 //=================================================================================================
7405 //
7406 // MULTTRAIT SPECIALIZATIONS
7407 //
7408 //=================================================================================================
7409
7410 //*************************************************************************************************
7411 /*! \cond BLAZE_INTERNAL */
7412 template< typename T1, typename T2 >
7413 struct MultTraitEval2< T1, T2
7414 , EnableIf_t< IsDenseMatrix_v<T1> &&
7415 IsScalar_v<T2> &&
7416 ( Size_v<T1,0UL> == DefaultSize_v ) &&
7417 ( Size_v<T1,1UL> == DefaultSize_v ) &&
7418 ( MaxSize_v<T1,0UL> == DefaultMaxSize_v ) &&
7419 ( MaxSize_v<T1,1UL> == DefaultMaxSize_v ) > >
7420 {
7421 using ET = MultTrait_t< ElementType_t<T1>, T2 >;
7422
7423 using Type = DynamicMatrix< ET
7424 , StorageOrder_v<T1>
7425 , DynamicAllocator_t< ET, GetAllocator_t<T1> >
7426 , MultTrait_t< TagType_t<T1>, T2 > >;
7427 };
7428
7429 template< typename T1, typename T2 >
7430 struct MultTraitEval2< T1, T2
7431 , EnableIf_t< IsScalar_v<T1> &&
7432 IsDenseMatrix_v<T2> &&
7433 ( Size_v<T2,0UL> == DefaultSize_v ) &&
7434 ( Size_v<T2,1UL> == DefaultSize_v ) &&
7435 ( MaxSize_v<T2,0UL> == DefaultMaxSize_v ) &&
7436 ( MaxSize_v<T2,1UL> == DefaultMaxSize_v ) > >
7437 {
7438 using ET = MultTrait_t< T1, ElementType_t<T2> >;
7439
7440 using Type = DynamicMatrix< ET
7441 , StorageOrder_v<T2>
7442 , DynamicAllocator_t< ET, GetAllocator_t<T2> >
7443 , MultTrait_t< T1, TagType_t<T2> > >;
7444 };
7445
7446 template< typename T1, typename T2 >
7447 struct MultTraitEval2< T1, T2
7448 , EnableIf_t< IsDenseVector_v<T1> &&
7449 IsDenseVector_v<T2> &&
7450 IsColumnVector_v<T1> &&
7451 IsRowVector_v<T2> &&
7452 ( ( Size_v<T1,0UL> == DefaultSize_v ) ||
7453 ( Size_v<T2,0UL> == DefaultSize_v ) ) &&
7454 ( ( MaxSize_v<T1,0UL> == DefaultMaxSize_v ) ||
7455 ( MaxSize_v<T2,0UL> == DefaultMaxSize_v ) ) > >
7456 {
7457 using ET = MultTrait_t< ElementType_t<T1>, ElementType_t<T2> >;
7458
7459 using Type = DynamicMatrix< ET
7460 , false
7461 , DynamicAllocator_t< ET, GetAllocator_t<T1>, GetAllocator_t<T2> >
7462 , MultTrait_t< TagType_t<T1>, TagType_t<T2> > >;
7463 };
7464
7465 template< typename T1, typename T2 >
7466 struct MultTraitEval2< T1, T2
7467 , EnableIf_t< IsMatrix_v<T1> &&
7468 IsMatrix_v<T2> &&
7469 ( IsDenseMatrix_v<T1> || IsDenseMatrix_v<T2> ) &&
7470 ( ( Size_v<T1,0UL> == DefaultSize_v &&
7471 ( !IsSquare_v<T1> || Size_v<T2,0UL> == DefaultSize_v ) ) ||
7472 ( Size_v<T2,1UL> == DefaultSize_v &&
7473 ( !IsSquare_v<T2> || Size_v<T1,1UL> == DefaultSize_v ) ) ) &&
7474 ( ( MaxSize_v<T1,0UL> == DefaultMaxSize_v &&
7475 ( !IsSquare_v<T1> || MaxSize_v<T2,0UL> == DefaultMaxSize_v ) ) ||
7476 ( MaxSize_v<T2,1UL> == DefaultMaxSize_v &&
7477 ( !IsSquare_v<T2> || MaxSize_v<T1,1UL> == DefaultMaxSize_v ) ) ) > >
7478 {
7479 using M1 = MultTrait_t< ElementType_t<T1>, ElementType_t<T2> >;
7480 using M2 = MultTrait_t< TagType_t<T1>, TagType_t<T2> >;
7481 using ET = AddTrait_t<M1,M1>;
7482
7483 using Type = DynamicMatrix< ET
7484 , ( IsSparseMatrix_v<T1> ? StorageOrder_v<T2> : StorageOrder_v<T1> )
7485 , DynamicAllocator_t< ET, GetAllocator_t<T1>, GetAllocator_t<T2> >
7486 , AddTrait_t<M2,M2> >;
7487 };
7488 /*! \endcond */
7489 //*************************************************************************************************
7490
7491
7492
7493
7494 //=================================================================================================
7495 //
7496 // KRONTRAIT SPECIALIZATIONS
7497 //
7498 //=================================================================================================
7499
7500 //*************************************************************************************************
7501 /*! \cond BLAZE_INTERNAL */
7502 template< typename T1, typename T2 >
7503 struct KronTraitEval2< T1, T2
7504 , EnableIf_t< IsDenseMatrix_v<T1> &&
7505 IsDenseMatrix_v<T2> &&
7506 ( ( Size_v<T1,0UL> == DefaultSize_v ) ||
7507 ( Size_v<T2,0UL> == DefaultSize_v ) ||
7508 ( Size_v<T1,1UL> == DefaultSize_v ) ||
7509 ( Size_v<T2,1UL> == DefaultSize_v ) ) &&
7510 ( ( MaxSize_v<T1,0UL> == DefaultMaxSize_v ) ||
7511 ( MaxSize_v<T2,0UL> == DefaultMaxSize_v ) ||
7512 ( MaxSize_v<T1,1UL> == DefaultMaxSize_v ) ||
7513 ( MaxSize_v<T2,1UL> == DefaultMaxSize_v ) ) > >
7514 {
7515 using ET = MultTrait_t< ElementType_t<T1>, ElementType_t<T2> >;
7516
7517 using Type = DynamicMatrix< ET
7518 , StorageOrder_v<T2>
7519 , DynamicAllocator_t< ET, GetAllocator_t<T1>, GetAllocator_t<T2> >
7520 , MultTrait_t< TagType_t<T1>, TagType_t<T2> > >;
7521 };
7522 /*! \endcond */
7523 //*************************************************************************************************
7524
7525
7526
7527
7528 //=================================================================================================
7529 //
7530 // DIVTRAIT SPECIALIZATIONS
7531 //
7532 //=================================================================================================
7533
7534 //*************************************************************************************************
7535 /*! \cond BLAZE_INTERNAL */
7536 template< typename T1, typename T2 >
7537 struct DivTraitEval2< T1, T2
7538 , EnableIf_t< IsDenseMatrix_v<T1> &&
7539 IsScalar_v<T2> &&
7540 ( Size_v<T1,0UL> == DefaultSize_v ) &&
7541 ( Size_v<T1,1UL> == DefaultSize_v ) &&
7542 ( MaxSize_v<T1,0UL> == DefaultMaxSize_v ) &&
7543 ( MaxSize_v<T1,1UL> == DefaultMaxSize_v ) > >
7544 {
7545 using ET = DivTrait_t< ElementType_t<T1>, T2 >;
7546
7547 using Type = DynamicMatrix< ET
7548 , StorageOrder_v<T1>
7549 , DynamicAllocator_t< ET, GetAllocator_t<T1> >
7550 , DivTrait_t< TagType_t<T1>, T2 > >;
7551 };
7552 /*! \endcond */
7553 //*************************************************************************************************
7554
7555
7556
7557
7558 //=================================================================================================
7559 //
7560 // MAPTRAIT SPECIALIZATIONS
7561 //
7562 //=================================================================================================
7563
7564 //*************************************************************************************************
7565 /*! \cond BLAZE_INTERNAL */
7566 template< typename T, typename OP >
7567 struct UnaryMapTraitEval2< T, OP
7568 , EnableIf_t< IsDenseMatrix_v<T> &&
7569 ( Size_v<T,0UL> == DefaultSize_v ||
7570 Size_v<T,1UL> == DefaultSize_v ) &&
7571 ( MaxSize_v<T,0UL> == DefaultMaxSize_v ||
7572 MaxSize_v<T,1UL> == DefaultMaxSize_v ) > >
7573 {
7574 using ET =
7575 EvaluateTrait_t< decltype( std::declval<OP>()( std::declval< ElementType_t<T> >() ) ) >;
7576
7577 using Type = DynamicMatrix< ET
7578 , StorageOrder_v<T>
7579 , DynamicAllocator_t< ET, GetAllocator_t<T> >
7580 , MapTrait_t< TagType_t<T>, OP > >;
7581 };
7582 /*! \endcond */
7583 //*************************************************************************************************
7584
7585
7586 //*************************************************************************************************
7587 /*! \cond BLAZE_INTERNAL */
7588 template< typename T1, typename T2, typename OP >
7589 struct BinaryMapTraitEval2< T1, T2, OP
7590 , EnableIf_t< IsColumnVector_v<T1> &&
7591 IsRowVector_v<T2> &&
7592 ( ( Size_v<T1,0UL> == DefaultSize_v ) ||
7593 ( Size_v<T2,0UL> == DefaultSize_v ) ) &&
7594 ( ( MaxSize_v<T1,0UL> == DefaultMaxSize_v ) ||
7595 ( MaxSize_v<T2,0UL> == DefaultMaxSize_v ) ) > >
7596 {
7597 using ET =
7598 EvaluateTrait_t< decltype( std::declval<OP>()( std::declval< ElementType_t<T1> >()
7599 , std::declval< ElementType_t<T2> >() ) ) >;
7600
7601 using Type = DynamicMatrix< ET
7602 , false
7603 , DynamicAllocator_t< ET, GetAllocator_t<T1>, GetAllocator_t<T2> >
7604 , MapTrait_t< TagType_t<T1>, TagType_t<T2>, OP > >;
7605 };
7606
7607 template< typename T1, typename T2, typename OP >
7608 struct BinaryMapTraitEval2< T1, T2, OP
7609 , EnableIf_t< IsMatrix_v<T1> &&
7610 IsMatrix_v<T2> &&
7611 ( Size_v<T1,0UL> == DefaultSize_v ) &&
7612 ( Size_v<T2,0UL> == DefaultSize_v ) &&
7613 ( Size_v<T1,1UL> == DefaultSize_v ) &&
7614 ( Size_v<T2,1UL> == DefaultSize_v ) &&
7615 ( MaxSize_v<T1,0UL> == DefaultMaxSize_v ) &&
7616 ( MaxSize_v<T2,0UL> == DefaultMaxSize_v ) &&
7617 ( MaxSize_v<T1,1UL> == DefaultMaxSize_v ) &&
7618 ( MaxSize_v<T2,1UL> == DefaultMaxSize_v ) > >
7619 {
7620 using ET =
7621 EvaluateTrait_t< decltype( std::declval<OP>()( std::declval< ElementType_t<T1> >()
7622 , std::declval< ElementType_t<T2> >() ) ) >;
7623
7624 static constexpr bool SO1 = StorageOrder_v<T1>;
7625 static constexpr bool SO2 = StorageOrder_v<T2>;
7626
7627 static constexpr bool SO = ( IsDenseMatrix_v<T1> && IsDenseMatrix_v<T2>
7628 ? ( IsSymmetric_v<T1> ^ IsSymmetric_v<T2>
7629 ? ( IsSymmetric_v<T1>
7630 ? SO2
7631 : SO1 )
7632 : SO1 && SO2 )
7633 : ( IsDenseMatrix_v<T1>
7634 ? SO1
7635 : SO2 ) );
7636
7637 using Type = DynamicMatrix< ET
7638 , SO
7639 , DynamicAllocator_t< ET, GetAllocator_t<T1>, GetAllocator_t<T2> >
7640 , MapTrait_t< TagType_t<T1>, TagType_t<T2>, OP > >;
7641 };
7642 /*! \endcond */
7643 //*************************************************************************************************
7644
7645
7646
7647
7648 //=================================================================================================
7649 //
7650 // EXPANDTRAIT SPECIALIZATIONS
7651 //
7652 //=================================================================================================
7653
7654 //*************************************************************************************************
7655 /*! \cond BLAZE_INTERNAL */
7656 template< typename T, size_t E >
7657 struct ExpandTraitEval2< T, E
7658 , EnableIf_t< IsDenseVector_v<T> &&
7659 ( ( E == inf ) ||
7660 ( ( Size_v<T,0UL> == DefaultSize_v ) &&
7661 ( MaxSize_v<T,0UL> == DefaultMaxSize_v ) ) ) > >
7662 {
7663 using Type = DynamicMatrix< ElementType_t<T>
7664 , ( IsColumnVector_v<T> ? columnMajor : rowMajor )
7665 , DynamicAllocator_t< ElementType_t<T>, GetAllocator_t<T> >
7666 , TagType_t<T> >;
7667 };
7668 /*! \endcond */
7669 //*************************************************************************************************
7670
7671
7672
7673
7674 //=================================================================================================
7675 //
7676 // REPEATTRAIT SPECIALIZATIONS
7677 //
7678 //=================================================================================================
7679
7680 //*************************************************************************************************
7681 /*! \cond BLAZE_INTERNAL */
7682 template< typename T, size_t R0, size_t R1 >
7683 struct RepeatTraitEval2< T, R0, R1, inf
7684 , EnableIf_t< IsDenseMatrix_v<T> &&
7685 ( ( R0 == inf && R1 == inf ) ||
7686 ( ( Size_v<T,0UL> == DefaultSize_v ) &&
7687 ( MaxSize_v<T,0UL> == DefaultMaxSize_v ) ) ||
7688 ( ( Size_v<T,1UL> == DefaultSize_v ) &&
7689 ( MaxSize_v<T,1UL> == DefaultMaxSize_v ) ) ) > >
7690 {
7691 using Type = DynamicMatrix< ElementType_t<T>
7692 , StorageOrder_v<T>
7693 , DynamicAllocator_t< ElementType_t<T>, GetAllocator_t<T> >
7694 , TagType_t<T> >;
7695 };
7696 /*! \endcond */
7697 //*************************************************************************************************
7698
7699
7700
7701
7702 //=================================================================================================
7703 //
7704 // SOLVETRAIT SPECIALIZATIONS
7705 //
7706 //=================================================================================================
7707
7708 //*************************************************************************************************
7709 /*! \cond BLAZE_INTERNAL */
7710 template< typename T1, typename T2 >
7711 struct SolveTraitEval2< T1, T2
7712 , EnableIf_t< IsDenseMatrix_v<T1> &&
7713 IsDenseMatrix_v<T2> &&
7714 ( ( ( Size_v<T1,0UL> == DefaultSize_v ) &&
7715 ( Size_v<T2,0UL> == DefaultSize_v ) &&
7716 ( Size_v<T1,1UL> == DefaultSize_v ) &&
7717 ( MaxSize_v<T1,0UL> == DefaultMaxSize_v ) &&
7718 ( MaxSize_v<T2,0UL> == DefaultMaxSize_v ) &&
7719 ( MaxSize_v<T1,1UL> == DefaultMaxSize_v ) ) ||
7720 ( ( Size_v<T2,1UL> == DefaultSize_v ) &&
7721 ( MaxSize_v<T2,1UL> == DefaultMaxSize_v ) ) ) > >
7722 {
7723 using Type = DynamicMatrix< ElementType_t<T2>
7724 , StorageOrder_v<T2>
7725 , DynamicAllocator_t< ElementType_t<T2>, GetAllocator_t<T2> >
7726 , TagType_t<T2> >;
7727 };
7728 /*! \endcond */
7729 //*************************************************************************************************
7730
7731
7732
7733
7734 //=================================================================================================
7735 //
7736 // HIGHTYPE SPECIALIZATIONS
7737 //
7738 //=================================================================================================
7739
7740 //*************************************************************************************************
7741 /*! \cond BLAZE_INTERNAL */
7742 template< typename T1, bool SO, typename Alloc, typename Tag, typename T2 >
7743 struct HighType< DynamicMatrix<T1,SO,Alloc,Tag>, DynamicMatrix<T2,SO,Alloc,Tag> >
7744 {
7745 using Type = DynamicMatrix< typename HighType<T1,T2>::Type, SO, Alloc, Tag >;
7746 };
7747 /*! \endcond */
7748 //*************************************************************************************************
7749
7750
7751
7752
7753 //=================================================================================================
7754 //
7755 // LOWTYPE SPECIALIZATIONS
7756 //
7757 //=================================================================================================
7758
7759 //*************************************************************************************************
7760 /*! \cond BLAZE_INTERNAL */
7761 template< typename T1, bool SO, typename Alloc, typename Tag, typename T2 >
7762 struct LowType< DynamicMatrix<T1,SO,Alloc,Tag>, DynamicMatrix<T2,SO,Alloc,Tag> >
7763 {
7764 using Type = DynamicMatrix< typename LowType<T1,T2>::Type, SO, Alloc, Tag >;
7765 };
7766 /*! \endcond */
7767 //*************************************************************************************************
7768
7769
7770
7771
7772 //=================================================================================================
7773 //
7774 // SUBMATRIXTRAIT SPECIALIZATIONS
7775 //
7776 //=================================================================================================
7777
7778 //*************************************************************************************************
7779 /*! \cond BLAZE_INTERNAL */
7780 template< typename MT >
7781 struct SubmatrixTraitEval2< MT, inf, inf, inf, inf
7782 , EnableIf_t< IsDenseMatrix_v<MT> &&
7783 ( Size_v<MT,0UL> == DefaultSize_v ||
7784 Size_v<MT,1UL> == DefaultSize_v ) &&
7785 ( MaxSize_v<MT,0UL> == DefaultMaxSize_v ||
7786 MaxSize_v<MT,1UL> == DefaultMaxSize_v ) > >
7787 {
7788 using ET = RemoveConst_t< ElementType_t<MT> >;
7789
7790 using Type = DynamicMatrix< ET
7791 , StorageOrder_v<MT>
7792 , DynamicAllocator_t< ET, GetAllocator_t<MT> >
7793 , TagType_t<MT> >;
7794 };
7795 /*! \endcond */
7796 //*************************************************************************************************
7797
7798
7799
7800
7801 //=================================================================================================
7802 //
7803 // ROWSTRAIT SPECIALIZATIONS
7804 //
7805 //=================================================================================================
7806
7807 //*************************************************************************************************
7808 /*! \cond BLAZE_INTERNAL */
7809 template< typename MT, size_t M >
7810 struct RowsTraitEval2< MT, M
7811 , EnableIf_t< IsDenseMatrix_v<MT> &&
7812 ( M == 0UL || Size_v<MT,1UL> == DefaultSize_v ) &&
7813 ( M == 0UL || MaxSize_v<MT,1UL> == DefaultMaxSize_v ) > >
7814 {
7815 using ET = RemoveConst_t< ElementType_t<MT> >;
7816
7817 using Type = DynamicMatrix< ET
7818 , false
7819 , DynamicAllocator_t< ET, GetAllocator_t<MT> >
7820 , TagType_t<MT> >;
7821 };
7822 /*! \endcond */
7823 //*************************************************************************************************
7824
7825
7826
7827
7828 //=================================================================================================
7829 //
7830 // COLUMNSTRAIT SPECIALIZATIONS
7831 //
7832 //=================================================================================================
7833
7834 //*************************************************************************************************
7835 /*! \cond BLAZE_INTERNAL */
7836 template< typename MT, size_t N >
7837 struct ColumnsTraitEval2< MT, N
7838 , EnableIf_t< IsDenseMatrix_v<MT> &&
7839 ( N == 0UL || Size_v<MT,0UL> == DefaultSize_v ) &&
7840 ( N == 0UL || MaxSize_v<MT,0UL> == DefaultMaxSize_v ) > >
7841 {
7842 using ET = RemoveConst_t< ElementType_t<MT> >;
7843
7844 using Type = DynamicMatrix< ET
7845 , true
7846 , DynamicAllocator_t< ET, GetAllocator_t<MT> >
7847 , TagType_t<MT> >;
7848 };
7849 /*! \endcond */
7850 //*************************************************************************************************
7851
7852 } // namespace blaze
7853
7854 #endif
7855