- ISPMDLane: add MaskGather, MaskStore, Scatter, MaskScatter; update MaskLoad/Gather signatures for hardware parity - WideLane/ScalarLane: implement new methods with HW/fallback logic - MathV: gather/mask-gather now delegate to lane methods - Vector2/3/4: add CompressStore, Scatter, MaskScatter - SPMD jobs/tests/README: migrate to new APIs for correctness - Use Unsafe.BitCast instead of Unsafe.As/AsRef - Add SPMDUtility for gather index extraction - Job system: add ICustomJob<TSelf>, ScheduleCustom overload - FreeList concurrency obsolete; always thread-safe - NuGet: include LICENSE/README, set license/readme in .csproj - Docs: update SPMD usage, clarify safety notes - Minor: doc fixes, CompressStore test improvements
543 lines
21 KiB
Plaintext
543 lines
21 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.Diagnostics.CodeAnalysis;
|
|
using System.Numerics;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Runtime.Intrinsics;
|
|
using System.Runtime.Intrinsics.X86;
|
|
|
|
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 #>
|
|
{
|
|
return new <#= vectorType #>
|
|
{
|
|
<# for (int i = 0; i < dimension; i++) { #>
|
|
<#= components[i] #> = <#= TLane #>.Load(pSrc + <#= 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 #> MaskLoadVector<#= dimension #><<#= GenericParameters #>>(<#= TNumber #>* pSrc, <#= TLane #> mask)
|
|
<#= TLaneRestrictions #>
|
|
<#= TNumberRestrictions #>
|
|
{
|
|
return new <#= vectorType #>
|
|
{
|
|
<# for (int i = 0; i < dimension; i++) { #>
|
|
<#= components[i] #> = <#= TLane #>.MaskLoad(pSrc + <#= i #>, mask),
|
|
<# } #>
|
|
};
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static <#= vectorType #> MaskLoadVector<#= dimension #><<#= GenericParameters #>>(ref <#= TNumber #> src, <#= TLane #> mask)
|
|
<#= TLaneRestrictions #>
|
|
<#= TNumberRestrictions #>
|
|
{
|
|
return MaskLoadVector<#= dimension #><<#= GenericParameters #>>((<#= TNumber #>*)Unsafe.AsPointer(ref src), mask);
|
|
}
|
|
|
|
[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, [ConstantExpected(Min = (byte)(1), Max = (byte)(8))] byte scale)
|
|
<#= TLaneRestrictions #>
|
|
<#= TNumberRestrictions #>
|
|
{
|
|
return new Vector<#= dimension #><TLane, TNumber>
|
|
{
|
|
<# for (int i = 0; i < dimension; i++) { #>
|
|
<#= components[i] #> = <#= TLane #>.Gather(pData + <#= i #>, indices, scale),
|
|
<# } #>
|
|
};
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static <#= vectorType #> GatherVector<#= dimension #><<#= GenericParameters #>>(<#= TNumber #>* pData, int* pIndices, [ConstantExpected(Min = (byte)(1), Max = (byte)(8))] byte scale)
|
|
<#= TLaneRestrictions #>
|
|
<#= TNumberRestrictions #>
|
|
{
|
|
return new Vector<#= dimension #><TLane, TNumber>
|
|
{
|
|
<# for (int i = 0; i < dimension; i++) { #>
|
|
<#= components[i] #> = <#= TLane #>.Gather(pData + <#= i #>, pIndices, scale),
|
|
<# } #>
|
|
};
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static <#= vectorType #> GatherVector<#= dimension #><<#= GenericParameters #>>(ref <#= TNumber #> baseAddress, <#= TLane #> indices, [ConstantExpected(Min = (byte)(1), Max = (byte)(8))] byte scale)
|
|
<#= TLaneRestrictions #>
|
|
<#= TNumberRestrictions #>
|
|
{
|
|
return GatherVector<#= dimension #><<#= GenericParameters #>>((<#= TNumber #>*)Unsafe.AsPointer(ref baseAddress), indices, scale);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static <#= vectorType #> GatherVector<#= dimension #><<#= GenericParameters #>>(ref <#= TNumber #> baseAddress, ref int baseIndex, [ConstantExpected(Min = (byte)(1), Max = (byte)(8))] byte scale)
|
|
<#= TLaneRestrictions #>
|
|
<#= TNumberRestrictions #>
|
|
{
|
|
return GatherVector<#= dimension #><<#= GenericParameters #>>((<#= TNumber #>*)Unsafe.AsPointer(ref baseAddress), (int*)Unsafe.AsPointer(ref baseIndex), scale);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static <#= vectorType #> MaskGatherVector<#= dimension #><TLane, TNumber>(<#= TNumber #>* pData, <#= TLane #> indices, <#= TLane #> mask, [ConstantExpected(Min = (byte)(1), Max = (byte)(8))] byte scale)
|
|
where TLane : unmanaged, ISPMDLane<TLane, TNumber>
|
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
|
{
|
|
return new Vector<#= dimension #><TLane, TNumber>
|
|
{
|
|
<# for (int i = 0; i < dimension; i++) { #>
|
|
<#= components[i] #> = <#= TLane #>.MaskGather(pData + <#= i #>, indices, mask, scale),
|
|
<# } #>
|
|
};
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static <#= vectorType #> MaskGatherVector<#= dimension #><TLane, TNumber>(<#= TNumber #>* pData, int* pIndices, <#= TLane #> mask, [ConstantExpected(Min = (byte)(1), Max = (byte)(8))] byte scale)
|
|
where TLane : unmanaged, ISPMDLane<TLane, TNumber>
|
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
|
{
|
|
return new Vector<#= dimension #><TLane, TNumber>
|
|
{
|
|
<# for (int i = 0; i < dimension; i++) { #>
|
|
<#= components[i] #> = <#= TLane #>.MaskGather(pData + <#= i #>, pIndices, mask, scale),
|
|
<# } #>
|
|
};
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static <#= vectorType #> MaskGatherVector<#= dimension #><<#= GenericParameters #>>(ref <#= TNumber #> baseAddress, <#= TLane #> indices, <#= TLane #> mask, [ConstantExpected(Min = (byte)(1), Max = (byte)(8))] byte scale)
|
|
<#= TLaneRestrictions #>
|
|
<#= TNumberRestrictions #>
|
|
{
|
|
return MaskGatherVector<#= dimension #><<#= GenericParameters #>>((<#= TNumber #>*)Unsafe.AsPointer(ref baseAddress), indices, mask, scale);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static <#= vectorType #> MaskGatherVector<#= dimension #><<#= GenericParameters #>>(ref <#= TNumber #> baseAddress, ref int baseIndex, <#= TLane #> mask, [ConstantExpected(Min = (byte)(1), Max = (byte)(8))] byte scale)
|
|
<#= TLaneRestrictions #>
|
|
<#= TNumberRestrictions #>
|
|
{
|
|
return MaskGatherVector<#= dimension #><<#= GenericParameters #>>((<#= TNumber #>*)Unsafe.AsPointer(ref baseAddress), (int*)Unsafe.AsPointer(ref baseIndex), mask, scale);
|
|
}
|
|
|
|
|
|
// 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 #> 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 #> isTrue, in <#= vectorType #> isFalse)
|
|
<#= TLaneRestrictions #>
|
|
<#= TNumberRestrictions #>
|
|
{
|
|
return new <#= vectorType #>
|
|
{
|
|
<# for (int i = 0; i < dimension; i++) { #>
|
|
<#= components[i] #> = <#= TLane #>.Select(condition, isTrue.<#= components[i] #>, isFalse.<#= components[i] #>),
|
|
<# } #>
|
|
};
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static <#= vectorType #> Select<<#= GenericParameters #>>(<#= vectorType #> condition, in <#= vectorType #> isTrue, in <#= vectorType #> isFalse)
|
|
<#= TLaneRestrictions #>
|
|
<#= TNumberRestrictions #>
|
|
{
|
|
return new <#= vectorType #>
|
|
{
|
|
<# for (int i = 0; i < dimension; i++) { #>
|
|
<#= components[i] #> = <#= TLane #>.Select(condition.<#= components[i] #>, isTrue.<#= components[i] #>, isFalse.<#= 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<int, string> action, string spliter = ", ")
|
|
{
|
|
return string.Join(spliter, Enumerable.Range(0, dimension).Select(i => action(i)));
|
|
}
|
|
#> |