我知道在Eigen中可以使用unaryExpr()
将自定义函数应用于我的Eigen矩阵和向量,例如
Eigen::VectorXd vec(4);
vec.unaryExpr([](double d) {
return d * cos(d);
});
将自定义功能应用于Eigen::VectorXd
。但是还有一种方法可以获取当前元素在Vector中的位置吗?我希望能够执行以下操作:
Eigen::VectorXd vec(4);
vec.unaryExpr([](double d, int index) {
return index * d;
});
例如,它将向量中的每个条目乘以其位置。
答案 0 :(得分:1)
您可以使用无效表达式来解决:
VectorXd v;
v = VectorXd::NullaryExpr([&v](Index i) { return v(i)*i; });
您几乎可以使用空表达式来完成所有操作:https://eigen.tuxfamily.org/dox/TopicCustomizing_NullaryExpr.html
答案 1 :(得分:1)
除了使用@ggael建议的无效表达式外,您还可以将二进制表达式与LinSpaced(size, 0, size-1)
一起使用:
VectorXd v; // some input vector
v = v.binaryExpr(VectorXd::LinSpaced(v.size(), 0, v.size()-1),
[](double d, double i){return d*i;});
// or much simpler and more efficient in this case:
v = v.cwiseProduct(VectorXd::LinSpaced(v.size(), 0, v.size()-1));
在最近版本的Eigen上,LinSpaced
应该被矢量化(尽管关于最后一个元素有些边界情况)。当然,binaryExpr
仅在传递的函子被矢量化时才被矢量化。
注意:如果您主要执行基于元素的操作,请考虑使用ArrayXd
而不是VectorXd
。
答案 2 :(得分:0)
您打算做的只是普通的for循环:
for (int i = 0; i < vec.size(); ++i)
vec(i) *= i;
那么为什么不简化事情呢?如果可以用于创建对象,请将其包装在辅助函数(模板)中。
此外,您可以要做的就是依靠Eigen的内部评估顺序。这似乎可行,但是我不确定是否会依靠它:
struct CountingUnaryFct {
double operator()(double d) const { return d*index++; }
mutable int index = 0;
};
vec.unaryExpr(CountingUnaryFct{});
这是一个相当丑陋的技巧,因为它欺骗了unaryExpr
模板,该模板要求其功能对象具有const
合格的成员operator()(double) const
({{1 }}-lambda,因此是函数对象)接受实际上确实在其内部改变其状态的实例。但是,它似乎至少在一维矩阵上可靠运行。