From 563c0b21524cf7183d0d2e16940eacde253e88d5 Mon Sep 17 00:00:00 2001 From: Aaron Barany Date: Wed, 19 Jun 2024 16:30:31 -0700 Subject: [PATCH] Improved relative epsilon checks. Allow both the absolute and relative epsilon values to be set differently. This allows for more flexibility, especially for very small values. Added missing SIMD implementation for relative equals of dsVector2d. --- modules/Math/include/DeepSea/Math/Core.h | 24 ++++--- modules/Math/include/DeepSea/Math/Vector2.h | 36 ++++++++--- modules/Math/include/DeepSea/Math/Vector3.h | 27 ++++---- modules/Math/include/DeepSea/Math/Vector4.h | 49 ++++++++------- modules/Math/src/Core.c | 6 +- modules/Math/src/Vector2.c | 8 ++- modules/Math/src/Vector3.c | 8 ++- modules/Math/src/Vector4.c | 8 ++- modules/Math/test/CoreTest.cpp | 62 ++++++------------- modules/Math/test/Vector2Test.cpp | 22 ++++--- modules/Math/test/Vector3Test.cpp | 26 +++++--- modules/Math/test/Vector4Test.cpp | 26 +++++--- .../Render/src/Shadows/ShadowCullVolume.c | 2 +- 13 files changed, 168 insertions(+), 136 deletions(-) diff --git a/modules/Math/include/DeepSea/Math/Core.h b/modules/Math/include/DeepSea/Math/Core.h index 44fafab51..5a616d13c 100644 --- a/modules/Math/include/DeepSea/Math/Core.h +++ b/modules/Math/include/DeepSea/Math/Core.h @@ -302,13 +302,17 @@ DS_MATH_EXPORT inline bool dsEpsilonEquald(double x, double y, double epsilon); * * @param x The first value. * @param y The second value. - * @param epsilon The epsilon to compare with. + * @param absoluteEps The absolute epsilon to compare with. + * @param relativeEps The relative epsilon to compare with. This will be scaled based on the values + * being compared. * @return True the values of x and y are within epsilon. */ -DS_MATH_EXPORT inline bool dsRelativeEpsilonEqualf(float x, float y, float epsilon); +DS_MATH_EXPORT inline bool dsRelativeEpsilonEqualf(float x, float y, float absoluteEps, + float relativeEps); /** @copydoc dsEpsilonEqualf() */ -DS_MATH_EXPORT inline bool dsRelativeEpsilonEquald(double x, double y, double epsilon); +DS_MATH_EXPORT inline bool dsRelativeEpsilonEquald(double x, double y, double absoluteEps, + double relativeEps); /** * @brief Checks to see if a value is equal to zero within an epsilon. @@ -379,26 +383,28 @@ DS_MATH_EXPORT inline bool dsEpsilonEquald(double x, double y, double epsilon) return fabs(x - y) <= epsilon; } -DS_MATH_EXPORT inline bool dsRelativeEpsilonEqualf(float x, float y, float epsilon) +DS_MATH_EXPORT inline bool dsRelativeEpsilonEqualf(float x, float y, float absoluteEps, + float relativeEps) { float diff = fabsf(x - y); - if (diff <= epsilon) + if (diff <= absoluteEps) return true; float absX = fabsf(x); float absY = fabsf(y); - return diff <= dsMax(absX, absY)*epsilon; + return diff <= dsMax(absX, absY)*relativeEps; } -DS_MATH_EXPORT inline bool dsRelativeEpsilonEquald(double x, double y, double epsilon) +DS_MATH_EXPORT inline bool dsRelativeEpsilonEquald(double x, double y, double absoluteEps, + double relativeEps) { double diff = fabs(x - y); - if (diff <= epsilon) + if (diff <= absoluteEps) return true; double absX = fabs(x); double absY = fabs(y); - return diff <= dsMax(absX, absY)*epsilon; + return diff <= dsMax(absX, absY)*relativeEps; } DS_MATH_EXPORT inline bool dsEpsilonEqualsZerof(float x, float epsilon) diff --git a/modules/Math/include/DeepSea/Math/Vector2.h b/modules/Math/include/DeepSea/Math/Vector2.h index 747775d94..18250fa62 100644 --- a/modules/Math/include/DeepSea/Math/Vector2.h +++ b/modules/Math/include/DeepSea/Math/Vector2.h @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 Aaron Barany + * Copyright 2016-2024 Aaron Barany * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -234,15 +234,17 @@ DS_MATH_EXPORT inline bool dsVector2d_epsilonEqual(const dsVector2d* a, const ds * @brief Checks to see if two values are equal within a relative epsilon. * @param a The first value. * @param b The second value. - * @param epsilon The epsilon to compare with. + * @param absoluteEps The absolute epsilon to compare with. + * @param relativeEps The relative epsilon to compare with. This will be scaled based on the values + * being compared. * @return True the values of a and b are within epsilon. */ DS_MATH_EXPORT inline bool dsVector2f_relativeEpsilonEqual(const dsVector2f* a, const dsVector2f* b, - float epsilon); + float absoluteEps, float relativeEps); /** @copydoc dsVector2f_epsilonEqual() */ DS_MATH_EXPORT inline bool dsVector2d_relativeEpsilonEqual(const dsVector2d* a, const dsVector2d* b, - double epsilon); + double absoluteEps, double relativeEps); /** @copydoc dsVector2_add() */ DS_MATH_EXPORT inline void dsVector2f_add(dsVector2f* result, const dsVector2f* a, @@ -767,17 +769,31 @@ inline bool dsVector2d_epsilonEqual(const dsVector2d* a, const dsVector2d* b, do #endif } -inline bool dsVector2f_relativeEpsilonEqual(const dsVector2f* a, const dsVector2f* b, float epsilon) +inline bool dsVector2f_relativeEpsilonEqual(const dsVector2f* a, const dsVector2f* b, + float absoluteEps, float relativeEps) { - return dsRelativeEpsilonEqualf(a->values[0], b->values[0], epsilon) && - dsRelativeEpsilonEqualf(a->values[1], b->values[1], epsilon); + return dsRelativeEpsilonEqualf(a->values[0], b->values[0], absoluteEps, relativeEps) && + dsRelativeEpsilonEqualf(a->values[1], b->values[1], absoluteEps, relativeEps); } inline bool dsVector2d_relativeEpsilonEqual(const dsVector2d* a, const dsVector2d* b, - double epsilon) + double absoluteEps, double relativeEps) { - return dsRelativeEpsilonEquald(a->values[0], b->values[0], epsilon) && - dsRelativeEpsilonEquald(a->values[1], b->values[1], epsilon); +#if DS_SIMD_ALWAYS_DOUBLE2 + dsSIMD2d diff = dsSIMD2d_abs(dsSIMD2d_sub(a->simd, b->simd)); + + dsSIMD2d epsEqual = dsSIMD2d_cmple(diff, dsSIMD2d_set1(absoluteEps)); + dsSIMD2d relativeEqual = dsSIMD2d_cmple(diff, + dsSIMD2d_mul(dsSIMD2d_max(dsSIMD2d_abs(a->simd), dsSIMD2d_abs(b->simd)), + dsSIMD2d_set1(relativeEps))); + + dsVector2l result; + result.simd = dsSIMD2db_or(epsEqual, relativeEqual); + return result.x && result.y; +#else + return dsRelativeEpsilonEquald(a->values[0], b->values[0], absoluteEps, relativeEps) && + dsRelativeEpsilonEquald(a->values[1], b->values[1], absoluteEps, relativeEps); +#endif } #ifdef __cplusplus diff --git a/modules/Math/include/DeepSea/Math/Vector3.h b/modules/Math/include/DeepSea/Math/Vector3.h index f5fcca74f..9d634dc43 100644 --- a/modules/Math/include/DeepSea/Math/Vector3.h +++ b/modules/Math/include/DeepSea/Math/Vector3.h @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 Aaron Barany + * Copyright 2016-2024 Aaron Barany * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -259,15 +259,17 @@ DS_MATH_EXPORT inline bool dsVector3d_epsilonEqual(const dsVector3d* a, const ds * @brief Checks to see if two values are equal within a relative epsilon. * @param a The first value. * @param b The second value. - * @param epsilon The epsilon to compare with. + * @param absoluteEps The absolute epsilon to compare with. + * @param relativeEps The relative epsilon to compare with. This will be scaled based on the values + * being compared. * @return True the values of a and b are within epsilon. */ DS_MATH_EXPORT inline bool dsVector3f_relativeEpsilonEqual(const dsVector3f* a, const dsVector3f* b, - float epsilon); + float absoluteEps, float relativeEps); /** @copydoc dsVector3f_relativeEpsilonEqual() */ DS_MATH_EXPORT inline bool dsVector3d_relativeEpsilonEqual(const dsVector3d* a, const dsVector3d* b, - double epsilon); + double absoluteEps, double relativeEps); /** @copydoc dsVector3_add() */ DS_MATH_EXPORT inline void dsVector3f_add(dsVector3f* result, const dsVector3f* a, @@ -785,19 +787,20 @@ inline bool dsVector3d_epsilonEqual(const dsVector3d* a, const dsVector3d* b, do dsEpsilonEquald(a->values[2], b->values[2], epsilon); } -inline bool dsVector3f_relativeEpsilonEqual(const dsVector3f* a, const dsVector3f* b, float epsilon) +inline bool dsVector3f_relativeEpsilonEqual(const dsVector3f* a, const dsVector3f* b, + float absoluteEps, float relativeEps) { - return dsRelativeEpsilonEqualf(a->values[0], b->values[0], epsilon) && - dsRelativeEpsilonEqualf(a->values[1], b->values[1], epsilon) && - dsRelativeEpsilonEqualf(a->values[2], b->values[2], epsilon); + return dsRelativeEpsilonEqualf(a->values[0], b->values[0], absoluteEps, relativeEps) && + dsRelativeEpsilonEqualf(a->values[1], b->values[1], absoluteEps, relativeEps) && + dsRelativeEpsilonEqualf(a->values[2], b->values[2], absoluteEps, relativeEps); } inline bool dsVector3d_relativeEpsilonEqual(const dsVector3d* a, const dsVector3d* b, - double epsilon) + double absoluteEps, double relativeEps) { - return dsRelativeEpsilonEquald(a->values[0], b->values[0], epsilon) && - dsRelativeEpsilonEquald(a->values[1], b->values[1], epsilon) && - dsRelativeEpsilonEquald(a->values[2], b->values[2], epsilon); + return dsRelativeEpsilonEquald(a->values[0], b->values[0], absoluteEps, relativeEps) && + dsRelativeEpsilonEquald(a->values[1], b->values[1], absoluteEps, relativeEps) && + dsRelativeEpsilonEquald(a->values[2], b->values[2], absoluteEps, relativeEps); } #ifdef __cplusplus diff --git a/modules/Math/include/DeepSea/Math/Vector4.h b/modules/Math/include/DeepSea/Math/Vector4.h index 965868118..0ee2ad2ce 100644 --- a/modules/Math/include/DeepSea/Math/Vector4.h +++ b/modules/Math/include/DeepSea/Math/Vector4.h @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 Aaron Barany + * Copyright 2016-2024 Aaron Barany * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -256,15 +256,17 @@ DS_MATH_EXPORT inline bool dsVector4d_epsilonEqual(const dsVector4d* a, const ds * @brief Checks to see if two values are equal within a relative epsilon. * @param a The first value. * @param b The second value. - * @param epsilon The epsilon to compare with. + * @param absoluteEps The absolute epsilon to compare with. + * @param relativeEps The relative epsilon to compare with. This will be scaled based on the values + * being compared. * @return True the values of a and b are within epsilon. */ DS_MATH_EXPORT inline bool dsVector4f_relativeEpsilonEqual(const dsVector4f* a, const dsVector4f* b, - float epsilon); + float absoluteEps, float relativeEps); /** @copydoc dsVector4f_epsilonEqual() */ DS_MATH_EXPORT inline bool dsVector4d_relativeEpsilonEqual(const dsVector4d* a, const dsVector4d* b, - double epsilon); + double absoluteEps, double relativeEps); /** @copydoc dsVector4_add() */ DS_MATH_EXPORT inline void dsVector4f_add(dsVector4f* result, const dsVector4f* a, @@ -883,54 +885,57 @@ DS_MATH_EXPORT inline bool dsVector4d_epsilonEqual(const dsVector4d* a, const ds } DS_MATH_EXPORT inline bool dsVector4f_relativeEpsilonEqual(const dsVector4f* a, const dsVector4f* b, - float epsilon) + float absoluteEps, float relativeEps) { #if DS_SIMD_ALWAYS_FLOAT4 dsSIMD4f diff = dsSIMD4f_abs(dsSIMD4f_sub(a->simd, b->simd)); - dsSIMD4f eps4 = dsSIMD4f_set1(epsilon); - dsSIMD4fb epsEqual = dsSIMD4f_cmple(diff, eps4); + dsSIMD4fb epsEqual = dsSIMD4f_cmple(diff, dsSIMD4f_set1(absoluteEps)); dsSIMD4fb relativeEqual = dsSIMD4f_cmple(diff, - dsSIMD4f_mul(dsSIMD4f_max(dsSIMD4f_abs(a->simd), dsSIMD4f_abs(b->simd)), eps4)); + dsSIMD4f_mul(dsSIMD4f_max(dsSIMD4f_abs(a->simd), dsSIMD4f_abs(b->simd)), + dsSIMD4f_set1(relativeEps))); dsVector4i result; result.simd = dsSIMD4fb_or(epsEqual, relativeEqual); return result.x && result.y && result.z && result.w; #else - return dsRelativeEpsilonEqualf(a->values[0], b->values[0], epsilon) && - dsRelativeEpsilonEqualf(a->values[1], b->values[1], epsilon) && - dsRelativeEpsilonEqualf(a->values[2], b->values[2], epsilon) && - dsRelativeEpsilonEqualf(a->values[3], b->values[3], epsilon); + return dsRelativeEpsilonEqualf(a->values[0], b->values[0], absoluteEps, relativeEps) && + dsRelativeEpsilonEqualf(a->values[1], b->values[1], absoluteEps, relativeEps) && + dsRelativeEpsilonEqualf(a->values[2], b->values[2], absoluteEps, relativeEps) && + dsRelativeEpsilonEqualf(a->values[3], b->values[3], absoluteEps, relativeEps); #endif } DS_MATH_EXPORT inline bool dsVector4d_relativeEpsilonEqual(const dsVector4d* a, const dsVector4d* b, - double epsilon) + double absoluteEps, double relativeEps) { #if DS_SIMD_ALWAYS_DOUBLE2 dsVector4d diff; diff.simd2[0] = dsSIMD2d_abs(dsSIMD2d_sub(a->simd2[0], b->simd2[0])); diff.simd2[1] = dsSIMD2d_abs(dsSIMD2d_sub(a->simd2[1], b->simd2[1])); - dsSIMD2d eps2 = dsSIMD2d_set1(epsilon); + dsSIMD2d absoluteEps2 = dsSIMD2d_set1(absoluteEps); + dsSIMD2d relativeEps2 = dsSIMD2d_set1(relativeEps); dsVector4l epsEqual; - epsEqual.simd2[0] = dsSIMD2d_cmple(diff.simd2[0], eps2); - epsEqual.simd2[1] = dsSIMD2d_cmple(diff.simd2[1], eps2); + epsEqual.simd2[0] = dsSIMD2d_cmple(diff.simd2[0], absoluteEps2); + epsEqual.simd2[1] = dsSIMD2d_cmple(diff.simd2[1], absoluteEps2); dsVector4l relativeEqual; relativeEqual.simd2[0] = dsSIMD2d_cmple(diff.simd2[0], - dsSIMD2d_mul(dsSIMD2d_max(dsSIMD2d_abs(a->simd2[0]), dsSIMD2d_abs(b->simd2[0])), eps2)); + dsSIMD2d_mul(dsSIMD2d_max(dsSIMD2d_abs(a->simd2[0]), dsSIMD2d_abs(b->simd2[0])), + relativeEps2)); relativeEqual.simd2[1] = dsSIMD2d_cmple(diff.simd2[1], - dsSIMD2d_mul(dsSIMD2d_max(dsSIMD2d_abs(a->simd2[1]), dsSIMD2d_abs(b->simd2[1])), eps2)); + dsSIMD2d_mul(dsSIMD2d_max(dsSIMD2d_abs(a->simd2[1]), dsSIMD2d_abs(b->simd2[1])), + relativeEps2)); dsVector4l result; result.simd2[0] = dsSIMD2db_or(epsEqual.simd2[0], relativeEqual.simd2[0]); result.simd2[1] = dsSIMD2db_or(epsEqual.simd2[1], relativeEqual.simd2[1]); return result.x && result.y && result.z && result.w; #else - return dsRelativeEpsilonEquald(a->values[0], b->values[0], epsilon) && - dsRelativeEpsilonEquald(a->values[1], b->values[1], epsilon) && - dsRelativeEpsilonEquald(a->values[2], b->values[2], epsilon) && - dsRelativeEpsilonEquald(a->values[3], b->values[3], epsilon); + return dsRelativeEpsilonEquald(a->values[0], b->values[0], absoluteEps, relativeEps) && + dsRelativeEpsilonEquald(a->values[1], b->values[1], absoluteEps, relativeEps) && + dsRelativeEpsilonEquald(a->values[2], b->values[2], absoluteEps, relativeEps) && + dsRelativeEpsilonEquald(a->values[3], b->values[3], absoluteEps, relativeEps); #endif } diff --git a/modules/Math/src/Core.c b/modules/Math/src/Core.c index 8968566a5..409cacd24 100644 --- a/modules/Math/src/Core.c +++ b/modules/Math/src/Core.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2021 Aaron Barany + * Copyright 2016-2024 Aaron Barany * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,8 +29,8 @@ double dsWrapd(double x, double min, double max); bool dsEpsilonEqualf(float x, float y, float epsilon); bool dsEpsilonEquald(double x, double y, double epsilon); -bool dsRelativeEpsilonEqualf(float x, float y, float epsilon); -bool dsRelativeEpsilonEquald(double x, double y, double epsilon); +bool dsRelativeEpsilonEqualf(float x, float y, float absoluteEps, float relativeEps); +bool dsRelativeEpsilonEquald(double x, double y, double absoluteEps, double relativeEps); bool dsEpsilonEqualsZerof(float x, float epsilon); bool dsEpsilonEqualsZerod(double x, double epsilon); diff --git a/modules/Math/src/Vector2.c b/modules/Math/src/Vector2.c index 9ed0784bb..a7c70df4c 100644 --- a/modules/Math/src/Vector2.c +++ b/modules/Math/src/Vector2.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 Aaron Barany + * Copyright 2016-2024 Aaron Barany * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -87,5 +87,7 @@ void dsVector2d_normalize(dsVector2d* result, const dsVector2d* a); bool dsVector2f_epsilonEqual(const dsVector2f* a, const dsVector2f* b, float epsilon); bool dsVector2d_epsilonEqual(const dsVector2d* a, const dsVector2d* b, double epsilon); -bool dsVector2f_relativeEpsilonEqual(const dsVector2f* a, const dsVector2f* b, float epsilon); -bool dsVector2d_relativeEpsilonEqual(const dsVector2d* a, const dsVector2d* b, double epsilon); +bool dsVector2f_relativeEpsilonEqual(const dsVector2f* a, const dsVector2f* b, float absoluteEps, + float relativeEps); +bool dsVector2d_relativeEpsilonEqual(const dsVector2d* a, const dsVector2d* b, double absoluteEps, + double relativeEps); diff --git a/modules/Math/src/Vector3.c b/modules/Math/src/Vector3.c index 6482b6422..603af43a8 100644 --- a/modules/Math/src/Vector3.c +++ b/modules/Math/src/Vector3.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 Aaron Barany + * Copyright 2016-2024 Aaron Barany * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -92,5 +92,7 @@ void dsVector3d_normalize(dsVector3d* result, const dsVector3d* a); bool dsVector3f_epsilonEqual(const dsVector3f* a, const dsVector3f* b, float epsilon); bool dsVector3d_epsilonEqual(const dsVector3d* a, const dsVector3d* b, double epsilon); -bool dsVector3f_relativeEpsilonEqual(const dsVector3f* a, const dsVector3f* b, float epsilon); -bool dsVector3d_relativeEpsilonEqual(const dsVector3d* a, const dsVector3d* b, double epsilon); +bool dsVector3f_relativeEpsilonEqual(const dsVector3f* a, const dsVector3f* b, float absoluteEps, + float relativeEps); +bool dsVector3d_relativeEpsilonEqual(const dsVector3d* a, const dsVector3d* b, double absoluteEps, + double relativeEps); diff --git a/modules/Math/src/Vector4.c b/modules/Math/src/Vector4.c index b18fc9d73..3c781533e 100644 --- a/modules/Math/src/Vector4.c +++ b/modules/Math/src/Vector4.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 Aaron Barany + * Copyright 2016-2024 Aaron Barany * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -87,5 +87,7 @@ void dsVector4d_normalize(dsVector4d* result, const dsVector4d* a); bool dsVector4f_epsilonEqual(const dsVector4f* a, const dsVector4f* b, float epsilon); bool dsVector4d_epsilonEqual(const dsVector4d* a, const dsVector4d* b, double epsilon); -bool dsVector4f_relativeEpsilonEqual(const dsVector4f* a, const dsVector4f* b, float epsilon); -bool dsVector4d_relativeEpsilonEqual(const dsVector4d* a, const dsVector4d* b, double epsilon); +bool dsVector4f_relativeEpsilonEqual(const dsVector4f* a, const dsVector4f* b, float absoluteEps, + float relativeEps); +bool dsVector4d_relativeEpsilonEqual(const dsVector4d* a, const dsVector4d* b, double absoluteEps, + double relativeEps); diff --git a/modules/Math/test/CoreTest.cpp b/modules/Math/test/CoreTest.cpp index cebe8fc20..b7a4adcf4 100644 --- a/modules/Math/test/CoreTest.cpp +++ b/modules/Math/test/CoreTest.cpp @@ -150,58 +150,36 @@ TEST(Core, EpsilonEquald) TEST(Core, RelativeEpsilonEqualf) { - EXPECT_TRUE(dsRelativeEpsilonEqualf(0.0f, 0.0f, 1e-3f)); + EXPECT_TRUE(dsRelativeEpsilonEqualf(0.0f, 0.0f, 1e-3f, 1e-3f)); - EXPECT_TRUE(dsRelativeEpsilonEqualf(2.345f, 2.3456f, 1e-3f)); - EXPECT_TRUE(dsRelativeEpsilonEqualf(2.345f, 2.3448f, 1e-3f)); - EXPECT_FALSE(dsRelativeEpsilonEqualf(2.345f, 2.349f, 1e-3f)); - EXPECT_FALSE(dsRelativeEpsilonEqualf(2.345f, 2.341f, 1e-3f)); + EXPECT_FALSE(dsRelativeEpsilonEqualf(23.45f, 23.456f, 1e-3f, 1e-4f)); + EXPECT_TRUE(dsRelativeEpsilonEqualf(23.45f, 23.456f, 1e-2f, 1e-4f)); + EXPECT_TRUE(dsRelativeEpsilonEqualf(23.45f, 23.456f, 1e-3f, 1e-3f)); - EXPECT_TRUE(dsRelativeEpsilonEqualf(23.45f, 23.456f, 1e-3f)); - EXPECT_TRUE(dsRelativeEpsilonEqualf(23.45f, 23.448f, 1e-3f)); - EXPECT_FALSE(dsRelativeEpsilonEqualf(23.45f, 23.49f, 1e-3f)); - EXPECT_FALSE(dsRelativeEpsilonEqualf(23.45f, 23.41f, 1e-3f)); + EXPECT_FALSE(dsRelativeEpsilonEqualf(-23.45f, -23.456f, 1e-3f, 1e-4f)); + EXPECT_TRUE(dsRelativeEpsilonEqualf(-23.45f, -23.456f, 1e-2f, 1e-4f)); + EXPECT_TRUE(dsRelativeEpsilonEqualf(-23.45f, -23.456f, 1e-3f, 1e-3f)); - EXPECT_TRUE(dsRelativeEpsilonEqualf(-2.345f, -2.3456f, 1e-3f)); - EXPECT_TRUE(dsRelativeEpsilonEqualf(-2.345f, -2.3448f, 1e-3f)); - EXPECT_FALSE(dsRelativeEpsilonEqualf(-2.345f, -2.349f, 1e-3f)); - EXPECT_FALSE(dsRelativeEpsilonEqualf(-2.345f, -2.341f, 1e-3f)); - - EXPECT_TRUE(dsRelativeEpsilonEqualf(-23.45f, -23.456f, 1e-3f)); - EXPECT_TRUE(dsRelativeEpsilonEqualf(-23.45f, -23.448f, 1e-3f)); - EXPECT_FALSE(dsRelativeEpsilonEqualf(-23.45f, -23.49f, 1e-3f)); - EXPECT_FALSE(dsRelativeEpsilonEqualf(-23.45f, -23.41f, 1e-3f)); - - EXPECT_FALSE(dsRelativeEpsilonEqualf(-2.345f, 2.345f, 1e-3f)); - EXPECT_FALSE(dsRelativeEpsilonEqualf(-23.45f, 23.45f, 1e-3f)); + EXPECT_FALSE(dsRelativeEpsilonEqualf(-23.45f, 23.456f, 1e-3f, 1e-4f)); + EXPECT_FALSE(dsRelativeEpsilonEqualf(-23.45f, 23.456f, 1e-2f, 1e-4f)); + EXPECT_FALSE(dsRelativeEpsilonEqualf(-23.45f, 23.456f, 1e-3f, 1e-3f)); } TEST(Core, RelativeEpsilonEquald) { - EXPECT_TRUE(dsRelativeEpsilonEquald(0.0f, 0.0f, 1e-3f)); - - EXPECT_TRUE(dsRelativeEpsilonEquald(2.345, 2.3456, 1e-3)); - EXPECT_TRUE(dsRelativeEpsilonEquald(2.345, 2.3448, 1e-3)); - EXPECT_FALSE(dsRelativeEpsilonEquald(2.345, 2.349, 1e-3)); - EXPECT_FALSE(dsRelativeEpsilonEquald(2.345, 2.341, 1e-3)); - - EXPECT_TRUE(dsRelativeEpsilonEquald(23.45, 23.456, 1e-3)); - EXPECT_TRUE(dsRelativeEpsilonEquald(23.45, 23.448, 1e-3)); - EXPECT_FALSE(dsRelativeEpsilonEquald(23.45, 23.49, 1e-3)); - EXPECT_FALSE(dsRelativeEpsilonEquald(23.45, 23.41, 1e-3)); + EXPECT_TRUE(dsRelativeEpsilonEquald(0.0, 0.0, 1e-3, 1e-3)); - EXPECT_TRUE(dsRelativeEpsilonEquald(-2.345, -2.3456, 1e-3)); - EXPECT_TRUE(dsRelativeEpsilonEquald(-2.345, -2.3448, 1e-3)); - EXPECT_FALSE(dsRelativeEpsilonEquald(-2.345, -2.349, 1e-3)); - EXPECT_FALSE(dsRelativeEpsilonEquald(-2.345, -2.341, 1e-3)); + EXPECT_FALSE(dsRelativeEpsilonEquald(23.45, 23.456, 1e-3, 1e-4)); + EXPECT_TRUE(dsRelativeEpsilonEquald(23.45, 23.456, 1e-2, 1e-4)); + EXPECT_TRUE(dsRelativeEpsilonEquald(23.45, 23.456, 1e-3, 1e-3)); - EXPECT_TRUE(dsRelativeEpsilonEquald(-23.45, -23.456, 1e-3)); - EXPECT_TRUE(dsRelativeEpsilonEquald(-23.45, -23.448, 1e-3)); - EXPECT_FALSE(dsRelativeEpsilonEquald(-23.45, -23.49, 1e-3)); - EXPECT_FALSE(dsRelativeEpsilonEquald(-23.45, -23.41, 1e-3)); + EXPECT_FALSE(dsRelativeEpsilonEquald(-23.45, -23.456, 1e-3, 1e-4)); + EXPECT_TRUE(dsRelativeEpsilonEquald(-23.45, -23.456, 1e-2, 1e-4)); + EXPECT_TRUE(dsRelativeEpsilonEquald(-23.45, -23.456, 1e-3, 1e-3)); - EXPECT_FALSE(dsRelativeEpsilonEquald(-2.345, 2.345, 1e-3)); - EXPECT_FALSE(dsRelativeEpsilonEquald(-23.45, 23.45, 1e-3)); + EXPECT_FALSE(dsRelativeEpsilonEquald(-23.45, 23.456, 1e-3, 1e-4)); + EXPECT_FALSE(dsRelativeEpsilonEquald(-23.45, 23.456, 1e-2, 1e-4)); + EXPECT_FALSE(dsRelativeEpsilonEquald(-23.45, 23.456, 1e-3, 1e-3)); } TEST(Core, EpsilonEqualsZerof) diff --git a/modules/Math/test/Vector2Test.cpp b/modules/Math/test/Vector2Test.cpp index aa32102ec..95b001ff1 100644 --- a/modules/Math/test/Vector2Test.cpp +++ b/modules/Math/test/Vector2Test.cpp @@ -126,14 +126,16 @@ inline bool dsVector2_epsilonEqual(const dsVector2d* a, const dsVector2d* b, dou return dsVector2d_epsilonEqual(a, b, epsilon); } -inline bool dsVector2_relativeEpsilonEqual(const dsVector2f* a, const dsVector2f* b, float epsilon) +inline bool dsVector2_relativeEpsilonEqual(const dsVector2f* a, const dsVector2f* b, + float absoluteEps, float relativeEps) { - return dsVector2f_relativeEpsilonEqual(a, b, epsilon); + return dsVector2f_relativeEpsilonEqual(a, b, absoluteEps, relativeEps); } -inline bool dsVector2_relativeEpsilonEqual(const dsVector2d* a, const dsVector2d* b, double epsilon) +inline bool dsVector2_relativeEpsilonEqual(const dsVector2d* a, const dsVector2d* b, + double absoluteEps, double relativeEps) { - return dsVector2d_relativeEpsilonEqual(a, b, epsilon); + return dsVector2d_relativeEpsilonEqual(a, b, absoluteEps, relativeEps); } TYPED_TEST(Vector2Test, Initialize) @@ -335,16 +337,20 @@ TYPED_TEST(Vector2FloatTest, EpsilonEqual) TYPED_TEST(Vector2FloatTest, RelativeEpsilonEqual) { typedef typename Vector2TypeSelector::Type Vector2Type; - TypeParam epsilon = (TypeParam)1e-3; + TypeParam smallEpsilon = (TypeParam)1e-5; + TypeParam mediumEpsilon = (TypeParam)1e-4; + TypeParam largeEpsilon = (TypeParam)1.001e-3; Vector2Type a = {{(TypeParam)-23.0, (TypeParam)45.0}}; Vector2Type b = {{(TypeParam)-23.001, (TypeParam)45.001}}; Vector2Type c = {{(TypeParam)-23.1, (TypeParam)45.0}}; Vector2Type d = {{(TypeParam)-23.0, (TypeParam)45.1}}; - EXPECT_TRUE(dsVector2_relativeEpsilonEqual(&a, &b, epsilon)); - EXPECT_FALSE(dsVector2_relativeEpsilonEqual(&a, &c, epsilon)); - EXPECT_FALSE(dsVector2_relativeEpsilonEqual(&a, &d, epsilon)); + EXPECT_FALSE(dsVector2_relativeEpsilonEqual(&a, &b, smallEpsilon, smallEpsilon)); + EXPECT_TRUE(dsVector2_relativeEpsilonEqual(&a, &b, largeEpsilon, smallEpsilon)); + EXPECT_TRUE(dsVector2_relativeEpsilonEqual(&a, &b, smallEpsilon, mediumEpsilon)); + EXPECT_FALSE(dsVector2_relativeEpsilonEqual(&a, &c, largeEpsilon, largeEpsilon)); + EXPECT_FALSE(dsVector2_relativeEpsilonEqual(&a, &d, largeEpsilon, largeEpsilon)); } TEST(Vector2, ConvertFloatToDouble) diff --git a/modules/Math/test/Vector3Test.cpp b/modules/Math/test/Vector3Test.cpp index 524ede71a..255ea3599 100644 --- a/modules/Math/test/Vector3Test.cpp +++ b/modules/Math/test/Vector3Test.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 Aaron Barany + * Copyright 2016-2024 Aaron Barany * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -126,14 +126,16 @@ inline bool dsVector3_epsilonEqual(const dsVector3d* a, const dsVector3d* b, dou return dsVector3d_epsilonEqual(a, b, epsilon); } -inline bool dsVector3_relativeEpsilonEqual(const dsVector3f* a, const dsVector3f* b, float epsilon) +inline bool dsVector3_relativeEpsilonEqual(const dsVector3f* a, const dsVector3f* b, + float absoluteEps, float relativeEps) { - return dsVector3f_relativeEpsilonEqual(a, b, epsilon); + return dsVector3f_relativeEpsilonEqual(a, b, absoluteEps, relativeEps); } -inline bool dsVector3_relativeEpsilonEqual(const dsVector3d* a, const dsVector3d* b, double epsilon) +inline bool dsVector3_relativeEpsilonEqual(const dsVector3d* a, const dsVector3d* b, + double absoluteEps, double relativeEps) { - return dsVector3d_relativeEpsilonEqual(a, b, epsilon); + return dsVector3d_relativeEpsilonEqual(a, b, absoluteEps, relativeEps); } TYPED_TEST(Vector3Test, Initialize) @@ -371,7 +373,9 @@ TYPED_TEST(Vector3FloatTest, EpsilonEqual) TYPED_TEST(Vector3FloatTest, RelativeEpsilonEqual) { typedef typename Vector3TypeSelector::Type Vector3Type; - TypeParam epsilon = (TypeParam)1e-3; + TypeParam smallEpsilon = (TypeParam)1e-5; + TypeParam mediumEpsilon = (TypeParam)1e-4; + TypeParam largeEpsilon = (TypeParam)1.001e-3; Vector3Type a = {{(TypeParam)-23.0, (TypeParam)45.0, (TypeParam)-67.0}}; Vector3Type b = {{(TypeParam)-23.001, (TypeParam)45.001, (TypeParam)-67.001}}; @@ -379,10 +383,12 @@ TYPED_TEST(Vector3FloatTest, RelativeEpsilonEqual) Vector3Type d = {{(TypeParam)-23.0, (TypeParam)45.1, (TypeParam)-67.0}}; Vector3Type e = {{(TypeParam)-23.0, (TypeParam)45.0, (TypeParam)-67.1}}; - EXPECT_TRUE(dsVector3_relativeEpsilonEqual(&a, &b, epsilon)); - EXPECT_FALSE(dsVector3_relativeEpsilonEqual(&a, &c, epsilon)); - EXPECT_FALSE(dsVector3_relativeEpsilonEqual(&a, &d, epsilon)); - EXPECT_FALSE(dsVector3_relativeEpsilonEqual(&a, &e, epsilon)); + EXPECT_FALSE(dsVector3_relativeEpsilonEqual(&a, &b, smallEpsilon, smallEpsilon)); + EXPECT_TRUE(dsVector3_relativeEpsilonEqual(&a, &b, largeEpsilon, smallEpsilon)); + EXPECT_TRUE(dsVector3_relativeEpsilonEqual(&a, &b, smallEpsilon, mediumEpsilon)); + EXPECT_FALSE(dsVector3_relativeEpsilonEqual(&a, &c, largeEpsilon, largeEpsilon)); + EXPECT_FALSE(dsVector3_relativeEpsilonEqual(&a, &d, largeEpsilon, largeEpsilon)); + EXPECT_FALSE(dsVector3_relativeEpsilonEqual(&a, &e, largeEpsilon, largeEpsilon)); } TEST(Vector3, ConvertFloatToDouble) diff --git a/modules/Math/test/Vector4Test.cpp b/modules/Math/test/Vector4Test.cpp index 1107faf0e..f245f6fa2 100644 --- a/modules/Math/test/Vector4Test.cpp +++ b/modules/Math/test/Vector4Test.cpp @@ -126,14 +126,16 @@ inline bool dsVector4_epsilonEqual(const dsVector4d* a, const dsVector4d* b, dou return dsVector4d_epsilonEqual(a, b, epsilon); } -inline bool dsVector4_relativeEpsilonEqual(const dsVector4f* a, const dsVector4f* b, float epsilon) +inline bool dsVector4_relativeEpsilonEqual(const dsVector4f* a, const dsVector4f* b, + float absoluteEps, float relativeEps) { - return dsVector4f_relativeEpsilonEqual(a, b, epsilon); + return dsVector4f_relativeEpsilonEqual(a, b, absoluteEps, relativeEps); } -inline bool dsVector4_relativeEpsilonEqual(const dsVector4d* a, const dsVector4d* b, double epsilon) +inline bool dsVector4_relativeEpsilonEqual(const dsVector4d* a, const dsVector4d* b, + double absoluteEps, double relativeEps) { - return dsVector4d_relativeEpsilonEqual(a, b, epsilon); + return dsVector4d_relativeEpsilonEqual(a, b, absoluteEps, relativeEps); } TYPED_TEST(Vector4Test, Initialize) @@ -485,7 +487,9 @@ TYPED_TEST(Vector4FloatTest, EpsilonEqual) TYPED_TEST(Vector4FloatTest, RelativeEpsilonEqual) { typedef typename Vector4TypeSelector::Type Vector4Type; - TypeParam epsilon = (TypeParam)1e-3; + TypeParam smallEpsilon = (TypeParam)1e-5; + TypeParam mediumEpsilon = (TypeParam)1e-4; + TypeParam largeEpsilon = (TypeParam)1.001e-3; Vector4Type a = {{(TypeParam)-23.0, (TypeParam)45.0, (TypeParam)-67.0, (TypeParam)89.0}}; Vector4Type b = {{(TypeParam)-23.001, (TypeParam)45.001, (TypeParam)-67.001, @@ -495,11 +499,13 @@ TYPED_TEST(Vector4FloatTest, RelativeEpsilonEqual) Vector4Type e = {{(TypeParam)-23.0, (TypeParam)45.0, (TypeParam)-67.1, (TypeParam)89.0}}; Vector4Type f = {{(TypeParam)-23.0, (TypeParam)45.0, (TypeParam)-67.0, (TypeParam)89.1}}; - EXPECT_TRUE(dsVector4_relativeEpsilonEqual(&a, &b, epsilon)); - EXPECT_FALSE(dsVector4_relativeEpsilonEqual(&a, &c, epsilon)); - EXPECT_FALSE(dsVector4_relativeEpsilonEqual(&a, &d, epsilon)); - EXPECT_FALSE(dsVector4_relativeEpsilonEqual(&a, &e, epsilon)); - EXPECT_FALSE(dsVector4_relativeEpsilonEqual(&a, &f, epsilon)); + EXPECT_FALSE(dsVector4_relativeEpsilonEqual(&a, &b, smallEpsilon, smallEpsilon)); + EXPECT_TRUE(dsVector4_relativeEpsilonEqual(&a, &b, largeEpsilon, smallEpsilon)); + EXPECT_TRUE(dsVector4_relativeEpsilonEqual(&a, &b, smallEpsilon, mediumEpsilon)); + EXPECT_FALSE(dsVector4_relativeEpsilonEqual(&a, &c, largeEpsilon, largeEpsilon)); + EXPECT_FALSE(dsVector4_relativeEpsilonEqual(&a, &d, largeEpsilon, largeEpsilon)); + EXPECT_FALSE(dsVector4_relativeEpsilonEqual(&a, &e, largeEpsilon, largeEpsilon)); + EXPECT_FALSE(dsVector4_relativeEpsilonEqual(&a, &f, largeEpsilon, largeEpsilon)); } TEST(Vector4Test, ConvertFloatToDouble) diff --git a/modules/Render/Render/src/Shadows/ShadowCullVolume.c b/modules/Render/Render/src/Shadows/ShadowCullVolume.c index 57d503d16..f7e245aec 100644 --- a/modules/Render/Render/src/Shadows/ShadowCullVolume.c +++ b/modules/Render/Render/src/Shadows/ShadowCullVolume.c @@ -95,7 +95,7 @@ static void addCorner(dsShadowCullVolume* volume, dsVector3d* cornerPoints, dsShadowCullCorner* corner = volume->corners + i; if ((corner->planes & planes) == planes) return; - else if (dsVector3d_relativeEpsilonEqual(cornerPoints + i, point, epsilon)) + else if (dsVector3d_relativeEpsilonEqual(cornerPoints + i, point, epsilon, epsilon)) { corner->planes |= planes; return;