diff --git a/src/Numerics/Complex.cs b/src/Numerics/Complex.cs index 8926415d..71ebd61b 100644 --- a/src/Numerics/Complex.cs +++ b/src/Numerics/Complex.cs @@ -1539,10 +1539,11 @@ namespace MathNet.Numerics /// The logarithm of value in base baseValue. public static Complex Log(Complex value, double baseValue) { - if( baseValue == 1.0) + if (baseValue == 1.0) { return double.NaN; } + return value.NaturalLogarithm() / Math.Log(baseValue, Math.E); } diff --git a/src/UnitTests/ComplexTests/ComplexTest.cs b/src/UnitTests/ComplexTests/ComplexTest.cs index 61259edc..3e52783d 100644 --- a/src/UnitTests/ComplexTests/ComplexTest.cs +++ b/src/UnitTests/ComplexTests/ComplexTest.cs @@ -102,6 +102,18 @@ namespace MathNet.Numerics.UnitTests.ComplexTests AssertHelpers.AlmostEqual(expected, value.Exponential(), 15); } + [Test] + [Row(0.0, 0.0, 1.0, 0.0)] + [Row(0.0, 1.0, 0.54030230586813977, 0.8414709848078965)] + [Row(-1.0, 1.0, 0.19876611034641295, 0.30955987565311222)] + [Row(-111.1, 111.1, -2.3259065941590448e-49, -5.1181940185795617e-49)] + public void CanComputeExp(double real, double imag, double expectedReal, double expectedImag) + { + var value = new Complex(real, imag); + var expected = new Complex(expectedReal, expectedImag); + AssertHelpers.AlmostEqual(expected, Complex.Exp(value), 15); + } + [Test] [Row(0.0, 0.0, double.NegativeInfinity, 0.0)] [Row(0.0, 1.0, 0.0, 1.5707963267948966)] @@ -115,6 +127,32 @@ namespace MathNet.Numerics.UnitTests.ComplexTests AssertHelpers.AlmostEqual(expected, value.NaturalLogarithm(), 15); } + [Test] + [Row(0.0, 0.0, double.NegativeInfinity, 0.0)] + [Row(0.0, 1.0, 0.0, 1.5707963267948966)] + [Row(-1.0, 1.0, 0.34657359027997264, 2.3561944901923448)] + [Row(-111.1, 111.1, 5.0570042869255571, 2.3561944901923448)] + [Row(111.1, -111.1, 5.0570042869255571, -0.78539816339744828)] + public void CanComputeLog(double real, double imag, double expectedReal, double expectedImag) + { + var value = new Complex(real, imag); + var expected = new Complex(expectedReal, expectedImag); + AssertHelpers.AlmostEqual(expected, Complex.Log(value), 15); + } + + [Test] + [Row(0.0, 0.0, double.NegativeInfinity, 0.0)] + [Row(0.0, 1.0, 0.0, 0.68218817692092071)] + [Row(-1.0, 1.0, 0.1505149978319906, 1.0232822653813811)] + [Row(-111.1, 111.1, 2.1962290567728582, 1.0232822653813811)] + [Row(111.1, -111.1, 2.1962290567728582, -0.34109408846046035)] + public void CanComputeLog10(double real, double imag, double expectedReal, double expectedImag) + { + var value = new Complex(real, imag); + var expected = new Complex(expectedReal, expectedImag); + AssertHelpers.AlmostEqual(expected, Complex.Log10(value), 15); + } + [Test] [MultipleAsserts] public void CanComputePower() @@ -158,6 +196,18 @@ namespace MathNet.Numerics.UnitTests.ComplexTests AssertEx.That(() => a.Power(b).IsNaN); } + [Test] + [MultipleAsserts] + public void CanComputePow() + { + var a = new Complex(1.19209289550780998537e-7, 1.19209289550780998537e-7); + var b = new Complex(1.19209289550780998537e-7, 1.19209289550780998537e-7); + AssertHelpers.AlmostEqual(new Complex(9.99998047207974718744e-1, -1.76553541154378695012e-6), Complex.Pow(a,b), 15); + a = new Complex(0.0, -8.388608e6); + AssertHelpers.AlmostEqual(new Complex(1.00000190048219620166, -1.87253870018168043834e-7), Complex.Pow(a, 1.19209289550780998537e-7), 15); + } + + [Test] [MultipleAsserts] public void CanComputeRoot() @@ -225,6 +275,28 @@ namespace MathNet.Numerics.UnitTests.ComplexTests AssertHelpers.AlmostEqual(Complex.Zero, complex.SquareRoot(), 15); } + [Test] + [MultipleAsserts] + public void CanComputeSqrt() + { + var complex = new Complex(1.19209289550780998537e-7, 1.19209289550780998537e-7); + AssertHelpers.AlmostEqual(new Complex(0.00037933934912842666, 0.00015712750315077684), Complex.Sqrt(complex), 15); + complex = new Complex(0.0, 1.19209289550780998537e-7); + AssertHelpers.AlmostEqual(new Complex(0.00024414062499999973, 0.00024414062499999976), Complex.Sqrt(complex), 15); + complex = new Complex(0.0, -1.19209289550780998537e-7); + AssertHelpers.AlmostEqual(new Complex(0.00024414062499999973, -0.00024414062499999976), Complex.Sqrt(complex), 15); + complex = new Complex(0.0, 0.5); + AssertHelpers.AlmostEqual(new Complex(0.5, 0.5), Complex.Sqrt(complex), 15); + complex = new Complex(0.0, -0.5); + AssertHelpers.AlmostEqual(new Complex(0.5, -0.5), Complex.Sqrt(complex), 15); + complex = new Complex(0.0, -8.388608e6); + AssertHelpers.AlmostEqual(new Complex(2048.0, -2048.0), Complex.Sqrt(complex), 15); + complex = new Complex(8.388608e6, 1.19209289550780998537e-7); + AssertHelpers.AlmostEqual(new Complex(2896.3093757400989, 2.0579515874459933e-11), Complex.Sqrt(complex), 15); + complex = new Complex(0.0, 0.0); + AssertHelpers.AlmostEqual(Complex.Zero, Complex.Sqrt(complex), 15); + } + [Test] [MultipleAsserts] public void CanConvertDoubleToComplex() @@ -252,6 +324,16 @@ namespace MathNet.Numerics.UnitTests.ComplexTests Assert.AreApproximatelyEqual(-1, complex.Imaginary, 1e-15, "Imaginary part is -1."); } + [Test] + [MultipleAsserts] + public void CanCreateComplexNumberFromPolarCoordinates() + { + var complex = Complex.FromPolarCoordinates(2, -Math.PI / 6); + Assert.AreApproximatelyEqual(Math.Sqrt(3), complex.Real, 1e-15, "Real part is Sqrt(3)."); + Assert.AreApproximatelyEqual(-1, complex.Imaginary, 1e-15, "Imaginary part is -1."); + } + + [Test] [MultipleAsserts] public void CanCreateComplexNumberWithRealImaginaryIntializer() @@ -463,6 +545,16 @@ namespace MathNet.Numerics.UnitTests.ComplexTests Assert.AreEqual(expected, new Complex(real, imag).Magnitude); } + [Test] + [Row(0.0, 0.0, 0.0)] + [Row(0.0, 1.0, 1.0)] + [Row(-1.0, 1.0, 1.4142135623730951)] + [Row(-111.1, 111.1, 157.11912677965086)] + public void CanComputeAbs(double real, double imag, double expected) + { + Assert.AreEqual(expected, Complex.Abs(new Complex(real, imag))); + } + [Test] [Row(double.PositiveInfinity, double.PositiveInfinity, Constants.Sqrt1Over2, Constants.Sqrt1Over2)] [Row(double.PositiveInfinity, double.NegativeInfinity, Constants.Sqrt1Over2, -Constants.Sqrt1Over2)] @@ -475,5 +567,239 @@ namespace MathNet.Numerics.UnitTests.ComplexTests { Assert.AreEqual(new Complex(expectedReal, expectedImag), new Complex(real, imag).Sign); } - } + + [Test] + [Row(0.0, 0.0, 1.0, 0.0)] + [Row(8.388608e6, 0.0, -0.90175467375875928, 0.0)] + [Row(-8.388608e6, 0.0, -0.90175467375875928, 0.0)] + [Row(1.19209289550780998537e-7, 0.0, 0.99999999999999289, 0.0)] + [Row(-1.19209289550780998537e-7, 0.0, 0.99999999999999289, 0.0)] + [Row(8.388608e6, 1.19209289550780998537e-7, -0.90175467375876572, -5.1528001100635277e-8)] + [Row(-1.19209289550780998537e-7, -8.388608e6, double.PositiveInfinity, double.NegativeInfinity)] + public void CanComputeCos(double real, double imag, double expectedReal, double expectedImag) + { + var actual = Complex.Cos(new Complex(real, imag)); + var expected = new Complex(expectedReal, expectedImag); + AssertHelpers.AlmostEqual(expected, actual, 13); + } + + [Test] + [Row(0.0, 0.0, 0.0, 0.0)] + [Row(8.388608e6, 0.0, 0.43224820225679778, 0.0)] + [Row(-8.388608e6, 0.0, -0.43224820225679778, 0.0)] + [Row(1.19209289550780998537e-7, 0.0, 1.19209289550780998537e-7, 0.0)] + [Row(-1.19209289550780998537e-7, 0.0, -1.19209289550780998537e-7, 0.0)] + [Row(8.388608e6, 1.19209289550780998537e-7, 0.43224820225680083, -1.0749753400787824e-7)] + [Row(-1.19209289550780998537e-7, -8.388608e6, double.NegativeInfinity, double.NegativeInfinity)] + public void CanComputeSin(double real, double imag, double expectedReal, double expectedImag) + { + var actual = Complex.Sin(new Complex(real, imag)); + var expected = new Complex(expectedReal, expectedImag); + AssertHelpers.AlmostEqual(expected, actual, 13); + } + + [Test] + [Row(0.0, 0.0, 0.0, 0.0)] + [Row(8.388608e6, 0.0, -0.47934123862654288, 0.0)] + [Row(-8.388608e6, 0.0, 0.47934123862654288, 0.0)] + [Row(1.19209289550780998537e-7, 0.0, 1.1920928955078157e-7, 0.0)] + [Row(-1.19209289550780998537e-7, 0.0, -1.1920928955078157e-7, 0.0)] + [Row(8.388608e6, 1.19209289550780998537e-7, -0.47934123862653449, 1.4659977233982276e-7)] + [Row(-8.388608e6, -1.19209289550780998537e-7, 0.47934123862653449, -1.4659977233982276e-7)] + public void CanComputeTan(double real, double imag, double expectedReal, double expectedImag) + { + var actual = Complex.Tan(new Complex(real, imag)); + var expected = new Complex(expectedReal, expectedImag); + AssertHelpers.AlmostEqual(expected, actual, 13); + } + + [Test] + [Row(0.0, 0.0, 0.0, 0.0)] + [Row(8.388608e6, 0.0, double.PositiveInfinity, 0.0)] + [Row(-8.388608e6, 0.0, double.NegativeInfinity, 0.0)] + [Row(1.19209289550780998537e-7, 0.0, 1.1920928955078128e-7, 0.0)] + [Row(-1.19209289550780998537e-7, 0.0, -1.1920928955078128e-7, 0.0)] + [Row(8.388608e6, 1.19209289550780998537e-7, double.PositiveInfinity, double.PositiveInfinity)] + [Row(-8.388608e6, -1.19209289550780998537e-7, double.NegativeInfinity, double.NegativeInfinity)] + [Row(0.5, -0.5, 0.45730415318424922, -0.54061268571315335)] + public void CanComputeSinh(double real, double imag, double expectedReal, double expectedImag) + { + var actual = Complex.Sinh(new Complex(real, imag)); + var expected = new Complex(expectedReal, expectedImag); + AssertHelpers.AlmostEqual(expected, actual, 14); + } + + [Test] + [Row(0.0, 0.0, 1.0, 0.0)] + [Row(8.388608e6, 0.0, double.PositiveInfinity, 0.0)] + [Row(-8.388608e6, 0.0, double.PositiveInfinity, 0.0)] + [Row(1.19209289550780998537e-7, 0.0, 1.0000000000000071, 0.0)] + [Row(-1.19209289550780998537e-7, 0.0, 1.0000000000000071, 0.0)] + [Row(8.388608e6, 1.19209289550780998537e-7, double.PositiveInfinity, double.PositiveInfinity)] + [Row(-8.388608e6, -1.19209289550780998537e-7, double.PositiveInfinity, double.PositiveInfinity)] + [Row(0.5, -0.5, 0.9895848833999199, -0.24982639750046154)] + public void CanComputeCosh(double real, double imag, double expectedReal, double expectedImag) + { + var actual = Complex.Cosh(new Complex(real, imag)); + var expected = new Complex(expectedReal, expectedImag); + AssertHelpers.AlmostEqual(expected, actual, 14); + } + + [Test] + [Row(0.0, 0.0, 0.0, 0.0)] + [Row(8.388608e6, 0.0, 1.0, 0.0)] + [Row(-8.388608e6, 0.0, -1.0, 0.0)] + [Row(1.19209289550780998537e-7, 0.0, 1.1920928955078043e-7, 0.0)] + [Row(-1.19209289550780998537e-7, 0.0, -1.1920928955078043e-7, 0.0)] + [Row(8.388608e6, 1.19209289550780998537e-7, 1.0, 0.0)] + [Row(-8.388608e6, -1.19209289550780998537e-7, -1.0, 0.0)] + [Row(0.5, -0.5, 0.56408314126749848, -0.40389645531602575)] + public void CanComputeTanh(double real, double imag, double expectedReal, double expectedImag) + { + var actual = Complex.Tanh(new Complex(real, imag)); + var expected = new Complex(expectedReal, expectedImag); + AssertHelpers.AlmostEqual(expected, actual, 14); + } + + + [Test] + [Row(0.0, 0.0, 0.0, 0.0)] + [Row(8.388608e6, 0.0, 1.5707963267948966, -16.635532333438682)] + [Row(-8.388608e6, 0.0, -1.5707963267948966, 16.635532333438682)] + [Row(1.19209289550780998537e-7, 0.0, 1.1920928955078128e-7, 0.0)] + [Row(-1.19209289550780998537e-7, 0.0, -1.1920928955078128e-7, 0.0)] + [Row(8.388608e6, 1.19209289550780998537e-7, 1.5707963267948966, 16.635532333438682)] + [Row(-8.388608e6, -1.19209289550780998537e-7, -1.5707963267948966, -16.635532333438682)] + [Row(0.5, -0.5, 0.4522784471511907, -0.53063753095251787)] + public void CanComputeAsin(double real, double imag, double expectedReal, double expectedImag) + { + var actual = Complex.Asin(new Complex(real, imag)); + var expected = new Complex(expectedReal, expectedImag); + AssertHelpers.AlmostEqual(expected, actual, 14); + } + + [Test] + [Row(0.0, 0.0, 1.5707963267948966, 0.0)] + [Row(8.388608e6, 0.0, 0.0, 16.635532333438682)] + [Row(-8.388608e6, 0.0, 3.1415926535897931, -16.635532333438682)] + [Row(1.19209289550780998537e-7, 0.0, 1.570796207585607, 0.0)] + [Row(-1.19209289550780998537e-7, 0.0, 1.5707964460041861, 0.0)] + [Row(8.388608e6, 1.19209289550780998537e-7, 1.4210854715202073e-14, -16.635532333438682)] + [Row(-8.388608e6, -1.19209289550780998537e-7, 3.1415926535897789, 16.63553233343868)] + [Row(0.5, -0.5, 1.1185178796437059, 0.53063753095251787)] + public void CanComputeAcos(double real, double imag, double expectedReal, double expectedImag) + { + var actual = Complex.Acos(new Complex(real, imag)); + var expected = new Complex(expectedReal, expectedImag); + AssertHelpers.AlmostEqual(expected, actual, 14); + } + + [Test] + [Row(0.0, 0.0, 0.0, 0.0)] + [Row(8.388608e6, 0.0, 1.570796207585607, 0.0)] + [Row(-8.388608e6, 0.0, -1.570796207585607, 0.0)] + [Row(1.19209289550780998537e-7, 0.0, 1.1920928955078043e-7, 0.0)] + [Row(-1.19209289550780998537e-7, 0.0, -1.1920928955078043e-7, 0.0)] + [Row(8.388608e6, 1.19209289550780998537e-7, 1.570796207585607, 0.0)] + [Row(-8.388608e6, -1.19209289550780998537e-7, -1.570796207585607, 0.0)] + [Row(0.5, -0.5, 0.5535743588970452, -0.40235947810852507)] + public void CanComputeAtan(double real, double imag, double expectedReal, double expectedImag) + { + var actual = Complex.Atan(new Complex(real, imag)); + var expected = new Complex(expectedReal, expectedImag); + AssertHelpers.AlmostEqual(expected, actual, 14); + } + + [Test] + [Row(0.0, 0.0, 0.0, 0.0)] + [Row(0, 8.388608e6, 0.0, -1.1920928955078125e-7)] + [Row(-8.388608e6, 8.388608e6, -5.9604644775390625e-8, -5.9604644775390625e-8)] + public void CanComputeReciprocal(double real, double imag, double expectedReal, double expectedImag) + { + var actual = Complex.Reciprocal(new Complex(real, imag)); + var expected = new Complex(expectedReal, expectedImag); + AssertHelpers.AlmostEqual(expected, actual, 15); + } + + [Test] + public void CanConvertDecimalToComplex() + { + var orginal = new decimal(1.234567890); + var complex = (Complex)orginal; + Assert.AreEqual(1.234567890, complex.Real); + Assert.AreEqual(0.0, complex.Imaginary); + } + + [Test] + public void CanConvertByteToComplex() + { + const byte orginal = 123; + var complex = (Complex)orginal; + Assert.AreEqual(123, complex.Real); + Assert.AreEqual(0.0, complex.Imaginary); + } + + [Test] + public void CanConvertShortToComplex() + { + const short orginal = 123; + var complex = (Complex)orginal; + Assert.AreEqual(123, complex.Real); + Assert.AreEqual(0.0, complex.Imaginary); + } + + [Test] + public void CanConvertIntToComplex() + { + const int orginal = 123; + var complex = (Complex)orginal; + Assert.AreEqual(123, complex.Real); + Assert.AreEqual(0.0, complex.Imaginary); + } + + [Test] + public void CanConvertLongToComplex() + { + const long orginal = 123; + var complex = (Complex)orginal; + Assert.AreEqual(123, complex.Real); + Assert.AreEqual(0.0, complex.Imaginary); + } + + [Test] + public void CanConvertUIntToComplex() + { + const uint orginal = 123; + var complex = (Complex)orginal; + Assert.AreEqual(123, complex.Real); + Assert.AreEqual(0.0, complex.Imaginary); + } + + [Test] + public void CanConvertULongToComplex() + { + const ulong orginal = 123; + var complex = (Complex)orginal; + Assert.AreEqual(123, complex.Real); + Assert.AreEqual(0.0, complex.Imaginary); + } + + [Test] + public void CanConvertFloatToComplex() + { + const float orginal = 123.456789f; + var complex = (Complex)orginal; + Assert.AreEqual(123.456789f, (float)complex.Real); + Assert.AreEqual(0.0, complex.Imaginary); + } + + [Test] + public void CanConvertDoulbeComplex() + { + const double orginal = 123.456789; + var complex = (Complex)orginal; + Assert.AreEqual(123.456789, complex.Real); + Assert.AreEqual(0.0, complex.Imaginary); + } + } } \ No newline at end of file