Home > Software design >  Error in calculating general lpNorm with Eigen
Error in calculating general lpNorm with Eigen

Time:01-13

I am trying to calculate the lpNorm of a vector with the Eigen library.

As it can be seen in the example below, with explicit values, such as v.lpNorm<1>(), it works. But it doesn't work inside the loop, with lpNorm<p>()

How can I fix this?

#include <iostream>
#include <Eigen/Dense>

using Eigen::VectorXd;

int main()
{

    int sizev = 3;
    int p;

    Eigen::VectorXd v(sizev);

    v(0) = 3.;
    v(1) = 2.;
    v(2) = 1.;

    // test 1, passes

    std::cout << "||v||_" << 1 << " = " << v.lpNorm<1>() << std::endl;
    std::cout << "||v||_" << 2 << " = " << v.lpNorm<2>() << std::endl;
    std::cout << "||v||_" << 3 << " = " << v.lpNorm<3>() << std::endl;
    std::cout << "||v||_" << 4 << " = " << v.lpNorm<4>() << std::endl;
    std::cout << "||v||_inf = "         << v.lpNorm<Eigen::Infinity>() << std::endl;

    // test 2, fails

    for (int p=1; p<5; p  )
    {
        std::cout << "||v||_" << p << " = " << v.lpNorm<p>() << std::endl;
    }
    
    return 0;

}

On compilation, I am getting the error

error: no matching member function for call to 'lpNorm'
        std::cout << "||v||_" << p << " = " << v.lpNorm<p>() << std::endl;
                                               ~~^~~~~~~~~

note: candidate template ignored: invalid explicitly-specified argument for template parameter 'p'
    template<int p> EIGEN_DEVICE_FUNC RealScalar lpNorm() const;
                                                 ^
1 error generated.

CodePudding user response:

You cannot use variable integer as a template argument, it needs to be a compile time constant, such as

constexpr int p = 3;
v.lpNorm<p>();

However, you can still have a kind of compile-time loop using e.g. std::integer_sequence. I modified a bit the example from documentation to call a function:

template<typename T, T... ints>
void exec_constexpr_loop(std::integer_sequence<T, ints...> int_seq, Eigen::Ref<Eigen::VectorXd> v)
{
    ((v.lpNorm<ints>()), ...);
}
exec_constexpr_loop(std::integer_sequence<int, 1, 2, 3>{}, v);

Live demo with dummy function, works since C 17.

  • Related