Blaze 3.9
Matrix Operations

Table of Contents


Constructors


Matrices are just as easy and intuitive to create as vectors. Still, there are a few rules to be aware of:

  • In case the last template parameter (the storage order) is omitted, the matrix is per default stored in row-major order.
  • The elements of a StaticMatrix or HybridMatrix are default initialized (i.e. built-in data types are initialized to 0, class types are initialized via the default constructor).
  • Newly allocated elements of a DynamicMatrix or CompressedMatrix remain uninitialized if they are of built-in type and are default constructed if they are of class type.


Default Construction

// All matrices can be default constructed. Whereas the size of
// a StaticMatrix is fixed via the second and third template
// parameter, the initial size of a constructed DynamicMatrix
// or CompressedMatrix is 0.
StaticMatrix<int,2UL,2UL> M1; // Instantiation of a 2x2 integer row-major
// matrix. All elements are initialized to 0.
DynamicMatrix<float> M2; // Instantiation of a single precision dynamic
// row-major matrix with 0 rows and 0 columns.
DynamicMatrix<double,columnMajor> M3; // Instantiation of a double precision dynamic
// column-major matrix with 0 rows and 0 columns.
CompressedMatrix<int> M4; // Instantiation of a compressed integer
// row-major matrix of size 0x0.
CompressedMatrix<double,columnMajor> M5; // Instantiation of a compressed double precision
// column-major matrix of size 0x0.
Efficient implementation of a compressed matrix.
Definition: CompressedMatrix.h:239
Efficient implementation of a dynamic matrix.
Definition: DynamicMatrix.h:242
Efficient implementation of a fixed-sized matrix.
Definition: StaticMatrix.h:249


Construction with Specific Size

The DynamicMatrix, HybridMatrix, and CompressedMatrix classes offer a constructor that allows to immediately give the matrices a specific number of rows and columns:

DynamicMatrix<int> M6( 5UL, 4UL ); // Instantiation of a 5x4 dynamic row-major
// matrix. The elements are not initialized.
HybridMatrix<double,5UL,9UL> M7( 3UL, 7UL ); // Instantiation of a 3x7 hybrid row-major
// matrix. The elements are not initialized.
CompressedMatrix<float,columnMajor> M8( 8UL, 6UL ); // Instantiation of an empty 8x6 compressed
// column-major matrix.

Note that dense matrices (in this case DynamicMatrix and HybridMatrix) immediately allocate enough capacity for all matrix elements. Sparse matrices on the other hand (in this example CompressedMatrix) merely acquire the size, but don't necessarily allocate memory.


Initialization Constructors

All dense matrix classes offer a constructor for a direct, homogeneous initialization of all matrix elements. In contrast, for sparse matrices the predicted number of non-zero elements can be specified.

StaticMatrix<int,4UL,3UL,columnMajor> M9( 7 ); // Instantiation of a 4x3 integer column-major
// matrix. All elements are initialized to 7.
DynamicMatrix<float> M10( 2UL, 5UL, 2.0F ); // Instantiation of a 2x5 single precision row-major
// matrix. All elements are initialized to 2.0F.
CompressedMatrix<int> M11( 3UL, 4UL, 4 ); // Instantiation of a 3x4 integer row-major
// matrix with capacity for 4 non-zero elements.


Array Construction

Alternatively, all dense matrix classes offer a constructor for an initialization with a dynamic or static array, or with a std::array. If the matrix is initialized from a dynamic array, the constructor expects the dimensions of values provided by the array as first and second argument, the array as third argument. In case of a static array or std::array, the fixed size of the array is used:

const std::unique_ptr<double[]> array1( new double[6] );
// ... Initialization of the dynamic array
blaze::StaticMatrix<double,2UL,3UL> M12( 2UL, 3UL, array1.get() );
int array2[2][2] = { { 4, -5 }, { -6, 7 } };
const std::array<std::array<float,3UL>,2UL> array3{ { { 1, 2, 3 }, { 4, 5, 6 } } };


matrix_operations_initializer_list_construction

In addition, all dense and sparse matrix classes can be directly initialized by means of an initializer list:

{ -0.9F, -1.2F },
{ 4.8F, 0.6F } };
{ 1 },
{ 0, 2 } };

Dynamically sized matrices (such as e.g. HybridMatrix, DynamicMatrix or CompressedMatrix) are sized according to the size of the initializer list and all their elements are (copy) assigned the values of the list. For fixed size matrices (such as e.g. StaticMatrix) missing values are initialized as default and in case the size of the top-level initializer list does not match the number of rows of the matrix or the size of any nested list exceeds the number of columns, a std::invalid_argument exception is thrown. In case of sparse matrices, only the non-zero elements are used to initialize the matrix.


Copy Construction

All dense and sparse matrices can be created as a copy of another dense or sparse matrix.

StaticMatrix<int,5UL,4UL,rowMajor> M17( M6 ); // Instantiation of the dense row-major matrix M16
// as copy of the dense row-major matrix M6.
DynamicMatrix<float,columnMajor> M18( M8 ); // Instantiation of the dense column-major matrix M17
// as copy of the sparse column-major matrix M8.
CompressedMatrix<double,columnMajor> M19( M7 ); // Instantiation of the compressed column-major matrix
// M18 as copy of the dense row-major matrix M7.
CompressedMatrix<float,rowMajor> M20( M8 ); // Instantiation of the compressed row-major matrix
// M19 as copy of the compressed column-major matrix M8.

Note that it is not possible to create a StaticMatrix as a copy of a matrix with a different number of rows and/or columns:

StaticMatrix<int,4UL,5UL,rowMajor> M21( M6 ); // Runtime error: Number of rows and columns
// does not match!
StaticMatrix<int,4UL,4UL,columnMajor> M22( M9 ); // Compile time error: Number of columns does
// not match!


Assignment


There are several types of assignment to dense and sparse matrices: Homogeneous Assignment, Array Assignment, Copy Assignment, and Compound Assignment.


Homogeneous Assignment

It is possible to assign the same value to all elements of a dense matrix. All dense matrix classes provide an according assignment operator:

// Setting all integer elements of the StaticMatrix to 4
M1 = 4;
// Setting all double precision elements of the DynamicMatrix to 3.5
M2 = 3.5


Array Assignment

Dense matrices can also be assigned a static array:

int array1[2][2] = { { 1, 2 }, { 3, 4 } };
double array2[3][2] = { { 3.1, 6.4 }, { -0.9, -1.2 }, { 4.8, 0.6 } };
M1 = array1;
M2 = array1;
M3 = array2;

Note that the dimensions of the static array have to match the size of a StaticMatrix, whereas a DynamicMatrix is resized according to the array dimensions:

                      \f$ M3 = \left(\begin{array}{*{2}{c}}
                       3.1 &  6.4 \\
                      -0.9 & -1.2 \\
                       4.8 &  0.6 \\
                      \end{array}\right)\f$


Initializer List Assignment

Alternatively, it is possible to directly assign an initializer list to a dense or sparse matrix:

M1 = { { 3.1, 6.4 }, { -0.9, -1.2 }, { 4.8, 0.6 } };
M2 = { { 1, 0 }, {}, { 0, 1 }, { 2 } };

Dynamically sized matrices (such as e.g. HybridMatrix, DynamicMatrix or CompressedMatrix) are resized according to the size of the initializer list and all their elements are (copy) assigned the values of the list. For fixed size matrices (such as e.g. StaticMatrix) missing values are reset to their default value and in case the size of the top-level initializer list does not match the number of rows of the matrix or the size of any nested list exceeds the number of columns, a std::invalid_argument exception is thrown. In case of sparse matrices, only the non-zero elements are considered.


Copy Assignment

All kinds of matrices can be assigned to each other. The only restriction is that since a StaticMatrix cannot change its size, the assigned matrix must match both in the number of rows and in the number of columns.

// ... Initialization of the matrices
M1 = M2; // OK: Assignment of a 3x2 dense row-major matrix to another 3x2 dense row-major matrix
M1 = M4; // OK: Assignment of a 3x2 sparse row-major matrix to a 3x2 dense row-major matrix
M1 = M3; // Runtime error: Cannot assign a 5x2 matrix to a 3x2 static matrix
M1 = M5; // OK: Assignment of a 3x2 sparse column-major matrix to a 3x2 dense row-major matrix


Compound Assignment

Compound assignment is also available for matrices: addition assignment, subtraction assignment, and multiplication assignment. In contrast to plain assignment, however, the number of rows and columns of the two operands have to match according to the arithmetic operation.

// ... Initialization of the matrices
M1 += M2; // OK: Addition assignment between two row-major matrices of the same dimensions
M1 -= M3; // OK: Subtraction assignment between between a row-major and a column-major matrix
M1 += M4; // Runtime error: No compound assignment between matrices of different size
M1 -= M5; // Compilation error: No compound assignment between matrices of different size
M2 *= M6; // OK: Multiplication assignment between two row-major matrices

Note that the multiplication assignment potentially changes the number of columns of the target matrix:

                      \f$\left(\begin{array}{*{3}{c}}
                      2 & 0 & 1 \\
                      0 & 3 & 2 \\
                      \end{array}\right) \times
                      \left(\begin{array}{*{2}{c}}
                      4 & 0 \\
                      1 & 0 \\
                      0 & 3 \\
                      \end{array}\right) =
                      \left(\begin{array}{*{2}{c}}
                      8 & 3 \\
                      3 & 6 \\
                      \end{array}\right)\f$

Since a StaticMatrix cannot change its size, only a square StaticMatrix can be used in a multiplication assignment with other square matrices of the same dimensions.


Element Access


Function Call Operator

The easiest way to access a specific dense or sparse matrix element is via the function call operator. The indices to access a matrix are zero-based:

M1(0,0) = 1;
M1(0,1) = 3;
// ...
M2(0,2) = 4.1;
M2(1,1) = -6.3;

Since dense matrices allocate enough memory for all contained elements, using the function call operator on a dense matrix directly returns a reference to the accessed value. In case of a sparse matrix, if the accessed value is currently not contained in the matrix, the value is inserted into the matrix prior to returning a reference to the value, which can be much more expensive than the direct access to a dense matrix. Consider the following example:

for( size_t i=0UL; i<M1.rows(); ++i ) {
for( size_t j=0UL; j<M1.columns(); ++j ) {
... = M1(i,j);
}
}
static constexpr size_t columns() noexcept
Returns the current number of columns of the matrix.
Definition: StaticMatrix.h:1885
static constexpr size_t rows() noexcept
Returns the current number of rows of the matrix.
Definition: StaticMatrix.h:1866

Although the compressed matrix is only used for read access within the for loop, using the function call operator temporarily inserts 16 non-zero elements into the matrix. Therefore the preferred way to traverse the non-zero elements of a sparse matrix is to use iterators.


Iterators

An alternate way to traverse the elements contained in a dense or sparse matrix is by means of iterators. For that purpose, all matrices provide the begin(), cbegin(), end(), and cend() members functions. Note that it is not possible to traverse all elements of the matrix, but that it is only possible to traverse elements in a row-wise fashion (in case of a row-major matrix) or in a column-wise fashion (in case of a column-major matrix). In case of non-const matrices, begin() and end() return an Iterator, which allows a manipulation of the (non-zero) value. In case of a constant matrix or in case cbegin() or cend() are used a ConstIterator is returned. Iterators on dense matrices traverse all elements of the matrix, including the zero elements. Iterators on sparse matrices only traverse the non-zero elements.

The following two examples demonstrate how to traverse the elements of a dense and sparse matrix, respectively:

DynamicMatrix<int,rowMajor> M1( 4UL, 6UL );
DynamicMatrix<int,columnMajor> M2( 4UL, 6UL );
// Traversing all elements contained in the row-major matrix by Iterator
for( size_t i=0UL; i<M1.rows(); ++i ) {
for( DynamicMatrix<int,rowMajor>::Iterator it=M1.begin(i); it!=M1.end(i); ++it ) {
*it = ...; // OK: Write access to the value of the element.
... = *it; // OK: Read access to the value of the element.
}
}
// Traversing all elements contained in the column-major matrix by ConstIterator
for( size_t j=0UL; j<M2.columns(); ++j ) {
for( DynamicMatrix<int,columnMajor>::ConstIterator it=M2.cbegin(j); it!=M2.cend(j); ++it ) {
*it = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid.
... = *it; // OK: Read access to the value of the element.
}
}
size_t columns() const noexcept
Returns the current number of columns of the matrix.
Definition: DynamicMatrix.h:1798
ConstIterator cend(size_t i) const noexcept
Returns an iterator just past the last element of row/column i.
Definition: DynamicMatrix.h:1370
ConstIterator cbegin(size_t i) const noexcept
Returns an iterator to the first element of row/column i.
Definition: DynamicMatrix.h:1298
constexpr Iterator begin(size_t i) noexcept
Returns an iterator to the first element of row/column i.
Definition: StaticMatrix.h:1262
constexpr Iterator end(size_t i) noexcept
Returns an iterator just past the last element of row/column i.
Definition: StaticMatrix.h:1343
constexpr bool rowMajor
Storage order flag for row-major matrices.
Definition: StorageOrder.h:71
constexpr bool columnMajor
Storage order flag for column-major matrices.
Definition: StorageOrder.h:99
CompressedMatrix<int,rowMajor> M3( 4UL, 6UL );
CompressedMatrix<int,columnMajor> M4( 4UL, 6UL );
// Traversing the non-zero elements contained in the row-major matrix by Iterator
for( size_t i=0UL; i<M3.rows(); ++i ) {
for( CompressedMatrix<int,rowMajor>::Iterator it=M3.begin(i); it!=M3.end(i); ++it ) {
it->value() = ...; // OK: Write access to the value of the non-zero element.
... = it->value(); // OK: Read access to the value of the non-zero element.
it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed.
... = it->index(); // OK: Read access to the index of the non-zero element.
}
}
// Traversing the non-zero elements contained in the column-major matrix by ConstIterator
for( size_t j=0UL; j<M4.columns(); ++j ) {
for( CompressedMatrix<int,columnMajor>::ConstIterator it=M4.cbegin(j); it!=M4.cend(j); ++it ) {
it->value() = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid.
... = it->value(); // OK: Read access to the value of the non-zero element.
it->index() = ...; // Compilation error: The index of a non-zero element cannot be changed.
... = it->index(); // OK: Read access to the index of the non-zero element.
}
}
size_t rows() const noexcept
Returns the current number of rows of the matrix.
Definition: DynamicMatrix.h:1782
Iterator begin(size_t i) noexcept
Returns an iterator to the first element of row/column i.
Definition: DynamicMatrix.h:1250
Iterator end(size_t i) noexcept
Returns an iterator just past the last element of row/column i.
Definition: DynamicMatrix.h:1322

Note that begin(), cbegin(), end(), and cend() are also available as free functions:

for( size_t i=0UL; i<M3.rows(); ++i ) {
for( CompressedMatrix<int,rowMajor>::Iterator it=begin( M3, i ); it!=end( M3, i ); ++it ) {
// ...
}
}
for( size_t j=0UL; j<M4.columns(); ++j ) {
for( CompressedMatrix<int,columnMajor>::ConstIterator it=cbegin( M4, j ); it!=cend( M4, j ); ++it ) {
// ...
}
}
MT::ConstIterator cend(const Matrix< MT, SO > &matrix, size_t i)
Returns an iterator just past the last element of row/column i.
Definition: Matrix.h:628
MT::ConstIterator cbegin(const Matrix< MT, SO > &matrix, size_t i)
Returns an iterator to the first element of row/column i.
Definition: Matrix.h:562
MT::Iterator end(Matrix< MT, SO > &matrix, size_t i)
Returns an iterator just past the last element of row/column i.
Definition: Matrix.h:584
MT::Iterator begin(Matrix< MT, SO > &matrix, size_t i)
Returns an iterator to the first element of row/column i.
Definition: Matrix.h:518


.data() / data()

Sometimes it is necessary to acquire a pointer to the first element of the underlying array of a dense matrix. For that purpose the data() member function or the free data() function can be used:

// Instantiating a dynamic vector with 10 elements
A.data(); // Returns a pointer to the first element of the dynamic matrix
data( A ); // Same effect as the member function
MT::ElementType * data(DenseMatrix< MT, SO > &dm) noexcept
Low-level data access to the dense matrix elements.
Definition: DenseMatrix.h:182

Note that you can NOT assume that all matrix elements lie adjacent to each other! The dense matrix may use techniques such as padding to improve the alignment of the data. Whereas the number of elements within a row/column are given by the rows() and columns() functions, respectively, the total number of elements including padding is given by the spacing() function.


Element Insertion


