0

I am writing a custom C++ numerical library that relies heavily on linear algebra routines. I am also using Eigen to cater for the actual matrix operations. I want to decouple my library from the Eigen implementation so that it is unaware of Eigen. This will allow me to keep Eigen references in one place and make it easy to change the linear algebra library to another implementation in the near future.

In java, this would be relatively simple. However I am running into difficulties with Eigen as it uses templates. In particular I am using the types MatrixXd and VectorXd. Does anyone have any suggestions about constructing a wrapper around these classes that will provide a solid boundary between Eigen and my library?

My first attempt was implemented using composition so that calls to MyBaseMatrix were directed to calls in the contained type (e.g. MatrixXd) as suggested here: https://forum.kde.org/viewtopic.php?f=74&t=87072&p=154014&hilit=wrap+eigen#p154014. However I am sceptical that I will retain Eigen under-the-hood optimisations?

Two other solutions are suggested here: http://eigen.tuxfamily.org/dox-devel/TopicCustomizingEigen.html#ExtendingMatrixBase, (extending MatrixBase or inheriting Matrix). However they don't seem to allow me the strict boundary between Eigen types and my numerical library. Also extending MatrixBase doesn't seem to allow operator overloading?

I considered inheriting Matrix and MyBaseMatrix (multiple inheritance), but the templating has caused me headaches when trying to retain a clean boundary.

Does anyone have any experience with this particular problem, or solutions to similar problems in C++?

rnoodle
  • 534
  • 2
  • 5
  • 21

1 Answers1

0

I would not recommend doing this from a code design standpoint, as a linear algebra library is not something you are likely to replace. So encapsulating it will most likely not be beneficial and will make your code more complicated. However if you really want to do this, you would use template specialization. Something along the lines of the following:

template< typename InternalMatrixType>
class Matrix
{
private:
    InternalMatrixType _matrix;
public:
   // Example function
   float operator[](unsigned index)
   {
      return _matrix[index];
   }
};

For a particular linear algebra library:

template<>
class Matrix<EigenMatrixType>
{
private:
    EigenMatrixType _matrix;
public:
   // Example function
   float operator[](unsigned index)
   {
      return _matrix.get(index);
   }
};

Edit: Added information on typedefs to clarify usage. Based on below comment from moodle.

Throughout the library you could then typedef the template class. This will allow you to use something like cMatrix vs Matrix<InternalMatrixType>.

typedef Matrix<InternalMatrixType> cMatrix;
  • 1
    Thank you for the suggestion, but I would like to respond to your first comment. Replacing the LA library is not the primary reason for wrapping up and having a non-permeable boundary (although the strength of this requirement will vary depending on who the user is). A more important reason is one of maintenance and testing - if I expose my numerical library only to an interface for LA operations, I can inject mocks into it to test its use of its dependencies. This is incredibly important for production code integrity. – rnoodle May 01 '14 at 22:00
  • Ah I see. Adding the overhead of polymorphism on top of a linear algebra library made me cringe. Perhaps the comment was a bit of knee jerk reaction. I would definitely say that a template approach is probably what you are looking for then. It will allow you to maintain a sane level of performance and handle swapping out the underlying matrix implementation. – James McMullan May 01 '14 at 22:22
  • I am going to accept your answer as I think a template solution is the only way forward. However it doesn't quite provide what I am after as I wanted my library to couple to a specific type - the template will be a different type depending on the choice of 'InternalMatrixType'. I may just decide to tightly couple with Eigen anyway... – rnoodle May 03 '14 at 13:25
  • I am sorry I left that part out of my answer. You would typedef Matrix as Matrix. So you just use Matrix through out your library. I will update my answer with some example code, when I get to a computer. – James McMullan May 03 '14 at 19:19