From 3c95d6d43e69c75c34ddc35b8612d27bd9b0430c Mon Sep 17 00:00:00 2001
From: Tweety-lab <108560864+Tweety-lab@users.noreply.github.com>
Date: Wed, 28 May 2025 19:10:11 +1000
Subject: [PATCH 01/52] start of 3.0 Silk.Net.Maths rewrite
From 04846e7715fc6cb0e0e5d2107dc8a1da52dda4f3 Mon Sep 17 00:00:00 2001
From: Tweety-lab <108560864+Tweety-lab@users.noreply.github.com>
Date: Wed, 28 May 2025 20:27:39 +1000
Subject: [PATCH 02/52] Start work on Vector2I.
---
.../Maths/Maths/{ => Legacy}/Vector2D.Ops.cs | 0
sources/Maths/Maths/{ => Legacy}/Vector2D.cs | 0
.../Maths/Maths/{ => Legacy}/Vector3D.Ops.cs | 0
sources/Maths/Maths/{ => Legacy}/Vector3D.cs | 0
.../Maths/Maths/{ => Legacy}/Vector4D.Ops.cs | 0
sources/Maths/Maths/{ => Legacy}/Vector4D.cs | 0
sources/Maths/Maths/Vector2I.cs | 96 +++++++++++++++++++
7 files changed, 96 insertions(+)
rename sources/Maths/Maths/{ => Legacy}/Vector2D.Ops.cs (100%)
rename sources/Maths/Maths/{ => Legacy}/Vector2D.cs (100%)
rename sources/Maths/Maths/{ => Legacy}/Vector3D.Ops.cs (100%)
rename sources/Maths/Maths/{ => Legacy}/Vector3D.cs (100%)
rename sources/Maths/Maths/{ => Legacy}/Vector4D.Ops.cs (100%)
rename sources/Maths/Maths/{ => Legacy}/Vector4D.cs (100%)
create mode 100644 sources/Maths/Maths/Vector2I.cs
diff --git a/sources/Maths/Maths/Vector2D.Ops.cs b/sources/Maths/Maths/Legacy/Vector2D.Ops.cs
similarity index 100%
rename from sources/Maths/Maths/Vector2D.Ops.cs
rename to sources/Maths/Maths/Legacy/Vector2D.Ops.cs
diff --git a/sources/Maths/Maths/Vector2D.cs b/sources/Maths/Maths/Legacy/Vector2D.cs
similarity index 100%
rename from sources/Maths/Maths/Vector2D.cs
rename to sources/Maths/Maths/Legacy/Vector2D.cs
diff --git a/sources/Maths/Maths/Vector3D.Ops.cs b/sources/Maths/Maths/Legacy/Vector3D.Ops.cs
similarity index 100%
rename from sources/Maths/Maths/Vector3D.Ops.cs
rename to sources/Maths/Maths/Legacy/Vector3D.Ops.cs
diff --git a/sources/Maths/Maths/Vector3D.cs b/sources/Maths/Maths/Legacy/Vector3D.cs
similarity index 100%
rename from sources/Maths/Maths/Vector3D.cs
rename to sources/Maths/Maths/Legacy/Vector3D.cs
diff --git a/sources/Maths/Maths/Vector4D.Ops.cs b/sources/Maths/Maths/Legacy/Vector4D.Ops.cs
similarity index 100%
rename from sources/Maths/Maths/Vector4D.Ops.cs
rename to sources/Maths/Maths/Legacy/Vector4D.Ops.cs
diff --git a/sources/Maths/Maths/Vector4D.cs b/sources/Maths/Maths/Legacy/Vector4D.cs
similarity index 100%
rename from sources/Maths/Maths/Vector4D.cs
rename to sources/Maths/Maths/Legacy/Vector4D.cs
diff --git a/sources/Maths/Maths/Vector2I.cs b/sources/Maths/Maths/Vector2I.cs
new file mode 100644
index 0000000000..d3fd8fea4b
--- /dev/null
+++ b/sources/Maths/Maths/Vector2I.cs
@@ -0,0 +1,96 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+
+using System.Collections;
+using System.Numerics;
+
+namespace Silk.NET.Maths
+{
+ /// A structure representing a 2D integer vector.
+ internal struct Vector2I : IEquatable>, IReadOnlyList, ISpanFormattable
+ where T : IBinaryInteger
+ {
+ /// The X component of the vector.
+ public T X;
+
+ /// The Y component of the vector.
+ public T Y;
+
+ /// Creates a vector whose elements have the specified values.
+ /// The value to assign to the field.
+ /// The value to assign to the field.
+ public Vector2I(T x, T y) => (X, Y) = (x, y);
+
+ ///Gets the component at the specified index: 0 = X, 1 = Y.
+ public T this[int index] => index switch {
+ 0 => X,
+ 1 => Y,
+ _ => throw new ArgumentOutOfRangeException(nameof(index), "Index must be 0 or 1.")
+ };
+
+ /// The number of elements in the vector.
+ public int Count => 2;
+
+ /// Returns a boolean indicating whether the given Object is equal to this instance.
+ public bool Equals(Vector2I other) => X.Equals(other.X) && Y.Equals(other.Y);
+
+ /// Returns an enumerator that iterates through the vector components.
+ public IEnumerator GetEnumerator()
+ {
+ yield return X;
+ yield return Y;
+ }
+
+ /// Formats the vector as a string using the specified format and format provider.
+ public string ToString(string? format, IFormatProvider? formatProvider)
+ {
+ return $"<{X.ToString(format, formatProvider)}, {Y.ToString(format, formatProvider)}>";
+ }
+
+ /// Formats the vector as a string using the specified format and format provider.
+ public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider)
+ {
+ // Format components individually into temporary buffers
+ // Not too sure about this implementation
+ Span xBuffer = stackalloc char[64];
+ Span yBuffer = stackalloc char[64];
+
+ if (!X.TryFormat(xBuffer, out int xChars, format, provider) ||
+ !Y.TryFormat(yBuffer, out int yChars, format, provider))
+ {
+ charsWritten = 0;
+ return false;
+ }
+
+ // Calculate total required length: < + x + ", " + y + >
+ int requiredLength = 1 + xChars + 2 + yChars + 1;
+
+ if (destination.Length < requiredLength)
+ {
+ charsWritten = 0;
+ return false;
+ }
+
+ int pos = 0;
+ destination[pos++] = '<';
+
+ xBuffer[..xChars].CopyTo(destination[pos..]);
+ pos += xChars;
+
+ destination[pos++] = ',';
+ destination[pos++] = ' ';
+
+ yBuffer[..yChars].CopyTo(destination[pos..]);
+ pos += yChars;
+
+ destination[pos++] = '>';
+
+ charsWritten = pos;
+ return true;
+ }
+
+ /// Returns an enumerator that iterates through the vector components.
+ IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+ }
+}
From 7afd57ff1cd8f4b9532ffb1525a8772c3337dc93 Mon Sep 17 00:00:00 2001
From: Tweety-lab <108560864+Tweety-lab@users.noreply.github.com>
Date: Wed, 28 May 2025 20:52:29 +1000
Subject: [PATCH 03/52] Finish implementing Vector2I Interfaces.
---
sources/Maths/Maths/Vector2I.cs | 151 ++++++++++++++++++++++++++++++--
1 file changed, 143 insertions(+), 8 deletions(-)
diff --git a/sources/Maths/Maths/Vector2I.cs b/sources/Maths/Maths/Vector2I.cs
index d3fd8fea4b..542193478c 100644
--- a/sources/Maths/Maths/Vector2I.cs
+++ b/sources/Maths/Maths/Vector2I.cs
@@ -3,12 +3,22 @@
using System.Collections;
+using System.Diagnostics.CodeAnalysis;
using System.Numerics;
+using System.Text;
namespace Silk.NET.Maths
{
/// A structure representing a 2D integer vector.
- internal struct Vector2I : IEquatable>, IReadOnlyList, ISpanFormattable
+ internal struct Vector2I :
+ IEquatable>,
+ IReadOnlyList,
+ ISpanFormattable,
+ ISpanParsable>,
+ IUtf8SpanFormattable,
+ IUtf8SpanParsable>,
+ IParsable>,
+ IFormattable
where T : IBinaryInteger
{
/// The X component of the vector.
@@ -17,11 +27,22 @@ internal struct Vector2I : IEquatable>, IReadOnlyList, ISpanFo
/// The Y component of the vector.
public T Y;
- /// Creates a vector whose elements have the specified values.
- /// The value to assign to the field.
- /// The value to assign to the field.
+ /// Initializes both components to the same value.
+ public Vector2I(T value) => (X, Y) = (value, value);
+
+ /// Initializes the vector with individual values for X and Y.
public Vector2I(T x, T y) => (X, Y) = (x, y);
+ /// Initializes the vector from a span of two values.
+ public Vector2I(ReadOnlySpan values)
+ {
+ if (values.Length != 2)
+ throw new ArgumentException("Input span must contain exactly 2 elements.", nameof(values));
+
+ X = values[0];
+ Y = values[1];
+ }
+
///Gets the component at the specified index: 0 = X, 1 = Y.
public T this[int index] => index switch {
0 => X,
@@ -43,10 +64,7 @@ public IEnumerator GetEnumerator()
}
/// Formats the vector as a string using the specified format and format provider.
- public string ToString(string? format, IFormatProvider? formatProvider)
- {
- return $"<{X.ToString(format, formatProvider)}, {Y.ToString(format, formatProvider)}>";
- }
+ public string ToString(string? format, IFormatProvider? formatProvider) => $"<{X.ToString(format, formatProvider)}, {Y.ToString(format, formatProvider)}>";
/// Formats the vector as a string using the specified format and format provider.
public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider)
@@ -90,7 +108,124 @@ public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan
return true;
}
+ /// Parses a span to a Vector2I instance.
+ public static Vector2I Parse(ReadOnlySpan s, IFormatProvider? provider)
+ {
+ if (!TryParse(s, provider, out var result))
+ throw new FormatException("Invalid format for Vector2I.");
+
+ return result;
+ }
+
+ /// Parses a string to a Vector2I instance.
+ public static Vector2I Parse(string s, IFormatProvider? provider) => Parse(s.AsSpan(), provider);
+
+ /// Tries to parse a span to a Vector2I instance.
+ public static bool TryParse(ReadOnlySpan s, IFormatProvider? provider, [MaybeNullWhen(false)] out Vector2I result)
+ {
+ result = default;
+
+ s = s.Trim();
+ if (s.Length < 5 || s[0] != '<' || s[^1] != '>')
+ return false;
+
+ s = s[1..^1]; // Remove < and >
+
+ int commaIndex = s.IndexOf(',');
+ if (commaIndex < 0)
+ return false;
+
+ ReadOnlySpan xSpan = s[..commaIndex].Trim();
+ ReadOnlySpan ySpan = s[(commaIndex + 1)..].Trim();
+
+ if (T.TryParse(xSpan, provider, out var x) &&
+ T.TryParse(ySpan, provider, out var y))
+ {
+ result = new Vector2I(x, y);
+ return true;
+ }
+
+ return false;
+ }
+
+
+ /// Tries to parse a string to a Vector2I instance.
+ public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, [MaybeNullWhen(false)] out Vector2I result) =>
+ TryParse(s.AsSpan(), provider, out result);
+
+ /// Parses a span to a Vector2I instance.
+ static Vector2I ISpanParsable>.Parse(ReadOnlySpan s, IFormatProvider? provider) =>
+ Parse(s, provider);
+
+ /// Parses a string to a Vector2I instance.
+ static Vector2I IParsable>.Parse(string s, IFormatProvider? provider) =>
+ Parse(s, provider);
+
+ /// Tries to parse a span to a Vector2I instance.
+ static bool ISpanParsable>.TryParse(ReadOnlySpan s, IFormatProvider? provider, [MaybeNullWhen(false)] out Vector2I result) =>
+ TryParse(s, provider, out result);
+
+ /// Tries to parse a string to a Vector2I instance.
+ static bool IParsable>.TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, [MaybeNullWhen(false)] out Vector2I result) =>
+ TryParse(s, provider, out result);
+
/// Returns an enumerator that iterates through the vector components.
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
+
+ /// Formats the vector as a UTF-8 string using the specified format and format provider.
+ public bool TryFormat(Span utf8Destination, out int bytesWritten, ReadOnlySpan format, IFormatProvider? provider)
+ {
+ // Format components individually into temporary buffers
+ // Not too sure about this implementation
+ Span xBuffer = stackalloc char[64];
+ Span yBuffer = stackalloc char[64];
+
+ if (!X.TryFormat(xBuffer, out int xChars, format, provider) ||
+ !Y.TryFormat(yBuffer, out int yChars, format, provider))
+ {
+ bytesWritten = 0;
+ return false;
+ }
+
+ // Estimate total required UTF-8 bytes
+ int estimatedSize = Encoding.UTF8.GetByteCount(xBuffer[..xChars]) +
+ Encoding.UTF8.GetByteCount(yBuffer[..yChars]) +
+ Encoding.UTF8.GetByteCount("<, >");
+
+ if (utf8Destination.Length < estimatedSize)
+ {
+ bytesWritten = 0;
+ return false;
+ }
+
+ int totalBytes = 0;
+
+ totalBytes += Encoding.UTF8.GetBytes("<", utf8Destination[totalBytes..]);
+ totalBytes += Encoding.UTF8.GetBytes(xBuffer[..xChars], utf8Destination[totalBytes..]);
+ totalBytes += Encoding.UTF8.GetBytes(", ", utf8Destination[totalBytes..]);
+ totalBytes += Encoding.UTF8.GetBytes(yBuffer[..yChars], utf8Destination[totalBytes..]);
+ totalBytes += Encoding.UTF8.GetBytes(">", utf8Destination[totalBytes..]);
+
+ bytesWritten = totalBytes;
+ return true;
+ }
+
+ /// Parses a UTF-8 span to a Vector2I instance.
+ public static Vector2I Parse(ReadOnlySpan utf8Text, IFormatProvider? provider)
+ {
+ int charCount = Encoding.UTF8.GetCharCount(utf8Text);
+ Span charBuffer = charCount <= 128 ? stackalloc char[charCount] : new char[charCount];
+ Encoding.UTF8.GetChars(utf8Text, charBuffer);
+ return Parse(charBuffer, provider);
+ }
+
+ /// Tries to parse a UTF-8 span to a Vector2I instance.
+ public static bool TryParse(ReadOnlySpan utf8Text, IFormatProvider? provider, [MaybeNullWhen(false)] out Vector2I result)
+ {
+ int charCount = Encoding.UTF8.GetCharCount(utf8Text);
+ Span charBuffer = charCount <= 128 ? stackalloc char[charCount] : new char[charCount];
+ Encoding.UTF8.GetChars(utf8Text, charBuffer);
+ return TryParse(charBuffer, provider, out result);
+ }
}
}
From 249be1fc97763f1a6bb48306cf36b629a5fa6273 Mon Sep 17 00:00:00 2001
From: Tweety-lab <108560864+Tweety-lab@users.noreply.github.com>
Date: Wed, 28 May 2025 20:55:03 +1000
Subject: [PATCH 04/52] Add Vector2I Unit properties.
---
sources/Maths/Maths/Vector2I.cs | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/sources/Maths/Maths/Vector2I.cs b/sources/Maths/Maths/Vector2I.cs
index 542193478c..e4bca600b4 100644
--- a/sources/Maths/Maths/Vector2I.cs
+++ b/sources/Maths/Maths/Vector2I.cs
@@ -43,6 +43,18 @@ public Vector2I(ReadOnlySpan values)
Y = values[1];
}
+ /// Gets a vector whose 2 elements are equal to one.
+ public static Vector2I One => new(Scalar.One);
+
+ /// Gets the vector (1, 0).
+ public static Vector2I UnitX => new(Scalar.One, Scalar.Zero);
+
+ /// Gets the vector (0, 1).
+ public static Vector2I UnitY => new(Scalar.Zero, Scalar.One);
+
+ /// Returns a vector whose 2 elements are equal to zero.
+ public static Vector2I Zero => default;
+
///Gets the component at the specified index: 0 = X, 1 = Y.
public T this[int index] => index switch {
0 => X,
From 709c14295d051c3131074189a1f395310c0bb2c4 Mon Sep 17 00:00:00 2001
From: Tweety-lab <108560864+Tweety-lab@users.noreply.github.com>
Date: Wed, 28 May 2025 21:10:07 +1000
Subject: [PATCH 05/52] Add Vector3I Maths methods.
---
sources/Maths/Maths/Vector2I.cs | 99 ++++++++++++++++++++++++++++++++-
1 file changed, 96 insertions(+), 3 deletions(-)
diff --git a/sources/Maths/Maths/Vector2I.cs b/sources/Maths/Maths/Vector2I.cs
index e4bca600b4..5d0befb58a 100644
--- a/sources/Maths/Maths/Vector2I.cs
+++ b/sources/Maths/Maths/Vector2I.cs
@@ -5,6 +5,7 @@
using System.Collections;
using System.Diagnostics.CodeAnalysis;
using System.Numerics;
+using System.Runtime.InteropServices;
using System.Text;
namespace Silk.NET.Maths
@@ -55,6 +56,12 @@ public Vector2I(ReadOnlySpan values)
/// Returns a vector whose 2 elements are equal to zero.
public static Vector2I Zero => default;
+ /// Gets the squared length of the vector (dot product with itself).
+ public T LengthSquared => (X * X) + (Y * Y);
+
+ /// The number of elements in the vector.
+ public int Count => 2;
+
///Gets the component at the specified index: 0 = X, 1 = Y.
public T this[int index] => index switch {
0 => X,
@@ -62,9 +69,6 @@ public Vector2I(ReadOnlySpan values)
_ => throw new ArgumentOutOfRangeException(nameof(index), "Index must be 0 or 1.")
};
- /// The number of elements in the vector.
- public int Count => 2;
-
/// Returns a boolean indicating whether the given Object is equal to this instance.
public bool Equals(Vector2I other) => X.Equals(other.X) && Y.Equals(other.Y);
@@ -75,9 +79,59 @@ public IEnumerator GetEnumerator()
yield return Y;
}
+ /// Computes the dot product of this vector with another vector.
+ public T Dot(Vector2I other) => (X * other.X) + (Y * other.Y);
+
+ /// Computes the dot product of two vectors.
+ public static T Dot(Vector2I left, Vector2I right) => (left.X * right.X) + (left.Y * right.Y);
+
+ /// Computes the cross product of this vector with another vector.
+ public T Cross(Vector2I other) => (X * other.Y) - (Y * other.X);
+
+ /// Computes the cross product of two vectors.
+ public static T Cross(Vector2I left, Vector2I right) => (left.X * right.Y) - (left.Y * right.X);
+
+ /// Returns a span over the vector components.
+ public Span AsSpan() => MemoryMarshal.CreateSpan(ref X, 2);
+
+ /// Returns a vector with the component-wise maximum of this and another vector.
+ public Vector2I Max(Vector2I other) =>
+ new Vector2I(T.Max(X, other.X), T.Max(Y, other.Y));
+
+ /// Returns a vector with the component-wise maximum of two vectors.
+ public static Vector2I Max(Vector2I left, Vector2I right) =>
+ new Vector2I(T.Max(left.X, right.X), T.Max(left.Y, right.Y));
+
+ /// Returns a vector with the component-wise maximum of this vector and a scalar.
+ public Vector2I Max(T scalar) =>
+ new Vector2I(T.Max(X, scalar), T.Max(Y, scalar));
+
+ /// Returns a vector with the component-wise maximum of a vector and a scalar.
+ public static Vector2I Max(Vector2I vector, T scalar) =>
+ new Vector2I(T.Max(vector.X, scalar), T.Max(vector.Y, scalar));
+
+ /// Returns a vector with the component-wise minimum of this and another vector.
+ public Vector2I Min(Vector2I other) =>
+ new Vector2I(T.Min(X, other.X), T.Min(Y, other.Y));
+
+ /// Returns a vector with the component-wise minimum of two vectors.
+ public static Vector2I Min(Vector2I left, Vector2I right) =>
+ new Vector2I(T.Min(left.X, right.X), T.Min(left.Y, right.Y));
+
+ /// Returns a vector with the component-wise minimum of this vector and a scalar.
+ public Vector2I Min(T scalar) =>
+ new Vector2I(T.Min(X, scalar), T.Min(Y, scalar));
+
+ /// Returns a vector with the component-wise minimum of a vector and a scalar.
+ public static Vector2I Min(Vector2I vector, T scalar) =>
+ new Vector2I(T.Min(vector.X, scalar), T.Min(vector.Y, scalar));
+
/// Formats the vector as a string using the specified format and format provider.
public string ToString(string? format, IFormatProvider? formatProvider) => $"<{X.ToString(format, formatProvider)}, {Y.ToString(format, formatProvider)}>";
+ /// Formats the vector as a string.
+ public override string ToString() => $"<{X}, {Y}>";
+
/// Formats the vector as a string using the specified format and format provider.
public bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider)
{
@@ -239,5 +293,44 @@ public static bool TryParse(ReadOnlySpan utf8Text, IFormatProvider? provid
Encoding.UTF8.GetChars(utf8Text, charBuffer);
return TryParse(charBuffer, provider, out result);
}
+
+ // Component Operators
+ public static Vector2I operator +(Vector2I left, Vector2I right) =>
+ new Vector2I(left.X + right.X, left.Y + right.Y);
+
+ public static Vector2I operator -(Vector2I left, Vector2I right) =>
+ new Vector2I(left.X - right.X, left.Y - right.Y);
+
+ public static Vector2I operator *(Vector2I left, Vector2I right) =>
+ new Vector2I(left.X * right.X, left.Y * right.Y);
+
+ public static Vector2I operator /(Vector2I left, Vector2I right) =>
+ new Vector2I(left.X / right.X, left.Y / right.Y);
+
+ public static Vector2I operator %(Vector2I left, Vector2I right) =>
+ new Vector2I(left.X % right.X, left.Y % right.Y);
+
+ // Scalar Operators
+ public static Vector2I operator +(Vector2I vector, T scalar) =>
+ new Vector2I(vector.X + scalar, vector.Y + scalar);
+
+ public static Vector2I operator -(Vector2I vector, T scalar) =>
+ new Vector2I(vector.X - scalar, vector.Y - scalar);
+
+ public static Vector2I operator *(Vector2I vector, T scalar) =>
+ new Vector2I(vector.X * scalar, vector.Y * scalar);
+
+ public static Vector2I operator /(Vector2I vector, T scalar) =>
+ new Vector2I(vector.X / scalar, vector.Y / scalar);
+
+ public static Vector2I operator %(Vector2I vector, T scalar) =>
+ new Vector2I(vector.X % scalar, vector.Y % scalar);
+
+ // + operator: returns the vector (?)
+ public static Vector2I operator +(Vector2I vector) => vector;
+
+ // - operator: returns the negated vector
+ public static Vector2I operator -(Vector2I vector) =>
+ new Vector2I(-vector.X, -vector.Y);
}
}
From 94a912d94edd9fd5eb3b30690fdf49a24430dcef Mon Sep 17 00:00:00 2001
From: Tweety-lab <108560864+Tweety-lab@users.noreply.github.com>
Date: Wed, 28 May 2025 21:25:44 +1000
Subject: [PATCH 06/52] Add more missing Vector2I requirements.
---
sources/Maths/Maths/Vector2I.cs | 137 +++++++++++++++++++++++++++++++-
1 file changed, 135 insertions(+), 2 deletions(-)
diff --git a/sources/Maths/Maths/Vector2I.cs b/sources/Maths/Maths/Vector2I.cs
index 5d0befb58a..dfe0d5060d 100644
--- a/sources/Maths/Maths/Vector2I.cs
+++ b/sources/Maths/Maths/Vector2I.cs
@@ -47,14 +47,17 @@ public Vector2I(ReadOnlySpan values)
/// Gets a vector whose 2 elements are equal to one.
public static Vector2I One => new(Scalar.One);
+ /// Returns a vector whose 2 elements are equal to zero.
+ public static Vector2I Zero => default;
+
/// Gets the vector (1, 0).
public static Vector2I UnitX => new(Scalar.One, Scalar.Zero);
/// Gets the vector (0, 1).
public static Vector2I UnitY => new(Scalar.Zero, Scalar.One);
- /// Returns a vector whose 2 elements are equal to zero.
- public static Vector2I Zero => default;
+ /// Gets a vector with all bits set for each component.
+ public static Vector2I AllBitsSet => new Vector2I(T.AllBitsSet, T.AllBitsSet);
/// Gets the squared length of the vector (dot product with itself).
public T LengthSquared => (X * X) + (Y * Y);
@@ -126,6 +129,29 @@ public Vector2I Min(T scalar) =>
public static Vector2I Min(Vector2I vector, T scalar) =>
new Vector2I(T.Min(vector.X, scalar), T.Min(vector.Y, scalar));
+ /// Clamps this vector's components between the corresponding Min and Max vectors.
+ public Vector2I Clamp(Vector2I min, Vector2I max) =>
+ new Vector2I(T.Clamp(X, min.X, max.X), T.Clamp(Y, min.Y, max.Y));
+
+ /// Clamps the components of a vector between the corresponding Min and Max vectors.
+ public static Vector2I Clamp(Vector2I vector, Vector2I min, Vector2I max) =>
+ new Vector2I(T.Clamp(vector.X, min.X, max.X), T.Clamp(vector.Y, min.Y, max.Y));
+
+ /// Clamps this vector's components between the Min and Max scalar values.
+ public Vector2I Clamp(T min, T max) =>
+ new Vector2I(T.Clamp(X, min, max), T.Clamp(Y, min, max));
+
+ /// Clamps the components of a vector between the Min and Max scalar values.
+ public static Vector2I Clamp(Vector2I vector, T min, T max) =>
+ new Vector2I(T.Clamp(vector.X, min, max), T.Clamp(vector.Y, min, max));
+
+ /// Returns a vector with the absolute value of each component of this vector.
+ public Vector2I Abs() => new Vector2I(T.Abs(X), T.Abs(Y));
+
+ /// Returns a vector with the absolute value of each component of the specified vector.
+ public static Vector2I Abs(Vector2I vector) =>
+ new Vector2I(T.Abs(vector.X), T.Abs(vector.Y));
+
/// Formats the vector as a string using the specified format and format provider.
public string ToString(string? format, IFormatProvider? formatProvider) => $"<{X.ToString(format, formatProvider)}, {Y.ToString(format, formatProvider)}>";
@@ -183,6 +209,55 @@ public static Vector2I Parse(ReadOnlySpan s, IFormatProvider? provider)
return result;
}
+ /// Copies the components of the vector to the specified array starting at index 0.
+ public void CopyTo(T[] array) => CopyTo(array, 0);
+
+ /// Copies the components of the vector to the specified array starting at the given index.
+ public void CopyTo(T[] array, int startIndex)
+ {
+ if (array == null)
+ throw new ArgumentNullException(nameof(array));
+ if (startIndex < 0 || startIndex + 2 > array.Length)
+ throw new ArgumentOutOfRangeException(nameof(startIndex));
+ array[startIndex] = X;
+ array[startIndex + 1] = Y;
+ }
+
+ /// Copies the components of the vector to the specified span starting at index 0.
+ public void CopyTo(Span span) => CopyTo(span, 0);
+
+ /// Copies the components of the vector to the specified span starting at the given index.
+ public void CopyTo(Span span, int startIndex)
+ {
+ if (startIndex < 0 || startIndex + 2 > span.Length)
+ throw new ArgumentOutOfRangeException(nameof(startIndex));
+ span[startIndex] = X;
+ span[startIndex + 1] = Y;
+ }
+
+ /// Returns a vector where each component is the sign of the original vector's component.
+ public Vector2I Sign() => new Vector2I(T.CreateChecked(T.Sign(X)), T.CreateChecked(T.Sign(Y)));
+
+ /// Returns a vector where each component is the sign of the input vector's component.
+ public static Vector2I Sign(Vector2I vector) =>
+ new Vector2I(T.CreateChecked(T.Sign(vector.X)), T.CreateChecked(T.Sign(vector.Y)));
+
+ /// Copies the sign of each component from another vector to this vector's components.
+ public Vector2I CopySign(Vector2I signSource) =>
+ new Vector2I(T.CopySign(X, signSource.X), T.CopySign(Y, signSource.Y));
+
+ /// Copies the sign of each component from another vector to a new vector.
+ public static Vector2I CopySign(Vector2I value, Vector2I signSource) =>
+ new Vector2I(T.CopySign(value.X, signSource.X), T.CopySign(value.Y, signSource.Y));
+
+ /// Copies the sign of a scalar onto each component of this vector.
+ public Vector2I CopySign(T signScalar) =>
+ new Vector2I(T.CopySign(X, signScalar), T.CopySign(Y, signScalar));
+
+ /// Copies the sign of a scalar onto each component of a new vector.
+ public static Vector2I CopySign(Vector2I value, T signScalar) =>
+ new Vector2I(T.CopySign(value.X, signScalar), T.CopySign(value.Y, signScalar));
+
/// Parses a string to a Vector2I instance.
public static Vector2I Parse(string s, IFormatProvider? provider) => Parse(s.AsSpan(), provider);
@@ -294,6 +369,16 @@ public static bool TryParse(ReadOnlySpan utf8Text, IFormatProvider? provid
return TryParse(charBuffer, provider, out result);
}
+ // Casts
+
+ /// Explicitly casts a System.Numerics.Vector2 to a Vector2I.
+ public static explicit operator Vector2I(System.Numerics.Vector2 v) =>
+ new Vector2I((T)Convert.ChangeType(v.X, typeof(T)), (T)Convert.ChangeType(v.Y, typeof(T)));
+
+ /// Explicitly casts a Vector2I to System.Numerics.Vector2.
+ public static explicit operator System.Numerics.Vector2(Vector2I v) =>
+ new System.Numerics.Vector2(Convert.ToSingle(v.X), Convert.ToSingle(v.Y));
+
// Component Operators
public static Vector2I operator +(Vector2I left, Vector2I right) =>
new Vector2I(left.X + right.X, left.Y + right.Y);
@@ -332,5 +417,53 @@ public static bool TryParse(ReadOnlySpan utf8Text, IFormatProvider? provid
// - operator: returns the negated vector
public static Vector2I operator -(Vector2I vector) =>
new Vector2I(-vector.X, -vector.Y);
+
+ // Bitwise Operators
+ public static Vector2I operator &(Vector2I left, Vector2I right) =>
+ new Vector2I(left.X & right.X, left.Y & right.Y);
+
+ public static Vector2I operator |(Vector2I left, Vector2I right) =>
+ new Vector2I(left.X | right.X, left.Y | right.Y);
+
+ public static Vector2I operator ^(Vector2I left, Vector2I right) =>
+ new Vector2I(left.X ^ right.X, left.Y ^ right.Y);
+
+ public static Vector2I operator &(Vector2I vector, T scalar) =>
+ new Vector2I(vector.X & scalar, vector.Y & scalar);
+
+ public static Vector2I operator &(T scalar, Vector2I vector) =>
+ new Vector2I(scalar & vector.X, scalar & vector.Y);
+
+ public static Vector2I operator |(Vector2I vector, T scalar) =>
+ new Vector2I(vector.X | scalar, vector.Y | scalar);
+
+ public static Vector2I operator |(T scalar, Vector2I vector) =>
+ new Vector2I(scalar | vector.X, scalar | vector.Y);
+
+ public static Vector2I operator ^(Vector2I vector, T scalar) =>
+ new Vector2I(vector.X ^ scalar, vector.Y ^ scalar);
+
+ public static Vector2I operator ^(T scalar, Vector2I vector) =>
+ new Vector2I(scalar ^ vector.X, scalar ^ vector.Y);
+
+ // NOT operator
+ public static Vector2I operator ~(Vector2I vector) =>
+ new Vector2I(~vector.X, ~vector.Y);
+
+ // IBinaryInteger
+ // TODO: Verify these are actually correct
+
+ public static Vector2I Log2(Vector2I x) =>
+ new Vector2I(T.Log2(x.X), T.Log2(x.Y));
+
+ public static (Vector2I Quotient, Vector2I Remainder) DivRem(Vector2I