Eigen non constant MatrixReplacement for sparse solver - c++

I want to use matrix free sparse solvers with custom matrix-vector product object. Here is great example how to to it - https://eigen.tuxfamily.org/dox/group__MatrixfreeSolverExample.html
But in this example custom matrix-product object should be constant due to generic_product_impl signature
template<typename Dest>
static void scaleAndAddTo(
Dest& dst,
const MatrixReplacement& lhs,
const Rhs& rhs,
const Scalar& alpha)
In many my problems i need a lot of temporary buffers for each product call. It's pretty wise to allocate them once but i can't store them inside MatrixReplacement because it passed as const.
Is it possible in Eigen to overcome this problem?

There are two immediate options:
Use the mutable keyword for the members that need to change in const methods (i.e. your temporary buffers). This keyword makes sense where observable behavior of your class is const, despite you needing to modify members. Examples include cached values, mutexes, or your buffers.
C++ is not perfectly strict with propagating const. A const unique_ptr<T> will return a (non-const) T& when dereferenced (because the const says "you can't change the pointer", not "you can't change the pointee"; this is the same with builtin pointers). You can similarly wrap your "real" sparse matrix class in something that pretends to be const but allows non-const access to the matrix if the STL smart pointers are insufficient. If you give it an appropriate name then it's not as terrible as it sounds.
I recommend option 1.

Related

Copy function parameter to const local variable

I'm digging in glm library, and found this type of code, also there are some other simmilar stuff. My question is: what is a purpose to copy function parameter to const local variable inside function, like this -- T const a(angle). Is it for some performance benefits?
template<typename T, qualifier Q>
GLM_FUNC_QUALIFIER qua<T, Q> angleAxis(T const& angle, vec<3, T, Q> const& v)
{
T const a(angle);
T const s = glm::sin(a * static_cast<T>(0.5));
return qua<T, Q>(glm::cos(a * static_cast<T>(0.5)), v * s);
}
There’s no purpose.
This was probably done in a misguided attempt to avoid the indirection of repeatedly accessing angle (which, being a reference, is probably implemented by the compiler as a pointer). Whether this outweighs the cost of a copy is not obvious: if the type T is small and trivially copyable then making a copy is free but for larger types this will in fact incur a nontrivial overhead. On the other hand, the repeated pointer access can often be avoided entirely by the compiler.
Regardless of these considerations, if that optimisation was the purpose, it would have been more appropriate to pass angle by value instead: first passing by reference and then copying locally truly serves no purpose.

non-temporary rvalue design pattern?

I'm writing a C++ matrix-like class that allocates memory and has methods (e.g. row(), col()) that returns views of itself referencing the same memory via shared_ptr.
e.g.
Matrix Matrix::row(int r)
The fundamental problem is that C++ regards an expression such as m.row(0) to be an rvalue whereas the return type of row() is not a self-contained temporary that can be moved but rather a view (with shared memory) into the non-temporary parent matrix.
The problem manifests whenever I want to use move semantics such as:
Matrix add(const Matrix &a, const Matrix &b);
Matrix add(Matrix &&a, Matrix &&b);
If I write add(m.row(0), m.row(1)) then the compiler will call the rvalue version of add() which may modify it's temporary parameters and therefore the non-temporary parent matrix m! :-(
I don't want to avoid rvalues and always pass by value instead:
Matrix add(Matrix a, Matrix b);
Since although this handles the rvalue case efficiently (via move construction), it also means I'm always copying non-rvalues which is inefficient.
I also don't want to make the return type of row() const since I want to be able to treat it as an lvalue:
m.row(0) = m.row(1);
I've considered explicitly testing whether rvalue parameters are views via shared_ptr use_count(), but this seems messy since the whole point of rvalues is that it's meant to be a type signature of temporary values that are inherently modifiable.
Can anyone suggest a design pattern for this type of situation where a function return value is a non-temporary value (such as a view onto something else), but you also want to use rvalue optimizations?

comparator for sorting a vector contatining pointers to objects of custom class

