using System.Diagnostics.Contracts; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using StitchATon2.Infra.Buffers; namespace StitchATon2.Domain; public static class Utils { [Pure] public static string GetSBSNotation(int row) => row <= 26 ? new string([(char)(row + 'A' - 1)]) : new string(['A', (char)(row + 'A' - 27)]); [Pure, MethodImpl(MethodImplOptions.AggressiveInlining)] private static int DivCeil(int a, int b) { return (a + b - 1) / b; } [Pure] public static (int Column, int Row) GetSBSCoordinate(string coordinate) { var column = coordinate[^1] - '0'; if(char.IsDigit(coordinate[^2])) column += 10 * (coordinate[^2] - '0'); var row = char.IsLetter(coordinate[1]) ? 26 + coordinate[1] - 'A' + 1 : coordinate[0] - 'A' + 1; return (column, row); } /// /// Performs a SIMD-accelerated calculation that generates a buffer of bounded, scaled indices. /// /// The amount by which to scale the sequence values. /// The total number of scalar values to generate. /// Upper limit (exclusive) for clamping values. /// The offset to apply before clamping. public static IBuffer BoundsMatrix(float scaleFactor, int length, int max, int offset) { var vectorSize = DivCeil(length, Vector.Count); using var buffer = MemoryAllocator.Allocate>(vectorSize); var span = buffer.Span; var vectorMin = Vector.Zero; var vectorOffset = new Vector(offset - 1); var vectorMax = new Vector(max - 1); var vectorScale = new Vector(scaleFactor); var vectorSequence = Vector.CreateSequence(0f, 1f); var seq = 0f; for (var i = 0; i < vectorSize; i++, seq += Vector.Count) { var sequence = new Vector(seq) + vectorSequence; span[i] = Vector.FusedMultiplyAdd(sequence, vectorScale, vectorScale); span[i] = Vector.Ceiling(span[i]); } var result = MemoryAllocator.Allocate(vectorSize * Vector.Count); var resultSpan = MemoryMarshal.Cast>(result.Span); for (var i = 0; i < vectorSize; i++) { resultSpan[i] = Vector.ConvertToInt32(span[i]); resultSpan[i] = Vector.Add(resultSpan[i], vectorOffset); resultSpan[i] = Vector.ClampNative(resultSpan[i], vectorMin, vectorMax); } return result; } }