Complex numbers — records carrying real and imaginary parts
Soma has no native complex type, so a Complex is a record { re, im }. Addition is componentwise; multiplication uses the FOIL identity (a+bi)(c+di) = (ac−bd) + (ad+bc)i; modulus is sqrt(re²+im²). Records carry a _type field so is_a recognizes them.
A Soma program from the math part of the verified corpus: 63 lines, cells Complex, ComplexTests. It passes soma check with soma 3.2.4.
How it is built
The cell Complex declares 4 signals in its face: cadd(x: Map, y: Map) -> Map, cmul(x: Map, y: Map) -> Map, cmod(x: Map) -> Float and run() -> Map. Handlers: cadd (line 21), cmul (line 25), cmod (line 32) and run (line 36).
The file also holds 1 test cell (ComplexTests) with 7 assertions, run by soma test.
The source
complex.cell
// ============================================================================
// Complex numbers — records carrying real and imaginary parts
// ============================================================================
//
// Soma has no native complex type, so a Complex is a record { re, im }.
// Addition is componentwise; multiplication uses the FOIL identity
// (a+bi)(c+di) = (ac−bd) + (ad+bc)i; modulus is sqrt(re²+im²). Records carry
// a _type field so is_a recognizes them.
//
// soma run complex.cell run
// ============================================================================
cell Complex {
face {
signal cadd(x: Map, y: Map) -> Map
signal cmul(x: Map, y: Map) -> Map
signal cmod(x: Map) -> Float
signal run() -> Map
}
on cadd(x: Map, y: Map) {
return Complex { re: x.re + y.re, im: x.im + y.im }
}
on cmul(x: Map, y: Map) {
return Complex {
re: x.re * y.re - x.im * y.im,
im: x.re * y.im + x.im * y.re
}
}
on cmod(x: Map) {
return sqrt(x.re * x.re + x.im * x.im)
}
on run() {
let a = Complex { re: 1.0, im: 2.0 }
let b = Complex { re: 3.0, im: 0 - 1.0 }
return map(
"sum", cadd(a, b),
"product", cmul(a, b),
"mod_a", cmod(a)
)
}
}
cell test ComplexTests {
rules {
// (1+2i) + (3-i) = 4 + i
assert cadd(Complex { re: 1.0, im: 2.0 }, Complex { re: 3.0, im: 0 - 1.0 }).re == 4.0
assert cadd(Complex { re: 1.0, im: 2.0 }, Complex { re: 3.0, im: 0 - 1.0 }).im == 1.0
// (1+2i)(3-i) = 3 - i + 6i - 2i^2 = 5 + 5i
assert cmul(Complex { re: 1.0, im: 2.0 }, Complex { re: 3.0, im: 0 - 1.0 }).re == 5.0
assert cmul(Complex { re: 1.0, im: 2.0 }, Complex { re: 3.0, im: 0 - 1.0 }).im == 5.0
// |3+4i| = 5
assert cmod(Complex { re: 3.0, im: 4.0 }) == 5.0
// i^2 = -1
assert cmul(Complex { re: 0, im: 1.0 }, Complex { re: 0, im: 1.0 }).re == 0 - 1.0
// records are typed
assert is_a(Complex { re: 1.0, im: 0 }, "Complex")
}
}What the toolchain says
$ soma check complex.cell
✓ All checks passed.$ soma test complex.cell
test ComplexTests ...
✓ assert cadd(Complex { re: 1.0, im: 2.0 }, Complex { re: 3.0, im: 0 - 1.0 }).re == 4.0
✓ assert cadd(Complex { re: 1.0, im: 2.0 }, Complex { re: 3.0, im: 0 - 1.0 }).im == 1.0
✓ assert cmul(Complex { re: 1.0, im: 2.0 }, Complex { re: 3.0, im: 0 - 1.0 }).re == 5.0
✓ assert cmul(Complex { re: 1.0, im: 2.0 }, Complex { re: 3.0, im: 0 - 1.0 }).im == 5.0
✓ assert cmod(Complex { re: 3.0, im: 4.0 }) == 5.0
✓ assert cmul(Complex { re: 0, im: 1.0 }, Complex { re: 0, im: 1.0 }).re == 0 - 1.0
✓ assert is_a(Complex { re: 1.0, im: 0 }, "Complex")
7 tests: 7 passed, 0 failed$ soma verify complex.cell
Verifying complex.cell...
No state machine in this program: nothing to prove beyond `soma check` (invariants and lifecycles are what verify proves).
VERIFY OK (vacuous — no state machine)$ soma run complex.cell run
{"sum": {"_type": "Complex", "re": 4.0, "im": 1.0}, "product": {"_type": "Complex", "re": 5.0, "im": 5.0}, "mod_a": 2.23606797749979}