aName
aName

Reputation: 257

Simplest way to have a function calculate a statement only once unless some arguments change?

So I have this great number mapping function:

double map(double input, double input_start, double input_end, double output_start, double output_end)
    {
        /* Note, "slope" below is a constant for given numbers, so if you are calculating
        a lot of output values, it makes sense to calculate it once.  It also makes
        understanding the code easier */

        double slope = (output_end - output_start) / (input_end - input_start);
        return output_start + slope * (input - input_start);
    }

Courtesy of Alok Singhal: Mapping a numeric range onto another

And he is correct, I call the function many many times, but usually with the same input and output start/end arguments.

What do you think is the cleanest/simplest solution to having slope calculated once, I can think of many ideas (such as just making a Map class and have slope calculated in the constructor) But I am new to programming, and usually my ideas are not the best! The most ultimate, probably would be that the function itself knows if slope needs to be recalculated, but that might get messy quickly. I dunno!

Upvotes: 3

Views: 349

Answers (1)

JVApen
JVApen

Reputation: 11317

As already hinted in the comments, using caching with an advanced structure won't do you much good. Calculating 2 minimus operations and a divide is really hard to beat. And most likely not a performance problem.

My recommendation: compile your code with -O3 to let the optimizer do its job and profile where you are loosing your time.

Looking at your actual problem, you have 2 steps, a constant part and a variable part.

To deal with this kind of caching, classes are perfect. You create them at the root of your data and propagate them onwards. A function it could make use of the internals.

For example:

class Slope {
    double input_start{};
    double output_start{};
    double slope{};

public:
    Slope(double input_start, double input_end, double output_start, double output_end)
        : input_start{input_start}
        , output_start{output_start}
    {
    slope = (output_end - output_start) / (input_end - input_start);
    }

  double map(double input) const
        return output_start + slope * (input - input_start);
    }

When data changes, you create a new instance that can then be used (but not with new, but rather just Slope slope(0., 1., 40., 50.); auto res = slope.map(0.2);).

Example usage:

for (std::string s : file)
{
      double inStart = getInStart(s);
      ...;
      Slope slope = Slope{inStart, inEnd, outStart, outEnd};
      ...;
      for (double in : points)
      {
           double end = slope.map(in);
      }
}

Upvotes: 1

Related Questions