Accessing an element of a matrix expression involving inv() results in long chain of compiler errors

Issue #262 wontfix
Mikhail Katliar created an issue

Example:

blaze::DynamicMatrix<double> R, B;
(B * inv(R))(0, 0);

Compiler output:

In file included from /usr/local/include/blaze/math/DenseMatrix.h:69,
                 from /usr/local/include/blaze/math/CustomMatrix.h:45,
                 from /usr/local/include/blaze/Math.h:51,
                 from test.cpp:1:
/usr/local/include/blaze/math/expressions/DMatDMatMultExpr.h: In instantiation of ‘blaze::DMatDMatMultExpr< <template-parameter-1-1>, <template-parameter-1-2>, <anonymous>, <anonymous>, <anonymous>, <anonymous> >::ReturnType blaze::DMatDMatMultExpr< <template-parameter-1-1>, <template-parameter-1-2>, <anonymous>, <anonymous>, <anonymous>, <anonymous> >::operator()(std::size_t, std::size_t) const [with MT1 = blaze::DynamicMatrix<double>; MT2 = blaze::DMatInvExpr<blaze::DynamicMatrix<double>, false>; bool SF = false; bool HF = false; bool LF = false; bool UF = false; blaze::DMatDMatMultExpr< <template-parameter-1-1>, <template-parameter-1-2>, <anonymous>, <anonymous>, <anonymous>, <anonymous> >::ReturnType = const double; std::size_t = long unsigned int]’:
test.cpp:6:19:   required from here
/usr/local/include/blaze/math/expressions/DMatDMatMultExpr.h:352:27: error: no match for call to ‘(blaze::DMatDMatMultExpr<blaze::DynamicMatrix<double>, blaze::DMatInvExpr<blaze::DynamicMatrix<double>, false>, false, false, false, false>::RightOperand {aka const blaze::DMatInvExpr<blaze::DynamicMatrix<double>, false>}) (std::size_t&, std::size_t&)’
          return lhs_(i,i) * rhs_(i,j);
/usr/local/include/blaze/math/expressions/DMatDMatMultExpr.h:355:27: error: no match for call to ‘(blaze::DMatDMatMultExpr<blaze::DynamicMatrix<double>, blaze::DMatInvExpr<blaze::DynamicMatrix<double>, false>, false, false, false, false>::RightOperand {aka const blaze::DMatInvExpr<blaze::DynamicMatrix<double>, false>}) (std::size_t&, std::size_t&)’
          return lhs_(i,j) * rhs_(j,j);
In file included from /usr/local/include/blaze/Math.h:44,
                 from test.cpp:1:
/usr/local/include/blaze/math/Aliases.h: In substitution of ‘template<class T> using ConstReference_t = typename T::ConstReference [with T = const blaze::DMatInvExpr<blaze::DynamicMatrix<double>, false>]’:
/usr/local/include/blaze/math/views/column/Dense.h:2278:47:   required from ‘class blaze::Column<const blaze::DMatInvExpr<blaze::DynamicMatrix<double>, false>, false, true, false>’
/usr/local/include/blaze/math/views/Column.h:314:11:   required from ‘decltype(auto) blaze::column(const blaze::Matrix<MT1, SO1>&, std::size_t, RCAs ...) [with MT = blaze::DMatInvExpr<blaze::DynamicMatrix<double>, false>; bool SO = false; RCAs = {blaze::Check<false>}; std::size_t = long unsigned int]’
/usr/local/include/blaze/math/expressions/DMatDMatMultExpr.h:380:34:   required from ‘blaze::DMatDMatMultExpr< <template-parameter-1-1>, <template-parameter-1-2>, <anonymous>, <anonymous>, <anonymous>, <anonymous> >::ReturnType blaze::DMatDMatMultExpr< <template-parameter-1-1>, <template-parameter-1-2>, <anonymous>, <anonymous>, <anonymous>, <anonymous> >::operator()(std::size_t, std::size_t) const [with MT1 = blaze::DynamicMatrix<double>; MT2 = blaze::DMatInvExpr<blaze::DynamicMatrix<double>, false>; bool SF = false; bool HF = false; bool LF = false; bool UF = false; blaze::DMatDMatMultExpr< <template-parameter-1-1>, <template-parameter-1-2>, <anonymous>, <anonymous>, <anonymous>, <anonymous> >::ReturnType = const double; std::size_t = long unsigned int]’
test.cpp:6:19:   required from here
/usr/local/include/blaze/math/Aliases.h:150:52: error: no type named ‘ConstReference’ in ‘const class blaze::DMatInvExpr<blaze::DynamicMatrix<double>, false>’
 using ConstReference_t = typename T::ConstReference;
                                                    ^
In file included from /usr/local/include/blaze/math/views/Column.h:75,
                 from /usr/local/include/blaze/math/adaptors/hermitianmatrix/Dense.h:72,
                 from /usr/local/include/blaze/math/adaptors/HermitianMatrix.h:45,
                 from /usr/local/include/blaze/math/SparseMatrix.h:44,
                 from /usr/local/include/blaze/math/CompressedMatrix.h:49,
                 from /usr/local/include/blaze/Math.h:48,
                 from test.cpp:1:
