use core::fmt::Debug;
use num_traits::{Float, Num, One, Zero};
#[cfg(feature = "complex")]
use num_complex::Complex;
pub trait Scalar: Copy + PartialEq + Debug + Zero + One + Num + 'static {}
impl<T: Copy + PartialEq + Debug + Zero + One + Num + 'static> Scalar for T {}
pub trait FloatScalar: Scalar + Float + LinalgScalar<Real = Self> {}
impl<T: Scalar + Float + LinalgScalar<Real = T>> FloatScalar for T {}
pub trait LinalgScalar: Scalar {
type Real: FloatScalar;
fn modulus(self) -> Self::Real;
fn conj(self) -> Self;
fn re(self) -> Self::Real;
fn lsqrt(self) -> Self;
fn lln(self) -> Self;
fn lepsilon() -> Self::Real;
fn from_real(r: Self::Real) -> Self;
}
macro_rules! impl_linalg_scalar_real {
($($t:ty),*) => {
$(
impl LinalgScalar for $t {
type Real = $t;
#[inline] fn modulus(self) -> $t { Float::abs(self) }
#[inline] fn conj(self) -> $t { self }
#[inline] fn re(self) -> $t { self }
#[inline] fn lsqrt(self) -> $t { Float::sqrt(self) }
#[inline] fn lln(self) -> $t { Float::ln(self) }
#[inline] fn lepsilon() -> $t { <$t as Float>::epsilon() }
#[inline] fn from_real(r: $t) -> $t { r }
}
)*
};
}
impl_linalg_scalar_real!(f32, f64);
#[cfg(feature = "complex")]
impl<T: FloatScalar> LinalgScalar for Complex<T> {
type Real = T;
#[inline]
fn modulus(self) -> T {
self.norm()
}
#[inline]
fn conj(self) -> Self {
Complex::conj(&self)
}
#[inline]
fn re(self) -> T {
self.re
}
#[inline]
fn lsqrt(self) -> Self {
self.sqrt()
}
#[inline]
fn lln(self) -> Self {
self.ln()
}
#[inline]
fn lepsilon() -> T {
T::epsilon()
}
#[inline]
fn from_real(r: T) -> Self {
Complex::new(r, T::zero())
}
}
pub trait MatrixRef<T> {
fn nrows(&self) -> usize;
fn ncols(&self) -> usize;
fn get(&self, row: usize, col: usize) -> &T;
fn col_as_slice(&self, col: usize, row_start: usize) -> &[T];
}
pub trait MatrixMut<T>: MatrixRef<T> {
fn get_mut(&mut self, row: usize, col: usize) -> &mut T;
fn col_as_mut_slice(&mut self, col: usize, row_start: usize) -> &mut [T];
}