# Sequential matrices¶

The Matrix<T> class is the building of the library: its purpose is to provide convenient mechanisms for performing basic matrix manipulations, such as setting and querying individual matrix entries, without giving up compatibility with interfaces such as BLAS and LAPACK, which assume column-major storage.

An example of generating an $$m \times n$$ matrix of real double-precision numbers where the $$(i,j)$$ entry is equal to $$i-j$$ would be:

#include "El.hpp"
using namespace El;
...
Matrix<double> A( m, n );
for( Int j=0; j<n; ++j )
for( Int i=0; i<m; ++i )
A.Set( i, j, double(i-j) );


whereas the complex double-precision equivalent could use Complex<double>, which is currently a typedef for std::complex<double>.

The underlying data storage for Matrix<T> is simply a contiguous buffer that stores entries in a column-major fashion with a leading dimension which is only required to be at least as large as the height of the matrix (so that entry $$(i,j)$$ is located at position i+j*ldim). For modifiable instances of the Matrix<T> class, the routine Matrix<T>::Buffer() returns a pointer to the underlying buffer, while Matrix<T>::LDim() returns the leading dimension; these two routines could be used to directly perform the equivalent of the first code sample as follows:

#include "El.hpp"
using namespace El;
...
Matrix<double> A( m, n );
double* buffer = A.Buffer();
const Int ldim = A.LDim();
for( Int j=0; j<n; ++j )
for( Int i=0; i<m; ++i )
buffer[i+j*ldim] = double(i-j);


For immutable instances of the Matrix<T> class, a const pointer to the underlying data can similarly be returned with a call to Matrix<T>::LockedBuffer(). In addition, a (const) pointer to the place in the (const) buffer where entry $$(i,j)$$ resides can be easily retrieved with a call to Matrix<T>::Buffer() or Matrix<T>::LockedBuffer().

It is also important to be able to create matrices which are simply views of existing (sub)matrices. In general, to view the submatrix with row indices $$[\text{iBeg},\text{iEnd}]$$ and column indices $$[\text{jBeg},\text{jEnd}]$$, one can use a statement of the form

#include "El.hpp"
...
auto ASub = A( IR(iBeg,iEnd), IR(jBeg,jEnd) );

template<>
class Matrix<T>

The goal is for the Matrix class to support any datatype T which supports both addition and multiplication and has the associated identities (that is, when the datatype T is a ring). While there are several barriers to reaching this goal, it is important to keep in mind that, in addition to T being allowed to be a real or complex (single- or double-precision) floating-point type, signed integers are also supported.

Constructors and destructors

Note

Many of the following constructors have the default parameter bool fixed=false, which can be changed to true in order to produce a Matrix whose entries can be modified, but the matrix’s dimensions cannot. This is useful for the DistMatrix<T> class, which contains a local Matrix<T> whose entries can be locally modified in cases where it would not make sense to change the local matrix size (which should instead result from changing the size of the full distributed matrix).

Matrix(bool fixed = false)

This simply creates a default $$0 \times 0$$ matrix with a leading dimension of one (BLAS and LAPACK require positive leading dimensions).

Matrix(Int height, Int width, bool fixed = false)

A height $$\times$$ width matrix is created with an unspecified leading dimension (though it is currently implemented as $$\max(height,1)$$).

Matrix(Int height, Int width, Int ldim, bool fixed = false)

A height $$\times$$ width matrix is created with a leading dimension equal to ldim (which must be greater than or equal $$\max(height,1)$$).

Matrix(Int height, Int width, const T *buffer, Int ldim, bool fixed = false)
Matrix(Int height, Int width, T *buffer, Int ldim, bool fixed = false)

A matrix is built around a column-major (immutable) buffer with the specified dimensions. The memory pointed to by buffer should not be freed until after the Matrix<T> object is destructed.

Matrix(const Matrix<T> &A)

A copy (not a view) of the matrix $$A$$ is built.

Matrix(Matrix<T> &&A) noexcept

