C#: Add float and double overloads to Mathf #71583
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Background and motivation
double
andfloat
1.Situations where you have to mix floating-type values may happen often since the engine uses
double
for scalar values andfloat
for vector values.double
values.Currently they are implemented using
real_t
which defaults tofloat
, this can be changed todouble
with--precision=double
but I see no reason not to offer the ability to usedouble
APIs even when using--precision=single
.float
may offer better performance by usingSystem.MathF
instead 2.Currently we use
System.Math
which usesdouble
and then convert tofloat
, there's a tiny performance cost and we may want to optimize this given how most of our math is used in areas wherefloat
is all that is required.PR design
This PR aims to solve the mentioned issues by adding
float
anddouble
overloads to all methods ofMathf
. This allows the methods to be usable withfloat
,double
orreal_t
, regardless of the--precision
flag.double
andfloat
overloads in the same class, users can seamlessly useMathf
regardless of the floating type that they're using. This should help reduce the need for converting tofloat
orreal_t
and allows for mixing different floating types which would return adouble
.This is the same behavior you would come to expect from math operations that mix
float
anddouble
:double
are also available in builds that use--precision=single
, allowing users to use thefloat
ordouble
methods depending on their use case.double
andfloat
methods allow us to use different implementations optimized for the situation. Thedouble
methods useSystem.Math
just like before, but now thefloat
methods can take advantage ofSystem.MathF
which should result in a minor performance improvement.Mathf
with calls to the methods inSystem.Math
andSystem.MathF
directly.Constants
One of the problems with this approach compared to alternative designs (see section below) is that when we only have one Math class we can't have constant overloads, so we end up with one of these options:
float
:This looses precision that may be useful to users working with
double
.double
:This requires converting to
float
every time users are usingfloat
-based APIs.float
anddouble
:This means we need to duplicate every constant and give them different names, which tends to be ugly (e.g.:
PiF
andPiD
).real_t
:This is the the way constants are currently defined today in
Mathf
, no changes.Because I'm not really convinced with any of the options I choose to keep the status quo with this PR, constants remain defined as
real_t
just as before, this should allow ease of usage when working withreal_t
.For users that require
float
ordouble
constants my recommendation would be to get them fromSystem.Math
,System.MathF
,System.Double
andSystem.Single
which contains most of the constants available inMathf
. Users are also free to define their own constants in their projects if they need to, and even publish libraries to NuGet for reusability.Alternative Designs
Multiple Math classes
We could implement the the Math methods in separate classes such as
MathF
andMathD
, this has the benefit of allowing us to use the same name for the constants but has the following problems:I'd expect most users would end up using
MathD
simply because it works everywhere sincefloat
implicitly converts todouble
, missing out on minor performance improvements.real_t
.When working with
real_t
values, such as when using vector types, users can't assume the vector usesfloat
so they'll be forced to useMathD
and then convert toreal_t
. This could be fixed if we also provide a third Math class forreal_t
but that increases the maintainability burden.System.Math
andSystem.MathF
so this approach doesn't really provide as many benefits.Generic Math
The new Generic Math feature introduced in .NET 7.0 would allow us to implement a Math class with generic
T
methods whereT
isINumber<T>
which means our methods would work with any numeric type (int
,long
,float
,double
, ...) and even any non-primitive type like a custom user-defined type as long as it implements theINumber<T>
interface.Unfortunately, this would require using .NET 7.0 and we're currently using .NET 6.0 (we may consider switching to .NET 7.0 for the 4.0 release but nothing has been decided so far).
Also, considering how important performance is for Math, I wonder if generic math is fast enough. This might not be an issue when using full AOT though, but we also don't support that today in Godot.
Related issues and PRs
Mathf
intoMaths
andMathd
and useMathf
as name forreal_t
#65832.Footnotes
https://github.com/godotengine/godot-proposals/issues/5403 ↩
https://github.com/godotengine/godot-proposals/issues/5509 ↩