# Complex Matrix Operations

## Complex promotion

This chapter provides the details of functions that operate over complex matrices, vectors, and row vectors. These mirror the operations over real complex_matrix types and are defined in the usual way for complex numbers.

### Promotion of complex arguments

If an expression e can be assigned to a variable of type T, then it can be used as an argument to a function that is specified to take arguments of type T. For instance, sqrt(real) is specified to take a real argument, but an integer expression such as 2 + 2 of type int can be passed to sqrt, so that sqrt(2 + 2) is well defined. This works by promoting the integer expression 2 + 2 to be of real type.

The rules for promotion in Stan are simple:

• int may be promoted to real,
• real may be promoted to complex,
• vector can be promoted to complex_vector,
• row_vector can be promoted to complex_row_vector,
• matrix can be promoted to complex_matrix,
• if T can be promoted to U and U can be promoted to V, then T can be promoted to V (transitive), and
• if T can be promoted to U, then T[] can be promoted to U[] (covariant).

### Signature selection

When a function is called, the definition requiring the fewest number of promotions is used. For example, when calling vector + vector, the real-valued signature is used. When calling any of complex_vector + vector, vector + complex_vector, or complex_vector + complex_vector, the complex signature is used. If more than one signature matches with a the minimal number of promotions, the call is ambiguous, and an error will be raised by the compiler. Promotion ambiguity leading to ill-defined calls should never happen with Stan built-in functions.

### Signatures for complex functions

Complex function signatures will only list the fully complex type. For example, with complex vector addition, we will list a single signature, complex operator+(complex_vector, complex_vector). Through promotion, operator+ may be called with one complex vector and one real vector as well, but the documentation elides the implied signatures operator+(complex_vector, vector) and operator+(vector, complex_vector).

### Generic functions work for complex containers

Generic functions work for arrays containing complex, complex matrix, complex vector, or complex row vector types. This includes the functions append_array, dims, head, num_elements, rep_array, reverse, segment, size, and tail.

## Integer-valued complex matrix size functions

int num_elements(complex_vector x)
The total number of elements in the vector x (same as function rows)

Available since 2.30

int num_elements(complex_row_vector x)
The total number of elements in the vector x (same as function cols)

Available since 2.30

int num_elements(complex_matrix x)
The total number of elements in the matrix x. For example, if x is a $$5 \times 3$$ matrix, then num_elements(x) is 15

Available since 2.30

int rows(complex_vector x)
The number of rows in the vector x

Available since 2.30

int rows(complex_row_vector x)
The number of rows in the row vector x, namely 1

Available since 2.30

int rows(complex_matrix x)
The number of rows in the matrix x

Available since 2.30

int cols(complex_vector x)
The number of columns in the vector x, namely 1

Available since 2.30

int cols(complex_row_vector x)
The number of columns in the row vector x

Available since 2.30

int cols(complex_matrix x)
The number of columns in the matrix x

Available since 2.30

int size(complex_vector x)
The size of x, i.e., the number of elements

Available since 2.30

int size(complex_row_vector x)
The size of x, i.e., the number of elements

Available since 2.30

int size(matrix x)
The size of the matrix x. For example, if x is a $$5 \times 3$$ matrix, then size(x) is 15.

Available since 2.30

## Complex matrix arithmetic operators

Stan supports all basic complex arithmetic operators using infix, prefix and postfix operations. This section lists the operations supported by Stan along with their argument and result types.

### Negation prefix operators

complex_vector operator-(complex_vector x)
The negation of the vector x.

Available since 2.30

complex_row_vector operator-(complex_row_vector x)
The negation of the row vector x.

Available since 2.30

complex_matrix operator-(complex_matrix x)
The negation of the matrix x.

Available since 2.30

T operator-(T x)
Vectorized version of operator-. If T x is a (possibly nested) array of matrix types, -x is the same shape array where each individual value is negated.

Available since 2.31

### Infix complex_matrix operators

complex_vector operator+(complex_vector x, complex_vector y)
The sum of the vectors x and y.

Available since 2.30

complex_row_vector operator+(complex_row_vector x, complex_row_vector y)
The sum of the row vectors x and y.

Available since 2.30

complex_matrix operator+(complex_matrix x, complex_matrix y)
The sum of the matrices x and y

Available since 2.30

