#if REAL_T_IS_DOUBLE
using real_t = System.Double;
#else
using real_t = System.Single;
#endif
using System;
namespace Godot
{
///
/// Provides constants and static methods for common mathematical functions.
///
public static partial class Mathf
{
// Define constants with Decimal precision and cast down to double or float.
///
/// The circle constant, the circumference of the unit circle in radians.
///
// 6.2831855f and 6.28318530717959
public const real_t Tau = (real_t)6.2831853071795864769252867666M;
///
/// Constant that represents how many times the diameter of a circle
/// fits around its perimeter. This is equivalent to Mathf.Tau / 2.
///
// 3.1415927f and 3.14159265358979
public const real_t Pi = (real_t)3.1415926535897932384626433833M;
///
/// Positive infinity. For negative infinity, use -Mathf.Inf.
///
public const real_t Inf = real_t.PositiveInfinity;
///
/// "Not a Number", an invalid value. NaN has special properties, including
/// that it is not equal to itself. It is output by some invalid operations,
/// such as dividing zero by zero.
///
public const real_t NaN = real_t.NaN;
// 0.0174532924f and 0.0174532925199433
private const real_t _deg2RadConst = (real_t)0.0174532925199432957692369077M;
// 57.29578f and 57.2957795130823
private const real_t _rad2DegConst = (real_t)57.295779513082320876798154814M;
///
/// Returns the absolute value of (i.e. positive value).
///
/// The input number.
/// The absolute value of .
public static int Abs(int s)
{
return Math.Abs(s);
}
///
/// Returns the absolute value of (i.e. positive value).
///
/// The input number.
/// The absolute value of .
public static real_t Abs(real_t s)
{
return Math.Abs(s);
}
///
/// Returns the arc cosine of in radians.
/// Use to get the angle of cosine .
///
/// The input cosine value. Must be on the range of -1.0 to 1.0.
///
/// An angle that would result in the given cosine value. On the range 0 to Tau/2.
///
public static real_t Acos(real_t s)
{
return (real_t)Math.Acos(s);
}
///
/// Returns the arc sine of in radians.
/// Use to get the angle of sine .
///
/// The input sine value. Must be on the range of -1.0 to 1.0.
///
/// An angle that would result in the given sine value. On the range -Tau/4 to Tau/4.
///
public static real_t Asin(real_t s)
{
return (real_t)Math.Asin(s);
}
///
/// Returns the arc tangent of in radians.
/// Use to get the angle of tangent .
///
/// The method cannot know in which quadrant the angle should fall.
/// See if you have both y and x.
///
/// The input tangent value.
///
/// An angle that would result in the given tangent value. On the range -Tau/4 to Tau/4.
///
public static real_t Atan(real_t s)
{
return (real_t)Math.Atan(s);
}
///
/// Returns the arc tangent of and in radians.
/// Use to get the angle of the tangent of y/x. To compute the value, the method takes into
/// account the sign of both arguments in order to determine the quadrant.
///
/// Important note: The Y coordinate comes first, by convention.
///
/// The Y coordinate of the point to find the angle to.
/// The X coordinate of the point to find the angle to.
///
/// An angle that would result in the given tangent value. On the range -Tau/2 to Tau/2.
///
public static real_t Atan2(real_t y, real_t x)
{
return (real_t)Math.Atan2(y, x);
}
///
/// Rounds upward (towards positive infinity).
///
/// The number to ceil.
/// The smallest whole number that is not less than .
public static real_t Ceil(real_t s)
{
return (real_t)Math.Ceiling(s);
}
///
/// Clamps a so that it is not less than
/// and not more than .
///
/// The value to clamp.
/// The minimum allowed value.
/// The maximum allowed value.
/// The clamped value.
public static int Clamp(int value, int min, int max)
{
return value < min ? min : value > max ? max : value;
}
///
/// Clamps a so that it is not less than
/// and not more than .
///
/// The value to clamp.
/// The minimum allowed value.
/// The maximum allowed value.
/// The clamped value.
public static real_t Clamp(real_t value, real_t min, real_t max)
{
return value < min ? min : value > max ? max : value;
}
///
/// Returns the cosine of angle in radians.
///
/// The angle in radians.
/// The cosine of that angle.
public static real_t Cos(real_t s)
{
return (real_t)Math.Cos(s);
}
///
/// Returns the hyperbolic cosine of angle in radians.
///
/// The angle in radians.
/// The hyperbolic cosine of that angle.
public static real_t Cosh(real_t s)
{
return (real_t)Math.Cosh(s);
}
///
/// Converts an angle expressed in degrees to radians.
///
/// An angle expressed in degrees.
/// The same angle expressed in radians.
public static real_t Deg2Rad(real_t deg)
{
return deg * _deg2RadConst;
}
///
/// Easing function, based on exponent. The values are:
/// 0 is constant, 1 is linear, 0 to 1 is ease-in, 1 or more is ease-out.
/// Negative values are in-out/out-in.
///
/// The value to ease.
///
/// 0 is constant, 1 is linear, 0 to 1 is ease-in, 1 or more is ease-out.
///
/// The eased value.
public static real_t Ease(real_t s, real_t curve)
{
if (s < 0f)
{
s = 0f;
}
else if (s > 1.0f)
{
s = 1.0f;
}
if (curve > 0f)
{
if (curve < 1.0f)
{
return 1.0f - Pow(1.0f - s, 1.0f / curve);
}
return Pow(s, curve);
}
if (curve < 0f)
{
if (s < 0.5f)
{
return Pow(s * 2.0f, -curve) * 0.5f;
}
return ((1.0f - Pow(1.0f - ((s - 0.5f) * 2.0f), -curve)) * 0.5f) + 0.5f;
}
return 0f;
}
///
/// The natural exponential function. It raises the mathematical
/// constant e to the power of and returns it.
///
/// The exponent to raise e to.
/// e raised to the power of .
public static real_t Exp(real_t s)
{
return (real_t)Math.Exp(s);
}
///
/// Rounds downward (towards negative infinity).
///
/// The number to floor.
/// The largest whole number that is not more than .
public static real_t Floor(real_t s)
{
return (real_t)Math.Floor(s);
}
///
/// Returns a normalized value considering the given range.
/// This is the opposite of .
///
/// The interpolated value.
/// The destination value for interpolation.
/// A value on the range of 0.0 to 1.0, representing the amount of interpolation.
/// The resulting value of the inverse interpolation.
public static real_t InverseLerp(real_t from, real_t to, real_t weight)
{
return (weight - from) / (to - from);
}
///
/// Returns if and are approximately equal
/// to each other.
/// The comparison is done using a tolerance calculation with .
///
/// One of the values.
/// The other value.
/// A for whether or not the two values are approximately equal.
public static bool IsEqualApprox(real_t a, real_t b)
{
// Check for exact equality first, required to handle "infinity" values.
if (a == b)
{
return true;
}
// Then check for approximate equality.
real_t tolerance = Epsilon * Abs(a);
if (tolerance < Epsilon)
{
tolerance = Epsilon;
}
return Abs(a - b) < tolerance;
}
///
/// Returns whether is an infinity value (either positive infinity or negative infinity).
///
/// The value to check.
/// A for whether or not the value is an infinity value.
public static bool IsInf(real_t s)
{
return real_t.IsInfinity(s);
}
///
/// Returns whether is a NaN ("Not a Number" or invalid) value.
///
/// The value to check.
/// A for whether or not the value is a NaN value.
public static bool IsNaN(real_t s)
{
return real_t.IsNaN(s);
}
///
/// Returns if is approximately zero.
/// The comparison is done using a tolerance calculation with .
///
/// This method is faster than using with one value as zero.
///
/// The value to check.
/// A for whether or not the value is nearly zero.
public static bool IsZeroApprox(real_t s)
{
return Abs(s) < Epsilon;
}
///
/// Linearly interpolates between two values by a normalized value.
/// This is the opposite .
///
/// The start value for interpolation.
/// The destination value for interpolation.
/// A value on the range of 0.0 to 1.0, representing the amount of interpolation.
/// The resulting value of the interpolation.
public static real_t Lerp(real_t from, real_t to, real_t weight)
{
return from + ((to - from) * weight);
}
///
/// Linearly interpolates between two angles (in radians) by a normalized value.
///
/// Similar to ,
/// but interpolates correctly when the angles wrap around .
///
/// The start angle for interpolation.
/// The destination angle for interpolation.
/// A value on the range of 0.0 to 1.0, representing the amount of interpolation.
/// The resulting angle of the interpolation.
public static real_t LerpAngle(real_t from, real_t to, real_t weight)
{
real_t difference = (to - from) % Mathf.Tau;
real_t distance = ((2 * difference) % Mathf.Tau) - difference;
return from + (distance * weight);
}
///
/// Natural logarithm. The amount of time needed to reach a certain level of continuous growth.
///
/// Note: This is not the same as the "log" function on most calculators, which uses a base 10 logarithm.
///
/// The input value.
/// The natural log of .
public static real_t Log(real_t s)
{
return (real_t)Math.Log(s);
}
///
/// Returns the maximum of two values.
///
/// One of the values.
/// The other value.
/// Whichever of the two values is higher.
public static int Max(int a, int b)
{
return a > b ? a : b;
}
///
/// Returns the maximum of two values.
///
/// One of the values.
/// The other value.
/// Whichever of the two values is higher.
public static real_t Max(real_t a, real_t b)
{
return a > b ? a : b;
}
///
/// Returns the minimum of two values.
///
/// One of the values.
/// The other value.
/// Whichever of the two values is lower.
public static int Min(int a, int b)
{
return a < b ? a : b;
}
///
/// Returns the minimum of two values.
///
/// One of the values.
/// The other value.
/// Whichever of the two values is lower.
public static real_t Min(real_t a, real_t b)
{
return a < b ? a : b;
}
///
/// Moves toward by the value.
///
/// Use a negative value to move away.
///
/// The start value.
/// The value to move towards.
/// The amount to move by.
/// The value after moving.
public static real_t MoveToward(real_t from, real_t to, real_t delta)
{
if (Abs(to - from) <= delta)
return to;
return from + (Sign(to - from) * delta);
}
///
/// Returns the nearest larger power of 2 for the integer .
///
/// The input value.
/// The nearest larger power of 2.
public static int NearestPo2(int value)
{
value--;
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
value++;
return value;
}
///
/// Performs a canonical Modulus operation, where the output is on the range [0, ).
///
/// The dividend, the primary input.
/// The divisor. The output is on the range [0, ).
/// The resulting output.
public static int PosMod(int a, int b)
{
int c = a % b;
if ((c < 0 && b > 0) || (c > 0 && b < 0))
{
c += b;
}
return c;
}
///
/// Performs a canonical Modulus operation, where the output is on the range [0, ).
///
/// The dividend, the primary input.
/// The divisor. The output is on the range [0, ).
/// The resulting output.
public static real_t PosMod(real_t a, real_t b)
{
real_t c = a % b;
if ((c < 0 && b > 0) || (c > 0 && b < 0))
{
c += b;
}
return c;
}
///
/// Returns the result of raised to the power of .
///
/// The base.
/// The exponent.
/// raised to the power of .
public static real_t Pow(real_t x, real_t y)
{
return (real_t)Math.Pow(x, y);
}
///
/// Converts an angle expressed in radians to degrees.
///
/// An angle expressed in radians.
/// The same angle expressed in degrees.
public static real_t Rad2Deg(real_t rad)
{
return rad * _rad2DegConst;
}
///
/// Rounds to the nearest whole number,
/// with halfway cases rounded towards the nearest multiple of two.
///
/// The number to round.
/// The rounded number.
public static real_t Round(real_t s)
{
return (real_t)Math.Round(s);
}
///
/// Returns the sign of : -1 or 1.
/// Returns 0 if is 0.
///
/// The input number.
/// One of three possible values: 1, -1, or 0.
public static int Sign(int s)
{
if (s == 0)
return 0;
return s < 0 ? -1 : 1;
}
///
/// Returns the sign of : -1 or 1.
/// Returns 0 if is 0.
///
/// The input number.
/// One of three possible values: 1, -1, or 0.
public static int Sign(real_t s)
{
if (s == 0)
return 0;
return s < 0 ? -1 : 1;
}
///
/// Returns the sine of angle in radians.
///
/// The angle in radians.
/// The sine of that angle.
public static real_t Sin(real_t s)
{
return (real_t)Math.Sin(s);
}
///
/// Returns the hyperbolic sine of angle in radians.
///
/// The angle in radians.
/// The hyperbolic sine of that angle.
public static real_t Sinh(real_t s)
{
return (real_t)Math.Sinh(s);
}
///
/// Returns a number smoothly interpolated between and ,
/// based on the . Similar to ,
/// but interpolates faster at the beginning and slower at the end.
///
/// The start value for interpolation.
/// The destination value for interpolation.
/// A value representing the amount of interpolation.
/// The resulting value of the interpolation.
public static real_t SmoothStep(real_t from, real_t to, real_t weight)
{
if (IsEqualApprox(from, to))
{
return from;
}
real_t x = Clamp((weight - from) / (to - from), (real_t)0.0, (real_t)1.0);
return x * x * (3 - (2 * x));
}
///
/// Returns the square root of , where is a non-negative number.
///
/// If you need negative inputs, use .
///
/// The input number. Must not be negative.
/// The square root of .
public static real_t Sqrt(real_t s)
{
return (real_t)Math.Sqrt(s);
}
///
/// Returns the position of the first non-zero digit, after the
/// decimal point. Note that the maximum return value is 10,
/// which is a design decision in the implementation.
///
/// The input value.
/// The position of the first non-zero digit.
public static int StepDecimals(real_t step)
{
double[] sd = new double[]
{
0.9999,
0.09999,
0.009999,
0.0009999,
0.00009999,
0.000009999,
0.0000009999,
0.00000009999,
0.000000009999,
};
double abs = Abs(step);
double decs = abs - (int)abs; // Strip away integer part
for (int i = 0; i < sd.Length; i++)
{
if (decs >= sd[i])
{
return i;
}
}
return 0;
}
///
/// Snaps float value to a given .
/// This can also be used to round a floating point number to an arbitrary number of decimals.
///
/// The value to snap.
/// The step size to snap to.
///
public static real_t Snapped(real_t s, real_t step)
{
if (step != 0f)
{
return Floor((s / step) + 0.5f) * step;
}
return s;
}
///
/// Returns the tangent of angle in radians.
///
/// The angle in radians.
/// The tangent of that angle.
public static real_t Tan(real_t s)
{
return (real_t)Math.Tan(s);
}
///
/// Returns the hyperbolic tangent of angle in radians.
///
/// The angle in radians.
/// The hyperbolic tangent of that angle.
public static real_t Tanh(real_t s)
{
return (real_t)Math.Tanh(s);
}
///
/// Wraps between and .
/// Usable for creating loop-alike behavior or infinite surfaces.
/// If is 0, this is equivalent
/// to , so prefer using that instead.
///
/// The value to wrap.
/// The minimum allowed value and lower bound of the range.
/// The maximum allowed value and upper bound of the range.
/// The wrapped value.
public static int Wrap(int value, int min, int max)
{
int range = max - min;
if (range == 0)
return min;
return min + ((((value - min) % range) + range) % range);
}
///
/// Wraps between and .
/// Usable for creating loop-alike behavior or infinite surfaces.
/// If is 0, this is equivalent
/// to , so prefer using that instead.
///
/// The value to wrap.
/// The minimum allowed value and lower bound of the range.
/// The maximum allowed value and upper bound of the range.
/// The wrapped value.
public static real_t Wrap(real_t value, real_t min, real_t max)
{
real_t range = max - min;
if (IsZeroApprox(range))
{
return min;
}
return min + ((((value - min) % range) + range) % range);
}
private static real_t Fract(real_t value)
{
return value - (real_t)Math.Floor(value);
}
///
/// Returns the [code]value[/code] wrapped between [code]0[/code] and the [code]length[/code].
/// If the limit is reached, the next value the function returned is decreased to the [code]0[/code] side or increased to the [code]length[/code] side (like a triangle wave).
/// If [code]length[/code] is less than zero, it becomes positive.
///
/// The value to pingpong.
/// The maximum value of the function.
/// The ping-ponged value.
public static real_t PingPong(real_t value, real_t length)
{
return (length != (real_t)0.0) ? Abs(Fract((value - length) / (length * (real_t)2.0)) * length * (real_t)2.0 - length) : (real_t)0.0;
}
}
}