Quadratic equations — discriminant and the two real roots
For ax² + bx + c = 0 the discriminant D = b² − 4ac decides the root count: D > 0 two real roots, D == 0 one repeated, D < 0 none real. Vieta's relations cross-check: roots sum to −b/a and multiply to c/a.
A Soma program from the math part of the verified corpus: 54 lines, cells Quadratic, QuadraticTests. It passes soma check with soma 3.2.4.
How it is built
The cell Quadratic declares 3 signals in its face: discriminant(a: Float, b: Float, c: Float) -> Float, roots(a: Float, b: Float, c: Float) -> List and run() -> Map. Handlers: discriminant (line 19), roots (line 23) and run (line 32).
The file also holds 1 test cell (QuadraticTests) with 6 assertions, run by soma test.
The source
quadratic.cell
// ============================================================================
// Quadratic equations — discriminant and the two real roots
// ============================================================================
//
// For ax² + bx + c = 0 the discriminant D = b² − 4ac decides the root count:
// D > 0 two real roots, D == 0 one repeated, D < 0 none real. Vieta's
// relations cross-check: roots sum to −b/a and multiply to c/a.
//
// soma run quadratic.cell run
// ============================================================================
cell Quadratic {
face {
signal discriminant(a: Float, b: Float, c: Float) -> Float
signal roots(a: Float, b: Float, c: Float) -> List
signal run() -> Map
}
on discriminant(a: Float, b: Float, c: Float) {
return b * b - 4.0 * a * c
}
on roots(a: Float, b: Float, c: Float) {
let d = discriminant(a, b, c)
if d < 0.0 { return [] } // no real roots
let sq = sqrt(d)
let r1 = (0 - b + sq) / (2.0 * a)
let r2 = (0 - b - sq) / (2.0 * a)
return [r1, r2]
}
on run() {
// x^2 - 5x + 6 = 0 -> roots 3 and 2
let r = roots(1.0, 0 - 5.0, 6.0)
return map("discriminant", discriminant(1.0, 0 - 5.0, 6.0), "roots", r)
}
}
cell test QuadraticTests {
rules {
// x^2 - 5x + 6: D = 25 - 24 = 1
assert discriminant(1.0, 0 - 5.0, 6.0) == 1.0
// roots are 3 and 2
assert abs(roots(1.0, 0 - 5.0, 6.0)[0] - 3.0) < 0.0000001
assert abs(roots(1.0, 0 - 5.0, 6.0)[1] - 2.0) < 0.0000001
// Vieta: sum of roots = -b/a = 5
assert abs(sum(roots(1.0, 0 - 5.0, 6.0)) - 5.0) < 0.0000001
// Vieta: product of roots = c/a = 6
assert abs(product(roots(1.0, 0 - 5.0, 6.0)) - 6.0) < 0.0000001
// negative discriminant -> no real roots
assert len(roots(1.0, 0.0, 1.0)) == 0
}
}What the toolchain says
$ soma check quadratic.cell
✓ All checks passed.$ soma test quadratic.cell
test QuadraticTests ...
✓ assert discriminant(1.0, 0 - 5.0, 6.0) == 1.0
✓ assert abs(roots(1.0, 0 - 5.0, 6.0)[0] - 3.0) < 0.0000001
✓ assert abs(roots(1.0, 0 - 5.0, 6.0)[1] - 2.0) < 0.0000001
✓ assert abs(sum(roots(1.0, 0 - 5.0, 6.0)) - 5.0) < 0.0000001
✓ assert abs(product(roots(1.0, 0 - 5.0, 6.0)) - 6.0) < 0.0000001
✓ assert len(roots(1.0, 0.0, 1.0)) == 0
6 tests: 6 passed, 0 failed$ soma verify quadratic.cell
Verifying quadratic.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 quadratic.cell run
{"discriminant": 1.0, "roots": [3.0, 2.0]}