Files
Misaki.HighPerformance/Misaki.HighPerformance.Mathematics.SPMD/Templates/MathV.Vector.tt

344 lines
12 KiB
Plaintext

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".gen.cs" #>
/// <auto-generated/>
/// This code is automatically generated by a T4 template.
/// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
/// </auto-generated>
using System.Numerics;
using System.Runtime.CompilerServices;
namespace Misaki.HighPerformance.Mathematics.SPMD;
<#
const string TLane = "TLane";
const string TNumber = "TNumber";
const string GenericParameters = $"{TLane}, {TNumber}";
var dimensions = new int[] { 2, 3, 4 };
var components = new char[] { 'x', 'y', 'z', 'w' };
var TLaneRestrictions = $@"where {TLane} : ISPMD<{TLane}, {TNumber}>";
var TNumberRestrictions = $@"where {TNumber} : unmanaged, INumber<{TNumber}>, IBinaryNumber<{TNumber}>, IMinMaxValue<{TNumber}>, IBitwiseOperators<{TNumber}, {TNumber}, {TNumber}>";
#>
public static unsafe partial class MathV
{
<# foreach (int dimension in dimensions) {
var vectorType = $"Vector{dimension}<{TLane}, {TNumber}>";
#>
# region Vector<#= dimension #>
// Creation Functions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> Create<<#= GenericParameters #>>(<#= ForEachDimension(dimension, i => $"in TLane {components[i]}") #>)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
return new <#= vectorType #>
{
<# for (int i = 0; i < dimension; i++) { #>
<#= components[i] #> = <#= components[i] #>,
<# } #>
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> CreateVector<#= dimension #><<#= GenericParameters #>>(in TLane value)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
return new <#= vectorType #>
{
<# for (int i = 0; i < dimension; i++) { #>
<#= components[i] #> = value,
<# } #>
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> LoadVector<#= dimension #><<#= GenericParameters #>>(TNumber* pSrc)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
var width = TLane.LaneWidth;
<# for (int i = 0; i < dimension; i++) { #>
var <#= components[i] #> = stackalloc TNumber[width];
<# } #>
for (var i = 0; i < width; i++)
{
<# for (int i = 0; i < dimension; i++) { #>
<#= components[i] #>[i] = pSrc[i * <#= dimension #> + <#= i #>];
<# } #>
}
return new <#= vectorType #>
{
<# for (int i = 0; i < dimension; i++) { #>
<#= components[i] #> = <#= TLane #>.Load(<#= components[i] #>),
<# } #>
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> LoadVector<#= dimension #><<#= GenericParameters #>>(ref TNumber src)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
return LoadVector<#= dimension #><<#= GenericParameters #>>((TNumber*)Unsafe.AsPointer(ref src));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> Load<<#= GenericParameters #>>(<#= ForEachDimension(dimension, i => $"TNumber* p{components[i]}") #>)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
return new <#= vectorType #>
{
<# for (int i = 0; i < dimension; i++) { #>
<#= components[i] #> = <#= TLane #>.Load(p<#= components[i] #>),
<# } #>
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> Load<<#= GenericParameters #>>(<#= ForEachDimension(dimension, i => $"ref TNumber {components[i]}") #>)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
return new <#= vectorType #>
{
<# for (int i = 0; i < dimension; i++) { #>
<#= components[i] #> = <#= TLane #>.Load(ref <#= components[i] #>),
<# } #>
};
}
// Math Functions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> Abs<<#= GenericParameters #>>(in Vector<#= dimension #><TLane, TNumber> vector)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
return new <#= vectorType #>
{
<# for (int i = 0; i < dimension; i++) { #>
<#= components[i] #> = <#= TLane #>.Abs(vector.<#= components[i] #>),
<# } #>
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= TLane #> Dot<<#= GenericParameters #>>(in <#= vectorType #> a, in <#= vectorType #> b)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
return <#= ForEachDimension(dimension, i => $"a.{components[i]} * b.{components[i]}", " + ") #>;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> Sqrt<<#= GenericParameters #>>(in <#= vectorType #> vector)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
return new <#= vectorType #>
{
<# for (int i = 0; i < dimension; i++) { #>
<#= components[i] #> = <#= TLane #>.Sqrt(vector.<#= components[i] #>),
<# } #>
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> Rsqrt<<#= GenericParameters #>>(in <#= vectorType #> vector)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
return new <#= vectorType #>
{
<# for (int i = 0; i < dimension; i++) { #>
<#= components[i] #> = <#= TLane #>.Rsqrt(vector.<#= components[i] #>),
<# } #>
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> Normalize<<#= GenericParameters #>>(in <#= vectorType #> vector)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
return vector * <#= TLane #>.Rsqrt(Dot(vector, vector));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> Reflect<<#= GenericParameters #>>(in <#= vectorType #> incident, in <#= vectorType #> normal)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
var dot = Dot(incident, normal);
return incident - normal * (dot + dot);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> Min<<#= GenericParameters #>>(in <#= vectorType #> a, in <#= vectorType #> b)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
return new <#= vectorType #>
{
<# for (int i = 0; i < dimension; i++) { #>
<#= components[i] #> = <#= TLane #>.Min(a.<#= components[i] #>, b.<#= components[i] #>),
<# } #>
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> Max<<#= GenericParameters #>>(in <#= vectorType #> a, in <#= vectorType #> b)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
return new <#= vectorType #>
{
<# for (int i = 0; i < dimension; i++) { #>
<#= components[i] #> = <#= TLane #>.Max(a.<#= components[i] #>, b.<#= components[i] #>),
<# } #>
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> Clamp<<#= GenericParameters #>>(in <#= vectorType #> value, in <#= vectorType #> min, in <#= vectorType #> max)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
return Min(Max(value, min), max);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> Saturate<<#= GenericParameters #>>(in <#= vectorType #> value)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
return Clamp(value, CreateVector<#= dimension #><<#= GenericParameters #>>(<#= TLane #>.Zero), CreateVector<#= dimension #><<#= GenericParameters #>>(<#= TLane #>.One));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> Lerp<<#= GenericParameters #>>(in <#= vectorType #> a, in <#= vectorType #> b, <#= TLane #> t)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
return a + (b - a) * t;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= TLane #> Length<<#= GenericParameters #>>(in <#= vectorType #> vector)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
return <#= TLane #>.Sqrt(Dot(vector, vector));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= TLane #> LengthSquared<<#= GenericParameters #>>(in <#= vectorType #> vector)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
return Dot(vector, vector);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= TLane #> Distance<<#= GenericParameters #>>(in <#= vectorType #> a, in <#= vectorType #> b)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
var diff = b - a;
return <#= TLane #>.Sqrt(Dot(diff, diff));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= TLane #> DistanceSquared<<#= GenericParameters #>>(in <#= vectorType #> a, in <#= vectorType #> b)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
var diff = b - a;
return Dot(diff, diff);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> Step<<#= GenericParameters #>>(in <#= vectorType #> edge, in <#= vectorType #> value)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
return Select(value >= edge, <#= vectorType #>.One, <#= vectorType #>.Zero);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> Smoothstep<<#= GenericParameters #>>(<#= vectorType #> xMin, <#= vectorType #> xMax, <#= vectorType #> x)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
var t = Saturate((x - xMin) / (xMax - xMin));
var two = <#= TLane #>.Create(<#= TNumber #>.CreateTruncating(2));
var three = <#= TLane #>.Create(<#= TNumber #>.CreateTruncating(3));
return t * t * (CreateVector<#= dimension #><<#= GenericParameters #>>(three) - (CreateVector<#= dimension #><<#= GenericParameters #>>(two) * t));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> Select<<#= GenericParameters #>>(<#= TLane #> condition, in <#= vectorType #> a, in <#= vectorType #> b)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
return new <#= vectorType #>
{
x = <#= TLane #>.Select(condition, b.x, a.x),
y = <#= TLane #>.Select(condition, b.y, a.y),
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> Select<<#= GenericParameters #>>(<#= vectorType #> condition, in <#= vectorType #> a, in <#= vectorType #> b)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
return new <#= vectorType #>
{
x = <#= TLane #>.Select(condition.x, b.x, a.x),
y = <#= TLane #>.Select(condition.y, b.y, a.y),
};
}
# endregion
<# } #>
# region Vector3 Specific
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3<<#= GenericParameters #>> Cross<<#= GenericParameters #>>(in Vector3<<#= GenericParameters #>> a, in Vector3<<#= GenericParameters #>> b)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
return new Vector3<<#= GenericParameters #>>
{
x = a.y * b.z - a.z * b.y,
y = a.z * b.x - a.x * b.z,
z = a.x * b.y - a.y * b.x,
};
}
# endregion
}
<#+
public string ForEachDimension(int dimension, Func<int, string> action, string spliter = ", ")
{
return string.Join(spliter, Enumerable.Range(0, dimension).Select(i => action(i)));
}
#>