Graphic mat 44 is now generic; TextRegex source gen will use goto instead of do{}while()
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Root Type="DevExpress.CodeRush.Formatting.UI.Options.BracesOptionsContainer">
|
||||
<Options Language="C#">
|
||||
<Options>
|
||||
<Item Id="{3920243c-1bac-46ce-960d-e4186d99c187}" Type="DevExpress.CodeRush.Formatting.UI.Options.Conversion.PropertyBracesOption">
|
||||
<WrapOpenBrace>
|
||||
<Option>Wrap</Option>
|
||||
</WrapOpenBrace>
|
||||
<WrapCloseBrace>
|
||||
<Option>Wrap</Option>
|
||||
</WrapCloseBrace>
|
||||
</Item>
|
||||
<Item Id="{692dd27b-3066-4dd3-beac-516a569f5203}" Type="DevExpress.CodeRush.Formatting.UI.Options.Conversion.SimplePropertyBracesOption">
|
||||
<WrapOpenBrace>
|
||||
<Option>Wrap</Option>
|
||||
</WrapOpenBrace>
|
||||
<WrapCloseBrace>
|
||||
<Option>Wrap</Option>
|
||||
</WrapCloseBrace>
|
||||
</Item>
|
||||
</Options>
|
||||
</Options>
|
||||
</Root>
|
||||
@@ -1,12 +0,0 @@
|
||||
[*]
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{bat,cmd,ps1}]
|
||||
end_of_line = crlf
|
||||
|
||||
[*.cs]
|
||||
# CS1591: 缺少对公共可见类型或成员的 XML 注释
|
||||
dotnet_diagnostic.CS1591.severity = suggestion
|
||||
@@ -15,11 +15,11 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
{
|
||||
|
||||
private bool _isLookAtAvailable;
|
||||
internal GraphicsMatrix _lookAt;
|
||||
internal GraphicsMatrix _projection;
|
||||
internal GraphicsMatrix cameraAtt;
|
||||
internal GraphicsMatrix rotation;
|
||||
internal GraphicsMatrix rotationAtt;
|
||||
internal GMatrix44<float> _lookAt;
|
||||
internal GMatrix44<float> _projection;
|
||||
internal GMatrix44<float> cameraAtt;
|
||||
internal GMatrix44<float> rotation;
|
||||
internal GMatrix44<float> rotationAtt;
|
||||
internal Radius _pitch;
|
||||
internal Radius _row;
|
||||
internal Radius _yaw;
|
||||
@@ -27,13 +27,13 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
|
||||
public Camera()
|
||||
{
|
||||
cameraAtt = GraphicsMatrix.Unit;
|
||||
cameraAtt = GMatrix44<float>.Unit;
|
||||
_target = Vec3<float>.Zero;
|
||||
up = Vec3<float>.Zero;
|
||||
_isLookAtAvailable = false;
|
||||
_lookAt = GraphicsMatrix.Unit;
|
||||
rotationAtt = GraphicsMatrix.Unit;
|
||||
_projection = new GraphicsMatrix();
|
||||
_lookAt = GMatrix44<float>.Unit;
|
||||
rotationAtt = GMatrix44<float>.Unit;
|
||||
_projection = new GMatrix44<float>();
|
||||
}
|
||||
|
||||
public Camera(
|
||||
@@ -43,32 +43,32 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
)
|
||||
: this()
|
||||
{
|
||||
rotationAtt = GraphicsMatrix.Unit;
|
||||
cameraAtt = new GraphicsMatrix();
|
||||
rotationAtt = GMatrix44<float>.Unit;
|
||||
cameraAtt = new GMatrix44<float>();
|
||||
SetViewDirection(position, target, up);
|
||||
_pitch = Radius.Zero;
|
||||
_row = Radius.Zero;
|
||||
_yaw = Radius.Zero;
|
||||
}
|
||||
|
||||
public GraphicsMatrix Projection => _projection;
|
||||
public GMatrix44<float> Projection => _projection;
|
||||
|
||||
public GraphicsMatrix View
|
||||
public GMatrix44<float> View
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_isLookAtAvailable) {
|
||||
return _lookAt;
|
||||
}
|
||||
GraphicsMatrix move = GraphicsMatrix.Unit;
|
||||
move.column[3] -= cameraAtt.column[3];
|
||||
GMatrix44<float> move = GMatrix44<float>.Unit;
|
||||
move[3] = move[3] - cameraAtt[3];
|
||||
_lookAt = rotationAtt.Transpose * move;
|
||||
_isLookAtAvailable = true;
|
||||
return _lookAt;
|
||||
}
|
||||
}
|
||||
|
||||
public GraphicsMatrix CameraMatrix()
|
||||
public GMatrix44<float> CameraMatrix()
|
||||
{
|
||||
return Projection * View;
|
||||
}
|
||||
@@ -77,7 +77,7 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
float distance
|
||||
)
|
||||
{
|
||||
cameraAtt.column[3].Z -= distance;
|
||||
cameraAtt[3, 2] -= distance;
|
||||
_isLookAtAvailable = false;
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
float distance
|
||||
)
|
||||
{
|
||||
cameraAtt.column[3].X -= distance;
|
||||
cameraAtt[3, 0] -= distance;
|
||||
_isLookAtAvailable = false;
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
float distance
|
||||
)
|
||||
{
|
||||
cameraAtt.column[3].Y -= distance;
|
||||
cameraAtt[3, 1] -= distance;
|
||||
_isLookAtAvailable = false;
|
||||
}
|
||||
|
||||
@@ -104,9 +104,9 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
)
|
||||
{
|
||||
Vec3<float> direction = position - target;
|
||||
if ((position == cameraAtt.column[3].XYZ) &&
|
||||
if ((position == new Vec3<float>(cameraAtt[3, 0], cameraAtt[3, 1], cameraAtt[3, 2])) &&
|
||||
(this.up == up) &&
|
||||
(cameraAtt.column[3].XYZ == direction)) {
|
||||
(new Vec3<float>(cameraAtt[3, 0], cameraAtt[3, 1], cameraAtt[3, 2]) == direction)) {
|
||||
return;
|
||||
}
|
||||
if (direction.GetLength() == 0)
|
||||
@@ -126,10 +126,10 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
|
||||
Vec3<float> right = Linear.Orthogonalize(Vec3.Cross(up, direction));
|
||||
|
||||
cameraAtt.column[0].XYZ = right;
|
||||
cameraAtt.column[1].XYZ = up;
|
||||
cameraAtt.column[2].XYZ = direction;
|
||||
cameraAtt.column[3].XYZ = position;
|
||||
cameraAtt[0] = new Vec4<float>(right, 0);
|
||||
cameraAtt[1] = new Vec4<float>(up, 0);
|
||||
cameraAtt[2] = new Vec4<float>(direction, 0);
|
||||
cameraAtt[3] = new Vec4<float>(position, 1);
|
||||
|
||||
InternalPitch();
|
||||
InternalRow();
|
||||
@@ -152,13 +152,13 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
width = MathF.Abs(GeometryScaler.Tan(fovRadius / 2) * near * 2),
|
||||
height = (width * size.Y) / size.X;
|
||||
|
||||
_projection.column[0].X = (2 * near) / width;
|
||||
_projection.column[1].Y = (2 * near) / height;
|
||||
_projection.column[2].X = (2 * offsetX) / width;
|
||||
_projection.column[2].Y = (2 * offsetY) / height;
|
||||
_projection.column[2].Z = (far + near) / (near - far);
|
||||
_projection.column[2].W = -1;
|
||||
_projection.column[3].Z = (2 * near * far) / (near - far);
|
||||
_projection[0].X = (2 * near) / width;
|
||||
_projection[1].Y = (2 * near) / height;
|
||||
_projection[2].X = (2 * offsetX) / width;
|
||||
_projection[2].Y = (2 * offsetY) / height;
|
||||
_projection[2].Z = (far + near) / (near - far);
|
||||
_projection[2].W = -1;
|
||||
_projection[3].Z = (2 * near * far) / (near - far);
|
||||
}
|
||||
|
||||
public void Test(
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// file="EBO"
|
||||
// Project: StgSharp
|
||||
// Copyright (c) Nitload.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
namespace Nitload.Graphics.OpenGL
|
||||
{
|
||||
/// <summary>A set of OpenGL element-buffer handles.</summary>
|
||||
public sealed record class ElementBuffer(
|
||||
GlHandle[] Handles
|
||||
)
|
||||
{
|
||||
|
||||
public int Count => Handles.Length;
|
||||
|
||||
public GlHandle this[int index] => Handles[index];
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// file="FBO"
|
||||
// Project: StgSharp
|
||||
// Copyright (c) Nitload.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
namespace Nitload.Graphics.OpenGL
|
||||
{
|
||||
/// <summary>A set of OpenGL framebuffer handles.</summary>
|
||||
public sealed record class FrameBuffer(
|
||||
GlHandle[] Handles
|
||||
)
|
||||
{
|
||||
|
||||
public int Count => Handles.Length;
|
||||
|
||||
public GlHandle this[int index] => Handles[index];
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// file="RBO"
|
||||
// Project: StgSharp
|
||||
// Copyright (c) Nitload.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
namespace Nitload.Graphics.OpenGL
|
||||
{
|
||||
/// <summary>A set of OpenGL renderbuffer handles.</summary>
|
||||
public sealed record class RenderBuffer(
|
||||
GlHandle[] Handles
|
||||
)
|
||||
{
|
||||
|
||||
public int Count => Handles.Length;
|
||||
|
||||
public GlHandle this[int index] => Handles[index];
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// file="TextureGL"
|
||||
// Project: StgSharp
|
||||
// Copyright (c) Nitload.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
namespace Nitload.Graphics.OpenGL
|
||||
{
|
||||
/// <summary>A set of OpenGL texture handles.</summary>
|
||||
public sealed record class TextureGL(
|
||||
GlHandle[] Handles
|
||||
)
|
||||
{
|
||||
|
||||
public int Count => Handles.Length;
|
||||
|
||||
public GlHandle this[int index] => Handles[index];
|
||||
|
||||
}
|
||||
|
||||
public readonly record struct TextureProperty(
|
||||
TextureFilter FilterOnMagnify,
|
||||
TextureFilter FilterOnMinify,
|
||||
TextureWrap WrapOnHorizontal,
|
||||
TextureWrap WrapOnVertical
|
||||
);
|
||||
|
||||
#pragma warning disable CA1008
|
||||
public enum TextureFilter
|
||||
#pragma warning restore CA1008
|
||||
{
|
||||
|
||||
Nearest = glConst.NEAREST,
|
||||
Linear = glConst.LINEAR,
|
||||
NearestLinearMipmap = glConst.NEAREST_MIPMAP_LINEAR,
|
||||
LinearLinearMipmap = glConst.LINEAR_MIPMAP_LINEAR,
|
||||
NearestNearestMipmap = glConst.NEAREST_MIPMAP_NEAREST,
|
||||
LinearNearestMipmap = glConst.LINEAR_MIPMAP_NEAREST,
|
||||
|
||||
}
|
||||
|
||||
#pragma warning disable CA1008
|
||||
public enum TextureWrap
|
||||
#pragma warning restore CA1008
|
||||
{
|
||||
|
||||
Repeat = glConst.REPEAT,
|
||||
MirroredRepeat = glConst.MIRRORED_REPEAT,
|
||||
ClampToEdge = glConst.CLAMP_TO_EDGE,
|
||||
ClampToBorder = glConst.CLAMP_TO_BORDER,
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// file="VAO"
|
||||
// Project: StgSharp
|
||||
// Copyright (c) Nitload.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
namespace Nitload.Graphics.OpenGL
|
||||
{
|
||||
/// <summary>A set of OpenGL vertex-array handles.</summary>
|
||||
public sealed record class VertexArray(
|
||||
GlHandle[] Handles
|
||||
)
|
||||
{
|
||||
|
||||
public int Count => Handles.Length;
|
||||
|
||||
public GlHandle this[int index] => Handles[index];
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// file="VBO"
|
||||
// Project: StgSharp
|
||||
// Copyright (c) Nitload.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
namespace Nitload.Graphics.OpenGL
|
||||
{
|
||||
/// <summary>A set of OpenGL vertex-buffer handles.</summary>
|
||||
public sealed record class VertexBuffer(
|
||||
GlHandle[] Handles
|
||||
)
|
||||
{
|
||||
|
||||
public int Count => Handles.Length;
|
||||
|
||||
public GlHandle this[int index] => Handles[index];
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1783,9 +1783,12 @@ namespace Nitload.Graphics.OpenGL
|
||||
/// <para>See <see href="https://docs.gl/gl4/glUniform">docs.gl</see>.</para>
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Uniform(int location, bool transpose, GraphicsMatrix value)
|
||||
public void Uniform(int location, bool transpose, GMatrix44<float> value)
|
||||
{
|
||||
__context->glUniformMatrix4fv(location, 1, transpose ? (byte)1 : (byte)0, (float*)&value);
|
||||
fixed (GMatrix44<float>* __value = &value)
|
||||
{
|
||||
__context->glUniformMatrix4fv(location, 1, transpose ? (byte)1 : (byte)0, (float*)__value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1794,9 +1797,9 @@ namespace Nitload.Graphics.OpenGL
|
||||
/// <para>See <see href="https://docs.gl/gl4/glUniform">docs.gl</see>.</para>
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Uniform(int location, bool transpose, ReadOnlySpan<GraphicsMatrix> values)
|
||||
public void Uniform(int location, bool transpose, ReadOnlySpan<GMatrix44<float>> values)
|
||||
{
|
||||
fixed (GraphicsMatrix* __value = values)
|
||||
fixed (GMatrix44<float>* __value = values)
|
||||
{
|
||||
__context->glUniformMatrix4fv(location, values.Length, transpose ? (byte)1 : (byte)0, (float*)__value);
|
||||
}
|
||||
|
||||
@@ -631,9 +631,12 @@ namespace Nitload.Graphics.OpenGL
|
||||
/// <para>See <see href="https://docs.gl/gl4/glProgramUniform">docs.gl</see>.</para>
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ProgramUniform(GlHandle program, int location, bool transpose, GraphicsMatrix value)
|
||||
public void ProgramUniform(GlHandle program, int location, bool transpose, GMatrix44<float> value)
|
||||
{
|
||||
__context->glProgramUniformMatrix4fv(program.Value, location, 1, transpose ? (byte)1 : (byte)0, (float*)&value);
|
||||
fixed (GMatrix44<float>* __value = &value)
|
||||
{
|
||||
__context->glProgramUniformMatrix4fv(program.Value, location, 1, transpose ? (byte)1 : (byte)0, (float*)__value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -642,9 +645,9 @@ namespace Nitload.Graphics.OpenGL
|
||||
/// <para>See <see href="https://docs.gl/gl4/glProgramUniform">docs.gl</see>.</para>
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void ProgramUniform(GlHandle program, int location, bool transpose, ReadOnlySpan<GraphicsMatrix> values)
|
||||
public void ProgramUniform(GlHandle program, int location, bool transpose, ReadOnlySpan<GMatrix44<float>> values)
|
||||
{
|
||||
fixed (GraphicsMatrix* __value = values)
|
||||
fixed (GMatrix44<float>* __value = values)
|
||||
{
|
||||
__context->glProgramUniformMatrix4fv(program.Value, location, values.Length, transpose ? (byte)1 : (byte)0, (float*)__value);
|
||||
}
|
||||
|
||||
@@ -16,41 +16,61 @@ namespace Nitload.Geometries
|
||||
|
||||
private bool globalCoordAvailable;
|
||||
private CoordinationBase localCoordination;
|
||||
private GraphicsMatrix coordMat;
|
||||
private GMatrix44<float> coordMat;
|
||||
|
||||
public CoordinationBase(
|
||||
CoordinationBase localCoordination
|
||||
)
|
||||
{
|
||||
this.localCoordination = localCoordination;
|
||||
coordMat = new GraphicsMatrix();
|
||||
coordMat = new GMatrix44<float>();
|
||||
}
|
||||
|
||||
public virtual Point LocalOrigin
|
||||
{
|
||||
get => new Point(coordMat.column[3].XYZ);
|
||||
internal set => coordMat.column[3].XYZ = value.Coord;
|
||||
get => new Point(new Vec3<float>(coordMat[3, 0], coordMat[3, 1], coordMat[3, 2]));
|
||||
internal set
|
||||
{
|
||||
coordMat[3, 0] = value.Coord.X;
|
||||
coordMat[3, 1] = value.Coord.Y;
|
||||
coordMat[3, 2] = value.Coord.Z;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual Vec3<float> LocalX
|
||||
{
|
||||
get => coordMat.column[3].XYZ;
|
||||
internal set => coordMat.column[3].XYZ = value;
|
||||
get => new Vec3<float>(coordMat[3, 0], coordMat[3, 1], coordMat[3, 2]);
|
||||
internal set
|
||||
{
|
||||
coordMat[3, 0] = value.X;
|
||||
coordMat[3, 1] = value.Y;
|
||||
coordMat[3, 2] = value.Z;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual Vec3<float> LocalY
|
||||
{
|
||||
get => coordMat.column[3].XYZ;
|
||||
internal set => coordMat.column[3].XYZ = value;
|
||||
get => new Vec3<float>(coordMat[3, 0], coordMat[3, 1], coordMat[3, 2]);
|
||||
internal set
|
||||
{
|
||||
coordMat[3, 0] = value.X;
|
||||
coordMat[3, 1] = value.Y;
|
||||
coordMat[3, 2] = value.Z;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual Vec3<float> LocalZ
|
||||
{
|
||||
get => coordMat.column[3].XYZ;
|
||||
set => coordMat.column[3].XYZ = value;
|
||||
get => new Vec3<float>(coordMat[3, 0], coordMat[3, 1], coordMat[3, 2]);
|
||||
set
|
||||
{
|
||||
coordMat[3, 0] = value.X;
|
||||
coordMat[3, 1] = value.Y;
|
||||
coordMat[3, 2] = value.Z;
|
||||
}
|
||||
}
|
||||
|
||||
protected ref GraphicsMatrix CoordMat => ref coordMat;
|
||||
protected ref GMatrix44<float> CoordMat => ref coordMat;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,11 +26,11 @@ namespace Nitload.Geometries
|
||||
)
|
||||
: base(local)
|
||||
{
|
||||
CoordMat = GraphicsMatrix.Unit;
|
||||
CoordMat = GMatrix44<float>.Unit;
|
||||
|
||||
CoordMat.column[0] = new Vec4<float>(xAxis, 0);
|
||||
CoordMat.column[1] = new Vec4<float>(yAxis, 0);
|
||||
CoordMat.column[2] = new Vec4<float>(Linear.Normalize(Vec3.Cross(xAxis, yAxis)), 0);
|
||||
CoordMat[0] = new Vec4<float>(xAxis, 0);
|
||||
CoordMat[1] = new Vec4<float>(yAxis, 0);
|
||||
CoordMat[2] = new Vec4<float>(Linear.Normalize(Vec3.Cross(xAxis, yAxis)), 0);
|
||||
|
||||
LocalOrigin = origin;
|
||||
}
|
||||
|
||||
@@ -41,9 +41,7 @@ namespace Nitload.Geometries
|
||||
|
||||
public Vec3<float> CenterPositionGlobal { get; internal set; }
|
||||
|
||||
public Vec3<float> Coord//
|
||||
{ get => GlobalBuffer.CoordAndRotationList[BufferId].XYZ;//
|
||||
set
|
||||
public Vec3<float> Coord { get => GlobalBuffer.CoordAndRotationList[BufferId].XYZ; set
|
||||
{
|
||||
Vec4<float> v = new(value, 0);
|
||||
GlobalBuffer.CoordAndRotationList[BufferId] = v;
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// file="GMatrix44_T"
|
||||
// Project: StgSharp
|
||||
// Copyright (c) Nitload.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using Nitload.Mathematics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Nitload.Mathematics.Numeric.Graphics
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 16)]
|
||||
public struct GMatrix44<T> where T : unmanaged, INumber<T>
|
||||
{
|
||||
|
||||
private Buffer _buffer;
|
||||
|
||||
public Vec4<T> this[
|
||||
int x
|
||||
]
|
||||
{
|
||||
readonly get => _buffer[x];
|
||||
set => _buffer[x] = value;
|
||||
}
|
||||
|
||||
public T this[
|
||||
int x,
|
||||
int y
|
||||
]
|
||||
{
|
||||
readonly get => _buffer[x][y];
|
||||
set => _buffer[x][y] = value;
|
||||
}
|
||||
|
||||
public static GMatrix44<T> Unit
|
||||
{
|
||||
get
|
||||
{
|
||||
GMatrix44<T> result = new();
|
||||
result[0] = new Vec4<T>(T.One, T.Zero, T.Zero, T.Zero);
|
||||
result[1] = new Vec4<T>(T.Zero, T.One, T.Zero, T.Zero);
|
||||
result[2] = new Vec4<T>(T.Zero, T.Zero, T.One, T.Zero);
|
||||
result[3] = new Vec4<T>(T.Zero, T.Zero, T.Zero, T.One);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public GMatrix44<T> Transpose
|
||||
{
|
||||
get
|
||||
{
|
||||
GMatrix44<T> transpose = new();
|
||||
|
||||
// Native SK transpose is intentionally deferred until the module
|
||||
// startup path can guarantee that GlobalContext has been initialized.
|
||||
|
||||
if (Unsafe.SizeOf<T>() == 4)
|
||||
{
|
||||
Vector128<T> row0Source = _buffer[0].AsVector128Unsafe();
|
||||
Vector128<T> row1Source = _buffer[1].AsVector128Unsafe();
|
||||
Vector128<T> row2Source = _buffer[2].AsVector128Unsafe();
|
||||
Vector128<T> row3Source = _buffer[3].AsVector128Unsafe();
|
||||
Vector128<int> row0 = Unsafe.As<Vector128<T>, Vector128<int>>(ref row0Source);
|
||||
Vector128<int> row1 = Unsafe.As<Vector128<T>, Vector128<int>>(ref row1Source);
|
||||
Vector128<int> row2 = Unsafe.As<Vector128<T>, Vector128<int>>(ref row2Source);
|
||||
Vector128<int> row3 = Unsafe.As<Vector128<T>, Vector128<int>>(ref row3Source);
|
||||
|
||||
Vector128<int> pairMask = Vector128.Create(-1, 0, -1, 0);
|
||||
Vector128<int> firstPairMask = Vector128.Create(-1, -1, 0, 0);
|
||||
Vector128<int> lowShuffle = Vector128.Create(0, 0, 1, 1);
|
||||
Vector128<int> highShuffle = Vector128.Create(2, 2, 3, 3);
|
||||
Vector128<int> secondLaneShuffle = Vector128.Create(2, 3, 2, 3);
|
||||
|
||||
Vector128<int> pair01Low = Vector128.ConditionalSelect(
|
||||
pairMask,
|
||||
Vector128.Shuffle(row0, lowShuffle),
|
||||
Vector128.Shuffle(row1, lowShuffle));
|
||||
Vector128<int> pair23Low = Vector128.ConditionalSelect(
|
||||
pairMask,
|
||||
Vector128.Shuffle(row2, lowShuffle),
|
||||
Vector128.Shuffle(row3, lowShuffle));
|
||||
Vector128<int> pair01High = Vector128.ConditionalSelect(
|
||||
pairMask,
|
||||
Vector128.Shuffle(row0, highShuffle),
|
||||
Vector128.Shuffle(row1, highShuffle));
|
||||
Vector128<int> pair23High = Vector128.ConditionalSelect(
|
||||
pairMask,
|
||||
Vector128.Shuffle(row2, highShuffle),
|
||||
Vector128.Shuffle(row3, highShuffle));
|
||||
|
||||
Vector128<int> result0 = Vector128.ConditionalSelect(
|
||||
firstPairMask, pair01Low, pair23Low);
|
||||
Vector128<int> result1 = Vector128.ConditionalSelect(
|
||||
firstPairMask,
|
||||
Vector128.Shuffle(pair01Low, secondLaneShuffle),
|
||||
Vector128.Shuffle(pair23Low, secondLaneShuffle));
|
||||
Vector128<int> result2 = Vector128.ConditionalSelect(
|
||||
firstPairMask, pair01High, pair23High);
|
||||
Vector128<int> result3 = Vector128.ConditionalSelect(
|
||||
firstPairMask,
|
||||
Vector128.Shuffle(pair01High, secondLaneShuffle),
|
||||
Vector128.Shuffle(pair23High, secondLaneShuffle));
|
||||
transpose._buffer[0] = Vec4.FromVector128Unsafe(
|
||||
Unsafe.As<Vector128<int>, Vector128<T>>(ref result0));
|
||||
transpose._buffer[1] = Vec4.FromVector128Unsafe(
|
||||
Unsafe.As<Vector128<int>, Vector128<T>>(ref result1));
|
||||
transpose._buffer[2] = Vec4.FromVector128Unsafe(
|
||||
Unsafe.As<Vector128<int>, Vector128<T>>(ref result2));
|
||||
transpose._buffer[3] = Vec4.FromVector128Unsafe(
|
||||
Unsafe.As<Vector128<int>, Vector128<T>>(ref result3));
|
||||
return transpose;
|
||||
}
|
||||
|
||||
if (Unsafe.SizeOf<T>() == 8)
|
||||
{
|
||||
Vector256<T> row0Source = _buffer[0].AsVector256Unsafe();
|
||||
Vector256<T> row1Source = _buffer[1].AsVector256Unsafe();
|
||||
Vector256<T> row2Source = _buffer[2].AsVector256Unsafe();
|
||||
Vector256<T> row3Source = _buffer[3].AsVector256Unsafe();
|
||||
Vector256<long> row0 = Unsafe.As<Vector256<T>, Vector256<long>>(ref row0Source);
|
||||
Vector256<long> row1 = Unsafe.As<Vector256<T>, Vector256<long>>(ref row1Source);
|
||||
Vector256<long> row2 = Unsafe.As<Vector256<T>, Vector256<long>>(ref row2Source);
|
||||
Vector256<long> row3 = Unsafe.As<Vector256<T>, Vector256<long>>(ref row3Source);
|
||||
|
||||
Vector256<long> pairMask = Vector256.Create(-1L, 0L, -1L, 0L);
|
||||
Vector256<long> firstPairMask = Vector256.Create(-1L, -1L, 0L, 0L);
|
||||
Vector256<long> firstShuffle = Vector256.Create(0L, 0L, 1L, 1L);
|
||||
Vector256<long> secondShuffle = Vector256.Create(2L, 2L, 3L, 3L);
|
||||
Vector256<long> pair01First = Vector256.ConditionalSelect(
|
||||
pairMask,
|
||||
Vector256.Shuffle(row0, firstShuffle),
|
||||
Vector256.Shuffle(row1, firstShuffle));
|
||||
Vector256<long> pair23First = Vector256.ConditionalSelect(
|
||||
pairMask,
|
||||
Vector256.Shuffle(row2, firstShuffle),
|
||||
Vector256.Shuffle(row3, firstShuffle));
|
||||
Vector256<long> pair01Second = Vector256.ConditionalSelect(
|
||||
pairMask,
|
||||
Vector256.Shuffle(row0, secondShuffle),
|
||||
Vector256.Shuffle(row1, secondShuffle));
|
||||
Vector256<long> pair23Second = Vector256.ConditionalSelect(
|
||||
pairMask,
|
||||
Vector256.Shuffle(row2, secondShuffle),
|
||||
Vector256.Shuffle(row3, secondShuffle));
|
||||
Vector256<long> result0 = Vector256.ConditionalSelect(
|
||||
firstPairMask, pair01First, pair23First);
|
||||
Vector256<long> result1 = Vector256.ConditionalSelect(
|
||||
firstPairMask,
|
||||
Vector256.Shuffle(pair01First, secondShuffle),
|
||||
Vector256.Shuffle(pair23First, secondShuffle));
|
||||
Vector256<long> result2 = Vector256.ConditionalSelect(
|
||||
firstPairMask, pair01Second, pair23Second);
|
||||
Vector256<long> result3 = Vector256.ConditionalSelect(
|
||||
firstPairMask,
|
||||
Vector256.Shuffle(pair01Second, secondShuffle),
|
||||
Vector256.Shuffle(pair23Second, secondShuffle));
|
||||
transpose._buffer[0] = Vec4.FromVector256Unsafe(
|
||||
Unsafe.As<Vector256<long>, Vector256<T>>(ref result0));
|
||||
transpose._buffer[1] = Vec4.FromVector256Unsafe(
|
||||
Unsafe.As<Vector256<long>, Vector256<T>>(ref result1));
|
||||
transpose._buffer[2] = Vec4.FromVector256Unsafe(
|
||||
Unsafe.As<Vector256<long>, Vector256<T>>(ref result2));
|
||||
transpose._buffer[3] = Vec4.FromVector256Unsafe(
|
||||
Unsafe.As<Vector256<long>, Vector256<T>>(ref result3));
|
||||
return transpose;
|
||||
}
|
||||
|
||||
throw GraphicVector.ThrowUnsupportedTypeException<T>();
|
||||
}
|
||||
}
|
||||
|
||||
[InlineArray(4)]
|
||||
private struct Buffer
|
||||
{
|
||||
|
||||
public Vec4<T> _column;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,261 +0,0 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// file="GraphicsMatrix"
|
||||
// Project: StgSharp
|
||||
// Copyright (c) Nitload.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using Nitload.Mathematics;
|
||||
using Nitload.Mathematics.Internal;
|
||||
using Nitload.Mathematics.Numeric;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
|
||||
namespace Nitload.Mathematics.Numeric.Graphics
|
||||
{
|
||||
[StructLayout(LayoutKind.Explicit, Size = 16 * sizeof(float), Pack = 16)]
|
||||
public unsafe struct GraphicsMatrix : IEquatable<GraphicsMatrix>
|
||||
{
|
||||
|
||||
[FieldOffset(0 * sizeof(float))] internal Column column;
|
||||
|
||||
[FieldOffset(0)] internal ColumnSet4 mat;
|
||||
[FieldOffset(0)] internal MatrixKernel<float> kernel;
|
||||
|
||||
internal GraphicsMatrix(
|
||||
ColumnSet4 mat
|
||||
)
|
||||
{
|
||||
Unsafe.SkipInit(out this);
|
||||
this.mat = mat;
|
||||
}
|
||||
|
||||
internal GraphicsMatrix(
|
||||
Vector4 vec0,
|
||||
Vector4 vec1,
|
||||
Vector4 vec2,
|
||||
Vector4 vec3
|
||||
)
|
||||
{
|
||||
Unsafe.SkipInit(out this);
|
||||
mat.colum0 = vec0;
|
||||
mat.colum1 = vec1;
|
||||
mat.colum2 = vec2;
|
||||
mat.colum3 = vec3;
|
||||
}
|
||||
|
||||
public GraphicsMatrix()
|
||||
{
|
||||
Unsafe.SkipInit(out this);
|
||||
}
|
||||
|
||||
public unsafe GraphicsMatrix(
|
||||
float a00,
|
||||
float a01,
|
||||
float a02,
|
||||
float a03,
|
||||
float a10,
|
||||
float a11,
|
||||
float a12,
|
||||
float a13,
|
||||
float a20,
|
||||
float a21,
|
||||
float a22,
|
||||
float a23,
|
||||
float a30,
|
||||
float a31,
|
||||
float a32,
|
||||
float a33
|
||||
)
|
||||
{
|
||||
Unsafe.SkipInit(out this);
|
||||
mat.colum0 = new Vector4(a00, a10, a20, a30);
|
||||
mat.colum1 = new Vector4(a01, a11, a21, a31);
|
||||
mat.colum2 = new Vector4(a02, a12, a22, a32);
|
||||
mat.colum3 = new Vector4(a03, a13, a23, a33);
|
||||
}
|
||||
|
||||
public unsafe float this[
|
||||
int rowNum,
|
||||
int columNum
|
||||
]
|
||||
{
|
||||
get
|
||||
{
|
||||
#if DEBUG
|
||||
if (rowNum is > 3 or < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(columNum));
|
||||
}
|
||||
if (columNum is > 3 or < 0) {
|
||||
throw new ArgumentOutOfRangeException(nameof(columNum));
|
||||
}
|
||||
#endif
|
||||
return kernel[rowNum + (4 * columNum)];
|
||||
}
|
||||
set
|
||||
{
|
||||
#if DEBUG
|
||||
if (rowNum is > 3 or < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(columNum));
|
||||
}
|
||||
if (columNum is > 3 or < 0) {
|
||||
throw new ArgumentOutOfRangeException(nameof(columNum));
|
||||
}
|
||||
#endif
|
||||
kernel[rowNum + (4 * columNum)] = value;
|
||||
}
|
||||
}
|
||||
|
||||
public GraphicsMatrix Transpose
|
||||
{
|
||||
get
|
||||
{
|
||||
GraphicsMatrix transpose = new();
|
||||
InternalTranspose(ref transpose);
|
||||
return transpose;
|
||||
}
|
||||
}
|
||||
|
||||
public static GraphicsMatrix Unit => new GraphicsMatrix(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0,
|
||||
0, 0, 0, 1);
|
||||
|
||||
public static GraphicsMatrix WNegativeUnit => new GraphicsMatrix(1, 0, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, 1, 0, 0, 0, 0, -1);
|
||||
|
||||
public static GraphicsMatrix XNegativeUnit => new GraphicsMatrix(-1, 0, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, 1, 0, 0, 0, 0, 1);
|
||||
|
||||
public static GraphicsMatrix YNegativeUnit => new GraphicsMatrix(1, 0, 0, 0, 0, -1, 0, 0, 0,
|
||||
0, 1, 0, 0, 0, 0, 1);
|
||||
|
||||
public static GraphicsMatrix ZNegativeUnit => new GraphicsMatrix(1, 0, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, -1, 0, 0, 0, 0, 1);
|
||||
|
||||
public ReadOnlySpan<float> AsSpan()
|
||||
{
|
||||
return MemoryMarshal.CreateReadOnlySpan(ref Unsafe.As<ColumnSet4, float>(ref mat), 16);
|
||||
}
|
||||
|
||||
public override bool Equals(
|
||||
object? obj
|
||||
)
|
||||
{
|
||||
return (obj is GraphicsMatrix x) && Equals(x);
|
||||
}
|
||||
|
||||
public bool Equals(
|
||||
GraphicsMatrix other
|
||||
)
|
||||
{
|
||||
return mat.Equals(other.mat);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(mat.colum0.GetHashCode(), mat.colum1.GetHashCode(),
|
||||
mat.colum2.GetHashCode(), mat.colum3.GetHashCode());
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal unsafe void InternalTranspose(
|
||||
ref GraphicsMatrix transpose
|
||||
)
|
||||
{
|
||||
const int f32 = 0;
|
||||
fixed (MatrixKernel<float>* source = &this.kernel, target = &transpose.kernel) {
|
||||
NumericalModule.GlobalContext.mat_sk[f32].Call(MatrixIntrinsicHandle.Transpose,
|
||||
null, (MatrixKernel*)source,
|
||||
(MatrixKernel*)target, 0);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static unsafe GraphicsMatrix operator -(
|
||||
GraphicsMatrix left,
|
||||
GraphicsMatrix right
|
||||
)
|
||||
{
|
||||
GraphicsMatrix ret = new();
|
||||
int f32 = MatrixElementType.F32.IntrinsicNode;
|
||||
NumericalModule.GlobalContext.mat_sk[f32].Call(MatrixIntrinsicHandle.Sub,
|
||||
(MatrixKernel*)&left.kernel,
|
||||
(MatrixKernel*)&right.kernel,
|
||||
(MatrixKernel*)&ret.kernel, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static bool operator !=(
|
||||
GraphicsMatrix left,
|
||||
GraphicsMatrix right
|
||||
)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static unsafe GraphicsMatrix operator *(
|
||||
GraphicsMatrix mat,
|
||||
float value
|
||||
)
|
||||
{
|
||||
int f32 = MatrixElementType.F32.IntrinsicNode;
|
||||
return new GraphicsMatrix(mat.mat.colum0 * value, mat.mat.colum1 * value,
|
||||
mat.mat.colum2 * value, mat.mat.colum3 * value);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static GraphicsMatrix operator *(
|
||||
GraphicsMatrix left,
|
||||
GraphicsMatrix right
|
||||
)
|
||||
{
|
||||
GraphicsMatrix ret = new();
|
||||
int f32 = MatrixElementType.F32.IntrinsicNode;
|
||||
NumericalModule.GlobalContext.mat_sk[f32].Call(MatrixIntrinsicHandle.Fma,
|
||||
(MatrixKernel*)&left,
|
||||
(MatrixKernel*)&right,
|
||||
(MatrixKernel*)&ret, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static unsafe GraphicsMatrix operator +(
|
||||
GraphicsMatrix left,
|
||||
GraphicsMatrix right
|
||||
)
|
||||
{
|
||||
GraphicsMatrix ret = new();
|
||||
int f32 = MatrixElementType.F32.IntrinsicNode;
|
||||
NumericalModule.GlobalContext.mat_sk[f32].Call(MatrixIntrinsicHandle.Add,
|
||||
(MatrixKernel*)&left,
|
||||
(MatrixKernel*)&right,
|
||||
(MatrixKernel*)&ret, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static bool operator ==(
|
||||
GraphicsMatrix left,
|
||||
GraphicsMatrix right
|
||||
)
|
||||
{
|
||||
return left.Equals(right);
|
||||
}
|
||||
|
||||
[InlineArray(4)]
|
||||
internal struct Column
|
||||
{
|
||||
|
||||
private Vec4<float> value;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,13 +15,61 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
public static class Vec3
|
||||
{
|
||||
|
||||
public static bool IsParallel<T>(Vec3<T> left, Vec3<T> right) where T: unmanaged,INumber<T>
|
||||
[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()));
|
||||
}
|
||||
|
||||
[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()));
|
||||
}
|
||||
|
||||
public static Vec3<T> FromSpan<T>(
|
||||
ReadOnlySpan<T> span
|
||||
) where T : unmanaged, INumber<T>
|
||||
{
|
||||
if (span.Length < 3) {
|
||||
throw new ArgumentException("Span length must be at least 3.", nameof(span));
|
||||
}
|
||||
|
||||
return new(span[0], span[1], span[2]);
|
||||
}
|
||||
|
||||
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)]
|
||||
internal static Vector128<T> AsVector128Safe<T>(this Vec3<T> source) 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);
|
||||
@@ -29,7 +77,9 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static Vector128<T> AsVector128Unsafe<T>(this Vec3<T> source) where T: unmanaged, INumber<T>
|
||||
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);
|
||||
@@ -37,7 +87,9 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static Vector256<T> AsVector256Safe<T>(this Vec3<T> source) where T: unmanaged, INumber<T>
|
||||
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);
|
||||
@@ -45,7 +97,9 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static Vector256<T> AsVector256Unsafe<T>(this Vec3<T> source) where T: unmanaged, INumber<T>
|
||||
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);
|
||||
@@ -53,45 +107,28 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static Vec3<T> FromVector128Unsafe<T>(Vector128<T> source) where T: unmanaged, INumber<T>
|
||||
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>
|
||||
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>
|
||||
public static Vec3<T> Cross<T>(
|
||||
Vec3<T> left,
|
||||
Vec3<T> right
|
||||
) where T : unmanaged, INumber<T>
|
||||
{
|
||||
if (typeof(T) == typeof(float))
|
||||
{
|
||||
@@ -140,7 +177,10 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static Vec3<double> CrossDouble(Vec3<double> left, Vec3<double> right)
|
||||
private static Vec3<double> CrossDouble(
|
||||
Vec3<double> left,
|
||||
Vec3<double> right
|
||||
)
|
||||
{
|
||||
Vector256<double> l = left.AsVector256Safe();
|
||||
Vector256<double> r = right.AsVector256Safe();
|
||||
@@ -151,7 +191,10 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static Vec3<int> CrossInt32(Vec3<int> left, Vec3<int> right)
|
||||
private static Vec3<int> CrossInt32(
|
||||
Vec3<int> left,
|
||||
Vec3<int> right
|
||||
)
|
||||
{
|
||||
Vector128<int> l = left.AsVector128Safe();
|
||||
Vector128<int> r = right.AsVector128Safe();
|
||||
@@ -162,7 +205,10 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static Vec3<float> CrossSingle(Vec3<float> left, Vec3<float> right)
|
||||
private static Vec3<float> CrossSingle(
|
||||
Vec3<float> left,
|
||||
Vec3<float> right
|
||||
)
|
||||
{
|
||||
Vector128<float> l = left.AsVector128Safe();
|
||||
Vector128<float> r = right.AsVector128Safe();
|
||||
@@ -173,7 +219,10 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static Vec3<uint> CrossUInt32(Vec3<uint> left, Vec3<uint> right)
|
||||
private static Vec3<uint> CrossUInt32(
|
||||
Vec3<uint> left,
|
||||
Vec3<uint> right
|
||||
)
|
||||
{
|
||||
Vector128<uint> l = left.AsVector128Safe();
|
||||
Vector128<uint> r = right.AsVector128Safe();
|
||||
@@ -184,7 +233,10 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static Vec3<ulong> CrossUInt64(Vec3<ulong> left, Vec3<ulong> right)
|
||||
private static Vec3<ulong> CrossUInt64(
|
||||
Vec3<ulong> left,
|
||||
Vec3<ulong> right
|
||||
)
|
||||
{
|
||||
Vector256<ulong> l = left.AsVector256Safe();
|
||||
Vector256<ulong> r = right.AsVector256Safe();
|
||||
@@ -195,7 +247,10 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static Vec3<long> CrossInt64(Vec3<long> left, Vec3<long> right)
|
||||
private static Vec3<long> CrossInt64(
|
||||
Vec3<long> left,
|
||||
Vec3<long> right
|
||||
)
|
||||
{
|
||||
Vector256<long> l = left.AsVector256Safe();
|
||||
Vector256<long> r = right.AsVector256Safe();
|
||||
|
||||
@@ -28,14 +28,21 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
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;
|
||||
@@ -73,7 +80,9 @@ namespace Nitload.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>() == 8)
|
||||
{
|
||||
@@ -89,31 +98,28 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public readonly bool Equals(Vec3<T> other)
|
||||
public readonly bool Equals(
|
||||
Vec3<T> other
|
||||
)
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4)
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4) {
|
||||
return this.AsVector128Safe() == other.AsVector128Safe();
|
||||
}
|
||||
if (Unsafe.SizeOf<T>() == 8) {
|
||||
} else if (Unsafe.SizeOf<T>() == 8) {
|
||||
return this.AsVector256Safe() == other.AsVector256Safe();
|
||||
}
|
||||
#pragma warning disable CA1065
|
||||
throw GraphicVector.ThrowUnsupportedTypeException<T>();
|
||||
#pragma warning restore CA1065
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (span.Length < 3) {
|
||||
throw new ArgumentException("Span length must be at least 3.", nameof(span));
|
||||
}
|
||||
|
||||
return new(span[0], span[1], span[2]);
|
||||
}
|
||||
|
||||
public readonly IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
yield return X;
|
||||
@@ -132,33 +138,40 @@ namespace Nitload.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)
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4) {
|
||||
return Vec3.FromVector128Unsafe(Vector128<T>.Zero - value.AsVector128Unsafe());
|
||||
}
|
||||
if (Unsafe.SizeOf<T>() == 8) {
|
||||
} else if (Unsafe.SizeOf<T>() == 8) {
|
||||
return Vec3.FromVector256Unsafe(Vector256<T>.Zero - value.AsVector256Unsafe());
|
||||
}
|
||||
throw GraphicVector.ThrowUnsupportedTypeException<T>();
|
||||
}
|
||||
|
||||
[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)
|
||||
{
|
||||
Vector128<T> left_v128 = left.AsVector128Unsafe();
|
||||
Vector128<T> right_v128 = right.AsVector128Unsafe();
|
||||
return Vec3.FromVector128Unsafe(left_v128 - right_v128);
|
||||
}
|
||||
if (Unsafe.SizeOf<T>() == 8)
|
||||
} else if (Unsafe.SizeOf<T>() == 8)
|
||||
{
|
||||
Vector256<T> left_v256 = left.AsVector256Unsafe();
|
||||
Vector256<T> right_v256 = right.AsVector256Unsafe();
|
||||
@@ -168,21 +181,26 @@ namespace Nitload.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)
|
||||
{
|
||||
Vector128<T> vector_v128 = vector.AsVector128Unsafe();
|
||||
Vector128<T> scalar_v128 = Vector128.Create(scalar);
|
||||
return Vec3.FromVector128Unsafe(vector_v128 * scalar_v128);
|
||||
}
|
||||
if (Unsafe.SizeOf<T>() == 8)
|
||||
} else if (Unsafe.SizeOf<T>() == 8)
|
||||
{
|
||||
Vector256<T> vector_v256 = vector.AsVector256Unsafe();
|
||||
Vector256<T> scalar_v256 = Vector256.Create(scalar);
|
||||
@@ -192,27 +210,35 @@ namespace Nitload.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)
|
||||
{
|
||||
Vector128<T> vector_v128 = vector.AsVector128Unsafe();
|
||||
Vector128<T> scalar_v128 = Vector128.Create(scalar);
|
||||
return Vec3.FromVector128Unsafe(vector_v128 / scalar_v128);
|
||||
}
|
||||
if (Unsafe.SizeOf<T>() == 8)
|
||||
} else if (Unsafe.SizeOf<T>() == 8)
|
||||
{
|
||||
Vector256<T> vector_v256 = vector.AsVector256Unsafe();
|
||||
Vector256<T> scalar_v256 = Vector256.Create(scalar);
|
||||
@@ -222,15 +248,17 @@ namespace Nitload.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)
|
||||
{
|
||||
Vector128<T> left_v128 = left.AsVector128Unsafe();
|
||||
Vector128<T> right_v128 = right.AsVector128Unsafe();
|
||||
return Vec3.FromVector128Unsafe(left_v128 + right_v128);
|
||||
}
|
||||
if (Unsafe.SizeOf<T>() == 8)
|
||||
} else if (Unsafe.SizeOf<T>() == 8)
|
||||
{
|
||||
Vector256<T> left_v256 = left.AsVector256Unsafe();
|
||||
Vector256<T> right_v256 = right.AsVector256Unsafe();
|
||||
@@ -240,13 +268,18 @@ namespace Nitload.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);
|
||||
}
|
||||
@@ -256,5 +289,13 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
[InlineArray(3)]
|
||||
private struct Buffer
|
||||
{
|
||||
|
||||
internal T _element;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
|
||||
namespace Nitload.Mathematics.Numeric.Graphics
|
||||
@@ -15,7 +16,55 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
{
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal static Vector128<T> AsVector128Unsafe<T>(this Vec4<T> source) where T: unmanaged, INumber<T>
|
||||
public static Vec4<double> ConvertToDouble(
|
||||
Vec4<long> source
|
||||
)
|
||||
{
|
||||
return FromVector256Unsafe(Vector256.ConvertToDouble(source.AsVector256Unsafe()));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec4<double> ConvertToDouble(
|
||||
Vec4<ulong> source
|
||||
)
|
||||
{
|
||||
return FromVector256Unsafe(Vector256.ConvertToDouble(source.AsVector256Unsafe()));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec4<float> ConvertToSingle(
|
||||
Vec4<int> source
|
||||
)
|
||||
{
|
||||
return FromVector128Unsafe(Vector128.ConvertToSingle(source.AsVector128Unsafe()));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec4<float> ConvertToSingle(
|
||||
Vec4<uint> source
|
||||
)
|
||||
{
|
||||
return FromVector128Unsafe(Vector128.ConvertToSingle(source.AsVector128Unsafe()));
|
||||
}
|
||||
|
||||
public static Vec4<T> FromSpan<T>(
|
||||
ReadOnlySpan<T> span
|
||||
) where T : unmanaged, INumber<T>
|
||||
{
|
||||
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 Unsafe.As<Vec4<T>, T>(ref result), 4);
|
||||
span[..4].CopyTo(target);
|
||||
return result;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
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);
|
||||
@@ -23,7 +72,9 @@ namespace Nitload.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);
|
||||
@@ -31,40 +82,20 @@ namespace Nitload.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);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec4<float> ConvertToSingle(Vec4<int> source)
|
||||
{
|
||||
return FromVector128Unsafe(Vector128.ConvertToSingle(source.AsVector128Unsafe()));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec4<float> ConvertToSingle(Vec4<uint> source)
|
||||
{
|
||||
return FromVector128Unsafe(Vector128.ConvertToSingle(source.AsVector128Unsafe()));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec4<double> ConvertToDouble(Vec4<long> source)
|
||||
{
|
||||
return FromVector256Unsafe(Vector256.ConvertToDouble(source.AsVector256Unsafe()));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec4<double> ConvertToDouble(Vec4<ulong> source)
|
||||
{
|
||||
return FromVector256Unsafe(Vector256.ConvertToDouble(source.AsVector256Unsafe()));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,7 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
public struct Vec4<T> : IUnmanagedVector<Vec4<T>> where T : unmanaged, INumber<T>
|
||||
{
|
||||
|
||||
public T W;
|
||||
|
||||
public T X;
|
||||
public T Y;
|
||||
public T Z;
|
||||
private Buffer _buffer;
|
||||
|
||||
public Vec4(
|
||||
Vec3<T> v3,
|
||||
@@ -50,9 +46,41 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
W = w;
|
||||
}
|
||||
|
||||
public T this[
|
||||
int index
|
||||
]
|
||||
{
|
||||
get => _buffer[index];
|
||||
set => _buffer[index] = value;
|
||||
}
|
||||
|
||||
public T X
|
||||
{
|
||||
get => _buffer[0];
|
||||
set => _buffer[0] = value;
|
||||
}
|
||||
|
||||
public T Y
|
||||
{
|
||||
get => _buffer[1];
|
||||
set => _buffer[1] = value;
|
||||
}
|
||||
|
||||
public T Z
|
||||
{
|
||||
get => _buffer[2];
|
||||
set => _buffer[2] = value;
|
||||
}
|
||||
|
||||
public T W
|
||||
{
|
||||
get => _buffer[3];
|
||||
set => _buffer[3] = value;
|
||||
}
|
||||
|
||||
public Vec2<T> XY
|
||||
{
|
||||
get => Unsafe.As<T, Vec2<T>>(ref X);
|
||||
get => Unsafe.As<T, Vec2<T>>(ref _buffer[0]);
|
||||
set
|
||||
{
|
||||
X = value.X;
|
||||
@@ -62,11 +90,60 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
|
||||
public Vec3<T> XYZ
|
||||
{
|
||||
get => Unsafe.As<T, Vec3<T>>(ref X);
|
||||
get => Unsafe.As<T, Vec3<T>>(ref _buffer[0]);
|
||||
set
|
||||
{
|
||||
T w = W;
|
||||
Unsafe.As<T, Vec3<T>>(ref X) = value;
|
||||
Unsafe.As<T, Vec3<T>>(ref _buffer[0]) = value;
|
||||
W = w;
|
||||
}
|
||||
}
|
||||
|
||||
public Vec3<T> ZXY
|
||||
{
|
||||
readonly get
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4)
|
||||
{
|
||||
Vector128<T> source = this.AsVector128Unsafe();
|
||||
Vector128<int> bits = Unsafe.As<Vector128<T>, Vector128<int>>(ref source);
|
||||
Vector128<int> result = Vector128.Shuffle(bits, Vector128.Create(2, 0, 1, 3));
|
||||
Vector128<T> shuffled = Unsafe.As<Vector128<int>, Vector128<T>>(ref result);
|
||||
return Vec3.FromVector128Unsafe(shuffled);
|
||||
}
|
||||
if (Unsafe.SizeOf<T>() == 8)
|
||||
{
|
||||
Vector256<T> source = this.AsVector256Unsafe();
|
||||
Vector256<long> bits = Unsafe.As<Vector256<T>, Vector256<long>>(ref source);
|
||||
Vector256<long> result = Vector256.Shuffle(bits, Vector256.Create(2L, 0L, 1L,
|
||||
3L));
|
||||
Vector256<T> shuffled = Unsafe.As<Vector256<long>, Vector256<T>>(ref result);
|
||||
return Vec3.FromVector256Unsafe(shuffled);
|
||||
}
|
||||
throw GraphicVector.ThrowUnsupportedTypeException<T>();
|
||||
}
|
||||
set
|
||||
{
|
||||
T w = W;
|
||||
if (Unsafe.SizeOf<T>() == 4)
|
||||
{
|
||||
Vector128<T> source = value.AsVector128Unsafe();
|
||||
Vector128<int> bits = Unsafe.As<Vector128<T>, Vector128<int>>(ref source);
|
||||
Vector128<int> result = Vector128.Shuffle(bits, Vector128.Create(1, 2, 0, 3));
|
||||
Vector128<T> shuffled = Unsafe.As<Vector128<int>, Vector128<T>>(ref result);
|
||||
Unsafe.As<T, Vec3<T>>(ref _buffer[0]) = Vec3.FromVector128Unsafe(shuffled);
|
||||
} else if (Unsafe.SizeOf<T>() == 8)
|
||||
{
|
||||
Vector256<T> source = value.AsVector256Unsafe();
|
||||
Vector256<long> bits = Unsafe.As<Vector256<T>, Vector256<long>>(ref source);
|
||||
Vector256<long> result = Vector256.Shuffle(bits, Vector256.Create(1L, 2L, 0L,
|
||||
3L));
|
||||
Vector256<T> shuffled = Unsafe.As<Vector256<long>, Vector256<T>>(ref result);
|
||||
Unsafe.As<T, Vec3<T>>(ref _buffer[0]) = Vec3.FromVector256Unsafe(shuffled);
|
||||
} else
|
||||
{
|
||||
throw GraphicVector.ThrowUnsupportedTypeException<T>();
|
||||
}
|
||||
W = w;
|
||||
}
|
||||
}
|
||||
@@ -86,7 +163,7 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
|
||||
public ReadOnlySpan<T> AsSpan()
|
||||
{
|
||||
return MemoryMarshal.CreateReadOnlySpan(ref X, 4);
|
||||
return MemoryMarshal.CreateReadOnlySpan(ref _buffer[0], 4);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
@@ -98,8 +175,7 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
{
|
||||
Vec4<T> product = Vec4.FromVector128Unsafe(this.AsVector128Unsafe() * right.AsVector128Unsafe());
|
||||
return product.X + product.Y + product.Z + product.W;
|
||||
}
|
||||
if (Unsafe.SizeOf<T>() == 8)
|
||||
} else if (Unsafe.SizeOf<T>() == 8)
|
||||
{
|
||||
Vec4<T> product = Vec4.FromVector256Unsafe(this.AsVector256Unsafe() * right.AsVector256Unsafe());
|
||||
return product.X + product.Y + product.Z + product.W;
|
||||
@@ -114,20 +190,6 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
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()
|
||||
{
|
||||
@@ -139,16 +201,41 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
return HashCode.Combine(X, Y, Z, W);
|
||||
}
|
||||
|
||||
public Vec4<T> Shuffle(
|
||||
int t0,
|
||||
int t1,
|
||||
int t2,
|
||||
int t3
|
||||
)
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4)
|
||||
{
|
||||
Vector128<T> v = this.AsVector128Unsafe();
|
||||
Vector128<int> bits = Unsafe.As<Vector128<T>, Vector128<int>>(ref v);
|
||||
Vector128<int> result = Vector128.Shuffle(bits, Vector128.Create(t0, t1, t2, t3));
|
||||
return Vec4.FromVector128Unsafe(Unsafe.As<Vector128<int>, Vector128<T>>(ref result));
|
||||
} else if (Unsafe.SizeOf<T>() == 8)
|
||||
{
|
||||
Vector256<T> v = this.AsVector256Unsafe();
|
||||
Vector256<long> bits = Unsafe.As<Vector256<T>, Vector256<long>>(ref v);
|
||||
Vector256<long> result = Vector256.Shuffle(bits, Vector256.Create(t0, t1, t2, t3));
|
||||
return Vec4.FromVector256Unsafe(Unsafe.As<Vector256<long>, Vector256<T>>(ref result));
|
||||
} else
|
||||
{
|
||||
throw GraphicVector.ThrowUnsupportedTypeException<T>();
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec4<T> operator -(
|
||||
Vec4<T> left,
|
||||
Vec4<T> right
|
||||
)
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4) {
|
||||
if (Unsafe.SizeOf<T>() == 4)
|
||||
{
|
||||
return Vec4.FromVector128Unsafe(left.AsVector128Unsafe() - right.AsVector128Unsafe());
|
||||
}
|
||||
if (Unsafe.SizeOf<T>() == 8) {
|
||||
} else if (Unsafe.SizeOf<T>() == 8) {
|
||||
return Vec4.FromVector256Unsafe(left.AsVector256Unsafe() - right.AsVector256Unsafe());
|
||||
}
|
||||
throw GraphicVector.ThrowUnsupportedTypeException<T>();
|
||||
@@ -168,10 +255,10 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
T scalar
|
||||
)
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4) {
|
||||
if (Unsafe.SizeOf<T>() == 4)
|
||||
{
|
||||
return Vec4.FromVector128Unsafe(vector.AsVector128Unsafe() * Vector128.Create(scalar));
|
||||
}
|
||||
if (Unsafe.SizeOf<T>() == 8) {
|
||||
} else if (Unsafe.SizeOf<T>() == 8) {
|
||||
return Vec4.FromVector256Unsafe(vector.AsVector256Unsafe() * Vector256.Create(scalar));
|
||||
}
|
||||
throw GraphicVector.ThrowUnsupportedTypeException<T>();
|
||||
@@ -186,6 +273,14 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
return vector * scalar;
|
||||
}
|
||||
|
||||
public static Vec4<T> operator *(
|
||||
GMatrix44<T> mat,
|
||||
Vec4<T> vec
|
||||
)
|
||||
{
|
||||
return (mat[0] * vec.X) + (mat[1] * vec.Y) + (mat[2] * vec.Z) + (mat[3] * vec.W);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static T operator *(
|
||||
Vec4<T> left,
|
||||
@@ -201,10 +296,10 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
T scalar
|
||||
)
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4) {
|
||||
if (Unsafe.SizeOf<T>() == 4)
|
||||
{
|
||||
return Vec4.FromVector128Unsafe(vector.AsVector128Unsafe() / Vector128.Create(scalar));
|
||||
}
|
||||
if (Unsafe.SizeOf<T>() == 8) {
|
||||
} else if (Unsafe.SizeOf<T>() == 8) {
|
||||
return Vec4.FromVector256Unsafe(vector.AsVector256Unsafe() / Vector256.Create(scalar));
|
||||
}
|
||||
throw GraphicVector.ThrowUnsupportedTypeException<T>();
|
||||
@@ -216,10 +311,10 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
Vec4<T> right
|
||||
)
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4) {
|
||||
if (Unsafe.SizeOf<T>() == 4)
|
||||
{
|
||||
return Vec4.FromVector128Unsafe(left.AsVector128Unsafe() + right.AsVector128Unsafe());
|
||||
}
|
||||
if (Unsafe.SizeOf<T>() == 8) {
|
||||
} else if (Unsafe.SizeOf<T>() == 8) {
|
||||
return Vec4.FromVector256Unsafe(left.AsVector256Unsafe() + right.AsVector256Unsafe());
|
||||
}
|
||||
throw GraphicVector.ThrowUnsupportedTypeException<T>();
|
||||
@@ -230,10 +325,10 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
Vec4<T> right
|
||||
)
|
||||
{
|
||||
if (Unsafe.SizeOf<T>() == 4) {
|
||||
if (Unsafe.SizeOf<T>() == 4)
|
||||
{
|
||||
return left.AsVector128Unsafe() == right.AsVector128Unsafe();
|
||||
}
|
||||
if (Unsafe.SizeOf<T>() == 8) {
|
||||
} else if (Unsafe.SizeOf<T>() == 8) {
|
||||
return left.AsVector256Unsafe() == right.AsVector256Unsafe();
|
||||
}
|
||||
#pragma warning disable CA1065
|
||||
@@ -241,5 +336,13 @@ namespace Nitload.Mathematics.Numeric.Graphics
|
||||
#pragma warning restore CA1065
|
||||
}
|
||||
|
||||
[InlineArray(4)]
|
||||
private struct Buffer
|
||||
{
|
||||
|
||||
private T _element;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// file="TextRegexSourceGen.ExitLabel"
|
||||
// Project: StgSharp
|
||||
// Copyright (c) Nitload.
|
||||
// SPDX-License-Identifier: MIT
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Nitload.RegularAnalysis.Text
|
||||
{
|
||||
internal partial class TextRegexSourceGen
|
||||
{
|
||||
|
||||
internal enum ExitMode
|
||||
{
|
||||
|
||||
Break,
|
||||
Continue,
|
||||
Goto,
|
||||
|
||||
}
|
||||
|
||||
internal readonly record struct ExitLabel
|
||||
{
|
||||
|
||||
public ExitLabel(
|
||||
ExitMode mode,
|
||||
int order
|
||||
)
|
||||
{
|
||||
Mode = mode;
|
||||
LabelOrder = order;
|
||||
}
|
||||
|
||||
public ExitMode Mode { get; init; }
|
||||
|
||||
public int LabelOrder { get; init; }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -183,6 +183,8 @@ namespace Nitload.RegularAnalysis.Text
|
||||
)
|
||||
{
|
||||
RegexAstNode current = node.Right;
|
||||
// TODO(NGRA-NAMING): Reserve exclusive names for future ALT cursor/capture snapshots;
|
||||
// their lifetime extends through retry labels, not just the candidate's emitted block.
|
||||
string exit_label = context.RequestExitLabel();
|
||||
|
||||
// TODO(NGRA): Walk every normalized ALT candidate exactly once. The final traversal
|
||||
@@ -229,9 +231,10 @@ namespace Nitload.RegularAnalysis.Text
|
||||
|
||||
// TODO(NGRA): Advance by code.Length rather than one character and
|
||||
// preserve the ALT rollback cursor on failure.
|
||||
_ = sc.AppendLine(@$"if({context.RemainSpan}.{MemoryExtensions.StartsWith}({FormatStringLiteral(code)}))")
|
||||
string liteal = FormatStringLiteral(code);
|
||||
_ = sc.AppendLine(@$"if({context.RemainSpan}.{MemoryExtensions.StartsWith}({liteal}))")
|
||||
.AppendLine("{")
|
||||
.AppendLine($@"{context.RemainSpan} = {context.RemainSpan}.Slice(1);")
|
||||
.AppendLine($@"{context.RemainSpan} = {context.RemainSpan}.Slice({code.Length});")
|
||||
.AppendLine($@"goto {exit_label};")
|
||||
.AppendLine("}");
|
||||
|
||||
@@ -269,6 +272,9 @@ namespace Nitload.RegularAnalysis.Text
|
||||
|
||||
RegexGroupPayload config = node.PayloadAs<RegexGroupPayload>();
|
||||
|
||||
// TODO(NGRA-NAMING): Reserve exclusive names for generated group snapshots and capture
|
||||
// temporaries. A capture's user-provided name is not a unique generated local name.
|
||||
|
||||
// TODO(NGRA): Select the owned group body using Empty-sentinel checks, snapshot its
|
||||
// start cursor, and restore it when the child matcher fails.
|
||||
if (left is not null)
|
||||
@@ -343,7 +349,8 @@ namespace Nitload.RegularAnalysis.Text
|
||||
int max,
|
||||
bool is_greedy,
|
||||
[NotNull] in SequenceEmitter<string> sc,
|
||||
in SourceGenContext context
|
||||
in SourceGenContext context,
|
||||
string exit_label
|
||||
)
|
||||
{
|
||||
if (min < 0 || (max >= 0 && max < min)) {
|
||||
@@ -359,16 +366,16 @@ namespace Nitload.RegularAnalysis.Text
|
||||
char expected = literal[0];
|
||||
string expected_literal = FormatCharLiteral(expected);
|
||||
string remain_span = context.RemainSpan;
|
||||
int scratch_scope_index = context.RentScratchScopeIndex();
|
||||
// TODO(NGRA-NAMING): Allocate required_rest, required_matched, required_chunk_index,
|
||||
// and additional_count through the exclusive-name pool, including loop-local names.
|
||||
int scratch_scope_index = context.RequestScratchScopeIndex();
|
||||
string required_rest = $"__required_rest_{scratch_scope_index}";
|
||||
string required_matched = $"__required_matched_{scratch_scope_index}";
|
||||
string required_chunk_index = $"__required_chunk_index_{scratch_scope_index}";
|
||||
string additional_count = $"__additional_count_{scratch_scope_index}";
|
||||
|
||||
// TODO(NGRA): Move ownership of this work region to the enclosing CONCAT or match
|
||||
// method. Until then, break demonstrates the local failure path but cannot prevent a
|
||||
// later sibling node from being emitted and executed.
|
||||
_ = sc.AppendLine("do").AppendLine("{");
|
||||
// TODO(NGRA): Replace this local COUNT exit with the inherited failure ExitLabel.
|
||||
// The temporary goto preserves the former local exit but still lets siblings execute.
|
||||
|
||||
if (min <= flattened_unit_count_threshold)
|
||||
{
|
||||
@@ -377,7 +384,7 @@ namespace Nitload.RegularAnalysis.Text
|
||||
string required_prefix = new(expected, min);
|
||||
_ = sc.AppendLine($"if (!{remain_span}.{nameof(MemoryExtensions.StartsWith)}({FormatStringLiteral(required_prefix)}))")
|
||||
.AppendLine("{")
|
||||
.AppendLine("break;")
|
||||
.AppendLine($"goto {exit_label};")
|
||||
.AppendLine("}")
|
||||
.AppendLine($"{remain_span} = {remain_span}.Slice({min});");
|
||||
}
|
||||
@@ -392,7 +399,7 @@ namespace Nitload.RegularAnalysis.Text
|
||||
|
||||
_ = sc.AppendLine($"if ({remain_span}.Length < {min})")
|
||||
.AppendLine("{")
|
||||
.AppendLine("break;")
|
||||
.AppendLine($"goto {exit_label};")
|
||||
.AppendLine("}")
|
||||
.AppendLine($"{ROS_char} {required_rest} = {remain_span};")
|
||||
.AppendLine($"bool {required_matched} = true;")
|
||||
@@ -417,7 +424,7 @@ namespace Nitload.RegularAnalysis.Text
|
||||
|
||||
_ = sc.AppendLine($"if (!{required_matched})")
|
||||
.AppendLine("{")
|
||||
.AppendLine("break;")
|
||||
.AppendLine($"goto {exit_label};")
|
||||
.AppendLine("}")
|
||||
.AppendLine($"{remain_span} = {remain_span}.Slice({min});");
|
||||
}
|
||||
@@ -445,8 +452,6 @@ namespace Nitload.RegularAnalysis.Text
|
||||
_ = sc.AppendLine("// TODO(NGRA): Retry the lazy COUNT tail from its continuation.");
|
||||
}
|
||||
|
||||
_ = sc.AppendLine("} while (false);");
|
||||
context.ReturnScratchScopeIndex(scratch_scope_index);
|
||||
}
|
||||
|
||||
private static void GenerateUnitSetCount(
|
||||
@@ -472,33 +477,52 @@ namespace Nitload.RegularAnalysis.Text
|
||||
|
||||
IReadOnlyList<RegexCharSet> charset = payload.Set;
|
||||
string remain_span = context.RemainSpan;
|
||||
int scratch_scope_index = context.RentScratchScopeIndex();
|
||||
// TODO(NGRA-NAMING): Allocate required_matched and additional_count through the
|
||||
// exclusive-name pool. Reserve required_rest/required_chunk_index if emitted later.
|
||||
int scratch_scope_index = context.RequestScratchScopeIndex();
|
||||
string required_rest = $"__required_rest_{scratch_scope_index}";
|
||||
string required_matched = $"__required_matched_{scratch_scope_index}";
|
||||
string required_chunk_index = $"__required_chunk_index_{scratch_scope_index}";
|
||||
string additional_count = $"__additional_count_{scratch_scope_index}";
|
||||
|
||||
|
||||
// TODO(NGRA): Move ownership of this work region to the enclosing CONCAT or match
|
||||
// method. Until then, break demonstrates the local failure path but cannot prevent a
|
||||
// later sibling node from being emitted and executed.
|
||||
// TODO(NGRA): Route a failed minimum check through the inherited failure ExitLabel.
|
||||
// The break below only stops charset scanning and must remain local to that loop.
|
||||
bool accept = payload.Accept;
|
||||
RegexCharSet _set = charset[0];
|
||||
_ = sc.AppendLine($"{ROS_char} {required_matched} = {remain_span}")
|
||||
.AppendLine($"int {additional_count} = 0;")
|
||||
.AppendLine()
|
||||
.AppendLine() //TODO loop head
|
||||
.AppendLine($"if({(accept ? string.Empty : "!(")} {GenerateCharSetExpression(_set)} ||");
|
||||
.AppendLine($"for(; {additional_count} < {max}; {additional_count} ++)")
|
||||
.AppendLine("{");
|
||||
if (charset.Count == 1)
|
||||
{
|
||||
// single charset rule
|
||||
_ = sc.AppendLine($"if({(accept ? string.Empty : "!(")} {GenerateCharSetExpression(_set)})");
|
||||
} else
|
||||
{
|
||||
// multi charset rule
|
||||
_ = sc.AppendLine($"if({(accept ? string.Empty : "!(")} {GenerateCharSetExpression(_set)} ||");
|
||||
for (int i = 1; i < charset.Count - 1; i++)
|
||||
{
|
||||
_set = charset[i];
|
||||
_ = sc.AppendLine($" {GenerateCharSetExpression(_set)} ||");
|
||||
}
|
||||
_set = charset[^1];
|
||||
_ = sc.AppendLine($" {GenerateCharSetExpression(_set)} ){(accept ? string.Empty : ')')}")
|
||||
.AppendLine("{")
|
||||
_ = sc.AppendLine($" {GenerateCharSetExpression(_set)} ){(accept ? string.Empty : ')')}");
|
||||
}
|
||||
_ = sc .AppendLine("{")
|
||||
.AppendLine($@"{context.RemainSpan} = {context.RemainSpan}.Slice(1);")
|
||||
.AppendLine("}")
|
||||
.AppendLine("else")
|
||||
.AppendLine("{")
|
||||
.AppendLine($@"break;")
|
||||
.AppendLine("}")
|
||||
.AppendLine("}")
|
||||
.AppendLine($"if({additional_count} < {min})")
|
||||
.AppendLine("{")
|
||||
.AppendLine("}")
|
||||
.AppendLine("else")
|
||||
.AppendLine("{")
|
||||
.AppendLine("}");
|
||||
}
|
||||
|
||||
@@ -508,7 +532,8 @@ namespace Nitload.RegularAnalysis.Text
|
||||
int max,
|
||||
bool is_greedy,
|
||||
[NotNull] in SequenceEmitter<string> sc,
|
||||
in SourceGenContext context
|
||||
in SourceGenContext context,
|
||||
string exit_label
|
||||
)
|
||||
{
|
||||
if (min < 0 || (max >= 0 && max < min)) {
|
||||
@@ -523,7 +548,10 @@ namespace Nitload.RegularAnalysis.Text
|
||||
|
||||
string expected_literal = FormatStringLiteral(literal);
|
||||
string remain_span = context.RemainSpan;
|
||||
int scratch_scope_index = context.RentScratchScopeIndex();
|
||||
// TODO(NGRA-NAMING): Allocate required_rest, required_matched, required_chunk_index,
|
||||
// required_count, and additional_count through the exclusive-name pool. Flattened
|
||||
// sibling COUNT nodes share the declaration space even after their exit labels.
|
||||
int scratch_scope_index = context.RequestScratchScopeIndex();
|
||||
string required_rest = $"__required_rest_{scratch_scope_index}";
|
||||
string required_matched = $"__required_matched_{scratch_scope_index}";
|
||||
string required_chunk_index = $"__required_chunk_index_{scratch_scope_index}";
|
||||
@@ -531,10 +559,8 @@ namespace Nitload.RegularAnalysis.Text
|
||||
string additional_count = $"__additional_count_{scratch_scope_index}";
|
||||
string starts_with = $"{nameof(MemoryExtensions.StartsWith)}";
|
||||
|
||||
// TODO(NGRA): Move ownership of this work region to the enclosing CONCAT or match
|
||||
// method. Until then, break demonstrates the local failure path but cannot prevent a
|
||||
// later sibling node from being emitted and executed.
|
||||
_ = sc.AppendLine("do").AppendLine("{");
|
||||
// TODO(NGRA): Replace this local COUNT exit with the inherited failure ExitLabel.
|
||||
// The temporary goto preserves the former local exit but still lets siblings execute.
|
||||
|
||||
if (literal.Length > flattened_unit_count_threshold)
|
||||
{
|
||||
@@ -549,7 +575,7 @@ namespace Nitload.RegularAnalysis.Text
|
||||
.AppendLine("}")
|
||||
.AppendLine($"if ({required_count} != {min})")
|
||||
.AppendLine("{")
|
||||
.AppendLine("break;")
|
||||
.AppendLine($"goto {exit_label};")
|
||||
.AppendLine("}")
|
||||
.AppendLine($"{remain_span} = {required_rest};");
|
||||
} else if (min <= flattened_unit_count_threshold / literal.Length)
|
||||
@@ -563,7 +589,7 @@ namespace Nitload.RegularAnalysis.Text
|
||||
string required_prefix = required_prefix_span.ToString();
|
||||
_ = sc.AppendLine($"if (!{remain_span}.{starts_with}({FormatStringLiteral(required_prefix)}))")
|
||||
.AppendLine("{")
|
||||
.AppendLine("break;")
|
||||
.AppendLine($"goto {exit_label};")
|
||||
.AppendLine("}")
|
||||
.AppendLine($"{remain_span} = {remain_span}.Slice({min * literal.Length});");
|
||||
}
|
||||
@@ -612,7 +638,7 @@ namespace Nitload.RegularAnalysis.Text
|
||||
|
||||
_ = sc.AppendLine($"if (!{required_matched})")
|
||||
.AppendLine("{")
|
||||
.AppendLine("break;")
|
||||
.AppendLine($"goto {exit_label};")
|
||||
.AppendLine("}")
|
||||
.AppendLine($"{remain_span} = {required_rest};");
|
||||
}
|
||||
@@ -640,8 +666,6 @@ namespace Nitload.RegularAnalysis.Text
|
||||
_ = sc.AppendLine("// TODO(NGRA): Retry the lazy COUNT tail from its continuation.");
|
||||
}
|
||||
|
||||
_ = sc.AppendLine("} while (false);");
|
||||
context.ReturnScratchScopeIndex(scratch_scope_index);
|
||||
}
|
||||
|
||||
private static void GenerateCount(
|
||||
@@ -659,6 +683,8 @@ namespace Nitload.RegularAnalysis.Text
|
||||
int min = payload.Min;
|
||||
int max = payload.Max;
|
||||
bool is_greedy = payload.IsGreedy;
|
||||
// TODO(NGRA-NAMING): Reserve exclusive names for future repetition/rollback state
|
||||
// across complex COUNT retries; recursive children must use the same method pool.
|
||||
string exit_label = context.RequestExitLabel();
|
||||
if ((value.Label & RegexElementLabel.SEQUENCE) == 0)
|
||||
{
|
||||
@@ -670,15 +696,16 @@ namespace Nitload.RegularAnalysis.Text
|
||||
switch (value.Label & RegexElementLabel.SEQUENCE)
|
||||
{
|
||||
case RegexElementLabel.UNIT:
|
||||
GenerateUnitCount(value, min, max, is_greedy, sc, context);
|
||||
GenerateUnitCount(value, min, max, is_greedy, sc, context, exit_label);
|
||||
break;
|
||||
case RegexElementLabel.UNIT_SET:
|
||||
GenerateUnitSetCount(value, min, max, is_greedy, sc, context);
|
||||
|
||||
// TODO(NGRA): Emit a bounded/unbounded charset counting loop, preferably
|
||||
// using IndexOfAnyExcept where the charset shape permits it.
|
||||
break;
|
||||
case RegexElementLabel.UNIT_SPAN:
|
||||
GenerateUnitSpanCount(value, min, max, is_greedy, sc, context);
|
||||
GenerateUnitSpanCount(value, min, max, is_greedy, sc, context, exit_label);
|
||||
break;
|
||||
default:
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@ namespace Nitload.RegularAnalysis.Text
|
||||
/// <remarks>
|
||||
/// Method level state is limited to the active cursor and the result of the most recent
|
||||
/// instruction. Everything else is either a region slot, a line slot, a capture slot, or
|
||||
/// a block scoped scratch variable. Scratch indices remain unique while rented and are
|
||||
/// recycled after their generated lexical scope has closed.
|
||||
/// a scratch variable. Scratch indices remain unique throughout the generated method;
|
||||
/// flattened regions cannot release their names for reuse by later nodes.
|
||||
/// </remarks>
|
||||
internal sealed class SourceGenContext
|
||||
{
|
||||
@@ -40,8 +40,6 @@ namespace Nitload.RegularAnalysis.Text
|
||||
|
||||
private int _scratch_scope_count;
|
||||
|
||||
private readonly Stack<int> _free_scratch_scope_indices = [];
|
||||
|
||||
public string RemainSpan { get; } = _remain_span;
|
||||
|
||||
public string FirstOfRemain { get; } = $@"{_remain_span}[0]";
|
||||
@@ -57,36 +55,22 @@ namespace Nitload.RegularAnalysis.Text
|
||||
|
||||
public string RequestExitLabel()
|
||||
{
|
||||
// TODO(NGRA-NAMING): Route ALT and COUNT labels through the method-wide label pool.
|
||||
// Keep every emitted label exclusive until method generation is complete.
|
||||
string code = $@"_exit_alt_{_exit_alt_count}";
|
||||
_exit_alt_count++;
|
||||
return code;
|
||||
}
|
||||
|
||||
public int RentScratchScopeIndex()
|
||||
public int RequestScratchScopeIndex()
|
||||
{
|
||||
if (_free_scratch_scope_indices.TryPop(out int recycled_index)) {
|
||||
return recycled_index;
|
||||
}
|
||||
|
||||
// TODO(NGRA-NAMING): Integrate scratch names with the method-wide exclusive-name
|
||||
// allocator. Until then, reserve each suffix permanently for this method.
|
||||
int index = _scratch_scope_count;
|
||||
_scratch_scope_count++;
|
||||
return index;
|
||||
}
|
||||
|
||||
public void ReturnScratchScopeIndex(
|
||||
int index
|
||||
)
|
||||
{
|
||||
if ((uint)index >= (uint)_scratch_scope_count) {
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
if (_free_scratch_scope_indices.Contains(index)) {
|
||||
throw new InvalidOperationException($"Scratch scope {index} was returned twice.");
|
||||
}
|
||||
|
||||
_free_scratch_scope_indices.Push(index);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace Nitload.RegularAnalysis.Text
|
||||
string static_modifier;
|
||||
|
||||
int brace_count = 0;
|
||||
do
|
||||
while (type is not null)
|
||||
{
|
||||
_ = file_name_sb.Append(CultureInfo.InvariantCulture, $@"{type.TypeName}.");
|
||||
string declare_type = type.DeclType switch
|
||||
@@ -74,7 +74,7 @@ namespace Nitload.RegularAnalysis.Text
|
||||
.AppendLine("{");
|
||||
brace_count++;
|
||||
type = type.InnerType!;
|
||||
} while (type is not null);
|
||||
}
|
||||
|
||||
static_modifier = gen_source.IsMethodStatic ? "static" : string.Empty;
|
||||
_ = ce.AppendLine(@$"{ToKeyword(gen_source.MethodAccessibility)} {static_modifier} {Text_Regex} {gen_source.MethodName}({ROS_char} {regex_gen_context.InputString})")
|
||||
@@ -90,8 +90,7 @@ namespace Nitload.RegularAnalysis.Text
|
||||
brace_count = 0;
|
||||
foreach (string line in ce)
|
||||
{
|
||||
bool is_right_brace = (line == "}") ||
|
||||
line.StartsWith("} while", StringComparison.InvariantCulture);
|
||||
bool is_right_brace = line == "}";
|
||||
brace_count -= is_right_brace ? 1 : 0;
|
||||
for (int i = 0; i < brace_count; i++) {
|
||||
_ = code_source.Append(" ");
|
||||
|
||||
@@ -232,13 +232,13 @@ namespace StgSharp.GenerateGL.Generation
|
||||
List<ManagedParameterDefinition> singleParameters = new List<ManagedParameterDefinition>(prefix)
|
||||
{
|
||||
new ManagedParameterDefinition("bool", "transpose", transposeSource),
|
||||
new ManagedParameterDefinition("GraphicsMatrix", "value", valueSource),
|
||||
new ManagedParameterDefinition("GMatrix44<float>", "value", valueSource),
|
||||
};
|
||||
List<ManagedParameterDefinition> spanParameters = new List<ManagedParameterDefinition>(prefix)
|
||||
{
|
||||
new ManagedParameterDefinition("bool", "transpose", transposeSource),
|
||||
new ManagedParameterDefinition(
|
||||
"ReadOnlySpan<GraphicsMatrix>",
|
||||
"ReadOnlySpan<GMatrix44<float>>",
|
||||
"values",
|
||||
valueSource),
|
||||
};
|
||||
|
||||
@@ -740,7 +740,7 @@ namespace StgSharp.GenerateGL.Generation
|
||||
string matrixName = EscapeIdentifier(matrix.Name);
|
||||
if (invocation.IsSpan)
|
||||
{
|
||||
builder.Append(" fixed (GraphicsMatrix* __value = ");
|
||||
builder.Append(" fixed (GMatrix44<float>* __value = ");
|
||||
builder.Append(matrixName);
|
||||
builder.Append(")\n");
|
||||
builder.Append(" {\n");
|
||||
|
||||
@@ -92,7 +92,7 @@ The generator merges a family only when it can validate the resulting signatures
|
||||
| `glUniform1*v` | `Uniform(..., ReadOnlySpan<T>)` |
|
||||
| `glUniform4*v` | `Uniform(..., ReadOnlySpan<Vec4<T>>)` |
|
||||
| `glUniform2*v` and `glUniform3*v` | Omitted because `Vec2` and `Vec3` storage is not a tightly packed C array |
|
||||
| `glUniformMatrix4fv` | `Uniform(..., GraphicsMatrix)` and matrix-span overloads |
|
||||
| `glUniformMatrix4fv` | `Uniform(..., GMatrix44<float>)` and matrix-span overloads |
|
||||
| Other matrix sizes and double matrices | Omitted because only the graphics-oriented 4x4 float layout is defined |
|
||||
| `glGetBooleanv`, `glGetFloatv`, `glGetIntegerv`, and related queries | `GetValue(..., Span<T>)` |
|
||||
| `glVertexAttrib1f/2f/3f/4f` and equivalent scalar forms | `VertexAttribute(...)`; component count is expressed by the parameter list |
|
||||
|
||||
Reference in New Issue
Block a user