///|
/// One directional lexicographic relaxation; reverse=true is its adjoint order.
pub fn smooth_gauss_seidel(
  operator : Operator,
  rhs : Field,
  initial : Field,
  sweeps : Int32,
  reverse~ : Bool = false,
) -> Field raise SolverError {
  require_same(operator.grid, rhs.grid)
  require_same(operator.grid, initial.grid)
  validate_sweeps(operator.grid, sweeps)
  let g = operator.grid
  let values = initial.values.copy()
  for _sweep in 0.. Field raise SolverError {
  validate_sweeps(operator.grid, pairs)
  if pairs > 5000 {
    raise Budget("symmetric sweep-pair budget exceeded")
  }
  let mut current = initial
  for _pair in 0.. Field raise SolverError {
  match self {
    Jacobi(omega) => smooth_jacobi(operator, rhs, initial, sweeps, omega~)
    SymmetricGaussSeidel => smooth_symmetric(operator, rhs, initial, sweeps)
  }
}

///|
pub extend Smoother with @debug.Debug::{to_repr}

///|
pub extend Smoother with Eq::{equal, not_equal}