complex_vector operator-(complex_vector x, complex_vector y)
The difference between the vectors x and y.

Available since 2.30

complex_row_vector operator-(complex_row_vector x, complex_row_vector y)
The difference between the row vectors x and y

Available since 2.30

complex_matrix operator-(complex_matrix x, complex_matrix y)
The difference between the matrices x and y

Available since 2.30

complex_vector operator*(complex x, complex_vector y)
The product of the scalar x and vector y

Available since 2.30

complex_row_vector operator*(complex x, complex_row_vector y)
The product of the scalar x and the row vector y

Available since 2.30

complex_matrix operator*(complex x, complex_matrix y)
The product of the scalar x and the matrix y

Available since 2.30

complex_vector operator*(complex_vector x, complex y)
The product of the scalar y and vector x

Available since 2.30

complex_matrix operator*(complex_vector x, complex_row_vector y)
The product of the vector x and row vector y

Available since 2.30

complex_row_vector operator*(complex_row_vector x, complex y)
The product of the scalar y and row vector x

Available since 2.30

complex operator*(complex_row_vector x, complex_vector y)
The product of the row vector x and vector y

Available since 2.30

complex_row_vector operator*(complex_row_vector x, complex_matrix y)
The product of the row vector x and matrix y

Available since 2.30

complex_matrix operator*(complex_matrix x, complex y)
The product of the scalar y and matrix x

Available since 2.30

complex_vector operator*(complex_matrix x, complex_vector y)
The product of the matrix x and vector y

Available since 2.30

complex_matrix operator*(complex_matrix x, complex_matrix y)
The product of the matrices x and y

Available since 2.30

complex_vector operator+(complex_vector x, complex y)
The result of adding y to every entry in the vector x

Available since 2.30

complex_vector operator+(complex x, complex_vector y)
The result of adding x to every entry in the vector y

Available since 2.30

complex_row_vector operator+(complex_row_vector x, complex y)
The result of adding y to every entry in the row vector x

Available since 2.30

complex_row_vector operator+(complex x, complex_row_vector y)
The result of adding x to every entry in the row vector y

Available since 2.30

complex_matrix operator+(complex_matrix x, complex y)
The result of adding y to every entry in the matrix x

Available since 2.30

complex_matrix operator+(complex x, complex_matrix y)
The result of adding x to every entry in the matrix y

Available since 2.30

complex_vector operator-(complex_vector x, complex y)
The result of subtracting y from every entry in the vector x

Available since 2.30

complex_vector operator-(complex x, complex_vector y)
The result of adding x to every entry in the negation of the vector y

Available since 2.30

complex_row_vector operator-(complex_row_vector x, complex y)
The result of subtracting y from every entry in the row vector x

Available since 2.30

complex_row_vector operator-(complex x, complex_row_vector y)
The result of adding x to every entry in the negation of the row vector y

Available since 2.30

complex_matrix operator-(complex_matrix x, complex y)
The result of subtracting y from every entry in the matrix x

Available since 2.30

complex_matrix operator-(complex x, complex_matrix y)
The result of adding x to every entry in negation of the matrix y

Available since 2.30

complex_vector operator/(complex_vector x, complex y)
The result of dividing each entry in the vector x by y

Available since 2.30

complex_row_vector operator/(complex_row_vector x, complex y)
The result of dividing each entry in the row vector x by y

Available since 2.30

complex_matrix operator/(complex_matrix x, complex y)
The result of dividing each entry in the matrix x by y

Available since 2.30

## Complex Transposition Operator

Complex complex_matrix transposition is represented using a postfix operator.

complex_matrix operator'(complex_matrix x)
The transpose of the matrix x, written as x'

Available since 2.30

complex_row_vector operator'(complex_vector x)
The transpose of the vector x, written as x'

Available since 2.30

complex_vector operator'(complex_row_vector x)
The transpose of the row vector x, written as x'

Available since 2.30

## Complex elementwise functions

As in the real case, elementwise complex functions apply a function to each element of a vector or matrix, returning a result of the same shape as the argument.

complex_vector operator.*(complex_vector x, complex_vector y)
The elementwise product of x and y

Available since 2.30

complex_row_vector operator.*(complex_row_vector x, complex_row_vector y)
The elementwise product of x and y

Available since 2.30

