oliverbooth / X10D

Extension methods on crack.
https://oliverbooth.github.io/X10D/
MIT License
28 stars 2 forks source link

[Request]: Additional math utilities #60

Closed RealityProgrammer closed 1 year ago

RealityProgrammer commented 2 years ago

Type to extend

Various (though primarily float)

Signature

Summary

1 + 2. Wrap the value between 2 boundaries. Lower boundary is inclusive, higher boundary is exclusive
3 + 4. Wrap the value between 0 and length (exclusive)
5. Calculate where the value is between a and b
6. Apply a simple bias function to value
7. Simulate pulse wave where 1 is returned if value is between 2 values (inclusive). 0 otherwise. (https://en.wikipedia.org/wiki/Pulse_wave)
8. Simulate incremental sawtooth wave (https://en.wikipedia.org/wiki/Sawtooth_wave)
9. Gamma correction
10. https://en.wikipedia.org/wiki/Sigmoid_function
11. Apply a simple smoothstep calculation between a and b
12. Clamp value between 0 and 1
13. Normalize given value between 2 boundaries
14. Return value between outmin and outmax based on linear interpolation between inmin and inmax
15. Exponential decay (https://en.wikipedia.org/wiki/Exponential_decay)
16. Convert linear value space to gamma value space (usually used for color space)
17. Convert gamma value space to linear value space (usually used for color space)

Parameters

1 + 2 Parameter Type Description
value float or int Value to be wrapped
low float or int The minimum value to wrap value, inclusive
high float or int The maximum value to wrap value, exclusive
3 + 4. Parameter Type Description
value float or int Value to be wrapped
length float or int Exclusive boundary
5. Parameter Type Description
value float Result value of Linear Interpolation (Lerp) operation
a float Start point
b float End point
6. Parameter Type Description
value float Value to apply bias to
bias float Bias value (0 to 1). If lower than 0.5, value will be shift downward, higher then value will be shift upward
7. Parameter Type Description
value float Value to check
a float Lower boundary (inclusive)
b float Higher boundary (inclusive)
8. Parameter Type Description
value float Value on the horizontal axis
magnitude float Magnitude of the sawtooth
9. Parameter Type Description
value float Brightness in linear space
gamma float Gamma value (typically 2.2)
10. Parameter Type Description
x float How "tight" the graph's S curve should be
11. Parameter Type Description
a float Lower boundary
b float Higher boundary
x float Value between a and b (linear)
12. Parameter Type Description
x float Value to saturate
13. Parameter Type Description
value float Value to normalize to a and b
min float Lower value
max float Higher value
14. Parameter Type Description
value float Value between inmin and inmax
inmin float Minimum input value
inmax float Maximum input value
outmin float Minimum output value
outmax float Maximum output value
15. Parameter Type Description
value float Initial value
t float Time value
decay float Decay constant
16. Parameter Type Description
linear float Value in linear space
17. Parameter Type Description
linear float Value in gamma space

Benefits

Some useless math function but might be fun to add some

Drawbacks

Might need rewrite after generic math come out

Implementation Example

1 + 2.

float d = high - low; 
return low + (((value - low) % d) + d) % d;

3 + 4.

return ((value % length) + length) % length;

5.

if (a == b) return 0;
return (value - a) / (b - a);

6.

return value / ((1f / bias - 2f) * (1f - value) + 1f);

7.

return (a <= value && value <= b) ? 1 : 0;

8.

return (value - MathF.Floor(value)) * magnitude;

9.

return MathF.Pow(value, 1 / gamma);

10.

return 1 / (1 + MathF.Exp(-x));

11.

x = Math.Clamp((x - a) / (b - a), 0, 1);
return x * x * (3 - 2 * x);

12.

return Math.Clamp(x, 0, 1);

13.

return (value - min) / (max - min);

14.

return outmin + (value - inmin) * (outmax - outmin) / (inmax - inmin);

15.

return value * MathF.Exp(-decay * t);

16.

return MathF.Pow(linear, 1 / 2.2f);

17.

return MathF.Pow(gamma, 2.2f);

Code of Conduct

oliverbooth commented 2 years ago

Can you explain what purpose Wrap serves? It seems like it behaves as Clamp. Same with Normalize

Perhaps example inputs and outputs will help clarify

RealityProgrammer commented 2 years ago

Wrap method will wrap the value around between 2 boundaries instead of clamping, so if it's overflow or underflow, it will rewrap on the otherside. Normalize method is just normalize value between a and b in form of 0 to 1, a bit awkward is it will never returns 1 but wrap back to 0 because of division

Here is the demo: https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA0AXEUCuA7AHwAEAmARgFgAoIgBgAIiyA6AFRgQwG5rqA3AIZR6AZ2D0AvPTwwA7vQDKGKAEs8AcwBCOFQBsAJjCgAKErRQAOAJQ8qY5gEEADk5h59AGTUxjAIgL0AGoCujgw9AEA6lACTsaCoTBo9ACsyWQpVhH00bHxIWHJ1tkActAAtiEqAF4+CYX0tOm0WQS+NtT2zq7uXjJ+BHBDw3CDI+MTI2OTk9Mz8+NtHVTUAGbQ9MZqGPQqko1cu/QAPPRktLSHKgDU11kA3tT0z/SruhACO3g45WT7uXEVMk0mdMrYXq93p9pD8SP8Yk4SFsissIU8XgB6DE5BFHYAwDCyGBuegAbSaZ1oAF1XhtDOUIHgRMpPipGfQnDgoE4ICIYOjnm8Pl8fgBmfZlKCVXQ1HwA5GNZpWZIU86ol4C0TARwuNz6YwAEn8z3uKhAABFRQBfZ4BCEQ+7fX5oOAkG32l52j2O2Hu+1ej0mp2il3WwMQpbgl5dXW9bzGZZW6hMACcxnsrAgSlUGgTy2TZCQkOFOLyQuh9SSxeh71kyXLOwAFip1I2HpqG/R9Ptm636HB6LXbJqiAB2QcQeTXTbGfKJfsT2RZACkXay0/0K67tiTKxoherOwBSM7lfrUJ2ujc6gwbfojyoELHM8r9FXV40t/Xg+vX7fP8/Rsd14fci07SVpVlYxTwKKtO3KNRzxLSoEHbR8XmfOcwgXBC8CybFjBQnC1ETIA

oliverbooth commented 2 years ago

Ah so Wrap serves as modulo with offset, understood. And Normalize is redundant because it's essentially InverseLerp

I know we discussed this in the server, just leaving this note here for myself

RealityProgrammer commented 2 years ago

Not exactly like C# modulo but another way to explain it that going through one end, you end up in another end like Portal

And the reason for extra complicated calculation is to make it works for negative number, still apply the same principle

Wrap around in an endless loop

oliverbooth commented 1 year ago

14 was added with eadb66f47002724c8a149142e81c83e25f6a987f under the name ScaleRange