use nalgebra::{RealField, SMatrix};
use num_complex::Complex;
use std::{
fmt::Debug,
ops::{Add, AddAssign, Div, Mul, Neg, Sub},
};
pub trait Real: Copy + RealField {
fn infinity() -> Self;
}
impl<T: Copy + RealField> Real for T {
#[inline]
fn infinity() -> Self {
Self::from_subset(&f64::INFINITY)
}
}
pub trait State<T: Real>:
Clone
+ Copy
+ Debug
+ Add<Output = Self>
+ Sub<Output = Self>
+ AddAssign
+ Mul<T, Output = Self>
+ Div<T, Output = Self>
+ Neg<Output = Self>
{
fn len(&self) -> usize;
fn get(&self, i: usize) -> T;
fn set(&mut self, i: usize, value: T);
fn zeros() -> Self;
}
impl<T: Real> State<T> for T {
fn len(&self) -> usize {
1
}
fn get(&self, i: usize) -> T {
if i == 0 {
*self
} else {
panic!("Index out of bounds")
}
}
fn set(&mut self, i: usize, value: T) {
if i == 0 {
*self = value;
} else {
panic!("Index out of bounds")
}
}
fn zeros() -> Self {
T::zero()
}
}
impl<T, const R: usize, const C: usize> State<T> for SMatrix<T, R, C>
where
T: Real,
{
fn len(&self) -> usize {
R * C
}
fn get(&self, i: usize) -> T {
self[(i / C, i % C)]
}
fn set(&mut self, i: usize, value: T) {
self[(i / C, i % C)] = value;
}
fn zeros() -> Self {
SMatrix::<T, R, C>::zeros()
}
}
impl<T> State<T> for Complex<T>
where
T: Real,
{
fn len(&self) -> usize {
2
}
fn get(&self, i: usize) -> T {
if i == 0 {
self.re
} else if i == 1 {
self.im
} else {
panic!("Index out of bounds")
}
}
fn set(&mut self, i: usize, value: T) {
if i == 0 {
self.re = value;
} else if i == 1 {
self.im = value;
} else {
panic!("Index out of bounds")
}
}
fn zeros() -> Self {
Complex::new(T::zero(), T::zero())
}
}