1use ndarray::{Array1, Array2};
2use num_traits::{Float, FromPrimitive, One, Zero};
3use std::fmt::Debug;
4use std::iter::Sum;
5use std::ops::{AddAssign, MulAssign, Neg, SubAssign};
6use single_utilities::traits::FloatOpsTS;
7
8pub fn determine_chunk_size(nrows: usize) -> usize {
9 let num_threads = rayon::current_num_threads();
10
11 let min_rows_per_thread = 16;
12 let desired_chunks_per_thread = 4;
13
14 let target_total_chunks = num_threads * desired_chunks_per_thread;
15 let chunk_size = nrows.div_ceil(target_total_chunks);
16
17 chunk_size.max(min_rows_per_thread)
18}
19
20pub trait SMat<T: Float>: Sync {
21 fn nrows(&self) -> usize;
22 fn ncols(&self) -> usize;
23 fn nnz(&self) -> usize;
24 fn svd_opa(&self, x: &[T], y: &mut [T], transposed: bool); fn compute_column_means(&self) -> Vec<T>;
27}
28
29#[derive(Debug, Clone, PartialEq)]
38pub struct SvdRec<T: Float> {
39 pub d: usize,
40 pub u: Array2<T>,
41 pub s: Array1<T>,
42 pub vt: Array2<T>,
43 pub diagnostics: Diagnostics<T>,
44}
45
46#[derive(Debug, Clone, PartialEq)]
61pub struct Diagnostics<T: Float> {
62 pub non_zero: usize,
63 pub dimensions: usize,
64 pub iterations: usize,
65 pub transposed: bool,
66 pub lanczos_steps: usize,
67 pub ritz_values_stabilized: usize,
68 pub significant_values: usize,
69 pub singular_values: usize,
70 pub end_interval: [T; 2],
71 pub kappa: T,
72 pub random_seed: u32,
73}
74
75pub trait SvdFloat:
76 FloatOpsTS
77{
78 fn eps() -> Self;
79 fn eps34() -> Self;
80 fn compare(a: Self, b: Self) -> bool;
81}
82
83impl SvdFloat for f32 {
84 fn eps() -> Self {
85 f32::EPSILON
86 }
87
88 fn eps34() -> Self {
89 f32::EPSILON.powf(0.75)
90 }
91
92 fn compare(a: Self, b: Self) -> bool {
93 (b - a).abs() < f32::EPSILON
94 }
95}
96
97impl SvdFloat for f64 {
98 fn eps() -> Self {
99 f64::EPSILON
100 }
101
102 fn eps34() -> Self {
103 f64::EPSILON.powf(0.75)
104 }
105
106 fn compare(a: Self, b: Self) -> bool {
107 (b - a).abs() < f64::EPSILON
108 }
109}