5.3 Complex numerical data type

The complex data type is a scalar, but unlike real and int types, it contains two components, a real and imaginary component, both of which are of type real. That is, the real and imaginary components of a complex number are 64-bit, IEEE 754-complaint floating point numbers.

5.3.1 Constructing and accessing complex numbers

Imaginary literals are written in mathematical notation using a numeral followed by the suffix i. For example, the following example constructs a complex number \(2 - 1.3i\) and assigns it to the variable z.

complex z = 2 - 1.3i;
real re = get_real(z);  // re has value 2.0
real im = get_imag(z);  // im has value -1.3

The getter functions then extract the real and imaginary components of z and assign them to re and im respectively.

The function to_complex constructs a complex number from its real and imaginary components. The functional form needs to be used whenever the components are not literal numerals, as in the following example.

vector[K] re;
vector[K] im;
// ...
for (k in 1:K) {
  complex z = to_complex(re[k], im[k]);
  // ...

5.3.2 Promoting real to complex

Expressions of type real may be assigned to variables of type complex. For example, the following is a valid sequence of Stan statements.

real x = 5.0;
complex z = x;  // get_real(z) == 5.0, get_imag(z) == 0

The real number assigned to a complex number determine’s the complex number’s real component, with the imaginary component set to zero.

Assignability is transitive, so that expressions of type int may also be assigned to variables of type complex, as in the following example.

int n = 2;
complex z = n;

Function arguments also support promotion of integer or real typed expressions to type complex.