Newskooler
Newskooler

Reputation: 4245

element wise vector multiplication c++ (code not working)

I cannot seen to understand why my code does not work. I have two vectors and I wish to substitute my second vector with the product of each element (v2[0] = v1[0] * v2[0], v2[1] = v1[1] * v2[1] and so on...)

code

vector <float> vectorMultiplication(vector <float> &v1, vector <float> &v2)
{
    return std::transform(v1.begin(), v1.end(), v2.begin(), std::multiplies<float>() );
}

If anyone can point out my mistake, I will be very grateful.

P.S. The error message that my compiler throws is: error: conversion from ‘__gnu_cxx::__normal_iterator<float*, std::vector<float> >’ to non-scalar type ‘std::vector<float>’ requested P.S. 2 I am running C++98

Upvotes: 2

Views: 1413

Answers (3)

Vittorio Romeo
Vittorio Romeo

Reputation: 93264

The error is pretty clear: std::transform returns an iterator, you're returning a vector<float>, which cannot be implicitly constructed by a single iterator.


Also, the overload of std::transform that you're trying to call is not the right one, as it accepts an UnaryOperation while std::multiplies is a BinaryOperation. You need this overload:

template< class InputIt1, class InputIt2, class OutputIt, class BinaryOperation >
OutputIt transform( InputIt1 first1, InputIt1 last1, InputIt2 first2, 
                    OutputIt d_first, BinaryOperation binary_op );

The following code will compile and work:

auto vectorMultiplication(const std::vector<float>& v1, const std::vector<float>& v2)
{
    std::vector<float> result;
    std::transform(v1.begin(), v1.end(), v2.begin(), 
                   std::back_inserter(result), std::multiplies<float>());
    return result;
}

coliru example


Usage example:

std::vector<float> v1 = {1, 2, 3, 4};
std::vector<float> v2 = {1, 2, 3, 4};

auto vm = vectorMultiplication(v1, v2);
for(const auto& x : vm) std::cout << x << " ";

Will print:

1 4 9 16

Upvotes: 6

BoBTFish
BoBTFish

Reputation: 19767

The error is that return std::transform(...); tries to return the resulting output iterator, but your function is declared to return vector<float>. You need to work out what you actually want to return, because it's not really clear here. Maybe just void, and remove the return keyword completely?

But you actually want to apply the function to an element from v1 and an element of v2 at the same time. The form of transform you are trying to use does not do this. There is another form that does, but it's going to be a bit confusing here:

std::transform(v1.begin(), // start of first input range
               v1.end(),   // end of first input range
               v2.begin(), // start of **second input** range
               v2.begin(), // start of **output** range
               std::multiplies<float>());

See version 3 here.

To do this, you need to be sure that v1.size() <= v2.size().

Click here for a working example.

Upvotes: 0

R Sahu
R Sahu

Reputation: 206577

The problem is obvious from the compiler's error message. The return type of std::transform is an iterator, not a container.

The call

 std::transform(v1.begin(), v1.end(), v2.begin(), std::multiplies<float>() );

updates v2 so that its elements contain the result of the element-wise multiplications.

You may change the return value of the function to void:

void vectorMultiplication(vector <float> &v1, vector <float> &v2)
{
   std::transform(v1.begin(), v1.end(), v2.begin(), std::multiplies<float>() );
}

or return v2:

vector <float> vectorMultiplication(vector <float> &v1, vector <float> &v2)
{
   std::transform(v1.begin(), v1.end(), v2.begin(), std::multiplies<float>() );
   return v2;
}

Upvotes: 0

Related Questions