I need to remap several different ranges of values in my application, for example [0 1.0] to [-1000 1000]. So I created a template class (below) with the previous max/min and type (int/double) and the new max/min and type. The code works for small ranges, but when I try to convert ranges that exceed the integer range I am getting wrong results.
What I mean is if I try and map a range of std::int16_t [-32767 32767] to something else, I am encountering integer overflow/rollover. How can I fix this?
template<class P, class N>
class Remap {
public:
/**
* @brief Construct a new Remap object
*
* @param prevMin the previous range minimum value
* @param prevMax the previous range maximum value
* @param newMin the new range minimum value
* @param newMax the new range maximum value
*/
Remap(P prevMin, P prevMax, N newMin, N newMax) :
prev_min_(prevMin),
prev_max_(prevMax),
new_min_(newMin),
new_max_(newMax) {
// TODO: Need to handle if min == max
prev_range_ = prev_max_ - prev_min_;
new_range_ = new_max_ - new_min_;
};
// Convert a previous value to the new mapping
N Convert(P v) {
return static_cast<N>((v - prev_min_) * new_range_ / prev_range_ + new_min_);
}
private:
P prev_min_;
P prev_max_;
N new_min_;
N new_max_;
P prev_range_;
N new_range_;
};
An example that causes incorrect values
Remap<std::int16_t, double> my_remap(-32767, 32767, -1.0, 1.0);
// Should get 1.0
my_remap.Convert(32767);
I have traced the problem to
prev_range_ = prev_max_ - prev_min;
The correct value should be 65534 however since P is type int16_t I am not getting that value. Suggestions on how I can fix this?
** Edit: ** I can fix this by declaring Remap<std::int32_t, double> ... but not sure if there is a better/proper solution that actually uses the desired type of std::int16_t.