Difference between "&" and std::reference_wrapper? - c++11

I have following code
#include <iostream>
#include <vector>
#include <functional>
int main() {
std::vector<double> v(5, 10.3);
std::vector<double>& r = v;
//std::vector<std::reference_wrapper<double>> r(v.begin(),v.end());
for (auto& i : v)
i *= 3;
for (auto i : r)
std::cout << i << " ";
std::cout << std::endl;
}
I am using reference of the vector 'r' using '&' operator and in the second line which I commented out I am using std::reference_wrapper of C++. Both do pretty much the same job? But I think there must be a purpose of making std::reference_wrapper even if we had '&' to do the job. can anyone explain please?

First, the two lines
std::vector<double>& r = v;
std::vector<std::reference_wrapper<double>> r(v.begin(),v.end());
Don't mean the same thing. One is a reference to a vector of doubles, the other one is a vector of "references" to doubles.
Second, std::reference_wrapper is useful in generic programming (ie: templates) where either a function might take its arguments by copy, but you still want to pass in an argument by reference. Or, if you want a container to have references, but can't use references because they aren't copyable or movable, then std::reference_wrapper can do the job.
Essentially, std::reference_wrapper acts like a "&" reference, except that it's copyable and reassignable

Related

Is it possible to place a std::array at a fixed memory address?

For an embedded design I want to place a C++ std::array at a specific memory address, which points to a buffer shared by hardware and software. Is this possible?
Try Placement new:
#include <array>
#include <iostream>
int main()
{
alignas(double) char buffer[100];
auto parr = new (buffer) std::array<double, 3> {3.14, 15.161, 12};
const auto & arr = *parr;
std::cout << (void*) &arr << " " << (void*) buffer << "\n";
for (auto x: arr)
std::cout << x << " ";
std::cout << "\n";
}
which may give this output:
0x7ffcdd906770 0x7ffcdd906770
3.14 15.161 12
One thing to be worried about is whether the address you want to use is consistent with the alignment requirements of the data you want to hold in the array. Most likely you will be dealing with chars, floats or ints, so this condition shouldn't be difficult to enforce.
For embedded code, two simple solutions spring to mind:
Declare extern int myArray[1234] ; and then define myArray (or rather its mangled form) in your linker definition file.
Define a macro: #define myArray ((int*)0xC0DEFACE)
The first solution is for the purists; the second is for the pragmatists.

Recommended way to cast a boost cpp_int to a double?

I have some code were I avoid some costly divisions by converting a boost integer to a double. For the real code I will build an fp type that's big enough to hold the maximal value (exponent). To test I am using a double. So I do this:
#define NTYPE_BITS 512
typedef number<cpp_int_backend<NTYPE_BITS, NTYPE_BITS, unsigned_magnitude, unchecked, void> > NTYPE;
NTYPE a1 = BIG_VALUE;
double a1f = (double)a1;
The code generated for that cast is quite complicated. I see it's basically looping over all the values in a1 (least significant first) scaling them by powers of two.
Now in this case I guess at most the number of elements that could affect the result are the last two (64 bits for each element and the most significant element might have less that 64 bits used).
Is there a better way to do this?
First off, NEVER use C-Style casts. (Why use static_cast<int>(x) instead of (int)x?).
Second, avoid using namespace.
(Third, reserve all-caps names for macros).
That said:
double a1f = a1.convert_to<double>();
Is your ticket.
Live On Coliru
#include <boost/multiprecision/cpp_int.hpp>
#include <iostream>
namespace bmp = boost::multiprecision;
//0xDEADBEEFE1E104B1D00008BADF00D000ABADBABE000D15EA5E
#define BIG_VALUE "0xDEADBEEFE1E104B1D00008BADF00D000ABADBABE000D15EA5E"
#define NTYPE_BITS 512
int main() {
using NTYPE = bmp::number<
bmp::cpp_int_backend<
NTYPE_BITS, NTYPE_BITS,
bmp::unsigned_magnitude, bmp::unchecked, void>>;
NTYPE a1(BIG_VALUE);
std::cout << a1 << "\n";
std::cout << std::hex << a1 << "\n";
std::cout << a1.convert_to<double>() << "\n";
}
Prints
1397776821048146366831161011449418369017198837637750820563550
deadbeefe1e104b1d00008badf00d000abadbabe000d15ea5e
1.39778e+60

Wrong results using auto with Eigen