complex_matrix operator.*(complex_matrix x, complex_matrix y)
The elementwise product of x and y

Available since 2.30

complex_vector operator./(complex_vector x, complex_vector y)
The elementwise quotient of x and y

Available since 2.30

complex_vector operator./(complex x, complex_vector y)
The elementwise quotient of x and y

Available since 2.30

complex_vector operator./(complex_vector x, complex y)
The elementwise quotient of x and y

Available since 2.30

complex_row_vector operator./(complex_row_vector x, complex_row_vector y)
The elementwise quotient of x and y

Available since 2.30

complex_row_vector operator./(complex x, complex_row_vector y)
The elementwise quotient of x and y

Available since 2.30

complex_row_vector operator./(complex_row_vector x, complex y)
The elementwise quotient of x and y

Available since 2.30

complex_matrix operator./(complex_matrix x, complex_matrix y)
The elementwise quotient of x and y

Available since 2.30

complex_matrix operator./(complex x, complex_matrix y)
The elementwise quotient of x and y

Available since 2.30

complex_matrix operator./(complex_matrix x, complex y)
The elementwise quotient of x and y

Available since 2.30

vector operator.^(complex_vector x, complex_vector y)
The elementwise power of y and x

Available since 2.30

vector operator.^(complex_vector x, complex y)
The elementwise power of y and x

Available since 2.30

vector operator.^(complex x, complex_vector y)
The elementwise power of y and x

Available since 2.30

row_vector operator.^(complex_row_vector x, complex_row_vector y)
The elementwise power of y and x

Available since 2.30

row_vector operator.^(complex_row_vector x, complex y)
The elementwise power of y and x

Available since 2.30

row_vector operator.^(complex x, complex_row_vector y)
The elementwise power of y and x

Available since 2.30

matrix operator.^( complex_matrix x, complex_matrix y)
The elementwise power of y and x

Available since 2.30

matrix operator.^( complex_matrix x, complex y)
The elementwise power of y and x

Available since 2.30

matrix operator.^(complex x, complex_matrix y)
The elementwise power of y and x

Available since 2.30

## Dot products and specialized products for complex matrices

complex dot_product(complex_vector x, complex_vector y)
The dot product of x and y

Available since 2.30

complex dot_product(complex_vector x, complex_row_vector y)
The dot product of x and y

Available since 2.30

complex dot_product(complex_row_vector x, complex_vector y)
The dot product of x and y

Available since 2.30

complex dot_product(complex_row_vector x, complex_row_vector y)
The dot product of x and y

Available since 2.30

complex_row_vector columns_dot_product(complex_vector x, complex_vector y)
The dot product of the columns of x and y

Available since 2.30

complex_row_vector columns_dot_product(complex_row_vector x, complex_row_vector y)
The dot product of the columns of x and y

Available since 2.30

complex_row_vector columns_dot_product(complex_matrix x, complex_matrix y)
The dot product of the columns of x and y

Available since 2.30

complex_vector rows_dot_product(complex_vector x, complex_vector y)
The dot product of the rows of x and y

Available since 2.30

complex_vector rows_dot_product(complex_row_vector x, complex_row_vector y)
The dot product of the rows of x and y

Available since 2.30

complex_vector rows_dot_product(complex_matrix x, complex_matrix y)
The dot product of the rows of x and y

Available since 2.30

complex dot_self(complex_vector x)
The dot product of the vector x with itself

Available since 2.30

complex dot_self(complex_row_vector x)
The dot product of the row vector x with itself

Available since 2.30

complex_row_vector columns_dot_self(complex_vector x)
The dot product of the columns of x with themselves

Available since 2.30

complex_row_vector columns_dot_self(complex_row_vector x)
The dot product of the columns of x with themselves

Available since 2.30

complex_row_vector columns_dot_self(complex_matrix x)
The dot product of the columns of x with themselves

Available since 2.30

complex_vector rows_dot_self(complex_vector x)
The dot product of the rows of x with themselves

Available since 2.30

complex_vector rows_dot_self(complex_row_vector x)
The dot product of the rows of x with themselves

Available since 2.30

complex_vector rows_dot_self(complex_matrix x)
The dot product of the rows of x with themselves

Available since 2.30

### Specialized products

complex_matrix diag_pre_multiply(complex_vector v, complex_matrix m)
Return the product of the diagonal matrix formed from the vector v and the matrix m, i.e., diag_matrix(v) * m.