/usr/local/include/blaze/math/views/column/Dense.h: In instantiation of ‘class blaze::Column<const blaze::DMatInvExpr<blaze::DynamicMatrix<double>, false>, false, true, false>’:
/usr/local/include/blaze/math/views/Column.h:314:11:   required from ‘decltype(auto) blaze::column(const blaze::Matrix<MT1, SO1>&, std::size_t, RCAs ...) [with MT = blaze::DMatInvExpr<blaze::DynamicMatrix<double>, false>; bool SO = false; RCAs = {blaze::Check<false>}; std::size_t = long unsigned int]’
/usr/local/include/blaze/math/expressions/DMatDMatMultExpr.h:380:34:   required from ‘blaze::DMatDMatMultExpr< <template-parameter-1-1>, <template-parameter-1-2>, <anonymous>, <anonymous>, <anonymous>, <anonymous> >::ReturnType blaze::DMatDMatMultExpr< <template-parameter-1-1>, <template-parameter-1-2>, <anonymous>, <anonymous>, <anonymous>, <anonymous> >::operator()(std::size_t, std::size_t) const [with MT1 = blaze::DynamicMatrix<double>; MT2 = blaze::DMatInvExpr<blaze::DynamicMatrix<double>, false>; bool SF = false; bool HF = false; bool LF = false; bool UF = false; blaze::DMatDMatMultExpr< <template-parameter-1-1>, <template-parameter-1-2>, <anonymous>, <anonymous>, <anonymous>, <anonymous> >::ReturnType = const double; std::size_t = long unsigned int]’
test.cpp:6:19:   required from here
/usr/local/include/blaze/math/views/column/Dense.h:2281:76: error: no type named ‘ConstReference’ in ‘const class blaze::DMatInvExpr<blaze::DynamicMatrix<double>, false>’
    using Reference = If_t< IsConst_v<MT>, ConstReference, Reference_t<MT> >;
                                                                            ^
In file included from /usr/local/include/blaze/Math.h:44,
                 from test.cpp:1:
/usr/local/include/blaze/math/Aliases.h: In substitution of ‘template<class T> using ConstPointer_t = typename T::ConstPointer [with T = const blaze::DMatInvExpr<blaze::DynamicMatrix<double>, false>]’:
/usr/local/include/blaze/math/views/column/Dense.h:2284:43:   required from ‘class blaze::Column<const blaze::DMatInvExpr<blaze::DynamicMatrix<double>, false>, false, true, false>’
/usr/local/include/blaze/math/views/Column.h:314:11:   required from ‘decltype(auto) blaze::column(const blaze::Matrix<MT1, SO1>&, std::size_t, RCAs ...) [with MT = blaze::DMatInvExpr<blaze::DynamicMatrix<double>, false>; bool SO = false; RCAs = {blaze::Check<false>}; std::size_t = long unsigned int]’
/usr/local/include/blaze/math/expressions/DMatDMatMultExpr.h:380:34:   required from ‘blaze::DMatDMatMultExpr< <template-parameter-1-1>, <template-parameter-1-2>, <anonymous>, <anonymous>, <anonymous>, <anonymous> >::ReturnType blaze::DMatDMatMultExpr< <template-parameter-1-1>, <template-parameter-1-2>, <anonymous>, <anonymous>, <anonymous>, <anonymous> >::operator()(std::size_t, std::size_t) const [with MT1 = blaze::DynamicMatrix<double>; MT2 = blaze::DMatInvExpr<blaze::DynamicMatrix<double>, false>; bool SF = false; bool HF = false; bool LF = false; bool UF = false; blaze::DMatDMatMultExpr< <template-parameter-1-1>, <template-parameter-1-2>, <anonymous>, <anonymous>, <anonymous>, <anonymous> >::ReturnType = const double; std::size_t = long unsigned int]’
test.cpp:6:19:   required from here
/usr/local/include/blaze/math/Aliases.h:130:48: error: no type named ‘ConstPointer’ in ‘const class blaze::DMatInvExpr<blaze::DynamicMatrix<double>, false>’
 using ConstPointer_t = typename T::ConstPointer;
                                                ^
In file included from /usr/local/include/blaze/math/views/Column.h:75,
                 from /usr/local/include/blaze/math/adaptors/hermitianmatrix/Dense.h:72,
                 from /usr/local/include/blaze/math/adaptors/HermitianMatrix.h:45,
                 from /usr/local/include/blaze/math/SparseMatrix.h:44,
                 from /usr/local/include/blaze/math/CompressedMatrix.h:49,
                 from /usr/local/include/blaze/Math.h:48,
                 from test.cpp:1:
