diff --git a/include/armadillo_bits/glue_times_meat.hpp b/include/armadillo_bits/glue_times_meat.hpp index 28f5ec4b..bd508d0f 100644 --- a/include/armadillo_bits/glue_times_meat.hpp +++ b/include/armadillo_bits/glue_times_meat.hpp @@ -104,6 +104,40 @@ glue_times_redirect2_helper::apply(Mat& out, const const strip_inv A_strip(X.A); + typedef typename strip_inv::stored_type T1_stripped; + + if( (is_cx::no) && (strip_inv::do_inv_gen) && (is_Mat::value) && (is_Mat::value) ) + { + const unwrap UA(A_strip.M); + const unwrap UB(X.B); + + const typename unwrap::stored_type& A = UA.M; + const typename unwrap::stored_type& B = UB.M; + + const uword N = A.n_rows; + + if( (N > 0) && (N <= uword(3)) && (N == A.n_cols) && (N == B.n_rows) && (void_ptr(&out) != void_ptr(&B)) ) + { + arma_debug_print("glue_times_redirect<2>::apply(): inv tiny matrix optimisation"); + + Mat AA(N, N, arma_nozeros_indicator()); + + arrayops::copy(AA.memptr(), A.memptr(), AA.n_elem); + + bool inv_status = false; + + if(N == 1) { const eT a = AA[0]; AA[0] = eT(1) / a; inv_status = (a != eT(0)); } + if(N == 2) { inv_status = op_inv_gen_full::apply_tiny_2x2(AA); } + if(N == 3) { inv_status = op_inv_gen_full::apply_tiny_3x3(AA); } + + if(inv_status) { glue_times::apply(out, AA, B, eT(0)); return; } + + arma_debug_print("glue_times_redirect<2>::apply(): inv tiny matrix optimisation failed"); + + // fallthrough if optimisation failed + } + } + Mat A = A_strip.M; arma_conform_check( (A.is_square() == false), "inv(): given matrix must be square sized" );