Whereas a dense matrix always provides enough capacity to store all matrix elements, a sparse matrix only stores the non-zero elements. Therefore it is necessary to explicitly add elements to the matrix.


Function Call Operator

The first possibility to add elements to a sparse matrix is the function call operator:

CompressedMatrix<int> M1( 3UL, 4UL );
M1(1,2) = 9;

In case the element at the given position is not yet contained in the sparse matrix, it is automatically inserted. Otherwise the old value is replaced by the new value 2. The operator returns a reference to the sparse vector element.


.set()

An alternative to the function call operator is the set() function: In case the element is not yet contained in the matrix the element is inserted, else the element's value is modified:

// Insert or modify the value at position (2,0)
M1.set( 2, 0, 1 );


.insert()

The insertion of elements can be better controlled via the insert() function. In contrast to the function call operator and the set() function it emits an exception in case the element is already contained in the matrix. In order to check for this case, the find() function can be used:

// In case the element at position (2,3) is not yet contained in the matrix it is inserted
// with a value of 4.
if( M1.find( 2, 3 ) == M1.end( 2 ) )
M1.insert( 2, 3, 4 );


.append()

Although the insert() function is very flexible, due to performance reasons it is not suited for the setup of large sparse matrices. A very efficient, yet also very low-level way to fill a sparse matrix is the append() function. It requires the sparse matrix to provide enough capacity to insert a new element in the specified row/column. Additionally, the index of the new element must be larger than the index of the previous element in the same row/column. Violating these conditions results in undefined behavior!

M1.reserve( 0, 3 ); // Reserving space for three non-zero elements in row 0
M1.append( 0, 1, 2 ); // Appending the element 2 in row 0 at column index 1
M1.append( 0, 2, -4 ); // Appending the element -4 in row 0 at column index 2
// ...

The most efficient way to fill a sparse matrix with elements, however, is a combination of reserve(), append(), and the finalize() function:

// Setup of the compressed row-major matrix
//
// ( 0 1 0 2 0 )
// A = ( 0 0 0 0 0 )
// ( 3 0 0 0 0 )
//
M1.reserve( 3 ); // Reserving enough space for 3 non-zero elements
M1.append( 0, 1, 1 ); // Appending the value 1 in row 0 with column index 1
M1.append( 0, 3, 2 ); // Appending the value 2 in row 0 with column index 3
M1.finalize( 0 ); // Finalizing row 0
M1.finalize( 1 ); // Finalizing the empty row 1 to prepare row 2
M1.append( 2, 0, 3 ); // Appending the value 3 in row 2 with column index 0
M1.finalize( 2 ); // Finalizing row 2
Note
The finalize() function has to be explicitly called for each row or column, even for empty ones!
Although append() does not allocate new memory, it still invalidates all iterators returned by the end() functions!


Element Removal


.erase()

The erase() member functions can be used to remove elements from a sparse matrix. The following example gives an impression of the five different flavors of erase():

CompressedMatrix<int,rowMajor> A( 42, 53 );
// ... Initialization of the matrix
// Erasing the element at position (21,23)
A.erase( 21, 23 );
// Erasing a single element in row 17 via iterator
A.erase( 17, A.find( 4 ) );
// Erasing all non-zero elements in the range [7..24] of row 33
A.erase( 33, A.lowerBound( 33, 7 ), A.upperBound( 33, 24 ) );
// Erasing all non-zero elements with a value larger than 9 by passing a unary predicate
A.erase( []( int i ){ return i > 9; } );
// Erasing all non-zero elements in the range [30..40] of row 37 with a value larger than 5
CompressedMatrix<int,rowMajor>::Iterator pos1( A.lowerBound( 37, 30 ) );
CompressedMatrix<int,rowMajor>::Iterator pos2( A.upperBound( 37, 40 ) );
A.erase( 37, pos1, pos2, []( int i ){ return i > 5; } );


Element Lookup


A sparse matrix only stores the non-zero elements contained in the matrix. Therefore, whenever accessing a matrix element at a specific position a lookup operation is required. Whereas the function call operator is performing this lookup automatically, it is also possible to use the find(), lowerBound(), and upperBound() member functions for a manual lookup.


.find() / find()

The find() function can be used to check whether a specific element is contained in the sparse matrix. It specifically searches for the element at the specified position. In case the element is found, the function returns an iterator to the element. Otherwise an iterator just past the last non-zero element of the according row or column (the end() iterator) is returned. Note that the returned iterator is subject to invalidation due to inserting operations via the function call operator, the set() function or the insert() function!

CompressedMatrix<int,rowMajor> A( 42, 53 );
// ... Initialization of the matrix
// Searching the element at position (7,17). In case the element is not
// contained in the vector, the end() iterator of row 7 is returned.
CompressedMatrix<int,rowMajor>::Iterator pos( A.find( 7, 17 ) );
if( pos != A.end( 7 ) ) {
// ...
}

Alternatively, the free function find() can be used to find a specific element in a sparse matrix:

find( A, 7, 17 ); // Searching the element at position (7,17); same effect as the member function
MT::Iterator find(SparseMatrix< MT, SO > &sm, size_t i, size_t j)
Searches for a specific matrix element.
Definition: SparseMatrix.h:144


.lowerBound() / lowerBound()

In case of a row-major matrix, this function returns a row iterator to the first element with an index not less then the given column index. In case of a column-major matrix, the function returns a column iterator to the first element with an index not less then the given row index. In combination with the upperBound() function this function can be used to create a pair of iterators specifying a range of indices. Note that the returned iterator is subject to invalidation due to inserting operations via the function call operator, the set() function or the insert() function!

CompressedMatrix<int,rowMajor> A( 42, 53 );
// ... Initialization of the matrix
// Searching the lower bound of column index 17 in row 7.
CompressedMatrix<int,rowMajor>::Iterator pos1( A.lowerBound( 7, 17 ) );
// Searching the upper bound of column index 28 in row 7
CompressedMatrix<int,rowMajor>::Iterator pos2( A.upperBound( 7, 28 ) );
// Erasing all elements in the specified range
A.erase( 7, pos1, pos2 );

Alternatively, the free function lowerBound() can be used to:

lowerBound( A, 7, 17 ); // Searching the lower bound of (7,17); same effect as the member function
MT::Iterator lowerBound(SparseMatrix< MT, SO > &sm, size_t i, size_t j)
Returns an iterator to the first index not less than the given index.
Definition: SparseMatrix.h:194


.upperBound() / upperBound()

In case of a row-major matrix, this function returns a row iterator to the first element with an index greater then the given column index. In case of a column-major matrix, the function returns a column iterator to the first element with an index greater then the given row index. In combination with the lowerBound() function this function can be used to create a pair of iterators specifying a range of indices. Note that the returned iterator is subject to invalidation due to inserting operations via the function call operator, the set() function or the insert() function!

CompressedMatrix<int,columnMajor> A( 42, 53 );
// ... Initialization of the matrix
// Searching the lower bound of row index 17 in column 9.
CompressedMatrix<int,columnMajor>::Iterator pos1( A.lowerBound( 17, 9 ) );
// Searching the upper bound of row index 28 in column 9
CompressedMatrix<int,columnMajor>::Iterator pos2( A.upperBound( 28, 9 ) );
// Erasing all elements in the specified range
A.erase( 9, pos1, pos2 );

Alternatively, the free function upperBound() can be used to:

upperBound( A, 28, 9 ); // Searching the upper bound of (28,9); same effect as the member function
MT::Iterator upperBound(SparseMatrix< MT, SO > &sm, size_t i, size_t j)
Returns an iterator to the first index greater than the given index.
Definition: SparseMatrix.h:244


Non-Modifying Operations


.rows() / rows()

The current number of rows of a matrix can be acquired via the rows() member function:

// Instantiating a dynamic matrix with 10 rows and 8 columns
blaze::DynamicMatrix<int> M1( 10UL, 8UL );
M1.rows(); // Returns 10
// Instantiating a compressed matrix with 8 rows and 12 columns
M2.rows(); // Returns 8

Alternatively, the free functions rows() can be used to query the current number of rows of a matrix. In contrast to the member function, the free function can also be used to query the number of rows of a matrix expression:

