New opengl api binding and new graphic purpose vector design

Signed-off-by: Nitload <YoumuLiu_NSI@whv0t.onmicrosoft.com>
This commit is contained in:
Nitload
2026-08-29 23:10:44 +08:00
parent 0b2593a5f6
commit 5d680542a8
16 changed files with 589 additions and 549 deletions
+13 -139
View File
@@ -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>
{
public T X;
public T Y;
public Vec2(
T x,
T y
)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vec2<float> ConvertToSingle(Vec2<int> source)
{
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);
}
}
}
+131 -70
View File
@@ -15,50 +15,130 @@ namespace StgSharp.Mathematics.Numeric.Graphics
public static class Vec3
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vec3<T> Cross<T>(Vec3<T> left, Vec3<T> right)
where T : unmanaged, INumber<T>
public static bool IsParallel<T>(Vec3<T> left, Vec3<T> right) where T: unmanaged,INumber<T>
{
if (typeof(T) == typeof(float)) {
return Cross(left, right).Equals(T.Zero);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
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))
{
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);
}
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);
}
throw new NotSupportedException($"Cross product is not supported for {typeof(T)}.");
}
[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]);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static Vec3<double> CrossDouble(Vec3<double> left, Vec3<double> right)
{
@@ -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);
}
+12 -162
View File
@@ -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;