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++?
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;
Related
So, we are working on a C++ math application designed for distributed memory systems (so typically some supercomputer with homogeneous nodes) and I have the following problem:
Currently, we have a implementation of a distributed vector (in the math sense), which is a tree-like structure of our second local vector class: pretty much being just a std::vector with some operations on top. Both vectors are template classes and inherit from some abstract math vector interface. I wrote some quick code below.
template<typenname T>
class AbstractVector {
public:
T one_norm() const = 0;
...
}
template<typename T>
class LocalVector : public AbstractVector<T> {
private:
std::vector<T> storage;
...
public:
T one_norm() const;
...
}
template<typename T>
class DistributedVector : AbstractVector<T> {
private:
AbstractVector<T>* children;
...
public:
T one_norm() const;
...
}
Now this all works well until I want to save certain attributes associated with the entries of my numerical vectors - so I would have e.g. one numerical vector and one that does not allow for computations at all but is just sort-of a storage of something.
Since the distributed math vector directly implements both, its storage model and the abstract vector interface, I cannot just use it for some random type since most of the numerical operations would not be defined for that type (e.g. "+" and "-" and "*") and would also not make any sense. Best example might even be a DistributedVector<bool> which does not make sense in the math vector but is totally reasonable else.
I think the design flaw is exactly that the concept of the distributed storage and its math implementation are not separated from each other (like in the local vector where I have the storage std::vector and the wrapper around it).
My question is - what is the nicest way to do better?
My first idea:
Ok, separate the concerns, have some kind of a distributed version of the std::vector and use that in the distributed math-vector as storage. The distributed math-vector would thus just be some kind of wrapper - or rather a decorator (the design pattern that came to my mind here) and provide the additional functionality that a math distributed vector would need.
Here I am not sure - should I let the math distributed vector inherit from both - the distributed storage and the abstract vector interface? Or is the nicer way similar to the local vector where the distributed math vector just owns a distributed storage and works on that?
Maybe there is also better design that I am missing, this is why I am asking here :)
I don't have any functional restrictions on the C++ standard I am using - but I my refactoring should not break everything possibly.
Thanks in advance!
Context
I was forced to switch from glm to Eigen only because eigen can handle dimensions beyond 4 and I don;t want to have 2 different lin alg libraries at the same time. As far as usability goes, Eigen is infinitely times worse than glm. Consider the simple operation of concatenating 2 vectors:
GLM: vec4(v1, v2);
Eigen: Vector4f v; v << v1, v2;
GLM can be done in place which means you can append in the call to a function or in the middle of a complex line with multiple math operations.
With the Eigen way you have to do the concatenation, store it in a variable and then use that variable. Eigen's way is objectively less versatile as far syntax goes.
This is one of my pet peeves but Eigen is full of stuff like this, and I am getting sick of having to comply to what it wants vs what I want to write.
With that in mind, I am thinking that maybe I can add constructors for the small cases (4 dimensional objects) to make Eigen feel more like glm. However since the class definition is in the source code of eigen, this would imply understanding and modifying its source code, which has the disadvantage of having to maintain that code unless I can merge it to eigen's source, which could take longer than I am willing to wait, and could even not be accepted.
Actual question
Can I grab a class that was defined somewhere else and create a new constructor?
The functionality you are looking for is Extension Functions. Some languages such as Kotlin have them, but C++ doesn't. So you're out of luck.
If you created your own vector library, it would be no problem, because you could then create a constructor that implicitly converts from other vectors and an operator that implicitly converts to other vectors. If you are migrating between libraries and don't need to keep both versions up to date, you could add these two functions and solve almost all compatibility issues.
At least you can define operators outside the classes, like:
glm::vec4 operator+(glm::vec4 a, Eigen::Vector4f b) {
return a + eigen_vector_to_glm_vector(b);
}
I am writing a templated function func that takes as input a matrix. I provide a SquareMatrix class that is compatible with func, but I want other matrix implementations to be compatible with func. For that reason, I have defined a concept for matrix.
template<typename T>
concept Matrix = requires (T a, int b, int c) {
{a(b, c)} -> std::convertible_to<double>;
{a.size1()}->std::convertible_to<size_t>;
{a.size2()}->std::convertible_to<size_t>;
};
I use this concept in 3 places. In my SquareMatrix.h and my SquareMatrix.cpp, I use it to define a templated constructor that produces a SquareMatrix from another Matrix. In func.h, I use it to define the templated function func. func.h imports SquareMatrix.h.
I now need to decide in what file I should put my user-defined concept Matrix. I have several questions related to this decision:
In what file should I put my Matrix concept? What should be the file name and extension?
Should each concept be in its own file? Should all the concepts for my project share a file?
I am using the Visual Studio IDE. Does that change anything?
Based on my experience, these are my recommendations:
This is a concept about matrices, so it is reasonable to write it in 'SquareMatrix.h', either at the top of the file with other concepts or just before the definition of class 'SquareMatrix'. In general, you want your concepts to be defined where a reviewer would find easier to look for it.
I don't think it is a good idea to separate all concepts into an independent file. Rather, all functions, classes and concepts related to an API should be close together. In this case, the API is related to square matrices, so all those entities should share the same file. That way you avoid jumping from file to file when reviewing, extending or fixing code.
Standard C++ is the same whether you use it on VS or anywhere else. If you are developing open source code, your collaborators will access the code in any IDE, or even with just text editors (i.e. vim, emacs). C++ is the same language for all of them.
One more thought: There are excellent matrix libraries out there. Check, for example, Armadillo, Eigen or Blaze. Instead of developing your own matrix library, it is more convenient and the code will be more efficient if you use a library.
I am writing an image processing application in C++. To define my image type, I am considering using either a boost multi array, or boost ublas matrix or Eigen 2D matrix. I would like to carefully benchmark these for all various operations I intend to do and choose one accordingly.
However, I cannot afford to pause development. Hence, I would like to start writing code in such a way that it should be easy to swap my image type definition from either ublas, Eigen or multiarray to another. I don't think typedef will save me here, because the element accessor operators are different in these libraries.
For instance, you access elements of 2D array 'myArray' as follows in each of the three libraries :
Boost multiarray : myArray[x][y]
Boost ublas : myArray (x,y)
Eigen 2DMatrix : myArray(x,y)
You can see the conflict is between [][] vs ( _ , _ ) way of accessing elements. Hence, I cannot write code for one type, and make it work with another type using a simple typedef.
Any ideas how to get around this?
I am thinking of wrapping the underlying type into a new universal type which standardizes access methodology, then I can simply swap one type for another using typedef,
Are there any pitfalls I should be worried about?
Will it cost me a lot of efficiency?
What languages feature can exploit best here?
If you could please help me get started, I will write a code and paste it here for further review.
P.S. I am not using any of the rich API of these three types. I am simply creating them, and accessing their elements.
I would use the Proxy Pattern for this case. You just easily wrap around the proxy and define a unique interface which will use your underlying objects. Hope this helps....
Edit:
I guess this link should be useful as well: Template Proxy
If you don't want to lose any efficiency, you could use a define:
typedef boost::multiarray MyArray ;
#define GET_AT(a,i,j) a[i][j]
Then you just change the typedef and define when you switch type. You could also do a template function (or proper overloading function):
template <class Array>
inline ... getAt (Array <...> const& a, int i, int j) { return a[i][j] ; }
inline ... getAt (2DMatrix <...> const& a, int i, int j) { return a(i,j) ; }
Anyway, if you'd prefer wrapping your class into a single interface, I think using the proper optimization will ensure you no efficiency loss.
I'm a C++ beginner benefiting very much from this website.
I have a questions that I've been working on for several days and I'm pretty stuck.
To give a simpler version of my problem, I have a perfectly functional class (library downloaded), say, called ProMatrix. This class performs all kinds of matrix operations such as addition, subtraction, and multiplication.
I also created my version of (derived) matrix class, say, called MyMatrix. I want MyMatrix class to perform the same kinds of matrix operations as the ProMatrix, but I want them to return things in MyMatrix format. Is there any short cut to do this???
I looked up on websites, but the examples given there only deal with void output and these functions don't do much inside.
How can I reuse a base class function in a derived class
http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Foverload_member_fn_base_derived.htm
Longer version of the story (original problem): I have downloaded TNT to do matrix operations, but they somehow don't find inverse or transpose... :(
http://wiki.cs.princeton.edu/index.php/TNT There I saw some kind person wrote the two needed functions. I struggled but I was able to incorporate them in TNT by modifying the downloaded header files, but it seems kind of dangerous to touch original codes. I couldn't figure out how to write my own header file to add these functions. So I figured that maybe I could create my own matrix class derived from TNT's Array2D, with all the properties of the parent class and also with inverse and transpose.
I'm sure there are better, cleaner ways to do it... Could you please recommend how I approach this problem? I'm really eager to develop my C++ skills and I would appreciate your time and help very much.
The usual approach is to write free functions for the additional operations; they take arguments of the original class type. So:
void transpose(ProMatrix& m); // transpose m in place
or
ProMatrix transpose(const ProMatrix& m); // return transpose of m