Some docs.

This commit is contained in:
That_One_Nerd 2023-11-27 13:37:39 -05:00
parent eee49b80a6
commit 32df5fdd79
3 changed files with 223 additions and 1 deletions

View File

@ -1,6 +1,20 @@
namespace Nerd_STF.Mathematics.Abstract;
/// <summary>
/// An <see langword="interface"/> that can be derived from to implement
/// absolute value functionality. This interface includes one method:
/// <list type="bullet">
/// <see cref="Absolute(T)"/>
/// </list>
/// </summary>
/// <typeparam name="T">This type.</typeparam>
public interface IAbsolute<T> where T : IAbsolute<T>
{
/// <summary>
/// Calculate the positive value of <typeparamref name="T"/>.
/// I know, this isn't technically the "absolute" value but whatever.
/// </summary>
/// <param name="val">The value of <typeparamref name="T"/> to calculate the absolute value of.</param>
/// <returns>The positive vlaue of <typeparamref name="T"/>.</returns>
public static abstract T Absolute(T val);
}

View File

@ -1,16 +1,49 @@
namespace Nerd_STF.Mathematics;
/// <summary>
/// A class that contains various mathematical methods using <see cref="float"/>s.
/// </summary>
public static class Mathf
{
/// <summary>
/// Calculate the absolute value of a <see cref="float"/>.
/// </summary>
/// <param name="val">The <see cref="float"/> to calculate the absolute value of.</param>
/// <returns></returns>
/// <remarks>Runs in <c>O(1)</c> time.</remarks>
public static float Absolute(float val) => val < 0 ? -val : val;
/// <summary>
/// Calculate the absolute value of a <see cref="int"/>.
/// </summary>
/// <param name="val">The <see cref="int"/> to calculate the absolute value of.</param>
/// <returns></returns>
/// <remarks>Runs in <c>O(1)</c> time.</remarks>
public static int Absolute(int val) => val < 0 ? -val : val;
/// <summary>
/// Calculates the absolute modulus value of a number. In C# by default, getting
/// the modulus of a negative number returns a negative value, while in math
/// that number is usually positive. This method ensures the number is positive.
/// </summary>
/// <param name="val">The value to apply the modulus to.</param>
/// <param name="mod">The number to modulus by.</param>
/// <returns>The smallest positive number that can be added to <paramref name="val"/> to create a multiple of <paramref name="mod"/>.</returns>
/// <remarks>Runs in <c>O(n)</c> time.</remarks>
public static float AbsoluteMod(float val, float mod)
{
while (val >= mod) val -= mod;
while (val < 0) val += mod;
return val;
}
/// <summary>
/// Calculates the absolute modulus value of a number. In C# by default, getting
/// the modulus of a negative number returns a negative value, while in math
/// that number is usually positive. This method ensures the number is positive.
/// </summary>
/// <param name="val">The value to apply the modulus to.</param>
/// <param name="mod">The number to modulus by.</param>
/// <returns>The smallest positive number that can be added to <paramref name="val"/> to create a multiple of <paramref name="mod"/>.</returns>
/// <remarks>Runs in <c>O(n)</c> time.</remarks>
public static int AbsoluteMod(int val, int mod)
{
while (val >= mod) val -= mod;
@ -18,15 +51,76 @@ public static class Mathf
return val;
}
/// <summary>
/// Calculates the inverse cosine of the value <paramref name="value"/>, such that
/// <c>cos(arccos(<paramref name="value"/>)) = <paramref name="value"/></c>.
///
/// Since <c>cos(x)</c> only returns a value between -1 and 1, the domain of
/// <c>arccos(x)</c> is [-1, 1], and its range is [0, π].
/// </summary>
/// <param name="value">The value to calculate the inverse cosine of.</param>
/// <returns>The angle θ representing <c>cos(θ) = <paramref name="value"/></c>.</returns>
/// <remarks>Runs in <c>O(n)</c> time.</remarks>
public static Angle ArcCos(float value) => ArcSin(-value) + Angle.Quarter;
/// <summary>
/// Calculates the inverse cotangent of the value <paramref name="value"/>, such that
/// <c>cot(arccot(<paramref name="value"/>)) = <paramref name="value"/></c>.
///
/// Since <c>cot(x)</c> returns any real number value, the domain of <c>arccot(x)</c>
/// is (-∞, ∞), and its range is (0, π).
/// </summary>
/// <param name="value">The value to calculate the inverse cotangent of.</param>
/// <returns>The angle θ representing <c>cot(θ) = <paramref name="value"/></c>.</returns>
/// <remarks>Runs in <c>O(n)</c> time.</remarks>
public static Angle ArcCot(float value) => ArcCos(value / Sqrt(1 + value * value));
/// <summary>
/// Calculates the invese cosecant of the value <paramref name="value"/>, such that
/// <c>csc(arccsc(<paramref name="value"/>)) = <paramref name="value"/></c>.
///
/// Since <c>csc(x)</c> returns any real number value such that <c>|csc(x)| >= 1</c>,
/// the domain of <c>arccsc(x)</c> is (-∞, 1] [1, ∞) and its range is [-π/2, π/2].
/// </summary>
/// <param name="value">The value to calculate the inverse cosecant of.</param>
/// <returns>The angle θ representing <c>csc(θ) = <paramref name="value"/></c>.</returns>
/// <remarks>Runs in <c>O(n)</c> time.</remarks>
public static Angle ArcCsc(float value) => ArcSin(1 / value);
/// <summary>
/// Calculates the inverse secant of the value <paramref name="value"/>, such that
/// <c>sec(arcsec(<paramref name="value"/>)) = <paramref name="value"/></c>.
///
/// Since <c>sec(x)</c> returns any real number value such that <c>|sec(x)| >= 1</c>,
/// the domain of <c>arcsec(x)</c> is (-∞, 1] [1, ∞) and its range is [0, π].
/// </summary>
/// <param name="value">The value to calculate the inverse secant of.</param>
/// <returns>The angle θ representing <c>sec(θ) = <paramref name="value"/></c>.</returns>
/// <remarks>Runs in <c>O(n)</c> time.</remarks>
public static Angle ArcSec(float value) => ArcCos(1 / value);
/// <summary>
/// Calculates the inverse sine of the value <paramref name="value"/>, such that
/// <c>sin(arcsin(<paramref name="value"/>)) = <paramref name="value"/></c>.
///
/// Since <c>sin(x)</c> returns a value between [-1, 1], the domain of <c>arcsin(x)</c>
/// is [-1, 1] and its range is [-π/2, π/2].
/// </summary>
/// <param name="value">The value to calculate the inverse sine of.</param>
/// <returns>The angle θ representing <c>sin(θ) = <paramref name="value"/></c>.</returns>
/// <exception cref="ArgumentOutOfRangeException">Thrown when the input is out of the domain of [-1, 1].</exception>
/// <remarks>Runs in <c>O(n)</c> time.</remarks>
public static Angle ArcSin(float value)
{
if (value > 1 || value < -1) throw new ArgumentOutOfRangeException(nameof(value));
return (SolveNewton(x => Sin(x) - value, 0), Angle.Type.Radians);
}
}
/// <summary>
/// Calculates the inverse tangent of the value <paramref name="value"/>, such that
/// <c>tan(arctan(<paramref name="value"/>)) = <paramref name="value"/></c>.
///
/// Since <c>tan(x)</c> returns any real number value, the domain of <c>arctan(x)</c>
/// is (-∞, ∞), and its range is (-π/2, π/2).
/// </summary>
/// <param name="value">The value to calculate the inverse cotangent of.</param>
/// <returns>The angle θ representing <c>tan(θ) = <paramref name="value"/></c>.</returns>
/// <remarks>Runs in <c>O(n)</c> time.</remarks>
public static Angle ArcTan(float value) => ArcSin(value / Sqrt(1 + value * value));
public static Angle ArcTan2(float a, float b) => ArcTan(a / b);
@ -47,12 +141,26 @@ public static class Mathf
for (float x = min; x <= max; x += step) vals.Add(equ(x));
return Average(vals.ToArray());
}
/// <summary>
/// Calculates the average of an array of <see cref="float"/>s.
/// </summary>
/// <param name="vals">The array to calculate the average of.</param>
/// <returns>The average of the array.</returns>
/// <remarks>Runs in O(n) time.</remarks>
public static float Average(params float[] vals)
{
float sum = 0;
foreach (float f in vals) sum += f;
return sum / vals.Length;
}
/// <summary>
/// Calculates the average of an array of <see cref="int"/>s.
/// Because the return type is also an <see cref="int"/>, the average
/// will be rounded down to the nearest whole number.
/// </summary>
/// <param name="vals">The array to calculate the average of.</param>
/// <returns>The average of the array, rounded down to the nearest <see cref="int"/>.</returns>
/// <remarks>Runs in <c>O(n)</c> time.</remarks>
public static int Average(params int[] vals)
{
int sum = 0;
@ -63,6 +171,12 @@ public static class Mathf
public static float Binomial(int n, int total, float successRate) =>
Combinations(total, n) * Power(successRate, n) * Power(1 - successRate, total - n);
/// <summary>
/// Calculates the cube root of a number.
/// </summary>
/// <param name="value">The number to calculate the cube root of.</param>
/// <returns>The cube root of <paramref name="value"/>.</returns>
/// <remarks>Runs in O(n) time.</remarks>
public static float Cbrt(float value) => SolveNewton(x => x * x * x - value, 1);
public static int Ceiling(float val)
@ -200,6 +314,15 @@ public static class Mathf
else return CordicHelper.LogAnyBase(@base, val, 16, 16);
}
/// <summary>
/// Creates an <see cref="Equation"/> out of a <see cref="Dictionary{TKey, TValue}"/>
/// of XY points. This equation has a domain of all real numbers and linearly
/// interpolates between points.
/// </summary>
/// <param name="vals">The <see cref="Dictionary{TKey, TValue}"/> of XY points to include in the <see cref="Equation"/>.</param>
/// <returns>An equation that interpolates between each point in <paramref name="vals"/>.</returns>
/// <exception cref="UndefinedException">Thrown when no points are contained in <paramref name="vals"/> or when two points in the dictionary cannot be joined together.</exception>
/// <remarks>Generates the <see cref="Equation"/> in <c>O(1)</c> time, however invoking that equation returns a result in <c>O(n)</c> time where <c>n</c> is the amount of points in <paramref name="vals"/>.</remarks>
public static Equation MakeEquation(Dictionary<float, float> vals) => delegate (float x)
{
if (vals.Count < 1) throw new UndefinedException();
@ -335,6 +458,15 @@ public static class Mathf
// nPr (n = total, r = size)
public static int Permutations(int total, int size) => Factorial(total) / Factorial(total - size);
/// <summary>
/// Returns an <see cref="Array"/> that contains all prime factors of the number
/// <paramref name="num"/>. A prime factor is defined as a prime number that
/// <paramref name="num"/> is divisible by at least once. Any counting number can
/// be represented as a unique collection of prime factors. Duplicate factors are
/// included.
/// </summary>
/// <param name="num">The number to calculate the prime factors of.</param>
/// <returns>An <see cref="Array"/> of prime factors.</returns>
public static int[] PrimeFactors(int num)
{
List<int> factors = new();

View File

@ -1,25 +1,101 @@
namespace Nerd_STF.Mathematics.Samples;
/// <summary>
/// A container of various mathematical constants.
/// </summary>
public static class Constants
{
/// <summary>
/// The ratio between a degree and a radian. This constant is intended to be used
/// as follows:
/// <code>degrees = radians * <see cref="DegToRad"/></code>
/// This is the reciprocal of <see cref="RadToDeg"/>.
/// </summary>
public const float DegToRad = Pi / 180;
/// <summary>
/// Exactly one half of the constant <see cref="Pi"/>. While this constant has many
/// uses, most of them are just a shorthand for <c><see cref="Pi"/> / 2</c>, unlike
/// <see cref="Tau"/>.
/// </summary>
/// <remarks>See also: <see href="https://en.wikipedia.org/wiki/Pi">Pi - Wikipedia</see></remarks>
public const float HalfPi = Pi / 2;
/// <summary>
/// The ratio between a circle's circumference and its diameter. This constant has
/// many uses.
/// </summary>
/// <remarks>See also: <see href="https://en.wikipedia.org/wiki/Pi">Pi - Wikipedia</see></remarks>
public const float Pi = 3.14159265359f;
/// <summary>
/// The ratio between a radian and a degree. This constant is intended to be used
/// as follows:
/// <code>radians = degrees * <see cref="RadToDeg"/></code>
/// This is the reciprocal of <see cref="DegToRad"/>.
/// </summary>
public const float RadToDeg = 180 / Pi;
/// <summary>
/// Exactly double the value of the constant <see cref="Pi"/>. Unlike
/// <see cref="HalfPi"/>, there are circumstances where this constant is preferrable
/// over its actual value of <c><see cref="Pi"/> * 2</c>.
/// </summary>
/// <remarks>See also: <see href="https://en.wikipedia.org/wiki/Pi">Pi - Wikipedia</see></remarks>
public const float Tau = Pi * 2;
/// <summary>
/// <c>E</c> is also known as Euler's number or the natural number. This constant
/// has a very large number of interpretations and uses.
/// </summary>
/// <remarks>See also: <see href="https://en.wikipedia.org/wiki/E_(mathematical_constant)">e (mathematical constant) - Wikipedia</see></remarks>
public const float E = 2.71828182846f;
/// <summary>
/// The limit of the summed error between the harmonic series and the natural logarithm.
/// </summary>
/// <remarks>See also: <see href="https://en.wikipedia.org/wiki/Euler%27s_constant">Euler's constant - Wikipedia</see></remarks>
public const float EulerConstant = 0.5772156649f;
/// <summary>
/// The natural logarithm of 2. It is a trancendental number.
/// </summary>
/// <remarks>
/// See also: <see href="https://en.wikipedia.org/wiki/Natural_logarithm_of_2">Natural logarithm of 2 - Wikipedia</see><br/>
/// See also: <see href="https://en.wikipedia.org/wiki/Natural_logarithm">Natural logarithm - Wikipedia</see>
/// </remarks>
public const float Ln2 = 0.69314718056f;
/// <summary>
/// The natural logarithm of 3. It is a trancendental number.
/// </summary>
/// <remarks>See also: <see href="https://en.wikipedia.org/wiki/Natural_logarithm">Natural logarithm - Wikipedia</see></remarks>
public const float Ln3 = 1.09861228867f;
/// <summary>
/// The natural logarithm of 5. It is a trancendental number.
/// </summary>
/// <remarks>See also: <see href="https://en.wikipedia.org/wiki/Natural_logarithm">Natural logarithm - Wikipedia</see></remarks>
public const float Ln5 = 1.60943791243f;
/// <summary>
/// The natural logarithm of 10. It is a trancendental number.
/// </summary>
/// <remarks>See also: <see href="https://en.wikipedia.org/wiki/Natural_logarithm">Natural logarithm - Wikipedia</see></remarks>
public const float Ln10 = 2.30258509299f;
/// <summary>
/// The logarithm (base 10) of 2.
/// </summary>
public const float Log2 = 0.301029995664f;
/// <summary>
/// The logarithm (base 10) of 3.
/// </summary>
public const float Log3 = 0.47712125472f;
/// <summary>
/// The logarithm (base 10) of 5.
/// </summary>
public const float Log5 = 0.698970004336f;
/// <summary>
/// The logarithm (base 10) of 10.
/// </summary>
public const float Log10 = 1;
/// <summary>
/// The resulting smallest angle when you apply the golden ratio to a circle (in degrees).
/// </summary>
/// <remarks>See also: <see href="https://en.wikipedia.org/wiki/Golden_angle">Golden angle - Wikipedia</see></remarks>
public const float GoldenAngle = 180 * (3 - Sqrt5);
public const float GoldenRatio = (1 + Sqrt5) / 2;
public const float SilverRatio = Sqrt2 + 1;