Refactor and enhance math and utility libraries
Some checks failed
Publish NuGet Packages / publish (push) Failing after 3m12s
Some checks failed
Publish NuGet Packages / publish (push) Failing after 3m12s
Refactored `sincos` usage across `quaternion` and `random` to use `out` parameters for improved performance. Enhanced `random` struct with updated random direction generation methods. Added new benchmarks in `MathematicsBenchmark` for vector operations, including SIMD-based `f4` struct. Downgraded target framework to `net9.0` for compatibility. Introduced `ReadOnlyUnsafeCollection` for low-level memory management. Added utility methods in `CollectionUtility` for span creation and optimized list operations. Renamed `MemoryUtilities` to `MemoryUtility` and updated all references. Enhanced `ObjectPool` with `Rent` and `TryRent` methods. Enabled `AllowUnsafeBlocks` and AOT compatibility in project configuration. Performed general code cleanup, including removal of unused methods, improved formatting, and alignment with modern coding practices.
This commit is contained in:
@@ -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)]";
|
||||
protected const string INLINE_METHOD_ATTRIBUTE = "[global::System.Runtime.CompilerServices.MethodImpl(global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining | global::System.Runtime.CompilerServices.MethodImplOptions.AggressiveOptimization)]";
|
||||
|
||||
protected static readonly string[] s_matrixComponents = new[] { "c0", "c1", "c2", "c3" };
|
||||
protected static readonly string[] s_vectorComponents = new[] { "x", "y", "z", "w" };
|
||||
@@ -70,7 +70,7 @@ namespace {typeInfo.TypeSymbol.ContainingNamespace.ToDisplayString()}
|
||||
protected virtual void GenerateTypeStart()
|
||||
{
|
||||
sourceBuilder.Append($@"
|
||||
[global::System.Runtime.CompilerServices.SkipLocalsInit]
|
||||
//[global::System.Runtime.CompilerServices.SkipLocalsInit]
|
||||
public partial struct {typeInfo.TypeSymbol.Name} : global::System.IEquatable<{typeInfo.TypeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}>
|
||||
{{");
|
||||
}
|
||||
|
||||
@@ -515,13 +515,6 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
|
||||
}
|
||||
|
||||
GenerateMulMethod();
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeInfo.TypeFullName} abs({typeInfo.TypeFullName} value)
|
||||
{{
|
||||
return new({string.Join(", ", s_matrixComponents.Take(typeInfo.Column).Select(c => $"abs(value.{c})"))});
|
||||
}}");
|
||||
}
|
||||
|
||||
sourceBuilder.Append($@"
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
|
||||
private int _missingComponents;
|
||||
private string _componentTypePrefix = null!;
|
||||
|
||||
private readonly List<(string signature, string assignment)> _constructorSignatures = new();
|
||||
private readonly List<(string signature, List<string> assignment)> _constructorSignatures = new();
|
||||
|
||||
private string GetConversionFromTemplate(string template, int componentIndex)
|
||||
{
|
||||
@@ -209,7 +209,7 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
|
||||
|
||||
_constructorSignatures.Add((
|
||||
signature: $"{componentType} value",
|
||||
assignment: string.Join(", ", Enumerable.Range(0, typeInfo.Row).Select(_ => "value"))));
|
||||
assignment: Enumerable.Range(0, typeInfo.Row).Select(_ => "value").ToList()));
|
||||
|
||||
if (string.IsNullOrEmpty(typeInfo.TypePrefix))
|
||||
{
|
||||
@@ -253,8 +253,7 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
|
||||
continue;
|
||||
}
|
||||
|
||||
var assignment = string.Join(", ", assignments);
|
||||
_constructorSignatures.Add((signature, assignment));
|
||||
_constructorSignatures.Add((signature, assignments));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,58 +264,34 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
|
||||
var targetTemplate = kv.Key;
|
||||
var targetTypes = kv.Value;
|
||||
|
||||
var tempSB = new StringBuilder();
|
||||
foreach (var type in targetTypes)
|
||||
{
|
||||
var assignments = new List<string>();
|
||||
for (var i = 0; i < typeInfo.Row; i++)
|
||||
{
|
||||
tempSB.Append(GetConversionFromTemplate(targetTemplate, i));
|
||||
if (i < typeInfo.Row - 1)
|
||||
{
|
||||
tempSB.Append(", ");
|
||||
}
|
||||
assignments.Add(GetConversionFromTemplate(targetTemplate, i));
|
||||
}
|
||||
|
||||
_constructorSignatures.Add((
|
||||
signature: $"{type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)} v",
|
||||
assignment: tempSB.ToString()));
|
||||
|
||||
tempSB.Clear();
|
||||
assignment: assignments));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var (signature, assignment) in _constructorSignatures)
|
||||
{
|
||||
sourceBuilder.AppendLine($@"
|
||||
sourceBuilder.Append($@"
|
||||
public {typeName}({signature})
|
||||
{{
|
||||
this = Create({assignment});
|
||||
}}");
|
||||
}
|
||||
|
||||
|
||||
sourceBuilder.Append($@"
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeName} Create({string.Join(", ", Enumerable.Range(0, typeInfo.Row).Select((_, i) => $"{typeInfo.ComponentTypeFullName} {s_vectorComponents[i]}"))})
|
||||
{{");
|
||||
|
||||
if (typeInfo.VectorType != null)
|
||||
{
|
||||
sourceBuilder.Append($@"
|
||||
global::System.Span<{typeInfo.ComponentTypeFullName}> span = [{string.Join(", ", Enumerable.Range(0, typeInfo.Row + _missingComponents).Select(i => i < typeInfo.Row ? $"{s_vectorComponents[i]}" : "default"))}];
|
||||
var vector = global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.Create(global::System.Runtime.CompilerServices.Unsafe.As<global::System.Span<{typeInfo.ComponentTypeFullName}>, global::System.ReadOnlySpan<{typeInfo.VectorTypeFullName}>>(ref span));");
|
||||
}
|
||||
else
|
||||
{
|
||||
sourceBuilder.Append($@"
|
||||
var vector = global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.Create({string.Join(", ", Enumerable.Range(0, typeInfo.Row + _missingComponents).Select(i => i < typeInfo.Row ? $"{s_vectorComponents[i]}" : "default"))});");
|
||||
}
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
ref var address = ref global::System.Runtime.CompilerServices.Unsafe.As<global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}<{typeInfo.VectorTypeFullName}>, byte>(ref vector);
|
||||
return global::System.Runtime.CompilerServices.Unsafe.ReadUnaligned<{typeInfo.TypeFullName}>(ref address);
|
||||
for (var i = 0; i < typeInfo.Row; i++)
|
||||
{
|
||||
sourceBuilder.Append($@"
|
||||
this.{s_vectorComponents[i]} = {assignment[i]};");
|
||||
}
|
||||
sourceBuilder.AppendLine($@"
|
||||
}}");
|
||||
}
|
||||
|
||||
EndRegion();
|
||||
}
|
||||
@@ -434,23 +409,22 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeName} operator +({typeName} lhs, {typeName} rhs)
|
||||
{{
|
||||
return (lhs.AsVector{_vectorBitsSize}() + rhs.AsVector{_vectorBitsSize}()).{asResult};
|
||||
return new {typeName}({string.Join(", ", s_vectorComponents.Take(typeInfo.Row).Select(c => $"lhs.{c} + rhs.{c}"))});
|
||||
}}
|
||||
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeName} operator +({typeName} lhs, {componentType} rhs)
|
||||
{{
|
||||
return lhs + new {typeName}(rhs);
|
||||
return new {typeName}({string.Join(", ", s_vectorComponents.Take(typeInfo.Row).Select(c => $"lhs.{c} + rhs"))});
|
||||
}}
|
||||
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeName} operator +({componentType} lhs, {typeName} rhs)
|
||||
{{
|
||||
return new {typeName}(lhs) + rhs;
|
||||
return new {typeName}({string.Join(", ", s_vectorComponents.Take(typeInfo.Row).Select(c => $"lhs + rhs.{c}"))});
|
||||
}}
|
||||
|
||||
#if NET10_0_OR_GREATER
|
||||
// Use scaler here to let JIT handle the simd optimization since we can not do a in-place vectorlization manually.
|
||||
#if false //NET10_0_OR_GREATER
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public void operator +=({typeName} other)
|
||||
{{");
|
||||
@@ -469,23 +443,22 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeName} operator -({typeName} lhs, {typeName} rhs)
|
||||
{{
|
||||
return (lhs.AsVector{_vectorBitsSize}() - rhs.AsVector{_vectorBitsSize}()).{asResult};
|
||||
return new {typeName}({string.Join(", ", s_vectorComponents.Take(typeInfo.Row).Select(c => $"lhs.{c} - rhs.{c}"))});
|
||||
}}
|
||||
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeName} operator -({typeName} lhs, {componentType} rhs)
|
||||
{{
|
||||
return lhs - new {typeName}(rhs);
|
||||
return new {typeName}({string.Join(", ", s_vectorComponents.Take(typeInfo.Row).Select(c => $"lhs.{c} - rhs"))});
|
||||
}}
|
||||
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeName} operator -({componentType} lhs, {typeName} rhs)
|
||||
{{
|
||||
return new {typeName}(lhs) - rhs;
|
||||
return new {typeName}({string.Join(", ", s_vectorComponents.Take(typeInfo.Row).Select(c => $"lhs - rhs.{c}"))});
|
||||
}}
|
||||
|
||||
#if NET10_0_OR_GREATER
|
||||
// Use scaler here to let JIT handle the simd optimization since we can not do a in-place vectorlization manually.
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public void operator -=({typeName} other)
|
||||
{{");
|
||||
@@ -504,19 +477,19 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeName} operator *({typeName} lhs, {typeName} rhs)
|
||||
{{
|
||||
return (lhs.AsVector{_vectorBitsSize}() * rhs.AsVector{_vectorBitsSize}()).{asResult};
|
||||
return new {typeName}({string.Join(", ", s_vectorComponents.Take(typeInfo.Row).Select(c => $"lhs.{c} * rhs.{c}"))});
|
||||
}}
|
||||
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeName} operator *({typeName} lhs, {componentType} rhs)
|
||||
{{
|
||||
return (lhs.AsVector{_vectorBitsSize}() * rhs).{asResult};
|
||||
return new {typeName}({string.Join(", ", s_vectorComponents.Take(typeInfo.Row).Select(c => $"lhs.{c} * rhs"))});
|
||||
}}
|
||||
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeName} operator *({componentType} lhs, {typeName} rhs)
|
||||
{{
|
||||
return new {typeName}(lhs) * rhs;
|
||||
return new {typeName}({string.Join(", ", s_vectorComponents.Take(typeInfo.Row).Select(c => $"lhs * rhs.{c}"))});
|
||||
}}
|
||||
|
||||
#if NET10_0_OR_GREATER
|
||||
@@ -539,19 +512,19 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeName} operator /({typeName} lhs, {typeName} rhs)
|
||||
{{
|
||||
return (lhs.AsVector{_vectorBitsSize}() / rhs.AsVector{_vectorBitsSize}()).{asResult};
|
||||
return new {typeName}({string.Join(", ", s_vectorComponents.Take(typeInfo.Row).Select(c => $"lhs.{c} / rhs.{c}"))});
|
||||
}}
|
||||
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeName} operator /({typeName} lhs, {componentType} rhs)
|
||||
{{
|
||||
return (lhs.AsVector{_vectorBitsSize}() / rhs).{asResult};
|
||||
return new {typeName}({string.Join(", ", s_vectorComponents.Take(typeInfo.Row).Select(c => $"lhs.{c} / rhs"))});
|
||||
}}
|
||||
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeName} operator /({componentType} lhs, {typeName} rhs)
|
||||
{{
|
||||
return new {typeName}(lhs) / rhs;
|
||||
return new {typeName}({string.Join(", ", s_vectorComponents.Take(typeInfo.Row).Select(c => $"lhs / rhs.{c}"))});
|
||||
}}
|
||||
|
||||
#if NET10_0_OR_GREATER
|
||||
@@ -580,13 +553,13 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeName} operator %({typeName} lhs, {componentType} rhs)
|
||||
{{
|
||||
return lhs % new {typeName}(rhs);
|
||||
return new {typeName}({string.Join(", ", s_vectorComponents.Take(typeInfo.Row).Select(c => $"lhs.{c} % rhs"))});
|
||||
}}
|
||||
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeName} operator %({componentType} lhs, {typeName} rhs)
|
||||
{{
|
||||
return new {typeName}(lhs) % rhs;
|
||||
return new {typeName}({string.Join(", ", s_vectorComponents.Take(typeInfo.Row).Select(c => $"lhs % rhs.{c}"))});
|
||||
}}
|
||||
|
||||
#if NET10_0_OR_GREATER
|
||||
@@ -615,19 +588,19 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeName} operator -({typeName} value)
|
||||
{{
|
||||
return (-value.AsVector{_vectorBitsSize}()).{asResult};
|
||||
return new {typeName}(0{_componentTypePrefix}) - value;
|
||||
}}
|
||||
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeName} operator ++({typeName} value)
|
||||
{{
|
||||
return (value.AsVector{_vectorBitsSize}() + global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.CreateScalar(1{_componentTypePrefix})).{asResult};
|
||||
return value + new {typeName}(1{_componentTypePrefix});
|
||||
}}
|
||||
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeName} operator --({typeName} value)
|
||||
{{
|
||||
return (value.AsVector{_vectorBitsSize}() - global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.CreateScalar(1{_componentTypePrefix})).{asResult};
|
||||
return value - new {typeName}(1{_componentTypePrefix});
|
||||
}}");
|
||||
|
||||
// Comparison operators
|
||||
@@ -788,7 +761,7 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
|
||||
else
|
||||
{
|
||||
sourceBuilder.Append($@"
|
||||
return global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.Create({string.Join(", ", Enumerable.Range(0, typeInfo.Row + _missingComponents).Select(i => i < typeInfo.Row ? $"value.{s_vectorComponents[i]}" : "0"))});");
|
||||
return global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.Create({string.Join(", ", Enumerable.Range(0, typeInfo.Row + _missingComponents).Select(i => i < typeInfo.Row ? $"value.{s_vectorComponents[i]}" : "default"))});");
|
||||
}
|
||||
sourceBuilder.Append($@"
|
||||
}}
|
||||
@@ -803,11 +776,6 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
|
||||
}}");
|
||||
}
|
||||
|
||||
private string ComponentwiseAssignments(Func<string, string> func, string separator = ", ")
|
||||
{
|
||||
return string.Join(separator, s_vectorComponents.Take(typeInfo.Row).Select(func));
|
||||
}
|
||||
|
||||
private void GenerateMathMethod()
|
||||
{
|
||||
var typeName = typeInfo.TypeName;
|
||||
@@ -824,7 +792,7 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} {typeName}({signature})
|
||||
{{
|
||||
return {typeFullName}.Create({assignment});
|
||||
return new {typeFullName}({string.Join(", ", assignment)});
|
||||
}}");
|
||||
}
|
||||
|
||||
@@ -881,724 +849,6 @@ namespace Misaki.HighPerformance.Mathematics.CodeGen.Generators
|
||||
throw new System.ArgumentException(""Invalid shuffle component: "" + component);
|
||||
}}
|
||||
}}");
|
||||
|
||||
if (typeInfo.ComponentTypeSymbol.SpecialType == SpecialType.System_Boolean)
|
||||
{
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns true if any component of the input {typeName} vector is true, false otherwise.</summary>
|
||||
/// <param name=""v"">Vector of values to compare.</param>
|
||||
/// <returns>True if any the components of v are true, false otherwise.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static bool any({typeFullName} v)
|
||||
{{
|
||||
return {ComponentwiseAssignments(c => $"v.{c}", " ||")};
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns true if all component of the input {typeName} vector is true, false otherwise.</summary>
|
||||
/// <param name=""v"">Vector of values to compare.</param>
|
||||
/// <returns>True if all the components of v are true, false otherwise.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static bool all({typeFullName} v)
|
||||
{{
|
||||
return {ComponentwiseAssignments(c => $"v.{c}", " && ")};
|
||||
}}");
|
||||
}
|
||||
|
||||
if (typeInfo.Arithmetic)
|
||||
{
|
||||
StartRegion("Math Methods");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise minimum of two {typeName} vectors.</summary>
|
||||
/// <param name=""x"">The first vector to compare.</param>
|
||||
/// <param name=""y"">The second vector to compare.</param>
|
||||
/// <returns>The componentwise minimum of the two vectors.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} min({typeFullName} x, {typeFullName} y)
|
||||
{{
|
||||
var vector = global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.Min(x.AsVector{_vectorBitsSize}(), y.AsVector{_vectorBitsSize}());
|
||||
return vector.As{typeName}();
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise maximum of two {typeName} vectors.</summary>
|
||||
/// <param name=""x"">The first vector to compare.</param>
|
||||
/// <param name=""y"">The second vector to compare.</param>
|
||||
/// <returns>The componentwise maximum of the two vectors.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} max({typeFullName} x, {typeFullName} y)
|
||||
{{
|
||||
var vector = global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.Max(x.AsVector{_vectorBitsSize}(), y.AsVector{_vectorBitsSize}());
|
||||
return vector.As{typeName}();
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise absolute value of a {typeName} vector.</summary>
|
||||
/// <param name=""v"">Input value.</param>
|
||||
/// <returns>The componentwise absolute value of the input.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} abs({typeFullName} v)
|
||||
{{
|
||||
return max(v, -v);
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the result of a componentwise clamping of the value v into the interval (inclusive) [min, max], where v, min and max are {typeName} vectors.</summary>
|
||||
/// <param name=""v"">Input value to be clamped.</param>
|
||||
/// <param name=""min"">Lower bound of the interval.</param>
|
||||
/// <param name=""max"">Upper bound of the interval.</param>
|
||||
/// <returns>The componentwise clamping of the input valueToClamp into the interval (inclusive) [min, max].</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} clamp({typeFullName} v, {typeFullName} min, {typeFullName} max)
|
||||
{{
|
||||
var vector = global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.Clamp(v.AsVector{_vectorBitsSize}(), min.AsVector{_vectorBitsSize}(), max.AsVector{_vectorBitsSize}());
|
||||
return vector.As{typeName}();
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the dot product of two {typeName} vectors.</summary>
|
||||
/// <param name=""x"">The first vector to dot.</param>
|
||||
/// <param name=""y"">The second vector to dot.</param>
|
||||
/// <returns>The dot product of the two vectors.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {componentTypeFullName} dot({typeFullName} x, {typeFullName} y)
|
||||
{{
|
||||
return global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.Dot(x.AsVector{_vectorBitsSize}(), y.AsVector{_vectorBitsSize}());
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns trueValue if test is true, falseValue otherwise.</summary>
|
||||
/// <param name=""falseValue"">Value to use if test is false.</param>
|
||||
/// <param name=""trueValue"">Value to use if test is true.</param>
|
||||
/// <param name=""test"">Bool value to choose between falseValue and trueValue.</param>
|
||||
/// <returns>The selection between falseValue and trueValue according to bool test.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} select({typeFullName} falseValue, {typeFullName} trueValue, bool test)
|
||||
{{
|
||||
return test ? trueValue : falseValue;
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>
|
||||
/// Returns a componentwise selection between two {typeName} vectors falseValue and trueValue based on a bool{typeInfo.Row} selection mask test.
|
||||
/// Per component, the component from trueValue is selected when test is true, otherwise the component from falseValue is selected.
|
||||
/// </summary>
|
||||
/// <param name=""falseValue"">Values to use if test is false.</param>
|
||||
/// <param name=""trueValue"">Values to use if test is true.</param>
|
||||
/// <param name=""test"">Selection mask to choose between falseValue and trueValue.</param>
|
||||
/// <returns>The componentwise selection between falseValue and trueValue according to selection mask test.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} select({typeFullName} falseValue, {typeFullName} trueValue, global::Misaki.HighPerformance.Mathematics.bool{typeInfo.Row} test)
|
||||
{{
|
||||
return new {typeFullName}({ComponentwiseAssignments(c => $"test.{c} ? trueValue.{c} : falseValue.{c}")});
|
||||
}}");
|
||||
|
||||
if (typeInfo.ComponentTypeSymbol.SpecialType != SpecialType.System_UInt16
|
||||
&& typeInfo.ComponentTypeSymbol.SpecialType != SpecialType.System_UInt32
|
||||
&& typeInfo.ComponentTypeSymbol.SpecialType != SpecialType.System_UInt64)
|
||||
{
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise sign of a {typeName} vector. 1 for positive components, 0 for zero components and -1 for negative components.</summary>
|
||||
/// <param name=""v"">Input value.</param>
|
||||
/// <returns>The componentwise sign of the input.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} sign({typeFullName} v)
|
||||
{{
|
||||
return new {typeFullName}({ComponentwiseAssignments(c => $"sign(v.{c})")});
|
||||
}}");
|
||||
}
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns true if any component of the input {typeName} vector is true, false otherwise.</summary>
|
||||
/// <param name=""v"">Vector of values to compare.</param>
|
||||
/// <returns>True if any the components of v are true, false otherwise.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static bool any({typeFullName} v)
|
||||
{{
|
||||
return {ComponentwiseAssignments(c => $"v.{c} != 0", " || ")};
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns true if all component of the input {typeName} vector is true, false otherwise.</summary>
|
||||
/// <param name=""v"">Vector of values to compare.</param>
|
||||
/// <returns>True if all the components of v are true, false otherwise.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static bool all({typeFullName} v)
|
||||
{{
|
||||
return {ComponentwiseAssignments(c => $"v.{c} != 0", " && ")};
|
||||
}}");
|
||||
|
||||
// Only floating point types support these methods
|
||||
if (typeInfo.ComponentTypeSymbol.SpecialType == SpecialType.System_Single
|
||||
|| typeInfo.ComponentTypeSymbol.SpecialType == SpecialType.System_Double)
|
||||
{
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the result of a componentwise clamping of the {typeName} vector v into the interval [0, 1].</summary>
|
||||
/// <param name=""v"">Input value.</param>
|
||||
/// <returns>The componentwise clamping of the input into the interval [0, 1].</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} saturate({typeFullName} v)
|
||||
{{
|
||||
return clamp(v, new {typeFullName}(0{_componentTypePrefix}), new {typeFullName}(1{_componentTypePrefix}));
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the linear interpolation between two {typeName} vectors x and y by the interpolant t.</summary>
|
||||
/// <param name=""x"">The vector when t is 0.</param>
|
||||
/// <param name=""y"">The vector when t is 1.</param>
|
||||
/// <param name=""t"">The interpolation factor.</param>
|
||||
/// <returns>The linearly interpolated vector.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} lerp({typeFullName} x, {typeFullName} y, {componentTypeFullName} t)
|
||||
{{
|
||||
var vector = global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.Lerp(x.AsVector{_vectorBitsSize}(), y.AsVector{_vectorBitsSize}(), global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.Create(t));
|
||||
return vector.As{typeName}();
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the result of a componentwise linear interpolation between two {typeName} vectors x and y using a {typeName} vector t.</summary>
|
||||
/// <param name=""x"">The value to interpolate from.</param>
|
||||
/// <param name=""y"">The value to interpolate to.</param>
|
||||
/// <param name=""t"">The interpolation factor.</param>
|
||||
/// <returns>The linearly interpolated vector.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} lerp({typeFullName} x, {typeFullName} y, {typeFullName} t)
|
||||
{{
|
||||
var vector = global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.Lerp(x.AsVector{_vectorBitsSize}(), y.AsVector{_vectorBitsSize}(), t.AsVector{_vectorBitsSize}());
|
||||
return vector.As{typeName}();
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise result of normalizing a value x to a range [a, b]. The opposite of lerp. Equivalent to (v - a) / (b - a).</summary>
|
||||
/// <param name=""start"">The start point of the range.</param>
|
||||
/// <param name=""end"">The end point of the range.</param>
|
||||
/// <param name=""v""> The value to normalize to the range.</param>
|
||||
/// <returns>The componentwise interpolation parameter of x with respect to the input range [a, b].</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} unlerp({typeFullName} start, {typeFullName} end, {typeFullName} v)
|
||||
{{
|
||||
return (v - start) / (end - start);
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise result of a non-clamping linear remapping of a value x from source range [srcStart, srcEnd] to the destination range [dstStart, dstEnd].</summary>
|
||||
/// <param name=""srcStart"">The start point of the source range [srcStart, srcEnd].</param>
|
||||
/// <param name=""srcEnd"">The end point of the source range [srcStart, srcEnd].</param>
|
||||
/// <param name=""dstStart"">The start point of the destination range [dstStart, dstEnd].</param>
|
||||
/// <param name=""dstEnd"">The end point of the destination range [dstStart, dstEnd].</param>
|
||||
/// <param name=""v"">The value to remap from the source to destination range.</param>
|
||||
/// <returns>The componentwise remap of input x from the source range to the destination range.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} remap({typeFullName} srcStart, {typeFullName} srcEnd, {typeFullName} dstStart, {typeFullName} dstEnd, {typeFullName} v)
|
||||
{{
|
||||
return lerp(dstStart, dstEnd, unlerp(srcStart, srcEnd, v));
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the result of a componentwise multiply-add operation (a * b + c) on 3 {typeName} vectors.</summary>
|
||||
/// <remarks>
|
||||
/// When fast math enabled on some architectures, this could be converted to a fused multiply add (FMA).
|
||||
/// FMA is more accurate due to rounding once at the end of the computation rather than twice that is required when
|
||||
/// this computation is not fused.
|
||||
/// </remarks>
|
||||
/// <param name=""mulA"">First value to multiply.</param>
|
||||
/// <param name=""mulB"">Second value to multiply.</param>
|
||||
/// <param name=""addC"">Third value to add to the product of a and b.</param>
|
||||
/// <returns>The componentwise multiply-add of the inputs.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} mad({typeFullName} mulA, {typeFullName} mulB, {typeFullName} addC)
|
||||
{{
|
||||
var vector = global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.FusedMultiplyAdd(mulA.AsVector{_vectorBitsSize}(), mulB.AsVector{_vectorBitsSize}(), addC.AsVector{_vectorBitsSize}());
|
||||
return vector.As{typeName}();
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise tangent of a {typeFullName} vector.</summary>
|
||||
/// <param name=""v"">Input value.</param>
|
||||
/// <returns>The componentwise tangent of the input.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} tan({typeFullName} v)
|
||||
{{
|
||||
return new {typeFullName}({ComponentwiseAssignments(c => $"tan(v.{c})")});
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise hyperbolic tangent of a {typeFullName} vector.</summary>
|
||||
/// <param name=""v"">Input value.</param>
|
||||
/// <returns>The componentwise hyperbolic tangent of the input.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} tanh({typeFullName} v)
|
||||
{{
|
||||
return new {typeFullName}({ComponentwiseAssignments(c => $"tanh(v.{c})")});
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise arctangent of a {typeFullName} vector.</summary>
|
||||
/// <param name=""v"">Input value.</param>
|
||||
/// <returns>The componentwise arctangent of the input.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} atan({typeFullName} v)
|
||||
{{
|
||||
return new {typeFullName}({ComponentwiseAssignments(c => $"atan(v.{c})")});
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise 2-argument arctangent of a {typeFullName} vector.</summary>
|
||||
/// <param name=""x"">Input value x.</param>
|
||||
/// <param name=""y"">Input value y.</param>
|
||||
/// <returns>The componentwise 2-argument arctangent of the input.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} atan2({typeFullName} x, {typeFullName} y)
|
||||
{{
|
||||
return new {typeFullName}({ComponentwiseAssignments(c => $"atan2(x.{c}, y.{c})")});
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise cosine of a {typeName} vector.</summary>
|
||||
/// <param name=""v"">Input value.</param>
|
||||
/// <returns>The componentwise cosine of the input.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} cos({typeFullName} v)
|
||||
{{
|
||||
var vector = global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.Cos(v.AsVector{_vectorBitsSize}());
|
||||
return vector.As{typeName}();
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise hyperbolic cosine of a {typeFullName} vector.</summary>
|
||||
/// <param name=""v"">Input value.</param>
|
||||
/// <returns>The componentwise hyperbolic cosine of the input.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} cosh({typeFullName} v)
|
||||
{{
|
||||
return new {typeFullName}({ComponentwiseAssignments(c => $"cosh(v.{c})")});
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise arccosine of a {typeFullName} vector.</summary>
|
||||
/// <param name=""v"">Input value.</param>
|
||||
/// <returns>The componentwise arccosine of the input.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} acos({typeFullName} v)
|
||||
{{
|
||||
return new {typeFullName}({ComponentwiseAssignments(c => $"acos(v.{c})")});
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise sine of a {typeName} vector.</summary>
|
||||
/// <param name=""v"">Input value.</param>
|
||||
/// <returns>The componentwise sine of the input.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} sin({typeFullName} v)
|
||||
{{
|
||||
var vector = global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.Sin(v.AsVector{_vectorBitsSize}());
|
||||
return vector.As{typeName}();
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise hyperbolic sine of a {typeFullName} vector.</summary>
|
||||
/// <param name=""v"">Input value.</param>
|
||||
/// <returns>The componentwise hyperbolic sine of the input.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} sinh({typeFullName} v)
|
||||
{{
|
||||
return new {typeFullName}({ComponentwiseAssignments(c => $"sinh(v.{c})")});
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise arcsine of a {typeFullName} vector.</summary>
|
||||
/// <param name=""v"">Input value.</param>
|
||||
/// <returns>The componentwise arcsine of the input.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} asin({typeFullName} v)
|
||||
{{
|
||||
return new {typeFullName}({ComponentwiseAssignments(c => $"asin(v.{c})")});
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise sine and cosine of a {typeName} vector.</summary>
|
||||
/// <param name=""v"">Input value.</param>
|
||||
/// <returns>The componentwise sine and cosine of the input.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static ({typeFullName} sin, {typeFullName} cos) sincos({typeFullName} v)
|
||||
{{
|
||||
var vectors = global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.SinCos(v.AsVector{_vectorBitsSize}());
|
||||
return (vectors.Sin.As{typeName}(), vectors.Cos.As{typeName}());
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise floor of a {typeName} vector.</summary>
|
||||
/// <param name=""v"">Input value.</param>
|
||||
/// <returns>The componentwise floor of the input.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} floor({typeFullName} v)
|
||||
{{
|
||||
var vector = global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.Floor(v.AsVector{_vectorBitsSize}());
|
||||
return vector.As{typeName}();
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise ceiling of a {typeName} vector.</summary>
|
||||
/// <param name=""v"">Input value.</param>
|
||||
/// <returns>The componentwise ceiling of the input.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} ceil({typeFullName} v)
|
||||
{{
|
||||
var vector = global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.Ceiling(v.AsVector{_vectorBitsSize}());
|
||||
return vector.As{typeName}();
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the result of rounding each component of a {typeName} vector value to the nearest integral value.</summary>
|
||||
/// <param name=""v"">Input value.</param>
|
||||
/// <returns>The componentwise round to nearest integral value of the input.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} round({typeFullName} v)
|
||||
{{
|
||||
return new {typeFullName}({ComponentwiseAssignments(c => $"round(v.{c})")});
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise base-e exponential of a {typeName} vector.</summary>
|
||||
/// <param name=""v"">Input value.</param>
|
||||
/// <returns>The componentwise base-e exponential of the input.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} exp({typeFullName} v)
|
||||
{{
|
||||
var vector = global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.Exp(v.AsVector{_vectorBitsSize}());
|
||||
return vector.As{typeName}();
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise base-2 exponential of a {typeName} vector.</summary>
|
||||
/// <param name=""v"">Input value.</param>
|
||||
/// <returns>The componentwise base-2 exponential of the input.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} exp2({typeFullName} v)
|
||||
{{
|
||||
var vector = global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.Exp(v.AsVector{_vectorBitsSize}() * 0.693147180559945309{_componentTypePrefix});
|
||||
return vector.As{typeName}();
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise base-10 exponential of a {typeName} vector.</summary>
|
||||
/// <param name=""v"">Input value.</param>
|
||||
/// <returns>The componentwise base-10 exponential of the input.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} exp10({typeFullName} v)
|
||||
{{
|
||||
var vector = global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.Exp(v.AsVector{_vectorBitsSize}() * 2.302585092994045684{_componentTypePrefix});
|
||||
return vector.As{typeName}();
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise natural logarithm (base-e) of a {typeName} vector.</summary>
|
||||
/// <param name=""v"">Input value.</param>
|
||||
/// <returns>The componentwise natural logarithm of the input.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} log({typeFullName} v)
|
||||
{{
|
||||
var vector = global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.Log(v.AsVector{_vectorBitsSize}());
|
||||
return vector.As{typeName}();
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise base-2 logarithm of a {typeName} vector.</summary>
|
||||
/// <param name=""v"">Input value.</param>
|
||||
/// <returns>The componentwise base-2 logarithm of the input.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} log2({typeFullName} v)
|
||||
{{
|
||||
var vector = global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.Log2(v.AsVector{_vectorBitsSize}());
|
||||
return vector.As{typeName}();
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise base-10 logarithm of a {typeName} vector.</summary>
|
||||
/// <param name=""v"">Input value.</param>
|
||||
/// <returns>The componentwise base-10 logarithm of the input.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} log10({typeFullName} v)
|
||||
{{
|
||||
return new {typeFullName}({ComponentwiseAssignments(c => $"log10(v.{c})")});
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise quadratic root of a {typeName} vector.</summary>
|
||||
/// <param name=""v"">Input value.</param>
|
||||
/// <returns>The componentwise quadratic root of the input.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} sqrt({typeFullName} v)
|
||||
{{
|
||||
var vector = global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.Sqrt(v.AsVector{_vectorBitsSize}());
|
||||
return vector.As{typeName}();
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the reciprocal square root of a {typeName} vector.</summary>
|
||||
/// <param name=""v"">Value to use when computing reciprocal square root.</param>
|
||||
/// <returns>The reciprocal square root.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} rsqrt({typeFullName} v)
|
||||
{{
|
||||
return 1{_componentTypePrefix} / sqrt(v);
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the length of a {typeName} vector.</summary>
|
||||
/// <param name=""v"">Vector to use when computing length.</param>
|
||||
/// <returns>Length of vector v.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {componentTypeFullName} length({typeFullName} v)
|
||||
{{
|
||||
return sqrt(dot(v, v));
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the squared length of a {typeName} vector.</summary>
|
||||
/// <param name=""v"">Vector to use when computing squared length.</param>
|
||||
/// <returns>Squared length of vector v.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {componentTypeFullName} lengthsq({typeFullName} v)
|
||||
{{
|
||||
return dot(v, v);
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the distance between two {typeName} vectors.</summary>
|
||||
/// <param name=""x"">First vector to use in distance computation.</param>
|
||||
/// <param name=""y"">Second vector to use in distance computation.</param>
|
||||
/// <returns>The distance between x and y.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {componentTypeFullName} distance({typeFullName} x, {typeFullName} y)
|
||||
{{
|
||||
return length(y - x);
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the squared distance between two {typeName} vectors.</summary>
|
||||
/// <param name=""x"">First vector to use in distance computation.</param>
|
||||
/// <param name=""y"">Second vector to use in distance computation.</param>
|
||||
/// <returns>The squared distance between x and y.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {componentTypeFullName} distancesq({typeFullName} x, {typeFullName} y)
|
||||
{{
|
||||
return lengthsq(y - x);
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise truncate of a {typeName} vector.</summary>
|
||||
/// <param name=""v"">Input value.</param>
|
||||
/// <returns>The componentwise truncate of the input.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} trunc({typeFullName} v)
|
||||
{{
|
||||
var vector = global::System.Runtime.Intrinsics.Vector{_vectorBitsSize}.Truncate(v.AsVector{_vectorBitsSize}());
|
||||
return vector.As{typeName}();
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise fractional parts of a {typeName} vector.</summary>
|
||||
/// <param name=""v"">Input value.</param>
|
||||
/// <returns>The componentwise fractional part of the input.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} frac({typeFullName} v)
|
||||
{{
|
||||
return v - floor(v);
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the reciprocal a {typeName} vector.</summary>
|
||||
/// <param name=""v"">Input value.</param>
|
||||
/// <returns>The reciprocal of the input.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} rcp({typeFullName} v)
|
||||
{{
|
||||
return 1{_componentTypePrefix} / v;
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise result of raising v to the power p.</summary>
|
||||
/// <param name=""x"">The exponent base.</param>
|
||||
/// <param name=""y"">The exponent power.</param>
|
||||
/// <returns>The componentwise result of raising x to the power y.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} pow({typeFullName} x, {typeFullName} y)
|
||||
{{
|
||||
return new {typeFullName}({ComponentwiseAssignments(c => $"pow(x.{c}, y.{c})")});
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the componentwise floating point remainder of x/y.</summary>
|
||||
/// <param name=""x"">The dividend in x/y.</param>
|
||||
/// <param name=""y"">The divisor in x/y.</param>
|
||||
/// <returns>The componentwise remainder of x/y.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} fmod({typeFullName} x, {typeFullName} y)
|
||||
{{
|
||||
return new {typeFullName}({ComponentwiseAssignments(c => $"x.{c} % y.{c}")});
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>
|
||||
/// Performs a componentwise split of a {typeName} vector into an integral part i and a fractional part that gets returned.
|
||||
/// Both parts take the sign of the corresponding input component.
|
||||
/// </summary>
|
||||
/// <param name=""x"">Value to split into integral and fractional part.</param>
|
||||
/// <param name=""i"">Output value containing integral part of x.</param>
|
||||
/// <returns>The componentwise fractional part of x.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} modf({typeFullName} x, out {typeFullName} i)
|
||||
{{
|
||||
i = trunc(x);
|
||||
return x - i;
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns a normalized version of the {typeName} vector v by scaling it by 1 / length(v).</summary>
|
||||
/// <param name=""v"">Vector to normalize.</param>
|
||||
/// <returns>The normalized vector.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} normalize({typeFullName} v)
|
||||
{{
|
||||
return rsqrt(dot(v, v)) * v;
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>
|
||||
/// Returns a safe normalized version of the {typeName} vector v by scaling it by 1 / length(v).
|
||||
/// Returns the given default value when 1 / length(v) does not produce a finite number.
|
||||
/// </summary>
|
||||
/// <param name=""v"">Vector to normalize.</param>
|
||||
/// <param name=""defaultvalue"">Vector to return if normalized vector is not finite.</param>
|
||||
/// <returns>The normalized vector or the default value if the normalized vector is not finite.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
static public {typeFullName} normalizesafe({typeFullName} v, {typeFullName} defaultvalue = default)
|
||||
{{
|
||||
var len = dot(v, v);
|
||||
return select(defaultvalue, v * rsqrt(len), len > FLT_MIN_NORMAL);
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns a componentwise smooth Hermite interpolation between 0.0f and 1.0f when v is in the interval (inclusive) [vMin, vMax].</summary>
|
||||
/// <param name=""vMin"">The minimum range of the v parameter.</param>
|
||||
/// <param name=""vMax"">The maximum range of the v parameter.</param>
|
||||
/// <param name=""v"">The value to be interpolated.</param>
|
||||
/// <returns>Returns component values camped to the range [0, 1].</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} smoothstep({typeFullName} vMin, {typeFullName} vMax, {typeFullName} v)
|
||||
{{
|
||||
var t = saturate((v - vMin) / (vMax - vMin));
|
||||
return t * t * (3{_componentTypePrefix} - (2{_componentTypePrefix} * t));
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the result of a componentwise step function where each component is 1.0f when v = threshold and 0.0f otherwise.</summary>
|
||||
/// <param name=""threshold"">Vector of values to be used as a threshold for returning 1.</param>
|
||||
/// <param name=""v"">Vector of values to compare against threshold.</param>
|
||||
/// <returns>1 if the componentwise comparison v = threshold is true, otherwise 0.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} step({typeFullName} threshold, {typeFullName} v)
|
||||
{{
|
||||
return select(new {typeFullName}(0{_componentTypePrefix}), new {typeFullName}(1{_componentTypePrefix}), v == threshold);
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Given an incident vector i and a normal vector n, returns the reflection vector r = i - 2.0 * dot(i, n) * n.</summary>
|
||||
/// <param name=""i"">Incident vector.</param>
|
||||
/// <param name=""n"">Normal vector.</param>
|
||||
/// <returns>Reflection vector.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} reflect({typeFullName} i, {typeFullName} n)
|
||||
{{
|
||||
return i - 2{_componentTypePrefix} * n * dot(i, n);
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the refraction vector given the incident vector i, the normal vector n and the refraction index.</summary>
|
||||
/// <param name=""i"">Incident vector.</param>
|
||||
/// <param name=""n"">Normal vector.</param>
|
||||
/// <param name=""indexOfRefraction"">Index of refraction.</param>
|
||||
/// <returns>Refraction vector.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} refract({typeFullName} i, {typeFullName} n, {componentTypeFullName} indexOfRefraction)
|
||||
{{
|
||||
var ni = dot(n, i);
|
||||
var k = 1.0f - indexOfRefraction * indexOfRefraction * (1{_componentTypePrefix} - ni * ni);
|
||||
return select(new(0{_componentTypePrefix}), indexOfRefraction * i - (indexOfRefraction * ni + sqrt(k)) * n, k >= 0);
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>
|
||||
/// Compute vector projection of a onto b.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Some finite vectors a and b could generate a non-finite result. This is most likely when a's components
|
||||
/// are very large (close to Single.MaxValue) or when b's components are very small (close to FLT_MIN_NORMAL).
|
||||
/// In these cases, you can call <see cref=""projectsafe({typeFullName},{typeFullName},{typeFullName})""/>
|
||||
/// which will use a given default value if the result is not finite.
|
||||
/// </remarks>
|
||||
/// <param name=""a"">Vector to project.</param>
|
||||
/// <param name=""ontoB"">Non-zero vector to project onto.</param>
|
||||
/// <returns>Vector projection of a onto b.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} project({typeFullName} a, {typeFullName} ontoB)
|
||||
{{
|
||||
return (dot(a, ontoB) / dot(ontoB, ontoB)) * ontoB;
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>
|
||||
/// Compute vector projection of a onto b. If result is not finite, then return the default value instead.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This function performs extra checks to see if the result of projecting a onto b is finite. If you know that
|
||||
/// your inputs will generate a finite result or you don't care if the result is finite, then you can call
|
||||
/// <see cref=""project({typeFullName},{typeFullName})""/> instead which is faster than this function.
|
||||
/// </remarks>
|
||||
/// <param name=""a"">Vector to project.</param>
|
||||
/// <param name=""ontoB"">Non-zero vector to project onto.</param>
|
||||
/// <param name=""defaultValue"">Default value to return if projection is not finite.</param>
|
||||
/// <returns>Vector projection of a onto b or the default value.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} projectsafe({typeFullName} a, {typeFullName} ontoB, {typeFullName} defaultValue = default)
|
||||
{{
|
||||
var proj = project(a, ontoB);
|
||||
|
||||
return select(defaultValue, proj, all(isfinite(proj)));
|
||||
}}");
|
||||
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Conditionally flips a vector n if two vectors i and ng are pointing in the same direction. Returns n if dot(i, ng) < 0, -n otherwise.</summary>
|
||||
/// <param name=""n"">Vector to conditionally flip.</param>
|
||||
/// <param name=""i"">First vector in direction comparison.</param>
|
||||
/// <param name=""ng"">Second vector in direction comparison.</param>
|
||||
/// <returns>-n if i and ng point in the same direction; otherwise return n unchanged.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} faceforward({typeFullName} n, {typeFullName} i, {typeFullName} ng)
|
||||
{{
|
||||
return select(n, -n, dot(ng, i) >= 0.0f);
|
||||
}}");
|
||||
}
|
||||
else
|
||||
{
|
||||
sourceBuilder.AppendLine($@"
|
||||
/// <summary>Returns the result of a componentwise multiply-add operation (a * b + c) on 3 {typeName} vectors.</summary>
|
||||
/// <param name=""mulA"">First value to multiply.</param>
|
||||
/// <param name=""mulB"">Second value to multiply.</param>
|
||||
/// <param name=""addC"">Third value to add to the product of a and b.</param>
|
||||
/// <returns>The componentwise multiply-add of the inputs.</returns>
|
||||
{INLINE_METHOD_ATTRIBUTE}
|
||||
public static {typeFullName} mad({typeFullName} mulA, {typeFullName} mulB, {typeFullName} addC)
|
||||
{{
|
||||
return mulA * mulB + addC;
|
||||
}}");
|
||||
}
|
||||
|
||||
EndRegion();
|
||||
}
|
||||
|
||||
sourceBuilder.Append($@"
|
||||
}}");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user