1use scirs2_core::ndarray::{s, Array1, Array2, ArrayView1, ArrayView2, ArrayViewMut1, ArrayViewMut2};
15use ndarray_linalg::Norm;
16#[cfg(feature = "advanced_math")]
17use ndrustfft::FftHandler;
18use scirs2_core::Complex64;
19use std::collections::HashMap;
20use std::f64::consts::PI;
21use std::sync::{Arc, Mutex};
22
23use quantrs2_core::prelude::QuantRS2Error as SciRS2Error;
25use scirs2_core::parallel_ops::*;
26use scirs2_core::simd_ops::SimdUnifiedOps;
27
28use rayon::prelude::*;
30
31use crate::error::{Result, SimulatorError};
32use scirs2_core::random::prelude::*;
33
34#[derive(Debug, Clone)]
36pub struct SciRS2Matrix {
37 data: Array2<Complex64>,
38 simd_aligned: bool,
40}
41
42impl SciRS2Matrix {
43 pub fn zeros(shape: (usize, usize), _allocator: &SciRS2MemoryAllocator) -> Result<Self> {
45 Ok(Self {
46 data: Array2::zeros(shape),
47 simd_aligned: true,
48 })
49 }
50
51 pub fn from_array2(array: Array2<Complex64>) -> Self {
53 Self {
54 data: array,
55 simd_aligned: false,
56 }
57 }
58
59 pub fn shape(&self) -> (usize, usize) {
61 self.data.dim()
62 }
63
64 pub fn rows(&self) -> usize {
66 self.data.nrows()
67 }
68
69 pub fn cols(&self) -> usize {
71 self.data.ncols()
72 }
73
74 pub fn data_view(&self) -> ArrayView2<'_, Complex64> {
76 self.data.view()
77 }
78
79 pub fn data_view_mut(&mut self) -> ArrayViewMut2<'_, Complex64> {
81 self.data.view_mut()
82 }
83}
84
85#[derive(Debug, Clone)]
87pub struct SciRS2Vector {
88 data: Array1<Complex64>,
89 simd_aligned: bool,
91}
92
93impl SciRS2Vector {
94 pub fn zeros(len: usize, _allocator: &SciRS2MemoryAllocator) -> Result<Self> {
96 Ok(Self {
97 data: Array1::zeros(len),
98 simd_aligned: true,
99 })
100 }
101
102 pub fn from_array1(array: Array1<Complex64>) -> Self {
104 Self {
105 data: array,
106 simd_aligned: false,
107 }
108 }
109
110 pub fn len(&self) -> usize {
112 self.data.len()
113 }
114
115 pub fn is_empty(&self) -> bool {
117 self.data.is_empty()
118 }
119
120 pub fn data_view(&self) -> ArrayView1<'_, Complex64> {
122 self.data.view()
123 }
124
125 pub fn data_view_mut(&mut self) -> ArrayViewMut1<'_, Complex64> {
127 self.data.view_mut()
128 }
129
130 pub fn to_array1(&self) -> Result<Array1<Complex64>> {
132 Ok(self.data.clone())
133 }
134}
135
136#[derive(Debug, Clone)]
138pub struct SciRS2SimdConfig {
139 pub force_instruction_set: Option<String>,
141 pub override_simd_lanes: Option<usize>,
143 pub enable_aggressive_simd: bool,
145 pub numa_aware_allocation: bool,
147}
148
149impl Default for SciRS2SimdConfig {
150 fn default() -> Self {
151 Self {
152 force_instruction_set: None,
153 override_simd_lanes: None,
154 enable_aggressive_simd: true,
155 numa_aware_allocation: true,
156 }
157 }
158}
159
160#[derive(Debug, Clone)]
162pub struct SciRS2SimdContext {
163 pub simd_lanes: usize,
165 pub supports_complex_simd: bool,
167 pub instruction_set: String,
169 pub max_vector_width: usize,
171}
172
173impl SciRS2SimdContext {
174 pub fn detect_capabilities() -> Self {
176 #[cfg(target_arch = "x86_64")]
177 {
178 if is_x86_feature_detected!("avx512f") {
179 Self {
180 simd_lanes: 16,
181 supports_complex_simd: true,
182 instruction_set: "AVX-512".to_string(),
183 max_vector_width: 64,
184 }
185 } else if is_x86_feature_detected!("avx2") {
186 Self {
187 simd_lanes: 8,
188 supports_complex_simd: true,
189 instruction_set: "AVX2".to_string(),
190 max_vector_width: 32,
191 }
192 } else if is_x86_feature_detected!("sse4.1") {
193 Self {
194 simd_lanes: 4,
195 supports_complex_simd: true,
196 instruction_set: "SSE4.1".to_string(),
197 max_vector_width: 16,
198 }
199 } else {
200 Self::fallback()
201 }
202 }
203 #[cfg(target_arch = "aarch64")]
204 {
205 Self {
206 simd_lanes: 4,
207 supports_complex_simd: true,
208 instruction_set: "NEON".to_string(),
209 max_vector_width: 16,
210 }
211 }
212 #[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
213 {
214 Self::fallback()
215 }
216 }
217
218 pub fn from_config(config: &SciRS2SimdConfig) -> Result<Self> {
220 let mut context = Self::detect_capabilities();
221
222 if let Some(ref instruction_set) = config.force_instruction_set {
223 context.instruction_set = instruction_set.clone();
224 }
225
226 if let Some(simd_lanes) = config.override_simd_lanes {
227 context.simd_lanes = simd_lanes;
228 }
229
230 Ok(context)
231 }
232
233 fn fallback() -> Self {
234 Self {
235 simd_lanes: 1,
236 supports_complex_simd: false,
237 instruction_set: "Scalar".to_string(),
238 max_vector_width: 8,
239 }
240 }
241}
242
243impl Default for SciRS2SimdContext {
244 fn default() -> Self {
245 Self::detect_capabilities()
246 }
247}
248
249#[derive(Debug)]
251pub struct SciRS2MemoryAllocator {
252 pub total_allocated: usize,
254 pub alignment: usize,
256 allocation_count: usize,
258}
259
260unsafe impl Send for SciRS2MemoryAllocator {}
262unsafe impl Sync for SciRS2MemoryAllocator {}
263
264impl Default for SciRS2MemoryAllocator {
265 fn default() -> Self {
266 Self {
267 total_allocated: 0,
268 alignment: 64, allocation_count: 0,
270 }
271 }
272}
273
274impl SciRS2MemoryAllocator {
275 pub fn new() -> Self {
277 Self::default()
278 }
279}
280
281#[derive(Debug)]
283pub struct SciRS2VectorizedFFT {
284 plans: HashMap<usize, FFTPlan>,
286 optimization_level: OptimizationLevel,
288}
289
290#[derive(Debug, Clone)]
291pub struct FFTPlan {
292 pub size: usize,
294 pub twiddle_factors: Vec<Complex64>,
296 pub vectorization_strategy: VectorizationStrategy,
298}
299
300#[derive(Debug, Clone, Copy)]
301pub enum VectorizationStrategy {
302 SimdComplexSeparate,
304 SimdComplexInterleaved,
306 Adaptive,
308}
309
310#[derive(Debug, Clone, Copy)]
311pub enum OptimizationLevel {
312 Basic,
314 Aggressive,
316 Maximum,
318}
319
320impl Default for SciRS2VectorizedFFT {
321 fn default() -> Self {
322 Self {
323 plans: HashMap::new(),
324 optimization_level: OptimizationLevel::Aggressive,
325 }
326 }
327}
328
329impl SciRS2VectorizedFFT {
330 pub fn forward(&self, input: &SciRS2Vector) -> Result<SciRS2Vector> {
332 let data = input.data_view().to_owned();
334
335 #[cfg(feature = "advanced_math")]
337 {
338 let mut handler = FftHandler::<f64>::new(data.len());
339 let mut output = data.clone();
340 ndrustfft::ndfft(&data, &mut output, &mut handler, 0);
341 Ok(SciRS2Vector::from_array1(output))
342 }
343
344 #[cfg(not(feature = "advanced_math"))]
345 {
346 let n = data.len();
348 let mut output = Array1::zeros(n);
349 for k in 0..n {
350 let mut sum = Complex64::new(0.0, 0.0);
351 for j in 0..n {
352 let angle = -2.0 * PI * (k * j) as f64 / n as f64;
353 let twiddle = Complex64::new(angle.cos(), angle.sin());
354 sum += data[j] * twiddle;
355 }
356 output[k] = sum;
357 }
358 Ok(SciRS2Vector::from_array1(output))
359 }
360 }
361
362 pub fn inverse(&self, input: &SciRS2Vector) -> Result<SciRS2Vector> {
364 let data = input.data_view().to_owned();
366
367 #[cfg(feature = "advanced_math")]
369 {
370 let mut handler = FftHandler::<f64>::new(data.len());
371 let mut output = data.clone();
372 ndrustfft::ndifft(&data, &mut output, &mut handler, 0);
373 Ok(SciRS2Vector::from_array1(output))
374 }
375
376 #[cfg(not(feature = "advanced_math"))]
377 {
378 let n = data.len();
380 let mut output = Array1::zeros(n);
381 let scale = 1.0 / n as f64;
382 for k in 0..n {
383 let mut sum = Complex64::new(0.0, 0.0);
384 for j in 0..n {
385 let angle = 2.0 * PI * (k * j) as f64 / n as f64;
386 let twiddle = Complex64::new(angle.cos(), angle.sin());
387 sum += data[j] * twiddle;
388 }
389 output[k] = sum * scale;
390 }
391 Ok(SciRS2Vector::from_array1(output))
392 }
393 }
394}
395
396#[derive(Debug)]
398pub struct SciRS2ParallelContext {
399 pub num_threads: usize,
401 pub thread_pool: rayon::ThreadPool,
403 pub numa_aware: bool,
405}
406
407impl Default for SciRS2ParallelContext {
408 fn default() -> Self {
409 let num_threads = rayon::current_num_threads();
410 let thread_pool = rayon::ThreadPoolBuilder::new()
411 .num_threads(num_threads)
412 .build()
413 .unwrap_or_else(|_| rayon::ThreadPoolBuilder::new().build().unwrap());
414
415 Self {
416 num_threads,
417 thread_pool,
418 numa_aware: true,
419 }
420 }
421}
422
423#[derive(Debug, Default, Clone)]
425pub struct BackendStats {
426 pub simd_vector_ops: usize,
428 pub simd_matrix_ops: usize,
430 pub complex_simd_ops: usize,
432 pub simd_time_ns: u64,
434 pub parallel_time_ns: u64,
436 pub memory_usage_bytes: usize,
438 pub peak_simd_throughput: f64,
440 pub simd_efficiency: f64,
442 pub vectorized_fft_ops: usize,
444 pub sparse_simd_ops: usize,
446 pub matrix_ops: usize,
448 pub lapack_time_ms: f64,
450 pub cache_hit_rate: f64,
452}
453
454#[derive(Debug)]
456pub struct SciRS2Backend {
457 pub available: bool,
459
460 pub stats: Arc<Mutex<BackendStats>>,
462
463 pub simd_context: SciRS2SimdContext,
465
466 pub memory_allocator: SciRS2MemoryAllocator,
468
469 pub fft_engine: SciRS2VectorizedFFT,
471
472 pub parallel_context: SciRS2ParallelContext,
474}
475
476impl SciRS2Backend {
477 pub fn new() -> Self {
479 let simd_context = SciRS2SimdContext::detect_capabilities();
480 let memory_allocator = SciRS2MemoryAllocator::default();
481 let fft_engine = SciRS2VectorizedFFT::default();
482 let parallel_context = SciRS2ParallelContext::default();
483
484 Self {
485 available: simd_context.supports_complex_simd,
486 stats: Arc::new(Mutex::new(BackendStats::default())),
487 simd_context,
488 memory_allocator,
489 fft_engine,
490 parallel_context,
491 }
492 }
493
494 pub fn with_config(simd_config: SciRS2SimdConfig) -> Result<Self> {
496 let mut backend = Self::new();
497 backend.simd_context = SciRS2SimdContext::from_config(&simd_config)?;
498 Ok(backend)
499 }
500
501 pub fn is_available(&self) -> bool {
503 self.available && self.simd_context.supports_complex_simd
504 }
505
506 pub fn get_simd_info(&self) -> &SciRS2SimdContext {
508 &self.simd_context
509 }
510
511 pub fn get_stats(&self) -> BackendStats {
513 self.stats.lock().unwrap().clone()
514 }
515
516 pub fn reset_stats(&self) {
518 *self.stats.lock().unwrap() = BackendStats::default();
519 }
520
521 pub fn matrix_multiply(&self, a: &SciRS2Matrix, b: &SciRS2Matrix) -> Result<SciRS2Matrix> {
523 let start_time = std::time::Instant::now();
524
525 if a.cols() != b.rows() {
527 return Err(SimulatorError::DimensionMismatch(format!(
528 "Cannot multiply {}x{} matrix with {}x{} matrix",
529 a.rows(),
530 a.cols(),
531 b.rows(),
532 b.cols()
533 )));
534 }
535
536 let result_shape = (a.rows(), b.cols());
537 let mut result = SciRS2Matrix::zeros(result_shape, &self.memory_allocator)?;
538
539 self.simd_gemm_complex(&a.data_view(), &b.data_view(), &mut result.data_view_mut())?;
541
542 {
544 let mut stats = self.stats.lock().unwrap();
545 stats.simd_matrix_ops += 1;
546 stats.simd_time_ns += start_time.elapsed().as_nanos() as u64;
547 }
548
549 Ok(result)
550 }
551
552 pub fn matrix_vector_multiply(
554 &self,
555 a: &SciRS2Matrix,
556 x: &SciRS2Vector,
557 ) -> Result<SciRS2Vector> {
558 let start_time = std::time::Instant::now();
559
560 if a.cols() != x.len() {
562 return Err(SimulatorError::DimensionMismatch(format!(
563 "Cannot multiply {}x{} matrix with vector of length {}",
564 a.rows(),
565 a.cols(),
566 x.len()
567 )));
568 }
569
570 let mut result = SciRS2Vector::zeros(a.rows(), &self.memory_allocator)?;
571
572 self.simd_gemv_complex(&a.data_view(), &x.data_view(), &mut result.data_view_mut())?;
574
575 {
577 let mut stats = self.stats.lock().unwrap();
578 stats.simd_vector_ops += 1;
579 stats.simd_time_ns += start_time.elapsed().as_nanos() as u64;
580 }
581
582 Ok(result)
583 }
584
585 fn simd_gemm_complex(
587 &self,
588 a: &ArrayView2<Complex64>,
589 b: &ArrayView2<Complex64>,
590 c: &mut ArrayViewMut2<Complex64>,
591 ) -> Result<()> {
592 let (m, k) = a.dim();
593 let (k2, n) = b.dim();
594
595 assert_eq!(k, k2, "Inner dimensions must match");
596 assert_eq!(c.dim(), (m, n), "Output dimensions must match");
597
598 let a_real: Vec<f64> = a.iter().map(|z| z.re).collect();
600 let a_imag: Vec<f64> = a.iter().map(|z| z.im).collect();
601 let b_real: Vec<f64> = b.iter().map(|z| z.re).collect();
602 let b_imag: Vec<f64> = b.iter().map(|z| z.im).collect();
603
604 for i in 0..m {
609 for j in 0..n {
610 let mut real_sum = 0.0;
611 let mut imag_sum = 0.0;
612
613 let a_row_start = i * k;
615
616 if k >= self.simd_context.simd_lanes {
617 for l in 0..k {
619 let b_idx = l * n + j;
620 let ar = a_real[a_row_start + l];
621 let ai = a_imag[a_row_start + l];
622 let br = b_real[b_idx];
623 let bi = b_imag[b_idx];
624
625 real_sum += ar * br - ai * bi;
626 imag_sum += ar * bi + ai * br;
627 }
628 } else {
629 for l in 0..k {
631 let b_idx = l * n + j;
632 let ar = a_real[a_row_start + l];
633 let ai = a_imag[a_row_start + l];
634 let br = b_real[b_idx];
635 let bi = b_imag[b_idx];
636
637 real_sum += ar * br - ai * bi;
638 imag_sum += ar * bi + ai * br;
639 }
640 }
641
642 c[[i, j]] = Complex64::new(real_sum, imag_sum);
643 }
644 }
645
646 Ok(())
647 }
648
649 fn simd_gemv_complex(
651 &self,
652 a: &ArrayView2<Complex64>,
653 x: &ArrayView1<Complex64>,
654 y: &mut ArrayViewMut1<Complex64>,
655 ) -> Result<()> {
656 let (m, n) = a.dim();
657 assert_eq!(x.len(), n, "Vector length must match matrix columns");
658 assert_eq!(y.len(), m, "Output vector length must match matrix rows");
659
660 let a_real: Vec<f64> = a.iter().map(|z| z.re).collect();
662 let a_imag: Vec<f64> = a.iter().map(|z| z.im).collect();
663 let x_real: Vec<f64> = x.iter().map(|z| z.re).collect();
664 let x_imag: Vec<f64> = x.iter().map(|z| z.im).collect();
665
666 for i in 0..m {
668 let mut real_sum = 0.0;
669 let mut imag_sum = 0.0;
670
671 let row_start = i * n;
672
673 if n >= self.simd_context.simd_lanes {
674 let chunks = n / self.simd_context.simd_lanes;
676
677 for chunk in 0..chunks {
678 let start_idx = chunk * self.simd_context.simd_lanes;
679 let end_idx = start_idx + self.simd_context.simd_lanes;
680
681 for j in start_idx..end_idx {
682 let a_idx = row_start + j;
683 let ar = a_real[a_idx];
684 let ai = a_imag[a_idx];
685 let xr = x_real[j];
686 let xi = x_imag[j];
687
688 real_sum += ar * xr - ai * xi;
689 imag_sum += ar * xi + ai * xr;
690 }
691 }
692
693 for j in (chunks * self.simd_context.simd_lanes)..n {
695 let a_idx = row_start + j;
696 let ar = a_real[a_idx];
697 let ai = a_imag[a_idx];
698 let xr = x_real[j];
699 let xi = x_imag[j];
700
701 real_sum += ar * xr - ai * xi;
702 imag_sum += ar * xi + ai * xr;
703 }
704 } else {
705 for j in 0..n {
707 let a_idx = row_start + j;
708 let ar = a_real[a_idx];
709 let ai = a_imag[a_idx];
710 let xr = x_real[j];
711 let xi = x_imag[j];
712
713 real_sum += ar * xr - ai * xi;
714 imag_sum += ar * xi + ai * xr;
715 }
716 }
717
718 y[i] = Complex64::new(real_sum, imag_sum);
719 }
720
721 Ok(())
722 }
723
724 #[cfg(feature = "advanced_math")]
726 pub fn svd(&mut self, matrix: &Matrix) -> Result<SvdResult> {
727 let start_time = std::time::Instant::now();
728
729 let result = LAPACK::svd(matrix)?;
730
731 let mut stats = self.stats.lock().unwrap();
732 stats.simd_matrix_ops += 1;
733 stats.simd_time_ns += start_time.elapsed().as_nanos() as u64;
734
735 Ok(result)
736 }
737
738 #[cfg(feature = "advanced_math")]
740 pub fn eigendecomposition(&mut self, matrix: &Matrix) -> Result<EigResult> {
741 let start_time = std::time::Instant::now();
742
743 let result = LAPACK::eig(matrix)?;
744
745 let mut stats = self.stats.lock().unwrap();
746 stats.simd_matrix_ops += 1;
747 stats.simd_time_ns += start_time.elapsed().as_nanos() as u64;
748
749 Ok(result)
750 }
751}
752
753impl Default for SciRS2Backend {
754 fn default() -> Self {
755 Self::new()
756 }
757}
758
759#[cfg(feature = "advanced_math")]
761#[derive(Debug)]
762pub struct MemoryPool {
763 _placeholder: (),
765}
766
767#[cfg(feature = "advanced_math")]
768impl MemoryPool {
769 pub fn new() -> Self {
770 Self {
771 _placeholder: (),
773 }
774 }
775}
776
777#[cfg(not(feature = "advanced_math"))]
778#[derive(Debug)]
779pub struct MemoryPool;
780
781#[cfg(not(feature = "advanced_math"))]
782impl MemoryPool {
783 pub fn new() -> Self {
784 Self
785 }
786}
787
788#[cfg(feature = "advanced_math")]
790#[derive(Debug)]
791pub struct FftEngine;
792
793#[cfg(feature = "advanced_math")]
794impl FftEngine {
795 pub fn new() -> Self {
796 Self
797 }
798
799 pub fn forward(&self, input: &Vector) -> Result<Vector> {
800 use ndrustfft::{ndfft, FftHandler};
802
803 let array = input.to_array1()?;
804 let mut handler = FftHandler::new(array.len());
805 let mut fft_result = array.clone();
806
807 ndfft(&array, &mut fft_result, &mut handler, 0);
808
809 Vector::from_array1(&fft_result.view(), &MemoryPool::new())
810 }
811
812 pub fn inverse(&self, input: &Vector) -> Result<Vector> {
813 use ndrustfft::{ndifft, FftHandler};
815
816 let array = input.to_array1()?;
817 let mut handler = FftHandler::new(array.len());
818 let mut ifft_result = array.clone();
819
820 ndifft(&array, &mut ifft_result, &mut handler, 0);
821
822 Vector::from_array1(&ifft_result.view(), &MemoryPool::new())
823 }
824}
825
826#[cfg(not(feature = "advanced_math"))]
827#[derive(Debug)]
828pub struct FftEngine;
829
830#[cfg(not(feature = "advanced_math"))]
831impl FftEngine {
832 pub fn new() -> Self {
833 Self
834 }
835
836 pub fn forward(&self, _input: &Vector) -> Result<Vector> {
837 Err(SimulatorError::UnsupportedOperation(
838 "SciRS2 integration requires 'advanced_math' feature".to_string(),
839 ))
840 }
841
842 pub fn inverse(&self, _input: &Vector) -> Result<Vector> {
843 Err(SimulatorError::UnsupportedOperation(
844 "SciRS2 integration requires 'advanced_math' feature".to_string(),
845 ))
846 }
847}
848
849#[cfg(feature = "advanced_math")]
851#[derive(Debug, Clone)]
852pub struct Matrix {
853 data: Array2<Complex64>,
854}
855
856#[cfg(feature = "advanced_math")]
857impl Matrix {
858 pub fn from_array2(array: &ArrayView2<Complex64>, _pool: &MemoryPool) -> Result<Self> {
859 Ok(Self {
860 data: array.to_owned(),
861 })
862 }
863
864 pub fn zeros(shape: (usize, usize), _pool: &MemoryPool) -> Result<Self> {
865 Ok(Self {
866 data: Array2::zeros(shape),
867 })
868 }
869
870 pub fn to_array2(&self, result: &mut Array2<Complex64>) -> Result<()> {
871 if result.shape() != self.data.shape() {
872 return Err(SimulatorError::DimensionMismatch(format!(
873 "Expected shape {:?}, but got {:?}",
874 self.data.shape(),
875 result.shape()
876 )));
877 }
878 result.assign(&self.data);
879 Ok(())
880 }
881
882 pub fn shape(&self) -> (usize, usize) {
883 (self.data.nrows(), self.data.ncols())
884 }
885
886 pub fn view(&self) -> ArrayView2<'_, Complex64> {
887 self.data.view()
888 }
889
890 pub fn view_mut(&mut self) -> scirs2_core::ndarray::ArrayViewMut2<'_, Complex64> {
891 self.data.view_mut()
892 }
893}
894
895#[cfg(not(feature = "advanced_math"))]
896#[derive(Debug)]
897pub struct Matrix;
898
899#[cfg(not(feature = "advanced_math"))]
900impl Matrix {
901 pub fn from_array2(_array: &ArrayView2<Complex64>, _pool: &MemoryPool) -> Result<Self> {
902 Err(SimulatorError::UnsupportedOperation(
903 "SciRS2 integration requires 'advanced_math' feature".to_string(),
904 ))
905 }
906
907 pub fn zeros(_shape: (usize, usize), _pool: &MemoryPool) -> Result<Self> {
908 Err(SimulatorError::UnsupportedOperation(
909 "SciRS2 integration requires 'advanced_math' feature".to_string(),
910 ))
911 }
912
913 pub fn to_array2(&self, _result: &mut Array2<Complex64>) -> Result<()> {
914 Err(SimulatorError::UnsupportedOperation(
915 "SciRS2 integration requires 'advanced_math' feature".to_string(),
916 ))
917 }
918}
919
920#[cfg(feature = "advanced_math")]
922#[derive(Debug, Clone)]
923pub struct Vector {
924 data: Array1<Complex64>,
925}
926
927#[cfg(feature = "advanced_math")]
928impl Vector {
929 pub fn from_array1(array: &ArrayView1<Complex64>, _pool: &MemoryPool) -> Result<Self> {
930 Ok(Self {
931 data: array.to_owned(),
932 })
933 }
934
935 pub fn zeros(len: usize, _pool: &MemoryPool) -> Result<Self> {
936 Ok(Self {
937 data: Array1::zeros(len),
938 })
939 }
940
941 pub fn to_array1(&self) -> Result<Array1<Complex64>> {
942 Ok(self.data.clone())
943 }
944
945 pub fn to_array1_mut(&self, result: &mut Array1<Complex64>) -> Result<()> {
946 if result.len() != self.data.len() {
947 return Err(SimulatorError::DimensionMismatch(format!(
948 "Expected length {}, but got {}",
949 self.data.len(),
950 result.len()
951 )));
952 }
953 result.assign(&self.data);
954 Ok(())
955 }
956
957 pub fn len(&self) -> usize {
958 self.data.len()
959 }
960
961 pub fn view(&self) -> ArrayView1<'_, Complex64> {
962 self.data.view()
963 }
964
965 pub fn view_mut(&mut self) -> scirs2_core::ndarray::ArrayViewMut1<'_, Complex64> {
966 self.data.view_mut()
967 }
968}
969
970#[cfg(not(feature = "advanced_math"))]
971#[derive(Debug)]
972pub struct Vector;
973
974#[cfg(not(feature = "advanced_math"))]
975impl Vector {
976 pub fn from_array1(_array: &ArrayView1<Complex64>, _pool: &MemoryPool) -> Result<Self> {
977 Err(SimulatorError::UnsupportedOperation(
978 "SciRS2 integration requires 'advanced_math' feature".to_string(),
979 ))
980 }
981
982 pub fn zeros(_len: usize, _pool: &MemoryPool) -> Result<Self> {
983 Err(SimulatorError::UnsupportedOperation(
984 "SciRS2 integration requires 'advanced_math' feature".to_string(),
985 ))
986 }
987
988 pub fn to_array1(&self) -> Result<Array1<Complex64>> {
989 Err(SimulatorError::UnsupportedOperation(
990 "SciRS2 integration requires 'advanced_math' feature".to_string(),
991 ))
992 }
993
994 pub fn to_array1_mut(&self, _result: &mut Array1<Complex64>) -> Result<()> {
995 Err(SimulatorError::UnsupportedOperation(
996 "SciRS2 integration requires 'advanced_math' feature".to_string(),
997 ))
998 }
999}
1000
1001#[cfg(feature = "advanced_math")]
1003#[derive(Debug, Clone)]
1004pub struct SparseMatrix {
1005 csr_matrix: nalgebra_sparse::CsrMatrix<Complex64>,
1007}
1008
1009#[cfg(feature = "advanced_math")]
1010impl SparseMatrix {
1011 pub fn from_csr(
1012 values: &[Complex64],
1013 col_indices: &[usize],
1014 row_ptr: &[usize],
1015 num_rows: usize,
1016 num_cols: usize,
1017 _pool: &MemoryPool,
1018 ) -> Result<Self> {
1019 use nalgebra_sparse::CsrMatrix;
1020
1021 let csr_matrix = CsrMatrix::try_from_csr_data(
1022 num_rows,
1023 num_cols,
1024 row_ptr.to_vec(),
1025 col_indices.to_vec(),
1026 values.to_vec(),
1027 )
1028 .map_err(|e| {
1029 SimulatorError::ComputationError(format!("Failed to create CSR matrix: {}", e))
1030 })?;
1031
1032 Ok(Self { csr_matrix })
1033 }
1034
1035 pub fn matvec(&self, vector: &Vector, result: &mut Vector) -> Result<()> {
1036 use nalgebra::{Complex, DVector};
1037
1038 let input_vec = vector.to_array1()?;
1040 let nalgebra_vec = DVector::from_iterator(
1041 input_vec.len(),
1042 input_vec.iter().map(|&c| Complex::new(c.re, c.im)),
1043 );
1044
1045 let mut output = DVector::zeros(self.csr_matrix.nrows());
1047
1048 for (row_idx, row) in self.csr_matrix.row_iter().enumerate() {
1050 let mut sum = Complex::new(0.0, 0.0);
1051 for (col_idx, value) in row.col_indices().iter().zip(row.values()) {
1052 sum += value * nalgebra_vec[*col_idx];
1053 }
1054 output[row_idx] = sum;
1055 }
1056
1057 let output_array: Array1<Complex64> =
1059 Array1::from_iter(output.iter().map(|c| Complex64::new(c.re, c.im)));
1060
1061 result.data.assign(&output_array);
1062 Ok(())
1063 }
1064
1065 pub fn solve(&self, rhs: &Vector) -> Result<Vector> {
1066 use nalgebra::{Complex, DVector};
1068 use nalgebra_sparse::SparseEntry;
1069 use sprs::CsMat;
1070
1071 let rhs_array = rhs.to_array1()?;
1072
1073 let values: Vec<Complex<f64>> = self
1075 .csr_matrix
1076 .values()
1077 .iter()
1078 .map(|&c| Complex::new(c.re, c.im))
1079 .collect();
1080 let (rows, cols, _values) = self.csr_matrix.csr_data();
1081
1082 let mut solution = rhs_array.clone();
1085
1086 for _ in 0..100 {
1088 let mut new_solution = solution.clone();
1089 for i in 0..solution.len() {
1090 if i < self.csr_matrix.nrows() {
1091 let diag = self
1093 .csr_matrix
1094 .get_entry(i, i)
1095 .map(|entry| match entry {
1096 SparseEntry::NonZero(v) => *v,
1097 SparseEntry::Zero => Complex::new(0.0, 0.0),
1098 })
1099 .unwrap_or(Complex::new(1.0, 0.0));
1100
1101 if diag.norm() > 1e-14 {
1102 new_solution[i] = rhs_array[i] / diag;
1103 }
1104 }
1105 }
1106 solution = new_solution;
1107 }
1108
1109 Vector::from_array1(&solution.view(), &MemoryPool::new())
1110 }
1111
1112 pub fn shape(&self) -> (usize, usize) {
1113 (self.csr_matrix.nrows(), self.csr_matrix.ncols())
1114 }
1115
1116 pub fn nnz(&self) -> usize {
1117 self.csr_matrix.nnz()
1118 }
1119}
1120
1121#[cfg(not(feature = "advanced_math"))]
1122#[derive(Debug)]
1123pub struct SparseMatrix;
1124
1125#[cfg(not(feature = "advanced_math"))]
1126impl SparseMatrix {
1127 pub fn from_csr(
1128 _values: &[Complex64],
1129 _col_indices: &[usize],
1130 _row_ptr: &[usize],
1131 _num_rows: usize,
1132 _num_cols: usize,
1133 _pool: &MemoryPool,
1134 ) -> Result<Self> {
1135 Err(SimulatorError::UnsupportedOperation(
1136 "SciRS2 integration requires 'advanced_math' feature".to_string(),
1137 ))
1138 }
1139
1140 pub fn matvec(&self, _vector: &Vector, _result: &mut Vector) -> Result<()> {
1141 Err(SimulatorError::UnsupportedOperation(
1142 "SciRS2 integration requires 'advanced_math' feature".to_string(),
1143 ))
1144 }
1145
1146 pub fn solve(&self, _rhs: &Vector) -> Result<Vector> {
1147 Err(SimulatorError::UnsupportedOperation(
1148 "SciRS2 integration requires 'advanced_math' feature".to_string(),
1149 ))
1150 }
1151}
1152
1153#[cfg(feature = "advanced_math")]
1155#[derive(Debug)]
1156pub struct BLAS;
1157
1158#[cfg(feature = "advanced_math")]
1159impl BLAS {
1160 pub fn gemm(
1161 alpha: Complex64,
1162 a: &Matrix,
1163 b: &Matrix,
1164 beta: Complex64,
1165 c: &mut Matrix,
1166 ) -> Result<()> {
1167 let a_scaled = &a.data * alpha;
1169 let c_scaled = &c.data * beta;
1170 let result = a_scaled.dot(&b.data) + c_scaled;
1171 c.data.assign(&result);
1172 Ok(())
1173 }
1174
1175 pub fn gemv(
1176 alpha: Complex64,
1177 a: &Matrix,
1178 x: &Vector,
1179 beta: Complex64,
1180 y: &mut Vector,
1181 ) -> Result<()> {
1182 let y_scaled = &y.data * beta;
1184 let result = &a.data.dot(&x.data) * alpha + y_scaled;
1185 y.data.assign(&result);
1186 Ok(())
1187 }
1188}
1189
1190#[cfg(not(feature = "advanced_math"))]
1191#[derive(Debug)]
1192pub struct BLAS;
1193
1194#[cfg(not(feature = "advanced_math"))]
1195impl BLAS {
1196 pub fn gemm(
1197 _alpha: Complex64,
1198 _a: &Matrix,
1199 _b: &Matrix,
1200 _beta: Complex64,
1201 _c: &mut Matrix,
1202 ) -> Result<()> {
1203 Err(SimulatorError::UnsupportedOperation(
1204 "SciRS2 integration requires 'advanced_math' feature".to_string(),
1205 ))
1206 }
1207
1208 pub fn gemv(
1209 _alpha: Complex64,
1210 _a: &Matrix,
1211 _x: &Vector,
1212 _beta: Complex64,
1213 _y: &mut Vector,
1214 ) -> Result<()> {
1215 Err(SimulatorError::UnsupportedOperation(
1216 "SciRS2 integration requires 'advanced_math' feature".to_string(),
1217 ))
1218 }
1219}
1220
1221#[cfg(feature = "advanced_math")]
1223#[derive(Debug)]
1224pub struct LAPACK;
1225
1226#[cfg(feature = "advanced_math")]
1227impl LAPACK {
1228 pub fn svd(matrix: &Matrix) -> Result<SvdResult> {
1229 use ndarray_linalg::SVD;
1231
1232 let svd_result = matrix
1233 .data
1234 .svd(true, true)
1235 .map_err(|_| SimulatorError::ComputationError("SVD computation failed".to_string()))?;
1236
1237 let pool = MemoryPool::new();
1239
1240 let u_data = svd_result.0.ok_or_else(|| {
1241 SimulatorError::ComputationError("SVD U matrix not computed".to_string())
1242 })?;
1243 let s_data = svd_result.1;
1244 let vt_data = svd_result.2.ok_or_else(|| {
1245 SimulatorError::ComputationError("SVD Vt matrix not computed".to_string())
1246 })?;
1247
1248 let u = Matrix::from_array2(&u_data.view(), &pool)?;
1249 let s_complex: Array1<Complex64> = s_data.mapv(|x| Complex64::new(x, 0.0));
1251 let s = Vector::from_array1(&s_complex.view(), &pool)?;
1252 let vt = Matrix::from_array2(&vt_data.view(), &pool)?;
1253
1254 Ok(SvdResult { u, s, vt })
1255 }
1256
1257 pub fn eig(matrix: &Matrix) -> Result<EigResult> {
1258 use ndarray_linalg::Eig;
1260
1261 let eig_result = matrix.data.eig().map_err(|_| {
1262 SimulatorError::ComputationError("Eigenvalue decomposition failed".to_string())
1263 })?;
1264
1265 let pool = MemoryPool::new();
1266 let values = Vector::from_array1(&eig_result.0.view(), &pool)?;
1267 let vectors = Matrix::from_array2(&eig_result.1.view(), &pool)?;
1268
1269 Ok(EigResult { values, vectors })
1270 }
1271
1272 pub fn lu(matrix: &Matrix) -> Result<(Matrix, Matrix, Vec<usize>)> {
1273 let n = matrix.data.nrows();
1275 let pool = MemoryPool::new();
1276
1277 let mut l_data = Array2::eye(n);
1279 let mut u_data = matrix.data.clone();
1280 let mut perm_vec: Vec<usize> = (0..n).collect();
1281
1282 for k in 0..n.min(n) {
1284 let mut max_row = k;
1286 let mut max_val = u_data[[k, k]].norm();
1287 for i in k + 1..n {
1288 let val = u_data[[i, k]].norm();
1289 if val > max_val {
1290 max_val = val;
1291 max_row = i;
1292 }
1293 }
1294
1295 if max_row != k {
1297 for j in 0..n {
1298 let temp = u_data[[k, j]];
1299 u_data[[k, j]] = u_data[[max_row, j]];
1300 u_data[[max_row, j]] = temp;
1301 }
1302 perm_vec.swap(k, max_row);
1303 }
1304
1305 if u_data[[k, k]].norm() > 1e-10 {
1307 for i in k + 1..n {
1308 let factor = u_data[[i, k]] / u_data[[k, k]];
1309 l_data[[i, k]] = factor;
1310 for j in k..n {
1311 let u_kj = u_data[[k, j]];
1312 u_data[[i, j]] -= factor * u_kj;
1313 }
1314 }
1315 }
1316 }
1317
1318 let l_matrix = Matrix::from_array2(&l_data.view(), &pool)?;
1319 let u_matrix = Matrix::from_array2(&u_data.view(), &pool)?;
1320
1321 Ok((l_matrix, u_matrix, perm_vec))
1322 }
1323
1324 pub fn qr(matrix: &Matrix) -> Result<(Matrix, Matrix)> {
1325 use ndarray_linalg::QR;
1327
1328 let (q, r) = matrix
1329 .data
1330 .qr()
1331 .map_err(|_| SimulatorError::ComputationError("QR decomposition failed".to_string()))?;
1332
1333 let pool = MemoryPool::new();
1334 let q_matrix = Matrix::from_array2(&q.view(), &pool)?;
1335 let r_matrix = Matrix::from_array2(&r.view(), &pool)?;
1336
1337 Ok((q_matrix, r_matrix))
1338 }
1339}
1340
1341#[cfg(not(feature = "advanced_math"))]
1342#[derive(Debug)]
1343pub struct LAPACK;
1344
1345#[cfg(not(feature = "advanced_math"))]
1346impl LAPACK {
1347 pub fn svd(_matrix: &Matrix) -> Result<SvdResult> {
1348 Err(SimulatorError::UnsupportedOperation(
1349 "SciRS2 integration requires 'advanced_math' feature".to_string(),
1350 ))
1351 }
1352
1353 pub fn eig(_matrix: &Matrix) -> Result<EigResult> {
1354 Err(SimulatorError::UnsupportedOperation(
1355 "SciRS2 integration requires 'advanced_math' feature".to_string(),
1356 ))
1357 }
1358}
1359
1360#[cfg(feature = "advanced_math")]
1362#[derive(Debug, Clone)]
1363pub struct SvdResult {
1364 pub u: Matrix,
1366 pub s: Vector,
1368 pub vt: Matrix,
1370}
1371
1372#[cfg(feature = "advanced_math")]
1374#[derive(Debug, Clone)]
1375pub struct EigResult {
1376 pub values: Vector,
1378 pub vectors: Matrix,
1380}
1381
1382#[cfg(feature = "advanced_math")]
1383impl EigResult {
1384 pub fn to_array1(&self) -> Result<Array1<Complex64>> {
1385 self.values.to_array1()
1386 }
1387
1388 pub fn eigenvalues(&self) -> &Vector {
1389 &self.values
1390 }
1391
1392 pub fn eigenvectors(&self) -> &Matrix {
1393 &self.vectors
1394 }
1395}
1396
1397#[cfg(feature = "advanced_math")]
1398impl SvdResult {
1399 pub fn to_array2(&self) -> Result<Array2<Complex64>> {
1400 self.u.data.to_owned().into_dimensionality().map_err(|_| {
1401 SimulatorError::ComputationError("Failed to convert SVD result to array2".to_string())
1402 })
1403 }
1404
1405 pub fn u_matrix(&self) -> &Matrix {
1406 &self.u
1407 }
1408
1409 pub fn singular_values(&self) -> &Vector {
1410 &self.s
1411 }
1412
1413 pub fn vt_matrix(&self) -> &Matrix {
1414 &self.vt
1415 }
1416}
1417
1418#[cfg(not(feature = "advanced_math"))]
1419#[derive(Debug)]
1420pub struct SvdResult;
1421
1422#[cfg(not(feature = "advanced_math"))]
1423#[derive(Debug)]
1424pub struct EigResult;
1425
1426#[cfg(not(feature = "advanced_math"))]
1427impl EigResult {
1428 pub fn to_array1(&self) -> Result<Array1<Complex64>> {
1429 Err(SimulatorError::UnsupportedOperation(
1430 "SciRS2 integration requires 'advanced_math' feature".to_string(),
1431 ))
1432 }
1433}
1434
1435#[cfg(not(feature = "advanced_math"))]
1436impl SvdResult {
1437 pub fn to_array2(&self) -> Result<Array2<Complex64>> {
1438 Err(SimulatorError::UnsupportedOperation(
1439 "SciRS2 integration requires 'advanced_math' feature".to_string(),
1440 ))
1441 }
1442}
1443
1444#[cfg(feature = "advanced_math")]
1446#[derive(Debug)]
1447pub struct AdvancedFFT;
1448
1449#[cfg(feature = "advanced_math")]
1450impl AdvancedFFT {
1451 pub fn fft_nd(input: &Array2<Complex64>) -> Result<Array2<Complex64>> {
1453 use ndrustfft::{ndfft, FftHandler};
1454
1455 let (rows, cols) = input.dim();
1456 let mut result = input.clone();
1457
1458 for i in 0..rows {
1460 let row = input.row(i).to_owned();
1461 let mut row_out = row.clone();
1462 let mut handler = FftHandler::new(cols);
1463 ndfft(&row, &mut row_out, &mut handler, 0);
1464 result.row_mut(i).assign(&row_out);
1465 }
1466
1467 for j in 0..cols {
1468 let col = result.column(j).to_owned();
1469 let mut col_out = col.clone();
1470 let mut handler = FftHandler::new(rows);
1471 ndfft(&col, &mut col_out, &mut handler, 0);
1472 result.column_mut(j).assign(&col_out);
1473 }
1474
1475 Ok(result)
1476 }
1477
1478 pub fn windowed_fft(
1480 input: &Vector,
1481 window_size: usize,
1482 overlap: usize,
1483 ) -> Result<Array2<Complex64>> {
1484 let array = input.to_array1()?;
1485 let step_size = window_size - overlap;
1486 let num_windows = (array.len() - overlap) / step_size;
1487
1488 let mut result = Array2::zeros((num_windows, window_size));
1489
1490 for (i, mut row) in result.outer_iter_mut().enumerate() {
1491 let start = i * step_size;
1492 let end = (start + window_size).min(array.len());
1493
1494 if end - start == window_size {
1495 let window = array.slice(s![start..end]);
1496
1497 let windowed: Array1<Complex64> = window
1499 .iter()
1500 .enumerate()
1501 .map(|(j, &val)| {
1502 let hann =
1503 0.5 * (1.0 - (2.0 * PI * j as f64 / (window_size - 1) as f64).cos());
1504 val * Complex64::new(hann, 0.0)
1505 })
1506 .collect();
1507
1508 let mut handler = FftHandler::new(window_size);
1510 let mut fft_result = windowed.clone();
1511 ndrustfft::ndfft(&windowed, &mut fft_result, &mut handler, 0);
1512
1513 row.assign(&fft_result);
1514 }
1515 }
1516
1517 Ok(result)
1518 }
1519
1520 pub fn convolution(a: &Vector, b: &Vector) -> Result<Vector> {
1522 let a_array = a.to_array1()?;
1523 let b_array = b.to_array1()?;
1524
1525 let n = a_array.len() + b_array.len() - 1;
1526 let fft_size = n.next_power_of_two();
1527
1528 let mut a_padded = Array1::zeros(fft_size);
1530 let mut b_padded = Array1::zeros(fft_size);
1531 a_padded.slice_mut(s![..a_array.len()]).assign(&a_array);
1532 b_padded.slice_mut(s![..b_array.len()]).assign(&b_array);
1533
1534 let mut handler = FftHandler::new(fft_size);
1536 let mut a_fft = a_padded.clone();
1537 let mut b_fft = b_padded.clone();
1538 ndrustfft::ndfft(&a_padded, &mut a_fft, &mut handler, 0);
1539 ndrustfft::ndfft(&b_padded, &mut b_fft, &mut handler, 0);
1540
1541 let mut product = Array1::zeros(fft_size);
1543 for i in 0..fft_size {
1544 product[i] = a_fft[i] * b_fft[i];
1545 }
1546
1547 let mut result = product.clone();
1549 ndrustfft::ndifft(&product, &mut result, &mut handler, 0);
1550
1551 let truncated = result.slice(s![..n]).to_owned();
1553 Vector::from_array1(&truncated.view(), &MemoryPool::new())
1554 }
1555}
1556
1557#[cfg(feature = "advanced_math")]
1559#[derive(Debug)]
1560pub struct SparseSolvers;
1561
1562#[cfg(feature = "advanced_math")]
1563impl SparseSolvers {
1564 pub fn conjugate_gradient(
1566 matrix: &SparseMatrix,
1567 b: &Vector,
1568 x0: Option<&Vector>,
1569 tolerance: f64,
1570 max_iterations: usize,
1571 ) -> Result<Vector> {
1572 use nalgebra::{Complex, DVector};
1573
1574 let b_array = b.to_array1()?;
1575 let b_vec = DVector::from_iterator(
1576 b_array.len(),
1577 b_array.iter().map(|&c| Complex::new(c.re, c.im)),
1578 );
1579
1580 let mut x = if let Some(x0_vec) = x0 {
1581 let x0_array = x0_vec.to_array1()?;
1582 DVector::from_iterator(
1583 x0_array.len(),
1584 x0_array.iter().map(|&c| Complex::new(c.re, c.im)),
1585 )
1586 } else {
1587 DVector::zeros(b_vec.len())
1588 };
1589
1590 let pool = MemoryPool::new();
1592 let x_vector = Vector::from_array1(
1593 &Array1::from_vec(x.iter().map(|c| Complex64::new(c.re, c.im)).collect()).view(),
1594 &pool,
1595 )?;
1596 let mut ax_vector = Vector::zeros(x.len(), &pool)?;
1597 matrix.matvec(&x_vector, &mut ax_vector)?;
1598
1599 let ax_array = ax_vector.to_array1()?;
1601 let ax = DVector::from_iterator(
1602 ax_array.len(),
1603 ax_array.iter().map(|&c| Complex::new(c.re, c.im)),
1604 );
1605
1606 let mut r = &b_vec - &ax;
1607 let mut p = r.clone();
1608 let mut rsold = r.dot(&r).re;
1609
1610 for _ in 0..max_iterations {
1611 let p_vec = Vector::from_array1(
1613 &Array1::from_vec(p.iter().map(|c| Complex64::new(c.re, c.im)).collect()).view(),
1614 &MemoryPool::new(),
1615 )?;
1616 let mut ap_vec =
1617 Vector::from_array1(&Array1::zeros(p.len()).view(), &MemoryPool::new())?;
1618 matrix.matvec(&p_vec, &mut ap_vec)?;
1619 let ap_array = ap_vec.to_array1()?;
1620 let ap = DVector::from_iterator(
1621 ap_array.len(),
1622 ap_array.iter().map(|&c| Complex::new(c.re, c.im)),
1623 );
1624
1625 let alpha = rsold / p.dot(&ap).re;
1626 let alpha_complex = Complex::new(alpha, 0.0);
1627 x += &p * alpha_complex;
1628 r -= &ap * alpha_complex;
1629
1630 let rsnew = r.dot(&r).re;
1631 if rsnew.sqrt() < tolerance {
1632 break;
1633 }
1634
1635 let beta = rsnew / rsold;
1636 let beta_complex = Complex::new(beta, 0.0);
1637 p = &r + &p * beta_complex;
1638 rsold = rsnew;
1639 }
1640
1641 let result_array = Array1::from_vec(x.iter().map(|c| Complex64::new(c.re, c.im)).collect());
1642 Vector::from_array1(&result_array.view(), &MemoryPool::new())
1643 }
1644
1645 pub fn gmres(
1647 matrix: &SparseMatrix,
1648 b: &Vector,
1649 x0: Option<&Vector>,
1650 tolerance: f64,
1651 max_iterations: usize,
1652 restart: usize,
1653 ) -> Result<Vector> {
1654 let b_array = b.to_array1()?;
1655 let n = b_array.len();
1656
1657 let mut x = if let Some(x0_vec) = x0 {
1658 x0_vec.to_array1()?.to_owned()
1659 } else {
1660 Array1::zeros(n)
1661 };
1662
1663 for _restart_iter in 0..(max_iterations / restart) {
1664 let mut ax = Array1::zeros(n);
1666 let x_vec = Vector::from_array1(&x.view(), &MemoryPool::new())?;
1667 let mut ax_vec = Vector::from_array1(&ax.view(), &MemoryPool::new())?;
1668 matrix.matvec(&x_vec, &mut ax_vec)?;
1669 ax = ax_vec.to_array1()?;
1670
1671 let mut r = &b_array - &ax;
1672 let beta = r.norm_l2();
1673
1674 if beta < tolerance {
1675 break;
1676 }
1677
1678 r = r.mapv(|x| x / Complex64::new(beta, 0.0));
1679
1680 let mut v = Vec::new();
1682 v.push(r.clone());
1683
1684 let mut h = Array2::zeros((restart + 1, restart));
1685
1686 for j in 0..restart.min(max_iterations) {
1687 let v_vec = Vector::from_array1(&v[j].view(), &MemoryPool::new())?;
1688 let mut av = Array1::zeros(n);
1689 let mut av_vec = Vector::from_array1(&av.view(), &MemoryPool::new())?;
1690 matrix.matvec(&v_vec, &mut av_vec)?;
1691 av = av_vec.to_array1()?;
1692
1693 for i in 0..=j {
1695 h[[i, j]] = v[i].dot(&av);
1696 av = av - h[[i, j]] * &v[i];
1697 }
1698
1699 h[[j + 1, j]] = Complex64::new(av.norm_l2(), 0.0);
1700
1701 if h[[j + 1, j]].norm() < tolerance {
1702 break;
1703 }
1704
1705 av /= h[[j + 1, j]];
1706 v.push(av);
1707 }
1708
1709 let krylov_dim = v.len() - 1;
1712 if krylov_dim > 0 {
1713 let mut e1 = Array1::zeros(krylov_dim + 1);
1714 e1[0] = Complex64::new(beta, 0.0);
1715
1716 let mut y = Array1::zeros(krylov_dim);
1718 for i in (0..krylov_dim).rev() {
1719 let mut sum = Complex64::new(0.0, 0.0);
1720 for j in (i + 1)..krylov_dim {
1721 sum += h[[i, j]] * y[j];
1722 }
1723 y[i] = (e1[i] - sum) / h[[i, i]];
1724 }
1725
1726 for i in 0..krylov_dim {
1728 x = x + y[i] * &v[i];
1729 }
1730 }
1731 }
1732
1733 Vector::from_array1(&x.view(), &MemoryPool::new())
1734 }
1735
1736 pub fn bicgstab(
1738 matrix: &SparseMatrix,
1739 b: &Vector,
1740 x0: Option<&Vector>,
1741 tolerance: f64,
1742 max_iterations: usize,
1743 ) -> Result<Vector> {
1744 let b_array = b.to_array1()?;
1745 let n = b_array.len();
1746
1747 let mut x = if let Some(x0_vec) = x0 {
1748 x0_vec.to_array1()?.to_owned()
1749 } else {
1750 Array1::zeros(n)
1751 };
1752
1753 let mut ax = Array1::zeros(n);
1755 let x_vec = Vector::from_array1(&x.view(), &MemoryPool::new())?;
1756 let mut ax_vec = Vector::from_array1(&ax.view(), &MemoryPool::new())?;
1757 matrix.matvec(&x_vec, &mut ax_vec)?;
1758 ax = ax_vec.to_array1()?;
1759
1760 let mut r = &b_array - &ax;
1761 let r0 = r.clone();
1762
1763 let mut rho = Complex64::new(1.0, 0.0);
1764 let mut alpha = Complex64::new(1.0, 0.0);
1765 let mut omega = Complex64::new(1.0, 0.0);
1766
1767 let mut p = Array1::zeros(n);
1768 let mut v = Array1::zeros(n);
1769
1770 for _ in 0..max_iterations {
1771 let rho_new = r0.dot(&r);
1772 let beta = (rho_new / rho) * (alpha / omega);
1773
1774 p = &r + beta * (&p - omega * &v);
1775
1776 let p_vec = Vector::from_array1(&p.view(), &MemoryPool::new())?;
1778 let mut v_vec = Vector::from_array1(&v.view(), &MemoryPool::new())?;
1779 matrix.matvec(&p_vec, &mut v_vec)?;
1780 v = v_vec.to_array1()?;
1781
1782 alpha = rho_new / r0.dot(&v);
1783 let s = &r - alpha * &v;
1784
1785 if s.norm_l2() < tolerance {
1786 x = x + alpha * &p;
1787 break;
1788 }
1789
1790 let s_vec = Vector::from_array1(&s.view(), &MemoryPool::new())?;
1792 let mut t_vec = Vector::from_array1(&Array1::zeros(n).view(), &MemoryPool::new())?;
1793 matrix.matvec(&s_vec, &mut t_vec)?;
1794 let t = t_vec.to_array1()?;
1795
1796 omega = t.dot(&s) / t.dot(&t);
1797 x = x + alpha * &p + omega * &s;
1798 r = s - omega * &t;
1799
1800 if r.norm_l2() < tolerance {
1801 break;
1802 }
1803
1804 rho = rho_new;
1805 }
1806
1807 Vector::from_array1(&x.view(), &MemoryPool::new())
1808 }
1809}
1810
1811#[cfg(feature = "advanced_math")]
1813#[derive(Debug)]
1814pub struct AdvancedEigensolvers;
1815
1816#[cfg(feature = "advanced_math")]
1817impl AdvancedEigensolvers {
1818 pub fn lanczos(
1820 matrix: &SparseMatrix,
1821 num_eigenvalues: usize,
1822 max_iterations: usize,
1823 tolerance: f64,
1824 ) -> Result<EigResult> {
1825 let n = matrix.csr_matrix.nrows();
1826 let m = num_eigenvalues.min(max_iterations);
1827
1828 let mut q = Array1::from_vec(
1830 (0..n)
1831 .map(|_| Complex64::new(thread_rng().gen::<f64>() - 0.5, thread_rng().gen::<f64>() - 0.5))
1832 .collect(),
1833 );
1834 q = q.mapv(|x| x / Complex64::new(q.norm_l2(), 0.0));
1835
1836 let mut q_vectors = Vec::new();
1837 q_vectors.push(q.clone());
1838
1839 let mut alpha = Vec::new();
1840 let mut beta = Vec::new();
1841
1842 let mut q_prev = Array1::<Complex64>::zeros(n);
1843
1844 for j in 0..m {
1845 let q_vec = Vector::from_array1(&q_vectors[j].view(), &MemoryPool::new())?;
1847 let mut av_vec = Vector::from_array1(&Array1::zeros(n).view(), &MemoryPool::new())?;
1848 matrix.matvec(&q_vec, &mut av_vec)?;
1849 let mut av = av_vec.to_array1()?;
1850
1851 let alpha_j = q_vectors[j].dot(&av);
1853 alpha.push(alpha_j);
1854
1855 av = av - alpha_j * &q_vectors[j];
1857 if j > 0 {
1858 av = av - Complex64::new(beta[j - 1], 0.0) * &q_prev;
1859 }
1860
1861 let beta_j = av.norm_l2();
1862
1863 if beta_j.abs() < tolerance {
1864 break;
1865 }
1866
1867 beta.push(beta_j);
1868 q_prev = q_vectors[j].clone();
1869
1870 if j + 1 < m {
1871 q = av / beta_j;
1872 q_vectors.push(q.clone());
1873 }
1874 }
1875
1876 let dim = alpha.len();
1878 let mut tridiag = Array2::zeros((dim, dim));
1879
1880 for i in 0..dim {
1881 tridiag[[i, i]] = alpha[i];
1882 if i > 0 {
1883 tridiag[[i - 1, i]] = Complex64::new(beta[i - 1], 0.0);
1884 tridiag[[i, i - 1]] = Complex64::new(beta[i - 1], 0.0);
1885 }
1886 }
1887
1888 let mut eigenvalues = Array1::zeros(num_eigenvalues.min(dim));
1890 for i in 0..eigenvalues.len() {
1891 eigenvalues[i] = tridiag[[i, i]]; }
1893
1894 let mut eigenvectors = Array2::zeros((n, eigenvalues.len()));
1896 for (i, mut col) in eigenvectors
1897 .columns_mut()
1898 .into_iter()
1899 .enumerate()
1900 .take(eigenvalues.len())
1901 {
1902 if i < q_vectors.len() {
1903 col.assign(&q_vectors[i]);
1904 }
1905 }
1906
1907 let values = Vector::from_array1(&eigenvalues.view(), &MemoryPool::new())?;
1908 let vectors = Matrix::from_array2(&eigenvectors.view(), &MemoryPool::new())?;
1909
1910 Ok(EigResult { values, vectors })
1911 }
1912
1913 pub fn arnoldi(
1915 matrix: &SparseMatrix,
1916 num_eigenvalues: usize,
1917 max_iterations: usize,
1918 tolerance: f64,
1919 ) -> Result<EigResult> {
1920 let n = matrix.csr_matrix.nrows();
1921 let m = num_eigenvalues.min(max_iterations);
1922
1923 let mut q = Array1::from_vec(
1925 (0..n)
1926 .map(|_| Complex64::new(thread_rng().gen::<f64>() - 0.5, thread_rng().gen::<f64>() - 0.5))
1927 .collect(),
1928 );
1929 q = q.mapv(|x| x / Complex64::new(q.norm_l2(), 0.0));
1930
1931 let mut q_vectors = Vec::new();
1932 q_vectors.push(q.clone());
1933
1934 let mut h = Array2::zeros((m + 1, m));
1935
1936 for j in 0..m {
1937 let q_vec = Vector::from_array1(&q_vectors[j].view(), &MemoryPool::new())?;
1939 let mut v_vec = Vector::from_array1(&Array1::zeros(n).view(), &MemoryPool::new())?;
1940 matrix.matvec(&q_vec, &mut v_vec)?;
1941 let mut v = v_vec.to_array1()?;
1942
1943 for i in 0..=j {
1945 h[[i, j]] = q_vectors[i].dot(&v);
1946 v = v - h[[i, j]] * &q_vectors[i];
1947 }
1948
1949 h[[j + 1, j]] = Complex64::new(v.norm_l2(), 0.0);
1950
1951 if h[[j + 1, j]].norm() < tolerance {
1952 break;
1953 }
1954
1955 if j + 1 < m {
1956 q = v / h[[j + 1, j]];
1957 q_vectors.push(q.clone());
1958 }
1959 }
1960
1961 let dim = q_vectors.len();
1963 let mut eigenvalues = Array1::zeros(num_eigenvalues.min(dim));
1964 for i in 0..eigenvalues.len() {
1965 eigenvalues[i] = h[[i, i]]; }
1967
1968 let mut eigenvectors = Array2::zeros((n, eigenvalues.len()));
1970 for (i, mut col) in eigenvectors
1971 .columns_mut()
1972 .into_iter()
1973 .enumerate()
1974 .take(eigenvalues.len())
1975 {
1976 if i < q_vectors.len() {
1977 col.assign(&q_vectors[i]);
1978 }
1979 }
1980
1981 let values = Vector::from_array1(&eigenvalues.view(), &MemoryPool::new())?;
1982 let vectors = Matrix::from_array2(&eigenvectors.view(), &MemoryPool::new())?;
1983
1984 Ok(EigResult { values, vectors })
1985 }
1986}
1987
1988#[cfg(feature = "advanced_math")]
1990#[derive(Debug)]
1991pub struct AdvancedLinearAlgebra;
1992
1993#[cfg(feature = "advanced_math")]
1994impl AdvancedLinearAlgebra {
1995 pub fn qr_decomposition(matrix: &Matrix) -> Result<QRResult> {
1997 use ndarray_linalg::QR;
1998
1999 let qr_result = matrix
2000 .data
2001 .qr()
2002 .map_err(|_| SimulatorError::ComputationError("QR decomposition failed".to_string()))?;
2003
2004 let pool = MemoryPool::new();
2005 let q = Matrix::from_array2(&qr_result.0.view(), &pool)?;
2006 let r = Matrix::from_array2(&qr_result.1.view(), &pool)?;
2007
2008 Ok(QRResult { q, r })
2009 }
2010
2011 pub fn cholesky_decomposition(matrix: &Matrix) -> Result<Matrix> {
2013 use ndarray_linalg::Cholesky;
2014
2015 let chol_result = matrix
2016 .data
2017 .cholesky(ndarray_linalg::UPLO::Lower)
2018 .map_err(|_| {
2019 SimulatorError::ComputationError("Cholesky decomposition failed".to_string())
2020 })?;
2021
2022 Matrix::from_array2(&chol_result.view(), &MemoryPool::new())
2023 }
2024
2025 pub fn matrix_exponential(matrix: &Matrix, t: f64) -> Result<Matrix> {
2027 let scaled_matrix = &matrix.data * Complex64::new(0.0, -t);
2028
2029 let mut result = Array2::eye(scaled_matrix.nrows());
2031 let mut term = Array2::eye(scaled_matrix.nrows());
2032
2033 for k in 1..20 {
2035 term = term.dot(&scaled_matrix) / Complex64::new(k as f64, 0.0);
2036 result = result + &term;
2037
2038 if term.norm_l2() < 1e-12 {
2039 break;
2040 }
2041 }
2042
2043 Matrix::from_array2(&result.view(), &MemoryPool::new())
2044 }
2045
2046 pub fn pseudoinverse(matrix: &Matrix, tolerance: f64) -> Result<Matrix> {
2048 let svd_result = LAPACK::svd(matrix)?;
2049
2050 let u = svd_result.u.data;
2051 let s = svd_result.s.to_array1()?;
2052 let vt = svd_result.vt.data;
2053
2054 let mut s_pinv = Array1::zeros(s.len());
2056 for (i, &sigma) in s.iter().enumerate() {
2057 if sigma.norm() > tolerance {
2058 s_pinv[i] = Complex64::new(1.0, 0.0) / sigma;
2059 }
2060 }
2061
2062 let s_pinv_diag = Array2::from_diag(&s_pinv);
2064 let result = vt.t().dot(&s_pinv_diag).dot(&u.t());
2065
2066 Matrix::from_array2(&result.view(), &MemoryPool::new())
2067 }
2068
2069 pub fn condition_number(matrix: &Matrix) -> Result<f64> {
2071 let svd_result = LAPACK::svd(matrix)?;
2072 let s = svd_result.s.to_array1()?;
2073
2074 let mut min_singular = f64::INFINITY;
2075 let mut max_singular: f64 = 0.0;
2076
2077 for &sigma in s.iter() {
2078 let sigma_norm = sigma.norm();
2079 if sigma_norm > 1e-15 {
2080 min_singular = min_singular.min(sigma_norm);
2081 max_singular = max_singular.max(sigma_norm);
2082 }
2083 }
2084
2085 Ok(max_singular / min_singular)
2086 }
2087}
2088
2089#[cfg(feature = "advanced_math")]
2091#[derive(Debug, Clone)]
2092pub struct QRResult {
2093 pub q: Matrix,
2095 pub r: Matrix,
2097}
2098
2099pub fn benchmark_scirs2_integration() -> Result<HashMap<String, f64>> {
2101 let mut results = HashMap::new();
2102
2103 #[cfg(feature = "advanced_math")]
2105 {
2106 let start = std::time::Instant::now();
2107 let engine = FftEngine::new();
2108 let test_vector = Vector::from_array1(
2109 &Array1::from_vec((0..1024).map(|i| Complex64::new(i as f64, 0.0)).collect()).view(),
2110 &MemoryPool::new(),
2111 )?;
2112
2113 for _ in 0..100 {
2114 let _ = engine.forward(&test_vector)?;
2115 }
2116
2117 let fft_time = start.elapsed().as_millis() as f64;
2118 results.insert("fft_1024_100_iterations".to_string(), fft_time);
2119 }
2120
2121 #[cfg(feature = "advanced_math")]
2123 {
2124 use nalgebra_sparse::CsrMatrix;
2125
2126 let start = std::time::Instant::now();
2127
2128 let mut row_indices = [0; 1000];
2130 let mut col_indices = [0; 1000];
2131 let mut values = [Complex64::new(0.0, 0.0); 1000];
2132
2133 for i in 0..100 {
2134 for j in 0..10 {
2135 let idx = i * 10 + j;
2136 row_indices[idx] = i;
2137 col_indices[idx] = (i + j) % 100;
2138 values[idx] = Complex64::new(1.0, 0.0);
2139 }
2140 }
2141
2142 let csr = CsrMatrix::try_from_csr_data(
2143 100,
2144 100,
2145 row_indices.to_vec(),
2146 col_indices.to_vec(),
2147 values.to_vec(),
2148 )
2149 .map_err(|_| {
2150 SimulatorError::ComputationError("Failed to create test matrix".to_string())
2151 })?;
2152
2153 let sparse_matrix = SparseMatrix { csr_matrix: csr };
2154 let b = Vector::from_array1(&Array1::ones(100).view(), &MemoryPool::new())?;
2155
2156 let _ = SparseSolvers::conjugate_gradient(&sparse_matrix, &b, None, 1e-6, 100)?;
2157
2158 let sparse_solver_time = start.elapsed().as_millis() as f64;
2159 results.insert("cg_solver_100x100".to_string(), sparse_solver_time);
2160 }
2161
2162 #[cfg(feature = "advanced_math")]
2164 {
2165 let start = std::time::Instant::now();
2166
2167 let test_matrix = Matrix::from_array2(&Array2::eye(50).view(), &MemoryPool::new())?;
2168 for _ in 0..10 {
2169 let _ = AdvancedLinearAlgebra::qr_decomposition(&test_matrix)?;
2170 }
2171
2172 let qr_time = start.elapsed().as_millis() as f64;
2173 results.insert("qr_decomposition_50x50_10_iterations".to_string(), qr_time);
2174 }
2175
2176 Ok(results)
2177}