From 51c16ae0281632d6e29b273bec9fdca43d61d952 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20K=C3=B6plinger?= Date: Wed, 13 Oct 2021 22:01:51 +0200 Subject: [PATCH] Fix System.Numerics.Vectors tests on iOS and other FullAOT targets (#60335) * Fix System.Numerics.Vectors tests on iOS and other FullAOT targets Instead of using dynamic we can use explicit type checks which don't require runtime code generation. Also fixed running just a subset of xunit tests on Apple targets in tests.mobile.targets. * Disable tests that fail on x86 due to a Mono runtime asserts See https://github.com/dotnet/runtime/issues/60347 --- eng/testing/tests.mobile.targets | 6 + .../TestUtilities/System/PlatformDetection.cs | 2 + .../tests/GenericVectorTests.cs | 40 ++++ .../System.Numerics.Vectors/tests/Util.cs | 207 +++++++++++++++--- 4 files changed, 225 insertions(+), 30 deletions(-) diff --git a/eng/testing/tests.mobile.targets b/eng/testing/tests.mobile.targets index 58dbfac94db89..acce583b8a96c 100644 --- a/eng/testing/tests.mobile.targets +++ b/eng/testing/tests.mobile.targets @@ -42,6 +42,12 @@ $(AdditionalXHarnessArguments) --arg=-c=$(XUnitClassName) + + + $(AdditionalXHarnessArguments) -- -m=$(XUnitMethodName) + $(AdditionalXHarnessArguments) -- -c=$(XUnitClassName) + + diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs index baec379eece8b..c4e2e657c07ab 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs @@ -48,6 +48,8 @@ public static partial class PlatformDetection public static bool IsNotArm64Process => !IsArm64Process; public static bool IsArmOrArm64Process => IsArmProcess || IsArm64Process; public static bool IsNotArmNorArm64Process => !IsArmOrArm64Process; + public static bool IsX86Process => RuntimeInformation.ProcessArchitecture == Architecture.X86; + public static bool IsNotX86Process => !IsX86Process; public static bool IsArgIteratorSupported => IsMonoRuntime || (IsWindows && IsNotArmProcess); public static bool IsArgIteratorNotSupported => !IsArgIteratorSupported; public static bool Is32BitProcess => IntPtr.Size == 4; diff --git a/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs b/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs index f861739278f95..556e6672b806c 100644 --- a/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs +++ b/src/libraries/System.Numerics.Vectors/tests/GenericVectorTests.cs @@ -958,8 +958,10 @@ private void TestToString(string format, IFormatProvider provider) where T : [Fact] public void AdditionInt64() { TestAddition(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void AdditionSingle() { TestAddition(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void AdditionDouble() { TestAddition(); } private void TestAddition() where T : struct { @@ -1023,8 +1025,10 @@ private void TestAdditionOverflow() where T : struct [Fact] public void SubtractionInt64() { TestSubtraction(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void SubtractionSingle() { TestSubtraction(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void SubtractionDouble() { TestSubtraction(); } private void TestSubtraction() where T : struct { @@ -1088,8 +1092,10 @@ private void TestSubtractionOverflow() where T : struct [Fact] public void MultiplicationInt64() { TestMultiplication(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MultiplicationSingle() { TestMultiplication(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MultiplicationDouble() { TestMultiplication(); } private void TestMultiplication() where T : struct { @@ -1122,8 +1128,10 @@ private void TestMultiplication() where T : struct [Fact] public void MultiplicationWithScalarInt64() { TestMultiplicationWithScalar(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MultiplicationWithScalarSingle() { TestMultiplicationWithScalar(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MultiplicationWithScalarDouble() { TestMultiplicationWithScalar(); } private void TestMultiplicationWithScalar() where T : struct { @@ -1164,8 +1172,10 @@ private void TestMultiplicationWithScalar() where T : struct [Fact] public void DivisionInt64() { TestDivision(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void DivisionSingle() { TestDivision(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void DivisionDouble() { TestDivision(); } private void TestDivision() where T : struct { @@ -1224,8 +1234,10 @@ private void TestDivisionByZeroException() where T : struct [Fact] public void UnaryMinusInt64() { TestUnaryMinus(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void UnaryMinusSingle() { TestUnaryMinus(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void UnaryMinusDouble() { TestUnaryMinus(); } private void TestUnaryMinus() where T : struct { @@ -1424,8 +1436,10 @@ private void TestBitwiseAndNot() where T : struct [Fact] public void VectorGreaterThanInt64() { TestVectorGreaterThan(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void VectorGreaterThanSingle() { TestVectorGreaterThan(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void VectorGreaterThanDouble() { TestVectorGreaterThan(); } private void TestVectorGreaterThan() where T : struct { @@ -1461,8 +1475,10 @@ private void TestVectorGreaterThan() where T : struct [Fact] public void GreaterThanOrEqualInt64() { TestVectorGreaterThanOrEqual(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void GreaterThanOrEqualSingle() { TestVectorGreaterThanOrEqual(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void GreaterThanOrEqualDouble() { TestVectorGreaterThanOrEqual(); } private void TestVectorGreaterThanOrEqual() where T : struct { @@ -1714,8 +1730,10 @@ private void TestVectorGreaterThanOrEqualAll() where T : struct [Fact] public void LessThanInt64() { TestVectorLessThan(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void LessThanSingle() { TestVectorLessThan(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void LessThanDouble() { TestVectorLessThan(); } private void TestVectorLessThan() where T : struct { @@ -1751,8 +1769,10 @@ private void TestVectorLessThan() where T : struct [Fact] public void LessThanOrEqualInt64() { TestVectorLessThanOrEqual(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void LessThanOrEqualSingle() { TestVectorLessThanOrEqual(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void LessThanOrEqualDouble() { TestVectorLessThanOrEqual(); } private void TestVectorLessThanOrEqual() where T : struct { @@ -1788,8 +1808,10 @@ private void TestVectorLessThanOrEqual() where T : struct [Fact] public void LessThanAnyInt64() { TestVectorLessThanAny(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void LessThanAnySingle() { TestVectorLessThanAny(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void LessThanAnyDouble() { TestVectorLessThanAny(); } private void TestVectorLessThanAny() where T : struct { @@ -2114,8 +2136,10 @@ private void TestVectorEqualsAll() where T : struct [Fact] public void ConditionalSelectInt64() { TestConditionalSelect(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void ConditionalSelectSingle() { TestConditionalSelect(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void ConditionalSelectDouble() { TestConditionalSelect(); } private void TestConditionalSelect() where T : struct { @@ -2166,8 +2190,10 @@ private void TestConditionalSelect() where T : struct [Fact] public void DotProductInt64() { TestDotProduct(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void DotProductSingle() { TestDotProduct(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void DotProductDouble() { TestDotProduct(); } private void TestDotProduct() where T : struct { @@ -2202,8 +2228,10 @@ private void TestDotProduct() where T : struct [Fact] public void MaxInt64() { TestMax(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MaxSingle() { TestMax(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MaxDouble() { TestMax(); } private void TestMax() where T : struct { @@ -2238,8 +2266,10 @@ private void TestMax() where T : struct [Fact] public void MinInt64() { TestMin(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MinSingle() { TestMin(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MinDouble() { TestMin(); } private void TestMin() where T : struct { @@ -2274,8 +2304,10 @@ private void TestMin() where T : struct [Fact] public void SquareRootInt64() { TestSquareRoot(-1); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void SquareRootSingle() { TestSquareRoot(6); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void SquareRootDouble() { TestSquareRoot(15); } private void TestSquareRoot(int precision = -1) where T : struct, IEquatable { @@ -2368,8 +2400,10 @@ public void FloorDouble() [Fact] public void AbsInt64() { TestAbs(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void AbsSingle() { TestAbs(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void AbsDouble() { TestAbs(); } private void TestAbs() where T : struct { @@ -2406,8 +2440,10 @@ private void TestAbs() where T : struct [Fact] public void MultiplicationReflectionInt64() { TestMultiplicationReflection(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MultiplicationReflectionSingle() { TestMultiplicationReflection(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void MultiplicationReflectionDouble() { TestMultiplicationReflection(); } private void TestMultiplicationReflection() where T : struct { @@ -2443,8 +2479,10 @@ private void TestMultiplicationReflection() where T : struct [Fact] public void AdditionReflectionInt64() { TestAdditionReflection(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void AdditionReflectionSingle() { TestAdditionReflection(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void AdditionReflectionDouble() { TestAdditionReflection(); } private void TestAdditionReflection() where T : struct { @@ -2480,8 +2518,10 @@ private void TestAdditionReflection() where T : struct [Fact] public void DivisionReflectionInt64() { TestDivisionReflection(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void DivisionReflectionSingle() { TestDivisionReflection(); } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60347", typeof(PlatformDetection), nameof(PlatformDetection.IsMonoRuntime), nameof(PlatformDetection.IsX86Process))] public void DivisionReflectionDouble() { TestDivisionReflection(); } private void TestDivisionReflection() where T : struct { diff --git a/src/libraries/System.Numerics.Vectors/tests/Util.cs b/src/libraries/System.Numerics.Vectors/tests/Util.cs index 4fb55a716afd1..135b3fc0e65e4 100644 --- a/src/libraries/System.Numerics.Vectors/tests/Util.cs +++ b/src/libraries/System.Numerics.Vectors/tests/Util.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Linq; - namespace System.Numerics.Tests { public static class Util @@ -93,57 +91,150 @@ public static T GenerateSingleValue(int min = 1, int max = 100) where T : str public static T Abs(T value) where T : struct { - Type[] unsignedTypes = new[] { typeof(byte), typeof(ushort), typeof(uint), typeof(ulong) }; - if (unsignedTypes.Contains(typeof(T))) - { - return value; - } - - dynamic dyn = (dynamic)value; - var abs = Math.Abs(dyn); - T ret = (T)abs; - return ret; + // unsigned types + if (value is byte) return value; + else if (value is ushort) return value; + else if (value is uint) return value; + else if (value is ulong) return value; + // signed types + else if (value is short) return (T)(ValueType)(short) ( Math.Abs((short) (ValueType)value) ); + else if (value is int) return (T)(ValueType)(int) ( Math.Abs((int) (ValueType)value) ); + else if (value is long) return (T)(ValueType)(long) ( Math.Abs((long) (ValueType)value) ); + else if (value is sbyte) return (T)(ValueType)(sbyte) ( Math.Abs((sbyte) (ValueType)value) ); + else if (value is float) return (T)(ValueType)(float) ( Math.Abs((float) (ValueType)value) ); + else if (value is double) return (T)(ValueType)(double) ( Math.Abs((double)(ValueType)value) ); + else throw new NotImplementedException(); } public static T Sqrt(T value) where T : struct { - return unchecked((T)(dynamic)(Math.Sqrt((dynamic)value))); + unchecked + { + if (value is short) return (T)(ValueType)(short) ( Math.Sqrt((short) (ValueType)value) ); + else if (value is int) return (T)(ValueType)(int) ( Math.Sqrt((int) (ValueType)value) ); + else if (value is long) return (T)(ValueType)(long) ( Math.Sqrt((long) (ValueType)value) ); + else if (value is ushort) return (T)(ValueType)(ushort) ( Math.Sqrt((ushort)(ValueType)value) ); + else if (value is uint) return (T)(ValueType)(uint) ( Math.Sqrt((uint) (ValueType)value) ); + else if (value is ulong) return (T)(ValueType)(ulong) ( Math.Sqrt((ulong) (ValueType)value) ); + else if (value is byte) return (T)(ValueType)(byte) ( Math.Sqrt((byte) (ValueType)value) ); + else if (value is sbyte) return (T)(ValueType)(sbyte) ( Math.Sqrt((sbyte) (ValueType)value) ); + else if (value is float) return (T)(ValueType)(float) ( Math.Sqrt((float) (ValueType)value) ); + else if (value is double) return (T)(ValueType)(double) ( Math.Sqrt((double)(ValueType)value) ); + else throw new NotImplementedException(); + } } public static T Multiply(T left, T right) where T : struct { - return unchecked((T)((dynamic)left * right)); + unchecked + { + if (left is short) return (T)(ValueType)(short) ( (short) (ValueType)left * (short) (ValueType)right ); + else if (left is int) return (T)(ValueType)(int) ( (int) (ValueType)left * (int) (ValueType)right ); + else if (left is long) return (T)(ValueType)(long) ( (long) (ValueType)left * (long) (ValueType)right ); + else if (left is ushort) return (T)(ValueType)(ushort) ( (ushort)(ValueType)left * (ushort)(ValueType)right ); + else if (left is uint) return (T)(ValueType)(uint) ( (uint) (ValueType)left * (uint) (ValueType)right ); + else if (left is ulong) return (T)(ValueType)(ulong) ( (ulong) (ValueType)left * (ulong) (ValueType)right ); + else if (left is byte) return (T)(ValueType)(byte) ( (byte) (ValueType)left * (byte) (ValueType)right ); + else if (left is sbyte) return (T)(ValueType)(sbyte) ( (sbyte) (ValueType)left * (sbyte) (ValueType)right ); + else if (left is float) return (T)(ValueType)(float) ( (float) (ValueType)left * (float) (ValueType)right ); + else if (left is double) return (T)(ValueType)(double) ( (double)(ValueType)left * (double)(ValueType)right ); + else throw new NotImplementedException(); + } } public static T Divide(T left, T right) where T : struct { - return (T)((dynamic)left / right); + if (left is short) return (T)(ValueType)(short) ( (short) (ValueType)left / (short) (ValueType)right ); + else if (left is int) return (T)(ValueType)(int) ( (int) (ValueType)left / (int) (ValueType)right ); + else if (left is long) return (T)(ValueType)(long) ( (long) (ValueType)left / (long) (ValueType)right ); + else if (left is ushort) return (T)(ValueType)(ushort) ( (ushort)(ValueType)left / (ushort)(ValueType)right ); + else if (left is uint) return (T)(ValueType)(uint) ( (uint) (ValueType)left / (uint) (ValueType)right ); + else if (left is ulong) return (T)(ValueType)(ulong) ( (ulong) (ValueType)left / (ulong) (ValueType)right ); + else if (left is byte) return (T)(ValueType)(byte) ( (byte) (ValueType)left / (byte) (ValueType)right ); + else if (left is sbyte) return (T)(ValueType)(sbyte) ( (sbyte) (ValueType)left / (sbyte) (ValueType)right ); + else if (left is float) return (T)(ValueType)(float) ( (float) (ValueType)left / (float) (ValueType)right ); + else if (left is double) return (T)(ValueType)(double) ( (double)(ValueType)left / (double)(ValueType)right ); + else throw new NotImplementedException(); } public static T Add(T left, T right) where T : struct { - return unchecked((T)((dynamic)left + right)); + unchecked + { + if (left is short) return (T)(ValueType)(short) ( (short) (ValueType)left + (short) (ValueType)right ); + else if (left is int) return (T)(ValueType)(int) ( (int) (ValueType)left + (int) (ValueType)right ); + else if (left is long) return (T)(ValueType)(long) ( (long) (ValueType)left + (long) (ValueType)right ); + else if (left is ushort) return (T)(ValueType)(ushort) ( (ushort)(ValueType)left + (ushort)(ValueType)right ); + else if (left is uint) return (T)(ValueType)(uint) ( (uint) (ValueType)left + (uint) (ValueType)right ); + else if (left is ulong) return (T)(ValueType)(ulong) ( (ulong) (ValueType)left + (ulong) (ValueType)right ); + else if (left is byte) return (T)(ValueType)(byte) ( (byte) (ValueType)left + (byte) (ValueType)right ); + else if (left is sbyte) return (T)(ValueType)(sbyte) ( (sbyte) (ValueType)left + (sbyte) (ValueType)right ); + else if (left is float) return (T)(ValueType)(float) ( (float) (ValueType)left + (float) (ValueType)right ); + else if (left is double) return (T)(ValueType)(double) ( (double)(ValueType)left + (double)(ValueType)right ); + else throw new NotImplementedException(); + } } public static T Subtract(T left, T right) where T : struct { - return unchecked((T)((dynamic)left - right)); + unchecked + { + if (left is short) return (T)(ValueType)(short) ( (short) (ValueType)left - (short) (ValueType)right ); + else if (left is int) return (T)(ValueType)(int) ( (int) (ValueType)left - (int) (ValueType)right ); + else if (left is long) return (T)(ValueType)(long) ( (long) (ValueType)left - (long) (ValueType)right ); + else if (left is ushort) return (T)(ValueType)(ushort) ( (ushort)(ValueType)left - (ushort)(ValueType)right ); + else if (left is uint) return (T)(ValueType)(uint) ( (uint) (ValueType)left - (uint) (ValueType)right ); + else if (left is ulong) return (T)(ValueType)(ulong) ( (ulong) (ValueType)left - (ulong) (ValueType)right ); + else if (left is byte) return (T)(ValueType)(byte) ( (byte) (ValueType)left - (byte) (ValueType)right ); + else if (left is sbyte) return (T)(ValueType)(sbyte) ( (sbyte) (ValueType)left - (sbyte) (ValueType)right ); + else if (left is float) return (T)(ValueType)(float) ( (float) (ValueType)left - (float) (ValueType)right ); + else if (left is double) return (T)(ValueType)(double) ( (double)(ValueType)left - (double)(ValueType)right ); + else throw new NotImplementedException(); + } } public static T Xor(T left, T right) where T : struct { - return (T)((dynamic)left ^ right); + if (left is short) return (T)(ValueType)(short) ( (short) (ValueType)left ^ (short) (ValueType)right ); + else if (left is int) return (T)(ValueType)(int) ( (int) (ValueType)left ^ (int) (ValueType)right ); + else if (left is long) return (T)(ValueType)(long) ( (long) (ValueType)left ^ (long) (ValueType)right ); + else if (left is ushort) return (T)(ValueType)(ushort) ( (ushort)(ValueType)left ^ (ushort)(ValueType)right ); + else if (left is uint) return (T)(ValueType)(uint) ( (uint) (ValueType)left ^ (uint) (ValueType)right ); + else if (left is ulong) return (T)(ValueType)(ulong) ( (ulong) (ValueType)left ^ (ulong) (ValueType)right ); + else if (left is byte) return (T)(ValueType)(byte) ( (byte) (ValueType)left ^ (byte) (ValueType)right ); + else if (left is sbyte) return (T)(ValueType)(sbyte) ( (sbyte) (ValueType)left ^ (sbyte) (ValueType)right ); + else throw new NotImplementedException(); } public static T AndNot(T left, T right) where T : struct { - return (T)((dynamic)left & ~(dynamic)right); + if (left is short) return (T)(ValueType)(short) ( (short) (ValueType)left & ~(short) (ValueType)right ); + else if (left is int) return (T)(ValueType)(int) ( (int) (ValueType)left & ~(int) (ValueType)right ); + else if (left is long) return (T)(ValueType)(long) ( (long) (ValueType)left & ~(long) (ValueType)right ); + else if (left is ushort) return (T)(ValueType)(ushort) ( (ushort)(ValueType)left & ~(ushort)(ValueType)right ); + else if (left is uint) return (T)(ValueType)(uint) ( (uint) (ValueType)left & ~(uint) (ValueType)right ); + else if (left is ulong) return (T)(ValueType)(ulong) ( (ulong) (ValueType)left & ~(ulong) (ValueType)right ); + else if (left is byte) return (T)(ValueType)(byte) ( (byte) (ValueType)left & ~(byte) (ValueType)right ); + else if (left is sbyte) return (T)(ValueType)(sbyte) ( (sbyte) (ValueType)left & ~(sbyte) (ValueType)right ); + else throw new NotImplementedException(); } public static T OnesComplement(T left) where T : struct { - return unchecked((T)(~(dynamic)left)); + unchecked + { + if (left is short) return (T)(ValueType)(short) ( ~(short) (ValueType)left ); + else if (left is int) return (T)(ValueType)(int) ( ~(int) (ValueType)left ); + else if (left is long) return (T)(ValueType)(long) ( ~(long) (ValueType)left ); + else if (left is ushort) return (T)(ValueType)(ushort) ( ~(ushort)(ValueType)left ); + else if (left is uint) return (T)(ValueType)(uint) ( ~(uint) (ValueType)left ); + else if (left is ulong) return (T)(ValueType)(ulong) ( ~(ulong) (ValueType)left ); + else if (left is byte) return (T)(ValueType)(byte) ( ~(byte) (ValueType)left ); + else if (left is sbyte) return (T)(ValueType)(sbyte) ( ~(sbyte) (ValueType)left ); + else throw new NotImplementedException(); + } } + public static float Clamp(float value, float min, float max) { return value > max ? max : value < min ? min : value; @@ -151,36 +242,92 @@ public static float Clamp(float value, float min, float max) public static T Zero() where T : struct { - return (T)(dynamic)0; + if (typeof(T) == typeof(short)) return (T)(ValueType)(short) 0; + else if (typeof(T) == typeof(int)) return (T)(ValueType)(int) 0; + else if (typeof(T) == typeof(long)) return (T)(ValueType)(long) 0; + else if (typeof(T) == typeof(ushort)) return (T)(ValueType)(ushort) 0; + else if (typeof(T) == typeof(uint)) return (T)(ValueType)(uint) 0; + else if (typeof(T) == typeof(ulong)) return (T)(ValueType)(ulong) 0; + else if (typeof(T) == typeof(byte)) return (T)(ValueType)(byte) 0; + else if (typeof(T) == typeof(sbyte)) return (T)(ValueType)(sbyte) 0; + else if (typeof(T) == typeof(float)) return (T)(ValueType)(float) 0; + else if (typeof(T) == typeof(double)) return (T)(ValueType)(double) 0; + else throw new NotImplementedException(); } public static T One() where T : struct { - return (T)(dynamic)1; + if (typeof(T) == typeof(short)) return (T)(ValueType)(short) 1; + else if (typeof(T) == typeof(int)) return (T)(ValueType)(int) 1; + else if (typeof(T) == typeof(long)) return (T)(ValueType)(long) 1; + else if (typeof(T) == typeof(ushort)) return (T)(ValueType)(ushort) 1; + else if (typeof(T) == typeof(uint)) return (T)(ValueType)(uint) 1; + else if (typeof(T) == typeof(ulong)) return (T)(ValueType)(ulong) 1; + else if (typeof(T) == typeof(byte)) return (T)(ValueType)(byte) 1; + else if (typeof(T) == typeof(sbyte)) return (T)(ValueType)(sbyte) 1; + else if (typeof(T) == typeof(float)) return (T)(ValueType)(float) 1; + else if (typeof(T) == typeof(double)) return (T)(ValueType)(double) 1; + else throw new NotImplementedException(); } public static bool GreaterThan(T left, T right) where T : struct { - var result = (dynamic)left > right; - return (bool)result; + if (left is short) return (short)(ValueType) left > (short)(ValueType) right; + else if (left is int) return (int)(ValueType) left > (int)(ValueType) right; + else if (left is long) return (long)(ValueType) left > (long)(ValueType) right; + else if (left is ushort) return (ushort)(ValueType) left > (ushort)(ValueType) right; + else if (left is uint) return (uint)(ValueType) left > (uint)(ValueType) right; + else if (left is ulong) return (ulong)(ValueType) left > (ulong)(ValueType) right; + else if (left is byte) return (byte)(ValueType) left > (byte)(ValueType) right; + else if (left is sbyte) return (sbyte)(ValueType) left > (sbyte)(ValueType) right; + else if (left is float) return (float)(ValueType) left > (float)(ValueType) right; + else if (left is double) return (double)(ValueType) left > (double)(ValueType) right; + else throw new NotImplementedException(); } public static bool GreaterThanOrEqual(T left, T right) where T : struct { - var result = (dynamic)left >= right; - return (bool)result; + if (left is short) return (short)(ValueType) left >= (short)(ValueType) right; + else if (left is int) return (int)(ValueType) left >= (int)(ValueType) right; + else if (left is long) return (long)(ValueType) left >= (long)(ValueType) right; + else if (left is ushort) return (ushort)(ValueType) left >= (ushort)(ValueType) right; + else if (left is uint) return (uint)(ValueType) left >= (uint)(ValueType) right; + else if (left is ulong) return (ulong)(ValueType) left >= (ulong)(ValueType) right; + else if (left is byte) return (byte)(ValueType) left >= (byte)(ValueType) right; + else if (left is sbyte) return (sbyte)(ValueType) left >= (sbyte)(ValueType) right; + else if (left is float) return (float)(ValueType) left >= (float)(ValueType) right; + else if (left is double) return (double)(ValueType) left >= (double)(ValueType) right; + else throw new NotImplementedException(); } public static bool LessThan(T left, T right) where T : struct { - var result = (dynamic)left < right; - return (bool)result; + if (left is short) return (short)(ValueType) left < (short)(ValueType) right; + else if (left is int) return (int)(ValueType) left < (int)(ValueType) right; + else if (left is long) return (long)(ValueType) left < (long)(ValueType) right; + else if (left is ushort) return (ushort)(ValueType) left < (ushort)(ValueType) right; + else if (left is uint) return (uint)(ValueType) left < (uint)(ValueType) right; + else if (left is ulong) return (ulong)(ValueType) left < (ulong)(ValueType) right; + else if (left is byte) return (byte)(ValueType) left < (byte)(ValueType) right; + else if (left is sbyte) return (sbyte)(ValueType) left < (sbyte)(ValueType) right; + else if (left is float) return (float)(ValueType) left < (float)(ValueType) right; + else if (left is double) return (double)(ValueType) left < (double)(ValueType) right; + else throw new NotImplementedException(); } public static bool LessThanOrEqual(T left, T right) where T : struct { - var result = (dynamic)left <= right; - return (bool)result; + if (left is short) return (short)(ValueType) left <= (short)(ValueType) right; + else if (left is int) return (int)(ValueType) left <= (int)(ValueType) right; + else if (left is long) return (long)(ValueType) left <= (long)(ValueType) right; + else if (left is ushort) return (ushort)(ValueType) left <= (ushort)(ValueType) right; + else if (left is uint) return (uint)(ValueType) left <= (uint)(ValueType) right; + else if (left is ulong) return (ulong)(ValueType) left <= (ulong)(ValueType) right; + else if (left is byte) return (byte)(ValueType) left <= (byte)(ValueType) right; + else if (left is sbyte) return (sbyte)(ValueType) left <= (sbyte)(ValueType) right; + else if (left is float) return (float)(ValueType) left <= (float)(ValueType) right; + else if (left is double) return (double)(ValueType) left <= (double)(ValueType) right; + else throw new NotImplementedException(); } public static bool AnyEqual(T[] left, T[] right) where T : struct