Hello again! In this video, we are going to look at numeric algorithms.
Most of the standard library algorithms are defined in the algorithm header.
But there are a few in the numeric header.
And these are more concerned with numeric processing.
The first one we're going to look at is called iota(), as in the Greek letter.
This takes an iterator range, and it sets each element in the range to have a value which increases
by one.
We call it by passing the iterator range.
These cannot be const iterators, because they are going to modify the vector elements.
And we also pass the starting value. So this will sets the first element in the vector to have the
value 1.
Then the next element is 2, 3, and so on until it gets to the last element in the vector.
We could also write this as a hand-written loop. So we have some variable which stores the current value.
Then we iterate through the vector elements.
We need to put an ampersand here, because we are going to modify the elements.
Then we sent the element to the current value of this variable.
Then we increment it.
And then on the next iteration, the next element will have the incremented value. And so on.
So here is some code.
We need to include the numeric header, which is easy to overlook!
We have a vector with 10 elements.
We have our call to iota().
So this is going to populate
every element in the vector, with the starting value as one.
And then we also have the handwritten loop, which will do the same thing.
So with any luck, we should get the same answer.
And there we are.
So the elements of the vector increase by one.
And that is quite a useful little algorithm, if you are doing
numeric programming.
There is also an algorithm called accumulate().
This will add up all the elements in an iterator range, and return their sum.
We give it the iterator range. We can use const iterators this time, because this will not modify the
vector.
We also give it a starting value for the sum.
Usually you will want this to be 0. And that will give you the total of adding all the elements. The
total sum of the elements.
But if you pass some other number, then that will be added to the sum.
And this is quite useful if you are doing repeated calculations.
For example, if we calculate the sum of the elements in "vec" and then we want to add the elements in
"vec2" to to that total, then we just pass the "vec" result as the argument.
So this is going to be the sum of the elements of "vec", and then we are going to add the sum of the elements in "vec2"
to that sum.
And then the result will be the sum of all the elements in both those vectors.
So here we can try it out.
We're going to call accumulate().
We pass the iterator range and the initial value of the sum.
We could also do this with a handwritten loop, which is - okay,
it is not rocket science, but sometimes it is useful to have more abstract representations of things.
So there we are.
The sum is 23.
By default, accumulate() will use the plus operator. So that will perform adddition of the elements, using
the element's plus operator. If we want to do something else, we can pass a callable object as an optional
argument.
So here is the same call again with a lambda expression.
This lambda expression is going to take the total so far and the current element. The element which
the accumulate() algorithm is processing. And the value that it returns will be the new value of the sum.
So with the plus element, this would just add the current element to the sum and returned the new value
of the sum. In this lambda expression,
the value that we return depends on whether the element is odd or even. If it is odd,
then we add it to the current sum and return the new sum.
So we have added the odd element to the running total.
If the element is not odd, then we just return the current value of the sum.
So we do not add the even numbers to the sum.
So the result of this will be the sum of all the odd elements in the vector.
And let's try this out to see if it works.
So we have our lambda expression.
It takes the current running total and the current element.
And if the element is od, it will add it to the current total.
Otherwise it will just return the current total.
And we get 19, so (three, four, five)
Yep, that is correct.
It is always nice when things give the right answer!
If you're interested in numerical programming, you are probably also interested in parallel processing.
So this is when we have several processors or processor cores which are all executing the same code
at the same time.
And this should give you the answer much more quickly.
Unfortunately, the accumulate() algorithm is not very conducive to parallel processing.
So let's look at how it works. If we have a vector {1, 2, 3} and the starting sum 0.
This will be evaluated as zero plus one, so it will take the starting sum and add the first element
to it.
And then once that has been calculated, it will add the next element.
And once that has been calculated, it will add the next element.
So this is all entirely sequential.
One operation must follow another.
We cannot have different operations executing at the same time.
In C++ 17, there is a new numeric algorithm function, reduce().
This is a reimplementation of accumulate(), which is compatible with parallel processing.
So we call it exactly the same.
The difference is that reduce() can perform the addition in any order. It is not forced to execute from
left to right.
And this means it is compatible with parallel processing.
So I am not really going to talk anymore about parallel processing.
Quite a few of the algorithms have been rewritten, so they work better with parallel processing.
And I cover that in my course on multi-threading.
Okay, so that is it for this video.
I will see you next time.
But until then, keep coding!