Implementing Matrix operations in C++ - c++

I am trying to write a simple C++ header-only library that implements some basic numerical algorithms. It's a hobbyist project, that I wish to do in my personal time.
I created a C++ MatrixX class that represents dynamic-size matrices, that is its dimensions can be supplied at run-time. Say, we create a MatrixX object as follows :
MatrixXd m {
{1, 0, 0},
{0, 1, 0},
{0, 0, 1}
};
My MatrixX<scalarType> templated class uses std::vector<scalarType> as the container to store data.
Currently, if I write m.row(i), it returns the i'th row vector of the matrix. What I'd also like is, to be able to have m.row(i) on the left-hand side of an assignment statement. Something like:
m.row(i) = {{1, 2, 3}};
m.row(j) = m.row(j) - 2*m.row(i);
Does anyone have any hints/tips on how to go about this task in C++? I am including my source code, unit tests and documentation as links below, and not pasting it inline for the sake of brevity.
Documentation
Source code
Unit Tests

A common approach for this type of situation is to have the row() method return a proxy object that represents the row without being the row itself.
You are then free to implement how this RowProxy behaves by having its operations inspect and maninupulate the matrix it was created from.
Here's a rough starting point:
template<typename T>
class RowProxy {
public:
template<std::size_t N>
RowProxy& operator=(const std::array<T, N>& rhs) {
assert(N == row_index_.columns());
// ...
}
RowProxy& operator=(const RowProxy& rhs) {
assert(matrix_.columns() == rhs.matrix_.columns());
// ...
}
RowProxy& operator=(const Vector<T>& rhs) {
assert(matrix_.columns() == rhs.matrix_.columns());
// ...
}
Vector<T>& operator*(const T& scalar) const {
return ...;
}
// more operators...
private:
MatrixX<T>& matrix_;
std::size_t row_;
template<typename T>
friend class MatrixX;
RowProxy(MatrixX<T>& m, std::size_t r) : matrix_(m), row_(r) {}
};
template<typename T>
struct MatrixX {
public:
// ...
RowProxy<T> row(std::size_t index) {
return RowProxy<T>{*this, index};
}
// ...
};
template<typename T>
Vector<T>& operator*(const T& scalar, const RowProxy* rhs) const {
return rhs * scalar;
}

Related

How to static_cast a template matrix class of int type to double type in operator overloading?

