A final category of algorithms, numerical algorithms. These are things like sums, inner products, adjacent sums. And generally speaking with the numerical algorithms, like sums or accumulate, they are going to be functions that can behave differently depending on what numerical operations are used with the functions, such as plus and times. And depending on whether the underlying types have appropriate definitions. So, it isn't absolutely the case that you have to use the numerical algorithms on mathematical types. You have to use them on types that they could be pseudomathematical types. As long as they have the appropriate operation. For example, in sums you're going to need the operation, a plus, to find. And if you have that sum operation plus defined, then it may make sense to use it on something that you wouldn't normally think of as a numerical entity to be summed. A common example in programming is strings. When I take string one and add it to string two, it's concatenation. I have a longer string. So it is reasonable, though it could be obscured. And it could be dangerous to apply numerical algorithms to non-numerical types. But the basis for doing numerical algorithms is really to produce numerical results. That’s the real use. And you probably should avoid using them in these other clever ways. Okay, I suggest that you also try to write a small program with vectors that tests using copy so you can see how some of this stuff works. Now here's an actual numerical algorithm. Very simply one. We have two primitive containers. It could also be done with vectors or the newer type array. So, again, depending on your energy level, you might try to redo this with some other container class. In one case we're going to produce some sum. And the other case we're going to produce something that we call the inner product. And sum we're going to accumulate. We have three elements. So here's the begin and end range. And here is what we start the accumulation with. And the typical thing that we start with is a zero. So we're going to add to 0, 1.0, then 2.5, then 4.6. Here's an inner product. Again, we give it a range. That's the inner product. If you remember, i if I had two vectors, let's call them v and u in a product. The interproduct in mathematical terms the sum ui times vi. In this case, when i went from 1 to 3. So I'd just be multiplying 1.0 by 1.0, 2.0 by 2.5, -3.5 by 4.6. And again, you have a starting value Which is not traditionally a zero. And by the way, by starting traditionally at zero, we could have avoided using that. But by allowing an arbitrary value there, we again maximize the orthogonality of the algorithm. Because we could want to accumulate over several ranges. And we might not have the ability to specify. Say we wanted to accumulate over v1 and v2 separately. So we'd have to do this first. We get an answer. And then we could do the second one. And we could actually shove the v1 as an argument here. We could make that accumulate. And then give it parameters. So you can see that, that sort of, in effect, creates interesting opportunities that's expands the utility of the STL library. So here's a prototype for what we've just seen. We start with a range. And then we give what typically will be a zero. And here's this further other interesting idea that lets us use something like a lambda or an equivalent, which is an operator that's intended to be a binary operator. It's actually, again, a functor. It's actually a definition. You're not actually going to put + there. But you could put something like + as a function that you define. But you can put an arbitrary binary operator there. And then accumulation is going to work not by doing a + b + c, but instead will be a, the binary operator, whatever special thing that is, + b, etc. So now, you again, through orthogonality, and through possibly using something like a lambda that would operate as a binary operator, a vast expansion of the effective use of the library.