Refactor core APIs, fix bugs, and improve safety

- Make image result/info structs readonly; improve error handling and memory safety in image library
- Introduce IJobScheduler interface; move job scheduling docs to interface
- Remove "index 0 invalid" convention from slot/sparse maps; fix Count logic
- Add Owner<T> for disposable value types in low-level utilities
- Improve ObjectPool<T> thread safety and logic
- Change List<T>.RemoveAndSwapBack to return bool
- Remove unsafe methods from generated math types; add debug range checks
- Update benchmarks and enable collection checks in tests
- Improve documentation, comments, and error messages
- Bump assembly versions across all projects
This commit is contained in:
2025-12-21 16:08:10 +09:00
parent a1ad0bd2da
commit 1fee890329
38 changed files with 1967 additions and 350 deletions

View File

@@ -6,7 +6,7 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
{
internal abstract class GeneratorBase
{
protected const string INLINE_METHOD_ATTRIBUTE = "[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining | global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveOptimization)]";
protected const string INLINE_METHOD_ATTRIBUTE = "[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]";
protected static readonly string[] s_matrixComponents = new[] { "c0", "c1", "c2", "c3" };
protected static readonly string[] s_vectorComponents = new[] { "x", "y", "z", "w" };
@@ -19,10 +19,9 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
this.typeInfo = typeInfo;
sourceBuilder.Clear();
var message = Validation();
if (message != null)
if (!Validation(out var message))
{
return message;
return message ?? string.Empty;
}
Initialize();
@@ -51,9 +50,10 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
#endregion");
}
protected virtual string? Validation()
protected virtual bool Validation(out string? message)
{
return null;
message = null;
return true;
}
protected virtual void Initialize()

View File

@@ -1,7 +1,6 @@
using Microsoft.CodeAnalysis;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
using System.Text;
namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
@@ -16,14 +15,16 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
.Replace("{c}", s_matrixComponents[componentIndex]);
}
protected override string? Validation()
protected override bool Validation(out string? message)
{
if (typeInfo.ElementTypeSymbol == null)
{
return "You must specify 'elementType' in NumericTypeAttribute for matrix types.";
message = "You must specify 'elementType' in NumericTypeAttribute for matrix types.";
return false;
}
return null;
message = null;
return true;
}
protected override void GenerateBody()
@@ -36,7 +37,6 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
}
GenerateConstructors();
GenerateUnsafeMethod();
GenerateOverrideMethod();
if (typeInfo.Arithmetic)
@@ -67,15 +67,20 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
{INLINE_METHOD_ATTRIBUTE}
get
{{
#if ENABLE_COLLECTION_CHECKS
if (index < 0 || index >= {typeInfo.Column})
{{
throw new global::System.ArgumentOutOfRangeException(nameof(index), $""Index {{index}} is out of range of '{typeInfo.TypeName}'"");
}}
#endif
RangeCheck(index);
return ref (({typeInfo.ComponentTypeFullName}*)global::System.Runtime.CompilerServices.Unsafe.AsPointer(ref this))[index];
}}
}}");
sourceBuilder.AppendLine($@"
[global::System.Diagnostics.Conditional(""ENABLE_COLLECTION_CHECKS"")]
private void RangeCheck(int index)
{{
if (index < 0 || index >= {typeInfo.Column})
{{
throw new global::System.ArgumentOutOfRangeException(nameof(index), $""Index {{index}} is out of range of '{typeInfo.TypeName}'"");
}}
}}");
}
private void GenerateUnitMatrix()
@@ -213,27 +218,11 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
sourceBuilder.Append($@"
this.{s_matrixComponents[i]} = {assignment[i]};");
}
sourceBuilder.AppendLine($@"
sourceBuilder.AppendLine($@"
}}");
}
}
private void GenerateUnsafeMethod()
{
sourceBuilder.AppendLine($@"
{INLINE_METHOD_ATTRIBUTE}
public unsafe {typeInfo.ComponentTypeFullName}* AsPointer()
{{
return ({typeInfo.ComponentTypeFullName}*)global::System.Runtime.CompilerServices.Unsafe.AsPointer(ref this);
}}
{INLINE_METHOD_ATTRIBUTE}
public unsafe global::System.Span<{typeInfo.ComponentTypeFullName}> AsSpan()
{{
return new global::System.Span<{typeInfo.ComponentTypeFullName}>(AsPointer(), {typeInfo.Column});
}}");
}
private void GenerateOverrideMethod()
{
var components = s_matrixComponents.Take(typeInfo.Column).ToArray();
@@ -760,7 +749,7 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
var columnSizeBytes = lhsRows * typeInfo.ComponentSize;
var vectorBits = columnSizeBytes > 16 ? 256 : 128;
bool isFloatingPoint = typeInfo.ElementTypeSymbol!.SpecialType == SpecialType.System_Single||
var isFloatingPoint = typeInfo.ElementTypeSymbol!.SpecialType == SpecialType.System_Single ||
typeInfo.ElementTypeSymbol!.SpecialType == SpecialType.System_Double;
sourceBuilder.Append($@"
@@ -768,7 +757,7 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
public static {resultVectorType} mul({lhsType} m, {rhsVectorType} v)
{{");
for (int i = 0; i < lhsCols; i++)
for (var i = 0; i < lhsCols; i++)
{
var component = s_vectorComponents[i];
sourceBuilder.Append($@"
@@ -779,7 +768,7 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
var sum = global::System.Runtime.Intrinsics.Vector{vectorBits}.Multiply(m.c0.AsVector{vectorBits}(), vx);");
for (int i = 1; i < lhsCols; i++)
for (var i = 1; i < lhsCols; i++)
{
var component = s_vectorComponents[i];
var col = s_matrixComponents[i];

View File

@@ -52,7 +52,6 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
}
GenerateConstructors();
GenerateUnsafeMethod();
GenerateOverrideMethod();
GenerateConvertionMethod();
@@ -95,15 +94,20 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
{INLINE_METHOD_ATTRIBUTE}
get
{{
#if ENABLE_COLLECTION_CHECKS
if (index < 0 || index >= {typeInfo.Row})
{{
throw new global::System.ArgumentOutOfRangeException(nameof(index), $""Index {{index}} is out of range of '{typeInfo.TypeName}'"");
}}
#endif
RangeCheck(index);
return ref (({typeInfo.ComponentTypeFullName}*)global::System.Runtime.CompilerServices.Unsafe.AsPointer(ref this))[index];
}}
}}");
sourceBuilder.AppendLine($@"
[global::System.Diagnostics.Conditional(""ENABLE_COLLECTION_CHECKS"")]
private void RangeCheck(int index)
{{
if (index < 0 || index >= {typeInfo.Row})
{{
throw new global::System.ArgumentOutOfRangeException(nameof(index), $""Index {{index}} is out of range of '{typeInfo.TypeName}'"");
}}
}}");
}
private static List<List<int>> GetPartitions(int target)
@@ -295,28 +299,10 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
EndRegion();
}
private void GenerateUnsafeMethod()
{
var componentType = typeInfo.ComponentTypeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
StartRegion("Unsafe Methods");
sourceBuilder.AppendLine($@"
{INLINE_METHOD_ATTRIBUTE}
public unsafe {componentType}* AsPointer()
{{
return ({componentType}*)global::System.Runtime.CompilerServices.Unsafe.AsPointer(ref this);
}}
{INLINE_METHOD_ATTRIBUTE}
public unsafe global::System.Span<{componentType}> AsSpan()
{{
return new global::System.Span<{componentType}>(AsPointer(), {typeInfo.Row});
}}");
}
private void GenerateOverrideMethod()
{
StartRegion("Override Methods");
var typeName = typeInfo.TypeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
var componentType = typeInfo.ComponentTypeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
var components = s_vectorComponents.Take(typeInfo.Row).ToArray();
@@ -715,6 +701,7 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
var modifier = canSet ? "public" : "public readonly";
sourceBuilder.Append($@"
[global::System.Text.Json.Serialization.JsonIgnore]
{modifier} {targetStruct} {property}
{{
{INLINE_METHOD_ATTRIBUTE}