...

/

Solving Generator Problems

Solving Generator Problems

Learn to solve generator problems, starting with a small utility for generating linearly spaced sequences between a start and stop value and examining different techniques.

Generator problems

We will now present a small problem and we will try to solve it using different techniques for the purpose of understanding which programming idioms we can potentially replace with generators. We will write a small utility for generating linearly spaced sequences between a start value and a stop value.

If you have been using MATLAB/Octave or Python NumPy, you might recognize this way of generating evenly (linearly) spaced numbers using a function called linspace(). It’s a handy utility that can be used in various contexts with arbitrary ranges.

We will call our generator lin_space(). Here is a usage example of generating five equally spaced values between 2.0 and 3.0:

Press + to interact
main.cpp
lin_value.h
for (auto v : lin_space(2.0f, 3.0f, 5)) {
std::cout << v << ", ";
}
// Prints: 2, 2.25, 2.5, 2.75, 3,

When generating floating-point values, we have to be a little bit cautious because we cannot simply compute the size of each step (0.25 in the preceding example) and accumulate it, since the step size might not be possible to represent exactly using a floating-point data type. The possible rounding error will add up at each iteration, and eventually, we may end up with completely nonsensical values. Instead, we need to calculate a number between the start and stop value at a specific increment using linear interpolation.

C++20 added a handy utility to <cmath> called std::lerp(), which computes the linear interpolation between two values with a specified amount. In our case, the amount will be a value between 0.0 and 1.0; an amount of 0 returns the start value and a value of 1.0 returns the stop value. Here are a few examples of using std::lerp():

Press + to interact
auto start = -1.0;
auto stop = 1.0;
std::lerp(start, stop, 0.0); // -1.0
std::lerp(start, stop, 0.5); // 0.0
std::lerp(start, stop, 1.0); // 1.0

The lin_space() ...