-
Notifications
You must be signed in to change notification settings - Fork 13.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Map function - IntegerDivideByZero #8938
Comments
So #7027 is the culprit. But code above does not check the value regardless, so our exception is replaced with a run-time error. Looking at esp32 where PR was also merged, it was eventually reverted back to original implementation because of errors with larger values. With the provided test (0...180 to 1000...2000 and back), error rate is 0. With 0 and 10000 as min and max - error rate becomes 99%, mapping value and mapping value back are off-by-one :/ Suppose in servo case it makes sense, but not in general func context. Or, calc should take a different value (and btw, divide-by-2 effect is not explained even in servo case besides that it is 'better' :/) Arduino/libraries/Servo/src/Servo.cpp Lines 36 to 38 in 521ae60
|
Shouldn't a simple fix like this be enough to prevent these crashes? if (divisor == 0) return in_min; Increasing resolution and int overflows with large values are much harder to fix.
This way the first part of the function can be something like this (untested, just notepad memory dump): long map(long x, long in_min, long in_max, long out_min, long out_max) {
const long divident = out_max - out_min;
const long divisor = in_max - in_min;
if (divisor == 0) return in_min;
const long delta = x - in_min;
if (divident == divisor) {
return out_min + delta;
}
if (divident == (-1 * divisor)) {
return out_max + delta;
}
... |
OK, just thought of something like this (still untested, just some gut feeling programming) long map(long x, long in_min, long in_max, long out_min, long out_max) {
const long divident = out_max - out_min;
const long divisor = in_max - in_min;
if (divisor == 0) return in_min;
const long delta = x - in_min;
if (divident == divisor) {
return out_min + delta;
}
if (divident == (-1 * divisor)) {
return out_max + delta;
}
if (abs(divident) > abs(divisor)) {
const long error = divident % divisor;
const long factor = (divident + error) / divisor;
return (delta * factor) + out_min;
}
// abs(divident) < abs(divisor)
const long factor = divisor / divident;
const long error = out_max - (in_max / factor + out_min);
return (delta + error) / factor + out_min;
} Not sure how modulo will act on negative values, so another approach could be something like this: long map(long x, long in_min, long in_max, long out_min, long out_max) {
const long divident = out_max - out_min;
const long divisor = in_max - in_min;
if (divisor == 0) return in_min;
const long delta = x - in_min;
if (divident == divisor) {
return out_min + delta;
}
if (divisor < 0 && divident < 0) {
return map(x, in_max, in_min, out_max, out_min);
} else if (divisor < 0) {
return map(in_max - x, in_max, in_min, out_min, out_max);
} else if (divident < 0) {
return map(in_max - x, in_min, in_max, out_max, out_min);
}
if (divident > divisor) {
const long error = divident % divisor;
const long factor = (divident + error) / divisor;
return (delta * factor) + out_min;
}
// divident < divisor
const long factor = divisor / divident;
const long error = out_max - (in_max / factor + out_min);
return (delta + error) / factor + out_min;
} |
Just did a quick test on cpp.sh with the last suggested option: long map(long x, long in_min, long in_max, long out_min, long out_max) {
const long divident = out_max - out_min;
const long divisor = in_max - in_min;
if (divisor == 0) return in_min;
const long delta = x - in_min;
if (divident == divisor) {
return out_min + delta;
}
if (divisor < 0 && divident < 0) {
return map(x, in_max, in_min, out_max, out_min);
} else if (divisor < 0) {
return map(in_max - x, in_max, in_min, out_min, out_max);
} else if (divident < 0) {
return map(in_max - x, in_min, in_max, out_max, out_min);
}
if (divident > divisor) {
const long error = divident % divisor;
const long factor = (divident + error) / divisor;
return (delta * factor) + out_min;
}
// divident < divisor
const long factor = divisor / divident;
const long error = out_max - (in_max / factor + out_min);
return (delta + error) / factor + out_min;
}
int main()
{
long value = 0;
for (size_t i = 1; i < 15; ++i) {
value = (i/3) * 2500 - 1 + i%3;
long output = map(value, 0, 10000, 10000, 0);
long output2 = map(value, 0, 100, 10000, 0);
long output3 = map(value, 0, 100, 0, 10000);
std::cout << value << ":\t" << output << "\t" << output2 << "\t" << output3 << "\n";
}
}
And also mapping to a smaller range: int main()
{
long value = 0;
for (size_t i = 1; i < 15; ++i) {
value = (i/3) * 2500 - 1 + i%3;
long output = map(value, 0, 10000, 999, 0);
long output2 = map(value, 0, 10000, 99, 0);
long output3 = map(value, 10000, 0, 0, 99);
std::cout << value << ":\t" << output << "\t" << output2 << "\t" << output3 << "\n";
}
} Result:
Edit: int main()
{
long value = 0;
for (size_t i = 1; i < 15; ++i) {
value = (i/3) * 2500 - 1 + i%3;
long output = map(value, 0, 10000, 255, 0);
long output2 = map(value, 0, 10000, 0, 255);
long output3 = map(value, 10000, 0, 0, 1024);
long output4 = map(value, 10000, 0, 1024, 0);
long output5 = map(value, 10000, 0, 0, 10240);
long output6 = map(value, 10000, 0, 10240, 0);
std::cout << value << ":\t" << output << "\t" << output2 << "\t" << output3 << "\t" << output4 << "\t" << output5 << "\t" << output6 << "\n";
}
} Not what it should be...
|
Made some progress.... // Example program
# include <iostream>
# include <string>
long map(long x, long in_min, long in_max, long out_min, long out_max) {
const long out_length = out_max - out_min;
const long in_length = in_max - in_min;
if (in_length == 0) { return in_min; }
if (out_length == 0) { return out_min; }
const long delta = x - in_min;
if (out_length == in_length) {
return out_min + delta;
}
if (out_length == (-1 * in_length)) {
return out_max + delta;
}
if ((out_length < 0) && (in_length < 0)) {
return map(x, in_max, in_min, out_max, out_min);
} else if (out_length < 0) {
return map(in_max - delta, in_min, in_max, out_max, out_min);
} else if (in_length < 0) {
return map(in_max - delta, in_max, in_min, out_min, out_max);
}
// We now know in_min < in_max and out_min < out_max
// Make sure x is within range of in_min ... in_max
if ((x < in_min) || (x > in_max)) {
long shift_factor = 0;
if (x < in_min) {
const long before_min = in_min - x;
shift_factor = -1 - (before_min / in_length);
} else if (x > in_max) {
const long passed_max = x - in_max;
shift_factor = 1 + (passed_max / in_length);
}
if (shift_factor != 0) {
const long in_shift = shift_factor * in_length;
const long out_shift = shift_factor * out_length;
return map(x, in_min + in_shift, in_max + in_shift, out_min + out_shift, out_max + out_shift);
}
}
const long abs_out_length = abs(out_length);
if (abs_out_length > abs(in_length)) {
const long intermediate_divisor = delta == 0 ? 1 : abs_out_length;
const long intermediate_max = (0x1FFFFFFF - abs(in_length / 2)) / intermediate_divisor;
if ((2 * intermediate_max) > abs_out_length) {
const long intermediate = (delta * intermediate_max * 2 + (in_length / 2)) / in_length - intermediate_max;
return map(intermediate, -intermediate_max, intermediate_max, out_min, out_max);
}
}
// abs(out_length) < abs(in_length)
return (delta * out_length + (in_length / 2)) / in_length + out_min;
}
int main()
{
long value = 0;
for (size_t i = 1; i < 15; ++i) {
value = (i / 3) * 2500 - 1 + i % 3;
const long values[] = {
map(value, 0, 1000, 255, 0),
map(value, 0, 1000, 0, 255),
map(value, 10000, 0, 0, 1024),
map(value, 10000, 0, 1024, 0),
map(value, 1000, 0, 0, 10240),
map(value, 1000, 0, 10240, 0),
map(value, 0, 1000, 0, 10240),
map(value, 0, 1000, 10240, 0),
map(value, 0, 10000, 10240, 0),
map(value, 10000, 0, 10240, 0)
};
std::cout << value << ":";
constexpr size_t nrvalues = sizeof(values) / sizeof(values[0]);
for (size_t i = 0; i < nrvalues; ++i) {
std::cout << "\t" << values[i];
}
std::cout << "\n";
}
} With output:
@mcspr I think this is working very well and stable, without using a single float. |
And some extra checks for int overflow: // Example program
# include <iostream>
# include <string>
long map(long x, long in_min, long in_max, long out_min, long out_max) {
const long out_length = out_max - out_min;
const long in_length = in_max - in_min;
if (in_length == 0) { return in_min; }
if (out_length == 0) { return out_min; }
const long delta = x - in_min;
if (out_length == in_length) {
return out_min + delta;
}
if (out_length == (-1 * in_length)) {
return out_max + delta;
}
if ((out_length < 0) && (in_length < 0)) {
return map(x, in_max, in_min, out_max, out_min);
} else if (out_length < 0) {
return map(in_max - delta, in_min, in_max, out_max, out_min);
} else if (in_length < 0) {
return map(in_max - delta, in_max, in_min, out_min, out_max);
}
// We now know in_min < in_max and out_min < out_max
// Make sure x is within range of in_min ... in_max
if ((x < in_min) || (x > in_max)) {
long shift_factor = 0;
if (x < in_min) {
const long before_min = in_min - x;
shift_factor = -1 - (before_min / in_length);
} else if (x > in_max) {
const long passed_max = x - in_max;
shift_factor = 1 + (passed_max / in_length);
}
if (shift_factor != 0) {
const long in_shift = shift_factor * in_length;
const long out_shift = shift_factor * out_length;
return map(x, in_min + in_shift, in_max + in_shift, out_min + out_shift, out_max + out_shift);
}
}
const long abs_out_length = abs(out_length);
if (abs_out_length > abs(in_length)) {
const long intermediate_max = (0x1FFFFFFF - abs(in_length / 2)) / abs_out_length;
if (intermediate_max > (abs_out_length >> 2)) {
const long intermediate = (delta * intermediate_max * 2 + (in_length / 2)) / in_length - intermediate_max;
return map(intermediate, -intermediate_max, intermediate_max, out_min, out_max);
}
// Probably running into integer overflow, so use the slightly less accurate factor approach.
const long factor = out_length / in_length;
return (delta * factor) + out_min;
}
// abs(out_length) < abs(in_length)
const unsigned long overflow_estimator =
(delta > 256 ? (static_cast<unsigned long>(delta) >> 8) : 1) *
(out_length > 256 ? (static_cast<unsigned long>(out_length) >> 8) : 1) +
(static_cast<unsigned long>(in_length / 2) >> 8);
if (overflow_estimator > (1u << 16)) {
// Would result in integer overflow, so use the slightly less accurate factor approach.
const long factor = in_length / out_length;
if (factor != 0) {
return delta / factor + out_min;
}
}
return (delta * out_length + (in_length / 2)) / in_length + out_min;
}
int main()
{
long input = 0;
for (size_t i = 0; i < 15; ++i) {
input = (i / 3) * 2500 - 1 + i % 3;
const long values[] = {
map(input, 0, 1000, 255, 0),
map(input, 0, 1000, 0, 255),
map(input, 10000, 0, 100, 10100),
map(input, 10000, 0, 0, 1024),
map(input, 10000, 0, 1024, 0),
map(input, 1000, 0, 0, 10240),
map(input, 1000, 0, 10240, 0),
map(input, 0, 1000, 0, 10240),
map(input, 0, 1000, 10240, 0),
map(input, 0, 10000, 10240, 0),
map(input, 10000, 0, 10240, 0),
map(input, 10000, 0, 10240000, 0),
map(input, 50, 0, 10240000, 0)
};
std::cout << input << ":";
constexpr size_t nrvalues = sizeof(values) / sizeof(values[0]);
for (size_t i = 0; i < nrvalues; ++i) {
std::cout << "\t" << values[i];
}
std::cout << "\n";
}
} Result:
|
Fixed another issue with "inverted shift" (same range, one counting up, one down) and added a test function to show the "error" compared to the interpolation function using // Example program
# include <iostream>
# include <string>
long map(long x, long in_min, long in_max, long out_min, long out_max) {
const long out_length = out_max - out_min;
const long in_length = in_max - in_min;
if (in_length == 0) { return in_min; }
if (out_length == 0) { return out_min; }
const long delta = x - in_min;
if (out_length == in_length) {
return out_min + delta;
}
if ((out_length < 0) && (in_length < 0)) {
return map(x, in_max, in_min, out_max, out_min);
} else if (out_length < 0) {
return map(in_max - delta, in_min, in_max, out_max, out_min);
} else if (in_length < 0) {
return map(in_max - delta, in_max, in_min, out_min, out_max);
}
// We now know in_min < in_max and out_min < out_max
// Make sure x is within range of in_min ... in_max
if ((x < in_min) || (x > in_max)) {
long shift_factor = 0;
if (x < in_min) {
const long before_min = in_min - x;
shift_factor = -1 - (before_min / in_length);
} else if (x > in_max) {
const long passed_max = x - in_max;
shift_factor = 1 + (passed_max / in_length);
}
if (shift_factor != 0) {
const long in_shift = shift_factor * in_length;
const long out_shift = shift_factor * out_length;
return map(x, in_min + in_shift, in_max + in_shift, out_min + out_shift, out_max + out_shift);
}
}
const long abs_out_length = abs(out_length);
if (abs_out_length > abs(in_length)) {
const long intermediate_max = (0x1FFFFFFF - abs(in_length / 2)) / abs_out_length;
if (intermediate_max > (abs_out_length >> 2)) {
const long intermediate = (delta * intermediate_max * 2 + (in_length / 2)) / in_length - intermediate_max;
return map(intermediate, -intermediate_max, intermediate_max, out_min, out_max);
}
// Probably running into integer overflow, so use the slightly less accurate factor approach.
const long factor = out_length / in_length;
return (delta * factor) + out_min;
}
// abs(out_length) < abs(in_length)
const unsigned long overflow_estimator =
(delta > 256 ? (static_cast<unsigned long>(delta) >> 8) : 1) *
(out_length > 256 ? (static_cast<unsigned long>(out_length) >> 8) : 1) +
(static_cast<unsigned long>(in_length / 2) >> 8);
if (overflow_estimator > (1u << 16)) {
// Would result in integer overflow, so use the slightly less accurate factor approach.
const long factor = in_length / out_length;
if (factor != 0) {
return delta / factor + out_min;
}
}
return (delta * out_length + (in_length / 2)) / in_length + out_min;
}
long test_map(long x, long in_min, long in_max, long out_min, long out_max) {
const double out_length = out_max - out_min;
const double in_length = in_max - in_min;
if (in_length == 0) { return in_min; }
if (out_length == 0) { return out_min; }
const double delta = x - in_min;
const double value = (delta * out_length + (in_length / 2)) / in_length + out_min;
// return std::round(value);
return value;
}
long check(long x, long in_min, long in_max, long out_min, long out_max) {
const long floatvalue = test_map(x, in_min, in_max, out_min, out_max);
const long map_value = map(x, in_min, in_max, out_min, out_max);
return floatvalue - map_value;
}
int main()
{
long input = 0;
for (size_t i = 0; i < 15; ++i) {
input = (i / 3) * 2500 - 1 + i % 3;
const long values[] = {
check(input, 0, 1000, 255, 0),
check(input, 0, 1000, 0, 255),
check(input, 10000, 0, 100, 10100),
check(input, 10000, 0, 10100, 100),
check(input, 10000, 0, 0, 1024),
check(input, 10000, 0, 1024, 0),
check(input, 1000, 0, 0, 10240),
check(input, 1000, 0, 10240, 0),
check(input, 0, 1000, 0, 10240),
check(input, 0, 1000, 10240, 0),
check(input, 0, 10000, 10240, 0),
check(input, 10000, 0, 10240, 0),
check(input, 10000, 0, 10240000, 0),
check(input, 50, 0, 10240000, 0)
};
std::cout << input << ":";
constexpr size_t nrvalues = sizeof(values) / sizeof(values[0]);
for (size_t i = 0; i < nrvalues; ++i) {
std::cout << "\t" << values[i];
}
std::cout << "\n";
}
} The "error" for each calculation.
I think this is as accurate as can be done using only integer calculations :) |
OK, still could be improved :) Now even more accurate with large numbers // Example program
# include <iostream>
# include <string>
long map(long x, long in_min, long in_max, long out_min, long out_max) {
const long out_length = out_max - out_min;
const long in_length = in_max - in_min;
if (in_length == 0) { return in_min; }
if (out_length == 0) { return out_min; }
const long delta = x - in_min;
if (out_length == in_length) {
return out_min + delta;
}
if ((out_length < 0) && (in_length < 0)) {
return map(x, in_max, in_min, out_max, out_min);
} else if (out_length < 0) {
return map(in_max - delta, in_min, in_max, out_max, out_min);
} else if (in_length < 0) {
return map(in_max - delta, in_max, in_min, out_min, out_max);
}
// We now know in_min < in_max and out_min < out_max
// Make sure x is within range of in_min ... in_max
if ((x < in_min) || (x > in_max)) {
long shift_factor = 0;
if (x < in_min) {
const long before_min = in_min - x;
shift_factor = -1 - (before_min / in_length);
} else if (x > in_max) {
const long passed_max = x - in_max;
shift_factor = 1 + (passed_max / in_length);
}
if (shift_factor != 0) {
const long in_shift = shift_factor * in_length;
const long out_shift = shift_factor * out_length;
return map(x, in_min + in_shift, in_max + in_shift, out_min + out_shift, out_max + out_shift);
}
}
const long abs_out_length = abs(out_length);
if (abs_out_length > abs(in_length)) {
const long intermediate_max = (0x2FFFFFFF - abs(in_length)) / abs_out_length;
if (intermediate_max > (abs_out_length >> 2)) {
const long intermediate = (delta * intermediate_max * 2 + (in_length / 2)) / in_length - intermediate_max;
return map(intermediate, -intermediate_max, intermediate_max, out_min, out_max);
}
// Probably running into integer overflow, so use the slightly less accurate factor approach.
const long factor = out_length / in_length;
const long error_mod = out_length % in_length;
const long error = (delta * error_mod) / in_length;
return (delta * factor) + out_min + error;
}
// abs(out_length) < abs(in_length)
const unsigned long overflow_estimator =
(delta > 256 ? (static_cast<unsigned long>(delta) >> 8) : 1) *
(out_length > 256 ? (static_cast<unsigned long>(out_length) >> 8) : 1) +
(static_cast<unsigned long>(in_length / 2) >> 8);
if (overflow_estimator > (1u << 16)) {
// Would result in integer overflow, so use the slightly less accurate factor approach.
const long factor = in_length / out_length;
const long error_mod = in_length % out_length;
const long error = (error_mod == 0 || delta == 0) ? 0 : out_length / (delta * error_mod);
return delta / factor + out_min + error;
}
return (delta * out_length + (in_length / 2)) / in_length + out_min;
}
long test_map(long x, long in_min, long in_max, long out_min, long out_max) {
const double out_length = out_max - out_min;
const double in_length = in_max - in_min;
if (in_length == 0) { return in_min; }
if (out_length == 0) { return out_min; }
const double delta = x - in_min;
const double value = (delta * out_length + (in_length / 2)) / in_length + out_min;
// return std::round(value);
return value;
}
long check(long x, long in_min, long in_max, long out_min, long out_max) {
const long floatvalue = test_map(x, in_min, in_max, out_min, out_max);
const long map_value = map(x, in_min, in_max, out_min, out_max);
return floatvalue - map_value;
}
int main()
{
long input = 0;
for (size_t i = 0; i < 15; ++i) {
input = (i / 3) * 2500 - 1 + i % 3;
const long values[] = {
check(input, 0, 1000, 255, 0),
check(input, 0, 1000, 0, 255),
check(input, 10000, 0, 100, 10100),
check(input, 10000, 0, 10100, 100),
check(input, 10000, 0, 0, 1024),
check(input, 10000, 0, 1024, 0),
check(input, 1000, 0, 0, 10240),
check(input, 1000, 0, 10240, 0),
check(input, 0, 1000, 0, 10240),
check(input, 0, 1000, 10240, 0),
check(input, 0, 10000, 10240, 0),
check(input, 10234567, 0, 1234567, 100),
check(input, 10000, 0, 10234567, 0),
check(input, 50, 1, 10234567, 0)
};
std::cout << input << ":";
constexpr size_t nrvalues = sizeof(values) / sizeof(values[0]);
for (size_t i = 0; i < nrvalues; ++i) {
std::cout << "\t" << values[i];
}
std::cout << "\n";
}
} Output:
|
OK, last update ... (for now) :) Made it more accurate for large 'delta' and mapping large input range to smaller output range. // Example program
# include <iostream>
# include <string>
long map(long x, long in_min, long in_max, long out_min, long out_max) {
const long out_length = out_max - out_min;
const long in_length = in_max - in_min;
if (in_length == 0) { return in_min; }
if (out_length == 0) { return out_min; }
long delta = x - in_min;
if (out_length == in_length) {
return out_min + delta;
}
if ((out_length < 0) && (in_length < 0)) {
return map(x, in_max, in_min, out_max, out_min);
} else if (out_length < 0) {
return map(in_max - delta, in_min, in_max, out_max, out_min);
} else if (in_length < 0) {
return map(in_max - delta, in_max, in_min, out_min, out_max);
}
// We now know in_min < in_max and out_min < out_max
// Make sure x is within range of in_min ... in_max
if ((x < in_min) || (x > in_max)) {
long shift_factor = 0;
if (x < in_min) {
const long before_min = in_min - x;
shift_factor = -1 - (before_min / in_length);
} else if (x > in_max) {
const long passed_max = x - in_max;
shift_factor = 1 + (passed_max / in_length);
}
if (shift_factor != 0) {
const long in_shift = shift_factor * in_length;
const long out_shift = shift_factor * out_length;
in_min += in_shift;
in_max += in_shift;
out_min += out_shift;
out_max += out_shift;
delta = x - in_min;
}
}
if (out_length > in_length) {
// Map to larger range
const long factor = out_length / in_length;
const long error_mod = out_length % in_length;
const long error = (delta * error_mod) / in_length;
return (delta * factor) + out_min + error;
}
// abs(out_length) < abs(in_length)
// Map to smaller range
const long factor = (in_length / out_length);
const long estimate_full = in_length / factor + out_min;
const long error = (delta * (out_max - estimate_full)) / in_length;
return delta / factor + out_min + error;
}
long test_map(long x, long in_min, long in_max, long out_min, long out_max) {
const double out_length = out_max - out_min;
const double in_length = in_max - in_min;
if (in_length == 0) { return in_min; }
if (out_length == 0) { return out_min; }
const double delta = x - in_min;
const double value = (delta * out_length + (in_length / 2)) / in_length + out_min;
// return std::round(value);
return value;
}
long check(long x, long in_min, long in_max, long out_min, long out_max) {
const long floatvalue = test_map(x, in_min, in_max, out_min, out_max);
const long map_value = map(x, in_min, in_max, out_min, out_max);
return floatvalue - map_value;
}
int main()
{
long input = 0;
for (size_t i = 0; i < 15; ++i) {
input = (i / 3) * 2500 - 1 + i % 3;
const long values[] = {
check(input, 0, 1000, 255, 0),
check(input, 0, 1000, 0, 255),
check(input, 10000, 0, 100, 10100),
check(input, 10000, 0, 10100, 100),
check(input, 10000, 0, 0, 1024),
check(input, 10000, 0, 1024, 0),
check(input, 1000, 0, 0, 10240),
check(input, 1000, 0, 10240, 0),
check(input, 0, 1000, 0, 10240),
check(input, 0, 1000, 10240, 0),
check(input, 0, 10000, 10240, 0),
check(input, 10234567, -12345, 10234567, 100),
check(input, 10000, 0, 10234567, 0),
check(input, 50, 1, 10234567, 0)
};
std::cout << input << ":";
constexpr size_t nrvalues = sizeof(values) / sizeof(values[0]);
for (size_t i = 0; i < nrvalues; ++i) {
std::cout << "\t" << values[i];
}
std::cout << "\n";
}
} Output:
|
Fixes: esp8266#8938 Also increase accuracy of mapping and fixing map issues with large values. Still only using integer operations. Test function to see absolute error compared to floating point map function using `double` precision floating point values. ```c++ # include <iostream> # include <string> long test_map(long x, long in_min, long in_max, long out_min, long out_max) { const double out_length = out_max - out_min; const double in_length = in_max - in_min; if (in_length == 0) { return in_min; } if (out_length == 0) { return out_min; } const double delta = x - in_min; const double value = (delta * out_length + (in_length / 2)) / in_length + out_min; // return std::round(value); return value; } long check(long x, long in_min, long in_max, long out_min, long out_max) { const long floatvalue = test_map(x, in_min, in_max, out_min, out_max); const long map_value = map(x, in_min, in_max, out_min, out_max); return floatvalue - map_value; } int main() { long input = 0; for (size_t i = 0; i < 15; ++i) { input = (i / 3) * 2500 - 1 + i % 3; const long values[] = { check(input, 0, 1000, 255, 0), check(input, 0, 1000, 0, 255), check(input, 10000, 0, 100, 10100), check(input, 10000, 0, 10100, 100), check(input, 10000, 0, 0, 1024), check(input, 10000, 0, 1024, 0), check(input, 1000, 0, 0, 10240), check(input, 1000, 0, 10240, 0), check(input, 0, 1000, 0, 10240), check(input, 0, 1000, 10240, 0), check(input, 0, 10000, 10240, 0), check(input, 10234567, -12345, 10234567, 100), check(input, 10000, 0, 10234567, 0), check(input, 50, 1, 10234567, 0) }; std::cout << input << ":"; constexpr size_t nrvalues = sizeof(values) / sizeof(values[0]); for (size_t i = 0; i < nrvalues; ++i) { std::cout << "\t" << values[i]; } std::cout << "\n"; } } ``` Output: ``` -1: 0 -1 0 0 0 -1 0 2 2 0 0 -1 2 2 0: 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 1: -1 0 0 0 -1 0 1 0 0 1 1 -1 0 0 2499: 1 -1 0 0 0 0 1 1 1 1 0 0 0 0 2500: 1 1 0 0 0 0 1 0 0 1 0 0 1 0 2501: 0 0 0 0 0 0 2 0 0 2 1 0 0 1 4999: 1 -1 0 0 0 0 1 1 1 1 0 0 0 0 5000: 1 0 0 0 0 0 1 0 0 1 0 0 1 1 5001: 0 0 0 0 0 0 2 0 0 2 1 0 1 0 7499: 1 -1 0 0 0 0 1 1 1 1 0 0 1 1 7500: 1 1 0 0 0 0 1 0 0 1 0 0 0 0 7501: 0 0 0 0 0 0 2 0 0 2 1 0 1 0 9999: 1 -1 0 0 0 -1 1 1 1 1 0 0 1 0 10000: 1 0 0 0 0 0 1 0 0 1 0 0 0 0 10001: 0 0 0 0 -1 0 2 0 0 2 2 0 0 1 ```
Hi!
Someone did a regression in map function and I'm getting this error.
This issue has been fixed here before.
Best regards.
The text was updated successfully, but these errors were encountered: