C++ 用运算符()扩展Eigen::EigenBase

C++ 用运算符()扩展Eigen::EigenBase,c++,eigen,eigen3,C++,Eigen,Eigen3,我想对偏移量为(0.5,0)和(0,0.5)的网格使用MatrixXd类。在数学公式中,速度是在单元格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 //

我想对偏移量为(0.5,0)和(0,0.5)的网格使用MatrixXd类。在数学公式中,速度是在单元格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;
}
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轴偏移,而不是同时适用于两者
  • 仅适用于硬编码到插件中的特定偏移量
  • 通过尝试使用不完全LUT预条件器编译BiCG示例,可以中断一些内部特征对流:
  • 这会导致非法免费:

    ==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
    
    ==6035==Invalid free()/delete/delete[]/realloc()
    ==6035==at 0x4C30D3B:空闲(在/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so中)
    ==6035==by 0x4E4224A:已对齐\u空闲(Memory.h:177)
    ==6035==by 0x4E4224A:条件对齐的空闲(Memory.h:230)
    ==6035==by 0x4E424A:条件对齐删除自动(Memory.h:416)
    ==6035==by 0x4E424A:调整大小(DenseStorage.h:406)
    ==6035==by 0x4E424A:调整大小(PlainObjectBase.h:293)
    ==6035==按0x4E424A:如果允许,请调整大小(AssignEvaluator.h:720)
    ==6035==by 0x4E424A:call\u density\u assignment\u循环(AssignEvaluator.h:734)
    ==6035==by 0x4E424A:run(AssignEvaluator.h:879)
    ==6035==by 0x4E424A:调用\u分配\u否\u别名(AssignEvaluator.h:836)
    ==6035==by 0x4E424A:call_赋值(AssignEvaluator.h:804)
    ==6035==by 0x4E424A:call_赋值(AssignEvaluator.h:782)
    ==6035==by 0x4E424A:_集(PlainObjectBase.h:710)
    ==6035==由0x4E424A:运算符=(矩阵h:225)
    ==6035==0x11044C:main(Runner.cpp:16)
    ==6035==地址0x2e642f73726573不是堆栈、malloc或(最近)空闲
    
    如果偏移量不是作为类成员引入的,而是操作符()中的局部变量,则valgrind不会检测到任何错误

    是否可以使用可设置的偏移量实现新的MatrixXd::operator()(双精度,双精度)

    编辑: 运算符()在父类中定义:

    本征设备功能
    特征强内联CoeffReturnType运算符()(索引行,索引列)常量
    {
    本征断言(行>=0&&row=0&&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_偏移量),int(c-c_偏移量))的代码吗

    也许,我看到您的运算符返回对标量临时对象的引用时出现了一个问题:

    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_偏移量),int(c-c_偏移量))的代码吗

    在原来的帖子中添加了答案。不确定返回副本是否是最佳解决方案。最初,我只是从中复制了一个at()方法。它返回了引用,所以我也尝试了它。编辑:不,不行。我需要这个代码的参考:
    vel(0.5,0.5)=1.0。没有引用,错误
    “=”:左操作数必须是l值,弹出窗口。@Kirikus关于您的错误,请发布一个,因为没有它我无法帮助您!在原来的帖子中添加了答案。不确定返回副本是否是最佳解决方案。最初,我只是从中复制了一个at()方法。它返回了引用,所以我也尝试了它。编辑:不,不行。我需要这个代码的参考:
    vel(0.5,0.5)=1.0。没有引用,错误
    “=”:左操作数必须是l值,弹出窗口。@Kirikus关于您的错误,请发布一个,因为没有它我无法帮助您!首先,我认为用
    (double,double)
    重载
    操作符()
    是个坏主意。如果您真的需要,我建议将
    MatrixXd
    对象包装在自定义类中。关于你的错误,请发一个帖子!首先,我认为用
    (double,double)
    重载
    操作符()
    是个坏主意。如果您真的需要,我建议将
    MatrixXd
    对象包装在自定义类中。关于你的错误,请发一个帖子!
    ==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
    
    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));
    }