use std::fmt::{Debug, Display};
use ndarray::LinalgScalar;
use num_traits::{Float, Zero, One, NumCast};
use std::ops::Sub;
use rand::distributions::range::SampleRange;
use std::{f32, f64};
use lapack::{c32, c64};
pub trait LinxalImplScalar
: Sized + Default + Clone + Debug + Display + Zero + One + Sub<Output = Self> + LinalgScalar
{
type RealPart: LinxalImplScalar + Float + NumCast + From<f32> + SampleRange;
type Complex: LinxalImplScalar;
fn cj(self) -> Self;
fn mag(self) -> Self::RealPart;
fn eps() -> Self::RealPart;
fn tol() -> Self::RealPart;
fn from_real(f: Self::RealPart) -> Self;
}
impl LinxalImplScalar for f32 {
type RealPart = f32;
type Complex = c32;
fn cj(self) -> Self {
self
}
fn eps() -> Self::RealPart {
f32::EPSILON
}
fn mag(self) -> Self::RealPart {
self.abs()
}
fn tol() -> Self::RealPart {
1e-5
}
fn from_real(f: Self::RealPart) -> Self {
f
}
}
impl LinxalImplScalar for f64 {
type RealPart = f64;
type Complex = c64;
fn cj(self) -> Self {
self
}
fn eps() -> Self::RealPart {
f64::EPSILON
}
fn mag(self) -> Self::RealPart {
self.abs()
}
fn tol() -> Self::RealPart {
2e-14
}
fn from_real(f: Self::RealPart) -> Self {
f
}
}
impl LinxalImplScalar for c32 {
type RealPart = f32;
type Complex = c32;
fn cj(self) -> Self {
self.conj()
}
fn eps() -> Self::RealPart {
f32::EPSILON
}
fn mag(self) -> Self::RealPart {
self.norm()
}
fn tol() -> Self::RealPart {
2e-5
}
fn from_real(f: Self::RealPart) -> Self {
Self::new(f, 0.0)
}
}
impl LinxalImplScalar for c64 {
type RealPart = f64;
type Complex = c64;
fn cj(self) -> Self {
self.conj()
}
fn eps() -> Self::RealPart {
f64::EPSILON
}
fn mag(self) -> Self::RealPart {
self.norm()
}
fn tol() -> Self::RealPart {
4e-14
}
fn from_real(f: Self::RealPart) -> Self {
Self::new(f, 0.0)
}
}
pub trait LinxalImplFloat: LinxalImplScalar + Float {}
impl<T: LinxalImplScalar + Float> LinxalImplFloat for T {}
pub trait LinxalImplComplex: LinxalImplScalar {}
impl LinxalImplComplex for c32 {}
impl LinxalImplComplex for c64 {}