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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//! Provisional numerical column selection for fixed rectangular arrays.
use crate::;
/// Numerical column selection for an `R`-row, `C`-column input.
///
/// Created by [`column_basis`]. Both input dimensions remain part of the type.
/// The selected indices are unique, strictly increasing, and less than `C`;
/// their count is at most `min(R, C)`. Storage is stack-backed, with capacity
/// `R`. Neither the indices nor their count certify exact independence or rank.
/// Select columns of a rectangular array by partial-pivoted elimination.
///
/// Columns are visited from left to right. At each step the largest absolute
/// entry among remaining rows is the candidate pivot; ties select the first
/// row in the current row order. A pivot is accepted only when its magnitude
/// is **strictly greater** than `tolerance.get()`. Rejected columns are skipped;
/// selection ends after all columns or `R` accepted pivots. Empty and zero
/// matrices return rank zero; tall, square, and wide shapes are supported.
///
/// The tolerance is absolute, in input coefficient units. There is no automatic
/// scaling or normalization. To use a relative policy, compute a finite absolute
/// threshold from the original input scale and pass it through
/// [`Tolerance::try_new`]. Rescaling rows or columns can change the selection.
/// Elimination uses partial row pivoting and fused multiply-add updates
/// (Gaussian elimination, `REFERENCES.md` \[11, 12\]). No absolute rounding-error
/// bound is provided. Rounding, underflow, growth, and ill-conditioning can alter
/// the selected columns and rank even at zero tolerance. The result is provisional:
/// exact certification of a square selected basis remains the caller's job.
/// Failure to find a pivot never produces an exact singularity claim.
///
/// The input is borrowed and preserved. A local `R × C` copy and `R` indices
/// use stack storage; no allocation or optional feature is required. Dimensions
/// have no dispatch cap. Work is `O(R (1 + C (1 + min(R, C))))`, including
/// validation and initialization for empty shapes.
///
/// # Errors
/// All inputs are checked in row-major order before elimination, including
/// columns beyond a full basis. NaN/infinity returns [`LaError::NonFinite`]
/// with input origin and the original matrix cell. A non-finite update returns
/// the same error with [`ArithmeticOperation::ColumnBasis`] and its cell in the
/// row-permuted work array. Insufficient numerical rank is a successful partial
/// selection, not an error. No partially computed result is returned on error.
///
/// # Examples
/// ```
/// use la_stack::prelude::*;
/// # fn main() -> Result<(), LaError> {
/// let rows = [[0.0, 1.0, 2.0, 0.0], [0.0, 2.0, 4.0, 1.0]];
/// let basis: ColumnBasis<2, 4> = column_basis(&rows, Tolerance::try_new(1e-12)?)?;
/// assert_eq!(basis.columns(), &[1, 3]);
/// assert_eq!(basis.rank(), 2);
/// # Ok(())
/// # }
/// ```
pub const