using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; namespace Craftimizer.Solver; public struct NodeScoresBuffer { [StructLayout(LayoutKind.Auto)] public struct ScoresBatch { public Vector256 ScoreSum; public Vector256 MaxScore; public Vector256 Visits; } public ScoresBatch[]? Data; public int Count { get; private set; } public void Add() { Data ??= GC.AllocateUninitializedArray(ArenaBuffer.BatchCount); var count = Count++; if ((count & ArenaBuffer.BatchSizeMask) == 0) Data[count >> ArenaBuffer.BatchSizeBits] = new(); } public readonly void Visit((int arrayIdx, int subIdx) at, float score) { ref var batch = ref Data![at.arrayIdx]; batch.ScoreSum.At(at.subIdx) += score; ref var maxScore = ref batch.MaxScore.At(at.subIdx); maxScore = Math.Max(maxScore, score); batch.Visits.At(at.subIdx)++; } public readonly int GetVisits((int arrayIdx, int subIdx) at) => Data![at.arrayIdx].Visits[at.subIdx]; } internal static class VectorUtils { public static ref T At(this ref Vector256 me, int idx) => ref Unsafe.Add(ref Unsafe.As, T>(ref me), idx); }