Enhance mathematical capabilities and job system

Added new numeric types for unsigned integers, including uint2, uint3, and uint4, along with their matrix types.
Added a new `quaternion` struct with constructors and methods for creating and manipulating quaternions.
Added methods for projecting and reflecting vectors, enhancing geometric operations.
Added utility functions for generating orthonormal bases and changing vector signs.
Added comprehensive unit tests for new mathematical functions and quaternion operations.
Added a high-performance job scheduling system with job management features and worker thread management.
Added new structs for job execution, allowing efficient job scheduling and execution.
Added utility functions for job execution, including methods for obtaining unique job IDs.

Changed access modifiers and property definitions in several files for improved clarity and maintainability.
Changed property definitions and method implementations in `ImageInfo.cs`, `ImageResult.cs`, and `ImageResultFloat.cs` for better readability.
Changed memory management functions in `CRuntime.cs` and improved memory allocation tracking in `MemoryStats.cs`.
Changed the project file to include references to necessary projects and enable unsafe code blocks.

Removed the `WorkerThreadPool.cs` file, integrating worker thread management directly into the `JobScheduler`.
Removed the `float4` struct and its associated methods and properties, transitioning to a new code generation strategy.
Removed the `float4.tt` template and other related files, indicating a shift in code generation approach.
Removed the `Vectorize.cs` file, indicating a change in how vector operations are handled.

Updated the `.gitignore` file to include IDE-specific settings.
Updated various XML files to define project components and structure.
Updated the `AllocationManager.cs` to improve memory allocation management and introduce new strategies.
Updated the `UnsafeArray.cs`, `UnsafeHashMap.cs`, and `UnsafeList.cs` to enhance performance and safety in unsafe contexts.
Updated error handling and function pointer management in `MemoryLeakException.cs` and `FunctionPointer.cs`.
Updated the `AssemblyInfo.cs` file to include global using directives for better code organization.
This commit is contained in:
2025-09-06 12:07:02 +09:00
parent eeff3313b5
commit a2a760594e
114 changed files with 20826 additions and 7217 deletions

View File

@@ -0,0 +1,95 @@
using Misaki.HighPerformance.Mathematics;
namespace Misaki.HighPerformance.Test.UnitTest.Mathematics;
[TestClass]
public class TestBool2
{
[TestMethod]
public void TestConstructors()
{
// Default constructor
var v1 = new bool2();
Assert.IsFalse(v1.x);
Assert.IsFalse(v1.y);
// Single value constructor
var v2 = new bool2(true);
Assert.IsTrue(v2.x);
Assert.IsTrue(v2.y);
// Component constructor
var v3 = new bool2(true, false);
Assert.IsTrue(v3.x);
Assert.IsFalse(v3.y);
}
[TestMethod]
public void TestLogicalOperators()
{
var a = new bool2(true, false);
var b = new bool2(false, true);
// Note: bool types don't typically have bitwise operators in this implementation
// They are primarily used for conditional operations with math functions
}
[TestMethod]
public void TestComparisonOperators()
{
var a = new bool2(true, false);
var b = new bool2(true, false);
var c = new bool2(false, true);
// For bool vectors, we typically use math.all for equality comparison
var isEqual = math.all(a == b);
Assert.IsTrue(isEqual);
var isNotEqual = math.any(a != c);
Assert.IsTrue(isNotEqual);
}
[TestMethod]
public void TestSwizzleProperties()
{
var v = new bool2(true, false);
Assert.IsTrue(v.x);
Assert.IsFalse(v.y);
var xy = v.xy;
Assert.IsTrue(xy.x);
Assert.IsFalse(xy.y);
}
[TestMethod]
public void TestMathFunctions()
{
var v = new bool2(true, false);
// Test any function
var anyResult = math.any(v);
Assert.IsTrue(anyResult);
var allFalse = new bool2(false, false);
var anyFalse = math.any(allFalse);
Assert.IsFalse(anyFalse);
// Test all function
var allResult = math.all(v);
Assert.IsFalse(allResult);
var allTrue = new bool2(true, true);
var allTrueResult = math.all(allTrue);
Assert.IsTrue(allTrueResult);
}
[TestMethod]
public void TestIndexer()
{
var v = new bool2(true, false);
Assert.IsTrue(v[0]);
Assert.IsFalse(v[1]);
}
}

View File

@@ -0,0 +1,123 @@
using Misaki.HighPerformance.Mathematics;
namespace Misaki.HighPerformance.Test.UnitTest.Mathematics;
[TestClass]
public class TestDouble2
{
[TestMethod]
public void TestConstructors()
{
// Default constructor
var v1 = new double2();
Assert.AreEqual(0.0, v1.x, 1e-15);
Assert.AreEqual(0.0, v1.y, 1e-15);
// Single value constructor
var v2 = new double2(5.5);
Assert.AreEqual(5.5, v2.x, 1e-15);
Assert.AreEqual(5.5, v2.y, 1e-15);
// Component constructor
var v3 = new double2(1.5, 2.5);
Assert.AreEqual(1.5, v3.x, 1e-15);
Assert.AreEqual(2.5, v3.y, 1e-15);
}
[TestMethod]
public void TestArithmeticOperators()
{
var a = new double2(10.5, 20.5);
var b = new double2(5.5, 4.5);
// Addition
var add = a + b;
Assert.AreEqual(16.0, add.x, 1e-15);
Assert.AreEqual(25.0, add.y, 1e-15);
// Subtraction
var sub = a - b;
Assert.AreEqual(5.0, sub.x, 1e-15);
Assert.AreEqual(16.0, sub.y, 1e-15);
// Multiplication
var mul = a * b;
Assert.AreEqual(57.75, mul.x, 1e-15);
Assert.AreEqual(92.25, mul.y, 1e-15);
// Division
var div = a / b;
Assert.AreEqual(10.5 / 5.5, div.x, 1e-15);
Assert.AreEqual(20.5 / 4.5, div.y, 1e-15);
// Scalar operations
var scalarMul = a * 2.0;
Assert.AreEqual(21.0, scalarMul.x, 1e-15);
Assert.AreEqual(41.0, scalarMul.y, 1e-15);
var scalarDiv = a / 2.0;
Assert.AreEqual(5.25, scalarDiv.x, 1e-15);
Assert.AreEqual(10.25, scalarDiv.y, 1e-15);
}
[TestMethod]
public void TestComparisonOperators()
{
var a = new double2(10.5, 20.5);
var b = new double2(10.5, 20.5);
var c = new double2(5.5, 30.5);
// Equality (approximate for floating point)
Assert.IsTrue(math.all(math.abs(a - b) < 1e-15));
Assert.IsFalse(math.all(math.abs(a - c) < 1e-15));
}
[TestMethod]
public void TestSwizzleProperties()
{
var v = new double2(1.5, 2.5);
Assert.AreEqual(1.5, v.x, 1e-15);
Assert.AreEqual(2.5, v.y, 1e-15);
// Test common swizzles
var xy = v.xy;
Assert.AreEqual(1.5, xy.x, 1e-15);
Assert.AreEqual(2.5, xy.y, 1e-15);
}
[TestMethod]
public void TestUnaryOperators()
{
var a = new double2(5.5, -3.5);
// Unary minus
var neg = -a;
Assert.AreEqual(-5.5, neg.x, 1e-15);
Assert.AreEqual(3.5, neg.y, 1e-15);
// Unary plus
var pos = +a;
Assert.AreEqual(5.5, pos.x, 1e-15);
Assert.AreEqual(-3.5, pos.y, 1e-15);
}
[TestMethod]
public void TestMathFunctions()
{
var v = new double2(3.0, 4.0);
// Test dot product
var dot = math.dot(v, v);
Assert.AreEqual(25.0, dot, 1e-15);
// Test length
var length = math.length(v);
Assert.AreEqual(5.0, length, 1e-15);
// Test normalize
var normalized = math.normalize(v);
var expectedLength = math.length(normalized);
Assert.AreEqual(1.0, expectedLength, 1e-15);
}
}

View File

