use super::InterpolationError;
use qtty::{Quantity, Unit};
use std::cmp::Ordering;
mod sealed {
pub trait Sealed {}
impl Sealed for f64 {}
impl<U: qtty::Unit> Sealed for qtty::Quantity<U> {}
}
pub trait AbscissaDelta: Copy {
fn scale(self, factor: f64) -> Self;
fn diagnostic_raw(self) -> f64;
}
impl AbscissaDelta for f64 {
#[inline]
fn scale(self, factor: f64) -> Self {
self * factor
}
#[inline]
fn diagnostic_raw(self) -> f64 {
self
}
}
impl<U: Unit> AbscissaDelta for Quantity<U> {
#[inline]
fn scale(self, factor: f64) -> Self {
self * factor
}
#[inline]
fn diagnostic_raw(self) -> f64 {
self.value()
}
}
pub trait InterpolationAbscissa: sealed::Sealed + Copy {
type Delta: AbscissaDelta;
fn is_finite(self) -> bool;
fn cmp_abscissa(self, other: Self) -> Ordering;
fn delta_since(self, origin: Self) -> Self::Delta;
fn normalize_between(self, start: Self, end: Self) -> Result<f64, InterpolationError>;
fn diagnostic_raw(self) -> f64;
}
impl InterpolationAbscissa for f64 {
type Delta = f64;
#[inline]
fn is_finite(self) -> bool {
self.is_finite()
}
#[inline]
fn cmp_abscissa(self, other: Self) -> Ordering {
self.total_cmp(&other)
}
#[inline]
fn delta_since(self, origin: Self) -> Self::Delta {
self - origin
}
#[inline]
fn normalize_between(self, start: Self, end: Self) -> Result<f64, InterpolationError> {
Ok((self - start) / (end - start))
}
#[inline]
fn diagnostic_raw(self) -> f64 {
self
}
}
impl<U: Unit> InterpolationAbscissa for Quantity<U> {
type Delta = Quantity<U>;
#[inline]
fn is_finite(self) -> bool {
self.value().is_finite()
}
#[inline]
fn cmp_abscissa(self, other: Self) -> Ordering {
self.value().total_cmp(&other.value())
}
#[inline]
fn delta_since(self, origin: Self) -> Self::Delta {
self - origin
}
#[inline]
fn normalize_between(self, start: Self, end: Self) -> Result<f64, InterpolationError> {
let offset = self - start;
let width = end - start;
Ok(offset.value() / width.value())
}
#[inline]
fn diagnostic_raw(self) -> f64 {
self.value()
}
}