A C++11 move constructor which creates a new matrix by moving the metadata from the specified matrix over to the new matrix, which cheaply gives the new matrix control over the resources originally assigned to the input matrix.

~Matrix()

Frees all resources owned by the matrix upon destruction.

Assignment and reconfiguration

Matrix<T> &operator=(const Matrix<T> &A)

Create a full copy of the specified matrix.

Matrix<T> &operator=(Matrix<T> &&A)

A C++11 move assignment which swaps the metadata of two matrices so that the resources owned by the two objects will have been cheaply switched.

void Empty()

Sets the matrix to $$0 \times 0$$ and frees any owned resources.

void Resize(Int height, Int width)

Reconfigures the matrix to be height $$\times$$ width.

void Resize(Int height, Int width, Int ldim)

Reconfigures the matrix to be height $$\times$$ width, but with leading dimension equal to ldim (which must be greater than or equal to $$\max(height,1)$$).

void Attach(Int height, Int width, T *buffer, Int ldim)
void LockedAttach(Int height, Int width, const T *buffer, Int ldim)

Reconfigure the matrix around the specified (unmodifiable) buffer.

void Control(Int height, Int width, T *buffer, Int ldim)

Reconfigure the matrix around a specified buffer and give ownership of the resource to the matrix.

Basic queries

Int Height() const
Int Width() const

Return the height/width of the matrix.

Int LDim() const

Return the leading dimension of the underlying buffer.

Int MemorySize() const

Return the number of entries of type T that this Matrix<T> instance has allocated space for.

Int DiagonalLength(Int offset = 0) const

Return the length of the specified diagonal of the matrix: an offset of $$0$$ refers to the main diagonal, an offset of $$1$$ refers to the superdiagonal, an offset of $$-1$$ refers to the subdiagonal, etc.

T *Buffer()
const T *LockedBuffer() const

Return a pointer to the (immutable) underlying buffer.

T *Buffer(Int i, Int j)
const T *LockedBuffer(Int i, Int j) const

Return a pointer to the (immutable) portion of the buffer that holds entry $$(i,j)$$.

bool Viewing() const

Returns true if the underlying buffer is merely a pointer into an externally-owned buffer.

bool FixedSize() const

Returns true if the dimensions of the matrix cannot be changed.

bool Locked() const

Returns true if the entries of the matrix cannot be changed.

Single-entry manipulation

T Get(Int i, Int j) const
Base<T> GetRealPart(Int i, Int j) const
Base<T> GetImagPart(Int i, Int j) const

Return entry $$(i,j)$$ (or its real or imaginary part).

void Set(Int i, Int j, T alpha)
void SetRealPart(Int i, Int j, Base<T> alpha)
void SetImagPart(Int i, Int j, Base<T> alpha)

Set entry $$(i,j)$$ (or its real or imaginary part) to $$\alpha$$.

void Update(Int i, Int j, T alpha)
void UpdateRealPart(Int i, Int j, Base<T> alpha)
void UpdateImagPart(Int i, Int j, Base<T> alpha)

Add $$\alpha$$ to entry $$(i,j)$$ (or its real or imaginary part).

void MakeReal(Int i, Int j)

Force the $$(i,j)$$ entry to be real.

void Conjugate(Int i, Int j)

Conjugate the $$(i,j)$$ entry of the matrix.

Diagonal manipulation

void GetDiagonal(Matrix<T> &d, Int offset = 0) const
void GetRealPartOfDiagonal(Matrix<Base<T>> &d, Int offset = 0) const
void GetImagPartOfDiagonal(Matrix<Base<T>> &d, Int offset = 0) const

Modify $$d$$ into a column-vector containing the entries (or their real or imaginary parts) lying on the offset diagonal of our matrix (for instance, the main diagonal has offset $$0$$, the subdiagonal has offset $$-1$$, and the superdiagonal has offset $$+1$$).

Matrix<T> GetDiagonal(Int offset = 0) const
Matrix<Base<T>> GetRealPartOfDiagonal(Int offset = 0) const
Matrix<Base<T>> GetRealPartOfDiagonal(Int offset = 0) const