@@ -0,0 +1,139 @@
using Misaki.HighPerformance.Mathematics;
namespace Misaki.HighPerformance.Test.UnitTest.Mathematics;
[TestClass]
public class TestFloat2
{
[TestMethod]
public void TestConstructors()
{
// Default constructor
var v1 = new float2();
Assert.AreEqual(0f, v1.x, 1e-6f);
Assert.AreEqual(0f, v1.y, 1e-6f);
// Single value constructor
var v2 = new float2(5.5f);
Assert.AreEqual(5.5f, v2.x, 1e-6f);
Assert.AreEqual(5.5f, v2.y, 1e-6f);
// Component constructor
var v3 = new float2(1.5f, 2.5f);
Assert.AreEqual(1.5f, v3.x, 1e-6f);
Assert.AreEqual(2.5f, v3.y, 1e-6f);
}
[TestMethod]
public void TestArithmeticOperators()
{
var a = new float2(10.5f, 20.5f);
var b = new float2(5.5f, 4.5f);
// Addition
var add = a + b;
Assert.AreEqual(16f, add.x, 1e-6f);
Assert.AreEqual(25f, add.y, 1e-6f);
// Subtraction
var sub = a - b;
Assert.AreEqual(5f, sub.x, 1e-6f);
Assert.AreEqual(16f, sub.y, 1e-6f);
// Multiplication
var mul = a * b;
Assert.AreEqual(57.75f, mul.x, 1e-6f);
Assert.AreEqual(92.25f, mul.y, 1e-6f);
// Division
var div = a / b;
Assert.AreEqual(10.5f / 5.5f, div.x, 1e-6f);
Assert.AreEqual(20.5f / 4.5f, div.y, 1e-6f);
// Scalar operations
var scalarMul = a * 2f;
Assert.AreEqual(21f, scalarMul.x, 1e-6f);
Assert.AreEqual(41f, scalarMul.y, 1e-6f);
var scalarDiv = a / 2f;
Assert.AreEqual(5.25f, scalarDiv.x, 1e-6f);
Assert.AreEqual(10.25f, scalarDiv.y, 1e-6f);
}
[TestMethod]
public void TestComparisonOperators()
{
var a = new float2(10.5f, 20.5f);
var b = new float2(10.5f, 20.5f);
var c = new float2(5.5f, 30.5f);
// Equality (approximate for floating point)
Assert.IsTrue(math.all(math.abs(a - b) < 1e-6f));
Assert.IsFalse(math.all(math.abs(a - c) < 1e-6f));
}
[TestMethod]
public void TestSwizzleProperties()
{
var v = new float2(1.5f, 2.5f);
Assert.AreEqual(1.5f, v.x, 1e-6f);
Assert.AreEqual(2.5f, v.y, 1e-6f);
var xy = v.xy;
Assert.AreEqual(1.5f, xy.x, 1e-6f);
Assert.AreEqual(2.5f, xy.y, 1e-6f);
}
[TestMethod]
public void TestStaticProperties()
{
var zero = float2.zero;
Assert.AreEqual(0f, zero.x, 1e-6f);
Assert.AreEqual(0f, zero.y, 1e-6f);
}
[TestMethod]
public void TestUnaryOperators()
{
var a = new float2(5.5f, -3.5f);
// Unary minus
var neg = -a;
Assert.AreEqual(-5.5f, neg.x, 1e-6f);
Assert.AreEqual(3.5f, neg.y, 1e-6f);
// Unary plus
var pos = +a;
Assert.AreEqual(5.5f, pos.x, 1e-6f);
Assert.AreEqual(-3.5f, pos.y, 1e-6f);
}
[TestMethod]
public void TestMathFunctions()
{
var v = new float2(3f, 4f);
// Test dot product
var dot = math.dot(v, v);
Assert.AreEqual(25f, dot, 1e-6f);
// Test length
var length = math.length(v);
Assert.AreEqual(5f, length, 1e-6f);
// Test normalize
var normalized = math.normalize(v);
var expectedLength = math.length(normalized);
Assert.AreEqual(1f, expectedLength, 1e-6f);
}
[TestMethod]
public void TestIndexer()
{
var v = new float2(10.5f, 20.5f);
Assert.AreEqual(10.5f, v[0], 1e-6f);
Assert.AreEqual(20.5f, v[1], 1e-6f);
}
}

View File

@@ -0,0 +1,177 @@
using Misaki.HighPerformance.Mathematics;
namespace Misaki.HighPerformance.Test.UnitTest.Mathematics;
[TestClass]
public class TestFloat3
{
[TestMethod]
public void TestConstructors()
{
// Default constructor
var v1 = new float3();
Assert.AreEqual(0f, v1.x, 1e-6f);
Assert.AreEqual(0f, v1.y, 1e-6f);
Assert.AreEqual(0f, v1.z, 1e-6f);
// Single value constructor
var v2 = new float3(5.5f);
Assert.AreEqual(5.5f, v2.x, 1e-6f);
Assert.AreEqual(5.5f, v2.y, 1e-6f);
Assert.AreEqual(5.5f, v2.z, 1e-6f);
// Component constructor
var v3 = new float3(1.5f, 2.5f, 3.5f);
Assert.AreEqual(1.5f, v3.x, 1e-6f);
Assert.AreEqual(2.5f, v3.y, 1e-6f);
Assert.AreEqual(3.5f, v3.z, 1e-6f);
// Mixed constructors
var v4 = new float3(new float2(1.5f, 2.5f), 3.5f);
Assert.AreEqual(1.5f, v4.x, 1e-6f);
Assert.AreEqual(2.5f, v4.y, 1e-6f);
Assert.AreEqual(3.5f, v4.z, 1e-6f);
}
[TestMethod]
public void TestArithmeticOperators()
{
var a = new float3(10.5f, 20.5f, 30.5f);
var b = new float3(5.5f, 4.5f, 6.5f);
// Addition
var add = a + b;
Assert.AreEqual(16f, add.x, 1e-6f);
Assert.AreEqual(25f, add.y, 1e-6f);
Assert.AreEqual(37f, add.z, 1e-6f);
// Subtraction
var sub = a - b;
Assert.AreEqual(5f, sub.x, 1e-6f);
Assert.AreEqual(16f, sub.y, 1e-6f);
Assert.AreEqual(24f, sub.z, 1e-6f);
// Multiplication
var mul = a * b;
Assert.AreEqual(57.75f, mul.x, 1e-6f);
Assert.AreEqual(92.25f, mul.y, 1e-6f);
Assert.AreEqual(198.25f, mul.z, 1e-6f);
// Scalar operations
var scalarMul = a * 2f;
Assert.AreEqual(21f, scalarMul.x, 1e-6f);
Assert.AreEqual(41f, scalarMul.y, 1e-6f);
Assert.AreEqual(61f, scalarMul.z, 1e-6f);
}
[TestMethod]
public void TestVectorOperations()
{
var a = new float3(1f, 0f, 0f);
var b = new float3(0f, 1f, 0f);
// Cross product
var cross = math.cross(a, b);
Assert.AreEqual(0f, cross.x, 1e-6f);
Assert.AreEqual(0f, cross.y, 1e-6f);
Assert.AreEqual(1f, cross.z, 1e-6f);
// Dot product
var dot = math.dot(a, b);
Assert.AreEqual(0f, dot, 1e-6f);
// Test with non-orthogonal vectors
var c = new float3(3f, 4f, 0f);
var d = new float3(1f, 1f, 1f);
var dotCD = math.dot(c, d);
Assert.AreEqual(7f, dotCD, 1e-6f); // 3*1 + 4*1 + 0*1 = 7
}
[TestMethod]
public void TestComparisonOperators()
{
var a = new float3(10.5f, 20.5f, 30.5f);
var b = new float3(10.5f, 20.5f, 30.5f);
var c = new float3(5.5f, 30.5f, 25.5f);
// Equality (approximate for floating point)
Assert.IsTrue(math.all(math.abs(a - b) < 1e-6f));
Assert.IsFalse(math.all(math.abs(a - c) < 1e-6f));
}
[TestMethod]
public void TestSwizzleProperties()
{
var v = new float3(1.5f, 2.5f, 3.5f);
Assert.AreEqual(1.5f, v.x, 1e-6f);
Assert.AreEqual(2.5f, v.y, 1e-6f);
Assert.AreEqual(3.5f, v.z, 1e-6f);
var xy = v.xy;
Assert.AreEqual(1.5f, xy.x, 1e-6f);
Assert.AreEqual(2.5f, xy.y, 1e-6f);
var xyz = v.xyz;
Assert.AreEqual(1.5f, xyz.x, 1e-6f);
Assert.AreEqual(2.5f, xyz.y, 1e-6f);
Assert.AreEqual(3.5f, xyz.z, 1e-6f);
}
[TestMethod]
public void TestUnaryOperators()
{
var a = new float3(5.5f, -3.5f, 7.5f);
// Unary minus
var neg = -a;
Assert.AreEqual(-5.5f, neg.x, 1e-6f);
Assert.AreEqual(3.5f, neg.y, 1e-6f);
Assert.AreEqual(-7.5f, neg.z, 1e-6f);
// Unary plus
var pos = +a;
Assert.AreEqual(5.5f, pos.x, 1e-6f);
Assert.AreEqual(-3.5f, pos.y, 1e-6f);
Assert.AreEqual(7.5f, pos.z, 1e-6f);
}
[TestMethod]
public void TestMathFunctions()
{
var v = new float3(3f, 4f, 0f);
// Test length
var length = math.length(v);
Assert.AreEqual(5f, length, 1e-6f);
// Test normalize
var normalized = math.normalize(v);
var expectedLength = math.length(normalized);
Assert.AreEqual(1f, expectedLength, 1e-6f);
Assert.AreEqual(0.6f, normalized.x, 1e-6f);
Assert.AreEqual(0.8f, normalized.y, 1e-6f);
Assert.AreEqual(0f, normalized.z, 1e-6f);
}
[TestMethod]
public void TestStaticValues()
{
var zero = float3.zero;
Assert.AreEqual(0f, zero.x, 1e-6f);
Assert.AreEqual(0f, zero.y, 1e-6f);
Assert.AreEqual(0f, zero.z, 1e-6f);
var right = new float3(1f, 0f, 0f);
var up = new float3(0f, 1f, 0f);
var forward = new float3(0f, 0f, 1f);
// These are common vector directions
Assert.AreEqual(1f, right.x, 1e-6f);
Assert.AreEqual(1f, up.y, 1e-6f);
Assert.AreEqual(1f, forward.z, 1e-6f);
}
}

View File

