【问题标题】:Returned Eigen Matrix from templated function changes value从模板化函数返回的特征矩阵更改值
【发布时间】:2022-01-17 20:21:17
【问题描述】:

我遇到了一些关于 eigen 库和模板化函数的奇怪行为。

也许有人可以向我解释,为什么第一个版本不起作用,而其他 3 个版本起作用。我的猜测是第一个释放一些局部变量的情况,但希望有人能启发我。提前致谢。

代码如下:

编译器-浏览器:https://compiler-explorer.com/z/r45xzE417

#include <concepts>
#include <iostream>

#include <Eigen/Core>

auto RungeKutta1_auto(const auto& f, const std::floating_point auto& h, const auto& y_n)
{
    auto ret = y_n + h * f(y_n);
    std::cout << ret.transpose() << std::endl;
    return ret;
}

template<typename _Scalar, int _Rows, int _Cols>
auto RungeKutta1_template(const auto& f, const std::floating_point auto& h, const Eigen::Matrix<_Scalar, _Rows, _Cols>& y_n)
{
    Eigen::Matrix<_Scalar, _Rows, _Cols> ret = y_n + h * f(y_n);
    std::cout << ret.transpose() << std::endl;
    return ret;
}

int main()
{
    auto f = [](const Eigen::Matrix<double, 10, 1>& y) {
        Eigen::Matrix<double, 10, 1> y_dot = 2 * y;
        return y_dot;
    };

    auto g = [](const Eigen::Matrix<double, 10, 1>& y) {
        return 2 * y;
    };

    std::cout << "RungeKutta1_auto(f, 0.05, y):" << std::endl;
    Eigen::Matrix<double, 10, 1> y;
    y << 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;
    y = RungeKutta1_auto(f, 0.05, y);
    std::cout << y.transpose() << std::endl;
    // Output
    //   0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9
    // 3.47627e-311            1            2            3            4            5          6.6            7            8            9

    std::cout << "RungeKutta1_template(f, 0.05, y):" << std::endl;
    y << 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;
    y = RungeKutta1_template(f, 0.05, y);
    std::cout << y.transpose() << std::endl;
    // Output
    //   0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9
    //   0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9

    std::cout << "RungeKutta1_auto(g, 0.05, y):" << std::endl;
    y << 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;
    y = RungeKutta1_auto(g, 0.05, y);
    std::cout << y.transpose() << std::endl;
    // Output
    //   0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9
    //   0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9

    std::cout << "RungeKutta1_template(g, 0.05, y):" << std::endl;
    y << 0, 1, 2, 3, 4, 5, 6, 7, 8, 9;
    y = RungeKutta1_template(g, 0.05, y);
    std::cout << y.transpose() << std::endl;
    // Output
    //   0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9
    //   0 1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 9.9
}

【问题讨论】:

标签: c++ lambda eigen auto


【解决方案1】:

在第一个版本中,

auto ret = y_n + h * f(y_n);

由于 Eigen 的表达式模板,这为您提供了一个中间表达式类型,而不是 Matrix 类型。您需要在其上显式调用 eval() 以强制发生惰性 eval(并在这种情况下将表达式转换为生成的 Matrix 类型对象);例如:

auto ret = (y_n + h * f(y_n)).eval();

在其他版本中,您将ret 的类型显式输入为Matrix 类型,这意味着您最终不会存储中间表达式模板类型。

【讨论】:

  • 谢谢,我猜这些表达式模板是失败的原因。唯一让我感到困惑的是,为什么带有 lambda f 和函数 RungeKutta1_auto 的版本失败,而 lambda g 和函数 RungeKutta1_auto 没有。我原以为g lambda 会产生更多的表达式模板,因此应该会失败更多。但我想这对 Eigen 库以及它们如何处理它们的类型来说太深入了。无论如何,谢谢你的回答。这为我解决了这个问题
猜你喜欢
  • 2022-01-23
  • 1970-01-01
  • 1970-01-01
  • 2012-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多