rows( M1 ); // Returns 10, i.e. has the same effect as the member function
rows( M2 ); // Returns 8, i.e. has the same effect as the member function
rows( M1 * M2 ); // Returns 10, i.e. the number of rows of the resulting matrix
constexpr size_t rows(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of rows of the matrix.
Definition: Matrix.h:644


.columns() / columns()

The current number of columns of a matrix can be acquired via the columns() member function:

// Instantiating a dynamic matrix with 6 rows and 8 columns
M1.columns(); // Returns 8
// Instantiating a compressed matrix with 8 rows and 7 columns
M2.columns(); // Returns 7

There is also a free function columns() available, which can also be used to query the number of columns of a matrix expression:

columns( M1 ); // Returns 8, i.e. has the same effect as the member function
columns( M2 ); // Returns 7, i.e. has the same effect as the member function
columns( M1 * M2 ); // Returns 7, i.e. the number of columns of the resulting matrix
constexpr size_t columns(const Matrix< MT, SO > &matrix) noexcept
Returns the current number of columns of the matrix.
Definition: Matrix.h:660

size()

The size() function returns the total number of elements of a matrix:

// Instantiating a dynamic matrix with 6 rows and 8 columns
size( M1 ); // Returns 48
// Instantiating a compressed matrix with 8 rows and 7 columns
size( M2 ); // Returns 56
constexpr size_t size(const Matrix< MT, SO > &matrix) noexcept
Returns the total number of elements of the matrix.
Definition: Matrix.h:676

.spacing() / spacing()

The total number of elements of a row or column of a dense matrix, including potential padding elements, can be acquired via the spacing member function. In case of a row-major matrix (i.e. in case the storage order is set to blaze::rowMajor) the function returns the spacing between two rows, in case of a column-major matrix (i.e. in case the storage flag is set to blaze::columnMajor) the function returns the spacing between two columns:

// Instantiating a row-major dynamic matrix with 7 rows and 8 columns
M1.spacing(); // Returns the total number of elements in a row
// Instantiating a column-major dynamic matrix with 8 rows and 12 columns
M2.spacing(); // Returns the total number of element in a column
size_t spacing() const noexcept
Returns the spacing between the beginning of two rows/columns.
Definition: DynamicMatrix.h:1819
static constexpr size_t spacing() noexcept
Returns the spacing between the beginning of two rows.
Definition: StaticMatrix.h:1907

Alternatively, the free functions spacing() can be used to query the current number of elements in a row/column.

spacing( M1 ); // Returns the total number of elements in a row
spacing( M2 ); // Returns the total number of elements in a column
size_t spacing(const DenseMatrix< MT, SO > &dm) noexcept
Returns the spacing between the beginning of two rows/columns.
Definition: DenseMatrix.h:265


.capacity() / capacity()

The capacity() member function returns the internal capacity of a dense or sparse matrix. Note that the capacity of a matrix doesn't have to be equal to the size of a matrix. In case of a dense matrix the capacity will always be greater or equal than the total number of elements of the matrix. In case of a sparse matrix, the capacity will usually be much less than the total number of elements.

M1.capacity(); // Returns at least 35
M2.capacity(); // Returns at least 28
static constexpr size_t capacity() noexcept
Returns the maximum capacity of the matrix.
Definition: StaticMatrix.h:1926

There is also a free function capacity() available to query the capacity. However, please note that this function cannot be used to query the capacity of a matrix expression:

capacity( M1 ); // Returns at least 35, i.e. has the same effect as the member function
capacity( M2 ); // Returns at least 28, i.e. has the same effect as the member function
capacity( M1 * M2 ); // Compilation error!
size_t capacity(const Matrix< MT, SO > &matrix) noexcept
Returns the maximum capacity of the matrix.
Definition: Matrix.h:692


.nonZeros() / nonZeros()

For both dense and sparse matrices the current number of non-zero elements can be queried via the nonZeros() member function. In case of matrices there are two flavors of the nonZeros() function: One returns the total number of non-zero elements in the matrix, the second returns the number of non-zero elements in a specific row (in case of a row-major matrix) or column (in case of a column-major matrix). Sparse matrices directly return their number of non-zero elements, dense matrices traverse their elements and count the number of non-zero elements.

// ... Initializing the dense matrix
M1.nonZeros(); // Returns the total number of non-zero elements in the dense matrix
M1.nonZeros( 2 ); // Returns the number of non-zero elements in row 2
size_t nonZeros() const
Returns the total number of non-zero elements in the matrix.
Definition: StaticMatrix.h:1978
// ... Initializing the sparse matrix
M2.nonZeros(); // Returns the total number of non-zero elements in the sparse matrix
M2.nonZeros( 3 ); // Returns the number of non-zero elements in column 3

The free nonZeros() function can also be used to query the number of non-zero elements in a matrix expression. However, the result is not the exact number of non-zero elements, but may be a rough estimation:

nonZeros( M1 ); // Has the same effect as the member function
nonZeros( M1, 2 ); // Has the same effect as the member function
nonZeros( M2 ); // Has the same effect as the member function
nonZeros( M2, 3 ); // Has the same effect as the member function
nonZeros( M1 * M2 ); // Estimates the number of non-zero elements in the matrix expression
size_t nonZeros(const Matrix< MT, SO > &matrix)
Returns the total number of non-zero elements in the matrix.
Definition: Matrix.h:730


isEmpty()

The isEmpty() function returns whether the total number of elements of the matrix is zero:

blaze::DynamicMatrix<int> A; // Create an empty matrix
isEmpty( A ); // Returns true
A.resize( 5, 0 ); // Resize to a 5x0 matrix
isEmpty( A ); // Returns true
A.resize( 5, 3 ); // Resize to a 5x3 matrix
isEmpty( A ); // Returns false
void resize(size_t m, size_t n, bool preserve=true)
Changing the size of the matrix.
Definition: DynamicMatrix.h:2028
constexpr bool isEmpty(const Matrix< MT, SO > &matrix) noexcept
Checks if the given matrix is empty.
Definition: Matrix.h:1364


isnan()

The isnan() function provides the means to check a dense or sparse matrix for non-a-number elements:

// ... Initialization
if( isnan( A ) ) { ... }
bool isnan(const DenseMatrix< MT, SO > &dm)
Checks the given dense matrix for not-a-number elements.
Definition: DenseMatrix.h:1290
// ... Initialization
if( isnan( A ) ) { ... }

If at least one element of the matrix is not-a-number, the function returns true, otherwise it returns false.


isinf()

The isinf() function checks the given dense or sparse matrix for infinite (inf) elements:

// ... Initialization
if( isinf( A ) ) { ... }
bool isinf(const DenseMatrix< MT, SO > &dm)
Checks the given dense matrix for infinite elements.
Definition: DenseMatrix.h:1339
// ... Initialization
if( isinf( A ) ) { ... }

If at least one element of the matrix is infinite, the function returns true, otherwise it returns false.


isfinite()

The isfinite() function checks if all elements of the given dense or sparse matrix are finite elements (i.e. normal, subnormal or zero elements, but not infinite or NaN):

// ... Initialization
if( isfinite( A ) ) { ... }
bool isfinite(const DenseMatrix< MT, SO > &dm)
Checks the given dense matrix for finite elements.
Definition: DenseMatrix.h:1389
// ... Initialization
if( isfinite( A ) ) { ... }

If all elements of the matrix are finite, the function returns true, otherwise it returns false.


isDefault()

The isDefault() function returns whether the given dense or sparse matrix is in default state:

// ... Resizing and initialization
if( isDefault( A ) ) { ... }
Efficient implementation of a dynamically sized matrix with static memory.
Definition: HybridMatrix.h:256
bool isDefault(const DiagonalMatrix< MT, SO, DF > &m)
Returns whether the given diagonal matrix is in default state.
Definition: DiagonalMatrix.h:169

A matrix is in default state if it appears to just have been default constructed. All resizable matrices (HybridMatrix, DynamicMatrix, or CompressedMatrix) and CustomMatrix are in default state if its size is equal to zero. A non-resizable matrix (StaticMatrix and all submatrices) is in default state if all its elements are in default state. For instance, in case the matrix is instantiated for a built-in integral or floating point data type, the function returns true in case all matrix elements are 0 and false in case any matrix element is not 0.


isSquare()

Whether a dense or sparse matrix is a square matrix (i.e. if the number of rows is equal to the number of columns) can be checked via the isSquare() function:

// ... Resizing and initialization
if( isSquare( A ) ) { ... }
bool isSquare(const Matrix< MT, SO > &matrix) noexcept
Checks if the given matrix is a square matrix.
Definition: Matrix.h:1383


isSymmetric()

Via the isSymmetric() function it is possible to check whether a dense or sparse matrix is symmetric:

// ... Resizing and initialization
if( isSymmetric( A ) ) { ... }
bool isSymmetric(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is symmetric.
Definition: DenseMatrix.h:1456

Note that non-square matrices are never considered to be symmetric!


isUniform()

In order to check if all matrix elements are identical, the isUniform() function can be used:

// ... Resizing and initialization
if( isUniform( A ) ) { ... }
bool isUniform(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is a uniform matrix.
Definition: DenseMatrix.h:1766

Note that in case of a sparse matrix also the zero elements are also taken into account!


isZero()

In order to check if all matrix elements are zero, the isZero() function can be used:

// ... Resizing and initialization
if( isZero( A ) ) { ... }
bool isZero(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is a zero matrix.
Definition: DenseMatrix.h:1819


isLower()

Via the isLower() function it is possible to check whether a dense or sparse matrix is lower triangular:

// ... Resizing and initialization
if( isLower( A ) ) { ... }
bool isLower(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is a lower triangular matrix.
Definition: DenseMatrix.h:1921

Note that non-square matrices are never considered to be lower triangular!


isUniLower()

Via the isUniLower() function it is possible to check whether a dense or sparse matrix is lower unitriangular:

// ... Resizing and initialization
if( isUniLower( A ) ) { ... }
bool isUniLower(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is a lower unitriangular matrix.
Definition: DenseMatrix.h:2009

Note that non-square matrices are never considered to be lower unitriangular!


isStrictlyLower()

Via the isStrictlyLower() function it is possible to check whether a dense or sparse matrix is strictly lower triangular:

// ... Resizing and initialization
if( isStrictlyLower( A ) ) { ... }
bool isStrictlyLower(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is a strictly lower triangular matrix.
Definition: DenseMatrix.h:2096

Note that non-square matrices are never considered to be strictly lower triangular!


isUpper()

Via the isUpper() function it is possible to check whether a dense or sparse matrix is upper triangular:

// ... Resizing and initialization
if( isUpper( A ) ) { ... }
bool isUpper(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is an upper triangular matrix.
Definition: DenseMatrix.h:2188

Note that non-square matrices are never considered to be upper triangular!


isUniUpper()

Via the isUniUpper() function it is possible to check whether a dense or sparse matrix is upper unitriangular:

// ... Resizing and initialization
if( isUniUpper( A ) ) { ... }
bool isUniUpper(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is an upper unitriangular matrix.
Definition: DenseMatrix.h:2276

Note that non-square matrices are never considered to be upper unitriangular!


isStrictlyUpper()

Via the isStrictlyUpper() function it is possible to check whether a dense or sparse matrix is strictly upper triangular:

// ... Resizing and initialization
if( isStrictlyUpper( A ) ) { ... }
bool isStrictlyUpper(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is a strictly upper triangular matrix.
Definition: DenseMatrix.h:2363

Note that non-square matrices are never considered to be strictly upper triangular!


isDiagonal()

The isDiagonal() function checks if the given dense or sparse matrix is a diagonal matrix, i.e. if it has only elements on its diagonal and if the non-diagonal elements are default elements:

// ... Resizing and initialization
if( isDiagonal( A ) ) { ... }
bool isDiagonal(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is diagonal.
Definition: DenseMatrix.h:2456

Note that non-square matrices are never considered to be diagonal!


isIdentity()

The isIdentity() function checks if the given dense or sparse matrix is an identity matrix, i.e. if all diagonal elements are 1 and all non-diagonal elements are 0:

// ... Resizing and initialization
if( isIdentity( A ) ) { ... }
bool isIdentity(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is an identity matrix.
Definition: DenseMatrix.h:2561

Note that non-square matrices are never considered to be identity matrices!


isPositiveDefinite()

The isPositiveDefinite() function checks if the given dense matrix is positive definite.

// ... Initialization
if( isPositiveDefinite( A ) ) { ... }
bool isPositiveDefinite(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is a positive definite matrix.
Definition: DenseMatrix.h:2657

Note that non-square matrices are never considered to be positive definite!

Note
The isPositiveDefinite() function can only be used for dense matrices with float, double, complex<float> or complex<double> element type. The attempt to call the function with matrices of any other element type or with a sparse matrix results in a compile time error!
The function is depending on LAPACK kernels. Thus the function can only be used if a fitting LAPACK library is available and linked to the executable. Otherwise a linker error will be created.


trans()

Matrices can be transposed via the trans() function. Row-major matrices are transposed into a column-major matrix and vice versa:

M1 = M2; // Assigning a column-major matrix to a row-major matrix
M1 = trans( M2 ); // Assigning the transpose of M2 (i.e. a row-major matrix) to M1
M1 += trans( M2 ); // Addition assignment of two row-major matrices
decltype(auto) trans(const DenseMatrix< MT, SO > &dm)
Calculation of the transpose of the given dense matrix.
Definition: DMatTransExpr.h:766


ctrans()

The conjugate transpose of a dense or sparse matrix (also called adjoint matrix, Hermitian conjugate, or transjugate) can be computed via the ctrans() function:

M1 = ctrans( M2 ); // Compute the conjugate transpose matrix
decltype(auto) ctrans(const DenseMatrix< MT, SO > &dm)
Returns the conjugate transpose matrix of dm.
Definition: DMatMapExpr.h:1501

Note that the ctrans() function has the same effect as manually applying the conj() and trans() function in any order:

M1 = trans( conj( M2 ) ); // Computing the conjugate transpose matrix
M1 = conj( trans( M2 ) ); // Computing the conjugate transpose matrix
decltype(auto) conj(const DenseMatrix< MT, SO > &dm)
Returns a matrix containing the complex conjugate of each single element of dm.
Definition: DMatMapExpr.h:1464


reverse()

Via the reverse() function is is possible to reverse the rows or columns of a dense or sparse matrix. The following examples gives an impression of both alternatives:

{ 2, 4, 0, 1 },
{ 0, 3, 1, 0 } };
// Reversing the rows result in the matrix
//
// ( 0 3 1 0 )
// ( 2 4 0 1 )
// ( 1 0 2 3 )
//
B = reverse<rowwise>( A );
// Reversing the columns result in the matrix
//
// ( 3 2 0 1 )
// ( 1 0 4 2 )
// ( 0 1 3 0 )
//
B = reverse<columnwise>( A );


eval() / evaluate()

The evaluate() function forces an evaluation of the given matrix expression and enables an automatic deduction of the correct result type of an operation. The following code example demonstrates its intended use for the multiplication of a lower and a strictly lower dense matrix:

LowerMatrix< DynamicMatrix<double> > A;
StrictlyLowerMatrix< DynamicMatrix<double> > B;
// ... Resizing and initialization
auto C = evaluate( A * B );
Matrix adapter for lower triangular matrices.
Definition: BaseTemplate.h:558
Matrix adapter for strictly lower triangular matrices.
Definition: BaseTemplate.h:563
MT::ResultType evaluate(const Matrix< MT, SO > &matrix)
Evaluates the given matrix expression.
Definition: Matrix.h:1282

In this scenario, the evaluate() function assists in deducing the exact result type of the operation via the auto keyword. Please note that if evaluate() is used in this way, no temporary matrix is created and no copy operation is performed. Instead, the result is directly written to the target matrix due to the return value optimization (RVO). However, if evaluate() is used in combination with an explicit target type, a temporary will be created and a copy operation will be performed if the used type differs from the type returned from the function:

StrictlyLowerMatrix< DynamicMatrix<double> > D( A * B ); // No temporary & no copy operation
LowerMatrix< DynamicMatrix<double> > E( A * B ); // Temporary & copy operation
DynamicMatrix<double> F( A * B ); // Temporary & copy operation
D = evaluate( A * B ); // Temporary & copy operation

Sometimes it might be desirable to explicitly evaluate a sub-expression within a larger expression. However, please note that evaluate() is not intended to be used for this purpose. This task is more elegantly and efficiently handled by the eval() function:

D = A + evaluate( B * C ); // Unnecessary creation of a temporary matrix
D = A + eval( B * C ); // No creation of a temporary matrix
decltype(auto) eval(const DenseMatrix< MT, SO > &dm)
Forces the evaluation of the given dense matrix expression dm.
Definition: DMatEvalExpr.h:790

In contrast to the evaluate() function, eval() can take the complete expression into account and therefore can guarantee the most efficient way to evaluate it (see also Intra-Statement Optimization).


noalias()

The Blaze library is able to reliably detect aliasing during the assignment of matrices. In case the aliasing would lead to an incorrect result, Blaze introduces an intermediate temporary of the appropriate type to break the aliasing. For instance, in the following example Blaze performs an alias detection in both assignments, but only, in the second assignment it detects a problematic aliasing and uses an intermediate temporary in order to be able to compute the correct result:

A = A + B; // No problematic aliasing of A, no intermediate temporary is required.
A = A * B; // Problematic aliasing of A; intermediate temporary required!

The detection of aliasing effects, however, takes a small runtime effort. In order to disable the aliasing detection, the noalias() function can be used:

A = noalias( A + B ); // No alias detection performed, no intermediate temporary.
A = noalias( A * B ); // No alias detection performed, no intermediate temporary.
// Note that the final result will be incorrect!
decltype(auto) noalias(const DenseMatrix< MT, SO > &dm)
Forces the non-aliased evaluation of the given dense matrix expression dm.
Definition: DMatNoAliasExpr.h:679
Warning
The noalias() operation has the semantics of a cast: The caller is completely responsible and the system trusts the given information. Using noalias() in a situation where an aliasing effect occurs leads to undefined behavior (which can be violated invariants or wrong computation results)!


nosimd()

By default, Blaze attempts to vectorize all operations by means of SSE, AVX, etc. in order to achieve maximum performance. However, via the nosimd() operation it is possible to disable the SIMD evaluation of any operation:

A = nosimd( A + B ); // Disables SIMD for the matrix/matrix addition
A = nosimd( A * B ); // Disables SIMD for the matrix/matrix multiplication
decltype(auto) nosimd(const DenseMatrix< MT, SO > &dm)
Disables the SIMD evaluation of the given dense matrix expression dm.
Definition: DMatNoSIMDExpr.h:717

Please note that the main purpose of the nosimd() operation is to enable an easy performance comparison between the vectorized and non-vectorized evaluation. Using the nosimd() operation will likely result in significantly reduced performance!


fix()

By default, resizable matrices such as DynamicMatrix, HybridMatrix, and CompressedMatrix can adapt their numbers of rows and columns during an assignment:

blaze::DynamicMatrix<int> A{ { 1, 2 } }; // Setup of a 1x2 matrix
blaze::DynamicVector<int> B{ { 1, 2, 3 }, { 4, 5, 6, } }; // Setup of a 2x3 matrix
A = B; // Resizes matrix 'A' to a 2x3 matrix
Efficient implementation of an arbitrary sized vector.
Definition: DynamicVector.h:223

Via the fix() operation it is possible to fix the size of a resizable matrix. If a matrix with a different number of rows or a different number of columns is assigned, instead of resizing the matrix the operation fails by throwing a std::invalid_argument exception:

blaze::DynamicMatrix<int> A{ { 1, 2 } }; // Setup of a 1x2 matrix
blaze::DynamicVector<int> B{ { 1, 2, 3 }, { 4, 5, 6, } }; // Setup of a 2x3 matrix
fix( A ) = B; // Throws an exception: Matrix cannot be resized!
decltype(auto) fix(DenseMatrix< MT, SO > &dm) noexcept
Fixing the size of the given dense matrix.
Definition: DMatFixExpr.h:227


Modifying Operations


.resize() / .reserve()

The dimensions of a StaticMatrix are fixed at compile time by the second and third template parameter and a CustomMatrix cannot be resized. In contrast, the number or rows and columns of DynamicMatrix, HybridMatrix, and CompressedMatrix can be changed at runtime:

DynamicMatrix<int,rowMajor> M1;
CompressedMatrix<int,columnMajor> M2( 3UL, 2UL );
// Adapting the number of rows and columns via the resize() function. The (optional)
// third parameter specifies whether the existing elements should be preserved. Per
// default, the existing elements are preserved.
M1.resize( 2UL, 2UL ); // Resizing matrix M1 to 2x2 elements. Elements of built-in type
// remain uninitialized, elements of class type are default
// constructed.
M1.resize( 3UL, 1UL, false ); // Resizing M1 to 3x1 elements. The old elements are lost, the
// new elements are NOT initialized!
M2.resize( 5UL, 7UL, true ); // Resizing M2 to 5x7 elements. The old elements are preserved.
M2.resize( 3UL, 2UL, false ); // Resizing M2 to 3x2 elements. The old elements are lost.

Note that resizing a matrix invalidates all existing views (see e.g. Submatrices) on the matrix:

blaze::DynamicMatrix<int,rowMajor> M1( 10UL, 20UL ); // Creating a 10x20 matrix
auto row8 = row( M1, 8UL ); // Creating a view on the 8th row of the matrix
M1.resize( 6UL, 20UL ); // Resizing the matrix invalidates the view
decltype(auto) row(Matrix< MT, SO > &, RRAs...)
Creating a view on a specific row of the given matrix.
Definition: Row.h:137

When the internal capacity of a matrix is no longer sufficient, the allocation of a larger junk of memory is triggered. In order to avoid frequent reallocations, the reserve() function can be used up front to set the internal capacity:

M1.reserve( 100 );
M1.rows(); // Returns 0
M1.capacity(); // Returns at least 100
void reserve(size_t elements)
Setting the minimum capacity of the matrix.
Definition: DynamicMatrix.h:2116
size_t capacity() const noexcept
Returns the maximum capacity of the matrix.
Definition: DynamicMatrix.h:1835

Additionally it is possible to reserve memory in a specific row (for a row-major matrix) or column (for a column-major matrix):

M1.reserve( 1, 4 ); // Reserving enough space for four non-zero elements in row 1


.shrinkToFit()

The internal capacity of matrices with dynamic memory is preserved in order to minimize the number of reallocations. For that reason, the resize() and reserve() functions can lead to memory overhead. The shrinkToFit() member function can be used to minimize the internal capacity:

blaze::DynamicMatrix<int> M1( 100UL, 100UL ); // Create a 100x100 integer matrix
M1.resize( 10UL, 10UL ); // Resize to 10x10, but the capacity is preserved
M1.shrinkToFit(); // Remove the unused capacity
void shrinkToFit()
Requesting the removal of unused capacity.
Definition: DynamicMatrix.h:2148

Please note that due to padding the capacity might not be reduced exactly to rows() times columns(). Please also note that in case a reallocation occurs, all iterators (including end() iterators), all pointers and references to elements of this matrix are invalidated.

reset() / clear

In order to reset all elements of a dense or sparse matrix, the reset() function can be used. The number of rows and columns of the matrix are preserved:

// Setting up a single precision row-major matrix, whose elements are initialized with 2.0F.
blaze::DynamicMatrix<float> M1( 4UL, 5UL, 2.0F );
// Resetting all elements to 0.0F.
reset( M1 ); // Resetting all elements
M1.rows(); // Returns 4: size and capacity remain unchanged
constexpr void reset(Matrix< MT, SO > &matrix)
Resetting the given matrix.
Definition: Matrix.h:806

Alternatively, only a single row or column of the matrix can be resetted:

blaze::DynamicMatrix<int,blaze::rowMajor> M1( 7UL, 6UL, 5 ); // Setup of a row-major matrix
blaze::DynamicMatrix<int,blaze::columnMajor> M2( 4UL, 5UL, 4 ); // Setup of a column-major matrix
reset( M1, 2UL ); // Resetting the 2nd row of the row-major matrix
reset( M2, 3UL ); // Resetting the 3rd column of the column-major matrix

In order to reset a row of a column-major matrix or a column of a row-major matrix, use a row or column view (see Rows and views_colums).

In order to return a matrix to its default state (i.e. the state of a default constructed matrix), the clear() function can be used:

// Setting up a single precision row-major matrix, whose elements are initialized with 2.0F.
blaze::DynamicMatrix<float> M1( 4UL, 5UL, 2.0F );
// Resetting all elements to 0.0F.
clear( M1 ); // Resetting the entire matrix
M1.rows(); // Returns 0: size is reset, but capacity remains unchanged
constexpr void clear(Matrix< MT, SO > &matrix)
Clearing the given matrix.
Definition: Matrix.h:960


transpose()

In addition to the non-modifying trans() function, matrices can be transposed in-place via the transpose() function:

transpose( M ); // In-place transpose operation.
M = trans( M ); // Same as above
void transpose(Matrix< MT, SO > &matrix)
In-place transpose of the given matrix.
Definition: Matrix.h:1195

Note however that the transpose operation fails if ...

  • ... the given matrix has a fixed size and is non-square;
  • ... the given matrix is a triangular matrix;
  • ... the given submatrix affects the restricted parts of a triangular matrix;
  • ... the given submatrix would cause non-deterministic results in a symmetric/Hermitian matrix.


ctranspose()

The ctranspose() function can be used to perform an in-place conjugate transpose operation:

ctranspose( M ); // In-place conjugate transpose operation.
M = ctrans( M ); // Same as above
void ctranspose(Matrix< MT, SO > &matrix)
In-place conjugate transpose of the given matrix.
Definition: Matrix.h:1221

Note however that the conjugate transpose operation fails if ...

  • ... the given matrix has a fixed size and is non-square;
  • ... the given matrix is a triangular matrix;
  • ... the given submatrix affects the restricted parts of a triangular matrix;
  • ... the given submatrix would cause non-deterministic results in a symmetric/Hermitian matrix.


swap()

Via the swap() function it is possible to completely swap the contents of two matrices of the same type:

swap( M1, M2 ); // Swapping the contents of M1 and M2
void swap(DiagonalMatrix< MT, SO, DF > &a, DiagonalMatrix< MT, SO, DF > &b) noexcept
Swapping the contents of two matrices.
Definition: DiagonalMatrix.h:225


Arithmetic Operations


min() / max()

The min() and max() functions can be used for a single matrix, multiple matrices, and a matrix and a scalar.

Single Matrix

If passed a single matrix, the functions return the smallest and largest element of the given dense matrix or the smallest and largest non-zero element of the given sparse matrix, respectively:

{ -4, 0, 1 } };
min( A ); // Returns -5
max( A ); // Returns 7
decltype(auto) min(const DenseMatrix< MT1, SO1 > &lhs, const DenseMatrix< MT2, SO2 > &rhs)
Computes the componentwise minimum of the dense matrices lhs and rhs.
Definition: DMatDMatMapExpr.h:1339
decltype(auto) max(const DenseMatrix< MT1, SO1 > &lhs, const DenseMatrix< MT2, SO2 > &rhs)
Computes the componentwise maximum of the dense matrices lhs and rhs.
Definition: DMatDMatMapExpr.h:1375
{ 0, 0, 0 } };
min( B ); // Returns 1
max( B ); // Returns 3

For more information on the unary min() and max() reduction operations see the Reduction Operations section.

Multiple Matrices

If passed two or more dense matrices, the min() and max() functions compute the componentwise minimum or maximum of the given matrices, respectively:

blaze::StaticMatrix<int,2UL,3UL,rowMajor> C{ { -5, 1, -7 }, { 4, 1, 0 } };
blaze::StaticMatrix<int,2UL,3UL,rowMajor> D{ { -5, 3, 0 }, { 2, 2, -2 } };
min( A, C ); // Results in the matrix ( -5, 1, -7 ) ( -4, 0, 0 )
max( A, C, D ); // Results in the matrix ( -5, 3, 7 ) ( 4, 2, 1 )

Please note that sparse matrices can only be used in the unary min() and max() functions. Also note that all forms of the min() and max() functions can be used to compute the smallest and largest element of a matrix expression:

min( A + B + C ); // Returns -9, i.e. the smallest value of the resulting matrix
max( A - B - C ); // Returns 11, i.e. the largest value of the resulting matrix

Matrix and Scalar

If passed a dense matrix and a scalar, the min() and max() functions compute the componentwise minimum or maximum between the given matrix and a uniform matrix represented by the scalar value:

min( A, 0 ); // Results in the matrix ( 0, 2, 7 ) ( 0, 0, 1 )
min( 0, A ); // Results in the matrix ( 0, 2, 7 ) ( 0, 0, 1 )
max( A, 0 ); // Results in the matrix ( -5, 0, 0 ) ( -4, 0, 0 )
max( 0, A ); // Results in the matrix ( -5, 0, 0 ) ( -4, 0, 0 )


softmax()

The softmax function, also called the normalized exponential function, of a given dense matrix can be computed via softmax(). The resulting dense matrix consists of real values in the range (0..1], which add up to 1.

, { 4.0, 1.0, 2.0 }
, { 3.0, 4.0, 1.0 } };
// Evaluating the softmax function
B = softmax( A ); // Results in ( 0.0157764 0.0428847 0.116573 )
// ( 0.316878 0.0157764 0.0428847 )
// ( 0.116573 0.316878 0.0157764 )
double b = sum( B ); // Results in 1
decltype(auto) sum(const DenseMatrix< MT, SO > &dm)
Reduces the given dense matrix by means of addition.
Definition: DMatReduceExpr.h:2156
auto softmax(const DenseMatrix< MT, SO > &dm)
Computes the softmax function for the given dense matrix.
Definition: DMatSoftmaxExpr.h:88

Alternatively it is possible to compute a row- or columnwise softmax() function. The resulting dense matrix consists of real values in the range (0..1], which add up to the number of rows or columns, respectively.

// Evaluating the rowwise softmax function
C = softmax<rowwise>( A ); // Results in ( 0.0900306 0.244728 0.665241 )
// ( 0.843795 0.0420101 0.114195 )
// ( 0.259496 0.705385 0.035119 )
double c = sum( C ); // Results in 3 (the number of rows of A)
// Evaluating the columnwise softmax function
D = softmax<columnwise>( A ); // Results in ( 0.035119 0.114195 0.665241 )
// ( 0.705385 0.0420101 0.244728 )
// ( 0.259496 0.843795 0.0900306 )
double d = sum( D ); // Results in 3 (the number of columns of A)
constexpr ReductionFlag columnwise
Reduction flag for column-wise reduction operations.
Definition: ReductionFlag.h:97
constexpr ReductionFlag rowwise
Reduction flag for row-wise reduction operations.
Definition: ReductionFlag.h:77


trace()

The trace() function sums the diagonal elements of a square dense or sparse matrix:

, { -4, -5, 6 }
, { 7, -8, -9 } };
trace( A ); // Returns the sum of the diagonal elements, i.e. -15
auto trace(const Matrix< MT, SO > &m)
Computes the trace of the given square matrix.
Definition: Matrix.h:792

In case the given matrix is not a square matrix, a std::invalid_argument exception is thrown.


det()

The determinant of a square dense matrix can be computed by means of the det() function:

// ... Resizing and initialization
double d = det( A ); // Compute the determinant of A
ElementType_t< MT > det(const DenseMatrix< MT, SO > &dm)
Computation of the determinant of the given dense square matrix.
Definition: DMatDetExpr.h:384

In case the given dense matrix is not a square matrix, a std::invalid_argument exception is thrown.

Note
The det() function can only be used for dense matrices with float, double, complex<float> or complex<double> element type. The attempt to call the function with matrices of any other element type or with a sparse matrix results in a compile time error!
The function is depending on LAPACK kernels. Thus the function can only be used if a fitting LAPACK library is available and linked to the executable. Otherwise a linker error will be created.


rank()

The rank() function computes the rank of a given dense matrix:

// ... Initialization
rank( A );
size_t rank(const DenseMatrix< MT, SO > &dm)
Computes the rank of the given dense matrix.
Definition: DenseMatrix.h:2715

The rank is determined as the number of singular values greater than a given tolerance. This tolerance is computed as

tolerance = max(m,n) * max(s) * epsilon,
constexpr Epsilon epsilon
Global Epsilon instance.
Definition: Epsilon.h:906

where m is the number of rows of the dense matrix, n is the number of columns of the dense matrix, max(s) is the maximum singular value of the dense matrix and epsilon is the difference between 1 and the least value greater than 1 that is representable by the floating point type of the singular values.

Note
The rank() function can only be used for dense matrices with float, double, complex<float> or complex<double> element type. The attempt to call the function with matrices of any other element type or with a sparse matrix results in a compile time error!
The function is depending on LAPACK kernels. Thus the function can only be used if a fitting LAPACK library is available and linked to the executable. Otherwise a linker error will be created.


abs()

The abs() function can be used to compute the absolute values of each element of a matrix. For instance, the following computation

{ 4, -5, 6 } };
decltype(auto) abs(const DenseMatrix< MT, SO > &dm)
Applies the abs() function to each single element of the dense matrix dm.
Definition: DMatMapExpr.h:1296

results in the matrix

                      \f$ B = \left(\begin{array}{*{3}{c}}
                      1 & 2 & 3 \\
                      4 & 5 & 6 \\
                      \end{array}\right)\f$


sign()

The sign() function can be used to evaluate the sign of each element of a matrix A. For each element (i,j) the corresponding result is 1 if A(i,j) is greater than zero, 0 if A(i,j) is zero, and -1 if A(i,j) is less than zero. For instance, the following use of the sign() function

{ 4, 0, -6 } };
decltype(auto) sign(const DenseMatrix< MT, SO > &dm)
Applies the sign() function to each single element of the dense matrix dm.
Definition: DMatMapExpr.h:1324

results in the matrix

                      \f$ B = \left(\begin{array}{*{3}{c}}
                      -1 & 1 &  0 \\
                       1 & 0 & -1 \\
                      \end{array}\right)\f$


floor() / ceil() / trunc() / round()

The floor(), ceil(), trunc(), and round() functions can be used to round down/up each element of a matrix, respectively:

B = floor( A ); // Rounding down each element of the matrix
B = ceil ( A ); // Rounding up each element of the matrix
B = trunc( A ); // Truncating each element of the matrix
B = round( A ); // Rounding each element of the matrix
decltype(auto) trunc(const DenseMatrix< MT, SO > &dm)
Applies the trunc() function to each single element of the dense matrix dm.
Definition: DMatMapExpr.h:1408
decltype(auto) floor(const DenseMatrix< MT, SO > &dm)
Applies the floor() function to each single element of the dense matrix dm.
Definition: DMatMapExpr.h:1352
decltype(auto) ceil(const DenseMatrix< MT, SO > &dm)
Applies the ceil() function to each single element of the dense matrix dm.
Definition: DMatMapExpr.h:1380
decltype(auto) round(const DenseMatrix< MT, SO > &dm)
Applies the round() function to each single element of the dense matrix dm.
Definition: DMatMapExpr.h:1436


conj()

The conj() function can be applied on a dense or sparse matrix to compute the complex conjugate of each element of the matrix:

using cplx = std::complex<double>;
// Creating the matrix
// ( (1,0) (-2,-1) )
// ( (1,1) ( 0, 1) )
StaticMatrix<cplx,2UL,2UL> A{ { cplx( 1.0, 0.0 ), cplx( -2.0, -1.0 ) },
{ cplx( 1.0, 1.0 ), cplx( 0.0, 1.0 ) } };
// Computing the matrix of conjugate values
// ( (1, 0) (-2, 1) )
// ( (1,-1) ( 0,-1) )
StaticMatrix<cplx,2UL,2UL> B;
B = conj( A );

Additionally, matrices can be conjugated in-place via the conjugate() function:

conjugate( C ); // In-place conjugate operation.
C = conj( C ); // Same as above
BLAZE_ALWAYS_INLINE void conjugate(T &a) noexcept(IsNumeric_v< T >)
In-place conjugation of the given value/object.
Definition: Conjugate.h:118


real()

The real() function can be used on a dense or sparse matrix to extract the real part of each element of the matrix:

using cplx = std::complex<double>;
// Creating the matrix
// ( (1,0) (-2,-1) )
// ( (1,1) ( 0, 1) )
StaticMatrix<cplx,2UL,2UL> A{ { cplx( 1.0, 0.0 ), cplx( -2.0, -1.0 ) },
{ cplx( 1.0, 1.0 ), cplx( 0.0, 1.0 ) } };
// Extracting the real part of each matrix element
// ( 1 -2 )
// ( 1 0 )
StaticMatrix<double,2UL,2UL> B;
B = real( A );
decltype(auto) real(const DenseMatrix< MT, SO > &dm)
Returns a matrix containing the real part of each single element of dm.
Definition: DMatMapExpr.h:1529


imag()

The imag() function can be used on a dense or sparse matrix to extract the imaginary part of each element of the matrix:

using cplx = std::complex<double>;
// Creating the matrix
// ( (1,0) (-2,-1) )
// ( (1,1) ( 0, 1) )
StaticMatrix<cplx,2UL,2UL> A{ { cplx( 1.0, 0.0 ), cplx( -2.0, -1.0 ) },
{ cplx( 1.0, 1.0 ), cplx( 0.0, 1.0 ) } };
// Extracting the imaginary part of each matrix element
// ( 0 -1 )
// ( 1 1 )
StaticMatrix<double,2UL,2UL> B;
B = imag( A );
decltype(auto) imag(const DenseMatrix< MT, SO > &dm)
Returns a matrix containing the imaginary part of each single element of dm.
Definition: DMatMapExpr.h:1557


arg()

The arg() function can be used on a dense or sparse matrix to compute the phase angle for each element of the matrix:

using cplx = std::complex<double>;
// Creating the matrix
// ( (1,0) (-2,-1) )
// ( (1,1) ( 0, 1) )
StaticMatrix<cplx,2UL,2UL> A{ { cplx( 1.0, 0.0 ), cplx( -2.0, -1.0 ) },
{ cplx( 1.0, 1.0 ), cplx( 0.0, 1.0 ) } };
// Computing the phase angle of each matrix element
// ( 0.0 -2.67795 )
// ( 0.785398 1.5708 )
StaticMatrix<double,2UL,2UL> B;
B = arg( A );
decltype(auto) arg(const DenseMatrix< MT, SO > &dm)
Returns a matrix containing the phase angle of each single element of dm.
Definition: DMatMapExpr.h:1585


sqrt() / invsqrt()

Via the sqrt() and invsqrt() functions the (inverse) square root of each element of a matrix can be computed:

B = sqrt( A ); // Computes the square root of each element
C = invsqrt( A ); // Computes the inverse square root of each element
decltype(auto) invsqrt(const DenseMatrix< MT, SO > &dm)
Computes the inverse square root of each single element of the dense matrix dm.
Definition: DMatMapExpr.h:1647
decltype(auto) sqrt(const DenseMatrix< MT, SO > &dm)
Computes the square root of each single element of the dense matrix dm.
Definition: DMatMapExpr.h:1616

Note that in case of sparse matrices only the non-zero elements are taken into account!


cbrt() / invcbrt()

The cbrt() and invcbrt() functions can be used to compute the the (inverse) cubic root of each element of a matrix:

B = cbrt( A ); // Computes the cubic root of each element
C = invcbrt( A ); // Computes the inverse cubic root of each element
decltype(auto) cbrt(const DenseMatrix< MT, SO > &dm)
Computes the cubic root of each single element of the dense matrix dm.
Definition: DMatMapExpr.h:1678
decltype(auto) invcbrt(const DenseMatrix< MT, SO > &dm)
Computes the inverse cubic root of each single element of the dense matrix dm.
Definition: DMatMapExpr.h:1709

Note that in case of sparse matrices only the non-zero elements are taken into account!


hypot()

The hypot() function can be used to compute the componentwise hypotenous for a pair of dense matrices:

C = hypot( A, B ); // Computes the componentwise hypotenuous
decltype(auto) hypot(const DenseMatrix< MT1, SO1 > &lhs, const DenseMatrix< MT2, SO2 > &rhs)
Computes the componentwise hypotenous for the dense matrices lhs and rhs.
Definition: DMatDMatMapExpr.h:1412


clamp()

The clamp() function can be used to restrict all elements of a matrix to a specific range:

B = clamp( A, -1.0, 1.0 ); // Restrict all elements to the range [-1..1]
decltype(auto) clamp(const DenseMatrix< MT, SO > &dm, const DT &min, const DT &max)
Restricts each single element of the dense matrix dm to the range .
Definition: DMatMapExpr.h:1740

Note that in case of sparse matrices only the non-zero elements are taken into account!


pow()

The pow() function can be used to compute the exponential value of each element of a matrix. If passed a matrix and a numeric exponent, the function computes the exponential value of each element of the matrix using the same exponent. If passed a second matrix, the function computes the componentwise exponential value:

C = pow( A, 1.2 ); // Computes the exponential value of each element
C = pow( A, B ); // Computes the componentwise exponential value
decltype(auto) pow(const DenseMatrix< MT1, SO1 > &lhs, const DenseMatrix< MT2, SO2 > &rhs)
Computes the componentwise exponential value for the dense matrices lhs and rhs.
Definition: DMatDMatMapExpr.h:1448


exp() / exp2() / exp10()

exp(), exp2() and exp10() compute the base e/2/10 exponential of each element of a matrix, respectively:

B = exp( A ); // Computes the base e exponential of each element
B = exp2( A ); // Computes the base 2 exponential of each element
B = exp10( A ); // Computes the base 10 exponential of each element
decltype(auto) exp(const DenseMatrix< MT, SO > &dm)
Computes for each single element of the dense matrix dm.
Definition: DMatMapExpr.h:1801
decltype(auto) exp2(const DenseMatrix< MT, SO > &dm)
Computes for each single element of the dense matrix dm.
Definition: DMatMapExpr.h:1829
decltype(auto) exp10(const DenseMatrix< MT, SO > &dm)
Computes for each single element of the dense matrix dm.
Definition: DMatMapExpr.h:1857

Note that in case of sparse matrices only the non-zero elements are taken into account!


log() / log2() / log10() / log1p() / lgamma()

The log(), log2(), log10(), log1p() and lgamma() functions can be used to compute the natural, binary and common logarithm of each element of a matrix:

B = log( A ); // Computes the natural logarithm of each element
B = log2( A ); // Computes the binary logarithm of each element
B = log10( A ); // Computes the common logarithm of each element
B = log1p( A ); // Computes the natural logarithm of x+1 of each element
B = lgamma( A ); // Computes the natural logarithm of the absolute value of the gamma function
decltype(auto) log1p(const DenseMatrix< MT, SO > &dm)
Computes the natural logarithm of x+1 for each single element of the dense matrix dm.
Definition: DMatMapExpr.h:1983
decltype(auto) log(const DenseMatrix< MT, SO > &dm)
Computes the natural logarithm for each single element of the dense matrix dm.
Definition: DMatMapExpr.h:1888
decltype(auto) log2(const DenseMatrix< MT, SO > &dm)
Computes the binary logarithm for each single element of the dense matrix dm.
Definition: DMatMapExpr.h:1919
decltype(auto) log10(const DenseMatrix< MT, SO > &dm)
Computes the common logarithm for each single element of the dense matrix dm.
Definition: DMatMapExpr.h:1950
decltype(auto) lgamma(const DenseMatrix< MT, SO > &dm)
Computes the natural logarithm of the absolute value of the gamma function for each single element of...
Definition: DMatMapExpr.h:2016


sin() / cos() / tan() / asin() / acos() / atan()

The following trigonometric functions are available for both dense and sparse matrices:

B = sin( A ); // Computes the sine of each element of the matrix
B = cos( A ); // Computes the cosine of each element of the matrix
B = tan( A ); // Computes the tangent of each element of the matrix
B = asin( A ); // Computes the inverse sine of each element of the matrix
B = acos( A ); // Computes the inverse cosine of each element of the matrix
B = atan( A ); // Computes the inverse tangent of each element of the matrix
decltype(auto) sin(const DenseMatrix< MT, SO > &dm)
Computes the sine for each single element of the dense matrix dm.
Definition: DMatMapExpr.h:2044
decltype(auto) acos(const DenseMatrix< MT, SO > &dm)
Computes the inverse cosine for each single element of the dense matrix dm.
Definition: DMatMapExpr.h:2190
decltype(auto) atan(const DenseMatrix< MT, SO > &dm)
Computes the inverse tangent for each single element of the dense matrix dm.
Definition: DMatMapExpr.h:2305
decltype(auto) asin(const DenseMatrix< MT, SO > &dm)
Computes the inverse sine for each single element of the dense matrix dm.
Definition: DMatMapExpr.h:2075
decltype(auto) cos(const DenseMatrix< MT, SO > &dm)
Computes the cosine for each single element of the dense matrix dm.
Definition: DMatMapExpr.h:2159
decltype(auto) tan(const DenseMatrix< MT, SO > &dm)
Computes the tangent for each single element of the dense matrix dm.
Definition: DMatMapExpr.h:2277

Note that in case of sparse matrices only the non-zero elements are taken into account!


sinh() / cosh() / tanh() / asinh() / acosh() / atanh()

The following hyperbolic functions are available for both dense and sparse matrices:

B = sinh( A ); // Computes the hyperbolic sine of each element of the matrix
B = cosh( A ); // Computes the hyperbolic cosine of each element of the matrix
B = tanh( A ); // Computes the hyperbolic tangent of each element of the matrix
B = asinh( A ); // Computes the inverse hyperbolic sine of each element of the matrix
B = acosh( A ); // Computes the inverse hyperbolic cosine of each element of the matrix
B = atanh( A ); // Computes the inverse hyperbolic tangent of each element of the matrix
decltype(auto) asinh(const DenseMatrix< MT, SO > &dm)
Computes the inverse hyperbolic sine for each single element of the dense matrix dm.
Definition: DMatMapExpr.h:2131
decltype(auto) acosh(const DenseMatrix< MT, SO > &dm)
Computes the inverse hyperbolic cosine for each single element of the dense matrix dm.
Definition: DMatMapExpr.h:2249
decltype(auto) sinh(const DenseMatrix< MT, SO > &dm)
Computes the hyperbolic sine for each single element of the dense matrix dm.
Definition: DMatMapExpr.h:2103
decltype(auto) tanh(const DenseMatrix< MT, SO > &dm)
Computes the hyperbolic tangent for each single element of the dense matrix dm.
Definition: DMatMapExpr.h:2336
decltype(auto) cosh(const DenseMatrix< MT, SO > &dm)
Computes the hyperbolic cosine for each single element of the dense matrix dm.
Definition: DMatMapExpr.h:2218
decltype(auto) atanh(const DenseMatrix< MT, SO > &dm)
Computes the inverse hyperbolic tangent for each single element of the dense matrix dm.
Definition: DMatMapExpr.h:2367


atan2()

The multi-valued inverse tangent is available for a pair of dense matrices:

C = atan2( A, B ); // Computes the componentwise multi-valued inverse tangent
decltype(auto) atan2(const DenseMatrix< MT1, SO1 > &lhs, const DenseMatrix< MT2, SO2 > &rhs)
Computes the multi-valued inverse tangent of the dense matrices lhs and rhs.
Definition: DMatDMatMapExpr.h:1484


erf() / erfc()

The erf() and erfc() functions compute the (complementary) error function of each element of a matrix:

B = erf( A ); // Computes the error function of each element
B = erfc( A ); // Computes the complementary error function of each element
decltype(auto) erfc(const DenseMatrix< MT, SO > &dm)
Computes the complementary error function for each single element of the dense matrix dm.
Definition: DMatMapExpr.h:2423
decltype(auto) erf(const DenseMatrix< MT, SO > &dm)
Computes the error function for each single element of the dense matrix dm.
Definition: DMatMapExpr.h:2395

Note that in case of sparse matrices only the non-zero elements are taken into account!


map() / forEach()

Via the map() functions it is possible to execute componentwise custom operations on matrices. The unary map() function can be used to apply a custom operation on each element of a dense or sparse matrix. For instance, the following example demonstrates a custom square root computation via a lambda:

B = map( A, []( double d ) { return std::sqrt( d ); } );
decltype(auto) map(const DenseMatrix< MT1, SO > &lhs, const DenseMatrix< MT2, SO > &rhs, OP op)
Elementwise evaluation of the given binary operation on each single element of the dense matrices lhs...
Definition: DMatDMatMapExpr.h:1144

The N-ary map() functions can be used to apply an operation componentwise to the elements of N dense matrices (where $ N <= 6 $). The following example demonstrates the merging of two matrices of double precision values into a matrix of double precision complex numbers:

blaze::DynamicMatrix<double> real{ { 2.1, -4.2 }, { 1.0, 0.6 } };
blaze::DynamicMatrix<double> imag{ { 0.3, 1.4 }, { 2.9, -3.4 } };
// Creating the matrix
// ( ( 2.1, 0.3) (-4.2, 1.4) )
// ( ( 1.0, 2.9) ( 0.6, -3.4) )
cplx = map( real, imag, []( double r, double i ){ return complex<double>( r, i ); } );
Complex data type of the Blaze library.

Although the computation can be parallelized it is not vectorized and thus cannot perform at peak performance. However, it is also possible to create vectorized custom operations. See Custom Operations for a detailed overview of the possibilities of custom operations.

Please note that unary custom operations on vectors have been introduced in Blaze 3.0 in form of the forEach() function. With the introduction of binary custom functions, the forEach() function has been renamed to map(). The forEach() function can still be used, but the function might be deprecated in future releases of Blaze.


select()

The select() function performs a componentwise, conditional selection of elements. Given the three dense matrices cond, A, and B, in case an element in the cond vector evaluates to true, the according element of A is selected, in case the cond element evaluates to false, the according element of B is selected. The following example demonstrates the use of the select() function:

blaze::DynamicMatrix<bool> cond{ { true, false }, { true false } };
blaze::DynamicMatrix<int> A{ { 1, -1 }, { 1, -1 } };
blaze::DynamicMatrix<int> B{ { -2, 2 }, { -2, 2 } };
// ... Resizing and initialization
C = select( cond, A, B ); // Results in ( 1, 2 ) ( 1, 2 )
decltype(auto) select(const DenseMatrix< MT1, SO > &cond, const DenseMatrix< MT2, SO > &lhs, const DenseMatrix< MT3, SO > &rhs)
Elementwise conditional selection of values from the dense matrices lhs and rhs.
Definition: DMatDMatMapExpr.h:1528


Reduction Operations


reduce()

The reduce() function performs either a total reduction, a rowwise reduction or a columnwise reduction of the elements of the given dense matrix or the non-zero elements of the given sparse matrix. The following examples demonstrate the total reduction of a dense and sparse matrix:

// ... Resizing and initialization
const double totalsum1 = reduce( A, blaze::Add() );
const double totalsum2 = reduce( A, []( double a, double b ){ return a + b; } );
decltype(auto) reduce(const DenseMatrix< MT, SO > &dm, OP op)
Performs a custom reduction operation on the given dense matrix.
Definition: DMatReduceExpr.h:2025
Generic wrapper for the addition operator.
Definition: Add.h:85
// ... Resizing and initialization
const double totalsum1 = reduce( A, blaze::Add() );
const double totalsum2 = reduce( A, []( double a, double b ){ return a + b; } );

By specifying blaze::columnwise or blaze::rowwise the reduce() function performs a column-wise or row-wise reduction, respectively. In case blaze::columnwise is specified, the (non-zero) elements of the matrix are reduced column-wise and the result is a row vector. In case blaze::rowwise is specified, the (non-zero) elements of the matrix are reduced row-wise and the result is a column vector:

// ... Resizing and initialization
colsum1 = reduce<columnwise>( A, blaze::Add() );
colsum2 = reduce<columnwise>( B, []( double a, double b ){ return a + b; } );
// ... Resizing and initialization
rowsum1 = reduce<rowwise>( A, blaze::Add() );
rowsum2 = reduce<rowwise>( B, []( double a, double b ){ return a + b; } );

As demonstrated in the examples it is possible to pass any binary callable as custom reduction operation. However, for instance in the case of lambdas the vectorization of the reduction operation is compiler dependent and might not perform at peak performance. However, it is also possible to create vectorized custom operations. See Custom Operations for a detailed overview of the possibilities of custom operations.

Please note that the evaluation order of the reduce() function is unspecified. Thus the behavior is non-deterministic if the given reduction operation is not associative or not commutative. Also, the operation is undefined if the given reduction operation modifies the values.


sum()

The sum() function reduces the elements of the given dense vector or the non-zero elements of the given sparse vector by means of addition:

blaze::DynamicMatrix<int> A{ { 1, 2 }, { 3, 4 } };
const int totalsum = sum( A ); // Results in 10
blaze::CompressedMatrix<int> a{ { 1, 2 }, { 3, 4 } };
const int totalsum = sum( A ); // Results in 10

By specifying blaze::columnwise or blaze::rowwise the sum() function performs a column-wise or row-wise summation, respectively. In case blaze::columnwise is specified, the (non-zero) elements of the matrix are summed up column-wise and the result is a row vector. In case blaze::rowwise is specified, the (non-zero) elements of the matrix are summed up row-wise and the result is a column vector:

blaze::DynamicMatrix<int> A{ { 1, 0, 2 }, { 1, 3, 4 } };
blaze::CompressedMatrix<int> B{ { 1, 0, 2 }, { 1, 3, 4 } };
colsum1 = sum<columnwise>( A ); // Results in ( 2, 3, 6 )
colsum2 = sum<columnwise>( B ); // Same result
blaze::DynamicMatrix<int> A{ { 1, 0, 2 }, { 1, 3, 4 } };
blaze::CompressedMatrix<int> B{ { 1, 0, 2 }, { 1, 3, 4 } };
rowsum1 = sum<rowwise>( A ); // Results in ( 3, 8 )
rowsum2 = sum<rowwise>( B ); // Same result

Please note that the evaluation order of the sum() function is unspecified.


prod()

The prod() function reduces the elements of the given dense vector or the non-zero elements of the given sparse vector by means of multiplication:

blaze::DynamicMatrix<int> A{ { 1, 2 }, { 3, 4 } };
const int totalprod = prod( A ); // Results in 24
decltype(auto) prod(const DenseMatrix< MT, SO > &dm)
Reduces the given dense matrix by means of multiplication.
Definition: DMatReduceExpr.h:2229
blaze::CompressedMatrix<int> A{ { 1, 2 }, { 3, 4 } };
const int totalprod = prod( A ); // Results in 24

By specifying blaze::columnwise or blaze::rowwise the prod() function performs a column-wise or row-wise multiplication, respectively. In case blaze::columnwise is specified, the (non-zero) elements of the matrix are multiplied column-wise and the result is a row vector. In case blaze::rowwise is specified, the (non-zero) elements of the matrix are multiplied row-wise and the result is a column vector:

blaze::DynamicMatrix<int> A{ { 1, 0, 2 }, { 1, 3, 4 } };
blaze::CompressedMatrix<int> B{ { 1, 0, 2 }, { 1, 3, 4 } };
colprod1 = prod<columnwise>( A ); // Results in ( 1, 0, 8 )
colprod2 = prod<columnwise>( A ); // Results in ( 1, 3, 8 )
blaze::DynamicMatrix<int> A{ { 1, 0, 2 }, { 1, 3, 4 } };
blaze::CompressedMatrix<int> B{ { 1, 0, 2 }, { 1, 3, 4 } };
rowprod1 = prod<rowwise>( A ); // Results in ( 0, 12 )
rowprod2 = prod<rowwise>( A ); // Results in ( 2, 12 )

Please note that the evaluation order of the prod() function is unspecified.


min()

The unary min() function returns the smallest element of the given dense matrix or the smallest non-zero element of the given sparse matrix. This function can only be used for element types that support the smaller-than relationship. In case the given matrix currently has either 0 rows or 0 columns, the returned value is the default value (e.g. 0 in case of fundamental data types).

blaze::DynamicMatrix<int> A{ { 1, 2 }, { 3, 4 } };
const int totalmin = min( A ); // Results in 1
blaze::CompressedMatrix<int> A{ { 1, 0 }, { 3, 0 } };
const int totalmin = min( A ); // Results in 1
Note
In case the sparse matrix is not completely filled, the implicit zero elements are NOT taken into account. In the previous example the compressed matrix has only 2 non-zero elements. However, the minimum of this matrix is 1.

By specifying blaze::columnwise or blaze::rowwise the min() function determines the smallest (non-zero) element in each row or column, respectively. In case blaze::columnwise is specified, the smallest (non-zero) element of each column is determined and the result is a row vector. In case blaze::rowwise is specified, the smallest (non-zero) element of each row is determined and the result is a column vector.

blaze::DynamicMatrix<int> A{ { 1, 0, 2 }, { 1, 3, 4 } };
blaze::CompressedMatrix<int> B{ { 1, 0, 2 }, { 1, 3, 4 } };
colmin1 = min<columnwise>( A ); // Results in ( 1, 0, 2 )
colmin2 = min<columnwise>( B ); // Results in ( 1, 3, 2 )
blaze::DynamicMatrix<int> A{ { 1, 0, 2 }, { 1, 3, 4 } };
blaze::CompressedMatrix<int> B{ { 1, 0, 2 }, { 1, 3, 4 } };
rowmin1 = min<rowwise>( A ); // Results in ( 0, 1 )
rowmin2 = min<rowwise>( B ); // Results in ( 1, 1 )
Note
In case the sparse matrix is not completely filled, the implicit zero elements are NOT taken into account.


max()

The unary max() function returns the largest element of the given dense matrix or the largest non-zero element of the given sparse matrix. This function can only be used for element types that support the smaller-than relationship. In case the given matrix currently has either 0 rows or 0 columns, the returned value is the default value (e.g. 0 in case of fundamental data types).

blaze::DynamicMatrix<int> A{ { 1, 2 }, { 3, 4 } };
const int totalmax = max( A ); // Results in 4
blaze::CompressedMatrix<int> A{ { -1, 0 }, { -3, 0 } };
const int totalmax = max( A ); // Results in -1
Note
In case the sparse matrix is not completely filled, the implicit zero elements are NOT taken into account. In the previous example the compressed matrix has only 2 non-zero elements. However, the maximum of this matrix is -1.

By specifying blaze::columnwise or blaze::rowwise the max() function determines the largest (non-zero) element in each row or column, respectively. In case blaze::columnwise is specified, the largest (non-zero) element of each column is determined and the result is a row vector. In case blaze::rowwise is specified, the largest (non-zero) element of each row is determined and the result is a column vector.

blaze::DynamicMatrix<int> A{ { 1, 0, 2 }, { 1, 3, 4 } };
blaze::CompressedMatrix<int> B{ { -1, 0, -2 }, { -1, -3, -4 } };
colmax1 = max<columnwise>( A ); // Results in ( 1, 3, 4 )
colmax2 = max<columnwise>( B ); // Results in ( -1, -3, -2 )
blaze::DynamicMatrix<int> A{ { 1, 0, 2 }, { 1, 3, 4 } };
blaze::CompressedMatrix<int> B{ { -1, 0, -2 }, { -1, -3, -4 } };
rowmax1 = max<rowwise>( A ); // Results in ( 2, 4 )
rowmax2 = max<rowwise>( B ); // Results in ( -1, -1 )
Note
In case the sparse matrix is not completely filled, the implicit zero elements are NOT taken into account.


Norms


norm()

The norm() function computes the L2 norm of the given dense or sparse matrix:

// ... Resizing and initialization
const double norm1 = norm( A );
const double norm2 = norm( B );
decltype(auto) norm(const DenseMatrix< MT, SO > &dm)
Computes the L2 norm for the given dense matrix.
Definition: DMatNormExpr.h:573


sqrNorm()

The sqrNorm() function computes the squared L2 norm of the given dense or sparse matrix:

// ... Resizing and initialization
const double norm1 = sqrNorm( A );
const double norm2 = sqrNorm( B );
decltype(auto) sqrNorm(const DenseMatrix< MT, SO > &dm)
Computes the squared L2 norm for the given dense matrix.
Definition: DMatNormExpr.h:599


l1Norm()

The l1Norm() function computes the squared L1 norm of the given dense or sparse matrix:

// ... Resizing and initialization
const double norm1 = l1Norm( A );
const double norm2 = l1Norm( B );
decltype(auto) l1Norm(const DenseMatrix< MT, SO > &dm)
Computes the L1 norm for the given dense matrix.
Definition: DMatNormExpr.h:625


l2Norm()

The l2Norm() function computes the squared L2 norm of the given dense or sparse matrix:

// ... Resizing and initialization
const double norm1 = l2Norm( A );
const double norm2 = l2Norm( B );
decltype(auto) l2Norm(const DenseMatrix< MT, SO > &dm)
Computes the L2 norm for the given dense matrix.
Definition: DMatNormExpr.h:651


l3Norm()

The l3Norm() function computes the squared L3 norm of the given dense or sparse matrix:

// ... Resizing and initialization
const double norm1 = l3Norm( A );
const double norm2 = l3Norm( B );
decltype(auto) l3Norm(const DenseMatrix< MT, SO > &dm)
Computes the L3 norm for the given dense matrix.
Definition: DMatNormExpr.h:677


l4Norm()

The l4Norm() function computes the squared L4 norm of the given dense or sparse matrix:

// ... Resizing and initialization
const double norm1 = l4Norm( A );
const double norm2 = l4Norm( B );
decltype(auto) l4Norm(const DenseMatrix< MT, SO > &dm)
Computes the L4 norm for the given dense matrix.
Definition: DMatNormExpr.h:703


lpNorm()

The lpNorm() function computes the general Lp norm of the given dense or sparse matrix, where the norm is specified by either a compile time or a runtime argument:

// ... Resizing and initialization
const double norm1 = lpNorm<2>( A ); // Compile time argument
const double norm2 = lpNorm( B, 2.3 ); // Runtime argument
decltype(auto) lpNorm(const DenseMatrix< MT, SO > &dm, ST p)
Computes the Lp norm for the given dense matrix.
Definition: DMatNormExpr.h:735


linfNorm() / maxNorm()

The linfNorm() and maxNorm() functions compute the infinity/maximum norm of the given dense or sparse matrix:

// ... Resizing and initialization
const double norm1 = linfNorm( A );
const double norm2 = maxNorm( B );
decltype(auto) linfNorm(const DenseMatrix< MT, SO > &dm)
Computes the infinity norm for the given dense matrix.
Definition: DMatNormExpr.h:799
decltype(auto) maxNorm(const DenseMatrix< MT, SO > &dm)
Computes the maximum norm for the given dense matrix.
Definition: DMatNormExpr.h:825


minNorm()

The minNorm() function computes the minimum norm of the given dense or sparse matrix:

// ... Resizing and initialization
const double norm = minNorm( B );
decltype(auto) minNorm(const DenseMatrix< MT, SO > &dm)
Computes the minimum norm for the given dense matrix.
Definition: DMatNormExpr.h:851


Scalar Expansion


By means of the uniform() function it is possible to expand a scalar value into a dense, uniform matrix. By default, the resulting uniform matrix is a row-major matrix, but it is possible to specify the storage order explicitly:

int scalar = 5;
// ... Resizing and initialization
// Expansion of 'scalar' to a 3x5 row-major matrix
//
// ( 5 5 5 5 5 )
// ( 5 5 5 5 5 )
// ( 5 5 5 5 5 )
//
A = uniform( 3UL, 5UL, scalar );
A = uniform<columnMajor>( 3UL, 5UL, scalar );
constexpr decltype(auto) uniform(size_t m, size_t n, T &&init)
Creating a uniform matrix.
Definition: UniformMatrix.h:1640


Matrix Repetition


Via the repeat() function it is possible to repeat a dense or sparse matrix multiple times to represent a larger matrix. Repeating a row-major matrix results in a row-major matrix, repeating a column-major matrix results in a column-major matrix. As demonstrated by the following examples, repeat() can be used with both runtime and compile time parameters:

blaze::DynamicMatrix<int,rowMajor> A1{ { 1, 0, -2 }, { 0, 5, 0 } };
blaze::CompressedMatrix<int,columnMajor> B1{ { 0, -1 }, { 0, 4 }, { 7, 0 } };
// ... Resizing and initialization
// Repeating the 2x3 dense row-major matrix 'A1' 2x rowwise and 3x columnwise results in
//
// ( 1 0 -2 1 0 -2 1 0 -2 )
// ( 0 5 0 0 5 0 0 5 0 )
// ( 1 0 -2 1 0 -2 1 0 -2 )
// ( 0 5 0 0 5 0 0 5 0 )
//
A2 = repeat( A1, 2UL, 3UL );
A2 = repeat<2UL,3UL>( A1 );
// Repeating the 3x2 sparse column-major matrix 'B1' 2x rowwise and 3x columnwise results in
//
// ( 0 -1 0 -1 0 -1 )
// ( 0 4 0 4 0 4 )
// ( 7 0 7 0 7 0 )
// ( 0 -1 0 -1 0 -1 )
// ( 0 4 0 4 0 4 )
// ( 7 0 7 0 7 0 )
//
B2 = repeat( B1, 2UL, 3UL );
B2 = repeat<2UL,3UL>( B1 );
decltype(auto) repeat(const DenseMatrix< MT, SO > &dm, size_t m, size_t n)
Repeats the given dense matrix.
Definition: DMatRepeatExpr.h:543


Statistic Operations


mean()

The (arithmetic) mean of a dense or sparse matrix can be computed via the mean() function. In case of a sparse matrix, both the non-zero and zero elements are taken into account. The following example demonstrates the computation of the mean of a dense matrix:

blaze::DynamicMatrix<int> A{ { 1, 4, 3, 6, 7 }
, { 2, 6, 3, 1, 0 } };
const double m = mean( A ); // Results in 3.3 (i.e. 33/10)
decltype(auto) mean(const DenseMatrix< MT, SO > &dm)
Computes the (arithmetic) mean for the given dense matrix.
Definition: DMatMeanExpr.h:134

In case the number of rows or columns of the given matrix is 0, a std::invalid_argument is thrown.

Alternatively it is possible to compute the row- or columnwise mean:

blaze::DynamicMatrix<int> A{ { 1, 4, 3, 6, 7 }
, { 2, 6, 3, 1, 0 } };
rm = mean<rowwise>( A ); // Results in ( 4.2 2.4 )
cm = mean<columnwise>( A ); // Results in ( 1.5 5.0 3.0 3.5 3.5 )
constexpr bool columnVector
Transpose flag for column vectors.
Definition: TransposeFlag.h:58
constexpr bool rowVector
Transpose flag for row vectors.
Definition: TransposeFlag.h:73

In case the rowwise mean is computed and the number of columns of the given matrix is 0 or in case the columnwise mean is computed and the number of rows of the given matrix is 0, a std::invalid_argument is thrown.


var()

The variance of a dense or sparse matrix can be computed via the var() function. In case of a sparse vector, both the non-zero and zero elements are taken into account. The following example demonstrates the computation of the variance of a dense matrix:

, { 2, 6, 4 }
, { 9, 6, 3 } };
const double v = var( A ); // Results in 6.5
decltype(auto) var(const DenseMatrix< MT, SO > &dm)
Computes the variance for the given dense matrix.
Definition: DMatVarExpr.h:138

In case the size of the given matrix is smaller than 2, a std::invalid_argument is thrown.

Alternatively it is possible to compute the row- or columnwise variance:

, { 2, 6, 4 }
, { 9, 6, 3 } };
rv = var<rowwise>( A ); // Results in ( 1 4 9 )
cv = var<columnwise>( A ); // Results in ( 19 3 1 )

In case the rowwise varoamce is computed and the number of columns of the given matrix is smaller than 2 or in case the columnwise mean is computed and the number of rows of the given matrix is smaller than 2, a std::invalid_argument is thrown.


stddev()

The standard deviation of a dense or sparse matrix can be computed via the stddev() function. In case of a sparse vector, both the non-zero and zero elements are taken into account. The following example demonstrates the computation of the standard deviation of a dense matrix:

, { 2, 6, 4 }
, { 9, 6, 3 } };
const double s = stddev( A ); // Results in sqrt(6.5)
decltype(auto) stddev(const DenseMatrix< MT, SO > &dm)
Computes the standard deviation for the given dense matrix.
Definition: DMatStdDevExpr.h:83

In case the size of the given matrix is smaller than 2, a std::invalid_argument is thrown.

Alternatively it is possible to compute the row- or columnwise standard deviation:

, { 2, 6, 4 }
, { 9, 6, 3 } };
rs = stddev<rowwise>( A ); // Results in ( 1 2 3 )
cs = stddev<columnwise>( A ); // Results in ( sqrt(19) sqrt(3) 1 )

In case the rowwise standard deviation is computed and the number of columns of the given matrix is smaller than 2 or in case the columnwise mean is computed and the number of rows of the given matrix is smaller than 2, a std::invalid_argument is thrown.


Declaration Operations


declsym()

The declsym() operation can be used to explicitly declare any matrix or matrix expression as symmetric:

// ... Resizing and initialization
B = declsym( A );
decltype(auto) declsym(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as symmetric.
Definition: DMatDeclSymExpr.h:1005

Any matrix or matrix expression that has been declared as symmetric via declsym() will gain all the benefits of a symmetric matrix, which range from reduced runtime checking to a considerable speed-up in computations:

DynamicMatrix<double> A, B, C;
SymmetricMatrix< DynamicMatrix<double> > S;
// ... Resizing and initialization
isSymmetric( declsym( A ) ); // Will always return true without runtime effort
S = declsym( A ); // Omit any runtime check for symmetry
C = declsym( A * B ); // Declare the result of the matrix multiplication as symmetric,
// i.e. perform an optimized matrix multiplication
Matrix adapter for symmetric matrices.
Definition: BaseTemplate.h:614
Warning
The declsym() operation has the semantics of a cast: The caller is completely responsible and the system trusts the given information. Declaring a non-symmetric matrix or matrix expression as symmetric via the declsym() operation leads to undefined behavior (which can be violated invariants or wrong computation results)!


declherm()

The declherm() operation can be used to explicitly declare any matrix or matrix expression as Hermitian:

// ... Resizing and initialization
B = declherm( A );
decltype(auto) declherm(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as Hermitian.
Definition: DMatDeclHermExpr.h:1005

Any matrix or matrix expression that has been declared as Hermitian via declherm() will gain all the benefits of an Hermitian matrix, which range from reduced runtime checking to a considerable speed-up in computations:

DynamicMatrix<double> A, B, C;
HermitianMatrix< DynamicMatrix<double> > S;
// ... Resizing and initialization
isHermitian( declherm( A ) ); // Will always return true without runtime effort
S = declherm( A ); // Omit any runtime check for Hermitian symmetry
C = declherm( A * B ); // Declare the result of the matrix multiplication as Hermitian,
// i.e. perform an optimized matrix multiplication
Matrix adapter for Hermitian matrices.
Definition: BaseTemplate.h:616
bool isHermitian(const DenseMatrix< MT, SO > &dm)
Checks if the given dense matrix is Hermitian.
Definition: DenseMatrix.h:1534
Warning
The declherm() operation has the semantics of a cast: The caller is completely responsible and the system trusts the given information. Declaring a non-Hermitian matrix or matrix expression as Hermitian via the declherm() operation leads to undefined behavior (which can be violated invariants or wrong computation results)!


decllow()

The decllow() operation can be used to explicitly declare any matrix or matrix expression as lower triangular:

// ... Resizing and initialization
B = decllow( A );
decltype(auto) decllow(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as lower.
Definition: DMatDeclLowExpr.h:1004

Any matrix or matrix expression that has been declared as lower triangular via decllow() will gain all the benefits of a lower triangular matrix, which range from reduced runtime checking to a considerable speed-up in computations:

DynamicMatrix<double> A, B, C;
LowerMatrix< DynamicMatrix<double> > L;
// ... Resizing and initialization
isLower( decllow( A ) ); // Will always return true without runtime effort
L = decllow( A ); // Omit any runtime check for A being a lower matrix
C = decllow( A * B ); // Declare the result of the matrix multiplication as lower triangular,
// i.e. perform an optimized matrix multiplication
Warning
The decllow() operation has the semantics of a cast: The caller is completely responsible and the system trusts the given information. Declaring a non-lower matrix or matrix expression as lower triangular via the decllow() operation leads to undefined behavior (which can be violated invariants or wrong computation results)!


declunilow()

The declunilow() operation can be used to explicitly declare any matrix or matrix expression as lower unitriangular:

// ... Resizing and initialization
B = declunilow( A );
decltype(auto) declunilow(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as unilower.
Definition: DMatDeclUniLowExpr.h:1004

Any matrix or matrix expression that has been declared as lower unitriangular via declunilow() will gain all the benefits of a lower unitriangular matrix, which range from reduced runtime checking to a considerable speed-up in computations:

DynamicMatrix<double> A, B, C;
UniLowerMatrix< DynamicMatrix<double> > L;
// ... Resizing and initialization
isUniLower( declunilow( A ) ); // Will always return true without runtime effort
L = declunilow( A ); // Omit any runtime check for A being an unilower matrix
C = declunilow( A * B ); // Declare the result of the matrix multiplication as lower
// unitriangular, i.e. perform an optimized matrix multiplication
Matrix adapter for lower unitriangular matrices.
Definition: BaseTemplate.h:582
Warning
The declunilow() operation has the semantics of a cast: The caller is completely responsible and the system trusts the given information. Declaring a non-unilower matrix or matrix expression as lower unitriangular via the declunilow() operation leads to undefined behavior (which can be violated invariants or wrong computation results)!


declstrlow()

The declstrlow() operation can be used to explicitly declare any matrix or matrix expression as strictly lower triangular:

// ... Resizing and initialization
B = declstrlow( A );
decltype(auto) declstrlow(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as strictly lower.
Definition: DMatDeclStrLowExpr.h:1003

Any matrix or matrix expression that has been declared as strictly lower triangular via declstrlow() will gain all the benefits of a strictly lower triangular matrix, which range from reduced runtime checking to a considerable speed-up in computations:

DynamicMatrix<double> A, B, C;
StrictlyLowerMatrix< DynamicMatrix<double> > L;
// ... Resizing and initialization
isStrictlyLower( declstrlow( A ) ); // Will always return true without runtime effort
L = declstrlow( A ); // Omit any runtime check for A being a strictly lower matrix
C = declstrlow( A * B ); // Declare the result of the matrix multiplication as strictly lower
// triangular, i.e. perform an optimized matrix multiplication
Warning
The declstrlow() operation has the semantics of a cast: The caller is completely responsible and the system trusts the given information. Declaring a non-strictly-lower matrix or matrix expression as strictly lower triangular via the declstrlow() operation leads to undefined behavior (which can be violated invariants or wrong computation results)!


declupp()

The declupp() operation can be used to explicitly declare any matrix or matrix expression as upper triangular:

// ... Resizing and initialization
B = declupp( A );
decltype(auto) declupp(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as upper.
Definition: DMatDeclUppExpr.h:1004

Any matrix or matrix expression that has been declared as upper triangular via declupp() will gain all the benefits of an upper triangular matrix, which range from reduced runtime checking to a considerable speed-up in computations:

DynamicMatrix<double> A, B, C;
UpperMatrix< DynamicMatrix<double> > U;
// ... Resizing and initialization
isUpper( declupp( A ) ); // Will always return true without runtime effort
U = declupp( A ); // Omit any runtime check for A being an upper matrix
C = declupp( A * B ); // Declare the result of the matrix multiplication as upper triangular,
// i.e. perform an optimized matrix multiplication
Matrix adapter for upper triangular matrices.
Definition: BaseTemplate.h:558
Warning
The declupp() operation has the semantics of a cast: The caller is completely responsible and the system trusts the given information. Declaring a non-upper matrix or matrix expression as upper triangular via the declupp() operation leads to undefined behavior (which can be violated invariants or wrong computation results)!


decluniupp()

The decluniupp() operation can be used to explicitly declare any matrix or matrix expression as upper unitriangular:

// ... Resizing and initialization
B = decluniupp( A );
decltype(auto) decluniupp(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as uniupper.
Definition: DMatDeclUniUppExpr.h:1005

Any matrix or matrix expression that has been declared as upper unitriangular via decluniupp() will gain all the benefits of a upper unitriangular matrix, which range from reduced runtime checking to a considerable speed-up in computations:

DynamicMatrix<double> A, B, C;
UniUpperMatrix< DynamicMatrix<double> > L;
// ... Resizing and initialization
isUniUpper( decluniupp( A ) ); // Will always return true without runtime effort
L = decluniupp( A ); // Omit any runtime check for A being an uniupper matrix
C = decluniupp( A * B ); // Declare the result of the matrix multiplication as upper
// unitriangular, i.e. perform an optimized matrix multiplication
Matrix adapter for upper unitriangular matrices.
Definition: BaseTemplate.h:581
Warning
The decluniupp() operation has the semantics of a cast: The caller is completely responsible and the system trusts the given information. Declaring a non-uniupper matrix or matrix expression as upper unitriangular via the decluniupp() operation leads to undefined behavior (which can be violated invariants or wrong computation results)!


declstrupp()

The declstrupp() operation can be used to explicitly declare any matrix or matrix expression as strictly upper triangular:

// ... Resizing and initialization
B = declstrupp( A );
decltype(auto) declstrupp(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as strictly upper.
Definition: DMatDeclStrUppExpr.h:1003

Any matrix or matrix expression that has been declared as strictly upper triangular via declstrupp() will gain all the benefits of a strictly upper triangular matrix, which range from reduced runtime checking to a considerable speed-up in computations:

DynamicMatrix<double> A, B, C;
StrictlyUpperMatrix< DynamicMatrix<double> > L;
// ... Resizing and initialization
isStrictlyUpper( declstrupp( A ) ); // Will always return true without runtime effort
L = declstrupp( A ); // Omit any runtime check for A being a strictly upper matrix
C = declstrupp( A * B ); // Declare the result of the matrix multiplication as strictly upper
// triangular, i.e. perform an optimized matrix multiplication
Matrix adapter for strictly upper triangular matrices.
Definition: BaseTemplate.h:563
Warning
The declstrupp() operation has the semantics of a cast: The caller is completely responsible and the system trusts the given information. Declaring a non-strictly-upper matrix or matrix expression as strictly upper triangular via the declstrupp() operation leads to undefined behavior (which can be violated invariants or wrong computation results)!


decldiag()

The decldiag() operation can be used to explicitly declare any matrix or matrix expression as diagonal:

// ... Resizing and initialization
B = decldiag( A );
decltype(auto) decldiag(const DenseMatrix< MT, SO > &dm)
Declares the given dense matrix expression dm as diagonal.
Definition: DMatDeclDiagExpr.h:978

Any matrix or matrix expression that has been declared as diagonal via decldiag() will gain all the benefits of a diagonal matrix, which range from reduced runtime checking to a considerable speed-up in computations:

DynamicMatrix<double> A, B, C;
DiagonalMatrix< DynamicMatrix<double> > D;
// ... Resizing and initialization
isDiagonal( decldiag( A ) ); // Will always return true without runtime effort
D = decldiag( A ); // Omit any runtime check for A being a diagonal matrix
C = decldiag( A * B ); // Declare the result of the matrix multiplication as diagonal,
// i.e. perform an optimized matrix multiplication
Matrix adapter for diagonal matrices.
Definition: BaseTemplate.h:565
Warning
The decldiag() operation has the semantics of a cast: The caller is completely responsible and the system trusts the given information. Declaring a non-diagonal matrix or matrix expression as diagonal via the decldiag() operation leads to undefined behavior (which can be violated invariants or wrong computation results)!


declid()

The declid() operation can be used to explicitly declare any matrix or matrix expression as identity matrix:

// ... Resizing and initialization
B = declid( A );
IdentityMatrix< ElementType_t< MT >, SO > declid(const Matrix< MT, SO > &m)
Declares the given matrix expression m as identity matrix.
Definition: IdentityMatrix.h:1285

Any matrix or matrix expression that has been declared as identity matrix via declid() will gain all the benefits of an identity matrix, which range from reduced runtime checking to a considerable speed-up in computations:

DynamicMatrix<double> A, B, C;
DiagonalMatrix< DynamicMatrix<double> > D;
// ... Resizing and initialization
isIdentity( declid( A ) ); // Will always return true without runtime effort
D = declid( A ); // Omit any runtime check for A being a diagonal matrix
C = declid( A ) * B; // Declare the left operand of the matrix multiplication as an
// identity matrix, i.e. perform an optimized matrix multiplication
Warning
The declid() operation has the semantics of a cast: The caller is completely responsible and the system trusts the given information. Declaring a non-identity matrix or matrix expression as identity matrix via the declid() operation leads to undefined behavior (which can be violated invariants or wrong computation results)!


declzero()

The declzero() operation can be used to explicitly declare any matrix or matrix expression as zero matrix:

// ... Resizing and initialization
B = declzero( A );
ZeroMatrix< ElementType_t< MT >, SO > declzero(const Matrix< MT, SO > &m)
Declares the given matrix expression m as zero matrix.
Definition: ZeroMatrix.h:1382

Any matrix or matrix expression that has been declared as zero matrix via declzero() will gain all the benefits of a zero matrix, which range from reduced runtime checking to a considerable speed-up in computations:

DynamicMatrix<double> A, B, C;
// ... Resizing and initialization
isZero( declzero( A ) ); // Will always return true without runtime effort
C = declzero( A ) + B; // Declare the left operand of the matrix addition as a
// zero matrix, i.e. no addition needs to be performed
Warning
The declzero() operation has the semantics of a cast: The caller is completely responsible and the system trusts the given information. Declaring a non-zero matrix or matrix expression as zero matrix via the declzero() operation leads to undefined behavior (which can be violated invariants or wrong computation results)!


Matrix Generators


generate()

The generate() function returns a dense matrix filled elementwise via the given custom binary operation. By default, the returned matrix is a row-major matrix, but this setting can be changed via the BLAZE_DEFAULT_STORAGE_ORDER switch (see Default Matrix Storage). Alternatively it is possible to specify the storage order explicitly.
The following example demonstrates the use of the generate() function:

// Generates the uniform integer matrix ( ( 2, 2, 2 ), ( 2, 2, 2 ) )
A = generate( 2UL, 3UL, []( size_t i, size_t j ){ return 2; } );
// Generates the linearly spaced float matrix ( ( 2.1, 3.2, 4.3 ), ( 5.4, 6.5, 7.6 ) )
B = generate( 2UL, 3UL, []( size_t i, size_t j ){ return 2.1F + 1.1F*(i*3UL+j); } );
// Generates the logarithmically spaced double vector ( ( 1.0, 10.0 ), ( 100.0, 1000.0 ) )
C = generate<rowMajor>( 2UL, 2UL, []( size_t i, size_t j ) { return blaze::exp10( 1.0 + 1.0*(i*2UL+j) ); } );
// Generates the vector of integer vectors ( ( 1, 2 ), ( 2, 3 ), ( 3, 4 ), ( 4, 5 ) )
using VT = StaticVector<int,2UL>;
D = generate<columnMajor>( 2UL, 2UL, []( size_t i, size_t j ) { return evaluate( VT{ 1, 2 } + (i*2UL+j) ); } );
decltype(auto) generate(size_t m, size_t n, OP op)
Generates a new dense matrix filled via the given custom binary operation.
Definition: DMatGenExpr.h:675


uniform()

The uniform() function creates a uniform matrix of the given size. By default, the resulting uniform matrix is a row-major matrix, but this setting can be changed via the BLAZE_DEFAULT_STORAGE_ORDER switch (see Default Matrix Storage). Alternatively it is possible to specify the storage order explicitly.
The following example demonstrates the use of the uniform() function:

// Creates the uniform row-major matrix
// ( 1, 1, 1, 1, 1 )
// ( 1, 1, 1, 1, 1 )
auto U1 = uniform( 2UL, 5UL, 1 );
// Creates the uniform row-major matrix
// ( 1.2, 1.2 )
// ( 1.2, 1.2 )
// ( 1.2, 1.2 )
auto U2 = uniform<rowMajor>( 3UL, 2UL, 1.2 );
// Creates the uniform column-major matrix
// ( 5U, 5U, 5U, 5U, 5U, 5U, 5U )
// ( 5U, 5U, 5U, 5U, 5U, 5U, 5U )
auto U3 = uniform<columnMajor>( 2UL, 7UL, 5U );


zero()

The zero() function creates a zero matrix of the given element type and size. By default, the resulting zero matrix is a row-major matrix, but this setting can be changed via the BLAZE_DEFAULT_STORAGE_ORDER switch (see Default Matrix Storage). Alternatively it is possible to specify the storage order explicitly.
The following example demonstrates the use of the zero() function:

// Creates the row-major zero matrix
// ( 0, 0, 0, 0, 0 )
// ( 0, 0, 0, 0, 0 )
auto Z1 = zero<int>( 2UL, 5UL );
// Creates the row-major zero matrix
// ( 0.0, 0.0 )
// ( 0.0, 0.0 )
// ( 0.0, 0.0 )
auto Z2 = zero<double,rowMajor>( 3UL, 2UL );
// Creates the column-major zero matrix
// ( 0U, 0U, 0U, 0U, 0U, 0U, 0U )
// ( 0U, 0U, 0U, 0U, 0U, 0U, 0U )
auto Z3 = zero<unsigned int,columnMajor>( 2UL, 7UL );
constexpr decltype(auto) zero(size_t m, size_t n) noexcept
Creating a zero matrix.
Definition: ZeroMatrix.h:1356


Matrix Inversion


The inverse of a square dense matrix can be computed via the inv() function:

// ... Resizing and initialization
B = inv( A ); // Compute the inverse of A
decltype(auto) inv(const DenseMatrix< MT, SO > &dm)
Calculation of the inverse of the given dense matrix.
Definition: DMatInvExpr.h:405

Alternatively, an in-place inversion of a dense matrix can be performed via the invert() function:

// ... Resizing and initialization
invert( A ); // In-place matrix inversion
void invert(const HermitianProxy< MT > &proxy)
In-place inversion of the represented element.
Definition: HermitianProxy.h:693

Both the inv() and the invert() functions will automatically select the most suited matrix inversion algorithm depending on the size and type of the given matrix. For small matrices of up to 6x6, both functions use manually optimized kernels for maximum performance. For matrices larger than 6x6 the inversion is performed by means of the most suited matrix decomposition method: In case of a general matrix the LU decomposition is used, for symmetric matrices the LDLT decomposition is applied, for Hermitian matrices the LDLH decomposition is performed, and for triangular matrices the inverse is computed via a forward or back substitution.

In case the type of the matrix does not provide additional compile time information about its structure (symmetric, lower, upper, diagonal, ...), the information can be provided manually by means of Declaration Operations when calling the invert() function:

invert( declsym( A ) ); // In-place inversion of a symmetric matrix
invert( declherm( A ) ); // In-place inversion of an Hermitian matrix
invert( decllow( A ) ); // In-place inversion of a lower triangular matrix
invert( declunilow( A ) ); // In-place inversion of a lower unitriangular matrix
invert( declupp( A ) ); // In-place inversion of an upper triangular matrix
invert( decluniupp( A ) ); // In-place inversion of an upper unitriangular matrix
invert( decldiag( A ) ); // In-place inversion of a diagonal matrix

Alternatively, via the invert() function it is possible to explicitly specify the inversion algorithm:

// In-place inversion of a general matrix by means of an LU decomposition
invert<byLU>( A );
// In-place inversion of a symmetric indefinite matrix by means of a Bunch-Kaufman decomposition
invert<byLDLT>( A );
// In-place inversion of an Hermitian indefinite matrix by means of a Bunch-Kaufman decomposition
invert<byLDLH>( A );
// In-place inversion of a positive definite matrix by means of a Cholesky decomposition
invert<byLLH>( A );
@ byLDLT
Flag for the Bunch-Kaufman-based inversion for symmetric matrices.
Definition: InversionFlag.h:104
@ byLDLH
Flag for the Bunch-Kaufman-based inversion for Hermitian matrices.
Definition: InversionFlag.h:105
@ byLU
Flag for the LU-based matrix inversion.
Definition: InversionFlag.h:103
@ byLLH
Flag for the Cholesky-based inversion for positive-definite matrices.
Definition: InversionFlag.h:106

Whereas the inversion by means of an LU decomposition works for every general square matrix, the inversion by LDLT only works for symmetric indefinite matrices, the inversion by LDLH is restricted to Hermitian indefinite matrices and the Cholesky decomposition (LLH) only works for Hermitian positive definite matrices. Please note that it is in the responsibility of the function caller to guarantee that the selected algorithm is suited for the given matrix. In case this precondition is violated the result can be wrong and might not represent the inverse of the given matrix!

For both the inv() and invert() function the matrix inversion fails if ...

  • ... the given matrix is not a square matrix;
  • ... the given matrix is singular and not invertible.

In all failure cases either a compilation error is created if the failure can be predicted at compile time or a std::invalid_argument exception is thrown.

Note
The matrix inversion can only be used for dense matrices with float, double, complex<float> or complex<double> element type. The attempt to call the function with matrices of any other element type or with a sparse matrix results in a compile time error!
The functions invert the dense matrix by means of LAPACK kernels. Thus the functions can only be used if a fitting LAPACK library is available and linked to the executable. Otherwise a linker error will be created.
It is not possible to use any kind of view on the expression object returned by the inv() function. Also, it is not possible to access individual elements via the function call operator on the expression object:
row( inv( A ), 2UL ); // Compilation error: Views cannot be used on an inv() expression!
inv( A )(1,2); // Compilation error: It is not possible to access individual elements!
Note
The inversion functions do not provide any exception safety guarantee, i.e. in case an exception is thrown the matrix may already have been modified.


Matrix Exponential


The matrix exponential of a $N \times N$ matrix $ X $ is defined as

              \f[ e^X = \sum\limits_{k=0}^\infty \frac{1}{k!} X^k. \f]

In order to compute the matrix exponential of a square dense matrix, the matexp() function can be used:

// ... Resizing and initialization
B = matexp( A ); // Compute the exponential of A
decltype(auto) matexp(const DenseMatrix< MT, SO > &dm)
Calculation of the exponential of the given dense matrix.
Definition: DMatExpExpr.h:564
Note
The matrix exponential can only be used for dense matrices with float, double, complex<float> or complex<double> element type. The attempt to call the function with matrices of any other element type results in a compile time error!
It is not possible to use any kind of view on the expression object returned by the matexp() function. Also, it is not possible to access individual elements via the function call operator on the expression object:
row( matexp( A ), 2UL ); // Compilation error: Views cannot be used on an matexp() expression!
matexp( A )(1,2); // Compilation error: It is not possible to access individual elements!


Matrix Decomposition


Note
All decomposition functions can only be used for dense matrices with float, double, complex<float> or complex<double> element type. The attempt to call the function with matrices of any other element type or with a sparse matrix results in a compile time error!
The functions decompose a dense matrix by means of LAPACK kernels. Thus the functions can only be used if a fitting LAPACK library is available and linked to the executable. Otherwise a linker error will be created.

LU Decomposition

The LU decomposition of a dense matrix can be computed via the lu() function:

// ... Resizing and initialization
lu( A, L, U, P ); // LU decomposition of a row-major matrix
assert( A == L * U * P );
void lu(const DenseMatrix< MT1, SO1 > &A, DenseMatrix< MT2, SO1 > &L, DenseMatrix< MT3, SO1 > &U, Matrix< MT4, SO2 > &P)
LU decomposition of the given dense matrix.
Definition: LU.h:222
// ... Resizing and initialization
lu( A, L, U, P ); // LU decomposition of a column-major matrix
assert( A == P * L * U );

The function works for both rowMajor and columnMajor matrices. Note, however, that the three matrices A, L and U are required to have the same storage order. Also, please note that the way the permutation matrix P needs to be applied differs between row-major and column-major matrices, since the algorithm uses column interchanges for row-major matrices and row interchanges for column-major matrices.

Furthermore, lu() can be used with adaptors. For instance, the following example demonstrates the LU decomposition of a symmetric matrix into a lower and upper triangular matrix:


Cholesky Decomposition

The Cholesky (LLH) decomposition of a dense matrix can be computed via the llh() function:

// ... Resizing and initialization
llh( A, L ); // LLH decomposition of a row-major matrix
assert( A == L * ctrans( L ) );
void llh(const DenseMatrix< MT1, SO1 > &A, DenseMatrix< MT2, SO2 > &L)
Cholesky (LLH) decomposition of the given dense matrix.
Definition: LLH.h:127

The function works for both rowMajor and columnMajor matrices and the two matrices A and L can have any storage order.

Furthermore, llh() can be used with adaptors. For instance, the following example demonstrates the LLH decomposition of a symmetric matrix into a lower triangular matrix:


QR Decomposition

The QR decomposition of a dense matrix can be computed via the qr() function:

// ... Resizing and initialization
qr( A, Q, R ); // QR decomposition of a row-major matrix
assert( A == Q * R );
void qr(const DenseMatrix< MT1, SO1 > &A, DenseMatrix< MT2, SO2 > &Q, DenseMatrix< MT3, SO3 > &R)
QR decomposition of the given dense matrix.
Definition: QR.h:179

The function works for both rowMajor and columnMajor matrices and the three matrices A, Q and R can have any storage order.

Furthermore, qr() can be used with adaptors. For instance, the following example demonstrates the QR decomposition of a symmetric matrix into a general matrix and an upper triangular matrix:


RQ Decomposition

Similar to the QR decomposition, the RQ decomposition of a dense matrix can be computed via the rq() function:

// ... Resizing and initialization
rq( A, R, Q ); // RQ decomposition of a row-major matrix
assert( A == R * Q );
void rq(const DenseMatrix< MT1, SO1 > &A, DenseMatrix< MT2, SO2 > &R, DenseMatrix< MT3, SO3 > &Q)
RQ decomposition of the given dense matrix.
Definition: RQ.h:180

The function works for both rowMajor and columnMajor matrices and the three matrices A, R and Q can have any storage order.

Also the rq() function can be used in combination with matrix adaptors. For instance, the following example demonstrates the RQ decomposition of an Hermitian matrix into a general matrix and an upper triangular matrix:


QL Decomposition

The QL decomposition of a dense matrix can be computed via the ql() function:

// ... Resizing and initialization
ql( A, Q, L ); // QL decomposition of a row-major matrix
assert( A == Q * L );
void ql(const DenseMatrix< MT1, SO1 > &A, DenseMatrix< MT2, SO2 > &Q, DenseMatrix< MT3, SO3 > &L)
QL decomposition of the given dense matrix.
Definition: QL.h:179

The function works for both rowMajor and columnMajor matrices and the three matrices A, Q and L can have any storage order.

Also the ql() function can be used in combination with matrix adaptors. For instance, the following example demonstrates the QL decomposition of a symmetric matrix into a general matrix and a lower triangular matrix:


LQ Decomposition

The LQ decomposition of a dense matrix can be computed via the lq() function:

// ... Resizing and initialization
lq( A, L, Q ); // LQ decomposition of a row-major matrix
assert( A == L * Q );
void lq(const DenseMatrix< MT1, SO1 > &A, DenseMatrix< MT2, SO2 > &Q, DenseMatrix< MT3, SO3 > &R)
LQ decomposition of the given dense matrix.
Definition: LQ.h:179

The function works for both rowMajor and columnMajor matrices and the three matrices A, L and Q can have any storage order.

Furthermore, lq() can be used with adaptors. For instance, the following example demonstrates the LQ decomposition of an Hermitian matrix into a lower triangular matrix and a general matrix:


Linear Systems


The solve() function computes a solution for the given dense linear system of equations (LSE) $ A*x=b $, where A is the given system matrix, x is the solution vector, and b is the given dense right-hand side vector:

blaze::DynamicMatrix<double> A; // The square general system matrix
blaze::DynamicVector<double> b; // The right-hand side vector
// ... Resizing and initialization
blaze::DynamicVector<double> x; // The solution vector
solve( A, x, b ); // Computing the solution x
x = solve( A, b ); // Alternative syntax
void solve(const DenseMatrix< MT, SO > &A, DenseVector< VT1, TF1 > &x, const DenseVector< VT2, TF2 > &b)
Solving the given linear system of equations ( ).
Definition: LSE.h:6343

Alternatively, solve() computes a solution for the given dense LSE $ A*X=B $, where A is the given dense system matrix, the columns of X are the solution vectors, and the columns of B are the given right-hand side vectors:

blaze::DynamicMatrix<double> A; // The square general system matrix
blaze::DynamicMatrix<double> B; // The right-hand side matrix
// ... Resizing and initialization
blaze::DynamicMatrix<double> X; // The solution matrix
solve( A, X, B ); // Computing the solutions X
X = solve( A, B ); // Alternative syntax

Both solve() functions will automatically select the most suited direct solver algorithm depending on the size and type of the given system matrix. For small matrices of up to 6x6, both functions use manually optimized kernels for maximum performance. For matrices larger than 6x6 the computation is performed by means of the most suited LAPACK solver method (see Linear System Solver).

In case the type of the matrix does not provide additional compile time information about its structure (symmetric, lower, upper, diagonal, ...), the information can be provided manually by means of Declaration Operations when calling the solve() functions:

blaze::DynamicMatrix<double> A; // The square lower system matrix
blaze::DynamicVector<double> b; // The right-hand side vector
// ... Resizing and initialization
blaze::DynamicVector<double> x; // The solution vector
solve( declsym( A ), x, b ); // Solving the LSE with a symmetric system matrix
solve( declherm( A ), x, b ); // Solving the LSE with an Hermitian system matrix
solve( decllow( A ), x, b ); // Solving the LSE with a lower system matrix
solve( declunilow( A ), x, b ); // Solving the LSE with an unilower system matrix
solve( declupp( A ), x, b ); // Solving the LSE with an upper system matrix
solve( decluniupp( A ), x, b ); // Solving the LSE with an uniupper system matrix
solve( decldiag( A ), x, b ); // Solving the LSE with a diagonal system matrix

For both solve() functions the computation fails if ...

  • ... the given matrix is not a square matrix;
  • ... the size of the right-hand side vector doesn't match the dimensions of the system matrix;
  • ... the number of rows of the right-hand side matrix doesn't match the dimensions of the system matrix;
  • ... the given matrix is singular and not invertible.

In all failure cases either a compilation error is created if the failure can be predicted at compile time or a std::invalid_argument exception is thrown.

Note
The solve() functions can only be used for dense matrices with float, double, complex<float> or complex<double> element type. The attempt to call the function with matrices of any other element type or with a sparse matrix results in a compile time error!
The functions may make use of LAPACK kernels. Thus the functions can only be used if a fitting LAPACK library is available and linked to the executable. Otherwise a linker error will be created.
It is not possible to use any kind of view on the expression object returned by the two-argument solve() function. Also, it is not possible to access individual elements via the function call operator on the expression object:
row( solve( A, b ), 2UL ); // Compilation error: Views cannot be used on an solve() expression!
solve( A, b )[2]; // Compilation error: It is not possible to access individual elements!
rows( solve( A, B ), { 2UL, 4UL } ); // Compilation error: Views cannot be used on an solve() expression!
solve( A, B )(1,2); // Compilation error: It is not possible to access individual elements!
Note
The solve() functions do not provide any exception safety guarantee, i.e. in case an exception is thrown the solution vector or matrix may already have been modified.


Eigenvalues/Eigenvectors


The eigenvalues and eigenvectors of a dense matrix can be computed via the eigen() functions. The following examples give an impression of the computation of eigenvalues and eigenvectors for a general, a symmetric, and an Hermitian matrix:

DynamicMatrix<double,rowMajor> A( 5UL, 5UL ); // The general matrix A
// ... Initialization
DynamicVector<complex<double>,columnVector> w( 5UL ); // The vector for the complex eigenvalues
DynamicMatrix<complex<double>,rowMajor> V( 5UL, 5UL ); // The matrix for the left eigenvectors
w = eigen( A ); // Computing only the eigenvalues of A (one argument)
eigen( A, w ); // Computing only the eigenvalues of A (two arguments)
eigen( A, w, V ); // Computing both the eigenvalues and eigenvectors of A (three arguments)
void eigen(const DenseMatrix< MT, SO > &A, DenseVector< VT, TF > &w)
Eigenvalue computation of the given dense matrix.
Definition: Eigen.h:351
SymmetricMatrix< DynamicMatrix<double,rowMajor> > A( 5UL ); // The symmetric matrix A
// ... Initialization
DynamicVector<double,columnVector> w( 5UL ); // The vector for the real eigenvalues
DynamicMatrix<double,rowMajor> V( 5UL, 5UL ); // The matrix for the left eigenvectors
w = eigen( A ); // Computing only the eigenvalues of A (one argument)
eigen( A, w ); // Computing only the eigenvalues of A (two arguments)
eigen( A, w, V ); // Computing both the eigenvalues and eigenvectors of A (three arguments)
HermitianMatrix< DynamicMatrix<complex<double>,rowMajor> > A( 5UL ); // The Hermitian matrix A
// ... Initialization
DynamicVector<double,columnVector> w( 5UL ); // The vector for the real eigenvalues
DynamicMatrix<complex<double>,rowMajor> V( 5UL, 5UL ); // The matrix for the left eigenvectors
w = eigen( A ); // Computing only the eigenvalues of A (one argument)
eigen( A, w ); // Computing only the eigenvalues of A (two arguments)
eigen( A, w, V ); // Computing both the eigenvalues and eigenvectors of A (three arguments)

The one- and two-argument functions compute only the eigenvalues of the given n-by-n matrix, the three-argument function additionally computes the eigenvectors. The eigenvalues are returned in the given vector w and the eigenvectors are returned in the given matrix V, which are both resized to the correct dimensions (if possible and necessary).

Depending on the given matrix type, the resulting eigenvalues are either of floating point or complex type: In case the given matrix is either a compile time symmetric matrix with floating point elements or an Hermitian matrix with complex elements, the resulting eigenvalues will be of floating point type and therefore the elements of the given eigenvalue vector are expected to be of floating point type. In all other cases they are expected to be of complex type. Please note that for complex eigenvalues no order of eigenvalues can be assumed, except that complex conjugate pairs of eigenvalues appear consecutively with the eigenvalue having the positive imaginary part first.

In case A is a row-major matrix, V will contain the left eigenvectors, otherwise V will contain the right eigenvectors. In case V is a row-major matrix the eigenvectors are returned in the rows of V, in case V is a column-major matrix the eigenvectors are returned in the columns of V. In case the given matrix is a compile time symmetric matrix with floating point elements, the resulting eigenvectors will be of floating point type and therefore the elements of the given eigenvector matrix are expected to be of floating point type. In all other cases they are expected to be of complex type.

The functions fail if ...

  • ... the given matrix A is not a square matrix;
  • ... the given vector w is a fixed size vector and the size doesn't match;
  • ... the given matrix V is a fixed size matrix and the dimensions don't match;
  • ... the eigenvalue computation fails.

In all failure cases an exception is thrown.

Note
All eigen() functions can only be used for dense matrices with float, double, complex<float> or complex<double> element type. The attempt to call the function with matrices of any other element type or with a sparse matrix results in a compile time error!
The functions compute the eigenvalues and/or eigenvectors of a dense matrix by means of LAPACK kernels. Thus the functions can only be used if a fitting LAPACK library is available and linked to the executable. Otherwise a linker error will be created.


Singular Values/Singular Vectors


The singular value decomposition (SVD) of a dense matrix can be computed via the svd() functions. The following two examples give an impression of the computation of singular values and singular vectors for a general dense matrix with double and complex<double> element type, respectively:

DynamicMatrix<double,rowMajor> A( 5UL, 8UL ); // The general matrix A
// ... Initialization
DynamicMatrix<double,rowMajor> U; // The matrix for the left singular vectors
DynamicVector<double,columnVector> s; // The vector for the singular values
DynamicMatrix<double,rowMajor> V; // The matrix for the right singular vectors
s = svd( A ); // (1) Computing only the singular values of A
svd( A, s ); // (2) Computing only the singular values of A
svd( A, U, s, V ); // (3) Computing the singular values and vectors of A
svd( A, s, 0.0, 1.0 ); // (4) Computing all singular values in the floating point range [0.0..1.0)
svd( A, U, s, V, 0, 2 ); // (5) Computing the singular values and vectors in the index range [0..2]
void svd(const DenseMatrix< MT, SO > &A, DenseVector< VT, TF > &s)
Singular value decomposition (SVD) of the given dense general matrix.
Definition: SVD.h:135
DynamicMatrix<complex<double>,rowMajor> A( 5UL, 8UL ); // The general matrix A
// ... Initialization
DynamicMatrix<complex<double>,rowMajor> U; // The matrix for the left singular vectors
DynamicVector<double,columnVector> s; // The vector for the singular values
DynamicMatrix<complex<double>,rowMajor> V; // The matrix for the right singular vectors
s = svd( A ); // (1) Computing only the singular values of A
svd( A, s ); // (2) Computing only the singular values of A
svd( A, U, s, V ); // (3) Computing the singular values and vectors of A
svd( A, s, 0.0, 1.0 ); // (4) Computing all singular values in the floating point range [0.0..1.0)
svd( A, U, s, V, 0, 2 ); // (5) Computing the singular values and vectors in the index range [0..2]

Functions (1), (2) and (4) compute only singular values of the given general m-by-n matrix, functions (3) and (5) additionally compute singular vectors. The resulting singular values are returned in the given vector s, the left singular vectors are returned in the given matrix U, and the right singular vectors are returned in the matrix V. s, U, and V are resized to the correct dimensions (if possible and necessary).

Functions (4) and (5) allow for the specification of a subset of singular values and/or vectors. The number of singular values and vectors to be computed is specified by the lower bound low and the upper bound upp, which either form an integral or a floating point range.

In case low and upp form are of integral type, the function computes all singular values in the index range $[low..upp]$. The num resulting real and non-negative singular values are stored in descending order in the given vector s, which is either resized (if possible) or expected to be a num-dimensional vector. The resulting left singular vectors are stored in the given matrix U, which is either resized (if possible) or expected to be a m-by-num matrix. The resulting right singular vectors are stored in the given matrix V, which is either resized (if possible) or expected to be a num-by-n matrix.

In case low and upp are of floating point type, the function computes all singular values in the half-open interval $(low..upp]$. The resulting real and non-negative singular values are stored in descending order in the given vector s, which is either resized (if possible) or expected to be a min(m,n)-dimensional vector. The resulting left singular vectors are stored in the given matrix U, which is either resized (if possible) or expected to be a m-by-min(m,n) matrix. The resulting right singular vectors are stored in the given matrix V, which is either resized (if possible) or expected to be a min(m,n)-by-n matrix.

The functions fail if ...

  • ... the given matrix U is a fixed size matrix and the dimensions don't match;
  • ... the given vector s is a fixed size vector and the size doesn't match;
  • ... the given matrix V is a fixed size matrix and the dimensions don't match;
  • ... the given scalar values don't form a proper range;
  • ... the singular value decomposition fails.

In all failure cases an exception is thrown.

Note
All svd() functions can only be used for dense matrices with float, double, complex<float> or complex<double> element type. The attempt to call the function with matrices of any other element type or with a sparse matrix results in a compile time error!
The functions compute the singular values and/or singular vectors of a dense matrix by means of LAPACK kernels. Thus the functions can only be used if a fitting LAPACK library is available and linked to the executable. Otherwise a linker error will be created.


Previous: Matrix Types     Next: Adaptors