// // 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. // using System; using System.Runtime.InteropServices; using System.Text; using System.Text.RegularExpressions; using MathNet.Numerics.Properties; namespace MathNet.Numerics { /// /// 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); /// /// Since there is no canonical order among the complex numbers, /// Complex does not implement IComparable but several /// lexicographic IComparer implementations are provided, see /// , /// and /// . /// For mathematical details about complex numbers, please /// have a look at the /// Wikipedia /// [Serializable] [StructLayout(LayoutKind.Sequential)] public struct Complex : IFormattable, IEquatable { #region fields /// /// Regular expressionused to parse strings into complex numbers. /// private static readonly Regex parseExpression = new Regex(@"^((?(([-+]?(\d+\.?\d*|\d*\.?\d+)([Ee][-+]?[0-9]+)?)|(NaN)|([-+]?Infinity)))|(?(([-+]?((\d+\.?\d*|\d*\.?\d+)([Ee][-+]?[0-9]+)?)|(NaN)|([-+]?Infinity))?[i]))|(?(([-+]?(\d+\.?\d*|\d*\.?\d+)([Ee][-+]?[0-9]+)?)|(NaN)|([-+]?Infinity)))(?(([-+]((\d+\.?\d*|\d*\.?\d+)([Ee][-+]?[0-9]+)?)|[-+](NaN)|([-+]Infinity))?[i])))$", RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); /// /// Represents imaginary unit number. /// private static readonly Complex i = new Complex(0, 1); /// /// Represents a infite complex number /// private static readonly Complex infinity = new Complex(double.PositiveInfinity, double.PositiveInfinity); /// /// Reprensents 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 struct 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 MathNet.PreciseNumerics and MathNet.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 I { 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 whether the Complex is zero. /// /// true if this instance is zero; otherwise, false. public bool IsZero { get { return _real.AlmostZero() && _imag.AlmostZero(); } } /// /// Gets a value indicating whether the Complex is one. /// /// true if this instance is one; otherwise, false. public bool IsOne { get { return _real.AlmostEqual(1.0) && _imag.AlmostZero(); } } /// /// Gets a value indicating whether the Complex is the imaginary unit. /// /// true if this instance is I; otherwise, false. public bool IsI { get { return _real.AlmostZero() && _imag.AlmostEqual(1.0); } } /// /// Gets a value indicating whether the provided Complex evaluates to a /// value that is not a number. /// /// true if this instance is NaN; 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.AlmostZero(); } } /// /// 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.AlmostZero() && _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 or modulus of this Complex. /// /// public double Modulus { get { return Math.Sqrt((_real * _real) + (_imag * _imag)); } } /// /// Gets the squared modulus of this Complex. /// /// public double ModulusSquared { get { return (_real * _real) + (_imag * _imag); } } /// /// Gets argument of this Complex. /// /// /// Argument 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 Argument { 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 "Modulus"! var mod = SpecialFunctions.Hypotenuse(_real, _imag); if (mod.AlmostZero()) { return Zero; } return new Complex(_real / mod, _imag / mod); } } #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", 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 IFormatProvider 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 IFormatProvider that supplies culture-specific formatting information. public string ToString(string format, IFormatProvider formatProvider) { if (IsNaN) { return "NaN"; } if (IsInfinity) { return "Infinity"; } var ret = new StringBuilder(); if (!_real.AlmostZero()) { ret.Append(_real.ToString(format, formatProvider)); } if (!_imag.AlmostZero()) { if (!_real.AlmostZero()) { if (_imag < 0) { ret.Append(" "); } else { ret.Append(" + "); } } ret.Append(_imag.ToString(format, formatProvider)).Append("i"); } 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.ModulusSquared; 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.ModulusSquared; 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.AlmostZero()) { return Infinity; } return new Complex(dividend._real / divisor, dividend._imag / divisor); } /// /// Implicit conversion of a real double to a real Complex. /// /// The double value to convert. /// The result of the conversion. public static implicit operator Complex(double number) { return new Complex(number, 0.0); } /// /// 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 } }