/usr/local/include/blaze/math/views/column/Dense.h: In instantiation of ‘class blaze::Column<const blaze::DMatInvExpr<blaze::DynamicMatrix<double>, false>, false, true, false>’:
/usr/local/include/blaze/math/views/Column.h:314:11:   required from ‘decltype(auto) blaze::column(const blaze::Matrix<MT1, SO1>&, std::size_t, RCAs ...) [with MT = blaze::DMatInvExpr<blaze::DynamicMatrix<double>, false>; bool SO = false; RCAs = {blaze::Check<false>}; std::size_t = long unsigned int]’
/usr/local/include/blaze/math/expressions/DMatDMatMultExpr.h:380:34:   required from ‘blaze::DMatDMatMultExpr< <template-parameter-1-1>, <template-parameter-1-2>, <anonymous>, <anonymous>, <anonymous>, <anonymous> >::ReturnType blaze::DMatDMatMultExpr< <template-parameter-1-1>, <template-parameter-1-2>, <anonymous>, <anonymous>, <anonymous>, <anonymous> >::operator()(std::size_t, std::size_t) const [with MT1 = blaze::DynamicMatrix<double>; MT2 = blaze::DMatInvExpr<blaze::DynamicMatrix<double>, false>; bool SF = false; bool HF = false; bool LF = false; bool UF = false; blaze::DMatDMatMultExpr< <template-parameter-1-1>, <template-parameter-1-2>, <anonymous>, <anonymous>, <anonymous>, <anonymous> >::ReturnType = const double; std::size_t = long unsigned int]’
test.cpp:6:19:   required from here
/usr/local/include/blaze/math/views/column/Dense.h:2287:101: error: no type named ‘ConstPointer’ in ‘const class blaze::DMatInvExpr<blaze::DynamicMatrix<double>, false>’
    using Pointer = If_t< IsConst_v<MT> || !HasMutableDataAccess_v<MT>, ConstPointer, Pointer_t<MT> >;
                                                                                                     ^
/usr/local/include/blaze/math/views/column/Dense.h:2619:73: error: no type named ‘ConstIterator’ in ‘const class blaze::DMatInvExpr<blaze::DynamicMatrix<double>, false>’
    using ConstIterator = ColumnIterator< const MT, ConstIterator_t<MT> >;
                                                                         ^
/usr/local/include/blaze/math/views/column/Dense.h:2622:95: error: no type named ‘ConstIterator’ in ‘const class blaze::DMatInvExpr<blaze::DynamicMatrix<double>, false>’
    using Iterator = If_t< IsConst_v<MT>, ConstIterator, ColumnIterator< MT, Iterator_t<MT> > >;
                                                                                               ^
In file included from /usr/local/include/blaze/math/views/band/Dense.h:46,
                 from /usr/local/include/blaze/math/views/Band.h:72,
                 from /usr/local/include/blaze/math/Band.h:50,
                 from /usr/local/include/blaze/Math.h:46,
                 from test.cpp:1:
/usr/local/include/blaze/math/views/column/Dense.h:2756:4: error: static assertion failed: Computation type detected
    BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE     ( MT );
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

I understand that accessing an element of an expression involving matrix inversion is non-trivial, and probably does not make a lot of sense. Maybe adding a compile-time check to make the compiler output shorter and more meaningful would help.

Comments (5)

  1. Mikhail Katliar reporter

    Actually the last error message

    /usr/local/include/blaze/math/views/column/Dense.h:2756:4: error: static assertion failed: Computation type detected
        BLAZE_CONSTRAINT_MUST_NOT_BE_COMPUTATION_TYPE     ( MT );
    

    is the one which is informative. But it gets lost in the other errors about missing types etc..

  2. Klaus Iglberger

    Hi Mikhail!

    Thanks for creating this issue. Indeed, it is not possible to access individual elements of a matrix inversion. This fact is even documented in the wiki:

    … Furthermore, it is important to note that it is not possible to use any kind of view on the expression object returned by the inv() function. Also, it is not possible to access individual elements via the function call operator on the expression object: …

    Still, you are correct that the error message could be clearer and more specific. We will try to improve the error message.

    Best regards,

    Klaus!

  3. Klaus Iglberger

    Hi Mikhail!

    Thanks again for creating this issue. I have taken a closer look at the issue and found that the complexity of the error message depends on the compiler. Whereas GCC prints a long list of errors, which hide the real problem, Clang creates a very short and specific error message:

    $(HOME)/blaze/blaze/math/expressions/DMatDMatMultExpr.h:352:29: error: type 'blaze::DMatDMatMultExpr<blaze::DynamicMatrix<double, false>, blaze::DMatInvExpr<blaze::DynamicMatrix<double, false>,
          false>, false, false, false, false>::RightOperand' (aka 'const blaze::DMatInvExpr<blaze::DynamicMatrix<double, false>, false>') does not provide a call operator
             return lhs_(i,i) * rhs_(i,j);
                                ^~~~
    src/Sandbox.cpp:406:16: note: in instantiation of member function 'blaze::DMatDMatMultExpr<blaze::DynamicMatrix<double, false>, blaze::DMatInvExpr<blaze::DynamicMatrix<double, false>, false>, false,
          false, false, false>::operator()' requested here
       (B * inv(R))(0, 0);
                   ^
    1 error generated.
    

    I have tried a couple of things to make GCC create a similarly short error message, but unfortunately did not succeed to move the important part of the error message to the top. Thus I give up and hope that in time the error messages in GCC improve. Thanks again,

    Best regards,

    Klaus!

  4. Log in to comment