<#@ 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" #> /// /// 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. /// 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} : unmanaged, ISPMDLane<{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 #> { <# for (int i = 0; i < dimension; i++) { #> Unsafe.SkipInit(out TLane <#= components[i] #>); var p<#= components[i] #> = (<#= TNumber #>*)&<#= components[i] #>; <# } #> for (var i = 0; i < TLane.LaneWidth; i++) { <# for (int i = 0; i < dimension; i++) { #> p<#= components[i] #>[i] = pSrc[i * <#= dimension #> + <#= i #>]; <# } #> } return new <#= vectorType #> { <# for (int i = 0; i < dimension; i++) { #> <#= components[i] #> = <#= 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] #>), <# } #> }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static <#= vectorType #> GatherVector<#= dimension #><<#= GenericParameters #>>(<#= TNumber #>* pData, <#= TLane #> indices, int scale) <#= TLaneRestrictions #> <#= TNumberRestrictions #> { <# for (int i = 0; i < dimension; i++) { #> Unsafe.SkipInit(out TLane <#= components[i] #>); var p<#= components[i] #> = (<#= TNumber #>*)&<#= components[i] #>; <# } #> for (var i = 0; i < TLane.LaneWidth; i++) { var scalarIdx = int.CreateTruncating(indices[i]); <# for (int i = 0; i < dimension; i++) { #> p<#= components[i] #>[i] = pData[scalarIdx + <#= i #> * scale]; <# } #> } return new Vector<#= dimension #> { <# for (int i = 0; i < dimension; i++) { #> <#= components[i] #> = <#= components[i] #>, <# } #> }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static <#= vectorType #> GatherVector<#= dimension #><<#= GenericParameters #>>(<#= TNumber #>* pData, int* pIndices, int scale) <#= TLaneRestrictions #> <#= TNumberRestrictions #> { <# for (int i = 0; i < dimension; i++) { #> Unsafe.SkipInit(out TLane <#= components[i] #>); var p<#= components[i] #> = (<#= TNumber #>*)&<#= components[i] #>; <# } #> for (var i = 0; i < TLane.LaneWidth; i++) { var scalerIdx = pIndices[i]; <# for (int i = 0; i < dimension; i++) { #> p<#= components[i] #>[i] = pData[scalerIdx + <#= i #> * scale]; <# } #> } return new Vector<#= dimension #> { <# for (int i = 0; i < dimension; i++) { #> <#= components[i] #> = <#= components[i] #>, <# } #> }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static <#= vectorType #> GatherVector<#= dimension #><<#= GenericParameters #>>(ref <#= TNumber #> baseAddress, <#= TLane #> indices, int scale) <#= TLaneRestrictions #> <#= TNumberRestrictions #> { <# for (int i = 0; i < dimension; i++) { #> Unsafe.SkipInit(out TLane <#= components[i] #>); var p<#= components[i] #> = (<#= TNumber #>*)&<#= components[i] #>; <# } #> for (var i = 0; i < TLane.LaneWidth; i++) { var scalarIdx = int.CreateTruncating(indices[i]); <# for (int i = 0; i < dimension; i++) { #> p<#= components[i] #>[i] = Unsafe.Add(ref baseAddress, scalarIdx + <#= i #> * scale); <# } #> } return new Vector<#= dimension #> { <# for (int i = 0; i < dimension; i++) { #> <#= components[i] #> = <#= components[i] #>, <# } #> }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static <#= vectorType #> GatherVector<#= dimension #><<#= GenericParameters #>>(ref <#= TNumber #> baseAddress, ref int baseIndex, int scale) <#= TLaneRestrictions #> <#= TNumberRestrictions #> { <# for (int i = 0; i < dimension; i++) { #> Unsafe.SkipInit(out TLane <#= components[i] #>); var p<#= components[i] #> = (<#= TNumber #>*)&<#= components[i] #>; <# } #> for (var i = 0; i < TLane.LaneWidth; i++) { var scalarIdx = Unsafe.Add(ref baseIndex, i); <# for (int i = 0; i < dimension; i++) { #> p<#= components[i] #>[i] = Unsafe.Add(ref baseAddress, scalarIdx + <#= i #> * scale); <# } #> } return new Vector<#= dimension #> { <# for (int i = 0; i < dimension; i++) { #> <#= components[i] #> = <#= components[i] #>, <# } #> }; } // Math Functions [MethodImpl(MethodImplOptions.AggressiveInlining)] public static <#= vectorType #> Abs<<#= GenericParameters #>>(in Vector<#= dimension #>> 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 #> Sin<<#= GenericParameters #>>(in <#= vectorType #> vector) <#= TLaneRestrictions #> <#= TNumberRestrictions #> { return new <#= vectorType #> { <# for (int i = 0; i < dimension; i++) { #> <#= components[i] #> = <#= TLane #>.Sin(vector.<#= components[i] #>), <# } #> }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static <#= vectorType #> Cos<<#= GenericParameters #>>(in <#= vectorType #> vector) <#= TLaneRestrictions #> <#= TNumberRestrictions #> { return new <#= vectorType #> { <# for (int i = 0; i < dimension; i++) { #> <#= components[i] #> = <#= TLane #>.Cos(vector.<#= components[i] #>), <# } #> }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void SinCos<<#= GenericParameters #>>(in <#= vectorType #> vector, out <#= vectorType #> sin, out <#= vectorType #> cos) <#= TLaneRestrictions #> <#= TNumberRestrictions #> { <# for (int i = 0; i < dimension; i++) { #> <#= TLane #>.SinCos(vector.<#= components[i] #>, out sin.<#= components[i] #>, out cos.<#= 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 #> Tan<<#= GenericParameters #>>(in <#= vectorType #> vector) <#= TLaneRestrictions #> <#= TNumberRestrictions #> { return new <#= vectorType #> { <# for (int i = 0; i < dimension; i++) { #> <#= components[i] #> = <#= TLane #>.Tan(vector.<#= components[i] #>), <# } #> }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static <#= vectorType #> Asin<<#= GenericParameters #>>(in <#= vectorType #> vector) <#= TLaneRestrictions #> <#= TNumberRestrictions #> { return new <#= vectorType #> { <# for (int i = 0; i < dimension; i++) { #> <#= components[i] #> = <#= TLane #>.Asin(vector.<#= components[i] #>), <# } #> }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static <#= vectorType #> Acos<<#= GenericParameters #>>(in <#= vectorType #> vector) <#= TLaneRestrictions #> <#= TNumberRestrictions #> { return new <#= vectorType #> { <# for (int i = 0; i < dimension; i++) { #> <#= components[i] #> = <#= TLane #>.Acos(vector.<#= components[i] #>), <# } #> }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static <#= vectorType #> Atan<<#= GenericParameters #>>(in <#= vectorType #> vector) <#= TLaneRestrictions #> <#= TNumberRestrictions #> { return new <#= vectorType #> { <# for (int i = 0; i < dimension; i++) { #> <#= components[i] #> = <#= TLane #>.Atan(vector.<#= components[i] #>), <# } #> }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static <#= vectorType #> Atan2<<#= GenericParameters #>>(in <#= vectorType #> x, in <#= vectorType #> y) <#= TLaneRestrictions #> <#= TNumberRestrictions #> { return new <#= vectorType #> { <# for (int i = 0; i < dimension; i++) { #> <#= components[i] #> = <#= TLane #>.Atan2(x.<#= components[i] #>, y.<#= 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 #> { <# for (int i = 0; i < dimension; i++) { #> <#= components[i] #> = <#= TLane #>.Select(condition, b.<#= components[i] #>, a.<#= components[i] #>), <# } #> }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static <#= vectorType #> Select<<#= GenericParameters #>>(<#= vectorType #> condition, in <#= vectorType #> a, in <#= vectorType #> b) <#= TLaneRestrictions #> <#= TNumberRestrictions #> { return new <#= vectorType #> { <# for (int i = 0; i < dimension; i++) { #> <#= components[i] #> = <#= TLane #>.Select(condition.<#= components[i] #>, b.<#= components[i] #>, a.<#= components[i] #>), <# } #> }; } # 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 action, string spliter = ", ") { return string.Join(spliter, Enumerable.Range(0, dimension).Select(i => action(i))); } #>