mirror of
https://github.com/godotengine/godot.git
synced 2024-11-27 09:16:35 +08:00
Merge pull request #48882 from aaronfranke/approx-use-double
Make is_equal_approx have explicit float and double versions
This commit is contained in:
commit
342f3efc7e
@ -109,7 +109,7 @@ bool Basis::is_diagonal() const {
|
||||
}
|
||||
|
||||
bool Basis::is_rotation() const {
|
||||
return Math::is_equal_approx(determinant(), 1, UNIT_EPSILON) && is_orthogonal();
|
||||
return Math::is_equal_approx(determinant(), 1, (real_t)UNIT_EPSILON) && is_orthogonal();
|
||||
}
|
||||
|
||||
#ifdef MATH_CHECKS
|
||||
|
@ -311,20 +311,20 @@ public:
|
||||
static float random(float from, float to);
|
||||
static int random(int from, int to);
|
||||
|
||||
static _ALWAYS_INLINE_ bool is_equal_approx(real_t a, real_t b) {
|
||||
static _ALWAYS_INLINE_ bool is_equal_approx(float a, float b) {
|
||||
// Check for exact equality first, required to handle "infinity" values.
|
||||
if (a == b) {
|
||||
return true;
|
||||
}
|
||||
// Then check for approximate equality.
|
||||
real_t tolerance = CMP_EPSILON * abs(a);
|
||||
float tolerance = CMP_EPSILON * abs(a);
|
||||
if (tolerance < CMP_EPSILON) {
|
||||
tolerance = CMP_EPSILON;
|
||||
}
|
||||
return abs(a - b) < tolerance;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ bool is_equal_approx(real_t a, real_t b, real_t tolerance) {
|
||||
static _ALWAYS_INLINE_ bool is_equal_approx(float a, float b, float tolerance) {
|
||||
// Check for exact equality first, required to handle "infinity" values.
|
||||
if (a == b) {
|
||||
return true;
|
||||
@ -333,7 +333,33 @@ public:
|
||||
return abs(a - b) < tolerance;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ bool is_zero_approx(real_t s) {
|
||||
static _ALWAYS_INLINE_ bool is_zero_approx(float s) {
|
||||
return abs(s) < CMP_EPSILON;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ bool is_equal_approx(double a, double b) {
|
||||
// Check for exact equality first, required to handle "infinity" values.
|
||||
if (a == b) {
|
||||
return true;
|
||||
}
|
||||
// Then check for approximate equality.
|
||||
double tolerance = CMP_EPSILON * abs(a);
|
||||
if (tolerance < CMP_EPSILON) {
|
||||
tolerance = CMP_EPSILON;
|
||||
}
|
||||
return abs(a - b) < tolerance;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ bool is_equal_approx(double a, double b, double tolerance) {
|
||||
// Check for exact equality first, required to handle "infinity" values.
|
||||
if (a == b) {
|
||||
return true;
|
||||
}
|
||||
// Then check for approximate equality.
|
||||
return abs(a - b) < tolerance;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ bool is_zero_approx(double s) {
|
||||
return abs(s) < CMP_EPSILON;
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,7 @@ Quat Quat::normalized() const {
|
||||
}
|
||||
|
||||
bool Quat::is_normalized() const {
|
||||
return Math::is_equal_approx(length_squared(), 1.0, UNIT_EPSILON); //use less epsilon
|
||||
return Math::is_equal_approx(length_squared(), 1, (real_t)UNIT_EPSILON); //use less epsilon
|
||||
}
|
||||
|
||||
Quat Quat::inverse() const {
|
||||
|
@ -59,7 +59,7 @@ Vector2 Vector2::normalized() const {
|
||||
|
||||
bool Vector2::is_normalized() const {
|
||||
// use length_squared() instead of length() to avoid sqrt(), makes it more stringent.
|
||||
return Math::is_equal_approx(length_squared(), 1.0, UNIT_EPSILON);
|
||||
return Math::is_equal_approx(length_squared(), 1, (real_t)UNIT_EPSILON);
|
||||
}
|
||||
|
||||
real_t Vector2::distance_to(const Vector2 &p_vector2) const {
|
||||
|
@ -423,7 +423,7 @@ Vector3 Vector3::normalized() const {
|
||||
|
||||
bool Vector3::is_normalized() const {
|
||||
// use length_squared() instead of length() to avoid sqrt(), makes it more stringent.
|
||||
return Math::is_equal_approx(length_squared(), 1.0, UNIT_EPSILON);
|
||||
return Math::is_equal_approx(length_squared(), 1, (real_t)UNIT_EPSILON);
|
||||
}
|
||||
|
||||
Vector3 Vector3::inverse() const {
|
||||
|
@ -513,7 +513,7 @@ void SpriteFramesEditor::_animation_select() {
|
||||
|
||||
if (frames->has_animation(edited_anim)) {
|
||||
double value = anim_speed->get_line_edit()->get_text().to_float();
|
||||
if (!Math::is_equal_approx(value, frames->get_animation_speed(edited_anim))) {
|
||||
if (!Math::is_equal_approx(value, (double)frames->get_animation_speed(edited_anim))) {
|
||||
_animation_fps_changed(value);
|
||||
}
|
||||
}
|
||||
|
@ -987,7 +987,7 @@ Vector<Vector2> TextServer::shaped_text_get_selection(RID p_shaped, int p_start,
|
||||
while (i < ranges.size()) {
|
||||
int j = i + 1;
|
||||
while (j < ranges.size()) {
|
||||
if (Math::is_equal_approx(ranges[i].y, ranges[j].x, UNIT_EPSILON)) {
|
||||
if (Math::is_equal_approx(ranges[i].y, ranges[j].x, (real_t)UNIT_EPSILON)) {
|
||||
ranges.write[i].y = ranges[j].y;
|
||||
ranges.remove(j);
|
||||
continue;
|
||||
|
@ -101,13 +101,13 @@ TEST_CASE("[Color] Reading methods") {
|
||||
const Color dark_blue = Color(0, 0, 0.5, 0.4);
|
||||
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(dark_blue.get_h(), 240 / 360.0),
|
||||
Math::is_equal_approx(dark_blue.get_h(), 240.0f / 360.0f),
|
||||
"The returned HSV hue should match the expected value.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(dark_blue.get_s(), 1),
|
||||
Math::is_equal_approx(dark_blue.get_s(), 1.0f),
|
||||
"The returned HSV saturation should match the expected value.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(dark_blue.get_v(), 0.5),
|
||||
Math::is_equal_approx(dark_blue.get_v(), 0.5f),
|
||||
"The returned HSV value should match the expected value.");
|
||||
}
|
||||
|
||||
|
@ -83,13 +83,13 @@ TEST_CASE("[Curve] Custom curve with free tangents") {
|
||||
Math::is_equal_approx(curve->interpolate(-0.1), 0),
|
||||
"Custom free curve should return the expected value at offset 0.1.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(curve->interpolate(0.1), 0.352),
|
||||
Math::is_equal_approx(curve->interpolate(0.1), (real_t)0.352),
|
||||
"Custom free curve should return the expected value at offset 0.1.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(curve->interpolate(0.4), 0.352),
|
||||
Math::is_equal_approx(curve->interpolate(0.4), (real_t)0.352),
|
||||
"Custom free curve should return the expected value at offset 0.1.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(curve->interpolate(0.7), 0.896),
|
||||
Math::is_equal_approx(curve->interpolate(0.7), (real_t)0.896),
|
||||
"Custom free curve should return the expected value at offset 0.1.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(curve->interpolate(1), 1),
|
||||
@ -102,13 +102,13 @@ TEST_CASE("[Curve] Custom curve with free tangents") {
|
||||
Math::is_equal_approx(curve->interpolate_baked(-0.1), 0),
|
||||
"Custom free curve should return the expected baked value at offset 0.1.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(curve->interpolate_baked(0.1), 0.352),
|
||||
Math::is_equal_approx(curve->interpolate_baked(0.1), (real_t)0.352),
|
||||
"Custom free curve should return the expected baked value at offset 0.1.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(curve->interpolate_baked(0.4), 0.352),
|
||||
Math::is_equal_approx(curve->interpolate_baked(0.4), (real_t)0.352),
|
||||
"Custom free curve should return the expected baked value at offset 0.1.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(curve->interpolate_baked(0.7), 0.896),
|
||||
Math::is_equal_approx(curve->interpolate_baked(0.7), (real_t)0.896),
|
||||
"Custom free curve should return the expected baked value at offset 0.1.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(curve->interpolate_baked(1), 1),
|
||||
@ -172,13 +172,13 @@ TEST_CASE("[Curve] Custom curve with linear tangents") {
|
||||
Math::is_equal_approx(curve->interpolate(-0.1), 0),
|
||||
"Custom linear curve should return the expected value at offset -0.1.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(curve->interpolate(0.1), 0.4),
|
||||
Math::is_equal_approx(curve->interpolate(0.1), (real_t)0.4),
|
||||
"Custom linear curve should return the expected value at offset 0.1.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(curve->interpolate(0.4), 0.4),
|
||||
Math::is_equal_approx(curve->interpolate(0.4), (real_t)0.4),
|
||||
"Custom linear curve should return the expected value at offset 0.4.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(curve->interpolate(0.7), 0.8),
|
||||
Math::is_equal_approx(curve->interpolate(0.7), (real_t)0.8),
|
||||
"Custom linear curve should return the expected value at offset 0.7.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(curve->interpolate(1), 1),
|
||||
@ -191,13 +191,13 @@ TEST_CASE("[Curve] Custom curve with linear tangents") {
|
||||
Math::is_equal_approx(curve->interpolate_baked(-0.1), 0),
|
||||
"Custom linear curve should return the expected baked value at offset -0.1.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(curve->interpolate_baked(0.1), 0.4),
|
||||
Math::is_equal_approx(curve->interpolate_baked(0.1), (real_t)0.4),
|
||||
"Custom linear curve should return the expected baked value at offset 0.1.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(curve->interpolate_baked(0.4), 0.4),
|
||||
Math::is_equal_approx(curve->interpolate_baked(0.4), (real_t)0.4),
|
||||
"Custom linear curve should return the expected baked value at offset 0.4.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(curve->interpolate_baked(0.7), 0.8),
|
||||
Math::is_equal_approx(curve->interpolate_baked(0.7), (real_t)0.8),
|
||||
"Custom linear curve should return the expected baked value at offset 0.7.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(curve->interpolate_baked(1), 1),
|
||||
@ -210,10 +210,10 @@ TEST_CASE("[Curve] Custom curve with linear tangents") {
|
||||
curve->remove_point(10);
|
||||
ERR_PRINT_ON;
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(curve->interpolate(0.7), 0.8),
|
||||
Math::is_equal_approx(curve->interpolate(0.7), (real_t)0.8),
|
||||
"Custom free curve should return the expected value at offset 0.7 after removing point at invalid index 10.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(curve->interpolate_baked(0.7), 0.8),
|
||||
Math::is_equal_approx(curve->interpolate_baked(0.7), (real_t)0.8),
|
||||
"Custom free curve should return the expected baked value at offset 0.7 after removing point at invalid index 10.");
|
||||
}
|
||||
} // namespace TestCurve
|
||||
|
@ -83,42 +83,42 @@ TEST_CASE("[Expression] Floating-point arithmetic") {
|
||||
expression.parse("-123.456") == OK,
|
||||
"Float identity should parse successfully.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(float(expression.execute()), -123.456),
|
||||
Math::is_equal_approx(double(expression.execute()), -123.456),
|
||||
"Float identity should return the expected result.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
expression.parse("2.0 + 3.0") == OK,
|
||||
"Float addition should parse successfully.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(float(expression.execute()), 5),
|
||||
Math::is_equal_approx(double(expression.execute()), 5),
|
||||
"Float addition should return the expected result.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
expression.parse("3.0 / 10") == OK,
|
||||
"Float / integer division should parse successfully.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(float(expression.execute()), 0.3),
|
||||
Math::is_equal_approx(double(expression.execute()), 0.3),
|
||||
"Float / integer division should return the expected result.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
expression.parse("3 / 10.0") == OK,
|
||||
"Basic integer / float division should parse successfully.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(float(expression.execute()), 0.3),
|
||||
Math::is_equal_approx(double(expression.execute()), 0.3),
|
||||
"Basic integer / float division should return the expected result.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
expression.parse("3.0 / 10.0") == OK,
|
||||
"Float / float division should parse successfully.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(float(expression.execute()), 0.3),
|
||||
Math::is_equal_approx(double(expression.execute()), 0.3),
|
||||
"Float / float division should return the expected result.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
expression.parse("2.5 * (6.0 + 14.25) / 2.0 - 5.12345") == OK,
|
||||
"Float multiplication-addition-subtraction-division should parse successfully.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(float(expression.execute()), 20.18905),
|
||||
Math::is_equal_approx(double(expression.execute()), 20.18905),
|
||||
"Float multiplication-addition-subtraction-division should return the expected result.");
|
||||
}
|
||||
|
||||
@ -129,7 +129,7 @@ TEST_CASE("[Expression] Scientific notation") {
|
||||
expression.parse("2.e5") == OK,
|
||||
"The expression should parse successfully.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(float(expression.execute()), 200'000),
|
||||
Math::is_equal_approx(double(expression.execute()), 200'000),
|
||||
"The expression should return the expected result.");
|
||||
|
||||
// The middle "e" is ignored here.
|
||||
@ -137,14 +137,14 @@ TEST_CASE("[Expression] Scientific notation") {
|
||||
expression.parse("2e5") == OK,
|
||||
"The expression should parse successfully.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(float(expression.execute()), 25),
|
||||
Math::is_equal_approx(double(expression.execute()), 25),
|
||||
"The expression should return the expected result.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
expression.parse("2e.5") == OK,
|
||||
"The expression should parse successfully.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(float(expression.execute()), 2),
|
||||
Math::is_equal_approx(double(expression.execute()), 2),
|
||||
"The expression should return the expected result.");
|
||||
}
|
||||
|
||||
@ -176,14 +176,14 @@ TEST_CASE("[Expression] Built-in functions") {
|
||||
expression.parse("snapped(sin(0.5), 0.01)") == OK,
|
||||
"The expression should parse successfully.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(float(expression.execute()), 0.48),
|
||||
Math::is_equal_approx(double(expression.execute()), 0.48),
|
||||
"`snapped(sin(0.5), 0.01)` should return the expected result.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
expression.parse("pow(2.0, -2500)") == OK,
|
||||
"The expression should parse successfully.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_zero_approx(float(expression.execute())),
|
||||
Math::is_zero_approx(double(expression.execute())),
|
||||
"`pow(2.0, -2500)` should return the expected result (asymptotically zero).");
|
||||
}
|
||||
|
||||
@ -410,7 +410,7 @@ TEST_CASE("[Expression] Unusual expressions") {
|
||||
"The expression should parse successfully.");
|
||||
ERR_PRINT_OFF;
|
||||
CHECK_MESSAGE(
|
||||
Math::is_inf(float(expression.execute())),
|
||||
Math::is_inf(double(expression.execute())),
|
||||
"`-25.4 / 0` should return inf.");
|
||||
ERR_PRINT_ON;
|
||||
|
||||
|
@ -80,7 +80,7 @@ TEST_CASE("[JSON] Parsing single data types") {
|
||||
err_line == 0,
|
||||
"Parsing an integer number as JSON should parse successfully.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(result, 123'456),
|
||||
(int)result == 123'456,
|
||||
"Parsing an integer number as JSON should return the expected value.");
|
||||
|
||||
json.parse("0.123456", result, err_str, err_line);
|
||||
@ -155,7 +155,7 @@ TEST_CASE("[JSON] Parsing objects (dictionaries)") {
|
||||
dictionary["bugs"] == Variant(),
|
||||
"The parsed JSON should contain the expected values.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(Dictionary(dictionary["apples"])["blue"], -20),
|
||||
(int)Dictionary(dictionary["apples"])["blue"] == -20,
|
||||
"The parsed JSON should contain the expected values.");
|
||||
CHECK_MESSAGE(
|
||||
dictionary["empty_object"].hash() == Dictionary().hash(),
|
||||
|
@ -312,19 +312,19 @@ TEST_CASE("[Rect2i] Basic setters") {
|
||||
|
||||
TEST_CASE("[Rect2i] Area getters") {
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(Rect2i(0, 100, 1280, 720).get_area(), 921'600),
|
||||
Rect2i(0, 100, 1280, 720).get_area() == 921'600,
|
||||
"get_area() should return the expected value.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(Rect2i(0, 100, -1280, -720).get_area(), 921'600),
|
||||
Rect2i(0, 100, -1280, -720).get_area() == 921'600,
|
||||
"get_area() should return the expected value.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(Rect2i(0, 100, 1280, -720).get_area(), -921'600),
|
||||
Rect2i(0, 100, 1280, -720).get_area() == -921'600,
|
||||
"get_area() should return the expected value.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_equal_approx(Rect2i(0, 100, -1280, 720).get_area(), -921'600),
|
||||
Rect2i(0, 100, -1280, 720).get_area() == -921'600,
|
||||
"get_area() should return the expected value.");
|
||||
CHECK_MESSAGE(
|
||||
Math::is_zero_approx(Rect2i(0, 100, 0, 720).get_area()),
|
||||
Rect2i(0, 100, 0, 720).get_area() == 0,
|
||||
"get_area() should return the expected value.");
|
||||
|
||||
CHECK_MESSAGE(
|
||||
|
Loading…
Reference in New Issue
Block a user