Available since 2.30

complex_matrix diag_pre_multiply(complex_row_vector v, complex_matrix m)
Return the product of the diagonal matrix formed from the vector rv and the matrix m, i.e., diag_matrix(rv) * m.

Available since 2.30

complex_matrix diag_post_multiply(complex_matrix m, complex_vector v)
Return the product of the matrix m and the diagonal matrix formed from the vector v, i.e., m * diag_matrix(v).

Available since 2.30

complex_matrix diag_post_multiply(complex_matrix m, complex_row_vector v)
Return the product of the matrix m and the diagonal matrix formed from the the row vector rv, i.e., m * diag_matrix(rv).

Available since 2.30

## Complex reductions

### Sums and products

complex sum(complex_vector x)
The sum of the values in x, or 0 if x is empty

Available since 2.30

complex sum(complex_row_vector x)
The sum of the values in x, or 0 if x is empty

Available since 2.30

complex sum(complex_matrix x)
The sum of the values in x, or 0 if x is empty

Available since 2.30

complex prod(complex_vector x)
The product of the values in x, or 1 if x is empty

Available since 2.30

complex prod(complex_row_vector x)
The product of the values in x, or 1 if x is empty

Available since 2.30

complex prod(complex_matrix x)
The product of the values in x, or 1 if x is empty

Available since 2.30

## Vectorized accessor functions

Much like with complex scalars, two functions are defined to get the real and imaginary components of complex-valued objects.

### Type “demotion”

These functions return the same shape (e.g., matrix, vector, row vector, or array) object as their input, but demoted to a real type. For example, get_real(complex_matrix M) yields a matrix containing the real component of each value in M.

The following table contains examples of what this notation can mean:

Type T Type T_demoted
complex real
complex_vector vector
complex_row_vector row_vector
complex_matrix matrix
array[] complex array[] real
array[,,] complex array[,,] real

### Real and imaginary component accessor functions

T_demoted get_real(T x)
Given an object of complex type T, return the same shape object but of type real by getting the real component of each element of x.

Available since 2.30

T_demoted get_imag(T x)
Given an object of complex type T, return the same shape object but of type real by getting the imaginary component of each element of x.

Available since 2.30

For example, given the Stan declaration

  complex_vector[2] z = [3+4i, 5+6i]';

A call get_real(z) will yield the vector [3, 5]', and a call get_imag(z) will yield the vector [4, 6]'.

The following broadcast functions allow vectors, row vectors and matrices to be created by copying a single element into all of their cells. Matrices may also be created by stacking copies of row vectors vertically or stacking copies of column vectors horizontally.

complex_vector rep_vector(complex z, int m)
Return the size m (column) vector consisting of copies of z.

Available since 2.30

complex_row_vector rep_row_vector(complex z, int n)
Return the size n row vector consisting of copies of z.

Available since 2.30

complex_matrix rep_matrix(complex z, int m, int n)
Return the m by n matrix consisting of copies of z.

Available since 2.30

complex_matrix rep_matrix(complex_vector v, int n)
Return the m by n matrix consisting of n copies of the (column) vector v of size m.

Available since 2.30

complex_matrix rep_matrix(complex_row_vector rv, int m)
Return the m by n matrix consisting of m copies of the row vector rv of size n.

Available since 2.30

### Symmetrization

complex_matrix symmetrize_from_lower_tri(complex_matrix A)
Construct a symmetric matrix from the lower triangle of A.

Available since 2.30

## Diagonal complex matrix functions

complex_matrix add_diag(complex_matrix m, complex_row_vector d)
Add row_vector d to the diagonal of matrix m.

Available since 2.30

complex_matrix add_diag(complex_matrix m, complex_vector d)
Add vector d to the diagonal of matrix m.

Available since 2.30

complex_matrix add_diag(complex_matrix m, complex d)
Add scalar d to every diagonal element of matrix m.

Available since 2.30

complex_vector diagonal(complex_matrix x)
The diagonal of the matrix x

Available since 2.30

complex_matrix diag_matrix(complex_vector x)
The diagonal matrix with diagonal x

Available since 2.30

## Slicing and blocking functions for complex matrices

Stan provides several functions for generating slices or blocks or diagonal entries for matrices.

