2
0
Эх сурвалжийг харах

Merge pull request #48882 from aaronfranke/approx-use-double

Make is_equal_approx have explicit float and double versions
Rémi Verschelde 4 жил өмнө
parent
commit
342f3efc7e

+ 1 - 1
core/math/basis.cpp

@@ -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

+ 30 - 4
core/math/math_funcs.h

@@ -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;
 	}
 

+ 1 - 1
core/math/quat.cpp

@@ -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 {

+ 1 - 1
core/math/vector2.cpp

@@ -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 {

+ 1 - 1
core/math/vector3.h

@@ -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 {

+ 1 - 1
editor/plugins/sprite_frames_editor_plugin.cpp

@@ -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);
 		}
 	}

+ 1 - 1
servers/text_server.cpp

@@ -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;

+ 3 - 3
tests/test_color.h

@@ -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.");
 }
 

+ 14 - 14
tests/test_curve.h

@@ -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

+ 12 - 12
tests/test_expression.h

@@ -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;
 

+ 2 - 2
tests/test_json.h

@@ -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(),

+ 5 - 5
tests/test_rect2.h

@@ -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(