@@ -0,0 +1,200 @@
using Misaki.HighPerformance.Mathematics;
namespace Misaki.HighPerformance.Test.UnitTest.Mathematics;
[TestClass]
public class TestFloat4
{
[TestMethod]
public void TestConstructors()
{
// Default constructor
var v1 = new float4();
Assert.AreEqual(0f, v1.x, 1e-6f);
Assert.AreEqual(0f, v1.y, 1e-6f);
Assert.AreEqual(0f, v1.z, 1e-6f);
Assert.AreEqual(0f, v1.w, 1e-6f);
// Single value constructor
var v2 = new float4(5.5f);
Assert.AreEqual(5.5f, v2.x, 1e-6f);
Assert.AreEqual(5.5f, v2.y, 1e-6f);
Assert.AreEqual(5.5f, v2.z, 1e-6f);
Assert.AreEqual(5.5f, v2.w, 1e-6f);
// Component constructor
var v3 = new float4(1.5f, 2.5f, 3.5f, 4.5f);
Assert.AreEqual(1.5f, v3.x, 1e-6f);
Assert.AreEqual(2.5f, v3.y, 1e-6f);
Assert.AreEqual(3.5f, v3.z, 1e-6f);
Assert.AreEqual(4.5f, v3.w, 1e-6f);
// Mixed constructors
var v4 = new float4(new float2(1.5f, 2.5f), 3.5f, 4.5f);
Assert.AreEqual(1.5f, v4.x, 1e-6f);
Assert.AreEqual(2.5f, v4.y, 1e-6f);
Assert.AreEqual(3.5f, v4.z, 1e-6f);
Assert.AreEqual(4.5f, v4.w, 1e-6f);
var v5 = new float4(new float3(1.5f, 2.5f, 3.5f), 4.5f);
Assert.AreEqual(1.5f, v5.x, 1e-6f);
Assert.AreEqual(2.5f, v5.y, 1e-6f);
Assert.AreEqual(3.5f, v5.z, 1e-6f);
Assert.AreEqual(4.5f, v5.w, 1e-6f);
}
[TestMethod]
public void TestArithmeticOperators()
{
var a = new float4(10.5f, 20.5f, 30.5f, 40.5f);
var b = new float4(5.5f, 4.5f, 6.5f, 8.5f);
// Addition
var add = a + b;
Assert.AreEqual(16f, add.x, 1e-6f);
Assert.AreEqual(25f, add.y, 1e-6f);
Assert.AreEqual(37f, add.z, 1e-6f);
Assert.AreEqual(49f, add.w, 1e-6f);
// Subtraction
var sub = a - b;
Assert.AreEqual(5f, sub.x, 1e-6f);
Assert.AreEqual(16f, sub.y, 1e-6f);
Assert.AreEqual(24f, sub.z, 1e-6f);
Assert.AreEqual(32f, sub.w, 1e-6f);
// Multiplication
var mul = a * b;
Assert.AreEqual(57.75f, mul.x, 1e-6f);
Assert.AreEqual(92.25f, mul.y, 1e-6f);
Assert.AreEqual(198.25f, mul.z, 1e-6f);
Assert.AreEqual(344.25f, mul.w, 1e-6f);
// Scalar operations
var scalarMul = a * 2f;
Assert.AreEqual(21f, scalarMul.x, 1e-6f);
Assert.AreEqual(41f, scalarMul.y, 1e-6f);
Assert.AreEqual(61f, scalarMul.z, 1e-6f);
Assert.AreEqual(81f, scalarMul.w, 1e-6f);
}
[TestMethod]
public void TestVectorOperations()
{
var a = new float4(1f, 2f, 3f, 4f);
var b = new float4(5f, 6f, 7f, 8f);
// Dot product
var dot = math.dot(a, b);
Assert.AreEqual(70f, dot, 1e-6f); // 1*5 + 2*6 + 3*7 + 4*8 = 5+12+21+32 = 70
}
[TestMethod]
public void TestComparisonOperators()
{
var a = new float4(10.5f, 20.5f, 30.5f, 40.5f);
var b = new float4(10.5f, 20.5f, 30.5f, 40.5f);
var c = new float4(5.5f, 30.5f, 25.5f, 45.5f);
// Equality (approximate for floating point)
Assert.IsTrue(math.all(math.abs(a - b) < 1e-6f));
Assert.IsFalse(math.all(math.abs(a - c) < 1e-6f));
}
[TestMethod]
public void TestSwizzleProperties()
{
var v = new float4(1.5f, 2.5f, 3.5f, 4.5f);
Assert.AreEqual(1.5f, v.x, 1e-6f);
Assert.AreEqual(2.5f, v.y, 1e-6f);
Assert.AreEqual(3.5f, v.z, 1e-6f);
Assert.AreEqual(4.5f, v.w, 1e-6f);
var xy = v.xy;
Assert.AreEqual(1.5f, xy.x, 1e-6f);
Assert.AreEqual(2.5f, xy.y, 1e-6f);
var xyz = v.xyz;
Assert.AreEqual(1.5f, xyz.x, 1e-6f);
Assert.AreEqual(2.5f, xyz.y, 1e-6f);
Assert.AreEqual(3.5f, xyz.z, 1e-6f);
var xyzw = v.xyzw;
Assert.AreEqual(1.5f, xyzw.x, 1e-6f);
Assert.AreEqual(2.5f, xyzw.y, 1e-6f);
Assert.AreEqual(3.5f, xyzw.z, 1e-6f);
Assert.AreEqual(4.5f, xyzw.w, 1e-6f);
}
[TestMethod]
public void TestUnaryOperators()
{
var a = new float4(5.5f, -3.5f, 7.5f, -9.5f);
// Unary minus
var neg = -a;
Assert.AreEqual(-5.5f, neg.x, 1e-6f);
Assert.AreEqual(3.5f, neg.y, 1e-6f);
Assert.AreEqual(-7.5f, neg.z, 1e-6f);
Assert.AreEqual(9.5f, neg.w, 1e-6f);
// Unary plus
var pos = +a;
Assert.AreEqual(5.5f, pos.x, 1e-6f);
Assert.AreEqual(-3.5f, pos.y, 1e-6f);
Assert.AreEqual(7.5f, pos.z, 1e-6f);
Assert.AreEqual(-9.5f, pos.w, 1e-6f);
}
[TestMethod]
public void TestMathFunctions()
{
var v = new float4(1f, 2f, 2f, 0f);
// Test length
var length = math.length(v);
Assert.AreEqual(3f, length, 1e-6f); // sqrt(1+4+4+0) = sqrt(9) = 3
// Test normalize
var normalized = math.normalize(v);
var expectedLength = math.length(normalized);
Assert.AreEqual(1f, expectedLength, 1e-6f);
Assert.AreEqual(1f / 3f, normalized.x, 1e-6f);
Assert.AreEqual(2f / 3f, normalized.y, 1e-6f);
Assert.AreEqual(2f / 3f, normalized.z, 1e-6f);
Assert.AreEqual(0f, normalized.w, 1e-6f);
}
[TestMethod]
public void TestStaticValues()
{
var zero = float4.zero;
Assert.AreEqual(0f, zero.x, 1e-6f);
Assert.AreEqual(0f, zero.y, 1e-6f);
Assert.AreEqual(0f, zero.z, 1e-6f);
Assert.AreEqual(0f, zero.w, 1e-6f);
// Test unit vectors
var unitX = new float4(1f, 0f, 0f, 0f);
var unitY = new float4(0f, 1f, 0f, 0f);
var unitZ = new float4(0f, 0f, 1f, 0f);
var unitW = new float4(0f, 0f, 0f, 1f);
Assert.AreEqual(1f, unitX.x, 1e-6f);
Assert.AreEqual(1f, unitY.y, 1e-6f);
Assert.AreEqual(1f, unitZ.z, 1e-6f);
Assert.AreEqual(1f, unitW.w, 1e-6f);
}
[TestMethod]
public void TestIndexer()
{
var v = new float4(10.5f, 20.5f, 30.5f, 40.5f);
Assert.AreEqual(10.5f, v[0], 1e-6f);
Assert.AreEqual(20.5f, v[1], 1e-6f);
Assert.AreEqual(30.5f, v[2], 1e-6f);
Assert.AreEqual(40.5f, v[3], 1e-6f);
}
}

View File