### Columns and rows

complex_vector col(complex_matrix x, int n)
The n-th column of matrix x

Available since 2.30

complex_row_vector row(complex_matrix x, int m)
The m-th row of matrix x

Available since 2.30

### Block operations

#### Matrix slicing operations

complex_matrix block(complex_matrix x, int i, int j, int n_rows, int n_cols)
Return the submatrix of x that starts at row i and column j and extends n_rows rows and n_cols columns.

Available since 2.30

complex_vector sub_col(complex_matrix x, int i, int j, int n_rows)
Return the sub-column of x that starts at row i and column j and extends n_rows rows and 1 column.

Available since 2.30

complex_row_vector sub_row(complex_matrix x, int i, int j, int n_cols)
Return the sub-row of x that starts at row i and column j and extends 1 row and n_cols columns.

Available since 2.30

#### Vector slicing operations.

complex_vector head(complex_vector v, int n)
Return the vector consisting of the first n elements of v.

Available since 2.30

complex_row_vector head(complex_row_vector rv, int n)
Return the row vector consisting of the first n elements of rv.

Available since 2.30

complex_vector tail(complex_vector v, int n)
Return the vector consisting of the last n elements of v.

Available since 2.30

complex_row_vector tail(complex_row_vector rv, int n)
Return the row vector consisting of the last n elements of rv.

Available since 2.30

complex_vector segment(complex_vector v, int i, int n)
Return the vector consisting of the n elements of v starting at i; i.e., elements i through through i + n - 1.

Available since 2.30

complex_row_vector segment(complex_row_vector rv, int i, int n)
Return the row vector consisting of the n elements of rv starting at i; i.e., elements i through through i + n - 1.

Available since 2.30

## Complex matrix concatenation

### Horizontal concatenation

complex_matrix append_col(complex_matrix x, complex_matrix y)
Combine matrices x and y by column. The matrices must have the same number of rows.

Available since 2.30

complex_matrix append_col(complex_matrix x, complex_vector y)
Combine matrix x and vector y by column. The matrix and the vector must have the same number of rows.

Available since 2.30

complex_matrix append_col(complex_vector x, complex_matrix y)
Combine vector x and matrix y by column. The vector and the matrix must have the same number of rows.

Available since 2.30

complex_matrix append_col(complex_vector x, complex_vector y)
Combine vectors x and y by column. The vectors must have the same number of rows.

Available since 2.30

complex_row_vector append_col(complex_row_vector x, complex_row_vector y)
Combine row vectors x and y (of any size) into another row vector by appending y to the end of x.

Available since 2.30

complex_row_vector append_col(complex x, complex_row_vector y)
Append x to the front of y, returning another row vector.

Available since 2.30

complex_row_vector append_col(complex_row_vector x, complex y)
Append y to the end of x, returning another row vector.

Available since 2.30

### Vertical concatenation

complex_matrix append_row(complex_matrix x, complex_matrix y)
Combine matrices x and y by row. The matrices must have the same number of columns.

Available since 2.30

complex_matrix append_row(complex_matrix x, complex_row_vector y)
Combine matrix x and row vector y by row. The matrix and the row vector must have the same number of columns.

Available since 2.30

complex_matrix append_row(complex_row_vector x, complex_matrix y)
Combine row vector x and matrix y by row. The row vector and the matrix must have the same number of columns.

Available since 2.30

complex_matrix append_row(complex_row_vector x, complex_row_vector y)
Combine row vectors x and y by row. The row vectors must have the same number of columns.

Available since 2.30

complex_vector append_row(complex_vector x, complex_vector y)
Concatenate vectors x and y of any size into another vector.

Available since 2.30

complex_vector append_row(complex x, complex_vector y)
Append x to the top of y, returning another vector.

Available since 2.30

complex_vector append_row(complex_vector x, complex y)
Append y to the bottom of x, returning another vector.

Available since 2.30

## Complex special matrix functions

### Fast Fourier transforms

Stan’s fast Fourier transform functions take the standard definition of the discrete Fourier transform (see the definitions below for specifics) and scale the inverse transform by one over dimensionality so that the following identities hold for complex vectors u and v,

    fft(inv_fft(u)) == u        inv_fft(fft(v)) == v

and in the 2-dimensional case for complex matrices A and B,

    fft2(inv_fft2(A)) == A      inv_fft2(fft2(B)) == B

