Using `transform` to create an increasing vector - c++

I am trying to make an increasing vector using transform and must not be doing it correctly. I want to use transform. What am I doing wrong?
PS - I will be using the c++ 11 standard and g++.
#include <iostream>
#include <algorithm>
#include <vector>
int main()
{
std::vector<double> x(10);
x.front() = 0.0;
double h = 0.1;
std::transform(x.begin(), x.end() - 1, x.begin() + 1, [h](unsigned int xn) {return xn + h;});
std::cout << x.at(3) << " " << x.at(9) << std::endl;
}

The conversion to unsigned int is truncating each value when it is used to calculate the next

std::transform - Using an unary operator
std::transform applies the given function to a range and stores the
result in another range, beginning at d_first.
Via std::transform and a closure you can initialize your std::vector:
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
std::vector<double> v(10);
const double step = 0.1;
std::transform(begin(v), end(v), begin(v),
[step](const double value) { return value + step; });
for (const auto value : v) {
std::cout << value << ' ';
}
}
std::generate - Increment via a callable
Assigns each element in range [first, last) a value generated by the
given function object
If you want a custom increment, you can use std::generate:
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
std::vector<double> v(10);
double seed = 0.0;
std::generate(begin(v), end(v), [&seed]() {
const auto ret = seed;
seed += 0.1;
return ret;
});
for (const auto value : v) {
std::cout << value << ' ';
} // outputs: 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9
}
std::iota - Increment via ++value
Slightly off topic. You can provide a type with a operator++ for an increment of 0.1 but it is not intuitive for the reader.
You can use std::iota which relies on operator++.
Fills the range [first, last) with sequentially increasing values, starting with value and repetitively evaluating ++value.
The code in your case will be:
#include <numeric>
#include <iostream>
#include <vector>
int main() {
std::vector<double> v(10);
std::iota(begin(v), end(v), 0.0);
for (const auto value : v) {
std::cout << value << ' ';
} // outputs: 0 1 2 3 4 5 6 7 8 9
}

The lambda declares a wrong type of the parameter
[h](unsigned int xn) {return xn + h;});
^^^^^^^^^^^^^^^
There should be
[h]( double xn ) {return xn + h;});
^^^^^^^^^^^

Here are some other ways to write this. You may find them more expressive.
#include <vector>
#include <algorithm>
#include <numeric>
std::vector<double> create1(double i, double h)
{
std::vector<double> v(10);
std::generate(std::begin(v), std::end(v),
[&]() mutable
{
auto result = i;
i += h;
return i;
});
return v;
}
std::vector<double> create2(double i, double h)
{
std::vector<double> v(10);
for (std::size_t x = 0 ; v.size() ; ++x) {
v[x] = i + h * x;
}
return v;
}
std::vector<double> create3(double i, double h)
{
struct emitter
{
emitter& operator++() {
i += h;
}
operator double() const { return i; }
double i, h;
};
std::vector<double> v(10);
std::iota(v.begin(), v.end(), emitter { i, h });
return v;
}
int main()
{
auto v1 = create1(0, 0.1);
auto v2 = create2(0, 0.1);
auto v3 = create3(0, 0.1);
}

Regardless of any other problems it might have, your implementation has a subtle flaw: it relies on each preceding value in the vector having been already set.
This is not guaranteed to work, because std::transform() does not guarantee in-order application of the operator.

Related

Int from byte representation in vector c++