@@ -0,0 +1,224 @@
using Misaki.HighPerformance.Mathematics;
namespace Misaki.HighPerformance.Test.UnitTest.Mathematics;
[TestClass]
public class TestFloat4x4
{
[TestMethod]
public void TestConstructors()
{
// Default constructor
var m1 = new float4x4();
var identity = float4x4.identity;
Assert.AreEqual(1f, identity.c0.x, 1e-6f);
Assert.AreEqual(0f, identity.c0.y, 1e-6f);
Assert.AreEqual(0f, identity.c0.z, 1e-6f);
Assert.AreEqual(0f, identity.c0.w, 1e-6f);
Assert.AreEqual(0f, identity.c1.x, 1e-6f);
Assert.AreEqual(1f, identity.c1.y, 1e-6f);
Assert.AreEqual(0f, identity.c1.z, 1e-6f);
Assert.AreEqual(0f, identity.c1.w, 1e-6f);
// Column constructor
var c0 = new float4(1f, 0f, 0f, 0f);
var c1 = new float4(0f, 1f, 0f, 0f);
var c2 = new float4(0f, 0f, 1f, 0f);
var c3 = new float4(0f, 0f, 0f, 1f);
var m2 = new float4x4(c0, c1, c2, c3);
Assert.AreEqual(1f, m2.c0.x, 1e-6f);
Assert.AreEqual(1f, m2.c1.y, 1e-6f);
Assert.AreEqual(1f, m2.c2.z, 1e-6f);
Assert.AreEqual(1f, m2.c3.w, 1e-6f);
}
[TestMethod]
public void TestArithmeticOperators()
{
var a = new float4x4(
new float4(1f, 2f, 3f, 4f),
new float4(5f, 6f, 7f, 8f),
new float4(9f, 10f, 11f, 12f),
new float4(13f, 14f, 15f, 16f)
);
var b = new float4x4(
new float4(1f, 1f, 1f, 1f),
new float4(1f, 1f, 1f, 1f),
new float4(1f, 1f, 1f, 1f),
new float4(1f, 1f, 1f, 1f)
);
// Addition
var add = a + b;
Assert.AreEqual(2f, add.c0.x, 1e-6f);
Assert.AreEqual(3f, add.c0.y, 1e-6f);
Assert.AreEqual(6f, add.c1.x, 1e-6f);
Assert.AreEqual(7f, add.c1.y, 1e-6f);
// Subtraction
var sub = a - b;
Assert.AreEqual(0f, sub.c0.x, 1e-6f);
Assert.AreEqual(1f, sub.c0.y, 1e-6f);
Assert.AreEqual(4f, sub.c1.x, 1e-6f);
Assert.AreEqual(5f, sub.c1.y, 1e-6f);
// Scalar multiplication
var scalarMul = a * 2f;
Assert.AreEqual(2f, scalarMul.c0.x, 1e-6f);
Assert.AreEqual(4f, scalarMul.c0.y, 1e-6f);
Assert.AreEqual(10f, scalarMul.c1.x, 1e-6f);
Assert.AreEqual(12f, scalarMul.c1.y, 1e-6f);
}
[TestMethod]
public void TestMatrixMultiplication()
{
// Identity matrix multiplication
var identity = new float4x4(
new float4(1f, 0f, 0f, 0f),
new float4(0f, 1f, 0f, 0f),
new float4(0f, 0f, 1f, 0f),
new float4(0f, 0f, 0f, 1f)
);
var testMatrix = new float4x4(
new float4(2f, 3f, 4f, 5f),
new float4(6f, 7f, 8f, 9f),
new float4(10f, 11f, 12f, 13f),
new float4(14f, 15f, 16f, 17f)
);
// Matrix multiplication with identity should return original matrix
var result = math.mul(identity, testMatrix);
Assert.AreEqual(testMatrix.c0.x, result.c0.x, 1e-6f);
Assert.AreEqual(testMatrix.c0.y, result.c0.y, 1e-6f);
Assert.AreEqual(testMatrix.c1.x, result.c1.x, 1e-6f);
Assert.AreEqual(testMatrix.c1.y, result.c1.y, 1e-6f);
}
[TestMethod]
public void TestMatrixVectorMultiplication()
{
var matrix = new float4x4(
new float4(1f, 0f, 0f, 0f),
new float4(0f, 1f, 0f, 0f),
new float4(0f, 0f, 1f, 0f),
new float4(0f, 0f, 0f, 1f)
);
var vector = new float4(1f, 2f, 3f, 1f);
// Identity matrix multiplication should return original vector
var result = math.mul(matrix, vector);
Assert.AreEqual(1f, result.x, 1e-6f);
Assert.AreEqual(2f, result.y, 1e-6f);
Assert.AreEqual(3f, result.z, 1e-6f);
Assert.AreEqual(1f, result.w, 1e-6f);
}
[TestMethod]
public void TestTranspose()
{
var matrix = new float4x4(
new float4(1f, 2f, 3f, 4f),
new float4(5f, 6f, 7f, 8f),
new float4(9f, 10f, 11f, 12f),
new float4(13f, 14f, 15f, 16f)
);
var transposed = math.transpose(matrix);
// Check that rows and columns are swapped
Assert.AreEqual(matrix.c0.x, transposed.c0.x, 1e-6f); // (0,0) stays same
Assert.AreEqual(matrix.c1.x, transposed.c0.y, 1e-6f); // (1,0) becomes (0,1)
Assert.AreEqual(matrix.c2.x, transposed.c0.z, 1e-6f); // (2,0) becomes (0,2)
Assert.AreEqual(matrix.c3.x, transposed.c0.w, 1e-6f); // (3,0) becomes (0,3)
Assert.AreEqual(matrix.c0.y, transposed.c1.x, 1e-6f); // (0,1) becomes (1,0)
Assert.AreEqual(matrix.c1.y, transposed.c1.y, 1e-6f); // (1,1) stays same
}
[TestMethod]
public void TestDeterminant()
{
// Test determinant of identity matrix (should be 1)
var identity = new float4x4(
new float4(1f, 0f, 0f, 0f),
new float4(0f, 1f, 0f, 0f),
new float4(0f, 0f, 1f, 0f),
new float4(0f, 0f, 0f, 1f)
);
var det = math.determinant(identity);
Assert.AreEqual(1f, det, 1e-6f);
}
[TestMethod]
public void TestInverse()
{
// Test inverse of identity matrix (should be identity)
var identity = new float4x4(
new float4(1f, 0f, 0f, 0f),
new float4(0f, 1f, 0f, 0f),
new float4(0f, 0f, 1f, 0f),
new float4(0f, 0f, 0f, 1f)
);
var inverse = math.inverse(identity);
Assert.AreEqual(1f, inverse.c0.x, 1e-6f);
Assert.AreEqual(0f, inverse.c0.y, 1e-6f);
Assert.AreEqual(0f, inverse.c1.x, 1e-6f);
Assert.AreEqual(1f, inverse.c1.y, 1e-6f);
Assert.AreEqual(1f, inverse.c2.z, 1e-6f);
Assert.AreEqual(1f, inverse.c3.w, 1e-6f);
}
[TestMethod]
public void TestComparisonOperators()
{
var a = new float4x4(
new float4(1f, 2f, 3f, 4f),
new float4(5f, 6f, 7f, 8f),
new float4(9f, 10f, 11f, 12f),
new float4(13f, 14f, 15f, 16f)
);
var b = new float4x4(
new float4(1f, 2f, 3f, 4f),
new float4(5f, 6f, 7f, 8f),
new float4(9f, 10f, 11f, 12f),
new float4(13f, 14f, 15f, 16f)
);
// Test equality
var isEqual = math.all(a.c0 == b.c0) &&
math.all(a.c1 == b.c1) &&
math.all(a.c2 == b.c2) &&
math.all(a.c3 == b.c3);
Assert.IsTrue(isEqual);
}
[TestMethod]
public void TestIndexer()
{
var matrix = new float4x4(
new float4(1f, 2f, 3f, 4f),
new float4(5f, 6f, 7f, 8f),
new float4(9f, 10f, 11f, 12f),
new float4(13f, 14f, 15f, 16f)
);
// Test column access
Assert.AreEqual(1f, matrix[0].x, 1e-6f);
Assert.AreEqual(2f, matrix[0].y, 1e-6f);
Assert.AreEqual(5f, matrix[1].x, 1e-6f);
Assert.AreEqual(6f, matrix[1].y, 1e-6f);
}
}

View File

@@ -0,0 +1,171 @@
using Misaki.HighPerformance.Mathematics;
namespace Misaki.HighPerformance.Test.UnitTest.Mathematics;
[TestClass]
public class TestInt2
{
[TestMethod]
public void TestConstructors()
{
// Default constructor
var v1 = new int2();
Assert.AreEqual(0, v1.x);
Assert.AreEqual(0, v1.y);
// Single value constructor
var v2 = new int2(5);
Assert.AreEqual(5, v2.x);
Assert.AreEqual(5, v2.y);
// Component constructor
var v3 = new int2(1, 2);
Assert.AreEqual(1, v3.x);
Assert.AreEqual(2, v3.y);
}
[TestMethod]
public void TestArithmeticOperators()
{
var a = new int2(10, 20);
var b = new int2(5, 4);
// Addition
var add = a + b;
Assert.AreEqual(15, add.x);
Assert.AreEqual(24, add.y);
// Subtraction
var sub = a - b;
Assert.AreEqual(5, sub.x);
Assert.AreEqual(16, sub.y);
// Multiplication
var mul = a * b;
Assert.AreEqual(50, mul.x);
Assert.AreEqual(80, mul.y);
// Division
var div = a / b;
Assert.AreEqual(2, div.x);
Assert.AreEqual(5, div.y);
// Scalar operations
var scalarMul = a * 2;
Assert.AreEqual(20, scalarMul.x);
Assert.AreEqual(40, scalarMul.y);
var scalarDiv = a / 2;
Assert.AreEqual(5, scalarDiv.x);
Assert.AreEqual(10, scalarDiv.y);
}
[TestMethod]
public void TestBitwiseOperators()
{
var a = new int2(0b1010, 0b1100);
var b = new int2(0b1100, 0b1010);
// Bitwise AND
var and = a & b;
Assert.AreEqual(0b1000, and.x);
Assert.AreEqual(0b1000, and.y);
// Bitwise OR
var or = a | b;
Assert.AreEqual(0b1110, or.x);
Assert.AreEqual(0b1110, or.y);
// Bitwise XOR
var xor = a ^ b;
Assert.AreEqual(0b0110, xor.x);
Assert.AreEqual(0b0110, xor.y);
// Bitwise NOT
var not = ~a;
Assert.AreEqual(~0b1010, not.x);
Assert.AreEqual(~0b1100, not.y);
}
[TestMethod]
public void TestShiftOperators()
{
var a = new int2(8, 16);
// Left shift
var leftShift = a << 1;
Assert.AreEqual(16, leftShift.x);
Assert.AreEqual(32, leftShift.y);
// Right shift
var rightShift = a >> 1;
Assert.AreEqual(4, rightShift.x);
Assert.AreEqual(8, rightShift.y);
}
[TestMethod]
public void TestComparisonOperators()
{
var a = new int2(10, 20);
var b = new int2(10, 20);
var c = new int2(5, 30);
// Equality
Assert.IsTrue(math.all(a == b));
Assert.IsFalse(math.all(a == c));
// Inequality
Assert.IsFalse(math.all(a != b));
Assert.IsTrue(math.all(a != c));
}
[TestMethod]
public void TestSwizzleProperties()
{
var v = new int2(1, 2);
// Test common swizzles if they exist
Assert.AreEqual(1, v.x);
Assert.AreEqual(2, v.y);
var xy = v.xy;
Assert.AreEqual(1, xy.x);
Assert.AreEqual(2, xy.y);
}
[TestMethod]
public void TestStaticProperties()
{
var zero = int2.zero;
Assert.AreEqual(0, zero.x);
Assert.AreEqual(0, zero.y);
var one = int2.one;
Assert.AreEqual(1, one.x);
Assert.AreEqual(1, one.y);
}
[TestMethod]
public void TestUnaryOperators()
{
var a = new int2(5, -3);
// Unary minus
var neg = -a;
Assert.AreEqual(-5, neg.x);
Assert.AreEqual(3, neg.y);
// Unary plus
var pos = +a;
Assert.AreEqual(5, pos.x);
Assert.AreEqual(-3, pos.y);
}
[TestMethod]
public void TestIndexer()
{
var v = new int2(10, 20);
Assert.AreEqual(10, v[0]);
Assert.AreEqual(20, v[1]);
}
}

