Files
stgsharp/StgSharp.Mathematics/Numeric/MatrixComputeModel.cs
T
2025-11-14 18:28:15 +08:00

251 lines
12 KiB
C#

//-----------------------------------------------------------------------
// -----------------------------------------------------------------------
// file="MatrixComputeModel"
// 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.Runtime.CompilerServices;
namespace StgSharp.Mathematics.Numeric
{
internal static class MatrixComputeModel
{
internal static unsafe void BufferComputeBinary(MatrixParallelTaskPackageNonGeneric* p)
{
int size = p->ElementSize * 16;
int count = p->PrimCount * p->SecCount;
int offset = p->LeftPrimOffset * p->SecCount;
((delegate* unmanaged[Cdecl]<void*, void*, void*, int, void>)p->ComputeHandle)((void*)(p->Left + offset * size),
(void*)(p->Right + offset * size),
(void*)(p->Result + offset * size),
count);
}
internal static unsafe void BufferComputeUnaryScalar(MatrixParallelTaskPackageNonGeneric* p)
{
int size = p->ElementSize * 16;
int count = p->PrimCount * p->SecCount;
int offset = p->LeftPrimOffset * p->SecCount;
((delegate* unmanaged[Cdecl]<void*, void*, int, void>)p->ComputeHandle)((void*)(p->Right + offset * size),
(void*)(p->Result + offset * size),
count);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe void Compute_Binary(MatrixParallelTaskPackageNonGeneric* p)
{
int eSize = p->ElementSize;
// base pointer to matrix kernels
nint l = p->Left, r = p->Right, a = p->Result;
long
// set beginning value to counters for primary offsets
lCount = (long)p->LeftPrimOffset * p->LeftPrimStride,
rCount = (long)p->RightPrimOffset * p->RightPrimStride,
aCount = (long)p->ResultPrimOffset * p->ResultPrimStride,
pCount = int.Min(p->PrimCount, p->PrimCountInTile + p->PrimTileOffset) /*_count of tile may be too much*/,
//edge to reset counters
lLimit = pCount - p->LeftPrimOffset,
rLimit = pCount - p->RightPrimOffset,
aLimit = pCount - p->ResultPrimOffset;
delegate* unmanaged[Cdecl]<IntPtr, IntPtr, IntPtr, void> op =
(delegate* unmanaged[Cdecl]<IntPtr, IntPtr, IntPtr, void>)p->ComputeHandle;
for (long i = p->PrimTileOffset % pCount; i < pCount; i++)
{
// update primary counters
// if reaches edge, reset to zero
lCount = i < lLimit ? lCount + p->LeftPrimStride : 0;
rCount = i < rLimit ? rCount + p->RightPrimStride : 0;
aCount = i < rLimit ? aCount + p->ResultPrimStride : 0;
// get kernel column pointers
nint left = l + (nint)(lCount * eSize);
nint right = r + (nint)(rCount * eSize);
nint ans = a + (nint)(aCount * eSize);
long
lc = (long)p->LeftSecOffset * p->LeftSecStride,
rc = (long)p->RightSecOffset * p->RightSecStride,
ac = (long)p->ResultSecOffset * p->ResultSecStride,
sCount = int.Min(p->SecCount, p->SecCountInTile * p->SecTileOffset);
long
ll = sCount - p->LeftSecOffset,
rl = sCount - p->RightSecOffset,
al = sCount - p->ResultSecOffset;
for (long j = p->SecTileOffset % sCount; j < sCount; j++)
{
lc = j < ll ? lc + p->LeftSecStride : 0;
rc = j < rl ? rc + p->RightSecStride : 0;
ac = j < al ? ac + p->ResultSecStride : 0;
op(left + (nint)lc, right + (nint)rc, ans + (nint)ac);
}
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe void Compute_BinaryScalar(MatrixParallelTaskPackageNonGeneric* p)
{
int eSize = p->ElementSize;
// base pointer to matrix kernels
nint l = p->Left, r = p->Right, a = p->Result;
long
// set beginning value to counters for primary offsets
lCount = (long)p->LeftPrimOffset * p->LeftPrimStride,
rCount = (long)p->RightPrimOffset * p->RightPrimStride,
aCount = (long)p->ResultPrimOffset * p->ResultPrimStride,
pCount = int.Min(p->PrimCount, p->PrimCountInTile + p->PrimTileOffset) /*_count of tile may be too much*/,
//edge to reset counters
lLimit = pCount - p->LeftPrimOffset,
rLimit = pCount - p->RightPrimOffset,
aLimit = pCount - p->ResultPrimOffset;
delegate* unmanaged[Cdecl]<IntPtr, IntPtr, IntPtr, ScalarPacket*, void> op =
(delegate* unmanaged[Cdecl]<IntPtr, IntPtr, IntPtr, ScalarPacket*, void>)p->ComputeHandle;
for (long i = p->PrimTileOffset % pCount; i < pCount; i++)
{
// update primary counters
// if reaches edge, reset to zero
lCount = i < lLimit ? lCount + p->LeftPrimStride : 0;
rCount = i < rLimit ? rCount + p->RightPrimStride : 0;
aCount = i < rLimit ? aCount + p->ResultPrimStride : 0;
// get kernel column pointers
nint left = l + (nint)(lCount * eSize);
nint right = r + (nint)(rCount * eSize);
nint ans = a + (nint)(aCount * eSize);
long
lc = (long)p->LeftSecOffset * p->LeftSecStride,
rc = (long)p->RightSecOffset * p->RightSecStride,
ac = (long)p->ResultSecOffset * p->ResultSecStride,
sCount = int.Min(p->SecCount, p->SecCountInTile * p->SecTileOffset);
long
ll = sCount - p->LeftSecOffset,
rl = sCount - p->RightSecOffset,
al = sCount - p->ResultSecOffset;
for (long j = p->SecTileOffset % sCount; j < sCount; j++)
{
lc = j < ll ? lc + p->LeftSecStride : 0;
rc = j < rl ? rc + p->RightSecStride : 0;
ac = j < al ? ac + p->ResultSecStride : 0;
op(left + (nint)lc, right + (nint)rc, ans + (nint)ac, p->Scalar);
}
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe void Compute_Unary(MatrixParallelTaskPackageNonGeneric* p)
{
int eSize = p->ElementSize;
// base pointer to matrix kernels
nint r = p->Right, a = p->Result;
long
// set beginning value to counters for primary offsets
rCount = (long)p->RightPrimOffset * p->RightPrimStride,
aCount = (long)p->ResultPrimOffset * p->ResultPrimStride,
pCount = int.Min(p->PrimCount, p->PrimCountInTile + p->PrimTileOffset) /*_count of tile may be too much*/,
//edge to reset counters
rLimit = pCount - p->RightPrimOffset,
aLimit = pCount - p->ResultPrimOffset;
delegate* unmanaged[Cdecl]<IntPtr, IntPtr, void> op =
(delegate* unmanaged[Cdecl]<IntPtr, IntPtr, void>)p->ComputeHandle;
for (long i = p->PrimTileOffset % pCount; i < pCount; i++)
{
// update primary counters
// if reaches edge, reset to zero
rCount = i < rLimit ? rCount + p->RightPrimStride : 0;
aCount = i < rLimit ? aCount + p->ResultPrimStride : 0;
// get kernel column pointers
nint right = r + (nint)(rCount * eSize);
nint ans = a + (nint)(aCount * eSize);
long
rc = (long)p->RightSecOffset * p->RightSecStride,
ac = (long)p->ResultSecOffset * p->ResultSecStride,
sCount = int.Min(p->SecCount, p->SecCountInTile * p->SecTileOffset);
long
rl = sCount - p->RightSecOffset,
al = sCount - p->ResultSecOffset;
for (long j = p->SecTileOffset % sCount; j < sCount; j++)
{
rc = j < rl ? rc + p->RightSecStride : 0;
ac = j < al ? ac + p->ResultSecStride : 0;
op(right + (nint)rc, ans + (nint)ac);
}
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe void Compute_UnaryScalar(MatrixParallelTaskPackageNonGeneric* p)
{
int eSize = p->ElementSize;
// base pointer to matrix kernels
nint r = p->Right, a = p->Result;
long
// set beginning value to counters for primary offsets
rCount = (long)p->RightPrimOffset * p->RightPrimStride,
aCount = (long)p->ResultPrimOffset * p->ResultPrimStride,
pCount = int.Min(p->PrimCount, p->PrimCountInTile + p->PrimTileOffset) /*_count of tile may be too much*/,
//edge to reset counters
rLimit = pCount - p->RightPrimOffset,
aLimit = pCount - p->ResultPrimOffset;
delegate* unmanaged[Cdecl]<IntPtr, IntPtr, ScalarPacket*, void> op =
(delegate* unmanaged[Cdecl]<IntPtr, IntPtr, ScalarPacket*, void>)p->ComputeHandle;
for (long i = p->PrimTileOffset % pCount; i < pCount; i++)
{
// update primary counters
// if reaches edge, reset to zero
rCount = i < rLimit ? rCount + p->RightPrimStride : 0;
aCount = i < rLimit ? aCount + p->ResultPrimStride : 0;
// get kernel column pointers
nint right = r + (nint)(rCount * eSize);
nint ans = a + (nint)(aCount * eSize);
long
rc = (long)p->RightSecOffset * p->RightSecStride,
ac = (long)p->ResultSecOffset * p->ResultSecStride,
sCount = int.Min(p->SecCount, p->SecCountInTile * p->SecTileOffset);
long
rl = sCount - p->RightSecOffset,
al = sCount - p->ResultSecOffset;
for (long j = p->SecTileOffset % sCount; j < sCount; j++)
{
rc = j < rl ? rc + p->RightSecStride : 0;
ac = j < al ? ac + p->ResultSecStride : 0;
op(right + (nint)rc, ans + (nint)ac, p->Scalar);
}
}
}
}
}