From abb46af960552d29719d04fa55e6486f6d5da056 Mon Sep 17 00:00:00 2001 From: Marcus Cuda Date: Sun, 25 Apr 2010 16:20:31 +0800 Subject: [PATCH] synced up complex code to use the .NET 4.0 Complex class oved the Silverlight project to Silverlight 4 RC2 - needed to support the .NET 4.0 complex class --- .../Atlas/AtlasLinearAlgebraProvider.cs | 13 +- .../LinearAlgebra/Atlas/SafeNativeMethods.cs | 2 + .../LinearAlgebra/ILinearAlgebraProvider.cs | 2 + .../ManagedLinearAlgebraProvider.cs | 9 +- .../Mkl/MklLinearAlgebraProvider.cs | 13 +- .../LinearAlgebra/Mkl/SafeNativeMethods.cs | 2 + src/Numerics/Complex.cs | 1632 ----------------- src/Numerics/Complex32.cs | 378 +++- src/Numerics/ComplexExtensions.cs | 580 ++++++ .../DiscreteFourierTransform.Bluestein.cs | 5 +- .../DiscreteFourierTransform.Naive.cs | 1 + .../DiscreteFourierTransform.Options.cs | 1 + .../DiscreteFourierTransform.RadixN.cs | 1 + src/Numerics/IntegralTransforms/Transform.cs | 1 + src/Numerics/Numerics.csproj | 3 +- src/Numerics/Precision.cs | 54 + src/Numerics/Trigonometry.cs | 31 +- src/Silverlight/Silverlight.csproj | 10 +- src/UnitTests/AssertHelpers.cs | 19 + src/UnitTests/ComplexTests/Complex32Test.cs | 77 +- .../ComplexTests/ComplexTest.TextHandling.cs | 136 +- src/UnitTests/ComplexTests/ComplexTest.cs | 604 +----- .../IntegralTransformsTests/FourierTest.cs | 1 + .../IntegralTransformsTests/HartleyTest.cs | 1 + .../InverseTransformTest.cs | 1 + .../MatchingNaiveTransformTest.cs | 1 + .../ParsevalTheoremTest.cs | 5 +- src/UnitTests/TrigonometryTest.cs | 2 +- src/UnitTests/UnitTests.csproj | 1 + 29 files changed, 1148 insertions(+), 2438 deletions(-) delete mode 100644 src/Numerics/Complex.cs create mode 100644 src/Numerics/ComplexExtensions.cs diff --git a/src/Numerics/Algorithms/LinearAlgebra/Atlas/AtlasLinearAlgebraProvider.cs b/src/Numerics/Algorithms/LinearAlgebra/Atlas/AtlasLinearAlgebraProvider.cs index ce02c42e..316bc6ae 100644 --- a/src/Numerics/Algorithms/LinearAlgebra/Atlas/AtlasLinearAlgebraProvider.cs +++ b/src/Numerics/Algorithms/LinearAlgebra/Atlas/AtlasLinearAlgebraProvider.cs @@ -29,6 +29,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas { using System; + using System.Numerics; using Properties; /// @@ -1256,7 +1257,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas throw new ArgumentException(Resources.ArgumentVectorsSameLength); } - if (alpha.IsZero) + if (alpha.IsZero()) { return; } @@ -1275,9 +1276,9 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas if (x == null) { throw new ArgumentNullException("x"); - } + } - if (alpha.IsOne) + if (alpha.IsOne()) { return; } @@ -1852,7 +1853,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas throw new ArgumentException(Resources.ArgumentVectorsSameLength); } - if (alpha.IsZero) + if (alpha.IsZero()) { return; } @@ -1871,9 +1872,9 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas if (x == null) { throw new ArgumentNullException("x"); - } + } - if (alpha.IsOne) + if (alpha.IsOne()) { return; } diff --git a/src/Numerics/Algorithms/LinearAlgebra/Atlas/SafeNativeMethods.cs b/src/Numerics/Algorithms/LinearAlgebra/Atlas/SafeNativeMethods.cs index 250767ba..7a8fd4e4 100644 --- a/src/Numerics/Algorithms/LinearAlgebra/Atlas/SafeNativeMethods.cs +++ b/src/Numerics/Algorithms/LinearAlgebra/Atlas/SafeNativeMethods.cs @@ -36,6 +36,8 @@ using System.Security; namespace MathNet.Numerics.Algorithms.LinearAlgebra.Atlas { + using System.Numerics; + /// /// P/Invoke methods to the native math libraries. /// diff --git a/src/Numerics/Algorithms/LinearAlgebra/ILinearAlgebraProvider.cs b/src/Numerics/Algorithms/LinearAlgebra/ILinearAlgebraProvider.cs index e0a4a0be..943938ec 100644 --- a/src/Numerics/Algorithms/LinearAlgebra/ILinearAlgebraProvider.cs +++ b/src/Numerics/Algorithms/LinearAlgebra/ILinearAlgebraProvider.cs @@ -25,6 +25,8 @@ // INITIAL DRAFT MISSING EXCEPTION SPECIFICATIONS namespace MathNet.Numerics.Algorithms.LinearAlgebra { + using System.Numerics; + /// /// Interface to linear algebra algorithms that work off 1-D arrays. /// diff --git a/src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.cs b/src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.cs index d4212109..2b1db7ea 100644 --- a/src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.cs +++ b/src/Numerics/Algorithms/LinearAlgebra/ManagedLinearAlgebraProvider.cs @@ -24,6 +24,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra { using System; + using System.Numerics; using Properties; using Threading; @@ -2406,7 +2407,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra throw new ArgumentNullException("x"); } - if (alpha.IsOne) + if (alpha.IsOne()) { return; } @@ -2736,7 +2737,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra cColumns = bColumns; } - if (alpha.IsZero && beta.IsZero) + if (alpha.IsZero() && beta.IsZero()) { Array.Clear(c, 0, c.Length); return; @@ -2766,9 +2767,9 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra bdata = b; } - if (alpha.IsOne) + if (alpha.IsOne()) { - if (beta.IsZero) + if (beta.IsZero()) { if ((int)transposeA > 111 && (int)transposeB > 111) { diff --git a/src/Numerics/Algorithms/LinearAlgebra/Mkl/MklLinearAlgebraProvider.cs b/src/Numerics/Algorithms/LinearAlgebra/Mkl/MklLinearAlgebraProvider.cs index f5085928..1422bde4 100644 --- a/src/Numerics/Algorithms/LinearAlgebra/Mkl/MklLinearAlgebraProvider.cs +++ b/src/Numerics/Algorithms/LinearAlgebra/Mkl/MklLinearAlgebraProvider.cs @@ -29,6 +29,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl { using System; + using System.Numerics; using Properties; /// @@ -1255,7 +1256,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl throw new ArgumentException(Resources.ArgumentVectorsSameLength); } - if (alpha.IsZero) + if (alpha.IsZero()) { return; } @@ -1274,9 +1275,9 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl if (x == null) { throw new ArgumentNullException("x"); - } + } - if (alpha.IsOne) + if (alpha.IsOne()) { return; } @@ -1851,7 +1852,7 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl throw new ArgumentException(Resources.ArgumentVectorsSameLength); } - if (alpha.IsZero) + if (alpha.IsZero()) { return; } @@ -1870,9 +1871,9 @@ namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl if (x == null) { throw new ArgumentNullException("x"); - } + } - if (alpha.IsOne) + if (alpha.IsOne()) { return; } diff --git a/src/Numerics/Algorithms/LinearAlgebra/Mkl/SafeNativeMethods.cs b/src/Numerics/Algorithms/LinearAlgebra/Mkl/SafeNativeMethods.cs index 755d4b51..09aa5d19 100644 --- a/src/Numerics/Algorithms/LinearAlgebra/Mkl/SafeNativeMethods.cs +++ b/src/Numerics/Algorithms/LinearAlgebra/Mkl/SafeNativeMethods.cs @@ -36,6 +36,8 @@ using System.Security; namespace MathNet.Numerics.Algorithms.LinearAlgebra.Mkl { + using System.Numerics; + /// /// P/Invoke methods to the native math libraries. /// diff --git a/src/Numerics/Complex.cs b/src/Numerics/Complex.cs deleted file mode 100644 index 4cab271a..00000000 --- a/src/Numerics/Complex.cs +++ /dev/null @@ -1,1632 +0,0 @@ -// -// Math.NET Numerics, part of the Math.NET Project -// http://mathnet.opensourcedotnet.info -// -// Copyright (c) 2009 Math.NET -// -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. -// - -namespace MathNet.Numerics -{ - using System; - using System.Collections.Generic; - using System.Runtime.InteropServices; - using System.Text; - using Properties; - - /// - /// Complex numbers class. - /// - /// - /// - /// The class Complex provides all elementary operations - /// on complex numbers. All the operators +, -, - /// *, /, ==, != are defined in the - /// canonical way. Additional complex trigonometric functions such - /// as , ... - /// are also provided. Note that the Complex structures - /// has two special constant values and - /// . - /// - /// - /// In order to avoid possible ambiguities resulting from a - /// Complex(double, double) constructor, the static methods - /// and - /// are provided instead. - /// - /// - /// - /// Complex x = Complex.FromRealImaginary(1d, 2d); - /// Complex y = Complex.FromModulusArgument(1d, Math.Pi); - /// Complex z = (x + y) / (x - y); - /// - /// - /// - /// For mathematical details about complex numbers, please - /// have a look at the - /// Wikipedia - /// - /// -#if !SILVERLIGHT - [Serializable] -#endif - [StructLayout(LayoutKind.Sequential)] - public struct Complex : IFormattable, IEquatable, IPrecisionSupport - { - #region fields - - /// - /// Represents imaginary unit number. - /// - private static readonly Complex _i = new Complex(0, 1); - - /// - /// Represents a infinite complex number - /// - private static readonly Complex _infinity = new Complex(double.PositiveInfinity, double.PositiveInfinity); - - /// - /// Represents not-a-number. - /// - private static readonly Complex _nan = new Complex(Double.NaN, Double.NaN); - - /// - /// Representing the one value. - /// - private static readonly Complex _one = new Complex(1.0, 0.0); - - /// - /// Representing the zero value. - /// - private static readonly Complex _zero = new Complex(0.0, 0.0); - - /// - /// The real component of the complex number. - /// - private readonly double _real; - - /// - /// The imaginary component of the complex number. - /// - private readonly double _imag; - - #endregion fields - - #region Constructor - - /// - /// Initializes a new instance of the Complex structure with the given real - /// and imaginary parts. - /// - /// - /// The value for the real component. - /// - /// - /// The value for the imaginary component. - /// - public Complex(double real, double imaginary) - { - _real = real; - _imag = imaginary; - } - - #endregion - - #region Properties - - /// - /// Gets a value representing the infinity value. This field is constant. - /// - /// The infinity. - /// - /// The semantic associated to this value is a Complex of - /// infinite real and imaginary part. If you need more formal complex - /// number handling (according to the Riemann Sphere and the extended - /// complex plane C*, or using directed infinity) please check out the - /// alternative Math.NET symbolics packages instead. - /// - /// A value representing the infinity value. - public static Complex Infinity - { - get { return _infinity; } - } - - /// - /// Gets a value representing not-a-number. This field is constant. - /// - /// A value representing not-a-number. - public static Complex NaN - { - get { return _nan; } - } - - /// - /// Gets a value representing the imaginary unit number. This field is constant. - /// - /// A value representing the imaginary unit number. - public static Complex ImaginaryOne - { - get { return _i; } - } - - /// - /// Gets a value representing the zero value. This field is constant. - /// - /// A value representing the zero value. - public static Complex Zero - { - get { return new Complex(0.0, 0.0); } - } - - /// - /// Gets a value representing the 1 value. This field is constant. - /// - /// A value representing the 1 value. - public static Complex One - { - get { return _one; } - } - - #endregion Properties - - /// - /// Gets the real component of the complex number. - /// - /// The real component of the complex number. - public double Real - { - get { return _real; } - } - - /// - /// Gets the real imaginary component of the complex number. - /// - /// The real imaginary component of the complex number. - public double Imaginary - { - get { return _imag; } - } - - /// - /// Gets a value indicating whether the Complex is zero. - /// - /// true if this instance is zero; otherwise, false. - public bool IsZero - { - get { return _real == 0.0 && _imag == 0.0; } - } - - /// - /// Gets a value indicating whether the Complex is one. - /// - /// true if this instance is one; otherwise, false. - public bool IsOne - { - get { return _real == 1.0 && _imag == 0.0; } - } - - /// - /// Gets a value indicating whether the Complex is the imaginary unit. - /// - /// true if this instance is ImaginaryOne; otherwise, false. - public bool IsImaginaryOne - { - get { return _real == 0.0 && _imag == 1.0; } - } - - /// - /// Gets a value indicating whether the provided Complexevaluates - /// to a value that is not a number. - /// - /// - /// true if this instance is ; otherwise, - /// false. - /// - public bool IsNaN - { - get { return double.IsNaN(_real) || double.IsNaN(_imag); } - } - - /// - /// Gets a value indicating whether the provided Complex evaluates to an - /// infinite value. - /// - /// - /// true if this instance is infinite; otherwise, false. - /// - /// - /// True if it either evaluates to a complex infinity - /// or to a directed infinity. - /// - public bool IsInfinity - { - get { return double.IsInfinity(_real) || double.IsInfinity(_imag); } - } - - /// - /// Gets a value indicating whether the provided Complex is real. - /// - /// true if this instance is a real number; otherwise, false. - public bool IsReal - { - get { return _imag == 0.0; } - } - - /// - /// Gets a value indicating whether the provided Complex is real and not negative, that is >= 0. - /// - /// - /// true if this instance is real nonnegative number; otherwise, false. - /// - public bool IsRealNonNegative - { - get { return _imag == 0.0 && _real >= 0; } - } - - /// - /// Gets the conjugate of this Complex. - /// - /// - /// The semantic of setting the conjugate is such that - /// - /// // a, b of type Complex - /// a.Conjugate = b; - /// - /// is equivalent to - /// - /// // a, b of type Complex - /// a = b.Conjugate - /// - /// - public Complex Conjugate - { - get { return new Complex(_real, -_imag); } - } - - /// - /// Gets the magnitude or modulus of this Complex. - /// - /// - public double Magnitude - { - get { return Math.Sqrt((_real * _real) + (_imag * _imag)); } - } - - /// - /// Gets the squared magnitude of this Complex. - /// - /// - public double MagnitudeSquared - { - get { return (_real * _real) + (_imag * _imag); } - } - - /// - /// Gets phase or argument of this Complex. - /// - /// - /// Phase always returns a value bigger than negative Pi and - /// smaller or equal to Pi. If this Complex is zero, the Complex - /// is assumed to be positive real with an argument of zero. - /// - public double Phase - { - get - { - if (IsReal && _real < 0) - { - return Math.PI; - } - - return IsRealNonNegative ? 0 : Math.Atan2(_imag, _real); - } - } - - /// - /// Gets the unity of this complex (same argument, but on the unit circle; exp(I*arg)) - /// - public Complex Sign - { - get - { - if (double.IsPositiveInfinity(_real) && double.IsPositiveInfinity(_imag)) - { - return new Complex(Constants.Sqrt1Over2, Constants.Sqrt1Over2); - } - - if (double.IsPositiveInfinity(_real) && double.IsNegativeInfinity(_imag)) - { - return new Complex(Constants.Sqrt1Over2, -Constants.Sqrt1Over2); - } - - if (double.IsNegativeInfinity(_real) && double.IsPositiveInfinity(_imag)) - { - return new Complex(-Constants.Sqrt1Over2, -Constants.Sqrt1Over2); - } - - if (double.IsNegativeInfinity(_real) && double.IsNegativeInfinity(_imag)) - { - return new Complex(-Constants.Sqrt1Over2, Constants.Sqrt1Over2); - } - - // don't replace this with "Magnitude"! - var mod = SpecialFunctions.Hypotenuse(_real, _imag); - if (mod == 0.0) - { - return Zero; - } - - return new Complex(_real / mod, _imag / mod); - } - } - - #region Exponential Functions - - /// - /// Exponential of this Complex (exp(x), E^x). - /// - /// - /// The exponential of this complex number. - /// - public Complex Exponential() - { - var exp = Math.Exp(_real); - if (IsReal) - { - return new Complex(exp, 0.0); - } - - return new Complex(exp * Trig.Cosine(_imag), exp * Trig.Sine(_imag)); - } - - /// - /// Natural Logarithm of this Complex (Base E). - /// - /// - /// The natural logarithm of this complex number. - /// - public Complex NaturalLogarithm() - { - if (IsRealNonNegative) - { - return new Complex(Math.Log(_real), 0.0); - } - - return new Complex(0.5 * Math.Log(MagnitudeSquared), Phase); - } - - /// - /// Raise this Complex to the given value. - /// - /// - /// The exponent. - /// - /// - /// The complex number raised to the given exponent. - /// - public Complex Power(Complex exponent) - { - if (IsZero) - { - if (exponent.IsZero) - { - return One; - } - - if (exponent.Real > 0.0) - { - return Zero; - } - - if (exponent.Real < 0) - { - if (exponent.Imaginary == 0.0) - { - return new Complex(double.PositiveInfinity, 0.0); - } - - return new Complex(double.PositiveInfinity, double.PositiveInfinity); - } - - return NaN; - } - - return (exponent * NaturalLogarithm()).Exponential(); - } - - /// - /// Raise this Complex to the inverse of the given value. - /// - /// - /// The root exponent. - /// - /// - /// The complex raised to the inverse of the given exponent. - /// - public Complex Root(Complex rootExponent) - { - return Power(1 / rootExponent); - } - - /// - /// The Square (power 2) of this Complex - /// - /// - /// The square of this complex number. - /// - public Complex Square() - { - if (IsReal) - { - return new Complex(_real * _real, 0.0); - } - - return new Complex((_real * _real) - (_imag * _imag), 2 * _real * _imag); - } - - /// - /// The Square Root (power 1/2) of this Complex - /// - /// - /// The square root of this complex number. - /// - public Complex SquareRoot() - { - if (IsRealNonNegative) - { - return new Complex(Math.Sqrt(_real), 0.0); - } - - Complex result; - - var absReal = Math.Abs(Real); - var absImag = Math.Abs(Imaginary); - double w; - if (absReal >= absImag) - { - var ratio = Imaginary / Real; - w = Math.Sqrt(absReal) * Math.Sqrt(0.5 * (1.0 + Math.Sqrt(1.0 + (ratio * ratio)))); - } - else - { - var ratio = Real / Imaginary; - w = Math.Sqrt(absImag) * Math.Sqrt(0.5 * (Math.Abs(ratio) + Math.Sqrt(1.0 + (ratio * ratio)))); - } - - if (Real >= 0.0) - { - result = new Complex(w, Imaginary / (2.0 * w)); - } - else if (Imaginary >= 0.0) - { - result = new Complex(absImag / (2.0 * w), w); - } - else - { - result = new Complex(absImag / (2.0 * w), -w); - } - - return result; - } - - #endregion - - #region Static Initializers - - /// - /// Constructs a Complex from its real - /// and imaginary parts. - /// - /// - /// The value for the real component. - /// - /// - /// The value for the imaginary component. - /// - /// - /// A new Complex with the given values. - /// - public static Complex WithRealImaginary(double real, double imaginary) - { - return new Complex(real, imaginary); - } - - /// - /// Constructs a Complex from its modulus and - /// argument. - /// - /// - /// Must be non-negative. - /// - /// - /// Real number. - /// - /// - /// A new Complex from the given values. - /// - public static Complex WithModulusArgument(double modulus, double argument) - { - if (modulus < 0.0) - { - throw new ArgumentOutOfRangeException("modulus", Resources.ArgumentNotNegative); - } - - return new Complex(modulus * Math.Cos(argument), modulus * Math.Sin(argument)); - } - - #endregion - - #region IFormattable Members - - /// - /// A string representation of this complex number. - /// - /// - /// The string representation of this complex number. - /// - public override string ToString() - { - return ToString(null, null); - } - - /// - /// A string representation of this complex number. - /// - /// - /// The string representation of this complex number formatted as specified by the - /// format string. - /// - /// - /// A format specification. - /// - public string ToString(string format) - { - return ToString(format, null); - } - - /// - /// A string representation of this complex number. - /// - /// - /// The string representation of this complex number formatted as specified by the - /// format provider. - /// - /// - /// An that supplies culture-specific formatting information. - /// - public string ToString(IFormatProvider formatProvider) - { - return ToString(null, formatProvider); - } - - /// - /// A string representation of this complex number. - /// - /// - /// The string representation of this complex number formatted as specified by the - /// format string and format provider. - /// - /// - /// if the n, is not a number. - /// - /// - /// if s, is . - /// - /// - /// A format specification. - /// - /// - /// An that supplies culture-specific formatting information. - /// - public string ToString(string format, IFormatProvider formatProvider) - { - var numberFormatInfo = formatProvider.GetNumberFormatInfo(); - - if (IsNaN) - { - return numberFormatInfo.NaNSymbol; - } - - if (IsInfinity) - { - return numberFormatInfo.PositiveInfinitySymbol; - } - - var ret = new StringBuilder(); - - if (_real != 0.0) - { - ret.Append(_real.ToString(format, formatProvider)); - } - - if (_imag != 0.0) - { - if (_real != 0.0) - { - if (_imag < 0) - { - ret.Append(" "); - } - else - { - ret.Append(" + "); - } - } - - ret.Append(_imag.ToString(format, formatProvider)).Append("i"); - } - - if (ret.Length == 0) - { - ret.Append(0.0.ToString(format, formatProvider)); - } - - return ret.ToString(); - } - - #endregion - - #region IEquatable Members - - /// - /// Checks if two complex numbers are equal. Two complex numbers are equal if their - /// corresponding real and imaginary components are equal. - /// - /// - /// Returns true if the two objects are the same object, or if their corresponding - /// real and imaginary components are equal, false otherwise. - /// - /// - /// The complex number to compare to with. - /// - public bool Equals(Complex other) - { - if (IsNaN || other.IsNaN) - { - return false; - } - - if (IsInfinity && other.IsInfinity) - { - return true; - } - - return _real.AlmostEqual(other._real) && _imag.AlmostEqual(other._imag); - } - - /// - /// The hash code for the complex number. - /// - /// - /// The hash code of the complex number. - /// - /// - /// The hash code is calculated as - /// System.Math.Exp(ComplexMath.Absolute(complexNumber)). - /// - public override int GetHashCode() - { - return _real.GetHashCode() ^ (-_imag.GetHashCode()); - } - - /// - /// Checks if two complex numbers are equal. Two complex numbers are equal if their - /// corresponding real and imaginary components are equal. - /// - /// - /// Returns true if the two objects are the same object, or if their corresponding - /// real and imaginary components are equal, false otherwise. - /// - /// - /// The complex number to compare to with. - /// - public override bool Equals(object obj) - { - return (obj is Complex) && Equals((Complex)obj); - } - - #endregion - - #region Operators - - /// - /// Equality test. - /// - /// One of complex numbers to compare. - /// The other complex numbers to compare. - /// true if the real and imaginary components of the two complex numbers are equal; false otherwise. - public static bool operator ==(Complex complex1, Complex complex2) - { - return complex1.Equals(complex2); - } - - /// - /// Inequality test. - /// - /// One of complex numbers to compare. - /// The other complex numbers to compare. - /// true if the real or imaginary components of the two complex numbers are not equal; false otherwise. - public static bool operator !=(Complex complex1, Complex complex2) - { - return !complex1.Equals(complex2); - } - - /// - /// Unary addition. - /// - /// The complex number to operate on. - /// Returns the same complex number. - public static Complex operator +(Complex summand) - { - return summand; - } - - /// - /// Unary minus. - /// - /// The complex number to operate on. - /// The negated value of the . - public static Complex operator -(Complex subtrahend) - { - return new Complex(-subtrahend._real, -subtrahend._imag); - } - - /// Addition operator. Adds two complex numbers together. - /// The result of the addition. - /// One of the complex numbers to add. - /// The other complex numbers to add. - public static Complex operator +(Complex summand1, Complex summand2) - { - return new Complex(summand1._real + summand2._real, summand1._imag + summand2._imag); - } - - /// Subtraction operator. Subtracts two complex numbers. - /// The result of the subtraction. - /// The complex number to subtract from. - /// The complex number to subtract. - public static Complex operator -(Complex minuend, Complex subtrahend) - { - return new Complex(minuend._real - subtrahend._real, minuend._imag - subtrahend._imag); - } - - /// Addition operator. Adds a complex number and double together. - /// The result of the addition. - /// The complex numbers to add. - /// The double value to add. - public static Complex operator +(Complex summand1, double summand2) - { - return new Complex(summand1._real + summand2, summand1._imag); - } - - /// Subtraction operator. Subtracts double value from a complex value. - /// The result of the subtraction. - /// The complex number to subtract from. - /// The double value to subtract. - public static Complex operator -(Complex minuend, double subtrahend) - { - return new Complex(minuend._real - subtrahend, minuend._imag); - } - - /// Addition operator. Adds a complex number and double together. - /// The result of the addition. - /// The double value to add. - /// The complex numbers to add. - public static Complex operator +(double summand1, Complex summand2) - { - return new Complex(summand2._real + summand1, summand2._imag); - } - - /// Subtraction operator. Subtracts complex value from a double value. - /// The result of the subtraction. - /// The double vale to subtract from. - /// The complex value to subtract. - public static Complex operator -(double minuend, Complex subtrahend) - { - return new Complex(minuend - subtrahend._real, -subtrahend._imag); - } - - /// Multiplication operator. Multiplies two complex numbers. - /// The result of the multiplication. - /// One of the complex numbers to multiply. - /// The other complex number to multiply. - public static Complex operator *(Complex multiplicand, Complex multiplier) - { - return new Complex( - (multiplicand._real * multiplier._real) - (multiplicand._imag * multiplier._imag), - (multiplicand._real * multiplier._imag) + (multiplicand._imag * multiplier._real)); - } - - /// Multiplication operator. Multiplies a complex number with a double value. - /// The result of the multiplication. - /// The double value to multiply. - /// The complex number to multiply. - public static Complex operator *(double multiplicand, Complex multiplier) - { - return new Complex(multiplier._real * multiplicand, multiplier._imag * multiplicand); - } - - /// Multiplication operator. Multiplies a complex number with a double value. - /// The result of the multiplication. - /// The complex number to multiply. - /// The double value to multiply. - public static Complex operator *(Complex multiplicand, double multiplier) - { - return new Complex(multiplicand._real * multiplier, multiplicand._imag * multiplier); - } - - /// Division operator. Divides a complex number by another. - /// The result of the division. - /// The dividend. - /// The divisor. - public static Complex operator /(Complex dividend, Complex divisor) - { - if (divisor.IsZero) - { - return Infinity; - } - - var modSquared = divisor.MagnitudeSquared; - return new Complex( - ((dividend._real * divisor._real) + (dividend._imag * divisor._imag)) / modSquared, - ((dividend._imag * divisor._real) - (dividend._real * divisor._imag)) / modSquared); - } - - /// Division operator. Divides a double value by a complex number. - /// The result of the division. - /// The dividend. - /// The divisor. - public static Complex operator /(double dividend, Complex divisor) - { - if (divisor.IsZero) - { - return Infinity; - } - - var zmod = divisor.MagnitudeSquared; - return new Complex(dividend * divisor._real / zmod, -dividend * divisor._imag / zmod); - } - - /// Division operator. Divides a complex number by a double value. - /// The result of the division. - /// The dividend. - /// The divisor. - public static Complex operator /(Complex dividend, double divisor) - { - if (divisor == 0.0) - { - return Infinity; - } - - return new Complex(dividend._real / divisor, dividend._imag / divisor); - } - - /// - /// Unary addition. - /// - /// - /// Returns the same complex number. - /// - public Complex Plus() - { - return this; - } - - /// - /// Unary minus. - /// - /// - /// The negated value of this complex number. - /// - public Complex Negate() - { - return -this; - } - - /// - /// Adds a complex number to this one. - /// - /// - /// The result of the addition. - /// - /// - /// The other complex number to add. - /// - public Complex Add(Complex other) - { - return this + other; - } - - /// - /// Subtracts a complex number from this one. - /// - /// - /// The result of the subtraction. - /// - /// - /// The other complex number to subtract from this one. - /// - public Complex Subtract(Complex other) - { - return this - other; - } - - /// - /// Multiplies this complex number with this one. - /// - /// - /// The result of the multiplication. - /// - /// - /// The complex number to multiply. - /// - public Complex Multiply(Complex multiplier) - { - return this * multiplier; - } - - /// - /// Divides this complex number by another. - /// - /// - /// The result of the division. - /// - /// - /// The divisor. - /// - public Complex Divide(Complex divisor) - { - return this / divisor; - } - - #endregion - - #region IPrecisionSupport - - /// - /// Returns a Norm of a value of this type, which is appropriate for measuring how - /// close this value is to zero. - /// - /// - /// A norm of this value. - /// - double IPrecisionSupport.Norm() - { - return MagnitudeSquared; - } - - /// - /// Returns a Norm of the difference of two values of this type, which is - /// appropriate for measuring how close together these two values are. - /// - /// - /// The value to compare with. - /// - /// - /// A norm of the difference between this and the other value. - /// - double IPrecisionSupport.NormOfDifference(Complex otherValue) - { - return (this - otherValue).MagnitudeSquared; - } - - #endregion - - #region Parse Functions - - /// - /// Creates a complex number based on a string. The string can be in the - /// following formats (without the quotes): 'n', 'ni', 'n +/- ni', - /// 'ni +/- n', 'n,n', 'n,ni,' '(n,n)', or '(n,ni)', where n is a double. - /// - /// - /// A complex number containing the value specified by the given string. - /// - /// - /// The string to parse. - /// - public static Complex Parse(string value) - { - return Parse(value, null); - } - - /// - /// Creates a complex number based on a string. The string can be in the - /// following formats (without the quotes): 'n', 'ni', 'n +/- ni', - /// 'ni +/- n', 'n,n', 'n,ni,' '(n,n)', or '(n,ni)', where n is a double. - /// - /// - /// A complex number containing the value specified by the given string. - /// - /// - /// the string to parse. - /// - /// - /// An that supplies culture-specific - /// formatting information. - /// - public static Complex Parse(string value, IFormatProvider formatProvider) - { - if (value == null) - { - throw new ArgumentNullException(value); - } - - value = value.Trim(); - if (value.Length == 0) - { - throw new FormatException(); - } - - // strip out parens - if (value.StartsWith("(", StringComparison.Ordinal)) - { - if (!value.EndsWith(")", StringComparison.Ordinal)) - { - throw new FormatException(); - } - - value = value.Substring(1, value.Length - 2).Trim(); - } - - // keywords - var numberFormatInfo = formatProvider.GetNumberFormatInfo(); - var textInfo = formatProvider.GetTextInfo(); - var keywords = - new[] - { - textInfo.ListSeparator, numberFormatInfo.NaNSymbol, - numberFormatInfo.NegativeInfinitySymbol, numberFormatInfo.PositiveInfinitySymbol, - "+", "-", "i", "j" - }; - - // lexing - var tokens = new LinkedList(); - GlobalizationHelper.Tokenize(tokens.AddFirst(value), keywords, 0); - var token = tokens.First; - - // parse the left part - bool isLeftPartImaginary; - double leftPart = ParsePart(ref token, out isLeftPartImaginary, formatProvider); - if (token == null) - { - return isLeftPartImaginary ? new Complex(0, leftPart) : new Complex(leftPart, 0); - } - - // parse the right part - if (token.Value == textInfo.ListSeparator) - { - // format: real,imag - token = token.Next; - - if (isLeftPartImaginary) - { - // left must not contain 'i', right doesn't matter. - throw new FormatException(); - } - - bool isRightPartImaginary; - double rightPart = ParsePart(ref token, out isRightPartImaginary, formatProvider); - - return new Complex(leftPart, rightPart); - } - else - { - // format: real + imag - bool isRightPartImaginary; - double rightPart = ParsePart(ref token, out isRightPartImaginary, formatProvider); - - if (!(isLeftPartImaginary ^ isRightPartImaginary)) - { - // either left or right part must contain 'i', but not both. - throw new FormatException(); - } - - return isLeftPartImaginary ? new Complex(rightPart, leftPart) : new Complex(leftPart, rightPart); - } - } - - /// - /// Parse a part (real or complex) from a complex number. - /// - /// Start Token. - /// Is set to true if the part identified itself as being imaginary. - /// - /// An that supplies culture-specific - /// formatting information. - /// - /// Resulting part as double. - /// - private static double ParsePart(ref LinkedListNode token, out bool imaginary, IFormatProvider format) - { - imaginary = false; - if (token == null) - { - throw new FormatException(); - } - - // handle prefix modifiers - if (token.Value == "+") - { - token = token.Next; - - if (token == null) - { - throw new FormatException(); - } - } - - bool negative = false; - if (token.Value == "-") - { - negative = true; - token = token.Next; - - if (token == null) - { - throw new FormatException(); - } - } - - // handle prefix imaginary symbol - if (String.Compare(token.Value, "i", StringComparison.OrdinalIgnoreCase) == 0 - || String.Compare(token.Value, "j", StringComparison.OrdinalIgnoreCase) == 0) - { - imaginary = true; - token = token.Next; - - if (token == null) - { - return negative ? -1 : 1; - } - } - -#if SILVERLIGHT - var value = GlobalizationHelper.ParseDouble(ref token); -#else - var value = GlobalizationHelper.ParseDouble(ref token, format.GetCultureInfo()); -#endif - - // handle suffix imaginary symbol - if (token != null && (String.Compare(token.Value, "i", StringComparison.OrdinalIgnoreCase) == 0 - || String.Compare(token.Value, "j", StringComparison.OrdinalIgnoreCase) == 0)) - { - if (imaginary) - { - // only one time allowed: either prefix or suffix, or neither. - throw new FormatException(); - } - - imaginary = true; - token = token.Next; - } - - return negative ? -value : value; - } - - /// - /// Converts the string representation of a complex number to a double-precision complex number equivalent. - /// A return value indicates whether the conversion succeeded or failed. - /// - /// - /// A string containing a complex number to convert. - /// - /// - /// The parsed value. - /// - /// - /// If the conversion succeeds, the result will contain a complex number equivalent to value. - /// Otherwise the result will contain complex32.Zero. This parameter is passed uninitialized - /// - public static bool TryParse(string value, out Complex result) - { - return TryParse(value, null, out result); - } - - /// - /// Converts the string representation of a complex number to double-precision complex number equivalent. - /// A return value indicates whether the conversion succeeded or failed. - /// - /// - /// A string containing a complex number to convert. - /// - /// - /// An that supplies culture-specific formatting information about value. - /// - /// - /// The parsed value. - /// - /// - /// If the conversion succeeds, the result will contain a complex number equivalent to value. - /// Otherwise the result will contain complex32.Zero. This parameter is passed uninitialized - /// - public static bool TryParse(string value, IFormatProvider formatProvider, out Complex result) - { - bool ret; - try - { - result = Parse(value, formatProvider); - ret = true; - } - catch (ArgumentNullException) - { - result = _zero; - ret = false; - } - catch (FormatException) - { - result = _zero; - ret = false; - } - - return ret; - } - - #endregion - - #region Conversion - /// - /// Explicit conversion of a Complex32 to a Complex. - /// - /// The decimal value to convert. - /// The result of the conversion. - public static implicit operator Complex(Complex32 value) - { - return new Complex(value.Real, value.Imaginary); - } - - /// - /// Explicit conversion of a real decimal to a Complex. - /// - /// The decimal value to convert. - /// The result of the conversion. - public static explicit operator Complex(decimal value) - { - return new Complex((double)value, 0.0); - } - - /// - /// Implicit conversion of a real byte to a Complex. - /// - /// The byte value to convert. - /// The result of the conversion. - public static implicit operator Complex(byte value) - { - return new Complex(value, 0.0); - } - - /// - /// Implicit conversion of a real short to a Complex. - /// - /// The short value to convert. - /// The result of the conversion. - public static implicit operator Complex(short value) - { - return new Complex(value, 0.0); - } - - /// - /// Implicit conversion of a real int to a Complex. - /// - /// The int value to convert. - /// The result of the conversion. - public static implicit operator Complex(int value) - { - return new Complex(value, 0.0); - } - - /// - /// Implicit conversion of a real long to a Complex. - /// - /// The long value to convert. - /// The result of the conversion. - public static implicit operator Complex(long value) - { - return new Complex(value, 0.0); - } - - /// - /// Implicit conversion of a real uint to a Complex. - /// - /// The uint value to convert. - /// The result of the conversion. - public static implicit operator Complex(uint value) - { - return new Complex(value, 0.0); - } - - /// - /// Implicit conversion of a real ulong to a Complex. - /// - /// The ulong value to convert. - /// The result of the conversion. - public static implicit operator Complex(ulong value) - { - return new Complex(value, 0.0); - } - - /// - /// Implicit conversion of a real float to a Complex. - /// - /// The float value to convert. - /// The result of the conversion. - public static implicit operator Complex(float value) - { - return new Complex(value, 0.0); - } - - /// - /// Implicit conversion of a real double to a Complex. - /// - /// The double value to convert. - /// The result of the conversion. - public static implicit operator Complex(double value) - { - return new Complex(value, 0.0); - } - - #endregion - - #region Static methods from .NET 4.0 - /// - /// Gets the absolute value (or magnitude) of a complex number. - /// - /// A complex number. - /// The absolute value (or magnitude) of a complex number. - public static double Abs(Complex value) - { - return value.Magnitude; - } - - /// - /// Trigonometric Arc Cosine of a Complex number. - /// - /// A complex number. - /// - /// The arc cosine of a complex number. - /// - public static Complex Acos(Complex value) - { - return value.InverseCosine(); - } - - /// - /// Trigonometric Arc Sine of a Complex number. - /// - /// A complex number. - /// - /// The arc sine of a complex number. - /// - public static Complex Asin(Complex value) - { - return value.InverseSine(); - } - - /// - /// Trigonometric Arc Tangent of a Complex number. - /// - /// A complex number. - /// - /// The arc tangent of a complex number. - /// - public static Complex Atan(Complex value) - { - return value.InverseTangent(); - } - - /// - /// Trigonometric Cosine of a Complex number. - /// - /// A complex number. - /// - /// The cosine of a complex number. - /// - public static Complex Cos(Complex value) - { - return value.Cosine(); - } - - /// - /// Trigonometric Sine of a Complex number. - /// - /// A complex number. - /// - /// The Sine of a complex number. - /// - public static Complex Sin(Complex value) - { - return value.Sine(); - } - - /// - /// Trigonometric Tangent of a Complex number. - /// - /// A complex number. - /// - /// The tangent of a complex number. - /// - public static Complex Tan(Complex value) - { - return value.Tangent(); - } - - /// - /// Trigonometric Hyperbolic Cosine of a Complex number. - /// - /// A complex number. - /// - /// The hyperbolic cosine of a complex number. - /// - public static Complex Cosh(Complex value) - { - return value.HyperbolicCosine(); - } - - /// - /// Trigonometric Hyperbolic Sine of a Complex number. - /// - /// A complex number. - /// - /// The hyperbolic sine of a complex number. - /// - public static Complex Sinh(Complex value) - { - return value.HyperbolicSine(); - } - - /// - /// Trigonometric Hyperbolic Tangent of a Complex number. - /// - /// A complex number. - /// - /// The hyperbolic tangent of a complex number. - /// - public static Complex Tanh(Complex value) - { - return value.HyperbolicTangent(); - } - - /// - /// Exponential of a Complex number (exp(x), E^x). - /// - /// A complex number. - /// - /// The exponential of a complex number. - /// - public static Complex Exp(Complex value) - { - return value.Exponential(); - } - - /// - /// Constructs a Complex from its magnitude and phase. - /// - /// - /// Must be non-negative. - /// - /// - /// Real number. - /// - /// - /// A new Complex from the given values. - /// - /// - public static Complex FromPolarCoordinates(double magnitude, double phase) - { - return WithModulusArgument(magnitude, phase); - } - - /// - /// Natural Logarithm of a Complex number (exp(x), E^x). - /// - /// A complex number. - /// - /// The natural logarithm of a complex number. - /// - public static Complex Log(Complex value) - { - return value.NaturalLogarithm(); - } - - /// - /// Returns the logarithm of a specified complex number in a specified base - /// - /// A complex number. - /// The base of the logarithm. - /// The logarithm of value in base baseValue. - public static Complex Log(Complex value, double baseValue) - { - if (baseValue == 1.0) - { - return double.NaN; - } - - return value.NaturalLogarithm() / Math.Log(baseValue, Math.E); - } - - /// - /// Returns the base-10 logarithm of a specified complex number in a specified base - /// - /// A complex number. - /// The base-10 logarithm of the complex number. - public static Complex Log10(Complex value) - { - return Log(value, 10); - } - - /// - /// Raise this a Complexnumber to the given value. - /// - /// A complex number. - /// The exponent. - /// - /// The complex number raised to the given exponent. - /// - public static Complex Pow(Complex value, Complex power) - { - return value.Power(power); - } - - /// - /// Raise this a Complexnumber to the given value. - /// - /// A complex number. - /// The exponent. - /// - /// The complex number raised to the given exponent. - /// - public static Complex Pow(Complex value, double power) - { - return value.Power(power); - } - - /// - /// Returns the multiplicative inverse of a complex number. - /// - /// A complex number. - /// The reciprocal of value. - /// If value is , the method returns . Otherwise, it returns the result of the expression / value. - public static Complex Reciprocal(Complex value) - { - if (value.IsZero) - { - return _zero; - } - - return 1.0 / value; - } - - /// - /// The Square Root (power 1/2) of a Complex number. - /// - /// A complex number. - /// - /// The square root of a complex number. - /// - public static Complex Sqrt(Complex value) - { - return value.SquareRoot(); - } - - #endregion - } -} \ No newline at end of file diff --git a/src/Numerics/Complex32.cs b/src/Numerics/Complex32.cs index 076cc641..913a05d4 100644 --- a/src/Numerics/Complex32.cs +++ b/src/Numerics/Complex32.cs @@ -2,7 +2,7 @@ // Math.NET Numerics, part of the Math.NET Project // http://mathnet.opensourcedotnet.info // -// Copyright (c) 2009 Math.NET +// Copyright (c) 2009-2010 Math.NET // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation @@ -30,6 +30,8 @@ namespace MathNet.Numerics { using System; using System.Collections.Generic; + using System.Numerics; + using System.Runtime; using System.Runtime.InteropServices; using System.Text; using Properties; @@ -124,6 +126,9 @@ namespace MathNet.Numerics /// /// The value for the imaginary component. /// +#if !SILVERLIGHT + [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] +#endif public Complex32(float real, float imaginary) { _real = real; @@ -195,6 +200,10 @@ namespace MathNet.Numerics /// The real component of the complex number. public float Real { +#if !SILVERLIGHT + [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] +#endif + get { return _real; } } @@ -204,6 +213,10 @@ namespace MathNet.Numerics /// The real imaginary component of the complex number. public float Imaginary { +#if !SILVERLIGHT + [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] +#endif + get { return _imag; } } @@ -211,27 +224,27 @@ namespace MathNet.Numerics /// Gets a value indicating whether the Complex32 is zero. /// /// true if this instance is zero; otherwise, false. - public bool IsZero + public bool IsZero() { - get { return _real == 0.0f && _imag == 0.0f; } + return _real == 0.0f && _imag == 0.0f; } /// /// Gets a value indicating whether the Complex32 is one. /// /// true if this instance is one; otherwise, false. - public bool IsOne + public bool IsOne() { - get { return _real == 1.0f && _imag == 0.0f; } + return _real == 1.0f && _imag == 0.0f; } /// /// Gets a value indicating whether the Complex32 is the imaginary unit. /// /// true if this instance is ImaginaryOne; otherwise, false. - public bool IsImaginaryOne + public bool IsImaginaryOne() { - get { return _real == 0.0f && _imag == 1.0f; } + return _real == 0.0f && _imag == 1.0f; } /// @@ -242,9 +255,9 @@ namespace MathNet.Numerics /// true if this instance is ; otherwise, /// false. /// - public bool IsNaN + public bool IsNaN() { - get { return float.IsNaN(_real) || float.IsNaN(_imag); } + return float.IsNaN(_real) || float.IsNaN(_imag); } /// @@ -258,18 +271,18 @@ namespace MathNet.Numerics /// True if it either evaluates to a complex infinity /// or to a directed infinity. /// - public bool IsInfinity + public bool IsInfinity() { - get { return float.IsInfinity(_real) || float.IsInfinity(_imag); } + return float.IsInfinity(_real) || float.IsInfinity(_imag); } /// /// Gets a value indicating whether the provided Complex32 is real. /// /// true if this instance is a real number; otherwise, false. - public bool IsReal + public bool IsReal() { - get { return _imag == 0.0f; } + return _imag == 0.0f; } /// @@ -278,9 +291,9 @@ namespace MathNet.Numerics /// /// true if this instance is real nonnegative number; otherwise, false. /// - public bool IsRealNonNegative + public bool IsRealNonNegative() { - get { return _imag == 0.0f && _real >= 0; } + return _imag == 0.0f && _real >= 0; } /// @@ -298,9 +311,9 @@ namespace MathNet.Numerics /// a = b.Conjugate /// /// - public Complex32 Conjugate + public Complex32 Conjugate() { - get { return new Complex32(_real, -_imag); } + return new Complex32(_real, -_imag); } /// @@ -333,12 +346,12 @@ namespace MathNet.Numerics { get { - if (IsReal && _real < 0) + if (IsReal() && _real < 0) { return (float)Math.PI; } - return IsRealNonNegative ? 0.0f : (float)Math.Atan2(_imag, _real); + return IsRealNonNegative() ? 0.0f : (float)Math.Atan2(_imag, _real); } } @@ -391,7 +404,7 @@ namespace MathNet.Numerics public Complex32 Exponential() { var exp = (float)Math.Exp(_real); - if (IsReal) + if (IsReal()) { return new Complex32(exp, 0.0f); } @@ -407,7 +420,7 @@ namespace MathNet.Numerics /// public Complex32 NaturalLogarithm() { - if (IsRealNonNegative) + if (IsRealNonNegative()) { return new Complex32((float)Math.Log(_real), 0.0f); } @@ -426,9 +439,9 @@ namespace MathNet.Numerics /// public Complex32 Power(Complex32 exponent) { - if (IsZero) + if (IsZero()) { - if (exponent.IsZero) + if (exponent.IsZero()) { return One; } @@ -476,7 +489,7 @@ namespace MathNet.Numerics /// public Complex32 Square() { - if (IsReal) + if (IsReal()) { return new Complex32(_real * _real, 0.0f); } @@ -492,7 +505,7 @@ namespace MathNet.Numerics /// public Complex32 SquareRoot() { - if (IsRealNonNegative) + if (IsRealNonNegative()) { return new Complex32((float)Math.Sqrt(_real), 0.0f); } @@ -642,12 +655,12 @@ namespace MathNet.Numerics { var numberFormatInfo = formatProvider.GetNumberFormatInfo(); - if (IsNaN) + if (IsNaN()) { return numberFormatInfo.NaNSymbol; } - if (IsInfinity) + if (IsInfinity()) { return numberFormatInfo.PositiveInfinitySymbol; } @@ -701,12 +714,12 @@ namespace MathNet.Numerics /// public bool Equals(Complex32 other) { - if (IsNaN || other.IsNaN) + if (IsNaN() || other.IsNaN()) { return false; } - if (IsInfinity && other.IsInfinity) + if (IsInfinity() && other.IsInfinity()) { return true; } @@ -880,7 +893,7 @@ namespace MathNet.Numerics /// The divisor. public static Complex32 operator /(Complex32 dividend, Complex32 divisor) { - if (divisor.IsZero) + if (divisor.IsZero()) { return Infinity; } @@ -897,7 +910,7 @@ namespace MathNet.Numerics /// The divisor. public static Complex32 operator /(float dividend, Complex32 divisor) { - if (divisor.IsZero) + if (divisor.IsZero()) { return Infinity; } @@ -926,6 +939,10 @@ namespace MathNet.Numerics /// /// Returns the same complex number. /// +#if !SILVERLIGHT + [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] +#endif + public Complex32 Plus() { return this; @@ -937,6 +954,10 @@ namespace MathNet.Numerics /// /// The negated value of this complex number. /// +#if !SILVERLIGHT + [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] +#endif + public Complex32 Negate() { return -this; @@ -951,6 +972,10 @@ namespace MathNet.Numerics /// /// The other complex number to add. /// +#if !SILVERLIGHT + [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] +#endif + public Complex32 Add(Complex32 other) { return this + other; @@ -965,6 +990,10 @@ namespace MathNet.Numerics /// /// The other complex number to subtract from this one. /// +#if !SILVERLIGHT + [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] +#endif + public Complex32 Subtract(Complex32 other) { return this - other; @@ -979,6 +1008,10 @@ namespace MathNet.Numerics /// /// The complex number to multiply. /// +#if !SILVERLIGHT + [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] +#endif + public Complex32 Multiply(Complex32 multiplier) { return this * multiplier; @@ -993,6 +1026,10 @@ namespace MathNet.Numerics /// /// The divisor. /// +#if !SILVERLIGHT + [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] +#endif + public Complex32 Divide(Complex32 divisor) { return this / divisor; @@ -1324,6 +1361,28 @@ namespace MathNet.Numerics return new Complex32(value, 0.0f); } + /// + /// Implicit conversion of a signed byte to a Complex32. + /// + /// The signed byte value to convert. + /// The result of the conversion. + [CLSCompliant(false)] + public static implicit operator Complex32(sbyte value) + { + return new Complex32(value, 0.0f); + } + + /// + /// Implicit conversion of a unsgined real short to a Complex32. + /// + /// The unsgined short value to convert. + /// The result of the conversion. + [CLSCompliant(false)] + public static implicit operator Complex32(ushort value) + { + return new Complex32(value, 0.0f); + } + /// /// Implicit conversion of a real int to a Complex32. /// @@ -1334,6 +1393,16 @@ namespace MathNet.Numerics return new Complex32(value, 0.0f); } + /// + /// Implicit conversion of a BigInteger int to a Complex32. + /// + /// The BigInteger value to convert. + /// The result of the conversion. + public static implicit operator Complex32(BigInteger value) + { + return new Complex32((long)value, 0.0f); + } + /// /// Implicit conversion of a real long to a Complex32. /// @@ -1349,6 +1418,7 @@ namespace MathNet.Numerics /// /// The uint value to convert. /// The result of the conversion. + [CLSCompliant(false)] public static implicit operator Complex32(uint value) { return new Complex32(value, 0.0f); @@ -1359,6 +1429,7 @@ namespace MathNet.Numerics /// /// The ulong value to convert. /// The result of the conversion. + [CLSCompliant(false)] public static implicit operator Complex32(ulong value) { return new Complex32(value, 0.0f); @@ -1384,6 +1455,251 @@ namespace MathNet.Numerics return new Complex32((float)value, 0.0f); } + public Complex ToComplex() + { + return new Complex(this._real, this._imag); + } + #endregion + + /// + /// Gets the absolute value (or magnitude) of a complex number. + /// + /// A complex number. + /// The absolute value (or magnitude) of a complex number. + public static double Abs(Complex32 value) + { + return value.Magnitude; + } + + /// + /// Trigonometric Arc Cosine of a Complex number. + /// + /// A complex number. + /// + /// The arc cosine of a complex number. + /// + public static Complex32 Acos(Complex32 value) + { + return (Complex32)value.ToComplex().InverseCosine(); + } + + /// + /// Trigonometric Arc Sine of a Complex number. + /// + /// A complex number. + /// + /// The arc sine of a complex number. + /// + public static Complex32 Asin(Complex32 value) + { + return (Complex32)value.ToComplex().InverseSine(); + } + + /// + /// Trigonometric Arc Tangent of a Complex number. + /// + /// A complex number. + /// + /// The arc tangent of a complex number. + /// + public static Complex32 Atan(Complex32 value) + { + return (Complex32)value.ToComplex().InverseTangent(); + } + + /// + /// Trigonometric Cosine of a Complex number. + /// + /// A complex number. + /// + /// The cosine of a complex number. + /// + public static Complex32 Cos(Complex32 value) + { + return (Complex32)value.ToComplex().Cosine(); + } + + /// + /// Trigonometric Sine of a Complex number. + /// + /// A complex number. + /// + /// The Sine of a complex number. + /// + public static Complex32 Sin(Complex32 value) + { + return (Complex32)value.ToComplex().Sine(); + } + + /// + /// Trigonometric Tangent of a Complex number. + /// + /// A complex number. + /// + /// The tangent of a complex number. + /// + public static Complex32 Tan(Complex32 value) + { + return (Complex32)value.ToComplex().Tangent(); + } + + /// + /// Trigonometric Hyperbolic Cosine of a Complex number. + /// + /// A complex number. + /// + /// The hyperbolic cosine of a complex number. + /// + public static Complex32 Cosh(Complex32 value) + { + return (Complex32)value.ToComplex().HyperbolicCosine(); + } + + /// + /// Trigonometric Hyperbolic Sine of a Complex number. + /// + /// A complex number. + /// + /// The hyperbolic sine of a complex number. + /// + public static Complex32 Sinh(Complex32 value) + { + return (Complex32)value.ToComplex().HyperbolicSine(); + } + + /// + /// Trigonometric Hyperbolic Tangent of a Complex number. + /// + /// A complex number. + /// + /// The hyperbolic tangent of a complex number. + /// + public static Complex32 Tanh(Complex32 value) + { + return (Complex32)value.ToComplex().HyperbolicTangent(); + } + + /// + /// Exponential of a Complex number (exp(x), E^x). + /// + /// A complex number. + /// + /// The exponential of a complex number. + /// + public static Complex32 Exp(Complex32 value) + { + return (Complex32)value.ToComplex().Exponential(); + } + + /// + /// Constructs a Complex from its magnitude and phase. + /// + /// + /// Must be non-negative. + /// + /// + /// Real number. + /// + /// + /// A new Complex from the given values. + /// + /// + public static Complex32 FromPolarCoordinates(float magnitude, float phase) + { + return WithModulusArgument(magnitude, phase); + } + + /// + /// Natural Logarithm of a Complex number (exp(x), E^x). + /// + /// A complex number. + /// + /// The natural logarithm of a complex number. + /// + public static Complex32 Log(Complex32 value) + { + return (Complex32)value.ToComplex().NaturalLogarithm(); + } + + /// + /// Returns the logarithm of a specified complex number in a specified base + /// + /// A complex number. + /// The base of the logarithm. + /// The logarithm of value in base baseValue. + public static Complex32 Log(Complex32 value, float baseValue) + { + if (baseValue == 1.0) + { + return float.NaN; + } + + return (Complex32)(value.ToComplex().NaturalLogarithm() / Math.Log(baseValue, Math.E)); + } + + /// + /// Returns the base-10 logarithm of a specified complex number in a specified base + /// + /// A complex number. + /// The base-10 logarithm of the complex number. + public static Complex32 Log10(Complex32 value) + { + return Log(value, 10); + } + + /// + /// Raise this a Complexnumber to the given value. + /// + /// A complex number. + /// The exponent. + /// + /// The complex number raised to the given exponent. + /// + public static Complex32 Pow(Complex32 value, Complex32 power) + { + return value.Power(power); + } + + /// + /// Raise this a Complexnumber to the given value. + /// + /// A complex number. + /// The exponent. + /// + /// The complex number raised to the given exponent. + /// + public static Complex32 Pow(Complex32 value, float power) + { + return value.Power(power); + } + + /// + /// Returns the multiplicative inverse of a complex number. + /// + /// A complex number. + /// The reciprocal of value. + /// If value is , the method returns . Otherwise, it returns the result of the expression / value. + public static Complex32 Reciprocal(Complex32 value) + { + if (value.IsZero()) + { + return _zero; + } + + return 1.0f / value; + } + + /// + /// The Square Root (power 1/2) of a Complex number. + /// + /// A complex number. + /// + /// The square root of a complex number. + /// + public static Complex32 Sqrt(Complex32 value) + { + return value.SquareRoot(); + } } } \ No newline at end of file diff --git a/src/Numerics/ComplexExtensions.cs b/src/Numerics/ComplexExtensions.cs new file mode 100644 index 00000000..16d5aff5 --- /dev/null +++ b/src/Numerics/ComplexExtensions.cs @@ -0,0 +1,580 @@ +// +// Math.NET Numerics, part of the Math.NET Project +// http://mathnet.opensourcedotnet.info +// +// Copyright (c) 2009-2010 Math.NET +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +namespace MathNet.Numerics +{ + using System; + using System.Collections.Generic; + using System.Numerics; + + /// + /// Extension methods + /// + public static class ComplexExtensions + { + /// + /// Gets a value indicating whether the Complex32 is zero. + /// + /// true if this instance is zero; otherwise, false. + public static bool IsZero(this Complex complex) + { + return complex.Real == 0.0 && complex.Imaginary == 0.0; + } + + /// + /// Gets a value indicating whether the Complex32 is one. + /// + /// true if this instance is one; otherwise, false. + public static bool IsOne(this Complex complex) + { + return complex.Real == 1.0 && complex.Imaginary == 0.0; + } + + /// + /// Gets a value indicating whether the Complex32 is the imaginary unit. + /// + /// true if this instance is ImaginaryOne; otherwise, false. + public static bool IsImaginaryOne(this Complex complex) + { + return complex.Real == 0.0 && complex.Imaginary == 1.0; + } + + /// + /// Gets a value indicating whether the provided Complex32evaluates + /// to a value that is not a number. + /// + /// + /// true if this instance is ; otherwise, + /// false. + /// + public static bool IsNaN(this Complex complex) + { + return double.IsNaN(complex.Real) || double.IsNaN(complex.Imaginary); + } + + /// + /// Gets a value indicating whether the provided Complex32 evaluates to an + /// infinite value. + /// + /// + /// true if this instance is infinite; otherwise, false. + /// + /// + /// True if it either evaluates to a complex infinity + /// or to a directed infinity. + /// + public static bool IsInfinity(this Complex complex) + { + return double.IsInfinity(complex.Real) || double.IsInfinity(complex.Imaginary); + } + + /// + /// Gets a value indicating whether the provided Complex32 is real. + /// + /// true if this instance is a real number; otherwise, false. + public static bool IsReal(this Complex complex) + { + return complex.Imaginary == 0.0; + } + + /// + /// Gets a value indicating whether the provided Complex32 is real and not negative, that is >= 0. + /// + /// + /// true if this instance is real nonnegative number; otherwise, false. + /// + public static bool IsRealNonNegative(this Complex complex) + { + return complex.Imaginary == 0.0f && complex.Real >= 0; + } + + /// + /// Gets the conjugate of this Complex32. + /// + /// + /// The semantic of setting the conjugate is such that + /// + /// // a, b of type Complex32 + /// a.Conjugate = b; + /// + /// is equivalent to + /// + /// // a, b of type Complex32 + /// a = b.Conjugate + /// + /// + public static Complex Conjugate(this Complex complex) + { + return new Complex(complex.Real, -complex.Imaginary); + } + + /// + /// Gets the squared magnitude of this Complex. + /// + public static double MagnitudeSquared(this Complex complex) + { + return (complex.Real * complex.Real) + (complex.Imaginary * complex.Imaginary); + } + + /// + /// Exponential of this Complex (exp(x), E^x). + /// + /// + /// The exponential of this complex number. + /// + public static Complex Exponential(this Complex complex) + { + var exp = Math.Exp(complex.Real); + if (complex.IsReal()) + { + return new Complex(exp, 0.0); + } + + return new Complex(exp * Trig.Cosine(complex.Imaginary), exp * Trig.Sine(complex.Imaginary)); + } + + /// + /// Natural Logarithm of this Complex (Base E). + /// + /// + /// The natural logarithm of this complex number. + /// + public static Complex NaturalLogarithm(this Complex complex) + { + if (complex.IsRealNonNegative()) + { + return new Complex(Math.Log(complex.Real), 0.0); + } + + return new Complex(0.5 * Math.Log(complex.MagnitudeSquared()), complex.Phase); + } + + /// + /// Raise this Complex to the given value. + /// + /// + /// The exponent. + /// + /// + /// The complex number raised to the given exponent. + /// + public static Complex Power(this Complex complex, Complex exponent) + { + if (complex.IsZero()) + { + if (exponent.IsZero()) + { + return Complex.One; + } + + if (exponent.Real > 0.0) + { + return Complex.Zero; + } + + if (exponent.Real < 0) + { + if (exponent.Imaginary == 0.0) + { + return new Complex(double.PositiveInfinity, 0.0); + } + + return new Complex(double.PositiveInfinity, double.PositiveInfinity); + } + + return double.NaN; + } + + return (exponent * complex.NaturalLogarithm()).Exponential(); + } + + /// + /// Raise this Complex to the inverse of the given value. + /// + /// + /// The root exponent. + /// + /// + /// The complex raised to the inverse of the given exponent. + /// + public static Complex Root(this Complex complex, Complex rootExponent) + { + return Power(complex, 1 / rootExponent); + } + + /// + /// The Square (power 2) of this Complex + /// + /// + /// The square of this complex number. + /// + public static Complex Square(this Complex complex) + { + if (complex.IsReal()) + { + return new Complex(complex.Real * complex.Real, 0.0); + } + + return new Complex((complex.Real * complex.Real) - (complex.Imaginary * complex.Imaginary), 2 * complex.Real * complex.Imaginary); + } + + /// + /// The Square Root (power 1/2) of this Complex + /// + /// + /// The square root of this complex number. + /// + public static Complex SquareRoot(this Complex complex) + { + if (complex.IsRealNonNegative()) + { + return new Complex(Math.Sqrt(complex.Real), 0.0); + } + + Complex result; + + var absReal = Math.Abs(complex.Real); + var absImag = Math.Abs(complex.Imaginary); + double w; + if (absReal >= absImag) + { + var ratio = complex.Imaginary / complex.Real; + w = Math.Sqrt(absReal) * Math.Sqrt(0.5 * (1.0 + Math.Sqrt(1.0 + (ratio * ratio)))); + } + else + { + var ratio = complex.Real / complex.Imaginary; + w = Math.Sqrt(absImag) * Math.Sqrt(0.5 * (Math.Abs(ratio) + Math.Sqrt(1.0 + (ratio * ratio)))); + } + + if (complex.Real >= 0.0) + { + result = new Complex(w, complex.Imaginary / (2.0 * w)); + } + else if (complex.Imaginary >= 0.0) + { + result = new Complex(absImag / (2.0 * w), w); + } + else + { + result = new Complex(absImag / (2.0 * w), -w); + } + + return result; + } + + /// + /// Returns a Norm of a value of this type, which is appropriate for measuring how + /// close this value is to zero. + /// + /// A norm of this value. + public static double Norm(this Complex complex) + { + return complex.MagnitudeSquared(); + } + + /// + /// Returns a Norm of the difference of two values of this type, which is + /// appropriate for measuring how close together these two values are. + /// + /// The value to compare with. + /// A norm of the difference between this and the other value. + public static double NormOfDifference(this Complex complex, Complex otherValue) + { + return (complex- otherValue).MagnitudeSquared(); + } + + /// + /// Creates a complex number based on a string. The string can be in the + /// following formats (without the quotes): 'n', 'ni', 'n +/- ni', + /// 'ni +/- n', 'n,n', 'n,ni,' '(n,n)', or '(n,ni)', where n is a double. + /// + /// + /// A complex number containing the value specified by the given string. + /// + /// + /// The string to parse. + /// + public static Complex ToComplex(this string value) + { + return value.ToComplex(null); + } + + /// + /// Creates a complex number based on a string. The string can be in the + /// following formats (without the quotes): 'n', 'ni', 'n +/- ni', + /// 'ni +/- n', 'n,n', 'n,ni,' '(n,n)', or '(n,ni)', where n is a double. + /// + /// + /// A complex number containing the value specified by the given string. + /// + /// + /// the string to parse. + /// + /// + /// An that supplies culture-specific + /// formatting information. + /// + public static Complex ToComplex(this string value, IFormatProvider formatProvider) + { + if (value == null) + { + throw new ArgumentNullException(value); + } + + value = value.Trim(); + if (value.Length == 0) + { + throw new FormatException(); + } + + // strip out parens + if (value.StartsWith("(", StringComparison.Ordinal)) + { + if (!value.EndsWith(")", StringComparison.Ordinal)) + { + throw new FormatException(); + } + + value = value.Substring(1, value.Length - 2).Trim(); + } + + // keywords + var numberFormatInfo = formatProvider.GetNumberFormatInfo(); + var textInfo = formatProvider.GetTextInfo(); + var keywords = + new[] + { + textInfo.ListSeparator, numberFormatInfo.NaNSymbol, + numberFormatInfo.NegativeInfinitySymbol, numberFormatInfo.PositiveInfinitySymbol, + "+", "-", "i", "j" + }; + + // lexing + var tokens = new LinkedList(); + GlobalizationHelper.Tokenize(tokens.AddFirst(value), keywords, 0); + var token = tokens.First; + + // parse the left part + bool isLeftPartImaginary; + double leftPart = ParsePart(ref token, out isLeftPartImaginary, formatProvider); + if (token == null) + { + return isLeftPartImaginary ? new Complex(0, leftPart) : new Complex(leftPart, 0); + } + + // parse the right part + if (token.Value == textInfo.ListSeparator) + { + // format: real,imag + token = token.Next; + + if (isLeftPartImaginary) + { + // left must not contain 'i', right doesn't matter. + throw new FormatException(); + } + + bool isRightPartImaginary; + double rightPart = ParsePart(ref token, out isRightPartImaginary, formatProvider); + + return new Complex(leftPart, rightPart); + } + else + { + // format: real + imag + bool isRightPartImaginary; + double rightPart = ParsePart(ref token, out isRightPartImaginary, formatProvider); + + if (!(isLeftPartImaginary ^ isRightPartImaginary)) + { + // either left or right part must contain 'i', but not both. + throw new FormatException(); + } + + return isLeftPartImaginary ? new Complex(rightPart, leftPart) : new Complex(leftPart, rightPart); + } + } + + /// + /// Parse a part (real or complex) from a complex number. + /// + /// Start Token. + /// Is set to true if the part identified itself as being imaginary. + /// + /// An that supplies culture-specific + /// formatting information. + /// + /// Resulting part as double. + /// + private static double ParsePart(ref LinkedListNode token, out bool imaginary, IFormatProvider format) + { + imaginary = false; + if (token == null) + { + throw new FormatException(); + } + + // handle prefix modifiers + if (token.Value == "+") + { + token = token.Next; + + if (token == null) + { + throw new FormatException(); + } + } + + bool negative = false; + if (token.Value == "-") + { + negative = true; + token = token.Next; + + if (token == null) + { + throw new FormatException(); + } + } + + // handle prefix imaginary symbol + if (String.Compare(token.Value, "i", StringComparison.OrdinalIgnoreCase) == 0 + || String.Compare(token.Value, "j", StringComparison.OrdinalIgnoreCase) == 0) + { + imaginary = true; + token = token.Next; + + if (token == null) + { + return negative ? -1 : 1; + } + } + +#if SILVERLIGHT + var value = GlobalizationHelper.ParseDouble(ref token); +#else + var value = GlobalizationHelper.ParseDouble(ref token, format.GetCultureInfo()); +#endif + + // handle suffix imaginary symbol + if (token != null && (String.Compare(token.Value, "i", StringComparison.OrdinalIgnoreCase) == 0 + || String.Compare(token.Value, "j", StringComparison.OrdinalIgnoreCase) == 0)) + { + if (imaginary) + { + // only one time allowed: either prefix or suffix, or neither. + throw new FormatException(); + } + + imaginary = true; + token = token.Next; + } + + return negative ? -value : value; + } + + /// + /// Converts the string representation of a complex number to a double-precision complex number equivalent. + /// A return value indicates whether the conversion succeeded or failed. + /// + /// + /// A string containing a complex number to convert. + /// + /// + /// The parsed value. + /// + /// + /// If the conversion succeeds, the result will contain a complex number equivalent to value. + /// Otherwise the result will contain complex32.Zero. This parameter is passed uninitialized + /// + public static bool TryToComplex(this string value, out Complex result) + { + return value.TryToComplex(null, out result); + } + + /// + /// Converts the string representation of a complex number to double-precision complex number equivalent. + /// A return value indicates whether the conversion succeeded or failed. + /// + /// + /// A string containing a complex number to convert. + /// + /// + /// An that supplies culture-specific formatting information about value. + /// + /// + /// The parsed value. + /// + /// + /// If the conversion succeeds, the result will contain a complex number equivalent to value. + /// Otherwise the result will contain complex32.Zero. This parameter is passed uninitialized + /// + public static bool TryToComplex(this string value, IFormatProvider formatProvider, out Complex result) + { + bool ret; + try + { + result = value.ToComplex(formatProvider); + ret = true; + } + catch (ArgumentNullException) + { + result = Complex.Zero; + ret = false; + } + catch (FormatException) + { + result = Complex.Zero; + ret = false; + } + + return ret; + } + + public static Complex32 ToComplex32(this string value) + { + return Complex32.Parse(value); + } + + public static Complex32 ToComplex32(this string value, IFormatProvider formatProvider) + { + return Complex32.Parse(value, formatProvider); + } + + public static bool TryToComplex32(this string value, out Complex32 result) + { + return Complex32.TryParse(value, out result); + } + + public static bool TryToComplex32(this string value, IFormatProvider formatProvider, out Complex32 result) + { + return Complex32.TryParse(value, formatProvider, out result); + } + } +} diff --git a/src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.Bluestein.cs b/src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.Bluestein.cs index 1b790523..cb70a23d 100644 --- a/src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.Bluestein.cs +++ b/src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.Bluestein.cs @@ -29,6 +29,7 @@ namespace MathNet.Numerics.IntegralTransforms.Algorithms { using System; + using System.Numerics; using NumberTheory; using Threading; @@ -91,7 +92,7 @@ namespace MathNet.Numerics.IntegralTransforms.Algorithms // Build and transform padded sequence a_k = x_k * exp(-I*Pi*k^2/N) for (int i = 0; i < samples.Length; i++) { - a[i] = sequence[i].Conjugate * samples[i]; + a[i] = sequence[i].Conjugate() * samples[i]; } Radix2(a, -1); @@ -107,7 +108,7 @@ namespace MathNet.Numerics.IntegralTransforms.Algorithms var nbinv = 1.0 / m; for (int i = 0; i < samples.Length; i++) { - samples[i] = nbinv * sequence[i].Conjugate * a[i]; + samples[i] = nbinv * sequence[i].Conjugate() * a[i]; } } diff --git a/src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.Naive.cs b/src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.Naive.cs index e1f40521..1803aa37 100644 --- a/src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.Naive.cs +++ b/src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.Naive.cs @@ -29,6 +29,7 @@ namespace MathNet.Numerics.IntegralTransforms.Algorithms { using System; + using System.Numerics; using Threading; /// diff --git a/src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.Options.cs b/src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.Options.cs index bff00a96..ba7e9483 100644 --- a/src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.Options.cs +++ b/src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.Options.cs @@ -29,6 +29,7 @@ namespace MathNet.Numerics.IntegralTransforms.Algorithms { using System; + using System.Numerics; /// /// Complex Fast (FFT) Implementation of the Discrete Fourier Transform (DFT). diff --git a/src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.RadixN.cs b/src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.RadixN.cs index b738d175..046bb40d 100644 --- a/src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.RadixN.cs +++ b/src/Numerics/IntegralTransforms/Algorithms/DiscreteFourierTransform.RadixN.cs @@ -29,6 +29,7 @@ namespace MathNet.Numerics.IntegralTransforms.Algorithms { using System; + using System.Numerics; using NumberTheory; using Properties; using Threading; diff --git a/src/Numerics/IntegralTransforms/Transform.cs b/src/Numerics/IntegralTransforms/Transform.cs index 2248f2f1..a3ac4d77 100644 --- a/src/Numerics/IntegralTransforms/Transform.cs +++ b/src/Numerics/IntegralTransforms/Transform.cs @@ -28,6 +28,7 @@ namespace MathNet.Numerics.IntegralTransforms { + using System.Numerics; using Algorithms; /// diff --git a/src/Numerics/Numerics.csproj b/src/Numerics/Numerics.csproj index 778f840b..1bac2a3e 100644 --- a/src/Numerics/Numerics.csproj +++ b/src/Numerics/Numerics.csproj @@ -63,6 +63,7 @@ 3.5 + @@ -91,7 +92,7 @@ SafeNativeMethods.tt - + diff --git a/src/Numerics/Precision.cs b/src/Numerics/Precision.cs index d0761a2e..f2384772 100644 --- a/src/Numerics/Precision.cs +++ b/src/Numerics/Precision.cs @@ -30,6 +30,7 @@ namespace MathNet.Numerics { using System; using System.Collections.Generic; + using System.Numerics; /// /// Utilities for working with floating point numbers. @@ -767,6 +768,23 @@ namespace MathNet.Numerics return AlmostEqualWithError(a.Norm(), b.Norm(), diff, _defaultDoubleRelativeAccuracy); } + /// + /// Compares two doubles and determines if they are equal within + /// the specified maximum error. + /// + /// The first value. + /// The second value. + /// The accuracy required for being almost equal. + /// + /// if both doubles are almost equal up to the + /// specified maximum error, otherwise. + /// + public static bool AlmostEqualWithError(this Complex a, Complex b, double maximumError) + { + double diff = a.NormOfDifference(b); + return AlmostEqualWithError(a.Norm(), b.Norm(), diff, maximumError); + } + /// /// Compares two doubles and determines if they are equal within /// the specified maximum error. @@ -819,6 +837,42 @@ namespace MathNet.Numerics return true; } + /// + /// Compares two lists of doubles and determines if they are equal within the + /// specified maximum error. + /// + /// The first value list. + /// The second value list. + /// + /// The accuracy required for being almost equal. + /// + /// + /// if both doubles are almost equal up to the specified + /// maximum error, otherwise. + /// + public static bool AlmostEqualListWithError(this IList a, IList b, double maximumError) + { + if (a == null && b == null) + { + return true; + } + + if (a == null || b == null || a.Count != b.Count) + { + return false; + } + + for (int i = 0; i < a.Count; i++) + { + if (!AlmostEqualWithError(a[i].Norm(), b[i].Norm(), a[i].NormOfDifference(b[i]), maximumError)) + { + return false; + } + } + + return true; + } + /// /// Compares two structure with precision support and determines if they are equal /// within the specified maximum relative error. diff --git a/src/Numerics/Trigonometry.cs b/src/Numerics/Trigonometry.cs index 1f80b090..becea22e 100644 --- a/src/Numerics/Trigonometry.cs +++ b/src/Numerics/Trigonometry.cs @@ -25,6 +25,7 @@ namespace MathNet.Numerics { using System; + using System.Numerics; /// /// Double-precision trigonometry toolkit. @@ -61,7 +62,7 @@ namespace MathNet.Numerics /// public static Complex Cosecant(this Complex value) { - if (value.IsReal) + if (value.IsReal()) { return new Complex(Cosecant(value.Real), 0d); } @@ -98,7 +99,7 @@ namespace MathNet.Numerics /// public static Complex Cosine(this Complex value) { - if (value.IsReal) + if (value.IsReal()) { return new Complex(Cosine(value.Real), 0.0); } @@ -133,7 +134,7 @@ namespace MathNet.Numerics /// public static Complex Cotangent(this Complex value) { - if (value.IsReal) + if (value.IsReal()) { return new Complex(Cotangent(value.Real), 0d); } @@ -226,14 +227,14 @@ namespace MathNet.Numerics /// public static Complex HyperbolicCosecant(this Complex value) { - if (value.IsReal) + if (value.IsReal()) { return new Complex(HyperbolicCosecant(value.Real), 0.0); } var exp = value.Exponential(); - if (exp.IsInfinity) + if (exp.IsInfinity()) { return Complex.Zero; } @@ -266,7 +267,7 @@ namespace MathNet.Numerics /// public static Complex HyperbolicCosine(this Complex value) { - if (value.IsReal) + if (value.IsReal()) { return new Complex(HyperbolicCosine(value.Real), 0.0); } @@ -313,7 +314,7 @@ namespace MathNet.Numerics /// public static Complex HyperbolicCotangent(this Complex value) { - if (value.IsReal) + if (value.IsReal()) { return new Complex(HyperbolicCotangent(value.Real), 0.0); } @@ -356,14 +357,14 @@ namespace MathNet.Numerics /// public static Complex HyperbolicSecant(this Complex value) { - if (value.IsReal) + if (value.IsReal()) { return new Complex(HyperbolicSecant(value.Real), 0.0); } var exp = value.Exponential(); - if (exp.IsInfinity) + if (exp.IsInfinity()) { return Complex.Zero; } @@ -396,7 +397,7 @@ namespace MathNet.Numerics /// public static Complex HyperbolicSine(this Complex value) { - if (value.IsReal) + if (value.IsReal()) { return new Complex(HyperbolicSine(value.Real), 0.0); } @@ -443,7 +444,7 @@ namespace MathNet.Numerics /// public static Complex HyperbolicTangent(this Complex value) { - if (value.IsReal) + if (value.IsReal()) { return new Complex(HyperbolicTangent(value.Real), 0.0); } @@ -549,7 +550,7 @@ namespace MathNet.Numerics /// public static Complex InverseCotangent(this Complex value) { - if (value.IsZero) + if (value.IsZero()) { return Math.PI / 2.0; } @@ -868,7 +869,7 @@ namespace MathNet.Numerics /// public static Complex Secant(this Complex value) { - if (value.IsReal) + if (value.IsReal()) { return new Complex(Secant(value.Real), 0d); } @@ -905,7 +906,7 @@ namespace MathNet.Numerics /// public static Complex Sine(this Complex value) { - if (value.IsReal) + if (value.IsReal()) { return new Complex(Sine(value.Real), 0.0); } @@ -940,7 +941,7 @@ namespace MathNet.Numerics /// public static Complex Tangent(this Complex value) { - if (value.IsReal) + if (value.IsReal()) { return new Complex(Tangent(value.Real), 0.0); } diff --git a/src/Silverlight/Silverlight.csproj b/src/Silverlight/Silverlight.csproj index 3aa1ca34..eacf7d5a 100644 --- a/src/Silverlight/Silverlight.csproj +++ b/src/Silverlight/Silverlight.csproj @@ -14,7 +14,7 @@ Properties MathNet.Numerics MathNet.Numerics.Silverlight - v3.0 + v4.0 false true true @@ -41,6 +41,7 @@ false false true + true @@ -66,6 +67,7 @@ AllRules.ruleset + @@ -87,12 +89,12 @@ Combinatorics.cs - - Complex.cs - Complex32.cs + + ComplexExtensions.cs + Constants.cs diff --git a/src/UnitTests/AssertHelpers.cs b/src/UnitTests/AssertHelpers.cs index 4088d5eb..12b9d3db 100644 --- a/src/UnitTests/AssertHelpers.cs +++ b/src/UnitTests/AssertHelpers.cs @@ -30,6 +30,7 @@ namespace MathNet.Numerics.UnitTests { using System.Collections.Generic; + using System.Numerics; using MbUnit.Framework; /// @@ -158,5 +159,23 @@ namespace MathNet.Numerics.UnitTests } } } + + /// + /// Asserts that the expected value and the actual value are equal up to a certain + /// maximum error. + /// + /// The expected value list. + /// The actual value list. + /// The accuracy required for being almost equal. + public static void AlmostEqualList(IList expected, IList actual, double maximumError) + { + for (int i = 0; i < expected.Count; i++) + { + if (!actual[i].AlmostEqualWithError(expected[i], maximumError)) + { + Assert.Fail("Not equal within a maximum error {0}. Expected:{1}; Actual:{2}", maximumError, expected[i], actual[i]); + } + } + } } } diff --git a/src/UnitTests/ComplexTests/Complex32Test.cs b/src/UnitTests/ComplexTests/Complex32Test.cs index 2ad39642..bc113281 100644 --- a/src/UnitTests/ComplexTests/Complex32Test.cs +++ b/src/UnitTests/ComplexTests/Complex32Test.cs @@ -29,6 +29,7 @@ namespace MathNet.Numerics.UnitTests.ComplexTests { using System; + using System.Numerics; using MbUnit.Framework; [TestFixture] @@ -38,10 +39,10 @@ namespace MathNet.Numerics.UnitTests.ComplexTests [MultipleAsserts] public void CanAddComplexNumberAndDoubleUsingOperartor() { - AssertEx.That(() => (Complex32.NaN + float.NaN).IsNaN); - AssertEx.That(() => (float.NaN + Complex32.NaN).IsNaN); - AssertEx.That(() => (float.PositiveInfinity + Complex32.One).IsInfinity); - AssertEx.That(() => (Complex32.Infinity + 1.0f).IsInfinity); + AssertEx.That(() => (Complex32.NaN + float.NaN).IsNaN()); + AssertEx.That(() => (float.NaN + Complex32.NaN).IsNaN()); + AssertEx.That(() => (float.PositiveInfinity + Complex32.One).IsInfinity()); + AssertEx.That(() => (Complex32.Infinity + 1.0f).IsInfinity()); AssertEx.That(() => (Complex32.One + 0.0f) == Complex32.One); AssertEx.That(() => (0.0f + Complex32.One) == Complex32.One); AssertEx.That(() => (new Complex32(1.1f, -2.2f) + 1.1f == new Complex32(2.2f, -2.2f))); @@ -52,8 +53,8 @@ namespace MathNet.Numerics.UnitTests.ComplexTests [MultipleAsserts] public void CanAddSubtractComplexNumbersUsingOperartor() { - AssertEx.That(() => (Complex32.NaN - Complex32.NaN).IsNaN); - AssertEx.That(() => (Complex32.Infinity - Complex32.One).IsInfinity); + AssertEx.That(() => (Complex32.NaN - Complex32.NaN).IsNaN()); + AssertEx.That(() => (Complex32.Infinity - Complex32.One).IsInfinity()); AssertEx.That(() => (Complex32.One - Complex32.Zero) == Complex32.One); AssertEx.That(() => (new Complex32(1.1f, -2.2f) - new Complex32(1.1f, -2.2f)) == Complex32.Zero); } @@ -62,8 +63,8 @@ namespace MathNet.Numerics.UnitTests.ComplexTests [MultipleAsserts] public void CanAddTwoComplexNumbers() { - AssertEx.That(() => Complex32.NaN.Add(Complex32.NaN).IsNaN); - AssertEx.That(() => Complex32.Infinity.Add(Complex32.One).IsInfinity); + AssertEx.That(() => Complex32.NaN.Add(Complex32.NaN).IsNaN()); + AssertEx.That(() => Complex32.Infinity.Add(Complex32.One).IsInfinity()); AssertEx.That(() => Complex32.One.Add(Complex32.Zero) == Complex32.One); AssertEx.That(() => new Complex32(1.1f, -2.2f).Add(new Complex32(-1.1f, 2.2f)) == Complex32.Zero); } @@ -72,8 +73,8 @@ namespace MathNet.Numerics.UnitTests.ComplexTests [MultipleAsserts] public void CanAddTwoComplexNumbersUsingOperartor() { - AssertEx.That(() => (Complex32.NaN + Complex32.NaN).IsNaN); - AssertEx.That(() => (Complex32.Infinity + Complex32.One).IsInfinity); + AssertEx.That(() => (Complex32.NaN + Complex32.NaN).IsNaN()); + AssertEx.That(() => (Complex32.Infinity + Complex32.One).IsInfinity()); AssertEx.That(() => (Complex32.One + Complex32.Zero) == Complex32.One); AssertEx.That(() => (new Complex32(1.1f, -2.2f) + new Complex32(-1.1f, 2.2f)) == Complex32.Zero); } @@ -156,7 +157,7 @@ namespace MathNet.Numerics.UnitTests.ComplexTests AssertHelpers.AlmostEqual(new Complex32(float.PositiveInfinity, float.PositiveInfinity), a.Power(b), 7); a = new Complex32(0.0f, 0.0f); b = new Complex32(0.0f, 1.0f); - AssertEx.That(() => a.Power(b).IsNaN); + AssertEx.That(() => a.Power(b).IsNaN()); } [Test] @@ -230,8 +231,8 @@ namespace MathNet.Numerics.UnitTests.ComplexTests [MultipleAsserts] public void CanConvertDoubleToComplex() { - AssertEx.That(() => ((Complex32)float.NaN).IsNaN); - AssertEx.That(() => ((Complex32)float.NegativeInfinity).IsInfinity); + AssertEx.That(() => ((Complex32)float.NaN).IsNaN()); + AssertEx.That(() => ((Complex32)float.NegativeInfinity).IsInfinity()); Assert.AreEqual(1.1f, new Complex32(1.1f, 0)); } @@ -267,7 +268,7 @@ namespace MathNet.Numerics.UnitTests.ComplexTests public void CanDetermineIfImaginaryUnit() { var complex = new Complex32(0, 1); - Assert.IsTrue(complex.IsImaginaryOne, "Imaginary unit"); + Assert.IsTrue(complex.IsImaginaryOne(), "Imaginary unit"); } [Test] @@ -275,11 +276,11 @@ namespace MathNet.Numerics.UnitTests.ComplexTests public void CanDetermineIfInfinity() { var complex = new Complex32(float.PositiveInfinity, 1); - Assert.IsTrue(complex.IsInfinity, "Real part is infinity."); + Assert.IsTrue(complex.IsInfinity(), "Real part is infinity."); complex = new Complex32(1, float.NegativeInfinity); - Assert.IsTrue(complex.IsInfinity, "Imaginary part is infinity."); + Assert.IsTrue(complex.IsInfinity(), "Imaginary part is infinity."); complex = new Complex32(float.NegativeInfinity, float.PositiveInfinity); - Assert.IsTrue(complex.IsInfinity, "Both parts are infinity."); + Assert.IsTrue(complex.IsInfinity(), "Both parts are infinity."); } [Test] @@ -287,46 +288,46 @@ namespace MathNet.Numerics.UnitTests.ComplexTests public void CanDetermineIfNaN() { var complex = new Complex32(float.NaN, 1); - Assert.IsTrue(complex.IsNaN, "Real part is NaN."); + Assert.IsTrue(complex.IsNaN(), "Real part is NaN."); complex = new Complex32(1, float.NaN); - Assert.IsTrue(complex.IsNaN, "Imaginary part is NaN."); + Assert.IsTrue(complex.IsNaN(), "Imaginary part is NaN."); complex = new Complex32(float.NaN, float.NaN); - Assert.IsTrue(complex.IsNaN, "Both parts are NaN."); + Assert.IsTrue(complex.IsNaN(), "Both parts are NaN."); } [Test] public void CanDetermineIfOneValueComplexNumber() { var complex = new Complex32(1, 0); - Assert.IsTrue(complex.IsOne, "Complex32 number with a value of one."); + Assert.IsTrue(complex.IsOne(), "Complex32 number with a value of one."); } [Test] public void CanDetermineIfRealNonNegativeNumber() { var complex = new Complex32(1, 0); - Assert.IsTrue(complex.IsReal, "Is a real non-negative number."); + Assert.IsTrue(complex.IsReal(), "Is a real non-negative number."); } [Test] public void CanDetermineIfRealNumber() { var complex = new Complex32(-1, 0); - Assert.IsTrue(complex.IsReal, "Is a real number."); + Assert.IsTrue(complex.IsReal(), "Is a real number."); } [Test] public void CanDetermineIfZeroValueComplexNumber() { var complex = new Complex32(0, 0); - Assert.IsTrue(complex.IsZero, "Zero complex number."); + Assert.IsTrue(complex.IsZero(), "Zero complex number."); } [Test] [MultipleAsserts] public void CanDivideComplexNumberAndDoubleUsingOperators() { - AssertEx.That(() => (Complex32.NaN * 1.0f).IsNaN); + AssertEx.That(() => (Complex32.NaN * 1.0f).IsNaN()); Assert.AreEqual(new Complex32(-2, 2), new Complex32(4, -4) / -2); Assert.AreEqual(new Complex32(0.25f, 0.25f), 2 / new Complex32(4, -4)); Assert.AreEqual(Complex32.Infinity, 2.0f / Complex32.Zero); @@ -337,7 +338,7 @@ namespace MathNet.Numerics.UnitTests.ComplexTests [MultipleAsserts] public void CanDivideTwoComplexNumbers() { - AssertEx.That(() => Complex32.NaN.Multiply(Complex32.One).IsNaN); + AssertEx.That(() => Complex32.NaN.Multiply(Complex32.One).IsNaN()); Assert.AreEqual(new Complex32(-2, 0), new Complex32(4, -4).Divide(new Complex32(-2, 2))); Assert.AreEqual(Complex32.Infinity, Complex32.One.Divide(Complex32.Zero)); } @@ -346,7 +347,7 @@ namespace MathNet.Numerics.UnitTests.ComplexTests [MultipleAsserts] public void CanDivideTwoComplexNumbersUsingOperators() { - AssertEx.That(() => (Complex32.NaN / Complex32.One).IsNaN); + AssertEx.That(() => (Complex32.NaN / Complex32.One).IsNaN()); Assert.AreEqual(new Complex32(-2, 0), new Complex32(4, -4) / new Complex32(-2, 2)); Assert.AreEqual(Complex32.Infinity, Complex32.One / Complex32.Zero); } @@ -355,7 +356,7 @@ namespace MathNet.Numerics.UnitTests.ComplexTests [MultipleAsserts] public void CanMultipleComplexNumberAndDoubleUsingOperators() { - AssertEx.That(() => (Complex32.NaN * 1.0f).IsNaN); + AssertEx.That(() => (Complex32.NaN * 1.0f).IsNaN()); Assert.AreEqual(new Complex32(8, -8), new Complex32(4, -4) * 2); Assert.AreEqual(new Complex32(8, -8), 2 * new Complex32(4, -4)); } @@ -364,7 +365,7 @@ namespace MathNet.Numerics.UnitTests.ComplexTests [MultipleAsserts] public void CanMultipleTwoComplexNumbers() { - AssertEx.That(() => Complex32.NaN.Multiply(Complex32.One).IsNaN); + AssertEx.That(() => Complex32.NaN.Multiply(Complex32.One).IsNaN()); Assert.AreEqual(new Complex32(0, 16), new Complex32(4, -4).Multiply(new Complex32(-2, 2))); } @@ -372,7 +373,7 @@ namespace MathNet.Numerics.UnitTests.ComplexTests [MultipleAsserts] public void CanMultipleTwoComplexNumbersUsingOperators() { - AssertEx.That(() => (Complex32.NaN * Complex32.One).IsNaN); + AssertEx.That(() => (Complex32.NaN * Complex32.One).IsNaN()); Assert.AreEqual(new Complex32(0, 16), new Complex32(4, -4) * new Complex32(-2, 2)); } @@ -394,10 +395,10 @@ namespace MathNet.Numerics.UnitTests.ComplexTests [MultipleAsserts] public void CanSubtractComplexNumberAndDoubleUsingOperartor() { - AssertEx.That(() => (Complex32.NaN - float.NaN).IsNaN); - AssertEx.That(() => (float.NaN - Complex32.NaN).IsNaN); - AssertEx.That(() => (float.PositiveInfinity - Complex32.One).IsInfinity); - AssertEx.That(() => (Complex32.Infinity - 1.0f).IsInfinity); + AssertEx.That(() => (Complex32.NaN - float.NaN).IsNaN()); + AssertEx.That(() => (float.NaN - Complex32.NaN).IsNaN()); + AssertEx.That(() => (float.PositiveInfinity - Complex32.One).IsInfinity()); + AssertEx.That(() => (Complex32.Infinity - 1.0f).IsInfinity()); AssertEx.That(() => (Complex32.One - 0.0f) == Complex32.One); AssertEx.That(() => (0.0f - Complex32.One) == -Complex32.One); AssertEx.That(() => (new Complex32(1.1f, -2.2f) - 1.1f == new Complex32(0.0f, -2.2f))); @@ -408,8 +409,8 @@ namespace MathNet.Numerics.UnitTests.ComplexTests [MultipleAsserts] public void CanSubtractTwoComplexNumbers() { - AssertEx.That(() => Complex32.NaN.Subtract(Complex32.NaN).IsNaN); - AssertEx.That(() => Complex32.Infinity.Subtract(Complex32.One).IsInfinity); + AssertEx.That(() => Complex32.NaN.Subtract(Complex32.NaN).IsNaN()); + AssertEx.That(() => Complex32.Infinity.Subtract(Complex32.One).IsInfinity()); AssertEx.That(() => Complex32.One.Subtract(Complex32.Zero) == Complex32.One); AssertEx.That(() => new Complex32(1.1f, -2.2f).Subtract(new Complex32(1.1f, -2.2f)) == Complex32.Zero); } @@ -563,8 +564,8 @@ namespace MathNet.Numerics.UnitTests.ComplexTests [Test] public void CanGetConjugate() { - var complex = new Complex(123.456, -78.9); - var conjugate = complex.Conjugate; + var complex = new Complex32(123.456f, -78.9f); + var conjugate = complex.Conjugate(); Assert.AreEqual(complex.Real, conjugate.Real); Assert.AreEqual(-complex.Imaginary, conjugate.Imaginary); } diff --git a/src/UnitTests/ComplexTests/ComplexTest.TextHandling.cs b/src/UnitTests/ComplexTests/ComplexTest.TextHandling.cs index de8106db..b7169454 100644 --- a/src/UnitTests/ComplexTests/ComplexTest.TextHandling.cs +++ b/src/UnitTests/ComplexTests/ComplexTest.TextHandling.cs @@ -31,97 +31,12 @@ namespace MathNet.Numerics.UnitTests.ComplexTests using System; using System.Globalization; using MbUnit.Framework; + using System.Numerics; [TestFixture] public class ComplexTextHandlingTest { - [Test] - [Row(1, -2, "1 -2i")] - [Row(1, 2, "1 + 2i")] - [Row(1, 0, "1")] - [Row(0, -2, "-2i")] - [Row(0, 2, "2i")] - [Row(0, 2, "2i")] - [Row(0, 0, "0")] - [Row(Double.NaN, Double.NaN, "{1}")] - [Row(Double.NaN, 0, "{1}")] - [Row(0, Double.NaN, "{1}")] - [Row(Double.PositiveInfinity, Double.PositiveInfinity, "{2}")] - [Row(1.1, 0, "1{0}1")] - [Row(-1.1, 0, "-1{0}1")] - [Row(0, 1.1, "1{0}1i")] - [Row(0, -1.1, "-1{0}1i")] - [Row(1.1, 1.1, "1{0}1 + 1{0}1i")] - public void CanFormatComplexToString(double real, double imag, string expected) - { - var numberFormat = NumberFormatInfo.CurrentInfo; - var a = new Complex(real, imag); - Assert.AreEqual( - String.Format( - expected, - numberFormat.NumberDecimalSeparator, - numberFormat.NaNSymbol, - numberFormat.PositiveInfinitySymbol), - a.ToString()); - } - - [Test] - [MultipleAsserts] - [Row("en-US", "NaN", "Infinity", "1.1")] - [Row("tr-TR", "NaN", "Infinity", "1,1")] - [Row("de-DE", "n. def.", "+unendlich", "1,1")] - [Row("de-CH", "n. def.", "+unendlich", "1.1")] - [Row("he-IL", "לא מספר", "אינסוף חיובי", "1.1")] - public void CanFormatComplexToStringWithCulture( - string cultureName, string nan, string infinity, string number) - { - var provider = CultureInfo.GetCultureInfo(cultureName); - Assert.AreEqual(nan, Complex.NaN.ToString(provider)); - Assert.AreEqual(infinity, Complex.Infinity.ToString(provider)); - Assert.AreEqual("0", Complex.Zero.ToString(provider)); - Assert.AreEqual(String.Format("{0}", number), new Complex(1.1, 0).ToString(provider)); - Assert.AreEqual(String.Format("-{0}", number), new Complex(-1.1, 0).ToString(provider)); - Assert.AreEqual(String.Format("-{0}i", number), new Complex(0, -1.1).ToString(provider)); - Assert.AreEqual(String.Format("{0}i", number), new Complex(0, 1.1).ToString(provider)); - Assert.AreEqual(String.Format("{0} + {0}i", number), new Complex(1.1, 1.1).ToString(provider)); - } - - [Test] - [MultipleAsserts] - public void CanFormatComplexToStringWithFormat() - { - Assert.AreEqual("0", String.Format("{0:G}", Complex.Zero)); - Assert.AreEqual("1 + 2i", String.Format("{0:G}", new Complex(1, 2))); - Assert.AreEqual("001 + 002i", String.Format("{0:000;minus 000;zero}", new Complex(1, 2))); - Assert.AreEqual("minus 002i", String.Format("{0:000;minus 000;zero}", new Complex(0, -2))); - Assert.AreEqual("zero", String.Format("{0:000;minus 000;zero}", Complex.Zero)); - - Assert.AreEqual("0", Complex.Zero.ToString("G")); - Assert.AreEqual("1 + 2i", new Complex(1, 2).ToString("G")); - Assert.AreEqual("001 + 002i", new Complex(1, 2).ToString("#000;minus 000;zero")); - Assert.AreEqual("minus 002i", new Complex(0, -2).ToString("#000;minus 000;zero")); - Assert.AreEqual("zero", Complex.Zero.ToString("#000;minus 000;zero")); - } - - [Test] - [MultipleAsserts] - public void CanFormatComplexToStringWithFormatInvariant() - { - var culture = CultureInfo.InvariantCulture; - - Assert.AreEqual("NaN", String.Format(culture, "{0:.000}", Complex.NaN)); - Assert.AreEqual(".000", String.Format(culture, "{0:.000}", Complex.Zero)); - Assert.AreEqual("1.100", String.Format(culture, "{0:.000}", new Complex(1.1, 0))); - Assert.AreEqual("1.100 + 1.100i", String.Format(culture, "{0:.000}", new Complex(1.1, 1.1))); - - Assert.AreEqual("NaN", Complex.NaN.ToString("#.000", culture)); - Assert.AreEqual("Infinity", Complex.Infinity.ToString("#.000", culture)); - Assert.AreEqual(".000", Complex.Zero.ToString("#.000", culture)); - Assert.AreEqual("1.100", new Complex(1.1, 0).ToString("#.000", culture)); - Assert.AreEqual("-1.100i", new Complex(0, -1.1).ToString("#.000", culture)); - Assert.AreEqual("1.100i", new Complex(0, 1.1).ToString("#.000", culture)); - Assert.AreEqual("1.100 + 1.100i", new Complex(1.1, 1.1).ToString("#.000", culture)); - } + [Test] [Row("-1 -2i", -1, -2, "en-US")] @@ -129,7 +44,7 @@ namespace MathNet.Numerics.UnitTests.ComplexTests public void CanParseStringToComplexWithCulture( string text, double expectedReal, double expectedImaginary, string cultureName) { - Complex parsed = Complex.Parse(text, CultureInfo.GetCultureInfo(cultureName)); + Complex parsed = text.ToComplex(CultureInfo.GetCultureInfo(cultureName)); Assert.AreEqual(expectedReal, parsed.Real); Assert.AreEqual(expectedImaginary, parsed.Imaginary); } @@ -167,7 +82,7 @@ namespace MathNet.Numerics.UnitTests.ComplexTests { var invariantCulture = CultureInfo.InvariantCulture; Complex z; - var ret = Complex.TryParse(str, invariantCulture, out z); + var ret = str.TryToComplex(invariantCulture, out z); Assert.IsTrue(ret); Assert.AreEqual(expectedReal, z.Real); Assert.AreEqual(expectedImaginary, z.Imaginary); @@ -176,7 +91,7 @@ namespace MathNet.Numerics.UnitTests.ComplexTests [Test] public void ParseThrowsFormatExceptionIfMissingClosingParen() { - Assert.Throws(() => Complex.Parse("(1,2")); + Assert.Throws(() => "(1,2".ToComplex()); } [Test] @@ -185,30 +100,33 @@ namespace MathNet.Numerics.UnitTests.ComplexTests Complex z; var ni = NumberFormatInfo.CurrentInfo; var separator = CultureInfo.CurrentCulture.TextInfo.ListSeparator; - var ret = Complex.TryParse( - ni.NegativeInfinitySymbol + separator + ni.PositiveInfinitySymbol, out z); + + var symbol = ni.NegativeInfinitySymbol + separator + ni.PositiveInfinitySymbol; + var ret = symbol.TryToComplex(out z); Assert.IsTrue(ret, "A1"); Assert.AreEqual(double.NegativeInfinity, z.Real, "A2"); Assert.AreEqual(double.PositiveInfinity, z.Imaginary, "A3"); - ret = Complex.TryParse(ni.NaNSymbol + separator + ni.NaNSymbol, out z); + symbol = ni.NaNSymbol + separator + ni.NaNSymbol; + ret = symbol.TryToComplex(out z); Assert.IsTrue(ret, "B1"); Assert.AreEqual(double.NaN, z.Real, "B2"); Assert.AreEqual(double.NaN, z.Imaginary, "B3"); - ret = Complex.TryParse(ni.NegativeInfinitySymbol + "+" + ni.PositiveInfinitySymbol + "i", out z); + symbol = ni.NegativeInfinitySymbol + "+" + ni.PositiveInfinitySymbol + "i"; + ret = symbol.TryToComplex(out z); Assert.IsTrue(ret, "C1"); Assert.AreEqual(double.NegativeInfinity, z.Real, "C2"); Assert.AreEqual(double.PositiveInfinity, z.Imaginary, "C3"); - ret = Complex.TryParse(ni.NaNSymbol + "+" + ni.NaNSymbol + "i", out z); + symbol = ni.NaNSymbol + "+" + ni.NaNSymbol + "i"; + ret = symbol.TryToComplex(out z); Assert.IsTrue(ret, "D1"); Assert.AreEqual(double.NaN, z.Real, "D2"); Assert.AreEqual(double.NaN, z.Imaginary, "D3"); - ret = Complex.TryParse( - double.MaxValue.ToString("R") + " " + double.MinValue.ToString("R") + "i", - out z); + symbol = double.MaxValue.ToString("R") + " " + double.MinValue.ToString("R") + "i"; + ret = symbol.TryToComplex(out z); Assert.IsTrue(ret, "E1"); Assert.AreEqual(double.MaxValue, z.Real, "E2"); Assert.AreEqual(double.MinValue, z.Imaginary, "E3"); @@ -226,31 +144,33 @@ namespace MathNet.Numerics.UnitTests.ComplexTests var culture = CultureInfo.GetCultureInfo(cultureName); var ni = culture.NumberFormat; var separator = culture.TextInfo.ListSeparator; - var ret = Complex.TryParse( - ni.NegativeInfinitySymbol + separator + ni.PositiveInfinitySymbol, culture, out z); + + var symbol = ni.NegativeInfinitySymbol + separator + ni.PositiveInfinitySymbol; + var ret = symbol.TryToComplex(culture, out z); Assert.IsTrue(ret, "A1"); Assert.AreEqual(double.NegativeInfinity, z.Real, "A2"); Assert.AreEqual(double.PositiveInfinity, z.Imaginary, "A3"); - ret = Complex.TryParse(ni.NaNSymbol + separator + ni.NaNSymbol, culture, out z); + symbol = ni.NaNSymbol + separator + ni.NaNSymbol; + ret = symbol.TryToComplex(culture, out z); Assert.IsTrue(ret, "B1"); Assert.AreEqual(double.NaN, z.Real, "B2"); Assert.AreEqual(double.NaN, z.Imaginary, "B3"); - ret = Complex.TryParse(ni.NegativeInfinitySymbol + "+" + ni.PositiveInfinitySymbol + "i", culture, out z); + symbol = ni.NegativeInfinitySymbol + "+" + ni.PositiveInfinitySymbol + "i"; + ret = symbol.TryToComplex(culture, out z); Assert.IsTrue(ret, "C1"); Assert.AreEqual(double.NegativeInfinity, z.Real, "C2"); Assert.AreEqual(double.PositiveInfinity, z.Imaginary, "C3"); - ret = Complex.TryParse(ni.NaNSymbol + "+" + ni.NaNSymbol + "i", culture, out z); + symbol = ni.NaNSymbol + "+" + ni.NaNSymbol + "i"; + ret = symbol.TryToComplex(culture, out z); Assert.IsTrue(ret, "D1"); Assert.AreEqual(double.NaN, z.Real, "D2"); Assert.AreEqual(double.NaN, z.Imaginary, "D3"); - ret = Complex.TryParse( - double.MaxValue.ToString("R", culture) + " " + double.MinValue.ToString("R", culture) + "i", - culture, - out z); + symbol = double.MaxValue.ToString("R", culture) + " " + double.MinValue.ToString("R", culture) + "i"; + ret = symbol.TryToComplex(culture, out z); Assert.IsTrue(ret, "E1"); Assert.AreEqual(double.MaxValue, z.Real, "E2"); Assert.AreEqual(double.MinValue, z.Imaginary, "E3"); @@ -275,7 +195,7 @@ namespace MathNet.Numerics.UnitTests.ComplexTests public void TryParseReturnsFalseWhenGivenBadValueWithInvariant(string str) { Complex z; - var ret = Complex.TryParse(str, CultureInfo.InvariantCulture, out z); + var ret = str.TryToComplex(CultureInfo.InvariantCulture, out z); Assert.IsFalse(ret); Assert.AreEqual(0, z.Real); Assert.AreEqual(0, z.Imaginary); diff --git a/src/UnitTests/ComplexTests/ComplexTest.cs b/src/UnitTests/ComplexTests/ComplexTest.cs index 454df4f7..912d3086 100644 --- a/src/UnitTests/ComplexTests/ComplexTest.cs +++ b/src/UnitTests/ComplexTests/ComplexTest.cs @@ -26,69 +26,15 @@ // OTHER DEALINGS IN THE SOFTWARE. // -namespace MathNet.Numerics.UnitTests.ComplexTests +namespace MathNet.Numerics.UnitTests.ComplexExtensionTests { using System; + using System.Numerics; using MbUnit.Framework; [TestFixture] - public class ComplexTest + public class ComplexExtensionTest { - [Test] - [MultipleAsserts] - public void CanAddComplexNumberAndDoubleUsingOperartor() - { - AssertEx.That(() => (Complex.NaN + double.NaN).IsNaN); - AssertEx.That(() => (double.NaN + Complex.NaN).IsNaN); - AssertEx.That(() => (double.PositiveInfinity + Complex.One).IsInfinity); - AssertEx.That(() => (Complex.Infinity + 1.0).IsInfinity); - AssertEx.That(() => (Complex.One + 0.0) == Complex.One); - AssertEx.That(() => (0.0 + Complex.One) == Complex.One); - AssertEx.That(() => (new Complex(1.1, -2.2) + 1.1 == new Complex(2.2, -2.2))); - AssertEx.That(() => -2.2 + new Complex(-1.1, 2.2) == new Complex(-3.3, 2.2)); - } - - [Test] - [MultipleAsserts] - public void CanAddSubtractComplexNumbersUsingOperartor() - { - AssertEx.That(() => (Complex.NaN - Complex.NaN).IsNaN); - AssertEx.That(() => (Complex.Infinity - Complex.One).IsInfinity); - AssertEx.That(() => (Complex.One - Complex.Zero) == Complex.One); - AssertEx.That(() => (new Complex(1.1, -2.2) - new Complex(1.1, -2.2)) == Complex.Zero); - } - - [Test] - [MultipleAsserts] - public void CanAddTwoComplexNumbers() - { - AssertEx.That(() => Complex.NaN.Add(Complex.NaN).IsNaN); - AssertEx.That(() => Complex.Infinity.Add(Complex.One).IsInfinity); - AssertEx.That(() => Complex.One.Add(Complex.Zero) == Complex.One); - AssertEx.That(() => new Complex(1.1, -2.2).Add(new Complex(-1.1, 2.2)) == Complex.Zero); - } - - [Test] - [MultipleAsserts] - public void CanAddTwoComplexNumbersUsingOperartor() - { - AssertEx.That(() => (Complex.NaN + Complex.NaN).IsNaN); - AssertEx.That(() => (Complex.Infinity + Complex.One).IsInfinity); - AssertEx.That(() => (Complex.One + Complex.Zero) == Complex.One); - AssertEx.That(() => (new Complex(1.1, -2.2) + new Complex(-1.1, 2.2)) == Complex.Zero); - } - - [Test] - [MultipleAsserts] - public void CanCalculateHashCode() - { - var complex = new Complex(1, 0); - Assert.AreEqual(1072693248, complex.GetHashCode()); - complex = new Complex(0, 1); - Assert.AreEqual(-1072693248, complex.GetHashCode()); - complex = new Complex(1, 1); - Assert.AreEqual(-2097152, complex.GetHashCode()); - } [Test] [Row(0.0, 0.0, 1.0, 0.0)] @@ -102,18 +48,6 @@ 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)] @@ -127,32 +61,6 @@ 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() @@ -193,21 +101,9 @@ namespace MathNet.Numerics.UnitTests.ComplexTests AssertHelpers.AlmostEqual(new Complex(double.PositiveInfinity, double.PositiveInfinity), a.Power(b), 15); a = new Complex(0.0, 0.0); b = new Complex(0.0, 1.0); - AssertEx.That(() => a.Power(b).IsNaN); + 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() @@ -275,79 +171,11 @@ 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() - { - AssertEx.That(() => ((Complex)double.NaN).IsNaN); - AssertEx.That(() => ((Complex)double.NegativeInfinity).IsInfinity); - Assert.AreEqual(1.1, new Complex(1.1, 0)); - } - - [Test] - [MultipleAsserts] - public void CanCreateComplexNumberUsingTheConstructor() - { - var complex = new Complex(1.1, -2.2); - Assert.AreEqual(1.1, complex.Real, "Real part is 1.1."); - Assert.AreEqual(-2.2, complex.Imaginary, "Imaginary part is -2.2."); - } - - [Test] - [MultipleAsserts] - public void CanCreateComplexNumberWithModulusArgument() - { - var complex = Complex.WithModulusArgument(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 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() - { - var complex = Complex.WithRealImaginary(1.1, -2.2); - Assert.AreEqual(1.1, complex.Real, "Real part is 1.1."); - Assert.AreEqual(-2.2, complex.Imaginary, "Imaginary part is -2.2."); - } - [Test] public void CanDetermineIfImaginaryUnit() { var complex = new Complex(0, 1); - Assert.IsTrue(complex.IsImaginaryOne, "Imaginary unit"); + Assert.IsTrue(complex.IsImaginaryOne(), "Imaginary unit"); } [Test] @@ -355,11 +183,11 @@ namespace MathNet.Numerics.UnitTests.ComplexTests public void CanDetermineIfInfinity() { var complex = new Complex(double.PositiveInfinity, 1); - Assert.IsTrue(complex.IsInfinity, "Real part is infinity."); + Assert.IsTrue(complex.IsInfinity(), "Real part is infinity."); complex = new Complex(1, double.NegativeInfinity); - Assert.IsTrue(complex.IsInfinity, "Imaginary part is infinity."); + Assert.IsTrue(complex.IsInfinity(), "Imaginary part is infinity."); complex = new Complex(double.NegativeInfinity, double.PositiveInfinity); - Assert.IsTrue(complex.IsInfinity, "Both parts are infinity."); + Assert.IsTrue(complex.IsInfinity(), "Both parts are infinity."); } [Test] @@ -367,439 +195,39 @@ namespace MathNet.Numerics.UnitTests.ComplexTests public void CanDetermineIfNaN() { var complex = new Complex(double.NaN, 1); - Assert.IsTrue(complex.IsNaN, "Real part is NaN."); + Assert.IsTrue(complex.IsNaN(), "Real part is NaN."); complex = new Complex(1, double.NaN); - Assert.IsTrue(complex.IsNaN, "Imaginary part is NaN."); + Assert.IsTrue(complex.IsNaN(), "Imaginary part is NaN."); complex = new Complex(double.NaN, double.NaN); - Assert.IsTrue(complex.IsNaN, "Both parts are NaN."); + Assert.IsTrue(complex.IsNaN(), "Both parts are NaN."); } [Test] public void CanDetermineIfOneValueComplexNumber() { var complex = new Complex(1, 0); - Assert.IsTrue(complex.IsOne, "Complex number with a value of one."); + Assert.IsTrue(complex.IsOne(), "Complex number with a value of one."); } [Test] public void CanDetermineIfRealNonNegativeNumber() { var complex = new Complex(1, 0); - Assert.IsTrue(complex.IsReal, "Is a real non-negative number."); + Assert.IsTrue(complex.IsReal(), "Is a real non-negative number."); } [Test] public void CanDetermineIfRealNumber() { var complex = new Complex(-1, 0); - Assert.IsTrue(complex.IsReal, "Is a real number."); + Assert.IsTrue(complex.IsReal(), "Is a real number."); } [Test] public void CanDetermineIfZeroValueComplexNumber() { var complex = new Complex(0, 0); - Assert.IsTrue(complex.IsZero, "Zero complex number."); - } - - [Test] - [MultipleAsserts] - public void CanDivideComplexNumberAndDoubleUsingOperators() - { - AssertEx.That(() => (Complex.NaN * 1.0).IsNaN); - Assert.AreEqual(new Complex(-2, 2), new Complex(4, -4) / -2); - Assert.AreEqual(new Complex(0.25, 0.25), 2 / new Complex(4, -4)); - Assert.AreEqual(Complex.Infinity, 2.0 / Complex.Zero); - Assert.AreEqual(Complex.Infinity, Complex.One / 0); - } - - [Test] - [MultipleAsserts] - public void CanDivideTwoComplexNumbers() - { - AssertEx.That(() => Complex.NaN.Multiply(Complex.One).IsNaN); - Assert.AreEqual(new Complex(-2, 0), new Complex(4, -4).Divide(new Complex(-2, 2))); - Assert.AreEqual(Complex.Infinity, Complex.One.Divide(Complex.Zero)); - } - - [Test] - [MultipleAsserts] - public void CanDivideTwoComplexNumbersUsingOperators() - { - AssertEx.That(() => (Complex.NaN / Complex.One).IsNaN); - Assert.AreEqual(new Complex(-2, 0), new Complex(4, -4) / new Complex(-2, 2)); - Assert.AreEqual(Complex.Infinity, Complex.One / Complex.Zero); - } - - [Test] - [MultipleAsserts] - public void CanMultipleComplexNumberAndDoubleUsingOperators() - { - AssertEx.That(() => (Complex.NaN * 1.0).IsNaN); - Assert.AreEqual(new Complex(8, -8), new Complex(4, -4) * 2); - Assert.AreEqual(new Complex(8, -8), 2 * new Complex(4, -4)); - } - - [Test] - [MultipleAsserts] - public void CanMultipleTwoComplexNumbers() - { - AssertEx.That(() => Complex.NaN.Multiply(Complex.One).IsNaN); - Assert.AreEqual(new Complex(0, 16), new Complex(4, -4).Multiply(new Complex(-2, 2))); - } - - [Test] - [MultipleAsserts] - public void CanMultipleTwoComplexNumbersUsingOperators() - { - AssertEx.That(() => (Complex.NaN * Complex.One).IsNaN); - Assert.AreEqual(new Complex(0, 16), new Complex(4, -4) * new Complex(-2, 2)); - } - - [Test] - public void CanNegateValue() - { - var complex = new Complex(1.1, -2.2); - Assert.AreEqual(new Complex(-1.1, 2.2), complex.Negate()); - } - - [Test] - public void CanNegateValueUsingOperator() - { - var complex = new Complex(1.1, -2.2); - Assert.AreEqual(new Complex(-1.1, 2.2), -complex); - } - - [Test] - [MultipleAsserts] - public void CanSubtractComplexNumberAndDoubleUsingOperartor() - { - AssertEx.That(() => (Complex.NaN - double.NaN).IsNaN); - AssertEx.That(() => (double.NaN - Complex.NaN).IsNaN); - AssertEx.That(() => (double.PositiveInfinity - Complex.One).IsInfinity); - AssertEx.That(() => (Complex.Infinity - 1.0).IsInfinity); - AssertEx.That(() => (Complex.One - 0.0) == Complex.One); - AssertEx.That(() => (0.0 - Complex.One) == -Complex.One); - AssertEx.That(() => (new Complex(1.1, -2.2) - 1.1 == new Complex(0.0, -2.2))); - AssertEx.That(() => -2.2 - new Complex(-1.1, 2.2) == new Complex(-1.1, -2.2)); - } - - [Test] - [MultipleAsserts] - public void CanSubtractTwoComplexNumbers() - { - AssertEx.That(() => Complex.NaN.Subtract(Complex.NaN).IsNaN); - AssertEx.That(() => Complex.Infinity.Subtract(Complex.One).IsInfinity); - AssertEx.That(() => Complex.One.Subtract(Complex.Zero) == Complex.One); - AssertEx.That(() => new Complex(1.1, -2.2).Subtract(new Complex(1.1, -2.2)) == Complex.Zero); - } - - [Test] - [MultipleAsserts] - public void CanTestForEquality() - { - Assert.AreNotEqual(Complex.NaN, Complex.NaN); - Assert.AreEqual(Complex.Infinity, Complex.Infinity); - Assert.AreEqual(new Complex(1.1, -2.2), new Complex(1.1, -2.2)); - Assert.AreNotEqual(new Complex(-1.1, 2.2), new Complex(1.1, -2.2)); - } - - [Test] - [MultipleAsserts] - public void CanTestForEqualityUsingOperators() - { - AssertEx.That(() => Complex.NaN != Complex.NaN); - AssertEx.That(() => Complex.Infinity == Complex.Infinity); - AssertEx.That(() => new Complex(1.1, -2.2) == new Complex(1.1, -2.2)); - AssertEx.That(() => new Complex(-1.1, 2.2) != new Complex(1.1, -2.2)); - } - - [Test] - public void CanUsePlus() - { - var complex = new Complex(1.1, -2.2); - Assert.AreEqual(complex, complex.Plus()); - } - - [Test] - public void CanUsePlusOperator() - { - var complex = new Complex(1.1, -2.2); - Assert.AreEqual(complex, +complex); - } - - [Test] - public void WithModulusArgumentThrowsArgumentOutOfRangeException() - { - Assert.Throws( - () => Complex.WithModulusArgument(-1, 1), "Throws exception because modulus is negative."); - } - - [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 CanComputeMagnitude(double real, double imag, double expected) - { - 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)] - [Row(double.NegativeInfinity, double.PositiveInfinity, -Constants.Sqrt1Over2, -Constants.Sqrt1Over2)] - [Row(double.NegativeInfinity, double.NegativeInfinity, -Constants.Sqrt1Over2, Constants.Sqrt1Over2)] - [Row(0.0, 0.0, 0.0, 0.0)] - [Row(-1.0, 1.0, -0.70710678118654746, 0.70710678118654746)] - [Row(-111.1, 111.1, -0.70710678118654746, 0.70710678118654746)] - public void CanComputeSign(double real, double imag, double expectedReal, double expectedImag) - { - 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 CanConvertComplex32ToComplex() - { - var complex32 = new Complex32(123.456f, -78.9f); - var complex = (Complex)complex32; - Assert.AreEqual(123.456f, (float)complex.Real); - Assert.AreEqual(-78.9f, (float)complex.Imaginary); + Assert.IsTrue(complex.IsZero(), "Zero complex number."); } - } + } } \ No newline at end of file diff --git a/src/UnitTests/IntegralTransformsTests/FourierTest.cs b/src/UnitTests/IntegralTransformsTests/FourierTest.cs index eceaa8ce..095f7c94 100644 --- a/src/UnitTests/IntegralTransformsTests/FourierTest.cs +++ b/src/UnitTests/IntegralTransformsTests/FourierTest.cs @@ -34,6 +34,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests using IntegralTransforms.Algorithms; using MbUnit.Framework; using Sampling; + using System.Numerics; [TestFixture] public class FourierTest diff --git a/src/UnitTests/IntegralTransformsTests/HartleyTest.cs b/src/UnitTests/IntegralTransformsTests/HartleyTest.cs index 0358269d..eda5c2d9 100644 --- a/src/UnitTests/IntegralTransformsTests/HartleyTest.cs +++ b/src/UnitTests/IntegralTransformsTests/HartleyTest.cs @@ -29,6 +29,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests { using System; + using System.Numerics; using Distributions; using IntegralTransforms; using IntegralTransforms.Algorithms; diff --git a/src/UnitTests/IntegralTransformsTests/InverseTransformTest.cs b/src/UnitTests/IntegralTransformsTests/InverseTransformTest.cs index f76a592a..6b29a34a 100644 --- a/src/UnitTests/IntegralTransformsTests/InverseTransformTest.cs +++ b/src/UnitTests/IntegralTransformsTests/InverseTransformTest.cs @@ -29,6 +29,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests { using System; + using System.Numerics; using Distributions; using IntegralTransforms; using IntegralTransforms.Algorithms; diff --git a/src/UnitTests/IntegralTransformsTests/MatchingNaiveTransformTest.cs b/src/UnitTests/IntegralTransformsTests/MatchingNaiveTransformTest.cs index ff4e16ee..4dabca38 100644 --- a/src/UnitTests/IntegralTransformsTests/MatchingNaiveTransformTest.cs +++ b/src/UnitTests/IntegralTransformsTests/MatchingNaiveTransformTest.cs @@ -29,6 +29,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests { using System; + using System.Numerics; using Distributions; using IntegralTransforms; using IntegralTransforms.Algorithms; diff --git a/src/UnitTests/IntegralTransformsTests/ParsevalTheoremTest.cs b/src/UnitTests/IntegralTransformsTests/ParsevalTheoremTest.cs index cf2afbc0..f5b98822 100644 --- a/src/UnitTests/IntegralTransformsTests/ParsevalTheoremTest.cs +++ b/src/UnitTests/IntegralTransformsTests/ParsevalTheoremTest.cs @@ -35,6 +35,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests using MbUnit.Framework; using Sampling; using Statistics; + using System.Numerics; [TestFixture] public class ParsevalTheoremTest @@ -48,7 +49,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests { var samples = Sample.Random((u, v) => new Complex(u, v), _uniform, count); - var timeSpaceEnergy = (from s in samples select s.MagnitudeSquared).Mean(); + var timeSpaceEnergy = (from s in samples select s.MagnitudeSquared()).Mean(); var work = new Complex[samples.Length]; samples.CopyTo(work, 0); @@ -56,7 +57,7 @@ namespace MathNet.Numerics.UnitTests.IntegralTransformsTests // Default -> Symmetric Scaling Transform.FourierForward(work); - var frequencySpaceEnergy = (from s in work select s.MagnitudeSquared).Mean(); + var frequencySpaceEnergy = (from s in work select s.MagnitudeSquared()).Mean(); Assert.AreApproximatelyEqual(timeSpaceEnergy, frequencySpaceEnergy, 1e-12); } diff --git a/src/UnitTests/TrigonometryTest.cs b/src/UnitTests/TrigonometryTest.cs index 1e31ea4f..c5c00d19 100644 --- a/src/UnitTests/TrigonometryTest.cs +++ b/src/UnitTests/TrigonometryTest.cs @@ -1,7 +1,7 @@ namespace MathNet.Numerics.UnitTests { using System; - + using System.Numerics; using MbUnit.Framework; [TestFixture] diff --git a/src/UnitTests/UnitTests.csproj b/src/UnitTests/UnitTests.csproj index f12524be..d2d15ea6 100644 --- a/src/UnitTests/UnitTests.csproj +++ b/src/UnitTests/UnitTests.csproj @@ -71,6 +71,7 @@ 3.5 + 3.5