View File

@@ -0,0 +1,198 @@
using Misaki.HighPerformance.Mathematics;
namespace Misaki.HighPerformance.Test.UnitTest.Mathematics;
[TestClass]
public class TestInt2x2
{
[TestMethod]
public void TestConstructors()
{
// Default constructor
var m1 = new int2x2();
// Column constructor
var c0 = new int2(1, 2);
var c1 = new int2(3, 4);
var m2 = new int2x2(c0, c1);
Assert.AreEqual(1, m2.c0.x);
Assert.AreEqual(2, m2.c0.y);
Assert.AreEqual(3, m2.c1.x);
Assert.AreEqual(4, m2.c1.y);
var m3 = new int2x2(1, 2, 3, 4);
Assert.AreEqual(1, m3.c0.x);
Assert.AreEqual(2, m3.c1.x);
Assert.AreEqual(3, m3.c0.y);
Assert.AreEqual(4, m3.c1.y);
}
[TestMethod]
public void TestArithmeticOperators()
{
var a = new int2x2(
new int2(1, 2),
new int2(3, 4)
);
var b = new int2x2(
new int2(5, 6),
new int2(7, 8)
);
// Addition
var add = a + b;
Assert.AreEqual(6, add.c0.x);
Assert.AreEqual(8, add.c0.y);
Assert.AreEqual(10, add.c1.x);
Assert.AreEqual(12, add.c1.y);
// Subtraction
var sub = b - a;
Assert.AreEqual(4, sub.c0.x);
Assert.AreEqual(4, sub.c0.y);
Assert.AreEqual(4, sub.c1.x);
Assert.AreEqual(4, sub.c1.y);
// Scalar multiplication
var scalarMul = a * 2;
Assert.AreEqual(2, scalarMul.c0.x);
Assert.AreEqual(4, scalarMul.c0.y);
Assert.AreEqual(6, scalarMul.c1.x);
Assert.AreEqual(8, scalarMul.c1.y);
}
[TestMethod]
public void TestMatrixMultiplication()
{
var a = new int2x2(
new int2(1, 2),
new int2(3, 4)
);
var b = new int2x2(
new int2(5, 6),
new int2(7, 8)
);
// Matrix multiplication
var mul = math.mul(a, b);
// Expected result: [1 3] * [5 7] = [1*5+3*6 1*7+3*8] = [23 31]
// [2 4] [6 8] [2*5+4*6 2*7+4*8] [34 46]
Assert.AreEqual(23, mul.c0.x);
Assert.AreEqual(34, mul.c0.y);
Assert.AreEqual(31, mul.c1.x);
Assert.AreEqual(46, mul.c1.y);
}
[TestMethod]
public void TestMatrixVectorMultiplication()
{
var matrix = new int2x2(
new int2(1, 2),
new int2(3, 4)
);
var vector = new int2(5, 6);
// Matrix-vector multiplication
var result = math.mul(matrix, vector);
// Expected: [1 3] * [5] = [1*5 + 3*6] = [23]
// [2 4] [6] [2*5 + 4*6] [34]
Assert.AreEqual(23, result.x);
Assert.AreEqual(34, result.y);
}
[TestMethod]
public void TestTranspose()
{
var matrix = new int2x2(
new int2(1, 2),
new int2(3, 4)
);
var transposed = math.transpose(matrix);
// [1 3] -> [1 2]
// [2 4] [3 4]
Assert.AreEqual(1, transposed.c0.x);
Assert.AreEqual(3, transposed.c0.y);
Assert.AreEqual(2, transposed.c1.x);
Assert.AreEqual(4, transposed.c1.y);
}
[TestMethod]
public void TestDeterminant()
{
var matrix = new int2x2(
new int2(1, 2),
new int2(3, 4)
);
var det = math.determinant(matrix);
// det = 1*4 - 2*3 = 4 - 6 = -2
Assert.AreEqual(-2, det);
}
[TestMethod]
public void TestIdentityMatrix()
{
var identity = int2x2.identity;
var testMatrix = new int2x2(
new int2(5, 6),
new int2(7, 8)
);
var result = math.mul(identity, testMatrix);
Assert.AreEqual(testMatrix.c0.x, result.c0.x);
Assert.AreEqual(testMatrix.c0.y, result.c0.y);
Assert.AreEqual(testMatrix.c1.x, result.c1.x);
Assert.AreEqual(testMatrix.c1.y, result.c1.y);
}
[TestMethod]
public void TestIndexer()
{
var matrix = new int2x2(
new int2(1, 2),
new int2(3, 4)
);
Assert.AreEqual(1, matrix[0].x);
Assert.AreEqual(2, matrix[0].y);
Assert.AreEqual(3, matrix[1].x);
Assert.AreEqual(4, matrix[1].y);
}
[TestMethod]
public void TestComparisonOperators()
{
var a = new int2x2(
new int2(1, 2),
new int2(3, 4)
);
var b = new int2x2(
new int2(1, 2),
new int2(3, 4)
);
var c = new int2x2(
new int2(5, 6),
new int2(7, 8)
);
// Test equality
var isEqual = math.all(a.c0 == b.c0) && math.all(a.c1 == b.c1);
Assert.IsTrue(isEqual);
var isDifferent = math.any(a.c0 != c.c0) || math.any(a.c1 != c.c1);
Assert.IsTrue(isDifferent);
}
}

View File

@@ -0,0 +1,167 @@
using Misaki.HighPerformance.Mathematics;
namespace Misaki.HighPerformance.Test.UnitTest.Mathematics;
[TestClass]
public class TestInt3
{
[TestMethod]
public void TestConstructors()
{
// Default constructor
var v1 = new int3();
Assert.AreEqual(0, v1.x);
Assert.AreEqual(0, v1.y);
Assert.AreEqual(0, v1.z);
// Single value constructor
var v2 = new int3(5);
Assert.AreEqual(5, v2.x);
Assert.AreEqual(5, v2.y);
Assert.AreEqual(5, v2.z);
// Component constructor
var v3 = new int3(1, 2, 3);
Assert.AreEqual(1, v3.x);
Assert.AreEqual(2, v3.y);
Assert.AreEqual(3, v3.z);
// Mixed constructors
var v4 = new int3(new int2(1, 2), 3);
Assert.AreEqual(1, v4.x);
Assert.AreEqual(2, v4.y);
Assert.AreEqual(3, v4.z);
var v5 = new int3(1, new int2(2, 3));
Assert.AreEqual(1, v5.x);
Assert.AreEqual(2, v5.y);
Assert.AreEqual(3, v5.z);
}
[TestMethod]
public void TestArithmeticOperators()
{
var a = new int3(10, 20, 30);
var b = new int3(5, 4, 6);
// Addition
var add = a + b;
Assert.AreEqual(15, add.x);
Assert.AreEqual(24, add.y);
Assert.AreEqual(36, add.z);
// Subtraction
var sub = a - b;
Assert.AreEqual(5, sub.x);
Assert.AreEqual(16, sub.y);
Assert.AreEqual(24, sub.z);
// Multiplication
var mul = a * b;
Assert.AreEqual(50, mul.x);
Assert.AreEqual(80, mul.y);
Assert.AreEqual(180, mul.z);
// Division
var div = a / b;
Assert.AreEqual(2, div.x);
Assert.AreEqual(5, div.y);
Assert.AreEqual(5, div.z);
// Scalar operations
var scalarMul = a * 2;
Assert.AreEqual(20, scalarMul.x);
Assert.AreEqual(40, scalarMul.y);
Assert.AreEqual(60, scalarMul.z);
}
[TestMethod]
public void TestBitwiseOperators()
{
var a = new int3(0b1010, 0b1100, 0b1001);
var b = new int3(0b1100, 0b1010, 0b1011);
// Bitwise AND
var and = a & b;
Assert.AreEqual(0b1000, and.x);
Assert.AreEqual(0b1000, and.y);
Assert.AreEqual(0b1001, and.z);
// Bitwise OR
var or = a | b;
Assert.AreEqual(0b1110, or.x);
Assert.AreEqual(0b1110, or.y);
Assert.AreEqual(0b1011, or.z);
}
[TestMethod]
public void TestComparisonOperators()
{
var a = new int3(10, 20, 30);
var b = new int3(10, 20, 30);
var c = new int3(5, 30, 25);
// Equality
Assert.IsTrue(math.all(a == b));
Assert.IsFalse(math.all(a == c));
// Inequality
Assert.IsFalse(math.all(a != b));
Assert.IsTrue(math.all(a != c));
}
[TestMethod]
public void TestSwizzleProperties()
{
var v = new int3(1, 2, 3);
Assert.AreEqual(1, v.x);
Assert.AreEqual(2, v.y);
Assert.AreEqual(3, v.z);
// Test common swizzles if they exist
try
{
var xy = v.xy;
Assert.AreEqual(1, xy.x);
Assert.AreEqual(2, xy.y);
var xyz = v.xyz;
Assert.AreEqual(1, xyz.x);
Assert.AreEqual(2, xyz.y);
Assert.AreEqual(3, xyz.z);
}
catch
{
// Swizzles might not be implemented
}
}
[TestMethod]
public void TestUnaryOperators()
{
var a = new int3(5, -3, 7);
// Unary minus
var neg = -a;
Assert.AreEqual(-5, neg.x);
Assert.AreEqual(3, neg.y);
Assert.AreEqual(-7, neg.z);
// Unary plus
var pos = +a;
Assert.AreEqual(5, pos.x);
Assert.AreEqual(-3, pos.y);
Assert.AreEqual(7, pos.z);
}
[TestMethod]
public void TestIndexer()
{
var v = new int3(10, 20, 30);
Assert.AreEqual(10, v[0]);
Assert.AreEqual(20, v[1]);
Assert.AreEqual(30, v[2]);
}
}

