@@ -873,23 +873,36 @@ mod tests {
873873 ) ;
874874 }
875875
876- #[ test]
877- fn det_direct_const_eval_d2 ( ) {
878- // Const evaluation proves the function is truly const fn.
879- const DET : Option < f64 > = {
880- let m = Matrix :: < 2 > :: from_rows ( [ [ 1.0 , 0.0 ] , [ 0.0 , 1.0 ] ] ) ;
881- m. det_direct ( )
876+ // === det_direct const-evaluability tests (D = 2..=5) ===
877+ //
878+ // Every dimension hits a distinct arm of the `match D { … }` body inside
879+ // `det_direct`, so exercising each at compile time is the tightest
880+ // const-fn proof available.
881+
882+ macro_rules! gen_det_direct_const_eval_tests {
883+ ( $d: literal) => {
884+ paste! {
885+ /// `Matrix::<D>::det_direct()` on the identity must const-evaluate
886+ /// to `Some(1.0)` for every closed-form dimension `D ∈ {1, 2, 3, 4}`.
887+ #[ test]
888+ fn [ <det_direct_const_eval_ $d d>] ( ) {
889+ const DET : Option <f64 > = Matrix :: <$d>:: identity( ) . det_direct( ) ;
890+ assert_eq!( DET , Some ( 1.0 ) ) ;
891+ }
892+ }
882893 } ;
883- assert_eq ! ( DET , Some ( 1.0 ) ) ;
884894 }
885895
896+ gen_det_direct_const_eval_tests ! ( 2 ) ;
897+ gen_det_direct_const_eval_tests ! ( 3 ) ;
898+ gen_det_direct_const_eval_tests ! ( 4 ) ;
899+
886900 #[ test]
887- fn det_direct_const_eval_d3 ( ) {
888- const DET : Option < f64 > = {
889- let m = Matrix :: < 3 > :: from_rows ( [ [ 2.0 , 0.0 , 0.0 ] , [ 0.0 , 3.0 , 0.0 ] , [ 0.0 , 0.0 , 5.0 ] ] ) ;
890- m. det_direct ( )
891- } ;
892- assert_eq ! ( DET , Some ( 30.0 ) ) ;
901+ fn det_direct_const_eval_d5_is_none ( ) {
902+ // D ≥ 5 has no closed-form arm; `det_direct` returns `None`. Verify
903+ // that the wildcard arm is reachable in a `const { … }` context.
904+ const DET : Option < f64 > = Matrix :: < 5 > :: identity ( ) . det_direct ( ) ;
905+ assert_eq ! ( DET , None ) ;
893906 }
894907
895908 // === det_errbound tests (no `exact` feature required) ===
@@ -909,46 +922,58 @@ mod tests {
909922 assert_eq ! ( Matrix :: <5 >:: identity( ) . det_errbound( ) , None ) ;
910923 }
911924
912- #[ test]
913- fn det_errbound_const_eval_d2 ( ) {
914- // Const evaluation proves the function is truly const fn.
915- const BOUND : Option < f64 > = {
916- let m = Matrix :: < 2 > :: from_rows ( [ [ 1.0 , 2.0 ] , [ 3.0 , 4.0 ] ] ) ;
917- m. det_errbound ( )
918- } ;
919- assert ! ( BOUND . is_some( ) ) ;
920- assert ! ( BOUND . unwrap( ) > 0.0 ) ;
921- }
925+ // === det_errbound const-evaluability tests (D = 2..=5) ===
922926
923- #[ test]
924- fn det_errbound_const_eval_d3 ( ) {
925- const BOUND : Option < f64 > = {
926- let m = Matrix :: < 3 > :: from_rows ( [ [ 1.0 , 2.0 , 3.0 ] , [ 4.0 , 5.0 , 6.0 ] , [ 7.0 , 8.0 , 9.0 ] ] ) ;
927- m. det_errbound ( )
927+ macro_rules! gen_det_errbound_const_eval_tests {
928+ ( $d: literal) => {
929+ paste! {
930+ /// `Matrix::<D>::det_errbound()` on the identity must const-evaluate
931+ /// to `Some(bound)` with `bound > 0` for every closed-form dimension
932+ /// `D ∈ {2, 3, 4}`. Each dimension hits a distinct arm of
933+ /// `det_errbound` with a dimension-specific permanent computation.
934+ #[ test]
935+ fn [ <det_errbound_const_eval_ $d d>] ( ) {
936+ const BOUND : Option <f64 > = Matrix :: <$d>:: identity( ) . det_errbound( ) ;
937+ assert!( BOUND . is_some( ) ) ;
938+ assert!( BOUND . unwrap( ) > 0.0 ) ;
939+ }
940+ }
928941 } ;
929- assert ! ( BOUND . is_some( ) ) ;
930- assert ! ( BOUND . unwrap( ) > 0.0 ) ;
931942 }
932943
944+ gen_det_errbound_const_eval_tests ! ( 2 ) ;
945+ gen_det_errbound_const_eval_tests ! ( 3 ) ;
946+ gen_det_errbound_const_eval_tests ! ( 4 ) ;
947+
933948 #[ test]
934- fn inf_norm_const_eval_d2 ( ) {
935- // Maximum absolute row sum: row 0 = 3, row 1 = 7 ⇒ 7.
936- const NORM : f64 = {
937- let m = Matrix :: < 2 > :: from_rows ( [ [ 1.0 , -2.0 ] , [ 3.0 , 4.0 ] ] ) ;
938- m. inf_norm ( )
939- } ;
940- assert ! ( ( NORM - 7.0 ) . abs( ) <= 1e-12 ) ;
949+ fn det_errbound_const_eval_d5_is_none ( ) {
950+ // D ≥ 5 has no fast-filter bound; `det_errbound` returns `None`.
951+ const BOUND : Option < f64 > = Matrix :: < 5 > :: identity ( ) . det_errbound ( ) ;
952+ assert_eq ! ( BOUND , None ) ;
941953 }
942954
943- #[ test]
944- fn inf_norm_const_eval_d3 ( ) {
945- const NORM : f64 = {
946- let m = Matrix :: < 3 > :: identity ( ) ;
947- m. inf_norm ( )
955+ // === inf_norm const-evaluability tests (D = 2..=5) ===
956+
957+ macro_rules! gen_inf_norm_const_eval_tests {
958+ ( $d: literal) => {
959+ paste! {
960+ /// `Matrix::<D>::inf_norm()` on the identity must const-evaluate
961+ /// to `1.0` for every `D ≥ 1` — each row has a single `1.0`
962+ /// entry, so the max absolute row sum is exactly `1.0`.
963+ #[ test]
964+ fn [ <inf_norm_const_eval_ $d d>] ( ) {
965+ const NORM : f64 = Matrix :: <$d>:: identity( ) . inf_norm( ) ;
966+ assert!( ( NORM - 1.0 ) . abs( ) <= 1e-12 ) ;
967+ }
968+ }
948969 } ;
949- assert ! ( ( NORM - 1.0 ) . abs( ) <= 1e-12 ) ;
950970 }
951971
972+ gen_inf_norm_const_eval_tests ! ( 2 ) ;
973+ gen_inf_norm_const_eval_tests ! ( 3 ) ;
974+ gen_inf_norm_const_eval_tests ! ( 4 ) ;
975+ gen_inf_norm_const_eval_tests ! ( 5 ) ;
976+
952977 // === inf_norm NaN / Inf propagation (regression tests for #85) ===
953978
954979 macro_rules! gen_inf_norm_nonfinite_tests {
0 commit comments