Efficiently construct and return the particular diagonal (or its real or imaginary part) via C++11 move semantics.

void SetDiagonal(const Matrix<T> &d, Int offset = 0)
void SetRealPartOfDiagonal(const Matrix<Base<T>> &d, Int offset = 0)
void SetImagPartOfDiagonal(const Matrix<Base<T>> &d, Int offset = 0)

Set the entries (or their real or imaginary parts) in the offset diagonal entries from the contents of the column-vector $$d$$.

void UpdateDiagonal(T alpha, const Matrix<T> &d, Int offset = 0)
void UpdateRealPartOfDiagonal(Base<T> alpha, const Matrix<Base<T>> &d, Int offset = 0)
void UpdateImagPartOfDiagonal(Base<T> alpha, const Matrix<Base<T>> &d, Int offset = 0)

Add the contents of $$\alpha d$$ onto the entries (or the real or imaginary parts) in the offset diagonal.

void MakeDiagonalReal(Int offset = 0)

Force the specified diagonal of the matrix to be real.

void ConjugateDiagonal(nt offset = 0)

Conjugate the specified diagonal of the matrix.

Arbitrary-submatrix manipulation

void GetSubmatrix(const std::vector<Int> &I, const std::vector<Int> &J, Matrix<T> &ASub) const
void GetRealPartOfSubmatrix(const std::vector<Int> &I, const std::vector<Int> &J, Matrix<Base<T>> &ASub) const
void GetImagPartOfSubmatrix(const std::vector<Int> &I, const std::vector<Int> &J, Matrix<Base<T>> &ASub) const

Return the submatrix (or its real or imaginary part) with the specified row and column indices via ASub.

Matrix<T> GetSubmatrix(const std::vector<Int> &I, const std::vector<Int> &J) const
Matrix<Base<T>> GetRealPartOfSubmatrix(const std::vector<Int> &I, const std::vector<Int> &J) const
Matrix<Base<T>> GetImagPartOfSubmatrix(const std::vector<Int> &I, const std::vector<Int> &J) const

Return the submatrix (or its real or imaginary part) with the specified row and column indices via C++11 move semantics.

void SetSubmatrix(const std::vector<Int> &I, const std::vector<Int> &J, const Matrix<T> &ASub)
void SetRealPartOfSubmatrix(const std::vector<Int> &I, const std::vector<Int> &J, const Matrix<Base<T>> &ASub)
void SetImagPartOfSubmatrix(const std::vector<Int> &I, const std::vector<Int> &J, const Matrix<Base<T>> &ASub)

Set the submatrix (or its real or imaginary part) with the specified row and column indices equal to the matrix ASub.

void UpdateSubmatrix(const std::vector<Int> &I, const std::vector<Int> &J, T alpha, const Matrix<T> &ASub)
void UpdateRealPartOfSubmatrix(const std::vector<Int> &I, const std::vector<Int> &J, Base<T> alpha, const Matrix<Base<T>> &ASub)
void UpdateImagPartOfSubmatrix(const std::vector<Int> &I, const std::vector<Int> &J, Base<T> alpha, const Matrix<Base<T>> &ASub)

Update the submatrix (or its real or imaginary part) with the specified row and column indices with alpha times ASub.

void MakeSubmatrixReal(const std::vector<Int> &I, const std::vector<Int> &J)

Force the submatrix with the specified row and column indices to be real.

void ConjugateSubmatrix(const std::vector<Int> &I, const std::vector<Int> &J)

Conjugate the entries in the submatrix with the specified row and column indices.

## Special cases used in Elemental¶

This list of special cases is here to help clarify the notation used throughout Elemental’s source (as well as this documentation). These are all special cases of Matrix<T>.

template<>
class Matrix<Real>

Used to denote that the underlying datatype Real is real.

template<>
class Matrix<Complex<Real>>

Used to denote that the underlying datatype Complex<Real> is complex with base type Real.

template<>
class Matrix<F>

Used to denote that the underlying datatype F is a field.

template<>
class Matrix<Int>

When the underlying datatype is a signed integer.