diff --git a/Nerd_STF/Extensions/EquationExtension.cs b/Nerd_STF/Extensions/EquationExtension.cs index dd3be8e..473b454 100644 --- a/Nerd_STF/Extensions/EquationExtension.cs +++ b/Nerd_STF/Extensions/EquationExtension.cs @@ -20,6 +20,9 @@ public static class EquationExtension public static Equation Absolute(this Equation equ) => x => Mathf.Absolute(equ(x)); public static Equation AbsoluteMod(this Equation equ, float mod) => x => Mathf.AbsoluteMod(equ(x), mod); + public static Equation Add(this Equation equ, float offset) => x => equ(x) + offset; + public static Equation Add(this Equation equ, Equation offset) => x => equ(x) + offset(x); + public static Equation ArcCos(this Equation equ) => x => Mathf.ArcCos(equ(x)).Radians; public static Equation ArcCot(this Equation equ) => x => Mathf.ArcCot(equ(x)).Radians; public static Equation ArcCsc(this Equation equ) => x => Mathf.ArcCsc(equ(x)).Radians; @@ -65,7 +68,8 @@ public static class EquationExtension public static Equation Coth(this Equation equ) => x => Mathf.Coth(equ(x)); public static Equation Csch(this Equation equ) => x => Mathf.Csch(equ(x)); - // todo: add divide, multiply, add, subtract + public static Equation Divide(this Equation equ, float factor) => x => equ(x) / factor; + public static Equation Divide(this Equation equ, Equation factor) => x => equ(x) / factor(x); public static Equation Factorial(this Equation equ) => x => Mathf.Factorial((int)equ(x)); @@ -100,6 +104,9 @@ public static class EquationExtension public static float Min(this Equation equ, float min, float max, float step = Calculus.DefaultStep) => Mathf.Min(equ, min, max, step); + public static Equation Multiply(this Equation equ, float factor) => x => equ(x) * factor; + public static Equation Multiply(this Equation equ, Equation factor) => x => equ(x) * factor(x); + public static Equation Permutations(this Equation equ, int size) => x => Mathf.Permutations(size, (int)equ(x)); public static Equation Permutations(this Equation equ, Equation size) => @@ -108,6 +115,9 @@ public static class EquationExtension public static Equation Power(this Equation equ, float pow) => x => Mathf.Power(equ(x), pow); public static Equation Power(this Equation equ, Equation pow) => x => Mathf.Power(equ(x), pow(x)); + public static float Product(this Equation equ, float lower, float upper, float step = 1) => + Mathf.Product(equ, lower, upper, step); + public static Equation Root(this Equation equ, float index) => x => Mathf.Root(equ(x), index); public static Equation Root(this Equation equ, Equation index) => x => Mathf.Root(equ(x), index(x)); @@ -131,6 +141,12 @@ public static class EquationExtension public static Equation Sqrt(this Equation equ) => x => Mathf.Sqrt(equ(x)); + public static Equation Subtract(this Equation equ, float offset) => x => equ(x) - offset; + public static Equation Subtract(this Equation equ, Equation offset) => x => equ(x) - offset(x); + + public static float Sum(this Equation equ, float lower, float upper, float step = 1) => + Mathf.Sum(equ, lower, upper, step); + public static Equation Tan(this Equation equ) => x => Mathf.Tan(equ(x)); public static Equation Tanh(this Equation equ) => x => Mathf.Tanh(equ(x)); diff --git a/Nerd_STF/Mathematics/Algebra/Matrix2x2.cs b/Nerd_STF/Mathematics/Algebra/Matrix2x2.cs index 8025e93..d26f8dc 100644 --- a/Nerd_STF/Mathematics/Algebra/Matrix2x2.cs +++ b/Nerd_STF/Mathematics/Algebra/Matrix2x2.cs @@ -169,7 +169,12 @@ public class Matrix2x2 : ICloneable, IStaticMatrix public static Matrix2x2 Absolute(Matrix2x2 val) => new(Mathf.Absolute(val.r1c1), Mathf.Absolute(val.r1c2), Mathf.Absolute(val.r2c1), Mathf.Absolute(val.r2c2)); - public static Matrix2x2 Average(params Matrix2x2[] vals) => Sum(vals) / vals.Length; + public static Matrix2x2 Average(params Matrix2x2[] vals) + { + Matrix2x2 sum = Zero; + foreach (Matrix2x2 m in vals) sum += m; + return sum / vals.Length; + } public static Matrix2x2 Ceiling(Matrix2x2 val) => new(Mathf.Ceiling(val.r1c1), Mathf.Ceiling(val.r1c2), Mathf.Ceiling(val.r2c1), Mathf.Ceiling(val.r2c2)); public static Matrix2x2 Clamp(Matrix2x2 val, Matrix2x2 min, Matrix2x2 max) => diff --git a/Nerd_STF/Mathematics/Algebra/Matrix3x3.cs b/Nerd_STF/Mathematics/Algebra/Matrix3x3.cs index 312fe8e..dfcdda3 100644 --- a/Nerd_STF/Mathematics/Algebra/Matrix3x3.cs +++ b/Nerd_STF/Mathematics/Algebra/Matrix3x3.cs @@ -257,7 +257,12 @@ public class Matrix3x3 : ICloneable, IStaticMatrix new(Mathf.Absolute(val.r1c1), Mathf.Absolute(val.r1c2), Mathf.Absolute(val.r1c3), Mathf.Absolute(val.r2c1), Mathf.Absolute(val.r2c2), Mathf.Absolute(val.r2c3), Mathf.Absolute(val.r3c1), Mathf.Absolute(val.r3c2), Mathf.Absolute(val.r3c3)); - public static Matrix3x3 Average(params Matrix3x3[] vals) => Sum(vals) / vals.Length; + public static Matrix3x3 Average(params Matrix3x3[] vals) + { + Matrix3x3 sum = Zero; + foreach (Matrix3x3 m in vals) sum += m; + return sum / vals.Length; + } public static Matrix3x3 Ceiling(Matrix3x3 val) => new(Mathf.Ceiling(val.r1c1), Mathf.Ceiling(val.r1c2), Mathf.Ceiling(val.r1c3), Mathf.Ceiling(val.r2c1), Mathf.Ceiling(val.r2c2), Mathf.Ceiling(val.r2c3), diff --git a/Nerd_STF/Mathematics/Algebra/Matrix4x4.cs b/Nerd_STF/Mathematics/Algebra/Matrix4x4.cs index 9a34a2c..db00dbf 100644 --- a/Nerd_STF/Mathematics/Algebra/Matrix4x4.cs +++ b/Nerd_STF/Mathematics/Algebra/Matrix4x4.cs @@ -303,7 +303,12 @@ public class Matrix4x4 : ICloneable, IStaticMatrix Mathf.Absolute(val.r2c1), Mathf.Absolute(val.r2c2), Mathf.Absolute(val.r2c3), Mathf.Absolute(val.r2c4), Mathf.Absolute(val.r3c1), Mathf.Absolute(val.r3c2), Mathf.Absolute(val.r3c3), Mathf.Absolute(val.r3c4), Mathf.Absolute(val.r4c1), Mathf.Absolute(val.r4c2), Mathf.Absolute(val.r4c3), Mathf.Absolute(val.r4c4)); - public static Matrix4x4 Average(params Matrix4x4[] vals) => Sum(vals) / vals.Length; + public static Matrix4x4 Average(params Matrix4x4[] vals) + { + Matrix4x4 sum = Zero; + foreach (Matrix4x4 m in vals) sum += m; + return sum / vals.Length; + } public static Matrix4x4 Ceiling(Matrix4x4 val) => new(Mathf.Ceiling(val.r1c1), Mathf.Ceiling(val.r1c2), Mathf.Ceiling(val.r1c3), Mathf.Ceiling(val.r1c4), Mathf.Ceiling(val.r2c1), Mathf.Ceiling(val.r2c2), Mathf.Ceiling(val.r2c3), Mathf.Ceiling(val.r2c4), diff --git a/Nerd_STF/Mathematics/Algebra/Vector2d.cs b/Nerd_STF/Mathematics/Algebra/Vector2d.cs index e8f8cdf..540a4ee 100644 --- a/Nerd_STF/Mathematics/Algebra/Vector2d.cs +++ b/Nerd_STF/Mathematics/Algebra/Vector2d.cs @@ -4,8 +4,7 @@ public record struct Vector2d : IAbsolute, IAverage, IClampMagnitude, IComparable, ICross, IDot, IEquatable, IFromTuple, ILerp, IMax, IMagnitude, IMedian, IMin, - IPresets2d, ISplittable, ISubtract, - ISum + IPresets2d, ISplittable { public static Vector2d Down => new(Angle.Down); public static Vector2d Left => new(Angle.Left); @@ -84,18 +83,6 @@ public record struct Vector2d : IAbsolute, IAverage, } public static Vector2d Round(Vector2d val, Angle.Type angleRound = Angle.Type.Degrees) => new(Angle.Round(val.theta, angleRound), Mathf.Round(val.magnitude)); - public static Vector2d Subtract(Vector2d num, params Vector2d[] vals) - { - foreach (Vector2d v in vals) num -= v; - return num; - } - public static Vector2d Sum(params Vector2d[] vals) - { - if (vals.Length < 1) return Zero; - Vector2d val = One; - foreach (Vector2d v in vals) val += v; - return val; - } public static (Angle[] rots, float[] mags) SplitArray(params Vector2d[] vals) { diff --git a/Nerd_STF/Mathematics/Algebra/Vector3d.cs b/Nerd_STF/Mathematics/Algebra/Vector3d.cs index 2aaa603..f145c7d 100644 --- a/Nerd_STF/Mathematics/Algebra/Vector3d.cs +++ b/Nerd_STF/Mathematics/Algebra/Vector3d.cs @@ -4,7 +4,7 @@ public record struct Vector3d : IAbsolute, IAverage, IClampM IComparable, ICross, IDot, IEquatable, IFromTuple, IIndexAll, IIndexRangeAll, ILerp, IMagnitude, IMax, IMedian, IMin, - IPresets3d, ISubtract, ISum + IPresets3d { public static Vector3d Back => new(Angle.Zero, Angle.Up); public static Vector3d Down => new(Angle.Down, Angle.Zero); @@ -142,18 +142,6 @@ public record struct Vector3d : IAbsolute, IAverage, IClampM } public static Vector3d Round(Vector3d val, Angle.Type angleRound = Angle.Type.Degrees) => new(Angle.Round(val.yaw, angleRound), Angle.Round(val.pitch, angleRound), Mathf.Round(val.magnitude)); - public static Vector3d Subtract(Vector3d num, params Vector3d[] vals) - { - foreach (Vector3d v in vals) num -= v; - return num; - } - public static Vector3d Sum(params Vector3d[] vals) - { - if (vals.Length < 1) return Zero; - Vector3d val = One; - foreach (Vector3d v in vals) val += v; - return val; - } public static (Angle[] yaws, Angle[] pitches, float[] mags) SplitArray(params Vector3d[] vals) { diff --git a/Nerd_STF/Mathematics/Float2.cs b/Nerd_STF/Mathematics/Float2.cs index 72f26b3..70315aa 100644 --- a/Nerd_STF/Mathematics/Float2.cs +++ b/Nerd_STF/Mathematics/Float2.cs @@ -79,7 +79,12 @@ public record struct Float2 : IAbsolute, IAverage, ICeiling new(Mathf.Absolute(val.x), Mathf.Absolute(val.y)); - public static Float2 Average(params Float2[] vals) => Sum(vals) / vals.Length; + public static Float2 Average(params Float2[] vals) + { + Float2 sum = Zero; + foreach (Float2 f in vals) sum += f; + return sum / vals.Length; + } public static Int2 Ceiling(Float2 val) => new(Mathf.Ceiling(val.x), Mathf.Ceiling(val.y)); public static Float2 Clamp(Float2 val, Float2 min, Float2 max) => diff --git a/Nerd_STF/Mathematics/Float3.cs b/Nerd_STF/Mathematics/Float3.cs index 72d6d01..ee1ce2d 100644 --- a/Nerd_STF/Mathematics/Float3.cs +++ b/Nerd_STF/Mathematics/Float3.cs @@ -119,7 +119,12 @@ public record struct Float3 : IAbsolute, IAverage, public static Float3 Absolute(Float3 val) => new(Mathf.Absolute(val.x), Mathf.Absolute(val.y), Mathf.Absolute(val.z)); - public static Float3 Average(params Float3[] vals) => Sum(vals) / vals.Length; + public static Float3 Average(params Float3[] vals) + { + Float3 sum = Zero; + foreach (Float3 f in vals) sum += f; + return sum / vals.Length; + } public static Int3 Ceiling(Float3 val) => new(Mathf.Ceiling(val.x), Mathf.Ceiling(val.y), Mathf.Ceiling(val.z)); public static Float3 Clamp(Float3 val, Float3 min, Float3 max) => diff --git a/Nerd_STF/Mathematics/Float4.cs b/Nerd_STF/Mathematics/Float4.cs index 17e8482..2f0ba3a 100644 --- a/Nerd_STF/Mathematics/Float4.cs +++ b/Nerd_STF/Mathematics/Float4.cs @@ -194,7 +194,12 @@ public record struct Float4 : IAbsolute, public static Float4 Absolute(Float4 val) => new(Mathf.Absolute(val.x), Mathf.Absolute(val.y), Mathf.Absolute(val.z), Mathf.Absolute(val.w)); - public static Float4 Average(params Float4[] vals) => Sum(vals) / vals.Length; + public static Float4 Average(params Float4[] vals) + { + Float4 sum = Zero; + foreach (Float4 f in vals) sum += f; + return sum / vals.Length; + } public static Int4 Ceiling(Float4 val) => new(Mathf.Ceiling(val.x), Mathf.Ceiling(val.y), Mathf.Ceiling(val.z), Mathf.Ceiling(val.w)); public static Float4 Clamp(Float4 val, Float4 min, Float4 max) => diff --git a/Nerd_STF/Mathematics/Int2.cs b/Nerd_STF/Mathematics/Int2.cs index 440027d..ea69be9 100644 --- a/Nerd_STF/Mathematics/Int2.cs +++ b/Nerd_STF/Mathematics/Int2.cs @@ -77,7 +77,12 @@ public record struct Int2 : IAbsolute, IAverage, IClamp, IClam public static Int2 Absolute(Int2 val) => new(Mathf.Absolute(val.x), Mathf.Absolute(val.y)); - public static Int2 Average(params Int2[] vals) => Sum(vals) / vals.Length; + public static Int2 Average(params Int2[] vals) + { + Int2 sum = Zero; + foreach (Int2 i in vals) sum += i; + return sum / vals.Length; + } public static Int2 Clamp(Int2 val, Int2 min, Int2 max) => new(Mathf.Clamp(val.x, min.x, max.x), Mathf.Clamp(val.y, min.y, max.y)); diff --git a/Nerd_STF/Mathematics/Int3.cs b/Nerd_STF/Mathematics/Int3.cs index 69a10f9..3fcdff5 100644 --- a/Nerd_STF/Mathematics/Int3.cs +++ b/Nerd_STF/Mathematics/Int3.cs @@ -116,7 +116,12 @@ public record struct Int3 : IAbsolute, IAverage, IClamp, IClam public static Int3 Absolute(Int3 val) => new(Mathf.Absolute(val.x), Mathf.Absolute(val.y), Mathf.Absolute(val.z)); - public static Int3 Average(params Int3[] vals) => Sum(vals) / vals.Length; + public static Int3 Average(params Int3[] vals) + { + Int3 sum = Zero; + foreach (Int3 i in vals) sum += i; + return sum / vals.Length; + } public static Int3 Clamp(Int3 val, Int3 min, Int3 max) => new(Mathf.Clamp(val.x, min.x, max.x), Mathf.Clamp(val.y, min.y, max.y), diff --git a/Nerd_STF/Mathematics/Int4.cs b/Nerd_STF/Mathematics/Int4.cs index 1cc576b..5a7c99e 100644 --- a/Nerd_STF/Mathematics/Int4.cs +++ b/Nerd_STF/Mathematics/Int4.cs @@ -191,7 +191,12 @@ public record struct Int4 : IAbsolute, IAverage, IClamp, IClam public static Int4 Absolute(Int4 val) => new(Mathf.Absolute(val.x), Mathf.Absolute(val.y), Mathf.Absolute(val.z), Mathf.Absolute(val.w)); - public static Int4 Average(params Int4[] vals) => Sum(vals) / vals.Length; + public static Int4 Average(params Int4[] vals) + { + Int4 sum = Zero; + foreach (Int4 i in vals) sum += i; + return sum / vals.Length; + } public static Int4 Clamp(Int4 val, Int4 min, Int4 max) => new(Mathf.Clamp(val.x, min.x, max.x), Mathf.Clamp(val.y, min.y, max.y), diff --git a/Nerd_STF/Mathematics/Mathf.cs b/Nerd_STF/Mathematics/Mathf.cs index ba83714..132f1df 100644 --- a/Nerd_STF/Mathematics/Mathf.cs +++ b/Nerd_STF/Mathematics/Mathf.cs @@ -47,8 +47,18 @@ public static class Mathf for (float x = min; x <= max; x += step) vals.Add(equ(x)); return Average(vals.ToArray()); } - public static float Average(params float[] vals) => Sum(vals) / vals.Length; - public static int Average(params int[] vals) => Sum(vals) / vals.Length; + public static float Average(params float[] vals) + { + float sum = 0; + foreach (float f in vals) sum += f; + return sum / vals.Length; + } + public static int Average(params int[] vals) + { + int sum = 0; + foreach (int i in vals) sum += i; + return sum / vals.Length; + } public static float Binomial(int n, int total, float successRate) => Combinations(total, n) * Power(successRate, n) * Power(1 - successRate, total - n); @@ -98,20 +108,20 @@ public static class Mathf public static float Dot(float[] a, float[] b) { if (a.Length != b.Length) throw new InvalidSizeException("Both arrays must have the same length"); - float[] vals = new float[a.Length]; - for (int i = 0; i < a.Length; i++) vals[i] = a[i] * b[i]; - return Sum(vals); + float sum = 0; + for (int i = 0; i < a.Length; i++) sum += a[i] * b[i]; + return sum; } public static float Dot(params float[][] vals) { - float[] res = new float[vals[0].Length]; - for (int i = 0; i < res.Length; i++) + float sum = 0; + for (int i = 0; i < vals[0].Length; i++) { float m = 1; for (int j = 0; j < vals.Length; j++) m *= vals[j][i]; - res[i] = m; + sum += m; } - return Sum(res); + return sum; } public static int Factorial(int amount) @@ -162,7 +172,12 @@ public static class Mathf _ => throw new ArgumentException("Unknown prime check method.", nameof(method)) }; - public static int LeastCommonMultiple(params int[] vals) => Product(vals) / GreatestCommonFactor(vals); + public static int LeastCommonMultiple(params int[] vals) + { + int product = 1; + foreach (int i in vals) product *= i; + return product / GreatestCommonFactor(vals); + } public static float Lerp(float a, float b, float t, bool clamp = true) { @@ -376,6 +391,13 @@ public static class Mathf return val; } + public static float Product(Equation equ, float lower, float upper, float step = 1) + { + float result = 0; + for (float f = lower; f < upper; f += step) result *= equ(f); + return result; + } + public static float Root(float value, float index) => (float)Math.Exp(Math.Log(value) / index); public static float Round(float num) => num % 1 >= 0.5 ? Ceiling(num) : Floor(num); @@ -491,11 +513,16 @@ public static class Mathf public static float Sqrt(float value) => SolveNewton(x => x * x - value, 1); - // TODO: include equation product and sum - // Known as stdev public static float StandardDeviation(params float[] vals) => Sqrt(Variance(vals)); + public static float Sum(Equation equ, float lower, float upper, float step = 1) + { + float result = 0; + for (float f = lower; f < upper; f += step) result += equ(f); + return result; + } + public static float Tan(Angle angle) => Tan(angle.Radians); public static float Tan(float radians) => Sin(radians) / Cos(radians); diff --git a/Nerd_STF/Mathematics/NumberSystems/Quaternion.cs b/Nerd_STF/Mathematics/NumberSystems/Quaternion.cs index ea95b02..7427bda 100644 --- a/Nerd_STF/Mathematics/NumberSystems/Quaternion.cs +++ b/Nerd_STF/Mathematics/NumberSystems/Quaternion.cs @@ -7,7 +7,7 @@ public record struct Quaternion(float u, float i, float j, float k) : IAbsolute< IDot, IEquatable, IFloor, IGroup, IIndexAll, IIndexRangeAll, ILerp, IMax, IMedian, IMin, IPresets4d, IRound, - ISplittable, + ISplittable { public static Quaternion Back => new(0, 0, -1, 0); public static Quaternion Down => new(0, -1, 0, 0); diff --git a/Nerd_STF/Mathematics/Rational.cs b/Nerd_STF/Mathematics/Rational.cs index 6f655a8..429355a 100644 --- a/Nerd_STF/Mathematics/Rational.cs +++ b/Nerd_STF/Mathematics/Rational.cs @@ -79,7 +79,24 @@ public readonly record struct Rational : IAbsolute, IAverage public static Rational Absolute(Rational value) => new(Mathf.Absolute(value.numerator), value.denominator); - public static Rational Average(params Rational[] vals) => Sum(vals) / (float)vals.Length; + public static Rational Average(params Rational[] vals) + { + // TODO: this doesn't work. + + int[] denominators = new int[vals.Length]; + for (int i = 0; i < vals.Length; i++) denominators[i] = vals[i].denominator; + + int lcm = Mathf.LeastCommonMultiple(denominators); + int sumNum = 0, sumDen = lcm * vals.Length; + + foreach (Rational r in vals) + { + int scale = lcm / r.denominator; + sumNum += r.numerator * scale; + } + + return new(sumNum / vals.Length, sumDen); + } public static int Ceiling(Rational r) { int mod = r.numerator % r.denominator; diff --git a/Nerd_STF/NDArray.cs b/Nerd_STF/NDArray.cs index 56c799f..49545dc 100644 --- a/Nerd_STF/NDArray.cs +++ b/Nerd_STF/NDArray.cs @@ -38,21 +38,32 @@ public class NDArray : IEnumerable, IEquatable> sizes = new int[dimensions]; Array.Fill(sizes, allLengths); - arr = new T[Mathf.Product(sizes)]; + long allSizes = 1; + foreach (int i in sizes) allSizes *= i; + + arr = new T[allSizes]; } public NDArray(int[] lengths) { - arr = new T[Mathf.Product(lengths)]; dimensions = lengths.Length; sizes = lengths; + + long allSizes = 1; + foreach (int i in sizes) allSizes *= i; + + arr = new T[allSizes]; } public NDArray(int dimensions, int[] lengths) { if (dimensions != lengths.Length) throw new InvalidSizeException("Dimension count doesn't match length count."); - arr = new T[Mathf.Product(lengths)]; this.dimensions = lengths.Length; sizes = lengths; + + long allSizes = 1; + foreach (int i in sizes) allSizes *= i; + + arr = new T[allSizes]; } public NDArray(T[] items, int[] lengths) { @@ -60,17 +71,30 @@ public class NDArray : IEnumerable, IEquatable> dimensions = lengths.Length; sizes = lengths; - if (arr.Length != Mathf.Product(lengths)) throw new InvalidSizeException("Too many or too few items were provided."); + long allSizes = 1; + foreach (int i in sizes) allSizes *= i; + + arr = new T[allSizes]; + + if (arr.Length != allSizes) + throw new InvalidSizeException("Too many or too few items were provided."); } public NDArray(T[] items, int dimensions, int[] lengths) { - if (dimensions != lengths.Length) throw new InvalidSizeException("Dimension count doesn't match length count."); + if (dimensions != lengths.Length) + throw new InvalidSizeException("Dimension count doesn't match length count."); arr = items; this.dimensions = lengths.Length; sizes = lengths; - if (arr.Length != Mathf.Product(lengths)) throw new InvalidSizeException("Too many or too few items were provided."); + long allSizes = 1; + foreach (int i in sizes) allSizes *= i; + + arr = new T[allSizes]; + + if (arr.Length != allSizes) + throw new InvalidSizeException("Too many or too few items were provided."); } public T this[params int[] indexes] @@ -81,7 +105,8 @@ public class NDArray : IEnumerable, IEquatable> private int FlattenIndex(params int[] indexes) { - if (indexes.Length != sizes.Length) throw new InvalidSizeException("Too many or too few indexes were provided."); + if (indexes.Length != sizes.Length) + throw new InvalidSizeException("Too many or too few indexes were provided."); int ind = indexes[^1]; Console.WriteLine($"Start at {ind}");