use num_traits::NumCast;
const DEBUG_MATRIX_GRAMSCHMIDT: bool = false;
use crate::matrix::FloatComplex;
use crate::error::{Result, Error};
pub fn matrix_proj<T>(u: &[T], v: &[T], e: &mut [T]) -> Result<()>
where
T: FloatComplex,
{
let n = u.len();
if n != v.len() || n != e.len() {
return Err(Error::Range("matrix_proj: input vectors must have the same length".to_owned()));
}
let mut uv = <T as NumCast>::from(0.0).unwrap();
let mut uu = <T as NumCast>::from(0.0).unwrap();
for i in 0..n {
uv = uv + u[i] * v[i].conj();
uu = uu + u[i] * u[i].conj();
}
let g = uv / uu;
for i in 0..n {
e[i] = u[i] * g;
}
Ok(())
}
pub fn matrix_gramschmidt<T>(x: &[T], rx: usize, cx: usize, v: &mut [T]) -> Result<()>
where
T: FloatComplex,
{
if rx == 0 || cx == 0 {
return Err(Error::Range("matrix_gramschmidt: input matrix cannot have zero-length dimensions".to_owned()));
}
v.copy_from_slice(x);
let n = rx; let mut proj_ij = vec![<T as NumCast>::from(0.0).unwrap(); n];
for j in 0..cx {
for i in 0..j {
if DEBUG_MATRIX_GRAMSCHMIDT {
println!("computing proj(v_{}, v_{})", i, j);
}
let mut vij = <T as NumCast>::from(0.0).unwrap(); let mut vii = <T as NumCast>::from(0.0).unwrap(); for k in 0..n {
let ti = v[k * cx + i];
let tj = v[k * cx + j];
let prodij = ti * tj.conj();
vij = vij + prodij;
let prodii = ti * ti.conj();
vii = vii + prodii;
}
let g = vij / vii;
for k in 0..n {
proj_ij[k] = v[k * cx + i] * g;
}
for k in 0..n {
v[k * cx + j] = v[k * cx + j] - proj_ij[k];
}
}
let mut vjj = <T as NumCast>::from(0.0).unwrap(); for k in 0..n {
let tj = v[k * cx + j];
let prodjj = tj * tj.conj();
vjj = vjj + prodjj;
}
let g = <T as NumCast>::from(1.0).unwrap() / vjj.sqrt();
for k in 0..n {
v[k * cx + j] = v[k * cx + j] * g;
}
if DEBUG_MATRIX_GRAMSCHMIDT {
}
}
Ok(())
}