Rows

Table of Contents

Rows provide views on a specific row of a dense or sparse matrix. As such, rows act as a reference to a specific row. This reference is valid and can be used in every way any other row vector can be used as long as the matrix containing the row is not resized or entirely destroyed. The row also acts as an alias to the row elements: Changes made to the elements (e.g. modifying values, inserting or erasing elements) are immediately visible in the matrix and changes made via the matrix are immediately visible in the row.


The Row Class Template


The blaze::Row class template represents a reference to a specific row of a dense or sparse matrix primitive. It can be included via the header file

#include <blaze/math/Row.h>

The type of the matrix is specified via template parameter:

template< typename MT >
class Row;

MT specifies the type of the matrix primitive. Row can be used with every matrix primitive, but does not work with any matrix expression type.


Setup of Rows


A reference to a dense or sparse row can be created very conveniently via the row() function. This reference can be treated as any other row vector, i.e. it can be assigned to, it can be copied from, and it can be used in arithmetic operations. The reference can also be used on both sides of an assignment: The row can either be used as an alias to grant write access to a specific row of a matrix primitive on the left-hand side of an assignment or to grant read-access to a specific row of a matrix primitive or expression on the right-hand side of an assignment. The following two examples demonstrate this for dense and sparse matrices:

typedef blaze::DynamicMatrix<double,rowMajor> DenseMatrixType;
DenseVectorType x;
SparseVectorType y;
DenseMatrixType A, B;
SparseMatrixType C, D;
// ... Resizing and initialization
// Setting the 2nd row of matrix A to x
row2 = x;
// Setting the 3rd row of matrix B to y
row( B, 3UL ) = y;
// Setting x to the 4th row of the result of the matrix multiplication
x = row( A * B, 4UL );
// Setting y to the 2nd row of the result of the sparse matrix multiplication
y = row( C * D, 2UL );

The row() function can be used on any dense or sparse matrix, including expressions, as illustrated by the source code example. However, rows cannot be instantiated for expression types, but only for matrix primitives, respectively, i.e. for matrix types that offer write access.


Common Operations


A row view can be used like any other row vector. For instance, the current number of elements can be obtained via the size() function, the current capacity via the capacity() function, and the number of non-zero elements via the nonZeros() function. However, since rows are references to specific rows of a matrix, several operations are not possible on views, such as resizing and swapping. The following example shows this by means of a dense row view:

typedef blaze::Row<MatrixType> RowType;
MatrixType A( 42UL, 42UL );
// ... Resizing and initialization
// Creating a reference to the 2nd row of matrix A
RowType row2 = row( A, 2UL );
row2.size(); // Returns the number of elements in the row
row2.capacity(); // Returns the capacity of the row
row2.nonZeros(); // Returns the number of non-zero elements contained in the row
row2.resize( 84UL ); // Compilation error: Cannot resize a single row of a matrix
RowType row3 = row( A, 3UL );
swap( row2, row3 ); // Compilation error: Swap operation not allowed


Element Access


The elements of the row can be directly accessed with the subscript operator. The numbering of the row elements is

\[\left(\begin{array}{*{5}{c}} 0 & 1 & 2 & \cdots & N-1 \\ \end{array}\right),\]

where N is the number of columns of the referenced matrix. Alternatively, the elements of a row can be traversed via iterators. Just as with vectors, in case of non-const rows, begin() and end() return an Iterator, which allows a manipulation of the non-zero value, in case of a constant row a ConstIterator is returned:

typedef blaze::Row<MatrixType> RowType;
MatrixType A( 128UL, 256UL );
// ... Resizing and initialization
// Creating a reference to the 31st row of matrix A
RowType row31 = row( A, 31UL );
for( RowType::Iterator it=row31.begin(); it!=row31.end(); ++it ) {
*it = ...; // OK; Write access to the dense row value
... = *it; // OK: Read access to the dense row value.
}
for( RowType::ConstIterator it=row31.begin(); it!=row31.end(); ++it ) {
*it = ...; // Compilation error: Assignment to the value via a ConstIterator is invalid.
... = *it; // OK: Read access to the dense row value.
}
typedef blaze::Row<MatrixType> RowType;
MatrixType A( 128UL, 256UL );
// ... Resizing and initialization
// Creating a reference to the 31st row of matrix A
RowType row31 = row( A, 31UL );
for( RowType::Iterator it=row31.begin(); it!=row31.end(); ++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 sparse element.
}
for( RowType::Iterator it=row31.begin(); it!=row31.end(); ++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 sparse element.
}


