使用 operator() 扩展 Eigen::EigenBase
Extending Eigen::EigenBase with operator()
我想将MatrixXd类用于偏移量为(0.5,0(和(0,0.5(的网格。在数学公式中,速度是在单元格 i,i+1 之间计算的,这写为 vel(i+0.5,j(。我想介绍这样的语法:
#include <Eigen/Dense>
int main() {
Eigen::MatrixXd m = Eigen::MatrixXd::Zero(5,5);
// Want to use similar syntax:
// m(0, 1.5) = 1.0;
// and
// m(3.5, 1) = 2.0;
// Instead of:
m(0, 2) = 1.0;
m(4, 1) = 2.0;
}
使用如下所示EIGEN_MATRIXBASE_PLUGIN:
inline Scalar& operator()(int r, int c) {
return Base::operator()(r, c);
}
inline Scalar& operator()(double r, int c) {
return Base::operator()(int(r + 0.5), c);
}
inline Scalar& operator()(int r, double c) {
return Base::operator()(r, int(c + 0.5));
}
但是,这种方法:
- 仅适用于 X 轴或 Y 轴偏移,不能同时用于两者。
- 仅适用于硬编码到插件中的特定偏移量。
- 打破了一些内部特征对流,可以通过尝试使用 IncompleteLUT 预条件器编译 BiCG 示例来演示:
int n = 10000;
VectorXd x(n), b(n);
SparseMatrix<double> A(n,n);
/* ... fill A and b ... */
BiCGSTAB<SparseMatrix<double>,IncompleteLUT<double>> solver;
solver.compute(A);
x = solver.solve(b);
导致以下错误:
term does not evaluate to a function taking 1 arguments
'Eigen::SparseMatrix<double,1,int>::insertBackByOuterInnerUnordered': function does not take 1 arguments
添加运算符(((双offset_col,双offset_row(来解决第二个问题,如下所示:
double r_offset = -0.5, c_offset = -0.5;
inline void set_r_offset(double val) { r_offset = val; }
inline void set_c_offset(double val) { c_offset = val; }
inline double get_r_offset() { return r_offset; }
inline double get_c_offset() { return c_offset; }
inline Scalar& operator()(double r, double c) {
// double r_offset = -0.5, c_offset = -0.5;
return Base::operator()(int(r - r_offset), int(c - c_offset));
}
这会导致非法免费:
==6035== Invalid free() / delete / delete[] / realloc()
==6035== at 0x4C30D3B: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6035== by 0x4E4224A: aligned_free (Memory.h:177)
==6035== by 0x4E4224A: conditional_aligned_free<true> (Memory.h:230)
==6035== by 0x4E4224A: conditional_aligned_delete_auto<double, true> (Memory.h:416)
==6035== by 0x4E4224A: resize (DenseStorage.h:406)
==6035== by 0x4E4224A: resize (PlainObjectBase.h:293)
==6035== by 0x4E4224A: resize_if_allowed<Eigen::Matrix<double, -1, -1>, Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op<double>, Eigen::Matrix<double, -1, -1> >, double, double> (AssignEvaluator.h:720)
==6035== by 0x4E4224A: call_dense_assignment_loop<Eigen::Matrix<double, -1, -1>, Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op<double>, Eigen::Matrix<double, -1, -1> >, Eigen::internal::assign_op<double, double> > (AssignEvaluator.h:734)
==6035== by 0x4E4224A: run (AssignEvaluator.h:879)
==6035== by 0x4E4224A: call_assignment_no_alias<Eigen::Matrix<double, -1, -1>, Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op<double>, Eigen::Matrix<double, -1, -1> >, Eigen::internal::assign_op<double, double> > (AssignEvaluator.h:836)
==6035== by 0x4E4224A: call_assignment<Eigen::Matrix<double, -1, -1>, Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op<double>, Eigen::Matrix<double, -1, -1> >, Eigen::internal::assign_op<double, double> > (AssignEvaluator.h:804)
==6035== by 0x4E4224A: call_assignment<Eigen::Matrix<double, -1, -1>, Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op<double>, Eigen::Matrix<double, -1, -1> > > (AssignEvaluator.h:782)
==6035== by 0x4E4224A: _set<Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op<double>, Eigen::Matrix<double, -1, -1> > > (PlainObjectBase.h:710)
==6035== by 0x4E4224A: operator=<Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op<double>, Eigen::Matrix<double, -1, -1> > > (Matrix.h:225)
==6035== by 0x11044C: main (Runner.cpp:16)
==6035== Address 0x2e642f73726573 is not stack'd, malloc'd or (recently) free'd
如果偏移量不是作为类成员引入的,而是 operator(( 中的局部变量,则 valgrind 不会检测到任何错误。
是否可以实现具有可设置偏移量的新 MatrixXd::operator(((double, double(?
编辑: Operator(( 在父类 DenseCoeffsBase 中定义:
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE CoeffReturnType operator()(Index row, Index col) const
{
eigen_assert(row >= 0 && row < rows()
&& col >= 0 && col < cols());
return coeff(row, col);
}
也许,我看到您的运算符存在一个问题,它返回对标量临时对象的引用:
inline Scalar& operator()(double r, double c) {
// double r_offset = -0.5, c_offset = -0.5;
return Base::operator()(int(r - r_offset), int(c - c_offset));
}
所以你应该通过复制返回标量。
你能分享 Base::operator(((int(r - r_offset(, int(c - c_offset((;的代码吗?
相关文章:
- Eigen如何在容器循环中干净地附加矩阵
- 当在带有Eigen的C++中使用GDB时,我如何才能看到更多的大矩阵
- 使用Pybind11向Python公开Eigen::张量
- 如何在没有数据拷贝的情况下从指针创建一个Eigen VectorXd对象
- Eigen:调用lpNorm()的正确方法
- 如何调整 std::vector of Eigen::MatrixXd 的大小
- 如何将 Eigen::Ref 与 pybind11 一起使用?
- Eigen c++ 三角形来自
- 使用 operator() 扩展 Eigen::EigenBase
- 如何将 Eigen 库安装到 IAR c/c++ 编译器
- 初始化 std::数组 of Eigen::Map
- Eigen - matrix.transpose 会创建矩阵的副本吗?
- 将 MatrixXd 的行传递给要修改的函数,而不在 Eigen 中创建副本
- C++ Eigen 库中的 argmax() 方法
- Eigen::VectorXd 和 Boost::Odeint,不起作用
- 将数据从 std::Vector 存储到 Eigen::Vector 时出错
- Eigen LinSpaced - 已弃用的副本警告
- C++:如何将 std::vector 操作转换为 Eigen::VectorXf?
- Eigen:我应该使用对齐地图进行密集计算吗?
- 返回 Eigen::Ref 合法吗?