Updating Complex to implement INumberBase and ISignedNumber (#68612)
authorTanner Gooding <tagoo@outlook.com>
Sat, 7 May 2022 00:19:10 +0000 (17:19 -0700)
committerGitHub <noreply@github.com>
Sat, 7 May 2022 00:19:10 +0000 (17:19 -0700)
* Updating Complex to implement INumberBase and ISignedNumber

* Adding generic math tests for Complex

* Fixing some generic math tests for Complex to match the current behavior around -0

* Update src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs

Co-authored-by: Drew Kersnar <dakersnar@me.com>
Co-authored-by: Drew Kersnar <dakersnar@me.com>
src/libraries/System.Runtime.Numerics/ref/System.Runtime.Numerics.cs
src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs
src/libraries/System.Runtime.Numerics/tests/ComplexTests.GenericMath.cs [new file with mode: 0644]
src/libraries/System.Runtime.Numerics/tests/System.Runtime.Numerics.Tests.csproj

index 8abdc6b..974d233 100644 (file)
@@ -165,7 +165,7 @@ namespace System.Numerics
         public static bool TryParse([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] string? value, out System.Numerics.BigInteger result) { throw null; }
         public bool TryWriteBytes(System.Span<byte> destination, out int bytesWritten, bool isUnsigned = false, bool isBigEndian = false) { throw null; }
     }
