use super::minted::{MINTED, UNMEASURED};
use crate::lattice::MAX_CONJUNCTS;
use crate::shuffle::{self, Kernel};
use crate::skip::Skip;
#[derive(Debug, Clone, Copy)]
pub struct Calibration {
pub arch: &'static str,
pub kernel: Kernel,
pub host: &'static str,
pub minted: &'static str,
pub dfa_skip: f64,
pub dfa_walk: f64,
pub dfa_excursion: f64,
pub skip_excursion: [f64; 2],
pub sieve: [f64; MAX_CONJUNCTS],
}
#[must_use]
pub fn active() -> Calibration {
let kernel = shuffle::kernel();
MINTED
.iter()
.copied()
.find(|cal| cal.arch == std::env::consts::ARCH && cal.kernel == kernel)
.unwrap_or(UNMEASURED)
}
impl Calibration {
#[must_use]
pub fn is_measured(&self) -> bool {
self.sieve.iter().any(|&cost| cost > 0.0) && self.dfa_walk > 0.0
}
#[must_use]
pub fn sieve_per_byte(&self, conjuncts: usize) -> f64 {
let want = conjuncts.clamp(1, MAX_CONJUNCTS) - 1;
if let Some(below) = (0..=want).rev().find(|&i| self.sieve[i] > 0.0) {
return self.sieve[below] * (1u64 << (want - below)) as f64;
}
self.sieve[want..]
.iter()
.copied()
.find(|&cost| cost > 0.0)
.unwrap_or(f64::INFINITY)
}
#[must_use]
pub fn rival_per_byte(&self, accelerator: &[u8], freq: &[f64; 256]) -> f64 {
if accelerator.is_empty() {
return self.dfa_walk;
}
let escape: f64 = accelerator
.iter()
.map(|&b| freq[usize::from(b)])
.sum::<f64>()
.clamp(0.0, 1.0);
let cost = self.dfa_skip * (1.0 - escape) + self.dfa_walk * escape * self.dfa_excursion;
cost.min(self.dfa_walk)
}
#[must_use]
pub fn skip_per_byte(&self, skip: &Skip, freq: &[f64; 256]) -> f64 {
let leaves = skip.leaves();
if leaves.is_empty() {
return self.dfa_skip;
}
let escape: f64 = leaves
.iter()
.map(|&b| freq[usize::from(b)])
.sum::<f64>()
.clamp(0.0, 1.0);
let excursion = self.skip_excursion[skip.instrument() as usize];
let cost = self.dfa_skip * (1.0 - escape) + self.dfa_walk * escape * excursion;
cost.min(self.dfa_walk)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::price::{CostFact, MACOS_AARCH64, NOMINAL_LEN};
use crate::prior;
const UNMINTED: Calibration = UNMEASURED;
#[test]
fn a_target_nobody_measured_is_infinite_never_free() {
for n in 1..=MAX_CONJUNCTS {
assert!(
UNMINTED.sieve_per_byte(n).is_infinite(),
"a zero coefficient would pass every worth test"
);
}
assert!(
!UNMEASURED.is_measured(),
"the unmeasured row must admit it is unmeasured"
);
assert!(MACOS_AARCH64.is_measured());
}
#[test]
fn scaling_the_whole_calibration_changes_no_decision() {
let freq = prior::Prior::Source.byte_freq();
for k in [0.25f64, 1.0, 3.7, 91.0] {
let scaled = Calibration {
dfa_skip: MACOS_AARCH64.dfa_skip * k,
dfa_walk: MACOS_AARCH64.dfa_walk * k,
dfa_excursion: MACOS_AARCH64.dfa_excursion,
sieve: MACOS_AARCH64.sieve.map(|c| c * k),
..MACOS_AARCH64
};
for accel in [&b""[..], b"W", b"e", b"abg"] {
for fallthrough in [0.0, 1e-6, 1e-3, 0.5] {
let of = |cal: &Calibration| CostFact {
fallthrough,
len: NOMINAL_LEN,
sieve: cal.sieve_per_byte(MAX_CONJUNCTS),
rival: cal.rival_per_byte(accel, &freq),
};
let (base, now) = (of(&MACOS_AARCH64), of(&scaled));
assert_eq!(
base.pays(),
now.pays(),
"k={k} accel={accel:?} f={fallthrough} flipped the gate"
);
assert!(
(base.speedup() - now.speedup()).abs() < 1e-9,
"k={k} moved the predicted speedup: {} vs {}",
base.speedup(),
now.speedup()
);
}
}
}
}
#[test]
fn resolution_matches_this_machine_or_admits_it_cannot() {
let cal = active();
if cal.is_measured() {
assert_eq!(cal.arch, std::env::consts::ARCH);
assert_eq!(cal.kernel, crate::shuffle::kernel());
} else {
assert!(
!MINTED
.iter()
.any(|c| c.arch == std::env::consts::ARCH
&& c.kernel == crate::shuffle::kernel()),
"a row exists for this machine but resolution missed it"
);
}
}
#[test]
fn extrapolation_errs_high_in_both_directions() {
let cal = Calibration {
sieve: [0.0, 0.5],
..UNMINTED
};
assert_eq!(cal.sieve_per_byte(1), 0.5);
assert_eq!(cal.sieve_per_byte(2), 0.5);
let cal = Calibration {
sieve: [0.5, 0.0],
..UNMINTED
};
assert_eq!(cal.sieve_per_byte(1), 0.5);
assert_eq!(cal.sieve_per_byte(2), 1.0);
}
}