Writing an operator function to multiply a custom template matrix class with a scalar.
template <typename T>
class Matrix
{
public:
Matrix() //default constructor
Matrix(size_t Row, size_t Col); //initialize with zeros of row,col
explicit Matrix(const vector<vector<T>> matElems); // create a matrix from vec<vec>>
friend Matrix<ret_type> operator*(const Matrix<mat_type> matrix,
const scalar_type scalar);
private:
vector<vector<T>> elements;
std::size_t nRows;
std::size_t nCols;
};
template <typename mat_type, typename scalar_type,
typename ret_type = decltype(mat_type()* scalar_type())>
Matrix<ret_type> operator*(const Matrix<mat_type> matrix,
const scalar_type scalar)
{
Matrix<mat_type> copy_matrix = matrix;
Matrix<ret_type> result = static_cast<Matrix<ret_type>>(copy_matrix);
for (vector<ret_type> v : result.elements)
{
std::transform(v.begin(), v.end(), v.begin(),
std::bind1st(std::multiplies<ret_type>(), scalar));
}
return result;
}
Error:
no matching function for call to ‘Matrix<double>::Matrix(Matrix<int>&)’
on the line **Matrix<ret_type> result = static_cast<Matrix<ret_type>>(copy_matrix)**
The reason of doing this is to cast an int type matrix to double if it is multiplied by a double scalar.
You have type mismatch issue!
The Matrix is a class template which gives you a concrete type, when you instantiate with a template argument T. That means the instantiated classes with two different Ts will be two distinct types of Matrix.
That means, the Matrix<ret_type> is different from Matrix<mat_type>, hence the casting will not work, which you have tried at this line:
Matrix<ret_type> result = static_cast<Matrix<ret_type>>(copy_matrix);
This produces, the compiler error!
You need to iterate via each element of the Matrix<mat_type> and cast to the ret_type and make a new Matrix<ret_type> out of it.
That being said,
You do not require a type cast there. Since you want to return a new Matrix<ret_type> from a Matrix<int>, you could have generated a new Matrix with required type from the passed matrix.
The std::bind1st has been deprecated in c++11 and has been removed in c++17. Hence, having them in the code-base will produce compiler errors in the future compiler update. Since you have access to the c++11, use lambda functions instead.
last but not least, have a look at: Why is "using namespace std;" considered bad practice?
The following is the updated code. I hope the comments can drive through the code!
#include <iostream>
#include <vector>
#include <utility> // std::move
#include <type_traits> // std::common_type
template <typename T> class Matrix /* final */
{
private:
std::vector<std::vector<T>> elements{};
std::size_t nRows{};
std::size_t nCols{};
public:
Matrix() = default; // default constructor
explicit Matrix(std::vector<std::vector<T>> matElems)
: elements{ std::move(matElems) }
, nRows{ elements.size() }
, nCols{ elements.empty() ? 0u : elements[0].size() }
{}
template<typename mat_type, typename scalar_type>
friend auto operator*(const Matrix<mat_type>& matrix, const scalar_type scalar)
->Matrix<typename std::common_type<mat_type, scalar_type>::type>;
// or
// -> Matrix<decltype(mat_type{} * scalar_type{})> ;
// some useful member functions!
void reserve(const std::size_t n) noexcept { elements.reserve(n); }
std::size_t size() const noexcept { return elements.size(); }
// to make the "Matrix" iteratable: Useful in range-based for loop/ standard algorithms.
auto begin() noexcept ->decltype(elements.begin()) { return elements.begin(); }
auto end() noexcept ->decltype(elements.end()) { return elements.end(); }
auto begin() const noexcept ->decltype(elements.cbegin()) { return elements.cbegin(); }
auto end() const noexcept ->decltype(elements.cend()) { return elements.cend(); }
// operator<< overload for printing
friend std::ostream& operator<<(std::ostream& out, const Matrix& obj) noexcept
{
for (const auto& raw: obj)
{
for (const T ele : raw) out << ele << ' ';
out << '\n';
}
return out;
}
};
// non-member operator* definition
template<typename mat_type, typename scalar_type>
auto operator*(const Matrix<mat_type>& matrix, const scalar_type scalar)
-> Matrix<typename std::common_type<mat_type, scalar_type>::type>
// or
// -> Matrix<decltype(mat_type{} * scalar_type{}) >
{
using ret_type = typename std::common_type<mat_type, scalar_type>::type;
Matrix<ret_type> result; // default constructed matrix!
// reserve some memory for "Matrix" for unwanted reallocations!
result.reserve(matrix.size()); // calls the Matrix<T>::reserve()
for (const std::vector<mat_type>& rawVec : matrix)
{
std::vector<ret_type> newRaw;
// reserve the memory for raw vectors for unwanted reallocations!
newRaw.reserve(rawVec.size());
for (mat_type element : rawVec) newRaw.emplace_back(element * scalar);
// add the updated raws to the "result"
result.elements.emplace_back(newRaw);
}
return result;
}
int main()
{
Matrix<int> matInt{ { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} } };
auto res = matInt * 0.1;
std::cout << res; // 0.1 0.2 0.3
// 0.4 0.5 0.6
// 0.7 0.8 0.9
return 0;
}
Here is (a complete demo)
Also, note that, you can always have one dimensional std::vector (if the raw-size and col-size are run time) or std::array (if the dimension is known at compile time), and treat them as two dimentional array by index manupulations.

