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