#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 }