I have a vector<int> of length n which contains only 0 and 1's. For example we can have the following vector of length 10:
0 1 1 0 1 0 0 1 0 0
Now I use the number represented by that vector to access a location in an array with 2^n entries (so in this case an array of 2^10 = 1024). I'm not sure how I can obtain one integer from the byte representation stored in this vector<int>.
Simply run through the vector and collect powers of 2.
It depends on which end of the vector you want as most significant digit but e.g.
auto to_int( const vector<int>& digits )
-> int
{
int result = 0;
for( int const digit : digits )
{
result += 2*result + digit;
}
return result;
}
Or the other way,
auto to_int( const vector<int>& digits )
-> int
{
int result = 0;
for( int i = (int)digits.size(); i --> 0; )
{
result += 2*result + digits[i];
}
return result;
}
Disclaimer: code not reviewed by compiler.
use a std::bitset (http://en.cppreference.com/w/cpp/utility/bitset) which has a to_ulong() method
Something like this:
int integer=0;
int c=0;
for(int i : intVector){
integer+=i<<c;
c++;
}
return integer;
A simply way using a for loop:
size_t val{0};
for (const auto i : vec)
val = (val << 1) + i;
You can keep the std::vector and use std::bitset:
#include <iostream>
#include <vector>
#include <bitset>
#include <algorithm>
#include <climits>
template <typename IterType>
unsigned long getValue(IterType i1, IterType i2)
{
unsigned long i = 0;
std::bitset<CHAR_BIT * sizeof(unsigned long)> b;
std::for_each(i1, i2, [&](auto n) { b.set(i++, n);});
return b.to_ulong();
}
int main()
{
std::vector<int> v = {0, 1, 1, 0, 1, 0, 0, 1, 0, 0};
auto val = getValue(v.rbegin(), v.rend());
std::cout << val << "\n";;
auto val2 = getValue(v.begin(), v.end());
std::cout << val2;
}
Note that depending on which bit is the most significant bit, you supply the iterators accordingly. For right-to-left, supply reverse iterators, otherwise supply forward iterators.
Live Example

Lambda function in accumulate

I'm trying to learn how to use lamba functions, and want to do something like:
Given a vector = {1,2,3,4,5}
I want the sum of pairwise sums = (1+2)+(2+3)+...
Below is my attempt, which is not working properly.
#include <vector>
#include <algorithm>
using namespace std;
vector <double> data = {1,10,100};
double mean = accumulate(data.begin(),data.end(),0.0);
double foo()
{
auto bar = accumulate(data.begin(),data.end(),0.0,[&](int k, int l){return (k+l);});
return bar
}
I tried changing the return statement to return (data.at(k)+data.at(l)), which didn't quite work.
Adding pairwise sums is the same as summing over everything twice except the first and last elements. No need for a fancy lambda.
auto result = std::accumulate(std::begin(data), std::end(data), 0.0)
* 2.0 - data.front() - data.end();
Or a little safer:
auto result = std::accumulate(std::begin(data), std::end(data), 0.0)
* 2.0 - (!data.empty() ? data.front() : 0) - (data.size() > 1 ? data.back() : 0);
If you insist on a lambda, you can move the doubling inside:
result = std::accumulate(std::begin(data), std::end(data), 0.0,
[](double lhs, double rhs){return lhs + 2.0*rhs;})
- data.front() - data.back();
Note that lhs within the lambda is the current sum, not the next two numbers in the sequence.
If you insist on doing all the work within the lambda, you can track an index by using generalized capture:
result = std::accumulate(std::begin(data), std::end(data), 0.0,
[currIndex = 0U, lastIndex = data.size()-1] (double lhs, double rhs) mutable
{
double result = lhs + rhs;
if (currIndex != 0 && currIndex != lastIndex)
result += rhs;
++currIndex;
return result;
});
Demo of all approaches
You misunderstand how std::accumulate works. Let's say you have int array[], then accumulate does:
int value = initial_val;
value = lambda( value, array[0] );
value = lambda( value, array[1] );
...
return value;
this is pseudo code, but it should be pretty easy to understand how it works. So in your case std::accumulate does not seem to be applicable. You may write a loop, or create your own special accumulate function:
auto lambda = []( int a, int b ) { return a + b; };
auto sum = 0.0;
for( auto it = data.begin(); it != data.end(); ++it ) {
auto itn = std::next( it );
if( itn == data.end() ) break;
sum += lambda( *it, *itn );
}
You could capture a variable in the lambda to keep the last value:
#include <vector>
#include <algorithm>
#include <numeric>
std::vector<double> data = {1,10,100};
double mean = accumulate(data.begin(), data.end(), 0.0);
double foo()
{
double last{0};
auto bar = accumulate(data.begin(), data.end(), 0.0, [&](auto k, auto l)
{
auto total = l + last;
last = l;
return total+k;
});
return bar;
}
int main()
{
auto val = foo();
}
You could use some sort of index, and add the next number.
size_t index = 1;
auto bar = accumulate(data.begin(), data.end(), 0.0, [&index, &data](double a, double b) {
if (index < data.size())
return a + b + data[index++];
else
return a + b;
});
Note you have a vector of doubles but are using ints to sum.

In CUDA / Thrust, how can I access a vector element's neighbor during a for-each operation?

I am trying to do some scientific simulation using Thrust library in CUDA, but I got stuck in the following operation which is basically a for-each loop:
device_vector<float> In(N);
for-each In(x) in In
Out(x) = some_calculation(In(x-1),In(x),In(x+1));
end
I have already looked up stackoverflow.com and find some similar questions:
Similar questions 1
But it seems using a transform iterator is only possible when the some_calculation function is done between 2 parameters, for transform iterator passes two parameters at most.
Then, for question 2:
Similar questions 2
The discussion just ended without a conclusion.
I believe this is a simple problem because it's a natural requirements for parallel calculation. Anyone could tell me what to do?
Fancy iterators are the key to this sort of operation, which isn't all that intuitive in thrust. You can use the zip_iterator to create tuples of values which can then be iterated over, so for a typical f(x[i-1], x[i], x[i+1]) type function, you get something like this:
#include <iostream>
#include <cmath>
#include <thrust/iterator/zip_iterator.h>
#include <thrust/tuple.h>
#include <thrust/transform.h>
struct divided_diff {
float dx;
divided_diff(float _dx) : dx(_dx) {};
float operator()(const thrust::tuple<float, float, float> &in) const {
float y0 = in.get<0>();
float y1 = in.get<1>();
float y2 = in.get<2>();
return (y0 - 2.f * y1 + y2) / (dx * dx);
}
};
int main() {
const int N = 10;
const float dx = 0.1f;
float x[N], y[N], dydx[N];
for (int i = 0; i < N; ++i) {
x[i] = dx * float(i);
y[i] = std::sin(x[i]);
dydx[i] = 0.f;
}
auto begin = thrust::make_zip_iterator(thrust::make_tuple(&y[0], &y[1], &y[2]));
auto end = thrust::make_zip_iterator(thrust::make_tuple(&y[N-2], &y[N-1], &y[N]));
divided_diff f(dx);
thrust::transform(begin, end, &dydx[1], f);
for (int i = 0; i < N; ++i) {
std::cout << i << " " << dydx[i] << std::endl;
}
return 0;
}
Here the functor processes one tuple at a time, where the tuple contains the three inputs from three different starting points in the same array or iterative sequence.
EDIT: Apparently converting a host version of this code to use device constructs was proving challenging for the originally poster, so here is a version which executes everything on the device using thrust::device_vector as the base container:
#include <iostream>
#include <cmath>
#include <thrust/tuple.h>
#include <thrust/transform.h>
#include <thrust/iterator/zip_iterator.h>
#include <thrust/device_vector.h>
#include <thrust/sequence.h>
struct divided_diff {
float dx;
divided_diff(float _dx) : dx(_dx) {};
__device__
float operator()(const thrust::tuple<float, float, float> &in) {
float y0 = in.get<0>();
float y1 = in.get<1>();
float y2 = in.get<2>();
return (y0 - 2.f*y1 + y2) / (dx * dx);
}
};
struct mysinf {
__device__
float operator()(const float &x) {
return __sinf(x);
}
};
int main()
{
const int N = 10;
const float dx = 0.1f;
thrust::device_vector<float> x(N), y(N), dydx(N-2);
thrust::sequence(x.begin(), x.end(), 0.f, dx);
thrust::transform(x.begin(), x.end(), y.begin(), mysinf());
auto start = thrust::make_zip_iterator(thrust::make_tuple(y.begin(), y.begin()+1, y.begin()+2));
auto finish = thrust::make_zip_iterator(thrust::make_tuple(y.end()-2, y.end()-1, y.end()));
divided_diff f(dx);
thrust::transform( start, finish, dydx.begin(), f);
thrust::device_vector<float>::iterator it = dydx.begin();
for(; it != dydx.end(); ++it) {
float val = *it;
std::cout << val << std::endl;
}
return 0;
}

Generate sequence of floats in a certain range

I want to fill a vector<float> with values, starting from a, increasing by inc, up to and including b. So basically what e.g. vec = 2:0.5:4 in Matlab would do - vec should now be { 2.0, 2.5, 3.0, 3.5, 4.0 }.
The best I could come up with is
vector<float> vec(10);
float increment = 0.5f;
std::generate(begin(vec), end(vec), [&increment]() {static float start = 2.0f; return start += increment ; });
But obviously it is incorrect as it starts at 2.5f, not 2.0f. And I would like to specify the parameters a bit easier or more concise.
I could imagine doing it in a dedicated class, but that would require quite some code.
Also I've looked at std::iota, but it can only increase by +1.
Any ideas on the best, concise approach? Using C++11 (and some parts of 14) welcome.
Edit: Of course I've also used a for-loop like:
for (float i = -1.0f; i <= 1.0f; i += 0.05f) {
vec.emplace_back(i);
}
but it has the problem that it sometimes doesn't go up to the end value, as in this example, because of float impreciseness (or rather representation). Fixing that requires some code and I think there should be a more concise way?
You could write your own variant of std::iota that also accepts a stride argument.
template<typename ForwardIterator, typename T>
void strided_iota(ForwardIterator first, ForwardIterator last, T value, T stride)
{
while(first != last) {
*first++ = value;
value += stride;
}
}
In your example, you'd use it as
std::vector<float> vec(10);
strided_iota(std::begin(vec), std::next(std::begin(vec), 5), 2.0f, 0.5f);
Live demo
I don't think you really need any fancy features for this.
void fill_vec(vector<float>& vec, float a, float inc, float b)
{
for(float n = a; n <= b; n += inc)
vec.push_back(n);
}
If you're worried about floating point precision missing the upper range, then you can add a small amount (often denoted by epsilon for this sort of thing):
float eps = 0.0000001f;
for(float n = a; n <= b + eps; n += inc)
If you include <cfloat>, you can use FLT_EPSILON which may vary between platforms to suit the implementation.
If the issue is that you want to include all the float values, then loop on integers and do the necessary calculations to go back to the float value within the loop.
for (int i = 20; i <= 40; i += 5) {
vec.emplace_back(i/10.0);
}
Here is an approach:
#include <iostream>
#include <vector>
#include <algorithm>
// functor
class generator_float
{
float _start, _inc;
public:
generator_float(float start, float inc): _start(start), _inc(inc) {};
float operator()() {
float tmp = _start;
_start += _inc;
return tmp;
}
};
int main()
{
std::vector<float> vec(10);
std::generate(std::begin(vec), std::end(vec), generator_float(2,0.5));
for(auto&& elem: vec)
std::cout << elem << " ";
std::cout << std::endl;
}
You can use a functor that works for both for iota and generate. Overload the function call and increment operator appropriately:
template <typename T>
class ArithmeticProgression
{
T val;
T inc;
public:
ArithmeticProg(T val, T inc) : val(val), inc(inc) {}
ArithmeticProg& operator++() noexcept(noexcept(val += inc))
{
val += inc;
return *this;
}
T operator()() noexcept(noexcept(val += inc))
{
auto tmp = val;
val += inc;
return tmp;
}
operator T() const noexcept {return val;}
};
template <typename T, typename U>
ArProg<typename std::common_type<T, U>::type> makeArithmeticProg( T val, U inc )
{
return {val, inc};
}
Usage:
int main()
{
std::vector<float> vec;
std::generate_n(std::back_inserter(vec), 5, makeArithmeticProg(2.0f, 0.5f) );
for (auto f : vec)
std::cout << f << ", ";
std::cout << '\n';
std::iota( std::begin(vec), std::end(vec), makeArithmeticProg(2.5f, 0.3f) );
for (auto f : vec)
std::cout << f << ", ";
}
Demo.

filtering out -inf and inf values to 0 in c++

lets say you have a std::complex<double> array[N];
how would you set all -inf and inf values to 0 in a for loop?
std::isinf won't work for me the compiler predates C++11
std::replace( array, array + N, std::complex( std::numeric_limits<double>::infinity(), 0.0), std::complex(0.0) );
std::replace( array, array + N, std::complex( -std::numeric_limits<double>::infinity(), 0.0), std::complex(0.0) );
or
bool isinf( std::complex<double> d )
{
return std::abs( d.real() ) == std::numeric_limits<double>::infinity()
}
std::replace_if( array, array + N, isinf, 0.0 );
Try this: std::numeric_limits<double>::infinity() will provide a value that tells you whether a number is an infinity or not.
Here is an example code for a vector of double values; you can change the repl_inf to use complex<double> instead.
#include <iostream>
#include <algorithm>
#include <vector>
#include <limits>
using namespace std;
int repl_inf (double v) { return (v== std::numeric_limits<double>::infinity() || -v== std::numeric_limits<double>::infinity()) ? 0.0 : v; }
int main() {
vector<double> v;
v.push_back(1);
v.push_back(1.0/0.0);
v.push_back(2);
v.push_back(-1.0/0.0);
transform (v.begin(), v.end(), v.begin(), repl_inf);
for (int i = 0 ; i != v.size() ; i++) {
cout << v[i] << endl;
}
return 0;
}
On ideone: link.
For complex<double>:
bool isInf(double v) {
return v== std::numeric_limits<double>::infinity()
|| -v== std::numeric_limits<double>::infinity();
}
bool isInf(complex<double> c) {
return isInf(c.real) || isInf(c.imag);
}