# 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*

### Broadcast infix operators

`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]'`

.

## Complex broadcast functions

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*