diff --git a/.cr/team/Editor/Formatting/Braces.CSharp.xml b/.cr/team/Editor/Formatting/Braces.CSharp.xml new file mode 100644 index 00000000..1c194ef8 --- /dev/null +++ b/.cr/team/Editor/Formatting/Braces.CSharp.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 3ea7454f..00000000 --- a/.editorconfig +++ /dev/null @@ -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 \ No newline at end of file diff --git a/src/Nitload.Graphics/Camera.cs b/src/Nitload.Graphics/Camera.cs index 8af8bb60..6a387a7d 100644 --- a/src/Nitload.Graphics/Camera.cs +++ b/src/Nitload.Graphics/Camera.cs @@ -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 _lookAt; + internal GMatrix44 _projection; + internal GMatrix44 cameraAtt; + internal GMatrix44 rotation; + internal GMatrix44 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.Unit; _target = Vec3.Zero; up = Vec3.Zero; _isLookAtAvailable = false; - _lookAt = GraphicsMatrix.Unit; - rotationAtt = GraphicsMatrix.Unit; - _projection = new GraphicsMatrix(); + _lookAt = GMatrix44.Unit; + rotationAtt = GMatrix44.Unit; + _projection = new GMatrix44(); } public Camera( @@ -43,32 +43,32 @@ namespace Nitload.Mathematics.Numeric.Graphics ) : this() { - rotationAtt = GraphicsMatrix.Unit; - cameraAtt = new GraphicsMatrix(); + rotationAtt = GMatrix44.Unit; + cameraAtt = new GMatrix44(); SetViewDirection(position, target, up); _pitch = Radius.Zero; _row = Radius.Zero; _yaw = Radius.Zero; } - public GraphicsMatrix Projection => _projection; + public GMatrix44 Projection => _projection; - public GraphicsMatrix View + public GMatrix44 View { get { if (_isLookAtAvailable) { return _lookAt; } - GraphicsMatrix move = GraphicsMatrix.Unit; - move.column[3] -= cameraAtt.column[3]; + GMatrix44 move = GMatrix44.Unit; + move[3] = move[3] - cameraAtt[3]; _lookAt = rotationAtt.Transpose * move; _isLookAtAvailable = true; return _lookAt; } } - public GraphicsMatrix CameraMatrix() + public GMatrix44 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 direction = position - target; - if ((position == cameraAtt.column[3].XYZ) && + if ((position == new Vec3(cameraAtt[3, 0], cameraAtt[3, 1], cameraAtt[3, 2])) && (this.up == up) && - (cameraAtt.column[3].XYZ == direction)) { + (new Vec3(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 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(right, 0); + cameraAtt[1] = new Vec4(up, 0); + cameraAtt[2] = new Vec4(direction, 0); + cameraAtt[3] = new Vec4(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( diff --git a/src/Nitload.Graphics/OpenGL/Buffer/EBO.cs b/src/Nitload.Graphics/OpenGL/Buffer/EBO.cs deleted file mode 100644 index e5cec88b..00000000 --- a/src/Nitload.Graphics/OpenGL/Buffer/EBO.cs +++ /dev/null @@ -1,21 +0,0 @@ -// ----------------------------------------------------------------------------- -// file="EBO" -// Project: StgSharp -// Copyright (c) Nitload. -// SPDX-License-Identifier: MIT -// ----------------------------------------------------------------------------- - -namespace Nitload.Graphics.OpenGL -{ - /// A set of OpenGL element-buffer handles. - public sealed record class ElementBuffer( - GlHandle[] Handles - ) - { - - public int Count => Handles.Length; - - public GlHandle this[int index] => Handles[index]; - - } -} diff --git a/src/Nitload.Graphics/OpenGL/Buffer/FBO.cs b/src/Nitload.Graphics/OpenGL/Buffer/FBO.cs deleted file mode 100644 index 82355654..00000000 --- a/src/Nitload.Graphics/OpenGL/Buffer/FBO.cs +++ /dev/null @@ -1,21 +0,0 @@ -// ----------------------------------------------------------------------------- -// file="FBO" -// Project: StgSharp -// Copyright (c) Nitload. -// SPDX-License-Identifier: MIT -// ----------------------------------------------------------------------------- - -namespace Nitload.Graphics.OpenGL -{ - /// A set of OpenGL framebuffer handles. - public sealed record class FrameBuffer( - GlHandle[] Handles - ) - { - - public int Count => Handles.Length; - - public GlHandle this[int index] => Handles[index]; - - } -} diff --git a/src/Nitload.Graphics/OpenGL/Buffer/RBO.cs b/src/Nitload.Graphics/OpenGL/Buffer/RBO.cs deleted file mode 100644 index 82712b88..00000000 --- a/src/Nitload.Graphics/OpenGL/Buffer/RBO.cs +++ /dev/null @@ -1,21 +0,0 @@ -// ----------------------------------------------------------------------------- -// file="RBO" -// Project: StgSharp -// Copyright (c) Nitload. -// SPDX-License-Identifier: MIT -// ----------------------------------------------------------------------------- - -namespace Nitload.Graphics.OpenGL -{ - /// A set of OpenGL renderbuffer handles. - public sealed record class RenderBuffer( - GlHandle[] Handles - ) - { - - public int Count => Handles.Length; - - public GlHandle this[int index] => Handles[index]; - - } -} diff --git a/src/Nitload.Graphics/OpenGL/Buffer/TextureGL.cs b/src/Nitload.Graphics/OpenGL/Buffer/TextureGL.cs deleted file mode 100644 index 75f62bf2..00000000 --- a/src/Nitload.Graphics/OpenGL/Buffer/TextureGL.cs +++ /dev/null @@ -1,54 +0,0 @@ -// ----------------------------------------------------------------------------- -// file="TextureGL" -// Project: StgSharp -// Copyright (c) Nitload. -// SPDX-License-Identifier: MIT -// ----------------------------------------------------------------------------- - -namespace Nitload.Graphics.OpenGL -{ - /// A set of OpenGL texture handles. - 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, - - } -} diff --git a/src/Nitload.Graphics/OpenGL/Buffer/VAO.cs b/src/Nitload.Graphics/OpenGL/Buffer/VAO.cs deleted file mode 100644 index 297d9a04..00000000 --- a/src/Nitload.Graphics/OpenGL/Buffer/VAO.cs +++ /dev/null @@ -1,21 +0,0 @@ -// ----------------------------------------------------------------------------- -// file="VAO" -// Project: StgSharp -// Copyright (c) Nitload. -// SPDX-License-Identifier: MIT -// ----------------------------------------------------------------------------- - -namespace Nitload.Graphics.OpenGL -{ - /// A set of OpenGL vertex-array handles. - public sealed record class VertexArray( - GlHandle[] Handles - ) - { - - public int Count => Handles.Length; - - public GlHandle this[int index] => Handles[index]; - - } -} diff --git a/src/Nitload.Graphics/OpenGL/Buffer/VBO.cs b/src/Nitload.Graphics/OpenGL/Buffer/VBO.cs deleted file mode 100644 index 26117906..00000000 --- a/src/Nitload.Graphics/OpenGL/Buffer/VBO.cs +++ /dev/null @@ -1,21 +0,0 @@ -// ----------------------------------------------------------------------------- -// file="VBO" -// Project: StgSharp -// Copyright (c) Nitload. -// SPDX-License-Identifier: MIT -// ----------------------------------------------------------------------------- - -namespace Nitload.Graphics.OpenGL -{ - /// A set of OpenGL vertex-buffer handles. - public sealed record class VertexBuffer( - GlHandle[] Handles - ) - { - - public int Count => Handles.Length; - - public GlHandle this[int index] => Handles[index]; - - } -} diff --git a/src/Nitload.Graphics/OpenGL/Generated/OpenGLFunction.Base.g.cs b/src/Nitload.Graphics/OpenGL/Generated/OpenGLFunction.Base.g.cs index 292d8f00..6889c48b 100644 --- a/src/Nitload.Graphics/OpenGL/Generated/OpenGLFunction.Base.g.cs +++ b/src/Nitload.Graphics/OpenGL/Generated/OpenGLFunction.Base.g.cs @@ -1783,9 +1783,12 @@ namespace Nitload.Graphics.OpenGL /// See docs.gl. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Uniform(int location, bool transpose, GraphicsMatrix value) + public void Uniform(int location, bool transpose, GMatrix44 value) { - __context->glUniformMatrix4fv(location, 1, transpose ? (byte)1 : (byte)0, (float*)&value); + fixed (GMatrix44* __value = &value) + { + __context->glUniformMatrix4fv(location, 1, transpose ? (byte)1 : (byte)0, (float*)__value); + } } /// @@ -1794,9 +1797,9 @@ namespace Nitload.Graphics.OpenGL /// See docs.gl. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Uniform(int location, bool transpose, ReadOnlySpan values) + public void Uniform(int location, bool transpose, ReadOnlySpan> values) { - fixed (GraphicsMatrix* __value = values) + fixed (GMatrix44* __value = values) { __context->glUniformMatrix4fv(location, values.Length, transpose ? (byte)1 : (byte)0, (float*)__value); } diff --git a/src/Nitload.Graphics/OpenGL/Generated/OpenGLFunction.v4_1.g.cs b/src/Nitload.Graphics/OpenGL/Generated/OpenGLFunction.v4_1.g.cs index d823b332..512d07be 100644 --- a/src/Nitload.Graphics/OpenGL/Generated/OpenGLFunction.v4_1.g.cs +++ b/src/Nitload.Graphics/OpenGL/Generated/OpenGLFunction.v4_1.g.cs @@ -631,9 +631,12 @@ namespace Nitload.Graphics.OpenGL /// See docs.gl. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ProgramUniform(GlHandle program, int location, bool transpose, GraphicsMatrix value) + public void ProgramUniform(GlHandle program, int location, bool transpose, GMatrix44 value) { - __context->glProgramUniformMatrix4fv(program.Value, location, 1, transpose ? (byte)1 : (byte)0, (float*)&value); + fixed (GMatrix44* __value = &value) + { + __context->glProgramUniformMatrix4fv(program.Value, location, 1, transpose ? (byte)1 : (byte)0, (float*)__value); + } } /// @@ -642,9 +645,9 @@ namespace Nitload.Graphics.OpenGL /// See docs.gl. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void ProgramUniform(GlHandle program, int location, bool transpose, ReadOnlySpan values) + public void ProgramUniform(GlHandle program, int location, bool transpose, ReadOnlySpan> values) { - fixed (GraphicsMatrix* __value = values) + fixed (GMatrix44* __value = values) { __context->glProgramUniformMatrix4fv(program.Value, location, values.Length, transpose ? (byte)1 : (byte)0, (float*)__value); } diff --git a/src/Nitload.Mathematics/Geometries/Coordination/CoordinationBase.cs b/src/Nitload.Mathematics/Geometries/Coordination/CoordinationBase.cs index 8d8c25d5..fe89098f 100644 --- a/src/Nitload.Mathematics/Geometries/Coordination/CoordinationBase.cs +++ b/src/Nitload.Mathematics/Geometries/Coordination/CoordinationBase.cs @@ -16,41 +16,61 @@ namespace Nitload.Geometries private bool globalCoordAvailable; private CoordinationBase localCoordination; - private GraphicsMatrix coordMat; + private GMatrix44 coordMat; public CoordinationBase( CoordinationBase localCoordination ) { this.localCoordination = localCoordination; - coordMat = new GraphicsMatrix(); + coordMat = new GMatrix44(); } public virtual Point LocalOrigin { - get => new Point(coordMat.column[3].XYZ); - internal set => coordMat.column[3].XYZ = value.Coord; + get => new Point(new Vec3(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 LocalX { - get => coordMat.column[3].XYZ; - internal set => coordMat.column[3].XYZ = value; + get => new Vec3(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 LocalY { - get => coordMat.column[3].XYZ; - internal set => coordMat.column[3].XYZ = value; + get => new Vec3(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 LocalZ { - get => coordMat.column[3].XYZ; - set => coordMat.column[3].XYZ = value; + get => new Vec3(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 CoordMat => ref coordMat; } } diff --git a/src/Nitload.Mathematics/Geometries/Coordination/PlainCoordinate.cs b/src/Nitload.Mathematics/Geometries/Coordination/PlainCoordinate.cs index d3bd8002..5262d425 100644 --- a/src/Nitload.Mathematics/Geometries/Coordination/PlainCoordinate.cs +++ b/src/Nitload.Mathematics/Geometries/Coordination/PlainCoordinate.cs @@ -26,11 +26,11 @@ namespace Nitload.Geometries ) : base(local) { - CoordMat = GraphicsMatrix.Unit; + CoordMat = GMatrix44.Unit; - CoordMat.column[0] = new Vec4(xAxis, 0); - CoordMat.column[1] = new Vec4(yAxis, 0); - CoordMat.column[2] = new Vec4(Linear.Normalize(Vec3.Cross(xAxis, yAxis)), 0); + CoordMat[0] = new Vec4(xAxis, 0); + CoordMat[1] = new Vec4(yAxis, 0); + CoordMat[2] = new Vec4(Linear.Normalize(Vec3.Cross(xAxis, yAxis)), 0); LocalOrigin = origin; } diff --git a/src/Nitload.Mathematics/Geometries/IInstancing.cs b/src/Nitload.Mathematics/Geometries/IInstancing.cs index 1fa00c3d..8d50e54d 100644 --- a/src/Nitload.Mathematics/Geometries/IInstancing.cs +++ b/src/Nitload.Mathematics/Geometries/IInstancing.cs @@ -41,13 +41,11 @@ namespace Nitload.Geometries public Vec3 CenterPositionGlobal { get; internal set; } - public Vec3 Coord// - { get => GlobalBuffer.CoordAndRotationList[BufferId].XYZ;// - set - { - Vec4 v = new(value, 0); - GlobalBuffer.CoordAndRotationList[BufferId] = v; - } } + public Vec3 Coord { get => GlobalBuffer.CoordAndRotationList[BufferId].XYZ; set + { + Vec4 v = new(value, 0); + GlobalBuffer.CoordAndRotationList[BufferId] = v; + } } public void Move() { diff --git a/src/Nitload.Mathematics/Numeric/Graphics/GMatrix44_T.cs b/src/Nitload.Mathematics/Numeric/Graphics/GMatrix44_T.cs new file mode 100644 index 00000000..4824e1e2 --- /dev/null +++ b/src/Nitload.Mathematics/Numeric/Graphics/GMatrix44_T.cs @@ -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 where T : unmanaged, INumber + { + + private Buffer _buffer; + + public Vec4 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 Unit + { + get + { + GMatrix44 result = new(); + result[0] = new Vec4(T.One, T.Zero, T.Zero, T.Zero); + result[1] = new Vec4(T.Zero, T.One, T.Zero, T.Zero); + result[2] = new Vec4(T.Zero, T.Zero, T.One, T.Zero); + result[3] = new Vec4(T.Zero, T.Zero, T.Zero, T.One); + return result; + } + } + + public GMatrix44 Transpose + { + get + { + GMatrix44 transpose = new(); + + // Native SK transpose is intentionally deferred until the module + // startup path can guarantee that GlobalContext has been initialized. + + if (Unsafe.SizeOf() == 4) + { + Vector128 row0Source = _buffer[0].AsVector128Unsafe(); + Vector128 row1Source = _buffer[1].AsVector128Unsafe(); + Vector128 row2Source = _buffer[2].AsVector128Unsafe(); + Vector128 row3Source = _buffer[3].AsVector128Unsafe(); + Vector128 row0 = Unsafe.As, Vector128>(ref row0Source); + Vector128 row1 = Unsafe.As, Vector128>(ref row1Source); + Vector128 row2 = Unsafe.As, Vector128>(ref row2Source); + Vector128 row3 = Unsafe.As, Vector128>(ref row3Source); + + Vector128 pairMask = Vector128.Create(-1, 0, -1, 0); + Vector128 firstPairMask = Vector128.Create(-1, -1, 0, 0); + Vector128 lowShuffle = Vector128.Create(0, 0, 1, 1); + Vector128 highShuffle = Vector128.Create(2, 2, 3, 3); + Vector128 secondLaneShuffle = Vector128.Create(2, 3, 2, 3); + + Vector128 pair01Low = Vector128.ConditionalSelect( + pairMask, + Vector128.Shuffle(row0, lowShuffle), + Vector128.Shuffle(row1, lowShuffle)); + Vector128 pair23Low = Vector128.ConditionalSelect( + pairMask, + Vector128.Shuffle(row2, lowShuffle), + Vector128.Shuffle(row3, lowShuffle)); + Vector128 pair01High = Vector128.ConditionalSelect( + pairMask, + Vector128.Shuffle(row0, highShuffle), + Vector128.Shuffle(row1, highShuffle)); + Vector128 pair23High = Vector128.ConditionalSelect( + pairMask, + Vector128.Shuffle(row2, highShuffle), + Vector128.Shuffle(row3, highShuffle)); + + Vector128 result0 = Vector128.ConditionalSelect( + firstPairMask, pair01Low, pair23Low); + Vector128 result1 = Vector128.ConditionalSelect( + firstPairMask, + Vector128.Shuffle(pair01Low, secondLaneShuffle), + Vector128.Shuffle(pair23Low, secondLaneShuffle)); + Vector128 result2 = Vector128.ConditionalSelect( + firstPairMask, pair01High, pair23High); + Vector128 result3 = Vector128.ConditionalSelect( + firstPairMask, + Vector128.Shuffle(pair01High, secondLaneShuffle), + Vector128.Shuffle(pair23High, secondLaneShuffle)); + transpose._buffer[0] = Vec4.FromVector128Unsafe( + Unsafe.As, Vector128>(ref result0)); + transpose._buffer[1] = Vec4.FromVector128Unsafe( + Unsafe.As, Vector128>(ref result1)); + transpose._buffer[2] = Vec4.FromVector128Unsafe( + Unsafe.As, Vector128>(ref result2)); + transpose._buffer[3] = Vec4.FromVector128Unsafe( + Unsafe.As, Vector128>(ref result3)); + return transpose; + } + + if (Unsafe.SizeOf() == 8) + { + Vector256 row0Source = _buffer[0].AsVector256Unsafe(); + Vector256 row1Source = _buffer[1].AsVector256Unsafe(); + Vector256 row2Source = _buffer[2].AsVector256Unsafe(); + Vector256 row3Source = _buffer[3].AsVector256Unsafe(); + Vector256 row0 = Unsafe.As, Vector256>(ref row0Source); + Vector256 row1 = Unsafe.As, Vector256>(ref row1Source); + Vector256 row2 = Unsafe.As, Vector256>(ref row2Source); + Vector256 row3 = Unsafe.As, Vector256>(ref row3Source); + + Vector256 pairMask = Vector256.Create(-1L, 0L, -1L, 0L); + Vector256 firstPairMask = Vector256.Create(-1L, -1L, 0L, 0L); + Vector256 firstShuffle = Vector256.Create(0L, 0L, 1L, 1L); + Vector256 secondShuffle = Vector256.Create(2L, 2L, 3L, 3L); + Vector256 pair01First = Vector256.ConditionalSelect( + pairMask, + Vector256.Shuffle(row0, firstShuffle), + Vector256.Shuffle(row1, firstShuffle)); + Vector256 pair23First = Vector256.ConditionalSelect( + pairMask, + Vector256.Shuffle(row2, firstShuffle), + Vector256.Shuffle(row3, firstShuffle)); + Vector256 pair01Second = Vector256.ConditionalSelect( + pairMask, + Vector256.Shuffle(row0, secondShuffle), + Vector256.Shuffle(row1, secondShuffle)); + Vector256 pair23Second = Vector256.ConditionalSelect( + pairMask, + Vector256.Shuffle(row2, secondShuffle), + Vector256.Shuffle(row3, secondShuffle)); + Vector256 result0 = Vector256.ConditionalSelect( + firstPairMask, pair01First, pair23First); + Vector256 result1 = Vector256.ConditionalSelect( + firstPairMask, + Vector256.Shuffle(pair01First, secondShuffle), + Vector256.Shuffle(pair23First, secondShuffle)); + Vector256 result2 = Vector256.ConditionalSelect( + firstPairMask, pair01Second, pair23Second); + Vector256 result3 = Vector256.ConditionalSelect( + firstPairMask, + Vector256.Shuffle(pair01Second, secondShuffle), + Vector256.Shuffle(pair23Second, secondShuffle)); + transpose._buffer[0] = Vec4.FromVector256Unsafe( + Unsafe.As, Vector256>(ref result0)); + transpose._buffer[1] = Vec4.FromVector256Unsafe( + Unsafe.As, Vector256>(ref result1)); + transpose._buffer[2] = Vec4.FromVector256Unsafe( + Unsafe.As, Vector256>(ref result2)); + transpose._buffer[3] = Vec4.FromVector256Unsafe( + Unsafe.As, Vector256>(ref result3)); + return transpose; + } + + throw GraphicVector.ThrowUnsupportedTypeException(); + } + } + + [InlineArray(4)] + private struct Buffer + { + + public Vec4 _column; + + } + + } +} diff --git a/src/Nitload.Mathematics/Numeric/Graphics/GraphicsMatrix.cs b/src/Nitload.Mathematics/Numeric/Graphics/GraphicsMatrix.cs deleted file mode 100644 index 2054a690..00000000 --- a/src/Nitload.Mathematics/Numeric/Graphics/GraphicsMatrix.cs +++ /dev/null @@ -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 - { - - [FieldOffset(0 * sizeof(float))] internal Column column; - - [FieldOffset(0)] internal ColumnSet4 mat; - [FieldOffset(0)] internal MatrixKernel 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 AsSpan() - { - return MemoryMarshal.CreateReadOnlySpan(ref Unsafe.As(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* 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 value; - - } - - } -} - diff --git a/src/Nitload.Mathematics/Numeric/Graphics/Vec3.cs b/src/Nitload.Mathematics/Numeric/Graphics/Vec3.cs index 8837fb93..8389f47e 100644 --- a/src/Nitload.Mathematics/Numeric/Graphics/Vec3.cs +++ b/src/Nitload.Mathematics/Numeric/Graphics/Vec3.cs @@ -15,13 +15,61 @@ namespace Nitload.Mathematics.Numeric.Graphics public static class Vec3 { - public static bool IsParallel(Vec3 left, Vec3 right) where T: unmanaged,INumber + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vec3 ConvertToDouble( + Vec3 source + ) + { + return FromVector256Unsafe(Vector256.ConvertToDouble(source.AsVector256Safe())); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vec3 ConvertToDouble( + Vec3 source + ) + { + return FromVector256Unsafe(Vector256.ConvertToDouble(source.AsVector256Safe())); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vec3 ConvertToSingle( + Vec3 source + ) + { + return FromVector128Unsafe(Vector128.ConvertToSingle(source.AsVector128Safe())); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vec3 ConvertToSingle( + Vec3 source + ) + { + return FromVector128Unsafe(Vector128.ConvertToSingle(source.AsVector128Safe())); + } + + public static Vec3 FromSpan( + ReadOnlySpan span + ) where T : unmanaged, INumber + { + 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( + Vec3 left, + Vec3 right + ) where T : unmanaged,INumber { return Cross(left, right).Equals(T.Zero); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static Vector128 AsVector128Safe(this Vec3 source) where T: unmanaged, INumber + internal static Vector128 AsVector128Safe( + this Vec3 source + ) where T : unmanaged, INumber { Vector128 result = Vector128.Zero; Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), source); @@ -29,7 +77,9 @@ namespace Nitload.Mathematics.Numeric.Graphics } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static Vector128 AsVector128Unsafe(this Vec3 source) where T: unmanaged, INumber + internal static Vector128 AsVector128Unsafe( + this Vec3 source + ) where T : unmanaged, INumber { Unsafe.SkipInit(out Vector128 result); Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), source); @@ -37,7 +87,9 @@ namespace Nitload.Mathematics.Numeric.Graphics } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static Vector256 AsVector256Safe(this Vec3 source) where T: unmanaged, INumber + internal static Vector256 AsVector256Safe( + this Vec3 source + ) where T : unmanaged, INumber { Vector256 result = Vector256.Zero; Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), source); @@ -45,7 +97,9 @@ namespace Nitload.Mathematics.Numeric.Graphics } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static Vector256 AsVector256Unsafe(this Vec3 source) where T: unmanaged, INumber + internal static Vector256 AsVector256Unsafe( + this Vec3 source + ) where T : unmanaged, INumber { Unsafe.SkipInit(out Vector256 result); Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), source); @@ -53,45 +107,28 @@ namespace Nitload.Mathematics.Numeric.Graphics } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static Vec3 FromVector128Unsafe(Vector128 source) where T: unmanaged, INumber + internal static Vec3 FromVector128Unsafe( + Vector128 source + ) where T : unmanaged, INumber { return Unsafe.As, Vec3>(ref source); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static Vec3 FromVector256Unsafe(Vector256 source) where T: unmanaged, INumber + internal static Vec3 FromVector256Unsafe( + Vector256 source + ) where T : unmanaged, INumber { return Unsafe.As, Vec3>(ref source); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vec3 ConvertToSingle(Vec3 source) - { - return FromVector128Unsafe(Vector128.ConvertToSingle(source.AsVector128Safe())); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vec3 ConvertToSingle(Vec3 source) - { - return FromVector128Unsafe(Vector128.ConvertToSingle(source.AsVector128Safe())); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vec3 ConvertToDouble(Vec3 source) - { - return FromVector256Unsafe(Vector256.ConvertToDouble(source.AsVector256Safe())); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vec3 ConvertToDouble(Vec3 source) - { - return FromVector256Unsafe(Vector256.ConvertToDouble(source.AsVector256Safe())); - } - #region cross [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vec3 Cross(Vec3 left, Vec3 right) where T: unmanaged, INumber + public static Vec3 Cross( + Vec3 left, + Vec3 right + ) where T : unmanaged, INumber { if (typeof(T) == typeof(float)) { @@ -140,7 +177,10 @@ namespace Nitload.Mathematics.Numeric.Graphics } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vec3 CrossDouble(Vec3 left, Vec3 right) + private static Vec3 CrossDouble( + Vec3 left, + Vec3 right + ) { Vector256 l = left.AsVector256Safe(); Vector256 r = right.AsVector256Safe(); @@ -151,7 +191,10 @@ namespace Nitload.Mathematics.Numeric.Graphics } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vec3 CrossInt32(Vec3 left, Vec3 right) + private static Vec3 CrossInt32( + Vec3 left, + Vec3 right + ) { Vector128 l = left.AsVector128Safe(); Vector128 r = right.AsVector128Safe(); @@ -162,7 +205,10 @@ namespace Nitload.Mathematics.Numeric.Graphics } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vec3 CrossSingle(Vec3 left, Vec3 right) + private static Vec3 CrossSingle( + Vec3 left, + Vec3 right + ) { Vector128 l = left.AsVector128Safe(); Vector128 r = right.AsVector128Safe(); @@ -173,7 +219,10 @@ namespace Nitload.Mathematics.Numeric.Graphics } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vec3 CrossUInt32(Vec3 left, Vec3 right) + private static Vec3 CrossUInt32( + Vec3 left, + Vec3 right + ) { Vector128 l = left.AsVector128Safe(); Vector128 r = right.AsVector128Safe(); @@ -184,7 +233,10 @@ namespace Nitload.Mathematics.Numeric.Graphics } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vec3 CrossUInt64(Vec3 left, Vec3 right) + private static Vec3 CrossUInt64( + Vec3 left, + Vec3 right + ) { Vector256 l = left.AsVector256Safe(); Vector256 r = right.AsVector256Safe(); @@ -195,7 +247,10 @@ namespace Nitload.Mathematics.Numeric.Graphics } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static Vec3 CrossInt64(Vec3 left, Vec3 right) + private static Vec3 CrossInt64( + Vec3 left, + Vec3 right + ) { Vector256 l = left.AsVector256Safe(); Vector256 r = right.AsVector256Safe(); diff --git a/src/Nitload.Mathematics/Numeric/Graphics/Vec3_T.cs b/src/Nitload.Mathematics/Numeric/Graphics/Vec3_T.cs index be430de6..68b0d1ad 100644 --- a/src/Nitload.Mathematics/Numeric/Graphics/Vec3_T.cs +++ b/src/Nitload.Mathematics/Numeric/Graphics/Vec3_T.cs @@ -21,21 +21,28 @@ namespace Nitload.Mathematics.Numeric.Graphics /// [StructLayout(LayoutKind.Sequential, Pack = 16)] public struct Vec3 : IUnmanagedVector>, IEquatable>, IEnumerable - where T: unmanaged, INumber + where T : unmanaged, INumber { public T X; public T Y; public T Z; - public Vec3(Vec2 xy, T z) + public Vec3( + Vec2 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 UnitZ => new(T.Zero, T.Zero, T.One); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly T Dot(Vec3 right) + public readonly T Dot( + Vec3 right + ) { if (Unsafe.SizeOf() == 8) { @@ -89,31 +98,28 @@ namespace Nitload.Mathematics.Numeric.Graphics } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly bool Equals(Vec3 other) + public readonly bool Equals( + Vec3 other + ) { - if (Unsafe.SizeOf() == 4) { + if (Unsafe.SizeOf() == 4) + { return this.AsVector128Safe() == other.AsVector128Safe(); - } - if (Unsafe.SizeOf() == 8) { + } else if (Unsafe.SizeOf() == 8) { return this.AsVector256Safe() == other.AsVector256Safe(); } +#pragma warning disable CA1065 throw GraphicVector.ThrowUnsupportedTypeException(); +#pragma warning restore CA1065 } - public override readonly bool Equals(object? obj) + public override readonly bool Equals( + object? obj + ) { return obj is Vec3 other && Equals(other); } - public static Vec3 FromSpan(ReadOnlySpan 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 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 left, Vec3 right) + public static bool IsParallel( + Vec3 left, + Vec3 right + ) { return Vec3.Cross(left, right) == Zero; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vec3 operator -(Vec3 value) + public static Vec3 operator -( + Vec3 value + ) { - if (Unsafe.SizeOf() == 4) { + if (Unsafe.SizeOf() == 4) + { return Vec3.FromVector128Unsafe(Vector128.Zero - value.AsVector128Unsafe()); - } - if (Unsafe.SizeOf() == 8) { + } else if (Unsafe.SizeOf() == 8) { return Vec3.FromVector256Unsafe(Vector256.Zero - value.AsVector256Unsafe()); } throw GraphicVector.ThrowUnsupportedTypeException(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vec3 operator -(Vec3 left, Vec3 right) + public static Vec3 operator -( + Vec3 left, + Vec3 right + ) { if (Unsafe.SizeOf() == 4) { Vector128 left_v128 = left.AsVector128Unsafe(); Vector128 right_v128 = right.AsVector128Unsafe(); return Vec3.FromVector128Unsafe(left_v128 - right_v128); - } - if (Unsafe.SizeOf() == 8) + } else if (Unsafe.SizeOf() == 8) { Vector256 left_v256 = left.AsVector256Unsafe(); Vector256 right_v256 = right.AsVector256Unsafe(); @@ -168,21 +181,26 @@ namespace Nitload.Mathematics.Numeric.Graphics } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator !=(Vec3 left, Vec3 right) + public static bool operator !=( + Vec3 left, + Vec3 right + ) { return !left.Equals(right); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vec3 operator *(Vec3 vector, T scalar) + public static Vec3 operator *( + Vec3 vector, + T scalar + ) { if (Unsafe.SizeOf() == 4) { Vector128 vector_v128 = vector.AsVector128Unsafe(); Vector128 scalar_v128 = Vector128.Create(scalar); return Vec3.FromVector128Unsafe(vector_v128 * scalar_v128); - } - if (Unsafe.SizeOf() == 8) + } else if (Unsafe.SizeOf() == 8) { Vector256 vector_v256 = vector.AsVector256Unsafe(); Vector256 scalar_v256 = Vector256.Create(scalar); @@ -192,27 +210,35 @@ namespace Nitload.Mathematics.Numeric.Graphics } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vec3 operator *(T scalar, Vec3 vector) + public static Vec3 operator *( + T scalar, + Vec3 vector + ) { return vector * scalar; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T operator *(Vec3 left, Vec3 right) + public static T operator *( + Vec3 left, + Vec3 right + ) { return left.Dot(right); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vec3 operator /(Vec3 vector, T scalar) + public static Vec3 operator /( + Vec3 vector, + T scalar + ) { if (Unsafe.SizeOf() == 4) { Vector128 vector_v128 = vector.AsVector128Unsafe(); Vector128 scalar_v128 = Vector128.Create(scalar); return Vec3.FromVector128Unsafe(vector_v128 / scalar_v128); - } - if (Unsafe.SizeOf() == 8) + } else if (Unsafe.SizeOf() == 8) { Vector256 vector_v256 = vector.AsVector256Unsafe(); Vector256 scalar_v256 = Vector256.Create(scalar); @@ -222,15 +248,17 @@ namespace Nitload.Mathematics.Numeric.Graphics } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vec3 operator +(Vec3 left, Vec3 right) + public static Vec3 operator +( + Vec3 left, + Vec3 right + ) { if (Unsafe.SizeOf() == 4) { Vector128 left_v128 = left.AsVector128Unsafe(); Vector128 right_v128 = right.AsVector128Unsafe(); return Vec3.FromVector128Unsafe(left_v128 + right_v128); - } - if (Unsafe.SizeOf() == 8) + } else if (Unsafe.SizeOf() == 8) { Vector256 left_v256 = left.AsVector256Unsafe(); Vector256 right_v256 = right.AsVector256Unsafe(); @@ -240,13 +268,18 @@ namespace Nitload.Mathematics.Numeric.Graphics } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool operator ==(Vec3 left, Vec3 right) + public static bool operator ==( + Vec3 left, + Vec3 right + ) { return left.Equals(right); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static implicit operator Vec3((T X, T Y, T Z) tuple) + public static implicit operator Vec3( + (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; + + } + } } diff --git a/src/Nitload.Mathematics/Numeric/Graphics/Vec4.cs b/src/Nitload.Mathematics/Numeric/Graphics/Vec4.cs index 85136c19..504396f4 100644 --- a/src/Nitload.Mathematics/Numeric/Graphics/Vec4.cs +++ b/src/Nitload.Mathematics/Numeric/Graphics/Vec4.cs @@ -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 AsVector128Unsafe(this Vec4 source) where T: unmanaged, INumber + public static Vec4 ConvertToDouble( + Vec4 source + ) + { + return FromVector256Unsafe(Vector256.ConvertToDouble(source.AsVector256Unsafe())); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vec4 ConvertToDouble( + Vec4 source + ) + { + return FromVector256Unsafe(Vector256.ConvertToDouble(source.AsVector256Unsafe())); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vec4 ConvertToSingle( + Vec4 source + ) + { + return FromVector128Unsafe(Vector128.ConvertToSingle(source.AsVector128Unsafe())); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Vec4 ConvertToSingle( + Vec4 source + ) + { + return FromVector128Unsafe(Vector128.ConvertToSingle(source.AsVector128Unsafe())); + } + + public static Vec4 FromSpan( + ReadOnlySpan span + ) where T : unmanaged, INumber + { + if (span.Length < 4) { + throw new ArgumentException("Span length must be at least 4.", nameof(span)); + } + + Unsafe.SkipInit(out Vec4 result); + Span target = MemoryMarshal.CreateSpan(ref Unsafe.As, T>(ref result), 4); + span[..4].CopyTo(target); + return result; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector128 AsVector128Unsafe( + this Vec4 source + ) where T : unmanaged, INumber { Unsafe.SkipInit(out Vector128 result); Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), source); @@ -23,7 +72,9 @@ namespace Nitload.Mathematics.Numeric.Graphics } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static Vector256 AsVector256Unsafe(this Vec4 source) where T: unmanaged, INumber + internal static Vector256 AsVector256Unsafe( + this Vec4 source + ) where T : unmanaged, INumber { Unsafe.SkipInit(out Vector256 result); Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), source); @@ -31,40 +82,20 @@ namespace Nitload.Mathematics.Numeric.Graphics } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static Vec4 FromVector128Unsafe(Vector128 source) where T: unmanaged, INumber + internal static Vec4 FromVector128Unsafe( + Vector128 source + ) where T : unmanaged, INumber { return Unsafe.As, Vec4>(ref source); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static Vec4 FromVector256Unsafe(Vector256 source) where T: unmanaged, INumber + internal static Vec4 FromVector256Unsafe( + Vector256 source + ) where T : unmanaged, INumber { return Unsafe.As, Vec4>(ref source); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vec4 ConvertToSingle(Vec4 source) - { - return FromVector128Unsafe(Vector128.ConvertToSingle(source.AsVector128Unsafe())); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vec4 ConvertToSingle(Vec4 source) - { - return FromVector128Unsafe(Vector128.ConvertToSingle(source.AsVector128Unsafe())); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vec4 ConvertToDouble(Vec4 source) - { - return FromVector256Unsafe(Vector256.ConvertToDouble(source.AsVector256Unsafe())); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Vec4 ConvertToDouble(Vec4 source) - { - return FromVector256Unsafe(Vector256.ConvertToDouble(source.AsVector256Unsafe())); - } - } } diff --git a/src/Nitload.Mathematics/Numeric/Graphics/Vec4_T.cs b/src/Nitload.Mathematics/Numeric/Graphics/Vec4_T.cs index 35dd4893..c265742c 100644 --- a/src/Nitload.Mathematics/Numeric/Graphics/Vec4_T.cs +++ b/src/Nitload.Mathematics/Numeric/Graphics/Vec4_T.cs @@ -20,11 +20,7 @@ namespace Nitload.Mathematics.Numeric.Graphics public struct Vec4 : IUnmanagedVector> where T : unmanaged, INumber { - public T W; - - public T X; - public T Y; - public T Z; + private Buffer _buffer; public Vec4( Vec3 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 XY { - get => Unsafe.As>(ref X); + get => Unsafe.As>(ref _buffer[0]); set { X = value.X; @@ -62,11 +90,60 @@ namespace Nitload.Mathematics.Numeric.Graphics public Vec3 XYZ { - get => Unsafe.As>(ref X); + get => Unsafe.As>(ref _buffer[0]); set { T w = W; - Unsafe.As>(ref X) = value; + Unsafe.As>(ref _buffer[0]) = value; + W = w; + } + } + + public Vec3 ZXY + { + readonly get + { + if (Unsafe.SizeOf() == 4) + { + Vector128 source = this.AsVector128Unsafe(); + Vector128 bits = Unsafe.As, Vector128>(ref source); + Vector128 result = Vector128.Shuffle(bits, Vector128.Create(2, 0, 1, 3)); + Vector128 shuffled = Unsafe.As, Vector128>(ref result); + return Vec3.FromVector128Unsafe(shuffled); + } + if (Unsafe.SizeOf() == 8) + { + Vector256 source = this.AsVector256Unsafe(); + Vector256 bits = Unsafe.As, Vector256>(ref source); + Vector256 result = Vector256.Shuffle(bits, Vector256.Create(2L, 0L, 1L, + 3L)); + Vector256 shuffled = Unsafe.As, Vector256>(ref result); + return Vec3.FromVector256Unsafe(shuffled); + } + throw GraphicVector.ThrowUnsupportedTypeException(); + } + set + { + T w = W; + if (Unsafe.SizeOf() == 4) + { + Vector128 source = value.AsVector128Unsafe(); + Vector128 bits = Unsafe.As, Vector128>(ref source); + Vector128 result = Vector128.Shuffle(bits, Vector128.Create(1, 2, 0, 3)); + Vector128 shuffled = Unsafe.As, Vector128>(ref result); + Unsafe.As>(ref _buffer[0]) = Vec3.FromVector128Unsafe(shuffled); + } else if (Unsafe.SizeOf() == 8) + { + Vector256 source = value.AsVector256Unsafe(); + Vector256 bits = Unsafe.As, Vector256>(ref source); + Vector256 result = Vector256.Shuffle(bits, Vector256.Create(1L, 2L, 0L, + 3L)); + Vector256 shuffled = Unsafe.As, Vector256>(ref result); + Unsafe.As>(ref _buffer[0]) = Vec3.FromVector256Unsafe(shuffled); + } else + { + throw GraphicVector.ThrowUnsupportedTypeException(); + } W = w; } } @@ -86,7 +163,7 @@ namespace Nitload.Mathematics.Numeric.Graphics public ReadOnlySpan 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 product = Vec4.FromVector128Unsafe(this.AsVector128Unsafe() * right.AsVector128Unsafe()); return product.X + product.Y + product.Z + product.W; - } - if (Unsafe.SizeOf() == 8) + } else if (Unsafe.SizeOf() == 8) { Vec4 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 v) && (v == this); } - public static Vec4 FromSpan( - ReadOnlySpan span - ) - { - if (span.Length < 4) { - throw new ArgumentException("Span length must be at least 4.", nameof(span)); - } - - Unsafe.SkipInit(out Vec4 result); - Span target = MemoryMarshal.CreateSpan(ref result.X, 4); - span[..4].CopyTo(target); - return result; - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlySpan.Enumerator GetEnumerator() { @@ -139,16 +201,41 @@ namespace Nitload.Mathematics.Numeric.Graphics return HashCode.Combine(X, Y, Z, W); } + public Vec4 Shuffle( + int t0, + int t1, + int t2, + int t3 + ) + { + if (Unsafe.SizeOf() == 4) + { + Vector128 v = this.AsVector128Unsafe(); + Vector128 bits = Unsafe.As, Vector128>(ref v); + Vector128 result = Vector128.Shuffle(bits, Vector128.Create(t0, t1, t2, t3)); + return Vec4.FromVector128Unsafe(Unsafe.As, Vector128>(ref result)); + } else if (Unsafe.SizeOf() == 8) + { + Vector256 v = this.AsVector256Unsafe(); + Vector256 bits = Unsafe.As, Vector256>(ref v); + Vector256 result = Vector256.Shuffle(bits, Vector256.Create(t0, t1, t2, t3)); + return Vec4.FromVector256Unsafe(Unsafe.As, Vector256>(ref result)); + } else + { + throw GraphicVector.ThrowUnsupportedTypeException(); + } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vec4 operator -( Vec4 left, Vec4 right ) { - if (Unsafe.SizeOf() == 4) { + if (Unsafe.SizeOf() == 4) + { return Vec4.FromVector128Unsafe(left.AsVector128Unsafe() - right.AsVector128Unsafe()); - } - if (Unsafe.SizeOf() == 8) { + } else if (Unsafe.SizeOf() == 8) { return Vec4.FromVector256Unsafe(left.AsVector256Unsafe() - right.AsVector256Unsafe()); } throw GraphicVector.ThrowUnsupportedTypeException(); @@ -168,10 +255,10 @@ namespace Nitload.Mathematics.Numeric.Graphics T scalar ) { - if (Unsafe.SizeOf() == 4) { + if (Unsafe.SizeOf() == 4) + { return Vec4.FromVector128Unsafe(vector.AsVector128Unsafe() * Vector128.Create(scalar)); - } - if (Unsafe.SizeOf() == 8) { + } else if (Unsafe.SizeOf() == 8) { return Vec4.FromVector256Unsafe(vector.AsVector256Unsafe() * Vector256.Create(scalar)); } throw GraphicVector.ThrowUnsupportedTypeException(); @@ -186,6 +273,14 @@ namespace Nitload.Mathematics.Numeric.Graphics return vector * scalar; } + public static Vec4 operator *( + GMatrix44 mat, + Vec4 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 left, @@ -201,10 +296,10 @@ namespace Nitload.Mathematics.Numeric.Graphics T scalar ) { - if (Unsafe.SizeOf() == 4) { + if (Unsafe.SizeOf() == 4) + { return Vec4.FromVector128Unsafe(vector.AsVector128Unsafe() / Vector128.Create(scalar)); - } - if (Unsafe.SizeOf() == 8) { + } else if (Unsafe.SizeOf() == 8) { return Vec4.FromVector256Unsafe(vector.AsVector256Unsafe() / Vector256.Create(scalar)); } throw GraphicVector.ThrowUnsupportedTypeException(); @@ -216,10 +311,10 @@ namespace Nitload.Mathematics.Numeric.Graphics Vec4 right ) { - if (Unsafe.SizeOf() == 4) { + if (Unsafe.SizeOf() == 4) + { return Vec4.FromVector128Unsafe(left.AsVector128Unsafe() + right.AsVector128Unsafe()); - } - if (Unsafe.SizeOf() == 8) { + } else if (Unsafe.SizeOf() == 8) { return Vec4.FromVector256Unsafe(left.AsVector256Unsafe() + right.AsVector256Unsafe()); } throw GraphicVector.ThrowUnsupportedTypeException(); @@ -230,10 +325,10 @@ namespace Nitload.Mathematics.Numeric.Graphics Vec4 right ) { - if (Unsafe.SizeOf() == 4) { + if (Unsafe.SizeOf() == 4) + { return left.AsVector128Unsafe() == right.AsVector128Unsafe(); - } - if (Unsafe.SizeOf() == 8) { + } else if (Unsafe.SizeOf() == 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; + + } + } } diff --git a/src/Nitload.RegularAnalysis/Text/TextRegexSourceGen.ExitLabel.cs b/src/Nitload.RegularAnalysis/Text/TextRegexSourceGen.ExitLabel.cs new file mode 100644 index 00000000..9be0c251 --- /dev/null +++ b/src/Nitload.RegularAnalysis/Text/TextRegexSourceGen.ExitLabel.cs @@ -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; } + + } + + } +} diff --git a/src/Nitload.RegularAnalysis/Text/TextRegexSourceGen.GenClass.cs b/src/Nitload.RegularAnalysis/Text/TextRegexSourceGen.GenClass.cs index 7248cf27..a5cdebcb 100644 --- a/src/Nitload.RegularAnalysis/Text/TextRegexSourceGen.GenClass.cs +++ b/src/Nitload.RegularAnalysis/Text/TextRegexSourceGen.GenClass.cs @@ -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(); + // 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 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,34 +477,53 @@ namespace Nitload.RegularAnalysis.Text IReadOnlyList 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)} ||"); - for (int i = 1; i < charset.Count - 1; i++) + .AppendLine($"for(; {additional_count} < {max}; {additional_count} ++)") + .AppendLine("{"); + if (charset.Count == 1) { - _set = charset[i]; - _ = sc.AppendLine($" {GenerateCharSetExpression(_set)} ||"); + // 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 : ')')}"); } - _set = charset[^1]; - _ = sc.AppendLine($" {GenerateCharSetExpression(_set)} ){(accept ? string.Empty : ')')}") - .AppendLine("{") - .AppendLine($@"{context.RemainSpan} = {context.RemainSpan}.Slice(1);") - .AppendLine($@"break;") - .AppendLine("}"); + _ = 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("}"); } private static void GenerateUnitSpanCount( @@ -508,7 +532,8 @@ namespace Nitload.RegularAnalysis.Text int max, bool is_greedy, [NotNull] in SequenceEmitter 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: diff --git a/src/Nitload.RegularAnalysis/Text/TextRegexSourceGen.GenContext.cs b/src/Nitload.RegularAnalysis/Text/TextRegexSourceGen.GenContext.cs index 5c594c7c..fd860735 100644 --- a/src/Nitload.RegularAnalysis/Text/TextRegexSourceGen.GenContext.cs +++ b/src/Nitload.RegularAnalysis/Text/TextRegexSourceGen.GenContext.cs @@ -26,8 +26,8 @@ namespace Nitload.RegularAnalysis.Text /// /// 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. /// internal sealed class SourceGenContext { @@ -40,8 +40,6 @@ namespace Nitload.RegularAnalysis.Text private int _scratch_scope_count; - private readonly Stack _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); - } - } } diff --git a/src/Nitload.RegularAnalysis/Text/TextRegexSourceGen.GenFile.cs b/src/Nitload.RegularAnalysis/Text/TextRegexSourceGen.GenFile.cs index 1eb88613..3bb41635 100644 --- a/src/Nitload.RegularAnalysis/Text/TextRegexSourceGen.GenFile.cs +++ b/src/Nitload.RegularAnalysis/Text/TextRegexSourceGen.GenFile.cs @@ -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(" "); diff --git a/tools/Nitload.GenerateGL/Generation/GlOverloadApiFilter.cs b/tools/Nitload.GenerateGL/Generation/GlOverloadApiFilter.cs index f9783252..6f1729af 100644 --- a/tools/Nitload.GenerateGL/Generation/GlOverloadApiFilter.cs +++ b/tools/Nitload.GenerateGL/Generation/GlOverloadApiFilter.cs @@ -232,13 +232,13 @@ namespace StgSharp.GenerateGL.Generation List singleParameters = new List(prefix) { new ManagedParameterDefinition("bool", "transpose", transposeSource), - new ManagedParameterDefinition("GraphicsMatrix", "value", valueSource), + new ManagedParameterDefinition("GMatrix44", "value", valueSource), }; List spanParameters = new List(prefix) { new ManagedParameterDefinition("bool", "transpose", transposeSource), new ManagedParameterDefinition( - "ReadOnlySpan", + "ReadOnlySpan>", "values", valueSource), }; diff --git a/tools/Nitload.GenerateGL/Generation/OpenGlGenerator.cs b/tools/Nitload.GenerateGL/Generation/OpenGlGenerator.cs index 40dc9334..0755f5b1 100644 --- a/tools/Nitload.GenerateGL/Generation/OpenGlGenerator.cs +++ b/tools/Nitload.GenerateGL/Generation/OpenGlGenerator.cs @@ -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* __value = "); builder.Append(matrixName); builder.Append(")\n"); builder.Append(" {\n"); diff --git a/tools/Nitload.GenerateGL/README.md b/tools/Nitload.GenerateGL/README.md index 9633f44d..c825d52c 100644 --- a/tools/Nitload.GenerateGL/README.md +++ b/tools/Nitload.GenerateGL/README.md @@ -92,7 +92,7 @@ The generator merges a family only when it can validate the resulting signatures | `glUniform1*v` | `Uniform(..., ReadOnlySpan)` | | `glUniform4*v` | `Uniform(..., ReadOnlySpan>)` | | `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)` 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)` | | `glVertexAttrib1f/2f/3f/4f` and equivalent scalar forms | `VertexAttribute(...)`; component count is expressed by the parameter list |