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