use crate::prelude::*;
use std::marker::PhantomData;
#[derive(Clone, Copy, Debug)]
pub struct Id<X> {
phantom: PhantomData<X>,
}
impl<X> Id<X> {
#[must_use]
pub const fn new() -> Self {
Self {
phantom: PhantomData,
}
}
}
impl<X> Default for Id<X> {
fn default() -> Self {
Self::new()
}
}
impl<X> Map for Id<X> {
type Input = X;
type Output = X;
fn eval(&self, x: X) -> X {
x
}
}
#[derive(Clone, Copy, Debug)]
pub struct Zero<X, S: smp::Sample> {
phantom: PhantomData<(X, S)>,
}
impl<X, S: smp::Sample> Zero<X, S> {
#[must_use]
pub const fn new() -> Self {
Self {
phantom: PhantomData,
}
}
}
impl<X, S: smp::Sample> Default for Zero<X, S> {
fn default() -> Self {
Self::new()
}
}
impl<X, S: smp::Sample> Map for Zero<X, S> {
type Input = X;
type Output = S;
fn eval(&self, _: X) -> S {
-S::ZERO
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Const<X, Y: Clone> {
pub val: Y,
phantom: PhantomData<X>,
}
impl<X, Y: Clone> Const<X, Y> {
pub const fn new(val: Y) -> Self {
Self {
val,
phantom: PhantomData,
}
}
}
impl<X, Y: Clone> Map for Const<X, Y> {
type Input = X;
type Output = Y;
fn eval(&self, _: X) -> Y {
self.val.clone()
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Comp<F: Map, G: Map<Input = F::Output>> {
pub inner: F,
pub outer: G,
}
impl<F: Map, G: Map<Input = F::Output>> Comp<F, G> {
pub const fn new(inner: F, outer: G) -> Self {
Self { inner, outer }
}
}
impl<F: Map, G: Map<Input = F::Output>> Map for Comp<F, G> {
type Input = F::Input;
type Output = G::Output;
fn eval(&self, x: F::Input) -> G::Output {
self.outer.eval(self.inner.eval(x))
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Pos;
impl Map for Pos {
type Input = f64;
type Output = f64;
fn eval(&self, x: f64) -> f64 {
map::pos(x)
}
}
impl<F: Map<Output = f64>> map::Comp<F, Pos> {
pub const fn pos(f: F) -> Self {
Self::new(f, Pos)
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Sgn;
impl Map for Sgn {
type Input = f64;
type Output = f64;
fn eval(&self, x: f64) -> f64 {
map::sgn(x)
}
}
impl<F: Map<Output = f64>> map::Comp<F, Sgn> {
pub const fn sgn(f: F) -> Self {
Self::new(f, Sgn)
}
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Neg;
impl Neg {
#[must_use]
pub const fn new() -> Self {
Self
}
}
impl Map for Neg {
type Input = f64;
type Output = f64;
fn eval(&self, x: f64) -> f64 {
-x
}
}
impl<F: Map<Output = f64>> map::Comp<F, Neg> {
pub const fn neg(f: F) -> Self {
Self::new(f, Neg)
}
}
#[derive(Clone, Copy, Debug)]
pub struct Linear {
pub slope: f64,
pub intercept: f64,
}
impl Linear {
#[must_use]
pub const fn new(slope: f64, intercept: f64) -> Self {
Self { slope, intercept }
}
#[must_use]
pub fn rescale(init_lo: f64, init_hi: f64, end_lo: f64, end_hi: f64) -> Self {
let slope = (end_hi - end_lo) / (init_hi - init_lo);
Self::new(slope, end_lo - slope * init_lo)
}
#[must_use]
pub fn rescale_unit(lo: f64, hi: f64) -> Self {
Self::rescale(0.0, 1.0, lo, hi)
}
#[must_use]
pub fn rescale_sgn(lo: f64, hi: f64) -> Self {
Self::rescale(-1.0, 1.0, lo, hi)
}
}
impl Map for Linear {
type Input = f64;
type Output = f64;
fn eval(&self, x: f64) -> f64 {
x * self.slope + self.intercept
}
}