I got different results using auto and using Vector when summing two vectors.
My code:
#include "stdafx.h"
#include <iostream>
#include "D:\externals\eigen_3_1_2\include\Eigen\Geometry"
typedef Eigen::Matrix<double, 3, 1> Vector3;
void foo(const Vector3& Ha, volatile int j)
{
const auto resAuto = Ha + Vector3(0.,0.,j * 2.567);
const Vector3 resVector3 = Ha + Vector3(0.,0.,j * 2.567);
std::cout << "resAuto = " << resAuto <<std::endl;
std::cout << "resVector3 = " << resVector3 <<std::endl;
}
int main(int argc, _TCHAR* argv[])
{
Vector3 Ha(-24.9536,-29.3876,65.801);
Vector3 z(0.,0.,2.567);
int j = 7;
foo(Ha,j);
return 0;
}
The results:
resAuto = -24.9536, -29.3876,65.801
resVector3 = -24.9536,-29.3876,83.77
Press any key to continue . . .
I understand that Eigen does internal optimization that generate different results. But it looks like a bug in Eigen and C++11.
The auto keyword tells the compiler to "guess" the best object based on the right hand side of the =. You can check the results by adding
std::cout << typeid(resAuto).name() <<std::endl;
std::cout << typeid(resVector3).name() <<std::endl;
to foo (don't forget to include <typeinfo>).
In this case, after constructing the temporary Vector3, the operator+ method is called, which creates a CwiseBinaryOp object. This object is part of Eigens lazy evaluation (can increase performance). If you want to force eager evaluation (and therefore type determination), you could use
const auto resAuto = (Ha + Vector3(0.,0.,j * 2.567)).eval();
instead of your line in foo.
A few side notes:
Vector3 is identical to the Vector3d class defined in Eigen
You can use #include <Eigen/Core> instead of #include <Eigen/Geometry> to include most of the Eigen headers, plus certain things get defined there that should be.

Can I move the contents of one vector to the end of another?

I want to do something like the following (a and b are both vector<my_moveable_type>):
a.insert(a.end(), b.begin(), b.end());
But I want the operation to move b's elements into a instead of copying them. I have found std::vector::emplace but that is just for a single element, not a range.
Can this be done?
You can use std::make_move_iterator, so that accesses to the iterator returns rvalue references instead of lvalue references:
a.insert(a.end(), std::make_move_iterator(b.begin()), std::make_move_iterator(b.end()));
There is a std::move algorithm that appears to do what you want. In the following code the source std::vector is left with empty strings (the vector size doesn't change).
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::vector<std::string> one{"cat", "dog", "newt"};
std::vector<std::string> two;
std::move(begin(one), end(one), back_inserter(two));
std::cout << "one:\n";
for (auto& str : one) {
std::cout << str << '\n';
}
std::cout << "two:\n";
for (auto& str : two) {
std::cout << str << '\n';
}
}
Working code at ideone.com

Set coefficients of an Eigen::Matrix according an arbitrary distribution

Eigen::Matrix has a setRandom() method which will set all coefficients of the matrix to random values. However, is there a built in way to set all the matrix coefficients to random values while specifying the distribution to use.
Is there a way to achieve something like the following:
Eigen::Matrix3f myMatrix;
std::tr1::mt19937 gen;
std::tr1::uniform_int<int> dist(0,MT_MAX);
myMatrix.setRandom(dist(gen));
You can do what you want using Boost and unaryExpr. The function you pass to unaryExpr needs to accept a dummy input which you can just ignore.
#include <boost/random.hpp>
#include <boost/random/normal_distribution.hpp>
#include <iostream>
#include <Eigen/Dense>
using namespace std;
using namespace boost;
using namespace Eigen;
double sample(double dummy)
{
static mt19937 rng;
static normal_distribution<> nd(3.0,1.0);
return nd(rng);
}
int main()
{
MatrixXd m =MatrixXd::Zero(2,3).unaryExpr(ptr_fun(sample));
cout << m << endl;
return 0;
}
If anyone is coming across this thread, I'm posting an easier answer that is possible nowadays and does not require boost. I found this in an old Eigen Bugzilla Report. All credits go to the author Gael Guennebaud for proposing the following simple method:
#include <Eigen/Sparse>
#include <iostream>
#include <random>
using namespace Eigen;
int main() {
std::default_random_engine generator;
std::poisson_distribution<int> distribution(4.1);
auto poisson = [&] (int) {return distribution(generator);};
RowVectorXi v = RowVectorXi::NullaryExpr(10, poisson );
std::cout << v << "\n";
}
Note that the signature with an int argument of the lambda function is required of Eigen NullaryExpr, despite not being used here in the example.
I had a problem with a similar problem and tried to solve it by using NullaryExpr. But a problem with NullaryExpr is that it cannot be vectorized explicitly. Thus, the solution with NullaryExpr runs quite slowly.
Because of this, I developed EigenRand, an add-on of random distribution for Eigen. I think it will help ones who want to generate random number fast and easily.
#include <Eigen/Dense>
#include <EigenRand/EigenRand>
#include <iostream>
using namespace Eigen;
int main() {
Rand::Vmt19937_64 generator;
// poisson distribution with rate = 4.1
MatrixXi v = Rand::poisson<MatrixXi>(4, 4, generator, 4.1);
std::cout << v << std::endl;
// normal distribution with mean = 3.0, stdev = 1.0
MatrixXf u = Rand::normal<MatrixXf>(4, 4, generator, 3.0, 1.0);
std::cout << u << std::endl;
return 0;
}
Apart the uniform distribution I am not aware of any other types of distribution that can be used directly on a matrix.
What you could do is to map the uniform distribution provided by Eigen directly to your custom distribution (if the mapping exists).
Suppose that your distribution is a sigmoid.
You can map an uniform distribution to the sigmoid distribution using the function y = a / ( b + c exp(x) ).
By temporary converting your matrix to array you can operate element-wise on all values of your matrix:
Matrix3f uniformM;
uniformM.setRandom();
Matrix3f sigmoidM;
sigmoidM.array() = a * ((0.5*uniformM+0.5).array().exp() * c + b).inv();

Resources