C++ Efficient arithmetic operator overloading for class containing Eigen matrices

I want to construct a class that contains several Eigen Matrices or Vectors. I want the objects to behave as mathematical vectors: therefore I want to overload +, - and *(by a scalar). I want to do very many linear combinations of these objects, so I would like to implement it in a way that it takes full advantage of Eigen and creates as few copies and temporaries as possible.
I usually follow the recommendations in What are the basic rules and idioms for operator overloading? but they require to pass some of the object by value rather than reference. Eigen "dislikes" when matrices are passed by value.
Below is my attempt (I overload only + for shortness) where I avoid passing by value in the overloading of + and instead I use the named return value optimization (NRVO):
template <int N> class myClass {
public:
Eigen::Matrix<double, N, N> mat = Eigen::Matrix<double, N, N>::Zero();
Eigen::Matrix<double, N, 1> vec = Eigen::Matrix<double, N, 1>::Zero();
public:
myClass(){}
myClass(Eigen::Matrix<double, N, N> & t_mat,Eigen::Matrix<double, N, 1> &t_vec) : mat (t_mat), vec(t_vec){ }
myClass(const myClass & other): mat(other.mat), vec(other.vec) {};
myClass& operator+=(const myClass& rhs){
mat += rhs.mat; vec += rhs.vec;
return *this;
}
public:
enum { NeedsToAlign = (sizeof(mat)%16)==0 || (sizeof(vec)%16)==0 };
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)
};
template <int N> myClass<N>& operator+( const myClass<N>& lhs, const myClass<N>& rhs )
{
myClass<N> nrv( lhs );
nrv += rhs;
return nrv;
}
Is this the best solution? Fastest?
As a final short question: it would be nice to use Boost/operators (https://www.boost.org/doc/libs/1_54_0/libs/utility/operators.htm) to easily complete the set of operator overloading. Can I use that, or would that cause problems? I guess it will implement binary operations passing the first argument by value.
I tried to solve the problem by myself. I tried several versions and compared them with directly summing Eigen vectors.
The first strategy follows What are the basic rules and idioms for operator overloading?:
using realValueType = double;
const int NDim = 1000000;
using InternalVecType = Eigen::Matrix<realValueType, Eigen::Dynamic, 1>;
class MyVec {
public:
InternalVecType vec;
// ... Other properties
public:
// Constructors
MyVec(): vec(InternalVecType::Random(NDim,1)) {} // Initialises as random, just for testing
MyVec(const InternalVecType& other): vec(other) {};
MyVec(const MyVec& other): vec(other.vec) {}; // Copy constructor
MyVec(MyVec&& other){vec.swap(other.vec);} // Move constructor
// Arithmetic
MyVec& operator=(MyVec other){vec.swap(other.vec);return *this;} // Copy-and-Swap
MyVec& operator+=(const MyVec& other) {vec+=other.vec; return *this;}
friend MyVec operator+(MyVec lhs, const MyVec& rhs) { lhs += rhs; return lhs;}
};
The second version uses NRVO
class MyVecNRVO {
public:
InternalVecType vec;
// ... Other properties
public:
// Constructors
MyVecNRVO(): vec(InternalVecType::Random(NDim,1)) {} // Initialises as random, just for testing
MyVecNRVO(const InternalVecType& other): vec(other) {};
MyVecNRVO(const MyVec& other): vec(other.vec) {}; // Copy constructor
MyVecNRVO(MyVec&& other){vec.swap(other.vec);} // Move constructor
// Arithmetic
MyVecNRVO& operator=(MyVecNRVO other){vec.swap(other.vec);return *this;} // Copy-and-Swap
MyVecNRVO& operator+=(const MyVecNRVO& other) {vec+=other.vec; return *this;}
friend MyVecNRVO operator+(const MyVecNRVO& lhs, const MyVecNRVO& rhs) {
MyVecNRVO nrv(lhs); nrv += rhs; return nrv;}
};
My third version uses (probably clumsily) expression templates
struct Add { static InternalVecType apply(InternalVecType lhs, InternalVecType rhs) {return lhs+rhs;} };
template<class E1, class E2, class Op> struct ComplexExpr {
E1 l_;
E2 r_;
ComplexExpr(E1 l, E2 r) : l_(l), r_(r) {}
InternalVecType getvec(){return Op::apply(l_.getvec(), r_.getvec());}
};
template<class E1, class E2> ComplexExpr<E1, E2, Add> operator+ (E1 e1, E2 e2) {
return ComplexExpr<E1, E2, Add>( e1, e2 );
}
class MyVecT {
public:
InternalVecType vec;
// ... Other properties
public:
// Constructors
MyVecT(): vec(InternalVecType::Random(NDim,1)) {} // Initialises as random, just for testing
MyVecT(const InternalVecType& other): vec(other) {};
// template<> MyVecT(
InternalVecType getvec(){return vec;};
};
To test it I created 15 vectors of types InternalVecType (meaning the Eigen type not wrapped in my class), MyVec, MyVecNRVO, and MyVecT and summed them in a single line.
What I have noticed is that the first version is not only the fastest, but also as fast as directly adding the Eigen vectors in a single line! NRVO is around 5 times slower, while my attempt at expression templates 100 times slower (ouch! but in my defence, it is my very first attempt ever :D).
It seems that the first option is not only the best, but also the optimal. Maybe a better implementation of expression templates could achieve a better speed, but since the first option is as fast as the raw summation, it does not seem worth to go in that direction. Any comment is welcome.

C++ lazy way to find union of std::sets

I want to find the union of two sets, ie add them together. I am aware of .insert() and std::set_union(), but, as far as I can tell, these require one to first obtain an iterator to the beginning and end of the second set (or worse for set_union()). It would be nice if I could just do something like + and +=; it seems like that would be a fairly obvious feature for a class that implements the mathematical concept of a set. What is the easiest way to do this?
I don't know of any ways to simplify it with existing C++ methods.
One way to simplify container algorithms that operate on the whole container is to wrap them in a template method accepting a container:
template <typename T>
void my_union(const T& cont1, const T& cont2, T& cont3)
{
// Make the union and store the result in cont3
}
If you want to have an operator for this, you can easily define one yourself:
template <typename T>
inline set<T>& operator+=(set<T>& lhs, const set<T>& rhs)
{
lhs.insert(begin(rhs), end(rhs));
return lhs;
}
template <typename T>
inline set<T> operator+(set<T> lhs, const set<T>& rhs)
{
lhs += rhs;
return lhs;
}
int main() {
set<int> a = {1, 2, 3 };
set<int> b = { 2, 3, 4};
a += b;
for (auto i : a)
cout << i << " ";
return 0;
}
The above example will print 1 2 3 4 to the console.

Making return-type dependent on source of invocation?

I wrote a c++-class that represents a mathematical matrix of arbitrary dimension NxM. Furthermore I also wrote a vector-class, deriving from it...
template<size_t N, size_t M>
class matrix{ ... };
template<size_t N>
class vector : public matrix<N,1>{ ... };
...so that an N-vector can be treated as an Nx1-matrix, for example when it comes to multiplying with integral values or addition/subtraction of equally dimensioned matrices (or vectors in this regard).
The idea behind this is to avoid repeating code - which generally is a noble goal, I think. But here is the problem arising from it:
Here is your operator-overload for the addition, which only exists in the matrix-class:
matrix<N,M> operator+(const matrix<N,M>& right){
//calculate some result and use it to construct a new instance
return matrix<N,M>(result);
}
Making sure, the vector-class offers a copy-constructor for it's matrix-representation, it should be possible to say something like this:
vector<3> a(1,2,3);
vector<3> b(3,2,1);
a = a+b;
but you can't say this:
(a+b).some_vector_instance_method();
...because (a+b) isn't a vector.
QUESTION: Is it possible to implement the matrix-operator+, so that it makes the return-type dependent on it's source of invocation? So, basically, if you invoke the + on a matrix, it should return a matrix; if invoked on a vector, it should return a vector.
Now you can do this:
template<typename D>
D operator+(const D& right){
//calculate result as usual, relying on 'right' to have what it takes
return D(result);
}
... but it is unsafe as hell.
Any ideas?
The simple approach to implementation is to implement a member operator+=() for both matrix<M, N> and for vector<M> where the latter simply delegates to the former an the matrix operator has the actual operation. Using a bit of tagging the operator+() is then implemented as a non-member operator in terms of these operator. Here is a brief sketch:
#include <iostream>
namespace matrix_operators
{
struct tag {};
template <typename T>
T operator+ (T const& lhs, T const& rhs) {
return T(lhs) += rhs;
}
}
template<size_t N, size_t M>
class matrix
: matrix_operators::tag
{
public:
matrix<N, M>& operator+= (matrix<N, M> const&) {
std::cout << "matrix<" << N << ", " << M << "::operator+=()\n";
return *this;
}
};
template<size_t N>
class vector:
public matrix<N,1>
{
public:
vector<N>& operator+= (vector<N> const& other) {
matrix<N, 1>::operator+= (other);
return *this;
}
void some_other_method() {
std::cout << "vector<" << N << ">::some_other_method()\n";
}
};
int main()
{
vector<3> a, b;
(a + b).some_other_method();
}

Inherited addition assignment op., how do I return the proper type?

I have this class to factorize common operations on N-dimensional vector spaces:
template <unsigned int N>
struct BaseVector
{
float m_data[N];
// Common operations like dot product, magnitude, test for unity, etc.
};
Note: I really want to factorize as much code as possible to minimize the amount of documentation and testing.
Now, I derive two classes:
// 3D geometric vectors
struct Vector3 : public BaseVector<3>
{
Vector3 Cross(const Vector3& other);
// ...
};
// Quaternions are a particular kind of vector space
struct Quaternion : public BaseVector<4>
{
void Interpolate(const Quaternion& start, const Quaternion& end, ...);
// ...
};
These classes behave similarly for addition and scalar multiplication (component-wise operation); so, I want to factorize operator+=() and operator*=() in the base vector class.
My question is: How do I return a reference of the proper type?
template <unsigned int N>
struct BaseVector
{
??? & operator+=(const BaseVector& other)
{
transform(m_data, m_data+N, other.m_data, m_data, plus<float>());
return ???
}
};
All my ideas so far (listed bellow) are not satisfying and I would appreciate some suggestions, thanks!
Idea #1: Use the C++ covariant return type mechanism. But then, I must overload these operators in the derived classes--am I right? (Which means duplicate testing to me.)
Idea #2: Go for templates?
template <unsigned int N>
struct BaseVector
{
template <typename T2>
T2 & operator+=(const T2& other)
{
transform(...);
return *this; // THIS IS WRONG! I'm trying to "upcast"
}
};
Idea #3: Factorize code into a private member in the base vector, but then I have to add more functions in derived classes (and more stuff to test)
template <unsigned int N>
struct BaseVector
{
private:
void DoOperatorPlus(const BaseVector& other) { transform(...); }
};
struct Vector4 : public BaseVector<4>
{
Vector4& operator+=(const Vector4& other)
{
DoOperatorPlus(other);
return *this;
}
};
You could actually try to use CRTP
The idea is that you give a template parameter to your base class of your derived class:
template <unsigned int N, typename Derived>
struct BaseVector
{
Derived & operator+=(const Derived& other)
{
transform(m_data, m_data+N, other.m_data, m_data, plus<float>());
return static_cast<Derived&>(*this);
}
};
I am not 100% sure about the return statement but this should give you an idea.