How to use divides and for_each? - c++

I have:
vector<double> ved1 = { 1,2,3,4,5,6,7,8,9,10 };
vector<double> ved2 = { 11,12,13,14,15,16,17,18,19,20 };
vector<double> ved3(10);
and I want to have ved3=ved3/2 but I can't get it correctly, the result is 2/ved3;
How to use divides?
transform(ved1.begin(), ved1.end(), ved2.begin(), ved3.begin(), plus<double>());
transform(ved3.begin(), ved3.end(), ved3.begin(), bind1st(divides<double>(),2));`
I want cos(ved2), but I cannot get it. What's wrong with my code?
double cos_1(double x) { return cos(x); }
for_each(ved2.begin(), ved2.end(), cos_1);

bind1st will bind 2 to the 1st argument of divides, and then transform will supply each element of ved3 to divides as the second argument. So the result will be divides(2, ved3[0]), divides(2, ved3[1]) and so on.
If you want to calculate divides(ved3[...], 2) instead, use bind2nd(divides<double>(), 2). This way, 2 will be bound to the second argument, leaving the first one vacant for transform.

How to use std::for_each to apply a cosine elementwise
std::for_each does not fill some output; or necessarily change the input container/range. It just applies an invocable object to each element of a range. If the function has no "side effects" - than the for_each would be useless. Specifically, in your case - you're computing the cosine of each value, but not doing anything with it.
If you want to change the values in-place, you'll need to specifically do that:
void apply_cos(double& x) { x = std::cos(x); }
// ...
for_each(ved2.begin(), ved2.end(), apply_cos);
or using a lambda expression:
for_each(ved2.begin(), ved2.end(), [](double& x) { x = cos(x); });
Note the use of a reference input to the function rather than a value: double& x, not double x. That means that when you change x in apply_cos(), the value in the input range to std::for_each changes.

Related

Pass either a double or a vector<double>& to a function

I have a function which calculates the first derivative dy/dx for discrete values y(x) stroed as std::vector:
vector<double> CalcDerivative(vector<double>&y, vector<double>&x) {...}
Often the spacing dx is constant so it would be more efficient to pass a double to this function instead of vector<double> as argument x.
I tried to accomplish this with std::variant. The drawback with std::variant is however, that it cannot handle references so the vector x has to be copied while being passed as a variant to the function.
For now I solved the problem by defining two functions with overloaded arguments. But I wonder whether there is a more elegant solution which won't duplicate the code for the two cases (x as double or as vector<double>).
One possible solution might be to define the "worker" function such that it is independent of the "number of passed doubles". For this purpose, std::span is suitable. The exemplary solution might look like:
std::vector<double> CalcDWorker(
std::span<const double> y, std::span<const double> x)
{
... // x.size() == 1 indicates uniform spacing
}
std::vector<double> CalcDerivative(
const std::vector<double>& y, const std::vector<double>& x)
{
return CaclDWorker({y.begin(), y.end()}, {x.begin(), x.end()});
}
std::vector<double> CalcDerivative(
const std::vector<double>& y, double x)
{
return CaclDWorker({y.begin(), y.end()}, {&x, 1});
}
It requires C++20, but there are third-party span implementations available also for earlier C++ versions (such as the one provided by Boost).
Live demo: https://godbolt.org/z/n6adEKWes

C++: Return a lambda expression from a function that captures parameter of the function

The following function is supposed to take the coefficients of a polynomial and create a function of time from them:
std::function<double(double)> to_equation(const std::vector<double>& coefficients)
{
return [coefficients](double t)
{
auto total = 0.0;
for (int i = 0; i < coefficients.size(); i++)
{
total += coefficients[i] * pow(t,i);
return total;
}
};
}
It should be usable as follows:
std::vector<double> coefficients = {1.0,2.0,3.0};
auto f = to_equation(coefficients);
auto value = f(t);
The code does however not work as intended, since at the time of execution of f(t), not the coefficients passed to to_equation(coefficients) are used, but some totally different values magically captured from the context. What is happening and how can I fix that?
Well, you are returning a lambda that capture coefficients by value. If you pass some vector to the to_equation function, all values will be copied, and the lambda won't refer to the original vector anymore.
I suggest this solution:
// auto is faster than std::function
auto to_equation(const std::vector<double>& coefficients)
{
// Here, you capture by reference.
// The lambda will use the vector passed in coefficients
return [&coefficients](double t)
{
// ...
};
}
However, you must sometime deal with code like this:
std::function<double(double)> f;
{
std::vector<double> coeff{0.2, 0.4, 9.8};
f = to_equation(coeff);
}
auto result = f(3);
This is bad, the vector coeff don't live long enough, and we refer to it after the vector is destroyed.
I suggest adding this overload to your function:
// when a vector is moved into coefficients, move it to the lambda
auto to_equation(std::vector<double>&& coefficients)
{
// Here, you capture by value.
// The lambda will use it's own copy.
return [coeff = std::move(coefficients)](double t)
{
// ...
};
}
Then, calling your function is possible in both ways:
std::vector<double> coeff{0.2, 0.4, 9.8};
auto f1 = to_equation(coeff); // uses reference to coeff
auto f2 = to_equation({0.2, 0.4, 9.8}) // uses value moved into the lambda
You can capture by reference, instead of by value. But, of course, if the underlying vector goes out of scope and gets destroyed before the lambda gets invoked, you'll have a big mess on your hands.
The safest course of action is to use a std::shared_ptr<std::vector<double>> instead of a plain vector, and capture that by value. Then, the lambda will always, essentially, feed on whatever were the most recent set of coefficients, and won't blow up if it gets called after all other references to the underlying vector, from whatever code computed them, go out of scope.
(Of course, you have to keep in mind what's going to happen here if the lambda gets copied around, since all copies of the original lambda will be using the same vector).
For more information, open the chapter of your C++ book that explains the difference between capturing by value and by reference, when using lambdas.

Passing output of c++ transform to a function

I'm sorry if this is a stupid question but I'm a bit of a c++ noob and I haven't been able to find the answer. I'm working with boost multi_array, and I'm trying to do something like this:
typedef boost::multi_array<double,2> array2D;
typedef array2D::array_view<1>::type array2Drow;
typedef boost::multi_array_types::index_range range;
...
array2D A = ... (2-d array) ...;
array2Drow X = A(boost::indices[0][range()]);
...
returnVal1 = f(X);
returnVal2 = f(X+0.1*X);
returnVal3 = f(X-0.1*X);
I was trying to use std::transform for this; I understand I can write some sort of functor (call it "op") that multiplies X by 0.1 and adds/subtracts the result from X, but this is where I run into trouble--I don't know what to put in place of the ???:
returnVal1 = f(X);
returnVal2 = f(transform(X.begin(),X.end(),???,op(0.1,X)));
returnVal3 = f(transform(X.begin(),X.end(),???,op(-0.1,X)));
Is there a way to do this without defining an intermediate object that then gets passed to f? Thanks in advance!
If your function f takes a container, then you will have to create a container with the transformed values. In your example you seem to also expect that X remains unchanged by the first transformation, so you you cannot just modify it inplace
returnVal1 = f( X );
transform( X.begin(), X.end(), X.begin(),
[]( double val ){ return val + 0.1*val; } );
returnVal2 = f( X );
If you don't want to create explicit local temporaries then you can construct them using a helper function.
// pass in by value to get a copy, modify it inplace and return it
array2Drow transformed( array2Drow copy, double factor )
{
std::transform( copy.begin(), copy.end(), copy.begin(),
[&]( double val ){ return val + factor*val; } ) );
return copy;
}
The calculation of the return values can then be written using the helper.
returnVal1 = f( X );
returnVal2 = f( transformed( X, 0.1 ) );
returnVal3 = f( transformed( X, -0.1 ) );
The ??? needs to be an iterator for a container where you want to store the result of the transform operation, i.e. the return value of op
However, your idea is wrong.
std::transform returns (see http://en.cppreference.com/w/cpp/algorithm/transform)
Return value
Output iterator to the element past the last element transformed.
It makes no sense to pass that iterator to a function as it is end of the container.
Further, the signature of op doesn't fulfil the requirements for std::transform.
If f expects to receive a array2Drow, then you need to pass it one (containing the correct data).
With that given, you really only have a couple of choices: either modify the data in the existing collection (and repeatedly pass the same collection), or else create a new collection each time you invoke it.
If f really only needs one of the items at a time (e.g., like an accumulator), then you may be able to rewrite f to only take one input at a time, then at the end of each "run", retrieve the value and reset the accumulator.
In that case, you can probably create an iterator type that will invoke the accumulator for each item as its created, and pass an instance of that accumulator to std::transform as the destination where the result should be written.
For reference, you may want to look at Boost Accumulators.

Understanding std::accumulate

I want to know why std::accumulate (aka reduce) 3rd parameter is needed. For those who do not know what accumulate is, it's used like so:
vector<int> V{1,2,3};
int sum = accumulate(V.begin(), V.end(), 0);
// sum == 6
Call to accumulate is equivalent to:
sum = 0; // 0 - value of 3rd param
for (auto x : V) sum += x;
There is also optional 4th parameter, which allow to replace addition with any other operation.
Rationale that I've heard is that if you need let say not to add up, but multiply elements of a vector, we need other (non-zero) initial value:
vector<int> V{1,2,3};
int product = accumulate(V.begin(), V.end(), 1, multiplies<int>());
But why not do like Python - set initial value for V.begin(), and use range starting from V.begin()+1. Something like this:
int sum = accumulate(V.begin()+1, V.end(), V.begin());
This will work for any op. Why is 3rd parameter needed at all?
You're making a mistaken assumption: that type T is of the same type as the InputIterator.
But std::accumulate is generic, and allows all different kinds of creative accumulations and reductions.
Example #1: Accumulate salary across Employees
Here's a simple example: an Employee class, with many data fields.
class Employee {
/** All kinds of data: name, ID number, phone, email address... */
public:
int monthlyPay() const;
};
You can't meaningfully "accumulate" a set of employees. That makes no sense; it's undefined. But, you can define an accumulation regarding the employees. Let's say we want to sum up all the monthly pay of all employees. std::accumulate can do that:
/** Simple class defining how to add a single Employee's
* monthly pay to our existing tally */
auto accumulate_func = [](int accumulator, const Employee& emp) {
return accumulator + emp.monthlyPay();
};
// And here's how you call the actual calculation:
int TotalMonthlyPayrollCost(const vector<Employee>& V)
{
return std::accumulate(V.begin(), V.end(), 0, accumulate_func);
}
So in this example, we're accumulating an int value over a collection of Employee objects. Here, the accumulation sum isn't the same type of variable that we're actually summing over.
Example #2: Accumulating an average
You can use accumulate for more complex types of accumulations as well - maybe want to append values to a vector; maybe you have some arcane statistic you're tracking across the input; etc. What you accumulate doesn't have to be just a number; it can be something more complex.
For example, here's a simple example of using accumulate to calculate the average of a vector of ints:
// This time our accumulator isn't an int -- it's a structure that lets us
// accumulate an average.
struct average_accumulate_t
{
int sum;
size_t n;
double GetAverage() const { return ((double)sum)/n; }
};
// Here's HOW we add a value to the average:
auto func_accumulate_average =
[](average_accumulate_t accAverage, int value) {
return average_accumulate_t(
{accAverage.sum+value, // value is added to the total sum
accAverage.n+1}); // increment number of values seen
};
double CalculateAverage(const vector<int>& V)
{
average_accumulate_t res =
std::accumulate(V.begin(), V.end(), average_accumulate_t({0,0}), func_accumulate_average)
return res.GetAverage();
}
Example #3: Accumulate a running average
Another reason you need the initial value is because that value isn't always the default/neutral value for the calculation you're making.
Let's build on the average example we've already seen. But now, we want a class that can hold a running average -- that is, we can keep feeding in new values, and check the average so far, across multiple calls.
class RunningAverage
{
average_accumulate_t _avg;
public:
RunningAverage():_avg({0,0}){} // initialize to empty average
double AverageSoFar() const { return _avg.GetAverage(); }
void AddValues(const vector<int>& v)
{
_avg = std::accumulate(v.begin(), v.end(),
_avg, // NOT the default initial {0,0}!
func_accumulate_average);
}
};
int main()
{
RunningAverage r;
r.AddValues(vector<int>({1,1,1}));
std::cout << "Running Average: " << r.AverageSoFar() << std::endl; // 1.0
r.AddValues(vector<int>({-1,-1,-1}));
std::cout << "Running Average: " << r.AverageSoFar() << std::endl; // 0.0
}
This is a case where we absolutely rely on being able to set that initial value for std::accumulate - we need to be able to initialize the accumulation from different starting points.
In summary, std::accumulate is good for any time you're iterating over an input range, and building up one single result across that range. But the result doesn't need to be the same type as the range, and you can't make any assumptions about what initial value to use -- which is why you must have an initial instance to use as the accumulating result.
The way things are, it is annoying for code that knows for sure a range isn't empty and that wants to start accumulating from the first element of the range on. Depending on the operation that is used to accumulate with, it's not always obvious what the 'zero' value to use is.
If on the other hand you only provide a version that requires non-empty ranges, it's annoying for callers that don't know for sure that their ranges aren't empty. An additional burden is put on them.
One perspective is that the best of both worlds is of course to provide both functionality. As an example, Haskell provides both foldl1 and foldr1 (which require non-empty lists) alongside foldl and foldr (which mirror std::transform).
Another perspective is that since the one can be implemented in terms of the other with a trivial transformation (as you've demonstrated: std::transform(std::next(b), e, *b, f) -- std::next is C++11 but the point still stands), it is preferable to make the interface as minimal as it can be with no real loss of expressive power.
Because standard library algorithms are supposed to work for arbitrary ranges of (compatible) iterators. So the first argument to accumulate doesn't have to be begin(), it could be any iterator between begin() and one before end(). It could also be using reverse iterators.
The whole idea is to decouple algorithms from data. Your suggestion, if I understand it correctly, requires a certain structure in the data.
If you wanted accumulate(V.begin()+1, V.end(), V.begin()) you could just write that. But what if you thought v.begin() might be v.end() (i.e. v is empty)? What if v.begin() + 1 is not implemented (because v only implements ++, not generized addition)? What if the type of the accumulator is not the type of the elements? Eg.
std::accumulate(v.begin(), v.end(), 0, [](long count, char c){
return isalpha(c) ? count + 1 : count
});
It's indeed not needed. Our codebase has 2 and 3-argument overloads which use a T{} value.
However, std::accumulate is pretty old; it comes from the original STL. Our codebase has fancy std::enable_if logic to distinguish between "2 iterators and initial value" and "2 iterators and reduction operator". That requires C++11. Our code also uses a trailing return type (auto accumulate(...) -> ...) to calculate the return type, another C++11 feature.

Multiply vector elements by a scalar value using STL

Hi I want to (multiply,add,etc) vector by scalar value for example myv1 * 3 , I know I can do a function with a forloop , but is there a way of doing this using STL function? Something like the {Algorithm.h :: transform function }?
Yes, using std::transform:
std::transform(myv1.begin(), myv1.end(), myv1.begin(),
std::bind(std::multiplies<T>(), std::placeholders::_1, 3));
Before C++17 you could use std::bind1st(), which was deprecated in C++11.
std::transform(myv1.begin(), myv1.end(), myv1.begin(),
std::bind1st(std::multiplies<T>(), 3));
For the placeholders;
#include <functional>
If you can use a valarray instead of a vector, it has builtin operators for doing a scalar multiplication.
v *= 3;
If you have to use a vector, you can indeed use transform to do the job:
transform(v.begin(), v.end(), v.begin(), _1 * 3);
(assuming you have something similar to Boost.Lambda that allows you to easily create anonymous function objects like _1 * 3 :-P)
Modern C++ solution for your question.
#include <algorithm>
#include <vector>
std::vector<double> myarray;
double myconstant{3.3};
std::transform(myarray.begin(), myarray.end(), myarray.begin(), [&myconstant](auto& c){return c*myconstant;});
I think for_each is very apt when you want to traverse a vector and manipulate each element according to some pattern, in this case a simple lambda would suffice:
std::for_each(myv1.begin(), mtv1.end(), [](int &el){el *= 3; });
note that any variable you want to capture for the lambda function to use (say that you e.g. wanted to multiply with some predetermined scalar), goes into the bracket as a reference.
If you had to store the results in a new vector, then you could use the std::transform() from the <algorithm> header:
#include <algorithm>
#include <vector>
int main() {
const double scale = 2;
std::vector<double> vec_input{1, 2, 3};
std::vector<double> vec_output(3); // a vector of 3 elements, Initialized to zero
// ~~~
std::transform(vec_input.begin(), vec_input.end(), vec_output.begin(),
[&scale](double element) { return element *= scale; });
// ~~~
return 0;
}
So, what we are saying here is,
take the values (elements) of vec_input starting from the beginning (vec_input.begin()) to the end (vec_input.begin()),
essentially, with the first two arguments, you specify a range of elements ([beginning, end)) to transform,
range
pass each element to the last argument, lambda expression,
take the output of lambda expression and put it in the vec_output starting from the beginning (vec_output.begin()).
the third argument is to specify the beginning of the destination vector.
The lambda expression
captures the value of scale factor ([&scale]) from outside by reference,
takes as its input a vector element of type double (passed to it by std::transform())
in the body of the function, it returns the final result,
which, as I mentioned above, will be consequently stored in the vec_input.
Final note: Although unnecessary, you could pass lambda expression per below:
[&scale](double element) -> double { return element *= scale; }
It explicitly states that the output of the lambda expression is a double. However, we can omit that, because the compiler, in this case, can deduce the return type by itself.
I know this not STL as you want, but it is something you can adapt as different needs arise.
Below is a template you can use to calculate; 'func' would be the function you want to do: multiply, add, and so on; 'parm' is the second parameter to the 'func'. You can easily extend this to take different func's with more parms of varied types.
template<typename _ITStart, typename _ITEnd, typename _Func , typename _Value >
_ITStart xform(_ITStart its, _ITEnd ite, _Func func, _Value parm)
{
while (its != ite) { *its = func(*its, parm); its++; }
return its;
}
...
int mul(int a, int b) { return a*b; }
vector< int > v;
xform(v.begin(), v.end(), mul, 3); /* will multiply each element of v by 3 */
Also, this is not a 'safe' function, you must do type/value-checking etc. before you use it.