use mdarray::{DSlice, DTensor, Dense, Layout};
use num_complex::{Complex, ComplexFloat};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum EigError {
#[error("Backend error code: {0}")]
BackendError(i32),
#[error("Backend failed to converge: {iterations} iterations exceeded")]
BackendDidNotConverge { iterations: i32 },
#[error("Matrix must be square for eigenvalue decomposition")]
NotSquareMatrix,
}
pub struct EigDecomp<T: ComplexFloat> {
pub eigenvalues: DTensor<Complex<T::Real>, 2>,
pub left_eigenvectors: Option<DTensor<Complex<T::Real>, 2>>,
pub right_eigenvectors: Option<DTensor<Complex<T::Real>, 2>>,
}
pub type EigResult<T> = Result<EigDecomp<T>, EigError>;
#[derive(Debug, Error)]
pub enum SchurError {
#[error("Backend error code: {0}")]
BackendError(i32),
#[error("Backend failed to converge: {iterations} iterations exceeded")]
BackendDidNotConverge { iterations: i32 },
#[error("Matrix must be square for Schur decomposition")]
NotSquareMatrix,
}
pub struct SchurDecomp<T: ComplexFloat> {
pub t: DTensor<T, 2>,
pub z: DTensor<T, 2>,
}
pub type SchurResult<T> = Result<SchurDecomp<T>, SchurError>;
pub trait Eig<T: ComplexFloat> {
fn eig<L: Layout>(&self, a: &mut DSlice<T, 2, L>) -> EigResult<T>;
fn eig_full<L: Layout>(&self, a: &mut DSlice<T, 2, L>) -> EigResult<T>;
fn eig_values<L: Layout>(&self, a: &mut DSlice<T, 2, L>) -> EigResult<T>;
fn eigh<L: Layout>(&self, a: &mut DSlice<T, 2, L>) -> EigResult<T>;
fn eigs<L: Layout>(&self, a: &mut DSlice<T, 2, L>) -> EigResult<T>;
fn schur<L: Layout>(&self, a: &mut DSlice<T, 2, L>) -> SchurResult<T>;
fn schur_overwrite<L: Layout>(
&self,
a: &mut DSlice<T, 2, L>,
t: &mut DSlice<T, 2, Dense>,
z: &mut DSlice<T, 2, Dense>,
) -> Result<(), SchurError>;
fn schur_complex<L: Layout>(&self, a: &mut DSlice<T, 2, L>) -> SchurResult<T>;
fn schur_complex_overwrite<L: Layout>(
&self,
a: &mut DSlice<T, 2, L>,
t: &mut DSlice<T, 2, Dense>,
z: &mut DSlice<T, 2, Dense>,
) -> Result<(), SchurError>;
}