New opengl api binding and new graphic purpose vector design
Signed-off-by: Nitload <YoumuLiu_NSI@whv0t.onmicrosoft.com>
This commit is contained in:
@@ -5,14 +5,8 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using StgSharp.HighPerformance.ProcessorAbstraction;
|
||||
using StgSharp.Mathematics.Numeric;
|
||||
using StgSharp.Mathematics.Numeric.Graphics;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
|
||||
namespace StgSharp.Mathematics.Numeric.Graphics
|
||||
@@ -21,9 +15,7 @@ namespace StgSharp.Mathematics.Numeric.Graphics
|
||||
{
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static Vector128<T> AsVector128Safe<T>(
|
||||
this Vec2<T> source
|
||||
) where T : unmanaged, INumber<T>
|
||||
internal static Vector128<T> AsVector128Safe<T>(this Vec2<T> source) where T: unmanaged, INumber<T>
|
||||
{
|
||||
Vector128<T> result = Vector128<T>.Zero;
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<Vector128<T>, byte>(ref result), source);
|
||||
@@ -31,9 +23,7 @@ namespace StgSharp.Mathematics.Numeric.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static Vector128<T> AsVector128Unsafe<T>(
|
||||
this Vec2<T> source
|
||||
) where T : unmanaged, INumber<T>
|
||||
internal static Vector128<T> AsVector128Unsafe<T>(this Vec2<T> source) where T: unmanaged, INumber<T>
|
||||
{
|
||||
Unsafe.SkipInit(out Vector128<T> result);
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<Vector128<T>, byte>(ref result), source);
|
||||
@@ -41,155 +31,39 @@ namespace StgSharp.Mathematics.Numeric.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static Vec2<T> FromVector128Safe<T>(
|
||||
Vector128<T> source
|
||||
) where T : unmanaged, INumber<T>
|
||||
internal static Vec2<T> FromVector128Safe<T>(Vector128<T> source) where T: unmanaged, INumber<T>
|
||||
{
|
||||
return Unsafe.As<Vector128<T>, Vec2<T>>(ref source);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static Vec2<T> FromVector128Unsafe<T>(
|
||||
Vector128<T> source
|
||||
) where T : unmanaged, INumber<T>
|
||||
internal static Vec2<T> FromVector128Unsafe<T>(Vector128<T> source) where T: unmanaged, INumber<T>
|
||||
{
|
||||
return Unsafe.As<Vector128<T>, Vec2<T>>(ref source);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A two dimension vector defined by two elements. Vec2 in World are default used as colum
|
||||
/// vector.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">
|
||||
///
|
||||
/// </typeparam>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 16)]
|
||||
public struct Vec2<T> : IUnmanagedVector<Vec2<T>> where T : unmanaged, INumber<T>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec2<float> ConvertToSingle(Vec2<int> source)
|
||||
{
|
||||
|
||||
public T X;
|
||||
public T Y;
|
||||
|
||||
public Vec2(
|
||||
T x,
|
||||
T y
|
||||
)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
|
||||
public static Vec2<T> Unit => new(T.One, T.One);
|
||||
|
||||
public static Vec2<T> Zero => new(T.Zero, T.Zero);
|
||||
|
||||
public static Vec2<T> One => new(T.One, T.One);
|
||||
|
||||
public Vec2<T> XY
|
||||
{
|
||||
readonly get => this;
|
||||
set => this = value;
|
||||
return FromVector128Unsafe(Vector128.ConvertToSingle(source.AsVector128Safe()));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public T Cross(
|
||||
Vec2<T> right
|
||||
)
|
||||
public static Vec2<float> ConvertToSingle(Vec2<uint> source)
|
||||
{
|
||||
return X * right.Y - Y * right.X;
|
||||
return FromVector128Unsafe(Vector128.ConvertToSingle(source.AsVector128Safe()));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public readonly T Dot(
|
||||
Vec2<T> vec
|
||||
)
|
||||
public static Vec2<double> ConvertToDouble(Vec2<long> source)
|
||||
{
|
||||
return X * vec.X + Y * vec.Y;
|
||||
return FromVector128Unsafe(Vector128.ConvertToDouble(source.AsVector128Safe()));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec2<T> operator -(
|
||||
Vec2<T> left,
|
||||
Vec2<T> right
|
||||
)
|
||||
public static Vec2<double> ConvertToDouble(Vec2<ulong> source)
|
||||
{
|
||||
Vector128<T> leftVec = left.AsVector128Unsafe();
|
||||
Vector128<T> rightVec = right.AsVector128Unsafe();
|
||||
return Vec2.FromVector128Unsafe(leftVec + rightVec);
|
||||
}
|
||||
|
||||
public static bool operator !=(
|
||||
Vec2<T> left,
|
||||
Vec2<T> right
|
||||
)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec2<T> operator *(
|
||||
Vec2<T> vec,
|
||||
T value
|
||||
)
|
||||
{
|
||||
Vector128<T> leftVec = vec.AsVector128Unsafe();
|
||||
return Vec2.FromVector128Unsafe(leftVec * value);
|
||||
}
|
||||
|
||||
public static Vec2<T> operator *(
|
||||
T value,
|
||||
Vec2<T> vec
|
||||
)
|
||||
{
|
||||
Vector128<T> leftVec = vec.AsVector128Unsafe();
|
||||
return Vec2.FromVector128Unsafe(leftVec * value);
|
||||
}
|
||||
|
||||
public static Vec2<T> operator /(
|
||||
Vec2<T> vec,
|
||||
T value
|
||||
)
|
||||
{
|
||||
Vector128<T> leftVec = vec.AsVector128Unsafe();
|
||||
return Vec2.FromVector128Unsafe(leftVec / value);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec2<T> operator +(
|
||||
Vec2<T> left,
|
||||
Vec2<T> right
|
||||
)
|
||||
{
|
||||
Vector128<T> leftVec = left.AsVector128Unsafe();
|
||||
Vector128<T> rightVec = right.AsVector128Unsafe();
|
||||
return Vec2.FromVector128Unsafe(leftVec + rightVec);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator ==(
|
||||
Vec2<T> left,
|
||||
Vec2<T> right
|
||||
)
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4) {
|
||||
return Unsafe.As<Vec2<T>, ulong>(ref left) == Unsafe.As<Vec2<T>, ulong>(ref right);
|
||||
}
|
||||
if (Unsafe.SizeOf<T>() == 8) {
|
||||
return Unsafe.As<Vec2<T>, Vector128<T>>(ref left) == Unsafe.As<Vec2<T>, Vector128<T>>(ref right);
|
||||
}
|
||||
#pragma warning disable CA1065
|
||||
throw new NotSupportedException($"Element type {typeof(T).Name} is not supported.");
|
||||
#pragma warning restore CA1065
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator Vec2<T>(
|
||||
(T, T) tuple
|
||||
)
|
||||
{
|
||||
return new Vec2<T>(tuple.Item1, tuple.Item2);
|
||||
return FromVector128Unsafe(Vector128.ConvertToDouble(source.AsVector128Safe()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// file="Vec2_T"
|
||||
// Project: StgSharp
|
||||
// Copyright (c) Nitload.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using StgSharp.Mathematics.Numeric;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
|
||||
namespace StgSharp.Mathematics.Numeric.Graphics
|
||||
{
|
||||
/// <summary>
|
||||
/// A two dimension vector defined by two elements. Vec2 in World are default used as colum
|
||||
/// vector.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">
|
||||
///
|
||||
/// </typeparam>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 16)]
|
||||
public struct Vec2<T>(T x, T y) : IUnmanagedVector<Vec2<T>> where T: unmanaged, INumber<T>
|
||||
{
|
||||
|
||||
public T X = x;
|
||||
public T Y = y;
|
||||
|
||||
public static Vec2<T> Unit => new(T.One, T.One);
|
||||
|
||||
public static Vec2<T> Zero => new(T.Zero, T.Zero);
|
||||
|
||||
public static Vec2<T> One => new(T.One, T.One);
|
||||
|
||||
public Vec2<T> XY
|
||||
{
|
||||
readonly get => this;
|
||||
set => this = value;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public T Cross(Vec2<T> right)
|
||||
{
|
||||
return (X * right.Y) - (Y * right.X);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public readonly T Dot(Vec2<T> vec)
|
||||
{
|
||||
Vector128<T> leftVec = this.AsVector128Unsafe();
|
||||
Vector128<T> rightVec = vec.AsVector128Unsafe();
|
||||
Vector128<T> result_v128 = leftVec * rightVec;
|
||||
Vec2<T> result = Unsafe.As<Vector128<T>, Vec2<T>>(ref result_v128);
|
||||
return result.X + result.Y;
|
||||
}
|
||||
|
||||
public override readonly bool Equals(object? obj)
|
||||
{
|
||||
return (obj is Vec2<T> other) && (other == this);
|
||||
}
|
||||
|
||||
public override readonly int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(X, Y);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec2<T> operator -(Vec2<T> left, Vec2<T> right)
|
||||
{
|
||||
Vector128<T> leftVec = left.AsVector128Unsafe();
|
||||
Vector128<T> rightVec = right.AsVector128Unsafe();
|
||||
return Vec2.FromVector128Unsafe(leftVec - rightVec);
|
||||
}
|
||||
|
||||
public static bool operator !=(Vec2<T> left, Vec2<T> right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec2<T> operator *(Vec2<T> vec, T value)
|
||||
{
|
||||
Vector128<T> leftVec = vec.AsVector128Unsafe();
|
||||
return Vec2.FromVector128Unsafe(leftVec * value);
|
||||
}
|
||||
|
||||
public static Vec2<T> operator *(T value, Vec2<T> vec)
|
||||
{
|
||||
Vector128<T> leftVec = vec.AsVector128Unsafe();
|
||||
return Vec2.FromVector128Unsafe(leftVec * value);
|
||||
}
|
||||
|
||||
public static Vec2<T> operator /(Vec2<T> vec, T value)
|
||||
{
|
||||
Vector128<T> leftVec = vec.AsVector128Unsafe();
|
||||
return Vec2.FromVector128Unsafe(leftVec / value);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec2<T> operator +(Vec2<T> left, Vec2<T> right)
|
||||
{
|
||||
Vector128<T> leftVec = left.AsVector128Unsafe();
|
||||
Vector128<T> rightVec = right.AsVector128Unsafe();
|
||||
return Vec2.FromVector128Unsafe(leftVec + rightVec);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator ==(Vec2<T> left, Vec2<T> right)
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4) {
|
||||
return Unsafe.As<Vec2<T>, ulong>(ref left) == Unsafe.As<Vec2<T>, ulong>(ref right);
|
||||
}
|
||||
if (Unsafe.SizeOf<T>() == 8) {
|
||||
return Unsafe.As<Vec2<T>, Vector128<T>>(ref left) == Unsafe.As<Vec2<T>, Vector128<T>>(ref right);
|
||||
}
|
||||
#pragma warning disable CA1065
|
||||
throw new NotSupportedException($"Element type {typeof(T).Name} is not supported.");
|
||||
#pragma warning restore CA1065
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator Vec2<T>((T, T) tuple)
|
||||
{
|
||||
return new Vec2<T>(tuple.Item1, tuple.Item2);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -15,48 +15,128 @@ namespace StgSharp.Mathematics.Numeric.Graphics
|
||||
public static class Vec3
|
||||
{
|
||||
|
||||
public static bool IsParallel<T>(Vec3<T> left, Vec3<T> right) where T: unmanaged,INumber<T>
|
||||
{
|
||||
return Cross(left, right).Equals(T.Zero);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec3<T> Cross<T>(Vec3<T> left, Vec3<T> right)
|
||||
where T : unmanaged, INumber<T>
|
||||
internal static Vector128<T> AsVector128Safe<T>(this Vec3<T> source) where T: unmanaged, INumber<T>
|
||||
{
|
||||
Vector128<T> result = Vector128<T>.Zero;
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<Vector128<T>, byte>(ref result), source);
|
||||
return result;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static Vector128<T> AsVector128Unsafe<T>(this Vec3<T> source) where T: unmanaged, INumber<T>
|
||||
{
|
||||
Unsafe.SkipInit(out Vector128<T> result);
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<Vector128<T>, byte>(ref result), source);
|
||||
return result;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static Vector256<T> AsVector256Safe<T>(this Vec3<T> source) where T: unmanaged, INumber<T>
|
||||
{
|
||||
Vector256<T> result = Vector256<T>.Zero;
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<Vector256<T>, byte>(ref result), source);
|
||||
return result;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static Vector256<T> AsVector256Unsafe<T>(this Vec3<T> source) where T: unmanaged, INumber<T>
|
||||
{
|
||||
Unsafe.SkipInit(out Vector256<T> result);
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<Vector256<T>, byte>(ref result), source);
|
||||
return result;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static Vec3<T> FromVector128Unsafe<T>(Vector128<T> source) where T: unmanaged, INumber<T>
|
||||
{
|
||||
return Unsafe.As<Vector128<T>, Vec3<T>>(ref source);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static Vec3<T> FromVector256Unsafe<T>(Vector256<T> source) where T: unmanaged, INumber<T>
|
||||
{
|
||||
return Unsafe.As<Vector256<T>, Vec3<T>>(ref source);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec3<float> ConvertToSingle(Vec3<int> source)
|
||||
{
|
||||
return FromVector128Unsafe(Vector128.ConvertToSingle(source.AsVector128Safe()));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec3<float> ConvertToSingle(Vec3<uint> source)
|
||||
{
|
||||
return FromVector128Unsafe(Vector128.ConvertToSingle(source.AsVector128Safe()));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec3<double> ConvertToDouble(Vec3<long> source)
|
||||
{
|
||||
return FromVector256Unsafe(Vector256.ConvertToDouble(source.AsVector256Safe()));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec3<double> ConvertToDouble(Vec3<ulong> source)
|
||||
{
|
||||
return FromVector256Unsafe(Vector256.ConvertToDouble(source.AsVector256Safe()));
|
||||
}
|
||||
|
||||
#region cross
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec3<T> Cross<T>(Vec3<T> left, Vec3<T> right) where T: unmanaged, INumber<T>
|
||||
{
|
||||
if (typeof(T) == typeof(float))
|
||||
{
|
||||
if (typeof(T) == typeof(float)) {
|
||||
Vec3<float> result = CrossSingle(
|
||||
Unsafe.As<Vec3<T>, Vec3<float>>(ref left),
|
||||
Unsafe.As<Vec3<T>, Vec3<float>>(ref right));
|
||||
return Unsafe.As<Vec3<float>, Vec3<T>>(ref result);
|
||||
}
|
||||
if (typeof(T) == typeof(double)) {
|
||||
if (typeof(T) == typeof(double))
|
||||
{
|
||||
Vec3<double> result = CrossDouble(
|
||||
Unsafe.As<Vec3<T>, Vec3<double>>(ref left),
|
||||
Unsafe.As<Vec3<T>, Vec3<double>>(ref right));
|
||||
return Unsafe.As<Vec3<double>, Vec3<T>>(ref result);
|
||||
}
|
||||
if (typeof(T) == typeof(int)) {
|
||||
if (typeof(T) == typeof(int))
|
||||
{
|
||||
Vec3<int> result = CrossInt32(
|
||||
Unsafe.As<Vec3<T>, Vec3<int>>(ref left),
|
||||
Unsafe.As<Vec3<T>, Vec3<int>>(ref right));
|
||||
return Unsafe.As<Vec3<int>, Vec3<T>>(ref result);
|
||||
}
|
||||
if (typeof(T) == typeof(uint)) {
|
||||
if (typeof(T) == typeof(uint))
|
||||
{
|
||||
Vec3<uint> result = CrossUInt32(
|
||||
Unsafe.As<Vec3<T>, Vec3<uint>>(ref left),
|
||||
Unsafe.As<Vec3<T>, Vec3<uint>>(ref right));
|
||||
return Unsafe.As<Vec3<uint>, Vec3<T>>(ref result);
|
||||
}
|
||||
|
||||
throw new NotSupportedException($"Cross product is not supported for {typeof(T)}.");
|
||||
if (typeof(T) == typeof(ulong))
|
||||
{
|
||||
Vec3<ulong> result = CrossUInt64(
|
||||
Unsafe.As<Vec3<T>, Vec3<ulong>>(ref left),
|
||||
Unsafe.As<Vec3<T>, Vec3<ulong>>(ref right));
|
||||
return Unsafe.As<Vec3<ulong>, Vec3<T>>(ref result);
|
||||
}
|
||||
if (typeof(T) == typeof(long))
|
||||
{
|
||||
Vec3<long> result = CrossInt64(
|
||||
Unsafe.As<Vec3<T>, Vec3<long>>(ref left),
|
||||
Unsafe.As<Vec3<T>, Vec3<long>>(ref right));
|
||||
return Unsafe.As<Vec3<long>, Vec3<T>>(ref result);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static Vec3<float> CrossSingle(Vec3<float> left, Vec3<float> right)
|
||||
{
|
||||
Vector128<float> l = left.AsVector128Safe();
|
||||
Vector128<float> r = right.AsVector128Safe();
|
||||
Vector128<int> yzx = Vector128.Create(1, 2, 0, 3);
|
||||
Vector128<int> zxy = Vector128.Create(2, 0, 1, 3);
|
||||
Vector128<float> result = Vector128.Shuffle(l, yzx) * Vector128.Shuffle(r, zxy) -
|
||||
Vector128.Shuffle(l, zxy) * Vector128.Shuffle(r, yzx);
|
||||
return new(result[0], result[1], result[2]);
|
||||
throw new NotSupportedException($"Cross product is not supported for {typeof(T)}.");
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@@ -66,9 +146,8 @@ namespace StgSharp.Mathematics.Numeric.Graphics
|
||||
Vector256<double> r = right.AsVector256Safe();
|
||||
Vector256<long> yzx = Vector256.Create(1L, 2L, 0L, 3L);
|
||||
Vector256<long> zxy = Vector256.Create(2L, 0L, 1L, 3L);
|
||||
Vector256<double> result = Vector256.Shuffle(l, yzx) * Vector256.Shuffle(r, zxy) -
|
||||
Vector256.Shuffle(l, zxy) * Vector256.Shuffle(r, yzx);
|
||||
return new(result[0], result[1], result[2]);
|
||||
Vector256<double> result = (Vector256.Shuffle(l, yzx) * Vector256.Shuffle(r, zxy)) - (Vector256.Shuffle(l, zxy) * Vector256.Shuffle(r, yzx));
|
||||
return FromVector256Unsafe(result);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@@ -78,9 +157,19 @@ namespace StgSharp.Mathematics.Numeric.Graphics
|
||||
Vector128<int> r = right.AsVector128Safe();
|
||||
Vector128<int> yzx = Vector128.Create(1, 2, 0, 3);
|
||||
Vector128<int> zxy = Vector128.Create(2, 0, 1, 3);
|
||||
Vector128<int> result = Vector128.Shuffle(l, yzx) * Vector128.Shuffle(r, zxy) -
|
||||
Vector128.Shuffle(l, zxy) * Vector128.Shuffle(r, yzx);
|
||||
return new(result[0], result[1], result[2]);
|
||||
Vector128<int> result = (Vector128.Shuffle(l, yzx) * Vector128.Shuffle(r, zxy)) - (Vector128.Shuffle(l, zxy) * Vector128.Shuffle(r, yzx));
|
||||
return FromVector128Unsafe(result);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static Vec3<float> CrossSingle(Vec3<float> left, Vec3<float> right)
|
||||
{
|
||||
Vector128<float> l = left.AsVector128Safe();
|
||||
Vector128<float> r = right.AsVector128Safe();
|
||||
Vector128<int> yzx = Vector128.Create(1, 2, 0, 3);
|
||||
Vector128<int> zxy = Vector128.Create(2, 0, 1, 3);
|
||||
Vector128<float> result = (Vector128.Shuffle(l, yzx) * Vector128.Shuffle(r, zxy)) - (Vector128.Shuffle(l, zxy) * Vector128.Shuffle(r, yzx));
|
||||
return FromVector128Unsafe(result);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@@ -90,60 +179,32 @@ namespace StgSharp.Mathematics.Numeric.Graphics
|
||||
Vector128<uint> r = right.AsVector128Safe();
|
||||
Vector128<uint> yzx = Vector128.Create(1U, 2U, 0U, 3U);
|
||||
Vector128<uint> zxy = Vector128.Create(2U, 0U, 1U, 3U);
|
||||
Vector128<uint> result = Vector128.Shuffle(l, yzx) * Vector128.Shuffle(r, zxy) -
|
||||
Vector128.Shuffle(l, zxy) * Vector128.Shuffle(r, yzx);
|
||||
return new(result[0], result[1], result[2]);
|
||||
Vector128<uint> result = (Vector128.Shuffle(l, yzx) * Vector128.Shuffle(r, zxy)) - (Vector128.Shuffle(l, zxy) * Vector128.Shuffle(r, yzx));
|
||||
return FromVector128Unsafe(result);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static Vector128<T> AsVector128Safe<T>(this Vec3<T> source)
|
||||
where T : unmanaged, INumber<T>
|
||||
private static Vec3<ulong> CrossUInt64(Vec3<ulong> left, Vec3<ulong> right)
|
||||
{
|
||||
Vector128<T> result = Vector128<T>.Zero;
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<Vector128<T>, byte>(ref result), source);
|
||||
return result;
|
||||
Vector256<ulong> l = left.AsVector256Safe();
|
||||
Vector256<ulong> r = right.AsVector256Safe();
|
||||
Vector256<ulong> yzx = Vector256.Create(1UL, 2UL, 0UL, 3UL);
|
||||
Vector256<ulong> zxy = Vector256.Create(2UL, 0UL, 1UL, 3UL);
|
||||
Vector256<ulong> result = (Vector256.Shuffle(l, yzx) * Vector256.Shuffle(r, zxy)) - (Vector256.Shuffle(l, zxy) * Vector256.Shuffle(r, yzx));
|
||||
return FromVector256Unsafe(result);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static Vector256<T> AsVector256Safe<T>(this Vec3<T> source)
|
||||
where T : unmanaged, INumber<T>
|
||||
private static Vec3<long> CrossInt64(Vec3<long> left, Vec3<long> right)
|
||||
{
|
||||
Vector256<T> result = Vector256<T>.Zero;
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<Vector256<T>, byte>(ref result), source);
|
||||
return result;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static Vector128<T> AsVector128Unsafe<T>(this Vec3<T> source)
|
||||
where T : unmanaged, INumber<T>
|
||||
{
|
||||
Unsafe.SkipInit(out Vector128<T> result);
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<Vector128<T>, byte>(ref result), source);
|
||||
return result;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static Vector256<T> AsVector256Unsafe<T>(this Vec3<T> source)
|
||||
where T : unmanaged, INumber<T>
|
||||
{
|
||||
Unsafe.SkipInit(out Vector256<T> result);
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<Vector256<T>, byte>(ref result), source);
|
||||
return result;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static Vec3<T> FromVector128Unsafe<T>(Vector128<T> source)
|
||||
where T : unmanaged, INumber<T>
|
||||
{
|
||||
return Unsafe.As<Vector128<T>, Vec3<T>>(ref source);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static Vec3<T> FromVector256Unsafe<T>(Vector256<T> source)
|
||||
where T : unmanaged, INumber<T>
|
||||
{
|
||||
return Unsafe.As<Vector256<T>, Vec3<T>>(ref source);
|
||||
Vector256<long> l = left.AsVector256Safe();
|
||||
Vector256<long> r = right.AsVector256Safe();
|
||||
Vector256<long> yzx = Vector256.Create(1U, 2U, 0U, 3U);
|
||||
Vector256<long> zxy = Vector256.Create(2U, 0U, 1U, 3U);
|
||||
Vector256<long> result = (Vector256.Shuffle(l, yzx) * Vector256.Shuffle(r, zxy)) - (Vector256.Shuffle(l, zxy) * Vector256.Shuffle(r, yzx));
|
||||
return FromVector256Unsafe(result);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,28 +21,21 @@ namespace StgSharp.Mathematics.Numeric.Graphics
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 16)]
|
||||
public struct Vec3<T> : IUnmanagedVector<Vec3<T>>, IEquatable<Vec3<T>>, IEnumerable<T>
|
||||
where T : unmanaged, INumber<T>
|
||||
where T: unmanaged, INumber<T>
|
||||
{
|
||||
|
||||
public T X;
|
||||
public T Y;
|
||||
public T Z;
|
||||
|
||||
public Vec3(
|
||||
Vec2<T> xy,
|
||||
T z
|
||||
)
|
||||
public Vec3(Vec2<T> xy, T z)
|
||||
{
|
||||
X = xy.X;
|
||||
Y = xy.Y;
|
||||
Z = z;
|
||||
}
|
||||
|
||||
public Vec3(
|
||||
T x,
|
||||
T y,
|
||||
T z
|
||||
)
|
||||
public Vec3(T x, T y, T z)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
@@ -80,13 +73,11 @@ namespace StgSharp.Mathematics.Numeric.Graphics
|
||||
public static Vec3<T> UnitZ => new(T.Zero, T.Zero, T.One);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public readonly T Dot(
|
||||
Vec3<T> right
|
||||
)
|
||||
public readonly T Dot(Vec3<T> right)
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4)
|
||||
if (Unsafe.SizeOf<T>() == 8)
|
||||
{
|
||||
Vec4<T> v = Vec4.FromVector128Unsafe(this.AsVector128Unsafe() * right.AsVector128Unsafe());
|
||||
Vec4<T> v = Vec4.FromVector256Unsafe(this.AsVector256Unsafe() * right.AsVector256Unsafe());
|
||||
return v.X + v.Y + v.Z;
|
||||
}
|
||||
if (Unsafe.SizeOf<T>() == 4)
|
||||
@@ -98,23 +89,23 @@ namespace StgSharp.Mathematics.Numeric.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public readonly bool Equals(
|
||||
Vec3<T> other
|
||||
)
|
||||
public readonly bool Equals(Vec3<T> other)
|
||||
{
|
||||
return X == other.X && Y == other.Y && Z == other.Z;
|
||||
if (Unsafe.SizeOf<T>() == 4) {
|
||||
return this.AsVector128Safe() == other.AsVector128Safe();
|
||||
}
|
||||
if (Unsafe.SizeOf<T>() == 8) {
|
||||
return this.AsVector256Safe() == other.AsVector256Safe();
|
||||
}
|
||||
throw GraphicVector.ThrowUnsupportedTypeException<T>();
|
||||
}
|
||||
|
||||
public override readonly bool Equals(
|
||||
object? obj
|
||||
)
|
||||
public override readonly bool Equals(object? obj)
|
||||
{
|
||||
return obj is Vec3<T> other && Equals(other);
|
||||
}
|
||||
|
||||
public static Vec3<T> FromSpan(
|
||||
ReadOnlySpan<T> span
|
||||
)
|
||||
public static Vec3<T> FromSpan(ReadOnlySpan<T> span)
|
||||
{
|
||||
if (span.Length < 3) {
|
||||
throw new ArgumentException("Span length must be at least 3.", nameof(span));
|
||||
@@ -141,18 +132,13 @@ namespace StgSharp.Mathematics.Numeric.Graphics
|
||||
return T.Max(X, T.Max(Y, Z));
|
||||
}
|
||||
|
||||
public static bool IsParallel(
|
||||
Vec3<T> left,
|
||||
Vec3<T> right
|
||||
)
|
||||
public static bool IsParallel(Vec3<T> left, Vec3<T> right)
|
||||
{
|
||||
return Vec3.Cross(left, right) == Zero;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec3<T> operator -(
|
||||
Vec3<T> value
|
||||
)
|
||||
public static Vec3<T> operator -(Vec3<T> value)
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4) {
|
||||
return Vec3.FromVector128Unsafe(Vector128<T>.Zero - value.AsVector128Unsafe());
|
||||
@@ -164,10 +150,7 @@ namespace StgSharp.Mathematics.Numeric.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec3<T> operator -(
|
||||
Vec3<T> left,
|
||||
Vec3<T> right
|
||||
)
|
||||
public static Vec3<T> operator -(Vec3<T> left, Vec3<T> right)
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4)
|
||||
{
|
||||
@@ -185,19 +168,13 @@ namespace StgSharp.Mathematics.Numeric.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator !=(
|
||||
Vec3<T> left,
|
||||
Vec3<T> right
|
||||
)
|
||||
public static bool operator !=(Vec3<T> left, Vec3<T> right)
|
||||
{
|
||||
return !left.Equals(right);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec3<T> operator *(
|
||||
Vec3<T> vector,
|
||||
T scalar
|
||||
)
|
||||
public static Vec3<T> operator *(Vec3<T> vector, T scalar)
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4)
|
||||
{
|
||||
@@ -215,28 +192,19 @@ namespace StgSharp.Mathematics.Numeric.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec3<T> operator *(
|
||||
T scalar,
|
||||
Vec3<T> vector
|
||||
)
|
||||
public static Vec3<T> operator *(T scalar, Vec3<T> vector)
|
||||
{
|
||||
return vector * scalar;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static T operator *(
|
||||
Vec3<T> left,
|
||||
Vec3<T> right
|
||||
)
|
||||
public static T operator *(Vec3<T> left, Vec3<T> right)
|
||||
{
|
||||
return left.Dot(right);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec3<T> operator /(
|
||||
Vec3<T> vector,
|
||||
T scalar
|
||||
)
|
||||
public static Vec3<T> operator /(Vec3<T> vector, T scalar)
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4)
|
||||
{
|
||||
@@ -254,10 +222,7 @@ namespace StgSharp.Mathematics.Numeric.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec3<T> operator +(
|
||||
Vec3<T> left,
|
||||
Vec3<T> right
|
||||
)
|
||||
public static Vec3<T> operator +(Vec3<T> left, Vec3<T> right)
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4)
|
||||
{
|
||||
@@ -275,18 +240,13 @@ namespace StgSharp.Mathematics.Numeric.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator ==(
|
||||
Vec3<T> left,
|
||||
Vec3<T> right
|
||||
)
|
||||
public static bool operator ==(Vec3<T> left, Vec3<T> right)
|
||||
{
|
||||
return left.Equals(right);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator Vec3<T>(
|
||||
(T X, T Y, T Z) tuple
|
||||
)
|
||||
public static implicit operator Vec3<T>((T X, T Y, T Z) tuple)
|
||||
{
|
||||
return new(tuple.X, tuple.Y, tuple.Z);
|
||||
}
|
||||
|
||||
@@ -5,16 +5,8 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using StgSharp.HighPerformance.ProcessorAbstraction;
|
||||
using StgSharp.Mathematics;
|
||||
using StgSharp.Mathematics.Internal;
|
||||
using StgSharp.Mathematics.Numeric;
|
||||
using StgSharp.Mathematics.Numeric.Graphics;
|
||||
using System;
|
||||
using System.Data.Common;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
|
||||
namespace StgSharp.Mathematics.Numeric.Graphics
|
||||
@@ -23,9 +15,7 @@ namespace StgSharp.Mathematics.Numeric.Graphics
|
||||
{
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static Vector128<T> AsVector128Unsafe<T>(
|
||||
this Vec4<T> source
|
||||
) where T : unmanaged, INumber<T>
|
||||
internal static Vector128<T> AsVector128Unsafe<T>(this Vec4<T> source) where T: unmanaged, INumber<T>
|
||||
{
|
||||
Unsafe.SkipInit(out Vector128<T> result);
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<Vector128<T>, byte>(ref result), source);
|
||||
@@ -33,9 +23,7 @@ namespace StgSharp.Mathematics.Numeric.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static Vector256<T> AsVector256Unsafe<T>(
|
||||
this Vec4<T> source
|
||||
) where T : unmanaged, INumber<T>
|
||||
internal static Vector256<T> AsVector256Unsafe<T>(this Vec4<T> source) where T: unmanaged, INumber<T>
|
||||
{
|
||||
Unsafe.SkipInit(out Vector256<T> result);
|
||||
Unsafe.WriteUnaligned(ref Unsafe.As<Vector256<T>, byte>(ref result), source);
|
||||
@@ -43,177 +31,39 @@ namespace StgSharp.Mathematics.Numeric.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static Vec4<T> FromVector128Unsafe<T>(
|
||||
Vector128<T> source
|
||||
) where T : unmanaged, INumber<T>
|
||||
internal static Vec4<T> FromVector128Unsafe<T>(Vector128<T> source) where T: unmanaged, INumber<T>
|
||||
{
|
||||
return Unsafe.As<Vector128<T>, Vec4<T>>(ref source);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static Vec4<T> FromVector256Unsafe<T>(
|
||||
Vector256<T> source
|
||||
) where T : unmanaged, INumber<T>
|
||||
internal static Vec4<T> FromVector256Unsafe<T>(Vector256<T> source) where T: unmanaged, INumber<T>
|
||||
{
|
||||
return Unsafe.As<Vector256<T>, Vec4<T>>(ref source);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A three dimension vector defined by two elements. Vec3 in World are default used as colum
|
||||
/// vector.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 16)]
|
||||
public struct Vec4<T> : IUnmanagedVector<Vec4<T>> where T : unmanaged, INumber<T>
|
||||
{
|
||||
|
||||
public T W;
|
||||
|
||||
public T X;
|
||||
public T Y;
|
||||
public T Z;
|
||||
|
||||
public Vec4(
|
||||
Vec3<T> v3,
|
||||
T w
|
||||
)
|
||||
{
|
||||
XYZ = v3;
|
||||
W = w;
|
||||
}
|
||||
|
||||
public Vec4(
|
||||
T x,
|
||||
T y,
|
||||
T z,
|
||||
T w
|
||||
)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Z = z;
|
||||
W = w;
|
||||
}
|
||||
|
||||
public unsafe Vec2<T> XY
|
||||
{
|
||||
get => Vec2.FromVector128Unsafe(this.AsVector128Unsafe());
|
||||
set
|
||||
{
|
||||
X = value.X;
|
||||
Y = value.Y;
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe Vec3<T> XYZ
|
||||
{
|
||||
get => Vec3.FromVector128Unsafe(this.AsVector128Unsafe());
|
||||
set
|
||||
{
|
||||
T w = W;
|
||||
Unsafe.As<T, Vec3<T>>(ref X) = value;
|
||||
W = w;
|
||||
}
|
||||
}
|
||||
|
||||
public static Vec4<T> One => new(T.One, T.One, T.One, T.One);
|
||||
|
||||
public static Vec4<T> Zero => new(T.Zero, T.Zero, T.Zero, T.Zero);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec4<T> Add(
|
||||
Vec4<T> left,
|
||||
Vec4<T> right
|
||||
)
|
||||
public static Vec4<float> ConvertToSingle(Vec4<int> source)
|
||||
{
|
||||
return left + right;
|
||||
}
|
||||
|
||||
public ReadOnlySpan<T> AsSpan()
|
||||
{
|
||||
return MemoryMarshal.CreateReadOnlySpan(ref X, 4);
|
||||
}
|
||||
|
||||
public override bool Equals(
|
||||
object obj
|
||||
)
|
||||
{
|
||||
return (obj is Vec4<T> v) && (v == this);
|
||||
}
|
||||
|
||||
public static Vec4<T> FromSpan(
|
||||
ReadOnlySpan<T> span
|
||||
)
|
||||
{
|
||||
if (span.Length < 4) {
|
||||
throw new ArgumentException("Span length must be at least 4.", nameof(span));
|
||||
}
|
||||
|
||||
Unsafe.SkipInit(out Vec4<T> result);
|
||||
Span<T> target = MemoryMarshal.CreateSpan(ref result.X, 4);
|
||||
span[..4].CopyTo(target);
|
||||
return result;
|
||||
return FromVector128Unsafe(Vector128.ConvertToSingle(source.AsVector128Unsafe()));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ReadOnlySpan<T>.Enumerator GetEnumerator()
|
||||
public static Vec4<float> ConvertToSingle(Vec4<uint> source)
|
||||
{
|
||||
return AsSpan().GetEnumerator();
|
||||
return FromVector128Unsafe(Vector128.ConvertToSingle(source.AsVector128Unsafe()));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec4<T> operator -(
|
||||
Vec4<T> left,
|
||||
Vec4<T> right
|
||||
)
|
||||
public static Vec4<double> ConvertToDouble(Vec4<long> source)
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4) {
|
||||
return Vec4.FromVector128Unsafe(left.AsVector128Unsafe() - right.AsVector128Unsafe());
|
||||
}
|
||||
if (Unsafe.SizeOf<T>() == 8) {
|
||||
return Vec4.FromVector256Unsafe(left.AsVector256Unsafe() - right.AsVector256Unsafe());
|
||||
}
|
||||
throw GraphicVector.ThrowUnsupportedTypeException<T>();
|
||||
}
|
||||
|
||||
public static bool operator !=(
|
||||
Vec4<T> left,
|
||||
Vec4<T> right
|
||||
)
|
||||
{
|
||||
return !(left == right);
|
||||
return FromVector256Unsafe(Vector256.ConvertToDouble(source.AsVector256Unsafe()));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec4<T> operator +(
|
||||
Vec4<T> left,
|
||||
Vec4<T> right
|
||||
)
|
||||
public static Vec4<double> ConvertToDouble(Vec4<ulong> source)
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4) {
|
||||
return Vec4.FromVector128Unsafe(left.AsVector128Unsafe() + right.AsVector128Unsafe());
|
||||
}
|
||||
if (Unsafe.SizeOf<T>() == 8) {
|
||||
return Vec4.FromVector256Unsafe(left.AsVector256Unsafe() + right.AsVector256Unsafe());
|
||||
}
|
||||
throw GraphicVector.ThrowUnsupportedTypeException<T>();
|
||||
}
|
||||
|
||||
public static bool operator ==(
|
||||
Vec4<T> left,
|
||||
Vec4<T> right
|
||||
)
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4) {
|
||||
return left.AsVector128Unsafe() == right.AsVector128Unsafe();
|
||||
}
|
||||
if (Unsafe.SizeOf<T>() == 8) {
|
||||
return left.AsVector256Unsafe() == right.AsVector256Unsafe();
|
||||
}
|
||||
#pragma warning disable CA1065
|
||||
throw GraphicVector.ThrowUnsupportedTypeException<T>();
|
||||
#pragma warning restore CA1065
|
||||
return FromVector256Unsafe(Vector256.ConvertToDouble(source.AsVector256Unsafe()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,203 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// file="Vec4_T"
|
||||
// Project: StgSharp
|
||||
// Copyright (c) Nitload.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using StgSharp.Mathematics.Numeric;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
|
||||
namespace StgSharp.Mathematics.Numeric.Graphics
|
||||
{
|
||||
/// <summary>
|
||||
/// A four-dimensional numeric vector.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 16)]
|
||||
public struct Vec4<T> : IUnmanagedVector<Vec4<T>> where T: unmanaged, INumber<T>
|
||||
{
|
||||
|
||||
public T X;
|
||||
public T Y;
|
||||
public T Z;
|
||||
public T W;
|
||||
|
||||
public Vec4(Vec3<T> v3, T w)
|
||||
{
|
||||
X = v3.X;
|
||||
Y = v3.Y;
|
||||
Z = v3.Z;
|
||||
W = w;
|
||||
}
|
||||
|
||||
public Vec4(T x, T y, T z, T w)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Z = z;
|
||||
W = w;
|
||||
}
|
||||
|
||||
public Vec2<T> XY
|
||||
{
|
||||
readonly get => new(X, Y);
|
||||
set
|
||||
{
|
||||
X = value.X;
|
||||
Y = value.Y;
|
||||
}
|
||||
}
|
||||
|
||||
public Vec3<T> XYZ
|
||||
{
|
||||
readonly get => new(X, Y, Z);
|
||||
set
|
||||
{
|
||||
T w = W;
|
||||
Unsafe.As<T, Vec3<T>>(ref X) = value;
|
||||
W = w;
|
||||
}
|
||||
}
|
||||
|
||||
public static Vec4<T> One => new(T.One, T.One, T.One, T.One);
|
||||
|
||||
public static Vec4<T> Zero => new(T.Zero, T.Zero, T.Zero, T.Zero);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec4<T> Add(Vec4<T> left, Vec4<T> right)
|
||||
{
|
||||
return left + right;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public readonly T Dot(Vec4<T> right)
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4)
|
||||
{
|
||||
Vec4<T> product = Vec4.FromVector128Unsafe(this.AsVector128Unsafe() * right.AsVector128Unsafe());
|
||||
return product.X + product.Y + product.Z + product.W;
|
||||
}
|
||||
if (Unsafe.SizeOf<T>() == 8)
|
||||
{
|
||||
Vec4<T> product = Vec4.FromVector256Unsafe(this.AsVector256Unsafe() * right.AsVector256Unsafe());
|
||||
return product.X + product.Y + product.Z + product.W;
|
||||
}
|
||||
throw GraphicVector.ThrowUnsupportedTypeException<T>();
|
||||
}
|
||||
|
||||
public ReadOnlySpan<T> AsSpan()
|
||||
{
|
||||
return MemoryMarshal.CreateReadOnlySpan(ref X, 4);
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return (obj is Vec4<T> v) && (v == this);
|
||||
}
|
||||
|
||||
public static Vec4<T> FromSpan(ReadOnlySpan<T> span)
|
||||
{
|
||||
if (span.Length < 4) {
|
||||
throw new ArgumentException("Span length must be at least 4.", nameof(span));
|
||||
}
|
||||
|
||||
Unsafe.SkipInit(out Vec4<T> result);
|
||||
Span<T> target = MemoryMarshal.CreateSpan(ref result.X, 4);
|
||||
span[..4].CopyTo(target);
|
||||
return result;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ReadOnlySpan<T>.Enumerator GetEnumerator()
|
||||
{
|
||||
return AsSpan().GetEnumerator();
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(X, Y, Z, W);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec4<T> operator -(Vec4<T> left, Vec4<T> right)
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4) {
|
||||
return Vec4.FromVector128Unsafe(left.AsVector128Unsafe() - right.AsVector128Unsafe());
|
||||
}
|
||||
if (Unsafe.SizeOf<T>() == 8) {
|
||||
return Vec4.FromVector256Unsafe(left.AsVector256Unsafe() - right.AsVector256Unsafe());
|
||||
}
|
||||
throw GraphicVector.ThrowUnsupportedTypeException<T>();
|
||||
}
|
||||
|
||||
public static bool operator !=(Vec4<T> left, Vec4<T> right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec4<T> operator *(Vec4<T> vector, T scalar)
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4) {
|
||||
return Vec4.FromVector128Unsafe(vector.AsVector128Unsafe() * Vector128.Create(scalar));
|
||||
}
|
||||
if (Unsafe.SizeOf<T>() == 8) {
|
||||
return Vec4.FromVector256Unsafe(vector.AsVector256Unsafe() * Vector256.Create(scalar));
|
||||
}
|
||||
throw GraphicVector.ThrowUnsupportedTypeException<T>();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec4<T> operator *(T scalar, Vec4<T> vector)
|
||||
{
|
||||
return vector * scalar;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static T operator *(Vec4<T> left, Vec4<T> right)
|
||||
{
|
||||
return left.Dot(right);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec4<T> operator /(Vec4<T> vector, T scalar)
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4) {
|
||||
return Vec4.FromVector128Unsafe(vector.AsVector128Unsafe() / Vector128.Create(scalar));
|
||||
}
|
||||
if (Unsafe.SizeOf<T>() == 8) {
|
||||
return Vec4.FromVector256Unsafe(vector.AsVector256Unsafe() / Vector256.Create(scalar));
|
||||
}
|
||||
throw GraphicVector.ThrowUnsupportedTypeException<T>();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec4<T> operator +(Vec4<T> left, Vec4<T> right)
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4) {
|
||||
return Vec4.FromVector128Unsafe(left.AsVector128Unsafe() + right.AsVector128Unsafe());
|
||||
}
|
||||
if (Unsafe.SizeOf<T>() == 8) {
|
||||
return Vec4.FromVector256Unsafe(left.AsVector256Unsafe() + right.AsVector256Unsafe());
|
||||
}
|
||||
throw GraphicVector.ThrowUnsupportedTypeException<T>();
|
||||
}
|
||||
|
||||
public static bool operator ==(Vec4<T> left, Vec4<T> right)
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4) {
|
||||
return left.AsVector128Unsafe() == right.AsVector128Unsafe();
|
||||
}
|
||||
if (Unsafe.SizeOf<T>() == 8) {
|
||||
return left.AsVector256Unsafe() == right.AsVector256Unsafe();
|
||||
}
|
||||
#pragma warning disable CA1065
|
||||
throw GraphicVector.ThrowUnsupportedTypeException<T>();
|
||||
#pragma warning restore CA1065
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// file="Vector.GetAngle"
|
||||
// Project: StgSharp
|
||||
// Copyright (c) Nitload.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using StgSharp.Mathematics.Numeric.Graphics;
|
||||
|
||||
namespace StgSharp.Mathematics.Numeric.Graphics
|
||||
{
|
||||
public static unsafe partial class Linear
|
||||
{
|
||||
|
||||
public static T GetAngle<T>(
|
||||
Vec2<T> vec1,
|
||||
Vec2<T> vec2
|
||||
) where T : unmanaged, INumber<T>
|
||||
{
|
||||
return MathF.Acos(
|
||||
1 / (vec1.GetLength() * vec2.GetLength()));
|
||||
}
|
||||
|
||||
public static T GetAngle<T>(
|
||||
Vec3<T> vec1,
|
||||
Vec3<T> vec2
|
||||
) where T : unmanaged, INumber<T>
|
||||
{
|
||||
return MathF.Acos(vec1 * vec2 / (vec1.GetLength() * vec2.GetLength()));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -14,17 +14,48 @@ namespace StgSharp.Mathematics.Numeric.Graphics
|
||||
|
||||
public static T GetLength<T>(
|
||||
this Vec3<T> vec
|
||||
) where T : unmanaged, INumber<T>
|
||||
) where T : unmanaged, INumber<T>, IRootFunctions<T>
|
||||
{
|
||||
return T.Sqrt(vec.Dot(vec));
|
||||
}
|
||||
|
||||
public static T GetLength<T>(
|
||||
this Vec2<T> vec
|
||||
) where T : unmanaged, INumber<T>
|
||||
) where T : unmanaged, INumber<T>, IRootFunctions<T>
|
||||
{
|
||||
return T.Sqrt(vec.Dot(vec));
|
||||
}
|
||||
|
||||
public static T GetLength<T>(
|
||||
this Vec4<T> vec
|
||||
) where T : unmanaged, INumber<T>, IRootFunctions<T>
|
||||
{
|
||||
return T.Sqrt(vec.Dot(vec));
|
||||
}
|
||||
|
||||
public static float GetLength(this Vec2<int> vec) => Vec2.ConvertToSingle(vec).GetLength();
|
||||
|
||||
public static float GetLength(this Vec2<uint> vec) => Vec2.ConvertToSingle(vec).GetLength();
|
||||
|
||||
public static double GetLength(this Vec2<long> vec) => Vec2.ConvertToDouble(vec).GetLength();
|
||||
|
||||
public static double GetLength(this Vec2<ulong> vec) => Vec2.ConvertToDouble(vec).GetLength();
|
||||
|
||||
public static float GetLength(this Vec3<int> vec) => Vec3.ConvertToSingle(vec).GetLength();
|
||||
|
||||
public static float GetLength(this Vec3<uint> vec) => Vec3.ConvertToSingle(vec).GetLength();
|
||||
|
||||
public static double GetLength(this Vec3<long> vec) => Vec3.ConvertToDouble(vec).GetLength();
|
||||
|
||||
public static double GetLength(this Vec3<ulong> vec) => Vec3.ConvertToDouble(vec).GetLength();
|
||||
|
||||
public static float GetLength(this Vec4<int> vec) => Vec4.ConvertToSingle(vec).GetLength();
|
||||
|
||||
public static float GetLength(this Vec4<uint> vec) => Vec4.ConvertToSingle(vec).GetLength();
|
||||
|
||||
public static double GetLength(this Vec4<long> vec) => Vec4.ConvertToDouble(vec).GetLength();
|
||||
|
||||
public static double GetLength(this Vec4<ulong> vec) => Vec4.ConvertToDouble(vec).GetLength();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,68 +5,55 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using StgSharp.Mathematics.Numeric.Graphics;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace StgSharp.Mathematics.Numeric.Graphics
|
||||
{
|
||||
public static partial class Linear
|
||||
{
|
||||
|
||||
public static Vec4 Normalize(
|
||||
Vec4 vec
|
||||
)
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec2<T> Normalize<T>(this Vec2<T> vec) where T: unmanaged, INumber<T>, IRootFunctions<T>
|
||||
{
|
||||
return new Vec4
|
||||
{
|
||||
vec = Vector4.Normalize(vec.vec)
|
||||
};
|
||||
return vec / T.Sqrt(vec.Dot(vec));
|
||||
}
|
||||
|
||||
public static Vec3 Normalize(
|
||||
Vec3 vec
|
||||
)
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec3<T> Normalize<T>(this Vec3<T> vec) where T: unmanaged, INumber<T>, IRootFunctions<T>
|
||||
{
|
||||
return new Vec3
|
||||
{
|
||||
v = Vector3.Normalize(vec.v)
|
||||
};
|
||||
return vec / T.Sqrt(vec.Dot(vec));
|
||||
}
|
||||
|
||||
public static unsafe void Normalize(
|
||||
ref Vec4 source,
|
||||
ref Vec4 target
|
||||
)
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec4<T> Normalize<T>(this Vec4<T> vec) where T: unmanaged, INumber<T>, IRootFunctions<T>
|
||||
{
|
||||
Vector4 s = source.vec;
|
||||
Vector4 t = target.vec;
|
||||
|
||||
s = Vector4.Normalize(s);
|
||||
|
||||
Vector4 projection = Vector4.Multiply(s, t);
|
||||
|
||||
t -= projection;
|
||||
|
||||
source.vec = s;
|
||||
target.vec = t;
|
||||
return vec / T.Sqrt(vec.Dot(vec));
|
||||
}
|
||||
|
||||
public static unsafe void Normalize(
|
||||
ref Vec3 source,
|
||||
ref Vec3 target
|
||||
)
|
||||
{
|
||||
Vector3 s = source.v;
|
||||
Vector3 t = target.v;
|
||||
public static Vec2<float> Normalize(this Vec2<int> vec) => Vec2.ConvertToSingle(vec).Normalize();
|
||||
|
||||
s = Vector3.Normalize(s);
|
||||
Vector3 projection = Vector3.Dot(t, s) / Vector3.Dot(s, s) * s;
|
||||
t -= projection;
|
||||
t = Vector3.Normalize(t);
|
||||
public static Vec2<float> Normalize(this Vec2<uint> vec) => Vec2.ConvertToSingle(vec).Normalize();
|
||||
|
||||
source.v = s;
|
||||
target.v = t;
|
||||
}
|
||||
public static Vec2<double> Normalize(this Vec2<long> vec) => Vec2.ConvertToDouble(vec).Normalize();
|
||||
|
||||
public static Vec2<double> Normalize(this Vec2<ulong> vec) => Vec2.ConvertToDouble(vec).Normalize();
|
||||
|
||||
public static Vec3<float> Normalize(this Vec3<int> vec) => Vec3.ConvertToSingle(vec).Normalize();
|
||||
|
||||
public static Vec3<float> Normalize(this Vec3<uint> vec) => Vec3.ConvertToSingle(vec).Normalize();
|
||||
|
||||
public static Vec3<double> Normalize(this Vec3<long> vec) => Vec3.ConvertToDouble(vec).Normalize();
|
||||
|
||||
public static Vec3<double> Normalize(this Vec3<ulong> vec) => Vec3.ConvertToDouble(vec).Normalize();
|
||||
|
||||
public static Vec4<float> Normalize(this Vec4<int> vec) => Vec4.ConvertToSingle(vec).Normalize();
|
||||
|
||||
public static Vec4<float> Normalize(this Vec4<uint> vec) => Vec4.ConvertToSingle(vec).Normalize();
|
||||
|
||||
public static Vec4<double> Normalize(this Vec4<long> vec) => Vec4.ConvertToDouble(vec).Normalize();
|
||||
|
||||
public static Vec4<double> Normalize(this Vec4<ulong> vec) => Vec4.ConvertToDouble(vec).Normalize();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,21 +10,14 @@ using System.Runtime.CompilerServices;
|
||||
|
||||
namespace StgSharp.RegularAnalysis.Text
|
||||
{
|
||||
// TODO 现在存在的问题是,AstNode过于依赖NodeFlag表达其内部语义,这导致进行精细优化时识别节点语义复杂,
|
||||
// TODO 当前Ast的类型差异过小,不利于保存特征数据,应当争取进一步细化,或者说这是AstNode一开始为了简化架构设计引入的妥协
|
||||
internal class RegexAstNode : ISyntaxNode<RegexAstNode, RegexElementLabel>
|
||||
{
|
||||
|
||||
// private RegexAstNode _left, _right;
|
||||
|
||||
public RegexAstNode(
|
||||
Token<RegexElementLabel> source
|
||||
)
|
||||
: this(RegexCommonPayload.FromToken(source)) { }
|
||||
public RegexAstNode(Token<RegexElementLabel> source) : this(RegexCommonPayload.FromToken(source)) { }
|
||||
|
||||
public RegexAstNode(
|
||||
RegexAstPayload payload
|
||||
)
|
||||
public RegexAstNode(RegexAstPayload payload)
|
||||
{
|
||||
Payload = payload;
|
||||
}
|
||||
@@ -85,19 +78,14 @@ namespace StgSharp.RegularAnalysis.Text
|
||||
|
||||
public string SourceCode => Source.Source;
|
||||
|
||||
public void AppendNode(
|
||||
RegexAstNode nextToken
|
||||
)
|
||||
public void AppendNode(RegexAstNode nextToken)
|
||||
{
|
||||
Next = nextToken;
|
||||
nextToken.Previous = this;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static (bool Valid, int Value) ComparePrecedence(
|
||||
RegexElementLabel left,
|
||||
RegexElementLabel right
|
||||
)
|
||||
public static (bool Valid, int Value) ComparePrecedence(RegexElementLabel left, RegexElementLabel right)
|
||||
{
|
||||
left &= RegexElementLabel.OPERATOR;
|
||||
right &= RegexElementLabel.OPERATOR;
|
||||
@@ -109,25 +97,19 @@ namespace StgSharp.RegularAnalysis.Text
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsNullOrEmpty(
|
||||
RegexAstNode node
|
||||
)
|
||||
public static bool IsNullOrEmpty(RegexAstNode node)
|
||||
{
|
||||
return node is null || ReferenceEquals(node, Empty);
|
||||
}
|
||||
/**/
|
||||
|
||||
public void PrependNode(
|
||||
RegexAstNode previousNode
|
||||
)
|
||||
public void PrependNode(RegexAstNode previousNode)
|
||||
{
|
||||
Previous = previousNode;
|
||||
previousNode.Next = this;
|
||||
}
|
||||
|
||||
public void RemoveChild(
|
||||
RegexAstNode node
|
||||
)
|
||||
public void RemoveChild(RegexAstNode node)
|
||||
{
|
||||
if (Left == node)
|
||||
{
|
||||
@@ -145,7 +127,7 @@ namespace StgSharp.RegularAnalysis.Text
|
||||
return new EmptyRegexAstNode();
|
||||
}
|
||||
|
||||
internal TPayload PayloadAs<TPayload>() where TPayload : RegexAstPayload
|
||||
internal TPayload PayloadAs<TPayload>() where TPayload: RegexAstPayload
|
||||
{
|
||||
return
|
||||
Payload as TPayload ??
|
||||
@@ -153,9 +135,7 @@ namespace StgSharp.RegularAnalysis.Text
|
||||
$"Node {Label} does not carry {typeof(TPayload).Name}.");
|
||||
}
|
||||
|
||||
internal void RemoveAndAsChild(
|
||||
bool useLeft
|
||||
)
|
||||
internal void RemoveAndAsChild(bool useLeft)
|
||||
{
|
||||
if (useLeft)
|
||||
{
|
||||
@@ -180,9 +160,7 @@ namespace StgSharp.RegularAnalysis.Text
|
||||
/// <param name="node">
|
||||
/// The node to replace the current node with.
|
||||
/// </param>
|
||||
internal void ReplaceBy(
|
||||
RegexAstNode node
|
||||
)
|
||||
internal void ReplaceBy(RegexAstNode node)
|
||||
{
|
||||
Payload = node.Payload;
|
||||
Left = node.Left;
|
||||
|
||||
Reference in New Issue
Block a user