///|
fn resample_indices(rng : RandomState, n : Int) -> Array[Int] {
  let result = Array::new(capacity=n)
  if n == 0 {
    return result
  }
  for _ in 0.. Double {
  mean(group_values(outcomes, treatment, true)) -
  mean(group_values(outcomes, treatment, false))
}

///|
fn resampled_values(
  values : Array[Double],
  indices : Array[Int],
) -> Array[Double] {
  let result = Array::new(capacity=indices.length())
  for index in indices {
    result.push(values[index])
  }
  result
}

///|
fn resampled_bool(values : Array[Bool], indices : Array[Int]) -> Array[Bool] {
  let result = Array::new(capacity=indices.length())
  for index in indices {
    result.push(values[index])
  }
  result
}

///|
/// Builds a reproducible nonparametric bootstrap distribution for the difference in means.
pub fn bootstrap_difference_in_means(
  outcomes : Array[Double],
  treatment : Array[Bool],
  replicates? : Int = 1000,
  seed? : UInt64 = 20260818UL,
) -> BootstrapSummary {
  let point = difference_in_means(outcomes, treatment)
  let rng = RandomState::new(seed)
  let samples : Array[Double] = Array::new(capacity=replicates)
  let mut successful = 0
  for _ in 0.. 0 && control > 0 {
      samples.push(difference_in_means(sample_outcomes, sample_treatment))
      successful += 1
    }
  }
  let standard_error = std_dev(samples, sample=true)
  {
    point_estimate: point,
    standard_error,
    lower: quantile(samples, 0.025),
    upper: quantile(samples, 0.975),
    replicates,
    successful_replicates: successful,
  }
}

///|
/// Calculates a randomization p-value under the sharp null using treatment permutations.
pub fn permutation_p_value(
  outcomes : Array[Double],
  treatment : Array[Bool],
  permutations? : Int = 1000,
  seed? : UInt64 = 20260818UL,
) -> Double {
  let observed = difference_in_means(outcomes, treatment).abs()
  let rng = RandomState::new(seed)
  let mut exceedances = 0
  for _ in 0..= observed {
      exceedances += 1
    }
  }
  (exceedances + 1).to_double() / (permutations + 1).to_double()
}

///|
/// Computes the leave-one-out influence values for the difference in means.
pub fn jackknife_influence(
  outcomes : Array[Double],
  treatment : Array[Bool],
) -> Array[Double] {
  let result = Array::new(capacity=outcomes.length())
  let full = difference_in_means(outcomes, treatment)
  for excluded in 0..