How do I write a function that has optional Eigen :: Ref output arguments?

I am writing a function that has 1 input and 3 outputs, for example:

void ComputeABC(const Eigen::Vector2d& x,
                Eigen::Matrix2d& a,
                Eigen::Matrix2d& b,
                Eigen::Matrix2d& c)

      

However, I need my output types for compatibility with Eigen::Matrix2d

and Eigen::Map<Eigen::Matrix2d>

. Fortunately, Eigen provides a type Ref

:

void ComputeABC(const Eigen::Vector2d& x,
                Eigen::Ref<Eigen::Matrix2d> a,
                Eigen::Ref<Eigen::Matrix2d> b,
                Eigen::Ref<Eigen::Matrix2d> c)

      

Now comes the tricky part. a, b and c are all expensive to compute, but some intermediate values ​​can be split up in the computation, thus preserving some computation. Given that it is expensive, I want to calculate each one. I can do this by creating each type of pointer output and passing in NULL

to signal that I don't want to compute that particular value.

void ComputeABC(const Eigen::Vector2d& x,
                Eigen::Ref<Eigen::Matrix2d>* optional_a,
                Eigen::Ref<Eigen::Matrix2d>* optional_b,
                Eigen::Ref<Eigen::Matrix2d>* optional_c)

      

Unfortunately, this is pretty ugly, as now the user has to build Ref

and then pass it. Trying to navigate to Eigen::Matrix2d*

or Eigen::Map<Eigen::Matrix2d>*

will result in a compilation error.

Does anyone have any suggestions on how to make this function easier to use given the following criteria?

  • Adding an extra 3 bools to optionally compute values ​​is rather awkward and the user will still have to create a dummy Eigen::Ref<Eigen::Matrix2d>

    for every unwanted output.
  • The calling code has either Eigen::Matrix2d

    or Eigen::Map<Eigen::Matrix2d>

    for each argument that must be filled, preferably with null copies.
  • Avoid using bare arrays double*

    as they do not provide bounds checking for the memory used.
  • Any subset of a, b, and c can be requested. ([a], [a, b], [a, b, c], [b], [b, c], [c]). So overloads don't scale very well.
+3


source to share


2 answers


I'm not sure how you can make a clean interface with so many combinations of output arguments in one function. Instead, I'm probably leaning towards turning it into a class.

class ABCComputer {
public:
  setInput(const Eigen::Vector2d& x);

  getOptionalA(Eigen::Ref<Eigen::Matrix2d>);
  getOptionalB(Eigen::Ref<Eigen::Matrix2d>);
  getOptionalC(Eigen::Ref<Eigen::Matrix2d>);
};

      

Since you say that intermediate value calculations separate A, B and C, you can calculate the requested values ​​right away by specifying which outputs are needed with flags:



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>);
};

      

and call it something like

ABCComputer abc;
abc.compute(x, ComputeA | ComputeC);
abc.getOptionalA(my_A);
abc.getOptionalC(my_C);

      

0


source


You can pass Ref<Matrix<double,2,Dynamic> >

for optional arguments and check if there is one 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 */ }
}

      

To call a function with calculations only a

and c

:



Matrix2d a, c;
Vector2d x(1.0, 2.0);
ComputeABC(x, a, Matrix2xd(), c); // Matrix2xd() constructs a temporary 2x0 matrix

      

If (internally ComputeABC

) the expression you are assigning a

is known to have 2 columns, you shouldn't even experience the vs difference Matrix2d

, other than checking the assertion that it a

does have 2 columns.

0


source







All Articles