No matching definitions.

tur/complex

stdlib/complex.tur

Complex numbers as a plain re/im pair of doubles.

A Complex is a two-float record, and every operation on it is written in ordinary Turmeric. Neither _Complex nor <complex.h> appears anywhere in the emitted C, deliberately:

* `c2mir` (the JIT front end) implements a C11 subset that does not
  include the optional `_Complex` feature; and
* even on a C compiler that supports it, `a * b` and `a / b` on
  `double _Complex` do not compile to arithmetic -- they compile to calls
  into `__muldc3` / `__divdc3` in the compiler runtime, which would become
  external symbols the JIT must resolve.

So the arithmetic is hand-written here, division uses Smith's algorithm (scale by the larger-magnitude denominator component before dividing), and the overflow behaviour is ours, identical on every engine, and testable.

Complex numbers are not ordered, so there is deliberately NO Ord instance. (lt? c1 c2) is a type error, and that is the right answer -- do not add a lexicographic one to fill the table.

Since: Phase N2 (numeric-tower-rational-complex-plan)

defstruct

Complex

(defstruct Complex :copy [re :float im :float])

a re/im pair of doubles.

:copy -- two plain doubles, no owned resource, so a Complex is freely copyable and never interacts with the rc/ref/borrow machinery.

Since: Phase N2

defn

complex/of

(complex/of [re :float im :float] :Complex)

build the complex number re + im*i.

rereal part
imimaginary part

The Complex re + im*i. This is what the #cx{re im} literal expands to.

(complex/re (complex/of 3.25 -1.5))  ; => 3.25

Since: Phase N2

defn

complex/from-float

(complex/from-float [x :float] :Complex)

embed a real number in the complex plane.

xthe real value

x + 0i.

(complex/im (complex/from-float 2.5))  ; => 0

Since: Phase N2

defn

complex/zero

(complex/zero :Complex)

the complex number 0.

0 + 0i.

(complex/re (complex/zero))  ; => 0

Since: Phase N2

defn

complex/one

(complex/one :Complex)

the complex number 1.

1 + 0i.

(complex/re (complex/one))  ; => 1

Since: Phase N2

defn

complex/i

(complex/i :Complex)

the imaginary unit.

0 + 1i.

(complex/im (complex/i))  ; => 1

Since: Phase N2

defn

complex/re

(complex/re [z :Complex] :float)

the real part.

za Complex

The real component.

(complex/re (complex/of 3.25 -1.5))  ; => 3.25

Since: Phase N2

defn

complex/im

(complex/im [z :Complex] :float)

the imaginary part.

za Complex

The imaginary component.

(complex/im (complex/of 3.25 -1.5))  ; => -1.5

Since: Phase N2

defn

complex/real?

(complex/real? [z :Complex] :bool)

does this value lie on the real axis?

za Complex

true when the imaginary part is exactly 0.

(complex/real? (complex/from-float 2.5))  ; => true

Since: Phase N2

defn

complex/add

(complex/add [x :Complex y :Complex] :Complex)

sum of two complex numbers.

xleft addend
yright addend

(a+bi) + (c+di) = (a+c) + (b+d)i.

(complex/re (complex/add (complex/of 3.25 1.5) (complex/of 0.75 0.5)))  ; => 4

Since: Phase N2

defn

complex/sub

(complex/sub [x :Complex y :Complex] :Complex)

difference of two complex numbers.

xminuend
ysubtrahend

(a+bi) - (c+di) = (a-c) + (b-d)i.

(complex/im (complex/sub (complex/of 3.25 1.5) (complex/of 0.75 0.5)))  ; => 1

Since: Phase N2

defn

complex/neg

(complex/neg [x :Complex] :Complex)

negate a complex number.

xa Complex

-(a+bi) = -a - bi.

(complex/re (complex/neg (complex/of 3.25 -1.5)))  ; => -3.25

Since: Phase N2

defn

complex/conj

(complex/conj [x :Complex] :Complex)

complex conjugate.

xa Complex

conj(a+bi) = a - bi.

(complex/im (complex/conj (complex/of 3.25 -1.5)))  ; => 1.5

