Similar to Fastest way to determine if an integer is between two integers (inclusive) with known sets of values, I wish to figure out if some value (most likely a double-precision floating point number) is between two other values (of the same type). The caveat is that I don't know already which value is larger than the other and I'm trying to determine if I should/how I should avoid using std::max/min. Here is some code I've tried to test this with already:
inline bool inRangeMult(double p, double v1, double v2) {
return (p - v1) * (p - v2) <= 0;
}
inline bool inRangeMinMax(double p, double v1, double v2) {
return p <= std::max(v1, v2) && p >= std::min(v1, v2);
}
inline bool inRangeComp(double p, double v1, double v2) {
return p < v1 != p < v2;
}
int main()
{
double a = 1e4;
std::clock_t start;
double duration;
bool res = false;
start = std::clock();
for (size_t i = 0; i < 2e4; ++i) {
for (size_t j = 0; j < 2e4; ++j) {
res = inRangeMult(a, i, j) ? res : !res;
}
}
duration = std::clock() - start;
std::cout << "InRangeMult: " << duration << std::endl;
start = std::clock();
for (size_t i = 0; i < 2e4; ++i) {
for (size_t j = 0; j < 2e4; ++j) {
res = inRangeMinMax(a, i, j) ? res : !res;
}
}
duration = std::clock() - start;
std::cout << "InRangeMinMax: " << duration << std::endl;
start = std::clock();
for (size_t i = 0; i < 2e4; ++i) {
for (size_t j = 0; j < 2e4; ++j) {
res = inRangeComp(a, i, j) ? res : !res;
}
}
duration = std::clock() - start;
std::cout << "InRangeComp: " << duration << std::endl;
std::cout << "Tricking the compiler by printing inane res: " << res << std::endl;
}
On most runs I'm finding that using std::min/max is still fastest, (latest run prints 346, 310, and 324 respectively), but I'm not 100% confident this is the best test setup, or that I've exhausted all of the reasonable implementations.
I'd appreciate anyone's input with a better profiling setup and/or better implementation.
EDIT: Updated code to make it less prone to compiler optimization.
2nd EDIT: Tweaked value of a and number of iterations. Results for one run are:
- inRangeMult: 1337
- inRangeMinMaz: 1127
- inRangeComp: 729
inline
to inline those functions for a performance gain that theinline
keyword doesn't carry much weight (if any) in determining when functions are inlined anymore. – François Andrieuxa
is essentially aconstexpr
and you never use the result of your functions your function calls can both be precalculated at compile time and completely optimized out. I wouldn't count on the accuracy of this benchmark. – François AndrieuxinRangeComp
as the fastest. Also, you can make the min max version with a single branch like this – NathanOliver