///|
fn validate_bounds(
  lower : Array[Double],
  upper : Array[Double],
) -> Unit raise ConformalError {
  validate_values(lower, "lower predictions")
  validate_values(upper, "upper predictions")
  same_length(lower.length(), upper.length())
  for i in 0.. upper[i] {
      raise Invalid("base quantile predictions cross")
    }
  }
}

///|
/// Signed CQR score max(lower-y, y-upper); negative scores must not be clipped.
pub fn cqr_scores(
  truth : Array[Double],
  lower : Array[Double],
  upper : Array[Double],
) -> Scores raise ConformalError {
  validate_values(truth, "truth")
  validate_bounds(lower, upper)
  same_length(truth.length(), lower.length())
  let out = []
  for i in 0.. b { a } else { b }
    if !finite(a) || !finite(b) {
      raise Invalid("CQR residual overflow")
    }
    out.push(score)
  }
  Scores::new(out)
}

///|
pub fn predict_cqr(
  scores : Scores,
  lower : Array[Double],
  upper : Array[Double],
  alpha : Double,
) -> Array[Interval] raise ConformalError {
  validate_bounds(lower, upper)
  let q = scores.threshold(alpha)
  let out = []
  for i in 0..