-    public readonly partial struct Complex : System.IEquatable<System.Numerics.Complex>, System.IFormattable
+    public readonly partial struct Complex : System.IEquatable<System.Numerics.Complex>, System.IFormattable, System.ISpanFormattable, System.Numerics.IAdditionOperators<System.Numerics.Complex, System.Numerics.Complex, System.Numerics.Complex>, System.Numerics.IAdditiveIdentity<System.Numerics.Complex, System.Numerics.Complex>, System.Numerics.IDecrementOperators<System.Numerics.Complex>, System.Numerics.IDivisionOperators<System.Numerics.Complex, System.Numerics.Complex, System.Numerics.Complex>, System.Numerics.IEqualityOperators<System.Numerics.Complex, System.Numerics.Complex>, System.Numerics.IIncrementOperators<System.Numerics.Complex>, System.Numerics.IMultiplicativeIdentity<System.Numerics.Complex, System.Numerics.Complex>, System.Numerics.IMultiplyOperators<System.Numerics.Complex, System.Numerics.Complex, System.Numerics.Complex>, System.Numerics.INumberBase<System.Numerics.Complex>, System.Numerics.ISignedNumber<System.Numerics.Complex>, System.Numerics.ISubtractionOperators<System.Numerics.Complex, System.Numerics.Complex, System.Numerics.Complex>, System.Numerics.IUnaryNegationOperators<System.Numerics.Complex, System.Numerics.Complex>, System.Numerics.IUnaryPlusOperators<System.Numerics.Complex, System.Numerics.Complex>
     {
         private readonly int _dummyPrimitive;
         public static readonly System.Numerics.Complex ImaginaryOne;
@@ -178,6 +178,11 @@ namespace System.Numerics
         public double Magnitude { get { throw null; } }
         public double Phase { get { throw null; } }
         public double Real { get { throw null; } }
+        static System.Numerics.Complex System.Numerics.IAdditiveIdentity<System.Numerics.Complex, System.Numerics.Complex>.AdditiveIdentity { get { throw null; } }
+        static System.Numerics.Complex System.Numerics.IMultiplicativeIdentity<System.Numerics.Complex, System.Numerics.Complex>.MultiplicativeIdentity { get { throw null; } }
+        static System.Numerics.Complex System.Numerics.INumberBase<System.Numerics.Complex>.One { get { throw null; } }
+        static System.Numerics.Complex System.Numerics.INumberBase<System.Numerics.Complex>.Zero { get { throw null; } }
+        static System.Numerics.Complex System.Numerics.ISignedNumber<System.Numerics.Complex>.NegativeOne { get { throw null; } }
         public static double Abs(System.Numerics.Complex value) { throw null; }
         public static System.Numerics.Complex Acos(System.Numerics.Complex value) { throw null; }
         public static System.Numerics.Complex Add(double left, System.Numerics.Complex right) { throw null; }
@@ -209,6 +214,7 @@ namespace System.Numerics
         public static System.Numerics.Complex operator +(double left, System.Numerics.Complex right) { throw null; }
         public static System.Numerics.Complex operator +(System.Numerics.Complex left, double right) { throw null; }
         public static System.Numerics.Complex operator +(System.Numerics.Complex left, System.Numerics.Complex right) { throw null; }
+        public static System.Numerics.Complex operator --(System.Numerics.Complex value) { throw null; }
         public static System.Numerics.Complex operator /(double left, System.Numerics.Complex right) { throw null; }
         public static System.Numerics.Complex operator /(System.Numerics.Complex left, double right) { throw null; }
         public static System.Numerics.Complex operator /(System.Numerics.Complex left, System.Numerics.Complex right) { throw null; }
@@ -229,6 +235,7 @@ namespace System.Numerics
         public static implicit operator System.Numerics.Complex (uint value) { throw null; }
         [System.CLSCompliantAttribute(false)]
         public static implicit operator System.Numerics.Complex (ulong value) { throw null; }
+        public static System.Numerics.Complex operator ++(System.Numerics.Complex value) { throw null; }
         public static bool operator !=(System.Numerics.Complex left, System.Numerics.Complex right) { throw null; }
         public static System.Numerics.Complex operator *(double left, System.Numerics.Complex right) { throw null; }
         public static System.Numerics.Complex operator *(System.Numerics.Complex left, double right) { throw null; }
@@ -237,17 +244,27 @@ namespace System.Numerics
         public static System.Numerics.Complex operator -(System.Numerics.Complex left, double right) { throw null; }
         public static System.Numerics.Complex operator -(System.Numerics.Complex left, System.Numerics.Complex right) { throw null; }
         public static System.Numerics.Complex operator -(System.Numerics.Complex value) { throw null; }
+        public static System.Numerics.Complex operator +(System.Numerics.Complex value) { throw null; }
         public static System.Numerics.Complex Pow(System.Numerics.Complex value, double power) { throw null; }
         public static System.Numerics.Complex Pow(System.Numerics.Complex value, System.Numerics.Complex power) { throw null; }
         public static System.Numerics.Complex Reciprocal(System.Numerics.Complex value) { throw null; }
         public static System.Numerics.Complex Sin(System.Numerics.Complex value) { throw null; }
         public static System.Numerics.Complex Sinh(System.Numerics.Complex value) { throw null; }
         public static System.Numerics.Complex Sqrt(System.Numerics.Complex value) { throw null; }
+        static System.Numerics.Complex System.Numerics.IAdditionOperators<System.Numerics.Complex, System.Numerics.Complex, System.Numerics.Complex>.operator checked +(System.Numerics.Complex left, System.Numerics.Complex right) { throw null; }
+        static System.Numerics.Complex System.Numerics.IDecrementOperators<System.Numerics.Complex>.operator checked --(System.Numerics.Complex value) { throw null; }
+        static System.Numerics.Complex System.Numerics.IDivisionOperators<System.Numerics.Complex, System.Numerics.Complex, System.Numerics.Complex>.operator checked /(System.Numerics.Complex left, System.Numerics.Complex right) { throw null; }
+        static System.Numerics.Complex System.Numerics.IIncrementOperators<System.Numerics.Complex>.operator checked ++(System.Numerics.Complex value) { throw null; }
+        static System.Numerics.Complex System.Numerics.IMultiplyOperators<System.Numerics.Complex, System.Numerics.Complex, System.Numerics.Complex>.operator checked *(System.Numerics.Complex left, System.Numerics.Complex right) { throw null; }
+        static System.Numerics.Complex System.Numerics.ISubtractionOperators<System.Numerics.Complex, System.Numerics.Complex, System.Numerics.Complex>.operator checked -(System.Numerics.Complex left, System.Numerics.Complex right) { throw null; }
+        static System.Numerics.Complex System.Numerics.IUnaryNegationOperators<System.Numerics.Complex, System.Numerics.Complex>.operator checked -(System.Numerics.Complex value) { throw null; }
         public static System.Numerics.Complex Subtract(double left, System.Numerics.Complex right) { throw null; }
         public static System.Numerics.Complex Subtract(System.Numerics.Complex left, double right) { throw null; }
         public static System.Numerics.Complex Subtract(System.Numerics.Complex left, System.Numerics.Complex right) { throw null; }
+        public bool TryFormat(System.Span<char> destination, out int charsWritten, System.ReadOnlySpan<char> format, System.IFormatProvider? provider) { throw null; }
         public static System.Numerics.Complex Tan(System.Numerics.Complex value) { throw null; }
         public static System.Numerics.Complex Tanh(System.Numerics.Complex value) { throw null; }
+
         public override string ToString() { throw null; }
         public string ToString(System.IFormatProvider? provider) { throw null; }
         public string ToString([System.Diagnostics.CodeAnalysis.StringSyntaxAttribute("NumericFormat")] string? format) { throw null; }
index 7a91d7e..db60888 100644 (file)
@@ -3,6 +3,7 @@
 
 using System.Diagnostics;
 using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
 using System.Runtime.CompilerServices;
 
 namespace System.Numerics
@@ -13,7 +14,11 @@ namespace System.Numerics
     /// </summary>
     [Serializable]
     [TypeForwardedFrom("System.Numerics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
-    public readonly struct Complex : IEquatable<Complex>, IFormattable
+    public readonly struct Complex
+        : IEquatable<Complex>,
+          IFormattable,
+          INumberBase<Complex>,
+          ISignedNumber<Complex>
     {
         public static readonly Complex Zero = new Complex(0.0, 0.0);
         public static readonly Complex One = new Complex(1.0, 0.0);
@@ -849,5 +854,145 @@ namespace System.Numerics
         {
             return new Complex((double)value, 0.0);
         }
+
+        //
+        // IAdditionOperators
+        //
+
+        /// <inheritdoc cref="IAdditionOperators{TSelf, TOther, TResult}.op_Addition(TSelf, TOther)" />
+        static Complex IAdditionOperators<Complex, Complex, Complex>.operator checked +(Complex left, Complex right) => left + right;
+
+        //
+        // IAdditiveIdentity
+        //
+
+        /// <inheritdoc cref="IAdditiveIdentity{TSelf, TResult}.AdditiveIdentity" />
+        static Complex IAdditiveIdentity<Complex, Complex>.AdditiveIdentity => new Complex(0.0, 0.0);
+
+        //
+        // IDecrementOperators
+        //
+
+        /// <inheritdoc cref="IDecrementOperators{TSelf}.op_Decrement(TSelf)" />
+        public static Complex operator --(Complex value) => value - One;
+
+        /// <inheritdoc cref="IDecrementOperators{TSelf}.op_Decrement(TSelf)" />
+        static Complex IDecrementOperators<Complex>.operator checked --(Complex value) => --value;
+
+        //
+        // IDivisionOperators
+        //
+
+        /// <inheritdoc cref="IDivisionOperators{TSelf, TOther, TResult}.op_CheckedDivision(TSelf, TOther)" />
+        static Complex IDivisionOperators<Complex, Complex, Complex>.operator checked /(Complex left, Complex right) => left / right;
+
+        //
+        // IIncrementOperators
+        //
+
+        /// <inheritdoc cref="IIncrementOperators{TSelf}.op_Increment(TSelf)" />
+        public static Complex operator ++(Complex value) => value + One;
+
+        /// <inheritdoc cref="IIncrementOperators{TSelf}.op_CheckedIncrement(TSelf)" />
+        static Complex IIncrementOperators<Complex>.operator checked ++(Complex value) => ++value;
+
+        //
+        // IMultiplicativeIdentity
+        //
+
+        /// <inheritdoc cref="IMultiplicativeIdentity{TSelf, TResult}.MultiplicativeIdentity" />
+        static Complex IMultiplicativeIdentity<Complex, Complex>.MultiplicativeIdentity => new Complex(1.0, 0.0);
+
+        //
+        // IMultiplyOperators
+        //
+
+        /// <inheritdoc cref="IMultiplyOperators{TSelf, TOther, TResult}.op_CheckedMultiply(TSelf, TOther)" />
+        static Complex IMultiplyOperators<Complex, Complex, Complex>.operator checked *(Complex left, Complex right) => left * right;
+
+        //
+        // INumberBase
+        //
+
+        /// <inheritdoc cref="INumberBase{TSelf}.One" />
+        static Complex INumberBase<Complex>.One => new Complex(1.0, 0.0);
+
+        /// <inheritdoc cref="INumberBase{TSelf}.Zero" />
+        static Complex INumberBase<Complex>.Zero => new Complex(0.0, 0.0);
+
+        //
+        // ISignedNumber
+        //
+
+        /// <inheritdoc cref="ISignedNumber{TSelf}.NegativeOne" />
+        static Complex ISignedNumber<Complex>.NegativeOne => new Complex(-1.0, 0.0);
+
+        //
+        // ISpanFormattable
+        //
+
+        /// <inheritdoc cref="ISpanFormattable.TryFormat(Span{char}, out int, ReadOnlySpan{char}, IFormatProvider?)" />
+        public bool TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider? provider)
+        {
+            int charsWrittenSoFar = 0;
+
+            // We have at least 6 more characters for: (0, 0)
+            if (destination.Length < 6)
+            {
+                charsWritten = charsWrittenSoFar;
+                return false;
+            }
+
+            destination[charsWrittenSoFar++] = '(';
+
+            bool tryFormatSucceeded = m_real.TryFormat(destination.Slice(charsWrittenSoFar), out int tryFormatCharsWritten, format, provider);
+            charsWrittenSoFar += tryFormatCharsWritten;
+
+            // We have at least 4 more characters for: , 0)
+            if (!tryFormatSucceeded || (destination.Length < (charsWrittenSoFar + 4)))
+            {
+                charsWritten = charsWrittenSoFar;
+                return false;
+            }
+
+            destination[charsWrittenSoFar++] = ',';
+            destination[charsWrittenSoFar++] = ' ';
+
+            tryFormatSucceeded = m_imaginary.TryFormat(destination.Slice(charsWrittenSoFar), out tryFormatCharsWritten, format, provider);
+            charsWrittenSoFar += tryFormatCharsWritten;
+
+            // We have at least 1 more character for: )
+            if (!tryFormatSucceeded || (destination.Length < (charsWrittenSoFar + 1)))
+            {
+                charsWritten = charsWrittenSoFar;
+                return false;
+            }
+
+            destination[charsWrittenSoFar++] = ')';
+
+            charsWritten = charsWrittenSoFar;
+            return true;
+        }
+
+        //
+        // ISubtractionOperators
+        //
+
+        /// <inheritdoc cref="ISubtractionOperators{TSelf, TOther, TResult}.op_CheckedSubtraction(TSelf, TOther)" />
+        static Complex ISubtractionOperators<Complex, Complex, Complex>.operator checked -(Complex left, Complex right) => left - right;
+
+        //
+        // IUnaryNegationOperators
+        //
+
+        /// <inheritdoc cref="IUnaryNegationOperators{TSelf, TResult}.op_CheckedUnaryNegation(TSelf)" />
+        static Complex IUnaryNegationOperators<Complex, Complex>.operator checked -(Complex value) => -value;
+
+        //
+        // IUnaryPlusOperators
+        //
+
+        /// <inheritdoc cref="IUnaryPlusOperators{TSelf, TResult}.op_UnaryPlus(TSelf)" />
+        public static Complex operator +(Complex value) => value;
     }
 }
diff --git a/src/libraries/System.Runtime.Numerics/tests/ComplexTests.GenericMath.cs b/src/libraries/System.Runtime.Numerics/tests/ComplexTests.GenericMath.cs
new file mode 100644 (file)
index 0000000..6ed1401
--- /dev/null
@@ -0,0 +1,306 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Xunit;
+
+namespace System.Numerics.Tests
+{
+    public class ComplexTests_GenericMath
+    {
+        private static Complex MinNormal => 2.2250738585072014E-308;
+
+        private static Complex MaxSubnormal => 2.2250738585072009E-308;
+
+        private static void AssertBitwiseEqual(double expected, double actual)
+        {
+            ulong expectedBits = BitConverter.DoubleToUInt64Bits(expected);
+            ulong actualBits = BitConverter.DoubleToUInt64Bits(actual);
+
+            if (expectedBits == actualBits)
+            {
+                return;
+            }
+
+            if (Complex.IsNaN(expected) && Complex.IsNaN(actual))
+            {
+                return;
+            }
+
+            throw new Xunit.Sdk.EqualException(expected, actual);
+        }
+
+        private static void AssertBitwiseEqual(Complex expected, Complex actual)
+        {
+            AssertBitwiseEqual(expected.Real, actual.Real);
+            AssertBitwiseEqual(expected.Imaginary, actual.Imaginary);
+        }
+
+        [Fact]
+        public static void AdditiveIdentityTest()
+        {
+            AssertBitwiseEqual(0.0, AdditiveIdentityHelper<Complex, Complex>.AdditiveIdentity);
+        }
+
+        [Fact]
+        public static void MultiplicativeIdentityTest()
+        {
+            AssertBitwiseEqual(1.0, MultiplicativeIdentityHelper<Complex, Complex>.MultiplicativeIdentity);
+        }
+
+        [Fact]
+        public static void NegativeOneTest()
+        {
+            Assert.Equal(-1.0, SignedNumberHelper<Complex>.NegativeOne);
+        }
+
+        [Fact]
+        public static void OneTest()
+        {
+            AssertBitwiseEqual(1.0, NumberBaseHelper<Complex>.One);
+        }
+
+        [Fact]
+        public static void ZeroTest()
+        {
+            AssertBitwiseEqual(0.0, NumberBaseHelper<Complex>.Zero);
+        }
+
+        [Fact]
+        public static void op_AdditionTest()
+        {
+            AssertBitwiseEqual(0.0, AdditionOperatorsHelper<Complex, Complex, Complex>.op_Addition(-1.0, 1.0));
+            AssertBitwiseEqual(1.0, AdditionOperatorsHelper<Complex, Complex, Complex>.op_Addition(-MinNormal, 1.0));
+            AssertBitwiseEqual(1.0, AdditionOperatorsHelper<Complex, Complex, Complex>.op_Addition(-MaxSubnormal, 1.0));
+            AssertBitwiseEqual(1.0, AdditionOperatorsHelper<Complex, Complex, Complex>.op_Addition(-0.0, 1.0));
+            AssertBitwiseEqual(Complex.NaN, AdditionOperatorsHelper<Complex, Complex, Complex>.op_Addition(Complex.NaN, 1.0));
+            AssertBitwiseEqual(1.0, AdditionOperatorsHelper<Complex, Complex, Complex>.op_Addition(0.0, 1.0));
+            AssertBitwiseEqual(1.0, AdditionOperatorsHelper<Complex, Complex, Complex>.op_Addition(MaxSubnormal, 1.0));
+            AssertBitwiseEqual(1.0, AdditionOperatorsHelper<Complex, Complex, Complex>.op_Addition(MinNormal, 1.0));
+            AssertBitwiseEqual(2.0, AdditionOperatorsHelper<Complex, Complex, Complex>.op_Addition(1.0, 1.0));
+        }
+
+        [Fact]
+        public static void op_CheckedAdditionTest()
+        {
+            AssertBitwiseEqual(0.0, AdditionOperatorsHelper<Complex, Complex, Complex>.op_CheckedAddition(-1.0, 1.0));
+            AssertBitwiseEqual(1.0, AdditionOperatorsHelper<Complex, Complex, Complex>.op_CheckedAddition(-MinNormal, 1.0));
+            AssertBitwiseEqual(1.0, AdditionOperatorsHelper<Complex, Complex, Complex>.op_CheckedAddition(-MaxSubnormal, 1.0));
+            AssertBitwiseEqual(1.0, AdditionOperatorsHelper<Complex, Complex, Complex>.op_CheckedAddition(-0.0, 1.0));
+            AssertBitwiseEqual(Complex.NaN, AdditionOperatorsHelper<Complex, Complex, Complex>.op_CheckedAddition(Complex.NaN, 1.0));
+            AssertBitwiseEqual(1.0, AdditionOperatorsHelper<Complex, Complex, Complex>.op_CheckedAddition(0.0, 1.0));
+            AssertBitwiseEqual(1.0, AdditionOperatorsHelper<Complex, Complex, Complex>.op_CheckedAddition(MaxSubnormal, 1.0));
+            AssertBitwiseEqual(1.0, AdditionOperatorsHelper<Complex, Complex, Complex>.op_CheckedAddition(MinNormal, 1.0));
+            AssertBitwiseEqual(2.0, AdditionOperatorsHelper<Complex, Complex, Complex>.op_CheckedAddition(1.0, 1.0));
+        }
+
+        [Fact]
+        public static void op_DecrementTest()
+        {
+            AssertBitwiseEqual(-2.0, DecrementOperatorsHelper<Complex>.op_Decrement(-1.0));
+            AssertBitwiseEqual(new Complex(-1.0, -0.0), DecrementOperatorsHelper<Complex>.op_Decrement(-MinNormal));
+            AssertBitwiseEqual(new Complex(-1.0, -0.0), DecrementOperatorsHelper<Complex>.op_Decrement(-MaxSubnormal));
+            AssertBitwiseEqual(-1.0, DecrementOperatorsHelper<Complex>.op_Decrement(-0.0));
+            AssertBitwiseEqual(Complex.NaN, DecrementOperatorsHelper<Complex>.op_Decrement(Complex.NaN));
+            AssertBitwiseEqual(-1.0, DecrementOperatorsHelper<Complex>.op_Decrement(0.0));
+            AssertBitwiseEqual(-1.0, DecrementOperatorsHelper<Complex>.op_Decrement(MaxSubnormal));
+            AssertBitwiseEqual(-1.0, DecrementOperatorsHelper<Complex>.op_Decrement(MinNormal));
+            AssertBitwiseEqual(0.0, DecrementOperatorsHelper<Complex>.op_Decrement(1.0));
+        }
+
+        [Fact]
+        public static void op_CheckedDecrementTest()
+        {
+            AssertBitwiseEqual(-2.0, DecrementOperatorsHelper<Complex>.op_CheckedDecrement(-1.0));
+            AssertBitwiseEqual(new Complex(-1.0, -0.0), DecrementOperatorsHelper<Complex>.op_CheckedDecrement(-MinNormal));
+            AssertBitwiseEqual(new Complex(-1.0, -0.0), DecrementOperatorsHelper<Complex>.op_CheckedDecrement(-MaxSubnormal));
+            AssertBitwiseEqual(-1.0, DecrementOperatorsHelper<Complex>.op_CheckedDecrement(-0.0));
+            AssertBitwiseEqual(Complex.NaN, DecrementOperatorsHelper<Complex>.op_CheckedDecrement(Complex.NaN));
+            AssertBitwiseEqual(-1.0, DecrementOperatorsHelper<Complex>.op_CheckedDecrement(0.0));
+            AssertBitwiseEqual(-1.0, DecrementOperatorsHelper<Complex>.op_CheckedDecrement(MaxSubnormal));
+            AssertBitwiseEqual(-1.0, DecrementOperatorsHelper<Complex>.op_CheckedDecrement(MinNormal));
+            AssertBitwiseEqual(0.0, DecrementOperatorsHelper<Complex>.op_CheckedDecrement(1.0));
+        }
+
+        [Fact]
+        public static void op_DivisionTest()
+        {
+            AssertBitwiseEqual(-0.5, DivisionOperatorsHelper<Complex, Complex, Complex>.op_Division(-1.0, 2.0));
+            AssertBitwiseEqual(-1.1125369292536007E-308, DivisionOperatorsHelper<Complex, Complex, Complex>.op_Division(-MinNormal, 2.0));
+            AssertBitwiseEqual(-1.1125369292536007E-308, DivisionOperatorsHelper<Complex, Complex, Complex>.op_Division(-MaxSubnormal, 2.0));
+            AssertBitwiseEqual(0.0, DivisionOperatorsHelper<Complex, Complex, Complex>.op_Division(-0.0, 2.0));
+            AssertBitwiseEqual(Complex.NaN, DivisionOperatorsHelper<Complex, Complex, Complex>.op_Division(Complex.NaN, 2.0));
+            AssertBitwiseEqual(0.0, DivisionOperatorsHelper<Complex, Complex, Complex>.op_Division(0.0, 2.0));
+            AssertBitwiseEqual(1.1125369292536007E-308, DivisionOperatorsHelper<Complex, Complex, Complex>.op_Division(MaxSubnormal, 2.0));
+            AssertBitwiseEqual(1.1125369292536007E-308, DivisionOperatorsHelper<Complex, Complex, Complex>.op_Division(MinNormal, 2.0));
+            AssertBitwiseEqual(0.5, DivisionOperatorsHelper<Complex, Complex, Complex>.op_Division(1.0, 2.0));
+        }
+
+        [Fact]
+        public static void op_CheckedDivisionTest()
+        {
+            AssertBitwiseEqual(-0.5, DivisionOperatorsHelper<Complex, Complex, Complex>.op_CheckedDivision(-1.0, 2.0));
+            AssertBitwiseEqual(-1.1125369292536007E-308, DivisionOperatorsHelper<Complex, Complex, Complex>.op_CheckedDivision(-MinNormal, 2.0));
+            AssertBitwiseEqual(-1.1125369292536007E-308, DivisionOperatorsHelper<Complex, Complex, Complex>.op_CheckedDivision(-MaxSubnormal, 2.0));
+            AssertBitwiseEqual(0.0, DivisionOperatorsHelper<Complex, Complex, Complex>.op_CheckedDivision(-0.0, 2.0));
+            AssertBitwiseEqual(Complex.NaN, DivisionOperatorsHelper<Complex, Complex, Complex>.op_CheckedDivision(Complex.NaN, 2.0));
+            AssertBitwiseEqual(0.0, DivisionOperatorsHelper<Complex, Complex, Complex>.op_CheckedDivision(0.0, 2.0));
+            AssertBitwiseEqual(1.1125369292536007E-308, DivisionOperatorsHelper<Complex, Complex, Complex>.op_CheckedDivision(MaxSubnormal, 2.0));
+            AssertBitwiseEqual(1.1125369292536007E-308, DivisionOperatorsHelper<Complex, Complex, Complex>.op_CheckedDivision(MinNormal, 2.0));
+            AssertBitwiseEqual(0.5, DivisionOperatorsHelper<Complex, Complex, Complex>.op_CheckedDivision(1.0, 2.0));
+        }
+
+        [Fact]
+        public static void op_EqualityTest()
+        {
+            Assert.False(EqualityOperatorsHelper<Complex, Complex>.op_Equality(-1.0, 1.0));
+            Assert.False(EqualityOperatorsHelper<Complex, Complex>.op_Equality(-MinNormal, 1.0));
+            Assert.False(EqualityOperatorsHelper<Complex, Complex>.op_Equality(-MaxSubnormal, 1.0));
+            Assert.False(EqualityOperatorsHelper<Complex, Complex>.op_Equality(-0.0, 1.0));
+            Assert.False(EqualityOperatorsHelper<Complex, Complex>.op_Equality(Complex.NaN, 1.0));
+            Assert.False(EqualityOperatorsHelper<Complex, Complex>.op_Equality(0.0, 1.0));
+            Assert.False(EqualityOperatorsHelper<Complex, Complex>.op_Equality(MaxSubnormal, 1.0));
+            Assert.False(EqualityOperatorsHelper<Complex, Complex>.op_Equality(MinNormal, 1.0));
+            Assert.True(EqualityOperatorsHelper<Complex, Complex>.op_Equality(1.0, 1.0));
+        }
+
+        [Fact]
+        public static void op_InequalityTest()
+        {
+            Assert.True(EqualityOperatorsHelper<Complex, Complex>.op_Inequality(-1.0, 1.0));
+            Assert.True(EqualityOperatorsHelper<Complex, Complex>.op_Inequality(-MinNormal, 1.0));
+            Assert.True(EqualityOperatorsHelper<Complex, Complex>.op_Inequality(-MaxSubnormal, 1.0));
+            Assert.True(EqualityOperatorsHelper<Complex, Complex>.op_Inequality(-0.0, 1.0));
+            Assert.True(EqualityOperatorsHelper<Complex, Complex>.op_Inequality(Complex.NaN, 1.0));
+            Assert.True(EqualityOperatorsHelper<Complex, Complex>.op_Inequality(0.0, 1.0));
+            Assert.True(EqualityOperatorsHelper<Complex, Complex>.op_Inequality(MaxSubnormal, 1.0));
+            Assert.True(EqualityOperatorsHelper<Complex, Complex>.op_Inequality(MinNormal, 1.0));
+            Assert.False(EqualityOperatorsHelper<Complex, Complex>.op_Inequality(1.0, 1.0));
+        }
+
+        [Fact]
+        public static void op_IncrementTest()
+        {
+            AssertBitwiseEqual(0.0, IncrementOperatorsHelper<Complex>.op_Increment(-1.0));
+            AssertBitwiseEqual(1.0, IncrementOperatorsHelper<Complex>.op_Increment(-MinNormal));
+            AssertBitwiseEqual(1.0, IncrementOperatorsHelper<Complex>.op_Increment(-MaxSubnormal));
+            AssertBitwiseEqual(1.0, IncrementOperatorsHelper<Complex>.op_Increment(-0.0));
+            AssertBitwiseEqual(Complex.NaN, IncrementOperatorsHelper<Complex>.op_Increment(Complex.NaN));
+            AssertBitwiseEqual(1.0, IncrementOperatorsHelper<Complex>.op_Increment(0.0));
+            AssertBitwiseEqual(1.0, IncrementOperatorsHelper<Complex>.op_Increment(MaxSubnormal));
+            AssertBitwiseEqual(1.0, IncrementOperatorsHelper<Complex>.op_Increment(MinNormal));
+            AssertBitwiseEqual(2.0, IncrementOperatorsHelper<Complex>.op_Increment(1.0));
+        }
+
+        [Fact]
+        public static void op_CheckedIncrementTest()
+        {
+            AssertBitwiseEqual(0.0, IncrementOperatorsHelper<Complex>.op_CheckedIncrement(-1.0));
+            AssertBitwiseEqual(1.0, IncrementOperatorsHelper<Complex>.op_CheckedIncrement(-MinNormal));
+            AssertBitwiseEqual(1.0, IncrementOperatorsHelper<Complex>.op_CheckedIncrement(-MaxSubnormal));
+            AssertBitwiseEqual(1.0, IncrementOperatorsHelper<Complex>.op_CheckedIncrement(-0.0));
+            AssertBitwiseEqual(Complex.NaN, IncrementOperatorsHelper<Complex>.op_CheckedIncrement(Complex.NaN));
+            AssertBitwiseEqual(1.0, IncrementOperatorsHelper<Complex>.op_CheckedIncrement(0.0));
+            AssertBitwiseEqual(1.0, IncrementOperatorsHelper<Complex>.op_CheckedIncrement(MaxSubnormal));
+            AssertBitwiseEqual(1.0, IncrementOperatorsHelper<Complex>.op_CheckedIncrement(MinNormal));
+            AssertBitwiseEqual(2.0, IncrementOperatorsHelper<Complex>.op_CheckedIncrement(1.0));
+        }
+
+        [Fact]
+        public static void op_MultiplyTest()
+        {
+            AssertBitwiseEqual(-2.0, MultiplyOperatorsHelper<Complex, Complex, Complex>.op_Multiply(-1.0, 2.0));
+            AssertBitwiseEqual(new Complex(-4.4501477170144028E-308, -0.0), MultiplyOperatorsHelper<Complex, Complex, Complex>.op_Multiply(-MinNormal, 2.0));
+            AssertBitwiseEqual(new Complex(-4.4501477170144018E-308, -0.0), MultiplyOperatorsHelper<Complex, Complex, Complex>.op_Multiply(-MaxSubnormal, 2.0));
+            AssertBitwiseEqual(-0.0, MultiplyOperatorsHelper<Complex, Complex, Complex>.op_Multiply(-0.0, 2.0));
+            AssertBitwiseEqual(Complex.NaN, MultiplyOperatorsHelper<Complex, Complex, Complex>.op_Multiply(Complex.NaN, 2.0));
+            AssertBitwiseEqual(0.0, MultiplyOperatorsHelper<Complex, Complex, Complex>.op_Multiply(0.0, 2.0));
+            AssertBitwiseEqual(4.4501477170144018E-308, MultiplyOperatorsHelper<Complex, Complex, Complex>.op_Multiply(MaxSubnormal, 2.0));
+            AssertBitwiseEqual(4.4501477170144028E-308, MultiplyOperatorsHelper<Complex, Complex, Complex>.op_Multiply(MinNormal, 2.0));
+            AssertBitwiseEqual(2.0, MultiplyOperatorsHelper<Complex, Complex, Complex>.op_Multiply(1.0, 2.0));
+        }
+
+        [Fact]
+        public static void op_CheckedMultiplyTest()
+        {
+            AssertBitwiseEqual(-2.0, MultiplyOperatorsHelper<Complex, Complex, Complex>.op_CheckedMultiply(-1.0, 2.0));
+            AssertBitwiseEqual(new Complex(-4.4501477170144028E-308, -0.0), MultiplyOperatorsHelper<Complex, Complex, Complex>.op_CheckedMultiply(-MinNormal, 2.0));
+            AssertBitwiseEqual(new Complex(-4.4501477170144018E-308, -0.0), MultiplyOperatorsHelper<Complex, Complex, Complex>.op_CheckedMultiply(-MaxSubnormal, 2.0));
+            AssertBitwiseEqual(-0.0, MultiplyOperatorsHelper<Complex, Complex, Complex>.op_CheckedMultiply(-0.0, 2.0));
+            AssertBitwiseEqual(Complex.NaN, MultiplyOperatorsHelper<Complex, Complex, Complex>.op_CheckedMultiply(Complex.NaN, 2.0));
+            AssertBitwiseEqual(0.0, MultiplyOperatorsHelper<Complex, Complex, Complex>.op_CheckedMultiply(0.0, 2.0));
+            AssertBitwiseEqual(4.4501477170144018E-308, MultiplyOperatorsHelper<Complex, Complex, Complex>.op_CheckedMultiply(MaxSubnormal, 2.0));
+            AssertBitwiseEqual(4.4501477170144028E-308, MultiplyOperatorsHelper<Complex, Complex, Complex>.op_CheckedMultiply(MinNormal, 2.0));
+            AssertBitwiseEqual(2.0, MultiplyOperatorsHelper<Complex, Complex, Complex>.op_CheckedMultiply(1.0, 2.0));
+        }
+
+        [Fact]
+        public static void op_SubtractionTest()
+        {
+            AssertBitwiseEqual(-2.0, SubtractionOperatorsHelper<Complex, Complex, Complex>.op_Subtraction(-1.0, 1.0));
+            AssertBitwiseEqual(new Complex(-1.0, -0.0), SubtractionOperatorsHelper<Complex, Complex, Complex>.op_Subtraction(-MinNormal, 1.0));
+            AssertBitwiseEqual(new Complex(-1.0, -0.0), SubtractionOperatorsHelper<Complex, Complex, Complex>.op_Subtraction(-MaxSubnormal, 1.0));
+            AssertBitwiseEqual(-1.0, SubtractionOperatorsHelper<Complex, Complex, Complex>.op_Subtraction(-0.0, 1.0));
+            AssertBitwiseEqual(Complex.NaN, SubtractionOperatorsHelper<Complex, Complex, Complex>.op_Subtraction(Complex.NaN, 1.0));
+            AssertBitwiseEqual(-1.0, SubtractionOperatorsHelper<Complex, Complex, Complex>.op_Subtraction(0.0, 1.0));
+            AssertBitwiseEqual(-1.0, SubtractionOperatorsHelper<Complex, Complex, Complex>.op_Subtraction(MaxSubnormal, 1.0));
+            AssertBitwiseEqual(-1.0, SubtractionOperatorsHelper<Complex, Complex, Complex>.op_Subtraction(MinNormal, 1.0));
+            AssertBitwiseEqual(0.0, SubtractionOperatorsHelper<Complex, Complex, Complex>.op_Subtraction(1.0, 1.0));
+        }
+
+        [Fact]
+        public static void op_CheckedSubtractionTest()
+        {
+            AssertBitwiseEqual(-2.0, SubtractionOperatorsHelper<Complex, Complex, Complex>.op_CheckedSubtraction(-1.0, 1.0));
+            AssertBitwiseEqual(new Complex(-1.0, -0.0), SubtractionOperatorsHelper<Complex, Complex, Complex>.op_CheckedSubtraction(-MinNormal, 1.0));
+            AssertBitwiseEqual(new Complex(-1.0, -0.0), SubtractionOperatorsHelper<Complex, Complex, Complex>.op_CheckedSubtraction(-MaxSubnormal, 1.0));
+            AssertBitwiseEqual(-1.0, SubtractionOperatorsHelper<Complex, Complex, Complex>.op_CheckedSubtraction(-0.0, 1.0));
+            AssertBitwiseEqual(Complex.NaN, SubtractionOperatorsHelper<Complex, Complex, Complex>.op_CheckedSubtraction(Complex.NaN, 1.0));
+            AssertBitwiseEqual(-1.0, SubtractionOperatorsHelper<Complex, Complex, Complex>.op_CheckedSubtraction(0.0, 1.0));
+            AssertBitwiseEqual(-1.0, SubtractionOperatorsHelper<Complex, Complex, Complex>.op_CheckedSubtraction(MaxSubnormal, 1.0));
+            AssertBitwiseEqual(-1.0, SubtractionOperatorsHelper<Complex, Complex, Complex>.op_CheckedSubtraction(MinNormal, 1.0));
+            AssertBitwiseEqual(0.0, SubtractionOperatorsHelper<Complex, Complex, Complex>.op_CheckedSubtraction(1.0, 1.0));
+        }
+
+        [Fact]
+        public static void op_UnaryNegationTest()
+        {
+            AssertBitwiseEqual(new Complex(1.0, -0.0), UnaryNegationOperatorsHelper<Complex, Complex>.op_UnaryNegation(-1.0));
+            AssertBitwiseEqual(MinNormal, UnaryNegationOperatorsHelper<Complex, Complex>.op_UnaryNegation(-MinNormal));
+            AssertBitwiseEqual(MaxSubnormal, UnaryNegationOperatorsHelper<Complex, Complex>.op_UnaryNegation(-MaxSubnormal));
+            AssertBitwiseEqual(new Complex(0.0, -0.0), UnaryNegationOperatorsHelper<Complex, Complex>.op_UnaryNegation(-0.0));
+            AssertBitwiseEqual(Complex.NaN, UnaryNegationOperatorsHelper<Complex, Complex>.op_UnaryNegation(Complex.NaN));
+            AssertBitwiseEqual(new Complex(-0.0, -0.0), UnaryNegationOperatorsHelper<Complex, Complex>.op_UnaryNegation(0.0));
+            AssertBitwiseEqual(-MaxSubnormal, UnaryNegationOperatorsHelper<Complex, Complex>.op_UnaryNegation(MaxSubnormal));
+            AssertBitwiseEqual(-MinNormal, UnaryNegationOperatorsHelper<Complex, Complex>.op_UnaryNegation(MinNormal));
+            AssertBitwiseEqual(new Complex(-1.0, -0.0), UnaryNegationOperatorsHelper<Complex, Complex>.op_UnaryNegation(1.0));
+        }
+
+        [Fact]
+        public static void op_CheckedUnaryNegationTest()
+        {
+            AssertBitwiseEqual(new Complex(1.0, -0.0), UnaryNegationOperatorsHelper<Complex, Complex>.op_CheckedUnaryNegation(-1.0));
+            AssertBitwiseEqual(MinNormal, UnaryNegationOperatorsHelper<Complex, Complex>.op_CheckedUnaryNegation(-MinNormal));
+            AssertBitwiseEqual(MaxSubnormal, UnaryNegationOperatorsHelper<Complex, Complex>.op_CheckedUnaryNegation(-MaxSubnormal));
+            AssertBitwiseEqual(new Complex(0.0, -0.0), UnaryNegationOperatorsHelper<Complex, Complex>.op_CheckedUnaryNegation(-0.0));
+            AssertBitwiseEqual(Complex.NaN, UnaryNegationOperatorsHelper<Complex, Complex>.op_CheckedUnaryNegation(Complex.NaN));
+            AssertBitwiseEqual(new Complex(-0.0, -0.0), UnaryNegationOperatorsHelper<Complex, Complex>.op_CheckedUnaryNegation(0.0));
+            AssertBitwiseEqual(-MaxSubnormal, UnaryNegationOperatorsHelper<Complex, Complex>.op_CheckedUnaryNegation(MaxSubnormal));
+            AssertBitwiseEqual(-MinNormal, UnaryNegationOperatorsHelper<Complex, Complex>.op_CheckedUnaryNegation(MinNormal));
+            AssertBitwiseEqual(new Complex(-1.0, -0.0), UnaryNegationOperatorsHelper<Complex, Complex>.op_CheckedUnaryNegation(1.0));
+        }
+
+        [Fact]
+        public static void op_UnaryPlusTest()
+        {
+            AssertBitwiseEqual(-1.0, UnaryPlusOperatorsHelper<Complex, Complex>.op_UnaryPlus(-1.0));
+            AssertBitwiseEqual(-MinNormal, UnaryPlusOperatorsHelper<Complex, Complex>.op_UnaryPlus(-MinNormal));
+            AssertBitwiseEqual(-MaxSubnormal, UnaryPlusOperatorsHelper<Complex, Complex>.op_UnaryPlus(-MaxSubnormal));
+            AssertBitwiseEqual(-0.0, UnaryPlusOperatorsHelper<Complex, Complex>.op_UnaryPlus(-0.0));
+            AssertBitwiseEqual(Complex.NaN, UnaryPlusOperatorsHelper<Complex, Complex>.op_UnaryPlus(Complex.NaN));
+            AssertBitwiseEqual(0.0, UnaryPlusOperatorsHelper<Complex, Complex>.op_UnaryPlus(0.0));
+            AssertBitwiseEqual(MaxSubnormal, UnaryPlusOperatorsHelper<Complex, Complex>.op_UnaryPlus(MaxSubnormal));
+            AssertBitwiseEqual(MinNormal, UnaryPlusOperatorsHelper<Complex, Complex>.op_UnaryPlus(MinNormal));
+            AssertBitwiseEqual(1.0, UnaryPlusOperatorsHelper<Complex, Complex>.op_UnaryPlus(1.0));
+        }
+    }
+}
index 4b9dbea..b5ca26d 100644 (file)
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFramework>$(NetCoreAppCurrent)</TargetFramework>
     <IncludeRemoteExecutor>true</IncludeRemoteExecutor>
     <Compile Include="ComplexTests.cs" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="$(CommonTestPath)System\GenericMathHelpers.cs" Link="Common\System\GenericMathHelpers.cs" />
+    <Compile Include="ComplexTests.GenericMath.cs" />
+  </ItemGroup>
+  <ItemGroup>
     <!-- Some internal types are needed, so we reference the implementation assembly, rather than the reference assembly. -->
     <ProjectReference Include="..\src\System.Runtime.Numerics.csproj" SkipUseReferenceAssembly="true" />
   </ItemGroup>