quantrs2_core/
linalg_stubs.rs

1//! Linear algebra utilities using SciRS2-Linalg
2//! Compliant with SciRS2 POLICY - uses scirs2_linalg for all operations
3
4use crate::error::QuantRS2Result;
5use scirs2_core::ndarray::{Array1, Array2, ArrayView2};
6use scirs2_core::Complex64;
7
8/// Sparse CSR matrix stub
9#[derive(Debug, Clone)]
10pub struct CsrMatrix<T> {
11    pub data: Vec<T>,
12    pub indices: Vec<usize>,
13    pub indptr: Vec<usize>,
14    pub shape: (usize, usize),
15}
16
17impl<T: Clone + Default> CsrMatrix<T> {
18    pub fn zeros(shape: (usize, usize)) -> Self {
19        Self {
20            data: Vec::new(),
21            indices: Vec::new(),
22            indptr: vec![0; shape.0 + 1],
23            shape,
24        }
25    }
26
27    pub const fn new(
28        data: Vec<T>,
29        indices: Vec<usize>,
30        indptr: Vec<usize>,
31        shape: (usize, usize),
32    ) -> Result<Self, String> {
33        Ok(Self {
34            data,
35            indices,
36            indptr,
37            shape,
38        })
39    }
40
41    pub const fn shape(&self) -> (usize, usize) {
42        self.shape
43    }
44
45    pub fn nnz(&self) -> usize {
46        self.data.len()
47    }
48}
49
50impl CsrMatrix<Complex64> {
51    pub fn to_dense(&self) -> Array2<Complex64> {
52        let (rows, cols) = self.shape;
53        let mut dense = Array2::zeros((rows, cols));
54
55        for row in 0..rows {
56            let start = self.indptr[row];
57            let end = self.indptr[row + 1];
58
59            for idx in start..end {
60                let col = self.indices[idx];
61                let val = self.data[idx];
62                dense[(row, col)] = val;
63            }
64        }
65
66        dense
67    }
68}
69
70/// SVD result
71pub struct SvdResult {
72    pub u: Array2<f64>,
73    pub s: Array1<f64>,
74    pub vt: Array2<f64>,
75}
76
77/// Compute SVD using SciRS2-Linalg (SciRS2 POLICY compliant)
78pub fn svd(
79    matrix: &ArrayView2<f64>,
80    full_matrices: bool,
81    compute_uv: Option<bool>,
82) -> QuantRS2Result<(Array2<f64>, Array1<f64>, Array2<f64>)> {
83    // Use scirs2_linalg for SVD computation (SciRS2 POLICY)
84    // svd returns (u, singular_values, vt) tuple
85    let (u, s, vt) = scirs2_linalg::svd(matrix, true, None)
86        .map_err(|e| crate::error::QuantRS2Error::ComputationError(format!("SVD failed: {e:?}")))?;
87
88    Ok((u, s, vt))
89}
90
91/// Compute SVD (simplified version)
92pub fn svd_simple(matrix: &Array2<f64>) -> QuantRS2Result<SvdResult> {
93    let (u, s, vt) = svd(&matrix.view(), true, Some(true))?;
94    Ok(SvdResult { u, s, vt })
95}
96
97/// Compute randomized SVD
98pub fn randomized_svd(
99    matrix: &ArrayView2<f64>,
100    rank: usize,
101    oversampling: Option<usize>,
102    n_iter: Option<usize>,
103    random_state: Option<u64>,
104) -> QuantRS2Result<(Array2<f64>, Array1<f64>, Array2<f64>)> {
105    // Stub implementation - just call regular SVD and truncate
106    let (u, s, vt) = svd(matrix, false, Some(true))?;
107    let k = rank.min(s.len());
108
109    Ok((
110        u.slice(scirs2_core::ndarray::s![.., ..k]).to_owned(),
111        s.slice(scirs2_core::ndarray::s![..k]).to_owned(),
112        vt.slice(scirs2_core::ndarray::s![..k, ..]).to_owned(),
113    ))
114}
115
116/// Compute truncated SVD
117pub fn truncated_svd(
118    matrix: &ArrayView2<f64>,
119    rank: usize,
120    random_state: Option<u64>,
121) -> QuantRS2Result<(Array2<f64>, Array1<f64>, Array2<f64>)> {
122    randomized_svd(matrix, rank, Some(10), Some(2), random_state)
123}