我正在编写一个具有1个输入和3个输出的函数,如下所示:
void ComputeABC(const Eigen::Vector2d& x,
Eigen::Matrix2d& a,
Eigen::Matrix2d& b,
Eigen::Matrix2d& c)
但是,我需要输出类型与Eigen::Matrix2d
和Eigen::Map<Eigen::Matrix2d>
兼容。幸运的是,Eigen提供了Ref
类型:
void ComputeABC(const Eigen::Vector2d& x,
Eigen::Ref<Eigen::Matrix2d> a,
Eigen::Ref<Eigen::Matrix2d> b,
Eigen::Ref<Eigen::Matrix2d> c)
现在是棘手的部分。 a,b和c的计算成本都很高,但是一些中间值可以在计算中共享,从而节省了一些计算量。鉴于这些都很昂贵,我想选择计算其中的每一个。我可以通过制作每种输出类型的指针来执行此操作,并传入NULL
以表示我不想计算该特定值。
void ComputeABC(const Eigen::Vector2d& x,
Eigen::Ref<Eigen::Matrix2d>* optional_a,
Eigen::Ref<Eigen::Matrix2d>* optional_b,
Eigen::Ref<Eigen::Matrix2d>* optional_c)
不幸的是,这非常难看,因为用户现在必须构建一个Ref
然后将其传入。尝试传入Eigen::Matrix2d*
或Eigen::Map<Eigen::Matrix2d>*
将导致编译错误。
根据以下标准,有没有人对如何使这个功能更容易使用有任何建议?
Eigen::Ref<Eigen::Matrix2d>
。Eigen::Matrix2d
或Eigen::Map<Eigen::Matrix2d>
,最好是零拷贝。double*
数组,因为这些数组不会对正在使用的内存进行任何边界检查。答案 0 :(得分:0)
我不确定如何在单个函数中使用如此多的输出参数组合创建一个干净的接口。相反,我可能倾向于把它变成一个班级。
class ABCComputer {
public:
setInput(const Eigen::Vector2d& x);
getOptionalA(Eigen::Ref<Eigen::Matrix2d>);
getOptionalB(Eigen::Ref<Eigen::Matrix2d>);
getOptionalC(Eigen::Ref<Eigen::Matrix2d>);
};
因为您说A,B和C的计算共享中间值,您可以通过使用标志指定所需的输出来一次计算所请求的值:
enum ABCOptions {
ComputeA = 0x01,
ComputeB = 0x02,
ComputeC = 0x04
};
class ABCComputer {
public:
compute(const Eigen::Vector2d& x, unsigned int options);
getOptionalA(Eigen::Ref<Eigen::Matrix2d>);
getOptionalB(Eigen::Ref<Eigen::Matrix2d>);
getOptionalC(Eigen::Ref<Eigen::Matrix2d>);
};
并使用类似
的方式调用它ABCComputer abc;
abc.compute(x, ComputeA | ComputeC);
abc.getOptionalA(my_A);
abc.getOptionalC(my_C);
答案 1 :(得分:0)
您可以为Ref<Matrix<double,2,Dynamic> >
传递可选参数,并检查cols()==0
。
using namespace Eigen;
typedef Matrix<double,2,Dynamic> Matrix2xd;
void ComputeABC(const Vector2d& x,
Ref<Matrix2xd> a, Ref<Matrix2xd> b, Ref<Matrix2xd> c)
{
if(a.cols()>0) { /* compute a */ }
if(b.cols()>0) { /* compute b */ }
if(c.cols()>0) { /* compute c */ }
}
仅使用计算a
和c
调用该函数:
Matrix2d a, c;
Vector2d x(1.0, 2.0);
ComputeABC(x, a, Matrix2xd(), c); // Matrix2xd() constructs a temporary 2x0 matrix
如果(在ComputeABC
内)已分配给a
的表达式已知有2列,则除了断言检查Matrix2d
之外,您甚至不应遇到差异a
{1}}确实有两列。
答案 2 :(得分:0)
您可以将Eigen :: Ref包装在c ++ 17 std :: optional中。有一个向c ++ 11的移植。
另一个选项使用EigenRef可默认构造为执行以下操作的事实:
template<class Obj>
class Opt
{
const bool has;
Obj obj;
public:
Opt(std::nullptr_t n=nullptr) : has(false) {}
template<class T>
Opt(T && o) : has(true), obj(std::forward<T>(o)) {}
Obj const& operator*() { return obj; }
operator bool() { return has; }
};
using namespace Eigen;
void print(Opt<Ref<VectorXf>> a, Opt<std::string> b)
{
if(a) { std::cout << "a=" << *a << std::endl; }
if(b) { std::cout << "b=" << *b << std::endl; }
}
int main()
{
VectorXf aaa;
print(aaa, nullptr);
std::cout << "Hello World!\n";
}