View File

@@ -0,0 +1,187 @@
using Misaki.HighPerformance.Mathematics;
namespace Misaki.HighPerformance.Test.UnitTest.Mathematics;
[TestClass]
public class TestInt4
{
[TestMethod]
public void TestConstructors()
{
// Default constructor
var v1 = new int4();
Assert.AreEqual(0, v1.x);
Assert.AreEqual(0, v1.y);
Assert.AreEqual(0, v1.z);
Assert.AreEqual(0, v1.w);
// Single value constructor
var v2 = new int4(5);
Assert.AreEqual(5, v2.x);
Assert.AreEqual(5, v2.y);
Assert.AreEqual(5, v2.z);
Assert.AreEqual(5, v2.w);
// Component constructor
var v3 = new int4(1, 2, 3, 4);
Assert.AreEqual(1, v3.x);
Assert.AreEqual(2, v3.y);
Assert.AreEqual(3, v3.z);
Assert.AreEqual(4, v3.w);
// Mixed constructors
var v4 = new int4(new int2(1, 2), 3, 4);
Assert.AreEqual(1, v4.x);
Assert.AreEqual(2, v4.y);
Assert.AreEqual(3, v4.z);
Assert.AreEqual(4, v4.w);
var v5 = new int4(new int3(1, 2, 3), 4);
Assert.AreEqual(1, v5.x);
Assert.AreEqual(2, v5.y);
Assert.AreEqual(3, v5.z);
Assert.AreEqual(4, v5.w);
var v6 = new int4(new int2(1, 2), new int2(3, 4));
Assert.AreEqual(1, v6.x);
Assert.AreEqual(2, v6.y);
Assert.AreEqual(3, v6.z);
Assert.AreEqual(4, v6.w);
}
[TestMethod]
public void TestArithmeticOperators()
{
var a = new int4(10, 20, 30, 40);
var b = new int4(5, 4, 6, 8);
// Addition
var add = a + b;
Assert.AreEqual(15, add.x);
Assert.AreEqual(24, add.y);
Assert.AreEqual(36, add.z);
Assert.AreEqual(48, add.w);
// Subtraction
var sub = a - b;
Assert.AreEqual(5, sub.x);
Assert.AreEqual(16, sub.y);
Assert.AreEqual(24, sub.z);
Assert.AreEqual(32, sub.w);
// Multiplication
var mul = a * b;
Assert.AreEqual(50, mul.x);
Assert.AreEqual(80, mul.y);
Assert.AreEqual(180, mul.z);
Assert.AreEqual(320, mul.w);
// Division
var div = a / b;
Assert.AreEqual(2, div.x);
Assert.AreEqual(5, div.y);
Assert.AreEqual(5, div.z);
Assert.AreEqual(5, div.w);
// Scalar operations
var scalarMul = a * 2;
Assert.AreEqual(20, scalarMul.x);
Assert.AreEqual(40, scalarMul.y);
Assert.AreEqual(60, scalarMul.z);
Assert.AreEqual(80, scalarMul.w);
}
[TestMethod]
public void TestBitwiseOperators()
{
var a = new int4(0b1010, 0b1100, 0b1001, 0b0110);
var b = new int4(0b1100, 0b1010, 0b1011, 0b1001);
// Bitwise AND
var and = a & b;
Assert.AreEqual(0b1000, and.x);
Assert.AreEqual(0b1000, and.y);
Assert.AreEqual(0b1001, and.z);
Assert.AreEqual(0b0000, and.w);
// Bitwise OR
var or = a | b;
Assert.AreEqual(0b1110, or.x);
Assert.AreEqual(0b1110, or.y);
Assert.AreEqual(0b1011, or.z);
Assert.AreEqual(0b1111, or.w);
}
[TestMethod]
public void TestComparisonOperators()
{
var a = new int4(10, 20, 30, 40);
var b = new int4(10, 20, 30, 40);
var c = new int4(5, 30, 25, 45);
// Equality
Assert.IsTrue(math.all(a == b));
Assert.IsFalse(math.all(a == c));
// Inequality
Assert.IsFalse(math.all(a != b));
Assert.IsTrue(math.all(a != c));
}
[TestMethod]
public void TestSwizzleProperties()
{
var v = new int4(1, 2, 3, 4);
Assert.AreEqual(1, v.x);
Assert.AreEqual(2, v.y);
Assert.AreEqual(3, v.z);
Assert.AreEqual(4, v.w);
var xy = v.xy;
Assert.AreEqual(1, xy.x);
Assert.AreEqual(2, xy.y);
var xyz = v.xyz;
Assert.AreEqual(1, xyz.x);
Assert.AreEqual(2, xyz.y);
Assert.AreEqual(3, xyz.z);
var xyzw = v.xyzw;
Assert.AreEqual(1, xyzw.x);
Assert.AreEqual(2, xyzw.y);
Assert.AreEqual(3, xyzw.z);
Assert.AreEqual(4, xyzw.w);
}
[TestMethod]
public void TestUnaryOperators()
{
var a = new int4(5, -3, 7, -9);
// Unary minus
var neg = -a;
Assert.AreEqual(-5, neg.x);
Assert.AreEqual(3, neg.y);
Assert.AreEqual(-7, neg.z);
Assert.AreEqual(9, neg.w);
// Unary plus
var pos = +a;
Assert.AreEqual(5, pos.x);
Assert.AreEqual(-3, pos.y);
Assert.AreEqual(7, pos.z);
Assert.AreEqual(-9, pos.w);
}
[TestMethod]
public void TestIndexer()
{
var v = new int4(10, 20, 30, 40);
Assert.AreEqual(10, v[0]);
Assert.AreEqual(20, v[1]);
Assert.AreEqual(30, v[2]);
Assert.AreEqual(40, v[3]);
}
}

View File

