Get spacing of a statically-sized matrix as a constexpr

Issue #369 wontfix
Mikhail Katliar created an issue

The StaticMatrix class defines its spacing() function as static constexpr, so the following code is possible:

using M = StaticMatrix<double, 2, 2>;
M A;
auto constexpr s = M::spacing();
auto constexpr s1 = A.spacing();

Previously, the following code also used to work:

using M = StaticMatrix<double, 2, 2>;
M A;
auto AT = trans(A);
auto constexpr s2 = decltype(AT)::spacing();
auto constexpr s3 = AT.spacing();

However after update to the current version the latter example produces the compilation error:

error: constexpr variable 's2' must be initialized by a constant expression

I would like to have a way to determine at compile-time the spacing of statically-sized matrix types, including transposed and adapted types.

Comments (8)

  1. Klaus Iglberger

    Hi Mikhail!

    I understand you motivation. Unfortunately I don’t know when the second code example used to compile, but intuitively I would argue that this shouldn’t work. Allow me to explain.

    There is an important difference between A and AT: A is a concrete matrix owning some memory, AT (derived via auto) is an expression object representing the result of an operation with no memory attached. Whereas every kind of matrix should be able to answer the question about rows() and columns() because these two functions are not related to memory, the spacing() function conceptually only makes sense for matrices owning memory. Therefore both s2 and s3 should not work.

    You can do the following instead:

    using M = StaticMatrix<double, 2, 2>;
    M A;
    auto AT = trans(A);
    using T = ResultType_t<decltype(AT)>;  // Query the concrete resulting type of the expression AT
    auto constexpr s4 = T::spacing();      // Get the static spacing information from the concrete resulting type (i.e. StaticMatrix)
    

    I hope this helps. Does this explain the rational and solve your problem?

    Best regards,

    Klaus!

  2. Mikhail Katliar reporter

    Hello Klaus!

    Thank you for the explanation. I understand your arguments. If you follow your argument “the spacing() function conceptually only makes sense for matrices owning memory” then the spacing() function should be removed from the DMatrTransExpr altogether, but it does exist. If it does exist, I don’t see a reason why it should not be constexpr if it is a compile-time constant.

    My use case is as follows: i write my own optimized implementation of LA routines which work with Blaze dense matrices. This implementation directly accesses memory owned by the matrices. From this point of view, both A and trans(A) represent the same memory layout, except that the order of indices is swapped. I need to be able to pass either StaticMatrix<> or a DMatTransExpr<StaticMatrix<>> to a function without changing its implementation. The recent changes had broken some of my code which previously compiled, but I fixed it with some specializations for the DMatrTransExpr arguments.

    Best regards,

    Misha

  3. Klaus Iglberger

    Hi Misha!

    I’m unfortunately still failing to comprehend why s2 and s3 could ever have been computed at compile time. I’m also failing to find a simple solution to the problem, because a simple constexpr in the DMatTransExpr::spacing() function doesn’t do the trick, it would require at least half a dozen other modifications, some of which would require to reimplement non-constexpr functions from the standard library. The only solution I can offer at this time is the following:

    template< typename MT
            , bool SO >
    void test( const DenseMatrix<MT,SO>& )
    {
       constexpr size_t spacing = ResultType_t<MT>::spacing();  // Compile-time evaluation of the spacing() function for StaticMatrix-related types
       std::cerr << " spacing = " << spacing << "\n";
    }
    

    If this doesn’t help, I would be glad about a pull request with the necessary modifications.

    Best regards,

    Klaus!

  4. Mikhail Katliar reporter

    Hello Klaus,

    sorry, my mistake – the code that I believed was working was actually never instantiated. I am closing the issue.

    Best,

    Misha

  5. Klaus Iglberger

    Hi Misha!

    Thanks for letting me know.

    Interesting, I’m not able to put an issue in the “invalid” state. Looks like you have a couple of more options. In order to be consistent with the remaining Blaze issues, I will change the state to “wont fix”. Thanks,

    Best regards,

    Klaus!

  6. Log in to comment