// // 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 { throw new NotImplementedException(); } // return Number.AlmostZero(real) && Number.AlmostZero(imag); } } /// /// Gets a value indicating whether the Complex is one. /// /// true if this instance is one; otherwise, false. public bool IsOne { get { throw new NotImplementedException(); } // return Number.AlmostEqual(real, 1) && Number.AlmostZero(imag); } } /// /// Gets a value indicating whether the Complex is the imaginary unit. /// /// true if this instance is I; otherwise, false. public bool IsI { get { throw new NotImplementedException(); } // return Number.AlmostZero(real) && Number.AlmostEqual(imag, 1); } } /// /// 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 { throw new NotImplementedException(); } // 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 infinie; 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 { throw new NotImplementedException(); } // return Number.AlmostZero(imag); } } /// /// 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 { throw new NotImplementedException(); } // return Number.AlmostZero(imag) && real >= 0; } } /// /// Gets a value indicating whetherthe provided Complex is imaginary. /// /// /// true if this instance is an imaginary number; otherwise, false. /// public bool IsImaginary { get { throw new NotImplementedException(); } // return Number.AlmostZero(real); } } #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(); ret.Append(_real.ToString(format, formatProvider)); 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) { return Real == other.Real && Imaginary == other.Imaginary; } /// 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 } }