ScaleAndAddTo in Eige GMEV - eigen

In order to provide matrix by vector multiplication, Eigen implements scaleAndAddTo operation which can be specialized for the users matrix type.
According to https://eigen.tuxfamily.org/dox/group__MatrixfreeSolverExample.html
the user have to provide an specialization for scaleAndAddTo, which computes dst += alpha * lhs * rhs.
I have been following the call stack of until this is called and Eigen is doing the following:
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void evalTo(Dst& dst, const Lhs& lhs, const Rhs& rhs)
{ dst.setZero(); scaleAndAddTo(dst, lhs, rhs, Scalar(1)); }
Since dst is set to zero, I can't understand why we need to provide a scaleAndAddTo instead of something like scale directly.
Why is the add part required?

Related

STL algorithm for splitting a vector into multiple smaller ones based on lambda

Let's say I have a vector containing a struct with a member describing its target vector.
struct Foo
{
int target;
static const int A = 0;
static const int B = 1;
static const int C = 2;
};
std::vector<Foo> elements;
std::vector<Foo> As;
std::vector<Foo> Bs;
std::vector<Foo> Cs;
std::vector<Foo> others;
Now I want to move each Foo in one of the four other vectors based on the value of Target.
For example
auto elements = std::vector<Foo>{ {Foo::A}, {Foo::A}, {Foo::B} };
Should result in two elements in As, one in Bs and none in Cs or others. Elements should be empty afterwards.
I could as well do it myself, but I wonder if there is an STL algorithm I could use to do its job.
Standard algorithms usually don't operate on multiple output destinations, so it's hard to come up with a suitable solution here when you want to abstract away the destination containers through output iterators. What might come closest is std::copy_if. This could look like
// Help predicate creation:
auto pred = [](int target){ return [target](const Foo& f){ return f.target == target; }; };
std::copy_if(elements.begin(), elements.end(), std::back_inserter(As), pred(Foo::A));
std::copy_if(elements.begin(), elements.end(), std::back_inserter(Bs), pred(Foo::B));
std::copy_if(elements.begin(), elements.end(), std::back_inserter(Cs), pred(Foo::C));
std::copy_if(elements.begin(), elements.end(), std::back_inserter(others),
[](const Foo& f){ return false; /* TODO */ });
elements.clear();
If copying is more expensive than move-construction, you should pass std::make_move_iterator(elements.begin()) and the same for elements.end() to the algorithm. The issue here is that this doesn't scale. std::copy_if linearly traverses the input range, and the above has to do this four times. One traversal can be obtained e.g. like the following.
auto doTheWork = [&As, &Bs, &Cs, &others](const Foo& foo) {
if (foo.target == Foo::A)
As.push_back(foo);
else if (foo.target == Foo::B)
Bs.push_back(foo);
else if (foo.target == Foo::C)
Cs.push_back(foo);
else
others.push_back(foo);
};
std::for_each(elements.begin(), elements.end(), doTheWork);
In this scenario, we have at least employed a standard algorithm, but shifted the logic into a rather ugly lambda. Note that the above lambda will always copy its arguments, it needs some adjustments to properly work with std::move_iterators.
Sometimes, a good old range based for loop is the most readable solution.

Eigen::DenseBase has no data member

Why does Eigen::DenseBase<Derived> has no data() method?
I thought a dense array would be contiguous in the memory.
Are blocks also DenseBase?
template <typename Derived>
void f(Eigen::DenseBase<Derived>& x) {
std::sort(x.data(), x.data() + x.size());
}
ArrayBase also has no data method.
Work around:
template <typename Derived>
void f(Eigen::DenseBase<Derived>& x) {
std::sort(&x[0], &x[0] + x.size()); // sort the whole vector
}
DenseBase is the base class for any dense expressions, including A+B, A*B, etc. If all you want is to call std::sort, then move to Eigen's head, and write:
std::sort(x.begin(), x.end());
If the expression you passed to f has a .data() member you can still reach it as follows: x.derived().data().

How to create a row-major C array from an Eigen matrix with run-time dimensions?

The following two posts are very helpful but not quite what I need:
Convert Eigen Matrix to C array
Creating an Eigen matrix from an array with row-major order
However, I need to create a row-major C array (see 2) from an Eigen::MatrixXd, and I need to be able to specify the dimensions at run-time. Meaning, I'm making an interface that lets me pass an Eigen::MatrixXd to be converted along with it's dimensions and preallocated target C array.
This works but is column-major,
void eigen_matrixXd_to_double_array(const Eigen::MatrixXd& evector, double* destination, uint32_t nrow, uint32_t ncol)
{
Eigen::Map<Eigen::MatrixXd>(destination,nrow,ncol) = evector;
}
I want something like:
void eigen_matrixXd_to_double_array(const Eigen::MatrixXd& evector, double* destination, uint32_t nrow, uint32_t ncol)
{
Eigen::Map<Eigen::Matrix<double, nrow, ncol, Eigen::RowMajor>>(destination,nrow,ncol) = evector;
}
or,
void eigen_matrixXd_to_double_array(const Eigen::MatrixXd& evector, double* destination, uint32_t nrow, uint32_t ncol)
{
Eigen::Map<Eigen::MatrixXd<Eigen::RowMajor>>(destination,nrow,ncol) = evector;
}
but neither of these work...
Any suggestions? Is it possible for me to make a row-major mapping with programmatic dimensions (realizing that the user of the C interface must get the dims correct)?
Thanks in advance...
You were very close:
typedef Matrix<double,Dynamic,Dynamic,RowMajor> RowMajMat;
RowMajMat::Map(destination, evector.rows(), evector.cols()) = evector;
Here, RowMajMat::Map is a static method returning a Map<RowMajMat>, so you can also write Map<RowMajMat>(destination, evector.rows(), evector.cols()).

