// ----------------------------------------------------------------------------- // file="Matrix" // Project: StgSharp // Copyright (c) Nitload. // SPDX-License-Identifier: MIT // ----------------------------------------------------------------------------- using StgSharp.Mathematics; using StgSharp.Mathematics.Numeric; using System; using System.Numerics; using System.Runtime.CompilerServices; // using hlsfHandle = global::StgSharp.HighPerformance.Memory.HybridLayerSegregatedFitAllocationHandle; namespace StgSharp.Mathematics.Numeric { public unsafe partial class Matrix where T : unmanaged, INumber { 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 { if ((y < 0) || (y > _size.ElementColumnLength) || (x < 0) || (x > _size.ElementRowLength)) { throw new ArgumentOutOfRangeException($"Index [{x},{y}] is out of matrix index range."); } long offset = GetElementOffset(x, y); if (offset < 0) { return T.Zero; } return ((T*)Buffer)[offset]; } set { if ((y < 0) || (y > _size.ElementColumnLength) || (x < 0) || (x > _size.ElementRowLength)) { throw new ArgumentOutOfRangeException($"Index [{x},{y}] is out of matrix index range."); } long offset = GetElementOffset(x, y); if (offset < 0) { return; } ((T*)Buffer)[offset] = value; } } /// /// Matlab style indexer to generate a new matrix /// /// /// /// /// /// /// /// /// /// /// /// /// public unsafe Matrix this[ ReadOnlySpan column, ReadOnlySpan row ] { 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 => (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 ) { return ref (_boarder.IsInBuffer(x, y, in _size) ? ref _buffer[_boarder.GetIndexOffset(x, y, in _size)] : ref Unsafe.NullRef>()); } internal long GetElementOffset( int x, int y ) { int k_c = y / 4, c = y % 4, k_r = x / 4, r = x % 4; if (!_boarder.IsInBuffer(k_r, k_c, in _size)) { return -1; } long kernelOffset = _boarder.GetIndexOffset(k_r, k_c, in _size); return (kernelOffset * 16) + (4 * r) + c; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal unsafe ref T GetElementUnsafe( int x, int y ) { // Caller guarantees: indices in range, layout is dense square. int k_c = y / 4; int k_r = x / 4; int c = y % 4; int r = x % 4; ref MatrixKernel kernel = ref _buffer[_boarder.GetIndexOffset(k_r, k_c, in _size)]; return ref kernel[c, r]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal unsafe MatrixKernel* GetKernelAddressUnsafe( int x, int y ) { return Buffer + _boarder.GetIndexOffset(x, y, in _size); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal unsafe ref MatrixKernel GetKernelUnsafe( int x, int y ) { // Caller guarantees: indices in range, layout is dense square. int k_c = y / 4; int k_r = x / 4; return ref _buffer[_boarder.GetIndexOffset(k_c, k_r, in _size)]; } } }