- Rename ISPMD interfaces to ISPMDLane for clarity - Add gather and mask load methods to ISPMDLane, implement for ScalarLane and WideLane - Add GetUnsafePtr() for direct pointer access - Update MathV and vector types to use new interface and gather methods - Update SPMD job interfaces and implementations to ISPMDLane - Improve hash codes, range checks, and safety checks in vector types - Update codegen templates for new interface/methods - Refactor SPMD jobs to use gather methods for efficient vectorized access
59 lines
2.4 KiB
Plaintext
59 lines
2.4 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" #>
|
|
using System.Numerics;
|
|
using System.Runtime.CompilerServices;
|
|
|
|
namespace Misaki.HighPerformance.Mathematics.SPMD;
|
|
<#
|
|
var conversions = new CastRoute[]
|
|
{
|
|
new CastRoute { From = "float", To = "int", Method = "Vector.ConvertToInt32" },
|
|
new CastRoute { From = "float", To = "uint", Method = "Vector.ConvertToUInt32" },
|
|
new CastRoute { From = "double", To = "long", Method = "Vector.ConvertToInt64" },
|
|
new CastRoute { From = "double", To = "ulong", Method = "Vector.ConvertToUInt64" },
|
|
new CastRoute { From = "int", To = "float", Method = "Vector.ConvertToSingle" },
|
|
new CastRoute { From = "uint", To = "float", Method = "Vector.ConvertToSingle" },
|
|
new CastRoute { From = "long", To = "double", Method = "Vector.ConvertToDouble" },
|
|
new CastRoute { From = "ulong", To = "double", Method = "Vector.ConvertToDouble" },
|
|
};
|
|
#>
|
|
|
|
public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNumber>, TNumber>
|
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
|
{
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public TOther Cast<TOther, TOtherNumber>()
|
|
where TOther : ISPMDLane<TOther, TOtherNumber>
|
|
where TOtherNumber : unmanaged, INumber<TOtherNumber>, IBinaryNumber<TOtherNumber>, IMinMaxValue<TOtherNumber>, IBitwiseOperators<TOtherNumber, TOtherNumber, TOtherNumber>
|
|
{
|
|
<# foreach (var c in conversions) { #>
|
|
if (typeof(TNumber) == typeof(<#= c.From #>) && typeof(TOtherNumber) == typeof(<#= c.To #>))
|
|
{
|
|
ref var vFrom = ref Unsafe.As<Vector<TNumber>, Vector<<#= c.From #>>>(ref Unsafe.AsRef(in value));
|
|
var vTo = <#= c.Method #>(vFrom);
|
|
return Unsafe.As<Vector<<#= c.To #>>, TOther>(ref vTo);
|
|
}
|
|
|
|
<# } #>
|
|
var casted = stackalloc TOtherNumber[LaneWidth];
|
|
for (var i = 0; (i < LaneWidth) && (i < TOther.LaneWidth); i++)
|
|
{
|
|
casted[i] = TOtherNumber.CreateTruncating(value[i]);
|
|
}
|
|
|
|
return TOther.Load(casted);
|
|
}
|
|
}
|
|
|
|
<#+
|
|
public struct CastRoute
|
|
{
|
|
public string From;
|
|
public string To;
|
|
public string Method;
|
|
}
|
|
#> |