///|
pub struct Equation {
  coefficients : Symbols
  payload : Symbols
}

///|
pub fn Equation::new(
  coefficients : Symbols,
  payload : Symbols,
) -> Equation raise CodeError {
  if coefficients.length() < 1 || coefficients.length() > 64 {
    raise Limit("equation coefficient count must be 1..64")
  }
  if payload.length() < 1 || payload.length() > 4096 {
    raise Limit("equation payload width must be 1..4096")
  }
  { coefficients, payload, }
}

///|
pub fn Equation::coefficients(self : Equation) -> Symbols {
  self.coefficients
}

///|
pub fn Equation::payload(self : Equation) -> Symbols {
  self.payload
}

///|
pub enum Admission {
  Innovative(Int32, Int32)
  Dependent
}

///|
pub struct Basis {
  columns : Int32
  width : Int32
  rows : Array[Equation?]
  mut rank_value : Int32
}

///|
pub fn Basis::new(columns : Int32, width : Int32) -> Basis raise CodeError {
  if columns < 1 || columns > 64 {
    raise Limit("basis columns must be 1..64")
  }
  if width < 1 || width > 4096 {
    raise Limit("basis payload width must be 1..4096")
  }
  { columns, width, rows: Array::make(columns, None), rank_value: 0, }
}

///|
pub fn Basis::rank(self : Basis) -> Int32 {
  self.rank_value
}

///|
pub fn Basis::deficit(self : Basis) -> Int32 {
  self.columns - self.rank_value
}

///|
pub fn Basis::pivots(self : Basis) -> Array[Int32] {
  let out : Array[Int32] = []
  for i in 0.. Array[Equation] {
  let out : Array[Equation] = []
  for row in self.rows {
    if row is Some(equation) {
      out.push(equation)
    }
  }
  out
}

///|
// Compute everything privately, then publish the new RREF state atomically.
// A dependent nonzero residual is a contradiction, never an innovation.
pub fn Basis::admit(
  self : Basis,
  equation : Equation,
) -> Admission raise CodeError {
  if equation.coefficients.length() != self.columns ||
    equation.payload.length() != self.width {
    raise Shape("equation does not match basis dimensions")
  }
  let coefficients = equation.coefficients.to_array()
  let payload = equation.payload.to_array()
  for i in 0.. Array[Symbols] raise CodeError {
  if self.deficit() != 0 {
    raise Incomplete(self.deficit())
  }
  let out : Array[Symbols] = []
  for row in self.rows {
    match row {
      Some(equation) => out.push(equation.payload)
      None => raise Incomplete(self.deficit())
    }
  }
  out
}

///|
// Rows containing just one coefficient already determine a source symbol.
pub fn Basis::known(self : Basis) -> Array[(Int32, Symbols)] {
  let out : Array[(Int32, Symbols)] = []
  for i in 0..