@@ -0,0 +1,292 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Misaki.HighPerformance.Mathematics;
namespace Misaki.HighPerformance.Test.UnitTest.Mathematics;
[TestClass]
public class TestMathFunctions
{
[TestMethod]
public void TestTrigonometricFunctions()
{
// Test sin, cos, tan
var angle = math.PI / 4f; // 45 degrees
var sinValue = math.sin(angle);
var cosValue = math.cos(angle);
var tanValue = math.tan(angle);
Assert.AreEqual(math.SQRT2 / 2f, sinValue, 1e-6f);
Assert.AreEqual(math.SQRT2 / 2f, cosValue, 1e-6f);
Assert.AreEqual(1f, tanValue, 1e-6f);
// Test vector versions
var angles = new float2(0f, math.PI / 2f);
var sinValues = math.sin(angles);
var cosValues = math.cos(angles);
Assert.AreEqual(0f, sinValues.x, 1e-6f);
Assert.AreEqual(1f, sinValues.y, 1e-6f);
Assert.AreEqual(1f, cosValues.x, 1e-6f);
Assert.AreEqual(0f, cosValues.y, 1e-6f);
}
[TestMethod]
public void TestHyperbolicFunctions()
{
var value = 1f;
var sinhValue = math.sinh(value);
var coshValue = math.cosh(value);
var tanhValue = math.tanh(value);
// sinh(1) ≈ 1.175, cosh(1) ≈ 1.543, tanh(1) ≈ 0.762
Assert.AreEqual(1.175201f, sinhValue, 1e-3f);
Assert.AreEqual(1.543081f, coshValue, 1e-3f);
Assert.AreEqual(0.761594f, tanhValue, 1e-3f);
}
[TestMethod]
public void TestExponentialAndLogarithmic()
{
// Test exp, log
var value = 2f;
var expValue = math.exp(value);
var logValue = math.log(expValue);
Assert.AreEqual(value, logValue, 1e-6f);
// Test exp2, log2
var exp2Value = math.exp2(value);
var log2Value = math.log2(exp2Value);
Assert.AreEqual(value, log2Value, 1e-6f);
// Test exp10, log10
var exp10Value = math.exp10(value);
var log10Value = math.log10(exp10Value);
Assert.AreEqual(value, log10Value, 1e-6f);
}
[TestMethod]
public void TestPowerFunctions()
{
// Test pow
var baseValue = 2f;
var exponent = 3f;
var powValue = math.pow(baseValue, exponent);
Assert.AreEqual(8f, powValue, 1e-6f);
// Test sqrt
var sqrtValue = math.sqrt(16f);
Assert.AreEqual(4f, sqrtValue, 1e-6f);
// Test rsqrt (reciprocal square root)
var rsqrtValue = math.rsqrt(16f);
Assert.AreEqual(0.25f, rsqrtValue, 1e-6f);
}
[TestMethod]
public void TestMinMaxClamp()
{
// Test min, max
var a = 3f;
var b = 7f;
Assert.AreEqual(3f, math.min(a, b));
Assert.AreEqual(7f, math.max(a, b));
// Test clamp
var value = 5f;
var clamped = math.clamp(value, 2f, 4f);
Assert.AreEqual(4f, clamped, 1e-6f);
var clampedLow = math.clamp(1f, 2f, 4f);
Assert.AreEqual(2f, clampedLow, 1e-6f);
var clampedNormal = math.clamp(3f, 2f, 4f);
Assert.AreEqual(3f, clampedNormal, 1e-6f);
// Test vector versions
var va = new float3(1f, 5f, 9f);
var vb = new float3(3f, 3f, 3f);
var minResult = math.min(va, vb);
var maxResult = math.max(va, vb);
Assert.AreEqual(1f, minResult.x, 1e-6f);
Assert.AreEqual(3f, minResult.y, 1e-6f);
Assert.AreEqual(3f, minResult.z, 1e-6f);
Assert.AreEqual(3f, maxResult.x, 1e-6f);
Assert.AreEqual(5f, maxResult.y, 1e-6f);
Assert.AreEqual(9f, maxResult.z, 1e-6f);
}
[TestMethod]
public void TestRoundingFunctions()
{
var value = 3.7f;
// Test floor, ceil, round, trunc
Assert.AreEqual(3f, math.floor(value), 1e-6f);
Assert.AreEqual(4f, math.ceil(value), 1e-6f);
Assert.AreEqual(4f, math.round(value), 1e-6f);
Assert.AreEqual(3f, math.trunc(value), 1e-6f);
var negativeValue = -3.7f;
Assert.AreEqual(-4f, math.floor(negativeValue), 1e-6f);
Assert.AreEqual(-3f, math.ceil(negativeValue), 1e-6f);
Assert.AreEqual(-4f, math.round(negativeValue), 1e-6f);
Assert.AreEqual(-3f, math.trunc(negativeValue), 1e-6f);
}
[TestMethod]
public void TestAbsAndSign()
{
// Test abs
Assert.AreEqual(5f, math.abs(-5f), 1e-6f);
Assert.AreEqual(5f, math.abs(5f), 1e-6f);
Assert.AreEqual(0f, math.abs(0f), 1e-6f);
// Test sign
Assert.AreEqual(-1f, math.sign(-5f), 1e-6f);
Assert.AreEqual(1f, math.sign(5f), 1e-6f);
Assert.AreEqual(0f, math.sign(0f), 1e-6f);
// Test vector versions
var v = new float3(-2f, 0f, 3f);
var absResult = math.abs(v);
var signResult = math.sign(v);
Assert.AreEqual(2f, absResult.x, 1e-6f);
Assert.AreEqual(0f, absResult.y, 1e-6f);
Assert.AreEqual(3f, absResult.z, 1e-6f);
Assert.AreEqual(-1f, signResult.x, 1e-6f);
Assert.AreEqual(0f, signResult.y, 1e-6f);
Assert.AreEqual(1f, signResult.z, 1e-6f);
}
[TestMethod]
public void TestInterpolation()
{
// Test lerp (linear interpolation)
var a = 0f;
var b = 10f;
var t = 0.3f;
var lerped = math.lerp(a, b, t);
Assert.AreEqual(3f, lerped, 1e-6f);
// Test vector lerp
var va = new float3(0f, 0f, 0f);
var vb = new float3(10f, 20f, 30f);
var vLerped = math.lerp(va, vb, t);
Assert.AreEqual(3f, vLerped.x, 1e-6f);
Assert.AreEqual(6f, vLerped.y, 1e-6f);
Assert.AreEqual(9f, vLerped.z, 1e-6f);
// Test unlerp (inverse lerp)
var unlerpResult = math.unlerp(a, b, 3f);
Assert.AreEqual(0.3f, unlerpResult, 1e-6f);
}
[TestMethod]
public void TestStep()
{
// Test step function
var edge = 5f;
Assert.AreEqual(0f, math.step(edge, 3f), 1e-6f);
Assert.AreEqual(1f, math.step(edge, 5f), 1e-6f);
Assert.AreEqual(1f, math.step(edge, 7f), 1e-6f);
// Test smoothstep
var smoothResult1 = math.smoothstep(0f, 10f, 5f);
Assert.AreEqual(0.5f, smoothResult1, 1e-6f);
var smoothResult2 = math.smoothstep(0f, 10f, 0f);
Assert.AreEqual(0f, smoothResult2, 1e-6f);
var smoothResult3 = math.smoothstep(0f, 10f, 10f);
Assert.AreEqual(1f, smoothResult3, 1e-6f);
}
[TestMethod]
public void TestModAndRemainder()
{
// Test fmod
var fmodResult = math.fmod(7.5f, 3f);
Assert.AreEqual(1.5f, fmodResult, 1e-6f);
// Test remainder functions if available
var a = 7f;
var b = 3f;
var remainder = a % b;
Assert.AreEqual(1f, remainder, 1e-6f);
}
[TestMethod]
public void TestAngleConversions()
{
var degrees = 180f;
var radians = math.radians(degrees);
Assert.AreEqual(math.PI, radians, 1e-6f);
var backToDegrees = math.degrees(radians);
Assert.AreEqual(degrees, backToDegrees, 1e-6f);
}
[TestMethod]
public void TestFloatingPointChecks()
{
// Test isnan
Assert.IsTrue(math.isnan(float.NaN));
Assert.IsFalse(math.isnan(1f));
// Test isinf
Assert.IsTrue(math.isinf(float.PositiveInfinity));
Assert.IsTrue(math.isinf(float.NegativeInfinity));
Assert.IsFalse(math.isinf(1f));
// Test isfinite
Assert.IsFalse(math.isfinite(float.PositiveInfinity));
Assert.IsFalse(math.isfinite(float.NaN));
Assert.IsTrue(math.isfinite(1f));
}
[TestMethod]
public void TestBitOperations()
{
// Test asfloat, asint, asuint
var floatValue = 1.5f;
var intBits = math.asint(floatValue);
var floatBack = math.asfloat(intBits);
Assert.AreEqual(floatValue, floatBack, 1e-6f);
var uintBits = math.asuint(floatValue);
var floatFromUint = math.asfloat(uintBits);
Assert.AreEqual(floatValue, floatFromUint, 1e-6f);
}
[TestMethod]
public void TestSelectFunction()
{
// Test select function
var condition = new bool3(true, false, true);
var a = new float3(1f, 2f, 3f);
var b = new float3(4f, 5f, 6f);
var result = math.select(b, a, condition);
Assert.AreEqual(1f, result.x, 1e-6f); // condition is true, so select a.x
Assert.AreEqual(5f, result.y, 1e-6f); // condition is false, so select b.y
Assert.AreEqual(3f, result.z, 1e-6f); // condition is true, so select a.z
}
}

View File

