UnityEngine.Mathf should use System.MathF

I have seen UnityEngine.Mathf often uses the double based System.Math. But since .NET Standard 2.1 there are System.MathF.

Unity from 2021.2 could switch to the new library and thus should improve performance in some places.

We have not done it so far because the UnityEngine assembly code does not have access to the .NET Standard 2.1 APIs. But we’re working on changing that internally now. Once that is complete, then we can look at doing this. There are a few caveats related to the VM implementations though.

For IL2CPP, the UnityEngine.Mathf APIs are already re-mapped as intrinsics to C standard library methods that do floating point math, so I think we’re already getting the best performance.

For Mono, the Mono version Unity used prior to Unity 2021.2 always did floating point math using 64-bit doubles, so this would not provide any benefit. The newer Mono has an option to use 32-bit floats, but that changes the behavior of some floating point code, so if we enable that, it will likely be an option.

But at the API level, I think this suggestion makes a lot of sense. I’ll raise it with the team. Thanks!

8 Likes

If you’re doing work on the Mathf class anyway, I think I found an improvement to Mathf.Repeat, although I haven’t done any tests.

// Current implementation
public static float Repeat(float t, float length)
{
    return Clamp(t - Floor(t / length) * length, 0f, length);
}

// My implementation
public static float Repeat(float t, float length)
{
    return (length + t % length) % length;
}

This has 2 division operators but no if checks (and is really elegant). It also only needs 2 interfaces from the System.Numerics namespace if you ever upgrade the API to include it (IAdditionOperators and IModulusOperators).

t = 8, length = 6
(6 + 8 % 6) % 6
= (6 + 2) % 6
= 8 % 6
= 2

t = -512, length = 17
(17 + -512 % 17) % 17
= (17 + -2) % 17
= 15 % 17
= 15
1 Like

this can further be simplified to (length + t) % length because Zn is a ring.
(unless there is some corner case with negative length)

[quote=M_R, post: 9238635, member: 820154]
this can further be simplified to (length + t) % length because Zn is a ring.
(unless there is some corner case with negative length)
[/quote]
Oh right, I should look into negative length…

The method you suggested wouldn’t work: the extra modulo is needed to account for t negative

t = -512, length = 17
(17 + -512) % 17
= -495 % 17
= -2 // should be 15
t = 512, length = -17
(-17 + 512 % -17) % -17
= (-17 + 2) % -17
= -15 % -17
= -15
t = -512, length = -17
(-17 + -512 % -17) % -17
= (-17 + -2) % -17
= -19 % -17
= -2

It actually works!

Unfortunately, a thread pointed out that this would not work for e.g. int.MaxValue because you would get an overflow exception.

There is a smarter answer hidden in this thread somewhere but I go sleep sleep now :3