//
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
//
// 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.
//
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using Complex = System.Numerics.Complex;
using BigInteger = System.Numerics.BigInteger;
#if !NETSTANDARD1_3
using System.Runtime;
#endif
namespace IStation.Numerics
{
///
/// 32-bit single precision complex numbers class.
///
///
///
/// The class Complex32 provides all elementary operations
/// on complex numbers. All the operators +, -,
/// *, /, ==, != are defined in the
/// canonical way. Additional complex trigonometric functions
/// are also provided. Note that the Complex32 structures
/// has two special constant values and
/// .
///
///
///
/// Complex32 x = new Complex32(1f,2f);
/// Complex32 y = Complex32.FromPolarCoordinates(1f, Math.Pi);
/// Complex32 z = (x + y) / (x - y);
///
///
///
/// For mathematical details about complex numbers, please
/// have a look at the
/// Wikipedia
///
///
[Serializable]
[StructLayout(LayoutKind.Sequential)]
[DataContract(Namespace = "urn:IStation/Numerics")]
public readonly struct Complex32 : IFormattable, IEquatable
{
///
/// The real component of the complex number.
///
[DataMember(Order = 1)]
private readonly float _real;
///
/// The imaginary component of the complex number.
///
[DataMember(Order = 2)]
private readonly float _imag;
///
/// Initializes a new instance of the Complex32 structure with the given real
/// and imaginary parts.
///
/// The value for the real component.
/// The value for the imaginary component.
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public Complex32(float real, float imaginary)
{
_real = real;
_imag = imaginary;
}
///
/// Creates a complex number from a point's polar coordinates.
///
/// A complex number.
/// The magnitude, which is the distance from the origin (the intersection of the x-axis and the y-axis) to the number.
/// The phase, which is the angle from the line to the horizontal axis, measured in radians.
public static Complex32 FromPolarCoordinates(float magnitude, float phase)
{
return new Complex32(magnitude * (float)Math.Cos(phase), magnitude * (float)Math.Sin(phase));
}
///
/// Returns a new instance
/// with a real number equal to zero and an imaginary number equal to zero.
///
public static readonly Complex32 Zero = new Complex32(0.0f, 0.0f);
///
/// Returns a new instance
/// with a real number equal to one and an imaginary number equal to zero.
///
public static readonly Complex32 One = new Complex32(1.0f, 0.0f);
///
/// Returns a new instance
/// with a real number equal to zero and an imaginary number equal to one.
///
public static readonly Complex32 ImaginaryOne = new Complex32(0, 1);
///
/// Returns a new instance
/// with real and imaginary numbers positive infinite.
///
public static readonly Complex32 PositiveInfinity = new Complex32(float.PositiveInfinity, float.PositiveInfinity);
///
/// Returns a new instance
/// with real and imaginary numbers not a number.
///
public static readonly Complex32 NaN = new Complex32(float.NaN, float.NaN);
///
/// Gets the real component of the complex number.
///
/// The real component of the complex number.
public float Real
{
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
get => _real;
}
///
/// Gets the real imaginary component of the complex number.
///
/// The real imaginary component of the complex number.
public float Imaginary
{
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
get => _imag;
}
///
/// Gets the phase or argument of this Complex32.
///
///
/// Phase always returns a value bigger than negative Pi and
/// smaller or equal to Pi. If this Complex32 is zero, the Complex32
/// is assumed to be positive real with an argument of zero.
///
/// The phase or argument of this Complex32
public float Phase
{
// NOTE: the special case for negative real numbers fixes negative-zero value behavior. Do not remove.
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
get => _imag == 0f && _real < 0f ? (float)Constants.Pi : (float)Math.Atan2(_imag, _real);
}
///
/// Gets the magnitude (or absolute value) of a complex number.
///
/// Assuming that magnitude of (inf,a) and (a,inf) and (inf,inf) is inf and (NaN,a), (a,NaN) and (NaN,NaN) is NaN
/// The magnitude of the current instance.
public float Magnitude
{
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
get
{
if (float.IsNaN(_real) || float.IsNaN(_imag))
return float.NaN;
if (float.IsInfinity(_real) || float.IsInfinity(_imag))
return float.PositiveInfinity;
float a = Math.Abs(_real);
float b = Math.Abs(_imag);
if (a > b)
{
double tmp = b / a;
return a * (float)Math.Sqrt(1.0f + tmp * tmp);
}
if (a == 0.0f) // one can write a >= float.Epsilon here
{
return b;
}
else
{
double tmp = a / b;
return b * (float)Math.Sqrt(1.0f + tmp * tmp);
}
}
}
///
/// Gets the squared magnitude (or squared absolute value) of a complex number.
///
/// The squared magnitude of the current instance.
public float MagnitudeSquared => _real * _real + _imag * _imag;
///
/// Gets the unity of this complex (same argument, but on the unit circle; exp(I*arg))
///
/// The unity of this Complex32.
public Complex32 Sign
{
get
{
if (float.IsPositiveInfinity(_real) && float.IsPositiveInfinity(_imag))
{
return new Complex32((float)Constants.Sqrt1Over2, (float)Constants.Sqrt1Over2);
}
if (float.IsPositiveInfinity(_real) && float.IsNegativeInfinity(_imag))
{
return new Complex32((float)Constants.Sqrt1Over2, -(float)Constants.Sqrt1Over2);
}
if (float.IsNegativeInfinity(_real) && float.IsPositiveInfinity(_imag))
{
return new Complex32(-(float)Constants.Sqrt1Over2, -(float)Constants.Sqrt1Over2);
}
if (float.IsNegativeInfinity(_real) && float.IsNegativeInfinity(_imag))
{
return new Complex32(-(float)Constants.Sqrt1Over2, (float)Constants.Sqrt1Over2);
}
// don't replace this with "Magnitude"!
var mod = SpecialFunctions.Hypotenuse(_real, _imag);
if (mod == 0.0f)
{
return Zero;
}
return new Complex32(_real / mod, _imag / mod);
}
}
///
/// Gets a value indicating whether the Complex32 is zero.
///
/// true if this instance is zero; otherwise, false.
public bool IsZero()
{
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()
{
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()
{
return _real == 0.0f && _imag == 1.0f;
}
///
/// Gets a value indicating whether the provided Complex32evaluates
/// to a value that is not a number.
///
///
/// true if this instance is ; otherwise,
/// false.
///
public bool IsNaN()
{
return float.IsNaN(_real) || float.IsNaN(_imag);
}
///
/// 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 bool IsInfinity()
{
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()
{
return _imag == 0.0f;
}
///
/// 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 bool IsRealNonNegative()
{
return _imag == 0.0f && _real >= 0;
}
///
/// Exponential of this Complex32 (exp(x), E^x).
///
///
/// The exponential of this complex number.
///
public Complex32 Exponential()
{
var exp = (float)Math.Exp(_real);
if (IsReal())
{
return new Complex32(exp, 0.0f);
}
return new Complex32(exp * (float)Math.Cos(_imag), exp * (float)Math.Sin(_imag));
}
///
/// Natural Logarithm of this Complex32 (Base E).
///
/// The natural logarithm of this complex number.
public Complex32 NaturalLogarithm()
{
if (IsRealNonNegative())
{
return new Complex32((float)Math.Log(_real), 0.0f);
}
return new Complex32(0.5f * (float)Math.Log(MagnitudeSquared), Phase);
}
///
/// Common Logarithm of this Complex32 (Base 10).
///
/// The common logarithm of this complex number.
public Complex32 CommonLogarithm()
{
return NaturalLogarithm() / (float)Constants.Ln10;
}
///
/// Logarithm of this Complex32 with custom base.
///
/// The logarithm of this complex number.
public Complex32 Logarithm(float baseValue)
{
return NaturalLogarithm() / (float)Math.Log(baseValue);
}
///
/// Raise this Complex32 to the given value.
///
///
/// The exponent.
///
///
/// The complex number raised to the given exponent.
///
public Complex32 Power(Complex32 exponent)
{
if (IsZero())
{
if (exponent.IsZero())
{
return One;
}
if (exponent.Real > 0f)
{
return Zero;
}
if (exponent.Real < 0f)
{
return exponent.Imaginary == 0f
? new Complex32(float.PositiveInfinity, 0f)
: new Complex32(float.PositiveInfinity, float.PositiveInfinity);
}
return NaN;
}
return (exponent * NaturalLogarithm()).Exponential();
}
///
/// Raise this Complex32 to the inverse of the given value.
///
///
/// The root exponent.
///
///
/// The complex raised to the inverse of the given exponent.
///
public Complex32 Root(Complex32 rootExponent)
{
return Power(1 / rootExponent);
}
///
/// The Square (power 2) of this Complex32
///
///
/// The square of this complex number.
///
public Complex32 Square()
{
if (IsReal())
{
return new Complex32(_real * _real, 0.0f);
}
return new Complex32((_real * _real) - (_imag * _imag), 2 * _real * _imag);
}
///
/// The Square Root (power 1/2) of this Complex32
///
///
/// The square root of this complex number.
///
public Complex32 SquareRoot()
{
if (IsRealNonNegative())
{
return new Complex32((float)Math.Sqrt(_real), 0.0f);
}
Complex32 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.0f + Math.Sqrt(1.0f + (ratio * ratio))));
}
else
{
var ratio = Real / Imaginary;
w = Math.Sqrt(absImag) * Math.Sqrt(0.5 * (Math.Abs(ratio) + Math.Sqrt(1.0f + (ratio * ratio))));
}
if (Real >= 0.0f)
{
result = new Complex32((float)w, (float)(Imaginary / (2.0f * w)));
}
else if (Imaginary >= 0.0f)
{
result = new Complex32((float)(absImag / (2.0 * w)), (float)w);
}
else
{
result = new Complex32((float)(absImag / (2.0 * w)), (float)-w);
}
return result;
}
///
/// Evaluate all square roots of this Complex32.
///
public Tuple SquareRoots()
{
var principal = SquareRoot();
return new Tuple(principal, -principal);
}
///
/// Evaluate all cubic roots of this Complex32.
///
public Tuple CubicRoots()
{
float r = (float)Math.Pow(Magnitude, 1d / 3d);
float theta = Phase / 3;
const float shift = (float)Constants.Pi2 / 3;
return new Tuple(
FromPolarCoordinates(r, theta),
FromPolarCoordinates(r, theta + shift),
FromPolarCoordinates(r, theta - shift));
}
///
/// 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 ==(Complex32 complex1, Complex32 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 !=(Complex32 complex1, Complex32 complex2)
{
return !complex1.Equals(complex2);
}
///
/// Unary addition.
///
/// The complex number to operate on.
/// Returns the same complex number.
public static Complex32 operator +(Complex32 summand)
{
return summand;
}
///
/// Unary minus.
///
/// The complex number to operate on.
/// The negated value of the .
public static Complex32 operator -(Complex32 subtrahend)
{
return new Complex32(-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 Complex32 operator +(Complex32 summand1, Complex32 summand2)
{
return new Complex32(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 Complex32 operator -(Complex32 minuend, Complex32 subtrahend)
{
return new Complex32(minuend._real - subtrahend._real, minuend._imag - subtrahend._imag);
}
/// Addition operator. Adds a complex number and float together.
/// The result of the addition.
/// The complex numbers to add.
/// The float value to add.
public static Complex32 operator +(Complex32 summand1, float summand2)
{
return new Complex32(summand1._real + summand2, summand1._imag);
}
/// Subtraction operator. Subtracts float value from a complex value.
/// The result of the subtraction.
/// The complex number to subtract from.
/// The float value to subtract.
public static Complex32 operator -(Complex32 minuend, float subtrahend)
{
return new Complex32(minuend._real - subtrahend, minuend._imag);
}
/// Addition operator. Adds a complex number and float together.
/// The result of the addition.
/// The float value to add.
/// The complex numbers to add.
public static Complex32 operator +(float summand1, Complex32 summand2)
{
return new Complex32(summand2._real + summand1, summand2._imag);
}
/// Subtraction operator. Subtracts complex value from a float value.
/// The result of the subtraction.
/// The float vale to subtract from.
/// The complex value to subtract.
public static Complex32 operator -(float minuend, Complex32 subtrahend)
{
return new Complex32(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 Complex32 operator *(Complex32 multiplicand, Complex32 multiplier)
{
return new Complex32(
(multiplicand._real * multiplier._real) - (multiplicand._imag * multiplier._imag),
(multiplicand._real * multiplier._imag) + (multiplicand._imag * multiplier._real));
}
/// Multiplication operator. Multiplies a complex number with a float value.
/// The result of the multiplication.
/// The float value to multiply.
/// The complex number to multiply.
public static Complex32 operator *(float multiplicand, Complex32 multiplier)
{
return new Complex32(multiplier._real * multiplicand, multiplier._imag * multiplicand);
}
/// Multiplication operator. Multiplies a complex number with a float value.
/// The result of the multiplication.
/// The complex number to multiply.
/// The float value to multiply.
public static Complex32 operator *(Complex32 multiplicand, float multiplier)
{
return new Complex32(multiplicand._real * multiplier, multiplicand._imag * multiplier);
}
/// Division operator. Divides a complex number by another.
/// Enhanced Smith's algorithm for dividing two complex numbers
///
/// The result of the division.
/// The dividend.
/// The divisor.
public static Complex32 operator /(Complex32 dividend, Complex32 divisor)
{
if (dividend.IsZero() && divisor.IsZero())
{
return NaN;
}
if (divisor.IsZero())
{
return PositiveInfinity;
}
float a = dividend.Real;
float b = dividend.Imaginary;
float c = divisor.Real;
float d = divisor.Imaginary;
if (Math.Abs(d) <= Math.Abs(c))
return InternalDiv(a, b, c, d, false);
return InternalDiv(b, a, d, c, true);
}
///
/// Helper method for dividing.
///
/// Re first
/// Im first
/// Re second
/// Im second
///
///
private static Complex32 InternalDiv(float a, float b, float c, float d, bool swapped)
{
float r = d / c;
float t = 1 / (c + d * r);
float e, f;
if (r != 0.0f) // one can use r >= float.Epsilon || r <= float.Epsilon instead
{
e = (a + b * r) * t;
f = (b - a * r) * t;
}
else
{
e = (a + d * (b / c)) * t;
f = (b - d * (a / c)) * t;
}
if (swapped)
f = -f;
return new Complex32(e, f);
}
/// Division operator. Divides a float value by a complex number.
/// Algorithm based on Smith's algorithm
///
/// The result of the division.
/// The dividend.
/// The divisor.
public static Complex32 operator /(float dividend, Complex32 divisor)
{
if (dividend == 0.0f && divisor.IsZero())
{
return NaN;
}
if (divisor.IsZero())
{
return PositiveInfinity;
}
float c = divisor.Real;
float d = divisor.Imaginary;
if (Math.Abs(d) <= Math.Abs(c))
return InternalDiv(dividend, 0, c, d, false);
return InternalDiv(0, dividend, d, c, true);
}
/// Division operator. Divides a complex number by a float value.
/// The result of the division.
/// The dividend.
/// The divisor.
public static Complex32 operator /(Complex32 dividend, float divisor)
{
if (dividend.IsZero() && divisor == 0.0f)
{
return NaN;
}
if (divisor == 0.0f)
{
return PositiveInfinity;
}
return new Complex32(dividend._real / divisor, dividend._imag / divisor);
}
///
/// Computes the conjugate of a complex number and returns the result.
///
public Complex32 Conjugate()
{
return new Complex32(_real, -_imag);
}
///
/// Returns the multiplicative inverse of a complex number.
///
public Complex32 Reciprocal()
{
if (IsZero())
{
return Zero;
}
return 1.0f / this;
}
#region IFormattable Members
///
/// Converts the value of the current complex number to its equivalent string representation in Cartesian form.
///
/// The string representation of the current instance in Cartesian form.
public override string ToString()
{
return string.Format(CultureInfo.CurrentCulture, "({0}, {1})", _real, _imag);
}
///
/// Converts the value of the current complex number to its equivalent string representation
/// in Cartesian form by using the specified format for its real and imaginary parts.
///
/// The string representation of the current instance in Cartesian form.
/// A standard or custom numeric format string.
///
/// is not a valid format string.
public string ToString(string format)
{
return string.Format(CultureInfo.CurrentCulture, "({0}, {1})",
_real.ToString(format, CultureInfo.CurrentCulture),
_imag.ToString(format, CultureInfo.CurrentCulture));
}
///
/// Converts the value of the current complex number to its equivalent string representation
/// in Cartesian form by using the specified culture-specific formatting information.
///
/// The string representation of the current instance in Cartesian form, as specified by .
/// An object that supplies culture-specific formatting information.
public string ToString(IFormatProvider provider)
{
return string.Format(provider, "({0}, {1})", _real, _imag);
}
/// Converts the value of the current complex number to its equivalent string representation
/// in Cartesian form by using the specified format and culture-specific format information for its real and imaginary parts.
/// The string representation of the current instance in Cartesian form, as specified by and .
/// A standard or custom numeric format string.
/// An object that supplies culture-specific formatting information.
///
/// is not a valid format string.
public string ToString(string format, IFormatProvider provider)
{
return string.Format(provider, "({0}, {1})",
_real.ToString(format, provider),
_imag.ToString(format, provider));
}
#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(Complex32 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()
{
int hash = 27;
hash = (13 * hash) + _real.GetHashCode();
hash = (13 * hash) + _imag.GetHashCode();
return hash;
}
///
/// 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 Complex32) && Equals((Complex32)obj);
}
#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 float.
///
///
/// A complex number containing the value specified by the given string.
///
///
/// the string to parse.
///
///
/// An that supplies culture-specific
/// formatting information.
///
public static Complex32 Parse(string value, IFormatProvider formatProvider = null)
{
if (value == null)
{
throw new ArgumentNullException(nameof(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;
var leftPart = ParsePart(ref token, out isLeftPartImaginary, formatProvider);
if (token == null)
{
return isLeftPartImaginary ? new Complex32(0, leftPart) : new Complex32(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;
var rightPart = ParsePart(ref token, out isRightPartImaginary, formatProvider);
return new Complex32(leftPart, rightPart);
}
else
{
// format: real + imag
bool isRightPartImaginary;
var 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 Complex32(rightPart, leftPart) : new Complex32(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 float.
///
private static float 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();
}
}
var 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 NETSTANDARD1_3
var value = GlobalizationHelper.ParseSingle(ref token);
#else
var value = GlobalizationHelper.ParseSingle(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 single-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 Complex32 result)
{
return TryParse(value, null, out result);
}
///
/// Converts the string representation of a complex number to single-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 Complex32 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 real decimal to a Complex32.
///
/// The decimal value to convert.
/// The result of the conversion.
public static explicit operator Complex32(decimal value)
{
return new Complex32((float)value, 0.0f);
}
///
/// Explicit conversion of a Complex to a Complex32.
///
/// The decimal value to convert.
/// The result of the conversion.
public static explicit operator Complex32(Complex value)
{
return new Complex32((float)value.Real, (float)value.Imaginary);
}
///
/// Implicit conversion of a real byte to a Complex32.
///
/// The byte value to convert.
/// The result of the conversion.
public static implicit operator Complex32(byte value)
{
return new Complex32(value, 0.0f);
}
///
/// Implicit conversion of a real short to a Complex32.
///
/// The short value to convert.
/// The result of the conversion.
public static implicit operator Complex32(short value)
{
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 unsigned real short to a Complex32.
///
/// The unsigned 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.
///
/// The int value to convert.
/// The result of the conversion.
public static implicit operator Complex32(int value)
{
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.
///
/// The long value to convert.
/// The result of the conversion.
public static implicit operator Complex32(long value)
{
return new Complex32(value, 0.0f);
}
///
/// Implicit conversion of a real uint to a Complex32.
///
/// 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);
}
///
/// Implicit conversion of a real ulong to a Complex32.
///
/// 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);
}
///
/// Implicit conversion of a real float to a Complex32.
///
/// The float value to convert.
/// The result of the conversion.
public static implicit operator Complex32(float value)
{
return new Complex32(value, 0.0f);
}
///
/// Implicit conversion of a real double to a Complex32.
///
/// The double value to convert.
/// The result of the conversion.
public static explicit operator Complex32(double value)
{
return new Complex32((float)value, 0.0f);
}
///
/// Converts this Complex32 to a .
///
/// A with the same values as this Complex32.
public Complex ToComplex()
{
return new Complex(_real, _imag);
}
#endregion
///
/// Returns the additive inverse of a specified complex number.
///
/// The result of the real and imaginary components of the value parameter multiplied by -1.
/// A complex number.
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public static Complex32 Negate(Complex32 value)
{
return -value;
}
///
/// Computes the conjugate of a complex number and returns the result.
///
/// The conjugate of .
/// A complex number.
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public static Complex32 Conjugate(Complex32 value)
{
return value.Conjugate();
}
///
/// Adds two complex numbers and returns the result.
///
/// The sum of and .
/// The first complex number to add.
/// The second complex number to add.
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public static Complex32 Add(Complex32 left, Complex32 right)
{
return left + right;
}
///
/// Subtracts one complex number from another and returns the result.
///
/// The result of subtracting from .
/// The value to subtract from (the minuend).
/// The value to subtract (the subtrahend).
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public static Complex32 Subtract(Complex32 left, Complex32 right)
{
return left - right;
}
///
/// Returns the product of two complex numbers.
///
/// The product of the and parameters.
/// The first complex number to multiply.
/// The second complex number to multiply.
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public static Complex32 Multiply(Complex32 left, Complex32 right)
{
return left * right;
}
///
/// Divides one complex number by another and returns the result.
///
/// The quotient of the division.
/// The complex number to be divided.
/// The complex number to divide by.
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public static Complex32 Divide(Complex32 dividend, Complex32 divisor)
{
return dividend / divisor;
}
///
/// Returns the multiplicative inverse of a complex number.
///
/// The reciprocal of .
/// A complex number.
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public static Complex32 Reciprocal(Complex32 value)
{
return value.Reciprocal();
}
///
/// Returns the square root of a specified complex number.
///
/// The square root of .
/// A complex number.
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public static Complex32 Sqrt(Complex32 value)
{
return value.SquareRoot();
}
///
/// Gets the absolute value (or magnitude) of a complex number.
///
/// The absolute value of .
/// A complex number.
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public static double Abs(Complex32 value)
{
return value.Magnitude;
}
///
/// Returns e raised to the power specified by a complex number.
///
/// The number e raised to the power .
/// A complex number that specifies a power.
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public static Complex32 Exp(Complex32 value)
{
return value.Exponential();
}
///
/// Returns a specified complex number raised to a power specified by a complex number.
///
/// The complex number raised to the power .
/// A complex number to be raised to a power.
/// A complex number that specifies a power.
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public static Complex32 Pow(Complex32 value, Complex32 power)
{
return value.Power(power);
}
///
/// Returns a specified complex number raised to a power specified by a single-precision floating-point number.
///
/// The complex number raised to the power .
/// A complex number to be raised to a power.
/// A single-precision floating-point number that specifies a power.
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public static Complex32 Pow(Complex32 value, float power)
{
return value.Power(power);
}
///
/// Returns the natural (base e) logarithm of a specified complex number.
///
/// The natural (base e) logarithm of .
/// A complex number.
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public static Complex32 Log(Complex32 value)
{
return value.NaturalLogarithm();
}
///
/// Returns the logarithm of a specified complex number in a specified base.
///
/// The logarithm of in base .
/// A complex number.
/// The base of the logarithm.
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public static Complex32 Log(Complex32 value, float baseValue)
{
return value.Logarithm(baseValue);
}
///
/// Returns the base-10 logarithm of a specified complex number.
///
/// The base-10 logarithm of .
/// A complex number.
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public static Complex32 Log10(Complex32 value)
{
return value.CommonLogarithm();
}
///
/// Returns the sine of the specified complex number.
///
/// The sine of .
/// A complex number.
public static Complex32 Sin(Complex32 value)
{
return (Complex32)Trig.Sin(value.ToComplex());
}
///
/// Returns the cosine of the specified complex number.
///
/// The cosine of .
/// A complex number.
public static Complex32 Cos(Complex32 value)
{
return (Complex32)Trig.Cos(value.ToComplex());
}
///
/// Returns the tangent of the specified complex number.
///
/// The tangent of .
/// A complex number.
public static Complex32 Tan(Complex32 value)
{
return (Complex32)Trig.Tan(value.ToComplex());
}
///
/// Returns the angle that is the arc sine of the specified complex number.
///
/// The angle which is the arc sine of .
/// A complex number.
public static Complex32 Asin(Complex32 value)
{
return (Complex32)Trig.Asin(value.ToComplex());
}
///
/// Returns the angle that is the arc cosine of the specified complex number.
///
/// The angle, measured in radians, which is the arc cosine of .
/// A complex number that represents a cosine.
public static Complex32 Acos(Complex32 value)
{
return (Complex32)Trig.Acos(value.ToComplex());
}
///
/// Returns the angle that is the arc tangent of the specified complex number.
///
/// The angle that is the arc tangent of .
/// A complex number.
public static Complex32 Atan(Complex32 value)
{
return (Complex32)Trig.Atan(value.ToComplex());
}
///
/// Returns the hyperbolic sine of the specified complex number.
///
/// The hyperbolic sine of .
/// A complex number.
public static Complex32 Sinh(Complex32 value)
{
return (Complex32)Trig.Sinh(value.ToComplex());
}
///
/// Returns the hyperbolic cosine of the specified complex number.
///
/// The hyperbolic cosine of .
/// A complex number.
public static Complex32 Cosh(Complex32 value)
{
return (Complex32)Trig.Cosh(value.ToComplex());
}
///
/// Returns the hyperbolic tangent of the specified complex number.
///
/// The hyperbolic tangent of .
/// A complex number.
public static Complex32 Tanh(Complex32 value)
{
return (Complex32)Trig.Tanh(value.ToComplex());
}
}
}