From 5caefce03d53702eacf40e8a28007ea39d2a1ffe Mon Sep 17 00:00:00 2001 From: conrad Date: Wed, 12 Jun 2024 19:16:41 +1000 Subject: [PATCH] more informative error messages --- include/armadillo_bits/fn_as_scalar.hpp | 82 ++++++++++++++++++++----- 1 file changed, 66 insertions(+), 16 deletions(-) diff --git a/include/armadillo_bits/fn_as_scalar.hpp b/include/armadillo_bits/fn_as_scalar.hpp index 38cf8bf1..a8238ece 100644 --- a/include/armadillo_bits/fn_as_scalar.hpp +++ b/include/armadillo_bits/fn_as_scalar.hpp @@ -35,6 +35,8 @@ struct as_scalar_redirect<2> { template inline static typename T1::elem_type apply(const Glue& X); + + inline static void check_size(const uword A_n_rows, const uword A_n_cols, const uword B_n_rows, const uword B_n_cols); }; @@ -57,7 +59,13 @@ as_scalar_redirect::apply(const T1& X) const Proxy P(X); - arma_conform_check( (P.get_n_elem() != 1), "as_scalar(): expression must evaluate to exactly one element" ); + if( (arma_config::check_conform) && (P.get_n_elem() != 1) ) + { + const uword n_rows = P.get_n_rows(); + const uword n_cols = P.get_n_rows(); + + arma_conform_check_bounds(true, (arma_str::format("as_scalar(): expected 1x1 matrix; got %zux%zu") % std::size_t(n_rows) % std::size_t(n_cols)) ); + } return (Proxy::use_at) ? P.at(0,0) : P[0]; } @@ -100,7 +108,10 @@ as_scalar_redirect<2>::apply(const Glue& X) const uword B_n_rows = (tmp2.do_trans == false) ? (TB::is_row ? 1 : B.n_rows) : (TB::is_col ? 1 : B.n_cols); const uword B_n_cols = (tmp2.do_trans == false) ? (TB::is_col ? 1 : B.n_cols) : (TB::is_row ? 1 : B.n_rows); - arma_conform_check( (A_n_rows != 1) || (B_n_cols != 1) || (A_n_cols != B_n_rows), "as_scalar(): incompatible dimensions" ); + if( (arma_config::check_conform) && ((A_n_rows != 1) || (B_n_cols != 1) || (A_n_cols != B_n_rows)) ) + { + as_scalar_redirect<2>::check_size(A_n_rows, A_n_cols, B_n_rows, B_n_cols); + } const eT val = op_dot::direct_dot(A.n_elem, A.memptr(), B.memptr()); @@ -111,11 +122,16 @@ as_scalar_redirect<2>::apply(const Glue& X) const Proxy PA(X.A); const Proxy PB(X.B); - arma_conform_check - ( - (PA.get_n_rows() != 1) || (PB.get_n_cols() != 1) || (PA.get_n_cols() != PB.get_n_rows()), - "as_scalar(): incompatible dimensions" - ); + const uword A_n_rows = PA.get_n_rows(); + const uword A_n_cols = PA.get_n_cols(); + + const uword B_n_rows = PB.get_n_rows(); + const uword B_n_cols = PB.get_n_cols(); + + if( (arma_config::check_conform) && ((A_n_rows != 1) || (B_n_cols != 1) || (A_n_cols != B_n_rows)) ) + { + as_scalar_redirect<2>::check_size(A_n_rows, A_n_cols, B_n_rows, B_n_cols); + } return op_dot::apply_proxy_linear(PA,PB); } @@ -123,6 +139,21 @@ as_scalar_redirect<2>::apply(const Glue& X) +inline +void +as_scalar_redirect<2>::check_size(const uword A_n_rows, const uword A_n_cols, const uword B_n_rows, const uword B_n_cols) + { + arma_conform_assert_mul_size(A_n_rows, A_n_cols, B_n_rows, B_n_cols, "matrix multiplication"); + + arma_conform_check_bounds + ( + ((A_n_rows != 1) || (B_n_cols != 1)), + (arma_str::format("as_scalar(): expected 1x1 matrix; got %zux%zu") % std::size_t(A_n_rows) % std::size_t(B_n_cols)) + ); + } + + + template inline typename T1::elem_type @@ -149,7 +180,10 @@ as_scalar_redirect<3>::apply(const Glue< Glue, T3, glue_time { const Mat tmp(X); - arma_conform_check( (tmp.n_elem != 1), "as_scalar(): expression must evaluate to exactly one element" ); + if( (arma_config::check_conform) && (tmp.n_elem != 1) ) + { + arma_conform_check_bounds(true, (arma_str::format("as_scalar(): expected 1x1 matrix; got %zux%zu") % std::size_t(tmp.n_rows) % std::size_t(tmp.n_cols)) ); + } return tmp[0]; } @@ -176,14 +210,14 @@ as_scalar_redirect<3>::apply(const Glue< Glue, T3, glue_time const eT val = tmp1.get_val() * tmp2.get_val() * tmp3.get_val(); - arma_conform_check + arma_conform_check_bounds ( (A_n_rows != 1) || (C_n_cols != 1) || (A_n_cols != B_n_rows) || (B_n_cols != C_n_rows) , - "as_scalar(): incompatible dimensions" + "as_scalar(): expected 1x1 matrix" ); @@ -226,7 +260,7 @@ as_scalar_diag(const Base& X) const unwrap tmp(X.get_ref()); const Mat& A = tmp.M; - arma_conform_check( (A.n_elem != 1), "as_scalar(): expression must evaluate to exactly one element" ); + arma_conform_check_bounds( (A.n_elem != 1), "as_scalar(): expected 1x1 matrix" ); return A.mem[0]; } @@ -271,14 +305,14 @@ as_scalar_diag(const Glue< Glue, T3, glue_times >& X) const eT val = tmp1.get_val() * tmp2.get_val() * tmp3.get_val(); - arma_conform_check + arma_conform_check_bounds ( (A_n_rows != 1) || (C_n_cols != 1) || (A_n_cols != B_n_rows) || (B_n_cols != C_n_rows) , - "as_scalar(): incompatible dimensions" + "as_scalar(): expected 1x1 matrix" ); @@ -324,7 +358,13 @@ as_scalar(const Base& X) const Proxy P(X.get_ref()); - arma_conform_check( (P.get_n_elem() != 1), "as_scalar(): expression must evaluate to exactly one element" ); + if( (arma_config::check_conform) && (P.get_n_elem() != 1) ) + { + const uword n_rows = P.get_n_rows(); + const uword n_cols = P.get_n_rows(); + + arma_conform_check_bounds(true, (arma_str::format("as_scalar(): expected 1x1 matrix; got %zux%zu") % std::size_t(n_rows) % std::size_t(n_cols)) ); + } return (Proxy::use_at) ? P.at(0,0) : P[0]; } @@ -340,7 +380,14 @@ as_scalar(const BaseCube& X) const ProxyCube P(X.get_ref()); - arma_conform_check( (P.get_n_elem() != 1), "as_scalar(): expression must evaluate to exactly one element" ); + if( (arma_config::check_conform) && (P.get_n_elem() != 1) ) + { + const uword n_r = P.get_n_rows(); + const uword n_c = P.get_n_rows(); + const uword n_s = P.get_n_slices(); + + arma_conform_check_bounds(true, (arma_str::format("as_scalar(): expected 1x1x1 cube; got %zux%zux%zu") % std::size_t(n_r) % std::size_t(n_c) % std::size_t(n_s)) ); + } return (ProxyCube::use_at) ? P.at(0,0,0) : P[0]; } @@ -371,7 +418,10 @@ as_scalar(const SpBase& X) const unwrap_spmat tmp(X.get_ref()); const SpMat& A = tmp.M; - arma_conform_check( (A.n_elem != 1), "as_scalar(): expression must evaluate to exactly one element" ); + if( (arma_config::check_conform) && (A.n_elem != 1) ) + { + arma_conform_check_bounds(true, (arma_str::format("as_scalar(): expected 1x1 matrix; got %zux%zu") % std::size_t(A.n_rows) % std::size_t(A.n_cols)) ); + } return A.at(0,0); }