@@ -68,7 +68,7 @@ Add this to your `Cargo.toml`:
6868
6969``` toml
7070[dependencies ]
71- la-stack = " 0.4.1 "
71+ la-stack = " 0.4.2 "
7272```
7373
7474Solve a 5×5 system via LU:
@@ -120,7 +120,16 @@ fn main() -> Result<(), LaError> {
120120 [0.0 , 0.0 , 0.0 , 1.0 , 2.0 ],
121121 ])? ;
122122
123- let det = a . ldlt (DEFAULT_SINGULAR_TOL )? . det ()? ;
123+ let ldlt = match a . ldlt (DEFAULT_SINGULAR_TOL ) {
124+ Ok (ldlt ) => ldlt ,
125+ Err (err @ LaError :: Asymmetric { row , col , .. }) => {
126+ eprintln! (" LDLT requires symmetry; first mismatch at ({row}, {col})" );
127+ return Err (err );
128+ }
129+ Err (err ) => return Err (err ),
130+ };
131+
132+ let det = ldlt . det ()? ;
124133 assert! ((det - 1.0 ). abs () <= 1 e - 12 );
125134
126135 Ok (())
@@ -149,18 +158,20 @@ evaluation when inputs are known:
149158use la_stack :: prelude :: * ;
150159
151160// Evaluated entirely at compile time — no runtime cost.
152- const DET : Result <Option <f64 >, LaError > = {
153- let m = match Matrix :: <3 >:: try_from_rows ([
154- [2.0 , 0.0 , 0.0 ],
155- [0.0 , 3.0 , 0.0 ],
156- [0.0 , 0.0 , 5.0 ],
157- ]) {
158- Ok (matrix ) => matrix ,
159- Err (_ ) => panic! (" matrix entries must be finite" ),
160- };
161- m . det_direct ()
161+ const DET : Result <Option <f64 >, LaError > = match Matrix :: <4 >:: try_from_rows ([
162+ [2.0 , 0.0 , 0.0 , 0.0 ],
163+ [0.0 , 3.0 , 0.0 , 0.0 ],
164+ [0.0 , 0.0 , 5.0 , 0.0 ],
165+ [0.0 , 0.0 , 0.0 , 7.0 ],
166+ ]) {
167+ Ok (matrix ) => matrix . det_direct (),
168+ Err (err ) => Err (err ),
162169};
163- assert_eq! (DET , Ok (Some (30.0 )));
170+
171+ fn main () -> Result <(), LaError > {
172+ assert_eq! (DET ? , Some (210.0 ));
173+ Ok (())
174+ }
164175```
165176
166177The public ` det() ` method automatically dispatches through the closed-form path
@@ -180,13 +191,14 @@ rationals (this pulls in `num-bigint`, `num-rational`, and `num-traits` for
180191
181192``` toml
182193[dependencies ]
183- la-stack = { version = " 0.4.1 " , features = [" exact" ] }
194+ la-stack = { version = " 0.4.2 " , features = [" exact" ] }
184195```
185196
186197** Determinants:**
187198
188199- ** ` det_exact() ` ** — returns the exact determinant as a ` BigRational `
189200- ** ` det_exact_f64() ` ** — returns the exact determinant converted to the nearest ` f64 `
201+ (or ` LaError::Overflow ` when the exact value is unrepresentable)
190202- ** ` det_sign_exact() ` ** — returns the provably correct sign (−1, 0, or +1)
191203
192204** Linear system solve:**
@@ -208,6 +220,19 @@ fn main() -> Result<(), LaError> {
208220
209221 let det = m.det_exact()?;
210222 assert_eq!(det, BigRational::from_integer(0.into())); // exact zero
223+ let det_f64 = m.det_exact_f64()?;
224+ assert_eq!(det_f64, 0.0);
225+
226+ // If the exact determinant cannot fit in f64, keep the BigRational value.
227+ let big = f64::MAX / 2.0;
228+ let huge = Matrix::<3>::try_from_rows([
229+ [0.0, 0.0, 1.0],
230+ [big, 0.0, 1.0],
231+ [0.0, big, 1.0],
232+ ])?;
233+ let huge_det = huge.det_exact()?;
234+ assert_eq!(huge.det_exact_f64(), Err(LaError::Overflow { index: None }));
235+ println!("exact determinant = {huge_det}");
211236
212237 // Exact linear system solve
213238 let a = Matrix::<2>::try_from_rows([[1.0, 2.0], [3.0, 4.0]])?;
0 commit comments