use crate::streams::*;
use core::mem::MaybeUninit;
pub struct SumStream<T, const N: usize, G, E>
where
T: AddAssign + Copy,
G: Getter<T, E>,
E: Clone + Debug,
{
addends: [G; N],
phantom_t: PhantomData<T>,
phantom_e: PhantomData<E>,
}
impl<T, const N: usize, G, E> SumStream<T, N, G, E>
where
T: AddAssign + Copy,
G: Getter<T, E>,
E: Clone + Debug,
{
pub const fn new(addends: [G; N]) -> Self {
if N < 1 {
panic!("rrtk::streams::SumStream must have at least one input stream");
}
Self {
addends,
phantom_t: PhantomData,
phantom_e: PhantomData,
}
}
}
impl<T, const N: usize, G, E> Getter<T, E> for SumStream<T, N, G, E>
where
T: AddAssign + Copy,
G: Getter<T, E>,
E: Clone + Debug,
{
fn get(&self) -> Output<T, E> {
let mut outputs = [MaybeUninit::uninit(); N];
let mut outputs_filled = 0;
for i in &self.addends {
if let Some(x) = i.get()? {
outputs[outputs_filled].write(x);
outputs_filled += 1;
}
}
if outputs_filled == 0 {
return Ok(None);
}
unsafe {
let mut value = outputs[0].assume_init();
for i in 1..outputs_filled {
value += outputs[i].assume_init();
}
Ok(Some(value))
}
}
}
impl<T, const N: usize, G, E> Updatable<E> for SumStream<T, N, G, E>
where
T: AddAssign + Copy,
G: Getter<T, E>,
E: Clone + Debug,
{
fn update(&mut self) -> NothingOrError<E> {
for getter in &mut self.addends {
getter.update()?;
}
Ok(())
}
}
pub struct Sum2<T1, T2, G1, G2, E>
where
T1: Add<T2>,
G1: Getter<T1, E>,
G2: Getter<T2, E>,
E: Clone + Debug,
{
addend1: G1,
addend2: G2,
phantom_t1: PhantomData<T1>,
phantom_t2: PhantomData<T2>,
phantom_e: PhantomData<E>,
}
impl<T1, T2, G1, G2, E> Sum2<T1, T2, G1, G2, E>
where
T1: Add<T2>,
G1: Getter<T1, E>,
G2: Getter<T2, E>,
E: Clone + Debug,
{
pub const fn new(addend1: G1, addend2: G2) -> Self {
Self {
addend1,
addend2,
phantom_t1: PhantomData,
phantom_t2: PhantomData,
phantom_e: PhantomData,
}
}
}
impl<T1, T2, TO, G1, G2, E> Getter<TO, E> for Sum2<T1, T2, G1, G2, E>
where
T1: Add<T2, Output = TO>,
G1: Getter<T1, E>,
G2: Getter<T2, E>,
E: Clone + Debug,
{
fn get(&self) -> Output<TO, E> {
let x = self.addend1.get()?;
let x = match x {
Some(x) => x,
None => {
return Ok(None);
}
};
let y = self.addend2.get()?;
let y = match y {
Some(y) => y,
None => return Ok(None),
};
Ok(Some(Datum::new(
core::cmp::max(x.time, y.time),
x.value + y.value,
)))
}
}
impl<T1, T2, G1, G2, E> Updatable<E> for Sum2<T1, T2, G1, G2, E>
where
T1: Add<T2>,
G1: Getter<T1, E>,
G2: Getter<T2, E>,
E: Clone + Debug,
{
fn update(&mut self) -> NothingOrError<E> {
self.addend1.update()?;
self.addend2.update()?;
Ok(())
}
}
pub struct DifferenceStream<TM, TS, GM, GS, E>
where
TM: Sub<TS>,
GM: Getter<TM, E>,
GS: Getter<TS, E>,
E: Clone + Debug,
{
minuend: GM,
subtrahend: GS,
phantom_tm: PhantomData<TM>,
phantom_ts: PhantomData<TS>,
phantom_e: PhantomData<E>,
}
impl<TM, TS, GM, GS, E> DifferenceStream<TM, TS, GM, GS, E>
where
TM: Sub<TS>,
GM: Getter<TM, E>,
GS: Getter<TS, E>,
E: Clone + Debug,
{
pub const fn new(minuend: GM, subtrahend: GS) -> Self {
Self {
minuend,
subtrahend,
phantom_tm: PhantomData,
phantom_ts: PhantomData,
phantom_e: PhantomData,
}
}
}
impl<TM, TS, TO, GM, GS, E> Getter<TO, E> for DifferenceStream<TM, TS, GM, GS, E>
where
TM: Sub<TS, Output = TO>,
GM: Getter<TM, E>,
GS: Getter<TS, E>,
E: Clone + Debug,
{
fn get(&self) -> Output<TO, E> {
let minuend_output = self.minuend.get()?;
let subtrahend_output = self.subtrahend.get()?;
match minuend_output {
Some(_) => {}
None => {
return Ok(None);
}
}
let minuend_output = minuend_output.unwrap();
match subtrahend_output {
Some(_) => {}
None => {
return Ok(None);
}
}
let subtrahend_output = subtrahend_output.unwrap();
let value = minuend_output.value - subtrahend_output.value;
let time = if minuend_output.time > subtrahend_output.time {
minuend_output.time
} else {
subtrahend_output.time
};
Ok(Some(Datum::new(time, value)))
}
}
impl<TM, TS, GM, GS, E> Updatable<E> for DifferenceStream<TM, TS, GM, GS, E>
where
TM: Sub<TS>,
GM: Getter<TM, E>,
GS: Getter<TS, E>,
E: Clone + Debug,
{
fn update(&mut self) -> NothingOrError<E> {
self.minuend.update()?;
self.subtrahend.update()?;
Ok(())
}
}
pub struct ProductStream<T, const N: usize, G, E>
where
T: MulAssign + Copy,
G: Getter<T, E>,
E: Clone + Debug,
{
factors: [G; N],
phantom_t: PhantomData<T>,
phantom_e: PhantomData<E>,
}
impl<T, const N: usize, G, E> ProductStream<T, N, G, E>
where
T: MulAssign + Copy,
G: Getter<T, E>,
E: Clone + Debug,
{
pub const fn new(factors: [G; N]) -> Self {
if N < 1 {
panic!("rrtk::streams::ProductStream must have at least one input stream");
}
Self {
factors,
phantom_t: PhantomData,
phantom_e: PhantomData,
}
}
}
impl<T, const N: usize, G, E> Getter<T, E> for ProductStream<T, N, G, E>
where
T: MulAssign + Copy,
G: Getter<T, E>,
E: Clone + Debug,
{
fn get(&self) -> Output<T, E> {
let mut outputs = [MaybeUninit::uninit(); N];
let mut outputs_filled = 0;
for i in &self.factors {
if let Some(x) = i.get()? {
outputs[outputs_filled].write(x);
outputs_filled += 1;
}
}
if outputs_filled == 0 {
return Ok(None);
}
unsafe {
let mut value = outputs[0].assume_init();
for i in 1..outputs_filled {
value *= outputs[i].assume_init();
}
Ok(Some(value))
}
}
}
impl<T, const N: usize, G, E> Updatable<E> for ProductStream<T, N, G, E>
where
T: MulAssign + Copy,
G: Getter<T, E>,
E: Clone + Debug,
{
fn update(&mut self) -> NothingOrError<E> {
for getter in &mut self.factors {
getter.update()?;
}
Ok(())
}
}
pub struct Product2<T1, T2, G1, G2, E>
where
T1: Mul<T2>,
G1: Getter<T1, E>,
G2: Getter<T2, E>,
E: Clone + Debug,
{
factor1: G1,
factor2: G2,
phantom_t1: PhantomData<T1>,
phantom_t2: PhantomData<T2>,
phantom_e: PhantomData<E>,
}
impl<T1, T2, G1, G2, E> Product2<T1, T2, G1, G2, E>
where
T1: Mul<T2>,
G1: Getter<T1, E>,
G2: Getter<T2, E>,
E: Clone + Debug,
{
pub const fn new(factor1: G1, factor2: G2) -> Self {
Self {
factor1,
factor2,
phantom_t1: PhantomData,
phantom_t2: PhantomData,
phantom_e: PhantomData,
}
}
}
impl<T1, T2, TO, G1, G2, E> Getter<TO, E> for Product2<T1, T2, G1, G2, E>
where
T1: Mul<T2, Output = TO>,
G1: Getter<T1, E>,
G2: Getter<T2, E>,
E: Clone + Debug,
{
fn get(&self) -> Output<TO, E> {
let x = self.factor1.get()?;
let x = match x {
Some(x) => x,
None => return Ok(None),
};
let y = self.factor2.get()?;
let y = match y {
Some(y) => y,
None => return Ok(None),
};
Ok(Some(Datum::new(
core::cmp::max(x.time, y.time),
x.value * y.value,
)))
}
}
impl<T1, T2, G1, G2, E> Updatable<E> for Product2<T1, T2, G1, G2, E>
where
T1: Mul<T2>,
G1: Getter<T1, E>,
G2: Getter<T2, E>,
E: Clone + Debug,
{
fn update(&mut self) -> NothingOrError<E> {
self.factor1.update()?;
self.factor2.update()?;
Ok(())
}
}
pub struct QuotientStream<TD, TS, GD, GS, E>
where
TD: Div<TS>,
GD: Getter<TD, E>,
GS: Getter<TS, E>,
E: Clone + Debug,
{
dividend: GD,
divisor: GS,
phantom_td: PhantomData<TD>,
phantom_ts: PhantomData<TS>,
phantom_e: PhantomData<E>,
}
impl<TD, TS, GD, GS, E> QuotientStream<TD, TS, GD, GS, E>
where
TD: Div<TS>,
GD: Getter<TD, E>,
GS: Getter<TS, E>,
E: Clone + Debug,
{
pub const fn new(dividend: GD, divisor: GS) -> Self {
Self {
dividend,
divisor,
phantom_td: PhantomData,
phantom_ts: PhantomData,
phantom_e: PhantomData,
}
}
}
impl<TD, TS, TO, GD, GS, E> Getter<TO, E> for QuotientStream<TD, TS, GD, GS, E>
where
TD: Div<TS, Output = TO>,
GD: Getter<TD, E>,
GS: Getter<TS, E>,
E: Clone + Debug,
{
fn get(&self) -> Output<TO, E> {
let dividend_output = self.dividend.get()?;
let divisor_output = self.divisor.get()?;
match dividend_output {
Some(_) => {}
None => {
return Ok(None);
}
}
let dividend_output = dividend_output.unwrap();
match divisor_output {
Some(_) => {}
None => {
return Ok(None);
}
}
let divisor_output = divisor_output.unwrap();
let value = dividend_output.value / divisor_output.value;
let time = if dividend_output.time > divisor_output.time {
dividend_output.time
} else {
divisor_output.time
};
Ok(Some(Datum::new(time, value)))
}
}
impl<TD, TS, GD, GS, E> Updatable<E> for QuotientStream<TD, TS, GD, GS, E>
where
TD: Div<TS>,
GD: Getter<TD, E>,
GS: Getter<TS, E>,
E: Clone + Debug,
{
fn update(&mut self) -> NothingOrError<E> {
self.dividend.update()?;
self.divisor.update()?;
Ok(())
}
}
#[cfg(feature = "internal_enhanced_float")]
pub struct ExponentStream<GB, GE, E>
where
GB: Getter<f32, E>,
GE: Getter<f32, E>,
E: Clone + Debug,
{
base: GB,
exponent: GE,
phantom_e: PhantomData<E>,
}
#[cfg(feature = "internal_enhanced_float")]
impl<GB, GE, E> ExponentStream<GB, GE, E>
where
GB: Getter<f32, E>,
GE: Getter<f32, E>,
E: Clone + Debug,
{
pub const fn new(base: GB, exponent: GE) -> Self {
Self {
base,
exponent,
phantom_e: PhantomData,
}
}
}
#[cfg(feature = "internal_enhanced_float")]
impl<GB, GE, E> Getter<f32, E> for ExponentStream<GB, GE, E>
where
GB: Getter<f32, E>,
GE: Getter<f32, E>,
E: Clone + Debug,
{
fn get(&self) -> Output<f32, E> {
let base_output = self.base.get()?;
let exponent_output = self.exponent.get()?;
match base_output {
Some(_) => {}
None => {
return Ok(None);
}
}
let base_output = base_output.unwrap();
match exponent_output {
Some(_) => {}
None => {
return Ok(Some(base_output));
}
}
let exponent_output = exponent_output.unwrap();
let value = powf(base_output.value, exponent_output.value);
let time = if base_output.time > exponent_output.time {
base_output.time
} else {
exponent_output.time
};
Ok(Some(Datum::new(time, value)))
}
}
#[cfg(feature = "internal_enhanced_float")]
impl<GB, GE, E> Updatable<E> for ExponentStream<GB, GE, E>
where
GB: Getter<f32, E>,
GE: Getter<f32, E>,
E: Clone + Debug,
{
fn update(&mut self) -> NothingOrError<E> {
self.base.update()?;
self.exponent.update()?;
Ok(())
}
}
pub struct DerivativeStream<T, O, G: Getter<T, E>, E: Clone + Debug> {
input: G,
value: Output<O, E>,
prev_output: Option<Datum<T>>,
}
impl<T, O, G: Getter<T, E>, E: Clone + Debug> DerivativeStream<T, O, G, E> {
pub const fn new(input: G) -> Self {
Self {
input,
value: Ok(None),
prev_output: None,
}
}
}
impl<T, O, G, E> Getter<O, E> for DerivativeStream<T, O, G, E>
where
DerivativeStream<T, O, G, E>: Updatable<E>,
O: Clone,
G: Getter<T, E>,
E: Clone + Debug,
{
fn get(&self) -> Output<O, E> {
self.value.clone()
}
}
impl<T, N1, O, G, E> Updatable<E> for DerivativeStream<T, O, G, E>
where
T: Copy + Sub<Output = N1>,
N1: Div<Time, Output = O>,
G: Getter<T, E>,
E: Clone + Debug,
{
fn update(&mut self) -> NothingOrError<E> {
self.input.update()?;
let output = self.input.get();
let output = match output {
Ok(ok) => ok,
Err(error) => {
self.value = Err(error.clone());
self.prev_output = None;
return Err(error);
}
};
let output = match output {
Some(some) => some,
None => {
self.value = Ok(None);
self.prev_output = None;
return Ok(());
}
};
let prev_output = match self.prev_output {
Some(some) => some,
None => {
self.prev_output = Some(output);
return Ok(());
}
};
let value = (output.value - prev_output.value) / (output.time - prev_output.time);
self.value = Ok(Some(Datum::new(output.time, value)));
self.prev_output = Some(output);
Ok(())
}
}
pub struct IntegralStream<T, O, G: Getter<T, E>, E: Clone + Debug> {
input: G,
value: Output<O, E>,
prev_output: Option<Datum<T>>,
}
impl<T, O, G: Getter<T, E>, E: Clone + Debug> IntegralStream<T, O, G, E> {
pub const fn new(input: G) -> Self {
Self {
input,
value: Ok(None),
prev_output: None,
}
}
}
impl<T, O, G, E> Getter<O, E> for IntegralStream<T, O, G, E>
where
IntegralStream<T, O, G, E>: Updatable<E>,
O: Clone,
G: Getter<T, E>,
E: Clone + Debug,
{
fn get(&self) -> Output<O, E> {
self.value.clone()
}
}
impl<T, O, N1, G, E> Updatable<E> for IntegralStream<T, O, G, E>
where
T: Copy + Add<Output = N1>,
Time: Mul<N1, Output = O>,
O: Copy + stulta::Half + Add<O, Output = O>,
G: Getter<T, E>,
E: Clone + Debug,
{
fn update(&mut self) -> NothingOrError<E> {
self.input.update()?;
let output = self.input.get();
let output = match output {
Ok(ok) => ok,
Err(error) => {
self.value = Err(error.clone());
self.prev_output = None;
return Err(error);
}
};
let output = match output {
Some(some) => some,
None => {
self.value = Ok(None);
self.prev_output = None;
return Ok(());
}
};
let prev_output = match self.prev_output {
Some(some) => some,
None => {
self.prev_output = Some(output);
return Ok(());
}
};
let delta_time = output.time - prev_output.time;
let value_addend = (delta_time * (prev_output.value + output.value)).half();
let value = match &self.value {
Ok(Some(real_value)) => value_addend + real_value.value,
_ => value_addend,
};
self.value = Ok(Some(Datum::new(output.time, value)));
self.prev_output = Some(output);
Ok(())
}
}