pub mod permute;
pub mod schedules;
pub mod select;
pub mod value;
use rustev_contract::ranking::{Bias, PairwiseSchedule, RankMode};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BoundError {
InvalidBias,
Overflow,
}
pub fn pairwise_bound(n: u64, schedule: PairwiseSchedule) -> Result<u64, BoundError> {
let count = match schedule {
PairwiseSchedule::RoundRobin => u128::from(n) * u128::from(n.saturating_sub(1)) / 2,
PairwiseSchedule::MergeSort => {
let n = u128::from(n);
let mut width = 1u128;
let mut total = 0u128;
while width < n {
let span = width * 2;
let remainder = n % span;
total += (n / span) * (span - 1);
if remainder > width {
total += remainder - 1;
}
width = span;
}
total
}
};
u64::try_from(count).map_err(|_| BoundError::Overflow)
}
pub fn max_requests(n: u64, mode: &RankMode, bias: &Bias) -> Result<u64, BoundError> {
let orders = match bias {
Bias::None | Bias::Shuffle { .. } => 1,
Bias::PermutationAverage { orders, .. } if (2..=8).contains(orders) => *orders,
Bias::PermutationAverage { .. } => return Err(BoundError::InvalidBias),
};
match mode {
RankMode::Listwise { .. } => Ok(orders),
RankMode::Pointwise if *bias == Bias::None => Ok(n),
RankMode::Pointwise => Err(BoundError::InvalidBias),
RankMode::Pairwise { schedule, .. } => {
if orders > 2 {
return Err(BoundError::InvalidBias);
}
pairwise_bound(n, *schedule)?
.checked_mul(orders)
.ok_or(BoundError::Overflow)
}
}
}