Skip to main content

faer/linalg/evd/schur/
mod.rs

1use super::*;
2pub(crate) mod complex_schur;
3pub(crate) mod real_schur;
4#[derive(Clone, Copy, Debug)]
5pub struct SchurParams {
6	/// function that returns the number of shifts to use for a given matrix
7	/// size
8	pub recommended_shift_count: extern "C" fn(
9		matrix_dimension: usize,
10		active_block_dimension: usize,
11	) -> usize,
12	/// function that returns the deflation window to use for a given matrix
13	/// size
14	pub recommended_deflation_window: extern "C" fn(
15		matrix_dimension: usize,
16		active_block_dimension: usize,
17	) -> usize,
18	/// threshold to switch between blocked and unblocked code
19	pub blocking_threshold: usize,
20	/// threshold of percent of aggressive-early-deflation window that must
21	/// converge to skip a sweep
22	pub nibble_threshold: usize,
23	#[doc(hidden)]
24	pub non_exhaustive: NonExhaustive,
25}
26impl<T: ComplexField> Auto<T> for SchurParams {
27	fn auto() -> Self {
28		Self {
29			recommended_shift_count: default_recommended_shift_count,
30			recommended_deflation_window: default_recommended_deflation_window,
31			blocking_threshold: 75,
32			nibble_threshold: 50,
33			non_exhaustive: NonExhaustive(()),
34		}
35	}
36}
37pub fn multishift_qr_scratch<T: ComplexField>(
38	n: usize,
39	nh: usize,
40	want_t: bool,
41	want_z: bool,
42	parallelism: Par,
43	params: SchurParams,
44) -> StackReq {
45	let nsr = (params.recommended_shift_count)(n, nh);
46	let _ = want_t;
47	let _ = want_z;
48	if n <= 3 {
49		return StackReq::EMPTY;
50	}
51	let nw_max = (n - 3) / 3;
52	StackReq::any_of(&[
53		hessenberg::hessenberg_in_place_scratch::<T>(nw_max, 1, parallelism, Default::default()),
54		linalg::householder::apply_block_householder_sequence_transpose_on_the_left_in_place_scratch::<T>(nw_max, nw_max, nw_max),
55		linalg::householder::apply_block_householder_sequence_on_the_right_in_place_scratch::<T>(nw_max, nw_max, nw_max),
56		temp_mat_scratch::<T>(3, nsr),
57	])
58}
59extern "C" fn default_recommended_shift_count(
60	dim: usize,
61	_active_block_dim: usize,
62) -> usize {
63	let n = dim;
64	if n < 30 {
65		2
66	} else if n < 60 {
67		4
68	} else if n < 150 {
69		12
70	} else if n < 590 {
71		32
72	} else if n < 3000 {
73		64
74	} else if n < 6000 {
75		128
76	} else {
77		256
78	}
79}
80extern "C" fn default_recommended_deflation_window(
81	dim: usize,
82	_active_block_dim: usize,
83) -> usize {
84	let n = dim;
85	if n < 30 {
86		2
87	} else if n < 60 {
88		4
89	} else if n < 150 {
90		10
91	} else if n < 590 {
92		#[cfg(feature = "std")]
93		{
94			(n as f64 / (n as f64).log2()) as usize
95		}
96		#[cfg(not(feature = "std"))]
97		{
98			libm::log2(n as f64 / (n as f64)) as usize
99		}
100	} else if n < 3000 {
101		96
102	} else if n < 6000 {
103		192
104	} else {
105		384
106	}
107}