Although the FFT functions only accept complex inputs, real vectors and matrices will be promoted to their complex counterparts before applying the FFT functions.

complex_vector fft(complex_vector v)
Return the discrete Fourier transform of the specified complex vector v. If $$v \in \mathbb{C}^N$$ is a complex vector with $$N$$ elements and $$u = \textrm{fft}(v)$$, then $\begin{equation*} u_n = \sum_{m < n} v_m \cdot \exp\left(\frac{-n \cdot m \cdot 2 \cdot \pi \cdot \sqrt{-1}}{N}\right). \end{equation*}$

Available since 2.30

complex_matrix fft2(complex_matrix m)
Return the 2D discrete Fourier transform of the specified complex matrix m. The 2D FFT is defined as the result of applying the FFT to each row and then to each column.

Available since 2.30

complex_vector inv_fft(complex_vector u)
Return the inverse of the discrete Fourier transform of the specified complex vector u. The inverse FFT (this function) is scaled so that fft(inv_fft(u)) == u. If $$u \in \mathbb{C}^N$$ is a complex vector with $$N$$ elements and $$v = \textrm{fft}^{-1}(u)$$, then $\begin{equation*} v_n = \frac{1}{N} \sum_{m < n} u_m \cdot \exp\left(\frac{n \cdot m \cdot 2 \cdot \pi \cdot \sqrt{-1}}{N}\right). \end{equation*}$ This only differs from the FFT by the sign inside the exponential and the scaling. The $$\frac{1}{N}$$ scaling ensures that fft(inv_fft(u)) == u and inv_fft(fft(v)) == v for complex vectors u and v.

Available since 2.30

complex_matrix inv_fft2(complex_matrix m)
Return the inverse of the 2D discrete Fourier transform of the specified complex matrix m. The 2D inverse FFT is defined as the result of applying the inverse FFT to each row and then to each column. The invertible scaling of the inverse FFT ensures fft2(inv_fft2(A)) == A and inv_fft2(fft2(B)) == B.

Available since 2.30

### Cumulative sums

The cumulative sum of a sequence $$x_1,\ldots,x_N$$ is the sequence $$y_1,\ldots,y_N$$, where $\begin{equation*} y_n = \sum_{m = 1}^{n} x_m. \end{equation*}$

array[] complex cumulative_sum(array[] complex x)
The cumulative sum of x

Available since 2.30

complex_vector cumulative_sum(complex_vector v)
The cumulative sum of v

Available since 2.30

complex_row_vector cumulative_sum(complex_row_vector rv)
The cumulative sum of rv

Available since 2.30

## Complex linear algebra functions

### Complex matrix division operators and functions

In general, it is much more efficient and also more arithmetically stable to use matrix division than to multiply by an inverse.

#### Complex matrix division operators

complex_row_vector operator/(complex_row_vector b, complex_matrix A)
The right division of b by A; equivalently b * inverse(A)

Available since 2.30

complex_matrix operator/(complex_matrix B, complex_matrix A)
The right division of B by A; equivalently B * inverse(A)

Available since 2.30

### Linear algebra functions

#### Trace

complex trace(complex_matrix A)
The trace of A, or 0 if A is empty; A is not required to be diagonal

Available since 2.30

#### Eigendecomposition

complex_vector eigenvalues(complex_matrix A)
The complex-valued vector of eigenvalues of the matrix A. The eigenvalues are repeated according to their algebraic multiplicity, so there are as many eigenvalues as rows in the matrix. The eigenvalues are not sorted in any particular order.

Available since 2.32

complex_matrix eigenvectors(complex_matrix A)
The matrix with the complex-valued (column) eigenvectors of the matrix A in the same order as returned by the function eigenvalues

Available since 2.32

tuple(complex_matrix, complex_vector) eigendecompose(complex_matrix A)
Return the matrix of (column) eigenvectors and vector of eigenvalues of the matrix A. This function is equivalent to (eigenvectors(A), eigenvalues(A)) but with a lower computational cost due to the shared work between the two results.

Available since 2.33

complex_vector eigenvalues_sym(complex_matrix A)
The vector of eigenvalues of a symmetric matrix A in ascending order

Available since 2.30

