///|
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..