@@ -0,0 +1,220 @@
using Misaki.HighPerformance.Mathematics;
namespace Misaki.HighPerformance.Test.UnitTest.Mathematics;
[TestClass]
public class TestQuaternion
{
[TestMethod]
public void TestConstructors()
{
// Default constructor (should be identity)
var q1 = new quaternion();
// Component constructor
var q2 = new quaternion(0.5f, 0.5f, 0.5f, 0.5f);
Assert.AreEqual(0.5f, q2.value.x, 1e-6f);
Assert.AreEqual(0.5f, q2.value.y, 1e-6f);
Assert.AreEqual(0.5f, q2.value.z, 1e-6f);
Assert.AreEqual(0.5f, q2.value.w, 1e-6f);
// float4 constructor
var q3 = new quaternion(new float4(0.1f, 0.2f, 0.3f, 0.4f));
Assert.AreEqual(0.1f, q3.value.x, 1e-6f);
Assert.AreEqual(0.2f, q3.value.y, 1e-6f);
Assert.AreEqual(0.3f, q3.value.z, 1e-6f);
Assert.AreEqual(0.4f, q3.value.w, 1e-6f);
// Identity quaternion
var identity = quaternion.identity;
Assert.AreEqual(0f, identity.value.x, 1e-6f);
Assert.AreEqual(0f, identity.value.y, 1e-6f);
Assert.AreEqual(0f, identity.value.z, 1e-6f);
Assert.AreEqual(1f, identity.value.w, 1e-6f);
}
[TestMethod]
public void TestEulerRotations()
{
// Test Euler angle constructors
var euler = new float3(math.PI / 4f, math.PI / 3f, math.PI / 6f);
// Test different rotation orders
var qXYZ = quaternion.EulerXYZ(euler);
var qXZY = quaternion.EulerXZY(euler);
var qYXZ = quaternion.EulerYXZ(euler);
var qYZX = quaternion.EulerYZX(euler);
var qZXY = quaternion.EulerZXY(euler);
var qZYX = quaternion.EulerZYX(euler);
// All should be unit quaternions
Assert.AreEqual(1f, math.length(qXYZ.value), 1e-6f);
Assert.AreEqual(1f, math.length(qXZY.value), 1e-6f);
Assert.AreEqual(1f, math.length(qYXZ.value), 1e-6f);
Assert.AreEqual(1f, math.length(qYZX.value), 1e-6f);
Assert.AreEqual(1f, math.length(qZXY.value), 1e-6f);
Assert.AreEqual(1f, math.length(qZYX.value), 1e-6f);
// Test generic Euler function with default order (ZXY)
var qDefault = quaternion.Euler(euler);
var qDefaultExplicit = quaternion.Euler(euler, math.RotationOrder.ZXY);
// Should be equal
Assert.AreEqual(qZXY.value.x, qDefault.value.x, 1e-6f);
Assert.AreEqual(qZXY.value.y, qDefault.value.y, 1e-6f);
Assert.AreEqual(qZXY.value.z, qDefault.value.z, 1e-6f);
Assert.AreEqual(qZXY.value.w, qDefault.value.w, 1e-6f);
}
[TestMethod]
public void TestAxisAngleRotation()
{
// Test rotation around Y-axis by 90 degrees
var axis = new float3(0f, 1f, 0f);
var angle = math.PI / 2f; // 90 degrees
var q = quaternion.AxisAngle(axis, angle);
// Should be unit quaternion
Assert.AreEqual(1f, math.length(q.value), 1e-6f);
// For 90-degree rotation around Y-axis, should be (0, sin(45°), 0, cos(45°))
var expectedSin = math.sin(angle / 2f);
var expectedCos = math.cos(angle / 2f);
Assert.AreEqual(0f, q.value.x, 1e-6f);
Assert.AreEqual(expectedSin, q.value.y, 1e-6f);
Assert.AreEqual(0f, q.value.z, 1e-6f);
Assert.AreEqual(expectedCos, q.value.w, 1e-6f);
}
[TestMethod]
public void TestQuaternionMultiplication()
{
var q1 = quaternion.identity;
var q2 = quaternion.AxisAngle(new float3(0f, 1f, 0f), math.PI / 4f);
// Identity * quaternion = quaternion
var result1 = math.mul(q1, q2);
Assert.AreEqual(q2.value.x, result1.value.x, 1e-6f);
Assert.AreEqual(q2.value.y, result1.value.y, 1e-6f);
Assert.AreEqual(q2.value.z, result1.value.z, 1e-6f);
Assert.AreEqual(q2.value.w, result1.value.w, 1e-6f);
// Quaternion * identity = quaternion
var result2 = math.mul(q2, q1);
Assert.AreEqual(q2.value.x, result2.value.x, 1e-6f);
Assert.AreEqual(q2.value.y, result2.value.y, 1e-6f);
Assert.AreEqual(q2.value.z, result2.value.z, 1e-6f);
Assert.AreEqual(q2.value.w, result2.value.w, 1e-6f);
}
[TestMethod]
public void TestQuaternionVectorRotation()
{
// Test rotating a vector with quaternion
var vector = new float3(1f, 0f, 0f);
var q = quaternion.AxisAngle(new float3(0f, 0f, 1f), math.PI / 2f); // 90° around Z-axis
var rotated = math.mul(q, vector);
// Should rotate (1,0,0) to approximately (0,1,0)
Assert.AreEqual(0f, rotated.x, 1e-6f);
Assert.AreEqual(1f, rotated.y, 1e-6f);
Assert.AreEqual(0f, rotated.z, 1e-6f);
}
[TestMethod]
public void TestQuaternionInverse()
{
var q = quaternion.AxisAngle(new float3(0f, 1f, 0f), math.PI / 3f);
var qInverse = math.inverse(q);
// q * inverse(q) should equal identity
var result = math.mul(q, qInverse);
Assert.AreEqual(quaternion.identity.value.x, result.value.x, 1e-6f);
Assert.AreEqual(quaternion.identity.value.y, result.value.y, 1e-6f);
Assert.AreEqual(quaternion.identity.value.z, result.value.z, 1e-6f);
Assert.AreEqual(quaternion.identity.value.w, result.value.w, 1e-6f);
}
[TestMethod]
public void TestQuaternionNormalize()
{
// Create non-unit quaternion
var q = new quaternion(1f, 2f, 3f, 4f);
var normalized = math.normalize(q);
// Should have length 1
Assert.AreEqual(1f, math.length(normalized.value), 1e-6f);
}
[TestMethod]
public void TestMatrixFromQuaternion()
{
// Test conversion from quaternion to rotation matrix
var q = quaternion.identity;
var matrix = new float3x3(q);
// Identity quaternion should produce identity matrix
Assert.AreEqual(1f, matrix.c0.x, 1e-6f);
Assert.AreEqual(0f, matrix.c0.y, 1e-6f);
Assert.AreEqual(0f, matrix.c0.z, 1e-6f);
Assert.AreEqual(0f, matrix.c1.x, 1e-6f);
Assert.AreEqual(1f, matrix.c1.y, 1e-6f);
Assert.AreEqual(0f, matrix.c1.z, 1e-6f);
Assert.AreEqual(0f, matrix.c2.x, 1e-6f);
Assert.AreEqual(0f, matrix.c2.y, 1e-6f);
Assert.AreEqual(1f, matrix.c2.z, 1e-6f);
}
[TestMethod]
public void TestQuaternionFromMatrix()
{
// Test conversion from matrix to quaternion
var identity3x3 = new float3x3(
new float3(1f, 0f, 0f),
new float3(0f, 1f, 0f),
new float3(0f, 0f, 1f)
);
var q = new quaternion(identity3x3);
// Should produce identity quaternion
Assert.AreEqual(quaternion.identity.value.x, q.value.x, 1e-6f);
Assert.AreEqual(quaternion.identity.value.y, q.value.y, 1e-6f);
Assert.AreEqual(quaternion.identity.value.z, q.value.z, 1e-6f);
Assert.AreEqual(quaternion.identity.value.w, q.value.w, 1e-6f);
}
[TestMethod]
public void TestSlerp()
{
var q1 = quaternion.identity;
var q2 = quaternion.AxisAngle(new float3(0f, 1f, 0f), math.PI / 2f);
// Test interpolation
var halfway = math.slerp(q1, q2, 0.5f);
// Should be unit quaternion
Assert.AreEqual(1f, math.length(halfway.value), 1e-6f);
// At t=0, should equal q1
var start = math.slerp(q1, q2, 0f);
Assert.AreEqual(q1.value.x, start.value.x, 1e-6f);
Assert.AreEqual(q1.value.y, start.value.y, 1e-6f);
Assert.AreEqual(q1.value.z, start.value.z, 1e-6f);
Assert.AreEqual(q1.value.w, start.value.w, 1e-6f);
// At t=1, should equal q2
var end = math.slerp(q1, q2, 1f);
Assert.AreEqual(q2.value.x, end.value.x, 1e-6f);
Assert.AreEqual(q2.value.y, end.value.y, 1e-6f);
Assert.AreEqual(q2.value.z, end.value.z, 1e-6f);
Assert.AreEqual(q2.value.w, end.value.w, 1e-6f);
}
}

View File

@@ -0,0 +1,147 @@
using Misaki.HighPerformance.Mathematics;
namespace Misaki.HighPerformance.Test.UnitTest.Mathematics;
[TestClass]
public class TestUint2
{
[TestMethod]
public void TestConstructors()
{
// Default constructor
var v1 = new uint2();
Assert.AreEqual(0u, v1.x);
Assert.AreEqual(0u, v1.y);
// Single value constructor
var v2 = new uint2(5u);
Assert.AreEqual(5u, v2.x);
Assert.AreEqual(5u, v2.y);
// Component constructor
var v3 = new uint2(1u, 2u);
Assert.AreEqual(1u, v3.x);
Assert.AreEqual(2u, v3.y);
}
[TestMethod]
public void TestArithmeticOperators()
{
var a = new uint2(10u, 20u);
var b = new uint2(5u, 4u);
// Addition
var add = a + b;
Assert.AreEqual(15u, add.x);
Assert.AreEqual(24u, add.y);
// Subtraction
var sub = a - b;
Assert.AreEqual(5u, sub.x);
Assert.AreEqual(16u, sub.y);
// Multiplication
var mul = a * b;
Assert.AreEqual(50u, mul.x);
Assert.AreEqual(80u, mul.y);
// Division
var div = a / b;
Assert.AreEqual(2u, div.x);
Assert.AreEqual(5u, div.y);
// Modulus
var mod = a % b;
Assert.AreEqual(0u, mod.x);
Assert.AreEqual(0u, mod.y);
// Scalar operations
var scalarMul = a * 2u;
Assert.AreEqual(20u, scalarMul.x);
Assert.AreEqual(40u, scalarMul.y);
}
[TestMethod]
public void TestBitwiseOperators()
{
var a = new uint2(0b1010u, 0b1100u);
var b = new uint2(0b1100u, 0b1010u);
// Bitwise AND
var and = a & b;
Assert.AreEqual(0b1000u, and.x);
Assert.AreEqual(0b1000u, and.y);
// Bitwise OR
var or = a | b;
Assert.AreEqual(0b1110u, or.x);
Assert.AreEqual(0b1110u, or.y);
// Bitwise XOR
var xor = a ^ b;
Assert.AreEqual(0b0110u, xor.x);
Assert.AreEqual(0b0110u, xor.y);
// Bitwise NOT
var not = ~a;
Assert.AreEqual(~0b1010u, not.x);
Assert.AreEqual(~0b1100u, not.y);
}
[TestMethod]
public void TestShiftOperators()
{
var a = new uint2(8u, 16u);
// Left shift
var leftShift = a << 1;
Assert.AreEqual(16u, leftShift.x);
Assert.AreEqual(32u, leftShift.y);
// Right shift
var rightShift = a >> 1;
Assert.AreEqual(4u, rightShift.x);
Assert.AreEqual(8u, rightShift.y);
}
[TestMethod]
public void TestComparisonOperators()
{
var a = new uint2(10u, 20u);
var b = new uint2(10u, 20u);
var c = new uint2(5u, 30u);
// Equality
var isEqual = math.all(a == b);
Assert.IsTrue(isEqual);
var isNotEqual = math.any(a != c);
Assert.IsTrue(isNotEqual);
}
[TestMethod]
public void TestUnaryOperators()
{
var a = new uint2(5u, 3u);
// Unary plus
var pos = +a;
Assert.AreEqual(5u, pos.x);
Assert.AreEqual(3u, pos.y);
// Note: unary minus doesn't make sense for unsigned types
}
[TestMethod]
public void TestSwizzleProperties()
{
var v = new uint2(1u, 2u);
Assert.AreEqual(1u, v.x);
Assert.AreEqual(2u, v.y);
var xy = v.xy;
Assert.AreEqual(1u, xy.x);
Assert.AreEqual(2u, xy.y);
}
}