1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
use crate::matrix::ci::CirculantMatrix; use crate::{matrix::Matrix, number::c64}; use rayon::prelude::*; use rustfft::FFTplanner; use std::f64::consts::PI; use std::mem::transmute; impl CirculantMatrix<f64> { pub fn cigv(&self) -> (Matrix<c64>, Matrix<c64>) { let n = self.row.len(); let mut fourier_matrix: Matrix<c64> = Matrix::<c64>::zeros(n, n); let omega = c64::new(0.0, 2.0 * PI / (n as f64)).exp(); for i in 0..n { for j in 0..i { fourier_matrix[i][j] = fourier_matrix[j][i]; } for j in i..n { fourier_matrix[i][j] = omega.powi((i * j) as i32); } } let mut input = self .row .par_iter() .map(|&e| c64::new(e, 0.0)) .collect::<Vec<c64>>(); let mut output = vec![c64::default(); n]; let mut planner = FFTplanner::new(false); let fft = planner.plan_fft(n); unsafe { fft.process( transmute::<&mut [c64], &mut [rustfft::num_complex::Complex<f64>]>(&mut input), transmute::<&mut [c64], &mut [rustfft::num_complex::Complex<f64>]>(&mut output), ); } let eigen_diag = Matrix::diag(&output); (fourier_matrix, eigen_diag) } } #[cfg(test)] mod tests { use super::*; #[test] fn it_works() { let a = CirculantMatrix::new(vec![1.0, 2.0, 3.0]); let diagonalized = a.cigv(); assert_eq!(diagonalized.1[0][0].re, 6.0); } }