Refactor vector API codegen and WideLane conversions
- Introduce IVectorAPIContext abstraction and supporting types for vectorized code generation - Add Avx2APIContext and UtilityTemplate for AVX2-specific code emission - Dynamically generate AVX2 sine methods in AVX2Rewriter - Refactor WideLane<TNumber> to use Unsafe.BitCast for all Vector conversions - Update all WideLane operators and math methods to use Unsafe.BitCast - Change MultiplyAdd parameter names for clarity - Remove static indices field in favor of Vector<TNumber>.Indices - Add implicit conversion from Vector<TNumber> to WideLane<TNumber> - Update tests and program files for compatibility
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
using Misaki.HighPerformance.HPC.Generator.VectorAPI;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Misaki.HighPerformance.HPC.Generator
|
namespace Misaki.HighPerformance.HPC.Generator
|
||||||
@@ -11,28 +12,39 @@ namespace Misaki.HighPerformance.HPC.Generator
|
|||||||
{
|
{
|
||||||
context.RegisterPostInitializationOutput(static ctx =>
|
context.RegisterPostInitializationOutput(static ctx =>
|
||||||
{
|
{
|
||||||
var source = @"
|
var api = new Avx2APIContext();
|
||||||
|
|
||||||
|
var sinFloat_standard = UtilityTemplate.SinFloat_Standard(api);
|
||||||
|
var sinFloat_fast = UtilityTemplate.SinFloat_Fast(api);
|
||||||
|
|
||||||
|
var source = @$"
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.Intrinsics;
|
using System.Runtime.Intrinsics;
|
||||||
using System.Runtime.Intrinsics.X86;
|
using System.Runtime.Intrinsics.X86;
|
||||||
|
|
||||||
namespace Misaki.HighPerformance.HPC
|
namespace Misaki.HighPerformance.HPC
|
||||||
{
|
{{
|
||||||
public static class AVX2Utility
|
public static class AVX2Utility
|
||||||
{
|
{{
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
|
{sinFloat_standard.GetFullCode(" ")}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
{sinFloat_fast.GetFullCode(" ")}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static Vector256<float> Asin(Vector256<float> value)
|
public static Vector256<float> Asin(Vector256<float> value)
|
||||||
{
|
{{
|
||||||
// asin(value) = pi/2 - acos(value)
|
// asin(value) = pi/2 - acos(value)
|
||||||
|
|
||||||
var piOver2 = Vector256.Create(MathF.PI / 2.0f);
|
var piOver2 = Vector256.Create(MathF.PI / 2.0f);
|
||||||
return Avx2.Subtract(piOver2, Acos(value));
|
return Avx2.Subtract(piOver2, Acos(value));
|
||||||
}
|
}}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static Vector256<float> Acos(Vector256<float> value)
|
public static Vector256<float> Acos(Vector256<float> value)
|
||||||
{
|
{{
|
||||||
// 0 <= value <= 1 : acos(value) = sqrt(1 - value) * (c0 + c1*value + c2*value^2 + c3*value^3)
|
// 0 <= value <= 1 : acos(value) = sqrt(1 - value) * (c0 + c1*value + c2*value^2 + c3*value^3)
|
||||||
// value < 0 : acos(value) = pi - acos(-value)
|
// value < 0 : acos(value) = pi - acos(-value)
|
||||||
|
|
||||||
@@ -54,11 +66,11 @@ namespace Misaki.HighPerformance.HPC
|
|||||||
var isNegative = Avx2.CompareLessThan(value, Vector256<float>.Zero);
|
var isNegative = Avx2.CompareLessThan(value, Vector256<float>.Zero);
|
||||||
|
|
||||||
return Avx2.BlendVariable(pi, Avx2.Subtract(pi, result), isNegative);
|
return Avx2.BlendVariable(pi, Avx2.Subtract(pi, result), isNegative);
|
||||||
}
|
}}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static Vector256<float> Atan2(Vector256<float> y, Vector256<float> x)
|
public static Vector256<float> Atan2(Vector256<float> y, Vector256<float> x)
|
||||||
{
|
{{
|
||||||
var absX = Vector256.Abs(x);
|
var absX = Vector256.Abs(x);
|
||||||
var absY = Vector256.Abs(y);
|
var absY = Vector256.Abs(y);
|
||||||
|
|
||||||
@@ -103,9 +115,9 @@ namespace Misaki.HighPerformance.HPC
|
|||||||
// (This works because our ratio logic effectively computed atan(|y|/|value|) above)
|
// (This works because our ratio logic effectively computed atan(|y|/|value|) above)
|
||||||
var negativeResult = Avx2.Subtract(Vector256<float>.Zero, result);
|
var negativeResult = Avx2.Subtract(Vector256<float>.Zero, result);
|
||||||
return Avx2.BlendVariable(negativeResult, result, yLtZero);
|
return Avx2.BlendVariable(negativeResult, result, yLtZero);
|
||||||
}
|
}}
|
||||||
}
|
}}
|
||||||
}";
|
}}";
|
||||||
|
|
||||||
ctx.AddSource("AVX2Utility.g.cs", source);
|
ctx.AddSource("AVX2Utility.g.cs", source);
|
||||||
});
|
});
|
||||||
|
|||||||
58
Misaki.HighPerformance.HPC.Generator/UtilityTemplate.cs
Normal file
58
Misaki.HighPerformance.HPC.Generator/UtilityTemplate.cs
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
using Misaki.HighPerformance.HPC.Generator.VectorAPI;
|
||||||
|
|
||||||
|
namespace Misaki.HighPerformance.HPC.Generator
|
||||||
|
{
|
||||||
|
internal static class UtilityTemplate
|
||||||
|
{
|
||||||
|
public static Method SinFloat_Standard(IVectorAPIContext api)
|
||||||
|
{
|
||||||
|
var body = api.Return(api.Call("Sin", "value"));
|
||||||
|
return new Method(
|
||||||
|
modifier: "public static",
|
||||||
|
returnType: api.GetVectorType<float>(),
|
||||||
|
name: $"SinFloat_Standard",
|
||||||
|
parameters: new[] { $"{api.GetVectorType<float>()} value" },
|
||||||
|
body: body);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Method SinFloat_Fast(IVectorAPIContext api)
|
||||||
|
{
|
||||||
|
var invPi = api.Create("0.318309886f").Assign();
|
||||||
|
|
||||||
|
var x_sin = new Expression(api, "value").Assign();
|
||||||
|
var y_sin = api.Multiply(x_sin, invPi).Assign();
|
||||||
|
var k_sin = api.Round(y_sin).Assign();
|
||||||
|
var z_sin = api.Subtract(y_sin, k_sin).Assign();
|
||||||
|
|
||||||
|
var half = api.Create("0.5f").Assign();
|
||||||
|
var two = api.Create("2.0f").Assign();
|
||||||
|
|
||||||
|
var k_even_sin = (api.Round(k_sin * half) * two).Assign();
|
||||||
|
var sign_sin = (api.One<float>() - two * api.Abs(k_sin - k_even_sin)).Assign();
|
||||||
|
|
||||||
|
var c1 = api.Create("3.14159265f").Assign();
|
||||||
|
var c3 = api.Create("-5.16771278f").Assign();
|
||||||
|
var c5 = api.Create("2.55016404f").Assign();
|
||||||
|
var c7 = api.Create("-0.59926453f").Assign();
|
||||||
|
var c9 = api.Create("0.08214589f").Assign();
|
||||||
|
|
||||||
|
var z2_sin = (z_sin * z_sin).Assign();
|
||||||
|
var poly_sin = api.MultiplyAdd(z2_sin, c9, c7).Assign();
|
||||||
|
|
||||||
|
var poly_sin_name = api.LastAssignedVariable;
|
||||||
|
poly_sin = api.MultiplyAdd(z2_sin, poly_sin, c5).Assign(poly_sin_name, false);
|
||||||
|
poly_sin = api.MultiplyAdd(z2_sin, poly_sin, c3).Assign(poly_sin_name, false);
|
||||||
|
poly_sin = api.MultiplyAdd(z2_sin, poly_sin, c1).Assign(poly_sin_name, false);
|
||||||
|
poly_sin = api.Multiply(z_sin, poly_sin).Assign(poly_sin_name, false);
|
||||||
|
|
||||||
|
var body = api.Return(poly_sin * sign_sin);
|
||||||
|
|
||||||
|
return new Method(
|
||||||
|
modifier: "public static",
|
||||||
|
returnType: api.GetVectorType<float>(),
|
||||||
|
name: $"SinFloat_Fast",
|
||||||
|
parameters: new[] { $"{api.GetVectorType<float>()} value" },
|
||||||
|
body: body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
117
Misaki.HighPerformance.HPC.Generator/VectorAPI/Avx2APIContext.cs
Normal file
117
Misaki.HighPerformance.HPC.Generator/VectorAPI/Avx2APIContext.cs
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Misaki.HighPerformance.HPC.Generator.VectorAPI
|
||||||
|
{
|
||||||
|
internal class Avx2APIContext : IVectorAPIContext
|
||||||
|
{
|
||||||
|
private readonly List<string> _statements = new();
|
||||||
|
private int _varCount = 0;
|
||||||
|
private string? _lastAssignedVariable;
|
||||||
|
|
||||||
|
public string? LastAssignedVariable => _lastAssignedVariable;
|
||||||
|
|
||||||
|
public string GetVectorType()
|
||||||
|
{
|
||||||
|
return "Vector256";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetVectorType<T>()
|
||||||
|
{
|
||||||
|
return $"Vector256<{VectorAPIContext.GetTypeName<T>()}>";
|
||||||
|
}
|
||||||
|
|
||||||
|
public Expression Call(string methodName, params string[] args)
|
||||||
|
{
|
||||||
|
return new Expression(this, $"{GetVectorType()}.{methodName}({string.Join(", ", args)})");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Expression Assign(Expression expr, string? varName = null, bool isNew = true)
|
||||||
|
{
|
||||||
|
varName ??= $"v{_varCount++}";
|
||||||
|
|
||||||
|
var statement = isNew ? $"var {varName} = {expr.Code};" : $"{varName} = {expr.Code};";
|
||||||
|
_statements.Add(statement);
|
||||||
|
_lastAssignedVariable = varName;
|
||||||
|
|
||||||
|
expr.Clear();
|
||||||
|
return new Expression(this, varName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Code Return(Expression expr)
|
||||||
|
{
|
||||||
|
var statement = $"return {expr.Code};";
|
||||||
|
_statements.Add(statement);
|
||||||
|
expr.Clear();
|
||||||
|
|
||||||
|
var fullCode = new Code(_statements);
|
||||||
|
Reset();
|
||||||
|
|
||||||
|
return fullCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Expression Create(string value)
|
||||||
|
{
|
||||||
|
return new Expression(this, $"{GetVectorType()}.Create({value})");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Expression Zero<T>()
|
||||||
|
{
|
||||||
|
return new Expression(this, $"{GetVectorType<T>()}.Zero");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Expression One<T>()
|
||||||
|
{
|
||||||
|
return new Expression(this, $"{GetVectorType<T>()}.One");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Expression Count<T>()
|
||||||
|
{
|
||||||
|
return new Expression(this, $"{GetVectorType<T>()}.Count");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Expression Add(Expression a, Expression b)
|
||||||
|
{
|
||||||
|
return new Expression(this, $"Avx2.Add({a}, {b})");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Expression Multiply(Expression a, Expression b)
|
||||||
|
{
|
||||||
|
return new Expression(this, $"Avx2.Multiply({a}, {b})");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Expression Subtract(Expression a, Expression b)
|
||||||
|
{
|
||||||
|
return new Expression(this, $"Avx2.Subtract({a}, {b})");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Expression Divide(Expression a, Expression b)
|
||||||
|
{
|
||||||
|
return new Expression(this, $"Avx2.Divide({a}, {b})");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Expression MultiplyAdd(Expression left, Expression right, Expression addend)
|
||||||
|
{
|
||||||
|
return new Expression(this, $"Fma.MultiplyAdd({left}, {right}, {addend})");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Expression Round(Expression value)
|
||||||
|
{
|
||||||
|
return new Expression(this, $"Avx2.RoundToNearestInteger({value})");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Expression Abs(Expression value)
|
||||||
|
{
|
||||||
|
return new Expression(this, $"{GetVectorType()}.Abs({value})");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
_statements.Clear();
|
||||||
|
_varCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,179 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Misaki.HighPerformance.HPC.Generator.VectorAPI
|
||||||
|
{
|
||||||
|
internal class Expression
|
||||||
|
{
|
||||||
|
public IVectorAPIContext API
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Code
|
||||||
|
{
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Expression(IVectorAPIContext api, string code)
|
||||||
|
{
|
||||||
|
API = api;
|
||||||
|
Code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Expression Assign(string? varName = null, bool isNew = true)
|
||||||
|
{
|
||||||
|
return API.Assign(this, varName, isNew);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
Code = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Expression operator +(Expression a, Expression b)
|
||||||
|
{
|
||||||
|
return a.API.Add(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Expression operator -(Expression a, Expression b)
|
||||||
|
{
|
||||||
|
return a.API.Subtract(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Expression operator *(Expression a, Expression b)
|
||||||
|
{
|
||||||
|
return a.API.Multiply(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Expression operator /(Expression a, Expression b)
|
||||||
|
{
|
||||||
|
return a.API.Divide(a, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal record Code
|
||||||
|
{
|
||||||
|
private readonly string[] _statements;
|
||||||
|
|
||||||
|
public Code(IEnumerable<string> statements)
|
||||||
|
{
|
||||||
|
_statements = statements.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetFullCode(string lineIndentation)
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
foreach (var stmt in _statements)
|
||||||
|
{
|
||||||
|
sb.AppendLine(lineIndentation + stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal record Method
|
||||||
|
{
|
||||||
|
public string Modifier
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ReturnType
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string[] Parameters
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Code Body
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Method(string modifier, string returnType, string name, string[] parameters, Code body)
|
||||||
|
{
|
||||||
|
Modifier = modifier;
|
||||||
|
ReturnType = returnType;
|
||||||
|
Name = name;
|
||||||
|
Parameters = parameters;
|
||||||
|
Body = body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetFullCode(string lineIndentation)
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.AppendLine(lineIndentation + $"{Modifier} {ReturnType} {Name}({string.Join(", ", Parameters)})");
|
||||||
|
sb.AppendLine(lineIndentation + "{");
|
||||||
|
sb.Append(Body.GetFullCode(lineIndentation + " "));
|
||||||
|
sb.AppendLine(lineIndentation + "}");
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal interface IVectorAPIContext
|
||||||
|
{
|
||||||
|
string? LastAssignedVariable
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
string GetVectorType();
|
||||||
|
string GetVectorType<T>();
|
||||||
|
|
||||||
|
Expression Call(string methodName, params string[] args);
|
||||||
|
Expression Assign(Expression expr, string? varName = null, bool isNew = true);
|
||||||
|
Code Return(Expression expr);
|
||||||
|
|
||||||
|
Expression Create(string value);
|
||||||
|
Expression Zero<T>();
|
||||||
|
Expression One<T>();
|
||||||
|
Expression Count<T>();
|
||||||
|
|
||||||
|
Expression Add(Expression a, Expression b);
|
||||||
|
Expression Subtract(Expression a, Expression b);
|
||||||
|
Expression Multiply(Expression a, Expression b);
|
||||||
|
Expression Divide(Expression a, Expression b);
|
||||||
|
Expression MultiplyAdd(Expression left, Expression right, Expression addend);
|
||||||
|
|
||||||
|
Expression Round(Expression value);
|
||||||
|
Expression Abs(Expression value);
|
||||||
|
|
||||||
|
void Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static class VectorAPIContext
|
||||||
|
{
|
||||||
|
public static string GetTypeName<T>()
|
||||||
|
{
|
||||||
|
return typeof(T) switch
|
||||||
|
{
|
||||||
|
_ when typeof(T) == typeof(float) => "float",
|
||||||
|
_ when typeof(T) == typeof(double) => "double",
|
||||||
|
_ when typeof(T) == typeof(byte) => "byte",
|
||||||
|
_ when typeof(T) == typeof(short) => "short",
|
||||||
|
_ when typeof(T) == typeof(int) => "int",
|
||||||
|
_ when typeof(T) == typeof(uint) => "uint",
|
||||||
|
_ when typeof(T) == typeof(long) => "long",
|
||||||
|
_ when typeof(T) == typeof(ulong) => "ulong",
|
||||||
|
_ => throw new NotSupportedException($"Type {typeof(T)} is not supported in vector operations.")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -416,14 +416,14 @@ public unsafe interface ISPMDLane<TSelf, TNumber> : ISPMDLane, IEquatable<TSelf>
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Computes a * b + c element-wise.
|
/// Computes a * b + c element-wise.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="a">The first multiplier.</param>
|
/// <param name="left">The first multiplier.</param>
|
||||||
/// <param name="b">The second multiplier.</param>
|
/// <param name="right">The second multiplier.</param>
|
||||||
/// <param name="c">The addend.</param>
|
/// <param name="addend">The addend.</param>
|
||||||
/// <returns>The result of the fused multiply-add operation.</returns>
|
/// <returns>The result of the fused multiply-add operation.</returns>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Float and double implementations should use fused multiply-add instructions when available for both accuracy and performance.
|
/// Float and double implementations should use fused multiply-add instructions when available for both accuracy and performance.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
static abstract TSelf MultiplyAdd(TSelf a, TSelf b, TSelf c);
|
static abstract TSelf MultiplyAdd(TSelf left, TSelf right, TSelf addend);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the minimum of the two lane values element-wise.
|
/// Returns the minimum of the two lane values element-wise.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -40,8 +40,6 @@ public static unsafe class WideLane
|
|||||||
public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<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>
|
where TNumber : unmanaged, INumber<TNumber>, IBinaryNumber<TNumber>, IMinMaxValue<TNumber>, IBitwiseOperators<TNumber, TNumber, TNumber>
|
||||||
{
|
{
|
||||||
private static readonly Vector<TNumber> s_indices;
|
|
||||||
|
|
||||||
public readonly Vector<TNumber> value;
|
public readonly Vector<TNumber> value;
|
||||||
|
|
||||||
public static int LaneWidth
|
public static int LaneWidth
|
||||||
@@ -53,13 +51,13 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNu
|
|||||||
public static WideLane<TNumber> Zero
|
public static WideLane<TNumber> Zero
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
get => new WideLane<TNumber>(Vector<TNumber>.Zero);
|
get => Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(Vector<TNumber>.Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static WideLane<TNumber> One
|
public static WideLane<TNumber> One
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
get => new WideLane<TNumber>(Vector<TNumber>.One);
|
get => Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(Vector<TNumber>.One);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static WideLane<TNumber> MinValue
|
public static WideLane<TNumber> MinValue
|
||||||
@@ -86,17 +84,6 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNu
|
|||||||
get => value[index];
|
get => value[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
static WideLane()
|
|
||||||
{
|
|
||||||
var pValues = stackalloc TNumber[LaneWidth];
|
|
||||||
for (var i = 0; i < LaneWidth; i++)
|
|
||||||
{
|
|
||||||
pValues[i] = TNumber.CreateTruncating(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
s_indices = Vector.Load(pValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
public WideLane(Vector<TNumber> value)
|
public WideLane(Vector<TNumber> value)
|
||||||
{
|
{
|
||||||
this.value = value;
|
this.value = value;
|
||||||
@@ -145,19 +132,19 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNu
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> Create(TNumber value)
|
public static WideLane<TNumber> Create(TNumber value)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(Vector.Create(value));
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(Vector.Create(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> Create(params ReadOnlySpan<TNumber> values)
|
public static WideLane<TNumber> Create(params ReadOnlySpan<TNumber> values)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(Vector.Create(values));
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(Vector.Create(values));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> Create(Vector<TNumber> value)
|
public static WideLane<TNumber> Create(Vector<TNumber> value)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(value);
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -185,20 +172,20 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNu
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(Vector.Create(start) + (Vector.Create(step) * s_indices));
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(Vector.Create(start) + (Vector.Create(step) * Vector<TNumber>.Indices));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> Load(ref TNumber value)
|
public static WideLane<TNumber> Load(ref TNumber value)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(Vector.LoadUnsafe(ref value));
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(Vector.LoadUnsafe(ref value));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> Load(TNumber* pValue)
|
public static WideLane<TNumber> Load(TNumber* pValue)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(Vector.Load(pValue));
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(Vector.Load(pValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -302,7 +289,7 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNu
|
|||||||
pResult[i] = *(TNumber*)((byte*)pData + (idx * scale));
|
pResult[i] = *(TNumber*)((byte*)pData + (idx * scale));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new WideLane<TNumber>(result);
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -352,7 +339,7 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNu
|
|||||||
pResult[i] = *(TNumber*)((byte*)pData + (pIndices[i] * scale));
|
pResult[i] = *(TNumber*)((byte*)pData + (pIndices[i] * scale));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new WideLane<TNumber>(result);
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -419,7 +406,7 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNu
|
|||||||
pResult[i] = *(TNumber*)((byte*)pData + (idx * scale));
|
pResult[i] = *(TNumber*)((byte*)pData + (idx * scale));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new WideLane<TNumber>(result);
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -473,7 +460,7 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNu
|
|||||||
pResult[i] = *(TNumber*)((byte*)pData + (pIndices[i] * scale));
|
pResult[i] = *(TNumber*)((byte*)pData + (pIndices[i] * scale));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new WideLane<TNumber>(result);
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -777,61 +764,61 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNu
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> operator +(WideLane<TNumber> a, WideLane<TNumber> b)
|
public static WideLane<TNumber> operator +(WideLane<TNumber> a, WideLane<TNumber> b)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(a.value + b.value);
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(a.value + b.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> operator -(WideLane<TNumber> a, WideLane<TNumber> b)
|
public static WideLane<TNumber> operator -(WideLane<TNumber> a, WideLane<TNumber> b)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(a.value - b.value);
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(a.value - b.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> operator *(WideLane<TNumber> a, WideLane<TNumber> b)
|
public static WideLane<TNumber> operator *(WideLane<TNumber> a, WideLane<TNumber> b)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(a.value * b.value);
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(a.value * b.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> operator /(WideLane<TNumber> a, WideLane<TNumber> b)
|
public static WideLane<TNumber> operator /(WideLane<TNumber> a, WideLane<TNumber> b)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(a.value / b.value);
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(a.value / b.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> operator %(WideLane<TNumber> a, WideLane<TNumber> b)
|
public static WideLane<TNumber> operator %(WideLane<TNumber> a, WideLane<TNumber> b)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(a.value - VectorFloor(a.value / b.value) * b.value);
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(a.value - VectorFloor(a.value / b.value) * b.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> operator -(WideLane<TNumber> a)
|
public static WideLane<TNumber> operator -(WideLane<TNumber> a)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(-a.value);
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(-a.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> operator &(WideLane<TNumber> a, WideLane<TNumber> b)
|
public static WideLane<TNumber> operator &(WideLane<TNumber> a, WideLane<TNumber> b)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(a.value & b.value);
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(a.value & b.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> operator |(WideLane<TNumber> a, WideLane<TNumber> b)
|
public static WideLane<TNumber> operator |(WideLane<TNumber> a, WideLane<TNumber> b)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(a.value | b.value);
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(a.value | b.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> operator ^(WideLane<TNumber> a, WideLane<TNumber> b)
|
public static WideLane<TNumber> operator ^(WideLane<TNumber> a, WideLane<TNumber> b)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(a.value ^ b.value);
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(a.value ^ b.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> operator ~(WideLane<TNumber> a)
|
public static WideLane<TNumber> operator ~(WideLane<TNumber> a)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(~a.value);
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(~a.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -881,7 +868,7 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNu
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> Abs(WideLane<TNumber> value)
|
public static WideLane<TNumber> Abs(WideLane<TNumber> value)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(Vector.Abs(value.value));
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(Vector.Abs(value.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -897,7 +884,7 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNu
|
|||||||
{
|
{
|
||||||
var v = Unsafe.BitCast<WideLane<TNumber>, Vector<double>>(value);
|
var v = Unsafe.BitCast<WideLane<TNumber>, Vector<double>>(value);
|
||||||
var floored = Vector.Floor(v);
|
var floored = Vector.Floor(v);
|
||||||
return new WideLane<TNumber>(Unsafe.BitCast<Vector<double>, Vector<TNumber>>(floored));
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(Unsafe.BitCast<Vector<double>, Vector<TNumber>>(floored));
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
@@ -906,60 +893,60 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNu
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> Frac(WideLane<TNumber> value)
|
public static WideLane<TNumber> Frac(WideLane<TNumber> value)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(value.value - VectorFloor(value.value));
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(value.value - VectorFloor(value.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> Sqrt(WideLane<TNumber> value)
|
public static WideLane<TNumber> Sqrt(WideLane<TNumber> value)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(Vector.SquareRoot(value.value));
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(Vector.SquareRoot(value.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> Lerp(WideLane<TNumber> a, WideLane<TNumber> b, WideLane<TNumber> t)
|
public static WideLane<TNumber> Lerp(WideLane<TNumber> a, WideLane<TNumber> b, WideLane<TNumber> t)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(a.value + (b.value - a.value) * t.value);
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(a.value + (b.value - a.value) * t.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> MultiplyAdd(WideLane<TNumber> a, WideLane<TNumber> b, WideLane<TNumber> c)
|
public static WideLane<TNumber> MultiplyAdd(WideLane<TNumber> left, WideLane<TNumber> right, WideLane<TNumber> addend)
|
||||||
{
|
{
|
||||||
if (typeof(TNumber) == typeof(float))
|
if (typeof(TNumber) == typeof(float))
|
||||||
{
|
{
|
||||||
var va = Unsafe.BitCast<WideLane<TNumber>, Vector<float>>(a);
|
var va = Unsafe.BitCast<WideLane<TNumber>, Vector<float>>(left);
|
||||||
var vb = Unsafe.BitCast<WideLane<TNumber>, Vector<float>>(b);
|
var vb = Unsafe.BitCast<WideLane<TNumber>, Vector<float>>(right);
|
||||||
var vc = Unsafe.BitCast<WideLane<TNumber>, Vector<float>>(c);
|
var vc = Unsafe.BitCast<WideLane<TNumber>, Vector<float>>(addend);
|
||||||
var result = Vector.FusedMultiplyAdd(va, vb, vc);
|
var result = Vector.FusedMultiplyAdd(va, vb, vc);
|
||||||
return Unsafe.BitCast<Vector<float>, WideLane<TNumber>>(result);
|
return Unsafe.BitCast<Vector<float>, WideLane<TNumber>>(result);
|
||||||
}
|
}
|
||||||
else if (typeof(TNumber) == typeof(double))
|
else if (typeof(TNumber) == typeof(double))
|
||||||
{
|
{
|
||||||
var va = Unsafe.BitCast<WideLane<TNumber>, Vector<double>>(a);
|
var va = Unsafe.BitCast<WideLane<TNumber>, Vector<double>>(left);
|
||||||
var vb = Unsafe.BitCast<WideLane<TNumber>, Vector<double>>(b);
|
var vb = Unsafe.BitCast<WideLane<TNumber>, Vector<double>>(right);
|
||||||
var vc = Unsafe.BitCast<WideLane<TNumber>, Vector<double>>(c);
|
var vc = Unsafe.BitCast<WideLane<TNumber>, Vector<double>>(addend);
|
||||||
var result = Vector.FusedMultiplyAdd(va, vb, vc);
|
var result = Vector.FusedMultiplyAdd(va, vb, vc);
|
||||||
return Unsafe.BitCast<Vector<double>, WideLane<TNumber>>(result);
|
return Unsafe.BitCast<Vector<double>, WideLane<TNumber>>(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new WideLane<TNumber>((a.value * b.value) + c.value);
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>((left.value * right.value) + addend.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> Min(WideLane<TNumber> a, WideLane<TNumber> b)
|
public static WideLane<TNumber> Min(WideLane<TNumber> a, WideLane<TNumber> b)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(Vector.Min(a.value, b.value));
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(Vector.Min(a.value, b.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> Max(WideLane<TNumber> a, WideLane<TNumber> b)
|
public static WideLane<TNumber> Max(WideLane<TNumber> a, WideLane<TNumber> b)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(Vector.Max(a.value, b.value));
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(Vector.Max(a.value, b.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> Clamp(WideLane<TNumber> value, WideLane<TNumber> min, WideLane<TNumber> max)
|
public static WideLane<TNumber> Clamp(WideLane<TNumber> value, WideLane<TNumber> min, WideLane<TNumber> max)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(Vector.Clamp(value.value, min.value, max.value));
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(Vector.Clamp(value.value, min.value, max.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -1010,7 +997,7 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNu
|
|||||||
{
|
{
|
||||||
var v = Unsafe.BitCast<WideLane<TNumber>, Vector<double>>(value);
|
var v = Unsafe.BitCast<WideLane<TNumber>, Vector<double>>(value);
|
||||||
var result = Vector.Sin(v);
|
var result = Vector.Sin(v);
|
||||||
return new WideLane<TNumber>(Unsafe.BitCast<Vector<double>, Vector<TNumber>>(result));
|
return Unsafe.BitCast<Vector<double>, WideLane<TNumber>>(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
@@ -1060,7 +1047,7 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNu
|
|||||||
{
|
{
|
||||||
var v = Unsafe.BitCast<WideLane<TNumber>, Vector<double>>(value);
|
var v = Unsafe.BitCast<WideLane<TNumber>, Vector<double>>(value);
|
||||||
var result = Vector.Cos(v);
|
var result = Vector.Cos(v);
|
||||||
return new WideLane<TNumber>(Unsafe.BitCast<Vector<double>, Vector<TNumber>>(result));
|
return Unsafe.BitCast<Vector<double>, WideLane<TNumber>>(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
@@ -1144,8 +1131,8 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNu
|
|||||||
{
|
{
|
||||||
var v = Unsafe.BitCast<WideLane<TNumber>, Vector<double>>(value);
|
var v = Unsafe.BitCast<WideLane<TNumber>, Vector<double>>(value);
|
||||||
var (sinResult, cosResult) = Vector.SinCos(v);
|
var (sinResult, cosResult) = Vector.SinCos(v);
|
||||||
sin = new WideLane<TNumber>(Unsafe.BitCast<Vector<double>, Vector<TNumber>>(sinResult));
|
sin = Unsafe.BitCast<Vector<double>, WideLane<TNumber>>(sinResult);
|
||||||
cos = new WideLane<TNumber>(Unsafe.BitCast<Vector<double>, Vector<TNumber>>(cosResult));
|
cos = Unsafe.BitCast<Vector<double>, WideLane<TNumber>>(cosResult);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1296,7 +1283,7 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNu
|
|||||||
{
|
{
|
||||||
var v = Unsafe.BitCast<WideLane<TNumber>, Vector<double>>(value);
|
var v = Unsafe.BitCast<WideLane<TNumber>, Vector<double>>(value);
|
||||||
var result = Vector.Exp(v);
|
var result = Vector.Exp(v);
|
||||||
return new WideLane<TNumber>(Unsafe.BitCast<Vector<double>, Vector<TNumber>>(result));
|
return Unsafe.BitCast<Vector<double>, WideLane<TNumber>>(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
@@ -1418,7 +1405,7 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNu
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> CopySign(WideLane<TNumber> magnitude, WideLane<TNumber> sign)
|
public static WideLane<TNumber> CopySign(WideLane<TNumber> magnitude, WideLane<TNumber> sign)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(Vector.CopySign(magnitude.value, sign.value));
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(Vector.CopySign(magnitude.value, sign.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -1538,7 +1525,7 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNu
|
|||||||
[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)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(Vector.ConditionalSelect(
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(Vector.ConditionalSelect(
|
||||||
conditionMask.value,
|
conditionMask.value,
|
||||||
ifTrue.value,
|
ifTrue.value,
|
||||||
ifFalse.value));
|
ifFalse.value));
|
||||||
@@ -1553,31 +1540,31 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNu
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> GreaterThan(WideLane<TNumber> a, WideLane<TNumber> b)
|
public static WideLane<TNumber> GreaterThan(WideLane<TNumber> a, WideLane<TNumber> b)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(Vector.GreaterThan(a.value, b.value));
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(Vector.GreaterThan(a.value, b.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> GreaterThanOrEqual(WideLane<TNumber> a, WideLane<TNumber> b)
|
public static WideLane<TNumber> GreaterThanOrEqual(WideLane<TNumber> a, WideLane<TNumber> b)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(Vector.GreaterThanOrEqual(a.value, b.value));
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(Vector.GreaterThanOrEqual(a.value, b.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> LessThan(WideLane<TNumber> a, WideLane<TNumber> b)
|
public static WideLane<TNumber> LessThan(WideLane<TNumber> a, WideLane<TNumber> b)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(Vector.LessThan(a.value, b.value));
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(Vector.LessThan(a.value, b.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> LessThanOrEqual(WideLane<TNumber> a, WideLane<TNumber> b)
|
public static WideLane<TNumber> LessThanOrEqual(WideLane<TNumber> a, WideLane<TNumber> b)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(Vector.LessThanOrEqual(a.value, b.value));
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(Vector.LessThanOrEqual(a.value, b.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static WideLane<TNumber> Equal(WideLane<TNumber> a, WideLane<TNumber> b)
|
public static WideLane<TNumber> Equal(WideLane<TNumber> a, WideLane<TNumber> b)
|
||||||
{
|
{
|
||||||
return new WideLane<TNumber>(Vector.Equals(a.value, b.value));
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(Vector.Equals(a.value, b.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -1623,4 +1610,10 @@ public readonly unsafe partial struct WideLane<TNumber> : ISPMDLane<WideLane<TNu
|
|||||||
{
|
{
|
||||||
return value.ToString();
|
return value.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static implicit operator WideLane<TNumber>(Vector<TNumber> v)
|
||||||
|
{
|
||||||
|
return Unsafe.BitCast<Vector<TNumber>, WideLane<TNumber>>(v);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ using Misaki.HighPerformance.Test.Benchmark;
|
|||||||
using Misaki.HighPerformance.Test.UnitTest;
|
using Misaki.HighPerformance.Test.UnitTest;
|
||||||
using Misaki.HighPerformance.Test.UnitTest.Jobs;
|
using Misaki.HighPerformance.Test.UnitTest.Jobs;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
|
using System.Runtime.Intrinsics;
|
||||||
|
using System.Runtime.Intrinsics.X86;
|
||||||
|
|
||||||
//BenchmarkRunner.Run<GGXMipGenerationBenchmark>();
|
//BenchmarkRunner.Run<GGXMipGenerationBenchmark>();
|
||||||
|
|
||||||
|
|||||||
@@ -118,12 +118,6 @@ internal struct DistanceJob : IJobSPMD<float>
|
|||||||
[TestClass]
|
[TestClass]
|
||||||
public partial class SPMDTest
|
public partial class SPMDTest
|
||||||
{
|
{
|
||||||
[HPCompute(TargetInstructionSet.AVX2)]
|
|
||||||
private static WideLane<float> Test(WideLane<float> a, WideLane<float> b, WideLane<float> c)
|
|
||||||
{
|
|
||||||
return WideLane<float>.MultiplyAdd(a, b, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
[HPCompute(TargetInstructionSet.AVX2)]
|
[HPCompute(TargetInstructionSet.AVX2)]
|
||||||
private static (TFloat, TFloat) Test_SPMD<TFloat>(TFloat a, TFloat b, TFloat c)
|
private static (TFloat, TFloat) Test_SPMD<TFloat>(TFloat a, TFloat b, TFloat c)
|
||||||
where TFloat : unmanaged, ISPMDLane<TFloat, float>
|
where TFloat : unmanaged, ISPMDLane<TFloat, float>
|
||||||
|
|||||||
Reference in New Issue
Block a user