Can I convert a non-const function argument to const and set the size of array?

Arrays require a constant to initialize the size. Hence, int iarr[10]
I thought I could possibly take a non-const argument and convert it to const then use it for an array size
int run(int const& size);
int run(int const& size)
{
const int csize = size;
constexpr int cesize = csize;
std::array<int, cesize> arr;
}
This, unfortunately doesn't work and I thought of using const_cast as
int run(int& size);
int run(int& size)
{
const int val = const_cast<int&>(size);
constexpr int cesize = val;
std::array<int, cesize> arr;
}
and this won't work either. I've read through a few SO posts to see if I can find anything
cannot-convert-argument-from-int-to-const-int
c-function-pass-non-const-argument-to-const-reference-parameter
what-does-a-const-cast-do-differently
Is there a way to ensure the argument is const when used as an initializer for the size of an array?
EDIT: I'm not asking why I can't initialize an array with a non-const. I'm asking how to initialize an array from a non-const function argument. Hence, initialize-array-size-from-another-array-value is not the question I am asking. I already know I can't do this but there may be a way and answer has been provided below.
std::array is a non-resizable container whose size is known at compile-time.
If you know your size values at compile-time, you can pass the value as a non-type template argument:
template <int Size>
int run()
{
std::array<int, Size> arr;
}
It can be used as follows:
run<5>();
Note that Size needs to be a constant expression.
If you do not know your sizes at compile-time, use std::vector instead of std::array:
int run(int size)
{
std::vector<int> arr;
arr.resize(size); // or `reserve`, depending on your needs
}
std::vector is a contiguous container that can be resized at run-time.
I'm asking how to initialize an array from a non-const function argument.
As you saw, it is not possible initialize an array size with an variable, because you need to specify the size or array at compiler time.
To solve your problem you should use std::vector that works like an array but you can resize it at run time. You can handle de vector as if you were handled an array, using the operator [], for example:
class MyClass
{
vector<char> myVector;
public:
MyClass();
void resizeMyArray(int newSize);
char getCharAt(int index);
};
MyClass::MyClass():
myVector(0) //initialize the vector to elements
{
}
void MyClass::resizeMyArray(int newSize)
{
myVector.clear();
myVector.resize(newSize, 0x00);
}
char MyClass::getCharAt(int index)
{
return myVector[index];
}
For more information check this link: http://www.cplusplus.com/reference/vector/vector/
Upgrade: Also, considere that std::array can't be resize, as this links say:
Arrays are fixed-size sequence containers: they hold a specific number of elements ordered in a strict linear sequence.

C++ Tuples and Readability

I think this is more of a philosophical question about readability and tupled types in C++11.
I am writing some code to produce Gaussian Mixture Models (the details are kind of irrelevant but it serves and a nice example.) My code is below:
GMM.hpp
#pragma once
#include <opencv2/opencv.hpp>
#include <vector>
#include <tuple>
#include "../Util/Types.hpp"
namespace LocalDescriptorAndBagOfFeature
{
// Weighted gaussian is defined as a (weight, mean vector, covariance matrix)
typedef std::tuple<double, cv::Mat, cv::Mat> WeightedGaussian;
class GMM
{
public:
GMM(int numGaussians);
void Train(const FeatureSet &featureSet);
std::vector<double> Supervector(const BagOfFeatures &bof);
int NumGaussians(void) const;
double operator ()(const cv::Mat &x) const;
private:
static double ComputeWeightedGaussian(const cv::Mat &x, WeightedGaussian wg);
std::vector<WeightedGaussian> _Gaussians;
int _NumGaussians;
};
}
GMM.cpp
using namespace LocalDescriptorAndBagOfFeature;
double GMM::ComputeWeightedGaussian(const cv::Mat &x, WeightedGaussian wg)
{
double weight;
cv::Mat mean, covariance;
std::tie(weight, mean, covariance) = wg;
cv::Mat precision;
cv::invert(covariance, precision);
double detp = cv::determinant(precision);
double outter = std::sqrt(detp / 2.0 * M_PI);
cv::Mat meanDist = x - mean;
cv::Mat meanDistTrans;
cv::transpose(meanDist, meanDistTrans);
cv::Mat symmetricProduct = meanDistTrans * precision * meanDist; // This is a "1x1" matrix e.g. a scalar value
double inner = symmetricProduct.at<double>(0,0) / -2.0;
return weight * outter * std::exp(inner);
}
double GMM::operator ()(const cv::Mat &x) const
{
return std::accumulate(_Gaussians.begin(), _Gaussians.end(), 0, [&x](double val, WeightedGaussian wg) { return val + ComputeWeightedGaussian(x, wg); });
}
In this case, am I gaining anything (clarity, readability, speed, ...) by using a tuple representation for the weighted Gaussian distribution over using a struct, or even a class with its own operator()?
You're reducing the size of your source code a little bit, but I'd argue that you're reducing its overall readability and type safety. Specifically, if you defined:
struct WeightedGaussian {
double weight;
cv::Mat mean, covariance;
};
then you wouldn't have a chance of writing the incorrect
std::tie(weight, covariance, mean) = wg;
and you'd guarantee that your users would use wg.mean instead of std::get<0>(wg). The biggest downside is that std::tuple comes with definitions of operator< and operator==, while you have to implement them yourself for a custom struct:
operator<(const WeightedGaussian& lhs, const WeightedGaussian& rhs) {
return std::tie(lhs.weight, lhs.mean, lhs.covariance) <
std::tie(rhs.weight, rhs.mean, rhs.covariance);
}

Resources