294 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			294 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using System;
 | 
						|
using System.Numerics;
 | 
						|
 | 
						|
namespace Engine.Core;
 | 
						|
 | 
						|
public static class Math
 | 
						|
{
 | 
						|
    /// <summary>
 | 
						|
    /// The value of Pi (π).
 | 
						|
    /// </summary>
 | 
						|
    public const float Pi = 3.1415926535897932f;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// The value of Tau (τ), mathematical constant equal to 2π.
 | 
						|
    /// </summary>
 | 
						|
    public const float Tau = 2f * Pi;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// The base of the natural logarithm.
 | 
						|
    /// </summary>
 | 
						|
    public const float E = 2.718281828459045f;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// The conversion factor from radians to degrees.
 | 
						|
    /// </summary>
 | 
						|
    public const float RadianToDegree = 180f / Pi;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// The conversion factor from degrees to radians.
 | 
						|
    /// </summary>
 | 
						|
    public const float DegreeToRadian = Pi / 180f;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Gets one minus of given <see cref="T"/>.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="value">The value <see cref="T"/>.</param>
 | 
						|
    /// <returns>One minus of given <see cref="T"/>.</returns>
 | 
						|
    public static T OneMinus<T>(T value) where T : INumber<T> => T.One - value;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Adds two <see cref="T"/>s.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="left">The first <see cref="T"/>.</param>
 | 
						|
    /// <param name="value">The second <see cref="T"/>.</param>
 | 
						|
    /// <returns>The sum of the two <see cref="T"/>s.</returns>
 | 
						|
    public static T Add<T>(T left, T value) where T : INumber<T> => left + value;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Subtracts one <see cref="T"/> from another.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="left">The <see cref="T"/> to subtract from.</param>
 | 
						|
    /// <param name="value">The <see cref="T"/> to subtract.</param>
 | 
						|
    /// <returns>The result of subtracting the second <see cref="T"/> from the first.</returns>
 | 
						|
    public static T Subtract<T>(T left, T value) where T : INumber<T> => left - value;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Multiplies a <see cref="T"/> by a scalar value.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="left">The <see cref="T"/>.</param>
 | 
						|
    /// <param name="multiplier">The scalar value.</param>
 | 
						|
    /// <returns>The result of multiplying the <see cref="T"/> by the scalar value.</returns>
 | 
						|
    public static T Multiply<T>(T left, T multiplier) where T : INumber<T> => left * multiplier;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Divides a <see cref="T"/> by a scalar value.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="left">The <see cref="T"/>.</param>
 | 
						|
    /// <param name="divider">The scalar value.</param>
 | 
						|
    /// <returns>The result of dividing the <see cref="T"/> by the scalar value.</returns>
 | 
						|
    public static T Divide<T>(T left, T divider) where T : INumber<T> => left / divider;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Returns the true mathematical modulus of a <see cref="T"/> value. 
 | 
						|
    /// Unlike the remainder operator (%), this result is always non-negative,
 | 
						|
    /// even when the <paramref name="value"/> operand is negative.
 | 
						|
    /// </summary>
 | 
						|
    /// <typeparam name="T">A numeric type that implements <see cref="INumber{T}"/>.</typeparam>
 | 
						|
    /// <param name="value">The dividend <see cref="T"/> value.</param>
 | 
						|
    /// <param name="modulus">The modulus <see cref="T"/> value (must be non-zero).</param>
 | 
						|
    /// <returns>
 | 
						|
    /// The non-negative remainder of <paramref name="value"/> divided by <paramref name="modulus"/>.
 | 
						|
    /// </returns>
 | 
						|
    public static T Mod<T>(T value, T modulus) where T : INumber<T>
 | 
						|
    {
 | 
						|
        T result = value % modulus;
 | 
						|
        if (result < T.Zero)
 | 
						|
            result += modulus;
 | 
						|
        return result;
 | 
						|
    }
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Returns the absolute value of a number.
 | 
						|
    /// </summary>
 | 
						|
    /// <typeparam name="T">The type of the number.</typeparam>
 | 
						|
    /// <param name="x">The number.</param>
 | 
						|
    /// <returns>The absolute value of <paramref name="x"/>.</returns>
 | 
						|
    public static T Abs<T>(T x) where T : INumber<T> => x > T.Zero ? x : -x;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Returns the cosine of a number.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="x">The number.</param>
 | 
						|
    /// <returns>The cosine of <paramref name="x"/>.</returns>
 | 
						|
    public static float Cos(float x) => MathF.Cos(x);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Returns the sine of a number.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="x">The number.</param>
 | 
						|
    /// <returns>The sine of <paramref name="x"/>.</returns>
 | 
						|
    public static float Sin(float x) => MathF.Sin(x);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Returns the arccosine of a number.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="x">The number.</param>
 | 
						|
    /// <returns>The arccosine of <paramref name="x"/>.</returns>
 | 
						|
    public static float Acos(float x) => MathF.Acos(x);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Returns the arcsine of a number.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="x">The number.</param>
 | 
						|
    /// <returns>The arcsine of <paramref name="x"/>.</returns>
 | 
						|
    public static float Asin(float x) => MathF.Asin(x);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Returns the angle whose tangent is the quotient of two specified numbers.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="y">The y-coordinate of a point.</param>
 | 
						|
    /// <param name="x">The x-coordinate of a point.</param>
 | 
						|
    /// <returns>The angle, measured in radians.</returns>
 | 
						|
    public static float Atan2(float y, float x) => MathF.Atan2(y, x);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Returns the hyperbolic arctangent of a number.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="x">The number.</param>
 | 
						|
    /// <returns>The hyperbolic arctangent of <paramref name="x"/>.</returns>
 | 
						|
    public static float Atanh(float x) => MathF.Atanh(x);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Clamps a number between a minimum and maximum value.
 | 
						|
    /// </summary>
 | 
						|
    /// <typeparam name="T">The type of the number.</typeparam>
 | 
						|
    /// <param name="x">The number to clamp.</param>
 | 
						|
    /// <param name="min">The minimum value.</param>
 | 
						|
    /// <param name="max">The maximum value.</param>
 | 
						|
    /// <returns>The clamped value.</returns>
 | 
						|
    public static T Clamp<T>(T x, T min, T max) where T : INumber<T> => (x < min) ? min : (x > max) ? max : x;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Returns the smallest integral value that is greater than or equal to the specified number.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="x">The number.</param>
 | 
						|
    /// <returns>The smallest integral value that is greater than or equal to <paramref name="x"/>.</returns>
 | 
						|
    public static float Ceiling(float x) => MathF.Ceiling(x);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Returns a value with the magnitude of <paramref name="x"/> and the sign of <paramref name="y"/>.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="x">The magnitude value.</param>
 | 
						|
    /// <param name="y">The sign value.</param>
 | 
						|
    /// <returns>A value with the magnitude of <paramref name="x"/> and the sign of <paramref name="y"/>.</returns>
 | 
						|
    public static float CopySign(float x, float y) => MathF.CopySign(x, y);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Returns the largest integral value that is less than or equal to the specified number.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="x">The number.</param>
 | 
						|
    /// <returns>The largest integral value that is less than or equal to <paramref name="x"/>.</returns>
 | 
						|
    public static float Floor(float x) => MathF.Floor(x);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Returns the remainder of the division of two specified numbers.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="x">The dividend.</param>
 | 
						|
    /// <param name="y">The divisor.</param>
 | 
						|
    /// <returns>The remainder of the division of <paramref name="x"/> by <paramref name="y"/>.</returns>
 | 
						|
    public static float IEEERemainder(float x, float y) => MathF.IEEERemainder(x, y);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Returns the natural (base e) logarithm of a specified number.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="x">The number.</param>
 | 
						|
    /// <param name="y">The base.</param>
 | 
						|
    /// <returns>The natural logarithm of <paramref name="x"/> with base <paramref name="y"/>.</returns>
 | 
						|
    public static float Log(float x, float y) => MathF.Log(x, y);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Returns the larger of two numbers.
 | 
						|
    /// </summary>
 | 
						|
    /// <typeparam name="T">The type of the numbers.</typeparam>
 | 
						|
    /// <param name="x">The first number.</param>
 | 
						|
    /// <param name="y">The second number.</param>
 | 
						|
    /// <returns>The larger of <paramref name="x"/> and <paramref name="y"/>.</returns>
 | 
						|
    public static T Max<T>(T x, T y) where T : INumber<T> => (x > y) ? x : y;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Returns the number whose absolute value is larger.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="x">The first number.</param>
 | 
						|
    /// <param name="y">The second number.</param>
 | 
						|
    /// <returns>The number whose absolute value is larger.</returns>
 | 
						|
    public static T AbsMax<T>(T x, T y) where T : INumber<T> => (Abs(x) > Abs(y)) ? x : y;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Returns the smaller of two numbers.
 | 
						|
    /// </summary>
 | 
						|
    /// <typeparam name="T">The type of the numbers.</typeparam>
 | 
						|
    /// <param name="x">The first number.</param>
 | 
						|
    /// <param name="y">The second number.</param>
 | 
						|
    /// <returns>The smaller of <paramref name="x"/> and <paramref name="y"/>.</returns>
 | 
						|
    public static T Min<T>(T x, T y) where T : INumber<T> => (x < y) ? x : y;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Returns the number whose absolute value is smaller.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="x">The first number.</param>
 | 
						|
    /// <param name="y">The second number.</param>
 | 
						|
    /// <returns>The number whose absolute value is smaller.</returns>
 | 
						|
    public static T AbsMin<T>(T x, T y) where T : INumber<T> => (Abs(x) < Abs(y)) ? x : y;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Returns a specified number raised to the specified power.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="x">The number to raise to a power.</param>
 | 
						|
    /// <param name="y">The power to raise <paramref name="x"/> to.</param>
 | 
						|
    /// <returns>The number <paramref name="x"/> raised to the power <paramref name="y"/>.</returns>
 | 
						|
    public static float Pow(float x, float y) => MathF.Pow(x, y);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Performs linear interpolation between two specified values.
 | 
						|
    /// </summary>
 | 
						|
    /// <typeparam name="T">The type of the values, which must implement <see cref="IFloatingPoint{T}"/>.</typeparam>
 | 
						|
    /// <param name="x">The starting value of the interpolation.</param>
 | 
						|
    /// <param name="y">The ending value of the interpolation.</param>
 | 
						|
    /// <param name="t">The interpolation factor, typically in the range [0, 1].</param>
 | 
						|
    /// <returns>A value that represents the linear interpolation between <paramref name="x"/> and <paramref name="y"/>.</returns>
 | 
						|
    public static T Lerp<T>(T x, T y, T t) where T : IFloatingPoint<T> => x + (y - x) * t;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Rounds a number to the closest integer.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="x">The number to round.</param>
 | 
						|
    /// <param name="roundMode">Specification for how to round <paramref name="x"/> if it is midway between two other numbers.</param>
 | 
						|
    /// <returns>The number <paramref name="x"/> rounded to the closest integer.</returns>
 | 
						|
    public static float Round(float x, RoundMode roundMode) => RoundToInt(x, roundMode);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Rounds a number to the closest integer.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="x">The number to round.</param>
 | 
						|
    /// <param name="roundMode">Specification for how to round <paramref name="x"/> if it's midway between two numbers</param>
 | 
						|
    /// <returns>The number <paramref name="x"/> rounded to the closest integer.</returns>
 | 
						|
    public static int RoundToInt(float x, RoundMode roundMode = RoundMode.Ceil)
 | 
						|
    {
 | 
						|
        float remainder = x.Mod(1f);
 | 
						|
 | 
						|
        if (remainder == .5f)
 | 
						|
            if (roundMode == RoundMode.Floor)
 | 
						|
                return (int)x;
 | 
						|
            else
 | 
						|
                return (int)(x + .5f);
 | 
						|
 | 
						|
        if (x < 0f)
 | 
						|
            return (int)(x - .5f);
 | 
						|
        return (int)(x + .5f);
 | 
						|
    }
 | 
						|
    public enum RoundMode { Ceil, Floor };
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Returns the square of a number.
 | 
						|
    /// </summary>
 | 
						|
    /// <typeparam name="T">The type of the number.</typeparam>
 | 
						|
    /// <param name="x">The number to square.</param>
 | 
						|
    /// <returns>The square of <paramref name="x"/>.</returns>
 | 
						|
    public static T Sqr<T>(T x) where T : INumber<T> => x * x;
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Returns the square root of a specified number.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="x">The number.</param>
 | 
						|
    /// <returns>The square root of <paramref name="x"/>.</returns>
 | 
						|
    public static float Sqrt(float x) => MathF.Sqrt(x);
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Calculates the integral part of a number.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="x">The number.</param>
 | 
						|
    /// <returns>The integral part of <paramref name="x"/>.</returns>
 | 
						|
    public static float Truncate(float x) => MathF.Truncate(x);
 | 
						|
}
 |