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:
@@ -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>
|
||||
@@ -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`
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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 #>
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}}
|
||||
}}");
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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) { #>
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user