Created
October 30, 2020 07:40
-
-
Save royvandam/fb479b646b037f32dadb6e9c2e9031fd to your computer and use it in GitHub Desktop.
Float comparison
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <cfloat> | |
#include <cmath> | |
#include <cstdlib> | |
/** | |
* @brief Math related utility functions | |
*/ | |
namespace Math { | |
/** | |
* @brief Union type for getting the integer representation of a float. | |
* Used for calculating the ULP distance between to floats. More information on | |
* comparing floats: | |
* https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ | |
*/ | |
union Float { | |
int32_t i; | |
float f; | |
constexpr Float(float val = 0.0f) : f(val) {} | |
constexpr bool isNegative() const { | |
return i < 0; | |
} | |
}; | |
/** | |
* @brief Compare two floats relatively to each other based on a max epsilon | |
* distance. | |
* @param lhs Left hand side value. | |
* @param rhs Right hand side value. | |
* @param epsilon Max epsilon distance. | |
*/ | |
constexpr bool EqualRel(float lhs, float rhs, float epsilon = FLT_EPSILON) { | |
float diff = std::abs(lhs - rhs); | |
float largest = std::max(std::abs(lhs), std::abs(rhs)); | |
return diff <= largest * epsilon; | |
} | |
/** | |
* Compare two floats to each other based on a max ULP distance. | |
* https://en.wikipedia.org/wiki/Unit_in_the_last_place | |
* @param lhs Left hand side value. | |
* @param rhs Right hand side value. | |
* @param epsilon Max epsilon distance. | |
*/ | |
constexpr bool EqualULP(float lhs, float rhs, int max_ulp_diff = 1) { | |
Float _lhs(lhs); | |
Float _rhs(rhs); | |
// Compare signs, in case they are different the values do not match. | |
if (_lhs.isNegative() != _rhs.isNegative()) { | |
// Check to make sure +0==-0 | |
return lhs == rhs; | |
} | |
// Get the ULP distance | |
int ulp_diff = std::abs(_lhs.i - _rhs.i); | |
return ulp_diff <= max_ulp_diff; | |
} | |
} // namespace Math |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment