Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: never compare equality of floating numbers #157

Merged
merged 5 commits into from
Sep 17, 2024

Conversation

brmassa
Copy link
Contributor

@brmassa brmassa commented Sep 16, 2024

single and double floats use an especial arithmetic that uses a trade-off of being super big/small, but not very precise.

Eventually, 100f - 10f might result in 90.000000001 instead of pure 90f, so when comparing if 2 floats are the same, we need actually to check if they are close enough. Doing the pure comparison might result in weird behaviors.

  • decide a max difference that will still be considered the same numbers (the code uses 0.0001f)
  • create a threshold number (Application.FloatEqualThreshold ?)
  • convert all float number tests to use this constant (generally, get the absolute difference and check if is smaller)

@@ -48,7 +49,7 @@ public unsafe bool ConfigureContactManifold<TManifold>(int workerIndex, Collidab
var b = CollidableMaterials[pair.B];
pairMaterial.FrictionCoefficient = a.FrictionCoefficient * b.FrictionCoefficient;
pairMaterial.MaximumRecoveryVelocity = (float)MathD.Max(a.MaximumRecoveryVelocity, b.MaximumRecoveryVelocity);
pairMaterial.SpringSettings = pairMaterial.MaximumRecoveryVelocity == a.MaximumRecoveryVelocity ? a.SpringSettings : b.SpringSettings;
pairMaterial.SpringSettings = Math.Abs(pairMaterial.MaximumRecoveryVelocity - a.MaximumRecoveryVelocity) < Application.FloatEqualThreshold ? a.SpringSettings : b.SpringSettings;
Copy link
Contributor

@michaelsakharov michaelsakharov Sep 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I imagine in the case of BepuPhysics this wouldn't be ideal due to possible performance costs it would come with.
This is very frequently called, and it wouldn't matter much if there are errors due to floating precision here.

Other than that this seems like a good change to make.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, now that I look more closely at the rest of the method, there's a hefty float/double cast and MathD.Max being used. So maybe it doesn't matter as much as I thought.

@PaperPrototype
Copy link
Contributor

instead of a threshold maybe create a custom comparison check? That uses Application.FloatEqualThreshold

  • Math.FloatIsEqual(floatValue, comparedTo)
  • Math.FloatIsGreater(floatValue, comparedTo)
  • Math.FloatIsLesser(floatValue, comparedTo)

@michaelsakharov
Copy link
Contributor

instead of a threshold maybe create a custom comparison check? That uses Application.FloatEqualThreshold

  • Math.FloatIsEqual(floatValue, comparedTo)
  • Math.FloatIsGreater(floatValue, comparedTo)
  • Math.FloatIsLesser(floatValue, comparedTo)

This is a good point Unity has Mathf.ApproximatelyEquals, Since our goal is to sorta mimic Unity's API to make transitioning as seamless as possible, it makes sense to recreate that idea.

@brmassa
Copy link
Contributor Author

brmassa commented Sep 16, 2024

I agree with all comments:

  • Bepu: the new check does not add much calculation. Also, pure equality might create weird physic bugs, very had to track
  • Mathf.ApproximatelyEquals: good option. Also, I've arbitrarily chosen 0.0001f. It would be nice to check the value selected by Unity
  • Math.* methods make it more readable. a* what about using Mathf.*? b* A operator == override (for floats and doubles)?

@brmassa
Copy link
Contributor Author

brmassa commented Sep 17, 2024

I've created Mathf.ApproximatelyEquals because it's the same method name used for MathD.

Also, I replaced several Epsilon comparisons with the Mathf.Epsilon and MathD.Epsilon

@michaelsakharov michaelsakharov merged commit b172d38 into ProwlEngine:development Sep 17, 2024
1 check passed
@brmassa brmassa deleted the fix/float-comparison branch September 18, 2024 11:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants