Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Complex Numbers

ccalc supports complex numbers using the same syntax as Octave/MATLAB. No special mode is needed — i and j are always available as the imaginary unit.

Creating complex numbers

3 + 4i           % 3 + 4i   — Ni suffix (no space before i/j)
3 + 4*i          % same — explicit multiply also works
3 + 4*j          % j is also the imaginary unit
complex(3, 4)    % construct from real and imaginary parts
5i               % pure imaginary: 5i
2 - 3i           % 2 - 3i

Ni suffix syntax: any decimal number immediately followed by i or j (no space, no further alphanumeric characters) is treated as a complex literal. The tokenizer expands 4i to 4 * i — the imaginary unit i must be in scope (it is always pre-seeded at startup).

Arithmetic

All standard operators work on complex numbers:

z1 = 3 + 4*i
z2 = 1 - 2*i

z1 + z2          % 4 + 2i
z1 - z2          % 2 + 6i
z1 * z2          % 11 - 2i     (a+bi)(c+di) = (ac-bd) + (ad+bc)i
z1 / z2          % -1 + 2i

Mixing complex and real scalars works naturally:

z1 + 10          % 13 + 4i
2 * z1           % 6 + 8i
z1 ^ 2           % -7 + 24i

When the imaginary part of a result is exactly zero, the value is shown and stored as a real scalar:

(1+i) * (1-i)    % 2   (not 2 + 0i)

Powers

Integer powers use binary exponentiation for exact results:

i^2              % -1    (exact)
i^3              % -i    (exact)
i^4              %  1    (exact)
(1+i)^4          % -4
(1+i)^-1         % 0.5 - 0.5i

Non-integer powers use the polar form exp((c+di)·ln(a+bi)):

i^0.5            % 0.7071067812 + 0.7071067812i   (sqrt of i)
2^(1+i)          % 1.5384778027 + 1.2779225526i

Polar form

Every complex number z = re + im*i has a polar representation z = r * (cos θ + i * sin θ), where r = abs(z) and θ = angle(z):

z = 3 + 4*i
abs(z)           % 5          (modulus |z| = sqrt(3² + 4²))
angle(z)         % 0.9272...  (argument in radians)
angle(z) * 180/pi  % 53.13°  (in degrees)

Reconstruct from polar using exp:

r = abs(z);
t = angle(z);
r * exp(1i * t)               % 3 + 4i   (Euler's formula: e^(it) = cos t + i·sin t)
complex(r*cos(t), r*sin(t))   % 3 + 4i   (equivalent, without exp)

Euler’s identity:

exp(1i * pi) + 1              % ≈ 0   (≈ 0 + 1.22e-16i — floating-point rounding)

Built-in functions

FunctionDescription
real(z)Real part (real(5) → 5, real(3+4i) → 3)
imag(z)Imaginary part (imag(5) → 0, imag(3+4i) → 4)
abs(z)Modulus (also works on real scalars and matrices)
angle(z)Argument in radians
conj(z)Complex conjugate: re - im*i
complex(re, im)Construct from two real scalars
isreal(z)1 if imaginary part is zero, else 0
exp(z)Complex exponential: e^a·(cos b + i·sin b) where z = a + bi
z = 3 + 4*i
real(z)          % 3
imag(z)          % 4
conj(z)          % 3 - 4i
abs(z)           % 5
angle(z)         % 0.927...
isreal(z)        % 0
isreal(5)        % 1
imag(7)          % 0

Conjugate and plain transpose

The postfix ' operator returns the conjugate of a complex scalar (matching the matrix Hermitian-transpose convention):

z = 3 + 4i
z'               % 3 - 4i   conjugate — flips imaginary sign
conj(z)          % 3 - 4i   same result

The postfix .' operator returns the plain transpose — no conjugation:

z.'              % 3 + 4i   plain transpose — imaginary part unchanged

For real scalars and matrices ' and .' give identical results. The distinction only matters for complex values.

Comparison

== and ~= compare both real and imaginary parts:

(3 + 4*i) == (3 + 4*i)    % 1
(3 + 4*i) == (3 - 4*i)    % 0
(3 + 4*i) ~= (3 - 4*i)    % 1

Ordering operators (<, >, <=, >=) return an error for complex numbers — ordering is not defined for the complex plane.

Imaginary unit variables

i and j are pre-set to 0 + 1i at startup. You can reassign them (e.g. i = 5 for a loop counter), in which case the original value is no longer available until you restart ccalc.

Complex Matrices

Any matrix literal that contains at least one complex element becomes a ComplexMatrix. Real elements are promoted automatically.

A = [1+2i, 3-4i; 5, 6+1i]   % 2×2 complex matrix
v = [1+i, 2-i, 3]            % 1×3 complex row vector

isreal distinguishes the two kinds:

isreal([1 2; 3 4])   % 1   (real matrix — no imaginary parts)
isreal(A)            % 0   (complex matrix)

Display

Every cell always shows both parts:

A(1,1)   % 1 + 2i   (not just "1+2i")
A(2,1)   % 5 + 0i   (imaginary part printed even when zero)

Arithmetic

+, -, .*, ./, .^ work element-wise. * performs matrix multiplication. Scalar / complex scalar broadcast applies to both operands:

A + B         % element-wise addition
A .* B        % element-wise multiply
A * B         % matrix multiply
2 * A         % scalar broadcast
A + [10, 20; 30, 40]   % mixed real + complex matrix

Transpose

M = [1+2i, 3+4i; 5+6i, 7+8i]
M'            % conjugate transpose (Hermitian adjoint)
M.'           % plain transpose (no conjugation)

M * M' is Hermitian — its diagonal is always real.

Element-wise built-ins on matrices

All of the scalar complex built-ins work element-wise on ComplexMatrix:

FunctionInputOutput
real(A)ComplexMatrixreal Matrix (one real part per element)
imag(A)ComplexMatrixreal Matrix (one imaginary part per element)
abs(A)ComplexMatrixreal Matrix (element-wise modulus)
conj(A)ComplexMatrixComplexMatrix (element-wise conjugate)
angle(A)ComplexMatrixreal Matrix (argument in radians)
isreal(A)ComplexMatrix0 (always)

Shape functions

size, numel, length, and norm (Frobenius) all work:

C = [1+1i, 2-1i, 3; 4, 5+2i, 6-3i]
size(C)           % [2  3]
numel(C)          % 6
norm(C)           % Frobenius norm

Indexing

1-based, column-major — the same conventions as real matrices:

w = [10+1i, 20+2i, 30+3i, 40+4i]
w(2)          % 20 + 2i
w(2:3)        % [20+2i, 30+3i]
G(1,:)        % first row
G(:,2)        % second column

Indexed assignment and auto-upcast

You can assign into an existing ComplexMatrix with any index expression:

A = [1+2i, 3-4i; 5, 6+1i]
A(1,1) = 0             % write a real scalar — stays ComplexMatrix
A(2,2) = 7 - 3i        % write a complex scalar
A(1,:) = [2+i, -1+0i]  % range assignment with a complex row vector

Assigning a complex value into a real matrix automatically promotes it to ComplexMatrix (MATLAB/Octave auto-upcast semantics). Existing real entries are preserved as x + 0i:

B = zeros(3, 3)          % real Matrix
B(2, 2) = 1 + 2i         % → B is now a ComplexMatrix; B(2,2) = 1 + 2i
B(1, :) = [3-1i, 0, 2i]  % range assignment; all other entries are x + 0i

Once a variable has been promoted to ComplexMatrix, assigning a real scalar back into an element leaves it as ComplexMatrix:

B(2, 2) = 9              % stays ComplexMatrix; B(2,2) = 9 + 0i

Reduction functions

trace, diag, sum, prod, and mean all work on ComplexMatrix, following the same conventions as for real matrices.

FunctionOn vectorOn M×N matrix
sum(A)single Complex scalarComplexMatrix 1×N of column sums
prod(A)single Complex scalarComplexMatrix 1×N of column products
mean(A)single Complex scalarComplexMatrix 1×N of column means
trace(A)(N/A)Complex scalar (sum of diagonal)
diag(A)diagonal matrixComplexMatrix N×1 column vector of diagonal
M = [1+2i, 3+4i; 5+6i, 7+8i]

trace(M)          % 8 + 10i  (sum of diagonal: (1+2i) + (7+8i))
diag(M)           % [1+2i; 7+8i]  — diagonal as a column vector
diag(diag(M))     % 2×2 diagonal ComplexMatrix

sum(M)            % [6+8i, 10+12i]  — column sums
prod(M)           % [(1+2i)*(5+6i), (3+4i)*(7+8i)]
mean(M)           % [3+4i, 5+6i]

sum([1+2i, 3+4i, 5+6i])   % 9 + 12i  — vector collapses to scalar

Block concatenation

ComplexMatrix blocks mix freely with real Matrix blocks in horizontal and vertical concatenation:

Z = [1+2i, 3-4i; 5, 6+1i]   % 2×2 ComplexMatrix
O = ones(2, 2)

[Z, O]    % 2×4 ComplexMatrix — horizontal
[Z; O]    % 4×2 ComplexMatrix — vertical
[Z, Z; O, O]  % 4×4 block matrix

FFT output

Since Phase 27, fft() returns a ComplexMatrix (1×N row vector) rather than a cell array. Access individual bins with X(k):

X = fft([1 2 3 4])
X(1)          % 10 + 0i  (DC component)
abs(X)        % real Matrix of bin magnitudes

Example

% Euler's identity: e^(i*pi) + 1 ≈ 0
e^(i * pi) + 1        % ≈ 0  (tiny floating-point residual from sin(π))

% Roots of x^2 + 1 = 0
x1 = i
x2 = -i

% AC impedance of a series RL circuit
R = 100; L = 0.05; f = 1000;
w = 2 * pi * f;
Z = complex(R, w * L)        % 100 + 314.159i
abs(Z)                        % impedance magnitude
angle(Z) * 180/pi             % phase angle in degrees

See examples/complex_numbers.calc for a complete annotated example.