Element Insertion


Inserting/accessing elements in a sparse row can be done by several alternative functions. The following example demonstrates all options:

MatrixType A( 10UL, 100UL ); // Non-initialized 10x100 matrix
typedef blaze::Row<MatrixType> RowType;
RowType row0( row( A, 0UL ) ); // Reference to the 0th row of A
// The subscript operator provides access to all possible elements of the sparse row,
// including the zero elements. In case the subscript operator is used to access an element
// that is currently not stored in the sparse row, the element is inserted into the row.
row0[42] = 2.0;
// The second operation for inserting elements is the set() function. In case the element
// is not contained in the row it is inserted into the row, if it is already contained in
// the row its value is modified.
row0.set( 45UL, -1.2 );
// An alternative for inserting elements into the row is the insert() function. However,
// it inserts the element only in case the element is not already contained in the row.
row0.insert( 50UL, 3.7 );
// A very efficient way to add new elements to a sparse row is the append() function.
// Note that append() requires that the appended element's index is strictly larger than
// the currently largest non-zero index of the row and that the row's capacity is large
// enough to hold the new element.
row0.reserve( 10UL );
row0.append( 51UL, -2.1 );


Arithmetic Operations


Both dense and sparse rows can be used in all arithmetic operations that any other dense or sparse row vector can be used in. The following example gives an impression of the use of dense rows within arithmetic operations. All operations (addition, subtraction, multiplication, scaling, ...) can be performed on all possible combinations of dense and sparse rows with fitting element types:

c[1] = 3.0;
DenseMatrix A( 4UL, 2UL ); // Non-initialized 4x2 matrix
typedef blaze::Row<DenseMatrix> RowType;
RowType row0( row( A, 0UL ) ); // Reference to the 0th row of A
row0[0] = 0.0; // Manual initialization of the 0th row of A
row0[1] = 0.0;
row( A, 1UL ) = 1.0; // Homogeneous initialization of the 1st row of A
row( A, 2UL ) = a; // Dense vector initialization of the 2nd row of A
row( A, 3UL ) = c; // Sparse vector initialization of the 3rd row of A
b = row0 + a; // Dense vector/dense vector addition
b = c + row( A, 1UL ); // Sparse vector/dense vector addition
b = row0 * row( A, 2UL ); // Component-wise vector multiplication
row( A, 1UL ) *= 2.0; // In-place scaling of the 1st row
b = row( A, 1UL ) * 2.0; // Scaling of the 1st row
b = 2.0 * row( A, 1UL ); // Scaling of the 1st row
row( A, 2UL ) += a; // Addition assignment
row( A, 2UL ) -= c; // Subtraction assignment
row( A, 2UL ) *= row( A, 0UL ); // Multiplication assignment
double scalar = row( A, 1UL ) * trans( c ); // Scalar/dot/inner product between two vectors
A = trans( c ) * row( A, 1UL ); // Outer product between two vectors


Views on Matrices with Non-Fitting Storage Order


Especially noteworthy is that row views can be created for both row-major and column-major matrices. Whereas the interface of a row-major matrix only allows to traverse a row directly and the interface of a column-major matrix only allows to traverse a column, via views it is possible to traverse a row of a column-major matrix or a column of a row-major matrix. For instance:

typedef blaze::Row<MatrixType> RowType;
MatrixType A( 64UL, 32UL );
// ... Resizing and initialization
// Creating a reference to the 31st row of a column-major matrix A
RowType row1 = row( A, 1UL );
for( RowType::Iterator it=row1.begin(); it!=row1.end(); ++it ) {
// ...
}

However, please note that creating a row view on a matrix stored in a column-major fashion can result in a considerable performance decrease in comparison to a view on a matrix with a fitting storage orientation. This is due to the non-contiguous storage of the matrix elements. Therefore care has to be taken in the choice of the most suitable storage order:

// Setup of two column-major matrices
CompressedMatrix<double,columnMajor> A( 128UL, 128UL );
CompressedMatrix<double,columnMajor> B( 128UL, 128UL );
// ... Resizing and initialization
// The computation of the 15th row of the multiplication between A and B ...
CompressedVector<double,rowVector> x = row( A * B, 15UL );
// ... is essentially the same as the following computation, which multiplies
// the 15th row of the column-major matrix A with B.
CompressedVector<double,rowVector> x = row( A, 15UL ) * B;

Although Blaze performs the resulting vector/matrix multiplication as efficiently as possible using a row-major storage order for matrix A would result in a more efficient evaluation.


Previous: Submatrices     Next: Columns