using System; using System.Runtime.CompilerServices; using System.Runtime.Intrinsics; namespace Robust.Shared.Maths { public static unsafe partial class NumericsHelpers { #region Sub /// /// Subtracts b to a and stores the result in a. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Sub(Span a, ReadOnlySpan b) { Sub(a, b, a); } /// /// Subtracts b to a and stores the result in s. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Sub(ReadOnlySpan a, ReadOnlySpan b, Span s) { if (a.Length != b.Length || a.Length != s.Length) throw new ArgumentException("Length of arrays must be the same!"); if (Vector256Enabled && LengthValid256Single(a.Length)) { Sub256(a, b, s); return; } Sub128(a, b, s); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void SubScalar(ReadOnlySpan a, ReadOnlySpan b, Span s, int start, int end) { for (var i = start; i < end; i++) { s[i] = a[i] - b[i]; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Sub128(ReadOnlySpan a, ReadOnlySpan b, Span s) { var remainder = a.Length & (Vector128.Count - 1); var length = a.Length - remainder; fixed (float* ptr = a) fixed (float* ptrB = b) fixed (float* ptrS = s) { for (var i = 0; i < length; i += Vector128.Count) { var j = Vector128.Load(ptr + i); var k = Vector128.Load(ptrB + i); Vector128.Subtract(j, k).Store(ptrS + i); } } if (remainder != 0) { SubScalar(a, b, s, length, a.Length); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Sub256(ReadOnlySpan a, ReadOnlySpan b, Span s) { var remainder = a.Length & (Vector256.Count - 1); var length = a.Length - remainder; fixed (float* ptr = a) fixed (float* ptrB = b) fixed (float* ptrS = s) { for (var i = 0; i < length; i += Vector256.Count) { var j = Vector256.Load(ptr + i); var k = Vector256.Load(ptrB + i); Vector256.Subtract(j, k).Store(ptrS + i); } } if (remainder != 0) { SubScalar(a, b, s, length, a.Length); } } #endregion #region SubByScalar /// /// Subtracts scalar b to a and stores the result in a. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Sub(Span a, float b) { Sub(a, b, a); } /// /// Subtracts scalar b to a and stores the result in s. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Sub(ReadOnlySpan a, float b, Span s) { if (a.Length != s.Length) throw new ArgumentException("Length of arrays must be the same!"); if (Vector256Enabled && LengthValid256Single(a.Length)) { Sub256(a, b, s); return; } Sub128(a, b, s); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void SubScalar(ReadOnlySpan a, float b, Span s, int start, int end) { for (var i = start; i < end; i++) { s[i] = a[i] - b; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Sub128(ReadOnlySpan a, float b, Span s) { var remainder = a.Length & (Vector128.Count - 1); var length = a.Length - remainder; var scalar = Vector128.Create(b); fixed (float* ptr = a) fixed (float* ptrS = s) { for (var i = 0; i < length; i += Vector128.Count) { var j = Vector128.Load(ptr + i); Vector128.Subtract(j, scalar).Store(ptrS + i); } } if (remainder != 0) { SubScalar(a, b, s, length, a.Length); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Sub256(ReadOnlySpan a, float b, Span s) { var remainder = a.Length & (Vector256.Count - 1); var length = a.Length - remainder; var scalar = Vector256.Create(b); fixed (float* ptr = a) fixed (float* ptrS = s) { for (var i = 0; i < length; i += Vector256.Count) { var j = Vector256.Load(ptr + i); Vector256.Subtract(j, scalar).Store(ptrS + i); } } if (remainder != 0) { SubScalar(a, b, s, length, a.Length); } } #endregion } }