///|
/// Stable order: larger probability first, then smaller label index.
/// Deterministic cumulative APS uses the full probability of the candidate label.
fn cumulative_scores(
  row : Array[Double],
  penalty : Double,
  regularized_after : Int32,
) -> Array[Double] raise ConformalError {
  let order = Array::makei(row.length(), i => i)
  order.sort_by((a, b) => {
    if row[a] > row[b] {
      -1
    } else if row[a] < row[b] {
      1
    } else {
      a - b
    }
  })
  let scores = Array::make(row.length(), 0.0)
  let mut mass = 0.0
  for rank in 0.. regularized_after {
      (rank + 1 - regularized_after).to_double() * penalty
    } else {
      0.0
    }
    let score = mass + extra
    if !finite(score) {
      raise Invalid("regularized score overflow")
    }
    scores[label] = score
  }
  scores
}