///|
pub(all) struct TopsisResult {
  ranking : Ranking
  normalized : Array[Array[Double]]
  weighted : Array[Array[Double]]
  ideal : Array[Double]
  anti_ideal : Array[Double]
  distance_ideal : Array[Double]
  distance_anti_ideal : Array[Double]
} derive(@debug.Debug)

///|
pub fn topsis(
  m : DecisionMatrix,
  weights : Array[Double],
  normalization~ : Normalization = MinMax,
  tolerance~ : Double = 1.0e-10,
) -> TopsisResult raise ChoiceError {
  let w = matrix_weights(m, weights)
  let x = m.normalize(normalization)
  let (n, p) = m.shape()
  let weighted = zeros(n, p)
  let ideal = Array::make(p, 0.0)
  let anti_ideal = Array::make(p, 0.0)
  for j in 0..

x[i][j] * w[j] ] ideal[j] = maximum(col) anti_ideal[j] = minimum(col) for i in 0..