#[doc(alias = "gsl_interp_accel")]
#[derive(Clone, Copy)]
pub struct Accelerator {
pub(crate) cache: usize,
pub(crate) hits: usize,
pub(crate) misses: usize,
}
impl Accelerator {
pub fn new() -> Self {
Accelerator {
cache: 0,
hits: 0,
misses: 0,
}
}
#[doc(alias = "gsl_interp_bsearch")]
pub(crate) fn bsearch<T>(&self, xarray: &[T], x: T, ilo: usize, ihi: usize) -> usize
where
T: num::Float,
{
let mut ilo = ilo;
let mut ihi = ihi;
while ihi > ilo + 1 {
let i = (ihi + ilo) / 2;
if xarray[i] > x {
ihi = i;
} else {
ilo = i;
}
}
ilo
}
#[doc(alias = "gsl_interp_accel_find")]
pub(crate) fn find<T>(&mut self, xarray: &[T], x: T) -> usize
where
T: num::Float,
{
if x < xarray[self.cache] {
self.misses += 1;
self.cache = self.bsearch(xarray, x, 0, self.cache);
} else if x >= xarray[self.cache + 1] {
self.misses += 1;
self.cache = self.bsearch(xarray, x, self.cache, xarray.len() - 1);
} else {
self.hits += 1;
}
self.cache
}
#[doc(alias = "gsl_interp_accel_reset")]
pub fn reset(&mut self) {
self.cache = 0;
self.hits = 0;
self.misses = 0;
}
pub fn hits(&self) -> usize {
self.hits
}
pub fn misses(&self) -> usize {
self.misses
}
pub fn cache(&self) -> usize {
self.cache
}
}
impl std::fmt::Debug for Accelerator {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Accelerator")
.field("cache", &self.cache)
.field("hits ", &self.hits)
.field("misses", &self.misses)
.finish()
}
}
impl Default for Accelerator {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_instantiation() {
let acc = Accelerator::default();
let _ = format!("{:?}", acc);
assert_eq!(acc.hits(), 0);
assert_eq!(acc.misses(), 0);
assert_eq!(acc.cache(), 0);
}
#[test]
fn test_reset() {
let mut acc = Accelerator::new();
acc.cache = 1;
acc.hits = 1;
acc.misses = 1;
acc.reset();
assert_eq!(acc.cache, 0);
assert_eq!(acc.hits, 0);
assert_eq!(acc.misses, 0);
}
}