diff --git a/.cr/personal/Editor/Painting/Structural Highlighting.xml b/.cr/personal/Editor/Painting/Structural Highlighting.xml
deleted file mode 100644
index 347228e8..00000000
--- a/.cr/personal/Editor/Painting/Structural Highlighting.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
- False
-
-
\ No newline at end of file
diff --git a/StgSharp.Common/Internal/Intrinsic/IntrinsicContext.cs b/StgSharp.Common/Internal/Intrinsic/IntrinsicContext.cs
index 2ae48623..e3830279 100644
--- a/StgSharp.Common/Internal/Intrinsic/IntrinsicContext.cs
+++ b/StgSharp.Common/Internal/Intrinsic/IntrinsicContext.cs
@@ -38,16 +38,19 @@ namespace StgSharp.Internal.Intrinsic
internal unsafe struct IntrinsicContext
{
- public delegate* unmanaged[Cdecl] city_hash_simplify;
- public delegate* unmanaged[Cdecl] f32_add;
- public delegate* unmanaged[Cdecl] f32_fill;
- public delegate* unmanaged[Cdecl] f32_fma;
- public delegate* unmanaged[Cdecl] f32_scalar_mul;
- public delegate* unmanaged[Cdecl] f32_sub;
- public delegate* unmanaged[Cdecl] f32_transpose;
- public delegate* unmanaged[Cdecl] factorial_simd;
- public delegate* unmanaged[Cdecl] index_pair;
- public delegate* unmanaged[Cdecl] normalize_3;
+ public delegate* unmanaged[Cdecl] city_hash_simplify; //city_hash_simplify
+ public delegate* unmanaged[Cdecl] f32_buffer_add; //f32_buffer_add
+ public delegate* unmanaged[Cdecl] f32_buffer_fill; //f32_buffer_fill
+ public delegate* unmanaged[Cdecl] f32_buffer_scalar_mul; //f32_buffer_s_m
+ public delegate* unmanaged[Cdecl] f32_buffer_sub; //f32_kernel_sub
+ public delegate* unmanaged[Cdecl] f32_buffer_transpose; //f32_kernel_transpose
+ public delegate* unmanaged[Cdecl] f32_build_panel; //f32_build_panel
+ public delegate* unmanaged[Cdecl] f32_normalize_3; //f32_normalize_3
+ public delegate* unmanaged[Cdecl] f32_panel_fma; //f32_panel_fma
+ public delegate* unmanaged[Cdecl] f32_store_panel; //f32_store_panel
+ public delegate* unmanaged[Cdecl] factorial_simd; //factorial_simd
+ public delegate* unmanaged[Cdecl] index_pair; //index_pair
+ public delegate* unmanaged[Cdecl] variant ; //variant
public IntrinsicContext()
{
diff --git a/StgSharp.Common/Mathematics/Graphic/Matrix44.cs b/StgSharp.Common/Mathematics/Graphic/Matrix44.cs
index 194f4f09..48c55340 100644
--- a/StgSharp.Common/Mathematics/Graphic/Matrix44.cs
+++ b/StgSharp.Common/Mathematics/Graphic/Matrix44.cs
@@ -185,7 +185,7 @@ namespace StgSharp.Mathematics.Graphic
mat.transpose.colum2 = rowSpan[2].vec;
mat.transpose.colum3 = rowSpan[3].vec;
- NativeIntrinsic.Intrinsic.f32_transpose(&mat.transpose, &mat.mat);
+ NativeIntrinsic.Intrinsic.f32_buffer_transpose(&mat.transpose, &mat.mat);
mat.isTransposed = false;
return mat;
}
@@ -208,7 +208,7 @@ namespace StgSharp.Mathematics.Graphic
if (!isTransposed)
{
fixed (ColumnSet4* source = &mat, target = &transpose) {
- NativeIntrinsic.Intrinsic.f32_transpose(source, target);
+ NativeIntrinsic.Intrinsic.f32_buffer_transpose(source, target);
}
isTransposed = true;
}
@@ -218,7 +218,7 @@ namespace StgSharp.Mathematics.Graphic
public static unsafe Matrix44 operator -(Matrix44 left, Matrix44 right)
{
Matrix44 ret = new();
- NativeIntrinsic.Intrinsic.f32_sub(&left, &right, &ret, 1);
+ NativeIntrinsic.Intrinsic.f32_buffer_sub(&left, &right, &ret, 1);
return ret;
}
@@ -260,7 +260,7 @@ namespace StgSharp.Mathematics.Graphic
public static unsafe Matrix44 operator +(Matrix44 left, Matrix44 right)
{
Matrix44 ret = new();
- NativeIntrinsic.Intrinsic.f32_add(&left, &right, &ret, 1);
+ NativeIntrinsic.Intrinsic.f32_buffer_add(&left, &right, &ret, 1);
return ret;
}
diff --git a/StgSharp.Common/Timing/StgSharpTime.cs b/StgSharp.Common/Timing/StgSharpTime.cs
index f08f06fc..aa407735 100644
--- a/StgSharp.Common/Timing/StgSharpTime.cs
+++ b/StgSharp.Common/Timing/StgSharpTime.cs
@@ -119,6 +119,7 @@ namespace StgSharp
{
if (!_subscribers[i].OnSpanTick(elapsedTicks))
{
+ Console.WriteLine("removed");
_subscribers.RemoveAt(i);
i--; // adjust index after removal
}
diff --git a/StgSharp.Common/Timing/TimeSequence.cs b/StgSharp.Common/Timing/TimeSequence.cs
index fba82b03..9dc446be 100644
--- a/StgSharp.Common/Timing/TimeSequence.cs
+++ b/StgSharp.Common/Timing/TimeSequence.cs
@@ -46,8 +46,10 @@ namespace StgSharp.Common.Timing
double initialSliceSeconds,
double totalSeconds,
double growthMultiplier,
- double minSliceSeconds) => new LogTimeSequence(initialSliceSeconds, totalSeconds,
- growthMultiplier, minSliceSeconds);
+ double minSliceSeconds) => new LogTimeSequence(initialSliceSeconds,
+ totalSeconds,
+ growthMultiplier,
+ minSliceSeconds);
public abstract bool EndsAt(long currentTick);
@@ -71,7 +73,6 @@ namespace StgSharp.Common.Timing
if (frameSeconds > totalSeconds) {
throw new ArgumentException("Frame length greater than total length.");
}
-
_totalSeconds = totalSeconds;
_frameSeconds = frameSeconds;
}
@@ -85,7 +86,7 @@ namespace StgSharp.Common.Timing
long span = currentTick - PreviousFrameTick;
if (span >= _frameLengthTicks && currentTick < EndingTick)
{
- PreviousFrameTick += _frameLengthTicks; // advance start of next frame
+ PreviousFrameTick += _frameLengthTicks;
return true;
}
return false;
@@ -105,25 +106,21 @@ namespace StgSharp.Common.Timing
}
///
- /// Logarithmic time sequence with growth factor. Boundaries (cumulative times since start)
- /// follow initial * multiplier^k, but each slice duration (difference between adjusted
- /// boundaries) is at least minSliceSeconds. First slice uses the exact initial length even if
- /// below minSliceSeconds, subsequent slices enforce minimum. Example: initial=2,
- /// multiplier=2, total>=8, min=3 => boundaries: 2,5,8 (durations:2,3,3).
+ /// Logarithmic time sequence with growth factor and minimum slice length enforcement.
///
internal sealed class LogTimeSequence : TimeSequence
{
+ private bool _finalEmitted;
private readonly double _initialSeconds;
- private double _lastBoundarySecondsAdjusted; // adjusted cumulative seconds of last emitted boundary (0 at start)
+ private double _lastBoundarySecondsAdjusted;
private readonly double _minSliceSeconds;
private readonly double _multiplier;
- private double _nextBoundarySecondsAdjusted; // adjusted cumulative seconds for next boundary
+ private double _nextBoundarySecondsAdjusted;
private readonly double _totalSeconds;
-
- private int _sliceIndex; // index of next boundary (0 => first boundary at initialSeconds)
+ private int _sliceIndex;
private long _freq;
- private long _nextBoundaryTick; // absolute tick for next boundary
+ private long _nextBoundaryTick;
private long _totalTicks;
public LogTimeSequence(
@@ -139,11 +136,9 @@ namespace StgSharp.Common.Timing
if (growthMultiplier < 1.0) {
throw new ArgumentException("growthMultiplier must be >= 1");
}
-
if (initialSliceSeconds > totalSeconds) {
throw new ArgumentException("Initial slice length greater than total length.");
}
-
_initialSeconds = initialSliceSeconds;
_totalSeconds = totalSeconds;
_multiplier = growthMultiplier;
@@ -151,49 +146,62 @@ namespace StgSharp.Common.Timing
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public override bool EndsAt(long currentTick) => currentTick >= EndingTick ||
- _nextBoundarySecondsAdjusted >= _totalSeconds;
+ public override bool EndsAt(long currentTick)
+ {
+ if (currentTick >= EndingTick)
+ {
+ Console.WriteLine("Ended");
+ return true;
+ }
+ return false;
+ }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool IsNextFrameReady(long currentTick)
{
- if (currentTick < _nextBoundaryTick || currentTick >= EndingTick) {
+ // Emit final once when reaching or passing end.
+ if (currentTick >= EndingTick)
+ {
+ if (_finalEmitted) {
+ return false;
+ }
+
+ PreviousFrameTick = EndingTick;
+ _finalEmitted = true;
+ return true;
+ }
+
+ // Not reached end: only when we cross the next boundary tick do we emit.
+ if (currentTick < _nextBoundaryTick)
+ {
return false;
}
- // Emit frame: update previous frame tick and prepare next boundary.
- PreviousFrameTick = _nextBoundaryTick; // boundary just reached
+ // Advance to this boundary.
+ PreviousFrameTick = _nextBoundaryTick;
_lastBoundarySecondsAdjusted = _nextBoundarySecondsAdjusted;
_sliceIndex++;
- // Compute original (unadjusted) next cumulative boundary in seconds.
- double originalNext = _initialSeconds * Math.Pow(_multiplier, _sliceIndex);
-
- // Enforce total cap.
- if (originalNext > _totalSeconds)
- {
- originalNext = _totalSeconds;
+ // Compute next cumulative boundary seconds with multiplier, then enforce min-slice and total cap.
+ double next = _initialSeconds * Math.Pow(_multiplier, _sliceIndex);
+ if (next > _totalSeconds) {
+ next = _totalSeconds;
}
- // Compute slice duration based on adjusted previous boundary.
- double delta = originalNext - _lastBoundarySecondsAdjusted;
- if (_sliceIndex > 0 && delta < _minSliceSeconds)
+ double delta = next - _lastBoundarySecondsAdjusted;
+ if (delta < _minSliceSeconds)
{
- // Enforce minimum (except for first slice which uses initial value)
- originalNext = _lastBoundarySecondsAdjusted + _minSliceSeconds;
- if (originalNext > _totalSeconds) {
- originalNext = _totalSeconds;
+ next = _lastBoundarySecondsAdjusted + _minSliceSeconds;
+ if (next > _totalSeconds) {
+ next = _totalSeconds;
}
}
- _nextBoundarySecondsAdjusted = originalNext;
- if (_nextBoundarySecondsAdjusted >= _totalSeconds)
- {
- _nextBoundaryTick = EndingTick; // sequence will end after this boundary
- } else
- {
- _nextBoundaryTick = BeginningTick + SecondsToTicks(_nextBoundarySecondsAdjusted);
- }
+ _nextBoundarySecondsAdjusted = next;
+ _nextBoundaryTick = (_nextBoundarySecondsAdjusted >= _totalSeconds) ?
+ EndingTick :
+ BeginningTick + SecondsToTicks(_nextBoundarySecondsAdjusted);
+
return true;
}
@@ -205,9 +213,10 @@ namespace StgSharp.Common.Timing
EndingTick = BeginningTick + _totalTicks;
_sliceIndex = 0;
_lastBoundarySecondsAdjusted = 0.0;
- _nextBoundarySecondsAdjusted = _initialSeconds; // first boundary uses exact initial length
+ _nextBoundarySecondsAdjusted = _initialSeconds;
_nextBoundaryTick = BeginningTick + SecondsToTicks(_nextBoundarySecondsAdjusted);
- PreviousFrameTick = BeginningTick; // start point
+ PreviousFrameTick = BeginningTick;
+ _finalEmitted = false;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
diff --git a/StgSharp.Common/Timing/TimeSpanProvider.Awaiting.cs b/StgSharp.Common/Timing/TimeSpanProvider.Awaiting.cs
index 128c6ab1..398d500e 100644
--- a/StgSharp.Common/Timing/TimeSpanProvider.Awaiting.cs
+++ b/StgSharp.Common/Timing/TimeSpanProvider.Awaiting.cs
@@ -86,11 +86,7 @@ namespace StgSharp.Timing
public void Dispose()
{
// mark provider as ended so external users can observe terminal state
- try
- {
- Volatile.Write(ref _endedFlag, 1);
- }
- catch { }
+ Volatile.Write(ref _endedFlag, 1);
s_unusedID.Push(TokenID);
_event.Dispose();
GC.SuppressFinalize(this);
@@ -211,6 +207,7 @@ namespace StgSharp.Timing
{
// mark ended due to sequence timeout, then dispose
Volatile.Write(ref _endedFlag, 1);
+ Console.WriteLine("Time span ended.");
Dispose();
return false;
}
@@ -238,9 +235,6 @@ namespace StgSharp.Timing
return true;
}
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal void Refresh() => _refreshHandler?.Invoke(this, EventArgs.Empty); // Legacy compatibility.
-
~TimeSpanProvider() => Dispose();
}
diff --git a/StgSharp.Common/Timing/TimeSpanProvider.cs b/StgSharp.Common/Timing/TimeSpanProvider.cs
index 67a1d741..f847b1f5 100644
--- a/StgSharp.Common/Timing/TimeSpanProvider.cs
+++ b/StgSharp.Common/Timing/TimeSpanProvider.cs
@@ -39,15 +39,18 @@ namespace StgSharp.Timing
public partial class TimeSpanProvider
{
- private bool _subscribed;
+ // private bool _subscribed;
private int _emittedSpanCount; // legacy counter
// internal ended flag (0 = running, 1 = ended)
- private int _endedFlag = 0;
+ private int _endedFlag;
private readonly TimeSequence _sequence;
private readonly TimeSourceProviderBase _timeSource;
- public TimeSpanProvider(TimeSequence sequence, TimeSourceProviderBase provider, int maxWaitCount = 1)
+ public TimeSpanProvider(
+ TimeSequence sequence,
+ TimeSourceProviderBase provider,
+ int maxWaitCount = 1)
{
ArgumentNullException.ThrowIfNull(provider);
ArgumentNullException.ThrowIfNull(sequence);
@@ -55,8 +58,10 @@ namespace StgSharp.Timing
_sequence = sequence;
_sequence.StartFrom(provider);
provider.AddSubscriber(this);
- _subscribed = true;
- if (!s_unusedID.TryPop(out int id)) {
+
+ // _subscribed = true;
+ if (!s_unusedID.TryPop(out int id))
+ {
id = Interlocked.Increment(ref s_maxID);
}
TokenID = id;
@@ -70,16 +75,20 @@ namespace StgSharp.Timing
///
public bool IsEnded => Volatile.Read(ref _endedFlag) != 0;
+ ///
+ /// Current emitted time in seconds relative to the sequence beginning.
+ ///
public double CurrentSecond
{
- get => (double)_sequence.PreviousFrameTick / _timeSource.Frequency;
+ get => (double)(_sequence.PreviousFrameTick - _sequence.BeginningTick) / _timeSource.Frequency;
}
public int CurrentSpan => _emittedSpanCount;
public static TimeSourceProviderBase DefaultProvider => World.MainTimeProvider;
- public static explicit operator int(TimeSpanProvider provider) => provider?._emittedSpanCount ?? 0;
+ public static explicit operator int(TimeSpanProvider provider) => provider?._emittedSpanCount ??
+ 0;
}
}
\ No newline at end of file
diff --git a/StgSharp.Mathematics/Numeric/MatrixCompute.Basic.cs b/StgSharp.Mathematics/Numeric/MatrixCompute.Basic.cs
index 7d76854d..52cec027 100644
--- a/StgSharp.Mathematics/Numeric/MatrixCompute.Basic.cs
+++ b/StgSharp.Mathematics/Numeric/MatrixCompute.Basic.cs
@@ -58,7 +58,7 @@ namespace StgSharp.Mathematics.Numeric
MatrixKernel* leftPtr = left.Buffer;
MatrixKernel* rightPtr = right.Buffer;
MatrixKernel* ansPtr = ans.Buffer;
- NativeIntrinsic.Intrinsic.f32_add(leftPtr, rightPtr, ansPtr, count);
+ NativeIntrinsic.Intrinsic.f32_buffer_add(leftPtr, rightPtr, ansPtr, count);
return ans;
} else if (count <= 1024)
@@ -68,7 +68,7 @@ namespace StgSharp.Mathematics.Numeric
MatrixKernel* leftPtr = left.Buffer;
MatrixKernel* rightPtr = right.Buffer;
MatrixKernel* ansPtr = ans.Buffer;
- NativeIntrinsic.Intrinsic.f32_add(leftPtr, rightPtr, ansPtr, count);
+ NativeIntrinsic.Intrinsic.f32_buffer_add(leftPtr, rightPtr, ansPtr, count);
MatrixParallel.ReturnParallelResources(ref pool);
return ans;
@@ -81,7 +81,7 @@ namespace StgSharp.Mathematics.Numeric
package->PrimCount = left.KernelColumnLength;
package->SecCount = left.KernelRowLength;
package->ComputeMode = new MatrixOpMode(MatrixOperationStyle.BUFFER_OP, MatrixOperationParam.LEFT_RIGHT_ANS_PARAM);
- package->ComputeHandle = (IntPtr)NativeIntrinsic.Intrinsic.f32_add;
+ package->ComputeHandle = (IntPtr)NativeIntrinsic.Intrinsic.f32_buffer_add;
MatrixParallelHandle taskGroup = MatrixParallel.ScheduleTask(package);
MatrixParallel.LaunchParallel(taskGroup, SleepMode.DeepSleep);
@@ -96,12 +96,12 @@ namespace StgSharp.Mathematics.Numeric
scalar->Data(0) = value;
if (count <= 256)
{
- NativeIntrinsic.Intrinsic.f32_fill(ans.Buffer, scalar, count);
+ NativeIntrinsic.Intrinsic.f32_buffer_fill(ans.Buffer, scalar, count);
return;
} else if (count <= 1024)
{
MatrixParallelThread[] pool = MatrixParallel.LeadParallel(1);
- NativeIntrinsic.Intrinsic.f32_fill(ans.Buffer, scalar, count);
+ NativeIntrinsic.Intrinsic.f32_buffer_fill(ans.Buffer, scalar, count);
MatrixParallel.ReturnParallelResources(ref pool);
return;
}
@@ -111,7 +111,7 @@ namespace StgSharp.Mathematics.Numeric
package->PrimCount = ans.KernelColumnLength;
package->SecCount = ans.KernelRowLength;
package->ComputeMode = new MatrixOpMode(MatrixOperationStyle.BUFFER_OP, MatrixOperationParam.ANS_SCALAR_PARAM);
- package->ComputeHandle = (IntPtr)NativeIntrinsic.Intrinsic.f32_fill;
+ package->ComputeHandle = (IntPtr)NativeIntrinsic.Intrinsic.f32_buffer_fill;
package->Scalar = scalar;
MatrixParallelHandle taskGroup = MatrixParallel.ScheduleTask(package);
MatrixParallel.LaunchParallel(taskGroup, SleepMode.DeepSleep);
@@ -144,7 +144,7 @@ namespace StgSharp.Mathematics.Numeric
{
MatrixKernel* leftPtr = left.Buffer;
MatrixKernel* ansPtr = ans.Buffer;
- NativeIntrinsic.Intrinsic.f32_scalar_mul(leftPtr, ansPtr, scalar, count);
+ NativeIntrinsic.Intrinsic.f32_buffer_scalar_mul(leftPtr, ansPtr, scalar, count);
return ans;
} else if (count <= 1024)
@@ -153,7 +153,7 @@ namespace StgSharp.Mathematics.Numeric
MatrixKernel* leftPtr = left.Buffer;
MatrixKernel* ansPtr = ans.Buffer;
- NativeIntrinsic.Intrinsic.f32_scalar_mul(leftPtr, ansPtr, scalar, count);
+ NativeIntrinsic.Intrinsic.f32_buffer_scalar_mul(leftPtr, ansPtr, scalar, count);
MatrixParallel.ReturnParallelResources(ref pool);
return ans;
@@ -166,7 +166,7 @@ namespace StgSharp.Mathematics.Numeric
package->SecCount = left.KernelRowLength;
package->Scalar = scalar;
package->ComputeMode = new MatrixOpMode(MatrixOperationStyle.BUFFER_OP, MatrixOperationParam.RIGHT_ANS_SCALAR_PARAM);
- package->ComputeHandle = (IntPtr)NativeIntrinsic.Intrinsic.f32_scalar_mul;
+ package->ComputeHandle = (IntPtr)NativeIntrinsic.Intrinsic.f32_buffer_scalar_mul;
MatrixParallelHandle taskGroup = MatrixParallel.ScheduleTask(package);
MatrixParallel.LaunchParallel(taskGroup, SleepMode.DeepSleep);
@@ -192,7 +192,7 @@ namespace StgSharp.Mathematics.Numeric
MatrixKernel* leftPtr = left.Buffer;
MatrixKernel* rightPtr = right.Buffer;
MatrixKernel* ansPtr = ans.Buffer;
- NativeIntrinsic.Intrinsic.f32_sub(leftPtr, rightPtr, ansPtr, count);
+ NativeIntrinsic.Intrinsic.f32_buffer_sub(leftPtr, rightPtr, ansPtr, count);
return ans;
} else if (count <= 1024)
@@ -202,7 +202,7 @@ namespace StgSharp.Mathematics.Numeric
MatrixKernel* leftPtr = left.Buffer;
MatrixKernel* rightPtr = right.Buffer;
MatrixKernel* ansPtr = ans.Buffer;
- NativeIntrinsic.Intrinsic.f32_sub(leftPtr, rightPtr, ansPtr, count);
+ NativeIntrinsic.Intrinsic.f32_buffer_sub(leftPtr, rightPtr, ansPtr, count);
MatrixParallel.ReturnParallelResources(ref pool);
return ans;
@@ -215,7 +215,7 @@ namespace StgSharp.Mathematics.Numeric
package->PrimCount = left.KernelColumnLength;
package->SecCount = left.KernelRowLength;
package->ComputeMode = new MatrixOpMode(MatrixOperationStyle.BUFFER_OP, MatrixOperationParam.LEFT_RIGHT_ANS_PARAM);
- package->ComputeHandle = (IntPtr)NativeIntrinsic.Intrinsic.f32_sub;
+ package->ComputeHandle = (IntPtr)NativeIntrinsic.Intrinsic.f32_buffer_sub;
MatrixParallelHandle taskGroup = MatrixParallel.ScheduleTask(package);
MatrixParallel.LaunchParallel(taskGroup, SleepMode.DeepSleep);
diff --git a/StgSharp.Native/StgSharp.Native.vcxproj b/StgSharp.Native/StgSharp.Native.vcxproj
index 47d66f39..81129ad1 100644
--- a/StgSharp.Native/StgSharp.Native.vcxproj
+++ b/StgSharp.Native/StgSharp.Native.vcxproj
@@ -148,7 +148,7 @@
-
+
@@ -156,7 +156,7 @@
- CppCode
+ CCode
diff --git a/StgSharp.Native/StgSharp.Native.vcxproj.filters b/StgSharp.Native/StgSharp.Native.vcxproj.filters
index 3abc766e..92bd11f3 100644
--- a/StgSharp.Native/StgSharp.Native.vcxproj.filters
+++ b/StgSharp.Native/StgSharp.Native.vcxproj.filters
@@ -51,7 +51,7 @@
源文件
-
+
源文件
diff --git a/StgSharp.Native/sn-head/sn_intrinsic.h b/StgSharp.Native/sn-head/sn_intrinsic.h
index 0ccff731..e16df462 100644
--- a/StgSharp.Native/sn-head/sn_intrinsic.h
+++ b/StgSharp.Native/sn-head/sn_intrinsic.h
@@ -131,6 +131,8 @@ typedef void(SN_DECL *BUF_PROC_LRA)(mat_kernel *left, mat_kernel *right, mat_ker
#pragma region matrix panel function type
+typedef void(SN_DECL *PANEL_PROC)(mat_panel *panel, mat_kernel *kernel, int col_length,
+ int row_length, int col_index, int row_index);
typedef void(SN_DECL *PNL_PROC_LRA)(mat_panel *left, mat_panel *right, mat_panel *ans);
typedef void(SN_DECL *PNL_PROC_RA)(mat_panel *right, mat_panel *ans);
typedef void(SN_DECL *PNL_PROC_LRAS)(mat_panel *left, mat_panel *right, mat_panel *ans,
@@ -250,22 +252,21 @@ INTERNAL int SN_DECL index_pair_sse(short const *str, uint32_t target, int lengt
#pragma endregion
-typedef void(SN_DECL *BUILD_PANEL_PROC)(mat_panel *panel, mat_kernel *kernel, int col_length,
- int row_length, int col_index, int row_index);
-
-// Reordered to match C# IntrinsicContext field order
-// C# order: city_hash_simplify, f32_add, f32_fill, f32_fma, f32_scalar_mul, f32_sub, f32_transpose, factorial_simd, index_pair, normalize_3
+// Mirrors C# IntrinsicContext field order so managed/unmanaged layouts stay in sync.
typedef struct sn_intrinsic {
- HASH city_hash_simplify; // city_hash_simplify
- BUF_PROC_LRA f32_buffer_add; // f32_add
- BUF_PROC_AS f32_buffer_fill; // f32_fill
- PNL_PROC_LRA f32_panel_fma; // f32_fma (panel variant)
- BUF_PROC_LRA f32_kernel_scalar_mul; // f32_scalar_mul (right+ans+scalar variant mapped here)
- BUF_PROC_LRA f32_kernel_sub; // f32_sub
- KER_PROC_RA f32_kernel_transpose; // f32_transpose
- FACTORIALROC factorial_simd; // factorial_simd
- INDEX_PAIR index_pair; // index_pair
- VECTORNORMALIZEPROC f32_normalize_3; // normalize_3
+ HASH city_hash_simplify;
+ BUF_PROC_LRA f32_buffer_add;
+ BUF_PROC_AS f32_buffer_fill;
+ BUF_PROC_RAS f32_buffer_scalar_mul;
+ BUF_PROC_LRA f32_buffer_sub;
+ KER_PROC_RA f32_buffer_transpose;
+ PANEL_PROC f32_build_panel;
+ VECTORNORMALIZEPROC f32_normalize_3;
+ PNL_PROC_LRA f32_panel_fma;
+ PANEL_PROC f32_store_panel;
+ FACTORIALROC factorial_simd;
+ INDEX_PAIR index_pair;
+ BUF_PROC_RAS variant;
} sn_intrinsic;
typedef enum most_advanced_instruction {
diff --git a/StgSharp.Native/sn-head/sn_matkernel.h b/StgSharp.Native/sn-head/sn_matkernel.h
index 42803f48..857b7af7 100644
--- a/StgSharp.Native/sn-head/sn_matkernel.h
+++ b/StgSharp.Native/sn-head/sn_matkernel.h
@@ -1,14 +1,17 @@
#ifndef SN_MATKERNEL
#define SN_MATKERNEL
-#define ELEMENTSIZE(T) sizeof(T)
-#define XMMCOUNT(T) sizeof(T)
-#define YMMCOUNT(T) sizeof(T) / 2
-#define ZMMCOUNT(T) sizeof(T) / 4
-
#include
#include
+#include "sn_internal.h"
+
+/* Kernel storage unions for a fixed 4x4 block. */
+#define ELEMENTSIZE(T) sizeof(T)
+#define XMMCOUNT(T) (sizeof(T))
+#define YMMCOUNT(T) (sizeof(T) / 2)
+#define ZMMCOUNT(T) (sizeof(T) / 4)
+
#define MAT_KERNEL(T) \
union { \
__m128 xmm[XMMCOUNT(T) / 4]; \
@@ -25,7 +28,8 @@
T v[4]; \
}
-#endif
+/* Provide a named alias for the zero kernel type to ensure consistent linkage in C++. */
+typedef MAT_KERNEL(uint64_t) sn_zero_kernel_u64;
/* Helpers (all compile-time): */
#define SN_LANES(T_VEC, T) (sizeof(T_VEC) / sizeof(T))
@@ -48,8 +52,8 @@
- SIMD view remains integer-typed; cast inside micro-kernels to the
appropriate floating-point/integer vector type on demand.
*/
-#define MAT_PANEL_SQ_MIN(T, T_VEC, MINQ) \
- SN_ALIGNAS(sizeof(T_VEC)) union { \
+#define MAT_PANEL_SQ_MIN_NOALIGN(T, T_VEC, MINQ) \
+ union { \
T_VEC vec[PANEL_Q(T, T_VEC, MINQ)][PANEL_CHUNKS(T, T_VEC, MINQ)]; \
T flat[PANEL_Q(T, T_VEC, MINQ) * PANEL_Q(T, T_VEC, MINQ)]; \
}
@@ -63,44 +67,53 @@
/* SSE panel layout: column-major buffer holding 4 logical columns with MINQ=4.
Columns: each column packs up to four scalars so ALIGN equals sizeof(__m128).
Alignment: every column boundary lands on a 16-byte multiple for XMM loads. */
-#define MAT_PANEL_SSE(T) MAT_PANEL_SQ_MIN(T, __m128, 4)
+#define MAT_PANEL_SSE(T) SN_ALIGNAS(16) MAT_PANEL_SQ_MIN_NOALIGN(T, __m128, 4)
/* AVX2 panel layout: column-major buffer holding 8 logical columns with MINQ=8.
Columns: each column stores eight elements via two 256-bit chunks when T is 32-bit.
Alignment: column starts are 32-byte aligned so AVX2 loads/stores remain contiguous. */
-#define MAT_PANEL_AVX(T) MAT_PANEL_SQ_MIN(T, __m256, 8)
+#define MAT_PANEL_AVX(T) SN_ALIGNAS(32) MAT_PANEL_SQ_MIN_NOALIGN(T, __m256, 8)
/* AVX-512 panel layout: column-major buffer holding 8 or more columns depending on T.
Columns: each column expands to ceil(Q/lanes) ZMM chunks; default MINQ=8 keeps double-wide tiles.
Alignment: column starts sit on 64-byte boundaries to match AVX-512 streaming access. */
-#define MAT_PANEL_512(T) MAT_PANEL_SQ_MIN(T, __m512, 8)
+#define MAT_PANEL_512(T) SN_ALIGNAS(64) MAT_PANEL_SQ_MIN_NOALIGN(T, __m512, 8)
+
+/* Global zero kernel declaration (defined in dllmain.c), aligned to 64 bytes */
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern __declspec(align(64)) sn_zero_kernel_u64 SN_ZERO_KERNEL;
+#ifdef __cplusplus
+}
+#endif
/* Access helpers (all compile-time friendly):
Given Q = PANEL_Q(...), CH = PANEL_CHUNKS(...), R = lanes per vector:
- Column c occupies vec[c][0..CH-1].
- Row r inside column c is located at vec[c][r / R] with lane (r % R).
*/
-
-/* Global zero kernel declaration (defined in dllmain.c), aligned to 64 bytes */
-#ifdef __cplusplus
-extern "C" {
-#endif
-__declspec(align(64)) extern MAT_KERNEL(uint64_t) SN_ZERO_KERNEL;
-#ifdef __cplusplus
-}
-#endif
-
#define PANEL_COL_VEC(panel_obj, c, chunk) ((panel_obj).vec[(int)(c)][(int)(chunk)])
/* Scalar flat index helper for column-major addressing */
#define PANEL_ELEM(panel_obj, T, T_VEC, MINQ, r, c) \
((panel_obj).flat[(int)(c) * PANEL_Q(T, T_VEC, MINQ) + (int)(r)])
+/* API macros */
#define BUILD_PANEL(arch, element) build_panel_##arch##_##element
-
-#include "sn_internal.h"
+#define STORE_PANEL(arch, element) store_panel_##arch##_##element
#define DECLARE_BUILD_PANEL(arch, element) \
INTERNAL void SN_DECL BUILD_PANEL(arch, element)( \
MAT_PANEL_##arch(element) *restrict panel, \
MAT_KERNEL(element) const *const matrix, int col_length, int row_length, \
int col_index, int row_index)
+#define DECLARE_STORE_PANEL(arch, element) \
+ INTERNAL void SN_DECL STORE_PANEL(arch, element)(MAT_KERNEL(element) *restrict matrix, \
+ MAT_PANEL_##arch(element) \
+ const *const panel, \
+ int col_length, int row_length, \
+ int col_index, int row_index)
+/* Declarations for AVX float variant */
DECLARE_BUILD_PANEL(AVX, float);
+DECLARE_STORE_PANEL(AVX, float);
+
+#endif /* SN_MATKERNEL */
diff --git a/StgSharp.Native/sn-src/dllmain.c b/StgSharp.Native/sn-src/dllmain.c
index c4af815c..677a0b71 100644
--- a/StgSharp.Native/sn-src/dllmain.c
+++ b/StgSharp.Native/sn-src/dllmain.c
@@ -1,16 +1,23 @@
#include "StgSharpNative.h"
#include "sn_matkernel.h"
+#include
#ifdef _WIN32
/* Define and initialize a global zero kernel aligned to 64 bytes for universal ISA usage */
-__declspec(align(64)) MAT_KERNEL(uint64_t) SN_ZERO_KERNEL;
+#ifdef __cplusplus
+extern "C" {
+#endif
+__declspec(align(64)) sn_zero_kernel_u64 SN_ZERO_KERNEL;
+#ifdef __cplusplus
+}
+#endif
static void init_zero_kernel(void)
{
for (int c = 0; c < 4; ++c) {
for (int r = 0; r < 4; ++r) {
- SN_ZERO_KERNEL.m[r][c] = 0.0;
+ SN_ZERO_KERNEL.m[r][c] = 0;
}
}
}
diff --git a/StgSharp.Native/sn-src/k_build_panel.c b/StgSharp.Native/sn-src/k_build_panel.c
deleted file mode 100644
index 7802efa4..00000000
--- a/StgSharp.Native/sn-src/k_build_panel.c
+++ /dev/null
@@ -1,42 +0,0 @@
-#include "sn_matkernel.h"
-
-DECLARE_BUILD_PANEL(AVX, float)
-{
- const int Q = 8; /* fixed for AVX float panel */
-
- /* Neighbor kernels; substitute global zero kernel where out-of-bounds */
- const int has_right = (col_index + 1) < col_length;
- const int has_bottom = (row_index + 1) < row_length;
-
- const MAT_KERNEL(float) *const k_lt = matrix + (col_index * row_length + row_index);
- const MAT_KERNEL(float) *const k_rt =
- has_right ? (matrix + ((col_index + 1) * row_length + row_index)) :
- (const MAT_KERNEL(float) *)&SN_ZERO_KERNEL;
- const MAT_KERNEL(float) *const k_lb =
- has_bottom ? (matrix + (col_index * row_length + (row_index + 1))) :
- (const MAT_KERNEL(float) *)&SN_ZERO_KERNEL;
- const MAT_KERNEL(float) *const k_rb =
- (has_right && has_bottom) ?
- (matrix + ((col_index + 1) * row_length + (row_index + 1))) :
- (const MAT_KERNEL(float) *)&SN_ZERO_KERNEL;
-
- register __m128 top128, bot128;
- register __m256 col256;
-
- for (int pc = 0; pc < Q; ++pc) {
- const int is_right_half = (pc >= 4);
- const int kc_col = pc & 3; /* column index inside 4x4 kernel */
-
- const MAT_KERNEL(float) *src_top = is_right_half ? k_rt : k_lt;
- const MAT_KERNEL(float) *src_bot = is_right_half ? k_rb : k_lb;
-
- /* Vector loads: each kernel column is a compact __m128 */
- top128 = src_top->xmm[kc_col];
- bot128 = src_bot->xmm[kc_col];
-
- /* Combine into an AVX column: low 128 = top, high 128 = bottom */
- col256 = _mm256_set_m128(bot128, top128);
-
- PANEL_COL_VEC((*panel), pc, 0) = col256;
- }
-}
diff --git a/StgSharp.Native/sn-src/k_panel.c b/StgSharp.Native/sn-src/k_panel.c
new file mode 100644
index 00000000..ae59bea7
--- /dev/null
+++ b/StgSharp.Native/sn-src/k_panel.c
@@ -0,0 +1,98 @@
+#include "sn_matkernel.h"
+
+DECLARE_BUILD_PANEL(AVX, float)
+{
+ const int Q = 8; /* fixed for AVX float panel */
+
+ /* Neighbor kernels; substitute global zero kernel where out-of-bounds */
+ const int has_right = (col_index + 1) < col_length;
+ const int has_bottom = (row_index + 1) < row_length;
+
+ const MAT_KERNEL(float) *const k_lt = matrix + (col_index * row_length + row_index);
+ const MAT_KERNEL(float) *const k_rt =
+ has_right ? (matrix + ((col_index + 1) * row_length + row_index)) :
+ (const MAT_KERNEL(float) *)&SN_ZERO_KERNEL;
+ const MAT_KERNEL(float) *const k_lb =
+ has_bottom ? (matrix + (col_index * row_length + (row_index + 1))) :
+ (const MAT_KERNEL(float) *)&SN_ZERO_KERNEL;
+ const MAT_KERNEL(float) *const k_rb =
+ (has_right && has_bottom) ?
+ (matrix + ((col_index + 1) * row_length + (row_index + 1))) :
+ (const MAT_KERNEL(float) *)&SN_ZERO_KERNEL;
+
+ register __m128 top128, bot128;
+ register __m256 col256;
+
+ for (int pc = 0; pc < Q; ++pc) {
+ const int is_right_half = (pc >= 4);
+ const int kc_col = pc & 3; /* column index inside 4x4 kernel */
+
+ const MAT_KERNEL(float) *src_top = is_right_half ? k_rt : k_lt;
+ const MAT_KERNEL(float) *src_bot = is_right_half ? k_rb : k_lb;
+
+ /* Vector loads: each kernel column is a compact __m128 */
+ top128 = src_top->xmm[kc_col];
+ bot128 = src_bot->xmm[kc_col];
+
+ /* Combine into an AVX column: low 128 = top, high 128 = bottom */
+ col256 = _mm256_set_m128(bot128, top128);
+
+ PANEL_COL_VEC((*panel), pc, 0) = col256;
+ }
+}
+
+DECLARE_STORE_PANEL(AVX, float)
+{
+ const int Q = 8; /* fixed for AVX float panel */
+
+ /* Local dummy kernel to swallow out-of-bounds writes; no init needed */
+ MAT_KERNEL(float) zero;
+
+ const int has_right = (col_index + 1) < col_length;
+ const int has_bottom = (row_index + 1) < row_length;
+
+ MAT_KERNEL(float) *const k_lt = (col_index < col_length && row_index < row_length) ?
+ (matrix + (col_index * row_length + row_index)) :
+ &zero;
+ MAT_KERNEL(float) *const k_rt =
+ has_right && (row_index < row_length) ?
+ (matrix + ((col_index + 1) * row_length + row_index)) :
+ &zero;
+ MAT_KERNEL(float) *const k_lb =
+ has_bottom && (col_index < col_length) ?
+ (matrix + (col_index * row_length + (row_index + 1))) :
+ &zero;
+ MAT_KERNEL(float) *const k_rb =
+ (has_right && has_bottom) ?
+ (matrix + ((col_index + 1) * row_length + (row_index + 1))) :
+ &zero;
+
+ register __m128 top128, bot128;
+ int i = 0;
+ for (; i < Q / 2; i++) {
+ const int kc_col = i; /* column index inside 4x4 kernel */
+
+ /* Load the panel column vector */
+ const __m256 col256 = PANEL_COL_VEC((*panel), i, 0);
+ /* Split into top/bottom halves */
+ top128 = _mm256_castps256_ps128(col256); /* low 128 */
+ bot128 = _mm256_extractf128_ps(col256, 1); /* high 128 */
+
+ /* Store back into kernels directly (out-of-bounds writes go to dummy) */
+ k_rt->xmm[kc_col] = top128;
+ k_rb->xmm[kc_col] = bot128;
+ }
+ for (; i < Q; i++) {
+ const int kc_col = i - 4; /* column index inside 4x4 kernel */
+
+ /* Load the panel column vector */
+ const __m256 col256 = PANEL_COL_VEC((*panel), i, 0);
+ /* Split into top/bottom halves */
+ top128 = _mm256_castps256_ps128(col256); /* low 128 */
+ bot128 = _mm256_extractf128_ps(col256, 1); /* high 128 */
+
+ /* Store back into kernels directly (out-of-bounds writes go to dummy) */
+ k_lt->xmm[kc_col] = top128;
+ k_lb->xmm[kc_col] = bot128;
+ }
+}
diff --git a/StgSharp.Native/sn-src/load_intrinsic.c b/StgSharp.Native/sn-src/load_intrinsic.c
index 0e2b17d4..a13c8383 100644
--- a/StgSharp.Native/sn-src/load_intrinsic.c
+++ b/StgSharp.Native/sn-src/load_intrinsic.c
@@ -68,9 +68,10 @@ void load_intrinsic_sse(sn_intrinsic *context)
context->f32_buffer_add = BUF_PROC(float, sse, add);
context->f32_panel_fma = KER_PROC(float, sse, fma);
context->f32_buffer_fill = BUF_PROC(float, sse, fill);
- context->f32_kernel_scalar_mul = BUF_PROC(float, sse, scalar_mul);
- context->f32_kernel_sub = BUF_PROC(float, sse, sub);
- context->f32_kernel_transpose = KER_PROC(float, sse, transpose);
+ context->variant = BUF_PROC(float, sse, scalar_mul);
+ context->f32_buffer_sub = BUF_PROC(float, sse, sub);
+ context->f32_buffer_transpose = KER_PROC(float, sse, transpose);
+ context->f32_buffer_scalar_mul = BUF_PROC(float, sse, scalar_mul);
context->f32_normalize_3 = f32_normalize;
}
@@ -82,9 +83,10 @@ void load_intrinsic_avx(sn_intrinsic *context)
context->f32_buffer_add = BUF_PROC(float, avx, add);
context->f32_panel_fma = KER_PROC(float, sse, fma);
context->f32_buffer_fill = BUF_PROC(float, avx, fill);
- context->f32_kernel_scalar_mul = BUF_PROC(float, avx, scalar_mul);
- context->f32_kernel_sub = BUF_PROC(float, avx, sub);
- context->f32_kernel_transpose = KER_PROC(float, avx, transpose);
+ context->variant = BUF_PROC(float, avx, scalar_mul);
+ context->f32_buffer_sub = BUF_PROC(float, avx, sub);
+ context->f32_buffer_transpose = KER_PROC(float, avx, transpose);
+ context->f32_buffer_scalar_mul = BUF_PROC(float, avx, scalar_mul);
context->f32_normalize_3 = f32_normalize;
}
@@ -96,8 +98,9 @@ void load_intrinsic_512(sn_intrinsic *context)
context->f32_buffer_add = BUF_PROC(float, 512, add);
context->f32_panel_fma = KER_PROC(float, sse, fma);
context->f32_buffer_fill = BUF_PROC(float, 512, fill);
- context->f32_kernel_scalar_mul = BUF_PROC(float, 512, scalar_mul);
- context->f32_kernel_sub = BUF_PROC(float, 512, sub);
- context->f32_kernel_transpose = KER_PROC(float, 512, transpose);
+ context->variant = BUF_PROC(float, 512, scalar_mul);
+ context->f32_buffer_sub = BUF_PROC(float, 512, sub);
+ context->f32_buffer_transpose = KER_PROC(float, 512, transpose);
+ context->f32_buffer_scalar_mul = BUF_PROC(float, 512, scalar_mul);
context->f32_normalize_3 = f32_normalize;
}
diff --git a/StgSharpDebug/Program.cs b/StgSharpDebug/Program.cs
index d3b1c84a..85612843 100644
--- a/StgSharpDebug/Program.cs
+++ b/StgSharpDebug/Program.cs
@@ -25,10 +25,12 @@
//
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
+using StgSharp.Common.Timing;
using StgSharp.HighPerformance;
using StgSharp.HighPerformance.Memory;
using StgSharp.Internal;
using StgSharp.Mathematics.Numeric;
+using StgSharp.Timing;
namespace StgSharp
{
@@ -49,9 +51,9 @@ namespace StgSharp
// TestRender();
// TestHlsf();
+
// HlsfStressTest.Run();
- M128 v = new M128();
- /**/
+ /*
HybridLayerSegregatedFitAllocator hlsf;
unchecked {
hlsf = new((nuint)(64 * (ulong)10000 * 10000));
@@ -84,7 +86,40 @@ namespace StgSharp
Console.WriteLine();
}
/**/
+
+ // --- Logarithmic time sequence test: print seconds at each emitted span ---
+
+ // Configure a simple sequence:
+ // initial slice = 0.5s, total = 5s, growth multiplier = 2, min slice = 0.75s
+ TimeSequence seq =
/*
+ TimeSequence.CreateLogarithmic(initialSliceSeconds:0.5,
+ totalSeconds:5.0,
+ growthMultiplier:2.0,
+ minSliceSeconds:0.75);
+ /**/
+ TimeSequence.CreateLinear(5, 1);
+ /**/
+
+ // Bind to default time source provider.
+ TimeSpanProvider provider = new TimeSpanProvider(seq, TimeSpanProvider.DefaultProvider);
+
+ // Print the second mark when a span is emitted.
+ provider.TimeSpanRefreshed += (s, e) => {
+ // CurrentSecond is PreviousFrameTick / Frequency
+ Console.WriteLine($"span @ {provider.CurrentSecond:0.000}s");
+ };
+
+ // Start the time source and wait until sequence ends.
+ TimeSpanProvider.DefaultProvider.StartProvidingTime();
+
+ while (!provider.IsEnded) {
+ provider.WaitNextSpan();
+ }
+
+ TimeSpanProvider.DefaultProvider.StopProvidingTime();
+
+ // end of log-time sequence test
}
catch (Exception ex)
{