diff --git a/Changelog.md b/Changelog.md index f0ca60f..2611457 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,150 +1,106 @@ -# Nerd_STF v2.3.1.52 +# Nerd_STF v2.3.1 -***Read this to know what works and what doesn't!*** +***Everything has been tested and most things work!*** + +**WARNING:** +All of the matrix classes have had all of their constructors' row and column variables swapped. You'll have to switch all your variables around. +Sorry for the inconvenience :(. The `v2.3.1.x` updates go through every single field and method in Nerd_STF to make sure it works correctly. You see, up until now I haven't actually tested literally anything at all. Partly because I didn't have the tools to and partly because I was lazy. But now, it's guarenteed to work in most cases (unless I like don't pick up some bug, you know). -The following types have been checked for the most part and can be safe to use: -- `Nerd_STF.FileType` -- `Nerd_STF.Fill` -- `Nerd_STF.Fill2D` -- `Nerd_STF.Foreach` -- `Nerd_STF.IClosest` -- `Nerd_STF.IContainer` -- `Nerd_STF.IEncapsulator` -- `Nerd_STF.IGroup` -- `Nerd_STF.IGroup2D` -- `Nerd_STF.Logger` -- `Nerd_STF.LogMessage` -- `Nerd_STF.LogSeverity` -- `Nerd_STF.Modifier` -- `Nerd_STF.Modifier2D` -- `Nerd_STF.Exceptions.DifferingVertCountException` -- `Nerd_STF.Exceptions.DisconnectedLinesException` -- `Nerd_STF.Exceptions.InvalidSizeException` -- `Nerd_STF.Exceptions.Nerd_STFException` -- `Nerd_STF.Exceptions.NoInverseException` -- `Nerd_STF.Extensions.Container2DExtension` -- `Nerd_STF.Extensions.ConversionExtension` -- `Nerd_STF.Extensions.EquationExtension` -- `Nerd_STF.Extensions.ToFillExtension` -- `Nerd_STF.Graphics.CMYKA` -- `Nerd_STF.Graphics.CMYKAByte` -- `Nerd_STF.Graphics.ColorChannel` -- `Nerd_STF.Graphics.HSVA` -- `Nerd_STF.Graphics.HSVAByte` -- `Nerd_STF.Graphics.IColor` -- `Nerd_STF.Graphics.IColorByte` -- `Nerd_STF.Graphics.IlluminationFlags` -- `Nerd_STF.Graphics.IlluminationModel` -- `Nerd_STF.Graphics.Image` -- `Nerd_STF.Graphics.Material` -- `Nerd_STF.Graphics.RGBA` -- `Nerd_STF.Graphics.RGBAByte` -- `Nerd_STF.Graphics.TextureConfig` -- `Nerd_STF.Mathematics.Angle` -- `Nerd_STF.Mathematics.Calculus` -- `Nerd_STF.Mathematics.Equation` -- `Nerd_STF.Mathematics.Float2` -- `Nerd_STF.Mathematics.Float3` -- `Nerd_STF.Mathematics.Float4` -- `Nerd_STF.Mathematics.Int2` -- `Nerd_STF.Mathematics.Int3` -- `Nerd_STF.Mathematics.Int4` -- `Nerd_STF.Mathematics.Mathf` -- `Nerd_STF.Mathematics.Geometry.ISubdividable` -- `Nerd_STF.Mathematics.NumberSystems.Complex` -- `Nerd_STF.Mathematics.NumberSystems.Quaternion` -- `Nerd_STF.Mathematics.Samples.Constants` -- `Nerd_STF.Mathematics.Samples.Equations` +Hi everyone! Everything has been checked now and most stuff works! Not everything, like the triangle and quadrilateral area stuff, but for the most part, it's all cool and good. -The following types haven't been checked yet, and should still be taken with a grain of salt: -- `Nerd_STF.Mathematics.Algebra.IMatrix` -- `Nerd_STF.Mathematics.Algebra.Matrix` -- `Nerd_STF.Mathematics.Algebra.Matrix2x2` -- `Nerd_STF.Mathematics.Algebra.Matrix3x3` -- `Nerd_STF.Mathematics.Algebra.Matrix4x4` -- `Nerd_STF.Mathematics.Algebra.Vector2d` -- `Nerd_STF.Mathematics.Algebra.Vector3d` -- `Nerd_STF.Mathematics.Geometry.Box2D` -- `Nerd_STF.Mathematics.Geometry.Box3D` -- `Nerd_STF.Mathematics.Geometry.ITriangulatable` -- `Nerd_STF.Mathematics.Geometry.Line` -- `Nerd_STF.Mathematics.Geometry.Polygon` -- `Nerd_STF.Mathematics.Geometry.Quadrilateral` -- `Nerd_STF.Mathematics.Geometry.Sphere` -- `Nerd_STF.Mathematics.Geometry.Triangle` -- `Nerd_STF.Mathematics.Geometry.Vert` +I've just now remembered how bad the Polygon struct was. It's getting remade. The v2.4.0 update will be mostly geometry focused, so that'll be the best time to figure out how to fix this stuff. The new Polygon struct will be much better, trust me. -16 left to go. +But all the matrix structs work like charm now! I'm honestly suprised they worked as well as they did before (especially the dynamic matrix). They can now be relied on. -Honestly, most of the time taken for this update was spent on Quaternions. Turns out my multiply function was subtley wrong. Who knew! -Just a relief to be done with it. The other stuff wasn't too much of a problem. Matrixes are probably going to be a huge pain if they don't work first try, though. That'll be in the next update, probably. - -I should also note that I just realized after way to long that the `.csproj` file isn't included in the Github. It's included in this new release, and sometime in the future I'll go back and add a correctly working `.csproj` file to all the other releases as well (with the exception of the legacy Nerd_STF 2021 versions likely. We'll see). I'll now not include the `/bin` build files. They'll be in the release and you can build it yourself if you need to now. Anyway, have fun. +Next up is the documentation update. Stay tuned! +(This may be another update with beta parts, but I'm not sure yet. We'll see). ``` * Nerd_STF + * Exceptions + * DifferingVertCountException + = Marked as deprecated (uses deprecated struct `Polygon`) * Extensions * Container2DExtension - = Fixed `Flatten(T[,], Int2)` - = `GetColumn(T[,], int, int)` and `GetRow(T[,], int, int)` have been fixed (They had swapped roles) - * ConversionExtension - + ToFill(T[]) - + ToFill(T[,], Int2) - + ToFill2D(T[,]) - * EquationExtension - = Fixed `Scale(Equation, float, ScaleType)` by swapping all instances of `x` and `value` (oops) - = Moved `ScaleType` out of parent class `EquationExtension` and into namespace `Nerd_STF` - * Geometry - * ITriangulatable - + TriangulateAll(T[]) where T : ITriangulatable - * Graphics - + Renamed `IColor` to `IColorFloat` - = Made IColor an object both `IColorFloat` and `IColorByte` inherit from. - * CMYKA - = Made `ToRGBA()` include the alpha value of the color. - * CMYKAByte - = In `ToHSVA()` and `ToHSVAByte()`, swapped some conversions from `RGBA` to `CMYKA` - * HSVA - = Made `ToRGBA()` include the alpha value of the color. - * Image - - Removed some useless constructors - = Fixed some broken constructors + + GetSize(T[,]) + + SwapDimensions(T[,], Int2?) + * Flatten(T[,]) + = Replaced a `size` parameter from an `Int2` to an `Int2?` * Mathematics * Algebra - * Vector2d - = Removed a default parameter value in `ToString(Angle.Type)` to prevent confusion. - * Vector3d - + string ToString() - + string ToString(Angle.Type) - + string ToString(IFormatProvider, Angle.Type) - = Fixed `ToXYZ()` - * NumberSystems - * Complex - + operator ~(Complex) - * Quaternion - + Rotate(Float3) - + Rotate(Vector3d) - + operator ~(Quaternion) - - ToVector() - = Gave `IJK` proper get and set accessors. - = Renamed some terms in `ToString()` - = Fixed the `Quaternion.FromAngles(*)` methods to do the proper thing. - = Fixed `Quaternion.Rotate(Quaternion)` - = Fixed `Quaternion.Rotate(Float3)` - = Fixed `operator *(Quaternion, Quaternion)` - = Optimized `GetAxis()` - = Simplified `ToXYZ()` - = Swapped the order of `Rotate(Quaternion)` - = Made `GetAxis()` not accidentally create an infinite vector. - * Angle - + Complimentary - + Supplementary - * Float2 - + operator *(Float2, Quaternion) - * Float3 - + operator *(Float3, Quaternion) - = Fixed `ToVector()` + * IMatrix + - ToDictionary() + * Matrix + + Cofactor() + + IdentityIsh(Int2) + + MinorOf(Int2) + - ToDictionary() + = Fixed `Determinant()` + = Fixed `Minors()` + = Fixed `Inverse()` + = Made `Identity(Int2)` only work with square matricies (since that's only when an identity exists) + = Marked the struct as `readonly` + = Simplified `Transpose()` + = Swapped row variables with column variables in all constructors (and methods that require those constructors). + = Swapped code for `Adjugate()` with `Cofactor()` + * Matrix2x2 + + Cofactor() + + operator *(Matrix2x2, Float2) + + operator /(Matrix2x2, Float2) + - ToDictionary() + = Swapped code for `Adjugate()` with `Cofactor()` + = Swapped row variables with column variables in all constructors (and methods that require those constructors). + = Fixed `this[int, int]` to compensate for the swapped variables. + = Fixed `operator -(Matrix2x2, Matrix2x2)` to not have an addition in one of the variables (fun). + = Fixed `Inverse()` + = Fixed `explicit operator Matrix2x2(Matrix)` + * Matrix3x3 + + Cofactor() + + operator *(Matrix3x3, Float3) + + operator /(Matrix3x3, Float3) + - ToDictionary() + = Swapped code for `Adjugate()` with `Cofactor()` + = Swapped row variables with column variables in all constructors (and methods that require those constructors). + = Fixed `this[int, int]` to compensate for the swapped variables. + = Fixed `Determinant()` + = Fixed `Inverse()` + = Fixed `explicit operator Matrix3x3(Matrix)` + * Matrix4x4 + + Cofactor() + + override string ToString() + + operator *(Matrix4x4, Float4) + + operator /(Matrix4x4, Float4) + - ToDictionary() + = Swapped code for `Adjugate()` with `Cofactor()` + = Swapped row variables with column variables in all constructors (and methods that require those constructors). + = Fixed `this[int, int]` to compensate for the swapped variables. + = Fixed `Determinant()` + = Fixed a typo in `Absolute(Matrix4x4)`, `Ceiling(Matrix4x4)`, `Floor(Matrix4x4)`, and `Round(Matrix4x4)` + = Fixed a typo in `Row1`, `Row2`, `Row3`, and `Row4`. Oops. + = Fixed some missing elements in `SplitArray(Matrix4x4[])` + = Fixed `explicit operator Matrix4x4(Matrix)` + * Geometry + * Box2D + = Simplified some code in `Perimeter` + * Box3D + + SurfaceArea + = Renamed `Area` to `Volume` + = Simplified some code in `Perimeter` + * Polygon + = Marked as deprecated (will be redone in v2.4.0) + = Simplified collection initialization in `Triangulate()` + * Quadrilateral + - explicit operator Triangle(Polygon) + = Marked `Area` as deprecated (uses deprecated `Triangle.Area` field) + * Sphere + = Fixed `ClosestTo(Vert)` + * Triangle + - explicit operator Triangle(Polygon) + = Marked `Area` as deprecated (will be fixed in v2.4.0) + * Vert + = Marked as deprecated (will be removed in v2.4.0). + = Optimized `Normalized` to not clone more than required. ``` diff --git a/Nerd_STF/Exceptions/DifferingVertCountException.cs b/Nerd_STF/Exceptions/DifferingVertCountException.cs index 361d82b..8dce0b3 100644 --- a/Nerd_STF/Exceptions/DifferingVertCountException.cs +++ b/Nerd_STF/Exceptions/DifferingVertCountException.cs @@ -3,6 +3,7 @@ namespace Nerd_STF.Exceptions; [Serializable] +[Obsolete("The Polygon struct is a garbage fire, and will be fixed in v2.4.0", false)] public class DifferingVertCountException : Nerd_STFException { public string? ParamName; diff --git a/Nerd_STF/Extensions/Container2DExtension.cs b/Nerd_STF/Extensions/Container2DExtension.cs index a2cbc7a..67ad7fa 100644 --- a/Nerd_STF/Extensions/Container2DExtension.cs +++ b/Nerd_STF/Extensions/Container2DExtension.cs @@ -2,10 +2,12 @@ public static class Container2DExtension { - public static T[] Flatten(this T[,] array, Int2 size) + public static T[] Flatten(this T[,] array, Int2? size = null) { - T[] res = new T[size.x * size.y]; - for (int x = 0; x < size.x; x++) for (int y = 0; y < size.y; y++) res[x + y * size.x] = array[y, x]; + size ??= GetSize(array); + T[] res = new T[size.Value.x * size.Value.y]; + for (int x = 0; x < size.Value.x; x++) for (int y = 0; y < size.Value.y; y++) + res[x + y * size.Value.x] = array[y, x]; return res; } @@ -21,4 +23,39 @@ public static class Container2DExtension for (int i = 0; i < length; i++) res[i] = array[row, i]; return res; } + + public static Int2 GetSize(this T[,] array) + { + Int2 size = Int2.Zero; + + try + { + while (true) + { + _ = array[size.x, 0]; + size.x++; + } + } + catch (IndexOutOfRangeException) { } + + try + { + while (true) + { + _ = array[0, size.y]; + size.y++; + } + } + catch (IndexOutOfRangeException) { } + + return size; + } + + public static T[,] SwapDimensions(this T[,] array, Int2? size = null) + { + size ??= GetSize(array); + T[,] vals = new T[size.Value.y, size.Value.x]; + for (int x = 0; x < size.Value.y; x++) for (int y = 0; y < size.Value.x; y++) vals[x, y] = array[y, x]; + return vals; + } } diff --git a/Nerd_STF/Mathematics/Algebra/IMatrix.cs b/Nerd_STF/Mathematics/Algebra/IMatrix.cs index 12aa38b..9e9339d 100644 --- a/Nerd_STF/Mathematics/Algebra/IMatrix.cs +++ b/Nerd_STF/Mathematics/Algebra/IMatrix.cs @@ -7,8 +7,6 @@ public interface IMatrix : ICloneable, IEnumerable, IEquatable, IGroup2D ToDictionary(); } public interface IMatrix : IMatrix where This : IMatrix diff --git a/Nerd_STF/Mathematics/Algebra/Matrix.cs b/Nerd_STF/Mathematics/Algebra/Matrix.cs index a0a16ae..0f7e827 100644 --- a/Nerd_STF/Mathematics/Algebra/Matrix.cs +++ b/Nerd_STF/Mathematics/Algebra/Matrix.cs @@ -1,8 +1,15 @@ namespace Nerd_STF.Mathematics.Algebra; -public struct Matrix : IMatrix +public readonly struct Matrix : IMatrix { public static Matrix Identity(Int2 size) + { + if (size.x != size.y) throw new InvalidSizeException("Can only create an identity matrix of a square matrix."); + Matrix m = Zero(size); + for (int i = 0; i < size.x; i++) m[i, i] = 1; + return m; + } + public static Matrix IdentityIsh(Int2 size) { Matrix m = Zero(size); int max = Mathf.Min(size.x, size.y); @@ -27,7 +34,7 @@ public struct Matrix : IMatrix array = new float[size.x, size.y]; if (all == 0) return; - for (int r = 0; r < size.y; r++) for (int c = 0; c < size.x; c++) array[c, r] = all; + for (int r = 0; r < size.x; r++) for (int c = 0; c < size.y; c++) array[r, c] = all; } public Matrix(Int2 size, float[] vals) { @@ -37,7 +44,7 @@ public struct Matrix : IMatrix if (vals.Length < size.x * size.y) throw new InvalidSizeException("Array must contain enough values to fill the matrix."); - for (int r = 0; r < size.y; r++) for (int c = 0; c < size.x; c++) array[c, r] = vals[c + r * size.y]; + for (int r = 0; r < size.x; r++) for (int c = 0; c < size.y; c++) array[r, c] = vals[c + r * size.y]; } public Matrix(Int2 size, int[] vals) { @@ -47,45 +54,45 @@ public struct Matrix : IMatrix if (vals.Length < size.x * size.y) throw new InvalidSizeException("Array must contain enough values to fill the matrix."); - for (int r = 0; r < size.y; r++) for (int c = 0; c < size.x; c++) array[c, r] = vals[c + r * size.y]; + for (int r = 0; r < size.x; r++) for (int c = 0; c < size.y; c++) array[r, c] = vals[c + r * size.y]; } public Matrix(Int2 size, Fill vals) { Size = size; array = new float[size.x, size.y]; - for (int r = 0; r < size.y; r++) for (int c = 0; c < size.x; c++) array[c, r] = vals(c + r * size.y); + for (int r = 0; r < size.x; r++) for (int c = 0; c < size.y; c++) array[r, c] = vals(c + r * size.y); } public Matrix(Int2 size, Fill vals) { Size = size; array = new float[size.x, size.y]; - for (int r = 0; r < size.y; r++) for (int c = 0; c < size.x; c++) array[c, r] = vals(c + r * size.y); + for (int r = 0; r < size.x; r++) for (int c = 0; c < size.y; c++) array[r, c] = vals(c + r * size.y); } public Matrix(Int2 size, float[,] vals) { Size = size; array = new float[size.x, size.y]; - for (int r = 0; r < size.y; r++) for (int c = 0; c < size.x; c++) array[c, r] = vals[c, r]; + for (int r = 0; r < size.x; r++) for (int c = 0; c < size.y; c++) array[r, c] = vals[r, c]; } public Matrix(Int2 size, int[,] vals) { Size = size; array = new float[size.x, size.y]; - for (int r = 0; r < size.y; r++) for (int c = 0; c < size.x; c++) array[c, r] = vals[c, r]; + for (int r = 0; r < size.x; r++) for (int c = 0; c < size.y; c++) array[r, c] = vals[r, c]; } public Matrix(Int2 size, Fill2D vals) { Size = size; array = new float[size.x, size.y]; - for (int r = 0; r < size.y; r++) for (int c = 0; c < size.x; c++) array[c, r] = vals(c, r); + for (int r = 0; r < size.x; r++) for (int c = 0; c < size.y; c++) array[r, c] = vals(r, c); } public Matrix(Int2 size, Fill2D vals) { Size = size; array = new float[size.x, size.y]; - for (int r = 0; r < size.y; r++) for (int c = 0; c < size.x; c++) array[c, r] = vals(c, r); + for (int r = 0; r < size.x; r++) for (int c = 0; c < size.y; c++) array[r, c] = vals(r, c); } public float this[int r, int c] @@ -135,37 +142,38 @@ public struct Matrix : IMatrix public void Apply(Modifier2D modifier) { - for (int r = 0; r < Size.y; r++) for (int c = 0; c < Size.x; c++) + for (int r = 0; r < Size.x; r++) for (int c = 0; c < Size.y; c++) array[r, c] = modifier(new(r, c), array[r, c]); } public float[] GetColumn(int column) { - float[] vals = new float[Size.y]; - for (int i = 0; i < Size.y; i++) vals[i] = array[i, column]; + float[] vals = new float[Size.x]; + for (int i = 0; i < Size.x; i++) vals[i] = array[i, column]; return vals; } public float[] GetRow(int row) { - float[] vals = new float[Size.x]; - for (int i = 0; i < Size.x; i++) vals[i] = array[row, i]; + float[] vals = new float[Size.y]; + for (int i = 0; i < Size.y; i++) vals[i] = array[row, i]; return vals; } public void SetColumn(int column, float[] vals) { - if (vals.Length < Size.y) + if (vals.Length < Size.x) throw new InvalidSizeException("Array must contain enough values to fill the column."); - for (int i = 0; i < Size.y; i++) array[i, column] = vals[i]; + for (int i = 0; i < Size.x; i++) array[i, column] = vals[i]; } public void SetRow(int row, float[] vals) { - if (vals.Length < Size.x) + if (vals.Length < Size.y) throw new InvalidSizeException("Array must contain enough values to fill the row."); - for (int i = 0; i < Size.x; i++) array[row, i] = vals[i]; + for (int i = 0; i < Size.y; i++) array[row, i] = vals[i]; } - - public Matrix Adjugate() + + public Matrix Adjugate() => Cofactor().Transpose(); + public Matrix Cofactor() { Matrix dets = new(Size); Matrix[,] minors = Minors(); @@ -175,12 +183,12 @@ public struct Matrix : IMatrix public float Determinant() { if (!IsSquare) throw new InvalidSizeException("Matrix must be square to calculate determinant."); - if (Size.x <= 0 || Size.y <= 0) return 0; - if (Size.x == 1 || Size.y == 1) return array[0, 0]; + if (Size.x <= 0) return 0; + if (Size.x == 1) return array[0, 0]; Matrix[] minors = Minors().GetRow(0, Size.x); float det = 0; - for (int i = 0; i < minors.Length; i++) det += minors[i].Determinant() * (i % 2 == 0 ? 1 : -1); + for (int i = 0; i < minors.Length; i++) det += array[0, i] * minors[i].Determinant() * (i % 2 == 0 ? 1 : -1); return det; } @@ -188,45 +196,30 @@ public struct Matrix : IMatrix { float d = Determinant(); if (d == 0) throw new NoInverseException(); - return Transpose().Adjugate() / d; + return Adjugate() / d; } public Matrix[,] Minors() { - // This will absolutely blow my mind if it works. - // Remember that whole "don't have a way to test" thing? - if (!HasMinors) return new Matrix[0,0]; - - Int2 newSize = Size - Int2.One; - Matrix[,] array = new Matrix[Size.x, Size.y]; - for (int r1 = 0; r1 < Size.y; r1++) for (int c1 = 0; c1 < Size.x; c1++) - { - Matrix m = new(newSize); - for (int r2 = 0; r2 < newSize.y; r2++) for (int c2 = 0; c2 < newSize.x; c2++) - { - int toSkip = c2 + r2 * newSize.y; - for (int r3 = 0; r3 < newSize.y; r3++) for (int c3 = 0; c3 < newSize.x; c3++) - { - if (r3 == r1 || c3 == c1) continue; - if (toSkip > 0) - { - toSkip--; - continue; - } - m[c2, r2] = this.array[c3, r3]; - break; - } - } - array[c1, r1] = m; - } - return array; + Matrix[,] minors = new Matrix[Size.x, Size.y]; + for (int r = 0; r < Size.x; r++) for (int c = 0; c < Size.y; c++) minors[r, c] = MinorOf(new(r, c)); + return minors; } public Matrix Transpose() { - Matrix m = new(new(Size.y, Size.x)); - for (int r = 0; r < Size.y; r++) m.SetColumn(r, GetRow(r)); - for (int c = 0; c < Size.x; c++) m.SetRow(c, GetColumn(c)); - return m; + Matrix @this = this; + return new(Size, (r, c) => @this[c, r]); + } + + public Matrix MinorOf(Int2 index) + { + Matrix @this = this; + return new(@this.Size - Int2.One, delegate (int r, int c) + { + if (r >= index.x) r++; + if (c >= index.y) c++; + return @this[r, c]; + }); } public override bool Equals([NotNullWhen(true)] object? obj) @@ -246,9 +239,9 @@ public struct Matrix : IMatrix public string ToString(string? provider) { string res = ""; - for (int r = 0; r < Size.y; r++) + for (int r = 0; r < Size.x; r++) { - for (int c = 0; c < Size.x; c++) res += array[c, r].ToString(provider) + " "; + for (int c = 0; c < Size.y; c++) res += array[r, c].ToString(provider) + " "; res += "\n"; } return res; @@ -258,7 +251,7 @@ public struct Matrix : IMatrix string res = ""; for (int r = 0; r < Size.y; r++) { - for (int c = 0; c < Size.x; c++) res += array[c, r].ToString(provider) + " "; + for (int c = 0; c < Size.x; c++) res += array[r, c].ToString(provider) + " "; res += "\n"; } return res; @@ -272,14 +265,8 @@ public struct Matrix : IMatrix for (int r = 0; r < Size.y; r++) for (int c = 0; c < Size.x; c++) yield return array[c, r]; } - public float[] ToArray() => array.Flatten(Size); + public float[] ToArray() => array.Flatten(new(Size.y, Size.x)); public float[,] ToArray2D() => array; - public Dictionary ToDictionary() - { - Dictionary dict = new(); - for (int r = 0; r < Size.y; r++) for (int c = 0; c < Size.x; c++) dict.Add(new(c, r), array[c, r]); - return dict; - } public Fill ToFill() => ToFillExtension.ToFill(this); public Fill2D ToFill2D() { @@ -292,8 +279,11 @@ public struct Matrix : IMatrix public static Matrix operator -(Matrix m) => m.Inverse(); public static Matrix operator -(Matrix a, Matrix b) => new(a.Size, (r, c) => a[r, c] - b[r, c]); public static Matrix operator *(Matrix a, float b) => new(a.Size, (r, c) => a[r, c] * b); - public static Matrix operator *(Matrix a, Matrix b) => - new(new(a.Size.y, b.Size.x), (r, c) => Mathf.Dot(a.GetRow(r), b.GetColumn(c))); + public static Matrix operator *(Matrix a, Matrix b) + { + if (a.Size.y != b.Size.x) throw new InvalidSizeException("Incompatible Dimensions."); + return new(new(a.Size.x, b.Size.y), (r, c) => Mathf.Dot(a.GetRow(r), b.GetColumn(c))); + } public static Complex operator *(Matrix a, Complex b) => (Complex)(a * (Matrix)b); public static Quaternion operator *(Matrix a, Quaternion b) => (Quaternion)(a * (Matrix)b); public static Float2 operator *(Matrix a, Float2 b) => (Float2)(a * (Matrix)b); diff --git a/Nerd_STF/Mathematics/Algebra/Matrix2x2.cs b/Nerd_STF/Mathematics/Algebra/Matrix2x2.cs index ea02672..9301818 100644 --- a/Nerd_STF/Mathematics/Algebra/Matrix2x2.cs +++ b/Nerd_STF/Mathematics/Algebra/Matrix2x2.cs @@ -55,11 +55,11 @@ public struct Matrix2x2 : IMatrix public float r1c1, r2c1, r1c2, r2c2; public Matrix2x2(float all) : this(all, all, all, all) { } - public Matrix2x2(float r1c1, float r2c1, float r1c2, float r2c2) + public Matrix2x2(float r1c1, float r1c2, float r2c1, float r2c2) { this.r1c1 = r1c1; - this.r2c1 = r2c1; this.r1c2 = r1c2; + this.r2c1 = r2c1; this.r2c2 = r2c2; } public Matrix2x2(float[] nums) : this(nums[0], nums[1], nums[2], nums[3]) { } @@ -70,17 +70,17 @@ public struct Matrix2x2 : IMatrix public Matrix2x2(int[,] nums) : this(nums[0, 0], nums[0, 1], nums[1, 0], nums[1, 1]) { } public Matrix2x2(Fill2D fill) : this(fill(0, 0), fill(0, 1), fill(1, 0), fill(1, 1)) { } public Matrix2x2(Fill2D fill) : this(fill(0, 0), fill(0, 1), fill(1, 0), fill(1, 1)) { } - public Matrix2x2(Float2 c1, Float2 c2) : this(c1.x, c1.y, c2.x, c2.y) { } + public Matrix2x2(Float2 r1, Float2 r2) : this(r1.x, r1.y, r2.x, r2.y) { } public Matrix2x2(Fill fill) : this(fill(0), fill(1)) { } public Matrix2x2(Fill fill) : this((IEnumerable)fill(0), fill(1)) { } - public Matrix2x2(IEnumerable c1, IEnumerable c2) : this(c1.ToFill(), c2.ToFill()) { } - public Matrix2x2(IEnumerable c1, IEnumerable c2) : this(c1.ToFill(), c2.ToFill()) { } - public Matrix2x2(Fill c1, Fill c2) : this(c1(0), c1(1), c2(0), c2(1)) { } - public Matrix2x2(Fill c1, Fill c2) : this(c1(0), c1(1), c2(0), c2(1)) { } + public Matrix2x2(IEnumerable r1, IEnumerable r2) : this(r1.ToFill(), r2.ToFill()) { } + public Matrix2x2(IEnumerable r1, IEnumerable r2) : this(r1.ToFill(), r2.ToFill()) { } + public Matrix2x2(Fill r1, Fill r2) : this(r1(0), r1(1), r2(0), r2(1)) { } + public Matrix2x2(Fill r1, Fill r2) : this(r1(0), r1(1), r2(0), r2(1)) { } public float this[int r, int c] { - get => ToArray2D()[c, r]; + get => ToArray2D()[r, c]; set { // Maybe this could be improved? @@ -117,24 +117,24 @@ public struct Matrix2x2 : IMatrix set => this[index.x, index.y] = value; } - public static Matrix2x2 Absolute(Matrix2x2 val) => new(Mathf.Absolute(val.r1c1), Mathf.Absolute(val.r2c1), - Mathf.Absolute(val.r1c2), Mathf.Absolute(val.r2c2)); + 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 Ceiling(Matrix2x2 val) => new(Mathf.Ceiling(val.r1c1), Mathf.Ceiling(val.r2c1), - Mathf.Ceiling(val.r1c2), Mathf.Ceiling(val.r2c2)); + 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) => - new(Mathf.Clamp(val.r1c1, min.r1c1, max.r1c1), Mathf.Clamp(val.r2c1, min.r2c1, max.r2c1), - Mathf.Clamp(val.r1c2, min.r1c2, max.r1c2), Mathf.Clamp(val.r2c2, min.r2c2, max.r2c2)); + new(Mathf.Clamp(val.r1c1, min.r1c1, max.r1c1), Mathf.Clamp(val.r1c2, min.r1c2, max.r1c2), + Mathf.Clamp(val.r2c1, min.r2c1, max.r2c1), Mathf.Clamp(val.r2c2, min.r2c2, max.r2c2)); public static Matrix2x2 Divide(Matrix2x2 num, params Matrix2x2[] vals) { foreach (Matrix2x2 m in vals) num /= m; return num; } - public static Matrix2x2 Floor(Matrix2x2 val) => new(Mathf.Floor(val.r1c1), Mathf.Floor(val.r2c1), - Mathf.Floor(val.r1c2), Mathf.Floor(val.r2c2)); + public static Matrix2x2 Floor(Matrix2x2 val) => new(Mathf.Floor(val.r1c1), Mathf.Floor(val.r1c2), + Mathf.Floor(val.r2c1), Mathf.Floor(val.r2c2)); public static Matrix2x2 Lerp(Matrix2x2 a, Matrix2x2 b, float t, bool clamp = true) => - new(Mathf.Lerp(a.r1c1, b.r1c1, t, clamp), Mathf.Lerp(a.r2c1, b.r2c1, t, clamp), - Mathf.Lerp(a.r1c2, b.r1c2, t, clamp), Mathf.Lerp(a.r2c2, b.r2c2, t, clamp)); + new(Mathf.Lerp(a.r1c1, b.r1c1, t, clamp), Mathf.Lerp(a.r1c2, b.r1c2, t, clamp), + Mathf.Lerp(a.r2c1, b.r2c1, t, clamp), Mathf.Lerp(a.r2c2, b.r2c2, t, clamp)); public static Matrix2x2 Median(params Matrix2x2[] vals) { float index = Mathf.Average(0, vals.Length - 1); @@ -148,8 +148,8 @@ public struct Matrix2x2 : IMatrix foreach (Matrix2x2 m in vals) val *= m; return val; } - public static Matrix2x2 Round(Matrix2x2 val) => new(Mathf.Round(val.r1c1), Mathf.Round(val.r2c1), - Mathf.Round(val.r1c2), Mathf.Round(val.r2c2)); + public static Matrix2x2 Round(Matrix2x2 val) => new(Mathf.Round(val.r1c1), Mathf.Round(val.r1c2), + Mathf.Round(val.r2c1), Mathf.Round(val.r2c2)); public static Matrix2x2 Subtract(Matrix2x2 num, params Matrix2x2[] vals) { foreach (Matrix2x2 m in vals) num -= m; @@ -162,21 +162,22 @@ public struct Matrix2x2 : IMatrix return val; } - public static (float[] r1c1s, float[] r2c1s, float[] r1c2s, float[] r2c2s) SplitArray(params Matrix2x2[] vals) + public static (float[] r1c1s, float[] r1c2s, float[] r2c1s, float[] r2c2s) SplitArray(params Matrix2x2[] vals) { - float[] r1c1s = new float[vals.Length], r2c1s = new float[vals.Length], r1c2s = new float[vals.Length], + float[] r1c1s = new float[vals.Length], r1c2s = new float[vals.Length], r2c1s = new float[vals.Length], r2c2s = new float[vals.Length]; for (int i = 0; i < vals.Length; i++) { r1c1s[i] = vals[i].r1c1; - r2c1s[i] = vals[i].r2c1; r1c2s[i] = vals[i].r1c2; + r2c1s[i] = vals[i].r2c1; r2c2s[i] = vals[i].r2c2; } - return (r1c1s, r2c1s, r1c2s, r2c2s); + return (r1c1s, r1c2s, r2c1s, r2c2s); } - public Matrix2x2 Adjugate() + public Matrix2x2 Adjugate() => Cofactor().Transpose(); + public Matrix2x2 Cofactor() { Matrix2x2 swapped = new(new[,] { @@ -203,10 +204,10 @@ public struct Matrix2x2 : IMatrix if (obj == null || obj.GetType() != typeof(Matrix2x2)) return base.Equals(obj); return Equals((Matrix2x2)obj); } - public bool Equals(Matrix2x2 other) => r1c1 == other.r1c1 && r2c1 == other.r2c1 - && r1c2 == other.r1c2&& r2c2 == other.r2c2; - public override int GetHashCode() => r1c1.GetHashCode() ^ r2c1.GetHashCode() - ^ r1c2.GetHashCode() ^ r2c2.GetHashCode(); + public bool Equals(Matrix2x2 other) => r1c1 == other.r1c1 && r1c2 == other.r1c2 + && r2c1 == other.r2c1 && r2c2 == other.r2c2; + public override int GetHashCode() => r1c1.GetHashCode() ^ r1c2.GetHashCode() + ^ r2c1.GetHashCode() ^ r2c2.GetHashCode(); public override string ToString() => ToString((string?)null); public string ToString(string? provider) => r1c1.ToString(provider) + " " + r1c2.ToString(provider) + "\n" + r2c1.ToString(provider) + " " + r2c2.ToString(provider); @@ -219,47 +220,42 @@ public struct Matrix2x2 : IMatrix public IEnumerator GetEnumerator() { yield return r1c1; - yield return r2c1; yield return r1c2; + yield return r2c1; yield return r2c2; } - public float[] ToArray() => new[] { r1c1, r2c1, r1c2, r2c2 }; + public float[] ToArray() => new[] { r1c1, r1c2, r2c1, r2c2 }; public float[,] ToArray2D() => new[,] { { r1c1, r1c2 }, { r2c1, r2c2 } }; - public Dictionary ToDictionary() - { - Dictionary dict = new(); - float[] arr = ToArray(); - for (int i = 0; i < arr.Length; i++) dict.Add(new(i % 2, i / 2), arr[i]); - return dict; - } public Fill ToFill() => ToFillExtension.ToFill(this); public Fill2D ToFill2D() { Matrix2x2 @this = this; return (x, y) => @this[x, y]; } - public List ToList() => new() { r1c1, r2c1, r1c2, r2c2 }; + public List ToList() => new() { r1c1, r1c2, r2c1, r2c2 }; - public static Matrix2x2 operator +(Matrix2x2 a, Matrix2x2 b) => new(a.r1c1 + b.r1c1, a.r2c1 + b.r2c1, - a.r1c2 + b.r1c2, a.r2c2 + b.r2c2); + public static Matrix2x2 operator +(Matrix2x2 a, Matrix2x2 b) => new(a.r1c1 + b.r1c1, a.r1c2 + b.r1c2, + a.r2c1 + b.r2c1, a.r2c2 + b.r2c2); public static Matrix2x2? operator -(Matrix2x2 m) => m.Inverse(); - public static Matrix2x2 operator -(Matrix2x2 a, Matrix2x2 b) => new(a.r1c1 - b.r1c1, a.r2c1 - b.r2c1, - a.r1c2 - b.r1c2, a.r2c2 + b.r2c2); - public static Matrix2x2 operator *(Matrix2x2 a, float b) => new(a.r1c1 * b, a.r2c1 * b, a.r1c2 * b, a.r2c2 * b); + public static Matrix2x2 operator -(Matrix2x2 a, Matrix2x2 b) => new(a.r1c1 - b.r1c1, a.r1c2 - b.r1c2, + a.r2c1 - b.r2c1, a.r2c2 - b.r2c2); + public static Matrix2x2 operator *(Matrix2x2 a, float b) => new(a.r1c1 * b, a.r1c2 * b, a.r2c1 * b, a.r2c2 * b); public static Matrix2x2 operator *(Matrix2x2 a, Matrix2x2 b) => new(new[,] { { Float2.Dot(a.Row1, b.Column1), Float2.Dot(a.Row1, b.Column2) }, { Float2.Dot(a.Row2, b.Column1), Float2.Dot(a.Row2, b.Column2) }, }); - public static Matrix2x2 operator /(Matrix2x2 a, float b) => new(a.r1c1 / b, a.r2c1 / b, a.r1c2 / b, a.r2c2 / b); + public static Float2 operator *(Matrix2x2 a, Float2 b) => (Matrix)a * b; + public static Matrix2x2 operator /(Matrix2x2 a, float b) => new(a.r1c1 / b, a.r1c2 / b, a.r2c1 / b, a.r2c2 / b); public static Matrix2x2 operator /(Matrix2x2 a, Matrix2x2 b) => a * b.Inverse(); + public static Float2 operator /(Matrix2x2 a, Float2 b) => (Matrix)a / b; public static Matrix2x2 operator ^(Matrix2x2 a, Matrix2x2 b) => // Single number multiplication. - new(a.r1c1 * b.r1c1, a.r2c1 * b.r2c1, a.r1c2 * b.r1c2, a.r2c2 * b.r2c2); + new(a.r1c1 * b.r1c1, a.r1c2 * b.r1c2, a.r2c1 * b.r2c1, a.r2c2 * b.r2c2); public static bool operator ==(Matrix2x2 a, Matrix2x2 b) => a.Equals(b); public static bool operator !=(Matrix2x2 a, Matrix2x2 b) => !a.Equals(b); @@ -267,7 +263,7 @@ public struct Matrix2x2 : IMatrix { Matrix2x2 res = Zero, identity = Identity; for (int r = 0; r < 2; r++) for (int c = 0; c < 2; c++) - res[c, r] = m.Size.x < c && m.Size.y < r ? m[r, c] : identity[r, c]; + res[c, r] = m.Size.x > r && m.Size.y > c ? m[r, c] : identity[r, c]; return res; } public static explicit operator Matrix2x2(Matrix3x3 m) => new(m.r1c1, m.r2c1, m.r1c2, m.r2c2); diff --git a/Nerd_STF/Mathematics/Algebra/Matrix3x3.cs b/Nerd_STF/Mathematics/Algebra/Matrix3x3.cs index 7e81f47..be67ed8 100644 --- a/Nerd_STF/Mathematics/Algebra/Matrix3x3.cs +++ b/Nerd_STF/Mathematics/Algebra/Matrix3x3.cs @@ -81,17 +81,17 @@ public struct Matrix3x3 : IMatrix public float r1c1, r2c1, r3c1, r1c2, r2c2, r3c2, r1c3, r2c3, r3c3; public Matrix3x3(float all) : this(all, all, all, all, all, all, all, all, all) { } - public Matrix3x3(float r1c1, float r2c1, float r3c1, float r1c2, - float r2c2, float r3c2, float r1c3, float r2c3, float r3c3) + public Matrix3x3(float r1c1, float r1c2, float r1c3, float r2c1, + float r2c2, float r2c3, float r3c1, float r3c2, float r3c3) { this.r1c1 = r1c1; - this.r2c1 = r2c1; - this.r3c1 = r3c1; this.r1c2 = r1c2; - this.r2c2 = r2c2; - this.r3c2 = r3c2; this.r1c3 = r1c3; + this.r2c1 = r2c1; + this.r2c2 = r2c2; this.r2c3 = r2c3; + this.r3c1 = r3c1; + this.r3c2 = r3c2; this.r3c3 = r3c3; } public Matrix3x3(float[] nums) : this(nums[0], nums[1], nums[2], @@ -110,21 +110,21 @@ public struct Matrix3x3 : IMatrix fill(1, 0), fill(1, 1), fill(1, 2), fill(2, 0), fill(2, 1), fill(2, 2)) { } public Matrix3x3(Fill2D fill) : this(fill(0, 0), fill(0, 1), fill(0, 2), fill(1, 0), fill(1, 1), fill(1, 2), fill(2, 0), fill(2, 1), fill(2, 2)) { } - public Matrix3x3(Float3 c1, Float3 c2, Float3 c3) : this(c1.x, c1.y, c1.z, c2.x, c2.y, c2.z, c3.x, c3.y, c3.z) { } + public Matrix3x3(Float3 r1, Float3 r2, Float3 r3) : this(r1.x, r1.y, r1.z, r2.x, r2.y, r2.z, r3.x, r3.y, r3.z) { } public Matrix3x3(Fill fill) : this(fill(0), fill(1), fill(2)) { } public Matrix3x3(Fill fill) : this((IEnumerable)fill(0), fill(1), fill(2)) { } - public Matrix3x3(IEnumerable c1, IEnumerable c2, IEnumerable c3) - : this(c1.ToFill(), c2.ToFill(), c3.ToFill()) { } - public Matrix3x3(IEnumerable c1, IEnumerable c2, IEnumerable c3) - : this(c1.ToFill(), c2.ToFill(), c3.ToFill()) { } - public Matrix3x3(Fill c1, Fill c2, Fill c3) - : this(c1(0), c1(1), c1(2), c2(0), c2(1), c2(2), c3(0), c3(1), c3(2)) { } - public Matrix3x3(Fill c1, Fill c2, Fill c3) - : this(c1(0), c1(1), c1(2), c2(0), c2(1), c2(2), c3(0), c3(1), c3(2)) { } + public Matrix3x3(IEnumerable r1, IEnumerable r2, IEnumerable r3) + : this(r1.ToFill(), r2.ToFill(), r3.ToFill()) { } + public Matrix3x3(IEnumerable r1, IEnumerable r2, IEnumerable r3) + : this(r1.ToFill(), r2.ToFill(), r3.ToFill()) { } + public Matrix3x3(Fill r1, Fill r2, Fill r3) + : this(r1(0), r1(1), r1(2), r2(0), r2(1), r2(2), r3(0), r3(1), r3(2)) { } + public Matrix3x3(Fill r1, Fill r2, Fill r3) + : this(r1(0), r1(1), r1(2), r2(0), r2(1), r2(2), r3(0), r3(1), r3(2)) { } public float this[int r, int c] { - get => ToArray2D()[c, r]; + get => ToArray2D()[r, c]; set { // Maybe this could be improved? @@ -182,19 +182,19 @@ public struct Matrix3x3 : IMatrix } public static Matrix3x3 Absolute(Matrix3x3 val) => - new(Mathf.Absolute(val.r1c1), Mathf.Absolute(val.r2c1), Mathf.Absolute(val.r3c1), - Mathf.Absolute(val.r1c2), Mathf.Absolute(val.r2c2), Mathf.Absolute(val.r3c2), - Mathf.Absolute(val.r1c3), Mathf.Absolute(val.r2c3), Mathf.Absolute(val.r3c3)); + 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 Ceiling(Matrix3x3 val) => - new(Mathf.Ceiling(val.r1c1), Mathf.Ceiling(val.r2c1), Mathf.Ceiling(val.r3c1), - Mathf.Ceiling(val.r1c2), Mathf.Ceiling(val.r2c2), Mathf.Ceiling(val.r3c2), - Mathf.Ceiling(val.r1c3), Mathf.Ceiling(val.r2c3), Mathf.Ceiling(val.r3c3)); + 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), + Mathf.Ceiling(val.r3c1), Mathf.Ceiling(val.r3c2), Mathf.Ceiling(val.r3c3)); public static Matrix3x3 Clamp(Matrix3x3 val, Matrix3x3 min, Matrix3x3 max) => - new(Mathf.Clamp(val.r1c1, min.r1c1, max.r1c1), Mathf.Clamp(val.r2c1, min.r2c1, max.r2c1), - Mathf.Clamp(val.r3c1, min.r3c1, max.r3c1), Mathf.Clamp(val.r1c2, min.r1c2, max.r1c2), - Mathf.Clamp(val.r2c2, min.r2c2, max.r2c2), Mathf.Clamp(val.r3c2, min.r3c2, max.r3c2), - Mathf.Clamp(val.r1c3, min.r1c3, max.r1c3), Mathf.Clamp(val.r2c3, min.r2c3, max.r2c3), + new(Mathf.Clamp(val.r1c1, min.r1c1, max.r1c1), Mathf.Clamp(val.r1c2, min.r1c2, max.r1c2), + Mathf.Clamp(val.r1c3, min.r1c3, max.r1c3), Mathf.Clamp(val.r2c1, min.r2c1, max.r2c1), + Mathf.Clamp(val.r2c2, min.r2c2, max.r2c2), Mathf.Clamp(val.r2c3, min.r2c3, max.r2c3), + Mathf.Clamp(val.r3c1, min.r3c1, max.r3c1), Mathf.Clamp(val.r3c2, min.r3c2, max.r3c2), Mathf.Clamp(val.r3c3, min.r3c3, max.r3c3)); public static Matrix3x3 Divide(Matrix3x3 num, params Matrix3x3[] vals) { @@ -202,14 +202,14 @@ public struct Matrix3x3 : IMatrix return num; } public static Matrix3x3 Floor(Matrix3x3 val) => - new(Mathf.Floor(val.r1c1), Mathf.Floor(val.r2c1), Mathf.Floor(val.r3c1), - Mathf.Floor(val.r1c2), Mathf.Floor(val.r2c2), Mathf.Floor(val.r3c2), - Mathf.Floor(val.r1c3), Mathf.Floor(val.r2c3), Mathf.Floor(val.r3c3)); + new(Mathf.Floor(val.r1c1), Mathf.Floor(val.r1c2), Mathf.Floor(val.r1c3), + Mathf.Floor(val.r2c1), Mathf.Floor(val.r2c2), Mathf.Floor(val.r2c3), + Mathf.Floor(val.r3c1), Mathf.Floor(val.r3c2), Mathf.Floor(val.r3c3)); public static Matrix3x3 Lerp(Matrix3x3 a, Matrix3x3 b, float t, bool clamp = true) => - new(Mathf.Lerp(a.r1c1, b.r1c1, t, clamp), Mathf.Lerp(a.r2c1, b.r2c1, t, clamp), - Mathf.Lerp(a.r3c1, b.r3c1, t, clamp), Mathf.Lerp(a.r1c2, b.r1c2, t, clamp), - Mathf.Lerp(a.r2c2, b.r2c2, t, clamp), Mathf.Lerp(a.r3c2, b.r3c2, t, clamp), - Mathf.Lerp(a.r1c3, b.r1c3, t, clamp), Mathf.Lerp(a.r2c3, b.r2c3, t, clamp), + new(Mathf.Lerp(a.r1c1, b.r1c1, t, clamp), Mathf.Lerp(a.r1c2, b.r1c2, t, clamp), + Mathf.Lerp(a.r1c3, b.r1c3, t, clamp), Mathf.Lerp(a.r2c1, b.r2c1, t, clamp), + Mathf.Lerp(a.r2c2, b.r2c2, t, clamp), Mathf.Lerp(a.r2c3, b.r2c3, t, clamp), + Mathf.Lerp(a.r3c1, b.r3c1, t, clamp), Mathf.Lerp(a.r3c2, b.r3c2, t, clamp), Mathf.Lerp(a.r3c3, b.r3c3, t, clamp)); public static Matrix3x3 Median(params Matrix3x3[] vals) { @@ -225,9 +225,9 @@ public struct Matrix3x3 : IMatrix return val; } public static Matrix3x3 Round(Matrix3x3 val) => - new(Mathf.Round(val.r1c1), Mathf.Round(val.r2c1), Mathf.Round(val.r3c1), - Mathf.Round(val.r1c2), Mathf.Round(val.r2c2), Mathf.Round(val.r3c2), - Mathf.Round(val.r1c3), Mathf.Round(val.r2c3), Mathf.Round(val.r3c3)); + new(Mathf.Round(val.r1c1), Mathf.Round(val.r1c2), Mathf.Round(val.r1c3), + Mathf.Round(val.r2c1), Mathf.Round(val.r2c2), Mathf.Round(val.r2c3), + Mathf.Round(val.r3c1), Mathf.Round(val.r3c2), Mathf.Round(val.r3c3)); public static Matrix3x3 Subtract(Matrix3x3 num, params Matrix3x3[] vals) { foreach (Matrix3x3 m in vals) num -= m; @@ -240,28 +240,29 @@ public struct Matrix3x3 : IMatrix return val; } - public static (float[] r1c1s, float[] r2c1s, float[] r3c1s, float[] r1c2s, float[] r2c2s, - float[] r3c2s, float[] r1c3s, float[] r2c3s, float[] r3c3s) SplitArray(params Matrix3x3[] vals) + public static (float[] r1c1s, float[] r1c2s, float[] r1c3s, float[] r2c1s, float[] r2c2s, + float[] r2c3s, float[] r3c1s, float[] r3c2s, float[] r3c3s) SplitArray(params Matrix3x3[] vals) { - float[] r1c1s = new float[vals.Length], r2c1s = new float[vals.Length], r3c1s = new float[vals.Length], - r1c2s = new float[vals.Length], r2c2s = new float[vals.Length], r3c2s = new float[vals.Length], - r1c3s = new float[vals.Length], r2c3s = new float[vals.Length], r3c3s = new float[vals.Length]; + float[] r1c1s = new float[vals.Length], r1c2s = new float[vals.Length], r1c3s = new float[vals.Length], + r2c1s = new float[vals.Length], r2c2s = new float[vals.Length], r2c3s = new float[vals.Length], + r3c1s = new float[vals.Length], r3c2s = new float[vals.Length], r3c3s = new float[vals.Length]; for (int i = 0; i < vals.Length; i++) { r1c1s[i] = vals[i].r1c1; - r2c1s[i] = vals[i].r2c1; - r3c1s[i] = vals[i].r3c1; r1c2s[i] = vals[i].r1c2; - r2c2s[i] = vals[i].r2c2; - r3c2s[i] = vals[i].r3c2; r1c3s[i] = vals[i].r1c3; + r2c1s[i] = vals[i].r2c1; + r2c2s[i] = vals[i].r2c2; r2c3s[i] = vals[i].r2c3; + r3c1s[i] = vals[i].r3c1; + r3c2s[i] = vals[i].r3c2; r3c3s[i] = vals[i].r3c3; } - return (r1c1s, r2c1s, r3c1s, r1c2s, r2c2s, r3c2s, r1c3s, r2c3s, r3c3s); + return (r1c1s, r1c2s, r1c3s, r2c1s, r2c2s, r2c3s, r3c1s, r3c2s, r3c3s); } - public Matrix3x3 Adjugate() + public Matrix3x3 Adjugate() => Cofactor().Transpose(); + public Matrix3x3 Cofactor() { Matrix3x3 dets = new(); Matrix2x2[,] minors = Minors(); @@ -271,20 +272,20 @@ public struct Matrix3x3 : IMatrix public float Determinant() { Matrix2x2[,] minors = Minors(); - return (r1c1 * minors[0, 0].Determinant()) - (r1c2 * minors[1, 0].Determinant()) - + (r1c3 * minors[2, 0].Determinant()); + return (r1c1 * minors[0, 0].Determinant()) - (r1c2 * minors[0, 1].Determinant()) + + (r1c3 * minors[0, 2].Determinant()); } public Matrix3x3 Inverse() { float d = Determinant(); if (d == 0) throw new NoInverseException(); - return Transpose().Adjugate() / d; + return Adjugate() / d; } public Matrix2x2[,] Minors() => new Matrix2x2[,] { - { new(r2c2, r3c2, r2c3, r3c3), new(r2c1, r3c1, r2c3, r3c3), new(r2c1, r3c1, r2c2, r3c2) }, - { new(r1c2, r3c2, r1c3, r3c3), new(r1c1, r3c1, r1c3, r3c3), new(r1c1, r3c1, r1c2, r3c2) }, - { new(r1c2, r2c2, r1c3, r2c3), new(r1c1, r2c1, r1c3, r2c3), new(r1c1, r2c1, r1c2, r2c2) } + { new(r2c2, r2c3, r3c2, r3c3), new(r2c1, r2c3, r3c1, r3c3), new(r2c1, r2c2, r3c1, r3c2) }, + { new(r1c2, r1c3, r3c2, r3c3), new(r1c1, r1c3, r3c1, r3c3), new(r1c1, r1c2, r3c1, r3c2) }, + { new(r1c2, r1c3, r2c2, r2c3), new(r1c1, r1c3, r2c1, r2c3), new(r1c1, r1c2, r2c1, r2c2) } }; public Matrix3x3 Transpose() => new(new[,] { @@ -299,13 +300,13 @@ public struct Matrix3x3 : IMatrix return Equals((Matrix3x3)obj); } public bool Equals(Matrix3x3 other) => - r1c1 == other.r1c1 && r2c1 == other.r2c1 && r3c1 == other.r3c1 && - r1c2 == other.r1c2 && r2c2 == other.r2c2 && r3c2 == other.r3c2 && - r1c3 == other.r1c3 && r2c3 == other.r2c3 && r3c3 == other.r3c3; + r1c1 == other.r1c1 && r1c2 == other.r1c2 && r1c3 == other.r1c3 && + r2c1 == other.r2c1 && r2c2 == other.r2c2 && r2c3 == other.r2c3 && + r3c1 == other.r3c1 && r3c2 == other.r3c2 && r3c3 == other.r3c3; public override int GetHashCode() => - r1c1.GetHashCode() ^ r2c1.GetHashCode() ^ r3c1.GetHashCode() ^ - r1c2.GetHashCode() ^ r2c2.GetHashCode() ^ r3c2.GetHashCode() ^ - r1c3.GetHashCode() ^ r2c3.GetHashCode() ^ r3c3.GetHashCode(); + r1c1.GetHashCode() ^ r1c2.GetHashCode() ^ r1c3.GetHashCode() ^ + r2c1.GetHashCode() ^ r2c2.GetHashCode() ^ r2c3.GetHashCode() ^ + r3c1.GetHashCode() ^ r3c2.GetHashCode() ^ r3c3.GetHashCode(); public override string ToString() => ToString((string?)null); public string ToString(string? provider) => r1c1.ToString(provider) + " " + r1c2.ToString(provider) + " " + r1c3.ToString(provider) + "\n" + @@ -322,66 +323,61 @@ public struct Matrix3x3 : IMatrix public IEnumerator GetEnumerator() { yield return r1c1; - yield return r2c1; - yield return r3c1; yield return r1c2; - yield return r2c2; - yield return r3c2; yield return r1c3; + yield return r2c1; + yield return r2c2; yield return r2c3; + yield return r3c1; + yield return r3c2; yield return r3c3; } - public float[] ToArray() => new[] { r1c1, r2c1, r3c1, r1c2, r2c2, r3c2, r1c3, r2c3, r3c3 }; + public float[] ToArray() => new[] { r1c1, r1c2, r1c3, r2c1, r2c2, r2c3, r3c1, r3c2, r3c3 }; public float[,] ToArray2D() => new[,] { { r1c1, r1c2, r1c3 }, { r2c1, r2c2, r2c3 }, { r3c1, r3c2, r3c3 } }; - public Dictionary ToDictionary() - { - Dictionary dict = new(); - float[] arr = ToArray(); - for (int i = 0; i < arr.Length; i++) dict.Add(new(i % 3, i / 3), arr[i]); - return dict; - } public Fill ToFill() => ToFillExtension.ToFill(this); public Fill2D ToFill2D() { Matrix3x3 @this = this; return (x, y) => @this[x, y]; } - public List ToList() => new() { r1c1, r2c1, r3c1, r1c2, r2c2, r3c2, r1c3, r2c3, r3c3 }; + public List ToList() => new() { r1c1, r1c2, r1c3, r2c1, r2c2, r2c3, r3c1, r3c2, r3c3 }; public static Matrix3x3 operator +(Matrix3x3 a, Matrix3x3 b) => - new(a.r1c1 + b.r1c1, a.r2c1 + b.r2c1, a.r3c1 + b.r3c1, - a.r1c2 + b.r1c2, a.r2c2 + b.r2c2, a.r3c2 + b.r3c2, - a.r1c3 + b.r1c3, a.r2c3 + b.r2c3, a.r3c3 + b.r3c3); + new(a.r1c1 + b.r1c1, a.r1c2 + b.r1c2, a.r1c3 + b.r1c3, + a.r2c1 + b.r2c1, a.r2c2 + b.r2c2, a.r2c3 + b.r2c3, + a.r3c1 + b.r3c1, a.r3c2 + b.r3c2, a.r3c3 + b.r3c3); public static Matrix3x3 operator -(Matrix3x3 m) => m.Inverse(); public static Matrix3x3 operator -(Matrix3x3 a, Matrix3x3 b) => - new(a.r1c1 - b.r1c1, a.r2c1 - b.r2c1, a.r3c1 - b.r3c1, - a.r1c2 - b.r1c2, a.r2c2 - b.r2c2, a.r3c2 - b.r3c2, - a.r1c3 - b.r1c3, a.r2c3 - b.r2c3, a.r3c3 - b.r3c3); + new(a.r1c1 - b.r1c1, a.r1c2 - b.r1c2, a.r1c3 - b.r1c3, + a.r2c1 - b.r2c1, a.r2c2 - b.r2c2, a.r2c3 - b.r2c3, + a.r3c1 - b.r3c1, a.r3c2 - b.r3c2, a.r3c3 - b.r3c3); public static Matrix3x3 operator *(Matrix3x3 a, float b) => - new(a.r1c1 * b, a.r2c1 * b, a.r3c1 * b, - a.r1c2 * b, a.r2c2 * b, a.r3c2 * b, - a.r1c3 * b, a.r2c3 * b, a.r3c3 * b); + new(a.r1c1 * b, a.r1c2 * b, a.r1c3 * b, + a.r2c1 * b, a.r2c2 * b, a.r2c3 * b, + a.r3c1 * b, a.r3c2 * b, a.r3c3 * b); public static Matrix3x3 operator *(Matrix3x3 a, Matrix3x3 b) => new(new[,] { { Float3.Dot(a.Row1, b.Column1), Float3.Dot(a.Row1, b.Column2), Float3.Dot(a.Row1, b.Column3) }, { Float3.Dot(a.Row2, b.Column1), Float3.Dot(a.Row2, b.Column2), Float3.Dot(a.Row2, b.Column3) }, { Float3.Dot(a.Row3, b.Column1), Float3.Dot(a.Row3, b.Column2), Float3.Dot(a.Row3, b.Column3) }, }); + public static Float3 operator *(Matrix3x3 a, Float3 b) => (Matrix)a * b; public static Matrix3x3 operator /(Matrix3x3 a, float b) => - new(a.r1c1 / b, a.r2c1 / b, a.r3c1 / b, - a.r1c2 / b, a.r2c2 / b, a.r3c2 / b, - a.r1c3 / b, a.r2c3 / b, a.r3c3 / b); + new(a.r1c1 / b, a.r1c2 / b, a.r1c3 / b, + a.r2c1 / b, a.r2c2 / b, a.r2c3 / b, + a.r3c1 / b, a.r3c2 / b, a.r3c3 / b); public static Matrix3x3 operator /(Matrix3x3 a, Matrix3x3 b) => a * b.Inverse(); + public static Float3 operator /(Matrix3x3 a, Float3 b) => (Matrix)a / b; public static Matrix3x3 operator ^(Matrix3x3 a, Matrix3x3 b) => // Single number multiplication - new(a.r1c1 * b.r1c1, a.r2c1 * b.r2c1, a.r3c1 * b.r3c1, - a.r1c2 * b.r1c2, a.r2c2 * b.r2c2, a.r3c2 * b.r3c2, - a.r1c3 * b.r1c3, a.r2c3 * b.r2c3, a.r3c3 * b.r3c3); + new(a.r1c1 * b.r1c1, a.r1c2 * b.r1c2, a.r1c3 * b.r1c3, + a.r2c1 * b.r2c1, a.r2c2 * b.r2c2, a.r2c3 * b.r2c3, + a.r3c1 * b.r3c1, a.r3c2 * b.r3c2, a.r3c3 * b.r3c3); public static bool operator ==(Matrix3x3 a, Matrix3x3 b) => a.Equals(b); public static bool operator !=(Matrix3x3 a, Matrix3x3 b) => !a.Equals(b); @@ -389,7 +385,7 @@ public struct Matrix3x3 : IMatrix { Matrix3x3 res = Zero, identity = Identity; for (int r = 0; r < 3; r++) for (int c = 0; c < 3; c++) - res[c, r] = m.Size.x < c && m.Size.y < r ? m[r, c] : identity[r, c]; + res[c, r] = m.Size.x > r && m.Size.y > c ? m[r, c] : identity[r, c]; return res; } public static implicit operator Matrix3x3(Matrix2x2 m) diff --git a/Nerd_STF/Mathematics/Algebra/Matrix4x4.cs b/Nerd_STF/Mathematics/Algebra/Matrix4x4.cs index 6b0cd2c..f5d71f5 100644 --- a/Nerd_STF/Mathematics/Algebra/Matrix4x4.cs +++ b/Nerd_STF/Mathematics/Algebra/Matrix4x4.cs @@ -65,7 +65,7 @@ public struct Matrix4x4 : IMatrix } public Float4 Row1 { - get => new(r1c1, r1c2, r1c3, r1c3); + get => new(r1c1, r1c2, r1c3, r1c4); set { r1c1 = value.x; @@ -76,7 +76,7 @@ public struct Matrix4x4 : IMatrix } public Float4 Row2 { - get => new(r2c1, r2c2, r2c3, r2c3); + get => new(r2c1, r2c2, r2c3, r2c4); set { r2c1 = value.x; @@ -87,7 +87,7 @@ public struct Matrix4x4 : IMatrix } public Float4 Row3 { - get => new(r3c1, r3c2, r3c3, r3c3); + get => new(r3c1, r3c2, r3c3, r3c4); set { r3c1 = value.x; @@ -98,7 +98,7 @@ public struct Matrix4x4 : IMatrix } public Float4 Row4 { - get => new(r4c1, r4c2, r4c3, r4c3); + get => new(r4c1, r4c2, r4c3, r4c4); set { r4c1 = value.x; @@ -112,8 +112,8 @@ public struct Matrix4x4 : IMatrix public Matrix4x4(float all) : this(all, all, all, all, all, all, all, all, all, all, all, all, all, all, all, all) { } - public Matrix4x4(float r1c1, float r2c1, float r3c1, float r4c1, float r1c2, float r2c2, float r3c2, - float r4c2, float r1c3, float r2c3, float r3c3, float r4c3, float r1c4, float r2c4, float r3c4, float r4c4) + public Matrix4x4(float r1c1, float r1c2, float r1c3, float r1c4, float r2c1, float r2c2, float r2c3, + float r2c4, float r3c1, float r3c2, float r3c3, float r3c4, float r4c1, float r4c2, float r4c3, float r4c4) { this.r1c1 = r1c1; this.r2c1 = r2c1; @@ -152,22 +152,22 @@ public struct Matrix4x4 : IMatrix public Matrix4x4(Fill2D fill) : this(fill(0, 0), fill(0, 1), fill(0, 2), fill(0, 3), fill(1, 0), fill(1, 1), fill(1, 2), fill(1, 3), fill(2, 0), fill(2, 1), fill(2, 2), fill(2, 3), fill(3, 0), fill(3, 1), fill(3, 2), fill(3, 3)) { } - public Matrix4x4(Float4 c1, Float4 c2, Float4 c3, Float4 c4) : this(c1.x, c1.y, c1.z, - c1.w, c2.x, c2.y, c2.z, c2.w, c3.x, c3.y, c3.z, c3.w, c4.x, c4.y, c4.z, c4.w) { } + public Matrix4x4(Float4 r1, Float4 r2, Float4 r3, Float4 r4) : this(r1.x, r1.y, r1.z, + r1.w, r2.x, r2.y, r2.z, r2.w, r3.x, r3.y, r3.z, r3.w, r4.x, r4.y, r4.z, r4.w) { } public Matrix4x4(Fill fill) : this(fill(0), fill(1), fill(2), fill(3)) { } public Matrix4x4(Fill fill) : this((IEnumerable)fill(0), fill(1), fill(2), fill(3)) { } - public Matrix4x4(IEnumerable c1, IEnumerable c2, IEnumerable c3, IEnumerable c4) - : this(c1.ToFill(), c2.ToFill(), c3.ToFill(), c4.ToFill()) { } - public Matrix4x4(IEnumerable c1, IEnumerable c2, IEnumerable c3, IEnumerable c4) - : this(c1.ToFill(), c2.ToFill(), c3.ToFill(), c4.ToFill()) { } - public Matrix4x4(Fill c1, Fill c2, Fill c3, Fill c4) : this(c1(0), c1(1), - c1(2), c1(3), c2(0), c2(1), c2(2), c2(3), c3(0), c3(1), c3(2), c3(3), c4(0), c4(1), c4(2), c4(3)) { } - public Matrix4x4(Fill c1, Fill c2, Fill c3, Fill c4) : this(c1(0), c1(1), - c1(2), c1(3), c2(0), c2(1), c2(2), c2(3), c3(0), c3(1), c3(2), c3(3), c4(0), c4(1), c4(2), c4(3)) { } + public Matrix4x4(IEnumerable r1, IEnumerable r2, IEnumerable r3, IEnumerable r4) + : this(r1.ToFill(), r2.ToFill(), r3.ToFill(), r4.ToFill()) { } + public Matrix4x4(IEnumerable r1, IEnumerable r2, IEnumerable r3, IEnumerable r4) + : this(r1.ToFill(), r2.ToFill(), r3.ToFill(), r4.ToFill()) { } + public Matrix4x4(Fill r1, Fill r2, Fill r3, Fill r4) : this(r1(0), r1(1), + r1(2), r1(3), r2(0), r2(1), r2(2), r2(3), r3(0), r3(1), r3(2), r3(3), r4(0), r4(1), r4(2), r4(3)) { } + public Matrix4x4(Fill r1, Fill r2, Fill r3, Fill r4) : this(r1(0), r1(1), + r1(2), r1(3), r2(0), r2(1), r2(2), r2(3), r3(0), r3(1), r3(2), r3(3), r4(0), r4(1), r4(2), r4(3)) { } public float this[int r, int c] { - get => ToArray2D()[c, r]; + get => ToArray2D()[r, c]; set { // Maybe this could be improved? @@ -253,44 +253,44 @@ public struct Matrix4x4 : IMatrix } public static Matrix4x4 Absolute(Matrix4x4 val) => - new(Mathf.Absolute(val.r1c1), Mathf.Absolute(val.r2c1), Mathf.Absolute(val.r3c1), Mathf.Absolute(val.r4c1), - Mathf.Absolute(val.r1c2), Mathf.Absolute(val.r2c2), Mathf.Absolute(val.r3c2), Mathf.Absolute(val.r4c2), - Mathf.Absolute(val.r1c3), Mathf.Absolute(val.r2c3), Mathf.Absolute(val.r3c3), Mathf.Absolute(val.r4c2), - Mathf.Absolute(val.r1c4), Mathf.Absolute(val.r2c4), Mathf.Absolute(val.r3c4), Mathf.Absolute(val.r4c4)); + new(Mathf.Absolute(val.r1c1), Mathf.Absolute(val.r1c2), Mathf.Absolute(val.r1c3), Mathf.Absolute(val.r1c4), + 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 Ceiling(Matrix4x4 val) => - new(Mathf.Ceiling(val.r1c1), Mathf.Ceiling(val.r2c1), Mathf.Ceiling(val.r3c1), Mathf.Ceiling(val.r4c1), - Mathf.Ceiling(val.r1c2), Mathf.Ceiling(val.r2c2), Mathf.Ceiling(val.r3c2), Mathf.Ceiling(val.r4c2), - Mathf.Ceiling(val.r1c3), Mathf.Ceiling(val.r2c3), Mathf.Ceiling(val.r3c3), Mathf.Ceiling(val.r4c2), - Mathf.Ceiling(val.r1c4), Mathf.Ceiling(val.r2c4), Mathf.Ceiling(val.r3c4), Mathf.Ceiling(val.r4c4)); + 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), + Mathf.Ceiling(val.r3c1), Mathf.Ceiling(val.r3c2), Mathf.Ceiling(val.r3c3), Mathf.Ceiling(val.r3c4), + Mathf.Ceiling(val.r4c1), Mathf.Ceiling(val.r4c2), Mathf.Ceiling(val.r4c3), Mathf.Ceiling(val.r4c4)); public static Matrix4x4 Clamp(Matrix4x4 val, Matrix4x4 min, Matrix4x4 max) => - new(Mathf.Clamp(val.r1c1, min.r1c1, max.r1c1), Mathf.Clamp(val.r2c1, min.r2c1, max.r2c1), - Mathf.Clamp(val.r3c1, min.r3c1, max.r3c1), Mathf.Clamp(val.r4c1, min.r4c1, max.r4c1), - Mathf.Clamp(val.r1c2, min.r1c2, max.r1c2), Mathf.Clamp(val.r2c2, min.r2c2, max.r2c2), - Mathf.Clamp(val.r3c2, min.r3c2, max.r3c2), Mathf.Clamp(val.r4c2, min.r4c2, max.r4c2), - Mathf.Clamp(val.r1c3, min.r1c3, max.r1c3), Mathf.Clamp(val.r2c3, min.r2c3, max.r2c3), - Mathf.Clamp(val.r3c3, min.r3c3, max.r3c3), Mathf.Clamp(val.r4c3, min.r4c3, max.r4c3), - Mathf.Clamp(val.r1c4, min.r1c4, max.r1c4), Mathf.Clamp(val.r2c4, min.r2c4, max.r2c4), - Mathf.Clamp(val.r3c4, min.r3c4, max.r3c4), Mathf.Clamp(val.r4c4, min.r4c4, max.r4c4)); + new(Mathf.Clamp(val.r1c1, min.r1c1, max.r1c1), Mathf.Clamp(val.r1c2, min.r1c2, max.r1c2), + Mathf.Clamp(val.r1c3, min.r1c3, max.r1c3), Mathf.Clamp(val.r1c4, min.r1c4, max.r1c4), + Mathf.Clamp(val.r2c1, min.r2c1, max.r2c1), Mathf.Clamp(val.r2c2, min.r2c2, max.r2c2), + Mathf.Clamp(val.r2c3, min.r2c3, max.r2c3), Mathf.Clamp(val.r2c4, min.r2c4, max.r2c4), + Mathf.Clamp(val.r3c1, min.r3c1, max.r3c1), Mathf.Clamp(val.r3c2, min.r3c2, max.r3c2), + Mathf.Clamp(val.r3c3, min.r3c3, max.r3c3), Mathf.Clamp(val.r3c4, min.r3c4, max.r3c4), + Mathf.Clamp(val.r4c1, min.r4c1, max.r4c1), Mathf.Clamp(val.r4c2, min.r4c2, max.r4c2), + Mathf.Clamp(val.r4c3, min.r4c3, max.r4c3), Mathf.Clamp(val.r4c4, min.r4c4, max.r4c4)); public static Matrix4x4 Divide(Matrix4x4 num, params Matrix4x4[] vals) { foreach (Matrix4x4 m in vals) num /= m; return num; } public static Matrix4x4 Floor(Matrix4x4 val) => - new(Mathf.Floor(val.r1c1), Mathf.Floor(val.r2c1), Mathf.Floor(val.r3c1), Mathf.Floor(val.r4c1), - Mathf.Floor(val.r1c2), Mathf.Floor(val.r2c2), Mathf.Floor(val.r3c2), Mathf.Floor(val.r4c2), - Mathf.Floor(val.r1c3), Mathf.Floor(val.r2c3), Mathf.Floor(val.r3c3), Mathf.Floor(val.r4c2), - Mathf.Floor(val.r1c4), Mathf.Floor(val.r2c4), Mathf.Floor(val.r3c4), Mathf.Floor(val.r4c4)); + new(Mathf.Floor(val.r1c1), Mathf.Floor(val.r1c2), Mathf.Floor(val.r1c3), Mathf.Floor(val.r1c4), + Mathf.Floor(val.r2c1), Mathf.Floor(val.r2c2), Mathf.Floor(val.r2c3), Mathf.Floor(val.r2c4), + Mathf.Floor(val.r3c1), Mathf.Floor(val.r3c2), Mathf.Floor(val.r3c3), Mathf.Floor(val.r3c4), + Mathf.Floor(val.r4c1), Mathf.Floor(val.r4c2), Mathf.Floor(val.r4c3), Mathf.Floor(val.r4c4)); public static Matrix4x4 Lerp(Matrix4x4 a, Matrix4x4 b, float t, bool clamp = true) => - new(Mathf.Lerp(a.r1c1, b.r1c1, t, clamp), Mathf.Lerp(a.r2c1, b.r2c1, t, clamp), - Mathf.Lerp(a.r3c1, b.r3c1, t, clamp), Mathf.Lerp(a.r4c1, b.r4c1, t, clamp), - Mathf.Lerp(a.r1c2, b.r1c2, t, clamp), Mathf.Lerp(a.r2c2, b.r2c2, t, clamp), - Mathf.Lerp(a.r3c2, b.r3c2, t, clamp), Mathf.Lerp(a.r4c2, b.r4c2, t, clamp), - Mathf.Lerp(a.r1c3, b.r1c3, t, clamp), Mathf.Lerp(a.r2c3, b.r2c3, t, clamp), - Mathf.Lerp(a.r3c3, b.r3c3, t, clamp), Mathf.Lerp(a.r4c3, b.r4c3, t, clamp), - Mathf.Lerp(a.r1c4, b.r1c4, t, clamp), Mathf.Lerp(a.r2c4, b.r2c4, t, clamp), - Mathf.Lerp(a.r3c4, b.r3c4, t, clamp), Mathf.Lerp(a.r4c4, b.r4c4, t, clamp)); + new(Mathf.Lerp(a.r1c1, b.r1c1, t, clamp), Mathf.Lerp(a.r1c2, b.r1c2, t, clamp), + Mathf.Lerp(a.r1c3, b.r1c3, t, clamp), Mathf.Lerp(a.r1c4, b.r1c4, t, clamp), + Mathf.Lerp(a.r2c1, b.r2c1, t, clamp), Mathf.Lerp(a.r2c2, b.r2c2, t, clamp), + Mathf.Lerp(a.r2c3, b.r2c3, t, clamp), Mathf.Lerp(a.r2c4, b.r2c4, t, clamp), + Mathf.Lerp(a.r3c1, b.r3c1, t, clamp), Mathf.Lerp(a.r3c2, b.r3c2, t, clamp), + Mathf.Lerp(a.r3c3, b.r3c3, t, clamp), Mathf.Lerp(a.r3c4, b.r3c4, t, clamp), + Mathf.Lerp(a.r4c1, b.r4c1, t, clamp), Mathf.Lerp(a.r4c2, b.r4c2, t, clamp), + Mathf.Lerp(a.r4c3, b.r4c3, t, clamp), Mathf.Lerp(a.r4c4, b.r4c4, t, clamp)); public static Matrix4x4 Median(params Matrix4x4[] vals) { float index = Mathf.Average(0, vals.Length - 1); @@ -305,10 +305,10 @@ public struct Matrix4x4 : IMatrix return val; } public static Matrix4x4 Round(Matrix4x4 val) => - new(Mathf.Round(val.r1c1), Mathf.Round(val.r2c1), Mathf.Round(val.r3c1), Mathf.Round(val.r4c1), - Mathf.Round(val.r1c2), Mathf.Round(val.r2c2), Mathf.Round(val.r3c2), Mathf.Round(val.r4c2), - Mathf.Round(val.r1c3), Mathf.Round(val.r2c3), Mathf.Round(val.r3c3), Mathf.Round(val.r4c2), - Mathf.Round(val.r1c4), Mathf.Round(val.r2c4), Mathf.Round(val.r3c4), Mathf.Round(val.r4c4)); + new(Mathf.Round(val.r1c1), Mathf.Round(val.r1c2), Mathf.Round(val.r1c3), Mathf.Round(val.r1c4), + Mathf.Round(val.r2c1), Mathf.Round(val.r2c2), Mathf.Round(val.r2c3), Mathf.Round(val.r2c4), + Mathf.Round(val.r3c1), Mathf.Round(val.r3c2), Mathf.Round(val.r3c3), Mathf.Round(val.r3c4), + Mathf.Round(val.r4c1), Mathf.Round(val.r4c2), Mathf.Round(val.r4c3), Mathf.Round(val.r4c4)); public static Matrix4x4 Subtract(Matrix4x4 num, params Matrix4x4[] vals) { foreach (Matrix4x4 m in vals) num -= m; @@ -321,37 +321,41 @@ public struct Matrix4x4 : IMatrix return val; } - public static (float[] r1c1s, float[] r2c1s, float[] r3c1s, float[] r4c1s, float[] r1c2s, float[] r2c2s, - float[] r3c2s, float[] r4c2s, float[] r1c3s, float[] r2c3s, float[] r3c3s, float[] r4c3s, float[] r1c4s, - float[] r2c4s, float[] r3c4s, float[] r4c4s) SplitArray(params Matrix4x4[] vals) + public static (float[] r1c1s, float[] r1c2, float[] r1c3, float[] r1c4, float[] r2c1, float[] r2c2s, + float[] r2c3, float[] r2c4, float[] r3c1, float[] r3c2, float[] r3c3s, float[] r3c4, float[] r4c1, + float[] r4c2, float[] r4c3, float[] r4c4s) SplitArray(params Matrix4x4[] vals) { - float[] r1c1s = new float[vals.Length], r2c1s = new float[vals.Length], r3c1s = new float[vals.Length], - r4c1s = new float[vals.Length], r1c2s = new float[vals.Length], r2c2s = new float[vals.Length], - r3c2s = new float[vals.Length], r4c2s = new float[vals.Length], r1c3s = new float[vals.Length], - r2c3s = new float[vals.Length], r3c3s = new float[vals.Length], r4c3s = new float[vals.Length], - r1c4s = new float[vals.Length], r2c4s = new float[vals.Length], r3c4s = new float[vals.Length], + float[] r1c1s = new float[vals.Length], r1c2s = new float[vals.Length], r1c3s = new float[vals.Length], + r1c4s = new float[vals.Length], r2c1s = new float[vals.Length], r2c2s = new float[vals.Length], + r2c3s = new float[vals.Length], r2c4s = new float[vals.Length], r3c1s = new float[vals.Length], + r3c2s = new float[vals.Length], r3c3s = new float[vals.Length], r3c4s = new float[vals.Length], + r4c1s = new float[vals.Length], r4c2s = new float[vals.Length], r4c3s = new float[vals.Length], r4c4s = new float[vals.Length]; for (int i = 0; i < vals.Length; i++) { r1c1s[i] = vals[i].r1c1; - r2c1s[i] = vals[i].r2c1; - r3c1s[i] = vals[i].r3c1; - r4c1s[i] = vals[i].r4c1; r1c2s[i] = vals[i].r1c2; - r2c2s[i] = vals[i].r2c2; - r3c2s[i] = vals[i].r3c2; - r4c2s[i] = vals[i].r4c2; r1c3s[i] = vals[i].r1c3; + r1c4s[i] = vals[i].r1c4; + r2c1s[i] = vals[i].r2c1; + r2c2s[i] = vals[i].r2c2; r2c3s[i] = vals[i].r2c3; + r2c4s[i] = vals[i].r2c4; + r3c1s[i] = vals[i].r3c1; + r3c2s[i] = vals[i].r3c2; r3c3s[i] = vals[i].r3c3; + r3c4s[i] = vals[i].r3c4; + r4c1s[i] = vals[i].r4c1; + r4c2s[i] = vals[i].r4c2; r4c3s[i] = vals[i].r4c3; r4c4s[i] = vals[i].r4c4; } - return (r1c1s, r2c1s, r3c1s, r4c1s, r1c2s, r2c2s, r3c2s, r4c2s, - r1c3s, r2c3s, r3c3s, r4c3s, r1c4s, r2c4s, r3c4s, r4c4s); + return (r1c1s, r1c2s, r1c3s, r1c4s, r2c1s, r2c2s, r2c3s, r2c4s, + r3c1s, r3c2s, r3c3s, r3c4s, r4c1s, r4c2s, r4c3s, r4c4s); } - public Matrix4x4 Adjugate() + public Matrix4x4 Adjugate() => Cofactor().Transpose(); + public Matrix4x4 Cofactor() { Matrix4x4 dets = new(); Matrix3x3[,] minors = Minors(); @@ -361,40 +365,40 @@ public struct Matrix4x4 : IMatrix public float Determinant() { Matrix3x3[,] minors = Minors(); - return (r1c1 * minors[0, 0].Determinant()) - (r1c2 * minors[1, 0].Determinant()) + - (r1c3 * minors[2, 0].Determinant()) - (r1c4 * minors[3, 0].Determinant()); + return (r1c1 * minors[0, 0].Determinant()) - (r1c2 * minors[0, 1].Determinant()) + + (r1c3 * minors[0, 2].Determinant()) - (r1c4 * minors[0, 3].Determinant()); } public Matrix4x4 Inverse() { float d = Determinant(); if (d == 0) throw new NoInverseException(); - return Transpose().Adjugate() / d; + return Adjugate() / d; } public Matrix3x3[,] Minors() => new Matrix3x3[,] { { - new(r2c2, r3c2, r4c2, r2c3, r3c3, r4c3, r2c4, r3c4, r4c4), - new(r2c1, r3c1, r4c1, r2c3, r3c3, r4c3, r2c4, r3c4, r4c4), - new(r2c1, r3c1, r4c1, r2c2, r3c2, r4c2, r2c4, r3c4, r4c4), - new(r2c1, r3c1, r4c1, r2c2, r3c2, r4c2, r2c3, r3c3, r4c3) + new(r2c2, r2c3, r2c4, r3c2, r3c3, r3c4, r4c2, r4c3, r4c4), + new(r2c1, r2c3, r2c4, r3c1, r3c3, r3c4, r4c1, r4c3, r4c4), + new(r2c1, r2c2, r2c4, r3c1, r3c2, r3c4, r4c1, r4c2, r4c4), + new(r2c1, r2c2, r2c3, r3c1, r3c2, r3c3, r4c1, r4c2, r4c3) }, { - new(r1c2, r3c2, r4c2, r1c3, r3c3, r4c3, r1c4, r3c4, r4c4), - new(r1c1, r3c1, r4c1, r1c3, r3c3, r4c3, r1c4, r3c4, r4c4), - new(r1c1, r3c1, r4c1, r1c2, r3c2, r4c2, r1c4, r3c4, r4c4), - new(r1c1, r3c1, r4c1, r1c2, r3c2, r4c2, r1c3, r3c3, r4c3) + new(r1c2, r1c3, r1c4, r3c2, r3c3, r3c4, r4c2, r4c3, r4c4), + new(r1c1, r1c3, r1c4, r3c1, r3c3, r3c4, r4c1, r4c3, r4c4), + new(r1c1, r1c2, r1c4, r3c1, r3c2, r3c4, r4c1, r4c2, r4c4), + new(r1c1, r1c2, r1c3, r3c1, r3c2, r3c3, r4c1, r4c2, r4c3) }, { - new(r1c2, r2c2, r4c2, r1c3, r2c3, r4c3, r1c4, r2c4, r4c4), - new(r1c1, r2c1, r4c1, r1c3, r2c3, r4c3, r1c4, r2c4, r4c4), - new(r1c1, r2c1, r4c1, r1c2, r2c2, r4c2, r1c4, r2c4, r4c4), - new(r1c1, r2c1, r4c1, r1c2, r2c2, r4c2, r1c3, r2c3, r4c3) + new(r1c2, r1c3, r1c4, r2c2, r2c3, r2c4, r4c2, r4c3, r4c4), + new(r1c1, r1c3, r1c4, r2c1, r2c3, r2c4, r4c1, r4c3, r4c4), + new(r1c1, r1c2, r1c4, r2c1, r2c2, r2c4, r4c1, r4c2, r4c4), + new(r1c1, r1c2, r1c3, r2c1, r2c2, r2c3, r4c1, r4c2, r4c3) }, { - new(r1c2, r2c2, r3c2, r1c3, r2c3, r3c3, r1c4, r2c4, r3c4), - new(r1c1, r2c1, r3c1, r1c3, r2c3, r3c3, r1c4, r2c4, r3c4), - new(r1c1, r2c1, r3c1, r1c2, r2c2, r3c2, r1c4, r2c4, r3c4), - new(r1c1, r2c1, r3c1, r1c2, r2c2, r3c2, r1c3, r2c3, r3c3) + new(r1c2, r1c3, r1c4, r2c2, r2c3, r2c4, r3c2, r3c3, r3c4), + new(r1c1, r1c3, r1c4, r2c1, r2c3, r2c4, r3c1, r3c3, r3c4), + new(r1c1, r1c2, r1c4, r2c1, r2c2, r2c4, r3c1, r3c2, r3c4), + new(r1c1, r1c2, r1c3, r2c1, r2c2, r2c3, r3c1, r3c2, r3c3) } }; public Matrix4x4 Transpose() => new(new[,] @@ -411,15 +415,16 @@ public struct Matrix4x4 : IMatrix return Equals((Matrix4x4)obj); } public bool Equals(Matrix4x4 other) => - r1c1 == other.r1c1 && r2c1 == other.r2c1 && r3c1 == other.r3c1 && r4c1 == other.r4c1 && - r1c2 == other.r1c2 && r2c2 == other.r2c2 && r3c2 == other.r3c2 && r4c2 == other.r4c2 && - r1c3 == other.r1c3 && r2c3 == other.r2c3 && r3c3 == other.r3c3 && r4c3 == other.r4c3 && - r1c4 == other.r1c4 && r2c3 == other.r2c4 && r3c4 == other.r3c4 && r4c4 == other.r4c4; + r1c1 == other.r1c1 && r1c2 == other.r1c2 && r1c3 == other.r1c3 && r1c4 == other.r1c4 && + r2c1 == other.r2c1 && r2c2 == other.r2c2 && r2c3 == other.r2c3 && r2c4 == other.r2c4 && + r3c1 == other.r3c1 && r3c2 == other.r3c2 && r3c3 == other.r3c3 && r3c4 == other.r3c4 && + r4c1 == other.r4c1 && r4c2 == other.r4c2 && r4c3 == other.r4c3 && r4c4 == other.r4c4; public override int GetHashCode() => - r1c1.GetHashCode() ^ r2c1.GetHashCode() ^ r3c1.GetHashCode() ^ r4c1.GetHashCode() ^ - r1c2.GetHashCode() ^ r2c2.GetHashCode() ^ r3c2.GetHashCode() ^ r4c2.GetHashCode() ^ - r1c3.GetHashCode() ^ r2c3.GetHashCode() ^ r3c3.GetHashCode() ^ r4c3.GetHashCode() ^ - r1c4.GetHashCode() ^ r2c4.GetHashCode() ^ r3c4.GetHashCode() ^ r4c4.GetHashCode(); + r1c1.GetHashCode() ^ r1c2.GetHashCode() ^ r1c3.GetHashCode() ^ r1c4.GetHashCode() ^ + r2c1.GetHashCode() ^ r2c2.GetHashCode() ^ r2c3.GetHashCode() ^ r2c4.GetHashCode() ^ + r3c1.GetHashCode() ^ r3c2.GetHashCode() ^ r3c3.GetHashCode() ^ r3c4.GetHashCode() ^ + r4c1.GetHashCode() ^ r4c2.GetHashCode() ^ r4c3.GetHashCode() ^ r4c4.GetHashCode(); + public override string ToString() => ToString((string?)null); public string ToString(string? provider) => r1c1.ToString(provider) + " " + r1c2.ToString(provider) + " " + r1c3.ToString(provider) + " " + r1c4.ToString(provider) + "\n" + r2c1.ToString(provider) + " " + r2c2.ToString(provider) + " " + @@ -441,20 +446,20 @@ public struct Matrix4x4 : IMatrix public IEnumerator GetEnumerator() { yield return r1c1; - yield return r2c1; - yield return r3c1; - yield return r4c1; yield return r1c2; - yield return r2c2; - yield return r3c2; - yield return r4c2; yield return r1c3; - yield return r2c3; - yield return r3c3; - yield return r4c3; yield return r1c4; + yield return r2c1; + yield return r2c2; + yield return r2c3; yield return r2c4; + yield return r3c1; + yield return r3c2; + yield return r3c3; yield return r3c4; + yield return r4c1; + yield return r4c2; + yield return r4c3; yield return r4c4; } @@ -472,13 +477,6 @@ public struct Matrix4x4 : IMatrix { r3c1, r3c2, r3c3, r3c4 }, { r4c1, r4c2, r4c3, r4c4 } }; - public Dictionary ToDictionary() - { - Dictionary dict = new(); - float[] arr = ToArray(); - for (int i = 0; i < arr.Length; i++) dict.Add(new(i % 4, i / 4), arr[i]); - return dict; - } public Fill ToFill() => ToFillExtension.ToFill(this); public Fill2D ToFill2D() { @@ -494,21 +492,21 @@ public struct Matrix4x4 : IMatrix }; public static Matrix4x4 operator +(Matrix4x4 a, Matrix4x4 b) => - new(a.r1c1 + b.r1c1, a.r2c1 + b.r2c1, a.r3c1 + b.r3c1, a.r4c1 + b.r4c1, - a.r1c2 + b.r1c2, a.r2c2 + b.r2c2, a.r3c2 + b.r3c2, a.r4c2 + b.r4c2, - a.r1c3 + b.r1c3, a.r2c3 + b.r2c3, a.r3c3 + b.r3c3, a.r4c3 + b.r4c3, - a.r1c4 + b.r1c4, a.r2c4 + b.r2c4, a.r3c4 + b.r3c4, a.r4c4 + b.r4c4); + new(a.r1c1 + b.r1c1, a.r1c2 + b.r1c2, a.r1c3 + b.r1c3, a.r1c4 + b.r1c4, + a.r2c1 + b.r2c1, a.r2c2 + b.r2c2, a.r2c3 + b.r2c3, a.r2c4 + b.r2c4, + a.r3c1 + b.r3c1, a.r3c2 + b.r3c2, a.r3c3 + b.r3c3, a.r3c4 + b.r3c4, + a.r4c1 + b.r4c1, a.r4c2 + b.r4c2, a.r4c3 + b.r4c3, a.r4c4 + b.r4c4); public static Matrix4x4 operator -(Matrix4x4 m) => m.Inverse(); public static Matrix4x4 operator -(Matrix4x4 a, Matrix4x4 b) => - new(a.r1c1 - b.r1c1, a.r2c1 - b.r2c1, a.r3c1 - b.r3c1, a.r4c1 - b.r4c1, - a.r1c2 - b.r1c2, a.r2c2 - b.r2c2, a.r3c2 - b.r3c2, a.r4c2 - b.r4c2, - a.r1c3 - b.r1c3, a.r2c3 - b.r2c3, a.r3c3 - b.r3c3, a.r4c3 - b.r4c3, - a.r1c4 - b.r1c4, a.r2c4 - b.r2c4, a.r3c4 - b.r3c4, a.r4c4 - b.r4c4); + new(a.r1c1 - b.r1c1, a.r1c2 - b.r1c2, a.r1c3 - b.r1c3, a.r1c4 - b.r1c4, + a.r2c1 - b.r2c1, a.r2c2 - b.r2c2, a.r2c3 - b.r2c3, a.r2c4 - b.r2c4, + a.r3c1 - b.r3c1, a.r3c2 - b.r3c2, a.r3c3 - b.r3c3, a.r3c4 - b.r3c4, + a.r4c1 - b.r4c1, a.r4c2 - b.r4c2, a.r4c3 - b.r4c3, a.r4c4 - b.r4c4); public static Matrix4x4 operator *(Matrix4x4 a, float b) => - new(a.r1c1 * b, a.r2c1 * b, a.r3c1 * b, a.r4c1 * b, - a.r1c2 * b, a.r2c2 * b, a.r3c2 * b, a.r4c2 * b, - a.r1c3 * b, a.r2c3 * b, a.r3c3 * b, a.r4c3 * b, - a.r1c4 * b, a.r2c4 * b, a.r3c4 * b, a.r4c4 * b); + new(a.r1c1 * b, a.r1c2 * b, a.r1c3 * b, a.r1c4 * b, + a.r2c1 * b, a.r2c2 * b, a.r2c3 * b, a.r2c4 * b, + a.r3c1 * b, a.r3c2 * b, a.r3c3 * b, a.r3c4 * b, + a.r4c1 * b, a.r4c2 * b, a.r4c3 * b, a.r4c4 * b); public static Matrix4x4 operator *(Matrix4x4 a, Matrix4x4 b) => new(new[,] { { Float4.Dot(a.Row1, b.Column1), Float4.Dot(a.Row1, b.Column2), @@ -520,17 +518,19 @@ public struct Matrix4x4 : IMatrix { Float4.Dot(a.Row4, b.Column1), Float4.Dot(a.Row4, b.Column2), Float4.Dot(a.Row4, b.Column3), Float4.Dot(a.Row4, b.Column4) } }); + public static Float4 operator *(Matrix4x4 a, Float4 b) => (Matrix)a * b; public static Matrix4x4 operator /(Matrix4x4 a, float b) => - new(a.r1c1 / b, a.r2c1 / b, a.r3c1 / b, a.r4c1 / b, - a.r1c2 / b, a.r2c2 / b, a.r3c2 / b, a.r4c2 / b, - a.r1c3 / b, a.r2c3 / b, a.r3c3 / b, a.r4c3 / b, - a.r1c4 / b, a.r2c4 / b, a.r3c4 / b, a.r4c4 / b); + new(a.r1c1 / b, a.r1c2 / b, a.r1c3 / b, a.r1c4 / b, + a.r2c1 / b, a.r2c2 / b, a.r2c3 / b, a.r2c4 / b, + a.r3c1 / b, a.r3c2 / b, a.r3c3 / b, a.r3c4 / b, + a.r4c1 / b, a.r4c2 / b, a.r4c3 / b, a.r4c4 / b); public static Matrix4x4 operator /(Matrix4x4 a, Matrix4x4 b) => a * b.Inverse(); + public static Float4 operator /(Matrix4x4 a, Float4 b) => (Matrix)a / b; public static Matrix4x4 operator ^(Matrix4x4 a, Matrix4x4 b) => // Single number multiplication - new(a.r1c1 * b.r1c1, a.r2c1 * b.r2c1, a.r3c1 * b.r3c1, a.r4c1 * b.r4c1, - a.r1c2 * b.r1c2, a.r2c2 * b.r2c2, a.r3c2 * b.r3c2, a.r4c2 * b.r4c2, - a.r1c3 * b.r1c3, a.r2c3 * b.r2c3, a.r3c3 * b.r3c3, a.r4c3 * b.r4c3, - a.r1c4 * b.r1c4, a.r2c4 * b.r2c4, a.r3c4 * b.r3c4, a.r4c4 * b.r4c4); + new(a.r1c1 * b.r1c1, a.r1c2 * b.r1c2, a.r1c3 * b.r1c3, a.r1c4 * b.r1c4, + a.r2c1 * b.r2c1, a.r2c2 * b.r2c2, a.r2c3 * b.r2c3, a.r2c4 * b.r2c4, + a.r3c1 * b.r3c1, a.r3c2 * b.r3c2, a.r3c3 * b.r3c3, a.r3c4 * b.r3c4, + a.r4c1 * b.r4c1, a.r4c2 * b.r4c2, a.r4c3 * b.r4c3, a.r4c4 * b.r4c4); public static bool operator ==(Matrix4x4 a, Matrix4x4 b) => a.Equals(b); public static bool operator !=(Matrix4x4 a, Matrix4x4 b) => !a.Equals(b); @@ -538,7 +538,7 @@ public struct Matrix4x4 : IMatrix { Matrix4x4 res = Zero, identity = Identity; for (int r = 0; r < 4; r++) for (int c = 0; c < 4; c++) - res[c, r] = m.Size.x < c && m.Size.y < r ? m[r, c] : identity[r, c]; + res[c, r] = m.Size.x > r && m.Size.y > c ? m[r, c] : identity[r, c]; return res; } public static implicit operator Matrix4x4(Matrix2x2 m) diff --git a/Nerd_STF/Mathematics/Float4.cs b/Nerd_STF/Mathematics/Float4.cs index 54ea508..34a678d 100644 --- a/Nerd_STF/Mathematics/Float4.cs +++ b/Nerd_STF/Mathematics/Float4.cs @@ -5,14 +5,14 @@ public struct Float4 : ICloneable, IComparable, IEquatable, IGro public static Float4 Back => new(0, 0, -1, 0); public static Float4 Down => new(0, -1, 0, 0); [Obsolete("Field has been replaced by " + nameof(HighW) + ", because it has a better name. " + - "This field will be removed in v2.4.0.", false)] + "This field will be removed in v2.4.0.", false)] public static Float4 Far => new(0, 0, 0, 1); public static Float4 Forward => new(0, 0, 1, 0); public static Float4 HighW => new(0, 0, 0, 1); public static Float4 Left => new(-1, 0, 0, 0); public static Float4 LowW => new(0, 0, 0, -1); [Obsolete("Field has been replaced by " + nameof(LowW) + ", because it has a better name. " + - "This field will be removed in v2.4.0.", false)] + "This field will be removed in v2.4.0.", false)] public static Float4 Near => new(0, 0, 0, -1); public static Float4 Right => new(1, 0, 0, 0); public static Float4 Up => new(0, 1, 0, 0); diff --git a/Nerd_STF/Mathematics/Geometry/Box2D.cs b/Nerd_STF/Mathematics/Geometry/Box2D.cs index b938c2f..177438a 100644 --- a/Nerd_STF/Mathematics/Geometry/Box2D.cs +++ b/Nerd_STF/Mathematics/Geometry/Box2D.cs @@ -24,7 +24,7 @@ public struct Box2D : ICloneable, IContainer, IEquatable } public float Area => size.x * size.y; - public float Perimeter => size.x * 2 + size.y * 2; + public float Perimeter => 2 * (size.x + size.y); public Vert center; public Float2 size; diff --git a/Nerd_STF/Mathematics/Geometry/Box3D.cs b/Nerd_STF/Mathematics/Geometry/Box3D.cs index 7930bff..73efa89 100644 --- a/Nerd_STF/Mathematics/Geometry/Box3D.cs +++ b/Nerd_STF/Mathematics/Geometry/Box3D.cs @@ -23,8 +23,9 @@ public struct Box3D : ICloneable, IContainer, IEquatable } } - public float Area => size.x * size.y * size.z; - public float Perimeter => size.x * 2 + size.y * 2 + size.z * 2; + public float Perimeter => 2 * (size.x + size.y + size.z); + public float SurfaceArea => 2 * (size.x * size.y + size.y * size.z + size.x * size.z); + public float Volume => size.x * size.y * size.z; public Vert center; public Float3 size; diff --git a/Nerd_STF/Mathematics/Geometry/Polygon.cs b/Nerd_STF/Mathematics/Geometry/Polygon.cs index 006a9f1..fb7084d 100644 --- a/Nerd_STF/Mathematics/Geometry/Polygon.cs +++ b/Nerd_STF/Mathematics/Geometry/Polygon.cs @@ -1,5 +1,6 @@ namespace Nerd_STF.Mathematics.Geometry; +[Obsolete("This struct is a garbage fire. This will be completely redesigned in v2.4.0")] public struct Polygon : ICloneable, IEquatable, IGroup, ISubdividable, ITriangulatable { public Line[] Lines @@ -379,8 +380,10 @@ public struct Polygon : ICloneable, IEquatable, IGroup, ISubdivid if (closest.Value.posB > closest.Value.posA) closest = (closest.Value.posB, closest.Value.posA, closest.Value.line); - List partA = new(Lines[closest.Value.posA..(closest.Value.posB - 1)]); - partA.Add(closest.Value.line); + List partA = new(Lines[closest.Value.posA..(closest.Value.posB - 1)]) + { + closest.Value.line + }; Polygon pA = new(partA.ToArray()); diff --git a/Nerd_STF/Mathematics/Geometry/Quadrilateral.cs b/Nerd_STF/Mathematics/Geometry/Quadrilateral.cs index ebf43b4..94929ce 100644 --- a/Nerd_STF/Mathematics/Geometry/Quadrilateral.cs +++ b/Nerd_STF/Mathematics/Geometry/Quadrilateral.cs @@ -94,6 +94,7 @@ public struct Quadrilateral : ICloneable, IEquatable, IGroup, IGroup fill) => new(fill); public static implicit operator Quadrilateral(Fill fill) => new(fill); public static implicit operator Quadrilateral(Fill fill) => new(fill); - public static explicit operator Quadrilateral(Polygon poly) => new(poly.Lines[0], poly.Lines[1], - poly.Lines[2], poly.Lines[3]); } diff --git a/Nerd_STF/Mathematics/Geometry/Sphere.cs b/Nerd_STF/Mathematics/Geometry/Sphere.cs index 850542e..bc81c5c 100644 --- a/Nerd_STF/Mathematics/Geometry/Sphere.cs +++ b/Nerd_STF/Mathematics/Geometry/Sphere.cs @@ -91,7 +91,7 @@ public struct Sphere : ICloneable, IClosest, IComparable, ICompara public bool Contains(Vert vert) => (center - vert).Magnitude <= radius; - public Vert ClosestTo(Vert vert) => Contains(vert) ? vert : ((vert - center).Normalized * radius) + vert; + public Vert ClosestTo(Vert vert) => Contains(vert) ? vert : ((vert - center).Normalized * radius) + center; public static Sphere operator +(Sphere a, Sphere b) => new(a.center + b.center, a.radius + b.radius); public static Sphere operator +(Sphere a, Vert b) => new(a.center + b, a.radius); diff --git a/Nerd_STF/Mathematics/Geometry/Triangle.cs b/Nerd_STF/Mathematics/Geometry/Triangle.cs index b9464c5..dab25e9 100644 --- a/Nerd_STF/Mathematics/Geometry/Triangle.cs +++ b/Nerd_STF/Mathematics/Geometry/Triangle.cs @@ -72,6 +72,7 @@ public struct Triangle : ICloneable, IEquatable, IGroup private Vert p_a, p_b, p_c; private Line p_ab, p_bc, p_ca; + [Obsolete("This field doesn't account for the Z-axis. This will be fixed in v2.4.0")] public float Area => (float)Mathf.Absolute((A.position.x * B.position.y) + (B.position.x * C.position.y) + (C.position.x * A.position.y) - ((B.position.x * A.position.y) + (C.position.x * B.position.y) + (A.position.x * C.position.y))) * 0.5f; @@ -273,5 +274,4 @@ public struct Triangle : ICloneable, IEquatable, IGroup public static implicit operator Triangle(Fill fill) => new(fill); public static implicit operator Triangle(Fill fill) => new(fill); public static implicit operator Triangle(Fill fill) => new(fill); - public static explicit operator Triangle(Polygon poly) => new(poly.Lines[0], poly.Lines[1], poly.Lines[2]); } diff --git a/Nerd_STF/Mathematics/Geometry/Vert.cs b/Nerd_STF/Mathematics/Geometry/Vert.cs index 6609ff7..6c48269 100644 --- a/Nerd_STF/Mathematics/Geometry/Vert.cs +++ b/Nerd_STF/Mathematics/Geometry/Vert.cs @@ -13,7 +13,7 @@ public struct Vert : ICloneable, IEquatable, IGroup public static Vert Zero => new(0, 0, 0); public float Magnitude => position.Magnitude; - public Vert Normalized => new(this / Magnitude); + public Vert Normalized => this / Magnitude; public Float3 position; diff --git a/Nerd_STF/Nerd_STF.csproj b/Nerd_STF/Nerd_STF.csproj index c63e564..5920e0c 100644 --- a/Nerd_STF/Nerd_STF.csproj +++ b/Nerd_STF/Nerd_STF.csproj @@ -12,16 +12,125 @@ Copyright (c) 2022 That_One_Nerd README.md https://github.com/That-One-Nerd/Nerd_STF - 2.3.1.52 + 2.3.1 c#;csharp;c sharp;math;mathematics;mathametics;maths;color;rgb;rgba;cmyk;cmyka;hsv;hsva;calculus;linear algebra;linalg;linearalgebra;matrix;matrix2x2;matrix 2x2;matrix3x3;matrix 3x3;matrix4x4;matrix 4x4;matrix multiplication;vector;vector2d;vector3d;vector2;vector3;float2;float3;float4;int2;int3;int4;angle;geometry;vert;line;polygon;triangle;quadrilateral;sphere;circle;number system;numbersystem;complex numbers;complex;2d numbers;2dnumbers;quaternions;4d numbers;4dnumbers - 2.3.1.52-alpha + 2.3.1 Nerd_STF Nerd_STF MIT Logo Square.png - The `v2.3.1.x` updates go through every single field and method in Nerd_STF to make sure it works correctly. + # Nerd_STF v2.3.1 + +***Everything has been tested and most things work!*** + +**WARNING:** +All of the matrix classes have had all of their constructors' row and column variables swapped. You'll have to switch all your variables around. +Sorry for the inconvenience :(. + +The `v2.3.1.x` updates go through every single field and method in Nerd_STF to make sure it works correctly. +You see, up until now I haven't actually tested literally anything at all. Partly because I didn't have the tools to and partly because I was lazy. But now, it's guarenteed to work in most cases (unless I like don't pick up some bug, you know). + +Hi everyone! Everything has been checked now and most stuff works! Not everything, like the triangle and quadrilateral area stuff, but for the most part, it's all cool and good. + +I've just now remembered how bad the Polygon struct was. It's getting remade. The v2.4.0 update will be mostly geometry focused, so that'll be the best time to figure out how to fix this stuff. The new Polygon struct will be much better, trust me. + +But all the matrix structs work like charm now! I'm honestly suprised they worked as well as they did before (especially the dynamic matrix). They can now be relied on. + +Next up is the documentation update. Stay tuned! +(This may be another update with beta parts, but I'm not sure yet. We'll see). + +*P.S. (NuGet only message): I didn't know I had the room to put the whole changelog here. I'll do that from now on.* + +``` +* Nerd_STF + * Exceptions + * DifferingVertCountException + = Marked as deprecated (uses deprecated struct `Polygon`) + * Extensions + * Container2DExtension + + GetSize<T>(T[,]) + + SwapDimensions<T>(T[,], Int2?) + * Flatten<T>(T[,]) + = Replaced a `size` parameter from an `Int2` to an `Int2?` + * Mathematics + * Algebra + * IMatrix + - ToDictionary() + * Matrix + + Cofactor() + + IdentityIsh(Int2) + + MinorOf(Int2) + - ToDictionary() + = Fixed `Determinant()` + = Fixed `Minors()` + = Fixed `Inverse()` + = Made `Identity(Int2)` only work with square matricies (since that's only when an identity exists) + = Marked the struct as `readonly` + = Simplified `Transpose()` + = Swapped row variables with column variables in all constructors (and methods that require those constructors). + = Swapped code for `Adjugate()` with `Cofactor()` + * Matrix2x2 + + Cofactor() + + operator *(Matrix2x2, Float2) + + operator /(Matrix2x2, Float2) + - ToDictionary() + = Swapped code for `Adjugate()` with `Cofactor()` + = Swapped row variables with column variables in all constructors (and methods that require those constructors). + = Fixed `this[int, int]` to compensate for the swapped variables. + = Fixed `operator -(Matrix2x2, Matrix2x2)` to not have an addition in one of the variables (fun). + = Fixed `Inverse()` + = Fixed `explicit operator Matrix2x2(Matrix)` + * Matrix3x3 + + Cofactor() + + operator *(Matrix3x3, Float3) + + operator /(Matrix3x3, Float3) + - ToDictionary() + = Swapped code for `Adjugate()` with `Cofactor()` + = Swapped row variables with column variables in all constructors (and methods that require those constructors). + = Fixed `this[int, int]` to compensate for the swapped variables. + = Fixed `Determinant()` + = Fixed `Inverse()` + = Fixed `explicit operator Matrix3x3(Matrix)` + * Matrix4x4 + + Cofactor() + + override string ToString() + + operator *(Matrix4x4, Float4) + + operator /(Matrix4x4, Float4) + - ToDictionary() + = Swapped code for `Adjugate()` with `Cofactor()` + = Swapped row variables with column variables in all constructors (and methods that require those constructors). + = Fixed `this[int, int]` to compensate for the swapped variables. + = Fixed `Determinant()` + = Fixed a typo in `Absolute(Matrix4x4)`, `Ceiling(Matrix4x4)`, `Floor(Matrix4x4)`, and `Round(Matrix4x4)` + = Fixed a typo in `Row1`, `Row2`, `Row3`, and `Row4`. Oops. + = Fixed some missing elements in `SplitArray(Matrix4x4[])` + = Fixed `explicit operator Matrix4x4(Matrix)` + * Geometry + * Box2D + = Simplified some code in `Perimeter` + * Box3D + + SurfaceArea + = Renamed `Area` to `Volume` + = Simplified some code in `Perimeter` + * Polygon + = Marked as deprecated (will be redone in v2.4.0) + = Simplified collection initialization in `Triangulate()` + * Quadrilateral + - explicit operator Triangle(Polygon) + = Marked `Area` as deprecated (uses deprecated `Triangle.Area` field) + * Sphere + = Fixed `ClosestTo(Vert)` + * Triangle + - explicit operator Triangle(Polygon) + = Marked `Area` as deprecated (will be fixed in v2.4.0) + * Vert + = Marked as deprecated (will be removed in v2.4.0). + = Optimized `Normalized` to not clone more than required. +``` https://github.com/That-One-Nerd/Nerd_STF False + False + False