element-wise multiplication of two vectors in c++ - c++

I am trying to do the following mathematical operation with two vectors:
v1 = [a1][a2][a3][a4][a5]
v2 = [b1][b2][b3][b4]b5]
Want to compute:
v = [a2*b2][a3*b3][a4*b4][a5*b5]
Note that I did not want the first element in the new vector.
I was wondering if there is a more efficient (one-liner) way to multiply (element-wise) two vectors in c++ than a for-loop (using push back). My current approach is as follows,
for(long i=1;i < v1.size();++i){
v.push_back(v1[i]*v2[i]);
}
I also tried the following,
for (long i = 1; i < v1.size(); ++i){
v[i-1] = v1[i]*v2[i];
}
Any suggestions?

std::transform( v1.begin()+1, v1.end(),
v2.begin()+1, v.begin(), // assumes v1,v2 of same size > 1,
// v one element smaller
std::multiplies<int>() ); // assumes values are 'int'
You can replace v.begin() with std::back_inserter(v) if v is empty, you should reserve() memory upfront to avoid multiple allocations.

You could look into std::valarray. It's designed to allow mathematical operations on every element in the array.

Related

subtracting elements of a vector from each other in CUDA

I have a vector (x_dev) in CUDA which has B elements and is of double type.
I am looking for the best way, to subtract each element from the next element, and overwrite the vector.
(I do not care about the last element).
Essentially, the corresponding of this c++ code:
for(int i = 0; i < B-1; i++)
x_dev[i] = x_dev[i] - x_dev[i+1];
You could use thrust::transform
thrust::transform(x.begin(), x.end()-1, x.begin()+1, x.begin(), _1 - _2);

Return the maximum of (two) element-wise added vectors

I wrote a function that first adds two vectors (v1 and b1 are added to vsum) and than returns the maximum of vsum. Here is what I tried to run, it doesn't work for some reason:
double MaximumOfSummedVectors(std::vector<double> &v1,std::vector<double> &v2) {
std::vector<double> vsum;
std::transform(v1.begin(),v1.end(),v2.begin(),vsum.begin(),std::plus<double>());
return *std::max_element(std::begin(vsum),std::end(vsum));
}
I've tested both the functionality of std::transform, std::max_element and std::plus<double> in my main environment. Everything worked as expected. What am I overlooking?
You are overlooking two things: the first is undefined behavior!
std::vector<double> vsum;
vsum has size zero at this point. But transform will just write into the iterator you pass in
Effects: Assigns through every iterator i in the range [result,result + (last1 - first1)) a new corresponding value equal to ...
But that range isn't initialized - so you're going to be writing to uninitialized memory! You need to do either:
vsum.resize(v1.size());
or pass an inserter:
std::transform(v1.begin(),v1.end(),v2.begin(),
std::back_inserter(vsum),
std::plus<double>());
The second thing is that you're constructing this whole new vector for little reason:
double MaximumOfSummedVectors(std::vector<double> &v1,std::vector<double> &v2)
{
auto i1 = v1.begin(), i2 = v2.begin();
double m = *i1++ + *i2++;
for (; i1 != v1.end(); ++i1, ++i2) {
m = std::max(m, *i1 + *i2);
}
return m;
}
You pass vsum.begin() as the output argument. This assumes that there's enough space in the vector to write the output sequence, when in fact the vector is empty; so the output is written off the end of the vector into undefined territory.
Instead, you want to insert the output values into the vector, using an insertion interator std::back_inserter(vsum).

Find n largest values in a vector

I currently have a vector and need to find the n largest numbers in it. For example, a user enters 5, i gotta run through it and output the 5 largest. Problem is, i can not sort this vector due to other constraints. Whats the best way to go about this?
Thanks!
Based on your description of not modifying the original vector and my assumption that you want the order to matter, I suggest std::partial_sort_copy:
//assume vector<int> as source
std::vector<int> dest(n); //largest n numbers; VLA or std::dynarray in C++14
std::partial_sort_copy(
std::begin(source), std::end(source), //.begin/.end in C++98/C++03
std::begin(dest), std::end(dest),
std::greater<int>() //remove "int" in C++14
);
//output dest however you want, e.g., std::copy
Is copying and sorting an option? I mean if your application is not that performance critical, this is the simplest (and asymptotically not too bad) way to go!
Something like this (A is incoming vector, N the number largest you want to find, v becomes the result vector):
vector<T> v(N, 0);
for each element in A:
if (element > v[N-1])
for(i = N-1; i > 0 && v[i] < element; i--)
v[i] = v[i-1];
v[i] = element;
This is some sort of "pseudo-C++", not exactly C++, but hopefully describes how you'd do this.

c std::vector splitting into two

Is there an easy and run-time efficient way to take a std::vector<> in c++ and split it in half into two other vectors?
Because right now I'm doing this:
std::vector<> v1, v2;
for(int i = 0; i < vector.size(); i++)
{
if(i < vector.size()/2) v1.push_back(vector[i]);
else v2.push_back(vector[i]);
}
which runs in O(n) time and this is an operation I have to perform quite frequently. So is there a better way?
If you really need 2 vectors, and you can't use GMan's suggestion in the comments:
// where v1 is your original vector
std::vector<T> v2(
std::make_move_iterator(v1.begin() + v1.size()/2),
std::make_move_iterator(v1.end()));
v1.erase(v1.begin() + v1.size()/2, v1.end());
It's still O(n), but you can't do any better than that.
If you need to keep the original vector separate:
std::vector<T> v2(v1.begin(), v1.begin() + v1.size()/2),
v3(v1.begin() + v1.size()/2, v1.end());

Quickest way to compute the number of shared elements between two vectors

Suppose I have two vectors of the same size vector< pair<float, NodeDataID> > v1, v2; I want to compute how many elements from both v1 and v2 have the same NodeDataID. For example if v1 = {<3.7, 22>, <2.22, 64>, <1.9, 29>, <0.8, 7>}, and v2 = {<1.66, 7>, <0.03, 9>, <5.65, 64>, <4.9, 11>}, then I want to return 2 because there are two elements from v1 and v2 that share the same NodeDataIDs: 7 and 64.
What is the quickest way to do that in C++ ?
Just for information, note that the type NodeDataIDs is defined as I use boost as:
typedef adjacency_list<setS, setS, undirectedS, NodeData, EdgeData> myGraph;
typedef myGraph::vertex_descriptor NodeDataID;
But it is not important since we can compare two NodeDataID using the operator == (that is, possible to do v1[i].second == v2[j].second)
Put the elements of the first vector into a hash table. Iterate over the second vector, testing each element whether it is in the hash table.
A hash table has the advantage that inserts and lookups can be done in constant time. This means, finding the intersection can be done in linear time. This is optimal, because regardless of the algorithm, you have to look at each vector element at least once.
Boost has boost::intrusive::hashtable, but it's (as the name suggests), intrusive.
The simplest solution is just to put elements of the first vector in a set then for the second vector we insert each element in this set (ret = myset.insert(an_id)) and if ret.second is false then the element exists, thus we increase a counter.
set<NodeDataID> myset;
int counter = 0;
for(int i = 0; i < v1.size(); ++i)
myset.insert(v1[i].second);
for(int i = 0; i < v2.size(); ++i)
{
pair<set<NodeDataID>::iterator,bool> ret = myset.insert(v2[i].second);
if(ret.second == false)
++counter;
}