diff --git a/StgSharp.Common/HighPerformance/MatrixKernel.cs b/StgSharp.Common/HighPerformance/MatrixKernel.cs index 4535487f..1b5adb73 100644 --- a/StgSharp.Common/HighPerformance/MatrixKernel.cs +++ b/StgSharp.Common/HighPerformance/MatrixKernel.cs @@ -44,6 +44,8 @@ namespace StgSharp.HighPerformance public unsafe struct MatrixKernel where T : unmanaged, INumber { + public static readonly int Size = 16 * sizeof(T); + private T c0r0; public MatrixKernel() @@ -58,10 +60,10 @@ namespace StgSharp.HighPerformance } } - public ref T this[int column, int row] + public ref T this[int row, int column] { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => ref Unsafe.Add(ref c0r0, (column * 4) + row); + get => ref Unsafe.Add(ref c0r0, (row * 4) + column); } } diff --git a/StgSharp.Common/Mathematics/Linear/CoordinationNaming.md b/StgSharp.Common/Mathematics/Linear/CoordinationNaming.md new file mode 100644 index 00000000..1f1cc175 --- /dev/null +++ b/StgSharp.Common/Mathematics/Linear/CoordinationNaming.md @@ -0,0 +1,88 @@ +# Matrix Coordinate & Naming Conventions (StgSharp) + +This document defines the coordinate terminology and naming rules used across `Matrix`, `MatrixKernel`, and packed/triangular storage layouts. +Goal: eliminate ambiguity around `column`/`row` names (e.g., “index **of** a column” vs “index **along** a column”). + +--- + +## 1) The key rule: encode prepositions into identifiers (`Of` vs `In`) + +### `...OfX` — “which X” (object identity / ordinal) +Use **`Of`** when the value identifies **which object** (which column, which row, which kernel, etc.). + +Examples: +- `columnOfElement`: the element is located in **which column** +- `rowOfKernel`: the kernel block is located in **which row** + +### `...InX` / `...WithinX` — “inside X” (local coordinate) +Use **`In`** (or `Within`) when the value is a **local coordinate inside** another object. + +Examples: +- `columnInKernel`: local column coordinate **inside** a kernel block +- `rowInKernel`: local row coordinate **inside** a kernel block + +> Quick mental model: **`Of` = identity**, **`In` = inside**. + +--- + +## 2) Coordinate levels: `Element`, `KernelGrid`, `InKernel` + +StgSharp commonly uses three coordinate levels: + +1. **Element-level**: final matrix element coordinates (`Matrix[col,row]`) +2. **Kernel-grid level**: coordinates of a kernel block in the kernel grid +3. **In-kernel level**: local element coordinates within a kernel (e.g., 4×4) + +Recommended names: + +| Level | Column name | Row name | Meaning | +|---|---|---|---| +| Element | `columnOfElement` | `rowOfElement` | element located in which column/row (0-based) | +| Kernel grid | `columnOfKernel` | `rowOfKernel` | kernel block located in which kernel-column/kernel-row (0-based) | +| In-kernel | `columnInKernel` | `rowInKernel` | local coordinate inside the kernel (0..KernelSize-1) | + +--- + +## 3) Index base: 0-based (mandatory) + +Unless explicitly documented otherwise, all coordinates are **0-based**: + +- `columnOfElement ∈ [0, ColumnLength-1]` +- `rowOfElement ∈ [0, RowLength-1]` +- `columnOfKernel ∈ [0, KernelColumnLength-1]` +- `rowOfKernel ∈ [0, KernelRowLength-1]` +- `columnInKernel ∈ [0, KernelSize-1]` +- `rowInKernel ∈ [0, KernelSize-1]` + +--- + +## 4) Mapping element coordinates to kernel coordinates (KernelSize = 4 example) + +For a fixed kernel size `KernelSize = 4`: + +```csharp +int columnOfKernel = columnOfElement / 4; +int rowOfKernel = rowOfElement / 4; + +int columnInKernel = columnOfElement % 4; +int rowInKernel = rowOfElement % 4; +``` + +If `columnOfElement` and `rowOfElement` are guaranteed non-negative, bit operations can be used: + +```csharp +int columnOfKernel = columnOfElement >> 2; +int rowOfKernel = rowOfElement >> 2; + +int columnInKernel = columnOfElement & 3; +int rowInKernel = rowOfElement & 3; +``` + +--- + +## 5) Packed storage: distinguish `Index` from `Offset` + +Packed layouts do **not** store “empty blocks”; stored blocks are placed contiguously in a packed buffer. + +### Use the correct terms +- **`packedKernelIndex`**: “the N-th kernel diff --git a/StgSharp.Common/Mathematics/Linear/Matrix.Create.cs b/StgSharp.Common/Mathematics/Linear/Matrix.Create.cs new file mode 100644 index 00000000..507672d5 --- /dev/null +++ b/StgSharp.Common/Mathematics/Linear/Matrix.Create.cs @@ -0,0 +1,104 @@ +//----------------------------------------------------------------------- +// ----------------------------------------------------------------------- +// file="Matrix.Create" +// Project: StgSharp +// AuthorGroup: Nitload +// Copyright (c) Nitload. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// ----------------------------------------------------------------------- +// ----------------------------------------------------------------------- +using StgSharp.HighPerformance; +using StgSharp.HighPerformance.Memory; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading.Tasks; + +namespace StgSharp.Mathematics.Numeric +{ + public unsafe partial class Matrix + { + + private const int KernelSideLength = 4; + + public static Matrix Create( + int columnLength, + int rowLength, + MatrixLayout layout, + HybridLayerSegregatedFitAllocator allocator) + { + ArgumentNullException.ThrowIfNull(allocator); + + ArgumentOutOfRangeException.ThrowIfNegativeOrZero(columnLength); + + ArgumentOutOfRangeException.ThrowIfNegativeOrZero(rowLength); + + int kernelColumns = DivideRoundUp(columnLength, KernelSideLength); + int kernelRows = DivideRoundUp(rowLength, KernelSideLength); + + if (layout is MatrixLayout.UpperTriangle or MatrixLayout.LowerTriangle) + { + if (kernelColumns != kernelRows) { + throw new ArgumentException("Triangular layouts require square matrices."); + } + } + + long kernelCount = layout switch + { + MatrixLayout.DenseRectangle => (long)kernelColumns * kernelRows, + MatrixLayout.UpperTriangle => TriangularKernelCount(kernelColumns), + MatrixLayout.LowerTriangle => TriangularKernelCount(kernelRows), + _ => throw new ArgumentOutOfRangeException(nameof(layout)) + }; + + long requiredBytes = kernelCount * MatrixKernel.Size; + if (requiredBytes <= 0 || requiredBytes > uint.MaxValue) { + throw new ArgumentOutOfRangeException(nameof(requiredBytes), "Requested matrix exceeds allocator capacity."); + } + + HybridLayerSegregatedFitAllocationHandle handle = allocator.Alloc((uint)requiredBytes); + MatrixStorageHLSF storage = new MatrixStorageHLSF(allocator, handle); + + Matrix matrix = new Matrix(MatrixKernelBoarder.Create(layout), new MatrixSize(columnLength, + rowLength, + kernelColumns, + kernelRows), storage); + + return matrix; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int DivideRoundUp(int value, int divisor) + { + return (value + (divisor - 1)) / divisor; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static long TriangularKernelCount(int order) + { + long n = order; + return (n * (n + 1L)) / 2L; + } + + } +} diff --git a/StgSharp.Common/Mathematics/Linear/Matrix.cs b/StgSharp.Common/Mathematics/Linear/Matrix.cs index 5738ecca..26bfd118 100644 --- a/StgSharp.Common/Mathematics/Linear/Matrix.cs +++ b/StgSharp.Common/Mathematics/Linear/Matrix.cs @@ -25,59 +25,140 @@ // // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- +using StgSharp.HighPerformance; +using StgSharp.Mathematics.Numeric; using System; -using System.Collections.Generic; -using System.Linq; using System.Numerics; using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; -using hlsfAllocator = global::StgSharp.HighPerformance.Memory.HybridLayerSegregatedFitAllocator; +// using hlsfHandle = global::StgSharp.HighPerformance.Memory.HybridLayerSegregatedFitAllocationHandle; namespace StgSharp.Mathematics.Numeric { - public static class Matrix + public unsafe partial class Matrix where T : unmanaged, INumber { - public static hlsfAllocator? DefaultAllocator + private protected static readonly int t_count = 16 / sizeof(T); + + private protected static readonly int t_size = sizeof(T); + private readonly MatrixKernelBoarder _boarder; + private readonly MatrixSize _size; + private readonly MatrixStorage _buffer; + + private protected Matrix( + MatrixKernelBoarder boarder, + MatrixSize size, + MatrixStorage buffer + + ) + { + _boarder = boarder; + _size = size; + _buffer = buffer; + } + + public T this[int x, int y] { get { - ArgumentNullException.ThrowIfNull(field, nameof(DefaultAllocator)); - return null; + if (y < 0 || y > _size.ElementColumnLength || x < 0 || x > _size.ElementRowLength) { + throw new ArgumentOutOfRangeException($"Index [{x},{y}] is out of matrix index range."); + } + + int + k_c = y / 4, + k_r = x / 4, + c = y % 4, + r = x % 4; + ref MatrixKernel kernel = ref GetMatrixKernel(k_c, k_r); + return Unsafe.IsNullRef(ref kernel) ? T.Zero : kernel[c, r]; } - set; - } = null; - - public static MatrixAllocation DefaultAllocation { get; set; } = MatrixAllocation.GC; - - public static Matrix FromDefault(int columnLength, int rowLength) - where T : unmanaged, INumber - { - return DefaultAllocation switch + set { - MatrixAllocation.GC => FromGC(columnLength, rowLength), - MatrixAllocation.HLSF => FromHlsf(columnLength, rowLength, DefaultAllocator!), - _ => throw new NotSupportedException("This allocation is not supported."), - }; + if (y < 0 || y > _size.ElementColumnLength || x < 0 || x > _size.ElementRowLength) { + throw new ArgumentOutOfRangeException($"Index [{x},{y}] is out of matrix index range."); + } + + int + k_c = y / 4, + k_r = x / 4, + c = y % 4, + r = x % 4; + ref MatrixKernel kernel = ref GetMatrixKernel(k_c, k_r); + if (!Unsafe.IsNullRef(ref kernel)) { + kernel[c, r] = value; + } + } } - public static Matrix FromGC(int columnLength, int rowLength) - where T : unmanaged, INumber + /// + /// Matlab style indexer to generate a new matrix + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public unsafe Matrix this[ + ReadOnlySpan column, + ReadOnlySpan row] { - return new GCMatrix(columnLength, rowLength); + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + + /// + /// Length of the matrix in columns. + /// + public int ColumnLength => _size.ElementColumnLength; + + /// + /// Length of the matrix in rows. + /// + public int RowLength => _size.ElementRowLength; + + public MatrixLayout Layout { get; init; } + + internal MatrixKernel* Buffer + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => (MatrixKernel*)_buffer.BufferPointer; + } + + protected internal int KernelColumnLength => _size.KernelColumnLength; + + protected internal int KernelRowLength => _size.KernelRowLength; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public unsafe ref MatrixKernel GetMatrixKernel(int x, int y) + { + MatrixKernelEnumerator enumerator = new(_size.KernelColumnLength, _size.KernelRowLength, + x, y); + return ref _boarder.IsInBuffer(x, y, in enumerator) ? + ref _buffer[_boarder.GetIndexOffset(x, y, in enumerator)] : + ref Unsafe.NullRef>(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Matrix FromHlsf( - int columnLength, - int rowLength, - hlsfAllocator allocator) - where T : unmanaged, INumber + internal unsafe ref T GetElementUnsafe(int x, int y) { - ArgumentNullException.ThrowIfNull(allocator, nameof(allocator)); - return new HlsfMatrix(columnLength, rowLength, allocator); + // Caller guarantees: indices in range, layout is dense square. + int k_c = y >> 2; + int k_r = x >> 2; + int c = y & 3; + int r = x & 3; + + MatrixKernelEnumerator enumerator = new(_size.KernelColumnLength, _size.KernelRowLength, + k_c, k_r); + ref MatrixKernel kernel = ref _buffer[_boarder.GetIndexOffset(k_c, k_r, in enumerator)]; + return ref kernel[c, r]; } } diff --git a/StgSharp.Common/Mathematics/Linear/MatrixMetadata.cs b/StgSharp.Common/Mathematics/Linear/MatrixMetadata.cs new file mode 100644 index 00000000..253710cd --- /dev/null +++ b/StgSharp.Common/Mathematics/Linear/MatrixMetadata.cs @@ -0,0 +1,234 @@ +//----------------------------------------------------------------------- +// ----------------------------------------------------------------------- +// file="MatrixMetadata" +// Project: StgSharp +// AuthorGroup: Nitload +// Copyright (c) Nitload. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// ----------------------------------------------------------------------- +// ----------------------------------------------------------------------- +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace StgSharp.Mathematics.Numeric +{ + public enum MatrixLayout + { + + DenseRectangle, + UpperTriangle, + LowerTriangle, + + } + + public abstract class MatrixKernelBoarder + { + + private static readonly MatrixKernelBoarder DenseSquareInstance = new DenseSquareKernelBoarder(); + private static readonly MatrixKernelBoarder LowerTriangleInstance = new LowerTriangleKernelBoarder(); + private static readonly MatrixKernelBoarder UpperTriangleInstance = new UpperTriangleKernelBoarder(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static MatrixKernelBoarder Create(MatrixLayout layout) + { + return layout switch + { + MatrixLayout.DenseRectangle => DenseSquareInstance, + MatrixLayout.UpperTriangle => UpperTriangleInstance, + MatrixLayout.LowerTriangle => LowerTriangleInstance, + _ => throw new ArgumentOutOfRangeException(nameof(layout)), + }; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public abstract long GetIndexOffset( + int xKernel, + int yKernel, + in MatrixKernelEnumerator enumerator); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public abstract bool IsInBuffer( + int xKernel, + int yKernel, + in MatrixKernelEnumerator enumerator); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected static long GetTriangularOrder(in MatrixKernelEnumerator enumerator) + { + return Math.Min(enumerator.KernelColumnLength, enumerator.KernelRowLength); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected static bool IsWithinKernelDomain( + in MatrixKernelEnumerator enumerator, + int xKernel, + int yKernel) + { + return xKernel >= 0 && + yKernel >= 0 && + xKernel < enumerator.KernelColumnLength && + yKernel < enumerator.KernelRowLength; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + protected static bool IsWithinTriangularDomain( + in MatrixKernelEnumerator enumerator, + int xKernel, + int yKernel) + { + long order = GetTriangularOrder(enumerator); + return xKernel >= 0 && yKernel >= 0 && xKernel < order && yKernel < order; + } + + private sealed class DenseSquareKernelBoarder : MatrixKernelBoarder + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override long GetIndexOffset( + int xKernel, + int yKernel, + in MatrixKernelEnumerator enumerator) + { + long x = xKernel; + long y = yKernel; + long rows = enumerator.KernelRowLength; + return x * rows + y; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override bool IsInBuffer( + int xKernel, + int yKernel, + in MatrixKernelEnumerator enumerator) + { + return IsWithinKernelDomain(enumerator, xKernel, yKernel); + } + + } + + private sealed class LowerTriangleKernelBoarder : MatrixKernelBoarder + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override long GetIndexOffset( + int xKernel, + int yKernel, + in MatrixKernelEnumerator enumerator) + { + long order = GetTriangularOrder(enumerator); + long x = xKernel; + long y = yKernel; + + long prefixColumns = x * order - (x * (x - 1L)) / 2L; + return prefixColumns + (y - x); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override bool IsInBuffer( + int xKernel, + int yKernel, + in MatrixKernelEnumerator enumerator) + { + return IsWithinTriangularDomain(enumerator, xKernel, yKernel) && yKernel >= xKernel; + } + + } + + private sealed unsafe class UpperTriangleKernelBoarder : MatrixKernelBoarder + { + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override long GetIndexOffset( + int xKernel, + int yKernel, + in MatrixKernelEnumerator enumerator) + { + long x = xKernel; + long y = yKernel; + + long prefixColumns = (x * (x + 1L)) / 2L; + return prefixColumns + y; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override bool IsInBuffer( + int xKernel, + int yKernel, + in MatrixKernelEnumerator enumerator) + { + return IsWithinTriangularDomain(enumerator, xKernel, yKernel) && yKernel <= xKernel; + } + + } + + } + + [StructLayout(LayoutKind.Explicit)] + public struct MatrixSize + { + + [FieldOffset(0)] public readonly int ElementColumnLength; + [FieldOffset(4)] public readonly int ElementRowLength; + + [FieldOffset(8)] public readonly int KernelColumnLength; + [FieldOffset(12)] public readonly int KernelRowLength; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public MatrixSize( + int elementColumnLength, + int elementRowLength, + int kernelColumnLength, + int kernelRowLength) + { + ElementColumnLength = elementColumnLength; + ElementRowLength = elementRowLength; + KernelColumnLength = kernelColumnLength; + KernelRowLength = kernelRowLength; + } + + } + + [StructLayout(LayoutKind.Explicit)] + public struct MatrixKernelEnumerator + { + + [FieldOffset(0)] public int CurrentColumn; + [FieldOffset(4)] public int CurrentRow; + + [FieldOffset(8)] public readonly int KernelColumnLength; + [FieldOffset(12)] public readonly int KernelRowLength; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public MatrixKernelEnumerator( + int kernelColumnLength, + int kernelRowLength, + int currentColumn = 0, + int currentRow = 0) + { + CurrentColumn = currentColumn; + CurrentRow = currentRow; + KernelColumnLength = kernelColumnLength; + KernelRowLength = kernelRowLength; + } + + } +} diff --git a/StgSharp.Common/Mathematics/Linear/MatrixEnum.cs b/StgSharp.Common/Mathematics/Linear/MatrixStorage.cs similarity index 55% rename from StgSharp.Common/Mathematics/Linear/MatrixEnum.cs rename to StgSharp.Common/Mathematics/Linear/MatrixStorage.cs index 4c0aee51..6df883fd 100644 --- a/StgSharp.Common/Mathematics/Linear/MatrixEnum.cs +++ b/StgSharp.Common/Mathematics/Linear/MatrixStorage.cs @@ -1,6 +1,6 @@ -//----------------------------------------------------------------------- +//----------------------------------------------------------------------- // ----------------------------------------------------------------------- -// file="MatrixEnum" +// file="MatrixStorage" // Project: StgSharp // AuthorGroup: Nitload // Copyright (c) Nitload. All rights reserved. @@ -25,19 +25,48 @@ // // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- +using StgSharp.HighPerformance; +using StgSharp.HighPerformance.Memory; using System; using System.Collections.Generic; using System.Linq; +using System.Numerics; +using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; +using HLSFAllocator = global::StgSharp.HighPerformance.Memory.HybridLayerSegregatedFitAllocator; +using HLSFHandle = global::StgSharp.HighPerformance.Memory.HybridLayerSegregatedFitAllocationHandle; + namespace StgSharp.Mathematics.Numeric { - public enum MatrixAllocation + public abstract class MatrixStorage : IDisposable where T : unmanaged, INumber { - HLSF, - GC, + internal unsafe ref MatrixKernel this[long index] + { + get { return ref Unsafe.AsRef>(BufferPointer + MatrixKernel.Size * index); } + } + + protected internal abstract unsafe T* BufferPointer { get; } + + public abstract void Dispose(); + + } + + internal class MatrixStorageHLSF(HLSFAllocator allocator, HLSFHandle handle) : MatrixStorage + where T : unmanaged, INumber + { + + internal HLSFAllocator _allocator = allocator; + internal HLSFHandle _handle = handle; + + protected internal override unsafe T* BufferPointer => (T*)_handle.Pointer; + + public override void Dispose() + { + allocator.Free(_handle); + } } } diff --git a/StgSharp.Common/Mathematics/Linear/Matrix_T.GC.cs b/StgSharp.Common/Mathematics/Linear/Matrix_T.GC.cs deleted file mode 100644 index 5d971427..00000000 --- a/StgSharp.Common/Mathematics/Linear/Matrix_T.GC.cs +++ /dev/null @@ -1,124 +0,0 @@ -//----------------------------------------------------------------------- -// ----------------------------------------------------------------------- -// file="Matrix_T.GC" -// Project: StgSharp -// AuthorGroup: Nitload -// Copyright (c) Nitload. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -// ----------------------------------------------------------------------- -// ----------------------------------------------------------------------- -using StgSharp.HighPerformance; -using StgSharp.Mathematics; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Numerics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace StgSharp.Mathematics.Numeric -{ - internal unsafe partial class GCMatrix : Matrix where T : unmanaged, INumber - { - - private readonly MatrixKernel* _buffer; - - public GCMatrix(int column, int row) - { - KernelColumnLength = (column + 3) / 4; - KernelRowLength = (row + 3) / t_count; - ColumnLength = column; - RowLength = row; - _buffer = (MatrixKernel*)NativeMemory.AlignedAlloc((nuint)(column * row * sizeof(T)), (nuint)World.DefaultSIMDAlignment); - } - - public override ref T this[int column, int row] - { - get - { - AssertIndex(column, row); - int kernelColumn = column / 4, c = column % 4; - int kernelRow = row / t_count, r = row % t_count; - ref MatrixKernel kernel = ref _buffer[kernelColumn + KernelColumnLength * kernelRow]; - return ref kernel[c, r]; - } - } - - public override Matrix this[ReadOnlySpan column, ReadOnlySpan row] - { - get => throw new NotImplementedException(); - set => throw new NotImplementedException(); - } - - internal override unsafe MatrixKernel* Buffer - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => _buffer; - } - - public override unsafe ref MatrixKernel GetMatrixKernel(int column, int row) - { - AssertIndex(column, row); - int kernelColumn = column / 4; - int kernelRow = row / t_count; - return ref _buffer[kernelColumn + (KernelColumnLength * kernelRow)]; - } - - public override ref T UnsafeIndex(int column, int row) - { - int kernelColumn = column / 4, c = column % 4; - int kernelRow = row / t_count, r = row % t_count; - ref MatrixKernel kernel = ref _buffer[kernelColumn + (KernelColumnLength * kernelRow)]; - return ref kernel[c, r]; - } - - ~GCMatrix() - { - NativeMemory.AlignedFree(_buffer); - } - - #region enumeration - - public override unsafe MatrixSegmentEnumeration ColumnEnumeration - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => new MatrixSegmentEnumeration(_buffer, KernelColumnLength, KernelColumnLength * KernelRowLength, 1, - KernelColumnLength); - } - - public override unsafe MatrixSegmentEnumeration GetRowEnumeration() - { - return new MatrixSegmentEnumeration(_buffer, 1, KernelColumnLength, KernelColumnLength, KernelRowLength); - } - - public override unsafe MatrixSegmentEnumeration SequentialEnumeration - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => new MatrixSegmentEnumeration(_buffer, KernelRowLength * KernelColumnLength, - KernelColumnLength * KernelRowLength, 1, - KernelRowLength * KernelColumnLength); - } - - #endregion - } -} diff --git a/StgSharp.Common/Mathematics/Linear/Matrix_T.HLSF.cs b/StgSharp.Common/Mathematics/Linear/Matrix_T.HLSF.cs deleted file mode 100644 index c0b28d22..00000000 --- a/StgSharp.Common/Mathematics/Linear/Matrix_T.HLSF.cs +++ /dev/null @@ -1,137 +0,0 @@ -//----------------------------------------------------------------------- -// ----------------------------------------------------------------------- -// file="Matrix_T.HLSF" -// Project: StgSharp -// AuthorGroup: Nitload -// Copyright (c) Nitload. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -// ----------------------------------------------------------------------- -// ----------------------------------------------------------------------- -using StgSharp.HighPerformance; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Numerics; -using System.Runtime.CompilerServices; -using System.Text; -using System.Threading.Tasks; - -using hlsfAllocator = global::StgSharp.HighPerformance.Memory.HybridLayerSegregatedFitAllocator; -using hlsfHandle = global::StgSharp.HighPerformance.Memory.HybridLayerSegregatedFitAllocationHandle; - -namespace StgSharp.Mathematics.Numeric -{ - internal unsafe partial class HlsfMatrix : Matrix where T : unmanaged, INumber - { - - private readonly MatrixKernel* k_buffer; - private readonly hlsfAllocator allocator; - private readonly hlsfHandle handle; - - internal HlsfMatrix(int column, int row, hlsfAllocator allocator) - { - KernelColumnLength = (column + 3) / 4; - KernelRowLength = (row + 3) / t_count; - ColumnLength = column; - RowLength = row; - long size = (long)KernelColumnLength * (long)KernelRowLength * (long)sizeof(MatrixKernel); - this.handle = allocator.Alloc((uint)(size)); - if (handle.AllocSize < size) { - throw new InsufficientMemoryException(); - } - k_buffer = (MatrixKernel*)handle.Pointer; - } - - public override ref T this[int column, int row] - { - get - { - AssertIndex(column, row); - int kernelColumn = column / 4, c = column % 4; - int kernelRow = row / t_count, r = row % t_count; - ref MatrixKernel kernel = ref k_buffer[(kernelColumn * kernelColumn) + kernelRow]; - return ref kernel[c, r]; - } - } - - public override Matrix this[ - ReadOnlySpan column, - ReadOnlySpan row] - { - get => throw new NotImplementedException(); - set => throw new NotImplementedException(); - } - - internal override unsafe MatrixKernel* Buffer - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => k_buffer; - } - - public override unsafe ref MatrixKernel GetMatrixKernel(int column, int row) - { - AssertIndex(column, row); - int kernelColumn = column / 4, c = column % 4; - int kernelRow = row / t_count, r = row % t_count; - return ref k_buffer[(kernelColumn * kernelColumn) + kernelRow]; - } - - public override ref T UnsafeIndex(int column, int row) - { - int kernelColumn = column / 4, c = column % 4; - int kernelRow = row / t_count, r = row % t_count; - ref MatrixKernel kernel = ref k_buffer[(kernelColumn * kernelColumn) + kernelRow]; - return ref kernel[c, r]; - } - - ~HlsfMatrix() - { - allocator.Free(handle); - } - - #region enumeration - - public override unsafe MatrixSegmentEnumeration ColumnEnumeration - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => new MatrixSegmentEnumeration(k_buffer, KernelColumnLength, - KernelColumnLength * KernelRowLength, 1, - KernelColumnLength); - } - - public override unsafe MatrixSegmentEnumeration GetRowEnumeration() - { - return new MatrixSegmentEnumeration(k_buffer, 1, KernelColumnLength, - KernelColumnLength, KernelRowLength); - } - - public override unsafe MatrixSegmentEnumeration SequentialEnumeration - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - - get => new MatrixSegmentEnumeration(k_buffer, KernelRowLength * KernelColumnLength, - KernelColumnLength * KernelRowLength, 1, - KernelRowLength * KernelColumnLength); - } - - #endregion - } -} diff --git a/StgSharp.Common/Mathematics/Linear/Matrix_T.cs b/StgSharp.Common/Mathematics/Linear/Matrix_T.cs deleted file mode 100644 index 3d1e3cff..00000000 --- a/StgSharp.Common/Mathematics/Linear/Matrix_T.cs +++ /dev/null @@ -1,218 +0,0 @@ -//----------------------------------------------------------------------- -// ----------------------------------------------------------------------- -// file="Matrix_T" -// Project: StgSharp -// AuthorGroup: Nitload -// Copyright (c) Nitload. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -// -// ----------------------------------------------------------------------- -// ----------------------------------------------------------------------- -using StgSharp.HighPerformance; -using System; -using System.Numerics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// using hlsfHandle = global::StgSharp.HighPerformance.Memory.HybridLayerSegregatedFitAllocationHandle; - -namespace StgSharp.Mathematics.Numeric -{ - public abstract unsafe partial class Matrix where T : unmanaged, INumber - { - - private protected readonly int t_count = 16 / sizeof(T); - - private protected readonly int t_size = sizeof(T); - - private protected Matrix() { } - - public abstract ref T this[int column, int row] - { - get; - } - - public abstract unsafe Matrix this[ReadOnlySpan column, ReadOnlySpan row] - { - get; - set; - } - - /// - /// Length of the matrix in columns. - /// - public int ColumnLength { get; init; } - - /// - /// Length of the matrix in rows. - /// - public int RowLength { get; init; } - - public abstract MatrixSegmentEnumeration ColumnEnumeration { get; } - - public abstract MatrixSegmentEnumeration SequentialEnumeration { get; } - - internal abstract MatrixKernel* Buffer { get; } - - protected internal int KernelColumnLength { get; init; } - - protected internal int KernelRowLength { get; init; } - - public abstract ref MatrixKernel GetMatrixKernel(int column, int row); - - public abstract MatrixSegmentEnumeration GetRowEnumeration(); - - [Obsolete("This method does not contain boarder check, so be careful on size or use indexer instead.", false)] - public abstract ref T UnsafeIndex(int column, int row); - - private protected void AssertIndex(int column, int row) - { - if (column < 0 || column >= ColumnLength) { - throw new ArgumentOutOfRangeException(nameof(column)); - } - - if (row < 0 || row >= RowLength) { - throw new ArgumentOutOfRangeException(nameof(row)); - } - } - - } - - public readonly unsafe ref struct MatrixSegmentEnumeration( - MatrixKernel* source, - int primStride, - int primSize, - int secondaryStride, - int secondarySize, - int primOffset = 0, - int secondaryOffset = 0) - where T : unmanaged, INumber - { - - private readonly MatrixKernel* _source = source; - internal readonly int PrimOffset = primOffset; - - internal readonly int PrimSize = primSize; - internal readonly int PrimStride = primStride; - internal readonly int SecondaryOffset = secondaryOffset; - internal readonly int SecondarySize = secondarySize; - internal readonly int SecondaryStride = secondaryStride; - - internal readonly MatrixKernel* Source - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => _source; - } - - public Enumerator GetEnumerator() - { - return new Enumerator(in this); - } - - public ref struct Enumerator(in MatrixSegmentEnumeration enumeration) - { - - private readonly MatrixKernel* _source = enumeration._source; - private int _indexCount = -1; - private readonly int _stride = enumeration.PrimStride; - private readonly long _bound = (long)enumeration.PrimSize * enumeration.PrimStride; - private long _index = (long)enumeration.PrimOffset * enumeration.PrimStride; - - private readonly MatrixSegmentEnumeration _enumeration; - - public readonly MatrixSegment Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => new(_source + _index, _enumeration.SecondarySize, _enumeration.SecondaryStride, - _enumeration.PrimOffset); - } - - public bool MoveNext() - { - _indexCount++; - _index += _stride; - if (_index >= _bound) { - _index = 0; - } - return _indexCount >= _enumeration.PrimSize; - } - - } - - } - - public readonly unsafe ref struct MatrixSegment(MatrixKernel* source, int size, int stride, int offset) - where T : unmanaged, INumber - { - - private readonly MatrixKernel* _source = source; - private readonly int _offset = offset; - private readonly int _secondarySize = size; - private readonly int _size = size; - private readonly int _stride = stride; - - public ref MatrixKernel this[int index] - { - get - { - if (index < 0 || index >= _size) { - throw new ArgumentOutOfRangeException(nameof(index)); - } - return ref _source[index * _stride]; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Enumerator GetEnumerator() - { - return new Enumerator(in this); - } - - public ref struct Enumerator(in MatrixSegment segment) - { - - private readonly int _end = segment._size; - - private int _indexCount = -1; - private readonly long _bound = (long)segment._size * segment._stride; - private long _index = (long)segment._offset * segment._stride; - private readonly MatrixSegment _segment = segment; - - public readonly MatrixKernel* Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => _segment._source + _index; - } - - public bool MoveNext() - { - _index += _segment._stride; - _indexCount++; - if (_index >= _bound) { - _index = 0; - } - - return _indexCount < _end; - } - - } - - } -} diff --git a/StgSharp.Mathematics/Numeric/MatrixCompute.Factorize.cs b/StgSharp.Mathematics/Numeric/MatrixCompute.Factorize.cs index ebc58bdd..bc4a4d1c 100644 --- a/StgSharp.Mathematics/Numeric/MatrixCompute.Factorize.cs +++ b/StgSharp.Mathematics/Numeric/MatrixCompute.Factorize.cs @@ -38,17 +38,69 @@ namespace StgSharp.Mathematics.Numeric public static void FactorizePLU( Matrix matrix, - Matrix p, + Span pivot, Matrix lower, Matrix upper) { if (matrix.ColumnLength != matrix.RowLength) { throw new InvalidOperationException("Matrix must be square."); } + if (matrix.Layout != MatrixLayout.DenseRectangle) { + throw new NotSupportedException("Only dense square matrices are supported."); + } + int n = matrix.RowLength; + if (pivot.Length < n) { + throw new ArgumentException("Pivot span length is insufficient.", nameof(pivot)); + } + if (lower.RowLength != n || + lower.ColumnLength != n || + lower.Layout != MatrixLayout.LowerTriangle) { + throw new ArgumentException("Lower matrix must be lower-triangular with same dimensions as input.", nameof(lower)); + } + if (upper.RowLength != n || + upper.ColumnLength != n || + upper.Layout != MatrixLayout.UpperTriangle) { + throw new ArgumentException("Upper matrix must be upper-triangular with same dimensions as input.", nameof(upper)); + } + int size = matrix.KernelColumnLength * matrix.KernelRowLength; if (size < 256) { - for (int i = 0; i < matrix.KernelColumnLength; i++) { } + // Naive Doolittle-style PLU without row swaps (for illustration). + for (int i = 0; i < n; i++) + { + pivot[i] = i; // identity pivot + lower[i, i] = 1.0f; // unit diagonal for L + } + + for (int k = 0; k < n; k++) + { + // Compute U[k, j] for j >= k + for (int j = k; j < n; j++) + { + float sum = 0f; + for (int s = 0; s < k; s++) { + sum += lower[k, s] * upper[s, j]; + } + upper[k, j] = matrix[k, j] - sum; + } + + // Compute L[i, k] for i > k + for (int i = k + 1; i < n; i++) + { + float sum = 0f; + for (int s = 0; s < k; s++) { + sum += lower[i, s] * upper[s, k]; + } + float u = upper[k, k]; + if (u == 0f) { + throw new InvalidOperationException("Zero pivot encountered in demonstration PLU."); + } + lower[i, k] = (matrix.GetElementUnsafe(i, k) - sum) / u; + } + } + + // TODO: For larger kernels, consider calling native pivot helper to extract 4 pivots at once. } else if (size < 1024) { } else { } } diff --git a/StgSharp.Mathematics/Numeric/MatrixCompute.cs b/StgSharp.Mathematics/Numeric/MatrixCompute.cs index 766dbd2c..cc66b7a2 100644 --- a/StgSharp.Mathematics/Numeric/MatrixCompute.cs +++ b/StgSharp.Mathematics/Numeric/MatrixCompute.cs @@ -198,6 +198,10 @@ namespace StgSharp.Mathematics.Numeric if (left.ColumnLength != ans.ColumnLength || left.RowLength != ans.RowLength) { throw new IndexOutOfRangeException("Matrix dimensions must agree."); } + if (left.Layout != MatrixLayout.DenseRectangle || + ans.Layout != MatrixLayout.DenseRectangle) { + throw new NotSupportedException("Only dense rectangle matrices are supported."); + } long count = (long)left.KernelColumnLength * left.KernelRowLength; ScalarPacket* scalar = MatrixParallelFactory.CreateScalarPacket(); scalar->Data(0) = right; @@ -243,6 +247,11 @@ namespace StgSharp.Mathematics.Numeric left.RowLength != ans.RowLength) { throw new IndexOutOfRangeException("Matrix dimensions must agree."); } + if (left.Layout != MatrixLayout.DenseRectangle || + right.Layout != MatrixLayout.DenseRectangle || + ans.Layout != MatrixLayout.DenseRectangle) { + throw new NotSupportedException("Only dense rectangle matrices are supported."); + } long count = (long)left.KernelColumnLength * left.KernelRowLength; if (count <= 256) { diff --git a/StgSharp.Native/sn-src/k_pivot.c b/StgSharp.Native/sn-src/k_pivot.c index 6617c14b..c2b51c7b 100644 --- a/StgSharp.Native/sn-src/k_pivot.c +++ b/StgSharp.Native/sn-src/k_pivot.c @@ -2,7 +2,7 @@ // Hybrid implementation: SIMD for Abs, Scalar for Max // Assumes Column-Major layout for both MAT_KERNEL content and Kernel sequence -static void povit_float_simd_abs(MAT_KERNEL(float) const *source, size_t col_begin, +static void povit_float(MAT_KERNEL(float) const *source, size_t col_begin, size_t col_length, size_t *restrict ans) { float max_v[4] = { -1.0f, -1.0f, -1.0f, -1.0f }; @@ -62,18 +62,3 @@ static void povit_float_simd_abs(MAT_KERNEL(float) const *source, size_t col_beg } } } - -DECLARE_MAT_POVIT_PROC(float, sse) -{ - povit_float_simd_abs(source, col_begin, col_length, ans); -} - -DECLARE_MAT_POVIT_PROC(float, avx) -{ - povit_float_simd_abs(source, col_begin, col_length, ans); -} - -DECLARE_MAT_POVIT_PROC(float, 512) -{ - povit_float_simd_abs(source, col_begin, col_length, ans); -} diff --git a/StgSharpDebug/Program.cs b/StgSharpDebug/Program.cs index bbae7ad6..f21e8f8b 100644 --- a/StgSharpDebug/Program.cs +++ b/StgSharpDebug/Program.cs @@ -58,11 +58,11 @@ namespace StgSharp unchecked { hlsf = new((nuint)(64 * (ulong)10000 * 10000)); } - Matrix m = Matrix.FromHlsf(4000, 4000, hlsf); + Matrix m = Matrix.Create(4000, 4000, MatrixLayout.DenseRectangle, hlsf); MatrixCompute.Fill(m, 1.0f); - Matrix n = Matrix.FromHlsf(4000, 4000, hlsf); + Matrix n = Matrix.Create(4000, 4000, MatrixLayout.DenseRectangle, hlsf); MatrixCompute.Fill(n, 1.0f); - Matrix p = Matrix.FromHlsf(4000, 4000, hlsf); + Matrix p = Matrix.Create(4000, 4000, MatrixLayout.DenseRectangle, hlsf); // MatrixCompute.Fill(p, 0.0f); /* diff --git a/StgSharpDevelop.sln b/StgSharpDevelop.sln index 1811afab..e099905a 100644 --- a/StgSharpDevelop.sln +++ b/StgSharpDevelop.sln @@ -46,8 +46,8 @@ Global {3EAF2EE6-FA9E-4F57-951F-7E6F8125DFBF}.Debug|x64.Build.0 = Debug|x64 {3EAF2EE6-FA9E-4F57-951F-7E6F8125DFBF}.PerformanceDebug|ARM64.ActiveCfg = PerformanceDebug|ARM64 {3EAF2EE6-FA9E-4F57-951F-7E6F8125DFBF}.PerformanceDebug|ARM64.Build.0 = PerformanceDebug|ARM64 - {3EAF2EE6-FA9E-4F57-951F-7E6F8125DFBF}.PerformanceDebug|x64.ActiveCfg = PerformanceDebug|x64 - {3EAF2EE6-FA9E-4F57-951F-7E6F8125DFBF}.PerformanceDebug|x64.Build.0 = PerformanceDebug|x64 + {3EAF2EE6-FA9E-4F57-951F-7E6F8125DFBF}.PerformanceDebug|x64.ActiveCfg = Release|x64 + {3EAF2EE6-FA9E-4F57-951F-7E6F8125DFBF}.PerformanceDebug|x64.Build.0 = Release|x64 {3EAF2EE6-FA9E-4F57-951F-7E6F8125DFBF}.Release|ARM64.ActiveCfg = Release|ARM64 {3EAF2EE6-FA9E-4F57-951F-7E6F8125DFBF}.Release|ARM64.Build.0 = Release|ARM64 {3EAF2EE6-FA9E-4F57-951F-7E6F8125DFBF}.Release|x64.ActiveCfg = Release|x64 @@ -58,8 +58,8 @@ Global {610B992B-BB34-49C3-9993-676C595FC12E}.Debug|x64.Build.0 = Debug|x64 {610B992B-BB34-49C3-9993-676C595FC12E}.PerformanceDebug|ARM64.ActiveCfg = PerformanceDebug|ARM64 {610B992B-BB34-49C3-9993-676C595FC12E}.PerformanceDebug|ARM64.Build.0 = PerformanceDebug|ARM64 - {610B992B-BB34-49C3-9993-676C595FC12E}.PerformanceDebug|x64.ActiveCfg = PerformanceDebug|x64 - {610B992B-BB34-49C3-9993-676C595FC12E}.PerformanceDebug|x64.Build.0 = PerformanceDebug|x64 + {610B992B-BB34-49C3-9993-676C595FC12E}.PerformanceDebug|x64.ActiveCfg = Release|x64 + {610B992B-BB34-49C3-9993-676C595FC12E}.PerformanceDebug|x64.Build.0 = Release|x64 {610B992B-BB34-49C3-9993-676C595FC12E}.Release|ARM64.ActiveCfg = Release|ARM64 {610B992B-BB34-49C3-9993-676C595FC12E}.Release|ARM64.Build.0 = Release|ARM64 {610B992B-BB34-49C3-9993-676C595FC12E}.Release|x64.ActiveCfg = Release|x64 @@ -69,8 +69,8 @@ Global {20CBFF26-6746-402E-992C-7B643E9423EB}.Debug|x64.Build.0 = Debug|x64 {20CBFF26-6746-402E-992C-7B643E9423EB}.PerformanceDebug|ARM64.ActiveCfg = PerformanceDebug|x64 {20CBFF26-6746-402E-992C-7B643E9423EB}.PerformanceDebug|ARM64.Build.0 = PerformanceDebug|x64 - {20CBFF26-6746-402E-992C-7B643E9423EB}.PerformanceDebug|x64.ActiveCfg = PerformanceDebug|x64 - {20CBFF26-6746-402E-992C-7B643E9423EB}.PerformanceDebug|x64.Build.0 = PerformanceDebug|x64 + {20CBFF26-6746-402E-992C-7B643E9423EB}.PerformanceDebug|x64.ActiveCfg = Release|x64 + {20CBFF26-6746-402E-992C-7B643E9423EB}.PerformanceDebug|x64.Build.0 = Release|x64 {20CBFF26-6746-402E-992C-7B643E9423EB}.Release|ARM64.ActiveCfg = Release|ARM64 {20CBFF26-6746-402E-992C-7B643E9423EB}.Release|ARM64.Build.0 = Release|ARM64 {20CBFF26-6746-402E-992C-7B643E9423EB}.Release|x64.ActiveCfg = Release|x64 @@ -81,8 +81,8 @@ Global {10B5819F-2A62-41B6-980A-EB9E76A0E95C}.Debug|x64.Build.0 = Debug|x64 {10B5819F-2A62-41B6-980A-EB9E76A0E95C}.PerformanceDebug|ARM64.ActiveCfg = PerformanceDebug|x64 {10B5819F-2A62-41B6-980A-EB9E76A0E95C}.PerformanceDebug|ARM64.Build.0 = PerformanceDebug|x64 - {10B5819F-2A62-41B6-980A-EB9E76A0E95C}.PerformanceDebug|x64.ActiveCfg = PerformanceDebug|x64 - {10B5819F-2A62-41B6-980A-EB9E76A0E95C}.PerformanceDebug|x64.Build.0 = PerformanceDebug|x64 + {10B5819F-2A62-41B6-980A-EB9E76A0E95C}.PerformanceDebug|x64.ActiveCfg = Release|x64 + {10B5819F-2A62-41B6-980A-EB9E76A0E95C}.PerformanceDebug|x64.Build.0 = Release|x64 {10B5819F-2A62-41B6-980A-EB9E76A0E95C}.Release|ARM64.ActiveCfg = Release|x64 {10B5819F-2A62-41B6-980A-EB9E76A0E95C}.Release|ARM64.Build.0 = Release|x64 {10B5819F-2A62-41B6-980A-EB9E76A0E95C}.Release|x64.ActiveCfg = Release|x64 @@ -93,8 +93,8 @@ Global {5B51F5EA-138C-46B5-B36F-1D389968B6CF}.Debug|x64.Build.0 = Debug|x64 {5B51F5EA-138C-46B5-B36F-1D389968B6CF}.PerformanceDebug|ARM64.ActiveCfg = PerformanceDebug|x64 {5B51F5EA-138C-46B5-B36F-1D389968B6CF}.PerformanceDebug|ARM64.Build.0 = PerformanceDebug|x64 - {5B51F5EA-138C-46B5-B36F-1D389968B6CF}.PerformanceDebug|x64.ActiveCfg = PerformanceDebug|x64 - {5B51F5EA-138C-46B5-B36F-1D389968B6CF}.PerformanceDebug|x64.Build.0 = PerformanceDebug|x64 + {5B51F5EA-138C-46B5-B36F-1D389968B6CF}.PerformanceDebug|x64.ActiveCfg = Release|x64 + {5B51F5EA-138C-46B5-B36F-1D389968B6CF}.PerformanceDebug|x64.Build.0 = Release|x64 {5B51F5EA-138C-46B5-B36F-1D389968B6CF}.Release|ARM64.ActiveCfg = Release|x64 {5B51F5EA-138C-46B5-B36F-1D389968B6CF}.Release|ARM64.Build.0 = Release|x64 {5B51F5EA-138C-46B5-B36F-1D389968B6CF}.Release|x64.ActiveCfg = Release|x64 @@ -105,8 +105,8 @@ Global {D9538DE0-EE4C-4183-86D6-7DFC08A7BDFB}.Debug|x64.Build.0 = Debug|x64 {D9538DE0-EE4C-4183-86D6-7DFC08A7BDFB}.PerformanceDebug|ARM64.ActiveCfg = PerformanceDebug|x64 {D9538DE0-EE4C-4183-86D6-7DFC08A7BDFB}.PerformanceDebug|ARM64.Build.0 = PerformanceDebug|x64 - {D9538DE0-EE4C-4183-86D6-7DFC08A7BDFB}.PerformanceDebug|x64.ActiveCfg = PerformanceDebug|x64 - {D9538DE0-EE4C-4183-86D6-7DFC08A7BDFB}.PerformanceDebug|x64.Build.0 = PerformanceDebug|x64 + {D9538DE0-EE4C-4183-86D6-7DFC08A7BDFB}.PerformanceDebug|x64.ActiveCfg = Release|x64 + {D9538DE0-EE4C-4183-86D6-7DFC08A7BDFB}.PerformanceDebug|x64.Build.0 = Release|x64 {D9538DE0-EE4C-4183-86D6-7DFC08A7BDFB}.Release|ARM64.ActiveCfg = Release|ARM64 {D9538DE0-EE4C-4183-86D6-7DFC08A7BDFB}.Release|ARM64.Build.0 = Release|ARM64 {D9538DE0-EE4C-4183-86D6-7DFC08A7BDFB}.Release|x64.ActiveCfg = Release|x64 @@ -117,8 +117,8 @@ Global {9946599F-4D34-440F-840D-F9443D5AEFAA}.Debug|x64.Build.0 = Debug|x64 {9946599F-4D34-440F-840D-F9443D5AEFAA}.PerformanceDebug|ARM64.ActiveCfg = PerformanceDebug|ARM64 {9946599F-4D34-440F-840D-F9443D5AEFAA}.PerformanceDebug|ARM64.Build.0 = PerformanceDebug|ARM64 - {9946599F-4D34-440F-840D-F9443D5AEFAA}.PerformanceDebug|x64.ActiveCfg = PerformanceDebug|x64 - {9946599F-4D34-440F-840D-F9443D5AEFAA}.PerformanceDebug|x64.Build.0 = PerformanceDebug|x64 + {9946599F-4D34-440F-840D-F9443D5AEFAA}.PerformanceDebug|x64.ActiveCfg = Release|x64 + {9946599F-4D34-440F-840D-F9443D5AEFAA}.PerformanceDebug|x64.Build.0 = Release|x64 {9946599F-4D34-440F-840D-F9443D5AEFAA}.Release|ARM64.ActiveCfg = Release|ARM64 {9946599F-4D34-440F-840D-F9443D5AEFAA}.Release|ARM64.Build.0 = Release|ARM64 {9946599F-4D34-440F-840D-F9443D5AEFAA}.Release|x64.ActiveCfg = Release|x64