mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-14 19:29:36 +01:00
* Move to Central Package Management. Allows us to store NuGet package versions all in one place. Yay! * Update NuGet packages and fix code for changes. Notable: Changes to ILVerify. Npgsql doesn't need hacks for inet anymore, now we need hacks to make the old code work with this new reality. NUnit's analyzers are already complaining and I didn't even update it to 4.x yet. TerraFX changed to GetLastSystemError so error handling had to be changed. Buncha APIs have more NRT annotations. * Remove dotnet-eng NuGet package source. I genuinely don't know what this was for, and Central Package Management starts throwing warnings about it, so YEET. * Fix double loading of assemblies due to ALC shenanigans. Due to how the "sideloading" code for the ModLoader was set up, it would first try to load Microsoft.Extensions.Primitives from next to the content dll. But we already have that library in Robust! Chaos ensues. We now try to forcibly prioritize loading from the default ALC first to avoid this. * Remove Robust.Physics project. Never used. * Remove erroneous NVorbis reference. Should be VorbisPizza and otherwise wasn't used. * Sandbox fixes * Remove unused unit test package references. Castle.Core and NUnit.ConsoleRunner. * Update NUnit to 4.0.1 This requires replacing all the old assertion methods because they removed them 🥲 * Mute CA1416 (platform check) errors TerraFX started annotating APIs with this and I can't be arsed to entertain this analyzer so out it goes. * Fine ya cranky, no more CPM for Robust.Client.Injectors * Changelog * Oh so that's what dotnet-eng was used for. Yeah ok that makes sense. * Central package management for remaining 2 robust projects * Ok that was a bad idea let's just use NUnit 3 on the analyzer test project * Oh right forgot to remove this one * Update to a newer version of RemoteExecutor * Disable RemoteExecutor test https://github.com/dotnet/arcade/issues/8483 Yeah this package is not well maintained and clearly we can't rely on it. * Fix immutable list serialization
1007 lines
22 KiB
C#
1007 lines
22 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Runtime.Intrinsics.X86;
|
|
using NUnit.Framework;
|
|
using Robust.Shared.Maths;
|
|
using Microsoft.DotNet.RemoteExecutor;
|
|
using System.Runtime.Intrinsics.Arm;
|
|
|
|
namespace Robust.UnitTesting.Shared.Maths
|
|
{
|
|
[Parallelizable(ParallelScope.All | ParallelScope.Fixtures)]
|
|
[TestFixture]
|
|
[TestOf(typeof(NumericsHelpers))]
|
|
[SuppressMessage("ReSharper", "AccessToStaticMemberViaDerivedType")]
|
|
public sealed class NumericsHelpers_Test
|
|
{
|
|
#region Utils
|
|
|
|
private static RemoteInvokeOptions GetInvokeOptions(bool avxEnabled = false)
|
|
{
|
|
var processStartInfo = new ProcessStartInfo();
|
|
|
|
processStartInfo.Environment[NumericsHelpers.AvxEnvironmentVariable] = avxEnabled.ToString();
|
|
|
|
return new RemoteInvokeOptions() { StartInfo = processStartInfo };
|
|
}
|
|
|
|
[Flags]
|
|
enum Intrinsics : byte
|
|
{
|
|
None = 0,
|
|
Sse = 1 << 1,
|
|
Sse2 = 1 << 2,
|
|
Sse3 = 1 << 3,
|
|
Avx = 1 << 4,
|
|
Avx2 = 1 << 5,
|
|
|
|
AdvSimd = 1 << 6,
|
|
AdvSimdArm64 = 1 << 7,
|
|
|
|
AllX86 = Sse | Sse2 | Sse3 | Avx | Avx2,
|
|
AllArm = AdvSimd | AdvSimdArm64,
|
|
}
|
|
|
|
private static bool ValidComputer(Intrinsics flags = Intrinsics.None)
|
|
{
|
|
if (!RemoteExecutor.IsSupported)
|
|
return false;
|
|
|
|
if (flags == Intrinsics.None)
|
|
return true;
|
|
|
|
// I realize we could do a bitwise AND operation here, but this isn't really written for performance.
|
|
if (flags.HasFlag(Intrinsics.Sse) && !Sse.IsSupported)
|
|
return false;
|
|
|
|
if (flags.HasFlag(Intrinsics.Sse2) && !Sse2.IsSupported)
|
|
return false;
|
|
|
|
if (flags.HasFlag(Intrinsics.Sse3) && !Sse3.IsSupported)
|
|
return false;
|
|
|
|
if (flags.HasFlag(Intrinsics.Avx) && !Avx.IsSupported)
|
|
return false;
|
|
|
|
if (flags.HasFlag(Intrinsics.Avx2) && !Avx2.IsSupported)
|
|
return false;
|
|
|
|
if (flags.HasFlag(Intrinsics.AdvSimd) && !AdvSimd.IsSupported)
|
|
return false;
|
|
|
|
if (flags.HasFlag(Intrinsics.AdvSimdArm64) && !AdvSimd.IsSupported)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
private void EqualsApprox(ReadOnlySpan<float> a, ReadOnlySpan<float> b, double tolerance = .00001)
|
|
{
|
|
Assert.That(a.Length, Is.EqualTo(b.Length));
|
|
|
|
for (var i = 0; i < a.Length; i++)
|
|
{
|
|
Assert.That(b[i], Is.Approximately(a[i], tolerance));
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
/*
|
|
[Test]
|
|
public void EnvironmentVariablesWorkAvx()
|
|
{
|
|
// The next one is only valid if the computer supports AVX.
|
|
if (!ValidComputer(Intrinsics.Avx2))
|
|
Assert.Ignore();
|
|
|
|
// Enabling NumericsHelper and enabling AVX.
|
|
RemoteExecutor.Invoke(() => { Assert.That(NumericsHelpers.Vector256Enabled, Is.True); },
|
|
GetInvokeOptions(true)).Dispose();
|
|
}
|
|
*/
|
|
|
|
#region Multiply
|
|
|
|
private static readonly float[] MultiplyA =
|
|
{
|
|
1f,
|
|
0f,
|
|
1f,
|
|
2f,
|
|
10f,
|
|
0.1f,
|
|
1234f,
|
|
678.234f,
|
|
};
|
|
|
|
private static readonly float[] MultiplyB =
|
|
{
|
|
1f,
|
|
0f,
|
|
0f,
|
|
2f,
|
|
10f,
|
|
1f,
|
|
4321f,
|
|
567.123f,
|
|
};
|
|
|
|
private static readonly float[] MultiplyResult =
|
|
{
|
|
1f,
|
|
0f,
|
|
0f,
|
|
4f,
|
|
100f,
|
|
0.1f,
|
|
5332114f,
|
|
384642.101f,
|
|
};
|
|
|
|
[Test]
|
|
public void MultiplyScalar()
|
|
{
|
|
Span<float> s = stackalloc float[MultiplyResult.Length];
|
|
|
|
NumericsHelpers.MultiplyScalar(MultiplyA, MultiplyB, s, 0, MultiplyA.Length);
|
|
|
|
EqualsApprox(MultiplyResult, s);
|
|
}
|
|
|
|
[Test]
|
|
public void Multiply128()
|
|
{
|
|
Span<float> s = stackalloc float[MultiplyResult.Length];
|
|
|
|
NumericsHelpers.Multiply128(MultiplyA, MultiplyB, s);
|
|
|
|
EqualsApprox(MultiplyResult, s);
|
|
}
|
|
|
|
[Test]
|
|
public void Multiply256()
|
|
{
|
|
Span<float> s = stackalloc float[MultiplyResult.Length];
|
|
|
|
NumericsHelpers.Multiply256(MultiplyA, MultiplyB, s);
|
|
|
|
EqualsApprox(MultiplyResult, s);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region MultiplyByScalar
|
|
|
|
private static readonly float[] MultiplyByScalarA =
|
|
{
|
|
1f,
|
|
0f,
|
|
0.01f,
|
|
2f,
|
|
10f,
|
|
0.1f,
|
|
1234f,
|
|
678.234f,
|
|
};
|
|
|
|
private const float MultiplyByScalarB = 50f;
|
|
|
|
private static readonly float[] MultiplyByScalarResult =
|
|
{
|
|
50f,
|
|
0f,
|
|
0.5f,
|
|
100f,
|
|
500f,
|
|
5f,
|
|
61700f,
|
|
33911.7f,
|
|
};
|
|
|
|
|
|
[Test]
|
|
public void MultiplyByScalarScalar()
|
|
{
|
|
Span<float> s = stackalloc float[MultiplyByScalarResult.Length];
|
|
|
|
NumericsHelpers.MultiplyScalar(MultiplyByScalarA, MultiplyByScalarB, s, 0, MultiplyByScalarA.Length);
|
|
|
|
EqualsApprox(MultiplyByScalarResult, s);
|
|
}
|
|
|
|
[Test]
|
|
public void MultiplyByScalar128()
|
|
{
|
|
Span<float> s = stackalloc float[MultiplyByScalarResult.Length];
|
|
|
|
NumericsHelpers.Multiply128(MultiplyByScalarA, MultiplyByScalarB, s);
|
|
|
|
EqualsApprox(MultiplyByScalarResult, s);
|
|
}
|
|
|
|
[Test]
|
|
public void MultiplyByScalar256()
|
|
{
|
|
Span<float> s = stackalloc float[MultiplyByScalarResult.Length];
|
|
|
|
NumericsHelpers.Multiply256(MultiplyByScalarA, MultiplyByScalarB, s);
|
|
|
|
EqualsApprox(MultiplyByScalarResult, s);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Divide
|
|
|
|
private static readonly float[] DivideA =
|
|
{
|
|
1f,
|
|
0f,
|
|
1f,
|
|
2f,
|
|
100f,
|
|
0.1f,
|
|
1234f,
|
|
678.234f,
|
|
};
|
|
|
|
private static readonly float[] DivideB =
|
|
{
|
|
1f,
|
|
1f,
|
|
2f,
|
|
2f,
|
|
10f,
|
|
1f,
|
|
4321f,
|
|
567.123f,
|
|
};
|
|
|
|
private static readonly float[] DivideResult =
|
|
{
|
|
1f,
|
|
0f,
|
|
0.5f,
|
|
1f,
|
|
10f,
|
|
0.1f,
|
|
0.285582041f,
|
|
1.19592046f,
|
|
};
|
|
|
|
[Test]
|
|
public void DivideScalar()
|
|
{
|
|
Span<float> s = stackalloc float[DivideResult.Length];
|
|
|
|
NumericsHelpers.DivideScalar(DivideA, DivideB, s, 0, DivideA.Length);
|
|
|
|
EqualsApprox(DivideResult, s);
|
|
}
|
|
|
|
[Test]
|
|
public void Divide128()
|
|
{
|
|
Span<float> s = stackalloc float[DivideResult.Length];
|
|
|
|
NumericsHelpers.Divide128(DivideA, DivideB, s);
|
|
|
|
EqualsApprox(DivideResult, s);
|
|
}
|
|
|
|
[Test]
|
|
public void Divide256()
|
|
{
|
|
Span<float> s = stackalloc float[DivideResult.Length];
|
|
|
|
NumericsHelpers.Divide256(DivideA, DivideB, s);
|
|
|
|
EqualsApprox(DivideResult, s);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region DivideByScalar
|
|
|
|
private static readonly float[] DivideByScalarA =
|
|
{
|
|
1f,
|
|
0f,
|
|
10000f,
|
|
2000f,
|
|
1234f,
|
|
9999f,
|
|
12340f,
|
|
678.234f,
|
|
};
|
|
|
|
private const float DivideByScalarB = 1234f;
|
|
|
|
private static readonly float[] DivideByScalarResult =
|
|
{
|
|
0.000810372771f,
|
|
0f,
|
|
8.10372771f,
|
|
1.62074554f,
|
|
1f,
|
|
8.10291734f,
|
|
10f,
|
|
0.549622366f,
|
|
};
|
|
|
|
[Test]
|
|
public void DivideByScalarScalar()
|
|
{
|
|
Span<float> s = stackalloc float[DivideByScalarResult.Length];
|
|
|
|
NumericsHelpers.DivideScalar(DivideByScalarA, DivideByScalarB, s, 0, DivideByScalarA.Length);
|
|
|
|
EqualsApprox(DivideByScalarResult, s);
|
|
}
|
|
|
|
[Test]
|
|
public void DivideByScalar128()
|
|
{
|
|
Span<float> s = stackalloc float[DivideByScalarResult.Length];
|
|
|
|
NumericsHelpers.Divide128(DivideByScalarA, DivideByScalarB, s);
|
|
|
|
EqualsApprox(DivideByScalarResult, s);
|
|
}
|
|
|
|
[Test]
|
|
public void DivideByScalar256()
|
|
{
|
|
Span<float> s = stackalloc float[DivideByScalarResult.Length];
|
|
|
|
NumericsHelpers.Divide256(DivideByScalarA, DivideByScalarB, s);
|
|
|
|
EqualsApprox(DivideByScalarResult, s);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Add
|
|
|
|
private static readonly float[] AddA =
|
|
{
|
|
1f,
|
|
0f,
|
|
1f,
|
|
2f,
|
|
100f,
|
|
0.1f,
|
|
1234f,
|
|
678.234f,
|
|
1f,
|
|
};
|
|
|
|
private static readonly float[] AddB =
|
|
{
|
|
1f,
|
|
1f,
|
|
2f,
|
|
2f,
|
|
10f,
|
|
1f,
|
|
4321f,
|
|
567.123f,
|
|
-1f,
|
|
};
|
|
|
|
private static readonly float[] AddResult =
|
|
{
|
|
2f,
|
|
1f,
|
|
3f,
|
|
4f,
|
|
110f,
|
|
1.1f,
|
|
5555f,
|
|
1245.357f,
|
|
0f,
|
|
};
|
|
|
|
[Test]
|
|
public void AddScalar()
|
|
{
|
|
Span<float> s = stackalloc float[AddResult.Length];
|
|
|
|
NumericsHelpers.AddScalar(AddA, AddB, s, 0, AddA.Length);
|
|
|
|
EqualsApprox(AddResult, s);
|
|
}
|
|
|
|
[Test]
|
|
public void Add128()
|
|
{
|
|
Span<float> s = stackalloc float[AddResult.Length];
|
|
|
|
NumericsHelpers.Add128(AddA, AddB, s);
|
|
|
|
EqualsApprox(AddResult, s);
|
|
}
|
|
|
|
[Test]
|
|
public void Add256()
|
|
{
|
|
Span<float> s = stackalloc float[AddResult.Length];
|
|
|
|
NumericsHelpers.Add256(AddA, AddB, s);
|
|
|
|
EqualsApprox(AddResult, s);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region AddByScalar
|
|
|
|
private static readonly float[] AddByScalarA =
|
|
{
|
|
1f,
|
|
0f,
|
|
15f,
|
|
2f,
|
|
100f,
|
|
0.1f,
|
|
1234f,
|
|
678.234f,
|
|
};
|
|
|
|
private const float AddByScalarB = 100f;
|
|
|
|
private static readonly float[] AddByScalarResult =
|
|
{
|
|
101f,
|
|
100f,
|
|
115f,
|
|
102f,
|
|
200f,
|
|
100.1f,
|
|
1334f,
|
|
778.234f,
|
|
};
|
|
|
|
[Test]
|
|
public void AddByScalarScalar()
|
|
{
|
|
Span<float> s = stackalloc float[AddByScalarResult.Length];
|
|
|
|
NumericsHelpers.AddScalar(AddByScalarA, AddByScalarB, s, 0, AddByScalarA.Length);
|
|
|
|
EqualsApprox(AddByScalarResult, s);
|
|
}
|
|
|
|
[Test]
|
|
public void AddByScalar128()
|
|
{
|
|
Span<float> s = stackalloc float[AddByScalarResult.Length];
|
|
|
|
NumericsHelpers.Add128(AddByScalarA, AddByScalarB, s);
|
|
|
|
EqualsApprox(AddByScalarResult, s);
|
|
}
|
|
|
|
[Test]
|
|
public void AddByScalar256()
|
|
{
|
|
Span<float> s = stackalloc float[AddByScalarResult.Length];
|
|
|
|
NumericsHelpers.Add256(AddByScalarA, AddByScalarB, s);
|
|
|
|
EqualsApprox(AddByScalarResult, s);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region HorizontalAdd
|
|
|
|
private static readonly float[] HorizontalAddA =
|
|
{
|
|
1f,
|
|
0f,
|
|
1f,
|
|
2f,
|
|
100f,
|
|
0.1f,
|
|
1234f,
|
|
678.234f,
|
|
10f,
|
|
1f,
|
|
0f,
|
|
1f,
|
|
2f,
|
|
100f,
|
|
0.1f,
|
|
1234f,
|
|
678.234f,
|
|
};
|
|
|
|
private const float HorizontalAddResult = 4042.668f;
|
|
|
|
[Test]
|
|
public void HorizontalAddScalar()
|
|
{
|
|
var added = NumericsHelpers.HorizontalAddScalar(HorizontalAddA, 0, HorizontalAddA.Length);
|
|
|
|
Assert.That(added, Is.Approximately(HorizontalAddResult));
|
|
}
|
|
|
|
[Test]
|
|
public void HorizontalAdd128()
|
|
{
|
|
var added = NumericsHelpers.HorizontalAdd128(HorizontalAddA);
|
|
|
|
Assert.That(added, Is.Approximately(HorizontalAddResult));
|
|
}
|
|
|
|
[Test]
|
|
public void HorizontalAdd256()
|
|
{
|
|
var added = NumericsHelpers.HorizontalAdd256(HorizontalAddA);
|
|
|
|
Assert.That(added, Is.Approximately(HorizontalAddResult));
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Sub
|
|
|
|
private static readonly float[] SubA =
|
|
{
|
|
1f,
|
|
0f,
|
|
1f,
|
|
2f,
|
|
100f,
|
|
0.1f,
|
|
1234f,
|
|
678.234f,
|
|
};
|
|
|
|
private static readonly float[] SubB =
|
|
{
|
|
1f,
|
|
1f,
|
|
2f,
|
|
2f,
|
|
10f,
|
|
1f,
|
|
4321f,
|
|
567.123f,
|
|
};
|
|
|
|
private static readonly float[] SubResult =
|
|
{
|
|
0f,
|
|
-1f,
|
|
-1f,
|
|
0f,
|
|
90f,
|
|
-0.9f,
|
|
-3087f,
|
|
111.11100f,
|
|
};
|
|
|
|
[Test]
|
|
public void SubScalar()
|
|
{
|
|
Span<float> s = stackalloc float[SubResult.Length];
|
|
|
|
NumericsHelpers.SubScalar(SubA, SubB, s, 0, SubA.Length);
|
|
|
|
EqualsApprox(SubResult, s);
|
|
}
|
|
|
|
[Test]
|
|
public void Sub128()
|
|
{
|
|
Span<float> s = stackalloc float[SubResult.Length];
|
|
|
|
NumericsHelpers.Sub128(SubA, SubB, s);
|
|
|
|
EqualsApprox(SubResult, s);
|
|
}
|
|
|
|
[Test]
|
|
public void Sub256()
|
|
{
|
|
Span<float> s = stackalloc float[SubResult.Length];
|
|
|
|
NumericsHelpers.Sub256(SubA, SubB, s);
|
|
|
|
EqualsApprox(SubResult, s);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region SubByScalar
|
|
|
|
private static readonly float[] SubByScalarA =
|
|
{
|
|
1f,
|
|
0f,
|
|
15f,
|
|
2f,
|
|
100f,
|
|
0.1f,
|
|
1234f,
|
|
678.234f,
|
|
};
|
|
|
|
private const float SubByScalarB = 100f;
|
|
|
|
private static readonly float[] SubByScalarResult =
|
|
{
|
|
-99f,
|
|
-100f,
|
|
-85f,
|
|
-98f,
|
|
0f,
|
|
-99.9f,
|
|
1134f,
|
|
578.234f,
|
|
};
|
|
|
|
[Test]
|
|
public void SubByScalarScalar()
|
|
{
|
|
Span<float> s = stackalloc float[SubByScalarResult.Length];
|
|
|
|
NumericsHelpers.SubScalar(SubByScalarA, SubByScalarB, s, 0, SubByScalarA.Length);
|
|
|
|
EqualsApprox(SubByScalarResult, s);
|
|
}
|
|
|
|
[Test]
|
|
public void SubByScalar128()
|
|
{
|
|
Span<float> s = stackalloc float[SubByScalarResult.Length];
|
|
|
|
NumericsHelpers.Sub128(SubByScalarA, SubByScalarB, s);
|
|
|
|
EqualsApprox(SubByScalarResult, s);
|
|
}
|
|
|
|
[Test]
|
|
public void SubByScalar256()
|
|
{
|
|
Span<float> s = stackalloc float[SubByScalarResult.Length];
|
|
|
|
NumericsHelpers.Sub256(SubByScalarA, SubByScalarB, s);
|
|
|
|
EqualsApprox(SubByScalarResult, s);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Abs
|
|
|
|
private static readonly float[] AbsA =
|
|
{
|
|
-1f,
|
|
0f,
|
|
-0f,
|
|
-15f,
|
|
-2f,
|
|
100f,
|
|
0.1f,
|
|
-1234f,
|
|
-678.234f,
|
|
};
|
|
|
|
private static readonly float[] AbsResult =
|
|
{
|
|
1f,
|
|
0f,
|
|
0f,
|
|
15f,
|
|
2f,
|
|
100f,
|
|
0.1f,
|
|
1234f,
|
|
678.234f,
|
|
};
|
|
|
|
[Test]
|
|
public void AbsScalar()
|
|
{
|
|
Span<float> s = stackalloc float[AbsResult.Length];
|
|
|
|
NumericsHelpers.AbsScalar(AbsA, s, 0, AbsA.Length);
|
|
|
|
EqualsApprox(AbsResult, s);
|
|
}
|
|
|
|
[Test]
|
|
public void Abs128()
|
|
{
|
|
Span<float> s = stackalloc float[AbsResult.Length];
|
|
|
|
NumericsHelpers.Abs128(AbsA, s);
|
|
|
|
EqualsApprox(AbsResult, s);
|
|
}
|
|
|
|
[Test]
|
|
public void Abs256()
|
|
{
|
|
Span<float> s = stackalloc float[AbsResult.Length];
|
|
|
|
NumericsHelpers.Abs256(AbsA, s);
|
|
|
|
EqualsApprox(AbsResult, s);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Min
|
|
|
|
private static readonly float[] MinA =
|
|
{
|
|
1f,
|
|
0f,
|
|
1f,
|
|
2f,
|
|
100f,
|
|
0.1f,
|
|
1234f,
|
|
678.234f,
|
|
};
|
|
|
|
private static readonly float[] MinB =
|
|
{
|
|
1f,
|
|
1f,
|
|
2f,
|
|
2f,
|
|
10f,
|
|
1f,
|
|
4321f,
|
|
567.123f,
|
|
};
|
|
|
|
private static readonly float[] MinResult =
|
|
{
|
|
1f,
|
|
0f,
|
|
1f,
|
|
2f,
|
|
10f,
|
|
0.1f,
|
|
1234f,
|
|
567.123f,
|
|
};
|
|
|
|
[Test]
|
|
public void MinScalar()
|
|
{
|
|
Span<float> s = stackalloc float[MinResult.Length];
|
|
|
|
NumericsHelpers.MinScalar(MinA, MinB, s, 0, MinA.Length);
|
|
|
|
EqualsApprox(MinResult, s);
|
|
}
|
|
|
|
[Test]
|
|
public void Min128()
|
|
{
|
|
Span<float> s = stackalloc float[MinResult.Length];
|
|
|
|
NumericsHelpers.Min128(MinA, MinB, s);
|
|
|
|
EqualsApprox(MinResult, s);
|
|
}
|
|
|
|
[Test]
|
|
public void Min256()
|
|
{
|
|
Span<float> s = stackalloc float[MinResult.Length];
|
|
|
|
NumericsHelpers.Min256(MinA, MinB, s);
|
|
|
|
EqualsApprox(MinResult, s);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region MinByScalar
|
|
|
|
private static readonly float[] MinByScalarA =
|
|
{
|
|
1f,
|
|
0f,
|
|
1f,
|
|
2f,
|
|
100f,
|
|
0.1f,
|
|
1234f,
|
|
678.234f,
|
|
0.05f,
|
|
0.5f,
|
|
-12.5f,
|
|
};
|
|
|
|
private const float MinByScalarB = 1f;
|
|
|
|
private static readonly float[] MinByScalarR =
|
|
{
|
|
1f,
|
|
0f,
|
|
1f,
|
|
1f,
|
|
1f,
|
|
0.1f,
|
|
1f,
|
|
1f,
|
|
0.05f,
|
|
0.5f,
|
|
-12.5f,
|
|
};
|
|
|
|
[Test]
|
|
public void MinByScalarScalar()
|
|
{
|
|
Span<float> s = stackalloc float[MinByScalarR.Length];
|
|
|
|
NumericsHelpers.MinScalar(MinByScalarA, MinByScalarB, s, 0, MinByScalarA.Length);
|
|
|
|
EqualsApprox(MinByScalarR, s);
|
|
}
|
|
|
|
[Test]
|
|
public void MinByScalar128()
|
|
{
|
|
Span<float> s = stackalloc float[MinByScalarR.Length];
|
|
|
|
NumericsHelpers.Min128(MinByScalarA, MinByScalarB, s);
|
|
|
|
EqualsApprox(MinByScalarR, s);
|
|
}
|
|
|
|
[Test]
|
|
public void MinByScalar256()
|
|
{
|
|
Span<float> s = stackalloc float[MinByScalarR.Length];
|
|
|
|
NumericsHelpers.Min256(MinByScalarA, MinByScalarB, s);
|
|
|
|
EqualsApprox(MinByScalarR, s);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Max
|
|
|
|
private static readonly float[] MaxA =
|
|
{
|
|
1f,
|
|
0f,
|
|
1f,
|
|
2f,
|
|
100f,
|
|
0.1f,
|
|
1234f,
|
|
678.234f,
|
|
};
|
|
|
|
private static readonly float[] MaxB =
|
|
{
|
|
1f,
|
|
1f,
|
|
2f,
|
|
2f,
|
|
10f,
|
|
1f,
|
|
4321f,
|
|
567.123f,
|
|
};
|
|
|
|
private static readonly float[] MaxResult =
|
|
{
|
|
1f,
|
|
1f,
|
|
2f,
|
|
2f,
|
|
100f,
|
|
1f,
|
|
4321f,
|
|
678.234f,
|
|
};
|
|
|
|
[Test]
|
|
public void MaxScalar()
|
|
{
|
|
Span<float> s = stackalloc float[MaxResult.Length];
|
|
|
|
NumericsHelpers.MaxScalar(MaxA, MaxB, s, 0, MaxA.Length);
|
|
|
|
EqualsApprox(MaxResult, s);
|
|
}
|
|
|
|
[Test]
|
|
public void Max128()
|
|
{
|
|
Span<float> s = stackalloc float[MaxResult.Length];
|
|
|
|
NumericsHelpers.Max128(MaxA, MaxB, s);
|
|
|
|
EqualsApprox(MaxResult, s);
|
|
}
|
|
|
|
[Test]
|
|
public void Max256()
|
|
{
|
|
Span<float> s = stackalloc float[MaxResult.Length];
|
|
|
|
NumericsHelpers.Max256(MaxA, MaxB, s);
|
|
|
|
EqualsApprox(MaxResult, s);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region MaxByScalar
|
|
|
|
private static readonly float[] MaxByScalarA =
|
|
{
|
|
1f,
|
|
0f,
|
|
1f,
|
|
200f,
|
|
100f,
|
|
0.1f,
|
|
1234f,
|
|
678.234f,
|
|
};
|
|
|
|
private const float MaxByScalarB = 100f;
|
|
|
|
private static readonly float[] MaxByScalarResult =
|
|
{
|
|
100f,
|
|
100f,
|
|
100f,
|
|
200f,
|
|
100f,
|
|
100f,
|
|
1234f,
|
|
678.234f,
|
|
};
|
|
|
|
[Test]
|
|
public void MaxByScalarScalar()
|
|
{
|
|
Span<float> s = stackalloc float[MaxByScalarResult.Length];
|
|
|
|
NumericsHelpers.MaxScalar(MaxByScalarA, MaxByScalarB, s, 0, MaxByScalarA.Length);
|
|
|
|
EqualsApprox(MaxByScalarResult, s);
|
|
}
|
|
|
|
[Test]
|
|
public void MaxByScalar128()
|
|
{
|
|
Span<float> s = stackalloc float[MaxByScalarResult.Length];
|
|
|
|
NumericsHelpers.Max128(MaxByScalarA, MaxByScalarB, s);
|
|
|
|
EqualsApprox(MaxByScalarResult, s);
|
|
}
|
|
|
|
[Test]
|
|
public void MaxByScalar256()
|
|
{
|
|
Span<float> s = stackalloc float[MaxByScalarResult.Length];
|
|
|
|
NumericsHelpers.Max256(MaxByScalarA, MaxByScalarB, s);
|
|
|
|
EqualsApprox(MaxByScalarResult, s);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|