Refactor SPMD lane abstraction and add gather support

- 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
This commit is contained in:
2026-04-25 11:50:51 +09:00
parent cfd01eb9b6
commit 9f7507ba71
18 changed files with 772 additions and 300 deletions

View File

@@ -5,7 +5,7 @@ namespace Misaki.HighPerformance.Mathematics.SPMD;
/// <summary>
/// Common marker interface for SPMD lane types.
/// </summary>
public interface ISPMD
public interface ISPMDLane
{
/// <summary>
/// Gets the number of lanes (vector width) for the SPMD implementation.
@@ -29,8 +29,8 @@ public interface ISPMD
/// </summary>
/// <typeparam name="TSelf">The concrete SPMD lane type implementing this interface.</typeparam>
/// <typeparam name="TNumber">The underlying numeric element type.</typeparam>
public interface ISPMD<TSelf, TNumber> : ISPMD, IEquatable<TSelf>
where TSelf : ISPMD<TSelf, TNumber>
public unsafe interface ISPMDLane<TSelf, TNumber> : ISPMDLane, IEquatable<TSelf>
where TSelf : ISPMDLane<TSelf, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
/// <summary>
@@ -116,7 +116,15 @@ public interface ISPMD<TSelf, TNumber> : ISPMD, IEquatable<TSelf>
/// <remarks>
/// Unsafe pointer overloads are provided for scenarios where sequential lane data is already contiguous in memory.
/// </remarks>
static abstract unsafe TSelf Load(TNumber* pValue);
static abstract TSelf Load(TNumber* pValue);
static abstract TSelf MaskLoad(TSelf mask, ref TNumber value);
static abstract TSelf MaskLoad(TSelf mask, TNumber* pValue);
static abstract TSelf Gather(TNumber* pData, TSelf indices, int scale);
static abstract TSelf Gather(TNumber* pData, int* pIndices, int scale);
static abstract TSelf Gather(ref TNumber baseAddress, TSelf indices, int scale);
static abstract TSelf Gather(ref TNumber baseAddress, ref int baseIndex, int scale);
/// <summary>
/// Stores the lane value to the specified reference.
@@ -127,7 +135,7 @@ public interface ISPMD<TSelf, TNumber> : ISPMD, IEquatable<TSelf>
/// Stores the lane value to the specified pointer.
/// </summary>
/// <param name="pDestination">The pointer to store to.</param>
unsafe void Store(TNumber* pDestination);
void Store(TNumber* pDestination);
/// <summary>
/// Compresses the data specified by the given mask and stores the compressed result in the provided destination
/// variable.
@@ -149,7 +157,7 @@ public interface ISPMD<TSelf, TNumber> : ISPMD, IEquatable<TSelf>
/// <remarks>
/// Implementations may use hardware-specific shuffle tables to reorder the selected lanes before storing, falling back to a scalar loop otherwise.
/// </remarks>
unsafe int CompressStore(TSelf mask, TNumber* pDestination);
int CompressStore(TSelf mask, TNumber* pDestination);
/// <summary>
/// Converts the lane value to a vector.
@@ -157,6 +165,8 @@ public interface ISPMD<TSelf, TNumber> : ISPMD, IEquatable<TSelf>
/// <returns>The backing vector representation.</returns>
Vector<TNumber> AsVector();
TNumber* GetUnsafePtr();
/// <summary>
/// Casts the lane value to another SPMD lane type with a different underlying numeric type.
/// </summary>
@@ -164,7 +174,7 @@ public interface ISPMD<TSelf, TNumber> : ISPMD, IEquatable<TSelf>
/// <typeparam name="TOtherNumber">The underlying numeric type of the other SPMD lane.</typeparam>
/// <returns>The casted lane value.</returns>
TOther Cast<TOther, TOtherNumber>()
where TOther : ISPMD<TOther, TOtherNumber>
where TOther : ISPMDLane<TOther, TOtherNumber>
where TOtherNumber : unmanaged, INumber<TOtherNumber>, IBinaryNumber<TOtherNumber>, IMinMaxValue<TOtherNumber>, IBitwiseOperators<TOtherNumber, TOtherNumber, TOtherNumber>;
/// <summary>
@@ -174,7 +184,7 @@ public interface ISPMD<TSelf, TNumber> : ISPMD, IEquatable<TSelf>
/// <typeparam name="TOtherNumber">The underlying numeric type of the other SPMD lane.</typeparam>
/// <returns>The bit-cast lane value.</returns>
TOther BitCast<TOther, TOtherNumber>()
where TOther : ISPMD<TOther, TOtherNumber>
where TOther : ISPMDLane<TOther, TOtherNumber>
where TOtherNumber : unmanaged, INumber<TOtherNumber>, IBinaryNumber<TOtherNumber>, IMinMaxValue<TOtherNumber>, IBitwiseOperators<TOtherNumber, TOtherNumber, TOtherNumber>;
/// <summary>

View File

@@ -21,8 +21,8 @@ This package is intended for code that wants to express vectorized work in a way
## Main types
- `ISPMD`
- `ISPMD<TSelf, TNumber>`
- `ISPMDLane`
- `ISPMDLane<TSelf, TNumber>`
- `ScalerLane`
- `WideLane`
- `IJobSPMD`

View File

@@ -5,7 +5,7 @@ using System.Runtime.InteropServices;
namespace Misaki.HighPerformance.Mathematics.SPMD;
[StructLayout(LayoutKind.Sequential)]
public readonly unsafe struct ScalarLane<TNumber> : ISPMD<ScalarLane<TNumber>, TNumber>
public readonly unsafe struct ScalarLane<TNumber> : ISPMDLane<ScalarLane<TNumber>, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
public readonly TNumber value;
@@ -19,25 +19,25 @@ public readonly unsafe struct ScalarLane<TNumber> : ISPMD<ScalarLane<TNumber>, T
public static ScalarLane<TNumber> Zero
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => new(TNumber.Zero);
get => new ScalarLane<TNumber>(TNumber.Zero);
}
public static ScalarLane<TNumber> One
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => new(TNumber.One);
get => new ScalarLane<TNumber>(TNumber.One);
}
public static ScalarLane<TNumber> MinValue
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => new(TNumber.MinValue);
get => new ScalarLane<TNumber>(TNumber.MinValue);
}
public static ScalarLane<TNumber> MaxValue
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => new(TNumber.MaxValue);
get => new ScalarLane<TNumber>(TNumber.MaxValue);
}
public readonly TNumber this[int index]
@@ -54,39 +54,76 @@ public readonly unsafe struct ScalarLane<TNumber> : ISPMD<ScalarLane<TNumber>, T
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> Create(TNumber value)
{
return new(value);
return new ScalarLane<TNumber>(value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> Create(params ReadOnlySpan<TNumber> values)
{
return new(values[0]);
return new ScalarLane<TNumber>(values[0]);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> Create(Vector<TNumber> value)
{
return new(value[0]);
return new ScalarLane<TNumber>(value[0]);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> Sequence(TNumber start, TNumber step)
{
return new(start);
return new ScalarLane<TNumber>(start);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> Load(ref TNumber value)
{
return new(value);
return new ScalarLane<TNumber>(value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> Load(TNumber* pValue)
{
return new(*pValue);
return new ScalarLane<TNumber>(*pValue);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> MaskLoad(ScalarLane<TNumber> mask, ref TNumber value)
{
return new ScalarLane<TNumber>(mask.value != TNumber.Zero ? value : TNumber.Zero);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> MaskLoad(ScalarLane<TNumber> mask, TNumber* pValue)
{
return new ScalarLane<TNumber>(mask.value != TNumber.Zero ? *pValue : TNumber.Zero);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> Gather(TNumber* pData, ScalarLane<TNumber> indices, int scale)
{
return new ScalarLane<TNumber>(pData[int.CreateTruncating(indices.value) * scale / sizeof(TNumber)]);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> Gather(TNumber* pData, int* pIndices, int scale)
{
return new ScalarLane<TNumber>(pData[pIndices[0] * scale / sizeof(TNumber)]);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> Gather(ref TNumber baseAddress, ScalarLane<TNumber> indices, int scale)
{
return new ScalarLane<TNumber>(Unsafe.Add(ref baseAddress, int.CreateTruncating(indices.value) * scale / sizeof(TNumber)));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> Gather(ref TNumber baseAddress, ref int baseIndex, int scale)
{
return new ScalarLane<TNumber>(Unsafe.Add(ref baseAddress, int.CreateTruncating(baseIndex) * scale / sizeof(TNumber)));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly void Store(ref TNumber destination)
{
@@ -123,9 +160,15 @@ public readonly unsafe struct ScalarLane<TNumber> : ISPMD<ScalarLane<TNumber>, T
return Vector.Create(value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly TNumber* GetUnsafePtr()
{
return (TNumber*)Unsafe.AsPointer(ref Unsafe.AsRef(in value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TOther Cast<TOther, TOtherNumber>()
where TOther : ISPMD<TOther, TOtherNumber>
where TOther : ISPMDLane<TOther, TOtherNumber>
where TOtherNumber : unmanaged, INumber<TOtherNumber>, IBinaryNumber<TOtherNumber>, IMinMaxValue<TOtherNumber>, IBitwiseOperators<TOtherNumber, TOtherNumber, TOtherNumber>
{
return TOther.Create(TOtherNumber.CreateChecked(value));
@@ -133,7 +176,7 @@ public readonly unsafe struct ScalarLane<TNumber> : ISPMD<ScalarLane<TNumber>, T
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TOther BitCast<TOther, TOtherNumber>()
where TOther : ISPMD<TOther, TOtherNumber>
where TOther : ISPMDLane<TOther, TOtherNumber>
where TOtherNumber : unmanaged, INumber<TOtherNumber>, IBinaryNumber<TOtherNumber>, IMinMaxValue<TOtherNumber>, IBitwiseOperators<TOtherNumber, TOtherNumber, TOtherNumber>
{
return Unsafe.BitCast<ScalarLane<TNumber>, TOther>(this);
@@ -142,61 +185,61 @@ public readonly unsafe struct ScalarLane<TNumber> : ISPMD<ScalarLane<TNumber>, T
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> operator +(ScalarLane<TNumber> a, ScalarLane<TNumber> b)
{
return new(a.value + b.value);
return new ScalarLane<TNumber>(a.value + b.value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> operator -(ScalarLane<TNumber> a, ScalarLane<TNumber> b)
{
return new(a.value - b.value);
return new ScalarLane<TNumber>(a.value - b.value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> operator *(ScalarLane<TNumber> a, ScalarLane<TNumber> b)
{
return new(a.value * b.value);
return new ScalarLane<TNumber>(a.value * b.value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> operator /(ScalarLane<TNumber> a, ScalarLane<TNumber> b)
{
return new(a.value / b.value);
return new ScalarLane<TNumber>(a.value / b.value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> operator %(ScalarLane<TNumber> a, ScalarLane<TNumber> b)
{
return new(a.value % b.value);
return new ScalarLane<TNumber>(a.value % b.value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> operator -(ScalarLane<TNumber> a)
{
return new(-a.value);
return new ScalarLane<TNumber>(-a.value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> operator &(ScalarLane<TNumber> a, ScalarLane<TNumber> b)
{
return new(a.value & b.value);
return new ScalarLane<TNumber>(a.value & b.value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> operator |(ScalarLane<TNumber> a, ScalarLane<TNumber> b)
{
return new(a.value | b.value);
return new ScalarLane<TNumber>(a.value | b.value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> operator ^(ScalarLane<TNumber> a, ScalarLane<TNumber> b)
{
return new(a.value ^ b.value);
return new ScalarLane<TNumber>(a.value ^ b.value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> operator ~(ScalarLane<TNumber> a)
{
return new(~a.value);
return new ScalarLane<TNumber>(~a.value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -240,7 +283,7 @@ public readonly unsafe struct ScalarLane<TNumber> : ISPMD<ScalarLane<TNumber>, T
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator ScalarLane<TNumber>(TNumber value)
{
return new(value);
return new ScalarLane<TNumber>(value);
}
@@ -248,7 +291,7 @@ public readonly unsafe struct ScalarLane<TNumber> : ISPMD<ScalarLane<TNumber>, T
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> Abs(ScalarLane<TNumber> value)
{
return new(TNumber.Abs(value.value));
return new ScalarLane<TNumber>(TNumber.Abs(value.value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -276,7 +319,7 @@ public readonly unsafe struct ScalarLane<TNumber> : ISPMD<ScalarLane<TNumber>, T
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> Frac(ScalarLane<TNumber> value)
{
return new(value.value - TNumber.CreateTruncating(value.value));
return new ScalarLane<TNumber>(value.value - TNumber.CreateTruncating(value.value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -301,37 +344,37 @@ public readonly unsafe struct ScalarLane<TNumber> : ISPMD<ScalarLane<TNumber>, T
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> Lerp(ScalarLane<TNumber> a, ScalarLane<TNumber> b, ScalarLane<TNumber> t)
{
return new(a.value + (b.value - a.value) * t.value);
return new ScalarLane<TNumber>(a.value + (b.value - a.value) * t.value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> MultipleAdd(ScalarLane<TNumber> a, ScalarLane<TNumber> b, ScalarLane<TNumber> c)
{
return new(TNumber.MultiplyAddEstimate(a.value, b.value, c.value));
return new ScalarLane<TNumber>(TNumber.MultiplyAddEstimate(a.value, b.value, c.value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> Min(ScalarLane<TNumber> a, ScalarLane<TNumber> b)
{
return new(TNumber.Min(a.value, b.value));
return new ScalarLane<TNumber>(TNumber.Min(a.value, b.value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> Max(ScalarLane<TNumber> a, ScalarLane<TNumber> b)
{
return new(TNumber.Max(a.value, b.value));
return new ScalarLane<TNumber>(TNumber.Max(a.value, b.value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> Clamp(ScalarLane<TNumber> value, ScalarLane<TNumber> min, ScalarLane<TNumber> max)
{
return new(TNumber.Clamp(value.value, min.value, max.value));
return new ScalarLane<TNumber>(TNumber.Clamp(value.value, min.value, max.value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> Saturate(ScalarLane<TNumber> value)
{
return Clamp(value, new(TNumber.Zero), new(TNumber.One));
return Clamp(value, new ScalarLane<TNumber>(TNumber.Zero), new ScalarLane<TNumber>(TNumber.One));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -638,19 +681,19 @@ public readonly unsafe struct ScalarLane<TNumber> : ISPMD<ScalarLane<TNumber>, T
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> Sign(ScalarLane<TNumber> value)
{
return new((value.value > TNumber.Zero) ? TNumber.One : (value.value < TNumber.Zero) ? ~TNumber.Zero : TNumber.Zero);
return new ScalarLane<TNumber>((value.value > TNumber.Zero) ? TNumber.One : (value.value < TNumber.Zero) ? ~TNumber.Zero : TNumber.Zero);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> CopySign(ScalarLane<TNumber> magnitude, ScalarLane<TNumber> sign)
{
return new(TNumber.CopySign(magnitude.value, sign.value));
return new ScalarLane<TNumber>(TNumber.CopySign(magnitude.value, sign.value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> Rcp(ScalarLane<TNumber> value)
{
return new(TNumber.One / value.value);
return new ScalarLane<TNumber>(TNumber.One / value.value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -662,37 +705,37 @@ public readonly unsafe struct ScalarLane<TNumber> : ISPMD<ScalarLane<TNumber>, T
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> Select(ScalarLane<TNumber> conditionMask, ScalarLane<TNumber> ifTrue, ScalarLane<TNumber> ifFalse)
{
return new(conditionMask.value != TNumber.Zero ? ifTrue.value : ifFalse.value);
return new ScalarLane<TNumber>(conditionMask.value != TNumber.Zero ? ifTrue.value : ifFalse.value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> GreaterThan(ScalarLane<TNumber> a, ScalarLane<TNumber> b)
{
return new(a.value > b.value ? ~TNumber.Zero : TNumber.Zero);
return new ScalarLane<TNumber>(a.value > b.value ? ~TNumber.Zero : TNumber.Zero);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> GreaterThanOrEqual(ScalarLane<TNumber> a, ScalarLane<TNumber> b)
{
return new(a.value >= b.value ? ~TNumber.Zero : TNumber.Zero);
return new ScalarLane<TNumber>(a.value >= b.value ? ~TNumber.Zero : TNumber.Zero);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> LessThan(ScalarLane<TNumber> a, ScalarLane<TNumber> b)
{
return new(a.value < b.value ? ~TNumber.Zero : TNumber.Zero);
return new ScalarLane<TNumber>(a.value < b.value ? ~TNumber.Zero : TNumber.Zero);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> LessThanOrEqual(ScalarLane<TNumber> a, ScalarLane<TNumber> b)
{
return new(a.value <= b.value ? ~TNumber.Zero : TNumber.Zero);
return new ScalarLane<TNumber>(a.value <= b.value ? ~TNumber.Zero : TNumber.Zero);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ScalarLane<TNumber> Equal(ScalarLane<TNumber> a, ScalarLane<TNumber> b)
{
return new(a.value == b.value ? ~TNumber.Zero : TNumber.Zero);
return new ScalarLane<TNumber>(a.value == b.value ? ~TNumber.Zero : TNumber.Zero);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -14,7 +14,7 @@ public interface IJobSPMD<TNumber0>
where TNumber0 : unmanaged, INumber<TNumber0>, IBinaryNumber<TNumber0>, IMinMaxValue<TNumber0>, IBitwiseOperators<TNumber0, TNumber0, TNumber0>
{
void Execute<TLane0>(int baseIndex, ref readonly JobExecutionContext ctx)
where TLane0 : unmanaged, ISPMD<TLane0, TNumber0>;
where TLane0 : unmanaged, ISPMDLane<TLane0, TNumber0>;
}
internal struct SPMDJobWrapper<T, TNumber0> : IJobParallelFor
@@ -69,8 +69,8 @@ public interface IJobSPMD<TNumber0, TNumber1>
where TNumber1 : unmanaged, INumber<TNumber1>, IBinaryNumber<TNumber1>, IMinMaxValue<TNumber1>, IBitwiseOperators<TNumber1, TNumber1, TNumber1>
{
void Execute<TLane0, TLane1>(int baseIndex, ref readonly JobExecutionContext ctx)
where TLane0 : unmanaged, ISPMD<TLane0, TNumber0>
where TLane1 : unmanaged, ISPMD<TLane1, TNumber1>;
where TLane0 : unmanaged, ISPMDLane<TLane0, TNumber0>
where TLane1 : unmanaged, ISPMDLane<TLane1, TNumber1>;
}
internal struct SPMDJobWrapper<T, TNumber0, TNumber1> : IJobParallelFor
@@ -129,9 +129,9 @@ public interface IJobSPMD<TNumber0, TNumber1, TNumber2>
where TNumber2 : unmanaged, INumber<TNumber2>, IBinaryNumber<TNumber2>, IMinMaxValue<TNumber2>, IBitwiseOperators<TNumber2, TNumber2, TNumber2>
{
void Execute<TLane0, TLane1, TLane2>(int baseIndex, ref readonly JobExecutionContext ctx)
where TLane0 : unmanaged, ISPMD<TLane0, TNumber0>
where TLane1 : unmanaged, ISPMD<TLane1, TNumber1>
where TLane2 : unmanaged, ISPMD<TLane2, TNumber2>;
where TLane0 : unmanaged, ISPMDLane<TLane0, TNumber0>
where TLane1 : unmanaged, ISPMDLane<TLane1, TNumber1>
where TLane2 : unmanaged, ISPMDLane<TLane2, TNumber2>;
}
internal struct SPMDJobWrapper<T, TNumber0, TNumber1, TNumber2> : IJobParallelFor
@@ -194,10 +194,10 @@ public interface IJobSPMD<TNumber0, TNumber1, TNumber2, TNumber3>
where TNumber3 : unmanaged, INumber<TNumber3>, IBinaryNumber<TNumber3>, IMinMaxValue<TNumber3>, IBitwiseOperators<TNumber3, TNumber3, TNumber3>
{
void Execute<TLane0, TLane1, TLane2, TLane3>(int baseIndex, ref readonly JobExecutionContext ctx)
where TLane0 : unmanaged, ISPMD<TLane0, TNumber0>
where TLane1 : unmanaged, ISPMD<TLane1, TNumber1>
where TLane2 : unmanaged, ISPMD<TLane2, TNumber2>
where TLane3 : unmanaged, ISPMD<TLane3, TNumber3>;
where TLane0 : unmanaged, ISPMDLane<TLane0, TNumber0>
where TLane1 : unmanaged, ISPMDLane<TLane1, TNumber1>
where TLane2 : unmanaged, ISPMDLane<TLane2, TNumber2>
where TLane3 : unmanaged, ISPMDLane<TLane3, TNumber3>;
}
internal struct SPMDJobWrapper<T, TNumber0, TNumber1, TNumber2, TNumber3> : IJobParallelFor
@@ -264,11 +264,11 @@ public interface IJobSPMD<TNumber0, TNumber1, TNumber2, TNumber3, TNumber4>
where TNumber4 : unmanaged, INumber<TNumber4>, IBinaryNumber<TNumber4>, IMinMaxValue<TNumber4>, IBitwiseOperators<TNumber4, TNumber4, TNumber4>
{
void Execute<TLane0, TLane1, TLane2, TLane3, TLane4>(int baseIndex, ref readonly JobExecutionContext ctx)
where TLane0 : unmanaged, ISPMD<TLane0, TNumber0>
where TLane1 : unmanaged, ISPMD<TLane1, TNumber1>
where TLane2 : unmanaged, ISPMD<TLane2, TNumber2>
where TLane3 : unmanaged, ISPMD<TLane3, TNumber3>
where TLane4 : unmanaged, ISPMD<TLane4, TNumber4>;
where TLane0 : unmanaged, ISPMDLane<TLane0, TNumber0>
where TLane1 : unmanaged, ISPMDLane<TLane1, TNumber1>
where TLane2 : unmanaged, ISPMDLane<TLane2, TNumber2>
where TLane3 : unmanaged, ISPMDLane<TLane3, TNumber3>
where TLane4 : unmanaged, ISPMDLane<TLane4, TNumber4>;
}
internal struct SPMDJobWrapper<T, TNumber0, TNumber1, TNumber2, TNumber3, TNumber4> : IJobParallelFor
@@ -339,12 +339,12 @@ public interface IJobSPMD<TNumber0, TNumber1, TNumber2, TNumber3, TNumber4, TNum
where TNumber5 : unmanaged, INumber<TNumber5>, IBinaryNumber<TNumber5>, IMinMaxValue<TNumber5>, IBitwiseOperators<TNumber5, TNumber5, TNumber5>
{
void Execute<TLane0, TLane1, TLane2, TLane3, TLane4, TLane5>(int baseIndex, ref readonly JobExecutionContext ctx)
where TLane0 : unmanaged, ISPMD<TLane0, TNumber0>
where TLane1 : unmanaged, ISPMD<TLane1, TNumber1>
where TLane2 : unmanaged, ISPMD<TLane2, TNumber2>
where TLane3 : unmanaged, ISPMD<TLane3, TNumber3>
where TLane4 : unmanaged, ISPMD<TLane4, TNumber4>
where TLane5 : unmanaged, ISPMD<TLane5, TNumber5>;
where TLane0 : unmanaged, ISPMDLane<TLane0, TNumber0>
where TLane1 : unmanaged, ISPMDLane<TLane1, TNumber1>
where TLane2 : unmanaged, ISPMDLane<TLane2, TNumber2>
where TLane3 : unmanaged, ISPMDLane<TLane3, TNumber3>
where TLane4 : unmanaged, ISPMDLane<TLane4, TNumber4>
where TLane5 : unmanaged, ISPMDLane<TLane5, TNumber5>;
}
internal struct SPMDJobWrapper<T, TNumber0, TNumber1, TNumber2, TNumber3, TNumber4, TNumber5> : IJobParallelFor
@@ -419,13 +419,13 @@ public interface IJobSPMD<TNumber0, TNumber1, TNumber2, TNumber3, TNumber4, TNum
where TNumber6 : unmanaged, INumber<TNumber6>, IBinaryNumber<TNumber6>, IMinMaxValue<TNumber6>, IBitwiseOperators<TNumber6, TNumber6, TNumber6>
{
void Execute<TLane0, TLane1, TLane2, TLane3, TLane4, TLane5, TLane6>(int baseIndex, ref readonly JobExecutionContext ctx)
where TLane0 : unmanaged, ISPMD<TLane0, TNumber0>
where TLane1 : unmanaged, ISPMD<TLane1, TNumber1>
where TLane2 : unmanaged, ISPMD<TLane2, TNumber2>
where TLane3 : unmanaged, ISPMD<TLane3, TNumber3>
where TLane4 : unmanaged, ISPMD<TLane4, TNumber4>
where TLane5 : unmanaged, ISPMD<TLane5, TNumber5>
where TLane6 : unmanaged, ISPMD<TLane6, TNumber6>;
where TLane0 : unmanaged, ISPMDLane<TLane0, TNumber0>
where TLane1 : unmanaged, ISPMDLane<TLane1, TNumber1>
where TLane2 : unmanaged, ISPMDLane<TLane2, TNumber2>
where TLane3 : unmanaged, ISPMDLane<TLane3, TNumber3>
where TLane4 : unmanaged, ISPMDLane<TLane4, TNumber4>
where TLane5 : unmanaged, ISPMDLane<TLane5, TNumber5>
where TLane6 : unmanaged, ISPMDLane<TLane6, TNumber6>;
}
internal struct SPMDJobWrapper<T, TNumber0, TNumber1, TNumber2, TNumber3, TNumber4, TNumber5, TNumber6> : IJobParallelFor
@@ -504,14 +504,14 @@ public interface IJobSPMD<TNumber0, TNumber1, TNumber2, TNumber3, TNumber4, TNum
where TNumber7 : unmanaged, INumber<TNumber7>, IBinaryNumber<TNumber7>, IMinMaxValue<TNumber7>, IBitwiseOperators<TNumber7, TNumber7, TNumber7>
{
void Execute<TLane0, TLane1, TLane2, TLane3, TLane4, TLane5, TLane6, TLane7>(int baseIndex, ref readonly JobExecutionContext ctx)
where TLane0 : unmanaged, ISPMD<TLane0, TNumber0>
where TLane1 : unmanaged, ISPMD<TLane1, TNumber1>
where TLane2 : unmanaged, ISPMD<TLane2, TNumber2>
where TLane3 : unmanaged, ISPMD<TLane3, TNumber3>
where TLane4 : unmanaged, ISPMD<TLane4, TNumber4>
where TLane5 : unmanaged, ISPMD<TLane5, TNumber5>
where TLane6 : unmanaged, ISPMD<TLane6, TNumber6>
where TLane7 : unmanaged, ISPMD<TLane7, TNumber7>;
where TLane0 : unmanaged, ISPMDLane<TLane0, TNumber0>
where TLane1 : unmanaged, ISPMDLane<TLane1, TNumber1>
where TLane2 : unmanaged, ISPMDLane<TLane2, TNumber2>
where TLane3 : unmanaged, ISPMDLane<TLane3, TNumber3>
where TLane4 : unmanaged, ISPMDLane<TLane4, TNumber4>
where TLane5 : unmanaged, ISPMDLane<TLane5, TNumber5>
where TLane6 : unmanaged, ISPMDLane<TLane6, TNumber6>
where TLane7 : unmanaged, ISPMDLane<TLane7, TNumber7>;
}
internal struct SPMDJobWrapper<T, TNumber0, TNumber1, TNumber2, TNumber3, TNumber4, TNumber5, TNumber6, TNumber7> : IJobParallelFor

View File

@@ -15,7 +15,7 @@ const string TLane = "TLane";
const string TNumber = "TNumber";
const string GenericParameters = $"{TLane}, {TNumber}";
var TLaneRestrictions = $@"where {TLane} : ISPMD<{TLane}, {TNumber}>";
var TLaneRestrictions = $@"where {TLane} : ISPMDLane<{TLane}, {TNumber}>";
var TNumberRestrictions = $@"where {TNumber} : unmanaged, INumber<{TNumber}>, IBinaryNumber<{TNumber}>, IMinMaxValue<{TNumber}>, IBitwiseOperators<{TNumber}, {TNumber}, {TNumber}>";
for (var i = 0; i < 8; i++) { #>
@@ -192,7 +192,7 @@ public string GetTLaneRestrictions(int dimension, string space = " ")
var sb = new StringBuilder();
for (var i = 0; i < dimension; i++)
{
sb.Append(space + $@"where TLane{i} : unmanaged, ISPMD<TLane{i}, TNumber{i}>");
sb.Append(space + $@"where TLane{i} : unmanaged, ISPMDLane<TLane{i}, TNumber{i}>");
if (i < dimension - 1)
{
sb.AppendLine();

View File

@@ -11,13 +11,13 @@ namespace Misaki.HighPerformance.Mathematics.SPMD;
public static unsafe partial class MathV
{
#region Vector2
# region Vector2
// Creation Functions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2<TLane, TNumber> Create<TLane, TNumber>(in TLane x, in TLane y)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector2<TLane, TNumber>
@@ -29,7 +29,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2<TLane, TNumber> CreateVector2<TLane, TNumber>(in TLane value)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector2<TLane, TNumber>
@@ -41,7 +41,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2<TLane, TNumber> LoadVector2<TLane, TNumber>(TNumber* pSrc)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var width = TLane.LaneWidth;
@@ -64,7 +64,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2<TLane, TNumber> LoadVector2<TLane, TNumber>(ref TNumber src)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return LoadVector2<TLane, TNumber>((TNumber*)Unsafe.AsPointer(ref src));
@@ -72,7 +72,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2<TLane, TNumber> Load<TLane, TNumber>(TNumber* px, TNumber* py)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector2<TLane, TNumber>
@@ -84,7 +84,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2<TLane, TNumber> Load<TLane, TNumber>(ref TNumber x, ref TNumber y)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector2<TLane, TNumber>
@@ -94,11 +94,93 @@ public static unsafe partial class MathV
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2<TLane, TNumber> GatherVector2<TLane, TNumber>(TNumber* pData, TLane indices, int scale)
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var buffer = stackalloc TNumber[TLane.LaneWidth * 2];
for (var i = 0; i < TLane.LaneWidth; i++)
{
var scalarIdx = int.CreateTruncating(indices[i]);
buffer[0 * TLane.LaneWidth + i] = pData[scalarIdx + 0 * scale];
buffer[1 * TLane.LaneWidth + i] = pData[scalarIdx + 1 * scale];
}
return new Vector2<TLane, TNumber>
{
x = TLane.Load(buffer + 0 * TLane.LaneWidth),
y = TLane.Load(buffer + 1 * TLane.LaneWidth),
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2<TLane, TNumber> GatherVector2<TLane, TNumber>(TNumber* pData, int* pIndices, int scale)
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var buffer = stackalloc TNumber[TLane.LaneWidth * 2];
for (var i = 0; i < TLane.LaneWidth; i++)
{
var scalarIdx = pIndices[i];
buffer[0 * TLane.LaneWidth + i] = pData[scalarIdx + 0 * scale];
buffer[1 * TLane.LaneWidth + i] = pData[scalarIdx + 1 * scale];
}
return new Vector2<TLane, TNumber>
{
x = TLane.Load(buffer + 0 * TLane.LaneWidth),
y = TLane.Load(buffer + 1 * TLane.LaneWidth),
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2<TLane, TNumber> GatherVector2<TLane, TNumber>(ref TNumber baseAddress, TLane indices, int scale)
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var buffer = stackalloc TNumber[TLane.LaneWidth * 2];
for (var i = 0; i < TLane.LaneWidth; i++)
{
var scalarIdx = int.CreateTruncating(indices[i]);
buffer[0 * TLane.LaneWidth + i] = Unsafe.Add(ref baseAddress, scalarIdx + 0 * scale);
buffer[1 * TLane.LaneWidth + i] = Unsafe.Add(ref baseAddress, scalarIdx + 1 * scale);
}
return new Vector2<TLane, TNumber>
{
x = TLane.Load(buffer + 0 * TLane.LaneWidth),
y = TLane.Load(buffer + 1 * TLane.LaneWidth),
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2<TLane, TNumber> GatherVector2<TLane, TNumber>(ref TNumber baseAddress, ref int baseIndex, int scale)
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var buffer = stackalloc TNumber[TLane.LaneWidth * 2];
for (var i = 0; i < TLane.LaneWidth; i++)
{
var scalarIdx = Unsafe.Add(ref baseIndex, i);
buffer[0 * TLane.LaneWidth + i] = Unsafe.Add(ref baseAddress, scalarIdx + 0 * scale);
buffer[1 * TLane.LaneWidth + i] = Unsafe.Add(ref baseAddress, scalarIdx + 1 * scale);
}
return new Vector2<TLane, TNumber>
{
x = TLane.Load(buffer + 0 * TLane.LaneWidth),
y = TLane.Load(buffer + 1 * TLane.LaneWidth),
};
}
// Math Functions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2<TLane, TNumber> Abs<TLane, TNumber>(in Vector2<TLane, TNumber> vector)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector2<TLane, TNumber>
@@ -110,7 +192,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TLane Dot<TLane, TNumber>(in Vector2<TLane, TNumber> a, in Vector2<TLane, TNumber> b)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return a.x * b.x + a.y * b.y;
@@ -118,7 +200,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2<TLane, TNumber> Sqrt<TLane, TNumber>(in Vector2<TLane, TNumber> vector)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector2<TLane, TNumber>
@@ -130,7 +212,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2<TLane, TNumber> Rsqrt<TLane, TNumber>(in Vector2<TLane, TNumber> vector)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector2<TLane, TNumber>
@@ -142,7 +224,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2<TLane, TNumber> Normalize<TLane, TNumber>(in Vector2<TLane, TNumber> vector)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return vector * TLane.Rsqrt(Dot(vector, vector));
@@ -150,7 +232,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2<TLane, TNumber> Reflect<TLane, TNumber>(in Vector2<TLane, TNumber> incident, in Vector2<TLane, TNumber> normal)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var dot = Dot(incident, normal);
@@ -159,7 +241,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2<TLane, TNumber> Min<TLane, TNumber>(in Vector2<TLane, TNumber> a, in Vector2<TLane, TNumber> b)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector2<TLane, TNumber>
@@ -171,7 +253,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2<TLane, TNumber> Max<TLane, TNumber>(in Vector2<TLane, TNumber> a, in Vector2<TLane, TNumber> b)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector2<TLane, TNumber>
@@ -183,7 +265,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2<TLane, TNumber> Clamp<TLane, TNumber>(in Vector2<TLane, TNumber> value, in Vector2<TLane, TNumber> min, in Vector2<TLane, TNumber> max)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return Min(Max(value, min), max);
@@ -191,7 +273,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2<TLane, TNumber> Saturate<TLane, TNumber>(in Vector2<TLane, TNumber> value)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return Clamp(value, CreateVector2<TLane, TNumber>(TLane.Zero), CreateVector2<TLane, TNumber>(TLane.One));
@@ -199,7 +281,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2<TLane, TNumber> Lerp<TLane, TNumber>(in Vector2<TLane, TNumber> a, in Vector2<TLane, TNumber> b, TLane t)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return a + (b - a) * t;
@@ -207,7 +289,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TLane Length<TLane, TNumber>(in Vector2<TLane, TNumber> vector)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return TLane.Sqrt(Dot(vector, vector));
@@ -215,7 +297,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TLane LengthSquared<TLane, TNumber>(in Vector2<TLane, TNumber> vector)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return Dot(vector, vector);
@@ -223,7 +305,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TLane Distance<TLane, TNumber>(in Vector2<TLane, TNumber> a, in Vector2<TLane, TNumber> b)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var diff = b - a;
@@ -232,7 +314,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TLane DistanceSquared<TLane, TNumber>(in Vector2<TLane, TNumber> a, in Vector2<TLane, TNumber> b)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var diff = b - a;
@@ -241,7 +323,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2<TLane, TNumber> Step<TLane, TNumber>(in Vector2<TLane, TNumber> edge, in Vector2<TLane, TNumber> value)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return Select(value >= edge, Vector2<TLane, TNumber>.One, Vector2<TLane, TNumber>.Zero);
@@ -249,7 +331,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2<TLane, TNumber> Smoothstep<TLane, TNumber>(Vector2<TLane, TNumber> xMin, Vector2<TLane, TNumber> xMax, Vector2<TLane, TNumber> x)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var t = Saturate((x - xMin) / (xMax - xMin));
@@ -261,7 +343,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2<TLane, TNumber> Select<TLane, TNumber>(TLane condition, in Vector2<TLane, TNumber> a, in Vector2<TLane, TNumber> b)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector2<TLane, TNumber>
@@ -273,7 +355,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector2<TLane, TNumber> Select<TLane, TNumber>(Vector2<TLane, TNumber> condition, in Vector2<TLane, TNumber> a, in Vector2<TLane, TNumber> b)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector2<TLane, TNumber>
@@ -283,15 +365,15 @@ public static unsafe partial class MathV
};
}
#endregion
# endregion
#region Vector3
# region Vector3
// Creation Functions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3<TLane, TNumber> Create<TLane, TNumber>(in TLane x, in TLane y, in TLane z)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector3<TLane, TNumber>
@@ -304,7 +386,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3<TLane, TNumber> CreateVector3<TLane, TNumber>(in TLane value)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector3<TLane, TNumber>
@@ -317,7 +399,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3<TLane, TNumber> LoadVector3<TLane, TNumber>(TNumber* pSrc)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var width = TLane.LaneWidth;
@@ -343,7 +425,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3<TLane, TNumber> LoadVector3<TLane, TNumber>(ref TNumber src)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return LoadVector3<TLane, TNumber>((TNumber*)Unsafe.AsPointer(ref src));
@@ -351,7 +433,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3<TLane, TNumber> Load<TLane, TNumber>(TNumber* px, TNumber* py, TNumber* pz)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector3<TLane, TNumber>
@@ -364,7 +446,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3<TLane, TNumber> Load<TLane, TNumber>(ref TNumber x, ref TNumber y, ref TNumber z)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector3<TLane, TNumber>
@@ -375,11 +457,101 @@ public static unsafe partial class MathV
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3<TLane, TNumber> GatherVector3<TLane, TNumber>(TNumber* pData, TLane indices, int scale)
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var buffer = stackalloc TNumber[TLane.LaneWidth * 3];
for (var i = 0; i < TLane.LaneWidth; i++)
{
var scalarIdx = int.CreateTruncating(indices[i]);
buffer[0 * TLane.LaneWidth + i] = pData[scalarIdx + 0 * scale];
buffer[1 * TLane.LaneWidth + i] = pData[scalarIdx + 1 * scale];
buffer[2 * TLane.LaneWidth + i] = pData[scalarIdx + 2 * scale];
}
return new Vector3<TLane, TNumber>
{
x = TLane.Load(buffer + 0 * TLane.LaneWidth),
y = TLane.Load(buffer + 1 * TLane.LaneWidth),
z = TLane.Load(buffer + 2 * TLane.LaneWidth),
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3<TLane, TNumber> GatherVector3<TLane, TNumber>(TNumber* pData, int* pIndices, int scale)
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var buffer = stackalloc TNumber[TLane.LaneWidth * 3];
for (var i = 0; i < TLane.LaneWidth; i++)
{
var scalarIdx = pIndices[i];
buffer[0 * TLane.LaneWidth + i] = pData[scalarIdx + 0 * scale];
buffer[1 * TLane.LaneWidth + i] = pData[scalarIdx + 1 * scale];
buffer[2 * TLane.LaneWidth + i] = pData[scalarIdx + 2 * scale];
}
return new Vector3<TLane, TNumber>
{
x = TLane.Load(buffer + 0 * TLane.LaneWidth),
y = TLane.Load(buffer + 1 * TLane.LaneWidth),
z = TLane.Load(buffer + 2 * TLane.LaneWidth),
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3<TLane, TNumber> GatherVector3<TLane, TNumber>(ref TNumber baseAddress, TLane indices, int scale)
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var buffer = stackalloc TNumber[TLane.LaneWidth * 3];
for (var i = 0; i < TLane.LaneWidth; i++)
{
var scalarIdx = int.CreateTruncating(indices[i]);
buffer[0 * TLane.LaneWidth + i] = Unsafe.Add(ref baseAddress, scalarIdx + 0 * scale);
buffer[1 * TLane.LaneWidth + i] = Unsafe.Add(ref baseAddress, scalarIdx + 1 * scale);
buffer[2 * TLane.LaneWidth + i] = Unsafe.Add(ref baseAddress, scalarIdx + 2 * scale);
}
return new Vector3<TLane, TNumber>
{
x = TLane.Load(buffer + 0 * TLane.LaneWidth),
y = TLane.Load(buffer + 1 * TLane.LaneWidth),
z = TLane.Load(buffer + 2 * TLane.LaneWidth),
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3<TLane, TNumber> GatherVector3<TLane, TNumber>(ref TNumber baseAddress, ref int baseIndex, int scale)
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var buffer = stackalloc TNumber[TLane.LaneWidth * 3];
for (var i = 0; i < TLane.LaneWidth; i++)
{
var scalarIdx = Unsafe.Add(ref baseIndex, i);
buffer[0 * TLane.LaneWidth + i] = Unsafe.Add(ref baseAddress, scalarIdx + 0 * scale);
buffer[1 * TLane.LaneWidth + i] = Unsafe.Add(ref baseAddress, scalarIdx + 1 * scale);
buffer[2 * TLane.LaneWidth + i] = Unsafe.Add(ref baseAddress, scalarIdx + 2 * scale);
}
return new Vector3<TLane, TNumber>
{
x = TLane.Load(buffer + 0 * TLane.LaneWidth),
y = TLane.Load(buffer + 1 * TLane.LaneWidth),
z = TLane.Load(buffer + 2 * TLane.LaneWidth),
};
}
// Math Functions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3<TLane, TNumber> Abs<TLane, TNumber>(in Vector3<TLane, TNumber> vector)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector3<TLane, TNumber>
@@ -392,7 +564,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TLane Dot<TLane, TNumber>(in Vector3<TLane, TNumber> a, in Vector3<TLane, TNumber> b)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return a.x * b.x + a.y * b.y + a.z * b.z;
@@ -400,7 +572,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3<TLane, TNumber> Sqrt<TLane, TNumber>(in Vector3<TLane, TNumber> vector)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector3<TLane, TNumber>
@@ -413,7 +585,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3<TLane, TNumber> Rsqrt<TLane, TNumber>(in Vector3<TLane, TNumber> vector)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector3<TLane, TNumber>
@@ -426,7 +598,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3<TLane, TNumber> Normalize<TLane, TNumber>(in Vector3<TLane, TNumber> vector)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return vector * TLane.Rsqrt(Dot(vector, vector));
@@ -434,7 +606,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3<TLane, TNumber> Reflect<TLane, TNumber>(in Vector3<TLane, TNumber> incident, in Vector3<TLane, TNumber> normal)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var dot = Dot(incident, normal);
@@ -443,7 +615,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3<TLane, TNumber> Min<TLane, TNumber>(in Vector3<TLane, TNumber> a, in Vector3<TLane, TNumber> b)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector3<TLane, TNumber>
@@ -456,7 +628,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3<TLane, TNumber> Max<TLane, TNumber>(in Vector3<TLane, TNumber> a, in Vector3<TLane, TNumber> b)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector3<TLane, TNumber>
@@ -469,7 +641,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3<TLane, TNumber> Clamp<TLane, TNumber>(in Vector3<TLane, TNumber> value, in Vector3<TLane, TNumber> min, in Vector3<TLane, TNumber> max)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return Min(Max(value, min), max);
@@ -477,7 +649,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3<TLane, TNumber> Saturate<TLane, TNumber>(in Vector3<TLane, TNumber> value)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return Clamp(value, CreateVector3<TLane, TNumber>(TLane.Zero), CreateVector3<TLane, TNumber>(TLane.One));
@@ -485,7 +657,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3<TLane, TNumber> Lerp<TLane, TNumber>(in Vector3<TLane, TNumber> a, in Vector3<TLane, TNumber> b, TLane t)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return a + (b - a) * t;
@@ -493,7 +665,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TLane Length<TLane, TNumber>(in Vector3<TLane, TNumber> vector)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return TLane.Sqrt(Dot(vector, vector));
@@ -501,7 +673,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TLane LengthSquared<TLane, TNumber>(in Vector3<TLane, TNumber> vector)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return Dot(vector, vector);
@@ -509,7 +681,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TLane Distance<TLane, TNumber>(in Vector3<TLane, TNumber> a, in Vector3<TLane, TNumber> b)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var diff = b - a;
@@ -518,7 +690,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TLane DistanceSquared<TLane, TNumber>(in Vector3<TLane, TNumber> a, in Vector3<TLane, TNumber> b)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var diff = b - a;
@@ -527,7 +699,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3<TLane, TNumber> Step<TLane, TNumber>(in Vector3<TLane, TNumber> edge, in Vector3<TLane, TNumber> value)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return Select(value >= edge, Vector3<TLane, TNumber>.One, Vector3<TLane, TNumber>.Zero);
@@ -535,7 +707,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3<TLane, TNumber> Smoothstep<TLane, TNumber>(Vector3<TLane, TNumber> xMin, Vector3<TLane, TNumber> xMax, Vector3<TLane, TNumber> x)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var t = Saturate((x - xMin) / (xMax - xMin));
@@ -547,7 +719,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3<TLane, TNumber> Select<TLane, TNumber>(TLane condition, in Vector3<TLane, TNumber> a, in Vector3<TLane, TNumber> b)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector3<TLane, TNumber>
@@ -560,7 +732,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3<TLane, TNumber> Select<TLane, TNumber>(Vector3<TLane, TNumber> condition, in Vector3<TLane, TNumber> a, in Vector3<TLane, TNumber> b)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector3<TLane, TNumber>
@@ -571,15 +743,15 @@ public static unsafe partial class MathV
};
}
#endregion
# endregion
#region Vector4
# region Vector4
// Creation Functions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4<TLane, TNumber> Create<TLane, TNumber>(in TLane x, in TLane y, in TLane z, in TLane w)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector4<TLane, TNumber>
@@ -593,7 +765,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4<TLane, TNumber> CreateVector4<TLane, TNumber>(in TLane value)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector4<TLane, TNumber>
@@ -607,7 +779,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4<TLane, TNumber> LoadVector4<TLane, TNumber>(TNumber* pSrc)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var width = TLane.LaneWidth;
@@ -636,7 +808,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4<TLane, TNumber> LoadVector4<TLane, TNumber>(ref TNumber src)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return LoadVector4<TLane, TNumber>((TNumber*)Unsafe.AsPointer(ref src));
@@ -644,7 +816,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4<TLane, TNumber> Load<TLane, TNumber>(TNumber* px, TNumber* py, TNumber* pz, TNumber* pw)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector4<TLane, TNumber>
@@ -658,7 +830,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4<TLane, TNumber> Load<TLane, TNumber>(ref TNumber x, ref TNumber y, ref TNumber z, ref TNumber w)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector4<TLane, TNumber>
@@ -670,11 +842,109 @@ public static unsafe partial class MathV
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4<TLane, TNumber> GatherVector4<TLane, TNumber>(TNumber* pData, TLane indices, int scale)
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var buffer = stackalloc TNumber[TLane.LaneWidth * 4];
for (var i = 0; i < TLane.LaneWidth; i++)
{
var scalarIdx = int.CreateTruncating(indices[i]);
buffer[0 * TLane.LaneWidth + i] = pData[scalarIdx + 0 * scale];
buffer[1 * TLane.LaneWidth + i] = pData[scalarIdx + 1 * scale];
buffer[2 * TLane.LaneWidth + i] = pData[scalarIdx + 2 * scale];
buffer[3 * TLane.LaneWidth + i] = pData[scalarIdx + 3 * scale];
}
return new Vector4<TLane, TNumber>
{
x = TLane.Load(buffer + 0 * TLane.LaneWidth),
y = TLane.Load(buffer + 1 * TLane.LaneWidth),
z = TLane.Load(buffer + 2 * TLane.LaneWidth),
w = TLane.Load(buffer + 3 * TLane.LaneWidth),
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4<TLane, TNumber> GatherVector4<TLane, TNumber>(TNumber* pData, int* pIndices, int scale)
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var buffer = stackalloc TNumber[TLane.LaneWidth * 4];
for (var i = 0; i < TLane.LaneWidth; i++)
{
var scalarIdx = pIndices[i];
buffer[0 * TLane.LaneWidth + i] = pData[scalarIdx + 0 * scale];
buffer[1 * TLane.LaneWidth + i] = pData[scalarIdx + 1 * scale];
buffer[2 * TLane.LaneWidth + i] = pData[scalarIdx + 2 * scale];
buffer[3 * TLane.LaneWidth + i] = pData[scalarIdx + 3 * scale];
}
return new Vector4<TLane, TNumber>
{
x = TLane.Load(buffer + 0 * TLane.LaneWidth),
y = TLane.Load(buffer + 1 * TLane.LaneWidth),
z = TLane.Load(buffer + 2 * TLane.LaneWidth),
w = TLane.Load(buffer + 3 * TLane.LaneWidth),
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4<TLane, TNumber> GatherVector4<TLane, TNumber>(ref TNumber baseAddress, TLane indices, int scale)
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var buffer = stackalloc TNumber[TLane.LaneWidth * 4];
for (var i = 0; i < TLane.LaneWidth; i++)
{
var scalarIdx = int.CreateTruncating(indices[i]);
buffer[0 * TLane.LaneWidth + i] = Unsafe.Add(ref baseAddress, scalarIdx + 0 * scale);
buffer[1 * TLane.LaneWidth + i] = Unsafe.Add(ref baseAddress, scalarIdx + 1 * scale);
buffer[2 * TLane.LaneWidth + i] = Unsafe.Add(ref baseAddress, scalarIdx + 2 * scale);
buffer[3 * TLane.LaneWidth + i] = Unsafe.Add(ref baseAddress, scalarIdx + 3 * scale);
}
return new Vector4<TLane, TNumber>
{
x = TLane.Load(buffer + 0 * TLane.LaneWidth),
y = TLane.Load(buffer + 1 * TLane.LaneWidth),
z = TLane.Load(buffer + 2 * TLane.LaneWidth),
w = TLane.Load(buffer + 3 * TLane.LaneWidth),
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4<TLane, TNumber> GatherVector4<TLane, TNumber>(ref TNumber baseAddress, ref int baseIndex, int scale)
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var buffer = stackalloc TNumber[TLane.LaneWidth * 4];
for (var i = 0; i < TLane.LaneWidth; i++)
{
var scalarIdx = Unsafe.Add(ref baseIndex, i);
buffer[0 * TLane.LaneWidth + i] = Unsafe.Add(ref baseAddress, scalarIdx + 0 * scale);
buffer[1 * TLane.LaneWidth + i] = Unsafe.Add(ref baseAddress, scalarIdx + 1 * scale);
buffer[2 * TLane.LaneWidth + i] = Unsafe.Add(ref baseAddress, scalarIdx + 2 * scale);
buffer[3 * TLane.LaneWidth + i] = Unsafe.Add(ref baseAddress, scalarIdx + 3 * scale);
}
return new Vector4<TLane, TNumber>
{
x = TLane.Load(buffer + 0 * TLane.LaneWidth),
y = TLane.Load(buffer + 1 * TLane.LaneWidth),
z = TLane.Load(buffer + 2 * TLane.LaneWidth),
w = TLane.Load(buffer + 3 * TLane.LaneWidth),
};
}
// Math Functions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4<TLane, TNumber> Abs<TLane, TNumber>(in Vector4<TLane, TNumber> vector)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector4<TLane, TNumber>
@@ -688,7 +958,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TLane Dot<TLane, TNumber>(in Vector4<TLane, TNumber> a, in Vector4<TLane, TNumber> b)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
@@ -696,7 +966,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4<TLane, TNumber> Sqrt<TLane, TNumber>(in Vector4<TLane, TNumber> vector)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector4<TLane, TNumber>
@@ -710,7 +980,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4<TLane, TNumber> Rsqrt<TLane, TNumber>(in Vector4<TLane, TNumber> vector)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector4<TLane, TNumber>
@@ -724,7 +994,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4<TLane, TNumber> Normalize<TLane, TNumber>(in Vector4<TLane, TNumber> vector)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return vector * TLane.Rsqrt(Dot(vector, vector));
@@ -732,7 +1002,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4<TLane, TNumber> Reflect<TLane, TNumber>(in Vector4<TLane, TNumber> incident, in Vector4<TLane, TNumber> normal)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var dot = Dot(incident, normal);
@@ -741,7 +1011,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4<TLane, TNumber> Min<TLane, TNumber>(in Vector4<TLane, TNumber> a, in Vector4<TLane, TNumber> b)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector4<TLane, TNumber>
@@ -755,7 +1025,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4<TLane, TNumber> Max<TLane, TNumber>(in Vector4<TLane, TNumber> a, in Vector4<TLane, TNumber> b)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector4<TLane, TNumber>
@@ -769,7 +1039,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4<TLane, TNumber> Clamp<TLane, TNumber>(in Vector4<TLane, TNumber> value, in Vector4<TLane, TNumber> min, in Vector4<TLane, TNumber> max)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return Min(Max(value, min), max);
@@ -777,7 +1047,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4<TLane, TNumber> Saturate<TLane, TNumber>(in Vector4<TLane, TNumber> value)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return Clamp(value, CreateVector4<TLane, TNumber>(TLane.Zero), CreateVector4<TLane, TNumber>(TLane.One));
@@ -785,7 +1055,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4<TLane, TNumber> Lerp<TLane, TNumber>(in Vector4<TLane, TNumber> a, in Vector4<TLane, TNumber> b, TLane t)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return a + (b - a) * t;
@@ -793,7 +1063,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TLane Length<TLane, TNumber>(in Vector4<TLane, TNumber> vector)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return TLane.Sqrt(Dot(vector, vector));
@@ -801,7 +1071,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TLane LengthSquared<TLane, TNumber>(in Vector4<TLane, TNumber> vector)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return Dot(vector, vector);
@@ -809,7 +1079,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TLane Distance<TLane, TNumber>(in Vector4<TLane, TNumber> a, in Vector4<TLane, TNumber> b)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var diff = b - a;
@@ -818,7 +1088,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TLane DistanceSquared<TLane, TNumber>(in Vector4<TLane, TNumber> a, in Vector4<TLane, TNumber> b)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var diff = b - a;
@@ -827,7 +1097,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4<TLane, TNumber> Step<TLane, TNumber>(in Vector4<TLane, TNumber> edge, in Vector4<TLane, TNumber> value)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return Select(value >= edge, Vector4<TLane, TNumber>.One, Vector4<TLane, TNumber>.Zero);
@@ -835,7 +1105,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4<TLane, TNumber> Smoothstep<TLane, TNumber>(Vector4<TLane, TNumber> xMin, Vector4<TLane, TNumber> xMax, Vector4<TLane, TNumber> x)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
var t = Saturate((x - xMin) / (xMax - xMin));
@@ -847,7 +1117,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4<TLane, TNumber> Select<TLane, TNumber>(TLane condition, in Vector4<TLane, TNumber> a, in Vector4<TLane, TNumber> b)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector4<TLane, TNumber>
@@ -861,7 +1131,7 @@ public static unsafe partial class MathV
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4<TLane, TNumber> Select<TLane, TNumber>(Vector4<TLane, TNumber> condition, in Vector4<TLane, TNumber> a, in Vector4<TLane, TNumber> b)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector4<TLane, TNumber>
@@ -873,14 +1143,14 @@ public static unsafe partial class MathV
};
}
#endregion
# endregion
#region Vector3 Specific
# region Vector3 Specific
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3<TLane, TNumber> Cross<TLane, TNumber>(in Vector3<TLane, TNumber> a, in Vector3<TLane, TNumber> b)
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
return new Vector3<TLane, TNumber>
@@ -891,6 +1161,6 @@ public static unsafe partial class MathV
};
}
#endregion
# endregion
}

View File

@@ -21,7 +21,7 @@ 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 TLaneRestrictions = $@"where {TLane} : ISPMDLane<{TLane}, {TNumber}>";
var TNumberRestrictions = $@"where {TNumber} : unmanaged, INumber<{TNumber}>, IBinaryNumber<{TNumber}>, IMinMaxValue<{TNumber}>, IBitwiseOperators<{TNumber}, {TNumber}, {TNumber}>";
#>
@@ -35,7 +35,7 @@ public static unsafe partial class MathV
// Creation Functions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> Create<<#= GenericParameters #>>(<#= ForEachDimension(dimension, i => $"in TLane {components[i]}") #>)
public static <#= vectorType #> Create<<#= GenericParameters #>>(<#= ForEachDimension(dimension, i => $"in {TLane} {components[i]}") #>)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
@@ -48,7 +48,7 @@ public static unsafe partial class MathV
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> CreateVector<#= dimension #><<#= GenericParameters #>>(in TLane value)
public static <#= vectorType #> CreateVector<#= dimension #><<#= GenericParameters #>>(in <#= TLane #> value)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
@@ -61,14 +61,14 @@ public static unsafe partial class MathV
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> LoadVector<#= dimension #><<#= GenericParameters #>>(TNumber* pSrc)
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];
var <#= components[i] #> = stackalloc <#= TNumber #>[width];
<# } #>
for (var i = 0; i < width; i++)
@@ -87,11 +87,11 @@ public static unsafe partial class MathV
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> LoadVector<#= dimension #><<#= GenericParameters #>>(ref TNumber src)
public static <#= vectorType #> LoadVector<#= dimension #><<#= GenericParameters #>>(ref <#= TNumber #> src)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
return LoadVector<#= dimension #><<#= GenericParameters #>>((TNumber*)Unsafe.AsPointer(ref src));
return LoadVector<#= dimension #><<#= GenericParameters #>>((<#= TNumber #>*)Unsafe.AsPointer(ref src));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -120,10 +120,100 @@ public static unsafe partial class MathV
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> GatherVector<#= dimension #><<#= GenericParameters #>>(<#= TNumber #>* pData, <#= TLane #> indices, int scale)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
var buffer = stackalloc <#= TNumber #>[TLane.LaneWidth * <#= dimension #>];
for (var i = 0; i < TLane.LaneWidth; i++)
{
var scalarIdx = int.CreateTruncating(indices[i]);
<# for (int i = 0; i < dimension; i++) { #>
buffer[<#= i #> * TLane.LaneWidth + i] = pData[scalarIdx + <#= i #> * scale];
<# } #>
}
return new <#= vectorType #>
{
<# for (int i = 0; i < dimension; i++) { #>
<#= components[i] #> = TLane.Load(buffer + <#= i #> * TLane.LaneWidth),
<# } #>
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> GatherVector<#= dimension #><<#= GenericParameters #>>(<#= TNumber #>* pData, int* pIndices, int scale)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
var buffer = stackalloc <#= TNumber #>[TLane.LaneWidth * <#= dimension #>];
for (var i = 0; i < TLane.LaneWidth; i++)
{
var scalarIdx = pIndices[i];
<# for (int i = 0; i < dimension; i++) { #>
buffer[<#= i #> * TLane.LaneWidth + i] = pData[scalarIdx + <#= i #> * scale];
<# } #>
}
return new <#= vectorType #>
{
<# for (int i = 0; i < dimension; i++) { #>
<#= components[i] #> = TLane.Load(buffer + <#= i #> * TLane.LaneWidth),
<# } #>
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> GatherVector<#= dimension #><<#= GenericParameters #>>(ref <#= TNumber #> baseAddress, <#= TLane #> indices, int scale)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
var buffer = stackalloc <#= TNumber #>[TLane.LaneWidth * <#= dimension #>];
for (var i = 0; i < TLane.LaneWidth; i++)
{
var scalarIdx = int.CreateTruncating(indices[i]);
<# for (int i = 0; i < dimension; i++) { #>
buffer[<#= i #> * TLane.LaneWidth + i] = Unsafe.Add(ref baseAddress, scalarIdx + <#= i #> * scale);
<# } #>
}
return new <#= vectorType #>
{
<# for (int i = 0; i < dimension; i++) { #>
<#= components[i] #> = TLane.Load(buffer + <#= i #> * TLane.LaneWidth),
<# } #>
};
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> GatherVector<#= dimension #><<#= GenericParameters #>>(ref <#= TNumber #> baseAddress, ref int baseIndex, int scale)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{
var buffer = stackalloc <#= TNumber #>[TLane.LaneWidth * <#= dimension #>];
for (var i = 0; i < TLane.LaneWidth; i++)
{
var scalarIdx = Unsafe.Add(ref baseIndex, i);
<# for (int i = 0; i < dimension; i++) { #>
buffer[<#= i #> * TLane.LaneWidth + i] = Unsafe.Add(ref baseAddress, scalarIdx + <#= i #> * scale);
<# } #>
}
return new <#= vectorType #>
{
<# for (int i = 0; i < dimension; i++) { #>
<#= components[i] #> = TLane.Load(buffer + <#= i #> * TLane.LaneWidth),
<# } #>
};
}
// Math Functions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static <#= vectorType #> Abs<<#= GenericParameters #>>(in Vector<#= dimension #><TLane, TNumber> vector)
public static <#= vectorType #> Abs<<#= GenericParameters #>>(in Vector<#= dimension #><TLane, <#= TNumber #>> vector)
<#= TLaneRestrictions #>
<#= TNumberRestrictions #>
{

View File

@@ -6,7 +6,7 @@ using System.Runtime.CompilerServices;
namespace Misaki.HighPerformance.Mathematics.SPMD;
public unsafe struct Vector2<TLane, TNumber> : IEquatable<Vector2<TLane, TNumber>>
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
public TLane x;
@@ -49,7 +49,7 @@ public unsafe struct Vector2<TLane, TNumber> : IEquatable<Vector2<TLane, TNumber
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[Conditional("ENABLE_COLLECTION_CHECKS")]
[Conditional("MHP_ENABLE_SAFETY_CHECKS")]
private static void RangeCheck(int index)
{
if (index < 0 || index >= 2)
@@ -420,8 +420,11 @@ public unsafe struct Vector2<TLane, TNumber> : IEquatable<Vector2<TLane, TNumber
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
public override readonly int GetHashCode()
{
throw new NotImplementedException();
var hash = new HashCode();
hash.Add(x);
hash.Add(y);
return hash.ToHashCode();
}
}

View File

@@ -6,7 +6,7 @@ using System.Runtime.CompilerServices;
namespace Misaki.HighPerformance.Mathematics.SPMD;
public unsafe struct Vector3<TLane, TNumber> : IEquatable<Vector3<TLane, TNumber>>
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
public TLane x;
@@ -52,12 +52,12 @@ public unsafe struct Vector3<TLane, TNumber> : IEquatable<Vector3<TLane, TNumber
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[Conditional("ENABLE_COLLECTION_CHECKS")]
[Conditional("MHP_ENABLE_SAFETY_CHECKS")]
private static void RangeCheck(int index)
{
if (index < 0 || index >= 3)
{
throw new IndexOutOfRangeException($"Index {index} is out of range for Vector2.");
throw new IndexOutOfRangeException($"Index {index} is out of range for Vector3.");
}
}
@@ -459,8 +459,12 @@ public unsafe struct Vector3<TLane, TNumber> : IEquatable<Vector3<TLane, TNumber
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
public override readonly int GetHashCode()
{
throw new NotImplementedException();
var hash = new HashCode();
hash.Add(x);
hash.Add(y);
hash.Add(z);
return hash.ToHashCode();
}
}

View File

@@ -6,7 +6,7 @@ using System.Runtime.CompilerServices;
namespace Misaki.HighPerformance.Mathematics.SPMD;
public unsafe struct Vector4<TLane, TNumber> : IEquatable<Vector4<TLane, TNumber>>
where TLane : ISPMD<TLane, TNumber>
where TLane : ISPMDLane<TLane, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
public TLane x;
@@ -55,12 +55,12 @@ public unsafe struct Vector4<TLane, TNumber> : IEquatable<Vector4<TLane, TNumber
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[Conditional("ENABLE_COLLECTION_CHECKS")]
[Conditional("MHP_ENABLE_SAFETY_CHECKS")]
private static void RangeCheck(int index)
{
if (index < 0 || index >= 4)
{
throw new IndexOutOfRangeException($"Index {index} is out of range for Vector2.");
throw new IndexOutOfRangeException($"Index {index} is out of range for Vector4.");
}
}
@@ -498,8 +498,13 @@ public unsafe struct Vector4<TLane, TNumber> : IEquatable<Vector4<TLane, TNumber
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
public override readonly int GetHashCode()
{
throw new NotImplementedException();
var hash = new HashCode();
hash.Add(x);
hash.Add(y);
hash.Add(z);
hash.Add(w);
return hash.ToHashCode();
}
}

View File

@@ -3,7 +3,7 @@
private const string TLane = "TLane";
private const string TNumber = "TNumber";
private string TLaneRestrictions = $@"where {TLane} : ISPMD<{TLane}, {TNumber}>";
private string TLaneRestrictions = $@"where {TLane} : ISPMDLane<{TLane}, {TNumber}>";
private string TNumberRestrictions = $@"where {TNumber} : unmanaged, INumber<{TNumber}>, IBinaryNumber<{TNumber}>, IMinMaxValue<{TNumber}>, IBitwiseOperators<{TNumber}, {TNumber}, {TNumber}>";
private int[] dimensions = new int[] { 2, 3, 4 };
@@ -83,12 +83,12 @@ public unsafe struct {typeName} : IEquatable<{typeName}>
}}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[Conditional(""ENABLE_COLLECTION_CHECKS"")]
[Conditional(""MHP_ENABLE_SAFETY_CHECKS"")]
private static void RangeCheck(int index)
{{
if (index < 0 || index >= {dimension})
{{
throw new IndexOutOfRangeException($""Index {{index}} is out of range for Vector2."");
throw new IndexOutOfRangeException($""Index {{index}} is out of range for Vector{dimension}."");
}}
}}
@@ -418,9 +418,11 @@ public unsafe struct {typeName} : IEquatable<{typeName}>
}}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
public override readonly int GetHashCode()
{{
throw new NotImplementedException();
var hash = new HashCode();
{ForEachDimension(dimension, 8, Environment.NewLine, (dim, sb) => sb.Append($"hash.Add({components[dim]});"))}
return hash.ToHashCode();
}}
}}");

View File

@@ -3,12 +3,12 @@ using System.Runtime.CompilerServices;
namespace Misaki.HighPerformance.Mathematics.SPMD;
public readonly unsafe partial struct WideLane<TNumber> : ISPMD<WideLane<TNumber>, TNumber>
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 : ISPMD<TOther, TOtherNumber>
where TOther : ISPMDLane<TOther, TOtherNumber>
where TOtherNumber : unmanaged, INumber<TOtherNumber>, IBinaryNumber<TOtherNumber>, IMinMaxValue<TOtherNumber>, IBitwiseOperators<TOtherNumber, TOtherNumber, TOtherNumber>
{
if (typeof(TNumber) == typeof(float) && typeof(TOtherNumber) == typeof(int))

View File

@@ -22,12 +22,12 @@ var conversions = new CastRoute[]
};
#>
public readonly unsafe partial struct WideLane<TNumber> : ISPMD<WideLane<TNumber>, TNumber>
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 : ISPMD<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) { #>

View File

@@ -32,7 +32,7 @@ public static unsafe class WideLane
}
[StructLayout(LayoutKind.Sequential)]
public readonly unsafe partial struct WideLane<TNumber> : ISPMD<WideLane<TNumber>, TNumber>
public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNumber>, TNumber>
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
{
private static readonly Vector<TNumber> s_indices;
@@ -48,13 +48,13 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMD<WideLane<TNumber
public static WideLane<TNumber> Zero
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => new(Vector<TNumber>.Zero);
get => new WideLane<TNumber>(Vector<TNumber>.Zero);
}
public static WideLane<TNumber> One
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => new(Vector<TNumber>.One);
get => new WideLane<TNumber>(Vector<TNumber>.One);
}
public static WideLane<TNumber> MinValue
@@ -134,39 +134,102 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMD<WideLane<TNumber
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> Create(TNumber value)
{
return new(Vector.Create(value));
return new WideLane<TNumber>(Vector.Create(value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> Create(params ReadOnlySpan<TNumber> values)
{
return new(Vector.Create(values));
return new WideLane<TNumber>(Vector.Create(values));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> Create(Vector<TNumber> value)
{
return new(value);
return new WideLane<TNumber>(value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> Sequence(TNumber start, TNumber step)
{
return new(Vector.Create(start) + (Vector.Create(step) * s_indices));
return new WideLane<TNumber>(Vector.Create(start) + (Vector.Create(step) * s_indices));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> Load(ref TNumber value)
{
return new(Vector.LoadUnsafe(ref value));
return new WideLane<TNumber>(Vector.LoadUnsafe(ref value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> Load(TNumber* pValue)
{
return new(Vector.Load(pValue));
return new WideLane<TNumber>(Vector.Load(pValue));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> MaskLoad(WideLane<TNumber> mask, ref TNumber value)
{
return MaskLoad(mask, (TNumber*)Unsafe.AsPointer(ref value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> MaskLoad(WideLane<TNumber> mask, TNumber* pValue)
{
var vector = Vector.Load(pValue);
return new WideLane<TNumber>(Vector.ConditionalSelect(mask.value, vector, Vector<TNumber>.Zero));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> Gather(TNumber* pData, WideLane<TNumber> indices, int scale)
{
var buffer = stackalloc TNumber[LaneWidth];
for (var i = 0; i < LaneWidth; i++)
{
buffer[i] = pData[int.CreateTruncating(indices[i]) * scale / sizeof(TNumber)];
}
return new WideLane<TNumber>(Vector.Load(buffer));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> Gather(TNumber* pData, int* pIndices, int scale)
{
var buffer = stackalloc TNumber[LaneWidth];
for (var i = 0; i < LaneWidth; i++)
{
buffer[i] = pData[pIndices[i] * scale / sizeof(TNumber)];
}
return new WideLane<TNumber>(Vector.Load(buffer));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> Gather(ref TNumber baseAddress, WideLane<TNumber> indices, int scale)
{
var buffer = stackalloc TNumber[LaneWidth];
for (var i = 0; i < LaneWidth; i++)
{
buffer[i] = Unsafe.Add(ref baseAddress, int.CreateTruncating(indices[i]) * scale / sizeof(TNumber));
}
return new WideLane<TNumber>(Vector.Load(buffer));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> Gather(ref TNumber baseAddress, ref int baseIndex, int scale)
{
var buffer = stackalloc TNumber[LaneWidth];
for (var i = 0; i < LaneWidth; i++)
{
buffer[i] = Unsafe.Add(ref baseAddress, Unsafe.Add(ref baseIndex, i) * scale / sizeof(TNumber));
}
return new WideLane<TNumber>(Vector.Load(buffer));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly void Store(ref TNumber destination)
{
@@ -301,9 +364,15 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMD<WideLane<TNumber
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly TNumber* GetUnsafePtr()
{
return (TNumber*)Unsafe.AsPointer(ref Unsafe.AsRef(in value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TOther BitCast<TOther, TOtherNumber>()
where TOther : ISPMD<TOther, TOtherNumber>
where TOther : ISPMDLane<TOther, TOtherNumber>
where TOtherNumber : unmanaged, INumber<TOtherNumber>, IBinaryNumber<TOtherNumber>, IMinMaxValue<TOtherNumber>, IBitwiseOperators<TOtherNumber, TOtherNumber, TOtherNumber>
{
return Unsafe.BitCast<WideLane<TNumber>, TOther>(this);
@@ -313,61 +382,61 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMD<WideLane<TNumber
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> operator +(WideLane<TNumber> a, WideLane<TNumber> b)
{
return new(a.value + b.value);
return new WideLane<TNumber>(a.value + b.value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> operator -(WideLane<TNumber> a, WideLane<TNumber> b)
{
return new(a.value - b.value);
return new WideLane<TNumber>(a.value - b.value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> operator *(WideLane<TNumber> a, WideLane<TNumber> b)
{
return new(a.value * b.value);
return new WideLane<TNumber>(a.value * b.value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> operator /(WideLane<TNumber> a, WideLane<TNumber> b)
{
return new(a.value / b.value);
return new WideLane<TNumber>(a.value / b.value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> operator %(WideLane<TNumber> a, WideLane<TNumber> b)
{
return new(a.value - VectorFloor(a.value / b.value) * b.value);
return new WideLane<TNumber>(a.value - VectorFloor(a.value / b.value) * b.value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> operator -(WideLane<TNumber> a)
{
return new(-a.value);
return new WideLane<TNumber>(-a.value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> operator &(WideLane<TNumber> a, WideLane<TNumber> b)
{
return new(a.value & b.value);
return new WideLane<TNumber>(a.value & b.value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> operator |(WideLane<TNumber> a, WideLane<TNumber> b)
{
return new(a.value | b.value);
return new WideLane<TNumber>(a.value | b.value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> operator ^(WideLane<TNumber> a, WideLane<TNumber> b)
{
return new(a.value ^ b.value);
return new WideLane<TNumber>(a.value ^ b.value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> operator ~(WideLane<TNumber> a)
{
return new(~a.value);
return new WideLane<TNumber>(~a.value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -417,7 +486,7 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMD<WideLane<TNumber
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> Abs(WideLane<TNumber> value)
{
return new(Vector.Abs(value.value));
return new WideLane<TNumber>(Vector.Abs(value.value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -442,19 +511,19 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMD<WideLane<TNumber
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> Frac(WideLane<TNumber> value)
{
return new(value.value - VectorFloor(value.value));
return new WideLane<TNumber>(value.value - VectorFloor(value.value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> Sqrt(WideLane<TNumber> value)
{
return new(Vector.SquareRoot(value.value));
return new WideLane<TNumber>(Vector.SquareRoot(value.value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> Lerp(WideLane<TNumber> a, WideLane<TNumber> b, WideLane<TNumber> t)
{
return new(a.value + (b.value - a.value) * t.value);
return new WideLane<TNumber>(a.value + (b.value - a.value) * t.value);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -478,26 +547,26 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMD<WideLane<TNumber
}
else
{
return new((a.value * b.value) + c.value);
return new WideLane<TNumber>((a.value * b.value) + c.value);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> Min(WideLane<TNumber> a, WideLane<TNumber> b)
{
return new(Vector.Min(a.value, b.value));
return new WideLane<TNumber>(Vector.Min(a.value, b.value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> Max(WideLane<TNumber> a, WideLane<TNumber> b)
{
return new(Vector.Max(a.value, b.value));
return new WideLane<TNumber>(Vector.Max(a.value, b.value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> Clamp(WideLane<TNumber> value, WideLane<TNumber> min, WideLane<TNumber> max)
{
return new(Vector.Clamp(value.value, min.value, max.value));
return new WideLane<TNumber>(Vector.Clamp(value.value, min.value, max.value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -826,7 +895,7 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMD<WideLane<TNumber
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> CopySign(WideLane<TNumber> magnitude, WideLane<TNumber> sign)
{
return new(Vector.CopySign(magnitude.value, sign.value));
return new WideLane<TNumber>(Vector.CopySign(magnitude.value, sign.value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -878,7 +947,7 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMD<WideLane<TNumber
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> Select(WideLane<TNumber> conditionMask, WideLane<TNumber> ifTrue, WideLane<TNumber> ifFalse)
{
return new(Vector.ConditionalSelect(
return new WideLane<TNumber>(Vector.ConditionalSelect(
conditionMask.value,
ifTrue.value,
ifFalse.value));
@@ -887,31 +956,31 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMD<WideLane<TNumber
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> GreaterThan(WideLane<TNumber> a, WideLane<TNumber> b)
{
return new(Vector.GreaterThan(a.value, b.value));
return new WideLane<TNumber>(Vector.GreaterThan(a.value, b.value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> GreaterThanOrEqual(WideLane<TNumber> a, WideLane<TNumber> b)
{
return new(Vector.GreaterThanOrEqual(a.value, b.value));
return new WideLane<TNumber>(Vector.GreaterThanOrEqual(a.value, b.value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> LessThan(WideLane<TNumber> a, WideLane<TNumber> b)
{
return new(Vector.LessThan(a.value, b.value));
return new WideLane<TNumber>(Vector.LessThan(a.value, b.value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> LessThanOrEqual(WideLane<TNumber> a, WideLane<TNumber> b)
{
return new(Vector.LessThanOrEqual(a.value, b.value));
return new WideLane<TNumber>(Vector.LessThanOrEqual(a.value, b.value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static WideLane<TNumber> Equal(WideLane<TNumber> a, WideLane<TNumber> b)
{
return new(Vector.Equals(a.value, b.value));
return new WideLane<TNumber>(Vector.Equals(a.value, b.value));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -1,4 +1,4 @@
using System.Diagnostics;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using static Misaki.HighPerformance.Mathematics.math;
@@ -711,53 +711,53 @@ public struct random
return t;
}
[Conditional("ENABLE_COLLECTION_CHECKS")]
[Conditional("MHP_ENABLE_SAFETY_CHECKS")]
private void CheckInitState()
{
#if ENABLE_COLLECTION_CHECKS
#if MHP_ENABLE_SAFETY_CHECKS
if (state == 0)
throw new System.ArgumentException("Seed must be non-zero");
#endif
}
[Conditional("ENABLE_COLLECTION_CHECKS")]
[Conditional("MHP_ENABLE_SAFETY_CHECKS")]
private static void CheckIndexForHash(uint index)
{
if (index == uint.MaxValue)
throw new System.ArgumentException("Index must not be uint.MaxValue");
}
[Conditional("ENABLE_COLLECTION_CHECKS")]
[Conditional("MHP_ENABLE_SAFETY_CHECKS")]
private void CheckState()
{
#if ENABLE_COLLECTION_CHECKS
#if MHP_ENABLE_SAFETY_CHECKS
if(state == 0)
throw new System.ArgumentException("Invalid state 0. Random object has not been properly initialized");
#endif
}
[Conditional("ENABLE_COLLECTION_CHECKS")]
[Conditional("MHP_ENABLE_SAFETY_CHECKS")]
private void CheckNextIntMax(int max)
{
#if ENABLE_COLLECTION_CHECKS
#if MHP_ENABLE_SAFETY_CHECKS
if (max < 0)
throw new System.ArgumentException("max must be positive");
#endif
}
[Conditional("ENABLE_COLLECTION_CHECKS")]
[Conditional("MHP_ENABLE_SAFETY_CHECKS")]
private void CheckNextIntMinMax(int min, int max)
{
#if ENABLE_COLLECTION_CHECKS
#if MHP_ENABLE_SAFETY_CHECKS
if (min > max)
throw new System.ArgumentException("min must be less than or equal to max");
#endif
}
[Conditional("ENABLE_COLLECTION_CHECKS")]
[Conditional("MHP_ENABLE_SAFETY_CHECKS")]
private void CheckNextUIntMinMax(uint min, uint max)
{
#if ENABLE_COLLECTION_CHECKS
#if MHP_ENABLE_SAFETY_CHECKS
if (min > max)
throw new System.ArgumentException("min must be less than or equal to max");
#endif

View File

@@ -20,8 +20,8 @@ internal unsafe struct MipLevel
}
internal unsafe struct GGXMipGenerationJobSPMD<TFloat, TInt> : IJobParallelFor
where TFloat : unmanaged, ISPMD<TFloat, float>
where TInt : unmanaged, ISPMD<TInt, int>
where TFloat : unmanaged, ISPMDLane<TFloat, float>
where TInt : unmanaged, ISPMDLane<TInt, int>
{
public const uint SAMPLE_COUNT = 1024u;
@@ -104,34 +104,12 @@ internal unsafe struct GGXMipGenerationJobSPMD<TFloat, TInt> : IJobParallelFor
var py = (uv.y * (h - 1.0f)).Cast<TInt, int>();
// Clamp
px = TInt.Clamp(px, TInt.Zero, TInt.Create(w - 1));
py = TInt.Clamp(py, TInt.Zero, TInt.Create(h - 1));
px = TInt.Clamp(px, TInt.Zero, w - 1);
py = TInt.Clamp(py, TInt.Zero, h - 1);
// Assuming float RGB array format
var idx = (py * w + px) * 3;
var laneWidth = TFloat.LaneWidth;
var rBuffer = stackalloc float[laneWidth];
var gBuffer = stackalloc float[laneWidth];
var bBuffer = stackalloc float[laneWidth];
// Gather operation: extract scalar indices, perform random memory reads, and construct SoA buffers
for (var i = 0; i < laneWidth; i++)
{
var scalarIdx = idx[i];
rBuffer[i] = img[scalarIdx];
gBuffer[i] = img[scalarIdx + 1];
bBuffer[i] = img[scalarIdx + 2];
}
// Load the gathered contiguous arrays back into TLane types
var rLane = TFloat.Load(rBuffer);
var gLane = TFloat.Load(gBuffer);
var bLane = TFloat.Load(bBuffer);
return MathV.Create<TFloat, float>(rLane, gLane, bLane);
return MathV.GatherVector3<TFloat, float>(img, idx.GetUnsafePtr(), 1);
}
public void Execute(int loopIndex, ref readonly JobExecutionContext ctx)
@@ -179,9 +157,10 @@ internal unsafe struct GGXMipGenerationJobSPMD<TFloat, TInt> : IJobParallelFor
TFloat.Create(V.z)
);
var vPrefilteredColorX = TFloat.Zero;
var vPrefilteredColorY = TFloat.Zero;
var vPrefilteredColorZ = TFloat.Zero;
//var vPrefilteredColorX = TFloat.Zero;
//var vPrefilteredColorY = TFloat.Zero;
//var vPrefilteredColorZ = TFloat.Zero;
var vPrefilteredColor = Vector3<TFloat, float>.Zero;
var vTotalWeight = TFloat.Zero;
// 3. Monte Carlo Integration Loop
@@ -219,10 +198,7 @@ internal unsafe struct GGXMipGenerationJobSPMD<TFloat, TInt> : IJobParallelFor
var fireflyWeight = TFloat.One / (TFloat.One + luma);
var finalWeight = NdotL * fireflyWeight;
vPrefilteredColorX += sampleColor.x * finalWeight;
vPrefilteredColorY += sampleColor.y * finalWeight;
vPrefilteredColorZ += sampleColor.z * finalWeight;
vPrefilteredColor += sampleColor * finalWeight;
vTotalWeight += finalWeight;
}
@@ -231,9 +207,9 @@ internal unsafe struct GGXMipGenerationJobSPMD<TFloat, TInt> : IJobParallelFor
for (var i = 0; i < TFloat.LaneWidth; i++)
{
prefilteredColor.x += vPrefilteredColorX[i];
prefilteredColor.y += vPrefilteredColorY[i];
prefilteredColor.z += vPrefilteredColorZ[i];
prefilteredColor.x += vPrefilteredColor.x[i];
prefilteredColor.y += vPrefilteredColor.y[i];
prefilteredColor.z += vPrefilteredColor.z[i];
totalWeight += vTotalWeight[i];
}

View File

@@ -239,7 +239,7 @@ internal unsafe struct NoiseJobMathSPMD : IJobSPMD<float>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static T GradDot<T>(T ix, T iy, T fx, T fy)
where T : unmanaged, ISPMD<T, float>
where T : unmanaged, ISPMDLane<T, float>
{
var c289 = T.Create(289f);
var c34 = T.Create(34f);
@@ -267,7 +267,7 @@ internal unsafe struct NoiseJobMathSPMD : IJobSPMD<float>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T Noise<T>(T uvX, T uvY)
where T : unmanaged, ISPMD<T, float>
where T : unmanaged, ISPMDLane<T, float>
{
var c1 = T.Create(1f);
var c6 = T.Create(6f);
@@ -292,7 +292,7 @@ internal unsafe struct NoiseJobMathSPMD : IJobSPMD<float>
}
public readonly void Execute<TLane>(int baseIndex, ref readonly JobExecutionContext ctx)
where TLane : unmanaged, ISPMD<TLane, float>
where TLane : unmanaged, ISPMDLane<TLane, float>
{
var indices = TLane.Sequence(baseIndex, 1f);
var w = TLane.Create(width);

View File

@@ -13,7 +13,7 @@ internal unsafe struct DotProductJob : IJobSPMD<float>
public float* results; // output array (dot products)
public readonly void Execute<TLane>(int baseIndex, ref readonly JobExecutionContext ctx)
where TLane : unmanaged, ISPMD<TLane, float>
where TLane : unmanaged, ISPMDLane<TLane, float>
{
var vecA = MathV.LoadVector3<TLane, float>((float*)(arrayA + baseIndex));
var vecB = MathV.LoadVector3<TLane, float>((float*)(arrayB + baseIndex));
@@ -30,7 +30,7 @@ internal unsafe struct Vector2LerpJob : IJobSPMD<float>
public float[] results;
public readonly void Execute<TLane>(int baseIndex, ref readonly JobExecutionContext ctx)
where TLane : unmanaged, ISPMD<TLane, float>
where TLane : unmanaged, ISPMDLane<TLane, float>
{
var a = MathV.LoadVector2<TLane, float>(ref arrayA[baseIndex].x);
var b = MathV.LoadVector2<TLane, float>(ref arrayB[baseIndex].x);
@@ -49,7 +49,7 @@ internal unsafe struct Vector4NormalizeJob : IJobSPMD<float>
public float4[] output;
public readonly void Execute<TLane>(int baseIndex, ref readonly JobExecutionContext ctx)
where TLane : unmanaged, ISPMD<TLane, float>
where TLane : unmanaged, ISPMDLane<TLane, float>
{
var vec = MathV.LoadVector4<TLane, float>(ref input[baseIndex].x);
var normalized = MathV.Normalize(vec);
@@ -64,7 +64,7 @@ internal unsafe struct Vector3CrossJob : IJobSPMD<float>
public float3[] results;
public readonly void Execute<TLane>(int baseIndex, ref readonly JobExecutionContext ctx)
where TLane : unmanaged, ISPMD<TLane, float>
where TLane : unmanaged, ISPMDLane<TLane, float>
{
var a = MathV.LoadVector3<TLane, float>(ref arrayA[baseIndex].x);
var b = MathV.LoadVector3<TLane, float>(ref arrayB[baseIndex].x);
@@ -82,7 +82,7 @@ internal unsafe struct MinMaxClampJob : IJobSPMD<float>
public float3[] results;
public readonly void Execute<TLane>(int baseIndex, ref readonly JobExecutionContext ctx)
where TLane : unmanaged, ISPMD<TLane, float>
where TLane : unmanaged, ISPMDLane<TLane, float>
{
var val = MathV.LoadVector3<TLane, float>(ref values[baseIndex].x);
var min = MathV.LoadVector3<TLane, float>(ref mins[baseIndex].x);
@@ -100,7 +100,7 @@ internal unsafe struct DistanceJob : IJobSPMD<float>
public float[] results;
public readonly void Execute<TLane>(int baseIndex, ref readonly JobExecutionContext ctx)
where TLane : unmanaged, ISPMD<TLane, float>
where TLane : unmanaged, ISPMDLane<TLane, float>
{
var a = MathV.LoadVector3<TLane, float>(ref arrayA[baseIndex].x);
var b = MathV.LoadVector3<TLane, float>(ref arrayB[baseIndex].x);