Add SPMD lane reductions, gather, and SinCos API changes
- Added MaskLoad, Gather, and reduction methods (ReduceAdd, ReduceMax, ReduceMin) to ISPMDLane<TSelf, TNumber> with XML docs - Changed SinCos to use out parameters instead of tuple return - Implemented reductions in ScalarLane and WideLane (loop-based, TODO: SIMD) - Added GetUnsafePtr to ISPMDLane - Extended MathV to support Sin, Cos, SinCos, Tan, Asin, Acos, Atan, Atan2 for Vector2/3/4 - Improved WideLane.Sequence to use best vector type - Updated GGX mip generation for new SinCos signature - Bumped version to 1.3.2 - Enabled PNG dumping in GGX benchmark
This commit is contained in:
@@ -118,12 +118,52 @@ public unsafe interface ISPMDLane<TSelf, TNumber> : ISPMDLane, IEquatable<TSelf>
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
static abstract TSelf Load(TNumber* pValue);
|
static abstract TSelf Load(TNumber* pValue);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Uses the specified mask to conditionally load lane values from the given reference, returning a lane value where masked lanes are loaded and unmasked lanes are set to zero.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mask">The mask to use for conditional loading.</param>
|
||||||
|
/// <param name="value">The reference to load from.</param>
|
||||||
|
/// <returns>The loaded lane value.</returns>
|
||||||
static abstract TSelf MaskLoad(TSelf mask, ref TNumber value);
|
static abstract TSelf MaskLoad(TSelf mask, ref TNumber value);
|
||||||
|
/// <summary>
|
||||||
|
/// Uses the specified mask to conditionally load lane values from the given pointer, returning a lane value where masked lanes are loaded and unmasked lanes are set to zero.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mask">The mask to use for conditional loading.</param>
|
||||||
|
/// <param name="pValue">The pointer to load from.</param>
|
||||||
|
/// <returns>The loaded lane value.</returns>
|
||||||
static abstract TSelf MaskLoad(TSelf mask, TNumber* pValue);
|
static abstract TSelf MaskLoad(TSelf mask, TNumber* pValue);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gathers lane values from the specified base address and indices, returning a lane value where each lane is loaded from the address computed by adding the corresponding index (multiplied by the scale) to the base address.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pData">The base address from which to gather values.</param>
|
||||||
|
/// <param name="indices">The indices of the values to gather.</param>
|
||||||
|
/// <param name="scale">The scale factor for the indices.</param>
|
||||||
|
/// <returns>The gathered lane value.</returns>
|
||||||
static abstract TSelf Gather(TNumber* pData, TSelf indices, int scale);
|
static abstract TSelf Gather(TNumber* pData, TSelf indices, int scale);
|
||||||
|
/// <summary>
|
||||||
|
/// Gathers lane values from the specified base address and indices, returning a lane value where each lane is loaded from the address computed by adding the corresponding index (multiplied by the scale) to the base address.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pData">The base address from which to gather values.</param>
|
||||||
|
/// <param name="pIndices">The pointer to the indices of the values to gather.</param>
|
||||||
|
/// <param name="scale">The scale factor for the indices.</param>
|
||||||
|
/// <returns>The gathered lane value.</returns>
|
||||||
static abstract TSelf Gather(TNumber* pData, int* pIndices, int scale);
|
static abstract TSelf Gather(TNumber* pData, int* pIndices, int scale);
|
||||||
|
/// <summary>
|
||||||
|
/// Gathers lane values from the specified base address and indices, returning a lane value where each lane is loaded from the address computed by adding the corresponding index (multiplied by the scale) to the base address.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="baseAddress">The base address from which to gather values.</param>
|
||||||
|
/// <param name="indices">The indices of the values to gather.</param>
|
||||||
|
/// <param name="scale">The scale factor for the indices.</param>
|
||||||
|
/// <returns>The gathered lane value.</returns>
|
||||||
static abstract TSelf Gather(ref TNumber baseAddress, TSelf indices, int scale);
|
static abstract TSelf Gather(ref TNumber baseAddress, TSelf indices, int scale);
|
||||||
|
/// <summary>
|
||||||
|
/// Gathers lane values from the specified base address and indices, returning a lane value where each lane is loaded from the address computed by adding the corresponding index (multiplied by the scale) to the base address.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="baseAddress">The base address from which to gather values.</param>
|
||||||
|
/// <param name="baseIndex">The reference to the base index.</param>
|
||||||
|
/// <param name="scale">The scale factor for the indices.</param>
|
||||||
|
/// <returns>The gathered lane value.</returns>
|
||||||
static abstract TSelf Gather(ref TNumber baseAddress, ref int baseIndex, int scale);
|
static abstract TSelf Gather(ref TNumber baseAddress, ref int baseIndex, int scale);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -165,6 +205,10 @@ public unsafe interface ISPMDLane<TSelf, TNumber> : ISPMDLane, IEquatable<TSelf>
|
|||||||
/// <returns>The backing vector representation.</returns>
|
/// <returns>The backing vector representation.</returns>
|
||||||
Vector<TNumber> AsVector();
|
Vector<TNumber> AsVector();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets an pointer to the lane's underlying data.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>An pointer to the lane's underlying data.</returns>
|
||||||
TNumber* GetUnsafePtr();
|
TNumber* GetUnsafePtr();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -403,7 +447,7 @@ public unsafe interface ISPMDLane<TSelf, TNumber> : ISPMDLane, IEquatable<TSelf>
|
|||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Implementations returning both sin and cos simultaneously can reuse intermediate values for better performance.
|
/// Implementations returning both sin and cos simultaneously can reuse intermediate values for better performance.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
static abstract (TSelf sin, TSelf cos) SinCos(TSelf value);
|
static abstract void SinCos(TSelf value, out TSelf sin, out TSelf cos);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Computes the tangent of each lane element.
|
/// Computes the tangent of each lane element.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -552,6 +596,16 @@ public unsafe interface ISPMDLane<TSelf, TNumber> : ISPMDLane, IEquatable<TSelf>
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
static abstract TSelf Rsqrt(TSelf value);
|
static abstract TSelf Rsqrt(TSelf value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Horizontally reduces the lane value by adding all lanes together, returning a single-lane result.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
static abstract TNumber ReduceAdd(TSelf value);
|
||||||
|
static abstract TNumber ReduceMax(TSelf value);
|
||||||
|
static abstract TNumber ReduceMin(TSelf value);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Selects values from two lane values based on a condition mask.
|
/// Selects values from two lane values based on a condition mask.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
<Authors>Misaki</Authors>
|
<Authors>Misaki</Authors>
|
||||||
<AssemblyVersion>1.3.1</AssemblyVersion>
|
<AssemblyVersion>1.3.2</AssemblyVersion>
|
||||||
<Version>$(AssemblyVersion)</Version>
|
<Version>$(AssemblyVersion)</Version>
|
||||||
<PackageProjectUrl>https://git.personalnas.com/Misaki/Misaki.HighPerformance.git</PackageProjectUrl>
|
<PackageProjectUrl>https://git.personalnas.com/Misaki/Misaki.HighPerformance.git</PackageProjectUrl>
|
||||||
<RepositoryUrl>https://git.personalnas.com/Misaki/Misaki.HighPerformance.git</RepositoryUrl>
|
<RepositoryUrl>https://git.personalnas.com/Misaki/Misaki.HighPerformance.git</RepositoryUrl>
|
||||||
|
|||||||
@@ -416,9 +416,27 @@ public readonly unsafe struct ScalarLane<TNumber> : ISPMDLane<ScalarLane<TNumber
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static (ScalarLane<TNumber> sin, ScalarLane<TNumber> cos) SinCos(ScalarLane<TNumber> value)
|
public static void SinCos(ScalarLane<TNumber> value, out ScalarLane<TNumber> sin, out ScalarLane<TNumber> cos)
|
||||||
{
|
{
|
||||||
return (Sin(value), Cos(value));
|
if (typeof(TNumber) == typeof(float))
|
||||||
|
{
|
||||||
|
var f = Unsafe.As<ScalarLane<TNumber>, float>(ref value);
|
||||||
|
var (s, c) = MathF.SinCos(f);
|
||||||
|
sin = Unsafe.As<float, ScalarLane<TNumber>>(ref s);
|
||||||
|
cos = Unsafe.As<float, ScalarLane<TNumber>>(ref c);
|
||||||
|
}
|
||||||
|
else if (typeof(TNumber) == typeof(double))
|
||||||
|
{
|
||||||
|
var d = Unsafe.As<ScalarLane<TNumber>, double>(ref value);
|
||||||
|
var (s, c) = Math.SinCos(d);
|
||||||
|
sin = Unsafe.As<double, ScalarLane<TNumber>>(ref s);
|
||||||
|
cos = Unsafe.As<double, ScalarLane<TNumber>>(ref c);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sin = value;
|
||||||
|
cos = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -702,6 +720,26 @@ public readonly unsafe struct ScalarLane<TNumber> : ISPMDLane<ScalarLane<TNumber
|
|||||||
return Sqrt(Rcp(value));
|
return Sqrt(Rcp(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static TNumber ReduceAdd(ScalarLane<TNumber> value)
|
||||||
|
{
|
||||||
|
return value.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static TNumber ReduceMax(ScalarLane<TNumber> value)
|
||||||
|
{
|
||||||
|
return value.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static TNumber ReduceMin(ScalarLane<TNumber> value)
|
||||||
|
{
|
||||||
|
return value.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static ScalarLane<TNumber> Select(ScalarLane<TNumber> conditionMask, ScalarLane<TNumber> ifTrue, ScalarLane<TNumber> ifFalse)
|
public static ScalarLane<TNumber> Select(ScalarLane<TNumber> conditionMask, ScalarLane<TNumber> ifTrue, ScalarLane<TNumber> ifFalse)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -198,6 +198,39 @@ public static unsafe partial class MathV
|
|||||||
return a.x * b.x + a.y * b.y;
|
return a.x * b.x + a.y * b.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector2<TLane, TNumber> Sin<TLane, TNumber>(in Vector2<TLane, TNumber> vector)
|
||||||
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
||||||
|
{
|
||||||
|
return new Vector2<TLane, TNumber>
|
||||||
|
{
|
||||||
|
x = TLane.Sin(vector.x),
|
||||||
|
y = TLane.Sin(vector.y),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector2<TLane, TNumber> Cos<TLane, TNumber>(in Vector2<TLane, TNumber> vector)
|
||||||
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
||||||
|
{
|
||||||
|
return new Vector2<TLane, TNumber>
|
||||||
|
{
|
||||||
|
x = TLane.Cos(vector.x),
|
||||||
|
y = TLane.Cos(vector.y),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void SinCos<TLane, TNumber>(in Vector2<TLane, TNumber> vector, out Vector2<TLane, TNumber> sin, out Vector2<TLane, TNumber> cos)
|
||||||
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
||||||
|
{
|
||||||
|
TLane.SinCos(vector.x, out sin.x, out cos.x);
|
||||||
|
TLane.SinCos(vector.y, out sin.y, out cos.y);
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static Vector2<TLane, TNumber> Sqrt<TLane, TNumber>(in Vector2<TLane, TNumber> vector)
|
public static Vector2<TLane, TNumber> Sqrt<TLane, TNumber>(in Vector2<TLane, TNumber> vector)
|
||||||
where TLane : ISPMDLane<TLane, TNumber>
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
@@ -210,6 +243,66 @@ public static unsafe partial class MathV
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector2<TLane, TNumber> Tan<TLane, TNumber>(in Vector2<TLane, TNumber> vector)
|
||||||
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
||||||
|
{
|
||||||
|
return new Vector2<TLane, TNumber>
|
||||||
|
{
|
||||||
|
x = TLane.Tan(vector.x),
|
||||||
|
y = TLane.Tan(vector.y),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector2<TLane, TNumber> Asin<TLane, TNumber>(in Vector2<TLane, TNumber> vector)
|
||||||
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
||||||
|
{
|
||||||
|
return new Vector2<TLane, TNumber>
|
||||||
|
{
|
||||||
|
x = TLane.Asin(vector.x),
|
||||||
|
y = TLane.Asin(vector.y),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector2<TLane, TNumber> Acos<TLane, TNumber>(in Vector2<TLane, TNumber> vector)
|
||||||
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
||||||
|
{
|
||||||
|
return new Vector2<TLane, TNumber>
|
||||||
|
{
|
||||||
|
x = TLane.Acos(vector.x),
|
||||||
|
y = TLane.Acos(vector.y),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector2<TLane, TNumber> Atan<TLane, TNumber>(in Vector2<TLane, TNumber> vector)
|
||||||
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
||||||
|
{
|
||||||
|
return new Vector2<TLane, TNumber>
|
||||||
|
{
|
||||||
|
x = TLane.Atan(vector.x),
|
||||||
|
y = TLane.Atan(vector.y),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector2<TLane, TNumber> Atan2<TLane, TNumber>(in Vector2<TLane, TNumber> x, in Vector2<TLane, TNumber> y)
|
||||||
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
||||||
|
{
|
||||||
|
return new Vector2<TLane, TNumber>
|
||||||
|
{
|
||||||
|
x = TLane.Atan2(x.x, y.x),
|
||||||
|
y = TLane.Atan2(x.y, y.y),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static Vector2<TLane, TNumber> Rsqrt<TLane, TNumber>(in Vector2<TLane, TNumber> vector)
|
public static Vector2<TLane, TNumber> Rsqrt<TLane, TNumber>(in Vector2<TLane, TNumber> vector)
|
||||||
where TLane : ISPMDLane<TLane, TNumber>
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
@@ -570,6 +663,42 @@ public static unsafe partial class MathV
|
|||||||
return a.x * b.x + a.y * b.y + a.z * b.z;
|
return a.x * b.x + a.y * b.y + a.z * b.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector3<TLane, TNumber> Sin<TLane, TNumber>(in Vector3<TLane, TNumber> vector)
|
||||||
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
||||||
|
{
|
||||||
|
return new Vector3<TLane, TNumber>
|
||||||
|
{
|
||||||
|
x = TLane.Sin(vector.x),
|
||||||
|
y = TLane.Sin(vector.y),
|
||||||
|
z = TLane.Sin(vector.z),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector3<TLane, TNumber> Cos<TLane, TNumber>(in Vector3<TLane, TNumber> vector)
|
||||||
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
||||||
|
{
|
||||||
|
return new Vector3<TLane, TNumber>
|
||||||
|
{
|
||||||
|
x = TLane.Cos(vector.x),
|
||||||
|
y = TLane.Cos(vector.y),
|
||||||
|
z = TLane.Cos(vector.z),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void SinCos<TLane, TNumber>(in Vector3<TLane, TNumber> vector, out Vector3<TLane, TNumber> sin, out Vector3<TLane, TNumber> cos)
|
||||||
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
||||||
|
{
|
||||||
|
TLane.SinCos(vector.x, out sin.x, out cos.x);
|
||||||
|
TLane.SinCos(vector.y, out sin.y, out cos.y);
|
||||||
|
TLane.SinCos(vector.z, out sin.z, out cos.z);
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static Vector3<TLane, TNumber> Sqrt<TLane, TNumber>(in Vector3<TLane, TNumber> vector)
|
public static Vector3<TLane, TNumber> Sqrt<TLane, TNumber>(in Vector3<TLane, TNumber> vector)
|
||||||
where TLane : ISPMDLane<TLane, TNumber>
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
@@ -583,6 +712,71 @@ public static unsafe partial class MathV
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector3<TLane, TNumber> Tan<TLane, TNumber>(in Vector3<TLane, TNumber> vector)
|
||||||
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
||||||
|
{
|
||||||
|
return new Vector3<TLane, TNumber>
|
||||||
|
{
|
||||||
|
x = TLane.Tan(vector.x),
|
||||||
|
y = TLane.Tan(vector.y),
|
||||||
|
z = TLane.Tan(vector.z),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector3<TLane, TNumber> Asin<TLane, TNumber>(in Vector3<TLane, TNumber> vector)
|
||||||
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
||||||
|
{
|
||||||
|
return new Vector3<TLane, TNumber>
|
||||||
|
{
|
||||||
|
x = TLane.Asin(vector.x),
|
||||||
|
y = TLane.Asin(vector.y),
|
||||||
|
z = TLane.Asin(vector.z),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector3<TLane, TNumber> Acos<TLane, TNumber>(in Vector3<TLane, TNumber> vector)
|
||||||
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
||||||
|
{
|
||||||
|
return new Vector3<TLane, TNumber>
|
||||||
|
{
|
||||||
|
x = TLane.Acos(vector.x),
|
||||||
|
y = TLane.Acos(vector.y),
|
||||||
|
z = TLane.Acos(vector.z),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector3<TLane, TNumber> Atan<TLane, TNumber>(in Vector3<TLane, TNumber> vector)
|
||||||
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
||||||
|
{
|
||||||
|
return new Vector3<TLane, TNumber>
|
||||||
|
{
|
||||||
|
x = TLane.Atan(vector.x),
|
||||||
|
y = TLane.Atan(vector.y),
|
||||||
|
z = TLane.Atan(vector.z),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector3<TLane, TNumber> Atan2<TLane, TNumber>(in Vector3<TLane, TNumber> x, in Vector3<TLane, TNumber> y)
|
||||||
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
||||||
|
{
|
||||||
|
return new Vector3<TLane, TNumber>
|
||||||
|
{
|
||||||
|
x = TLane.Atan2(x.x, y.x),
|
||||||
|
y = TLane.Atan2(x.y, y.y),
|
||||||
|
z = TLane.Atan2(x.z, y.z),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static Vector3<TLane, TNumber> Rsqrt<TLane, TNumber>(in Vector3<TLane, TNumber> vector)
|
public static Vector3<TLane, TNumber> Rsqrt<TLane, TNumber>(in Vector3<TLane, TNumber> vector)
|
||||||
where TLane : ISPMDLane<TLane, TNumber>
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
@@ -964,6 +1158,45 @@ public static unsafe partial class MathV
|
|||||||
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
|
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector4<TLane, TNumber> Sin<TLane, TNumber>(in Vector4<TLane, TNumber> vector)
|
||||||
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
||||||
|
{
|
||||||
|
return new Vector4<TLane, TNumber>
|
||||||
|
{
|
||||||
|
x = TLane.Sin(vector.x),
|
||||||
|
y = TLane.Sin(vector.y),
|
||||||
|
z = TLane.Sin(vector.z),
|
||||||
|
w = TLane.Sin(vector.w),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector4<TLane, TNumber> Cos<TLane, TNumber>(in Vector4<TLane, TNumber> vector)
|
||||||
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
||||||
|
{
|
||||||
|
return new Vector4<TLane, TNumber>
|
||||||
|
{
|
||||||
|
x = TLane.Cos(vector.x),
|
||||||
|
y = TLane.Cos(vector.y),
|
||||||
|
z = TLane.Cos(vector.z),
|
||||||
|
w = TLane.Cos(vector.w),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void SinCos<TLane, TNumber>(in Vector4<TLane, TNumber> vector, out Vector4<TLane, TNumber> sin, out Vector4<TLane, TNumber> cos)
|
||||||
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
||||||
|
{
|
||||||
|
TLane.SinCos(vector.x, out sin.x, out cos.x);
|
||||||
|
TLane.SinCos(vector.y, out sin.y, out cos.y);
|
||||||
|
TLane.SinCos(vector.z, out sin.z, out cos.z);
|
||||||
|
TLane.SinCos(vector.w, out sin.w, out cos.w);
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static Vector4<TLane, TNumber> Sqrt<TLane, TNumber>(in Vector4<TLane, TNumber> vector)
|
public static Vector4<TLane, TNumber> Sqrt<TLane, TNumber>(in Vector4<TLane, TNumber> vector)
|
||||||
where TLane : ISPMDLane<TLane, TNumber>
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
@@ -978,6 +1211,76 @@ public static unsafe partial class MathV
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector4<TLane, TNumber> Tan<TLane, TNumber>(in Vector4<TLane, TNumber> vector)
|
||||||
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
||||||
|
{
|
||||||
|
return new Vector4<TLane, TNumber>
|
||||||
|
{
|
||||||
|
x = TLane.Tan(vector.x),
|
||||||
|
y = TLane.Tan(vector.y),
|
||||||
|
z = TLane.Tan(vector.z),
|
||||||
|
w = TLane.Tan(vector.w),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector4<TLane, TNumber> Asin<TLane, TNumber>(in Vector4<TLane, TNumber> vector)
|
||||||
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
||||||
|
{
|
||||||
|
return new Vector4<TLane, TNumber>
|
||||||
|
{
|
||||||
|
x = TLane.Asin(vector.x),
|
||||||
|
y = TLane.Asin(vector.y),
|
||||||
|
z = TLane.Asin(vector.z),
|
||||||
|
w = TLane.Asin(vector.w),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector4<TLane, TNumber> Acos<TLane, TNumber>(in Vector4<TLane, TNumber> vector)
|
||||||
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
||||||
|
{
|
||||||
|
return new Vector4<TLane, TNumber>
|
||||||
|
{
|
||||||
|
x = TLane.Acos(vector.x),
|
||||||
|
y = TLane.Acos(vector.y),
|
||||||
|
z = TLane.Acos(vector.z),
|
||||||
|
w = TLane.Acos(vector.w),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector4<TLane, TNumber> Atan<TLane, TNumber>(in Vector4<TLane, TNumber> vector)
|
||||||
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
||||||
|
{
|
||||||
|
return new Vector4<TLane, TNumber>
|
||||||
|
{
|
||||||
|
x = TLane.Atan(vector.x),
|
||||||
|
y = TLane.Atan(vector.y),
|
||||||
|
z = TLane.Atan(vector.z),
|
||||||
|
w = TLane.Atan(vector.w),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static Vector4<TLane, TNumber> Atan2<TLane, TNumber>(in Vector4<TLane, TNumber> x, in Vector4<TLane, TNumber> y)
|
||||||
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
||||||
|
{
|
||||||
|
return new Vector4<TLane, TNumber>
|
||||||
|
{
|
||||||
|
x = TLane.Atan2(x.x, y.x),
|
||||||
|
y = TLane.Atan2(x.y, y.y),
|
||||||
|
z = TLane.Atan2(x.z, y.z),
|
||||||
|
w = TLane.Atan2(x.w, y.w),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static Vector4<TLane, TNumber> Rsqrt<TLane, TNumber>(in Vector4<TLane, TNumber> vector)
|
public static Vector4<TLane, TNumber> Rsqrt<TLane, TNumber>(in Vector4<TLane, TNumber> vector)
|
||||||
where TLane : ISPMDLane<TLane, TNumber>
|
where TLane : ISPMDLane<TLane, TNumber>
|
||||||
|
|||||||
@@ -233,6 +233,42 @@ public static unsafe partial class MathV
|
|||||||
return <#= ForEachDimension(dimension, i => $"a.{components[i]} * b.{components[i]}", " + ") #>;
|
return <#= ForEachDimension(dimension, i => $"a.{components[i]} * b.{components[i]}", " + ") #>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static <#= vectorType #> Sin<<#= GenericParameters #>>(in <#= vectorType #> vector)
|
||||||
|
<#= TLaneRestrictions #>
|
||||||
|
<#= TNumberRestrictions #>
|
||||||
|
{
|
||||||
|
return new <#= vectorType #>
|
||||||
|
{
|
||||||
|
<# for (int i = 0; i < dimension; i++) { #>
|
||||||
|
<#= components[i] #> = <#= TLane #>.Sin(vector.<#= components[i] #>),
|
||||||
|
<# } #>
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static <#= vectorType #> Cos<<#= GenericParameters #>>(in <#= vectorType #> vector)
|
||||||
|
<#= TLaneRestrictions #>
|
||||||
|
<#= TNumberRestrictions #>
|
||||||
|
{
|
||||||
|
return new <#= vectorType #>
|
||||||
|
{
|
||||||
|
<# for (int i = 0; i < dimension; i++) { #>
|
||||||
|
<#= components[i] #> = <#= TLane #>.Cos(vector.<#= components[i] #>),
|
||||||
|
<# } #>
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static void SinCos<<#= GenericParameters #>>(in <#= vectorType #> vector, out <#= vectorType #> sin, out <#= vectorType #> cos)
|
||||||
|
<#= TLaneRestrictions #>
|
||||||
|
<#= TNumberRestrictions #>
|
||||||
|
{
|
||||||
|
<# for (int i = 0; i < dimension; i++) { #>
|
||||||
|
<#= TLane #>.SinCos(vector.<#= components[i] #>, out sin.<#= components[i] #>, out cos.<#= components[i] #>);
|
||||||
|
<# } #>
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static <#= vectorType #> Sqrt<<#= GenericParameters #>>(in <#= vectorType #> vector)
|
public static <#= vectorType #> Sqrt<<#= GenericParameters #>>(in <#= vectorType #> vector)
|
||||||
<#= TLaneRestrictions #>
|
<#= TLaneRestrictions #>
|
||||||
@@ -246,6 +282,71 @@ public static unsafe partial class MathV
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static <#= vectorType #> Tan<<#= GenericParameters #>>(in <#= vectorType #> vector)
|
||||||
|
<#= TLaneRestrictions #>
|
||||||
|
<#= TNumberRestrictions #>
|
||||||
|
{
|
||||||
|
return new <#= vectorType #>
|
||||||
|
{
|
||||||
|
<# for (int i = 0; i < dimension; i++) { #>
|
||||||
|
<#= components[i] #> = <#= TLane #>.Tan(vector.<#= components[i] #>),
|
||||||
|
<# } #>
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static <#= vectorType #> Asin<<#= GenericParameters #>>(in <#= vectorType #> vector)
|
||||||
|
<#= TLaneRestrictions #>
|
||||||
|
<#= TNumberRestrictions #>
|
||||||
|
{
|
||||||
|
return new <#= vectorType #>
|
||||||
|
{
|
||||||
|
<# for (int i = 0; i < dimension; i++) { #>
|
||||||
|
<#= components[i] #> = <#= TLane #>.Asin(vector.<#= components[i] #>),
|
||||||
|
<# } #>
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static <#= vectorType #> Acos<<#= GenericParameters #>>(in <#= vectorType #> vector)
|
||||||
|
<#= TLaneRestrictions #>
|
||||||
|
<#= TNumberRestrictions #>
|
||||||
|
{
|
||||||
|
return new <#= vectorType #>
|
||||||
|
{
|
||||||
|
<# for (int i = 0; i < dimension; i++) { #>
|
||||||
|
<#= components[i] #> = <#= TLane #>.Acos(vector.<#= components[i] #>),
|
||||||
|
<# } #>
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static <#= vectorType #> Atan<<#= GenericParameters #>>(in <#= vectorType #> vector)
|
||||||
|
<#= TLaneRestrictions #>
|
||||||
|
<#= TNumberRestrictions #>
|
||||||
|
{
|
||||||
|
return new <#= vectorType #>
|
||||||
|
{
|
||||||
|
<# for (int i = 0; i < dimension; i++) { #>
|
||||||
|
<#= components[i] #> = <#= TLane #>.Atan(vector.<#= components[i] #>),
|
||||||
|
<# } #>
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static <#= vectorType #> Atan2<<#= GenericParameters #>>(in <#= vectorType #> x, in <#= vectorType #> y)
|
||||||
|
<#= TLaneRestrictions #>
|
||||||
|
<#= TNumberRestrictions #>
|
||||||
|
{
|
||||||
|
return new <#= vectorType #>
|
||||||
|
{
|
||||||
|
<# for (int i = 0; i < dimension; i++) { #>
|
||||||
|
<#= components[i] #> = <#= TLane #>.Atan2(x.<#= components[i] #>, y.<#= components[i] #>),
|
||||||
|
<# } #>
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static <#= vectorType #> Rsqrt<<#= GenericParameters #>>(in <#= vectorType #> vector)
|
public static <#= vectorType #> Rsqrt<<#= GenericParameters #>>(in <#= vectorType #> vector)
|
||||||
<#= TLaneRestrictions #>
|
<#= TLaneRestrictions #>
|
||||||
|
|||||||
@@ -151,9 +151,32 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNu
|
|||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> Sequence(TNumber start, TNumber step)
|
public static WideLane<TNumber> Sequence(TNumber start, TNumber step)
|
||||||
|
{
|
||||||
|
if (LaneWidth == Vector512<TNumber>.Count)
|
||||||
|
{
|
||||||
|
var v = Vector512.CreateSequence(start, step);
|
||||||
|
return Unsafe.As<Vector512<TNumber>, WideLane<TNumber>>(ref v);
|
||||||
|
}
|
||||||
|
else if (LaneWidth == Vector256<TNumber>.Count)
|
||||||
|
{
|
||||||
|
var v = Vector256.CreateSequence(start, step);
|
||||||
|
return Unsafe.As<Vector256<TNumber>, WideLane<TNumber>>(ref v);
|
||||||
|
}
|
||||||
|
else if (LaneWidth == Vector128<TNumber>.Count)
|
||||||
|
{
|
||||||
|
var v = Vector128.CreateSequence(start, step);
|
||||||
|
return Unsafe.As<Vector128<TNumber>, WideLane<TNumber>>(ref v);
|
||||||
|
}
|
||||||
|
else if (LaneWidth == Vector64<TNumber>.Count)
|
||||||
|
{
|
||||||
|
var v = Vector64.CreateSequence(start, step);
|
||||||
|
return Unsafe.As<Vector64<TNumber>, WideLane<TNumber>>(ref v);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(Vector.Create(start) + (Vector.Create(step) * s_indices));
|
return new WideLane<TNumber>(Vector.Create(start) + (Vector.Create(step) * s_indices));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> Load(ref TNumber value)
|
public static WideLane<TNumber> Load(ref TNumber value)
|
||||||
@@ -641,7 +664,7 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNu
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static (WideLane<TNumber> sin, WideLane<TNumber> cos) SinCos(WideLane<TNumber> value)
|
public static void SinCos(WideLane<TNumber> value, out WideLane<TNumber> sin, out WideLane<TNumber> cos)
|
||||||
{
|
{
|
||||||
var halfPi = Create(TNumber.CreateTruncating(1.570796327f));
|
var halfPi = Create(TNumber.CreateTruncating(1.570796327f));
|
||||||
var invPi = Create(TNumber.CreateTruncating(0.318309886f)); // 1 / PI
|
var invPi = Create(TNumber.CreateTruncating(0.318309886f)); // 1 / PI
|
||||||
@@ -700,7 +723,8 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNu
|
|||||||
poly_cos = MultipleAdd(z2_cos, poly_cos, c1);
|
poly_cos = MultipleAdd(z2_cos, poly_cos, c1);
|
||||||
poly_cos = z_cos * poly_cos;
|
poly_cos = z_cos * poly_cos;
|
||||||
|
|
||||||
return (poly_sin * sign_sin, poly_cos * sign_cos);
|
sin = poly_sin * sign_sin;
|
||||||
|
cos = poly_cos * sign_cos;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -976,13 +1000,13 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNu
|
|||||||
{
|
{
|
||||||
if (Sse.IsSupported && LaneWidth == Vector128<float>.Count)
|
if (Sse.IsSupported && LaneWidth == Vector128<float>.Count)
|
||||||
{
|
{
|
||||||
var vf = Unsafe.As<WideLane<TNumber>, Vector128<float>>(ref value);
|
ref var vf = ref Unsafe.As<WideLane<TNumber>, Vector128<float>>(ref value);
|
||||||
var result = Sse.Reciprocal(vf);
|
var result = Sse.Reciprocal(vf);
|
||||||
return Unsafe.As<Vector128<float>, WideLane<TNumber>>(ref result);
|
return Unsafe.As<Vector128<float>, WideLane<TNumber>>(ref result);
|
||||||
}
|
}
|
||||||
else if (Avx.IsSupported && LaneWidth == Vector256<float>.Count)
|
else if (Avx.IsSupported && LaneWidth == Vector256<float>.Count)
|
||||||
{
|
{
|
||||||
var vf = Unsafe.As<WideLane<TNumber>, Vector256<float>>(ref value);
|
ref var vf = ref Unsafe.As<WideLane<TNumber>, Vector256<float>>(ref value);
|
||||||
var result = Avx.Reciprocal(vf);
|
var result = Avx.Reciprocal(vf);
|
||||||
return Unsafe.As<Vector256<float>, WideLane<TNumber>>(ref result);
|
return Unsafe.As<Vector256<float>, WideLane<TNumber>>(ref result);
|
||||||
}
|
}
|
||||||
@@ -998,13 +1022,13 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNu
|
|||||||
{
|
{
|
||||||
if (Sse.IsSupported && LaneWidth == Vector128<float>.Count)
|
if (Sse.IsSupported && LaneWidth == Vector128<float>.Count)
|
||||||
{
|
{
|
||||||
var vf = Unsafe.As<WideLane<TNumber>, Vector128<float>>(ref value);
|
ref var vf = ref Unsafe.As<WideLane<TNumber>, Vector128<float>>(ref value);
|
||||||
var result = Sse.ReciprocalSqrt(vf);
|
var result = Sse.ReciprocalSqrt(vf);
|
||||||
return Unsafe.As<Vector128<float>, WideLane<TNumber>>(ref result);
|
return Unsafe.As<Vector128<float>, WideLane<TNumber>>(ref result);
|
||||||
}
|
}
|
||||||
else if (Avx.IsSupported && LaneWidth == Vector256<float>.Count)
|
else if (Avx.IsSupported && LaneWidth == Vector256<float>.Count)
|
||||||
{
|
{
|
||||||
var vf = Unsafe.As<WideLane<TNumber>, Vector256<float>>(ref value);
|
ref var vf = ref Unsafe.As<WideLane<TNumber>, Vector256<float>>(ref value);
|
||||||
var result = Avx.ReciprocalSqrt(vf);
|
var result = Avx.ReciprocalSqrt(vf);
|
||||||
return Unsafe.As<Vector256<float>, WideLane<TNumber>>(ref result);
|
return Unsafe.As<Vector256<float>, WideLane<TNumber>>(ref result);
|
||||||
}
|
}
|
||||||
@@ -1014,6 +1038,54 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNu
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static TNumber ReduceAdd(WideLane<TNumber> value)
|
||||||
|
{
|
||||||
|
// TODO: Use shuffle and add.
|
||||||
|
|
||||||
|
var result = TNumber.Zero;
|
||||||
|
for (var i = 0; i < LaneWidth; i++)
|
||||||
|
{
|
||||||
|
result += value[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static TNumber ReduceMax(WideLane<TNumber> value)
|
||||||
|
{
|
||||||
|
// TODO: Use shuffle and max.
|
||||||
|
|
||||||
|
var max = TNumber.Zero;
|
||||||
|
for (var i = 0; i < LaneWidth; i++)
|
||||||
|
{
|
||||||
|
if (value[i] > max)
|
||||||
|
{
|
||||||
|
max = value[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static TNumber ReduceMin(WideLane<TNumber> value)
|
||||||
|
{
|
||||||
|
// TODO: Use shuffle and min.
|
||||||
|
|
||||||
|
var min = TNumber.Zero;
|
||||||
|
for (var i = 0; i < LaneWidth; i++)
|
||||||
|
{
|
||||||
|
if (value[i] < min)
|
||||||
|
{
|
||||||
|
min = value[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> Select(WideLane<TNumber> conditionMask, WideLane<TNumber> ifTrue, WideLane<TNumber> ifFalse)
|
public static WideLane<TNumber> Select(WideLane<TNumber> conditionMask, WideLane<TNumber> ifTrue, WideLane<TNumber> ifFalse)
|
||||||
|
|||||||
@@ -63,16 +63,11 @@ internal unsafe struct GGXMipGenerationJobSPMD<TFloat, TInt> : IJobParallelFor
|
|||||||
|
|
||||||
var phi = 2.0f * PI * Xi.x;
|
var phi = 2.0f * PI * Xi.x;
|
||||||
|
|
||||||
// Clamp the inside of the cosTheta Sqrt to prevent NaN on division precision edges
|
var cosTheta = TFloat.Sqrt((1.0f - Xi.y) / (1.0f + (a * a - 1.0f) * Xi.y));
|
||||||
var cosThetaInner = TFloat.Max((1.0f - Xi.y) / (1.0f + (a * a - 1.0f) * Xi.y), TFloat.Zero);
|
var sinTheta = TFloat.Sqrt(1.0f - cosTheta * cosTheta);
|
||||||
var cosTheta = TFloat.Sqrt(cosThetaInner);
|
|
||||||
|
|
||||||
// Clamp the inside of sinTheta to prevent sqrt of negative floating-point errors
|
|
||||||
var sinThetaInner = TFloat.Max(1.0f - cosTheta * cosTheta, TFloat.Zero);
|
|
||||||
var sinTheta = TFloat.Sqrt(sinThetaInner);
|
|
||||||
|
|
||||||
// Spherical to Cartesian coordinates (Halfway vector)
|
// Spherical to Cartesian coordinates (Halfway vector)
|
||||||
var (sinPhi, cosPhi) = TFloat.SinCos(phi);
|
TFloat.SinCos(phi, out var sinPhi, out var cosPhi);
|
||||||
var H = MathV.Create<TFloat, float>(cosPhi * sinTheta, sinPhi * sinTheta, cosTheta);
|
var H = MathV.Create<TFloat, float>(cosPhi * sinTheta, sinPhi * sinTheta, cosTheta);
|
||||||
|
|
||||||
// Tangent space to World space
|
// Tangent space to World space
|
||||||
@@ -496,7 +491,7 @@ public unsafe class GGXMipGenerationBenchmark
|
|||||||
[GlobalCleanup]
|
[GlobalCleanup]
|
||||||
public void Cleanup()
|
public void Cleanup()
|
||||||
{
|
{
|
||||||
#if false
|
#if true
|
||||||
for (var i = 0; i < _mipLevels; i++)
|
for (var i = 0; i < _mipLevels; i++)
|
||||||
{
|
{
|
||||||
DumpMipLevelToPng(_pResult[i], (int)_pMipLevels[i].width, (int)_pMipLevels[i].height, $"C:\\Users\\Misaki\\Downloads\\Im\\mip_level_{i}.png");
|
DumpMipLevelToPng(_pResult[i], (int)_pMipLevels[i].width, (int)_pMipLevels[i].height, $"C:\\Users\\Misaki\\Downloads\\Im\\mip_level_{i}.png");
|
||||||
|
|||||||
Reference in New Issue
Block a user