//
// 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
}
}