///|
/// Separate tail calibration, using a union bound for the requested total error.
pub struct TailScores {
  priv low : Scores
  priv high : Scores
}

///|
pub fn tail_scores(
  truth : Array[Double],
  prediction : Array[Double],
) -> TailScores raise ConformalError {
  validate_values(truth, "truth")
  validate_values(prediction, "prediction")
  same_length(truth.length(), prediction.length())
  let low = []
  let high = []
  for i in 0.. Int32 {
  self.low.count()
}

///|
/// low_fraction allocates total alpha to the lower-tail failure event.
pub fn predict_tails(
  scores : TailScores,
  prediction : Array[Double],
  alpha : Double,
  low_fraction : Double,
) -> Array[Interval] raise ConformalError {
  validate_alpha(alpha)
  validate_alpha(low_fraction)
  validate_values(prediction, "prediction")
  let low_alpha = alpha * low_fraction
  let high_alpha = alpha * (1.0 - low_fraction)
  let lo = scores.low.threshold(low_alpha)
  let hi = scores.high.threshold(high_alpha)
  let out = []
  for center in prediction {
    let lower = if lo.is_pos_inf() { @double.neg_infinity } else { center - lo }
    let upper = if hi.is_pos_inf() { @double.infinity } else { center + hi }
    if (!lo.is_pos_inf() && !finite(lower)) ||
      (!hi.is_pos_inf() && !finite(upper)) {
      raise Invalid("tail endpoint overflow")
    }
    out.push({ lower, upper, })
  }
  out
}