Since: Phase N2

defn

complex/mul

(complex/mul [x :Complex y :Complex] :Complex)

product of two complex numbers.

xleft factor
yright factor

(a+bi)(c+di) = (ac - bd) + (ad + bc)i, written out as arithmetic rather than deferred to a __muldc3-style compiler-runtime helper.

(complex/re (complex/mul (complex/of 3.25 1.5) (complex/of 0.5 2.0)))  ; => -1.375

Since: Phase N2

defn

complex/scale

(complex/scale [x :Complex k :float] :Complex)

multiply a complex number by a real scalar.

xa Complex
kthe real scale factor

k*(a+bi) = ka + kb*i.

(complex/re (complex/scale (complex/of 3.25 -1.5) 2.0))  ; => 6.5

Since: Phase N2

defn

complex/div

(complex/div [x :Complex y :Complex] :Complex)

quotient of two complex numbers (Smith's algorithm).

xdividend
ydivisor

x/y. The naive (ac+bd)/(c^2+d^2) form overflows whenever c or d is large enough that its square leaves the double range, even when the true quotient is perfectly ordinary. Smith's algorithm divides through by the larger-magnitude denominator component first, so the intermediates stay near the magnitude of the result: |c| >= |d|: r = d/c, den = c + d*r, x/y = ((a + b*r) + (b - a*r)i)/den |c| < |d|: r = c/d, den = c*r + d, x/y = ((a*r + b) + (b*r - a)i)/den Dividing by the zero complex number yields the IEEE infinity/NaN result float division already produces; it is not an error here.

(complex/re (complex/div (complex/of 3.25 1.5) (complex/of 0.5 0.0)))  ; => 6.5

Since: Phase N2

defn

complex/abs2

(complex/abs2 [z :Complex] :float)

squared magnitude |z|^2.

za Complex

re^2 + im^2, with no square root. Prefer this to complex/abs when only comparing magnitudes -- it is exact where the square root is not.

(complex/abs2 (complex/of 3.0 4.0))  ; => 25

Since: Phase N2

defn

complex/abs

(complex/abs [z :Complex] :float)

magnitude |z|.

za Complex

sqrt(re^2 + im^2), computed by scaling out the larger component first (|a| * sqrt(1 + (b/a)^2)) so a value whose square would overflow still reports its true magnitude.

(complex/abs (complex/of 3.0 4.0))  ; => 5

Since: Phase N2

defn

complex/arg

(complex/arg [z :Complex] :float)

principal argument (phase angle) of z, in radians.

za Complex

atan2(im, re), in (-pi, pi].

(complex/arg (complex/of 0.0 1.5))  ; => 1.5708

Since: Phase N2

defn

complex/exp

(complex/exp [z :Complex] :Complex)

e raised to a complex power.

za Complex

e^(a+bi) = e^a * (cos b + i sin b), built from the real libm wrappers in stdlib/math.tur rather than from a complex-valued runtime helper.

(complex/re (complex/exp (complex/of 0.0 0.0)))  ; => 1

Since: Phase N2

defn

complex/eq?

(complex/eq? [x :Complex y :Complex] :bool)

componentwise equality.

xleft value
yright value

true when both the real and the imaginary parts compare equal. This is IEEE float equality, with all the usual caveats.

(complex/eq? (complex/of 3.25 -1.5) (complex/of 3.25 -1.5))  ; => true

Since: Phase N2

defn

complex->string

(complex->string [z :Complex] :String)

render a Complex as "3.25+4.5i" / "3.25-4.5i".

za Complex

A fresh owned String. The sign of the imaginary part is ALWAYS explicit, so the output is unambiguous and never depends on how the imaginary part happens to format.

(complex->string (complex/of 3.25 -1.5))  ; => String "3.25-1.5i"

Since: Phase N2

definstance

Num[Complex]

(definstance Num [Complex])

hand-written complex arithmetic behind + - * /.

definstance

Eq[Complex]

(definstance Eq [Complex])

componentwise IEEE equality.

definstance

Show[Complex]

(definstance Show [Complex])

"3.25+4.5i" with an always-explicit imaginary sign.