By this question I am also trying to understand fundamentals of C++, as I am very new to C++. There are many good answers to problem of sorting a vector/list of custom classes, like this. In all of the examples the signature of comparator functions passed to sort are like this:
(const ClassType& obj1, const ClassType& obj2)
Is this signature mandatory for comparator functions? Or we can give some thing like this also:
(ClassType obj1, ClassType obj2)
Assuming I will modify the body of comparator accordingly.
If the first signature is mandatory, then why?
I want to understand reasons behind using const and reference'&'.
What I can think is const is because you don't want the comparator function to be able to modify the element. And reference is so that no multiple copies are created.
How should my signature be if I want to sort a vector which contains pointers to objects of custom class? Like (1) or (2) (see below) or both will work?
vertor to be sorted is of type vector
(1)
(const ClassType*& ptr1, const ClassType*& ptr2)
(2)
(ClassType* ptr1, ClassType* ptr2)
I recommend looking through This Documentation.
It explains that the signature of the compare function must be equivalent to:
bool cmp(const Type1& a, const Type2& b);
Being more precise it then goes on to explain that each parameter needs to be a type that is implicitly convertable from an object that is obtained by dereferencing an iterator to the sort function.
So if your iterator is std::vector<ClassType*>::iterator then your arguments need to be implicitly convertable to ClassType*.
If you are using something relatively small like an int or a pointer then I would accept them by value:
bool cmp(const ClassType* ptr1, const ClassType* ptr2) // this is more efficient
NOTE: I made them pointers to const because a sort function should not modify the values it is sorting.
(ClassType obj1, ClassType obj2)
In most situations this signature will also work, for comparators. The reason it is not used is because you have to realize that this is passing the objects by value, which requires the objects to be copied.
This will be a complete waste. The comparator function does not need to have its own copies of its parameters. All it needs are references to two objects it needs to compare, that's it. Additionally, a comparator function does not need to modify the objects it is comparing. It should not do that. Hence, explicitly using a const reference forces the compiler to issue a compilation error, if the comparator function is coded, in error, to modify the object.
And one situation where this will definitely not work is for classes that have deleted copy constructors. Instances of those classes cannot be copied, at all. You can still emplace them into the containers, but they cannot be copied. But they still can be compared.
const is so you know not to change the values while you're comparing them. Reference is because you don't want to make a copy of the value while you're trying to compare them -- they may not even be copyable.
It should look like your first example -- it's always a reference to the const type of the elements of the vector.
If you have vector, it's always:
T const & left, T const & right
So, if T is a pointer, then the signature for the comparison includes the comparison.
There's nothing really special about the STL. I use it for two main reasons, as a slightly more convenient array (std::vector) and because a balanced binary search tree is a hassle to implement. STL has a standard signature for comparators, so all the algorithms are written to operate on the '<' operation (so they test for equality with if(!( a < b || b < a)) ). They could just as easily have chosen the '>' operation or the C qsort() convention, and you can write your own templated sort routines to do that if you want. However it's easier to use C++ if everything uses the same conventions.
The comparators take const references because a comparator shouldn't modify what it is comparing, and because references are more efficient for objects than passing by value. If you just want to sort integers (rarely you need to sort just raw integers in a real program, though it's often done as an exercise) you can quite possibly write your own sort that passes by value and is a tiny bit faster than the STL sort as a consequence.
You can define the comparator with the following signature:
bool com(ClassType* const & lhs, ClassType* const & rhs);
Note the difference from your first option. (What is needed is a const reference to a ClassType* instead of a reference to a const ClassType*)
The second option should also be good.

Calling Operator() "function call" to return reference to array element

I think I don't really understand what's behind references, and I'd be glad to learn more about those.
I'm writing a math "vector" Class to do basic linear algeabra for numerical simulation. I was using Eigen before i was convinced not to use external libraries anymore. My problem is pretty straightforward :
I declare vector and sets its 3 components of type Scalar (these are doubles). I can do math with my vectors as I overload operators, but this is beyond the scope of my question.
I want to access the i-th component of my object through the function call operator () as I was used with Eigen : myVector(0) = 0.0 ; or Scalar d = myVector(0)+1.0 ;
According to my understanding of references, this solution should be working :
class mtnVector {
public:
typedef double Scalar;
Scalar data [3];
(setters, math, etc...)
inline Scalar & operator() (const int i) const {
return data[i] ;
}
};
But g++ says that it doesn't like the way I implement it and comfirms I s*** at references :
Vector.h:185: error: invalid initialization of reference of type ?double&? from expression of type ?const double?
What's very strange from my point of view is that if the array containing the data is dynamically set (Scalar * data) (with new operator) at class construction, the code compiles fine. But I don't see the point of having dynamically set data holder.
I don't get neither the need of const to overload the function call operator but I accept it.
Your operator() is declared const. This means that calling the function should never end up modifying the object. That function returns a member of this object by non-const reference, which would allow whoever called operator() to modify the internals of the object. Obviously this would be silly, so the compiler just doesn't allow it. If you're going to return a reference to a member from a const member function, you need to make that reference const:
inline const Scalar& operator() (const int i) const {
return data[i] ;
}
You might want to provide both a const and non-const version of the function, one of which returns a const Scalar& and the other a Scalar& (this is how the standard library containers do it).
It seems strange that you'd want to use operator() for this. Your expression myVector(0) would look more natural as myVector[0], which you can achieve through overloading operator[] instead.
Also, you should ignore whoever convinced you that you shouldn't use external libraries. Eigen, in particular, is a very mature and thoroughly tested library. Unless you really have a good reason, you should be using it.

overhead of copying: doubles vs pointers

the overhead of copying two doubles can be noticeable but often less
than what a pair of pointers impose
from C++ prog. lang.
could someone explain it?
This is taken from Chapter 11 of "The C++ Programming Language" by Stroustrup.
Let's look at the quote in context:
We defined the complex operators to take arguments of type complex. This implies that for each use of a complex operator, each operand is copied. The overhead of copying two doubles can be noticeable but often less than what a pair of pointers impose (access through a pointer can be relatively expensive). Unfortunately, not all classes have a conveniently small representation. To avoid excessive copying, one can declare functions to take reference arguments. For example:
class Matrix {
double m[4][4];
public:
Matrix();
friend Matrix operator+(const Matrix&, const Matrix&);
friend Matrix operator*(const Matrix&, const Matrix&);
};
All he is saying is that, since complex is small, it is acceptable to pass it around by value rather than by const reference. This, however, would not be acceptable for larger types, such as Matrix above. For such type, passing by const reference is the preferred method since it would avoid having to copy the whole matrix.