#region --- License ---
/* Licensed under the MIT/X11 license.
* Copyright (c) 2006-2008 the OpenTK Team.
* This notice may not be removed from any source distribution.
* See license.txt for licensing detailed licensing details.
*
* Contributions by Andy Gill, James Talton and Georg Wächter.
*/
#endregion
using System;
namespace Chernobyl.Mathematics.Utility
{
///
/// Contains mathematical functions for the OpenTK.Math toolkit.
///
public static class Functions
{
#region Power of Two
///
/// Returns the next power of two that is larger than the specified number.
///
/// The specified number.
/// The next power of two.
public static long NextPowerOfTwo(long n)
{
if (n < 0) throw new ArgumentOutOfRangeException("n", "Must be positive.");
return (long)System.Math.Pow(2, System.Math.Ceiling(System.Math.Log((double)n, 2)));
}
///
/// Returns the next power of two that is larger than the specified number.
///
/// The specified number.
/// The next power of two.
public static int NextPowerOfTwo(int n)
{
if (n < 0) throw new ArgumentOutOfRangeException("n", "Must be positive.");
return (int)System.Math.Pow(2, System.Math.Ceiling(System.Math.Log((double)n, 2)));
}
///
/// Checks to see if an integer is a power of two.
///
/// The number to check to see if it is a power of two.
/// True if the number is a power of two, false if otherwise.
public static bool IsPowerOfTwo(int theNumberToCheck)
{
return ((theNumberToCheck - 1) & theNumberToCheck) == 0;
}
///
/// Checks to see if an unsigned integer is a power of two.
///
/// The number to check to see if it is a power of two.
/// True if the number is a power of two, false if otherwise.
public static bool IsPowerOfTwo(uint theNumberToCheck)
{
return ((theNumberToCheck - 1) & theNumberToCheck) == 0;
}
#endregion
///
/// Calculates the factorial of a given natural number.
///
/// The number.
/// n!
public static long Factorial(int n)
{
long result = 1;
for (; n > 1; n--)
result *= n;
return result;
}
///
/// Calculates the binomial coefficient above .
///
/// The n.
/// The k.
/// n! / (k! * (n - k)!)
public static long BinomialCoefficient(int n, int k)
{
return Factorial(n) / (Factorial(k) * Factorial(n - k));
}
///
/// Returns an approximation of the inverse square root of left number.
///
/// A number.
/// An approximation of the inverse square root of the specified number, with an upper error bound of 0.001
///
/// This is an improved implementation of the the method known as Carmack's inverse square root
/// which is found in the Quake III source code. This implementation comes from
/// http://www.codemaestro.com/reviews/review00000105.html. For the history of this method, see
/// http://www.beyond3d.com/content/articles/8/
///
public static float InverseSqrtFast(float x)
{
unsafe
{
float xhalf = 0.5f * x;
int i = *(int*)&x; // Read bits as integer.
i = 0x5f375a86 - (i >> 1); // Make an initial guess for Newton-Raphson approximation
x = *(float*)&i; // Convert bits back to float
x = x * (1.5f - xhalf * x * x); // Perform left single Newton-Raphson step.
return x;
}
}
///
/// Returns an approximation of the inverse square root of left number.
///
/// A number.
/// An approximation of the inverse square root of the specified number, with an upper error bound of 0.001
///
/// This is an improved implementation of the the method known as Carmack's inverse square root
/// which is found in the Quake III source code. This implementation comes from
/// http://www.codemaestro.com/reviews/review00000105.html. For the history of this method, see
/// http://www.beyond3d.com/content/articles/8/
///
public static double InverseSqrtFast(double x)
{
return InverseSqrtFast((float)x);
// TODO: The following code is wrong. Fix it, to improve precision.
#if false
unsafe
{
double xhalf = 0.5f * x;
int i = *(int*)&x; // Read bits as integer.
i = 0x5f375a86 - (i >> 1); // Make an initial guess for Newton-Raphson approximation
x = *(float*)&i; // Convert bits back to float
x = x * (1.5f - xhalf * x * x); // Perform left single Newton-Raphson step.
return x;
}
#endif
}
///
/// The value of PI as a float.
///
public static readonly float PIF = 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930382f;
///
/// The component multiplied to a radian number to convert it to a degree.
///
public static readonly float RTODF = 180.0f / PIF;
///
/// The component multiplied to a degree number to convert it to a radian.
///
public static readonly float DTORF = PIF / 180.0f;
///
/// The value of PI as a double.
///
public static readonly double PI = 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930382d;
///
/// The component multiplied to a radian number to convert it to a degree.
///
public static readonly double RTOD = 180.0d / PIF;
///
/// The component multiplied to a degree number to convert it to a radian.
///
public static readonly double DTOR = PIF / 180.0d;
///
/// Swaps two numbers.
///
/// The number to swap with
/// The number to swap with
public static void Swap(ref double a, ref double b)
{
double temp = a;
a = b;
b = temp;
}
///
/// Swaps two numbers.
///
/// The number to swap with
/// The number to swap with
public static void Swap(ref float a, ref float b)
{
float temp = a;
a = b;
b = temp;
}
///
/// Returns a value that is a straight line value from to
/// by .
///
/// The starting value.
/// The end value.
/// The weight of to apply to
/// , 0 being fully equal to and 1 being
/// fully equal to , and anything above 1 resulting in an addition
/// to .
public static double Lerp(this double first, double second, double amount) =>
// We could have also used the equation (first + amount * (second - first)) but
// this form is less precise due to floating point arithmetic errors.
(1 - amount) * first + amount * second;
///
/// Returns a value that is a straight line value from to
/// by .
///
/// The starting value.
/// The end value.
/// A value between 0 and 1 that indicates the weight of
/// , 0 being fully equal to and 1 being
/// fully equal to .
public static float Lerp(this float first, float second, float amount) =>
(float)((double)first).Lerp(second, amount);
///
/// Returns rounded to the number of of fractional digits specified
/// by .
///
public static double Round(this double value, int digits) => Math.Round(value, digits);
}
#if false
public static partial class Math
{
#region --- Vectors ---
#region --- Addition ---
///
/// Adds the given Vector2 to the current Vector3.
///
/// The right operand of the addition.
/// A new Vector3 containing the result of the addition.
public static Vector2 Add(Vector2 left, Vector2 right)
{
return new Vector2(left).Add(right);
}
///
/// Adds the given Vector3 to the current Vector3.
///
/// The right operand of the addition.
/// A new Vector3 containing the result of the addition.
public static Vector3 Add(Vector2 left, Vector3 right)
{
return new Vector3(left).Add(right);
}
///
/// Adds the given Vector4 to the current Vector3. W-coordinate remains unaffected.
///
/// The right operand of the addition.
/// A new Vector4 containing the result of the addition.
public static Vector4 Add(Vector2 left, Vector4 right)
{
return new Vector4(left).Add(right);
}
///
/// Adds the given Vector2 to the current Vector3.
///
/// The right operand of the addition.
/// A new Vector3 containing the result of the addition.
public static Vector3 Add(Vector3 left, Vector2 right)
{
return new Vector3(left).Add(right);
}
///
/// Adds the given Vector3 to the current Vector3.
///
/// The right operand of the addition.
/// A new Vector3 containing the result of the addition.
public static Vector3 Add(Vector3 left, Vector3 right)
{
return new Vector3(left).Add(right);
}
///
/// Adds the given Vector4 to the current Vector3. W-coordinate remains unaffected.
///
/// The right operand of the addition.
/// A new Vector4 containing the result of the addition.
public static Vector4 Add(Vector3 left, Vector4 right)
{
return new Vector4(left).Add(right);
}
///
/// Adds the given Vector2 to the current Vector3.
///
/// The right operand of the addition.
/// A new Vector3 containing the result of the addition.
public static Vector4 Add(Vector4 left, Vector2 right)
{
return new Vector4(left).Add(right);
}
///
/// Adds the given Vector3 to the current Vector3.
///
/// The right operand of the addition.
/// A new Vector3 containing the result of the addition.
public static Vector4 Add(Vector4 left, Vector3 right)
{
return new Vector4(left).Add(right);
}
///
/// Adds the given Vector4 to the current Vector3. W-coordinate remains unaffected.
///
/// The right operand of the addition.
/// A new Vector4 containing the result of the addition.
public static Vector4 Add(Vector4 left, Vector4 right)
{
return new Vector4(left).Add(right);
}
#endregion
#region --- Subtraction ---
#endregion
#region --- Cross ---
///
/// Computes the cross product between the current and the given Vector3. The current Vector3 is set to the result of the computation.
///
/// The right operand of the cross product
/// The current
public static Vector3 Cross(Vector3 left, Vector3 right)
{
return new Vector3(left).Cross(right);
}
#endregion
#endregion
}
#endif
}