From ece1143709da5c38e5b137ed75a2c48d2bbd1226 Mon Sep 17 00:00:00 2001 From: Andrii Kurdiumov Date: Sat, 2 Jun 2018 18:17:50 +0600 Subject: [PATCH] Addede mixed Complex/double arithmetic operators to Complex Implementation of simplified cases for performing math operations on the Complex Closes dotnet/corefx#15927 Commit migrated from https://github.com/dotnet/corefx/commit/68c127e5017500d24d6fb6ddfe6f7d0c31636c09 --- .../ref/System.Runtime.Numerics.cs | 16 +++ .../src/System/Numerics/Complex.cs | 96 ++++++++++++++- .../System.Runtime.Numerics/tests/ComplexTests.cs | 135 +++++++++++++++++++++ 3 files changed, 246 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Runtime.Numerics/ref/System.Runtime.Numerics.cs b/src/libraries/System.Runtime.Numerics/ref/System.Runtime.Numerics.cs index c24590a..3ee8be5 100644 --- a/src/libraries/System.Runtime.Numerics/ref/System.Runtime.Numerics.cs +++ b/src/libraries/System.Runtime.Numerics/ref/System.Runtime.Numerics.cs @@ -178,12 +178,16 @@ namespace System.Numerics 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(System.Numerics.Complex left, System.Numerics.Complex right) { throw null; } + public static System.Numerics.Complex Add(System.Numerics.Complex left, double right) { throw null; } + public static System.Numerics.Complex Add(double left, System.Numerics.Complex right) { throw null; } public static System.Numerics.Complex Asin(System.Numerics.Complex value) { throw null; } public static System.Numerics.Complex Atan(System.Numerics.Complex value) { throw null; } public static System.Numerics.Complex Conjugate(System.Numerics.Complex value) { throw null; } public static System.Numerics.Complex Cos(System.Numerics.Complex value) { throw null; } public static System.Numerics.Complex Cosh(System.Numerics.Complex value) { throw null; } public static System.Numerics.Complex Divide(System.Numerics.Complex dividend, System.Numerics.Complex divisor) { throw null; } + public static System.Numerics.Complex Divide(System.Numerics.Complex dividend, double divisor) { throw null; } + public static System.Numerics.Complex Divide(double dividend, System.Numerics.Complex divisor) { throw null; } public bool Equals(System.Numerics.Complex value) { throw null; } public override bool Equals(object obj) { throw null; } public static System.Numerics.Complex Exp(System.Numerics.Complex value) { throw null; } @@ -193,9 +197,15 @@ namespace System.Numerics public static System.Numerics.Complex Log(System.Numerics.Complex value, double baseValue) { throw null; } public static System.Numerics.Complex Log10(System.Numerics.Complex value) { throw null; } public static System.Numerics.Complex Multiply(System.Numerics.Complex left, System.Numerics.Complex right) { throw null; } + public static System.Numerics.Complex Multiply(System.Numerics.Complex left, double right) { throw null; } + public static System.Numerics.Complex Multiply(double left, System.Numerics.Complex right) { throw null; } public static System.Numerics.Complex Negate(System.Numerics.Complex value) { 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 left, double 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, 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 /(double left, System.Numerics.Complex right) { throw null; } public static bool operator ==(System.Numerics.Complex left, System.Numerics.Complex right) { throw null; } public static explicit operator System.Numerics.Complex (decimal value) { throw null; } public static explicit operator System.Numerics.Complex (System.Numerics.BigInteger value) { throw null; } @@ -215,7 +225,11 @@ namespace System.Numerics public static implicit operator System.Numerics.Complex (ulong value) { throw null; } public static bool operator !=(System.Numerics.Complex left, System.Numerics.Complex 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 left, double 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, 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 -(double left, System.Numerics.Complex right) { 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; } @@ -224,6 +238,8 @@ namespace System.Numerics public static System.Numerics.Complex Sinh(System.Numerics.Complex value) { throw null; } public static System.Numerics.Complex Sqrt(System.Numerics.Complex value) { throw null; } public static System.Numerics.Complex Subtract(System.Numerics.Complex 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(double left, System.Numerics.Complex right) { 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; } diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs index f42f22b..8591891 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs @@ -62,21 +62,61 @@ namespace System.Numerics return left + right; } + public static Complex Add(Complex left, double right) + { + return left + right; + } + + public static Complex Add(double left, Complex right) + { + return left + right; + } + public static Complex Subtract(Complex left, Complex right) { return left - right; } + public static Complex Subtract(Complex left, double right) + { + return left - right; + } + + public static Complex Subtract(double left, Complex right) + { + return left - right; + } + public static Complex Multiply(Complex left, Complex right) { return left * right; } + public static Complex Multiply(Complex left, double right) + { + return left * right; + } + + public static Complex Multiply(double left, Complex right) + { + return left * right; + } + public static Complex Divide(Complex dividend, Complex divisor) { return dividend / divisor; } - + + public static Complex Divide(Complex dividend, double divisor) + { + return dividend / divisor; + } + + public static Complex Divide(double dividend, Complex divisor) + { + return dividend / divisor; + } + public static Complex operator -(Complex value) /* Unary negation of a complex number */ { return new Complex(-value.m_real, -value.m_imaginary); @@ -86,12 +126,32 @@ namespace System.Numerics { return new Complex(left.m_real + right.m_real, left.m_imaginary + right.m_imaginary); } + + public static Complex operator +(Complex left, double right) + { + return new Complex(left.m_real + right, left.m_imaginary); + } + + public static Complex operator +(double left, Complex right) + { + return new Complex(left + right.m_real, right.m_imaginary); + } public static Complex operator -(Complex left, Complex right) { return new Complex(left.m_real - right.m_real, left.m_imaginary - right.m_imaginary); } + public static Complex operator -(Complex left, double right) + { + return new Complex(left.m_real - right, left.m_imaginary); + } + + public static Complex operator -(double left, Complex right) + { + return new Complex(left - right.m_real, -right.m_imaginary); + } + public static Complex operator *(Complex left, Complex right) { // Multiplication: (a + bi)(c + di) = (ac -bd) + (bc + ad)i @@ -100,6 +160,16 @@ namespace System.Numerics return new Complex(result_realpart, result_imaginarypart); } + public static Complex operator *(Complex left, double right) + { + return new Complex(left.m_real * right, left.m_imaginary * right); + } + + public static Complex operator *(double left, Complex right) + { + return new Complex(left * right.m_real, left * right.m_imaginary); + } + public static Complex operator /(Complex left, Complex right) { // Division : Smith's formula. @@ -120,6 +190,30 @@ namespace System.Numerics } } + public static Complex operator /(Complex left, double right) + { + return new Complex(left.m_real / right, left.m_imaginary / right); + } + + public static Complex operator /(double left, Complex right) + { + // Division : Smith's formula. + double a = left; + double c = right.m_real; + double d = right.m_imaginary; + + if (Math.Abs(d) < Math.Abs(c)) + { + double doc = d / c; + return new Complex(a / (c + d * doc), (-a * doc) / (c + d * doc)); + } + else + { + double cod = c / d; + return new Complex(a * cod / (d + c * cod), -a / (d + c * cod)); + } + } + public static double Abs(Complex value) { return Hypot(value.m_real, value.m_imaginary); diff --git a/src/libraries/System.Runtime.Numerics/tests/ComplexTests.cs b/src/libraries/System.Runtime.Numerics/tests/ComplexTests.cs index c05876a..f0a69a9 100644 --- a/src/libraries/System.Runtime.Numerics/tests/ComplexTests.cs +++ b/src/libraries/System.Runtime.Numerics/tests/ComplexTests.cs @@ -398,6 +398,34 @@ namespace System.Numerics.Tests } [Theory] + [MemberData(nameof(Add_TestData))] + [MemberData(nameof(Random_4_TestData))] + [MemberData(nameof(Invalid_4_TestData))] + public static void AddDouble(double realLeft, double imaginaryLeft, double realRight, double imaginaryRight) + { + var left = new Complex(realLeft, imaginaryLeft); + var right = realRight; + + // Calculate the expected results + double expectedReal = realLeft + realRight; + double expectedImaginary = imaginaryLeft; + + // Operator + Complex result = left + right; + VerifyRealImaginaryProperties(result, expectedReal, expectedImaginary); + + result = right + left; + VerifyRealImaginaryProperties(result, expectedReal, expectedImaginary); + + // Static method + result = Complex.Add(left, right); + VerifyRealImaginaryProperties(result, expectedReal, expectedImaginary); + + result = Complex.Add(right, left); + VerifyRealImaginaryProperties(result, expectedReal, expectedImaginary); + } + + [Theory] [MemberData(nameof(Primitives_2_TestData))] [MemberData(nameof(SmallRandom_2_TestData))] public static void ASin_Basic(double real, double imaginary) @@ -745,6 +773,58 @@ namespace System.Numerics.Tests VerifyRealImaginaryProperties(result, expectedReal, expectedImaginary); } + [Theory] + [MemberData(nameof(Divide_TestData))] + [MemberData(nameof(SmallRandom_4_TestData))] + [MemberData(nameof(Invalid_4_TestData))] + public static void DivideByDouble(double realLeft, double imaginaryLeft, double realRight, double imaginaryRight) + { + var dividend = new Complex(realLeft, imaginaryLeft); + var divisor = realRight; + + double expectedReal = dividend.Real / divisor; + double expectedImaginary = dividend.Imaginary / divisor; + + // Operator + Complex result = dividend / divisor; + VerifyRealImaginaryProperties(result, expectedReal, expectedImaginary); + + // Static method + result = Complex.Divide(dividend, divisor); + VerifyRealImaginaryProperties(result, expectedReal, expectedImaginary); + } + + [Theory] + [MemberData(nameof(Divide_TestData))] + [MemberData(nameof(SmallRandom_4_TestData))] + [MemberData(nameof(Invalid_4_TestData))] + public static void DivideByComplex(double realLeft, double imaginaryLeft, double realRight, double imaginaryRight) + { + var dividend = realLeft; + var divisor = new Complex(realRight, imaginaryRight); + + Complex expected = dividend * Complex.Conjugate(divisor); + double expectedReal = expected.Real; + double expectedImaginary = expected.Imaginary; + + if (!double.IsInfinity(expectedReal)) + { + expectedReal = expectedReal / (divisor.Magnitude * divisor.Magnitude); + } + if (!double.IsInfinity(expectedImaginary)) + { + expectedImaginary = expectedImaginary / (divisor.Magnitude * divisor.Magnitude); + } + + // Operator + Complex result = dividend / divisor; + VerifyRealImaginaryProperties(result, expectedReal, expectedImaginary); + + // Static method + result = Complex.Divide(dividend, divisor); + VerifyRealImaginaryProperties(result, expectedReal, expectedImaginary); + } + [Fact] [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework)] public static void Equals_netcore() @@ -1219,6 +1299,33 @@ namespace System.Numerics.Tests } [Theory] + [MemberData(nameof(Multiply_TestData))] + [MemberData(nameof(SmallRandom_4_TestData))] + [MemberData(nameof(Invalid_4_TestData))] + public static void MultiplyDouble(double realLeft, double imaginaryLeft, double realRight, double imaginaryRight) + { + var left = new Complex(realLeft, imaginaryLeft); + var right = realRight; + + double expectedReal = realLeft * realRight; + double expectedImaginary = imaginaryLeft * realRight; + + // Operator + Complex result = left * right; + VerifyRealImaginaryProperties(result, expectedReal, expectedImaginary); + + result = right * left; + VerifyRealImaginaryProperties(result, expectedReal, expectedImaginary); + + // Static method + result = Complex.Multiply(left, right); + VerifyRealImaginaryProperties(result, expectedReal, expectedImaginary); + + result = Complex.Multiply(right, left); + VerifyRealImaginaryProperties(result, expectedReal, expectedImaginary); + } + + [Theory] [MemberData(nameof(Valid_2_TestData))] [MemberData(nameof(Random_2_TestData))] [MemberData(nameof(Invalid_2_TestData))] @@ -1532,6 +1639,34 @@ namespace System.Numerics.Tests VerifyRealImaginaryProperties(result, expectedReal, expectedImaginary); } + [Theory] + [MemberData(nameof(Subtract_TestData))] + [MemberData(nameof(Random_4_TestData))] + [MemberData(nameof(Invalid_4_TestData))] + public static void SubtractDouble(double realLeft, double imaginaryLeft, double realRight, double imaginaryRight) + { + var left = new Complex(realLeft, imaginaryLeft); + var right = realRight; + + // calculate the expected results + double expectedReal = realLeft - realRight; + double expectedImaginary = imaginaryLeft; + + // Operator + Complex result = left - right; + VerifyRealImaginaryProperties(result, expectedReal, expectedImaginary); + + result = right - left; + VerifyRealImaginaryProperties(result, -expectedReal, -expectedImaginary); + + // Static method + result = Complex.Subtract(left, right); + VerifyRealImaginaryProperties(result, expectedReal, expectedImaginary); + + result = Complex.Subtract(right, left); + VerifyRealImaginaryProperties(result, -expectedReal, -expectedImaginary); + } + public static IEnumerable Sqrt_TestData() { // Simple known values. -- 2.7.4