complex_matrix eigenvectors_sym(complex_matrix A)
The matrix with the (column) eigenvectors of symmetric matrix A in the same order as returned by the function eigenvalues_sym

Available since 2.30

tuple(complex_matrix, complex_vector) eigendecompose_sym(complex_matrix A)
Return the matrix of (column) eigenvectors and vector of eigenvalues of the symmetric matrix A. This function is equivalent to (eigenvectors_sym(A), eigenvalues_sym(A)) but with a lower computational cost due to the shared work between the two results.

Available since 2.33

Because multiplying an eigenvector by $$-1$$ results in an eigenvector, eigenvectors returned by a decomposition are only identified up to a sign change. In order to compare the eigenvectors produced by Stan’s eigendecomposition to others, signs may need to be normalized in some way, such as by fixing the sign of a component, or doing comparisons allowing a multiplication by $$-1$$.

The condition number of a symmetric matrix is defined to be the ratio of the largest eigenvalue to the smallest eigenvalue. Large condition numbers lead to difficulty in numerical algorithms such as computing inverses, and thus known as “ill conditioned.” The ratio can even be infinite in the case of singular matrices (i.e., those with eigenvalues of 0).

#### Singular value decomposition

The matrix A can be decomposed into a diagonal matrix of singular values, D, and matrices of its left and right singular vectors, U and V, $\begin{equation*} A = U D V^T. \end{equation*}$ The matrices of singular vectors here are thin. That is for an $$N$$ by $$P$$ input A, $$M = min(N, P)$$, U is size $$N$$ by $$M$$ and V is size $$P$$ by $$M$$.

vector singular_values(complex_matrix A)
The singular values of A in descending order

Available since 2.30

complex_matrix svd_U(complex_matrix A)
The left-singular vectors of A

Available since 2.30

complex_matrix svd_V(complex_matrix A)
The right-singular vectors of A

Available since 2.30

tuple(complex_matrix, vector, complex_matrix) svd(complex_matrix A)
Returns a tuple containing the left-singular vectors of A, the singular values of A in descending order, and the right-singular values of A. This function is equivalent to (svd_U(A), singular_values(A), svd_V(A)) but with a lower computational cost due to the shared work between the different components.

Available since 2.33

#### Complex Schur Decomposition

The complex Schur decomposition of a square matrix $$A$$ produces a complex unitary matrix $$U$$ and a complex upper-triangular Schur form matrix $$T$$ such that $A = U \cdot T \cdot U^{-1}$

Since $$U$$ is unitary, its inverse is also its conjugate transpose, $$U^{-1} = U^*$$, $$U^*(i, j) = \mathrm{conj}(U(j, i))$$

complex_matrix complex_schur_decompose_t(matrix A)
Compute the upper-triangular Schur form matrix of the complex Schur decomposition of A.

Available since 2.31

complex_matrix complex_schur_decompose_t(complex_matrix A)
Compute the upper-triangular Schur form matrix of the complex Schur decomposition of A.

Available since 2.31

complex_matrix complex_schur_decompose_u(matrix A)
Compute the unitary matrix of the complex Schur decomposition of A.

Available since 2.31

complex_matrix complex_schur_decompose_u(complex_matrix A)
Compute the unitary matrix of the complex Schur decomposition of A.

Available since 2.31

tuple(complex_matrix, complex_matrix) complex_schur_decompose(matrix A)
Returns the unitary matrix and the upper-triangular Schur form matrix of the complex Schur decomposition of A. This function is equivalent to (complex_schur_decompose_u(A), complex_schur_decompose_t(A)) but with a lower computational cost due to the shared work between the two results. This overload is equivalent to complex_schur_decompose(to_complex(A,0)) but is more efficient.

Available since 2.33

tuple(complex_matrix, complex_matrix) complex_schur_decompose(complex_matrix A)
Returns the unitary matrix and the upper-triangular Schur form matrix of the complex Schur decomposition of A. This function is equivalent to (complex_schur_decompose_u(A), complex_schur_decompose_t(A)) but with a lower computational cost due to the shared work between the two results.

Available since 2.33

## Reverse functions for complex matrices

complex_vector reverse(complex_vector v)
Return a new vector containing the elements of the argument in reverse order.

Available since 2.30

complex_row_vector reverse(complex_row_vector v)
Return a new row vector containing the elements of the argument in reverse order.

Available since 2.30